[
  {
    "path": ".circleci/config.yml",
    "content": "# https://circleci.com/docs/hello-world/\nversion: 2.1\n\njobs:\n  hello-job:\n    docker:\n      - image: cimg/node:17.2.0 # the primary container, where your job's commands are run\n    steps:\n      - checkout # check out the code in the project directory\n      - run: echo \"hello world\" # run the `echo` command\n\nworkflows:\n  my-workflow:\n    jobs:\n      - hello-job\n"
  },
  {
    "path": ".github/workflows/conda/conda-env.yml",
    "content": "name: cppad\nchannels:\n  - conda-forge\n  - nodefaults\ndependencies:\n  - boost\n  - python"
  },
  {
    "path": ".github/workflows/conda-bash.yml",
    "content": "name: conda-bash\n\non:\n  pull_request:\n  push:\n    branches:\n      - master\n      - 'stable/*'\n\nenv:\n  BUILD_TYPE: Release\n\njobs:\n  build:\n    runs-on: ${{ matrix.os }}\n\n    strategy:\n      fail-fast: false\n      matrix:\n        # os: [\"ubuntu-latest\", \"macos-latest\"] 2024-04-26 macos-latest failing\n        # Error: No installed conda 'base' environment found ...; see\n        os: [\"ubuntu-latest\", \"macos-latest\", \"windows-latest\"]\n\n    steps:\n    - uses: actions/checkout@v4\n\n    - uses: conda-incubator/setup-miniconda@v3\n      with:\n        activate-environment: cppad\n        auto-update-conda: true\n\n    - name: Install cmake and pkgconfig\n      shell: bash -l {0}\n      run: |\n        conda activate cppad\n        conda install -y cmake\n        conda install -y pkgconfig\n\n    - name: Build CppAD\n      shell: bash -l {0}\n      run: |\n        conda activate cppad\n        if [ \"$RUNNER_OS\" == \"macOS\" ]\n        then\n          generator='Unix Makefiles'\n          export SDKROOT=$(xcrun --sdk macosx --show-sdk-path)\n          n_job=$(sysctl -n hw.ncpu)\n        elif  [ \"$RUNNER_OS\" == \"Windows\" ]\n        then\n          generator='Visual Studio 17 2022'\n          n_job=1\n        else\n          generator='Unix Makefiles'\n          n_job=$(nproc)\n        fi\n        echo \"RUNNER_OS=$RUNNER_OS, n_job=$n_job, generator=$generator\"\n        conda activate cppad\n        echo $CONDA_PREFIX\n\n        mkdir build\n        cd build\n        cmake .. \\\n          -G \"$generator\" \\\n          -D CMAKE_INSTALL_PREFIX=$CONDA_PREFIX \\\n          -D CMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}\n        cmake --build . \\\n          --config ${{env.BUILD_TYPE}} \\\n          --target check install \\\n          --parallel $n_job\n"
  },
  {
    "path": ".github/workflows/conda-windows-clang.yml",
    "content": "name: conda-windows-clang\non:\n  pull_request:\n  push:\n    branches:\n      - master\n      - 'stable/*'\n\nenv:\n  # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)\n  BUILD_TYPE: Release\n\njobs:\n  build:\n    runs-on: ${{ matrix.os }}\n    strategy:\n      fail-fast: true\n      matrix:\n        name: [windows-latest-clang-cl]\n\n        include:\n          - name: windows-latest-clang-cl\n            os: windows-2019\n            compiler: clang-cl\n\n    steps:\n    - uses: actions/checkout@v4\n    - name: Checkout submodules\n      run: |\n        git submodule update --init\n    - uses: conda-incubator/setup-miniconda@v3\n      env:\n        ACTIONS_ALLOW_UNSECURE_COMMANDS: 'true'\n      with:\n        activate-environment: cppad\n        environment-file: .github/workflows/conda/conda-env.yml\n        python-version: 3.7\n    - name: Install cmake , pkgconfig, and update conda\n      run: |\n        conda install cmake -c main\n        conda install pkgconfig -c conda-forge\n    - name: Build CppAD\n      shell: cmd /C CALL {0}\n      env:\n        ACTIONS_ALLOW_UNSECURE_COMMANDS: 'true'\n      run: |\n        :: unset extra Boost envs\n        set Boost_ROOT=\n        set BOOST_ROOT_1_69_0=\n        set BOOST_ROOT_1_72_0=\n        set PATH=%PATH:C:\\hostedtoolcache\\windows\\Boost\\1.72.0;=%\n\n        :: Create build directory\n        mkdir build\n        pushd build\n\n\n        :: Configure\n        # wd6316 is same as gnu -Wno-bitwise-instead-of-logical\n        # https://learn.microsoft.com/en-us/cpp/code-quality/c6316\n        cmake ^\n          -G \"Visual Studio 16 2019\" -T \"ClangCl\" ^\n          -DCMAKE_GENERATOR_PLATFORM=x64 ^\n          -DCMAKE_INSTALL_PREFIX=%CONDA_PREFIX%\\Library ^\n          -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} ^\n          -Dcppad_cxx_flags=\"/wd6316\" ^\n          -Dcppad_static_lib=TRUE ^\n          ..\n\n        :: Build\n        cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --target check install\n"
  },
  {
    "path": ".github/workflows/conda-windows-eigen.yml",
    "content": "name: conda-windows-eigen\non:\n  push:\n    branches:\n      - master\n      - 'stable/*'\n\njobs:\n  build:\n    runs-on: windows-2019\n\n    steps:\n    - uses: actions/checkout@v4\n    - uses: conda-incubator/setup-miniconda@v3\n      with:\n        activate-environment: conda_env\n\n    - name: Use conda to install eigen and pkgconfig\n      shell: cmd /C CALL {0}\n      run: |\n        echo conda install --yes eigen pkgconfig\n             conda install --yes eigen pkgconfig\n\n    - name: Create and check Eigen link, check for eigen3.pc\n      shell: cmd /C CALL {0}\n      run: |\n        mklink /d %CONDA_PREFIX%\\Library\\include\\Eigen^\n                  %CONDA_PREFIX%\\Library\\include\\eigen3\\Eigen\n        echo dir %CONDA_PREFIX%\\Library\\include\\Eigen\\Core\n             dir %CONDA_PREFIX%\\Library\\include\\Eigen\\Core\n        echo dir %CONDA_PREFIX%\\Library\\share\\pkgconfig\\eigen3.pc\n             dir %CONDA_PREFIX%\\Library\\share\\pkgconfig\\eigen3.pc\n\n    - name: Build and test CppAD with Eigen\n      shell: cmd /C CALL {0}\n      run: |\n        echo Use vcvarsall.bat to get proper version of cmake\n        call \"%programfiles(x86)%\\Microsoft Visual Studio\\2019\\Enterprise\\VC\\Auxiliary\\Build\\vcvarsall.bat\" amd64\n        echo where camke\n             where cmake\n        echo mkdir build\n             mkdir build\n        echo cd build\n             cd build\n        echo set PKG_CONFIG_PATH=%CONDA_PREFIX%\\Library\\share\\pkgconfig\n             set PKG_CONFIG_PATH=%CONDA_PREFIX%\\Library\\share\\pkgconfig\n        echo run cmake\n        cmake ^\n          -D CMAKE_CXX_COMPILER=cl ^\n          -D CMAKE_C_COMPILER=cl ^\n          -D CMAKE_BUILD_TYPE=release ^\n          -G \"NMake Makefiles\" ^\n          -D cppad_static_lib=TRUE ^\n          -D cppad_cxx_flags=\"/MP /EHs /EHc /std:c++17 /Zc:__cplusplus\" ^\n          ..\n        REM Build and run tests.\n        cmake --build . --target check --parallel 4\n"
  },
  {
    "path": ".github/workflows/conda-windows-v142.yml",
    "content": "name: conda-windows-v142\non:\n  pull_request:\n  push:\n    branches:\n      - master\n      - 'stable/*'\n\nenv:\n  # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)\n  BUILD_TYPE: Release\n\njobs:\n  build:\n    runs-on: ${{ matrix.os }}\n    strategy:\n      fail-fast: true\n      matrix:\n        name: [windows-latest]\n\n        include:\n          - name: windows-latest\n            os: windows-2019\n\n    steps:\n    - uses: actions/checkout@v4\n    - name: Checkout submodules\n      run: |\n        git submodule update --init\n    - uses: conda-incubator/setup-miniconda@v3\n      env:\n        ACTIONS_ALLOW_UNSECURE_COMMANDS: 'true'\n      with:\n        activate-environment: cppad\n        environment-file: .github/workflows/conda/conda-env.yml\n        python-version: 3.7\n    - name: Install cmake , pkgconfig and update conda\n      run: |\n        conda install cmake -c main\n        conda install pkgconfig -c conda-forge\n\n    - name: Build CppAD\n      shell: cmd /C CALL {0}\n      env:\n        ACTIONS_ALLOW_UNSECURE_COMMANDS: 'true'\n      run: |\n        :: unset extra Boost envs\n        set Boost_ROOT=\n        set BOOST_ROOT_1_69_0=\n        set BOOST_ROOT_1_72_0=\n        set PATH=%PATH:C:\\hostedtoolcache\\windows\\Boost\\1.72.0;=%\n\n        :: Create build directory\n        mkdir build\n        pushd build\n\n        :: Configure\n        cmake ^\n          -G \"Visual Studio 16 2019\" -T \"v142\" -DCMAKE_GENERATOR_PLATFORM=x64 ^\n          -DCMAKE_INSTALL_PREFIX=%CONDA_PREFIX%\\Library ^\n          -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} ^\n          -Dcppad_static_lib=TRUE ^\n          ..\n\n        :: Build, check and Install\n        # https://gitlab.kitware.com/cmake/cmake/-/issues/20564\n        # --parallel 1 works\n        # --parallel 4 does not work\n        cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --target check install --parallel 1\n"
  },
  {
    "path": ".github/workflows/ubuntu-macos.yml",
    "content": "name: ubuntu-macos\non:\n  pull_request:\n  push:\n    branches:\n      - master\n      - 'stable/*'\njobs:\n  run_tests:\n    runs-on: ${{ matrix.os }}\n    strategy:\n      matrix:\n        os: [ ubuntu-latest, macos-latest ]\n    steps:\n      - name: Check out repository code\n        uses: actions/checkout@v4\n      - name: set debug_which\n        run: |\n          mkdir build\n          cd build\n          set +e\n          random_03=$(expr $RANDOM % 4)\n          set -e\n          case $random_03 in\n            0) debug_which='debug_all'\n            ;;\n            1) debug_which='debug_even'\n            ;;\n            2) debug_which='debug_odd'\n            ;;\n            3) debug_which='debug_none'\n            ;;\n          esac\n          echo \"$debug_which\" > debug_which\n      - name: run cmake\n        run: |\n          cd build\n          debug_which=$(cat debug_which)\n          echo \"cmake -D cppad_debug_which=$debug_which\" ..\n          cmake -D cppad_debug_which=$debug_which ..\n      - name: run make check\n        run: |\n          if [ \"$RUNNER_OS\" == \"macOS\" ]\n          then\n            export SDKROOT=$(xcrun --sdk macosx --show-sdk-path)\n          fi\n          if which nproc >& /dev/null\n          then\n              n_job=$(nproc)\n          else\n              n_job=$(sysctl -n hw.ncpu)\n          fi\n          cd build\n          echo \"make -j $n_job check\"\n          make -j $n_job check\n      - run: echo \"job.status = ${{ job.status }}\"\n"
  },
  {
    "path": ".github/workflows/windows-msys2.yml",
    "content": "name: windows-msys2\n\non:\n  pull_request:\n  push:\n    branches:\n      - master\n      - 'stable/*'\n\njobs:\n  build:\n    runs-on: windows-latest\n    defaults:\n      run:\n        shell: msys2 {0}\n    steps:\n      - uses: actions/checkout@v4\n      - uses: msys2/setup-msys2@v2\n        with:\n          msystem: MINGW64\n          update: true\n          install: git mingw-w64-x86_64-cc mingw-w64-x86_64-cmake make\n\n      - name: CppAD check\n        run: |\n          #\n          # Create build directory\n          mkdir build\n          pushd build\n          #\n          # configure\n          cmake -G \"MSYS Makefiles\" -D cppad_static_lib=TRUE ..\n          #\n          # check\n          cmake --build . --target check --parallel 1\n"
  },
  {
    "path": ".gitignore",
    "content": "# ----------------------------------------------------------------------------\n# specific files\n#\n#\n# cmake configure files\n/bin/test_one.sh\n/include/cppad/configure.hpp\n#\n# create by bin/test_one.sh\n/test_one.cpp\n/test_one.exe\n/test_one.exe.dSYM/\n#\n# git commit script\n/git_commit.sh\n# ----------------------------------------------------------------------------\n# specific directories\n#\n# buld directories\n/build/\n/build2/\n#\n# for building external packages\n/external/\n#\n# for caching git changes\n/new/\n/new.*/\n# ----------------------------------------------------------------------------\n# specific extensions in top direcotry\n/*.err\n/*.log\n/*.tmp\n# ----------------------------------------------------------------------------\n# vim swap files in any directory\n*.swp\n# ----------------------------------------------------------------------------\n# temp files in any directory\ntemp\ntemp.*\n"
  },
  {
    "path": ".readthedocs.yaml",
    "content": "# !! EDITS TO THIS FILE ARE LOST DURING UPDATES BY xrst.git/bin/dev_tools.sh !!\n# {xrst_comment_ch #}\n#\n# Example Read the Docs Configuration\n# ###################################\n#\n# Read the Docs Specification\n# ***************************\n# `<https://docs.readthedocs.com/platform/stable/config-file>`_\n#\n# This Example File\n# *****************\n# {xrst_literal}\n#\nversion: 2\n\nbuild:\n   os: \"ubuntu-22.04\"\n   tools:\n      python: \"3.10\"\n   #\n   # The readthedocs commands feature is still in beta\n   commands:\n      #\n      # xrst\n      - pip install xrst\n      #\n      # This is only necessary if you need the most recent testing verison\n      - pip uninstall -y xrst\n      - pip install --index-url https://test.pypi.org/simple/ xrst\n      #\n      # This command prints the version of xrst that is being used\n      - xrst --version\n      #\n      # build/html\n      # This comamnd builds the xrst user documentation.\n      # Suppress spell warnings because readthdocs uses a different dictionry.\n      - xrst\n         --page_source\n         --html_theme furo\n         --group_list default app\n         --index_page_name user_guide\n         --suppress_spell_warnings\n      #\n      # _readthedocs/html\n      # The directory that Read the Docs uploads when commands is used.\n      - mkdir _readthedocs\n      - rm -r build/html/.doctrees\n      - cp -r build/html _readthedocs/html\n"
  },
  {
    "path": ".travis.yml",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n#\nsudo:     false\nlanguage: cpp\ncompiler: gcc\n\nscript:\n  # bin/travis.sh (make|test_one) target1 target2 ...\n  #\n  bin/travis.sh make check install uninstall\n\nnotifications:\n  email:\n    recipients:\n      bradbell@seanet.com\n    on_success: change # send e-mail what success status changes\n    on_failure: always # always send e-mail when a test fails\n"
  },
  {
    "path": "CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-26 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# =============================================================================\n# Some constants\n# =============================================================================\n#\n# Set the minimum required version of cmake for this project.\n# see https://cmake.org//pipermail/cmake/2013-January/053213.html\nCMAKE_MINIMUM_REQUIRED(VERSION 3.10)\n#\n# Use the version of BoostConfig.cmake provided by boost.\nIF( POLICY CMP0167 )\n    CMAKE_POLICY(SET CMP0167 NEW)\nENDIF( POLICY CMP0167 )\n#\n# Only interpret if() arguments as variables or keywords when unquoted.\nIF( POLICY CMP0054 )\n  CMAKE_POLICY(SET CMP0054 NEW)\nENDIF( POLICY CMP0054 )\n#\n# cppad_version is used by version.sh to get the version number.\nSET(cppad_version \"20260408\")\nSET(cppad_url          \"https://coin-or.github.io/CppAD\" )\nSET(cppad_description  \"Differentiation of C++ Algorithms\" )\nIF( NOT DEFINED CMAKE_BUILD_TYPE)\n     SET(CMAKE_BUILD_TYPE \"NOTFOUND\")\nENDIF( NOT DEFINED CMAKE_BUILD_TYPE)\n#\n# Set name of this project and create the variables\n# cppad_BINARY_DIR and cppad_SOURCE_DIR.\n# project(projectname [CXX] [C] [Java])\nPROJECT(cppad)\n#\n# Add the include sub-directory to the list of C++ preprocessor\n# include directories for the entire project.  The SYSTEM flag is not included\n# so warnings will be geenreated for this directory.\nINCLUDE_DIRECTORIES( ${cppad_SOURCE_DIR}/include )\n#\n# =============================================================================\n# Some system cmake language extensions\n# =============================================================================\n# CHECK_CXX_SOURCE_COMPILES(source variable)\n# Checks whether the code given in source will compile, link and run and\n# return zero status. You can set\n# CMAKE_REQUIRED_LIBRARIES, CMAKE_REQUIRED_FLAGS and CMAKE_REQUIRED_INCLUDES\n# accordingly if additional libraries or compiler flags are required.\nINCLUDE(CheckCXXSourceCompiles)\n# ============================================================================\n# Some local cmake language\n# ============================================================================\n# assert_value_in_set(value element_1 ... element_n)\nINCLUDE(cmake/assert_value_in_set.cmake)\n#\n# dos_path_to_unix(dos_path unix_path)\nINCLUDE(cmake/dos_path_to_unix.cmake)\n#\n# add_to_list(variable_list constant_value)\nINCLUDE(cmake/add_to_list.cmake)\n#\n# command_line_arg(variable default type description)\nINCLUDE(cmake/command_line_arg.cmake)\n#\n# prefix_info(package description)\nINCLUDE(cmake/prefix_info.cmake)\n#\n# compile_source_test(source variable)\nINCLUDE(cmake/compile_source_test.cmake)\n#\n# assert(variable)\nINCLUDE(cmake/assert.cmake)\n#\n# print_variable(variable)\nINCLUDE(cmake/print_variable.cmake)\n#\n# set_compile_flags( program_name debug_which source_list)\nINCLUDE(cmake/set_compile_flags.cmake)\n#\n# pkgconfig_info(name, system)\nINCLUDE(cmake/pkgconfig_info.cmake)\n#\n# eigen_info()\nINCLUDE(cmake/eigen_info.cmake)\n#\n# add_check_executable(parent_target short_name)\nINCLUDE(cmake/add_check_executable.cmake)\n# =============================================================================\n# command line arguments\n# =============================================================================\n# Arguments that are no longer used\n#\nIF( debug_which )\n    MESSAGE(FATAL_ERROR\n        \"Using debug_which, use cppad_debug_which or CMAKE_BUILD_TYPE instead\"\n    )\nENDIF( debug_which )\n#\nIF( cppad_sparse_list )\n    MESSAGE(FATAL_ERROR\n        \"cppad_sparse_list has been removed from cmake command\"\n    )\nENDIF( cppad_sparse_list )\n#\nIF( cppad_deprecated )\n    MESSAGE(FATAL_ERROR \"cppad_deprecated has been removed from cmake command\" )\nENDIF( cppad_deprecated )\n#\nIF( cmake_install_prefix )\n    MESSAGE(FATAL_ERROR\n        \"cmake_install_prefix has been changed to cppad_prefix\"\n    )\nENDIF( cmake_install_prefix )\n#\nIF( cmake_install_postfix )\n    MESSAGE(FATAL_ERROR\n        \"cmake_install_postfix has been changed to cppad_postfix\"\n    )\nENDIF( cmake_install_postfix )\n#\nFOREACH(pkg adolc eigen ipopt cppadcg)\n    IF( ${pkg}_prefix )\n        MESSAGE(FATAL_ERROR\n            \"-D ${pkg}_prefix=value has been changed to -D include_${pkg}=true\"\n        )\n    ENDIF( ${pkg}_prefix )\nENDFOREACH(pkg adolc eigen ipopt cppadcg)\n#\nIF( cmake_needs_dot_slash )\n    MESSAGE(FATAL_ERROR\n        \"cmake_needs_dot_slash was removed; see release notes for 2023-06-01\"\n    )\nENDIF( cmake_needs_dot_slash )\n#\nIF( include_eigen )\n    MESSAGE(FATAL_ERROR\n        \"include_eigen was removed; see release notes for 2024-10-02\"\n    )\nENDIF( )\n# -----------------------------------------------------------------------------\n# Current Arguments\n#\n# cmake_install_datadir\ncommand_line_arg(cmake_install_datadir share STRING\n    \"directory, below prefix, where cmake installs cppad data files\"\n)\n#\n# cmake_install_docdir\ncommand_line_arg(cmake_install_docdir NOTFOUND STRING\n    \"directory, below prefix, where cmake installs cppad documentation files\"\n)\n#\n# cmake_install_includedirs\ncommand_line_arg(cmake_install_includedirs include STRING\n    \"directories, below prefix, where cmake installs include files\"\n)\n#\n# cmake_install_libdirs\ncommand_line_arg(cmake_install_libdirs \"lib;lib64\" STRING\n    \"directories, below prefix, where cmake installs library files\"\n)\n#\n# cmake_defined_ok\ncommand_line_arg(cmake_defined_ok TRUE BOOL\n    \"If false, check that some symbols only get defined once\"\n    \"If true, you can use CMakeCache.txt to store previous settings\"\n)\n#\n# cppad_prefix\ncommand_line_arg(cppad_prefix \"${CMAKE_INSTALL_PREFIX}\" PATH\n    \"cppad install prefix\"\n)\n#\n# cppad_postfix\ncommand_line_arg(cppad_postfix NOTFOUND STRING\n    \"cppad install postfix\"\n)\n#\n# cppad_cxx_flags\ncommand_line_arg(cppad_cxx_flags \"\" STRING\n    \"compile flags used with cppad (besides debug, release, and profile flags)\"\n)\n#\n# cppad_link_flags\ncommand_line_arg(cppad_link_flags \"\" STRING\n    \"additional linker flags)\"\n)\n#\n# cppad_profile_flag\ncommand_line_arg(cppad_profile_flag NOTFOUND STRING\n    \"compile flag used to compile and link a profile version of a program\"\n)\n#\n# cppad_testvector\ncommand_line_arg(cppad_testvector cppad STRING\n    \"Namespace of vector used for testing, one of: boost, cppad, eigen, std\"\n)\nassert_value_in_set(cppad_testvector boost cppad eigen std)\n#\n# cppad_max_num_threads\ncommand_line_arg(cppad_max_num_threads 48 STRING\n    \"maximum number of threads that CppAD can use use\"\n)\nIF( \"${cppad_max_num_threads}\" LESS \"4\" )\n    MESSAGE(FATAL_ERROR\n        \"cppad_max_num_threads is not an integer greater than or equal 4\"\n    )\nENDIF( \"${cppad_max_num_threads}\" LESS \"4\" )\n#\n# cppad_tape_id_type\ncommand_line_arg(cppad_tape_id_type \"unsigned int\" STRING\n    \"type used to identify different tapes, size must be <= sizeof(size_t)\"\n)\n#\n# cppad_tape_addr_type\ncommand_line_arg(cppad_tape_addr_type \"unsigned int\" STRING\n\"type used to identify variables on one tape, size must be <= sizeof(size_t)\"\n)\n#\n# cppad_debug_and_release\ncommand_line_arg(cppad_debug_and_release TRUE BOOL\n    \"If true the cppad library and tests will be able to mix debug and release\"\n)\n#\n# cppad_static_lib\nSTRING( REGEX MATCH \"^MSYS\"    is_msys     \"${CMAKE_SYSTEM_NAME}\" )\nSTRING( REGEX MATCH \"^CYGWIN\"  is_cygwin   \"${CMAKE_SYSTEM_NAME}\" )\nSTRING( REGEX MATCH \"^Windows\" is_windows  \"${CMAKE_SYSTEM_NAME}\" )\nIF( is_msys OR is_cygwin OR is_windows )\n    SET(default_cppad_static_lib TRUE)\nELSE( )\n    SET(default_cppad_static_lib FALSE)\nENDIF( )\n#\n# cppad_static_lib\ncommand_line_arg(cppad_static_lib ${default_cppad_static_lib} BOOL\n    \"If true (false) the cppad library will be static (shared)\"\n)\n# ----------------------------------------------------------------------------\n#\n# Ensure c++11 support\nSET(CMAKE_REQUIRED_DEFINITIONS \"\")\nSET(CMAKE_REQUIRED_FLAGS       \"${cppad_cxx_flags}\")\nSET(CMAKE_REQUIRED_INCLUDES    \"\")\nSET(CMAKE_REQUIRED_LIBRARIES   \"\")\nSET(source \"\nint main(void)\n{   static_assert( __cplusplus >= 201103 , \\\"c++11 is supported\\\" );\n    return 0;\n}\"\n)\ncompile_source_test(${cmake_defined_ok} \"${source}\" minimal_cplusplus )\nIF( NOT minimal_cplusplus  )\n    MESSAGE(STATUS \"setting C++ standard to 2011\")\n    SET(CMAKE_CXX_STANDARD 11)\n    SET(CMAKE_CXX_STANDARD_REQUIRED ON)\nENDIF( NOT minimal_cplusplus  )\n#\n# use_cplusplus_2014_ok\nSET(source \"\nint main(void)\n{   static_assert( __cplusplus >= 201302L , \\\"c++17 is supported\\\" );\n    return 0;\n}\"\n)\ncompile_source_test(${cmake_defined_ok} \"${source}\" use_cplusplus_2014_ok )\n#\n# use_cplusplus_2017_ok\nSET(source \"\nint main(void)\n{   static_assert( __cplusplus >= 201703L , \\\"c++17 is supported\\\" );\n    return 0;\n}\"\n)\ncompile_source_test(${cmake_defined_ok} \"${source}\" use_cplusplus_2017_ok )\n# ----------------------------------------------------------------------------\n#\n# cppad_debug_and_release_01\nIF (cppad_debug_and_release )\n    SET(cppad_debug_and_release_01 1 )\nELSE (cppad_debug_and_release )\n    SET(cppad_debug_and_release_01 0 )\nENDIF ( )\n#\n# cppad_debug_which\n# CMAKE_BUILD_TYPE\nSET(debug_even_or_odd FALSE)\nIF( NOT ${cppad_debug_which} STREQUAL \"\" )\n    assert_value_in_set(\n        cppad_debug_which debug_even debug_odd debug_all debug_none\n    )\nENDIF( NOT ${cppad_debug_which} STREQUAL \"\" )\nIF( CMAKE_BUILD_TYPE )\n    IF( NOT ${cppad_debug_which} STREQUAL \"\" )\n        print_variable(CMAKE_BUILD_TYPE)\n        print_variable(cppad_debug_which)\n        MESSAGE(FATAL_ERROR\n            \"Both CMAKE_BUILD_TYPE and cppad_debug_which specified\"\n        )\n    ENDIF( )\n    STRING( TOLOWER \"${CMAKE_BUILD_TYPE}\" cmake_build_type_lower )\n    IF(cmake_build_type_lower MATCHES debug)\n        SET(cppad_debug_which \"debug_all\")\n    ELSEIF(cmake_build_type_lower MATCHES release)\n        SET(cppad_debug_which \"debug_none\")\n    ELSEIF(cmake_build_type_lower MATCHES relwithdebInfo)\n        SET(cppad_debug_which \"debug_none\")\n    ELSEIF(cmake_build_type_lower MATCHES minsizerel)\n        SET(cppad_debug_which \"debug_none\")\n    ELSE( )\n        MESSAGE(FATAL_ERROR\n            \"Unknown CMAKE_BUILD_TYPE = ${CMAKE_BUILD_TYPE}\"\n        )\n    ENDIF( )\nELSE( ) # CMAKE_BUILD_TYPE\n    IF( \"${cppad_debug_which}\" STREQUAL debug_all)\n        SET(CMAKE_BUILD_TYPE Debug)\n    ELSEIF( \"${cppad_debug_which}\" STREQUAL debug_none)\n        SET(CMAKE_BUILD_TYPE Release)\n    ELSEIF( \"${cppad_debug_which}\" STREQUAL debug_odd)\n        SET(CMAKE_BUILD_TYPE Debug)\n        SET(debug_even_or_odd TRUE)\n    ELSEIF( \"${cppad_debug_which}\" STREQUAL debug_even)\n        SET(CMAKE_BUILD_TYPE Release)\n        SET(debug_even_or_odd TRUE)\n    ENDIF( \"${cppad_debug_which}\" STREQUAL debug_all)\nENDIF( ) # CMAKE_BUILD_TYPE\nIF( debug_even_or_odd )\n    IF ( NOT cppad_debug_and_release )\n        MESSAGE(FATAL_ERROR\n\"cppad_debug_and_release is false and cppad_debug_which = ${cppad_debug_which}\"\n        )\n    ENDIF ( NOT cppad_debug_and_release )\n    IF( ${CMAKE_SYSTEM_NAME} STREQUAL \"Windows\" )\n        MESSAGE(FATAL_ERROR\n        \"Cannot have cppad_debug_which equal ${cppad_debug_which} on Windows.\"\n        )\n    ENDIF( ${CMAKE_SYSTEM_NAME} STREQUAL \"Windows\" )\nENDIF( debug_even_or_odd )\nprint_variable(CMAKE_SYSTEM_NAME)\nprint_variable(cppad_debug_which)\nprint_variable(CMAKE_BUILD_TYPE)\nMESSAGE(STATUS \"make check: available\")\n# -----------------------------------------------------------------------------\n# CMAKE_INSTALL_PREFIX\nSET(CMAKE_INSTALL_PREFIX \"${cppad_prefix}\"\n    CACHE PATH \"value copied from cppad_prefix\" FORCE\n)\n# -----------------------------------------------------------------------------\n# Optional package information\n# cppad_has_{package}, {package}_LINK_LIBRARIES, package INCLUDE_DIRECTORIES\n#\n# system_include\nSET(system_include TRUE)\n#\n# package = eigen\neigen_info()\n#\n# package = adolc\npkgconfig_info(adolc ${system_include})\n#\n# package = ipopt\npkgconfig_info(ipopt ${system_include})\n#\n# package = colpack\nprefix_info(colpack ${system_include} )\n#\n# package = sacado\nprefix_info(sacado ${system_include} )\n#\n# package = fadbad\nprefix_info(fadbad ${system_include} )\n#\n# check sacado\nIF( ${cppad_has_sacado} )\n    IF( NOT ${use_cplusplus_2017_ok} )\n        MESSAGE(FATAL_ERROR \"sacado_prefix is defined but c++17 not supported\")\n    ENDIF( )\nENDIF( )\n#\n# package = cppadcg\nSET( include_cppadcg FALSE CACHE BOOL \"include cppadcg\" )\nIF( include_cppadcg )\n    #\n    # cppad_has_cppadcg\n    SET(cppad_has_cppadcg 1)\n    #\n    # Assume bin/get_cppadcg.sh puts include files in this directory\n    SET(cppadcg_include_dir \"${CMAKE_BINARY_DIR}/prefix/include\" )\n    print_variable(cppadcg_include_dir)\n    INCLUDE_DIRECTORIES( SYSTEM ${cppadcg_include_dir})\nELSE( )\n    # cppad_has_cppadcg\n    SET(cppad_has_cppadcg 0)\nENDIF( include_cppadcg )\n#\n# package = xrst\nSET( include_doc FALSE CACHE BOOL \"include documentation\")\nIF( include_doc )\n    #\n    # xrst_path\n    FIND_PROGRAM( xrst_path xrst )\n    IF( \"${xrst_path}\" STREQUAL \"xrst_path-NOTFOUND\" )\n        MESSAGE(FATAL_ERROR\n            \"include_doc is true and cannot find xrst in system path\"\n        )\n    ENDIF( )\n    #\n    # processor_count\n    INCLUDE(ProcessorCount)\n    ProcessorCount(processor_count)\n    IF( processor_count EQUAL 0 )\n        SET(processor_count 1)\n    ENDIF( )\n    #\n    # see\n    # https://discourse.cmake.org/t/how-to-install-a-generated-directory/1267\n    #\n    # doc_dir\n    SET(doc_dir \"${CMAKE_SOURCE_DIR}/build/html\")\n    #\n    # doc_user\n    ADD_CUSTOM_TARGET(doc_user ALL\n        COMMAND xrst\n            --group_list default app\n            --local_toc\n            --html_theme sphinx_rtd_theme\n            --number_jobs ${processor_count}\n            --index_page_name user_guide\n            --suppress_spell_warnings\n            --config_file \"${CMAKE_SOURCE_DIR}/xrst.toml\"\n    )\n    #\n    # doc_dev\n    ADD_CUSTOM_TARGET(doc_dev\n        COMMAND xrst\n            --group_list default app dev\n            --local_toc\n            --html_theme sphinx_rtd_theme\n            --number_jobs ${processor_count}\n            --index_page_name user_guide\n            --suppress_spell_warnings\n            --config_file \"${CMAKE_SOURCE_DIR}/xrst.toml\"\n    )\nENDIF( include_doc )\n# =============================================================================\n# cppad_lib\n# Perhaps in the future cppad_lib will depend on cmake header only flag ?\nSET( cppad_lib    \"cppad_lib\" )\nLINK_DIRECTORIES( ${cppad_BINARY_DIR}/cppad_lib )\n# =============================================================================\n# colpack_libs\n#\nIF( cppad_has_colpack )\n    SET( colpack_libs \"ColPack\" )\nELSE( cppad_has_colpack )\n    SET( colpack_libs \"\" )\nENDIF( cppad_has_colpack )\n# =============================================================================\n# automated system configuration\n# =============================================================================\n# CMAKE_CXX_FLAGS\nIF( \"${cppad_debug_which}\" STREQUAL \"debug_all\" )\n    print_variable(CMAKE_CXX_FLAGS_DEBUG)\nELSEIF( \"${cppad_debug_which}\" STREQUAL \"debug_none\" )\n    print_variable(CMAKE_CXX_FLAGS_RELEASE)\nELSE( \"${cppad_debug_which}\" )\n    print_variable(CMAKE_CXX_FLAGS_DEBUG)\n    print_variable(CMAKE_CXX_FLAGS_RELEASE)\nENDIF( \"${cppad_debug_which}\" STREQUAL \"debug_all\" )\n# -----------------------------------------------------------------------------\n# cppad_abs_includedir, cppad_abs_libdir, cppad_abs_datadir, cppad_abs_docdir\n#\n# for dir_types = includedirs, libdirs, datadir, docdir\nFOREACH(dir_types includedirs libdirs datadir docdir)\n    # set dir_type = dir_types with  \"dirs\" -> \"dir\"\n    STRING(REGEX REPLACE \"dirs\" \"dir\" dir_type ${dir_types})\n    #\n    # set dir_name to first directory in cmake_install_${dir_types}\n    SET(dir_name NOTFOUND)\n    FOREACH(dir ${cmake_install_${dir_types}})\n        IF( NOT dir_name )\n            SET(dir_name ${dir})\n        ENDIF( NOT dir_name )\n    ENDFOREACH(dir ${cmake_install_${dir_types}})\n    #\n    # set cppad_abs_${dir_type}\n    SET(cppad_abs_${dir_type} \"${cppad_prefix}/${dir_name}\" )\n    #\n    # check if we need to add a postfix to it\n    IF( cppad_postfix )\n        SET(cppad_abs_${dir_type} ${cppad_abs_${dir_type}}/${cppad_postfix} )\n    ENDIF( cppad_postfix )\nENDFOREACH(dir_types includedirs libdirs datadir docdir)\n# ----------------------------------------------------------------------------\n# https://gitlab.kitware.com/cmake/community/-/wikis/doc/cmake/RPATH-handling\n#\n# CMAKE_SKIP_BUILD_RPATH\n# use, i.e. don't skip the full RPATH for the build tree\nSET(CMAKE_SKIP_BUILD_RPATH FALSE)\n#\n# CMAKE_BUILD_WITH_INSTALL_RPATH\n# when building shared libraries, don't use the install RPATH already\n# (but later on when installing)\nSET(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)\n#\n# CMAKE_INSTAL_RPATH_USE_LINK_PATH\n# add the automatically determined parts of the RPATH\n# which point to directories outside the build tree to the install RPATH\nSET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)\n#\n# isSystemDir\n# is this RPATH choice a system directory\nLIST(FIND\n    CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES\n    \"${cppad_abs_libdir}\"\n    isSystemDir\n)\n#\n# CMAKE_INSTALL_RPATH\n# the RPATH to be used when installing, but only if it's not a system directory\nSET(CMAKE_INSTALL_RPATH \"\")\nif(\"${isSystemDir}\" STREQUAL \"-1\")\n    SET(CMAKE_INSTALL_RPATH \"${cppad_abs_libdir}\")\nendif(\"${isSystemDir}\" STREQUAL \"-1\")\nprint_variable( CMAKE_INSTALL_RPATH )\n# -----------------------------------------------------------------------------\n# cppad_link_flags_has_m32\nSTRING( FIND \"${cppad_link_flags}\" \"-m32\" index)\nIF( \"${index}\" STREQUAL \"-1\" )\n    SET(cppad_link_flags_has_m32 0)\nELSE ( )\n    SET(cppad_link_flags_has_m32 1)\nENDIF( )\n# -----------------------------------------------------------------------------\n# OpenMP_CXX_FOUND, OpenMP_CXX_FLAGS\nIF( cppad_link_flags_has_m32 )\n    SET(OpenMP_CXX_FOUND FALSE)\n    MESSAGE(STATUS\n        \"Skipping OpenMP because -m32 is in cppad_link_flags\"\n    )\nELSEIF( ${CMAKE_SYSTEM_NAME} STREQUAL \"Darwin\" )\n    SET(OpenMP_CXX_FOUND FALSE)\n    MESSAGE(STATUS\n        \"Skipping OpenMP on Darwin (Mac) systems. 2DO: fix this\"\n    )\nELSE( )\n    FIND_PACKAGE(OpenMP)\nENDIF( )\n# -----------------------------------------------------------------------------\n# Boost_Found, cppad_has_boost\n# Only need components for object libraries, not include libraries.\nIF( cppad_link_flags_has_m32 )\n    MESSAGE(STATUS\n        \"Skipping Boost because -m32 is in cppad_link_flags\"\n    )\n    SET( Boost_FOUND 0)\n    SET(cppad_has_boost 0)\nELSE ( )\n    SET(CMAKE_REQUIRED_FLAGS \"\")  # 2DO: why is this necessary with clang ?\n    FIND_PACKAGE(Boost COMPONENTS thread)\n    SET(CMAKE_REQUIRED_FLAGS \"${cppad_cxx_flags}\")\nENDIF( )\nIF ( Boost_FOUND )\n    SET(cppad_has_boost 1)\n    #\n    # Extract the Boost prefix from Boost_INCLUDE_DIRS\n    #\n    # convert to using unix directory separator\n    dos_path_to_unix(\"${Boost_INCLUDE_DIRS}\" boost_include_dirs)\n    #\n    # convert to just one directory\n    STRING(REGEX REPLACE\n        \"([^ ]+).*\" \"\\\\1\"\n        boost_include_dir \"${boost_include_dirs}\"\n    )\n    #\n    # extract part before last backslash\n    STRING(REGEX REPLACE\n        \"([^ ]*)/[^/ ]*\" \"\\\\1\"\n        boost_prefix \"${boost_include_dir}\"\n    )\n    print_variable(boost_prefix)\n    #\n    # add boost include directories\n    FOREACH(dir ${cmake_install_includedirs})\n        IF( IS_DIRECTORY ${boost_prefix}/${dir} )\n            INCLUDE_DIRECTORIES( ${boost_prefix}/${dir} )\n            MESSAGE(STATUS \"Found ${boost_prefix}/${dir}\")\n        ENDIF( IS_DIRECTORY ${boost_prefix}/${dir} )\n    ENDFOREACH( dir )\n    #\n    # add boost link directories\n    FOREACH(dir ${cmake_install_libdirs})\n        IF( IS_DIRECTORY ${boost_prefix}/${dir} )\n            LINK_DIRECTORIES( ${boost_prefix}/${dir} )\n            MESSAGE(STATUS \"Found ${boost_prefix}/${dir}\")\n        ENDIF( IS_DIRECTORY ${boost_prefix}/${dir} )\n    ENDFOREACH( dir )\nENDIF ( Boost_FOUND )\n# -----------------------------------------------------------------------------\n# ipopt_LIBRARIES and ipopt_LIBRARY_DIRS\nIF( cppad_has_ipopt )\n    #\n    # Set the system environment variable PKG_CONFIG_PATH\n    FOREACH(dir ${cmake_install_libdirs})\n        IF(EXISTS \"${ipopt_prefix}/${dir}/pkgconfig/ipopt.pc\")\n            SET( ENV{PKG_CONFIG_PATH} ${ipopt_prefix}/${dir}/pkgconfig )\n        ENDIF(EXISTS \"${ipopt_prefix}/${dir}/pkgconfig/ipopt.pc\")\n    ENDFOREACH(dir)\n    #\n    # pkg_check_modules(<PREFIX> [REQUIRED] <MODULE> [<MODULE>]*)\n    # ipopt_LIBRARIES      ... only the libraries (w/o the '-l')\n    # ipopt_LIBRARY_DIRS   ... the paths of the libraries (w/o the '-L')\n    pkg_check_modules(ipopt ipopt)\n    IF( NOT ipopt_FOUND )\n        MESSAGE(FATAL_ERROR\n\"For all directories dir in cmake_install_libdirs, cannot find the file\n    ipopt_prefix/dir/pkgconfig/ipopt.pc\nwhere\n    ipopt_prefix = ${ipopt_prefix}\n    cmake_install_libdirs = ${cmake_install_libdirs}\n\"\n        )\n    ENDIF( NOT ipopt_FOUND )\nENDIF( cppad_has_ipopt )\n# =============================================================================\n# Currently building tests as normal executables\n# =============================================================================\n# The CMakeLists.txt file in the specified source directory is processed\n# before the current input file continues beyond this command.\n# add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])\n#\n#\n# is_cppad_lib_dynamic\nIF( cppad_static_lib )\n    SET(is_cppad_lib_dynamic 0)\nELSE( )\n    SET(is_cppad_lib_dynamic 1)\nENDIF( )\nprint_variable(is_cppad_lib_dynamic)\n#\n# CMAKE_EXE_LINKER_FLAGS\nSET(CMAKE_EXE_LINKER_FLAGS \"${cppad_link_flags}\" )\n#\n# Initialize list of tests as empty\nSET(check_depends \"\")\n#\n# directories with no check depends entries\nADD_SUBDIRECTORY(include/cppad)\nADD_SUBDIRECTORY(pkgconfig)\nADD_SUBDIRECTORY(cppad_lib)\n#\nIF( NOT ( \"${check_depends}\" STREQUAL \"\" ) )\n    MESSAGE(FATAL_ERROR \"Error in CMakeLists.txt scripts\")\nENDIF( NOT ( \"${check_depends}\" STREQUAL \"\" ) )\n#\n# directories with check depends entries\nADD_SUBDIRECTORY(val_graph)\nADD_SUBDIRECTORY(example)\nADD_SUBDIRECTORY(introduction)\nADD_SUBDIRECTORY(test_more)\nADD_SUBDIRECTORY(speed)\nIF( cppad_has_ipopt )\n    ADD_SUBDIRECTORY(cppad_ipopt)\nENDIF( cppad_has_ipopt )\n#\n# check, test\nADD_CUSTOM_TARGET(check DEPENDS ${check_depends})\nADD_CUSTOM_TARGET(test DEPENDS ${check_depends})\n# ============================================================================\n# Copy a file to another location and modify its contents.\n# configure_file(InputFile OutputFile [COPYONLY] [ESCAPE_QUOTES] [@ONLY])\nCONFIGURE_FILE(\n    ${CMAKE_CURRENT_SOURCE_DIR}/bin/test_one.sh.in\n    ${CMAKE_CURRENT_SOURCE_DIR}/bin/test_one.sh\n)\n# =============================================================================\n# install procedure\n# =============================================================================\n# install(DIRECTORY dirs... DESTINATION <dir>\n#  [FILE_PERMISSIONS permissions...]\n#  [DIRECTORY_PERMISSIONS permissions...]\n#  [USE_SOURCE_PERMISSIONS] [OPTIONAL]\n#  [CONFIGURATIONS [Debug|Release|...]]\n#  [COMPONENT <component>] [FILES_MATCHING]\n#  [[PATTERN <pattern> | REGEX <regex>]\n#  [EXCLUDE] [PERMISSIONS permissions...]] [...]\n# )\n# Note a trailing / in the source directory name drops the source directory\n# name during the copy.\n#\n# During install copy all the cppad include files to\n# ${cppad_abs_includedir}/cppad\nINSTALL(\n    DIRECTORY \"${CMAKE_CURRENT_SOURCE_DIR}/include/cppad/\"\n    DESTINATION ${cppad_abs_includedir}/cppad\n    FILES_MATCHING PATTERN \"*.hpp\" PATTERN \"xrst\" EXCLUDE\n)\n#\n# During install copy doc direcrory to cppad_abs_docdir/cppad\nIF ( cmake_install_docdir AND include_doc )\n    INSTALL(\n        DIRECTORY \"${CMAKE_SOURCE_DIR}/build/html/\"\n        DESTINATION ${cppad_abs_docdir}/cppad\n    )\nENDIF ( cmake_install_docdir AND include_doc )\n\n# =============================================================================\n# uninstall procedure\n# =============================================================================\nADD_CUSTOM_TARGET(uninstall COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/cppad_uninstall.cmake)\n"
  },
  {
    "path": "COPYING",
    "content": "-----------------------------------------------------------------------------\nCppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-18 Bradley M. Bell\n\n  CppAD is distributed under the terms of the\n               Eclipse Public License Version 2.0.\n\n  This Source Code may also be made available under the following\n  Secondary License when the conditions for such availability set forth\n  in the Eclipse Public License, Version 2.0 are satisfied:\n        GNU General Public License, Version 2.0 or later.\n-----------------------------------------------------------------------------\n"
  },
  {
    "path": "appendix/addon.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin addon app}\n{xrst_spell\n    adcomp\n    addons\n    cg\n    ext\n    includedir\n    libcppad\n    libdir\n    py\n    pycppad\n    tmb\n}\n\nCppAD Addons\n############\n\nName\n****\nEach CppAD addon has a short name which we denote by *name* below,\na longer name *longer* and a *description* :\n\n.. list-table::\n    :widths: auto\n\n    * - *name*\n      - *longer*\n      - *description*\n    * - `tmb <https://github.com/kaskr/adcomp>`_\n      - ``adcomp``\n      - An R Interface to CppAD with Random Effects Modeling Utilities\n    * - `cg <https://github.com/joaoleal/CppADCodeGen/>`_\n      - ``CppADCodeGen``\n      - C++ Source Code Generation of CppAD Derivative Calculations\n    * - `mixed <https://bradbell.github.io/cppad_mixed>`_\n      - ``cppad_mixed``\n      - A C++ Interface to Random Effects Laplace Approximation\n    * - `cppad_py <https://cppad-py.readthedocs.io>`_\n      - ``cppad_py``\n      - A Python Interface to CppAD\n    * - `swig <https://bradbell.github.io/cppad_swig>`_\n      - ``cppad_swig``\n      - A C++ AD Library with a Swig Interface to Perl, Octave, and Python\n         (no longer being developed)\n    * - `pycppad <https://github.com/b45ch1/pycppad>`_\n      - ``pycppad``\n      - A Python Interface to CppAD (no longer being developed)\n\n\nInclude Files\n*************\nIf *includedir* is the directory where the include files are installed,\nthe file\n\n    *includedir* / ``include/cppad/`` *name* . ``hpp``\n\nand the directory\n\n    *includedir* / ``include/cppad/`` *name*\n\nare reserved for use by the *name* addon.\n\nLibrary Files\n*************\nIf *libdir* is the directory where CppAD library files are installed,\nfiles with the name\n\n| |tab| *libdir* / ``libcppad_`` *name* . *ext*\n| |tab| *libdir* / ``libcppad_`` *name* _ *anything* . *ext*\n\nwhere *anything* and *ext* are arbitrary,\nare reserved for use by the *name* addon.\n\nPreprocessor Symbols\n********************\nC++ preprocessor symbols that begin with\n\n    ``CPPAD_`` *NAME* _\n\nwhere *NAME* is a upper-case version of *name* ,\nare reserved for use by the *name* addon.\n\nNamespace\n*********\nThe C++ namespace\n\n    ``CppAD::`` *name*\n\nis reserved for use by the *name* addon.\n\n{xrst_end addon}\n"
  },
  {
    "path": "appendix/appendix.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin appendix app}\n\nAppendix\n########\n\nContents\n********\n{xrst_toc_table\n    appendix/faq.xrst\n    appendix/directory.xrst\n    appendix/glossary.xrst\n    appendix/bib.xrst\n    appendix/wish_list.xrst\n    appendix/whats_new/whats_new.xrst\n    appendix/deprecated/deprecated.xrst\n    test_more/compare_c/CMakeLists.txt\n    appendix/numeric_ad.xrst\n    appendix/addon.xrst\n    appendix/license.xrst\n}\n\n{xrst_end appendix}\n"
  },
  {
    "path": "appendix/bib.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin Bib app}\n{xrst_spell\n    abramowitz\n    andreas\n    bjarne\n    flannery\n    fortran\n    griewank\n    rosenbrock\n    shampine\n    stegun\n    stroustrup\n    teukolsky\n    vetterling\n    vol\n}\n\nBibliography\n############\n\nAbramowitz and Stegun\n*********************\nHandbook of Mathematical Functions,\nDover, New York.\n\nThe C++ Programming Language\n****************************\nBjarne Stroustrup,\nThe C++ Programming Language,\nSpecial ed.,\nAT&T, 2000\n\nEvaluating Derivatives\n**********************\nEvaluating Derivatives: Principles and Techniques of\nAlgorithmic Differentiation,\nAndreas Griewank,\nSIAM,\nPhiladelphia,\n2000\n\nNumerical Recipes\n*****************\nNumerical Recipes in Fortran:\nThe Art of Scientific Computing,\nSecond Edition,\nWilliam H. Press,\nWilliam T. Vetterling,\nSaul, A. Teukolsky,\nBrian R. Flannery,\nCambridge University Press,\n1992\n\nShampine, L.F.\n**************\nImplementation of Rosenbrock Methods,\nACM Transactions on Mathematical Software,\nVol. 8,\nNo. 2,\nJune 1982.\n\n{xrst_end Bib}\n"
  },
  {
    "path": "appendix/deprecated/compare_change.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin CompareChange app}\n\nComparison Changes During Zero Order Forward Mode\n#################################################\n\nSyntax\n******\n| *c* = *f* . ``CompareChange`` ()\n\nSee Also\n********\n:ref:`FunCheck-name`\n\nDeprecated 2015-01-20\n*********************\nThis routine has been deprecated, use :ref:`compare_change-name`\ninstead.\n\nPurpose\n*******\nWe use :math:`F : \\B{R}^n \\rightarrow \\B{R}^m` to denote the\n:ref:`glossary@AD Function` corresponding to *f* .\nThis function may be not agree with the algorithm that was used\nto create the corresponding\nAD of *Base*\n:ref:`operation sequence<glossary@Operation@Sequence>`\nbecause of changes in AD\n:ref:`comparison<Compare-name>` results.\nThe ``CompareChange`` function can be used to detect these changes.\n\nf\n*\nThe object *f* has prototype\n\n    ``const ADFun`` < *Base* > *f*\n\nc\n*\nThe result *c* has prototype\n\n    ``size_t`` *c*\n\nIt is the number of\n``AD`` < *Base* > :ref:`comparison<Compare-name>`\noperations,\ncorresponding to the previous call to :ref:`Forward-name`\n\n    *f* . ``Forward`` (0, *x* )\n\nthat have a different result from\nwhen *F* was created by taping an algorithm.\n\nDiscussion\n**********\nIf *c* is not zero,\nthe boolean values resulting from some of the\n:ref:`comparison operations<Compare-name>` corresponding to *x*\nare different from when the\nAD of *Base*\n:ref:`operation sequence<glossary@Operation@Sequence>` was created.\nIn this case, you may want to re-tape the algorithm with the\n:ref:`independent variables<glossary@Tape@Independent Variable>`\nequal to the values in *x*\n(so AD operation sequence properly represents the algorithm\nfor this value of independent variables).\nOn the other hand, re-taping the AD operation sequence usually takes\nsignificantly more time than evaluation using :ref:`forward_zero-name` .\nIf the functions values have not changed (see :ref:`FunCheck-name` )\nit may not be worth re-taping a new AD operation sequence.\n\n{xrst_end CompareChange}\n"
  },
  {
    "path": "appendix/deprecated/deprecated.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin deprecated app}\n{xrst_spell\n    colpack\n}\n\nCppAD Deprecated API Features\n#############################\n\nContents\n********\n{xrst_toc_table\n    appendix/deprecated/include_deprecated.xrst\n    appendix/deprecated/fun_deprecated.xrst\n    appendix/deprecated/compare_change.xrst\n    include/cppad/core/omp_max_thread.hpp\n    include/cppad/utility/track_new_del.hpp\n    appendix/deprecated/omp_alloc.xrst\n    include/cppad/utility/memory_leak.hpp\n    include/cppad/core/epsilon.hpp\n    cppad_ipopt/src/cppad_ipopt_nlp.hpp\n    include/cppad/core/atomic/one/atomic.hpp\n    include/cppad/core/atomic/two/atomic.hpp\n    example/multi_thread/multi_atomic_two.xrst\n    include/cppad/core/chkpoint_one/chkpoint_one.hpp\n    example/multi_thread/multi_chkpoint_one.xrst\n    include/cppad/core/zdouble.hpp\n    configure\n}\n\nName Changes\n************\n\n.. list-table::\n    :widths: auto\n\n    * - ``CppADCreateUnaryBool``\n      - see Deprecated 2007-07-31 in :ref:`bool_fun-title`\n    * - ``CppADCreateDiscrete``\n      - see Deprecated 2007-07-31 in :ref:`bool_fun-title`\n    * - ``nan`` ( *zero* )\n      - :ref:`nan@nan(zero)`\n    * - ``colpack.star`` coloring\n      - see\n         :ref:`sparse_hes<sparse_hes@coloring@colpack.star Deprecated 2017-06-01>`\n         and\n         :ref:`sparse_hessian<sparse_hessian@work@colpack.star Deprecated 2017-06-01>`\n\n{xrst_end deprecated}\n"
  },
  {
    "path": "appendix/deprecated/fun_deprecated.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin fun_deprecated app}\n\nADFun Object Deprecated Member Functions\n########################################\n\nSyntax\n******\n| *f* . ``Dependent`` ( *y* )\n| *o* = *f* . ``Order`` ()\n| *m* = *f* . ``Memory`` ()\n| *s* = *f* . ``Size`` ()\n| *t* = *f* . ``taylor_size`` ()\n| *u* = *f* . ``use_VecAD`` ()\n| *v* = *f* . ``size_taylor`` ()\n| *w* = *f* . ``capacity_taylor`` ()\n\nPurpose\n*******\nThe ``ADFun`` < *Base* > functions documented here have been deprecated;\ni.e., they are no longer approved of and may be removed from some future\nversion of CppAD.\n\nDependent\n*********\nA recording of and AD of *Base*\n:ref:`operation sequence<glossary@Operation@Sequence>`\nis started by a call of the form\n\n    ``Independent`` ( *x* )\n\nIf there is only one such recording at the current time,\nyou can use *f* . ``Dependent`` ( *y* ) in place of\n\n    *f* . ``Dependent`` ( *x* , *y* )\n\nSee :ref:`Dependent-name` for a description of this operation.\n\nDeprecated 2007-08-07\n=====================\nThis syntax was deprecated when CppAD was extended to allow\nfor more than one ``AD`` < *Base* > recording to be\nactive at one time.\nThis was necessary to allow for multiple threading applications.\n\nOrder\n*****\nThe result *o* has prototype\n\n    ``size_t`` *o*\n\nand is the order of the previous forward operation\nusing the function *f* .\nThis is the highest order of the\n:ref:`Taylor coefficients<glossary@Taylor Coefficient>`\nthat are currently stored in *f* .\n\nDeprecated 2006-03-31\n=====================\nZero order corresponds to function values being stored in *f* .\nIn the future, we would like to be able to erase the function\nvalues so that *f* uses less memory.\nIn this case, the return value of ``Order`` would not make sense.\nUse :ref:`size_order-name` to obtain\nthe number of Taylor coefficients currently stored\nin the ADFun object *f*\n(which is equal to the order plus one).\n\nMemory\n******\nThe result\n\n    ``size_t`` *m*\n\nand is the number of memory units (``sizeof`` ) required for the\ninformation currently stored in *f* .\nThis memory is returned to the system when the destructor for\n*f* is called.\n\nDeprecated 2006-03-31\n=====================\nIt used to be the case that an ADFun object just kept increasing its\nbuffers to the maximum size necessary during its lifetime.\nIt would then return the buffers to the system when its destructor\nwas called.\nThis is no longer the case, an ADFun object now returns memory\nwhen it no longer needs the values stored in that memory.\nThus the ``Memory`` function is no longer well defined.\n\nSize\n****\nThe result *s* has prototype\n\n    ``size_t`` *s*\n\nand is the number of variables in the operation sequence plus the following:\none for a phantom variable with tape address zero,\none for each component of the domain that is a parameter.\nThe amount of work and memory necessary for computing function values\nand derivatives using *f* is roughly proportional to *s* .\n\nDeprecated 2006-04-03\n=====================\nThere are other sizes attached to an ADFun object, for example,\nthe number of operations in the sequence.\nIn order to avoid confusion with these other sizes,\nuse :ref:`fun_property@size_var` to obtain\nthe number of variables in the operation sequence.\n\ntaylor_size\n***********\nThe result *t* has prototype\n\n    ``size_t`` *t*\n\nand is the number of Taylor coefficient orders\ncurrently calculated and stored in the ADFun object *f* .\n\nDeprecated 2006-06-17\n=====================\nThis function has been replaced by :ref:`size_order-name` .\n\nuse_VecAD\n*********\nThe result *u* has prototype\n\n    ``bool`` *u*\n\nIf it is true, the\nAD of *Base*\n:ref:`operation sequence<glossary@Operation@Sequence>`\nstored in *f* contains\n:ref:`VecAD<VecAD@VecAD<Base\\>::reference>` operands.\nOtherwise *u* is false.\n\nDeprecated 2006-04-08\n=====================\nYou can instead use\n\n    *u* = *f* . ``size_VecAD`` () > 0\n\nsize_taylor\n***********\nThe result *v* has prototype\n\n    ``size_t`` *v*\n\nand is the number of Taylor coefficient orders\ncurrently calculated and stored in the ADFun object *f* .\n\nDeprecated 2014-03-18\n=====================\nThis function has been replaced by :ref:`size_order-name` .\n\ncapacity_taylor\n***************\nThe result *w* has prototype\n\n    ``size_t`` *w*\n\nand is the number of Taylor coefficient orders currently allocated\nin the ADFun object *f* .\n\nDeprecated 2014-03-18\n=====================\nThis function has been replaced by :ref:`capacity_order-name` .\n\n{xrst_end fun_deprecated}\n"
  },
  {
    "path": "appendix/deprecated/include_deprecated.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin include_deprecated app}\n\nDeprecated Include Files\n########################\n\nDeprecated 2015-11-30\n*********************\nThe :ref:`utility-name` individual include files have been deprecated; e.g.,\n::\n\n    # include <cppad/runge_45.hpp>\n\nYou must instead use\n::\n\n    # include <cppad/utility.hpp>\n\nor you can include individual utility files; e.g.,\n::\n\n    # include <cppad/utility/runge_45.hpp>\n\nDeprecated 2006-12-17\n*********************\nThe following is a list of deprecated include file names\nand the corresponding names that should be used.\nFor example, if your program uses the deprecated preprocessor command\n::\n\n    # include <CppAD/CppAD.h>\n\nyou must change it to the command\n::\n\n    # include <cppad/cppad.hpp>\n\nThe before 2015-11-30 column contains name used for the include file\nbetween 2006-12-17 and 2015-11-30 (see discussion above).\n\n.. csv-table::\n    :widths: auto\n\n    **Deprecated**,**Before 2015-11-30**,**Documentation**\n    CppAD/CheckNumericType.h,cppad/check_numeric_type.hpp,:ref:`CheckNumericType-name`\n    CppAD/CheckSimpleVector.h,cppad/check_simple_vector.hpp,:ref:`CheckSimpleVector-name`\n    CppAD/CppAD.h,cppad/cppad.hpp,:ref:`user_guide-name`\n    CppAD/CppAD_vector.h,cppad/vector.hpp,:ref:`CppAD_vector-name`\n    CppAD/ErrorHandler.h,cppad/error_handler.hpp,:ref:`ErrorHandler-name`\n    CppAD/LuFactor.h,cppad/lu_factor.hpp,:ref:`LuFactor-name`\n    CppAD/LuInvert.h,cppad/lu_invert.hpp,:ref:`LuInvert-name`\n    CppAD/LuSolve.h,cppad/lu_solve.hpp,:ref:`LuSolve-name`\n    CppAD/NearEqual.h,cppad/near_equal.hpp,:ref:`NearEqual-name`\n    CppAD/OdeErrControl.h,cppad/ode_err_control.hpp,:ref:`OdeErrControl-name`\n    CppAD/OdeGear.h,cppad/ode_gear.hpp,:ref:`OdeGear-name`\n    CppAD/OdeGearControl.h,cppad/ode_gear_control.hpp,:ref:`OdeGearControl-name`\n    CppAD/Poly.h,cppad/poly.hpp,:ref:`Poly-name`\n    CppAD/PowInt.h,cppad/pow_int.hpp,:ref:`pow_int-name`\n    CppAD/RombergMul.h,cppad/romberg_mul.hpp,:ref:`RombergMul-name`\n    CppAD/RombergOne.h,cppad/romberg_one.hpp,:ref:`RombergOne-name`\n    CppAD/Rosen34.h,cppad/rosen_34.hpp,:ref:`Rosen34-name`\n    CppAD/Runge45.h,cppad/runge_45.hpp,:ref:`Runge45-name`\n    CppAD/SpeedTest.h,cppad/speed_test.hpp,:ref:`SpeedTest-name`\n    CppAD/TrackNewDel.h,cppad/track_new_del.hpp,:ref:`track_new_del-name`\n\n{xrst_end include_deprecated}\n"
  },
  {
    "path": "appendix/deprecated/omp_alloc.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin omp_alloc app}\n\nA Quick OpenMP Memory Allocator Used by CppAD\n#############################################\n\nSyntax\n******\n| ``# include <cppad/omp_alloc.hpp>``\n\nPurpose\n*******\nThe C++ ``new`` and ``delete`` operators are thread safe,\nbut this means that a thread may have to wait for a lock on these operations.\nOnce memory is obtained for a thread, the ``omp_alloc`` memory\nallocator keeps that memory :ref:`omp_available-name` for the thread so that\nit can be re-used without waiting for a lock.\nAll the CppAD memory allocations use this utility.\nThe :ref:`omp_free_available-name` function should be used to return memory\nto the system (once it is no longer required by a thread).\n\nInclude\n*******\nThe routines in sections below are defined by ``cppad/omp_alloc.hpp`` .\nThis file is included by\n``cppad/cppad.hpp`` , but it can also be included separately with out\nthe rest of the ``CppAD`` .\n\nDeprecated 2011-08-23\n*********************\nUse :ref:`thread_alloc-name` instead.\n\nContents\n********\n{xrst_toc_table\n    include/cppad/utility/omp_alloc.hpp\n}\n\n{xrst_end omp_alloc}\n*/\n"
  },
  {
    "path": "appendix/directory.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin directory app}\n{xrst_spell\n    chkpoint\n    ipopt\n    jit\n    json\n    omh\n    pkgconfig\n}\n\nDirectory Structure\n###################\nA brief description of each of the CppAD directories is provided below:\n\nDistribution Directory\n**********************\nThe following table lists the sub-directories of the\n:ref:`download@Distribution Directory` :\n\n.. list-table::\n    :widths: auto\n\n    * - ``bin``\n      - Scripts used for CppAD development.\n    * - ``bug``\n      - Used to create a simple CppAD bug report or test.\n    * - ``build``\n      - Used to build the libraries, examples, and tests.\n    * - ``cmake``\n      - cmake macro files.\n    * - ``cppad_ipopt``\n      - Example and tests for the deprecated cppad_ipopt library.\n    * - ``cppad_lib``\n      - Source code corresponding to the CppAD library.\n    * - ``example``\n      - Source code for the CppAD examples.\n    * - ``external``\n      - Used to build optional packages; see :ref:`get_optional.sh-name`\n    * - ``include``\n      - The CppAD include directory.\n    * - ``introduction``\n      - Source code for the CppAD introduction.\n    * - ``omh``\n      - Contains files that are only used for documentation.\n    * - ``pkgconfig``\n      - Contains the CppAD pkg-config information.\n    * - ``speed``\n      - The CppAD speed tests.\n    * - ``test_more``\n      - Tests that are not part of the documentation.\n\nExample Directory\n*****************\nThe following table lists the sub-directories of the ``example``\ndirectory.\n\n.. list-table::\n    :widths: auto\n\n    * - ``abs_normal``\n      - examples using :ref:`abs_normal<example_abs_normal-name>` representation of non-smooth functions.\n    * - ``atomic_four``\n      - :ref:`atomic_four-title` function examples.\n    * - ``atomic_three``\n      - :ref:`atomic_three-title` function examples.\n    * - ``atomic_two``\n      - :ref:`atomic_two-title` examples not yet converted to use ``atomic_four`` .\n    * - ``chkpoint_two``\n      - :ref:`chkpoint_two-title` examples\n    * - ``code_gen_fun``\n      - :ref:`code_gen_fun-title` examples\n    * - ``general``\n      - general purpose examples.\n    * - ``get_started``\n      - a good place to get started using CppAD.\n    * - ``ipopt_solve``\n      - :ref:`ipopt_solve-title` examples.\n    * - ``jit``\n      - :ref:`example_jit-title`\n    * - ``json``\n      - :ref:`json_ad_graph-title` examples\n    * - ``multi_thread``\n      - CppAD :ref:`multi_threading<multi_thread-name>` examples.\n    * - ``optimize``\n      - examples using the :ref:`optimize-name` operation.\n    * - ``print_for``\n      - examples that used the :ref:`PrintFor-name` operation.\n    * - ``sparse``\n      - examples using :ref:`sparsity_patterns<sparsity_pattern-name>` and\n         :ref:`sparse_derivatives<sparse_derivative-name>` .\n    * - ``utility``\n      - example using the CppAD :ref:`utilities<utility-name>` .\n\n{xrst_end directory}\n"
  },
  {
    "path": "appendix/faq.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin Faq app}\n{xrst_spell\n    github\n}\n\nFrequently Asked Questions and Answers\n######################################\n\nAssignment and Independent\n**************************\nWhy does the code sequence\n\n| |tab| ``Independent`` ( *u* );\n| |tab| *v* = *u* [0];\n\nbehave differently from the code sequence\n\n| |tab| *v* = *u* [0];\n| |tab| ``Independent`` ( *u* );\n\nBefore the call to :ref:`Independent-name` ,\n*u* [0] is a :ref:`glossary@Parameter`\nand after the call it is a variable.\nThus in the first case, *v* is a variable\nand in the second case it is a parameter.\n\nBugs\n****\nWhat should I do if I suspect that there is a bug in CppAD ?\n\n#. The first step is to check currently open\n   `issues <https://github.com/coin-or/CppAD/issues>`_ on github.\n   If it is an open issue, and you want to hurry it along, you can add\n   a comment to the effect that it is holding you up.\n#. The next step is to search the\n   :ref:`whats_new-name` sections for mention of a related bug fix\n   between the date of the version you are using and the current date.\n   It the bug has been fixed, obtain a more recent release that has the fix\n   and see if that works for you.\n#. The next step is to\n   create a simple demonstration of the bug;\n   see the file ``bug/template.sh`` for a template that you can\n   edit for that purpose.\n   The smaller the program, the better the bug report.\n#. The next step is open a new issue on github and provide your simple\n   example so that the problem can be reproduced.\n\nCompareChange\n*************\nIf you attempt to use the\n:ref:`CompareChange-name`\nfunction when ``NDEBUG`` is true,\nyou will get an error message stating that\n``CompareChange`` is not a member of the\n:ref:`ADFun-name` template class.\n\nComplex Types\n*************\nWhich of the following complex types is better:\n\n| |tab| ``AD< std::complex<`` *Base* > >\n| |tab| ``std::complex< AD<`` *Base* > >\n\nThe :ref:`complex abs function<abs@Complex Types>` is differentiable\nwith respect to its real and imaginary parts,\nbut it is not complex differentiable.\nThus one would prefer to use\n\n    ``std::complex< AD<`` *Base* > >\n\nOn the other hand, the C++ standard only specifies\n``std::complex<`` *Type* > where *Type* is\n``float`` , ``double`` , or ``lone double`` .\nThe effect of instantiating the template complex for any other type\nis unspecified.\n\nExceptions\n**********\nWhy, in all the examples, do you pass back a boolean variable instead\nof throwing an exception ?\n\nThe examples are also used to test the correctness of CppAD\nand to check your installation.\nFor these two uses, it is helpful to run all the tests\nand to know which ones failed.\nThe actual code in CppAD uses the :ref:`ErrorHandler-name` utility\nto signal exceptions.\nSpecifications for redefining this action are provided.\n\nIndependent Variables\n*********************\nIs it possible to evaluate the same tape recording with different values\nfor the independent variables ?\n\nYes (see :ref:`forward_zero-name` ).\n\nMatrix Inverse\n**************\nIs it possible to differentiate (with respect to the matrix elements)\nthe computation of the inverse of a matrix\nwhere the computation of the inverse uses pivoting ?\n\nLuSolve\n=======\nThe example routine :ref:`LuSolve-name` can be used to do this\nbecause the inverse is a special case of the solution of linear equations.\nThe examples\n:ref:`jac_lu_det.cpp-name` and :ref:`hes_lu_det.cpp-name`\nuse LuSolve to compute derivatives of the\ndeterminant with respect to the components of the matrix.\n\nAtomic Operation\n================\nOne can also do this by making the inversion of the matrix an atomic operation;\ne.g., see :ref:`atomic_two_eigen_mat_inv.cpp-name` .\n\nMode: Forward or Reverse\n************************\nWhen evaluating derivatives,\none always has a choice between\nforward and reverse mode.\nHow does one decide which mode to use ?\n\nIn general, the best mode depends on the number of domain and range\ncomponents in the function that your are differentiating.\nEach call to :ref:`Forward-name` computes the derivative of all\nthe range directions with respect to one domain direction.\nEach call to :ref:`Reverse-name` computes the derivative of one\nrange direction with respect to all the domain directions.\nThe times required for (speed of)\ncalls ``Forward`` and ``Reverse`` are about equal.\nThe :ref:`fun_property@Parameter`\nfunction can be used to quickly determine that\nsome range directions have derivative zero.\n\nNamespace\n*********\n\nTest Vector Preprocessor Symbol\n===============================\nWhy do you use ``CPPAD_TESTVECTOR`` instead of a namespace for\nthe CppAD :ref:`testvector-name` class ?\n\nThe preprocessor symbol ``CPPAD_TESTVECTOR`` ( see :ref:`testvector-name` )\ndetermines which\n:ref:`SimpleVector-name` template class is used for extensive testing.\nThe default definition for ``CPPAD_TESTVECTOR`` is the\n:ref:`CppAD::vector<CppAD_vector-name>` template class, but it can be changed.\nNote that all the preprocessor symbols that are defined or used\nby CppAD begin with either ``CPPAD``\n(some old deprecated symbols begin with ``CppAD`` ).\n\nSpeed\n*****\nHow do I get the best speed performance out of CppAD ?\n\nNDEBUG\n======\nYou should compile your code with optimization, without debugging,\nand with the preprocessor symbol ``NDEBUG`` defined.\n(The :ref:`speed_cppad-name` tests do this.)\nNote that defining ``NDEBUG``\nwill turn off all of the error checking and reporting that\nis done using :ref:`ErrorHandler-name` .\n\nOptimize\n========\nIt is also possible that preforming a tape\n:ref:`optimization<optimize-name>` will improve the speed of evaluation\nmore than the time required for the optimization.\n\nMemory Allocation\n=================\nYou may also increase execution speed\nby calling ``hold_memory`` with\n:ref:`ta_hold_memory@value` equal to true.\n\nTape Storage: Disk or Memory\n****************************\nDoes CppAD store the tape on disk or in memory ?\n\nCppAD uses memory to store a different tape for recording operations\nfor each ``AD`` < *Base* > type that is used.\nIf you have a very large number calculations that are recorded\non a tape, the tape will keep growing to hold the necessary information.\nEventually, virtual memory may be used to store the tape\nand the calculations may slow down because of necessary disk access.\n\n{xrst_end Faq}\n"
  },
  {
    "path": "appendix/glossary.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin glossary app}\n{xrst_spell\n    is is\n}\n\nGlossary\n########\n\nAD Function\n***********\nGiven an :ref:`ADFun-name` object *f*\nthere is a corresponding\nAD of *Base* :ref:`operation sequence<glossary@Operation@Sequence>` .\nThis operation sequence\ndefines a function\n:math:`F : \\B{R}^n \\rightarrow \\B{R}^m`\nwhere :math:`\\B{R}` is the space corresponding to objects of type\n*Base* (usually the real numbers),\n*n* is the size of the :ref:`fun_property@Domain` space, and\n*m* is the size of the :ref:`fun_property@Range` space.\nWe refer to :math:`F` as the AD function corresponding to\nthe operation sequence stored in the object *f* .\n(See the :ref:`FunCheck discussion<FunCheck@Discussion>` for\npossible differences between :math:`F(x)` and the algorithm that defined\nthe operation sequence.)\n\nAD of Base\n**********\nAn object is called an AD of *Base* object its type is\neither ``AD`` < *Base* >\n(see the default and copy :ref:`constructors<ad_ctor-name>`\nor ``VecAD`` < *Base* >:: ``reference`` (see :ref:`VecAD-name` )\nfor some *Base* type.\n\nAD Type Above Base\n******************\nIf *Base* is a type,\nan AD type above *Base*\nis the following sequence of types:\n\n    ``AD`` < *Base* > , ``AD< AD<`` *Base* > > , ``AD< AD< AD<`` *Base* > > > , ...\n\nBase Function\n*************\nA function :math:`f : \\B{R} \\rightarrow \\B{R}`\nis referred to as a *Base* function,\nif *Base* is a C++ type that represent elements of\nthe domain and range space of *f* .\n\nBase Type\n*********\nIf *x* is an ``AD`` < *Base* > object,\n*Base* is referred to as the base type for *x* .\n\nElementary Vector\n*****************\nThe *j*-th elementary vector :math:`e^j \\in \\B{R}^m` is defined by\n\n.. math::\n\n    e_i^j = \\left\\{ \\begin{array}{ll}\n        1 & {\\rm if} \\; i = j \\\\\n        0 & {\\rm otherwise}\n    \\end{array} \\right.\n\nOperation\n*********\n\nAtomic\n======\nAn atomic *Type* operation is an operation that\nhas a *Type* result and is not made up of other\nmore basic operations.\n\nSequence\n========\nA sequence of atomic *Type* operations\nis called a *Type* operation sequence.\nA sequence of atomic :ref:`glossary@AD of Base` operations\nis referred to as an AD of *Base* operation sequence.\nThe abbreviated notation operation sequence is often used\nwhen it is not necessary to specify the type.\n\nDependent\n=========\nSuppose that *x* and *y* are *Type* objects and\nthe result of\n\n    *x* < *y*\n\nhas type ``bool`` (where *Type* is not the same as ``bool`` ).\nIf one executes the following code\n\n| |tab| ``if`` ( *x* < *y*  )\n| |tab| |tab| *y* = ``cos`` ( *x* );\n| |tab| ``else``\n| |tab| |tab| *y* = ``sin`` ( *x* );\n\nthe choice above depends on the value of *x* and *y*\nand the two choices result in a different *Type* operation sequence.\nIn this case, we say that the *Type* operation sequence depends\non *x* and *y* .\n\nIndependent\n===========\nSuppose that *i* and *n* are ``size_t`` objects,\nand *x* [ *i* ] , *y* are *Type* objects,\nwhere *Type* is different from ``size_t`` .\nThe *Type* sequence of operations corresponding to\n\n| |tab| *y* = *Type* (0);\n| |tab| ``for`` ( *i* = 0; *i* < *n* ; *i* ++)\n| |tab| |tab| *y* += *x* [ *i* ];\n\ndoes not depend on the value of *x* or *y* .\nIn this case, we say that the *Type* operation sequence\nis independent of *y* and the elements of *x* .\n\nParameter\n*********\n\nConstant\n========\nAn ``AD`` < *Base* > object *u* is a constant parameter if\nits value does not depend on the value of\nthe :ref:`Independent-name` variable vector\nor the :ref:`Independent@dynamic` parameter vector\nfor an :ref:`active tape<glossary@Tape@Active>` .\nIf *u* is a constant parameter,\n:ref:`Constant(u)<con_dyn_var@Constant>` returns true,\n:ref:`Parameter(u)<con_dyn_var@Parameter>` returns true,\n:ref:`Dynamic(u)<con_dyn_var@Dynamic>` returns false, and\n:ref:`Variable(u)<con_dyn_var@Variable>` returns false.\n\nDynamic\n=======\nAn ``AD`` < *Base* > object *u* is a dynamic parameter if\nits value does not depend on the value of\nthe :ref:`Independent-name` variable vector, but its value does depend\non the :ref:`Independent@dynamic` parameter vector,\nfor an :ref:`active tape<glossary@Tape@Active>` .\nIf *u* is a dynamic parameter, the function\n:ref:`Dynamic(u)<con_dyn_var@Dynamic>` returns true\n:ref:`Parameter(u)<con_dyn_var@Parameter>` returns true,\n:ref:`Constant(u)<con_dyn_var@Constant>` returns false, and\n:ref:`Variable(u)<con_dyn_var@Variable>` returns false.\n\nRow-major Representation\n************************\nA :ref:`SimpleVector-name` *v* is a row-major representation of a matrix\n:math:`M \\in \\B{R}^{m \\times n}` if *v* . ``size`` () == *m* * *n* and\nfor :math:`i = 0 , \\ldots , m-1`, :math:`j = 0 , \\ldots , n-1`\n\n.. math::\n\n    M_{i,j} = v[ i \\times n + j ]\n\nSparsity Pattern\n****************\nSuppose that :math:`A \\in \\B{R}^{m \\times n}` is a sparse matrix.\nCppAD has several ways to specify the elements of :math:`A`\nthat are possible non-zero.\n\nRow and Column Index Vectors\n============================\nA pair of non-negative integer vectors :math:`r`, :math:`c`\nare a sparsity pattern for :math:`A`\nif for every non-zero element :math:`A_{i,j}`,\nthere is a :math:`k` such that :math:`i = r_k` and :math:`j = c_k`.\nFurthermore, for every :math:`\\ell \\neq k`,\neither :math:`r_\\ell \\neq r_k` or :math:`c_\\ell \\neq c_k`.\n\nBoolean Vector\n==============\nA boolean vector :math:`b`, of length :math:`m \\times n`,\nis a sparsity pattern for :math:`A`\nif for every non-zero element :math:`A_{i,j}`,\n:math:`b_{i \\times n + j}` is true.\n\nVector of Sets\n==============\nA vector of sets :math:`s` of positive integers, of length :math:`m`,\nis a sparsity pattern for :math:`A`\nif for every non-zero element :math:`A_{i,j}`, :math:`j \\in s_i`.\n\nTape\n****\n\nActive\n======\nA new tape is created and becomes active\nafter each call of the form (see :ref:`Independent-name` )\n\n    ``Independent`` ( *x* )\n\nAll operations that depend on the elements of *x* are\nrecorded on this active tape.\n\nInactive\n========\nThe :ref:`operation sequence<glossary@Operation@Sequence>`\nstored in a tape can be transferred to a function object using the syntax\n\n| |tab| ``ADFun`` < *Base* > *f* ( *x* , *y* )\n| |tab| *f* . ``Dependent`` ( *x* , *y* )\n\nsee :ref:`fun_construct-name` .\nAfter such a transfer, the tape becomes inactive.\nThe tape becomes inactive, without storing the operation sequence,\nafter a call to :ref:`abort_recording-name` .\n\nIndependent Variable\n====================\nWhile the tape is active, we refer to the elements of *x*\nas the independent variables for the tape.\nWhen the tape becomes inactive,\nthe corresponding objects become\n:ref:`constants<glossary@Parameter@Constant>` .\n\nVariables\n=========\nWhile the tape is active, we use the term variables for any scalar\nwhose value depends on the independent variables for the tape.\nWhen the tape becomes inactive,\nthe corresponding objects become\n:ref:`constants<glossary@Parameter@Constant>` .\n\nTaylor Coefficient\n******************\nSuppose :math:`X : \\B{R} \\rightarrow \\B{R}^n` is a\nis :math:`p` times continuously differentiable function\nin some neighborhood of zero.\nFor :math:`k = 0 , \\ldots , p`,\nwe use the column vector :math:`x^{(k)} \\in \\B{R}^n` for the *k*-th order\nTaylor coefficient corresponding to :math:`X`\nwhich is defined by\n\n.. math::\n\n    x^{(k)} = \\frac{1}{k !} \\Dpow{k}{t} X(0)\n\nIt follows that\n\n.. math::\n\n    X(t) = x^{(0)} + x^{(1)} t + \\cdots + x^{(p)} t^p  + R(t)\n\nwhere the remainder :math:`R(t)` divided by :math:`t^p`\nconverges to zero and :math:`t` goes to zero.\n\nVariable\n********\nAn ``AD`` < *Base* > object *u* is a variable if\nits value depends on an independent variable vector for\na currently :ref:`active tape<glossary@Tape@Active>` .\nIf *u* is a variable,\n:ref:`Variable(u)<con_dyn_var@Variable>` returns true,\n:ref:`Constant(u)<con_dyn_var@Constant>` returns false,\n:ref:`Dynamic(u)<con_dyn_var@Dynamic>` returns false, and\n:ref:`Parameter(u)<con_dyn_var@Parameter>` returns false.\nFor example,\ndirectly after the code sequence\n\n| |tab| ``Independent`` ( *x* );\n| |tab| ``AD<double>`` *u* = *x* [0];\n\nthe ``AD<double>`` object *u* is currently a variable.\nDirectly after the code sequence\n\n| |tab| ``Independent`` ( *x* );\n| |tab| ``AD<double>`` *u* = *x* [0];\n| |tab| *u*  = 5;\n\n*u*  is currently a\n:ref:`glossary@Parameter@Constant` parameter,\nnot a dynamic parameter or a variable.\n\nNote that we often drop the word currently and\njust refer to an ``AD`` < *Base* > object as a variable\nor parameter.\n\n{xrst_end glossary}\n"
  },
  {
    "path": "appendix/license.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin License app}\n\nYour License for the CppAD Software\n###################################\n\nYour License\n************\n{xrst_literal\n    COPYING\n}\n\nEclipse Public License Version 2.0\n**********************************\n\n{xrst_literal\n    epl-2.0.txt\n}\n\n{xrst_end License}\n"
  },
  {
    "path": "appendix/numeric_ad.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin numeric_ad app}\n\nSome Numerical AD Utilities\n###########################\nThe routines listed below are numerical utilities that are\ndesigned to work with CppAD in particular.\n\nContents\n********\n{xrst_toc_table\n    include/cppad/core/bender_quad.hpp\n    include/cppad/core/opt_val_hes.hpp\n    include/cppad/core/lu_ratio.hpp\n}\n\n{xrst_end numeric_ad}\n"
  },
  {
    "path": "appendix/whats_new/2003.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin 2003 app}\n{xrst_spell\n    ddouble\n    def\n    dodds\n    faq\n    geq\n    hess\n    indvar\n    ini\n    leq\n    mak\n    valarray\n}\n\nRelease Notes for 2003\n######################\n\nmm-dd\n*****\n\n12-24\n=====\nSome references to ``double`` should have been references\nto the :ref:`glossary@Base Type`\n(in reverse mode and in the ``Grad/`` and ``Hess`` functions).\nThis has been fixed.\n\n12-22\n=====\nThe preprocessor symbol ``WIN32`` was being used to determine\nif one was using Microsoft's C++ compiler.\nThis symbol is predefined by the\n`MinGW <http://www.mingw.org>`_ version of the GNU C++ compiler\nand hence CppAD had errors during installation using MinGW.\nThis has been fixed by using the preprocessor symbol\n``_MSC_VER`` to determine if\none is using the Microsoft C++ compiler.\n\n12-14\n=====\nThe extended system solvers ``OdeOne`` and ``OdeTwo`` have\nbeen removed from the distribution.\nIn addition, the interface to the ODE solvers have been simplified.\n\n12-13\n=====\nRemove the ``CppADCreateTape`` macro\nand have the tapes created and grow automatically.\n\n12-12\n=====\nThe old method where one directly accesses the tape has been removed and the\nfollowing functions are no longer available:\n\n| |tab| |tab| ``size_t`` *TapeName* . ``Independent`` ( ``AD`` < *Base* > & *indvar* )\n| |tab| |tab| ``size_t`` *TapeName* . ``Record`` ( ``size_t`` *order* )\n| |tab| |tab| ``size_t`` *TapeName* . ``Stop`` ( ``void`` )\n| |tab| |tab| ``bool Dependent`` ( ``const AD`` < *Base* > & *var* ) ``const``\n| |tab| |tab| ``bool`` *TapeName* . ``Dependent`` ( ``const AD`` < *Base* > & *var* ) ``const``\n| |tab| |tab| ``size_t`` *TapeName* . ``Total`` ( ``void`` ) ``const``\n| |tab| |tab| ``size_t`` *TapeName* . ``Required`` ( ``void`` ) ``const``\n| |tab| |tab| ``size_t`` *TapeName* . ``Erase`` ( ``void`` )\n| |tab| |tab| ``TapeState`` *TapeName* . ``State`` ( ``void`` ) ``const``\n| |tab| |tab| ``size_t`` *TapeName* . ``Order`` ( ``void`` ) ``const``\n| |tab| |tab| ``size_t`` *TapeName* . ``Required`` ( ``void`` ) ``const``\n| |tab| |tab| ``bool Parameter`` ( ``CppADvector< AD<`` *Base* > > & *u* )\n| |tab| |tab| *TapeName* . ``Forward`` ( *indvar* )\n| |tab| |tab| *TapeName* . ``Reverse`` ( *var* )\n| |tab| |tab| *TapeName* . ``Partial`` ( *var* )\n| |tab| |tab| *TapeName* . ``ForwardTwo`` ( *indvar* )\n| |tab| |tab| *TapeName* . ``ReverseTwo`` ( *var* )\n| |tab| |tab| *TapeName* . ``PartialTwo`` ( *var* )\n\n12-10\n=====\nThe change on :ref:`2003@mm-dd@12-01` make the taping process simpler\nif one does not directly access\n``CppADCreateTape`` .\nThe :ref:`examples<example-name>` were changed to not use\n*TapeName* .\nThe following examples were skipped because\nthey document the functions that access *TapeName* :\n``DefFun.cpp`` ,\n``For.cpp`` ,\n``for_two.cpp`` ,\n``Rev.cpp`` , and\n``rev_two.cpp`` .\n\n12-05\n=====\nThere was a bug in\n*f* . ``Rev`` and\n*f* . ``RevTwo`` and\nwhen two dependent variables were always equal and shared\nthe same location in the tape.\nThis has been fixed.\n\nThe ODE Example was changed to tape the solution\n(and not use ``OdeOne`` or ``OdeTwo`` ).\nThis is simpler to use and\nthe resulting speed tests gave much faster results.\n\n12-01\n=====\nThe following function has been added:\n\n    ``void Independent`` ( ``const CppADvector`` < *Base* > & *x* )\n\nwhich will declare the independent variables and begin recording\n``AD`` < *Base* > operations\n(see :ref:`Independent-name` ).\nThe :ref:`ADFun-name` constructor was modified so that it\nstops the recording and erases that tape as well as creates the\n:ref:`ADFun-name` object.\nIn addition, the tape no longer needs to be specified in the constructor.\n\n11-21\n=====\nAdd ``StiffZero`` to set of ODE solvers.\n\n11-20\n=====\nThe ``AbsGeq`` and ``LeqZero`` in\n:ref:`LuSolve-name` were changed to template functions so they could have\ndefault definitions in the case where the ``<=`` and ``>=``\noperators are defined.\nThis made the ``double`` and ``AD<double>`` use of\n``LuSolve`` simpler because the user need not worry about these functions.\nOn the other hand, it made the ``std::complex``\nand ``AD<std::complex>`` use of\n``LuSolve`` more complex.\n\nThe member function names for the\n*fun* argument to ODE were changed from\n*fun* . ``f`` to\n*fun* . ``Ode``\nand from\n*fun* . ``g`` to\n*fun* . ``Ode_ini`` .\n\n11-16\n=====\nThe table of contents was reorganized\nto provide a better grouping of the documentation.\n\nThe :ref:`LuSolve-name` utility is now part of the distribution\nand not just an example; i.e.,\nit is automatically included by\n``cppad.hpp`` .\n\n11-15\n=====\nThe\nODE solver was modified so that it can\nbe used with any type (not just an AD type.\nThis was useful for the speed testing.\nIt is also useful for determining how the integrator\nsteps should be before starting the tape.\n\nThe template argument *Type* was changed to\n*Base* where ever it was the\n:ref:`glossary@Base Type` of an AD class.\n\n11-14\n=====\nAn\n``speed_cppad/OdeSpeed.cpp/`` test was added\nand some changes were made to the\nODE interface in order to make it faster.\nThe most significant change was in the specifications for\nthe ODE function object *fun* .\n\n11-12\n=====\nThe user defined unary function example\n``example/UnaryFun.cpp`` was incorrect.\nIt has been corrected and extended.\n\n11-11\n=====\nThe :ref:`CppAD::vector<CppAD_vector-name>` template class is now\nused where the ``std::vector`` template class was previously used.\nYou can replace the ``CppAD::vector`` class\nwith a vector template class of your choosing during the\n:ref:`Install-name` procedure.\n\n11-06\n=====\nThe documentation for\n:ref:`taping derivative calculations<mul_level-name>` was improved\nas well as the corresponding example.\nIn order to make this simpler,\nthe example tape name ``DoubleTape`` was changed to ``ADdoubleTape``\n(and the other example tape names were also changed).\n\n11-04\n=====\nThe ODE utility was changed from an example to\npart of the distribution.\nIn addition, it was extended so that it now supports taping the\nsolution of the differential equations (case *order* equal zero)\nor solving the extended set of differential equations\nfor both first and second derivatives (cases *order* equal\none and two).\nIn addition, an initial condition that depends on the parameter\nvalues is also allowed.\n\n11-02\n=====\nIt is now legal to differentiate a\n:ref:`glossary@Parameter`\nwith respect to an\n:ref:`glossary@Tape@Independent Variable`\n(parameter derivatives are always equal to zero).\nThis is an extension of the\n``Reverse`` ,\n``Partial`` ,\n``ReverseTwo`` , and\n``PartialTwo``\nfunctions.\n\n10-21\n=====\nAll the ``CppAD`` include files,\nexcept ``cppad.hpp`` were moved into an ``include`` subdirectory.\n\n10-16\n=====\nThe :ref:`ADFun-name` template class was added so that one can save\na tape recording and use it as a differentiable function.\nThe ``ADFun`` functions supports directional derivatives in both\n:ref:`Forward-name` and :ref:`Reverse-name` mode where as the\ntape only supports partial derivatives.\n\n10-14\n=====\nThe ``sqrt`` function was added to the\n:ref:`unary_standard_math-name` functions.\nIn addition, a definition of the power function for the types\n``float`` and ``double``\nwas automatically included in the ``CppAD`` namespace.\n\nThe :ref:`Value-name` function was changed so that it can\nbe called when the tape is in the Empty state.\n\n10-10\n=====\nThe ``atan`` function was added to the\n:ref:`unary_standard_math-name` functions.\n\n10-06\n=====\nIn the notation below, *zero* and *one*\nare parameters that are exactly equal to zero and one.\nIf the variables *z* and *x*\nwere related in any of the following ways,\nthey share can share the same record on the tape\nbecause they will have the same derivatives.\n\n| |tab| *z* = *x* + *zero* *z* = *x* * *one*\n| |tab| *z* = *zero* + *x* *z* = *one* * *x*\n| |tab| *z* = *x* ``-`` *zero* *z* = *x* / *one*\n\nFurthermore, in the following cases, the result\n*z* is a parameter (equal to zero)\nand need not be recorded in the tape:\n\n| |tab| *z* = *x* * *zero* *z* = *zero* / *x*\n| |tab| *z* = *zero* * *x*\n\nThe\n:ref:`arithmetic operators<Arithmetic-name>` were\nall checked to make sure they did not add to the tape\nin these special cases.\nThe total record count for the program in the Example directory\nwas 552 before this change\nand 458 after.\n\n10-05\n=====\nThe process of converting the tape to operators was completed.\nIn order to make this conversion, the binary user defined\nfunctions were removed.\n(Bob Goddard\nsuggested a very nice way to keep the unary functions.)\nAnother significant change was made to the user interface during this procedure,\nthe standard math library functions\nare now part of the CppAD distribution and not defined by the user.\n\nThe function *TapeName* . ``Total`` was added\nto make it easy to track how many tape records are used by\nthe test suite.\nThis will help with future optimization of the CppAD recording process.\n\nThere was a bug\n(found by `Mike Dodds <mailto:magister@u.washington.edu>`_)\nin the error checking of the\n*TapeName.Erase* function.\nIf ``Erase`` was called twice in a row,\nand ``NDEBUG`` was false during compilation,\nthe program would abort.\nThis has been fixed.\n\n09-30\n=====\nA process of changing the tape from storing partial derivatives to\nstoring operators has been started.\nThis will make the tape smaller and it will enable the computation\nof higher derivatives with out having to tape the tape\n(see :ref:`mul_level-name` ).\nThe Add, Subtract, Multiply and Divide operators have been converted.\nThe user defined functions are presenting some difficulties,\nso this process has not yet been completed.\n\nThere was a bug in reverse mode when an dependent variable\nwas exactly equal to an independent variable.\nIn this case, it was possible for it to be located\nbefore other of the independent variables on the tape.\nThese other independent variable partials were not initialized\nto zero before the reverse calculation and hence had what ever\nvalue was left by the previous mode calculation.\nThis has been fixed and the\n``Eq.cpp`` example has been changed to test for this case.\n\nThe following tape functions were changed to be declared\n``const`` because they do not modify the tape in any way:\n``State`` ,\n``Order`` ,\n``Required`` ,\n``Dependent`` , and\n:ref:`con_dyn_var@Parameter` .\n\n09-20\n=====\nThe functions ``Grad`` and ``Hess`` were\nchanged to use function objects\ninstead of function pointers.\n\n09-19\n=====\nThe higher order constructors (in standard valarray) were removed from the\nODE example in order to avoid memory allocation of temporaries\n(and hence increase speed).\nIn addition, the function objects in the\nODE examples were changed to be ``const`` .\n\n09-18\n=====\nAn ordinary differential equation solver was added.\nIn addition,\nthe extended system to differentiate the solution was included.\n\n09-15\n=====\nThe linked list of AD variables was not being maintained correctly\nby the AD destructor.\nThis was fixed by have the destructor use ``RemoveFromVarList``\nto remove variables from the list.\n(``RemoveFromVarList`` is a private AD member function\nnot visible to the user.)\n\n09-14\n=====\nThere is a new Faq question about evaluating derivatives at multiple\nvalues for the\n:ref:`Faq@Independent Variables` .\n\n09-13\n=====\nAn example that uses\n``AD< AD<double> >``\nto compute higher derivatives was added.\n\nThe name ``GaussEliminate`` was changed to\n:ref:`LuSolve-name` to better reflect the solution method.\n\n09-06\n=====\nChanged the\n:ref:`get_started.cpp-name` and :ref:`complex_poly.cpp-name` examples\nso they use a template function with both base type and AD type arguments.\n(The resulting code is simpler and a good use of templates.)\n\n09-05\n=====\nA :ref:`getting started<get_started.cpp-name>`\nexample was added and the organization\nof the :ref:`Examples<example-name>` was changed.\n\n09-04\n=====\nThe ``AbsOfDoubleNotDefine`` flag is no longer used\nand it was removed from the Windows\n:ref:`Install-name` instructions.\n\nThe 03-09-03 distribution did not have the proper date\nattached to it.\nThe distribution script has been changed so that attaching\nthe proper date is automated\n(i.e., this should not happen again).\n\nA :ref:`faq-title` section was started.\n\n09-03\n=====\nAdded the\n:ref:`Value-name` function which returns\nthe :ref:`glossary@Base Type` value\ncorresponding to an AD object.\n\n08-23\n=====\nA new version of Cygwin was installed on the development system\n(this may affect the timing tests reported in this document).\nIn addition, :ref:`LuSolve-name` was changed to use back substitution\ninstead of reduction to an identity matrix. This reduced the number\nof floating point operations corresponding to evaluation of the determinant.\nThe following results correspond to the speed test\nof DetLu on a 9 by 9 matrix:\n\n.. list-table::\n    :widths: auto\n\n    * - **Version**\n      - **double Rate**\n      - **AD<double> Rate**\n      - **Gradient Rate**\n      - **Hessian Rate**\n      - **Tape Length**\n    * - 03-08-20\n      - 8,524\n      - 5,278\n      - 4,260\n      - 2,450\n      - 532\n    * - 03-08-23\n      - 7,869\n      - 4,989\n      - 4,870\n      - 2,637\n      - 464\n\n08-22\n=====\nThe\n:ref:`unary minus<unary_minus-name>` operator was added to the AD operations.\n\n08-19\n=====\nThe standard math function\nexamples were extended to include the complex case.\n\nThe\n:ref:`LuSolve-name`\nroutine what changed to use\n``std::vector<`` *Base* > & arguments in place of\n*Base*  * arguments.\nThis removes the need to use ``new`` and ``delete``\nwith ``LuSolve`` .\n\nWhen testing the speed of the change to using standard vector,\nit was noticed that the LuSolve routine\nwas much slower. (see times for 03-08-16 below).\nThis was do to computing the determinant instead of the log\nof the determinant.\nConverting back to the log of the determinant regained\nthe high speeds.\nThe following results correspond to the speed test\nof DetLu on a 9 by 9 matrix:\n\n.. list-table::\n    :widths: auto\n\n    * - **Version**\n      - **double Rate**\n      - **AD<double> Rate**\n      - **Gradient Rate**\n      - **Hessian Rate**\n      - **Tape Length**\n    * - 03-08-16\n      - 9,509\n      - 5,565\n      - 3,587\n      - 54\n      - 537\n    * - 03-08-19\n      - 8,655\n      - 5,313\n      - 4,307\n      - 2,495\n      - 532\n\n08-17\n=====\nThe macro\n``CppADTapeOverflow`` was added\nso that CppAD can check for tape overflow\neven in the ``NDEBUG`` preprocessor flag is defined.\n\n08-16\n=====\nThe\n:ref:`LuSolve-name` routine was extended to\nhandle complex arguments.\nBecause the complex absolute value function is nowhere differentiable,\nthis required the allowing for user defined\n:ref:`boolean valued functions with AD arguments<bool_fun-name>` .\nThe examples\n:ref:`lu_solve.cpp-name`\nand\n``GradLu.cpp``\nwere converted to a complex case.\n\n08-11\n=====\nThe routine :ref:`LuSolve-name` was made more efficient\nso that it is more useful as a tool for\ndifferentiating linear algebra calculations.\nThe following results correspond to the speed test\nof DetLu on a 9 by 9 matrix:\n\n.. list-table::\n    :widths: auto\n\n    * - **Version**\n      - **double Rate**\n      - **AD<double> Rate**\n      - **Gradient Rate**\n      - **Hessian Rate**\n      - **Tape Length**\n    * - 03-08-10\n      - 49,201\n      - 7,787\n      - 2,655\n      - 1,809\n      - 824\n    * - 03-08-11\n      - 35,178\n      - 12,681\n      - 4,521\n      - 2,541\n      - 540\n\nIn addition the corresponding test case\n:ref:`lu_solve.cpp-name` was changed to a Hilbert matrix case.\n\n08-10\n=====\nA :ref:`complex polynomial<complex_poly.cpp-name>`\nexample was added.\n\nThe documentation and type conversion in\n:ref:`LuSolve-name` was improved.\n\nThe absolute value function was removed from the examples because\nsome systems do not yet properly support ``double abs`` ( ``double`` *x* ) ,\n\n08-07\n=====\nBecause the change to the multiplication operator had such\na large positive effect,\nall of the\n:ref:`arithmetic operators<Arithmetic-name>`\nwere modified to reduce the amount of information\nin the tape (where possible).\n\n08-06\n=====\nDuring Lu factorization, certain elements of the matrix\nare know to be zero or one and do not depend on the variables.\nThe :ref:`multiplication<ad_binary-name>` operator was modified to take\nadvantage of this fact.\nThis reduced the size of the tape and increased the speed\nfor the calculation of the gradient and Hessian for\nthe Lu determinant test of a 5 by 5 matrix as follows:\n\n.. list-table::\n    :widths: auto\n\n    * - **Version**\n      - **Tape Length**\n      - **Gradient Rate**\n      - **Hessian Rate**\n    * - 03-08-05\n      - 176\n      - 11,362\n      - 1,149\n    * - 03-08-06\n      - 167\n      - 12,780\n      - 10,625\n\n08-05\n=====\nFixed a mistake in the calculation of the sign of the determinant in\nthe :ref:`LuSolve-name` example.\n\n08-04\n=====\nAdded a the compiler flag\n::\n\n    AbsOfDoubleNotDefined\n\nto the make files so that it could be removed on systems where the\nfunction\n\n    ``double abs`` ( ``double`` *x* )\n\nwas defined in ``math.h`` .\n\n08-03\n=====\nThe\n``Grad`` and ``Hess`` functions were modified\nto handle the case where the function does not depend on\nthe independent variables.\n\nThe\n:ref:`LuSolve-name` example was added to show how\non can differentiate linear algebra calculations.\nIn addition, it was used to add another set of\n:ref:`speed tests<speed_cppad-name>` .\n\nThe standard Math functions were added both\nas examples of defining atomic operations and to support\nmathematical operations for the ``AD<double>`` case.\n\nThe :ref:`\\<\\<<ad_output-name>` operator was added to the ``AD``\ntemplate class for output to streams.\n\n08-01\n=====\nThe\n:ref:`compound assignment<Arithmetic-name>` operators were added\nto the ``AD`` template class.\n\nThe name of the ``Speed/SpeedTest`` program was changed to\n:ref:`Speed/Speed<speed_cppad-name>` .\nIn addition, ``Speed/SpeedRun`` was changed to\n``Speed/SpeedTest`` .\n\n07-30\n=====\nThe\n:ref:`assignment<ad_assign-name>`\noperator was changed so the it returns a reference to\nthe target.\nThis allows for statements of the form\n\n    *x* = *y* = *z* ;\n\ni.e., multiple assignments.\n\n07-29\n=====\nIf the\n:ref:`AD copy constructor<ad_ctor-name>` or\n:ref:`assignment<ad_assign-name>` operator\nused an\n:ref:`glossary@Tape@Independent Variable`\nfor its source value,\nthe result was also an independent variable.\nThis has been fixed so that the result is\na dependent variable in these cases.\n\n07-26\n=====\nThe ``AD`` < *Base* > data structure\nwas changed to include a doubly linked list of variables.\nThis enabled  the\n:ref:`AD copy constructor<ad_ctor-name>` and\n:ref:`assignment<ad_assign-name>` operator\nto create multiple references to\nthe same place in the tape.\nThis reduced the size of the tape and increased the speed\nfor the calculation of the gradient and Hessian for\nthe determinant of a 5 by 5 matrix as follows:\n\n.. list-table::\n    :widths: auto\n\n    * - **Version**\n      - **Tape Length**\n      - **Gradient Rate**\n      - **Hessian Rate**\n    * - 03-07-22\n      - 1668\n      - 1,363\n      - 53\n    * - 03-07-26\n      - 436\n      - 3,436\n      - 213\n\n07-22\n=====\nThe facility was added so that the user can define\nbinary functions\ntogether with their derivatives.\n(This facility has been removed because it is better to define\nbinary functions using AD variables.)\n\nThe Windows version make file directive ``/I ..\\..``\nin ``example\\Example.mak`` and ``Speed\\Speed.mak``\nwas changed to ``/I ..`` (as it should have been).\n\n07-20\n=====\nThe facility was added so that the user can define\nunary functions,\ntogether with their derivatives.\nFor example, the standard math functions such as\n:ref:`exp<exp.cpp-name>`\nare good candidates for such definitions.\n(This feature has been replaced by and the standard math functions\nare now part of the AD types, see :ref:`AD-name` .)\n\nThe first Alpha for the Windows\n:ref:`installation<Install-name>` was released.\n\n07-18\n=====\nComputing the determinant of a minor of a matrix\n:ref:`det_of_minor-name`\nwas documented as a realistic example using CppAD.\n\n07-16\n=====\nFixed some non-standard constructions that caused problems\nwith the installation on other machines.\n\nCompiled and ran the tests under Microsoft Windows.\n(The Windows release should not take much more work.)\n\n07-14\n=====\nFirst Alpha release of CppAD\nand is being released under the\n:ref:`Gnu Public License<License-name>` .\nIt is intended for use by a Unix system.\nA Microsoft release is intended in the near future.\n\n{xrst_end 2003}\n"
  },
  {
    "path": "appendix/whats_new/2004.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin 2004 app}\n{xrst_spell\n    aclocal\n    autoconf\n    automake\n    dep\n    deps\n    dodds\n    dsp\n    executables\n    ext\n    faq\n    filename\n    hess\n    mak\n    makefile\n    nmake\n    retape\n    ublas\n    usr\n    yy\n}\n\nRelease Notes for 2004\n######################\n\nmm-dd\n*****\n\n12-11\n=====\nThe documentation for the CppAD error macros was improved.\nThe package title in :ref:`user_guide-name` was changed.\nThe documentation for :ref:`CppAD::vector<CppAD_vector-name>`\nwas improved and the corresponding source code\n``cppad/vector.hpp`` was included.\n\n12-09\n=====\nThe :ref:`LuSolve-name` and ``OdeRunge`` source code\nwas modified to make the more in line with the introduction\nto C++ AD book\n(``OdeRunge`` has been replaced by :ref:`Runge45-name` ).\nIn addition, the examples ``OdeRunge.cpp`` and\n:ref:`lu_solve.cpp-name` were modified to make the simpler.\n(The more complex version of ``OdeRunge.cpp``\nwas moved to the ``TestMore`` directory.)\n\n12-03\n=====\nThe :ref:`Poly-name` documentation and source code were modified to\nmake them more in line with the introduction to C++ AD book.\n\n11-17\n=====\nChanging to Autoconf and Automake on\n:ref:`2004@mm-dd@08-24` mistakenly forgot\nthe ``-Wall`` compiler switch (all warnings).\nThis has been added and the corresponding warnings\nhave been fixed.\n\n11-16\n=====\nThe 11-15 Debug version would not compile under Visual C++ version 7.0\nbecause a declaration of ``LessThanOrZero`` was missing.\nThis has been fixed.\n\n11-15\n=====\nThe :ref:`ForOne-name` and :ref:`RevOne-name`\neasy to use  :ref:`Drivers-name` were added.\n\n11-14\n=====\nThe notation in the :ref:`ADFun-name` sections was changed\nto make the :ref:`Forward-name` and :ref:`Reverse-name` routines\neasier to use.\n\n11-13\n=====\nThe Taylor coefficient vector and matrix notation was folded into\njust :ref:`Taylor coefficients<glossary@Taylor Coefficient>` .\n\n11-12\n=====\nIf ``NDEBUG`` is not defined during compile time,\nall ``AD`` < *Base* >\n:ref:`comparison<Compare-name>` operations are checked during\n:ref:`zero order<forward_zero-name>` forward mode calculations.\nThe\n:ref:`CompareChange-name` function\nreturns the number of comparison operations that have changed.\n\n11-10\n=====\nThe :ref:`get_started.cpp-name` example was changed to use the\n:ref:`Jacobian-name` driver.\nIn addition, more index entries,\nthat point to the :ref:`easy to use drivers<Drivers-name>` ,\nwere added.\n\n11-04\n=====\nThe Microsoft Visual Studio\nproject file ``example/Example.dsp/`` was missing some\nnew examples that needed to be linked in\nthe install windows procedure.\nThis has been fixed.\n\n11-02\n=====\nThe :ref:`unix installation<configure-name>` required the user\nto touch the files to get the dates in proper order.\nThis is no longer necessary.\n\n11-01\n=====\nSome of the dependency directories and files, for example\n``PrintFor/.deps`` and\n``PrintFor/.deps/PrintFor.Po`` had an extra ``?``\nat the end of their names.\nThis seems to have been fixed by using a newer version of the autoconf\nand automake tools.\n\n10-29\n=====\nAdd the example and test :ref:`simple_vector.cpp-name`\nto the :ref:`SimpleVector-name` documentation.\n\nThe specifications for\n:ref:`preprocessor symbols<preprocessor-name>`\nstate that all the CppAD preprocessor symbols\nbegin with ``CppAD``\n(so they do not conflict with other packages).\nSome preprocessor symbols in the file ``cppad/config.h`` did\nbegan with ``WITH_`` .\nThis has been fixed.\n\n10-28\n=====\nThe examples\n:ref:`hes_lu_det.cpp-name` ,\n:ref:`hes_minor_det.cpp-name` ,\n:ref:`jac_lu_det.cpp-name` ,\nand\n:ref:`jac_minor_det.cpp-name` used the negative of a ``size_t`` value.\nThe value has been changed to an ``int`` .\n\nThe :ref:`CppAD::vector<CppAD_vector-name>` template class\nwas converted into a library routine so it can be used\nseparately from the rest of CppAD.\n\n10-27\n=====\nThe :ref:`PrintFor-name` example was moved to its own directory\nbecause the conversion from VC 6.0 to VC 7.0 projects\ndid not work when there were multiple executables in one project file.\nThe :ref:`install-name` instructions were modified to reflect this change.\n\n10-21\n=====\nOne declaration (for the :ref:`Value-name` function) was missing\nfrom the file ``cppad/local/Declare.h`` .\nThis has been added and CppAD should now compile and run\nunder both Microsoft VC 6.0 and 7.0.\n\n10-19\n=====\nThe current version of CppAD has a problem compiling under Microsoft\nVisual C++ version 7.0 (it compiles and works under version 6.0).\nThe problem appears to be due to a closer agreement between VC 7.0 and the\nC++ standard for declaring templates functions as friends.\nSome friend declarations were removed and others were made more specific\nin order to migrate the a version that will compile and run using VC 7.0.\n\n10-16\n=====\nThe example :ref:`compare.cpp-name` displayed the text from\n:ref:`bool_fun.cpp-name` by mistake.\nThis has been fixed.\n\nThe :ref:`Compare-name` operators have been extended to work with\n``int`` operands.\n\n10-06\n=====\nThe test\n``TapeDetLu`` was added to ``speed_cppad/DetLuSpeed.cpp``\nand\n``TapeDetMinor`` was added to ``speed_cppad/DetMinorSpeed.cpp`` .\nThese tests just tape the calculations without computing any derivatives.\nUsing this, and the other tests, one can to separate the taping time\nfrom the derivative calculation time.\n\nThe\nwindows installation steps\ndo not build a ``config.h`` file.\nHence a default ``config.h`` file was added to the\ndistribution for use with Microsoft Visual Studio.\n\nThe ``Distribute`` section of the\ndeveloper documentation was brought up to date.\n\nLinks to the ADOLC and FADBAD download pages were added\nto the :ref:`unix installation<configure-name>` instructions.\n\n09-29\n=====\nThe include files for the :ref:`utilities<utility-name>` are now included\nby the root file ``cppad/cppad.hpp`` .\nThey can still be included individually with out the rest of\nthe CppAD package.\n\n09-26\n=====\nThe routine ``OdeRunge`` was modified\nso that it will now integrate functions of a complex arguments.\nThis was done by removing\nall uses of greater than and less than comparisons were removed.\n(``OdeRunge`` has been replaced by :ref:`Runge45-name` ).\n\nThe changes on :ref:`2004@mm-dd@09-21` did not fix all\nthe file date and time problems; i.e., automake was still running\nin response to the :ref:`unix installation<configure-name>`\n``make`` command.\n\n09-23\n=====\nThere was a reference to *B* that should have been *X*\nin the description of the\n:ref:`LuSolve@X` argument of ``LuSolve`` .\nThis has been fixed.\n\n09-21\n=====\nThe :ref:`CondExp-name` function has been modified so that it works properly\nfor ``AD< AD<`` *Base* > > types; i.e.,\nit now works for multiple levels of taping.\n\nThe date of the files ``aclocal.m4`` and ``config.h.in``\nwere later than the date of top level ``Makefile.am`` .\nThis caused the ``make`` command during the\n:ref:`unix installation<configure-name>`\nto try to run ``autoconf``\nand this did not work on systems with very old versions of ``autoconf`` .\nThis has been fixed.\n\n09-13\n=====\nThe examples that are specific to an operation were moved\nto be below that operation in the documentation tree.\nFor example\n:ref:`add.cpp-name` is below :ref:`ad_binary-name`\nin the documentation tree.\n\n09-10\n=====\nThe version released on 04-09-09 did not have the\nnew file ``PrintFor.h`` in ``cppad/local`` .\nThis has been fixed.\n\nThe *Base* type requirements were simplified.\n\nThe :ref:`Unix installation<configure-name>` instructions\nwere modified so just one make command was executed at the top level.\nThis was necessary because the order of the makes is now important\n(as previously suggested, the makes did not work properly).\n\n09-09\n=====\nThe :ref:`PrintFor-name` function was added so that\nusers can debug the computation of function values\nat arguments that are different from those used when taping.\n\n09-07\n=====\nIn the :ref:`Unix installation<configure-name>` instructions\nplace ``./`` in front of current directory program names; for example,\n``./GetStarted`` instead of ``GetStarted``\n(because some unix systems do not have the current directory\nin the default executable path).\n\n09-04\n=====\nA library containing the\n:ref:`SpeedTest-name` and :ref:`NearEqual-name` object files\nwas added to the distribution.\n\nAll of the include files of the form\n< ``cppad/library/`` *name* . ``h>`` were moved to\n< ``cppad/`` *name* . ``h>`` .\n\n09-02\n=====\nSome more messages were added to the output of ``configure``\nduring the :ref:`Unix installation<configure-name>` .\n\nThe suggested compression program during\nWindows installation\nwas changed from\n`7-zip <https://7-zip.org/>`_\nto\n`WinZip <https://www.winzip.com/en/>`_.\n\n08-27\n=====\nThe error messages printed by the default version of\nthe CppAD error macros had ``YY-MM-DD`` in place of the\ndate for the current version.\nThis has been fixed.\n\nAll the correctness tests are now compiled with the ``-g``\ncommand line option\n(the speed tests are still compiled with ``-O2 -DNDEBUG`` ).\n\nThe :ref:`installation instructions<Install-name>` for\nUnix and Windows were split into separate pages.\n\n08-25\n=====\nThe :ref:`installation<Install-name>` now automates the replacement\nof :ref:`CppAD::vector<CppAD_vector-name>` by\neither the ``std::vector``\nor ``boost::numeric::ublas::vector`` .\n\n08-24\n=====\nThis date marks the first release that uses\nthe Gnu tools Autoconf and Automake.\nThis automates the building of the make files for the\n:ref:`installation<Install-name>` and is the standard\nway to distribute open source software.\nThis caused some organizational changes,\nfor example, the :ref:`GetStarted<get_started.cpp-name>` example now\nhas its own directory and\nthe distribution directory is named\n\n    ``cppad-`` *yy* ``-`` *mm* ``-`` *dd*\n\nwhere *yy* ``-`` *mm* ``-`` *dd* is the year, month and date\nof the distribution.\n(Note the distribution directory is different from the directory\nwhere CppAD is finally installed.)\n\n08-12\n=====\nMove ``OdeExplicit`` into the ``cppad/library/`` directory.\nIn addition, change it so that the vector type was a template argument; i.e.,\nworks for any type of vector (not just ``CppADvector`` ).\n\n07-31\n=====\nMove :ref:`LuSolve-name` into the ``cppad/library/`` directory.\nIn addition, change it so that the vector type was a template argument; i.e.,\nworks for any type of vector (not just ``CppADvector`` ).\n\n07-08\n=====\nThe file ``cppad/example/NearEqual.h`` has been moved\nto ``cppad/example/NearEqualExt.h`` because it contains\nextensions of the :ref:`NearEqual-name` routine to ``AD`` types.\n\n07-07\n=====\nThe ``double`` and ``std::complex<double>``\ncases for the :ref:`NearEqual-name` routine arguments\nhas been moved to the general purpose :ref:`utilities<utility-name>` .\n\n07-03\n=====\nThe CppAD error macros names\n``CppADExternalAssert`` and ``CppADInternalAssert``\nwere changed to\n``CppADUsageError`` and ``CppADUnknownError`` .\nThe :ref:`SpeedTest-name` routine was changed to use ``CppADUsageError``\ninstead of a C assert.\n\n07-02\n=====\nThe :ref:`SpeedTest-name` output was improved so that the columns of\nvalues line up. Previously, this was not the case when\nthe number of digits in the size changed.\n\n06-29\n=====\nAdded code to trap and report memory allocation errors during\n``new`` operations.\n\n06-25\n=====\nA discussion of the order dependence of the\n:ref:`assignment<ad_assign-name>` operator\nand the\n:ref:`independent function<Independent-name>`\nwas added to the\n:ref:`Faq<Faq@Assignment and Independent>` .\nIn addition,\na similar discussion\nwas added to the documentation for the\n:ref:`Independent-name` function.\n\nThe definition of a\n:ref:`glossary@Parameter`\nand\n:ref:`glossary@Variable`\nwere changed to reflect that fact that\nthese are time dependent (current) properties\nof an ``AD`` < *Base* > object.\n\n06-12\n=====\nAll of the\n:ref:`arithmetic operators<Arithmetic-name>`\n(except for the unary operators)\ncan now accept ``int`` arguments.\nThe documentation for these arguments has been changed to reflect this.\nIn addition,\nthe corresponding test cases have been changed to test this and to\ntest high order derivative cases.\nThe old versions of these tests were moved into the\n``cppad/Test`` directory.\n\n06-04\n=====\nThe :ref:`atan2-name` function was added.\n\n06-03\n=====\nThe ``asin`` and ``acos``\n:ref:`unary_standard_math-name` functions were added.\n\nThere was a bug the reverse mode theory and calculation of\nderivatives of :ref:`sqrt-name` for fourth and higher orders.\nThis has been fixed.\nIn addition,\nthe following examples have been changed\nso that they test derivative up to fifth order:\n:ref:`asin<Asin.cpp-name>` ,\n:ref:`atan<atan.cpp-name>` ,\n:ref:`cos<cos.cpp-name>` ,\n:ref:`exp<exp.cpp-name>` ,\n:ref:`log<log.cpp-name>` ,\n:ref:`sin<sin.cpp-name>` ,\n:ref:`sqrt<sqrt.cpp-name>` .\n\n06-01\n=====\nThere was a bug in the :ref:`atan-name` function\n:ref:`forward mode<Forward-name>` calculations for Taylor coefficient\norders greater than two.\nThis has been fixed.\n\n05-30\n=====\nThe :ref:`sin<sin.cpp-name>` and :ref:`cos<cos.cpp-name>` examples were\nchanged so that they tested higher order derivatives.\n\n05-29\n=====\nThe forward mode recursion formulas for each of the\n:ref:`standard math functions<forward_theory@Standard Math Functions@Cases that Apply Recursion Above>`\nhas been split into separate sections.\n\nA roman (instead of italic) font was used for the name of\nfor the name of each of the standard math functions\nin the assumption statements below the section\nfor the standard math functions.\nFor example, :math:`\\sin(x)` instead of :math:`sin(x)`.\n\n05-26\n=====\nIn the documentation for :ref:`Poly-name` ,\nthe reference to ``example/Poly.h``\nwas corrected to ``cppad/library/Poly.h`` .\n\nIn the documentation for :ref:`SpeedTest-name` ,\nthe reference to ``Lib/SpeedTest.h``\nwas corrected to ``cppad/library/SpeedTest.h`` .\nIn addition, the example case was corrected.\n\nIn :ref:`Reverse-name` , the definition for :math:`U(t, u)` had\n:math:`t^p-1` where it should have had :math:`t^{p-1}`.\nThis has been fixed.\n\n05-25\n=====\nThe special case where the second argument to the :ref:`pow-name` function is an\n``int`` has been added.\n\n05-14\n=====\nChange all of the include syntax\n\n    # ``include`` \" *filename* \"\n\nto the syntax\n\n    # ``include`` < *filename* >\n\nso that examples and other use better reflect how one would use CppAD after\nit was installed in a standard include directory; for example\n``/usr/local/include/cppad`` .\n\nThe user documentation was moved from the directory\n``cppad/User`` to the directory ``cppad/Doc`` .\n\nThe directory ``cppad/Lib`` was moved to ``cppad/library``\nto reflect that fact that it is not what one expects in a standard\n``lib`` directory or a standard ``include`` directory.\n\n05-12\n=====\nThe string ``YY-MM-DD`` in the preprocessor symbol ``CppADVersion``\nwas not being replaced by the current date during distribution.\nThis resulted in the ``CppADExternalAssert`` macro printing\n``YY-MM-DD`` where is should have printed the date of distribution.\nThis has been fixed.\n\nAll of the include commands of the form\n\n| |tab| # ``include`` \" ``include/`` *name* . ``h`` \"\n| |tab| # ``include`` \" ``lib/`` *name* . ``h`` \"\n\nhave been changed to the form\n\n| |tab| # ``include`` \" ``cppad/include/`` *name* . ``h`` \"\n| |tab| # ``include`` \" ``cppad/lib/`` *name* . ``h`` \"\n\nThis will avoid mistakenly loading a file from another package\nthat is in the set of directories being searched by the compiler.\nIt is therefore necessary to specify that the directory above the\n``CppAD`` directory be searched by the compiler.\nFor example,\nif ``CppAD`` is in ``/usr/local/cppad`` ,\nyou must specify that ``/usr/local`` be searched by the compiler.\nNote that if ``/usr/local/cppad/`` is no longer searched,\nyou will have to change\n::\n\n    # include \"cppad.hpp\"\n\nto::\n\n    # include \"cppad/cppad.hpp\"\n\nThe window ``nmake`` file ``Speed/Speed.mak`` was out of date.\nThis has been fixed.\n\n05-09\n=====\nMove :ref:`Poly-name` and :ref:`SpeedTest-name` into the\n``cppad/Lib`` directory and the ``CppAD`` namespace.\n\n05-07\n=====\nThe :ref:`divide operator tests<div.cpp-name>` were extended to\ninclude a second order derivative calculation using reverse mode.\n\nThe :ref:`Poly-name` routine was modified to be more efficient in the\nderivative case. In addition, it was changed to use an arbitrary\nvector for the coefficients (not just a ``CppADvector`` ).\n\n05-04\n=====\nA reloading of the data base\ncaused the files ``include/atan.h`` and ``include/cos.h`` to be\nmistakenly started with lower case letters.\nThese have been moved to ``include/Atan.h`` and ``include/Cos.h``\nrespectively.\n\n05-03\n=====\nThe :ref:`Reverse-name` mode calculations for\n:ref:`conditional expressions<CondExp-name>` were mistakenly left out.\nThis has been fixed.\n\n04-29\n=====\nThe unary functions, such as :ref:`sin-name` and :ref:`cos-name` ,\nwere not defined for elements of an :ref:`VecAD-name` vector.\nThis has been fixed.\n\n04-28\n=====\nThe operator :ref:`\\<\\<<CppAD_vector@Output>` was added to the\ndefault ``test_vector`` template class.\n\nA FADBAD correctness and speed comparison with CppAD\nwas added.\n\n04-25\n=====\nFactor out common sub-expressions in order to make\n:ref:`lu_vec_ad.cpp-name` faster.\n\nConvert description\nfrom C++ Automatic Differentiation to C++ Algorithmic Differentiation.\n\n04-24\n=====\nThe :ref:`VecAD-name` element class is no longer\na derived class of the :ref:`AD-name` class.\nThis enabled a decrease in tape memory\nand an increase in the speed for :ref:`VecAD-name` operations.\n\nThe :ref:`log10-name` function was added.\n\n04-22\n=====\nAdd :ref:`CondExp-name` and use it to speed up :ref:`lu_vec_ad.cpp-name` .\n\n04-21\n=====\nUse :ref:`abs-name` to speed up :ref:`lu_vec_ad.cpp-name` .\n\n04-20\n=====\nThe :ref:`absolute value<abs-name>` function was added.\n\nThe value *n* for\n``OdeExplicit`` and ``OdeImplicit``\nis deduced from the argument *x0* and is not passed\nas a separate argument.\nThis documentation has been fixed to this effect.\n\n04-19\n=====\nThe :ref:`+=<compound_assign-name>` operator did not function correctly\nwhen the left hand operand was a\n:ref:`glossary@Parameter`\nand the right hand operand was a variable\n(found by `Mike Dodds <mailto:magister@u.washington.edu>`_).\nThis has been fixed.\n\n04-09\n=====\nAdding special operators for using parameters to index ``VecAD`` objects\nincreased the speed and reduced the memory requirements (by about 20%) for\nthe :ref:`VecAD-name` case in the ``speed_cppad/LuSolveSpeed.cpp/`` test.\n\nThe :ref:`VecAD-name` objects are not being handled correctly by the\n:ref:`Reverse-name` function.\nThe ``VecAD`` test was extended to demonstrate the problem\nand the problem was fixed\n(it is now part of ``TestMore/VecAD`` ).\n\n04-08\n=====\nThe example :ref:`lu_vec_ad_ok.cpp-name`\nuses :ref:`VecAD-name` to executes different pivoting operations\nduring the solution of linear equations with out having to retape.\n\nThe speed test ``speed_cppad/LuSolveSpeed.cpp/`` has been added.\nIt shows that the initial implementation of :ref:`VecAD-name` is slow\n(and uses a lot of memory.)\nIn fact,\nit is faster to use :ref:`LuSolve-name` and retape for each set of equations\nthan it is to use :ref:`lu_vec_ad.cpp-name` and not have to retape.\nThis test will help us improve the speed of :ref:`lu_vec_ad.cpp-name` .\n\n04-07\n=====\nThere were bugs in the assignment to :ref:`VecAD-name` elements\nduring taping that have been fixed.\nIn addition, an example of tapping the pivoting operations in\nan :ref:`Lu factorization<lu_vec_ad.cpp-name>` has been added.\n\n04-03\n=====\nAdded ``size_t`` indexing to the :ref:`VecAD-name` class.\n\nFixed a bug connected to the :ref:`VecAD-name` class and erasing the tape.\n\n04-02\n=====\nSome memory savings is done with regard to equal parameter values\nbeing stored in the tape. There was a bug in this logic when parameter\nin an ``AD< AD<`` *Base* > > class had values that were variables in the\n``AD`` < *Base* > class.\nThis has been fixed.\n\n04-01\n=====\nThe name of the class that tapes indexing operations\nwas changed from ``ADVec`` to :ref:`VecAD-name` .\nThis class was extended so that\nthe value of elements in these vectors can be variables\n(need not be :ref:`parameters<glossary@Parameter>` ).\n\n03-30\n=====\nDo some simple searching of the parameter table during taping\navoid multiple copies of parameters on tape (use less tape memory).\n\n03-28\n=====\nThe version :ref:`ADVec<VecAD-name>` ,\na vector class that tapes indexing operations,\nis now available.\nIt is currently restricted by the fact that all the\nvalues in the vector must be\n:ref:`parameters<Glossary@Parameter>` .\n\n03-25\n=====\nThe internal taping structure has been changed to have variable length\ninstructions.\nThis is to save memory on the tape.\nIn addition, it may help in the implementation of the\nvector class that tracks indexing.\n(A now functioning version of this class is described in\n:ref:`VecAD-name` .)\n\n03-18\n=====\nA change was made to the way parameter values are stored on the tape.\nThis resulted in a significant savings in the amount of memory required.\n\n03-17\n=====\nChange the return type for :ref:`SpeedTest-name` from ``const char *``\nto ``std::string`` .\nThe memory required for the largest test cases was added to the\n:ref:`speed_cppad-name` tests output.\n\n03-15\n=====\nThe comparison between ADOLC and CppAD for\nthe ``DetLuADOLC.cpp/`` example was returning an error\n(because it was checking for exact equality of calculated derivatives\ninstead of nearly equal).\nThis has been fixed.\n\n03-12\n=====\nThe user defined unary functions were removed and\nthe user defined :ref:`discrete functions<Discrete-name>` were\nadded.\nThese discrete functions add the capability of conditional expressions\n(alternate calculations)\nbeing included in an :ref:`ADFun-name` object.\n\n03-11\n=====\nThe classes :ref:`det_by_minor-name` and :ref:`det_by_lu-name` were added\nand used these to simplify the\nexamples that compute determinants.\n\n03-09\n=====\nThe routines ``Grad`` and ``Hess`` have been removed.\nYou should use :ref:`Jacobian-name` and :ref:`Hessian-name` instead.\n\n03-07\n=====\nThe driver routines :ref:`Hessian-name` and :ref:`RevTwo-name` has been added.\nThese to compute specialized subsets of the second order partials.\n\nDocumentation errors in :ref:`ForTwo-name` and :ref:`Reverse-name` were fixed.\nThe :ref:`example-name` documentation was reorganized.\n\n03-06\n=====\nThe driver :ref:`ForTwo-name` has been added.\nIt uses forward mode to compute a subset of the second order partials.\n\nSplit all of the \"example\" and \"test\" index entries that come from\n``include/cppad/example/`` * . ``cpp``\ninto sorted subheadings.\n\n03-05\n=====\nThe ``Grad`` routine,\nwhich only computed first derivatives of scalar valued functions,\nhas been replaced by the :ref:`Jacobian-name` routine which\ncomputes the derivative of vector valued functions.\n\n03-04\n=====\nThe bug reported on :ref:`2004@mm-dd@02-17` was present in all\nthe operators. These have all been fixed and tests for all the operators\nhave been added to the ``cppad/Test`` directory.\n\nThe :ref:`f.Parameter()<fun_property@Parameter>` function was added so that\none can count how many components of the range space depend\non the value of the domain space components.\nThis helps when deciding whether to use forward or reverse mode.\n\n03-03\n=====\nSpecial operators were added to distinguish the cases where\none of the operands is a\n:ref:`glossary@Parameter` .\nThis reduced the amount of branching that is necessary\nwhen executing :ref:`Forward-name` and :ref:`Reverse-name` calculations.\n\nThe :ref:`Independent-name` and :ref:`fun_property@Parameter` functions\nwere moved below :ref:`ADFun-name` in the documentation.\n\n03-01\n=====\nThe DetLuADOLC.cpp, DetLu case was added to the ADOLC\ncomparison tests.\n\n02-29\n=====\nUnder certain optimization flag values,\nand on certain systems,\nan error was reported by the\nADOLC correctness comparison.\nIt turned out that CppAD was not initializing a particular index\nwhen debugging was turned off. This has been fixed.\n\n02-28\n=====\nA set of routines for comparing CppAD with\nADOLC has been added to the distribution.\nIn addition, documentation for compiling and linking the\n:ref:`Examples<example-name>` and :ref:`Speed Tests<speed_cppad-name>`\nhas been added.\n\n02-21\n=====\nIf you use the user defined unary atomic functions\nthere is a restriction on the order of the derivatives that can be calculated.\nThis restriction was documented in the user defined unary function\n:ref:`Forward-name`\nand :ref:`Reverse-name` .\n(These unary functions were removed on :ref:`2004@mm-dd@03-12` .)\n\n02-20\n=====\nA user interface to arbitrary order\n:ref:`reverse mode<Reverse-name>` calculations was implemented.\nIn addition, the :ref:`ADFun-name` member functions\n``Rev`` and ``RevTwo`` were removed\nbecause it is easier to use the uniform syntax below:\n\n.. list-table::\n    :widths: auto\n\n    * - **Old Syntax**\n      - **Uniform Syntax**\n    * - *r1* = *f* . ``Rev`` ( *v* )\n      - *r1* = *f* . ``Reverse`` (1, *v* )\n    * - *q1* = *f* . ``RevTwo`` ( *v* )\n      - *r2* = *f* . ``Reverse`` (2, *v* )\n    * -\n      - *q1* [ *i* ] == *r2* [2 * *i*  + 1]\n\nThe :ref:`Theory-name` section has been completely changed so that\nit corresponds to the arbitrary order calculations.\n(Some of this change was made when the arbitrary forward mode\ninterface was added on\n:ref:`04-02-15<2004@mm-dd@02-15>` .\n\nThe directory ``cppad/Test`` has been added.\nIt contains tests cases that are not intended as examples.\n\n02-17\n=====\nThere was a bug in the way CppAD handled the parameters zero and one\nwhen they were variables on a lower level tape; i.e. x might be a\nparameter on an ``AD< AD<`` *Base* > > tape and a its value\nmight be a variable on the\n``AD`` < *Base* > tape.\nThis bug in the multiply and divide routines has been fixed.\n\nThere was a bug that is some cases reported a divide by zero error\nwhen the numerator was zero. This has been fixed.\n\n02-16\n=====\nA bug in :ref:`Forward-name` prevented the calculation of derivatives\nwith higher order than two.\nIn addition, this checking for user errors in the use of ``Forward``\nwas also faulty.\nThis has been fixed.\n\nThe Microsoft project file ``example\\Example.dsp``\nwas out of date. This has been fixed.\n\nThe example that :ref:`tapes derivative calculations<mul_level-name>`\nhas been changed to an application of\n:ref:`Taylor's method<mul_level_ode.cpp-name>` for solving ordinary differential\nequations.\n\n02-15\n=====\nA user interface to arbitrary order\n:ref:`forward mode<Forward-name>` calculations was implemented.\nIn addition, the :ref:`ADFun-name` member functions\n``Arg`` , ``For`` and ``ForTwo`` were removed\nbecause it is easier to use the uniform syntax below:\n\n.. list-table::\n    :widths: auto\n\n    * - **Old Syntax**\n      - **Uniform Syntax**\n    * - *v0* = *f* . ``Arg`` ( *u0* )\n      - *v0* = *f* . ``Forward`` (0, *u0* )\n    * - *v1* = *f* . ``For`` ( *u1* )\n      - *v1* = *f* . ``Forward`` (1, *u1* )\n    * - *v2* = *f* . ``For`` ( *u2* )\n      - *v2* = *f* . ``Forward`` (1, *u2* )\n\n02-12\n=====\nAll of the derivative calculations are now done using arbitrary\norder Taylor arithmetic routines.\nThe :ref:`Theory-name` section was changed to document this method\nof calculation.\n\n02-01\n=====\nThe definition of a\n:ref:`glossary@Taylor Coefficient`\nwas changed to include the factorial factor.\nThis change was also made to the output specifications for the\n``FunForTwo`` routine.\n\n01-29\n=====\nThere were some bugs in the ``FunArg`` function\nthat were fixed.\n\n#. If one of the dependent variables was a\n   :ref:`glossary@Parameter`\n   ``FunArg`` did not set it's value properly.\n   (All its derivatives are zero and this was handled properly.)\n#. The user defined unary functions were not\n   computed correctly.\n\nThe specifications for the usage and unknown CppAD error macros\nwere modified so that they could be used with out side effects.\n\n01-28\n=====\nSome corrections and improvements were made to the documentation including:\n``CppADvector`` was placed before its use,\na reference to ``Ode_ind`` and ``Ode_dep`` was fixed in\n``OdeImplicit`` .\n\n01-22\n=====\nThe specifications for the routine ``FunForTwo``\nwas changed to use\n:ref:`Taylor coefficients<glossary@Taylor Coefficient>` .\nThis makes the interface to CppAD closer to the interface for\n`ADOLC <https://github.com/coin-or/ADOL-C>`_.\n\n{xrst_end 2004}\n"
  },
  {
    "path": "appendix/whats_new/2005.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin 2005 app}\n{xrst_spell\n    dlib\n    dsp\n    dsw\n    dussault\n    etc\n    gz\n    kutta\n    maxabs\n    neg\n    pearce\n    pkzip\n    scur\n    sln\n    typedef\n    valarray\n    vcproj\n    yy\n}\n\nRelease Notes for 2005\n######################\n\nmm-dd\n*****\n\n12-24\n=====\nFix a memory leak that could occur during the :ref:`ForSparseJac-name`\ncalculations.\n\n12-23\n=====\nThe buffers that are used to do\n:ref:`RevSparseJac-name` and  :ref:`RevSparseHes-name`\ncalculations are now freed directly after use.\n\nThe TrackNewDel.cpp example was missing from the Windows install\nexamples and testing\nproject file.\nThis has been fixed.\n\n12-22\n=====\nThe buffer that is are used to do\n:ref:`Reverse-name` mode\ncalculations is now freed directly after use.\nThis reduces the memory requirements attached to an :ref:`ADFun-name` object.\n\n12-20\n=====\nBuffers that are used to store the tape information corresponding to\nthe ``AD`` < *Base* > type are now freed when the corresponding\n:ref:`ADFun-name` object is constructed.\nThis reduces memory requirements and actually had better results\nwith the :ref:`speed_cppad-name` tests.\n\nThe :ref:`speed_cppad-name` test program now outputs the version of CppAD\nat the top (to help when comparing output between different versions).\n\n12-19\n=====\nThe :ref:`track_new_del-name` routines were added for track memory allocation\nand deletion with ``new[]`` and ``delete[]`` .\nThis is in preparation for making CppAD more efficient in it's use of\nmemory.\nThe bug mentioned on :ref:`2005@mm-dd@12-01` resurfaced\nand the corresponding routine was changed as follows:\n::\n\n    static local::ADTape<Base> *Tape(void)\n    {  // If we return &tape, instead of creating and returning ptr,\n    // there seems to be a bug in g++ with -O2 option.\n    static local::ADTape<Base> tape;\n    static local::ADTape<Base> *ptr = &tape;\n    return ptr;\n    }\n\n12-16\n=====\nThe :ref:`NearEqual-name` function documentation for the relative error case\nwas changed to\n\n    | *x* ``-`` *y* | <= *r* * ( | *x* | + | *y* | )\n\nso that there is no problem with division by zero when\n*x* and *y* are zero\n(the code was changed to that form also).\nThe ``std::abs`` function replaced the\ndirect computation of the complex norms\n(for the complex case in ``NearEqual`` ).\nIn addition, more extensive testing was done in :ref:`near_equal.cpp-name` .\n\n12-15\n=====\nExtend :ref:`NearEqual-name` and :ref:`near_equal_ext-name`\nto cover more cases while converting them from,\na library function in ``lib/CppADlib.a``\nand an utility in ``example/NearEqualExt.h`` ,\nto a template functions in\n``cppad/near_equal.hpp`` and\n``cppad/local/NearEqualExt.h`` .\nThis is another step along the way of removing\nthe entire ``CppADlib.a`` library.\n\nThe change on :ref:`2005@mm-dd@12-14` broke the\nMicrosoft project files ``example/Example.sln``\nand ``TestMore/TestMore.sln`` used during CppAD\ninstallation on Windows.\nThis has been fixed.\n\nMove ``lib/SpeedTest.cpp`` to ``cppad/speed_test.hpp`` .\nThis was the last change necessary in order to remove the CppAD library,\nso remove all commands related to building and linking ``CppADlib.a`` .\nThe corresponding entry has been removed from the :ref:`wish_list-name` .\n\nOne of the entries in the :ref:`wish_list-name` corresponded to the\n:ref:`Integer-name` function.\nIt has also been removed (because it is already implemented).\n\n12-14\n=====\nExtend :ref:`erf-name` to cover more cases while converting it\nfrom a function in ``lib/CppADlib.a``\nto a template function in ``cppad/local/Erf.h`` .\nThis is one step along the way of removing\nthe entire ``CppADlib.a`` library.\n\n12-11\n=====\nGroup routines that extend the domain for which an :ref:`ADFun-name`\nobject is useful into the ExtendDomain section.\n\nAdd an example of a C callable routine that computes\nderivatives using CppAD (see :ref:`interface2c.cpp-name` ).\n\n12-08\n=====\nSplit out :ref:`LuFactor-name` with the *ratio* argument\nto a separate function called :ref:`LuRatio-name` .\nThis needed to be done because :ref:`LuRatio-name` is more restrictive\nand should not be part of the general template :ref:`utilities<utility-name>` .\n\n12-07\n=====\nImprove :ref:`CheckSimpleVector-name` so that it tests element assignment.\nChange :ref:`check_simple_vector.cpp-name` so that it provides\nand example and test of a case where a simple vector returns a type\ndifferent from the element type and the element assignment returns\n``void`` .\n\n12-06\n=====\nThe specifications for a :ref:`SimpleVector-name` template class\nwere extended so that the return type of an element access is\nnot necessarily the same as the type of the elements.\nThis enables us to include ``std::vector<bool>``\nwhich packs multiple elements into a single storage location\nand returns a special type on element access (not the same as ``bool`` ).\nTo be more specific,\nif *x* is a ``std::vector<bool>`` object\nand *i* has type ``size_t`` ,\n*x* [ *i* ] does not have type ``bool`` .\n\nAdd a Home icon,\nthat links to the\n`CppAD home page <https://www.coin-or.org/CppAD/>`_,\nto the top left of the navigation frame\n(left frame) for each documentation section.\n\n12-05\n=====\nThe :ref:`RevSparseHes-name` reverse mode Hessian sparsity calculation\nhas been added.\n\nThe definition of a :ref:`glossary@Sparsity Pattern`\nhas been corrected to properly correspond to the more efficient form\nmentioned under :ref:`2005<2005@mm-dd@11-20>` below.\n\nThe dates in this file used to correspond to\nlocal time for when the change was checked\ninto the subversion repository.\nFrom now on the dates in this file will correspond to the first\nversion of CppAD where the change appears; i.e., the date in the\nunix and windows\ndownload file names ``CppAD-`` *yy* ``-`` *mm* ``-`` *dd* .\n\n12-03\n=====\nThere was a bug in the :ref:`RevSparseJac-name`\nreverse mode sparsity patterns when used with :ref:`VecAD-name` calculations.\nThis bug was fixed and the calculations were made more efficient\n(fewer true entries).\n\n12-02\n=====\nThere was a bug in the :ref:`ForSparseJac-name`\nforward mode sparsity patterns when used with :ref:`VecAD-name` calculations.\nThis bug was fixed and the calculations were made more efficient\n(fewer true entries).\n\n12-01\n=====\nThe speed test of :ref:`lu_vec_ad.cpp-name` has been reinstated.\nIt appears that there is some sort of bug in the gcc compiler with\nthe -O2 option whereby the following member function\n::\n\n    static local::ADTape<Base> *Tape(void)\n    {  static local::ADTape<Base> tape;\n    return &tape;\n    }\n\n(in ``cppad/local/AD.h`` )\nwould sometimes return a null value (during :ref:`VecAD-name` operations).\nA speed improvement in\n``cppad/local/ExtendBuffer.h`` seems to prevent\nthis problem.\nThis fix is not well understood; i.e., we should watch to see\nif this problem reoccurs.\n\nThe source code for\n:ref:`lu_vec_ad_ok.cpp-name` was mistakenly used for\n``speed_cppad/LuSolveSpeed.cpp`` .\nThis has been fixed.\n\n11-23\n=====\nThe speed test of :ref:`lu_vec_ad.cpp-name` has been commented out\nbecause it sometimes generates a segmentation fault.\nHere is an explanation:\n\nIf *X* is a ``AD`` < *Base* > object,\n*y* is a *Base* object,\n*X* [ *y* ] uses pointer from the element\nback to the original vector.\nOptimizing compilers might reorder operations so that\nthe vector is destroyed before the object is used.\nThis can be avoided by changing the syntax for :ref:`VecAD-name` objects\nto use ``set`` and ``get`` member functions.\n\n11-22\n=====\nA much better :ref:`example<vec_ad.cpp-name>` for using :ref:`VecAD-name`\nvectors has been provided. In addition, a bug\nin the computation of derivatives using ``VecAD`` vectors\nhas been fixed.\n\nCppAD now checks that the domain dimension during\n:ref:`Independent-name` and\nthe range dimension during :ref:`ADFun-name`\n(provided that ``-DNDEBUG`` is not defined).\nIf either of these is zero,\nthe ``CppADUsageError`` macro is invoked.\n\n11-20\n=====\nThe sparsity pattern routines\n:ref:`ForSparseJac-name` and :ref:`RevSparseJac-name`\nhave been modified so that they are relative\nto the Jacobian at a single argument value.\nThis enables us to return more efficient\n:ref:`sparsity patterns<glossary@Sparsity Pattern>` .\n\nAn extra :ref:`exception<VecAD@VecAD<Base\\>::reference@Exceptions>` has been\nadded to the use of :ref:`VecAD-name` elements.\nThis makes ``VecAD`` some what more efficient.\n\n11-19\n=====\nImprove the output messages generated during execution of the\n:ref:`configure@Configure` command.\n\nPut a try and catch block around all of the uses of\n``new`` so that if a memory allocation error occurs,\nit will generate a ``CppADUsageError/`` message.\n\nThe :ref:`get_started.cpp-name` example has been simplified\nso that it is easier to understand.\n\n11-15\n=====\nFix a memory leak in both the :ref:`ForSparseJac-name` and\n:ref:`RevSparseJac-name` calculations.\n\n11-12\n=====\nAdd reverse mode :ref:`Jacobian sparsity<RevSparseJac-name>` calculation.\n\n11-09\n=====\nAdd prototype documentation for :ref:`LuSolve@logdet` in\nthe :ref:`LuSolve-name` function.\n\nAdd the optional *ratio* argument to the\n:ref:`LuFactor-name` routine.\n(This has since been moved to a separate routine called :ref:`LuRatio-name` .)\n\n11-07\n=====\nRemove some blank lines from the example files listed\ndirectly below (under 11-06).\nComments for computing the entire Jacobian\n:ref:`ForSparseJac@Entire Sparsity Pattern`\nwas added.\n\n11-06\n=====\nThe cases of ``std::vector`` , ``std::valarray`` , and\n``CppAD::vector`` were folded into the standard example and tests\nformat for the following cases:\n:ref:`rev_two.cpp-name` ,\n:ref:`rev_one.cpp-name` ,\n``Reverse.cpp`` ,\n:ref:`hessian.cpp-name` ,\n:ref:`jacobian.cpp-name` ,\n:ref:`forward.cpp-name` ,\n:ref:`for_two.cpp-name` ,\n:ref:`for_one.cpp-name` ,\n``Fun.cpp``\n(``Fun.cpp`` has since been replaced by :ref:`independent.cpp-name` ,\n``Reverse.cpp`` has since been replaced by\n:ref:`reverse_one.cpp-name` and ``rev_checkpoint.cpp`` ).\n\n11-01\n=====\nAdd forward mode :ref:`Jacobian sparsity<ForSparseJac-name>` calculation.\n\n10-20\n=====\nAdd :ref:`sparsity patterns<glossary@Sparsity Pattern>` to\nthe wish list.\n\n10-18\n=====\nThe Unix install :ref:`configure@Configure` command\nwas missing the ``--`` before of the ``prefix`` command line\nargument.\n\n10-14\n=====\nThe template class :ref:`CppAD_vector-name` uses a try/catch block\nduring the allocation of memory (for error reporting).\nThis may be slow down memory allocation and hence it\nis now replaced by simple memory allocation when\nthe preprocessor variable ``NDEBUG`` is defined.\n\nThe specialization of ``CppAD::vector<bool>``\nwas moved to :ref:`CppAD_vector@vectorBool`\nso that ``CppAD::vector<bool>`` does not pack one bit per value\n(which can be slow to access).\n\n10-12\n=====\nChange the\n:ref:`configure@Configure` script so that compilation of the\n:ref:`get_started.cpp-name` and :ref:`print_for_cout.cpp-name` examples are optional.\n\nOne of the dates in the Unix installation\nextraction discussion was\nout of date. This has been fixed.\n\n10-06\n=====\nChange the Unix install ``configure`` script\nso that is reports information using the same order and notation as its\n:ref:`documentation<configure@Configure>` .\n\nSome compiler errors in the :ref:`ode_gear_control.cpp-name` and\n:ref:`ode_stiff.cpp-name` examples were fixed.\n\n09-29\n=====\nAdd a specialization to :ref:`CppAD_vector-name` for the\n``CppAD::vector<bool>`` case.\nA test for the ``push_back`` member function as well as a\n:ref:`CheckSimpleVector-name` test has been added to :ref:`cppad_vector.cpp-name` .\nThe source code for this template vector class,\n``cppad/vector.hpp`` ,\nhas been removed from the documentation.\n\n09-27\n=====\nAdd the\n:ref:`configure@prefix_dir` and\n*postfix_dir* ( *postfix_dir* has since been removed)\noptions to the ``configure`` command line.\nThis gives the user more control over the location where CppAD is installed.\n\n09-24\n=====\nThe stiff Ode routines,\n:ref:`OdeGear-name` and :ref:`OdeGearControl-name` ,\nwere added to the :ref:`utilities<utility-name>` .\nA comparison various Ode solvers on a stiff problem\n:ref:`ode_stiff.cpp-name` was added.\nIn addition, ``OdeGear`` and ``OdeGearControl``\nwere added to the :ref:`utilities<utility-name>` and the library was\nreorganized.\n\n09-20\n=====\nThe Microsoft compiler project files\n``example/Example.vcproj`` and ``TestMore/TestMore.vcproj``\nwere not up to date.\nThis has been fixed.\nIn addition, the example :ref:`numeric_type.cpp-name` has been added.\n\nMake the building of the\n``Example`` , ``TestMore`` , and ``Speed`` , directories\noptional during the :ref:`configure@Configure` command.\nThe :ref:`Unix installation instructions<configure-name>` were\noverhauled to make the larger set of options easy to understand.\n\n09-14\n=====\nAdded the :ref:`NumericType-name` concept and made the following\nlibrary routines require this\nconcept for their floating point template parameter type:\n:ref:`LuSolve-name` ,\n:ref:`LuFactor-name` ,\n:ref:`RombergOne-name` ,\n:ref:`RombergMul-name` ,\n:ref:`Runge45-name` ,\n:ref:`Rosen34-name` , and\n:ref:`OdeErrControl-name` .\nThis is more restrictive than the previous requirements\nfor these routines but it\nenables future changes to the implementation of these routines\n(for optimization purposes) with out affecting their specifications.\n\n09-09\n=====\nAdd the :ref:`unary_plus-name` operator and move the ``Neg``\nexamples and tests to :ref:`unary_minus-name` .\n\n09-07\n=====\nChange name of distribution files from\n``CppAD.unix.tar.gz`` and ``CppAD.dos.tar.gz``\nto\n``CppAD-`` *yy* ``-`` *mm* ``-`` *dd* . ``tar.gz`` and ``CppAD-`` *yy* ``-`` *mm* ``-`` *dd* . ``zip``\n(the * . ``zip`` file\nuses pkzip compression).\n\n08-30\n=====\nThe *maxabs* argument has been added to the\n:ref:`OdeErrControl-name` function so that it can be used\nwith relative errors where components of the ODE solution may be zero\n(some of the time).\nIn addition, some of the rest of the OdeErrControl documentation\nhas been improved.\n\nThe documentation for\nreplacing defaults\nin CppAD error macros has been improved.\n\n08-24\n=====\nChanged ``Romberg`` to :ref:`RombergOne-name` and added :ref:`RombergMul-name` .\nIn addition, added missing entries to :ref:`list_all_examples-name`\nand reorganized :ref:`utilities<utility-name>` .\n\n08-20\n=====\nBacked out addition of ``Romberg`` integration routine\n(at this point uncertain of the interface that is most useful in\nthe context of AD.)\n\n08-19\n=====\nAdded a ``Romberg`` integration routine for\nwhere the argument types are template parameters\n(for use with AD types).\n\n08-15\n=====\nThe Microsoft project files ``example/Example.vcproj`` and\n``TestMore/TestMore.vcproj`` were missing some necessary routines.\nIn addition, ``Speed/Speed.vcproj`` was generating a warning.\nThis has been fixed.\n\n08-14\n=====\nAn :ref:`Integer-name` conversion function as been added.\n\nThe :ref:`value.cpp-name` example has been improved and the old example\nhas been moved into the ``TestMore`` directory.\n\n08-13\n=====\nThe :ref:`unary_standard_math-name` functions\n``sinh`` , and ``cosh`` have been added.\nIn addition, more correctness testing\nhas been added for the ``sin`` and ``cos`` functions.\n\nThe :ref:`OdeErrControl-name` routine could lock in an infinite loop.\nThis has been fixed and a test case has been added to check for this problem.\n\n08-07\n=====\nThe :ref:`conditional expression<CondExp-name>` function has been changed\nfrom just ``CondExp`` to\n``CondExpLt`` ,\n``CondExpLe`` ,\n``CondExpEq`` ,\n``CondExpGe`` ,\n``CondExpGt`` .\nThis should make code with conditional expressions easier to understand.\nIn addition, it should reduce the number of tape operations because\none need not create as many temporaries to do comparisons with.\nThe old ``CondExp`` function has been deprecated.\n\n07-21\n=====\nRemove unnecessary no-op that was left in tape for the\n:ref:`unary_standard_math-name` functions\n``acos`` , ``asin`` , ``atan`` , ``cos`` .\n\nImprove the index entries in the documentation that corresponds\nto the ``cppad/local`` directory source code.\n\n07-19\n=====\nThe :ref:`wish_list-name` and ``Bugs`` information\nwere moved out of this section and into their own separate sections\n(the Bugs section has been removed; see the ``bug`` subdirectory\ninstead).\n\nA discussion of\n:ref:`VecAD speed and memory<VecAD@Speed and Memory>` was added\nas well as an entry in the\n:ref:`wish_list-name` to make it more efficient.\n\n07-15\n=====\nThe ``BOOST_DIR`` and ``CPP_ERROR_WARN``\n:ref:`configure@Configure` options\nwere not properly implemented for compiling the\n``lib`` sub-directory.\nThis has been fixed.\n\nSome compiler warnings in the file ``lib/ErrFun.cpp`` ,\nwhich computes the :ref:`erf-name` function,\nhave been fixed.\n\n07-11\n=====\nThe :ref:`CppAD_vector@push_back` function has\nbeen added to the ``CppAD::vector`` template class.\n\nIt appears that the ``TestMore/Runge45.cpp`` file was missing\nan include of ``example/NearEqualExt.h`` . This has been fixed.\n\n07-08\n=====\nThe documentation for :ref:`Forward-name` and :ref:`Reverse-name` has been\nimproved.\n\n07-05\n=====\nThe :ref:`rosen_34.cpp-name` example mixed the\n:ref:`CppAD::vector<CppAD_vector-name>` and\n``CppADvector`` vector types.\nThis caused the compilation of the examples to fail when\n``CppADvector`` was defined as something other than\n``CppAD::vector`` (found by Jon Pearce).\nThis has been fixed.\n\nThe :ref:`CheckSimpleVector-name` run time code has been improved so that it is\nonly run once per case that is being checked.\n\nSimple Vector concept checking (:ref:`CheckSimpleVector-name` ) was\nadded to the routines:\n:ref:`ForOne-name` ,\n:ref:`ForTwo-name` ,\n:ref:`Forward-name` ,\n:ref:`ADFun-name` ,\n:ref:`Hessian-name` ,\n:ref:`Independent-name` ,\n:ref:`Jacobian-name` ,\n:ref:`RevOne-name` ,\n:ref:`RevTwo-name` , and\n:ref:`Reverse-name` .\n\n07-04\n=====\nSimple Vector concept checking (:ref:`CheckSimpleVector-name` ) was\nadded to the routines:\n:ref:`LuFactor-name` ,\n:ref:`LuSolve-name` ,\n:ref:`LuInvert-name` ,\n:ref:`OdeErrControl-name` ,\n:ref:`Runge45-name` , and\n:ref:`Rosen34-name` .\n\nThe previous version of the\nroutine :ref:`OdeErrControl-name` was mistakenly in the global namespace.\nIt has been moved to the ``CppAD`` namespace\n(where all the other :ref:`utilities<utility-name>` routines are).\n\nThe previous distribution (version 05-07-02) was missing the file\n``cppad/local/Default.h`` .\nThis has been fixed.\n\n07-03\n=====\nAdded :ref:`CheckSimpleVector-name` , a C++ concept checking utility\nthat checks if a vector type has all the necessary conditions\nto be a :ref:`SimpleVector-name` class with a specific element type.\n\n07-02\n=====\nVersion 7 of Microsoft's C++ compiler\nsupports the standard declaration for a friend template function.\nVersion 6 did not and\nCppAD used macros to substitute the empty string for\n``<Base>`` , ``< AD<Base> >`` , and  ``< VecAD<Base> >``\nin these declarations.\nThese macro substitutions have been removed\nbecause Version 6 of Microsoft's C++ compiler\nis no longer supported by CppAD.\n\nThe copy base section was split into the default\nconstructor and the\nconstruction for the base type.\nThe construction from base type has been\nextended to include any type that is convertible to the base type.\nAs a special case, this provides the previous wish list item of\na constructor from an arbitrary *Base* to a\n``AD< AD<`` *Base* > > , ``AD< AD< AD<`` *Base* > > > etc.\n\n07-01\n=====\nThe permissions were set as executable for many of the no-executable files\nin the distribution; for example, the ``README`` , file.\nThis has been fixed.\n\n06-25\n=====\nSome improvements were made to the\nREADME, AUTHORS, COPYING, and INSTALL files.\nIn addition, the file\n``UWCopy040507.html``\nwhich contains the University of Washington's copyright\npolicy (see Section 2) was added to the distribution.\n\n06-24\n=====\nThe ``List2Vector``\nexample utility is no longer used and has\nbeen removed.\n\n06-18\n=====\nCppAD is now supported by Microsoft Visual C++ version 7 or higher.\nThe version 6 project files\n* . ``dsw`` and * . ``dsp``\nhave been replaced by the version 7 project files\n* . ``sln`` and * . ``vcproj`` .\n\n06-14\n=====\nA new :ref:`CondExp example<cond_exp.cpp-name>` has been added and\nthe old :ref:`CondExp-name` example has been moved to the\n``TestMore`` directory (it is now only a test).\n\n06-13\n=====\nThe changes made on 06-06 do not run under Microsoft Visual C++ version 6.0\n(even though they are within the C++ standard).\nPreliminary testing under version 7 indicates that Microsoft\nhas fixed this problem in later versions of their C++ compiler.\n\n06-06\n=====\nConverted the routines\n:ref:`Forward-name` and :ref:`Reverse-name` to allow for any\n:ref:`SimpleVector-name` instead of just ``CppADvector`` .\nIn addition, separated the syntax of the function call\nfrom the prototype for each of the arguments.\nThis was also done for all the easy to use :ref:`Drivers-name`\nas well as the :ref:`Independent-name` function and\nthe :ref:`ADFun-name` constructor.\n\nAdd a section containing a list of\n:ref:`all the examples<list_all_examples-name>` .\n\n05-19\n=====\nA significant improvement in speed was obtained by moving\nthe buffer extension to a separate function and then\ninline the rest of putting operators in the tape.\nFor example,\nhere is part of the speed test output before this change:\n::\n\n    Tape of Expansion by Minors Determinant: Length = 350, Memory = 6792\n    size = 5 rate = 230\n    size = 4 rate = 1,055\n    size = 3 rate = 3,408\n    size = 2 rate = 7,571\n    size = 1 rate = 13,642\n\nand here is the same output after this change:\n::\n\n    Tape of Expansion by Minors Determinant: Length = 350, Memory = 6792\n    size = 5 rate = 448\n    size = 4 rate = 2,004\n    size = 3 rate = 5,761\n    size = 2 rate = 10,221\n    size = 1 rate = 14,734\n\nNote that your results will vary depending on operating system and machine.\n\n05-18\n=====\nChange name of ``OdeControl`` to :ref:`OdeErrControl-name`\nand improve its documentation.\n\nCorrect the syntax for the :ref:`con_dyn_var@Parameter`\nand :ref:`con_dyn_var@Variable`\nfunctions.\n\n05-16\n=====\nChange :ref:`OdeErrControl-name` to have method return its order instead\nof having a separate argument to ``OdeErrControl`` .\n\nAdd the argument *scur* to ``OdeErrControl`` ,\nimprove ``OdeErrControl`` choice of step size and documentation.\n\n05-12\n=====\nUsing profiling, the\n:ref:`multiplication operator<ad_binary-name>` was show to take a significant\namount of time. It was reorganized in order to make it faster.\nThe profiling indicated an improvement so that same change was made\nto the :ref:`ad_binary-name` and :ref:`compound_assign-name` operators.\n\n05-06\n=====\nThe documentation for\n:ref:`SimpleVector-name` and :ref:`NearEqual-name`\nwere changed to use more syntax (what the user enters)\nand simpler prototypes\n(the compiler oriented description of the arguments).\nIn addition, exercises were added at the end of the\n:ref:`SimpleVector-name` , :ref:`CppAD_vector-name` , and :ref:`NearEqual-name`\ndocumentation.\n\nThere was a undesired divide by zero case in the file\n``TestMore/VecUnary.cpp`` that just happened to work\nin corresponding :ref:`NearEqual-name` check.\nThe ``NearEqual`` routine has been changed\nto return false if either of the values being compared\nis infinite or not a number.\nIn addition, the divide by zero has been removed from\nthe ``TestMore/VecUnary.cpp`` test.\n\n05-01\n=====\nThe doubly linked list was also removed from the :ref:`VecAD-name`\ninternal data structure because this method of coding is simpler\nand it makes it more like the rest of CppAD.\n\n04-21\n=====\nThe profiling indicated that the destructor for an AD object was using a\nsignificant amount of time.\nThe internal data structure of an AD object had a doubly linked list\nthat pointed to the current variables and this was modified when\nan AD object was destroyed.\nIn order to speed AD operations in general,\nthe internal data structure of an AD object has been changed so that\nthis list is no longer necessary (a tape id number is used in its place)\n\nDuring the process above, the function :ref:`con_dyn_var@Variable` was added.\n\n04-20\n=====\nAdd profiling\nto the speed tests.\n\n04-19\n=====\nRemove an extra (not necessary)\nsemi-colon from the file ``cppad/local/Operator.h`` .\n\n03-26\n=====\nThe new routine :ref:`OdeErrControl-name` does\nautomatic step size control for the ODE solvers.\n\n03-23\n=====\nThe routine :ref:`Rosen34-name` is an improved stiff integration method\nthat has an optional error estimate in the calling sequence.\nYou must change all your calls to ``OdeImplicit``\nto use ``Rosen34`` (but do not need to change other arguments\nbecause error estimate is optional).\n\n03-22\n=====\nThe routine :ref:`Runge45-name` is an improved Runge-Kutta method\nthat has an optional error estimate in the calling sequence.\nYou must change all your calls to ``OdeRunge``\nto use ``Runge45`` (but do not need to change other arguments\nbecause error estimate is optional).\n\n03-09\n=====\nSome extra semi-colons (empty statements)\nwere generating warnings on some compilers.\nThe ones that occurred after the macros\n``CppADStandardMathBinaryFun`` ,\n``CppADCompareMember`` ,\n``CppADBinaryMember`` , and\n``CppADFoldBinaryOperator`` have been removed.\n\n03-04\n=====\nAn new multiple level of AD example :ref:`mul_level-name` was added.\n\n03-01\n=====\nAn option that specifies error and warning\n:ref:`flags<configure@cxx_flags>`\nfor all the C++ compile commands,\nwas added to the\n:ref:`Unix installation instructions<configure-name>` .\n\n02-24\n=====\nThe routine :ref:`LuSolve-name` was split into :ref:`LuFactor-name`\nand :ref:`LuInvert-name` . This enables one to efficiently\nsolve equations where the matrix does not change\nand the right hand side for one equation depends on the\nleft hand side for a previous equation.\n\nAn extra requirement was added to the\n:ref:`SimpleVector-name` template class.\nThere must be a typedef for ``value_type``\nwhich is the type of elements in the vector\n\nUnder Mandrake Linux 10.1,\nsome template friend declarations were failing because the corresponding\noperations were not declared before being indicated as friends\n(found by\n`Jean-Pierre Dussault <mailto:Jean-Pierre.Dussault@Usherbrooke.ca>`_).\nThis has been fixed.\n\n01-08\n=====\nThe :ref:`erf-name` function was added.\nThe implementation of this function used conditional expressions\n(:ref:`CondExp-name` ) and some times the expression that was not\nvalid in a region caused division by zero.\nFor this reason, the check and abort on division by zero\nhas been removed.\n\n{xrst_end 2005}\n"
  },
  {
    "path": "appendix/whats_new/2006.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin 2006 app}\n{xrst_spell\n    aclocal\n    autoconf\n    automake\n    avector\n    delem\n    div\n    dw\n    fy\n    gprof\n    kasper\n    kristensen\n    makefile\n    memcheck\n    of of\n    omh\n    rpm\n    sed\n    speedtest\n    tautschnig\n    usr\n    valgrind\n    yy\n    yyyymmdd\n}\n\nRelease Notes for 2006\n######################\n\nmm-dd\n*****\n\n12-24\n=====\nMove ``exp_eps_ad`` to ``exp_eps_cppad`` and\nadd exercises to the following sections:\n:ref:`exp_eps_rev1-name` ,\n:ref:`exp_eps_cppad-name` .\n\nAdd operation sequence indices to help track operations in\n:ref:`exp_eps_for0-name` ,\n:ref:`exp_eps_for1-name` ,\n:ref:`exp_eps_rev1-name` .\n\n12-23\n=====\nAdd exercises to the following sections:\n:ref:`get_started.cpp-name` ,\n:ref:`exp_eps-name` ,\n:ref:`exp_eps_for0-name` , and\n:ref:`exp_eps_for1-name` .\n\n12-22\n=====\nMove :ref:`get_started.cpp-name` below the :ref:`introduction-name` directory.\n\nMove the exponential example to the subdirectory\n``introduction/exp_apx`` and change the\n``--with-Introduction``\nunix configure option\nto build both the :ref:`get_started.cpp-name` and :ref:`exp_apx.cpp-name`\nexample programs.\n(The ``--with-GetStarted`` configure command line option has been removed.)\n\n12-21\n=====\nAdd the :ref:`source code for Poly<poly.hpp-name>` to the documentation\nand include :ref:`Poly-name` in the in the :ref:`speed_utility-name` section.\n\nThe :ref:`get_started.cpp-name` section has been moved\ninto the :ref:`Introduction-name` and\n:ref:`get_started.cpp@Exercises` were added to that section.\nIn addition some sections has switched position between\nthe top level :ref:`user_guide-name` and the :ref:`appendix-name` .\n\n12-19\n=====\nReorganize so that the source code is below the corresponding routine\nin the documentation tree (instead of at the same level) for the\nfollowing routines:\n:ref:`det_by_minor-name` ,\n:ref:`det_grad_33-name` ,\n:ref:`uniform_01-name` ,\n:ref:`det_of_minor-name` ,\n:ref:`det_by_lu-name` ,\n:ref:`LuInvert-name` ,\n:ref:`LuFactor-name` ,\n:ref:`LuSolve-name` .\n\nSeparate the specifications for the source in\n:ref:`speed_utility-name` and add cross reference to the following routine\nspecification and implementations:\n:ref:`det_by_minor-name` ,\n:ref:`det_grad_33-name` ,\n:ref:`uniform_01-name` ,\n:ref:`det_of_minor-name` ,\n:ref:`det_by_lu-name` ,\n:ref:`LuInvert-name` ,\n:ref:`LuFactor-name` ,\n:ref:`LuSolve-name` .\n\n12-18\n=====\nMake the :ref:`speed-name` source code easier to read.\n\nChange the speed test output name ``det_poly`` to ``poly``\n(as it should have been).\n\n12-17\n=====\nThe speed test :ref:`det_grad_33-name` was missing its documentation\n(this has been fixed).\nIn addition, the titles and indexing for the speed test documentation\nhas been improved.\n\nAdd to the specifications that each repeated test corresponds to a\ndifferent matrix in\n:ref:`det_lu<link_det_lu-name>` and\n:ref:`det_minor<link_det_minor-name>` .\nIn addition, modify all the speed tests so that they abide by this rule.\n\nChange some references from the deprecated name ``CppAD.h`` to\nnew name ``cppad.hpp`` .\n\nChange :ref:`adolc_det_minor.cpp-name` and :ref:`cppad_det_minor.cpp-name`\nto tape once and reuse operation sequence for each repeated\nmatrix in the test.\n\nAdd the :ref:`poly<link_poly-name>` speed test for all three packages.\nIn addition, correct a missing include in :ref:`poly-name` routine.\n\n12-15\n=====\nThe wish list item\nto simplify and better organize the speed tests been completed:\n\n.. csv-table::\n    :widths: auto\n\n    :ref:`speed/<speed-name>`,template functions that are speed tested\n    ``speed/example``,example usage of speed template functions\n    :ref:`speed/adolc<speed_adolc-name>`,Adolc drivers for the template functions\n    :ref:`speed/cppad<speed_cppad-name>`,CppAD drivers for the template functions\n    :ref:`speed/fadbad<speed_fadbad-name>`,Fadbad drivers for the template functions\n    speed/profile,profiling version of CppAD drivers\n\n12-13\n=====\nNext step for the speed wish list item:\nremove ``speed_cppad`` from the documentation and replace it by\n``speed/cppad`` , see :ref:`speed_cppad-name` for the new CppAD speed\ntest routines.\n\n12-12\n=====\nStarted the speed wish list item by\nmove the ``adolc`` director to ``speed/adolc`` and\n``fadbad`` to ``speed/fadbad`` .\n\n12-11\n=====\nStarted the speed wish list item by\ncreating the ``speed/example`` directory and moving the relevant\nexamples from\n``example/`` * . ``cpp`` and\n``speed_example/`` * . ``cpp`` to\n``speed/example/`` * . ``cpp`` .\nIn addition, the relevant include files have been moved from\n``example/`` * . ``hpp`` to\n``speed/`` * . ``hpp`` .\n\nA new :ref:`speed_test-name` routine was added to the library.\n\n12-10\n=====\nThe :ref:`pow-name` function was changed to be a an ``AD`` < *Base* >\n:ref:`atomic_base<glossary@Operation@Atomic>` operation.\nThis function used to return a ``nan`` if\n*x* is negative because it was implemented as\n\n    ``pow`` ( *x* , *y* ) = ``exp`` ( ``log`` ( *x* ) * *y*  )\n\nThis has been fixed so that the function and its derivatives are now\ncalculated properly when *x* is less than zero.\nThe :ref:`pow-name` documentation was improved\nand the :ref:`pow.cpp-name` example was changed to\ntest more cases and to use the same variable\nnames as in the documentation.\n\n12-09\n=====\nA speed wish list item was added to the wish list.\n\nThe prototype for ``int`` arguments in binary operations\n(for example :ref:`addition<ad_binary-name>` ) was documented as\n``const int &`` but was actually just plain ``int`` .\nThis has been fixed.\n(Later changed to ``double`` .)\n\n12-07\n=====\nFix bug in the\nsubversion installation instructions; see\n`bug report <https://list.coin-or.org/pipermail/cppad/2006q4/000076.html>`_.\n\nThe some of the automatically generated ``makefile.in`` files\nhad an improper license statement in the GPL license version.\nThis has been fixed.\n\n12-05\n=====\nAdd the unix installation\n--with_Documentation option\nand remove the\n*postfix_dir* option.\n\nCreate a fixed\n:ref:`whats_new-name` section above the section for each particular year.\nAlso improve the CppAD distribution ``README`` file.\n\n12-03\n=====\nThe include file directory ``CppAD`` was changed to be all\nlower case; i.e., ``cppad`` .\nIf you are using a Unix system, see :ref:`include_deprecated-name` .\nThis completes the following :ref:`wish_list-name` items (which were removed):\n\n#. File and directory names should only contain lowercase letters,\n   numbers underscores and possibly one period.\n   The leading character must be alphabetic.\n\n#. C++ header files should have the ``.hpp`` extension.\n\n12-02\n=====\nPut explanation of version numbering in the\ndownload instructions.\n\nCorrect some file name references under the Windows heading in\n:ref:`speed_cppad-name` .\n\n12-01\n=====\nAll of the ``Makefile.am`` and ``Makefile`` files were changed\nto lower case; i.e., ``makefile.am`` and ``makefile`` .\n\nFix compiler warning while compiling ``cppad/RombergOne/``\n(mistake occurred during :ref:`11-20<2006@mm-dd@11-29>` change).\n\n11-30\n=====\nCygwin packages, and other system packages,\nshould not have a dash in the version number.\nSee\n`cygwin package file naming <https://cygwin.com/packaging-package-files.html>`_ .\nor, to quote the\n`rpm file naming convention <http://ftp.rpm.org/max-rpm/ch-rpm-file-format.html>`_\n*The only restriction placed on the version is that*\n*it cannot contain a dash \"-\".*\nAs per the acceptable package naming conventions for cygwin,\nCppAD version numbering has be changed from\n*yy* ``-`` *mm* ``-`` *dd* format to *yyyymmdd* ; i.e.\n``cppad-06-11-30`` was changed to ``cppad-20061130`` .\n\n11-29\n=====\nThere was a problem using :ref:`RombergOne-name` with floating point\ntypes other than ``double`` . This has been fixed.\n\n11-28\n=====\nThe :ref:`installation<Install-name>` download files were not being built\nbecause ``Makefile.am`` referenced ``Doc`` when it should have\nreferenced ``doc`` . This has been fixed.\n\n11-23\n=====\nA Version Numbering entry was added to the\n:ref:`wish_list-name` (this was completed on :ref:`2006@mm-dd@11-30` ).\n\n11-18\n=====\nThe example routine that computes determinants using expansion\nby minors ``DetOfMinor`` was changed to :ref:`det_of_minor-name` ,\nin preparation for\nmore formal speed comparisons with other packages.\nTo be specific, its documentation was improved,\nits dependence on the rest of CppAD was removed\n(it no longer includes CppAD.h ).\n\n11-12\n=====\nThe\n:ref:`general.cpp-name` and\n``test_more/test_more.cpp``\nprograms were\nchanged to print out the number of tests that passed or failed instead\nof just \"All the tests passed\" or \"At least one of the tests failed\".\n\nThe windows project files for\nexamples and testing\nshould have been changes to use lower case file names on\nas part of the 11-08 change below. This has been fixed.\n\n11-08\n=====\nMove the ``Example`` directory to ``example``\nand change all its files to use lower case names.\n\n11-06\n=====\nMove the ``TestMore`` directory to ``test_more``\nand change all its files to use lower case names.\n\n11-05\n=====\nRemove references in the :ref:`speed_cppad-name` tests to the\n``Memory`` and ``Size`` functions because they\nhave been :ref:`deprecated<fun_deprecated-name>` .\n\nCorrect some references to ``var_size`` that should have been\n:ref:`fun_property@size_var` .\n\n11-04\n=====\nPut text written to standard output in the documentation for the\n:ref:`get_started.cpp<get_started.cpp@Output>` and\n``print_for.cpp`` examples.\n(Now documentation can be built from a subversion checkout with out\nneeding to execute automake.)\nThe ``PrintFor.cpp`` and\n``speedtest.cpp`` examples were missing in :ref:`list_all_examples-name`\n(which has been fixed).\n\nMove the ``Speed`` directory to ``speed``\nand change all its files to use lower case names.\n\n11-02\n=====\nThe ``print_for`` directory was referenced as ``PrintFor``\nin the root CppAD ``Makefile.am`` this has been fixed.\n\nThe documentation for the Adolc helper routines\n``AllocVec``  and ``AllocMat`` were not being included.\nThis has been fixed.\n\nMove the ``GetStarted`` directory to ``get_started``\nand change all its files to use lower case names.\n\n11-01\n=====\nMove the ``PrintFor`` directory to ``print_for``\nand change all its files to use lower case names.\n\n10-31\n=====\nMove the ``SpeedExample`` directory to ``speed_cppad_example``\nand change all its files to use lower case names.\n\n10-29\n=====\nMove the ``Adolc`` directory to ``adolc``\nand change all its files to use lower case names.\n\nChange all the file in the ``omh`` directory to\nuse lower case names.\n\nThe file ``Makefile.am`` in the distribution directory had the\nCPL copyright message in the GPL version. This has been fixed.\n\n10-28\n=====\nThe copyright message in the script files\n``example/OneTest`` and ``TestMore/OneTest`` were GPL\n(in the CPL distribution).\nThis has been fixed by moving them to\n``example/OneTest.sh`` and ``TestMore/OneTest.sh`` so that\nthe distribution automatically edits the copyright message.\n\n10-27\n=====\nChange :ref:`hes_lagrangian.cpp-name` example so that it computes the\nLagrangian two ways. One is simpler and the other can be used\nto avoid re-taping operation sequence.\n\n10-26\n=====\nChange :ref:`hes_lagrangian.cpp-name` example so that it modifies\nthe independent variable vector between the call to\n:ref:`Independent-name` and the ``ADFun`` < *Base* >\n:ref:`constructor<fun_construct-name>` .\n\n10-25\n=====\nA subversion install procedure was\nadded to the documentation.\n\nFix definition of preprocessor symbol\n``PACKAGE_STRING`` in ``Speed/Speed.cpp``\n(broken by change on 10-18).\n\nAdded the example\n:ref:`hes_lagrangian.cpp-name` which computes the Hessian\nof a Lagrangian.\n\n10-18\n=====\nDocument and fix possible conflicts for\n:ref:`preprocessor symbols<preprocessor-name>`\nthat do not begin with ``CppAD`` or ``CPPAD_`` .\n\nInclude a default value for the file ``cppad/config.h``\nin the subversion repository.\n\n10-16\n=====\nFix bug when using :ref:`OdeErrControl-name` with the type\n``AD< AD<double> >`` .\n\n10-10\n=====\nAdd the :ref:`Var2Par-name` function so it is possible\nto obtain the :ref:`Value-name` of a variable.\nMove the ``Discrete.cpp`` example to :ref:`tape_index.cpp-name` .\nFix the Microsoft project file so that the Windows install\nexamples and testing works properly\n(it was missing the :ref:`stack_machine.cpp-name` example).\n\n09-30\n=====\nThese changes were grouped together because it took a while for Coin-Or\nto review the dual licensing version and because it was not possible to\nget the nightly build changed:\n\n#. Change shell scripts to use \\*.sh extension.\n#. Two versions, one with CPL and other with GPL license.\n#. Change subversion version of CppAD from GPL to CPL copyright.\n#. Change all files in cppad/local to use lower case and \\*.hpp extension.\n#. CppAD_vector.h was generating a warning on version 4 of gcc.\n   This have been fixed.\n#. Change the preprocessor ``# define`` commands\n   in ``cppad/local/\\*.hpp`` to use upper case names.\n#. Add the :ref:`stack_machine.cpp-name` example.\n\n08-17\n=====\nSome error message occurred while executing\n::\n\n    valgrind --tool=memcheck example/example\n    valgrind --tool=memcheck TestMore/TestMore\n\nThese were not really bugs, but they have been fixed to avoid\nthis conflict between CppAD and `valgrind <https://valgrind.org/>`_.\n\n07-14\n=====\nMake some improvements were made to the :ref:`Introduction-name` ,\n:ref:`exp_eps.hpp-name` and :ref:`exp_eps_rev1-name` sections.\n\n07-12\n=====\nUse a drop down menu for the navigation links, instead of a separate frame\nfor the navigation links, for each section in the documentation.\n\n06-29\n=====\nNewer versions of the gcc compiler generated an error because\n:ref:`erf-name` was using :ref:`CondExp-name` before it was defined.\nThis was found by Kasper Kristensen and his fix has been\nincluded in the CppAD distribution.\n\n06-22\n=====\nThe :ref:`ADFun-name` operation\n*f* ( *x* , *y* ) no longer executes a zero order\n:ref:`Forward-name` operation when a new operation sequence is stored in\n*f* .\nIn addition, the syntax for this operation was changed to\n*f* . ``Dependent`` ( *y* ) (see :ref:`Dependent-name` ).\n\n{xrst_comment ------------------------------------------------------ }\n06-19\n=====\nThe changes listed under 06-17 and 06-18 were made in the branches/ADFun branch\nof the CppAD subversion repository. They did not get merged into the trunk\nand become part of the distribution until 06-19. This accomplished the\nfollowing goal, which was removed from the :ref:`wish_list-name` :\n\n\"We would like to be able to erase the function\nvalues so that :ref:`ADFun-name` objects use less memory.\nWe may even want to erase the AD operation sequence so that\n:ref:`ADFun-name` objects use even less memory and can be used\nfor a subsequent AD operation sequence.\"\n\n#. 06-17:\n   Added :ref:`capacity_order-name` which can be used to control\n   the amount of memory used to store :ref:`Forward-name` results.\n   Also :ref:`deprecated<fun_deprecated-name>` ``taylor_size`` , and defined\n   :ref:`size_order-name` in its place.\n\n#. 06-18:\n   Added the :ref:`ADFun default constructor<fun_construct-name>`\n   and the ability to\n   :ref:`store a new operation sequence<Dependent-name>`\n   in an ``ADFun`` object with out having to use\n   ``ADFun`` pointers together with ``new``\n   and ``delete`` .\n\n{xrst_comment ------------------------------------------------------ }\n\n06-17\n=====\nThe location where the distribution files are stored has changed\nand this broke the Download Current Version links for the\nunix and windows installation.\nThis has been fixed.\n\nThe compiling instructions for the :ref:`speed_cppad-name` routines have been improved.\n\nThe :ref:`Value-name` function has been extended to allow for\n:ref:`glossary@Parameter` arguments even if the corresponding\ntape is in the Recording state.\n\nThe :ref:`BenderQuad-name` documentation and example have been improved\nby changing *Vector* to *BAvector* to emphasize that\nit corresponds to a vector of *Base* objects.\n\n06-15\n=====\nChange :ref:`BenderQuad-name` to use *Base* instead of\n``AD`` < *Base* > where every possible.\nThis allows for more calculations to be done in the base type; i.e.,\nis more efficient.\n\n06-09\n=====\nAdd a size check (size one) for the\n:ref:`function value argument, g<BenderQuad@g>` in ``BenderQuad`` .\n\n06-07\n=====\nSome major changes were made to the notation in\n:ref:`get_started.cpp-name` (to make it easier to start using CppAD).\n\nIn the :ref:`Introduction-name` example,\n:math:`exp_eps` was changed to :math:`{\\rm exp\\_eps}`.\n\n06-05\n=====\nChange :ref:`BenderQuad-name`\n:math:`F_y (x, y)` to :math:`H(x,y)` so applies in a more\ngeneral setting.\nThis was another change to the ``BenderQuad`` interface,\n*fun* . ``fy`` was changed to *fun* . ``h`` .\n\n06-02\n=====\nNewer versions of the gcc compiler generated a warning for possible\nuse of an uninitialized pointer.\nThis was found by Michael Tautschnig and his fix has been\nincluded in the CppAD distribution.\n\n05-31\n=====\nThe interface to :ref:`BenderQuad-name` has been changed.\nNow all the function evaluation routines\nare member functions of one class object.\nThis makes it easy for them to share common data.\n\n05-29\n=====\nChange statement of command syntax to\nbe in the same browser frame as the command documentation\n(for all the commands with a syntax statement).\nNow when a user links to a specific heading in\na command's documentation,\nthe syntax for that command is automatically included.\nBefore the user needed to\nfollow another link to see to the command syntax.\n\n05-27\n=====\nAdded :ref:`BenderQuad-name` for computing the Hessian of\nBender's reduced objective function.\n\nAdded special specifications for ``resize(0)``\nto :ref:`CppAD_vector-name` .\n\n05-03\n=====\nThe g++ (GCC) 4.1.0 (Red Hat 4.1.0-3) compiler reported an error\nbecause certain functions were used before being defined\n(version 3.4.4 did not complain about this).\nThis has been fixed.\n\n04-29\n=====\nChange all of the example and test driver programs so that they return\nerror codes; i.e., zero for no error and one for an error.\n\nAdd more discussion and a reference for a\n``gcc 3.4.4 -O2`` bug (since been removed).\n\n04-28\n=====\nImprove the :ref:`get_started.cpp-name` example and move\nit so that it is visible at the too level of the documentation.\n\n04-26\n=====\nThe programs in :ref:`Introduction-name` have been converted to automated\ntest that return true or false with the driver program\n:ref:`Introduction<exp_apx.cpp-name>` .\n\n04-25\n=====\nAdd an :ref:`Introduction-name` section to the documentation\n(replaces old example that was part of the :ref:`Theory-name` section).\n\n04-19\n=====\nA discussion was added near the end of the :ref:`FunCheck-name` documentation.\nAnd the cross references to the :ref:`CompareChange-name` discussion\nwere changed to the FunCheck discussion.\n\nAn operation sequence entry was added to the :ref:`wish_list-name` .\n\n04-18\n=====\nThe new definitions for\n:ref:`glossary@AD of Base`\nand\n:ref:`operation sequence<glossary@Operation@Sequence>`\nhave been used throughout the documentation.\n\nAdd the :ref:`FunCheck-name` section for checking that a sequence of\noperations is as intended.\n\n04-17\n=====\nThe documentation for :ref:`SpeedTest-name` and :ref:`Poly-name` was improved.\n\nDefinitions were added for an atomic :ref:`glossary@Operation`\nand for an operation sequence being\ndependent and independent of the values of specific operands.\n\nThe definition of AD sequence of operations was made abstract\nand moved to the glossary as\n:ref:`Type operation sequence<glossary@Operation@Sequence>` .\n\n04-15\n=====\nThe :ref:`mul_level-name` example was moved from\n:ref:`ADFun-name` to :ref:`General-name` .\nThe documentation for :ref:`SpeedTest-name` was improved.\n\n04-14\n=====\nDocumentation and examples were improved for the following routines:\n:ref:`ForTwo-name` ,\n:ref:`RevTwo-name` .\nIn addition, the computation in ``RevTwo`` was made more efficient\n(it used to possibly calculate some first order partials that were not used).\n\n04-13\n=====\nDocumentation and examples were improved for the following routines:\n:ref:`Jacobian-name` ,\n:ref:`ForOne-name` ,\n:ref:`RevOne-name` ,\nand :ref:`Hessian-name` .\n\n04-08\n=====\nIn the case where :ref:`fun_deprecated@use_VecAD` is true,\nthe :ref:`ForSparseJac-name` calculation in only for the current\nindependent variable values.\nIn this case, the sparsity pattern can be (and has been)\nmade more efficient; i.e., fewer true values\n(because it only applies to the current :ref:`forward_zero-name` ).\n\nThe conversion from\n:ref:`VecAD@VecAD\\<Base>::reference`\nto :ref:`AD-name` gave a compile error (this has been fixed).\nCode example for this fix\n::\n\n    VecAD<double> V(1);\n    AD<double> zero = 0;\n    V[zero] = 1.;\n    static_cast< AD<double> > ( V[zero] );\n\n04-06\n=====\nThe :ref:`ForSparseJac-name` , :ref:`RevSparseJac-name` , :ref:`RevSparseHes-name`\nsparsity results are now valid for\nall independent variable values\n(if the AD operation sequence does no use any\n``VecAD`` < *Base* > operands).\nIn addition, the\n``ForSparseJac`` , :ref:`RevSparseJac-name` and :ref:`RevSparseHes-name`\ndocumentation and examples were improved.\n\nThe :ref:`useVecAD<fun_deprecated@use_VecAD>`\nmember function was added to :ref:`ADFun-name` objects.\n\nThe ``var_size`` member function was changed to\n:ref:`fun_property@size_var`\n(this is not backward compatible, but ``var_size`` was just added on\n:ref:`2006@mm-dd@04-03` ).\n\n04-05\n=====\nThe documentation and example for :ref:`CompareChange-name` were\nimproved and moved to be part of the :ref:`Forward-name` section.\n\n04-04\n=====\nThe documentation and examples for :ref:`Reverse-name` were\nimproved and split into :ref:`reverse_one-name` and :ref:`reverse_any-name` .\n\n04-03\n=====\nCreate separate sections for the\n:ref:`zero<forward_zero-name>` and :ref:`forward_one-name` first order case\nof :ref:`Forward-name` mode.\n\nThe ADFun :ref:`fun_deprecated@Size` member function\nhas been deprecated (use :ref:`size_order-name` instead).\n\nThe :ref:`Reverse-name` member function is now declared,\nand documented as, ``const`` ; i.e.,\nit does not effect the state of the ADFun object.\n\nChange the examples that use :ref:`Reverse-name` to use the same\nreturn value notation as the documentation; i.e., ``dw`` .\n\n04-02\n=====\nThe member functions of :ref:`ADFun-name` that return properties of\nAD of *Base*\n:ref:`operation sequence<glossary@Operation@Sequence>`\nhave been grouped into the :ref:`fun_property-name` section.\nIn addition, the :ref:`fun_property.cpp-name` example has been added.\n\nThe :ref:`CompareChange-name` function documentation was improved\nand moved to a separate section.\n\nGroup the documentation for the :ref:`ADFun-name` member functions that\nevaluate functions and derivative values.\nThis organization has since been changed.\n\nRemove the old ``Fun.cpp`` example and extend\n:ref:`independent.cpp-name` so that it demonstrates using different\nchoices for the :ref:`SimpleVector-name` type.\n\n04-01\n=====\nMove the :ref:`ADFun Constructor<fun_construct-name>` to its own separate\nsection, improve its documentation, and use :ref:`independent.cpp-name`\nfor its example.\n\nThe following member functions of :ref:`ADFun-name` have been\n:ref:`deprecated<fun_deprecated-name>` :\n``Order`` , ``Memory`` .\n\nThe wish list entry for Memory usage\nwas updated on 04-01.\nThe request was implemented on :ref:`2006@mm-dd@06-19`\nand the entry was removed from the wish list.\n\n03-31\n=====\nAdd examples for the :ref:`Parameter, Variable<con_dyn_var-name>` and\n:ref:`Independent-name` functions.\n\nMove the :ref:`con_dyn_var@Parameter`\nand :ref:`con_dyn_var@Variable` functions from\nthe :ref:`ADFun-name` section to the :ref:`AD-name` section.\n\nIn the examples for the :ref:`AD-name` sections,\nrefer to the range space vector instead of the dependent variable vector\nbecause some of the components may not be\n:ref:`variables<glossary@Variable>` .\n\n03-30\n=====\nMove the :ref:`LuRatio-name` section below :ref:`lu_det_and_solve-name` .\n\nMove the definition of an\nAD of *Base*\n:ref:`operation sequence<glossary@Operation@Sequence>`\nfrom the glossary to the :ref:`AD-name` section.\n\nImprove the definition of tape state.\n\nAdd mention of taping to\n:ref:`Erf-name` , :ref:`bool_fun-name` , :ref:`near_equal_ext-name` ,and :ref:`Pow-name` .\n\nChange the definition for\n:ref:`VecAD@VecAD\\<Base>::reference`\nso that it stands out of the text better.\n\n03-29\n=====\nMention the :ref:`VecAD@VecAD\\<Base>::reference` case in\ndocumentation and examples for\n:ref:`abs-name` , :ref:`atan2-name` , :ref:`erf-name` , and :ref:`pow-name` .\n\nFix a bug derivative computation for ``abs`` ( *x* )\nwhen *x* had type ``AD< AD<double> >`` and *x*\nhad value zero.\n\nFix a bug using non-zero AD indices for :ref:`VecAD-name` vectors\nwhile the tape is in the empty state.\n\nExtend :ref:`erf-name` to include ``float`` , ``double`` ,\nand ``VecAD`` < *Base* >:: ``reference`` .\n\n03-28\n=====\nMention the\n:ref:`VecAD@VecAD\\<Base>::reference` case in\ndocumentation and examples for\n:ref:`unary_plus-name` ,\n:ref:`unary_minus-name` ,\n:ref:`ad_binary-name` ,\n:ref:`compound_assign-name` , and\n:ref:`unary_standard_math-name`\n\n03-27\n=====\nExtend and improve the\n:ref:`VecAD exceptions<VecAD@VecAD<Base\\>::reference@Exceptions>` .\n\nMention the :ref:`VecAD@VecAD\\<Base>::reference` case\nand generally improve\n:ref:`addition<ad_binary-name>` documentation and examples.\n\n03-26\n=====\nImprove documentation and examples for :ref:`VecAD-name` and change\nits element type from\n``VecADelem`` < *Base* > to ``VecAD_reference`` < *Base* >\n(so that it looks more like\n:ref:`VecAD@VecAD\\<Base>::reference` ).\n\nMention the :ref:`VecAD@VecAD\\<Base>::reference` case\nand generally improve\n:ref:`Value-name` , :ref:`ad_output-name` and :ref:`assignment<ad_assign-name>` documentation\nand examples.\n\nExtend :ref:`Integer-name` and :ref:`PrintFor-name` to include the\n:ref:`VecAD@VecAD\\<Base>::reference` case\n(and mention in documentation and examples).\n\n03-24\n=====\nMove :ref:`VecAD-name` and :ref:`LuRatio-name` from the old ExtendDomain section\nto :ref:`AD-name` .\n\n03-23\n=====\nImprove documentation and examples for\n:ref:`CondExp-name` and :ref:`Discrete-name` .\nMove both of these sections from ExtendDomain to :ref:`ADValued-name` .\n\n03-22\n=====\nThe documentation sections under :ref:`AD-name`\nhave been organized into a new set of sub-groups.\n\n03-18\n=====\nThe documentation and example for :ref:`PrintFor-name` have been improved.\nThe sections below :ref:`AD-name`\nin the documentation have been organized into subgroups.\n\n03-17\n=====\nThe documentation and examples have been improved for the\nfollowing functions:\n:ref:`bool_fun-name` , and\n:ref:`near_equal_ext-name` .\n\n03-16\n=====\nImprove the documentation and example for the :ref:`pow-name` function.\nThis includes splitting out and generalizing the integer case\n:ref:`pow_int-name` .\n\nThe copies of the ``atan2`` function were included\nin the CppAD namespace for the\n``float`` and ``double`` types.\n\n03-15\n=====\nImprove the introduction to CppAD on the top level page\nof the documentation.\n\n03-11\n=====\nThe file ``cppad/local/MathOther.h`` had a file name case error\nthat prevented the documentation from building and tests from running\n(except under Cygwin which is not really case sensitive).\nThis has been fixed.\n\nThe term AD of *Base*\n:ref:`operation sequence<glossary@Operation@Sequence>`\nhas been defined.\nIt will be used to improve the user's understanding of exactly\nhow an :ref:`ADFun-name` object is related to the C++ algorithm.\n\n03-10\n=====\nThe math functions that are not under :ref:`unary_standard_math-name` have\nbeen grouped under ``MathOther`` .\n\nThe documentation and examples have been improved for the\nfollowing functions:\n:ref:`abs-name` , :ref:`atan2-name` .\n\n03-09\n=====\nThe examples\n:ref:`cos.cpp-name` ,\n:ref:`cosh.cpp-name` ,\n:ref:`exp.cpp-name` ,\n:ref:`log.cpp-name` ,\n:ref:`log10.cpp-name` ,\n:ref:`sin.cpp-name` ,\n:ref:`sinh.cpp-name` ,\n:ref:`sqrt.cpp-name`\nhave been improved.\n\n03-07\n=====\nThe ``tan`` function has been added to CppAD.\n\nThe examples :ref:`Acos.cpp-name` , :ref:`Asin.cpp-name` and\n:ref:`atan.cpp-name` have been improved.\n\n03-05\n=====\nThe AD standard math unary functions documentation\nhas been grouped together with improved documentation\nin :ref:`unary_standard_math-name` .\n\n02-28\n=====\nThe :ref:`ad_output-name` and :ref:`Abs-name`\ndocumentation and example have been improved.\nMinor improvements were also made to the :ref:`lu_vec_ad.cpp-name` documentation.\n\n02-25\n=====\nThe :ref:`Compare-name` documentation and example have been improved.\n\n02-24\n=====\nThe documentation and examples have been improved for the following sections:\n:ref:`division<ad_binary-name>` , :ref:`-=<compound_assign-name>` , :ref:`\\*=<compound_assign-name>` , and :ref:`/=<compound_assign-name>` .\n\n02-23\n=====\nThe :ref:`multiplication<ad_binary-name>` documentation and example have been improved.\n\n02-21\n=====\nThe :ref:`subtraction<ad_binary-name>` documentation and example have been improved.\n\nThere was a bug :ref:`RevTwo-name` that was not detected by the\n:ref:`rev_two.cpp-name` test. This bug was reported by\n`Kasper Kristensen <https://list.coin-or.org/pipermail/cppad/2006-February/000020.html>`_\nA test was added ``TestMore/rev_two.cpp`` that detects this problem\nand the problem has been fixed.\n\n02-15\n=====\nThe :ref:`+=<compound_assign-name>` documentation and example have been improved.\n\n02-14\n=====\nThe :ref:`addition<ad_binary-name>` documentation and example have been improved.\n\n02-13\n=====\nCombine the old binary operator and compound assignment documentation\ninto :ref:`Arithmetic-name` documentation.\n\nThe documentation and examples have been improved for the following sections:\n:ref:`assignment<ad_assign-name>` , :ref:`unary_plus-name` , :ref:`unary_minus-name` .\n\n02-11\n=====\nThe documentation and examples have been improved for the following sections:\n:ref:`ad_ctor-name` ,\n:ref:`ad_ctor-name` and :ref:`ad_assign-name` , and\n:ref:`Value-name` .\n\n02-10\n=====\nThis is the beginning of a pass to improve the documentation:\nThe documentation sections\nThe CopyBase (formerly FromBase and now part of :ref:`ad_ctor-name` and :ref:`ad_assign-name` ) and\n:ref:`AD copy constructor<ad_ctor-name>`\n(formerly Copy) documentation has been modified.\n\nSome of the error messaging during :ref:`ADFun-name` construction\nhas been improved.\n\n02-04\n=====\nThere was a read memory access past the end of an array in\n:ref:`CppAD::vector::push_back<CppAD_vector@push_back>` .\nThis has been fixed and in addition\n:ref:`track_new_del-name` is now used to do and check the allocation in\n``CppAD::vector`` .\n\nThe routines :ref:`Runge45-name` and :ref:`Rosen34-name`\nhad static vectors to avoid recalculation on each call.\nThese have been changed to be plain vectors to avoid memory\nleak detection by :ref:`track_new_del@TrackCount` .\n\n01-20\n=====\nAdd software guidelines\nto the wish list.\n\n01-18\n=====\nImprove the definition for\n:ref:`parameters<glossary@Parameter>` and\n:ref:`variables<glossary@Variable>` .\nRemove unnecessary reference to parameter and variable\nin  documentation for :ref:`Independent-name` .\n\n01-08\n=====\nThe aclocal program is part of the automake and autoconf system.\nIt often generates warnings of the form:\n\n| |tab| / ``usr/share/aclocal/`` ...: ``warning: underquoted definition of``\n| |tab| ...\n\nThe shell script file ``FixAclocal`` ,\nwhich attempts to fix these warnings,\nwas added to the distribution.\n\n01-07\n=====\nChange CppAD error handler from using the macros defined in\n``cppad/CppADError.h`` to using a class defined in\n:ref:`include/cppad/utility/error_handler.hpp<ErrorHandler-name>` .\nThe macros ``CppADUnknownError`` and ``CppADUsageError``\nhave been deprecated (they are temporarily still available in the\nfile ``cppad/local/CppADError.h`` ).\n\n01-02\n=====\nAdd the sed script ``Speed/gprof.sed`` to aid in the display of the\nprofiling output.\n\nMake the following source code files easier to understand:\n``Add.h`` , ``Sub.h`` , ``Mul.h`` , ``Div.h``\n(in the directory ``cppad/local`` ).\n\n01-05\n=====\nMake the following source code files easier to understand:\n``RevSparseHes.h`` ,\n``Reverse.h`` ,\n``Fun.h`` ,\n``Forward.h`` ,\n``ForSparseJac.h`` ,\n``RevSparseJac.h``\n(in the directory ``cppad/local`` ).\n\n{xrst_end 2006}\n"
  },
  {
    "path": "appendix/whats_new/2007.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin 2007 app}\n{xrst_spell\n    adouble\n    apx\n    autoconf\n    automake\n    executables\n    gettimeofday\n    ginac\n    intro\n    inv\n    isnan\n    kipp\n    makefile\n    makefiles\n    omh\n    openmp\n    rpm\n    tarballs\n    tay\n    tgz\n    threadprivate\n    valgrind\n    vcproj\n    yyyymmdd\n}\n\nRelease Notes for 2007\n######################\n\nmm-dd\n*****\n\n12-29\n=====\nLicense conversions missed the copyright message at the top\nin the following special cases:\n``makefile.am`` , ``makefile.in`` , and\n``omh/appendix/license.omh`` .\n\n12-25\n=====\nThe :ref:`install-name` instructions have been improved.\n\n12-21\n=====\nThe --with_Documentation\noption on the ``configure`` command line caused an error on some\nsystems because it attempted to copy to many files.\nThis has been fixed by copying the directory instead of the individual files.\n\n12-08\n=====\nBy mistake, the documentation :ref:`License-name` statement\nfor the GPL distribution was the same as for the CPL distribution.\nThis has been fixed.\n\n12-05\n=====\nChange the name of the spec file from\n``cppad-`` *yyyymmdd* . ``spec`` to ``cppad.spec`` .\n\n12-04\n=====\nAdd the capability for the RPM spec file to use a different\nprefix directory.\n\n12-03\n=====\nThis is the first version with the rpm spec file\n``cppad.spec`` .\n\n12-02\n=====\nAdd the ``DESTDIR`` = *directory* option on the\n:ref:`configure@make install` command line.\n\n11-29\n=====\nThe :ref:`unary_standard_math-name` function ``sqrt`` did not link properly\nwhen *Base* was ``AD<double>`` .\nThis has been fixed.\n\n11-23\n=====\nThe routines ``nan`` and ``isnan`` were failing\nfor some systems because they use ``nan`` and or ``isnan``\nas preprocessor symbols.\nThis has been fixed; see :ref:`nan@Include@Macros` .\nIn addition, the example and test :ref:`nan.cpp-name` has been added.\n\n11-18\n=====\nSpeed tests for ``tape_values`` branch were not better than trunk,\nso the good parts of that branch (but not all) were merged into the trunk.\n\nThe interface specifications for\n:ref:`base type requirements<base_require-name>` have been changed so that\nCppAD would compile with ``gcc 4.1.1``\n(which requires more definitions before use in template functions).\nThis changed of requirements is demonstrated by the\n:ref:`base_complex.hpp-name` and :ref:`base_adolc.hpp-name` examples.\n\nThe problem with newer C++ compilers requiring more definitions before use\nalso required the user to know about ``float`` and ``double``\ndefinitions for the standard math\nfunctions in the CppAD namespace;\nsee :ref:`base_std_math-name` .\n\nThe ``example/test_one.sh`` and ``test_more/test_one.sh``\nscripts were modified so that one only need specify the test file name\n(does not also need the test routine name). Some of the test routine\ndeclarations were changed from *name* () to\n*name* ( ``void`` ) to make this possible.\n\nThe program ``test_more/test_more`` was changed to always\nreport the memory leak test results (same as ``example/example`` ).\n\nThe :ref:`PrintFor-name` function was putting an unused variable in the tape.\nThis has been fixed.\n\n11-06\n=====\nAdded the ``-DRAD_EQ_ALIAS`` compiler flag to the\n:ref:`Sacado speed tests<speed_sacado-name>` .\nIn addition, compiler flag documentation was included for\nSacado and all the other speed tests.\n\n11-05\n=====\nMS project files have been added for running the\n:ref:`cppad<speed_cppad-name>` and\n:ref:`double<speed_double-name>`\nspeed tests.\n\n11-04\n=====\nThe ``cppad/config.h`` file was not compatible with the\nWindows install procedure and\nthe Windows project's could not find a certain include file.\nThis has been fixed.\n\nThe :ref:`unix install<configure-name>` procedure has been modified\nso that the one configure flag\n``--with-Speed``\nbuilds all the possible executables related to the speed testing.\n\n11-03\n=====\nImprove the :ref:`speed_main-name` documentation and output\n(as well as the title for other sections under :ref:`speed-name` ).\n\nThe subversion copy of the :ref:`configure@Configure` script\nwas not executable.\nThis has been fixed.\n\n11-02\n=====\nThe instructions for downloading the current version using\n``subversion`` have changed.\nThe user should now directly edit the file\n::\n\n    trunk/configure\n\nin order to set the correct date for the installation\nand to build the corresponding documentation.\n\nThe :ref:`speed-name` section has been slightly reorganized\n(the main program and utilities have been separated).\n\nAdd :ref:`speed_double-name` for testing the speed of evaluating\nfunctions in ``double`` as apposed to gradients using AD types.\n\n11-01\n=====\nThe instructions for downloading the current version using subversion\nhave changed.\nThe user must now execute the command\n::\n\n    ./build.sh version\n\nin order to set the correct version number for her (or his) installation.\n\nAdd the return status for all the correctness tests\nto the documentation; see ``make test`` .\n\n10-30\n=====\nThe download instructions did not update current version number\nand this broke the links to the current tarballs.\nThis has been fixed.\n\nThe documentation for :ref:`det_by_minor-name` and :ref:`det_by_lu-name`\nhas been improved.\nThe order of the elements in :ref:`det_of_minor-name` has been\ncorrected (they were transposed but this did not really matter\nbecause determinants of transposes are equal).\n\nThe makefiles in the distribution have been changed so that\none can run configure from a directory other than the distribution directory.\n\n10-27\n=====\nA ``subversion`` method\nfor downloading CppAD has been added.\n\nThe installation was broken on some systems because the\n:ref:`configure@Configure` command tried to run\nthe ``autoconf`` and ``automake`` programs.\nThis has been fixed by adding\n``AM_MAINTAINER_MODE`` to the ``autoconf`` input file.\n\nExtend the\n``subversion``\nmethods to include a full installation and old versions.\n\n10-23\n=====\nThe :ref:`configure@cxx_flags` environment variable\nhas been changed from ``CPP_ERROR_WARN`` to ``CXX_FLAGS`` .\n\nThe command ``configure --help`` now prints a description\nof the environment variables\n``ADOLC_DIR`` ,\n``FADBAD_DIR`` ,\n``SACADO_DIR`` ,\n``BOOST_DIR`` ,\nand\n``CXX_FLAGS`` .\nIn addition, if the environment variables\n``POSTFIX_DIR`` or ``CPP_ERROR_WARN`` are used,\nan message is printed saying that are not longer valid.\n\n10-22\n=====\nThe correctness checks and speed test wrappers were moved\nfrom the individual package directories to :ref:`speed_main-name` .\nThis way they do not have to be reproduced for each package.\nThis makes it easier to add a new package,\nbut it requires the prototype for\n``compute_`` *test_name* to be the same for all packages.\n\nThe `Sacado <https://trilinos.github.io/sacado.html>`_\npackage was added to the list of :ref:`speed-name` tests.\nIn addition, the discussion about how to run each of the\nspeed tests was corrected to include the *seed* argument.\n\nThe *postfix_dir* option\nwas removed on :ref:`2006-12-05<2006@mm-dd@12-05>` but\nit was not removed from the\n:ref:`configure@Configure`\ndocumentation.\nThis has been fixed.\n\nThe routine :ref:`CheckSimpleVector-name` was changed.\nIt used to require conversion of the form\n\n    *Scalar* ( *i* )\n\nwhere *i* was ``0`` or ``1`` .\nThis does not work with when *Scalar* is\n``Sacado::Tay::Taylor<double>`` .\nThis requirement has been changed\n(see :ref:`CheckSimpleVector@Restrictions` )\nto support of\n\n    *x* = *i*\n\nwhere *x* has type *Scalar*\nand *i* has type ``int`` .\n\nFix include directives in :ref:`speed_fadbad-name` programs\n``det_lu`` , ``det_minor`` , and ``poly`` ,\nto use ``FADBAD++`` instead of ``Fadbad++`` directory.\n\nAdd ``ADOLC_DIR`` , ``FADBAD_DIR`` , ``SACADO_DIR`` ,\nand ``BOOST_DIR``\nto the :ref:`configure@Configure` help string.\n\n10-16\n=====\nAdd *seed* argument and\nimprove :ref:`speed_main-name` documentation.\n\n10-13\n=====\nFix the title in :ref:`adolc_det_lu.cpp-name` .\nAdd the package name to each test case result printed by\n:ref:`speed_main-name` .\n\n10-05\n=====\nAdded and example using complex calculations for a\nfunction that is not complex differentiable ``not_complex_ad.cpp`` .\n(This example has been removed; see :ref:`complex FAQ<Faq@Complex Types>` .)\n\n10-02\n=====\nExtend the :ref:`pow-name` function to work for any case where one argument\nis ``AD`` < *Base* > and the other is ``double``\n(as do the binary operators).\n\n09-06\n=====\nIf the :ref:`method.step<OdeErrControl@Method@step>` function returned\n``nan`` (not a number),\nit was possible for :ref:`OdeErrControl-name` to drop into an infinite loop.\nThis has been fixed.\n\n08-09\n=====\nLet user detect and handle the case where an ODE initial vector *xi*\ncontains  not a number ``nan``\n(see :ref:`Runge45-name` , :ref:`Rosen34-name` , and :ref:`OdeErrControl-name` ).\n\nUse the ``||`` operation instead of ``|``\noperator in the ``nan`` function\n(The Ginac library seems to use an alias for the type ``bool`` and\ndoes not have ``|`` defined for this alias).\n\nThe file ``test_more/ode_err_control.cpp`` was using the\nwrong include file name since the change on 08/07.\nThis has been fixed.\n\n08-07\n=====\nSometimes an ODE solver takes to large a step and this results\nin invalid values for the variables being integrated.\nThe ODE solvers :ref:`Runge45-name` and :ref:`Rosen34-name` have been\nmodified to abort\nand return :ref:`nan-name` when it is returned by the differential\nequation evaluation.\nThe solver :ref:`OdeErrControl-name` have been modified to try smaller steps\nwhen this happens.\n\nFix an :ref:`fun_construct@Sequence Constructor`\nreferenced to ``Dependent`` in documentation\n(was using the :ref:`fun_deprecated-name` one argument syntax).\n\nAdd comment about mixing debug and non-debug versions of\nCppAD in :ref:`track_new_del@TrackDelVec` error message.\n\n07-30\n=====\n``CppADCreateBinaryBool`` and ``CppADCreateUnaryBool``\nhave been replaced by ``CPPAD_BOOL_BINARY`` and\n``CPPAD_BOOL_UNARY`` respectively.\nIn addition, the :ref:`wish_list-name` item for conversion\nof all preprocessor macros to upper case been completed and removed.\n\n07-29\n=====\nThe preprocessor macros\n``CppADUsageError`` and ``CppADUnknownError``\nhave been replaced by ``CPPAD_ASSERT_KNOWN`` and\n``CPPAD_ASSERT_UNKNOWN`` respectively.\nThe meaning for these macros\nhas been included in the :ref:`cppad_assert-name` section.\nIn addition, the *known* argument to :ref:`ErrorHandler-name`\nwas wrong for the unknown case.\n\nThe :ref:`wish_list-name` item\nfor conversion of all preprocessor macros to upper case\nhas been changes (to an item that was previous missing).\n\n07-28\n=====\nThe preprocessor macro ``CPPAD_DISCRETE_FUNCTION`` was defined\nas a replacement for ``CppADCreateDiscrete``\nwhich has been deprecated.\n\n07-26\n=====\nMerge in changes made in ``branches/test_vector`` .\n\n#. 07-26:\n   Change all occurrences of ``CppADvector`` ,\n   in the files ``test_more/`` * . ``cpp`` and ``speed/`` * /* . ``cpp`` ,\n   where changed to ``CPPAD_TEST_VECTOR`` .\n   All occurrences of the ``CppADvector`` in the documentation\n   were edited to reflect that fact that it has been deprecated.\n   The documentation index and search for\n   deprecated items has been improved.\n\n#. 07-25:\n   Deprecate the preprocessor symbol ``CppADvector``\n   and start changing it to\n   ``CPPAD_TEST_VECTOR`` .\n\n    Change all occurrences of ``CppADvector`` ,\n    in the ``example/`` * . ``cpp`` files,\n    to ``CPPAD_TEST_VECTOR`` .\n\n07-23\n=====\nThe :ref:`track_new_del-name` macros\n``CppADTrackNewVec`` ,\n``CppADTrackDelVec`` , and\n``CppADTrackExtend`` have been deprecated.\nThe new macros names to use are\n``CPPAD_TRACK_NEW_VEC`` ,\n``CPPAD_TRACK_DEL_VEC`` , and\n``CPPAD_TRACK_EXTEND`` respectively.\nThis item has been removed from the\nsoftware guidelines section of the wish list.\n\nThe member variable entry in the software guideline\nwish list item has be brought up to date.\n\n07-22\n=====\nMinor improvements to the :ref:`mul_level_adolc_ode.cpp-name` example.\n\n07-21\n=====\n\n#. The ``openmp/run.sh`` example programs\n   ``example_a11c.cpp`` ,\n   ``openmp_newton_example.cpp`` , and\n   ``sum_i_inv.cpp``\n   have been changed so that they run on more systems\n   (are C++ standard compliant).\n#. :ref:`base_require-name` :\n   The ``IdenticalEqual`` function,\n   in the :ref:`base_require-name` specification,\n   was changed to ``IdenticalEqualCon``\n   (note the :ref:`base_require@API Warning` in the\n   *Base* requirement specifications).\n#. Implementation of the :ref:`base requirements<base_require-name>` for complex types\n   were moved into the :ref:`base_complex.hpp-name` example.\n\n07-20\n=====\nThe download for CppAD was still broken.\nIt turned out that the copyright message was missing from the file\n:ref:`base_adolc.hpp-name` and this stopped the creation of the download files.\nThis has been fixed.\nIn addition, the automated testing procedure has been modified so\nthat missing copyright messages and test program failures will\nbe more obvious in the test log.\n\n07-19\n=====\nThe download for CppAD has been broken since the example\n``mul_level_adolc_ode.cpp`` was added because the\n``example/example`` program was failing.\nThis has been fixed.\n\n07-18\n=====\nA realistic example using Adolc with CppAD\n:ref:`mul_level_adolc_ode.cpp-name` was added.\nThe documentation for :ref:`track_new_del-name` was improved.\n\n07-14\n=====\nAdd a discussion at the beginning of\n:ref:`mul_level_ode.cpp-name` example\n(and improve the notation used in the example).\n\n07-13\n=====\nSeparate the include file\n:ref:`base_adolc.hpp-name`\nfrom the :ref:`mul_level_adolc.cpp-name` example\nso that it can be used by other examples.\n\n06-22\n=====\nAdd :ref:`mul_level_adolc.cpp-name` , an example that demonstrates using\n``adouble`` and for the :ref:`Base<base_require-name>` type.\n\nThe :ref:`get_started.cpp-name`\nexample did not build when\nthe ``--with-Introduction`` and\n``BOOST_DIR`` options were included on the\n:ref:`configure@Configure` command line.\nIn fact, some of the :ref:`speed-name` tests also had compilation errors\nwhen ``BOOST_DIR`` was include in the configure command.\nThis has been fixed.\n\nThere was a namespace reference missing in the files\nthat could have caused compilation errors in the files\n``speed/cppad/det_minor.cpp`` and\n``speed/cppad/det_lu.cpp`` .\nThis has been fixed.\n\n06-20\n=====\nThe MS project\n``test_more/test_more.vcproj`` would not build because\nthe file ``test_more/fun_check.cpp`` was missing;\nthis has been fixed.\nIn addition,\nfix warnings generated by the MS compiler when compiling the\n``test_more/test_more.cpp`` file.\n\nAdd a section defining the :ref:`Base type requirements<base_require-name>` .\nRemove the *Base* type restrictions from the :ref:`Faq-name` .\nMake all the prototype for the default Base types agree with\nthe specifications in the Base type requirements.\n\nFix the description of the ``tan`` function in\n:ref:`unary_standard_math-name` .\n\n06-14\n=====\nThe routine :ref:`Rosen34-name` ( :ref:`Runge45-name` ) had a division\nof a ``size_t`` ( ``int`` ) by a *Scalar* ,\nwhere *Scalar* was any :ref:`NumericType-name` .\nSuch an operation may not be valid for a particular numeric type.\nThis has been fixed by explicitly converting the\n``size_t`` to an ``int`` ,\nthen converting the ``int`` to a *Scalar* ,\nand then preforming the division.\n(The conversion of an ``int`` to any numeric type must be valid.)\n\n05-26\n=====\nIf the *Base* type is not ``double`` ,\nthe :ref:`compound assignment<compound_assign-name>` operators did not\nalways allow for ``double`` operands. For example,\nif *x* had type ``AD< AD<double> >``\n\n    *x*  += .5;\n\nwould slice the value ``.5`` to an ``int``\nand then convert it to an ``AD< AD<double> >`` .\nThis has been fixed.\n\nThis slicing has also been fixed in the\n:ref:`assignment<ad_assign-name>` operation.\nIn addition, the assignment and copy operations\nhave been grouped together in the documentation; see :ref:`ad_ctor-name` and :ref:`ad_assign-name` .\n\n05-25\n=====\nDocument usage of ``double`` with\nbinary arithmetic operators,\nand combine all those operators into one section (:ref:`ad_binary-name` ).\n\nThe documentation for all the :ref:`compound assignment<compound_assign-name>`\noperators has been grouped together.\nIn addition, a\ncompound assignment wish list item has been added\n(it was completed and removed with the\n:ref:`2007@mm-dd@05-26` update.)\n\n05-24\n=====\nSuppose that *op* is a binary operation and we have\n\n    *left* *op* *right*\n\nwhere one of the operands was ``AD< AD<double> >`` and\nthe other operand was ``double`` .\nThere was a bug in this case that caused the ``double``\noperand to be converted to ``int`` before\nbeing converted to ``AD< AD<double> >`` .\nThis has been fixed.\n\n05-22\n=====\nThe Microsoft\nexamples and testing\nproject file ``example/example.vcproj``\nwas missing a reference to the\nsource code file ``example/reverse_two.cpp`` .\nThis has been fixed.\n\n05-08\n=====\nReverse mode does not work with the\n:ref:`pow-name` function when the base is less than or equal zero\nand the exponent is an integer.\nFor this reason, the :ref:`pow_int-name` function\nis no longer deprecated (and is used by CppAD when the exponent\nhas type ``int`` ).\n\n05-05\n=====\nThird and fourth order derivatives were included in the\nroutine ``test_more/sqrt.cpp`` that tests square roots.\n\nThe return value descriptions were improved for the introduction\nexamples:\n:ref:`exp_2_for1<exp_2_for1@Return Value>` ,\n:ref:`exp_2_for2<exp_2_for2@Return Value>` ,\n:ref:`exp_eps_for1<exp_eps_for1@Return Value>` , and\n:ref:`exp_eps_for2<exp_eps_for2@Return Value>` .\n\nThe summation index in :ref:`sqrt_reverse-name` was changed from\n:math:`k` to :math:`\\ell` to make partial differentiation\nwith respect to :math:`z^{(k)}` easier to understand.\nIn addition, a sign error was corrected near the end of\n:ref:`sqrt_reverse-name` .\n\nThe dimension for the notation :math:`X` in\n:ref:`reverse_identity-name` was corrected.\n\nThe word mega was added to the spelling exception list for\n``openmp/run.sh`` .\n\n04-19\n=====\nImprove connection from :ref:`reverse_identity-name` theorem\nto :ref:`reverse_any-name` calculations.\n\nImprove the ``openmp/run.sh`` script.\nIt now runs all the test cases at once in addition\nto including multiple number of thread cases for each test.\n\nAdd the ``sum_i_inv_time.cpp`` OpenMP example case.\n\nThere was a typo in the\n:ref:`forward_order@Second Order` discussion\n(found by Kipp Martin).\nIt has been fixed.\n\n04-17\n=====\nAdd a paragraph to :ref:`reverse_identity-name` explaining\nhow it relates to :ref:`reverse_any-name` calculations.\nAdd description of\n:ref:`first<reverse_any@First Order>` and\n:ref:`reverse_any@Second Order`\nresults in :ref:`reverse_any-name` .\n\n04-14\n=====\nSimplify the :ref:`Reverse-name` mode documentation by creating\na separate :ref:`reverse_two-name` section for second order reverse,\nmaking major changes to the description in :ref:`reverse_any-name` ,\nand creating a third order example :ref:`rev_checkpoint.cpp-name` for\nreverse mode calculations.\n\nImprove the :ref:`reverse_identity-name` proof.\n\n04-11\n=====\nMerge in changes made in ``branches/intro`` .\n\n#. 04-11:\n   Add :ref:`exp_eps_rev2-name` and its verification routine\n   :ref:`exp_eps_rev2.cpp-name` .\n\n#. 04-10:\n   Finished off :ref:`exp_2_rev2-name` and\n   added :ref:`exp_2_rev2.cpp-name` which verifies its calculations.\n   Added second order calculations to :ref:`exp_2_cppad-name` .\n   Added :ref:`exp_eps_for2-name` and its verification routine.\n\n#. 04-07:\n   Added a preliminary version of :ref:`exp_2_rev2-name`\n   (does not yet have verification or exercises).\n\n#. 04-06:\n   Fixed a problem with the Microsoft Visual Studio project file\n   ``introduction/exp_apx/exp_apx.vcproj``\n   (it did not track the file name changes of the form\n   ``exp_apx/exp_2_for`` to ``exp_apx/exp_2_for1``\n   on 04-05).\n\n    Added :ref:`exp_2_for2-name` to introduction.\n\n#. 04-05:\n   Use order expansions in introduction; e.g., the\n   :ref:`exp_2_for2@Second Order Expansion`\n   for the :ref:`exp_2-name` example.\n\n03-31\n=====\nMerge in changes made in ``branches/intro``\nand remove the corresponding Introduction item from the wish list:\n\n#. 03-31:\n   Create the a simpler exponential approximation in the :ref:`introduction-name`\n   called :ref:`exp_2-name` which has a different program\n   variable for each variable in the operation sequence.\n\n    Simplify the :ref:`exp_eps-name` approximation using the\n    :math:`v_1 , \\ldots , v_7` notation so that variables directly\n    correspond to index in operation sequence (as with the :ref:`exp_2-name`\n    example).\n\n#. 03-30:\n   The Microsoft project file ``introduction/exp_apx/exp_apx.vcproj``\n   was referencing ``exp_apx_ad.cpp`` which no longer exists.\n   It has been changed to reference ``exp_apx_cppad.cpp``\n   which is the new name for that file.\n\n03-29\n=====\nFixed entries in this file where the year was mistakenly used for the month.\nTo be more specific, 07 ``-`` *dd* was changed to 03 ``-`` *dd*\nfor some of the entries directly below.\n\nCorrected some places where ``CppAD`` was used in stead of ``Adolc``\nin the :ref:`adolc_poly.cpp-name` documentation.\n\nAdded an Introduction and\n:ref:`wish_list@Tracing` entry to the wish list.\n(The Introduction item was completed on :ref:`2007@mm-dd@03-31` .)\n\n03-20\n=====\nExample A.1.1c, ``example_a11c.cpp`` ,\nfrom the OpenMP 2.5 standards document,\nwas added to the tests that can be run using ``openmp/run.sh`` .\n\n03-15\n=====\nIncluded the changes from openmp branch\nso that so CppAD does not use the OpenMP ``threadprivate`` command\n(some systems do not support this command).\n\n#. 03-15:\n   Add command line arguments to ``openmp_newton_example.cpp`` , and\n   modified ``openmp/run.sh`` to allow for more flexible testing.\n\n#. 03-14:\n   Fixed some Microsoft compiler warnings by explicitly converting from\n   ``size_t`` to ``int`` .\n\n    In the Microsoft compiler case, the ``cppad/config.h`` file had\n    the wrong setting of ``GETTIMEOFDAY`` .\n    The setting is now overridden (and always false) when the\n    ``_MSC_VER`` preprocessor symbol is defined.\n\n    Some minor changes were made in an effort to speed up the multi-threading case.\n\n#. 03-13:\n   Started a new openmp branch and created a version of CppAD\n   that does not use the OpenMP ``threadprivate`` command\n   (not supported on some systems).\n\n03-09\n=====\nIncluded the changes from openmp branch\nso that OpenMP can be used with CppAD,\nsee :ref:`omp_max_thread-name` .\nThe changes below\nwere made in the openmp branch and transferred to the trunk on 03-09.\n\n#. 03-28:\n   The conditional include commands were missing on some include files;\n   for example\n   ::\n\n        # ifndef CPPAD_BENDER_QUAD_HPP\n        # define CPPAD_BENDER_QUAD_HPP\n\n    was missing at the beginning of the :ref:`BenderQuad-name` include file.\n    This has been fixed.\n\n    The ``speed_test`` routines :ref:`speed_test@Timing` was\n    changed to use ``gettimeofday`` if it is available.\n    (``gettimeofday`` measures wall clock time\n    which is better in a multi-threading environment).\n\n    Added the user multi-threading interface\n    :ref:`omp_max_thread-name` along with its examples\n    which are distributed in the directory ``openmp`` .\n\n    The ``speed/`` * . ``hpp`` files have been moved to\n    ``include/cppad/speed/`` * . ``hpp`` and the corresponding wish list\n    item has been removed.\n\n    The multiple tapes with the same base type wish list item\n    have been removed (it's purpose was multi-threading which\n    has been implemented).\n\n#. 02-27:\n   The :ref:`speed-name` include files are currently being distributed\n   above the ``cppad`` include directory.\n   A fix this wish list item has been added.\n\n    Multiple active tapes required a lot of multi-threading access\n    management for the tapes. This was made simpler (and faster)\n    by having at most one tape per thread.\n\n#. 02-22:\n   The include command in the :ref:`speed_test-name` documentation was\n   ::\n\n        # include <speed/speed_test.hpp>\n\n    but it should have been\n    ::\n\n        # include <cppad/speed_test.hpp>\n\n    This has been fixed.\n\n#. 02-17:\n   An entry about optimizing the operation\n   sequence in an :ref:`ADFun<fun_construct-name>` object was added to the\n   :ref:`wish_list-name` .\n\n    Change the argument syntax for :ref:`Dependent-name` and deprecate the\n    :ref:`old Dependent syntax<fun_deprecated@Dependent>` .\n\n#. 02-16:\n   Added ``VecAD`` < *Base* > as a valid argument type for the\n   :ref:`con_dyn_var@Parameter`\n   and :ref:`con_dyn_var@Variable` functions.\n   In addition, :ref:`VecAD@Base Indexing`\n   is was extended to be allowed during taping so long as the\n   VecAD object is a parameter.\n\n#. 02-15:\n   Fixed the ``example/test_one.sh`` script\n   (it was using its old name ``one_test`` ).\n\n02-06\n=====\nThe :ref:`BenderQuad-name` documentation was improved by adding the fact\nthat the *x* and *y* arguments to the ``f`` . *dy*\nmember function are equal to the *x* and *y* arguments\nto ``BenderQuad`` . Hence values depending on them can be stored\nas private objects in *f* and need not be recalculated.\n\n02-04\n=====\nThe method for distributing the documentation needed to be\nchanged in the top level ``makefile.am`` in order to\nbe compatible with automake version 1.10.\n\n02-03\n=====\nThe change on :ref:`2007@mm-dd@02-01` had a new, saved as a static\npointer, with no corresponding delete.\nThis was not a bug, but it has been changed to avoid\nan error message when using CppAD with\n`valgrind <https://valgrind.org/>`_.\n\nThe change to the ``pow`` function on\n:ref:`06-12-10<2006@mm-dd@12-10>` did not include the\nnecessary changes to the sparsity calculations.\nThis has been fixed.\n\n02-02\n=====\nFix minor errors and improve\nprofiling documentation.\nAlso change the problem sizes used for the :ref:`speed-name` tests.\n\n02-01\n=====\nThere seems to be a bug in the cygwin version of g++ version 3.4.4\nwith the -O2 flag whereby some static variables in static member functions\nsometimes do not get constructed before being used. This has been\navoided by using a static pointer and the new operator in cppad/local/ad.hpp.\n\n01-29\n=====\nThe copyright message was missing from some of the distribution files\nfor some new files added on :ref:`06-12-15<2006@mm-dd@12-15>` .\nThis resulted in the\ntarballs * . ``tgz`` and * . ``zip``\nnot existing for a period of time.\nThe automated tests have been extended so that this should not happen again.\n\n{xrst_end 2007}\n"
  },
  {
    "path": "appendix/whats_new/2008.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin 2008 app}\n{xrst_spell\n    fg\n    retape\n    speedtest\n    subregions\n    tarballs\n}\n\nRelease Notes for 2008\n######################\n\nmm-dd\n*****\n\n12-19\n=====\nIn the documentation for :ref:`pow_int-name` change the integer exponent\nfrom ``int`` *y* to ``const int &`` *y* .\nIn the implementation for :ref:`pow-name` make the integer base case\nagree with the documentation; i.e., change\nfrom ``int`` *x* to ``const int &`` *x* .\n\n12-14\n=====\nAdded another test of :ref:`mul_level-name` calculations (in the\n``test_more`` directory).\n\n12-04\n=====\nExtensive explanation for the ``ipopt_cppad/ipopt_cppad_ode`` example was\nprovided in the section ipopt_cppad_ode.\n\n11-22\n=====\nThe CppAD interface to the Ipopt nonlinear programming solver\n:ref:`cppad_ipopt_nlp-name`\nhas been moved from ``example/ipopt_cppad_nlp`` to\n``ipopt_cppad/ipopt_cppad_nlp`` .\n\n11-21\n=====\nThe Microsoft's Visual C++ Version 9.0 generates a warning of the form\n``warning C4396:`` %...%\nfor every template function that is declared as a both a friend and inline\n(it thinks it is only doing this for specializations of template functions).\nThe warnings are no longer generated because\nthese ``inline`` directives are converted to\nempty code when a Microsoft Visual C++ is used.\n\n11-20\n=====\nThe function ``tanh`` ( *x* ) was added to the\n:ref:`unary_standard_math-name` functions.\nThe ``abs`` and ``erf`` functions were removed from the\n:ref:`Base requirements<base_require-name>` .\nThe restrictions about the Base class were removed from\n:ref:`abs-name` , :ref:`atan2-name` , :ref:`LuRatio-name` , :ref:`erf-name` .\n\nVisual Studio Version 9.0 could not handle the large number of static\nconstants in the CppAD :ref:`erf-name` function.\nThis function was changed to a simpler representation\nthat is much faster and that\nis differentiable at all points (not defined differently on subregions).\nThe down side to this is that the new version\nis not as accurate.\n\n10-27\n=====\nChange prototypes for ``ipopt_cppad/ipopt_cppad_ode`` helper routines\nto use ``const`` (where appropriate).\n\n10-17\n=====\nMajor improvements to the ``ipopt_cppad/ipopt_cppad_ode`` example.\n\n10-16\n=====\nMinor improvement to description of optimization argument in\n``ipopt_cppad/ipopt_cppad_ode`` .\n\n09-30\n=====\nAdd or modify some wish list entries; see\n``cppad_ipopt_nlp`` (since removed),\nmultiple argument forward (completed with :ref:`forward_dir-name` ),\nand sparsity patterns\n(:ref:`sparsity patterns<glossary@Sparsity Pattern>` has been fulfilled).\n\n09-26\n=====\nUse parenthesis and brackets to group terms of the form\n:math:`m \\times I` to make the documentation of\n:ref:`cppad_ipopt_nlp-name` easier to read.\n\nChanged ``ipopt_cppad/ipopt_cppad_ode`` to use :math:`y(t)` for\nthe solution of the ODE to distinguish it for :math:`x`,\nthe vector we are optimizing with respect to.\n\n09-18\n=====\nChanged ``ipopt_cppad/ipopt_cppad_ode`` to a case where :math:`x(t)`\nis a pair of exponential functions instead of a linear and quadratic.\nFixed some of the comments in this example and included the source\ncode in the documentation (which was missing by mistake).\n\n09-17\n=====\nChanged ``ipopt_cppad/ipopt_cppad_ode`` to a case where there are\ntwo components in the ODE (instead of one).\nAlso removed an initialization section that was only intended for tests\nwith a specific initial value.\n\n09-16\n=====\nAdd ``ipopt_cppad/ipopt_cppad_ode`` , an example and test\nthat optimizes the solution of an ODE.\nChange ``r_eval`` to ``eval_r`` in :ref:`cppad_ipopt_nlp-name` .\nFix a dimension of ``u_ad`` error in ``ipopt_cppad_nlp`` .\n\n09-12\n=====\nConverted from storing full Hessian and Jacobian to a sparse data structure\nin :ref:`cppad_ipopt_nlp-name` .\nThis greatly reduced the memory requirements (and increased the speed)\nfor sparse problems.\n\n09-10\n=====\nFixed more indexing bugs in :ref:`cppad_ipopt_nlp-name`\nthat effected cases where the domain index vector :math:`J_{k, \\ell}`\nwas different for different values of :math:`k` and :math:`\\ell`.\n\nIn :ref:`cppad_ipopt_nlp-name` ,\ncombined *fg_info* ``->domain_index`` () and\n*fg_info* ``->range_index`` () into a single function called\n*fg_info* ``->index`` () .\nAlso added more error checking (if ``NDEBUG`` is not defined).\n\n09-09\n=====\nFixed an indexing bug in :ref:`cppad_ipopt_nlp-name` .\n(This effected cases where the domain index vector :math:`J_{k, \\ell}`\nwas different for different values of :math:`k` and :math:`\\ell`.)\n\n09-07\n=====\nChange :ref:`cppad_ipopt_nlp-name` so that object and constraints\nare expressed as the double summation of simpler functions.\nThis is more versatile that the single summation representation.\n\n09-06\n=====\nChecked in a major change to :ref:`cppad_ipopt_nlp-name`\nwhereby the object and constraints can be expressed as the\nsum of simpler functions.\nThis is the first step in what will eventually be a more versatile\nrepresentation.\n\n09-05\n=====\nFix bug in :ref:`cppad_ipopt_nlp-name` (not recording the function\nat the proper location. Here is the difference that occurred\nmultiple places in the ``ipopt_cppad/ipopt_cppad_nlp.cpp`` source:\n::\n\n    for(j = 0; j < n_; j++)\n    -       x_ad_vec[0] = x[j];\n    +       x_ad_vec[j] = x[j];\n\nThis did not show up in testing because there currently is no test of\n``ipopt_cppad_nlp`` where the operation sequence depends\non the value of :math:`x`.\n\nChanged ``eval_grad_f`` in ``ipopt_cppad_nlp.cpp``\nto be more efficient.\n\n09-04\n=====\nThe :ref:`cppad_ipopt_nlp-name` interface has been changed to use\na derived class object instead of a pointer to a function.\n\n09-03\n=====\nThe :ref:`cppad_ipopt_nlp-name` interface has been changed to use\n``size_t`` instead of ``Ipopt::Index`` .\n\n09-01\n=====\nBack out the changes made to :ref:`cppad_ipopt_nlp-name` on 08-29\n(because testing proved the change to be less efficient in the case\nthat motivated the change).\n\n08-29\n=====\nThe ``push_vector`` member function was missing from the\n:ref:`Cppad_vector@vectorBool` class.\nThis has been fixed.\nIn addition, it seems that for some cases (or compilers)\nthe assignment\n\n    *x* [ *i* ] = *y* [ *j* ]\n\ndid not work properly when both *x* and *y*\nhad type ``vectorBool`` .\nThis has been fixed.\n\nThe :ref:`cppad_ipopt_nlp-name` example has been extended\nso that it allows for both scalar and vector evaluation of the\nobjective and constraints; see the argument *fg_vector* in\n:ref:`cppad_ipopt_nlp-name` .\nIn the case where there is not a lot of common terms\nbetween the functions, the scalar evaluation may be more efficient.\n\n08-19\n=====\nAdd :ref:`push of a vector<CppAD_vector@push_vector>`\nto the ``CppAD::vector`` template class.\nThis makes it easy to accumulate multiple scalars and\n:ref:`simple vectors<SimpleVector-name>` into one large ``CppAD::vector`` .\n\n08-08\n=====\nThere was an indexing bug in the\n:ref:`cppad_ipopt_nlp-name` example\nthat affected the *retape* equal to ``false`` case.\nThis has been fixed.\nIn addition, the missing\n*retape* documentation was added.\n\n07-02\n=====\nExtend :ref:`configure@Configure` command to check for\nextras libraries that are necessary for linking the ipopt example.\n\n06-18\n=====\nAdd specifications for the Ipopt class :ref:`cppad_ipopt_nlp-name` .\nThis is only an example class it may change with future\nversions of CppAD.\n\n06-15\n=====\nThe nonlinear programming example ``ipopt_nlp_get_started.cpp`` was added.\nThis is a preliminary version of this example.\n\n06-11\n=====\nThe sparsity pattern for the Hessian was being calculated each time\nby :ref:`SparseHessian<sparse_hessian-name>` .\nThis is not efficient\nwhen the pattern does not change between calls to ``SparseHessian`` .\nAn optional sparsity pattern argument was added to ``SparseHessian``\nso that it need not be recalculated each time.\n\n06-10\n=====\nThe sparsity pattern for the Jacobian was being calculated each time\nby :ref:`SparseJacobian<sparse_jacobian-name>` .\nThis is not efficient\nwhen the pattern does not change between calls to ``SparseJacobian`` .\nAn optional sparsity pattern argument was added to ``SparseJacobian``\nso that it need not be recalculated each time.\n\n05-08\n=====\nThe :ref:`sparse_jacobian-name` routine has been added.\n\nThe example in :ref:`sparse_hessian-name` pointed to :ref:`hessian.cpp-name`\ninstead of :ref:`sparse_hessian.cpp-name` .\nThis has been fixed.\n\n05-03\n=====\nThe ``retape`` flag has been added to :ref:`speed_main-name` .\nIn addition the routines\n:ref:`link_det_minor-name` , :ref:`link_poly-name` , and :ref:`link_ode-name`\npass this flag along to the speed test implementations\n(because the corresponding tests have a fixed operation sequence).\nIf this flag is false, a test implementation is allowed to just tape\nthe operation sequence once and reuse it.\nThe following tests use this flag:\n:ref:`adolc_det_minor.cpp-name` ,\n:ref:`cppad_det_minor.cpp-name` ,\n:ref:`cppad_ode.cpp-name` ,\n:ref:`adolc_poly.cpp-name` ,\n:ref:`cppad_poly.cpp-name` .\n\nCreate specialized zero order forward mode routine that should be faster,\nbut does not test out as faster under cygwin g++ (GCC) 3.4.4.\n\n04-20\n=====\nAdded the :ref:`ode_evaluate-name` speed test utility in\npreparation for having ode speed tests.\nCreated ode speed test for the ``cppad`` and ``double``\ncases; see :ref:`speed_main-name` .\nIn addition,\nadded the examples :ref:`ode_evaluate.cpp-name` and :ref:`sparse_hessian.cpp-name` .\n\nChanged the :ref:`speed_main-name` routines defined for each package\nfrom ``compute_`` *name* to ``link_`` *name* .\nFor example, in ``speed/cppad/det_minor.cpp`` ,\nthe function name\n``compute_det_minor`` was changed to ``link_det_minor`` .\n\n04-18\n=====\nFix a problem in the :ref:`link_poly-name` correctness test.\nAlso add :ref:`double_sparse_hessian.cpp-name` to the set\nspeed and correctness tests (now available).\n\n04-10\n=====\nChange all the\n:ref:`Adolc speed<speed_adolc-name>` examples to use\n:ref:`track_new_del-name` instead of using ``new`` and ``delete``\ndirectly.\nThis makes it easy to check for memory allocation errors and leaks\n(when ``NDEBUG`` is not defined).\nAlso include in documentation sub functions that indicate\nthe ``sparse_hessian`` speed test is not available for\n:ref:`double_sparse_hessian.cpp-name` ,\n:ref:`fadbad_sparse_hessian.cpp-name` , and\n:ref:`sacado_sparse_hessian.cpp-name` .\n\n04-06\n=====\nThe following :ref:`wish list<wish_list-name>`\nentry has been completed and removed from the list:\n\"Change private member variables names\n(not part of the user interface)\nso that they all end with an underscore.\"\n\n04-04\n=====\nFix a problem compiling the speed test\n:ref:`main<speed_main-name>` program with gcc 4.3.\n\n03-27\n=====\nCorrected :ref:`cppad_sparse_hessian.cpp-name`\nso that it uses the sparse case when\n``USE_CPPAD_SPARSE_HESSIAN`` is ``1`` .\nAlso added a wish list sparsity pattern entry\n(the :ref:`glossary@Sparsity Pattern` entry\nhas been fulfilled).\n\nChange the name of ``speedtest.cpp`` to :ref:`speed_program.cpp-name` .\n\n02-05\n=====\nChange windows install instructions\nto use Unix formatted files (so only two instead of\nfour tarballs are necessary for each version).\nThe Microsoft project files for\n``speed/cppad`` , ``speed/double`` , and ``speed/example``\nwere missing. This has also been fixed.\n\n02-03\n=====\nThere was an ambiguity problem\n(detected by g++ 4.3) with the following operations\n\n    *x* *op* *y*\n\nwhere *x* and *y* were ``AD<double>`` and\n*op* was a member operator of that class.\nThis has been fixed by making all such member functions friends\ninstead of members of ``AD<double>`` .\n\nRemove compound assignment entry from wish list\n(it was fixed on :ref:`2007-05-26<2007@mm-dd@05-26>` ).\nAdd an expression hashing entry to the :ref:`wish_list-name`\n(it has since been removed).\nAdd Library and Scripting Languages to the wish list\n(this has since been fulfilled by the example :ref:`ad_in_c.cpp-name` ).\n\n01-26\n=====\nThe :ref:`LuFactor-name` routine gave a misleading error message\nwhen the input matrix had not a number or infinity in it.\nThis has been fixed.\n\n01-24\n=====\nThe :ref:`configure@postfix_dir`\nhas been added to the ``configure`` command line options.\n\n01-21\n=====\nA sparse Hessian case was added to the :ref:`speed-name` tests; see\n:ref:`sparse_hessian<link_sparse_hessian-name>` .\n\n01-20\n=====\nCppAD can now be installed using ``yum`` on\n``Fedora`` operating systems.\n\n01-11\n=====\nThe CppAD correctness tests assume that machine epsilon is less\nthan ``1e-13`` . A test for this has been added to the\n``test_more/test_more`` program.\n\n01-08\n=====\nAdded a :ref:`sparse_hessian-name` routine and\nextended :ref:`Hessian-name` to allow for a weight vector *w*\ninstead of just one component *l* .\n\n{xrst_end 2008}\n"
  },
  {
    "path": "appendix/whats_new/2009.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin 2009 app}\n{xrst_spell\n    adolc\n    apx\n    autoconf\n    automake\n    doxygen\n    eps\n    ip\n    ipopt\n    isnan\n    mhelp\n    nlp\n    of of\n    openmp\n    prev\n    pycppad\n    retape\n    svn\n    tarball\n    valgrind\n}\n\nRelease Notes for 2009\n######################\n\nmm-dd\n*****\n\n12-23\n=====\nThe\n``ADFun`` :ref:`fun_construct@Assignment Operator`\nwas changed so that it now copies forward mode\nTaylor coefficients and sparsity pattern information.\n(This assignment operator was added on :ref:`2009@mm-dd@10-24` .)\nYou can use :ref:`capacity_order-name` to delete the Taylor coefficients\nbefore copying them.\nTwo new functions were added so that you can query and delete the\nforward mode sparsity information;\nsee\n:ref:`ForSparseJac@f@size_forward_bool` and\n:ref:`ForSparseJac@f@size_forward_set` .\n\n12-22\n=====\nConvert the optimization of a sequence of additions from multiple operators\nto one operator with a varying number of arguments. This improved the speed\nfor forward and reverse mode computations of an optimized tape.\n\n12-18\n=====\nIt turns out that detection of a sequence of additions makes the optimization\nlonger. This was simplified and makes slightly faster by converting two\njointly recursive routines to one non-recursive routine that uses a\nstack for the necessary information.\nMore work is planned to make this optimization faster.\n\n12-12\n=====\nDetection of a sequence of additions that can be converted to one variable\nduring the :ref:`optimize-name` process.\nThis leads to a significant improvement in the tape size and speed.\n\n12-04\n=====\nChange hash coding of parameter values as part of operators\nduring the :ref:`optimize-name` process.\nThis should leads to more detection and removal of duplicate operations.\n\n12-02\n=====\nFix minor grammatical error in the Purpose heading\nfor :ref:`conditional expressions<CondExp@Purpose>` .\n\nAdd the following functions:\n:ref:`fun_property@size_op` ,\n:ref:`fun_property@size_op_arg` ,\nand\n:ref:`fun_property@size_op_seq` .\nIn addition, improve and extend the\n:ref:`fun_property.cpp-name` example.\n\n11-28\n=====\nFix bug in tape optimization with :ref:`VecAD-name` objects.\n\n11-27\n=====\nRemove duplicate expressions for the commutative binary operators; i.e.,\naddition and multiplication.\n\n11-26\n=====\nImprove :ref:`optimize-name` command so that it removes some duplicate\nexpressions from the tape (more of this is planned).\n\n10-30\n=====\nMake program that check Ipopt ODE example correctness\na separate file ``ipopt_nlp_ode_check.cpp``\nSplit out Ipopt driver for ODE example ``ipopt_nlp_ode_run.hpp`` .\nAdd the speed testing problem ``ipopt_cppad/ipopt_ode_speed.cpp`` .\n\n10-29\n=====\nSplit out the\node inverse problem,\nits simple representation,\nand\nits fast representation,\nas a separate files; to be specific,\n``ipopt_nlp_ode_problem.hpp`` ,\n``ipopt_nlp_ode_simple.hpp`` ,\n``ipopt_nlp_ode_fast.hpp`` ,\nand\n``ipopt_nlp_ode_check.cpp`` .\n\n10-28\n=====\nImprove the documentation for ``ipopt_nlp_ode_simple`` and\n``ipopt_nlp_ode_fast`` .\n\n10-27\n=====\nMoved old ``ipopt_cppad_simple.cpp`` to ``ipopt_nlp_get_started.cpp`` ,\ncreated the example ``ipopt_nlp_ode_simple.hpp`` ,\nand split and ``ipopt_cppad_ode.cpp``\ninto ``ipopt_nlp_ode_fast.hpp`` and ``ipopt_nlp_ode_check.cpp`` .\n\n10-24\n=====\nAdded the :ref:`fun_construct@Assignment Operator`\nto the ``ADFun`` object class.\nThis makes a copy of the entire operation sequence in another\nfunction object.\nThe intention is that the two functions objects can do calculations in\nparallel.\nIn addition,\nCppAD now check for the ``ADFun``\n:ref:`fun_construct@Copy Constructor`\nand generates an error message if it is used.\n\n10-23\n=====\nThe :ref:`sparse_hessian-name` routine was extended so the user can now choose\nbetween vectors of sets and boolean vectors for representing\n:ref:`sparsity patterns<glossary@Sparsity Pattern>` .\n\n10-21\n=====\nThe :ref:`CheckSimpleVector-name` function was extended so that\nit can check simple vectors where the elements of the vector\ncan not be assigned to integer values.\nThis was done by adding the :ref:`CheckSimpleVector@x, y`\narguments to ``CheckSimpleVector`` .\n\n10-16\n=====\nThe :ref:`sparse_jacobian-name` routine was extended so the user can now choose\nbetween vectors of sets and boolean vectors for representing\n:ref:`sparsity patterns<glossary@Sparsity Pattern>` .\n\n10-14\n=====\nThe *packed* parameter for the sparsity routines\n:ref:`ForSparseJac-name` , :ref:`RevSparseJac-name` , and :ref:`RevSparseHes-name`\n(introduced on :ref:`2009@mm-dd@09-26` ) has been removed.\nIt has been replaced by changing the argument and return values\nto be more versatile.\nTo be specific, they can now represent sparsity\nusing vectors of ``std::set<size_t>``\ninstead of just as vectors of ``bool``\n(see :ref:`sparsity patterns<glossary@Sparsity Pattern>` ).\n\n10-03\n=====\nThe Microsoft Visual Studio project files for\nexamples and testing\nand for\nmore correctness testing\nwere not including some new tests in their builds.\nThis has been fixed.\n\n09-30\n=====\nAdded the :ref:`cppad_sparse_jacobian.cpp-name` speed test\nand increased the sizes used by :ref:`link_sparse_hessian-name` .\nSome mistakes were fixed in the documentation for speed tests\n:ref:`link_sparse_hessian-name` and :ref:`sparse_hes_fun-name` .\n\n09-29\n=====\nThe documentation definition of the function :math:`H(x)` in\n:ref:`RevSparseHes-name` was missing a factor of :math:`R`.\nThis has been fixed.\n\n09-28\n=====\nChanged :ref:`RevSparseHes-name` so that it uses a sparse\nrepresentation when the corresponding call to\n:ref:`ForSparseJac-name` used a sparse representation.\nThis should have been included with the change on 09-26\nbecause Hessian sparsity patters after ``ForSparseJac``\nwith *packed* did not work.\nThus, this could be considered a bug fix.\n\n09-26\n=====\nAdded the ``packed`` parameter to\n:ref:`ForSparseJac-name` and :ref:`RevSparseJac-name` .\nIf *packed* is false,\na sparse instead of packed representation is used\nduring the calculations of sparsity patterns.\nThe sparse representation\nshould be faster, and use less memory, for very large sparse Jacobians.\nThe functions ``ForSparseJac`` and ``RevSparseJac``\nreturn packed representations.\nThe plan is to eventually provide new member functions that return\nsparse representations.\n\n09-20\n=====\nFixed a bug in the :ref:`Hessian Sparsity<RevSparseHes-name>` calculations\nthat included use of :ref:`VecAD-name` objects.\n\n09-19\n=====\nSome more memory allocation improvements (related to those\non 09-18) were made.\n\n09-18\n=====\nA bug was found in all the :ref:`sparsity_pattern-name` calculations.\nThe result was that eight times the necessary memory was being used\nduring these calculations.  This has been fixed.\n\n08-25\n=====\nAdd :ref:`ad_fun.cpp-name`\nan example of how to create your own interface to an :ref:`ADFun-name` object.\n\n08-14\n=====\nAdd :ref:`ad_in_c.cpp-name`\nan example of how to link CppAD to other languages.\n\n08_13\n=====\nAdd an option to :ref:`optimize-name` an operation sequence.\nThese changes come from the directory ``branches/optimize``\nin the CppAD subversion repository.\nThe dates below represent when the correspond change was made.\n\n#. 08-13:\n   An automatic check of the :ref:`forward_zero-name` results was added\n   after each call to :ref:`f.optimize()<optimize-name>`\n   (this :ref:`check<optimize@Checking Optimization>`\n   is skipped when ``NDEBUG`` is defined).\n   In addition, all of the ``speed/cppad/`` * . ``cpp`` tests\n   now check and use the speed test\n   :ref:`speed_main@Global Options@optimize` flag.\n\n#. 08-11:\n   Change the speed test :ref:`main program<speed_main-name>` so\n   that it uses a list of options instead of a boolean flag for each option.\n   This will make it possible to add options in the future with out\n   having to change all the existing tests because the options are now\n   global variables instead of arguments to the speed test routines; for example,\n   see ``retape`` speed test option.\n\n#. 08-10:\n   The routine for :ref:`optimizing<optimize-name>` the operation sequence\n   has been added has been further tested using ``test_more/optimize.cpp`` .\n   Some bugs have been fix and the routine can\n   now be trusted to work correctly.\n\n    The function\n    :ref:`fun_property@size_VecAD` function was added\n    so that the user could see the ``VecAD`` vectors\n    and elements corresponding to an operation sequence.\n\n#. 08-09:\n   A routine for :ref:`optimizing<optimize-name>` the operation sequence\n   has been added.\n   This is a preliminary version and needs more testing before it can\n   be trusted to work correctly.\n\n08-06\n=====\nAdd hash table coding to reduce the number of copies of the same\nparameter value necessary in a tape recording.\nIn addition, add the function\n:ref:`fun_property@size_par` was added\nso that the user could see the number of parameters\ncorresponding to an operation sequence.\n\n08-02\n=====\nFix bug in new version of how :ref:`ForSparseJac-name` handles\n:ref:`VecAD-name` objects.\n\nFix bug in overnight build where HTML version and entire documentation\nas one page versions of documentation were not being built.\n\nFix missing new line under\n:ref:`SimpleVector@Element Access@Using Value`\nheading for simple vector documentation.\n\n08-01\n=====\nFix bug in reverse mode Jacobian :ref:`sparsity<RevSparseJac-name>`\nfor :ref:`VecAD-name` objects.\n\n07-31\n=====\nThe :ref:`forward<ForSparseJac-name>` and :ref:`reverse<RevSparseJac-name>`\nsparse Jacobian routines have been improved so the resulting sparsity\npatterns are valid for all values of the independent variables\n(even if you use :ref:`CondExp-name` or :ref:`VecAD-name` ).\n\n07-26\n=====\nConvert developer documentation from\nforward and reverse mode sweep routines from OMhelp to doxygen.\n\n07-25\n=====\nAdd developer documentation for :ref:`PrintFor-name` operations.\n\n07-24\n=====\nAdd developer documentation for :ref:`Discrete-name` operations.\n\n07-23\n=====\nAdd developer documentation for tape evaluation of :ref:`VecAD-name` store\noperations. (a store operation changes the value of a VecAD element).\n\nImprove the :ref:`vec_ad.cpp-name` user example.\n\n07-06\n=====\nFixed a bug in second or higher order reverse mode calculations\nthat used :ref:`VecAD-name` .\nThis bug was demonstrated by the test case ``SecondOrderReverse``\nin the file ``test_more/vec_ad.cpp`` .\n\nAdd developer documentation for tape evaluation of the\nVecAD load operations\n(a load operation accesses an element of the vector but\ndoes not change it.)\n\nFix ``isnan`` undefined in ``example/cond_exp.cpp`` error\nintroduced on 07-04 change.\n\n07-04\n=====\nAdd developer documentation for the\n:ref:`CompareChange-name` operations during tape evaluation.\nThese changes come from the directory ``branches/sweep``\nin the CppAD subversion repository.\nThe dates below represent when the correspond change was made.\n\n#. 07-04:\n   Fixed a bug in second or higher order reverse mode calculations\n   that included :ref:`conditional expressions<CondExp-name>` .\n   This bug was demonstrated by the test case ``SecondOrderReverse``\n   in the file ``test_more/cond_exp.cpp`` .\n\n    A simpler and useful example was provided for\n    :ref:`conditional expressions<CondExp-name>` ;\n    see :ref:`cond_exp.cpp-name` .\n\n#. 07-03:\n   Some minor improvements were made to the documentation for\n   :ref:`CondExp-name` .\n   To be specific, a newer OMhelp option was used to change the formatting\n   of the syntax, some of the argument names were changed to be more descriptive.\n\n#. 07-02:\n   Add developer doxygen documentation of\n   tape evaluation for power (exponentiation) operators.\n\n#. 07-01:\n   Fix an example indexing error in\n   ``introduction/exp_apx/exp_eps_for2.cpp`` (found by valgrind).\n\n    Add developer doxygen documentation of\n    tape evaluation for multiplication and division operators.\n\n#. 06-30:\n   Add developer doxygen documentation of\n   tape evaluation for addition and subtraction operators.\n\n#. 06-29:\n   Add developer doxygen documentation of\n   tape evaluation for sin, sinh, cos, and cosh.\n\n#. 06-28:\n   Add developer doxygen documentation of\n   tape evaluation for atan, asin, acos, sqrt, log.\n\n06-25\n=====\nThe tarball for most recent release (of the subversion trunk for CppAD)\nwas not being placed in the\n`download <https://www.coin-or.org/download/source/CppAD/>`_\ndirectory.\nThis has been fixed.\n\n06-22\n=====\nFix compiler warnings during the ``openmp/run.sh`` test.\n\nChanged :ref:`speed_example.cpp-name` to omit the ``speed_test`` from\nthe correctness result.\nIn stead, a message is printed explaining that timing tests need\nto be run without a lot of other demands on the system.\n\n06-21\n=====\nThe configure instructions for :ref:`configure@ipopt_dir`\nhad the wrong path for ``IpIpoptApplication.hpp`` .\nThis has been fixed.\n\n06-20\n=====\nUpgrade to from autoconf 2.61 to 2.63,\nand from automake 1.10.1 to 1.11.\n\nFix conflict between CppAD's use of config.h preprocessor symbols\nand other packages use of the same symbol names.\n\n06-06\n=====\n\n#. Using complex of an AD type (instead of AD of complex) was not working\n   correctly in ``not_complex_ad.cpp`` because the\n   :ref:`default constructor<ad_ctor-name>` for an AD object has an unspecified value.\n   This has been fixed for the complex type by changing the default constructor\n   to use value zero.\n   (The ``not_complex_ad.cpp`` example has been removed;\n   see :ref:`complex FAQ<Faq@Complex Types>` .)\n#. Fixing the ``not_complex_ad.cpp`` problem above also fixed a warning\n   generated by `valgrind <https://valgrind.org/>`_.\n   Now ``valgrind`` runs the CppAD ``example/example`` program\n   with out any warning or error messages.\n   In addition, a minor initialization error was fixed in the\n   ``test_more/jacobian.cpp`` routine so now\n   ``valgrind`` also runs the CppAD ``test_more/test_more`` program\n   with out any warnings or error messages.\n\n05-20\n=====\nA change was make to the trunk on 05-19 (svn revision 1361) that broke the\n:ref:`Unix install<configure-name>` procedure.\nThis was has been fixed (revision 1362).\n\n03-24\n=====\nAdded cross references in\nthe :ref:`examples<list_all_examples-name>` to occurrence of the following tokens:\n:ref:`AD-name` ,\n:ref:`ADFun<fun_construct-name>` ,\n``CPPAD_TEST_VECTOR`` ,\n:ref:`Forward-name` ,\n:ref:`Independent-name` ,\n:ref:`Jacobian-name`\n:ref:`NearEqual-name` ,\n:ref:`Reverse-name` .\n\n02-20\n=====\nDemonstrate using AD to compute the derivative\nof the solution of an ODE with respect to a parameter\n(in the :ref:`runge_45.cpp-name` example).\n\n02-15\n=====\nChange the distribution\ncompressed tar file\nto only contain one copy of the documentation.\nLink to the current Internet documentation for the other three copies.\n\n02-01\n=====\nMove the ``Prev`` and ``Next`` buttons at the top of the documentation\nto the beginning so that their position does not change between sections.\nThis makes it easier to repeatedly select this links.\n\n01-31\n=====\nModify ``cppad/local/op_code.hpp`` to avoid incorrect warning by\ng++ version 4.3.2 when building ``pycppad`` (a python interface to CppAD).\n\n01-18\n=====\nSometimes an error occurs while taping AD operations.\nThe :ref:`abort_recording-name` function has been added\nto make it easier to recover in such cases.\n\nPreviously, CppAD speed and comparison tests used Adolc-1.10.2.\nThe version used in the tests has been upgraded to\n`Adolc-2.0.0. <https://github.com/coin-or/ADOL-C>`_\n\nA discussion has been added to the documentation for :ref:`Jacobian-name`\nabout its use of\n:ref:`Jacobian@Forward or Reverse`\nmode depending on which it estimates is more efficient.\n\nA minor typo has been fixed in the description of\n``W(t, u)`` in :ref:`reverse_any-name` .\nTo be specific,\n:math:`o ( t^{p-1} ) * t^{1-p} \\rightarrow 0`\nhas been replaced by\n:math:`o ( t^{p-1} ) / t^{1-p} \\rightarrow 0`.\n\n01-06\n=====\nMade some minor improvements to the documentation in\n:ref:`fun_construct-name` .\n\n{xrst_end 2009}\n"
  },
  {
    "path": "appendix/whats_new/2010.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin 2010 app}\n{xrst_spell\n    blas\n    ifdef\n    lagragian\n    libcppad\n    libipopt\n    linpack\n    makefile\n    retape\n    src\n    wshadow\n}\n\nRelease Notes for 2010\n######################\n\nmm-dd\n*****\n\n12-31\n=====\n\n#. Add specifications for the CppAD :ref:`pkgconfig-name` files.\n#. Update the CppAD README file.\n#. Move most all CppAD development shell scripts to the ``bin``\n   subdirectory of the distribution directory.\n#. Fix warnings generated by the ``g++`` compiler option ``-Wshadow`` ;\n   for example,\n\n        ``sparse_pack.hpp:101:2: warning: declaration of`` ``'end'`` ``shadows a member of`` ``'this'``\n\n11-27\n=====\nIf ``NDEBUB`` was defined,\nthe default CppAD :ref:`error handler<ErrorHandler-name>` would return\nbecause its ``assert`` had no effect in this case.\nThis has been fixed by placing a call to ``std::exit(1)``\nafter its assert.\n\n09-26\n=====\nThere was a bug\n(introduced on 09-22)\nin ``make test``\nwhen the ``configure`` command was executed from a directory\nother than the distribution directory\n(the :ref:`cppad_ipopt_nlp-name` did not build).\nThis has been fixed.\n\n09-22\n=====\nPromote :ref:`cppad_ipopt_nlp-name` from an example to a library\nthat gets installed\n(provided that the :ref:`configure@ipopt_dir`\nis specified on the ``configure`` command line).\n\n08-21\n=====\nFix problems with linking of :ref:`cppad_ipopt_nlp-name` test with\nboth older and newer versions of ``ipopt`` .\n\n07-14\n=====\nThe new versions of ipopt use ``pkg-config`` to record the location\nwhere its necessary libraries are stored on the system.\nThe cppad :ref:`configure@Configure` command has\nbeen improved so that it can work both with versions of ipopt that use\n``pkg-config`` and ones that don't.\n\n07-11\n=====\nOld versions of the ipopt library were located in\n*ipopt_dir* / ``lib/libipopt.`` *\n(see :ref:`configure@ipopt_dir` ),\nbut newer versions will be located in\n*ipopt_dir* / ``lib/coin-or/libipopt.`` * .\nThe directory *ipopt_dir* / ``lib/coin`` has been added to the library\nsearch path so that the\ncppad_ipopt_nlp examples\nwork with both old and new versions of ipopt.\n\n06-01\n=====\nIn the case where the preprocessor symbol ``NDEBUG`` was defined\n(see :ref:`Faq@Speed` ),\nthe function\n\n    ``CheckSimpleVector`` ( ``const`` *Scalar* & *x* , ``const`` *Scalar* & *y* )\n\nwas not defined; see\n`bug report <https://list.coin-or.org/pipermail/cppad/2010q2/000166.html>`_.\nThis has been fixed.\n\n04-28\n=====\nChange the multi-level taping examples\n:ref:`mul_level.cpp-name` and :ref:`mul_level_adolc.cpp-name`\nto be more efficient.\n\n04-26\n=====\nInclude Blas and Linpack libraries in makefile links for\n:ref:`cppad_ipopt_nlp-name` examples.\nThis removes the need to use get.Blas when building Ipopt.\n\nThe speed test in ``cppad_ipopt/speed`` was missing\na link to the library ``../src/libcppad_ipopt.a`` .\nThis has been fixed.\n\n04-24\n=====\nThere was a bug in the error checking done by ``cppad/local/sub_op.hpp``\nthat caused the following improper abort:\n\n| ``Error detected by false result for``\n| |tab| ``arg`` [1] < ``i_z``\n| ``at line 337 in the file``\n| |tab| .../ ``include/cppad/local/sub_op.hpp``\n\nThis was fixed in the trunk.\nIt was also fixed in the release with version number ``20100101.3``\nwhich can be downloaded from the CppAD\n`download directory <https://www.coin-or.org/download/source/CppAD/>`_.\n\n04-01\n=====\nSome of the :ref:`speed_utility-name` library\n(in ``speed/src`` ) was being compiled for debugging.\nThis has been changed and they are now compiled with debugging off\nand optimization on.\n\n03-11\n=====\nThe old :ref:`reverse_any-name` example was moved to :ref:`reverse_three.cpp-name` ,\nthe old checkpoint example is now the general case reverse example,\nand a better ``checkpoint.cpp/`` example was created.\n\n03-10\n=====\nThe :ref:`optimize-name` routine would mistakenly remove some\nexpressions that depended on the independent variables and that\naffected the result of certain :ref:`CondExp-name` operations.\nThis has been fixed.\n\n03-09\n=====\nExtend :ref:`reverse_any-name` so that it can be used for\n:ref:`checkpointing<chkpoint_one-name>` ; i.e.,\nsplitting reverse mode calculations at function composition points.\n\n03-03\n=====\nFixed a bug in handling\n:ref:`vector of boolean<glossary@Sparsity Pattern@Boolean Vector>`\nsparsity patterns.\n(when the number of elements per set was a multiple of\n``sizeof(size_t))`` .\n\n02-11\n=====\nThe ``speed`` directory has been reorganized and the\ncommon part of the :ref:`speed_main@Link Routines` ,\nas well as the ``microsoft_timer`` ,\nhave been moved to the subdirectory ``speed/src``\nwhere a library is built.\n\n02-08\n=====\nA bug was introduced in the :ref:`2010@mm-dd@02-05`\nchange whereby the ``make`` command tried to build the\n``libcppad_ipopt.a`` library even if ``IPOPT_DIR`` was\nnot specified on the :ref:`configure@Configure` command line.\nThis has been fixed.\n\n02-06\n=====\nThe Microsoft project files for the speed tests were extended\nso that the worked properly for the Release (as well as the Debug)\nconfiguration.\n(This required conversion from Visual Studio Version 7 to Visual Studio 2008\nformat.)\n\nAdd an automated check for :ref:`optimize-name` bug\nfixed on ``02-05`` .\n(Automatic checking for :ref:`PrintFor-name` bug was added on ``02-05`` .)\n\n02-05\n=====\n\n#. Simplify running all the tests by adding the\n   ``make test`` command.\n#. Simplify the :ref:`configure@Configure` command by removing\n   need for:\n   ``--with-Speed`` ,\n   ``--with-Introduction`` ,\n   ``--with-Example`` ,\n   ``--with-TestMore`` ,\n   and ``--with-PrintFor`` .\n#. Add files that were missing in the Microsoft Visual Studio\n   projects.\n#. Fix two significant bugs. One in the :ref:`optimize-name` command\n   and the other in the :ref:`PrintFor-name` command.\n\n02-03\n=====\nFix a mistakes in the test :ref:`bender_quad.cpp-name` .\nIn addition, the :ref:`optimize-name` routine was used to reduce the\ntape before doing the calculations.\n\nThe routine :ref:`opt_val_hes-name` was added as an alternative to\n:ref:`BenderQuad-name` .\n\n01-26\n=====\nAnother speed improvement was made to :ref:`cppad_ipopt_nlp-name` .\nTo be specific, the Lagragian multipliers where checked and components\nthat were zero were excluded form the Hessian evaluation.\n\n01-24\n=====\nIt appears that in :ref:`cppad_ipopt_nlp-name` , when ``retape[k]`` was true,\nand ``L[k] > 1`` , it was possible to use the wrong operation sequence\nin the calculations (though a test case that demonstrated this could not be\nproduced). This is because the argument value to :math:`r_k (u)` depends\non the value of :math:`\\ell` in the expression\n\n.. math::\n\n    r_k \\circ [ J_{k, \\ell} \\otimes n ] (x)\n\n(even when the value of :math:`x` does not change).\n\nThere was a bug in the ``ipopt_nlp_ode_check.cpp`` program,\nfor a long time,  that did not show up until now. Basically,\nthe check had code of the was using an undefined value.\nThis has been fixed.\n\n01-23\n=====\nImprove the sparsity patterns and reduce the amount of memory\nrequired for large sparse problems using :ref:`cppad_ipopt_nlp-name` .\nThe speed test ``cppad_ipopt/speed`` showed significant improvement.\n\n01-20\n=====\nWe plan to split up the\n``ipopt_cppad/src/ipopt_cppad_nlp.hpp`` include file.\nIn preparation,\nthe example ``ipopt_cppad`` has been changed to ``cppad_ipopt`` .\nThis will facilitate using ``CPPAD_IPOPT_*`` for the\n``# ifdef`` commands in the new include files\n(note that they must begin with ``CPPAD`` ).\n\n01-18\n=====\nThe ``ipopt_cppad`` subdirectory of the distribution\nhas been split into an ``src`` , ``example`` , and ``speed``\nsubdirectories.\nThe ``example`` (``speed`` )\nsubdirectory is where one builds the :ref:`cppad_ipopt_nlp-name` examples\n(speed tests).\n\n01-04\n=====\nThe following items have been fulfilled and\nhence were removed for the :ref:`wish_list-name` :\n\n#. If an exception occurs before the call to the corresponding\n   :ref:`ADFun-name` constructor or :ref:`Dependent-name` ,\n   the tape recording can be stopped using :ref:`abort_recording-name` .\n\n#. A speed test for :ref:`cppad_ipopt_nlp-name` was added; see\n   ``ipopt_ode_speed.cpp`` .\n\n#. The :ref:`optimize-name` command uses hash coding to check\n   when an expression is already in the tape and can be reused.\n\n#. The :ref:`optimize-name` command removes operations that\n   are not used by any of the dependent variables.\n\n#. The :ref:`ad_in_c.cpp-name` example demonstrates how to connect\n   CppAD to an arbitrary scripting language.\n\n#. The vector of sets option has been added to sparsity calculations;\n   see :ref:`glossary@Sparsity Pattern` .\n\n{xrst_end 2010}\n"
  },
  {
    "path": "appendix/whats_new/2011.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-25 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin 2011 app}\n{xrst_spell\n    automake\n    boostvector\n    builddir\n    executables\n    for for\n    geq\n    gpl\n    hasnan\n    initializer\n    inv\n    isnan\n    libspeed\n    makefile\n    matlab\n    omh\n    prefixdir\n    pthreads\n    retape\n    rosen\n    runge\n    svn\n    tgz\n    undefine\n    vcproj\n    wshadow\n}\n\nRelease Notes for 2011\n######################\n\nmm-dd\n*****\n\n12-30\n=====\n\n#. There was a bug when using :ref:`abs-name` with an ``AD< AD<double> >``\n   argument, whereby the corresponding ``AD<double>`` operation sequence\n   depended on the value of the argument to the ``abs`` function.\n#. Change the specifications for the derivative of the :ref:`abs-name`\n   function to be the :ref:`sign-name` function instead of a directional derivative.\n#. Add the :ref:`sign-name` function to the ``AD`` < *Base* > list of\n   available functions.\n   In addition, add the\n   :ref:`base_std_math@sign` function to the list of\n   :ref:`base type requirements<base_require-name>` .\n\n12-28\n=====\nThe file :ref:`time_test.hpp<time_test@Include>`\nwas not being included by ``cppad/cppad.hpp`` .\nThis has been fixed.\n\n12-21\n=====\nThe types\n``SizeVector`` ,\n``NumberVector`` ,\n``ADNumber`` , and\n``ADVector`` ,\nwere in the global namespace and this was causing warnings\nabout the shadowing of these declarations.\nThe\n:ref:`cppad_ipopt_nlp@cppad_ipopt namespace`\nwas created to avoid these problems.\nThe simplest way to make old :ref:`cppad_ipopt_nlp-name` code work with this\nchange is to use the command\n::\n\n    using namespace cppad_ipopt;\n\n12-20\n=====\n\n#. Change ``team_start`` to :ref:`team_thread.hpp@team_create`\n   and ``team_stop`` to :ref:`team_thread.hpp@team_destroy` .\n#. Change ``NDEBUG`` mentions to include link to\n   :ref:`Faq@Speed@NDEBUG` .\n#. Improve :ref:`memory_leak-name` documentation.\n\n11-29\n=====\nTHe :ref:`time_test-name` routine was still executing the\ntest at least twice, even if that was not necessary for the specified\nminimum time. This has been fixed.\n\n11-27\n=====\nMove ``multi_thread.cpp`` to :ref:`thread_test.cpp-name`\nand fix its :ref:`running<thread_test.cpp@Running Tests>` instructions.\n\n11-24\n=====\nCreate :ref:`preprocessor-name` section with pointers to all the\npreprocessor symbols that are in the CppAD API.\n\n11-21\n=====\nSeparate :ref:`--with-boostvector<configure@--with-<package>vector>`\nfor *boost_dir* .\nThis enables one to specify *boost_dir* for\n:ref:`team_bthread.cpp-name` with out using boost vectors.\n\n11-20\n=====\n\n#. Move ``sum_i_inv.cpp`` to :ref:`harmonic.cpp-name` .\n#. Include the date, time, CppAD version, and\n   :ref:`team_thread.hpp@team_name` in the\n   :ref:`thread_test.cpp-name` output.\n\n11-18\n=====\n\n#. The :ref:`thread_test.cpp-name` program was truncating *test_time*\n   to the nearest integer.\n   This has been fixed.\n#. The :ref:`time_test-name` routine has been made more efficient and now\n   check for the case where only one execution of the test is necessary\n   to achieve the desired *test_time*\n   (it used to always run at least two).\n#. The ``sum_i_inv_time.cpp`` and :ref:`multi_newton.cpp-name`\n   routines were calling the test an extra time at the end to check for\n   correctness.\n   The results of the last test are now cached and used for the correctness\n   test so that an extra call is not necessary (to make the tests run faster\n   when only a few repetitions are necessary).\n\n11-17\n=====\n\n#. Create another speed testing routine :ref:`time_test-name` which is\n   like :ref:`speed_test-name` but it returns the time instead of rate\n   and as a ``double`` instead of a ``size_t`` .\n   The use it for the timing tests in\n   ``sum_i_inv_time.cpp`` and :ref:`multi_newton_time-name` .\n#. Add *test_time* as a command line argument\n   to the multi-threading ``sum_i_inv``\n   and :ref:`thread_test.cpp@multi_newton`\n   timing tests.\n\n11-09\n=====\nChange ``thread_team.hpp`` to :ref:`team_thread.hpp-name` and do\nthe same for all other names that ended in ``_team`` ; e.g.,\n:ref:`team_openmp.cpp-name` .\n\n11-07\n=====\nThe users choice for ``test_vector`` was not actually changing\nthe tests that the user ran. This have been fixed.\n\n11-06\n=====\nMake all the output generated by :ref:`multi_newton.cpp-name` valid\nmatlab and octave input so it is easy to plot the results.\n\n11-04\n=====\nUse thread specific data to simplify :ref:`team_openmp.cpp-name` .\n\n11-01\n=====\nMake :ref:`team_bthread.cpp-name` more similar to :ref:`team_pthread.cpp-name` .\n\n10-30\n=====\n\n#. Reorganize and improve the :ref:`multi_thread-name` section and its subsections.\n#. There was a bug in :ref:`multi_newton.cpp-name` that only showed up when\n   the number of threads was greater than or equal 4.\n   This has been fixed.\n   In addition,\n   :ref:`multi_thread@CPPAD_MAX_NUM_THREADS`\n   was increased from 2 to 4 (to enable testing for this bug).\n#. The accuracy expected in the ``sum_i_inv.cpp`` results were failing\n   when ``mega_sum`` was large.\n   This check has been modified to include a correction for *mega_sum* .\n\n10-29\n=====\nThe following changes were merged in from ``branches/thread`` :\n\n#. Move ``openmp`` to ``example/multi_thread/openmp`` .\n   and create ``example/multi_thread/bthread`` , ``multi_thread/pthread``\n   with similar tests.\n#. Put multi-threading common code in ``multi_thread`` directory\n   and threading system specific code in ``example/multi_thread/`` *threading*\n   for *threading* equal to ``openmp`` , ``bthread`` ,\n   and ``pthread`` .\n#. Update the README file.\n#. Remove the ``bug/optimize.sh`` file (no longer a bug).\n#. Make ``arc_tan.cpp``\n   utility that can be used by multiple multi-threading tests.\n#. Create :ref:`team_thread.hpp-name` specifications,\n   move OpenMP management to :ref:`team_openmp.cpp-name` ,\n   Boost thread management to :ref:`team_bthread.cpp-name` ,\n   and pthread management to :ref:`team_pthread.cpp-name` .\n#. All of the make files were modified so that the command\n   ::\n\n        make test\n\n    would run the tests for the current directory.\n#. Extend the multi-threading speed tests\n   ``sum_i_inv.cpp`` and :ref:`multi_newton.cpp-name` so they run\n   using Boost threads and pthreads (as well as OpenMP threads).\n\n10-14\n=====\nFix some compiler warnings about shadowed variables that were\ndetected by ``g++`` version ``4.6.1 20110908`` .\n\n10-12\n=====\n\n#. The MAC version of the ``pthread`` library does not include the\n   ``pthread_barrier_wait`` function; i.e., is not compliant with\n   the IEEE Std 1003.1, 2004 Edition for ``pthread`` .\n   This caused the ``pthread_simple_ad.cpp`` to fail to compile on the MAC.\n   This has been fixed by not compiling the ``pthread`` examples\n   unless ``pthread_barrier_wait`` is present.\n#. The :ref:`cppad_ipopt_nlp-name` routine has been changed to\n   :ref:`optimize-name` the functions :math:`r_k (u)` such that\n   ``retape`` ( *k* ) is false.\n\n09-06\n=====\n\n#. Add the\n   `boost multi-threading <https://www.boost.org/doc/libs/1_47_0/doc/html/thread.html>`_\n   examples :ref:`a11c_bthread.cpp-name` and ``bthread_simple_ad.cpp`` .\n#. Improve documentation for\n   :ref:`ta_parallel_setup@thread_num` argument\n   to ``parallel_setup`` .\n#. More simplification of ``bthread_simple_ad.cpp`` example.\n\n09-05\n=====\nSimply and fix some problems with ``pthread_simple_ad.cpp`` ,\nincluding avoiding a :ref:`team_pthread.cpp@Bug in Cygwin` .\n\n09-02\n=====\n\n#. The OpenMP speed test program ``openmp/run.cpp`` was not setting\n   the number of threads for the one thread case (so dynamic thread adjustment was\n   used). This has been fixed.\n#. The :ref:`thread_alloc.cpp-name` example was missing from the\n   Microsoft ``example/example.vcproj`` file and a attempt was made\n   to link to missing OpenMP routines (this has been fixed).\n   In addition,\n   some Microsoft compiler warning have been fixed; see the examples and tests\n   in the Windows install instructions.\n#. There was an oversight,\n   and ``CPPAD_MAX_NUM_THREAD``\n   was being set to 2 when ``_OPENMP`` was not defined.\n   This has been fixed and\n   :ref:`multi_thread@CPPAD_MAX_NUM_THREADS`\n   has been documented and is now part of the CppAD API.\n#. The ``pthread_simple_ad.cpp`` test failed under cygwin.\n   This was because the previous test ``openmp_ad.cpp`` was\n   set up calls to OpenMP routines that were still in effect\n   when ``pthread/simple_ad`` ran.\n   This has been fixed by making\n   *num_threads*  == 1 a special case in\n   :ref:`parallel_setup<ta_parallel_setup-name>` .\n\n09-01\n=====\nModify the CppAD trunk using the\nchanges from svn revision 2060 to revision 2081 in the branch\n::\n\n    https://projects.coin-or.org/svn/CppAD/branches/pthread\n\nThese changes are described below.\n\n#. 09-01:\n   There was a bug in the :ref:`atomic_one-name` functions\n   in the case where none of the elements of the argument to the function\n   was a :ref:`glossary@Variable` .\n   This has been fixed.\n   In addition, old_tan.cpp generated an assert for this\n   case and this has also been fixed (in addition to including an example\n   for this case).\n\n#. 08-31:\n   Move the ``sum_i_inv_time.cpp`` test from\n   ``openmp/run.sh`` to ``openmp/run.cpp`` .\n#. 08-31:\n   Change ``--with-openmp`` to\n   OPENMP_FLAGS=openmp_flags configure\n   command line argument.\n\n#. 08-30:\n   Create the ``openmp/run.cpp`` program\n   and move the ``openmp_multi_newton.cpp`` test from\n   ``openmp/run.sh`` to ``openmp/run.cpp`` .\n   This uses :ref:`configure@Configure`\n   information for building the tests.\n#. 08-30:\n   Document the ``--with-openmp`` configure\n   command line argument.\n#. 08-30:\n   Move ``openmp/multi_newton.hpp`` to\n   ``openmp/newton_method.hpp`` and\n   ``openmp/multi_newton.cpp`` to\n   ``openmp/newton_example.cpp`` .\n\n#. 08-25:\n   Replace :ref:`omp_alloc-name` by :ref:`thread_alloc-name` in\n   :ref:`multi_thread-name` , the section on how to use CppAD in parallel.\n#. 08-25:\n   Implement :ref:`omp_alloc-name` as links to corresponding :ref:`thread_alloc-name`\n   sections.\n#. 08-25:\n   Create the ``pthread_simple_ad.cpp`` example that does AD using the\n   pthread library.\n   In addition, fix some problems in ``openmp_simple_ad.cpp``\n#. 08-25:\n   Move ``openmp/example_a11c.cpp`` to\n   :ref:`example/a11c_openmp.cpp<a11c_openmp.cpp-name>` .\n#. 08-25:\n   Move ``openmp/parallel_ad.cpp`` to\n   ``openmp_simple_ad.cpp`` .\n\n#. 08-23:\n   Beginning steps in replacing :ref:`omp_alloc-name` by :ref:`thread_alloc-name` :\n   Replace :ref:`omp_alloc-name` by :ref:`thread_alloc-name`\n   in the :ref:`utilities<utility-name>` .\n#. 08-23:\n   move :ref:`omp_alloc-name` to the deprecated section of the\n   documentation.\n#. 08-23:\n   Change all :ref:`omp_alloc-name` section names to begin with ``omp_`` ,\n   and change all :ref:`thread_alloc-name` section names to begin with ``new_`` .\n#. 08-23:\n   Convert :ref:`CppAD_vector-name` from using :ref:`omp_alloc-name` to using\n   :ref:`thread_alloc-name` for memory allocation.\n#. 08-23:\n   Extend the :ref:`memory_leak-name` routine to also check the\n   :ref:`thread_alloc-name` allocator.\n\n#. 08-21:\n   Create the OpenMP and pthread examples\n   :ref:`a11c_openmp.cpp-name` ,\n   :ref:`a11c_pthread.cpp-name` , and\n   ``openmp_simple_ad.cpp`` .\n   These OpenMP examples were originally in the ``openmp`` directory,\n   and have been moved, and modified to conform, to the normal example directory.\n\n08-11\n=====\nModify the CppAD trunk using the\nchanges from svn revision 2044 to revision 2056 in the branch\n::\n\n    https://projects.coin-or.org/svn/CppAD/branches/base_require\n\nThese changes are described below.\n\n#. 08-10:\n   Add the output stream optional argument *s* in\n\n        *f* . ``Forward`` (0, *x* , *s* )\n\n    See :ref:`zero order forward mode<forward_zero-name>` and :ref:`PrintFor-name` .\n#. 08-10:\n   Improve omp_alloc.cpp example.\n\n#. 08-09:\n   :ref:`base_require-name` :\n   Add :ref:`numeric_limits@epsilon` to the\n   *Base* type requirements.\n#. 08-09:\n   Extend ``epsilon`` to AD types.\n\n#. 08-08:\n   Improve the :ref:`base_require-name` documentation for\n   :ref:`standard math functions<base_std_math-name>` .\n#. 08-08:\n   :ref:`base_require-name` :\n   Add ``abs_geq`` to the :ref:`requirements<base_require-name>`\n   for a user defined *Base* type.\n#. 08-08:\n   Check that zero order forward mode results are approximately equal,\n   instead of exactly equal,\n   after an :ref:`optimize-name` operation.\n   This fixes a bug in the optimize correctness check\n   (The  order of operations can be changed by ``optimize``\n   and hence the zero order forward mode results may not be exactly the same.)\n\n#. 08-07:\n   Improve the :ref:`base_require-name` documentation for\n   :ref:`base_identical@EqualOpSeq` ,\n   :ref:`base_identical@Identical`\n   :ref:`base_require@Integer` , and\n   :ref:`Ordered<base_ordered-name>`\n   operations.\n\n#. 08-06:\n   Add the :ref:`base_cond_exp@CondExpRel` paragraph to the\n   base requirements documentation.\n   This was missing and are required for\n   :ref:`CondExp-name` to work with ``AD`` < *Base* > arguments\n   and a non-standard *Base* type.\n\n#. 08-04:\n   :ref:`base_require-name` :\n   Change the :ref:`include<base_require@Include Order>` file name to\n   :ref:`base_require.hpp<base_require-name>` .\n#. 08-04:\n   Use :ref:`base_float.hpp-name` and\n   :ref:`base_double.hpp-name` as additional examples\n   for the :ref:`CondExp Base requirements<base_cond_exp-name>` .\n\n08-03\n=====\nChange :ref:`PrintFor-name` condition from less than or equal zero\nto not greater than zero;i.e., not positive.\nThis makes ``nan`` print because it results in false for all comparisons.\n\n08-02\n=====\n\n#. Change :ref:`PrintFor-name` so it no longer aborts execution when\n   there is no operation sequence being recording; see\n   :ref:`Independent@Start Recording` .\n#. Improve the :ref:`print_for_cout.cpp-name` example.\n\n07-31\n=====\nAdd a conditional version of the :ref:`PrintFor-name` command\n\n    ``PrintFor`` ( *text* , *y* , *z* )\n\nwhich only prints when *z*  <= 0 .\nThis is useful for error reporting during forward mode; i.e.,\nreporting when the argument to the ``log`` function is not valid.\n\n07-29\n=====\n\n#. The routines :ref:`set_max_num_threads<omp_max_num_threads-name>` and\n   ``get_max_num_threads`` were created.\n   User's will need to replace calls to\n   :ref:`max_num_threads<old_max_num_threads-name>`\n   by calls to ``set_max_num_threads`` .\n#. The functions :ref:`omp_efficient-name` was deprecated because it\n   has not been shown to be useful.\n\n07-28\n=====\n\n#. Change :ref:`omp_return_memory-name` so that if :ref:`omp_max_num_threads-name` is one\n   (the default), :ref:`omp_alloc-name` does not hold onto memory\n   (keep it available for the corresponding thread).\n#. Add files that were missing from the Microsoft Visual Studio\n   ``example`` and ``test_more`` subdirectory\n   project files.\n#. Fix some warnings generated by Microsoft Visual Studio 2010 build.\n\n07-27\n=====\nMake ``tan`` and ``tanh`` :ref:`atomic_base<glossary@Operation@Atomic>`\noperations; see :ref:`tan_forward-name` and :ref:`tan_reverse-name` .\n\n07-25\n=====\nFinish the :ref:`atomic_one-name` example old_tan.cpp.\nThis is also a design and implementation of the routines necessary\nto make ``tan`` and ``tanh`` CppAD atomic operations.\n\n07-18\n=====\nThe reverse mode formulas for :math:`Z(t)` need to involve\nthe lower order Taylor coefficients for :math:`Y(t)`.\nThis has been fixed in :ref:`tan_reverse-name` .\n\n07-17\n=====\n\n#. Fix bug in :ref:`atomic_one-name` functions.\n   To be specific, the Taylor coefficients for :math:`y`,\n   of order less than *k* ,\n   were not passed into the ``atomic_one``\n   :ref:`atomic_one@forward` callback function.\n#. Derive the theory for including the tangent and hyperbolic tangent\n   as CppAD atomic operations :ref:`tan_forward-name` and :ref:`tan_reverse-name` ;\n   see the wish list item ``Tan and Tanh`` .\n#. Implement and test forward mode calculation of derivative for\n   the tangent and hyperbolic tangent functions;\n   see the new :ref:`atomic_one-name` example old_tan.cpp.\n\n07-14\n=====\n\n#. The :ref:`configure-name` instructions for running the individual\n   correctness and speed tests were out of date.\n   This has been fixed; see\n   :ref:`example and tests<configure@make@Examples and Tests>` .\n#. Move ``parallel_ad.cpp`` from ``example`` directory\n   to ``openmp`` directory (and convert it from a function to a program).\n#. Simplify ``example_a11c.cpp`` by making it just a correctness test.\n#. Change ``openmp/run.sh`` so that it runs correctness tests with\n   the compiler debugging flags.\n\n07-13\n=====\n\n#. static hash code data that was begin used by multiple threads\n   when recording ``AD`` < *Base* > operations\n   :ref:`omp_in_parallel-name` execution mode. This has been fixed.\n#. Make the sparse calculations safe\n   for use during :ref:`omp_in_parallel-name` execution mode.\n#. Add the ``parallel_ad.cpp`` example.\n#. Change ``example_a11c.cpp`` example so that is just a correctness\n   (not speed) test.\n\n07-11\n=====\n\n#. Change the upper limit for\n   :ref:`omp_max_num_threads-name` from 32 to 48.\n#. Add :ref:`parallel<ta_in_parallel-name>` documentation for,\n   ``nan`` ,\n   :ref:`Rosen34<Rosen34@Parallel Mode>` , and\n   :ref:`Runge45<Runge45@Parallel Mode>` .\n#. Fix :ref:`CheckNumericType-name` and :ref:`CheckSimpleVector-name`\n   so they work properly when used in parallel mode.\n\n#. The changes below were made on the ``openmp/run.sh`` branch:\n#. Change to ``openmp/run.sh``\n   maximum number of threads\n   instead of specifying the entire set of values to be tested.\n#. Change settings for\n   ``newton_example``\n   so that ``n_gird`` is a multiple of the maximum number of threads.\n#. Report dynamic number of thread\n   results as a separate result in the summary output line.\n#. Fix automatic removal of executables from ``openmp`` directory\n   (was commented out).\n#. The documentation for ``openmp/run.sh`` was moved to the\n   ``multi_thread`` section.\n\n07-10\n=====\n\n#. Add link to :ref:`Discrete-title` in :ref:`multi_thread-name` .\n#. Make use of the :ref:`track_new_del-name` routines\n   :ref:`omp_in_parallel-name` execution mode an error (it never worked properly);\n   see :ref:`TrackNewDel multi-threading<track_new_del@Multi-Threading>` .\n#. Change :ref:`memory_leak-name` so that it checks for a leak in all threads.\n   This is what ``openmp_newton_example.cpp`` and\n   ``sum_i_inv_time.cpp``\n   assumed was being done.\n\n07-09\n=====\nAll the OpenMP parallel execution requirements\nhave been grouped in the section :ref:`multi_thread-name` .\n\n07-07\n=====\nAdd the routine :ref:`parallel_ad-name` to fix bug when using\n``AD`` < *Base* > in :ref:`parallel<omp_in_parallel-name>` execution mode.\n\n06-23\n=====\n\n#. Fix a bug whereby the assert\n\n    | |tab| ``Error detected by false result for``\n    | |tab| |tab| ! ``omp_in_parallel`` ()\n    | |tab| ``at line`` *n* ``in the file``\n    | |tab| *prefix* / ``include/cppad/omp_alloc.hpp``\n\n    sometimes occurred.\n#. The routine :ref:`omp_max_thread-name` was deprecated,\n   use the routine :ref:`omp_max_num_threads-name` instead.\n#. The deprecated routines have been grouped together in the\n   :ref:`deprecated-name` section of the CppAD manual.\n\n06-21\n=====\n\n#. The ``openmp/run.sh`` routine was changed to use zero,\n   instead of ``automatic`` , for automatic choice of\n   ``openmp/run.sh``\n   number of repeats\n   and\n   maximum number of threads.\n\n#. The output of each of the OpenMP examples / speed tests\n   (run by ``openmp/run.sh`` )\n   was changed to be valid matlab / octave assignment statements.\n\n#. In the case where OpenMP is enabled during compilation,\n   a summary for the different number of threads as added at the end of\n   the ``openmp/run.sh`` output.\n\n06-18\n=====\n\n#. The :ref:`configure@tape_addr_type` option was added\n   to the :ref:`configure@Configure` command line.\n#. The function :ref:`fun_property@size_op_seq` results uses\n   ``sizeof(CppAD_TAPE_ADDR_TYPE)``\n   where it used to use ``sizeof(size_t)`` .\n#. Remove ``cppad/config.h`` from CppAD distribution,\n   (put the information in ``cppad/configure.hpp`` .)\n   This removes the need to undefine symbols that were\n   defined by ``cppad/config.h`` and that did not begin with ``CPPAD_`` .\n#. Change :ref:`adolc<configure@adolc_dir>` library linkage so it\n   works with version ``ADOL-C-2.2.0`` .\n\n05-29\n=====\nFix bug (introduced on :ref:`2011@mm-dd@05-22` )\nwhereby constructor might not be called (but required) when the\n:ref:`base type<base_require-name>` is not plain old data.\n\n05-28\n=====\n\n#. Add the :ref:`omp_efficient-name` routine to the :ref:`omp_alloc-name` system.\n#. Improve the ``omp_alloc`` tracing so it prints the same pointer\n   as returned to the user (not an offset version of that pointer).\n\n05-26\n=====\nFix Visual Studio project files that were broken during the change on 05-22.\nIn addition, in the file ``cppad/omp_alloc.hpp`` ,\nsuppress the following Microsoft Visual Studio warning\n::\n\n    warning C4345: behavior change: an object of POD type constructed with\n    an initializer of the form () will be default-initialized\n\n05-22\n=====\n\n#. The old memory tracking routines :ref:`track_new_del-name` have been deprecated.\n   Their use should be replaced using the :ref:`omp_alloc-name`\n   a memory allocator which is designed to work well in a multi-threading OpenMP\n   environment; see :ref:`omp_alloc@Purpose` .\n#. The replacement of ``TrackNewDel`` by ``omp_alloc``\n   has been throughout the CppAD source code, including the examples\n   that used ``TrackNewDel`` ; namely,\n   :ref:`mul_level_adolc.cpp-name` , :ref:`mul_level_adolc_ode.cpp-name` .\n#. The CppAD vector template class\n   and the :ref:`CppAD_vector@vectorBool` class\n   were modified to use the ``omp_alloc``\n   :ref:`memory<CppAD_vector@Memory and Parallel Mode>` manager.\n   This should improves its speed of memory allocation\n   :ref:`omp_in_parallel-name` sections of a program.\n#. The :ref:`speed_test-name` argument\n   :ref:`speed_test@size_vec` call was by value,\n   instead of by reference (as documented).\n   This has been fixed and the call is now by reference.\n#. The :ref:`CppAD_vector@capacity` function has been added\n   to the CppAD vector class.\n#. The simple vector\n   :ref:`SimpleVector@Element Constructor and Destructor`\n   description has been changed to explicitly specify that the\n   default constructor is used to initialize elements of the array.\n#. The :ref:`fun_property@size_op_seq` documentation\n   has been improved to mention that the allocated memory may be larger.\n\n05-11\n=====\n\n#. Avoid ambiguity in the definition of the\n   :ref:`complex isnan<base_complex.hpp@isnan>` function.\n#. Errors during ``make test`` were not\n   being detected.\n   This has been fixed.\n\n05-03\n=====\n\n#. If ``NDEBUG`` is not defined,\n   the :ref:`hasnan<nan-name>` function is used to make sure that the\n   results of any :ref:`Forward-name` operation does not contain a\n   nan (not a number).\n   If so, an error message is generated and the program terminates.\n   This error message and termination can be caught; see :ref:`ErrorHandler-name` .\n\n#. In the event that the\n   :ref:`cppad_ipopt_nlp-name` objective function, the constraints,\n   or their derivatives are infinite,\n   an error message is generated and the program terminates\n   (proved that ``NDEBUG`` is not defined and the default error\n   handler has not been replaced).\n\n04-29\n=====\n\n#. The Microsoft Visual Studio 2003 project files\n   for the Windows examples and tests no longer worked because\n   the current version of CppAD uses local types in template instantiation.\n   These project files were converted to Visual Studio 2008 where they do work\n   (if you use a later version, Visual Studio should automatically\n   convert them for you).\n\n#. The old speed test directory was moved to ``speed_cppad``\n   before the new :ref:`speed-name` test organization was created on 2006-12-11\n   (revision 715 of the repository).\n   The old speed tests have not been used for years and so have been deleted.\n\n04-20\n=====\nThe ``openmp/run.sh`` script what changed\nto take an argument that specifies which tests is run\n(it no longer runs all the tests).\nAlso improve the openmp test program output formatting.\n\n04-19\n=====\nThe *use_ad* option was added to the\n``openmp_newton_example.cpp`` test case.\n\n03-19\n=====\nThe subversion write protected directory\n``bin/.svn`` was mistakenly part of the\ncompressed tar file It has been removed.\n\n03-11\n=====\nThe vector of sets argument\n:ref:`atomic_one@rev_hes_sparse@r`\nto the ``atomic_one`` function *rev_hes_sparse*\nmust have size greater than or equal to *n* .\nThere was a check that its size was greater than or equal *q* .\nThis was incorrect and has been fixed.\n\n03-05\n=====\nAdd the :ref:`conjugate gradient<conj_grad.cpp-name>` example.\n\n02-22\n=====\nAdd the :ref:`speed_main@Global Options@atomic` option to the\nspeed test program and use\nold_mat_mul.hpp during the\n:ref:`cppad_mat_mul.cpp-name` speed test when the atomic option is specified.\n\n02-19\n=====\nThere was a bug when :ref:`omp_max_thread-name` was set to one,\nand ``NDEBUG`` was not defined,\nthe thread corresponding to parameters was one, but the only valid thread\nnumber was zero (only one thread)\nand an CPPAD stopped with an assertion error.\nThis has been fixed.\n\n02-17\n=====\nThere was a mistake in ``openmp/run.sh`` where it attempted\nto remove a non-existent file in the case where\n``openmp/run.sh``\nopenmp_flag was not ``\"\"`` .\nThis has been fixed.\n\n02-15\n=====\nA matrix multiply speed test has been added.\nSo far, this has only implemented for the\n:ref:`cppad<cppad_mat_mul.cpp-name>` and :ref:`double<double_mat_mul.cpp-name>` cases.\n(For the time being this test is not available for the other\nspeed comparison cases.)\n\n02-09\n=====\nA variable in ``atomic_one.hpp`` was declare of type *Base*\nwhen it should have been declared of type ``size_t`` .\nIt caused the :ref:`atomic_one-name` feature to fail with some base types.\nThis has been fixed.\n\nThe old_mat_mul.hpp example has been improved by\ncaching the :math:`x` variable information and using it during\n:ref:`reverse Hessian sparsity<atomic_one@rev_hes_sparse>` calculations.\n\nSome of the :ref:`atomic_one-name` documentation was extended to\ninclude more explanation.\n\n02-06\n=====\nThe use can now define complex :ref:`atomic_base<atomic_one-name>` operations\nand store them in a CppAD :ref:`ADFun-name` object.\nThis item has been remove from the\n:ref:`wish list<wish_list-name>` .\n\nThe documentation for :ref:`RevSparseHes-name` had a dimension error.\nThis has been fixed.\n\nA faster set operations item was added to the wish list.\nThis has since been satisfied by\n``cppad_sparse_list`` choice during\nthe install process (since removed).\n\n02-02\n=====\nThe documentation for :ref:`ForSparseJac-name` had some formatting errors.\nThe errors have been fix and the documentation has been improved.\n\n02-01\n=====\nThe subversion\ninstall instructions were brought up to date.\nThey have since been replaced by just separate\n``subversion`` instructions.\n\n01-19\n=====\nThe directory where the :ref:`pkgconfig-name` file ``cppad.pc``\nis stored has been moved from\n*prefixdir* / ``lib/pkgconfig/cppad.pc``\nto\n*prefixdir* / ``share/pkgconfig/cppad.pc`` .\n\n01-16\n=====\nThe following have been fixed:\n\n#. The install of the documentation failed\n   when it was done from a directory other than the top source directory.\n#. The GPL distribution had the output of the\n   :ref:`configure@Configure` command in it.\n#. Since the change on 01-09, the file\n   ``omh/appendix/11.omh`` has been required to build the\n   documentation (and it has been missing from the distribution).\n#. Fadbad was generating warnings due to the ``-Wshadow`` flag\n   with the ``g++`` compiler.\n   The Fadbad :ref:`speed<speed_fadbad-name>` tests have a special\n   flag with this warning removed from the\n   :ref:`configure@cxx_flags` .\n\n01-09\n=====\nThere were some problems running ``make test`` in the releases\n\n    ``https://www.coin-or.org/download/source/CppAD/cppad-20110101.0.`` *license* . ``tgz``\n\nwhere *license* is ``gpl`` or ``cpl`` .\n\n#. The version of automake used to build the corresponding\n   ``makefile.in`` files did not define ``abs_top_builddir`` .\n#. The include file ``cppad_ipopt_nlp.hpp`` was always installed, even if\n   :ref:`configure@ipopt_dir` was not defined on the\n   ``configure`` command line.\n#. The speed test library ``libspeed.a`` was being installed\n   (it is only intended for testing).\n\nThese problems are fixed in the trunk\nand these fixes will be copied to the corresponding stable and\nrelease versions; i.e.,\n\n    ``https://www.coin-or.org/download/source/CppAD/cppad-20110101.1.`` *license* . ``tgz``\n\nwill not have this problem.\n\n{xrst_end 2011}\n"
  },
  {
    "path": "appendix/whats_new/2012.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-25 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin 2012 app}\n{xrst_spell\n    datadir\n    doxygen\n    dw\n    eigenvector\n    fcur\n    gitlab\n    helgrind\n    includedir\n    inorder\n    libdir\n    libeigen\n    lpthread\n    lteuchos\n    makefile\n    posix\n    src\n    stdbool\n    sys\n    taddr\n    trilinos\n    txt\n    uninitialised\n    valgrind\n    yyyymmdd\n}\n\nRelease Notes for 2012\n######################\n\nmm-dd\n*****\n\n12-30\n=====\n\n#. Merge changes in ``branches/ipopt_solve`` to ``trunk`` ,\n   delete that branch, and\n   advance version number to ``cppad-20121230`` .\n#. Remove ``cppad/configure.hpp`` from repository because\n   it is built by the configuration process\n   (even for MS Visual Studio, now that we are using :ref:`cmake-name` ).\n#. Add the ``AD`` < *Base* > input stream operator :ref:`>><ad_input-name>` .\n\n12-29\n=====\nIn ``branches/ipopt_solve`` :\n\n#. Complete implementation of sparse Jacobian and Hessian calculations\n   and add options that allow to user to choose between forward and reverse\n   sparse Jacobians.\n#. The :ref:`ipopt_solve-name` routine seems to be faster and simpler\n   than :ref:`cppad_ipopt_nlp-name` .\n   More speed comparisons would be good to have.\n#. All of the :ref:`ADFun Drivers<Drivers-name>`\n   have added specifications for the zero order Taylor coefficients\n   after the routine is called.\n   For example, see\n   :ref:`Hessian@Hessian Uses Forward` .\n\n12-28\n=====\nIn ``branches/ipopt_solve`` :\n\n#. Add the :ref:`ipopt_solve_retape.cpp-name` and :ref:`ipopt_solve_ode_inverse.cpp-name`\n   examples.\n#. Use ``ipopt::solve`` :ref:`ipopt_solve@options`\n   argument (and not a file) for all the Ipopt options.\n   As well as allowing for adding ``ipopt::solve`` special options; e.g.,\n   :ref:`ipopt_solve@options@Retape` .\n\n12-27\n=====\nIn ``branches/ipopt_solve`` :\nChange documentation section names that begin with ``cppad_ipopt``\nto begin with :ref:`ipopt_nlp<cppad_ipopt_nlp-name>`\nto distinguish them from :ref:`CppAD::ipopt::solve<ipopt_solve-name>` .\n\n12-26\n=====\nIn ``branches/ipopt_solve`` :\n\n#. Convert documentation most all documentation references from\n   the deprecated :ref:`configure-name` instructions to the new :ref:`cmake-name`\n   instructions.\n#. Include the :ref:`Introduction-name` programs in the\n   :ref:`cmake_check-name` built using :ref:`cmake-name` .\n#. Deprecate :ref:`cppad_ipopt_nlp-name` and replace it by :ref:`ipopt_solve-name`\n   which is easier to use.\n   This is a first version of ``ipopt_solve`` and its speed\n   and memory use needs to be improved.\n\n12-23\n=====\nCopy development ``trunk`` to ``branches/ipopt_solve`` .\n\n12-22\n=====\nDefine a doxygen module (group) for each file that has doxygen documentation.\n\n12-20\n=====\n\n#. The :ref:`install instructions<install@Instructions>`\n   were installing ``cppad/CMakeLists.txt`` and ``cppad/configure.hpp.in``\n   in the ``cppad`` include directory.\n   This has been fixed so that only * . ``h`` and * . ``hpp`` files\n   get installed in the ``cppad`` include directory.\n#. Advance the version number to ``cppad-20121220`` .\n\n12-19\n=====\nThe files ``<stdbool.h>`` and ``<sys/time.h>``\ndo not exist for all C compilers,\nand this caused a problem when using the Windows compiler.\nThis has been fixed by defining the type bool inside the\n``compare_c/det_by_minor.c`` source code.\n\n12-17\n=====\nThere was a mistake in a check for a valid op code in the\nfile ``hash_code.hpp`` .\nThis mistake could generate a C++ assertion with an unknown error source.\nIt has been fixed.\n\n12-15\n=====\n\n#. Advance version number from ``20121120`` to ``20121215`` .\n   Note that the CppAD version number no longer automatically advances with the\n   date and is rather chosen to advance to the current date.\n#. The :ref:`cmake-name` installation was putting the ``cppad.pc``\n   :ref:`pkgconfig-name` file in\n\n        ``cppad_prefix`` / *cmake_install_datadir* / ``cppad.pc``\n\n    This has been fixed and is now\n\n        ``cppad_prefix`` / *cmake_install_datadir* / ``pkgconfig/cppad.pc``\n\n#. The :ref:`pkgconfig-name` documentation has been improved.\n#. The command for running the\n   :ref:`adolc examples<adolc@Examples>` and\n   :ref:`eigen examples<eigen@Examples>`\n   was fixed\n   (changed from ``make check`` to ``make check_example`` ).\n\n12-14\n=====\n\n#. Fix the old :ref:`configure-name` so that it works with the\n   new ``cppad.pc`` .\n#. Fix the old installation\n   --with_Documentation option\n   (it was attempting to copy from the wrong directory).\n\n12-13\n=====\n\n#. Include documentation for :ref:`ipopt-name`\n#. Fix the ``cppad.pc`` :ref:`pkgconfig-name` file\n   so that it includes the necessary libraries and include files\n   when :ref:`cmake@include_ipopt` is specified; see\n   :ref:`pkgconfig-name` .\n\n11-28\n=====\nUpdate the :ref:`wish_list-name` :\n\n#. Remove Microsoft compiler warning item that has been fixed.\n#. Remove faster sparse set operations item that was completed using\n   ``cppad_sparse_list`` (not part of user API).\n#. Remove :ref:`cmake-name` items that have been completed.\n#. Remove :ref:`CondExp-name` items related to using\n   ``AD< std::complex<double> >`` types because it is better to use\n   ``std::complex< AD<double> >`` .\n#. Remove :ref:`thread_alloc-name` memory chunk item that has been completed.\n#. Remove :ref:`VecAD-name` item about slicing from floating point type to ``int``\n   (not important).\n#. Change an Ipopt item to a :ref:`cppad_ipopt_nlp-name`\n   (which was removed because ``cppad_ipopt_nlp`` is now deprecated).\n   Add new ``cppad_ipopt_sum`` item to the wish list.\n   (This has been removed because :ref:`checkpointing<chkpoint_one-name>`\n   can now be used for this purpose.)\n#. Add new ``atomic_one`` :ref:`wish_list-name` item (since removed).\n\n11-21\n=====\n\n#. Fix the\n   :ref:`download@Version` number in link to the\n   current download files.\n#. Change the\n   ``subversion`` download instructions to use\n   the ``export`` instead of ``checkout`` command.\n   This avoids downloading the source code control files.\n\n11-20\n=====\n\n#. The ``cmake`` variables\n   ``cmake_install_includedir`` and\n   ``cmake_install_libdir``\n   were changed to\n   :ref:`cmake@cmake_install_includedirs` and\n   :ref:`cmake@cmake_install_libdirs`\n   to signify the fact that they can now be a list of directories.\n#. Advance version number to ``cppad-20121120`` .\n\n11-17\n=====\n\n#. Finish documenting the new :ref:`cmake-name` configuration instructions\n   and deprecate the old :ref:`unix<configure-name>` instructions.\n#. Change the specifications for\n   :ref:`multi_thread@CPPAD_MAX_NUM_THREADS`\n   to allow for a value of one.\n   This enables one to have more tapes during a program execution.\n#. Include the :ref:`C versus C++<compare_c-name>` speed comparison\n   in the :ref:`cmake-name` build.\n\n11-16\n=====\nFix a warning that occurred in :ref:`Rosen34-name`\nwhen it was compiled with the preprocessor symbol ``NDEBUG`` defined.\n\n11-14\n=====\nAdvanced the CppAD version to ``cppad-20121114`` .\n\n#. Started documenting the\n   :ref:`cmake-name` configuration procedure during installation.\n   This included factoring out the\n   :ref:`download-name` procedure as a separate section\n   so that the same download instruction also apply to the\n   :ref:`unix<configure-name>` install procedure.\n\n#. Changed\n   :ref:`example/compare_change.cpp<compare_change.cpp-name>`\n   to just return true when ``NDEBUG`` is defined.\n   This enabled all the tests in the\n   ``example`` directory to be compiled\n   with ``NDEBUG`` is defined and to pass.\n\n#. In the case where ``NDEBUG`` is defined,\n   removed detection of ``nan`` during forward mode from\n   ``test_more/forward.cpp%`` .\n   This enables all the tests in the\n   ``test_more`` directory to be compiled\n   with ``NDEBUG`` is defined and to pass.\n\n#. Started a wish list for CppAD's use of :ref:`cmake-name` .\n   The wish list items were completed and removed.\n\n11-09\n=====\nThe :ref:`team_pthread.cpp-name` was failing to link on Ubuntu 12.04\nbecause the libraries were not at the end of the link line.\nThis has been  fixed.\n\n11-06\n=====\n\n#. Remove some remaining references to the old licenses CPL-1.0 and GPL-2.0;\n   see :ref:`2012@mm-dd@10-24` .\n#. Remove out of date Microsoft project files from the distribution.\n   The build system is being converted to use\n   `cmake <https://cmake.org/>`_ which builds these files automatically\n   and thereby keeps them up to date.\n   This feature is not yet documented, but one can inspect the file\n   ``bin/run_cmake.sh`` to see how to use ``cmake`` with CppAD.\n\n11-04\n=====\nAdd missing return value to the example ``base_alloc``\n:ref:`base_alloc.hpp@CondExpOp` function.\nThis has been fixed and the comments for this example have been improved.\n\n10-31\n=====\nThe CppAD profiling was not compiling\nthe ``speed/src/\\*.cpp`` files with the profiling flag.\nThis has been changes\n(only for the profiling speed test).\n\n10-30\n=====\nThe :ref:`configure@fadbad_dir` directory install instructions\nwere changed.\nTo be specific, ``FADBAD++`` was changed to ``include/FADBAD++`` .\nThis makes it more like the other optional packages.\n\n10-25\n=====\nThe test :ref:`runge45_1.cpp-name` was failing when using gcc-4.5.2.\nThis has been fixed by properly defining ``fabs`` ( *x* ) where\n*x* is a double (without the ``std`` in front).\n\n10-24\n=====\nChange the CppAD licenses from CPL-1.0 and GPL-2.0 to\nEPL-1.0 and GPL-3.0.\n\n10-12\n=====\n\n#. Change all the multiple levels of AD examples to\n   start with :ref:`mul_level-name` .\n   To be specific, move\n   ``taylor_ode.cpp`` to :ref:`mul_level_ode.cpp-name` and\n   ``taylor_ode_adolc.cpp`` to :ref:`mul_level_adolc_ode.cpp-name` .\n#. Add :ref:`taylor_ode.cpp-name` as a example of Taylor's method for solving ODEs,\n   (:ref:`mul_level_ode.cpp-name` is an application of this method\n   to multi-level AD.)\n\n10-04\n=====\n\n#. Change :ref:`speed_main-name` so that it outputs small rates (less than 1000)\n   with two decimal points of precision (instead of as integers).\n   In addition, flush result for each size when it finishes to give user\n   more feedback about how things are progressing.\n#. Add the optional :ref:`time_test@test_size` argument\n   to the ``time_test`` routine.\n\n10-03\n=====\nChange the ``hold_memory`` speed to option to just\n:ref:`speed_main@Global Options@memory` .\nIn addition, in the speed test output, include all of the options\nthat are present in the output variable name;\nsee :ref:`speed_main@Speed Results` .\n\n10-02\n=====\nFix another problem with Debian's ``/bin/sh`` shell executing\n``example/multi_thread/test.sh`` ; see :ref:`2012@mm-dd@03-17`\n\n09-24\n=====\nImprove documentation for the\n:ref:`atomic_one-name`\n:ref:`atomic_one@rev_hes_sparse`\nargument\n:ref:`atomic_one@rev_hes_sparse@v` .\nIn addition,\nadd sparsity calculations to the old_reciprocal.cpp example.\n\n09-11\n=====\nAdd ``user_simple.cpp`` ,\na simpler :ref:`atomic_one-name` example.\n\n08-05\n=====\n\n#. A new type was added for the internal representation of\n   :ref:`glossary@Sparsity Pattern@Vector of Sets`\n   sparsity patterns; see the configure\n   ``--with-sparse_option`` (since removed).\n#. A new speed test, :ref:`compare_c-name` , compares the speed of the same\n   source code compiled with C and C++.\n\n07-30\n=====\n\n#. The :ref:`CppAD_vector@clear` function was added to\n   ``CppAD::vector`` .\n#. Warning !!:\n   The ``CppAD::vector`` :ref:`CppAD_vector@resize` specifications\n   were changed so that *x* . ``resize`` (0) no longer frees\n   the corresponding memory (use *x* . ``clear`` () instead).\n#. Fix a bug in error checking during :ref:`optimize-name` procedure\n   had the following ``valgrind`` symptom during the\n   ``optimize.cpp`` example:\n   ::\n\n        ==6344== Conditional jump or move depends on uninitialised value(s)\n\n#. Fix mistake in old_tan.cpp where ``w[2] = 0``\n   was missing before the call\n   ::\n\n        dw    = F.Reverse(1, w);\n\n07-08\n=====\n\n#. Improve the documentation for :ref:`pow-name` and :ref:`pow_int-name` .\n#. Change all the example section names to be same as corresponding file names;\n   e.g. change ``vectorBool.cpp`` to :ref:`vector_bool.cpp-name`\n   for the example ``example/utility/vector_bool.cpp`` .\n\n07-07\n=====\nAdd the ``CPPAD_TAPE_ID_TYPE`` argument to the\n:ref:`configure@Configure` command line.\n\n07-05\n=====\nDeprecate ``CPPAD_TEST_VECTOR`` and use\n:ref:`CPPAD_TESTVECTOR<testvector-name>` in its place.\nThis fixes a problem introduced by changes on 07-03 whereby code that\nused ``CPPAD_TEST_VECTOR`` would no longer work.\n\n07-04\n=====\n\n#. Replace the requirement that the :ref:`SimpleVector-name`\n   :ref:`SimpleVector@size` function return a ``size_t`` value to\n   the requirement that it can be converted to a ``size_t`` value.\n#. The :ref:`--with-eigenvector<configure@Configure>` option was\n   added to the ``configure`` command line.\n\n07-03\n=====\nFix bug in :ref:`atomic_one-name` functions identification of variables\nthat caused old_tan.cpp to fail with error message\n::\n\n    Error detected by false result for\n    y_taddr > 0\n    at line 262 in the file cppad/local/dependent.hpp\n\n07-02\n=====\nAdd  ``eigen_plugin.hpp`` so that\nan Eigen vector can be used as a\n:ref:`SimpleVector-name` .\nThis has since been removed; see\n:ref:`2017-05-11<2017@mm-dd@05-12>` .\n\n07-01\n=====\n\n.. _Using custom scalar types: https://\n    libeigen.gitlab.io/eigen/docs-nightly/TopicCustomizing_CustomScalar.html\n\n#. Change :ref:`cppad_eigen.hpp-name`\n   to match new specifications and example in eigen help files on\n   `Using custom scalar types`_ .\n\n#. Fix bug whereby a newly constructed :ref:`VecAD-name` object was a\n   :ref:`con_dyn_var@Variable` (instead of a parameter) directly after construction\n   (when no previous :ref:`ADFun<fun_construct-name>` object had been created).\n#. Change a ``ok != a == 0.`` to ``ok &= a == 0.`` in\n   the example :ref:`ad_ctor.cpp-name` .\n#. Add the :ref:`eigen_array.cpp-name` example.\n\n06-17\n=====\n\n#. Move :ref:`epsilon-name` to :ref:`numeric_limits-name`\n   and add the functions ``min`` and ``max``\n   in *CppAD::numeric_limits<* ``Type`` > .\n#. Convert use of the deprecated :ref:`epsilon-name` in examples\n   to use of ``numeric_limits`` :ref:`numeric_limits@epsilon` .\n#. Complete :ref:`cppad_eigen.hpp-name` interface to\n   ``lowest`` and ``highest`` functions for\n   all non-complex AD types.\n\n06-16\n=====\nAdd the example :ref:`eigen_det.cpp-name` that uses the\n`Eigen <https://libeigen.gitlab.io/>`_\nlinear algebra package.\n\n06-15\n=====\nInclude the :ref:`base_adolc.hpp-name` as\n``<cppad/example/base_adolc.hpp>`` under the\n:ref:`configure@prefix_dir` directory.\n\n06-12\n=====\nIncrease the size and of the\n:ref:`sparse Jacobian speed tests<link_sparse_jacobian-name>` .\n\n06-10\n=====\n\n#. Add the :ref:`hold_memory<speed_main@Global Options@memory>` option\n   to the speed test main program.\n   This was changed to just ``memory`` ; see\n   :ref:`2012@mm-dd@10-03` .\n#. In :ref:`cppad_sparse_jacobian.cpp-name` ,\n   change ``USE_BOOL_SPARSITY`` from true to false.\n   In addition, change the number of non-zeros per row from about approximately\n   three to approximately ten.\n\n06-09\n=====\nChange :ref:`adolc_sparse_jacobian.cpp-name` to use the sparse adolc\nJacobian (instead of the full Jacobian) driver.\nThis was also done for :ref:`adolc_sparse_hessian.cpp-name` ,\nbut there is a problem with the test that is being investigated.\n\n06-08\n=====\nImplement the matrix multiply speed test :ref:`link_mat_mul-name` for all packages\n(there is a problem with the :ref:`fadbad_mat_mul.cpp-name`\nimplementation and it is being looked into).\n\n06-07\n=====\nMake all the speed tests implementations (for the specific packages)\nuniform by having a Specification and Implementation heading and similar\nindexing. For example, see\n:ref:`adolc_det_minor.cpp-name` ,\n:ref:`cppad_det_minor.cpp-name` ,\n:ref:`double_det_minor.cpp-name` ,\n:ref:`fadbad_det_minor.cpp-name` , and\n:ref:`sacado_det_minor.cpp-name` .\n\n06-05\n=====\nAdd the :ref:`sacado_ode.cpp-name` speed test.\n\n06-04\n=====\n\n#. The specifications for :ref:`Runge45-name` where changes so that\n   it uses the ``fabs`` function instead of the ``<`` operation.\n   This enabled the a more precise statement about its\n   :ref:`Runge45@Operation Sequence` .\n#. The ``fabs`` function as added to the CppAD standard math library\n   (see :ref:`abs-name` )\n   and the :ref:`base type requirements<base_std_math-name>` .\n   This enables one to write code that works with ``AD<double>`` as\n   well as ``double`` without having to define ``abs`` for\n   ``double`` arguments\n   (and similarly for ``float`` ).\n#. Add the :ref:`adolc_ode.cpp-name` and :ref:`fadbad_ode.cpp-name` speed tests\n   (and edit the :ref:`cppad_ode.cpp-name` test).\n\n06-03\n=====\n\n#. The ``CppAD::vector`` class was extended to allow assignment\n   with the target of size zero and the source of non-zero size;\n   see :ref:`CppAD_vector@Assignment@Check Size` .\n#. A memory leak and a bug in ``cppad_mat_mul.cpp`` were fixed\n   (the bug was related to the change to ``CppAD::vector`` above).\n\n06-02\n=====\n\n#. Remove the deprecated symbol\n   ``CppADvector`` from the\n   :ref:`det_by_lu-name` speed test source code :ref:`det_by_lu.hpp-name` .\n#. Include :ref:`memory_leak-name` in the list of\n   :ref:`deprecated-name` features.\n#. Change the :ref:`ode_evaluate-name` speed test utility so that its\n   :ref:`operation sequence<glossary@Operation@Sequence>`\n   does not depend on the repetition; see\n   :ref:`ode_evaluate@p@p == 0` in its documentation.\n#. Use same argument for taping and derivative evaluation when\n   ``retape`` speed test option is true.\n#. Implement the *retape* == ``false`` option\n   in :ref:`cppad_ode.cpp-name` .\n#. Have\n   :ref:`cppad_det_lu.cpp-name` ,\n   :ref:`cppad_det_minor.cpp-name` ,\n   and :ref:`cppad_poly.cpp-name` ,\n   return false when one of the specified options is not supported.\n   Do the same for\n   *package* _ *test* . ``cpp`` for *package* equal to\n   ``adolc`` , ``fadbad`` , and ``sacado`` and\n   for *test* equal to\n   ``det_lu`` , ``det_minor`` , ``poly`` .\n\n06-01\n=====\nChange\n:ref:`cppad_sparse_hessian.cpp-name` and\n:ref:`cppad_sparse_jacobian.cpp-name`\nto use\nthe *row* , *col* interface to :ref:`sparse_hessian-name` .\nIn addition, implement the speed test\n``retape`` speed test option for these tests.\n\n05-31\n=====\nAdd the ``cppad_print_optimize`` routine to so that the corresponding\ncode does not need to be reproduced for all the\n:ref:`speed_cppad-name` tests.\nIn addition, during CppAD speed tests,\nprint out the optimization results for each test size.\n\n05-30\n=====\nChange specifications for\n:ref:`link_sparse_hessian-name` so that the row and column indices are\ninputs (instead of being chosen randomly by the test for each repetition).\nThis enables use of the\n``retape`` speed test option\nduring sparse Hessian speed tests.\n\n05-29\n=====\nAdd :ref:`index_sort-name` to the general purpose template :ref:`utilities<utility-name>`\nso that it can be used by the implementations of\n:ref:`link_sparse_jacobian-name` and :ref:`link_sparse_hessian-name` .\n\n05-27\n=====\nSplit the sparse Jacobian and Hessian test function the separate function\n:ref:`sparse_jac_fun-name` and :ref:`sparse_hes_fun-name`\n(do not use sparse Hessian for both).\nIn addition, change row and column indices from *i*\nand *j* to *row* and *col* .\n\n05-24\n=====\nMerged in changes from ``branches/sparse`` :\n\n#. A new interface was added to\n   :ref:`sparse_jacobian-name` and :ref:`sparse_hessian-name` .\n   This interface\n   returns a sparse representation of the corresponding matrices\n   using row and column index vectors.\n#. The examples\n   :ref:`sparse_jacobian.cpp-name` and\n   :ref:`sparse_hessian.cpp-name`  were improved\n   and extended to include the new interface.\n#. The definition of an\n   :ref:`glossary@AD Function` was improved\n   to include definition of the corresponding *n* and *m* .\n\n04-19\n=====\nThe *boost_dir*\nconfigure command line value has been changed to be the corresponding\nprefix during the installation of boost.\nTo be specific, it used to be that\n*boost_dir* / *boost* was the boost include directory,\nnow *boost_dir* / *include* is the boost include directory.\nThis make it the same as the other directory arguments on the configure\ncommand line.\nIn addition, it fixes some bugs in the detection of the boost\nmulti-threading library.\n\n04-18\n=====\nAdd documentation and testing for not using :ref:`free_all<ta_free_all-name>` and\n:ref:`atomic_one clear<atomic_one@clear>` while in\n:ref:`parallel<ta_in_parallel-name>` mode.\n\n04-17\n=====\nFix bug when using :ref:`atomic_one-name` functions with\n:ref:`multi_threading<multi_thread-name>` .\n\n04-10\n=====\nAdd control of the\n:ref:`configure@max_num_threads` argument\nto the unix\n:ref:`configure@Configure` command.\n\n04-06\n=====\n\n#. A change was made to the way that the tapes were managed to reduce\n   false sharing during :ref:`multi-threading<multi_thread-name>` .\n   Because of this change, it is now suggest that the user call\n   :ref:`parallel_ad-name` after the multi-threading section of the program.\n#. The routine :ref:`ta_free_all-name` was created to make it easier\n   to manage memory and the routine :ref:`memory_leak-name`\n   was deprecated.\n#. Add the ``-lteuchos`` flag to the link line for the\n   :ref:`speed_sacado-name` tests.\n   (This was not necessary for ``trilinos-10.8.3``\n   but is necessary for ``trilinos-10.10.1`` )\n\n04-05\n=====\nThe restriction was added that\n:ref:`parallel_ad-name` cannot be called while a tape is being recorded.\nThis was necessary inorder to initialize some new statics in the tape.\n\n04-01\n=====\nFixed a race condition when using CppAD with\n:ref:`multi-threading<multi_thread-name>` .\nThis has been fixed and the error message below no longer occurs.\nSuppose that you ran the CppAD\n:ref:`configure@Configure` command in the ``work``\ndirectory.\nIf you then edited the file ``work/multi_thread/makefile``\nand changed\n::\n\n    # AM_CXXFLAGS     = -g $(CXX_FLAGS)\n    AM_CXXFLAGS = -DNDEBUG -O2 $(CXX_FLAGS)\n\nto::\n\n    AM_CXXFLAGS     = -g $(CXX_FLAGS)\n    # AM_CXXFLAGS = -DNDEBUG -O2 $(CXX_FLAGS)\n\nand then executed the commands\n::\n\n    make clean\n    make pthread_test\n    valgrind --tool=helgrind ./pthread_test get_started\n\nThe following error message would result:\n\n| |tab| ... ``snip ...``\n| ==7041== ``Possible data race during write of size 4 at 0x8077460 by thread`` #1\n| ==7041== ``at 0x804FE23: CppAD::AD<double>::tape_new`` () ( ``tape_link.hpp:221`` )\n| ... ``snip ...``\n\n03-27\n=====\nReduce the amount of memory allocation and copying of information during\na :ref:`Dependent-name` operation or an ``ADFun``\n:ref:`fun_construct@Sequence Constructor` .\n\n03-26\n=====\nCalling ``taylor_capacity`` , with to with capacity equal to zero,\nwas not\n:ref:`capacity_order@c@Freeing Memory` .\nThis has been fixed.\n\n03-23\n=====\n\n#. Improve, the multi-threading examples\n   :ref:`openmp_get_started.cpp-name` ,\n   :ref:`bthread_get_started.cpp-name` , and\n   :ref:`pthread_get_started.cpp-name` .\n   This includes separating generic code that can be used for all applications\n   from problem specific code.\n#. Add initialization of statics in\n   :ref:`parallel_ad@CheckSimpleVector`\n   during ``parallel_ad`` call.\n   These statics are required to use\n   :ref:`CppAD::vector<CppAD_vector-name>` .\n#. Add a debugging check to make sure :ref:`CheckSimpleVector-name`\n   is initialized in sequential mode.\n\n03-21\n=====\nFix an incorrect error check in ``thread_alloc``\nthat did not allow :ref:`ta_return_memory-name`\nto return memory in sequential execution mode that was allocated by a\ndifferent thread during parallel execution.\n\n03-17\n=====\nDebian recently converted the default shell corresponding to\n``/bin/sh`` to  ``dash``\n(which caused ``example/multi_thread/test.sh`` to fail).\nThis has been fixed.\nIn general, Debian's policy is that ``bin/sh`` will be a\n`Posix Shell <https://pubs.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html>`_.\n\n03-11\n=====\nThere was a bug in :ref:`thread_alloc-name` where extra memory was held\nonto even if :ref:`hold_memory<ta_hold_memory-name>` was never called\nand only one thread was used by the program.  This caused\n\n    ``valgrind --leak-check`` = ``full --show-reachable`` = ``yes``\n\nto generate an error message.\nIf :ref:`multiple threads<multi_thread-name>` are used,\none should free this\n:ref:`ta_free_available@Purpose@Extra Memory`\nfor threads other than thread zero.\nIf ``hold_memory`` is used,\none should call :ref:`free_available<ta_free_available-name>` for all threads.\n\n03-03\n=====\n\n#. Add the examples\n   :ref:`openmp_get_started.cpp-name` ,\n   :ref:`bthread_get_started.cpp-name`\n   and :ref:`pthread_get_started.cpp-name` .\n#. Fix bug in finding boost multi-threading library\n   (due to fact that *boost_dir*\n   is not the prefix during the boost installation).\n\n03-02\n=====\n\n#. Change the name ``get_started.cpp`` to :ref:`team_example.cpp-name`\n#. The multi-threading ``team_example.cpp`` example was changed to use\n   :math:`f(x) = \\sqrt{ x^2 }` instead of the function\n   :math:`{\\rm atan2} [ \\sin(x) , \\cos (x) ]`\n   (both functions should behave like the identity function :math:`f(x) = x`).\n   This enabled the removal of ``example/multi_thread/arc_tan.cpp`` .\n#. In :ref:`team_example.cpp-name` check that all of the threads\n   pass their individual test; i.e. ``work_all_`` [ *thread_num* ]. *ok*\n   is true for all *thread_num* .\n\n02-11\n=====\n\n#. The requirements in\n   :ref:`base_member-name` were missing from the :ref:`base_require-name` documentation.\n   In addition,\n   the :ref:`base_require.cpp-name` example has been added.\n\nThe specifications for :ref:`memory_leak-name` where changes so that\ncalling routine specifies the amount of static memory to add.\nIn addition,\nit is now possible to call\n``memory_leak`` when :ref:`num_threads<ta_num_threads-name>`\nis greater than one\n(still can't be in parallel mode).\n\n02-10\n=====\n\n#. Add the missing Base class requirements in\n   the entire :ref:`base_member-name` section\n   and under the :ref:`base_require@Output Operator`\n   in the :ref:`base_require-name` section.\n#. Add the :ref:`base_alloc.hpp-name` example.\n\n02-09\n=====\n\n#. Add the *set_static* to :ref:`memory_leak-name` .\n   This is necessary for testing base types that allocate memory\n   for each element.\n#. Fix memory allocation bug in ``cppad/local/pod_vector.hpp``\n   when each element of the :ref:`Base<base_require-name>` type allocated memory.\n\n01-30\n=====\nMake another attempt to fix linking with boost threads where the wrong\nversion of the library is in the system include directory; i.e.,\nto have *boost_dir* override the default\nlibrary.\n\n01-27\n=====\nThere were some problems with\n:ref:`configure's<configure@Configure>` automatic detection of\nthe boost multi-threading library.\nThese have been fixed.\n\n01-24\n=====\nIt used to be that :ref:`thread_alloc-name` did not hold onto memory\nwhen *num_threads* was one in the previous call to\n:ref:`parallel_setup<ta_parallel_setup-name>` .\nHolding onto memory is now controlled by the separate routine\n:ref:`hold_memory<ta_hold_memory-name>` .\nThis give the user more control over the memory allocator\nand the ability to obtain a speed up even\nwhen there is only one thread.\nTo convert old code to the new interface, after each call to\n\n    ``thread_alloc::parallel_setup`` ( *num_threads* , *in_parallel* , *thread_num* );\n\nput the following call\n\n    ``thread_alloc::hold_memory`` ( *num_threads*  > 1);\n\n01-23\n=====\nChange variable notation and use :ref:`optimize-name` in\n:ref:`mul_level.cpp-name` .\n\n01-20\n=====\n\n#. Add the example :ref:`change_param.cpp-name`\n   which shows how to compute derivatives of functions that have\n   parameters that change, but derivatives are not computed\n   with respect to these parameters.\n#. The documentation for machine :ref:`epsilon-name`\n   has been improved.\n   (The fact that it can be used for *Base* types was missing.)\n\n01-19\n=====\n\n#. In cases where ``test.sh`` is trivial,\n   put its operations in corresponding makefile.\n#. Fix problem compiling ``cppad/speed/sparse_evaluate.hpp``\n   under gcc on Fedora 17.\n#. Run ``example/multi_thread/test.sh`` from source directory\n   (no need to copy to build directory).\n\n01-16\n=====\nThe test program ``example/multi_thread/test.sh`` failed if the\nopenmp_flags not present in the\n``configure`` command.\nThis has been fixed.\nIn addition, this ``test.sh`` has been made faster by cycling through\nthe available threading systems instead of doing every system for every\ntest.\n\n01-15\n=====\nFix ``make test`` so it works when\n:ref:`configure@Configure` is run in the distribution directory\n``cppad-`` *yyyymmdd*\n(not just when it is run in a different directory).\n\n01-12\n=====\nThe ``-lpthread`` library was missing from the\n:ref:`multi_thread-name` test program linker command.\nThis has been fixed.\n\n01-07\n=====\n\n#. A duplicated code block beginning with\n   ::\n\n        if( fabs( fcur ) <= epsilon_ )\n\n    was removed from the routine ``multi_newton_worker`` .\n\n#. The distance between solutions that are joined to one solution\n   has been corrected from :math:`(b - a) / (2 n )` to\n   :math:`(b - a) / n`; see\n   :ref:`multi_newton_run@xout` .\n   The correction was in the file :ref:`multi_newton.cpp-name` where\n   ``sub_length_ / 2`` was change to ``sub_length_`` .\n\n01-02\n=====\n\n#. The :ref:`thread_alloc-name` memory allocator was changed to avoid\n   certain false sharing situations\n   (cases where two different thread were changing and using memory\n   that is on the same page of cache).\n   On one tests machine, the execution time for the 32 thread case for the test\n   ::\n\n        ./openmp_test multi_newton 1 32 1000 4800 10 true\n\n    improved from  0.0302 seconds to 0.0135 seconds.\n\n#. There was a problem with the correctness test section of the\n   :ref:`multi_newton_time-name` test.\n   The convergence criteria, and correctness criteria,\n   needed to be scaled by the largest argument values.\n   This was a problem with over a hundred zeros were included in the test\n   (and the largest argument value was :math:`100 \\pi` or more).\n\n#. There was a problem with the way that\n   :ref:`multi_newton_takedown-name`\n   joined two solutions into one.\n   It is possible that one of the solutions that needs to be joined is on\n   the  boundary and very close to a solution in the next (or previous interval)\n   that is not on the  boundary. In this case,\n   the one with the smaller function value is chosen.\n\nfor the previous\n\n{xrst_end 2012}\n"
  },
  {
    "path": "appendix/whats_new/2013.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-25 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin 2013 app}\n{xrst_spell\n    algo\n    autotools\n    cout\n    ctor\n    impl\n    ip\n    src\n    struct\n    usead\n}\n\nRelease Notes for 2013\n######################\n\nmm-dd\n*****\n\n12-29\n=====\n\n#. The include file\n   :ref:`cppad_eigen.hpp-name` now automatically includes ``cppad.hpp`` .\n#. There was a problem with this automation\n   when ``eigen`` was used for the cppad :ref:`testvector-name` .\n   This has been fixed.\n#. There was a problem with deprecated :ref:`configure-name`\n   (created when optional implicit constructor from any type was added).\n   This has been fixed by adding the\n   ``--with-implicit_ctor`` option\n   (later removed on :ref:`2017-02-10<2017@mm-dd@02-10>` .)\n\n12-27\n=====\nThe constructor from an arbitrary type to ``AD`` < *Base* > was\nimplicit, but there was no specification to this effect.\nThe caused problems when using CppAD with\n:ref:`eigen 3.2<eigen-name>` (scheduled to be fixed in 3.3).\nThe default for this constructor has been changed to be\n:ref:`ad_ctor@x@explicit` .\nIn addition, other\n:ref:`ad_ctor@x@implicit` constructors\nare now listed in the documentation.\n\nIf you get a compiler error on an constructor / assignment of the form\n\n    ``AD`` < *Base* > ``x`` = *y*\n\n(that used to work) try changing the constructor call to\n\n    ``AD`` < *Base* >( *y*  )\n\nA deprecated alternative is to make this constructor implicit using the\ncmake ``cppad_deprecated``\noption during the install procedure.\n\n12-26\n=====\nDocument fact that monthly versions\nof the CppAD compressed tar file last till the end of the year.\nThis is no longer the case; see\n:ref:`2018@mm-dd@05-20` in whats new for 2018.\n\n12-24\n=====\nThe interface to :ref:`eigen<cppad_eigen.hpp-name>` defined a function\n\n    ``NumTraits< CppAD::AD<`` *Base* > >:: ``dummy_epsilon`` ()\n\nthat should have been named ``dummy_precision()`` .\nThis has been fixed.\n\n11-27\n=====\n\n#. Fix bug when using :ref:`optimize-name` with an :ref:`ADFun-name` object containing\n   the :ref:`sign-name` function.\n#. Add ``atomic_two_norm_sq.cpp`` , an atomic function example\n   with domain dimension two and range dimension one.\n\n11-13\n=====\nIt used to be that one had to define the ``std::set`` version of\n:ref:`atomic_two_rev_sparse_jac-name` for each atomic function that was\npart of an :ref:`ADFun-name` object that was :ref:`optimized<optimize-name>` .\nNow the current\n:ref:`atomic_two_option@atomic_sparsity` setting is used\nto determine if the ``bool`` or ``std::set`` version of\n``rev_sparse_jac`` is used by the optimization process.\n\n11-12\n=====\nError detection and reporting (when ``NDEBUG`` is not defined)\nhas been added for the following case:\nUsing :ref:`optimize-name`\nwith :ref:`atomic_two-name` functions that have not defined\n:ref:`optimize@Atomic Functions@rev_sparse_jac` .\n\n10-29\n=====\nThe :ref:`optimization<CondExp@Optimize>`\nnow handles nested conditional expressions.\nFor example, give the code\n::\n\n    x = CondExpLt(left_x, right_x, true_x, false_x)\n    y = CondExpGt(left_y, right_y, true_y, false_y)\n    z = CondExpEq(left_z, right_z, x, y)\n\nonly two of the conditional expressions will be evaluated\n(one will be skipped depending on the result of ``left_z == right_z`` ).\nFor more details, see :ref:`optimize_nest_conditional.cpp-name` .\n\n10-23\n=====\n\n#. Fix a bug in the optimization of calls to :ref:`atomic-name` functions.\n   This bug existed before recent change to optimizing conditional expressions.\n   This required adding the\n   :ref:`RevSparseJac@dependency` argument to the\n   reverse Jacobian sparsity pattern calculation.\n#. Fix the deprecated autotools install (see :ref:`configure-name` )\n   which was broken by the changes on 10-22.\n   To be specific, the\n   example for :ref:`number_skip-name` was not being included.\n\n10-22\n=====\n\n#. Add :ref:`optimization<optimize-name>` of conditional expressions; see\n   :ref:`CondExp<CondExp@Optimize>` .\n#. Add a phantom argument at the beginning of the operations sequence;\n   :ref:`fun_property@size_op_arg` and :ref:`fun_property.cpp-name` .\n   (This helps with the optimization mentioned above.)\n#. Add the function :ref:`number_skip-name` to measure how much optimization\n   of the conditional expressions there is.\n\n10-16\n=====\nFix bug in :ref:`wish_list@Tracing` :ref:`atomic-name` functions.\n\n10-15\n=====\nThe documentation for the class\n:ref:`CppAD_vector@vectorBool` was improved.\n\n10-14\n=====\nThe script :ref:`get_adolc.sh-name` was added\n(for downloading and installing\n`ADOL-C <https://github.com/coin-or/ADOL-C>`_) in the\n``build`` directory.\nNote that this local install of Adolc requires ColPack; see\n:ref:`get_colpack.sh-name` .\nIn addition, the requirement that ColPack and Adolc are installed\nwith the same prefix was added.\n\n10-13\n=====\nMake sure that all of the\n:ref:`preprocessor-name` symbols\nthat are not part of the CppAD API, are undefined when the\n``<cppad/cppad.hpp>`` file concludes.\n\n10-12\n=====\n\n#. Change ``get_eigen.sh`` so that it will reuse install information\n   when it is present.\n   In addition document reuse for\n   ``get_eigen.sh`` ,\n   :ref:`get_ipopt.sh-name` , and\n   :ref:`get_sacado.sh-name` .\n#. Fix following ``g++`` error on OSX system:\n   ::\n\n        error: no match for 'operator|=' (operand types are\n        'std::vector<bool>::reference {aka std::_Bit_reference}' and 'bool')\n        Check[i * n + j] |= F2[i * n + k] & r[ k * n + j];\n        ^\n\n09-20\n=====\n\n#. Add lines for :ref:`atomic_two-name` function documentation\n   to both the definition and use of each operation.\n   This required adding sub-headings in the example usages\n   corresponding to the function documentation sections.\n   For example; see\n   atomic forward examples.\n#. Improve the documentation for :ref:`atomic_two_clear-name`\n   and remove its use from the\n   :ref:`atomic_base examples<atomic_two@Examples>`\n   (because it is not needed).\n\n09-19\n=====\nAdd links from the :ref:`atomic_two-name` functions documentation\nto the corresponding examples.\nThis required adding headings in the examples that\ncorrespond to the function documentation sections.\nFor example; see\natomic forward examples.\n\n09-18\n=====\n\n#. A segmentation fault would occur if\n   an :ref:`ADFun-name` object used an :ref:`atomic-name`\n   function that had been deleted.\n   This has been fixed so that when ``NDEBUG`` is not defined,\n   an error message is generated.\n#. A mistake in the documentation for\n   :ref:`CppAD_vector@Memory and Parallel Mode`\n   has been fixed.\n   This corresponds to the change in the specifications for\n   :ref:`CppAD::vector::resize<CppAD_vector@resize>` made on\n   :ref:`2012-07-30<2012@mm-dd@07-30>`\n#. There was a bug during the\n   :ref:`checking for nan<check_for_nan-name>` during\n   :ref:`reverse-name` mode.\n   This has been fixed.\n#. It appears, from inspecting the Ipopt source file\n   ``Ipopt/src/Algorithm/IpIpoptAlg.cpp`` that the option ``sb``\n   to ``yes`` suppress the printing of the Ipopt banner.\n   The Ipopt examples and tests have been changed to use this option\n   (although it is not in the ipopt documentation).\n#. Fix the a typo in the documentation for ``ipopt_solve``\n   :ref:`ipopt_solve@options@Integer` options\n   (``Numeric`` was changed to ``Integer`` ).\n\n09-07\n=====\nThere was a bug in the cumulative sum operator\n(which is used by :ref:`optimize-name` )\nfor :ref:`Forward-name` orders greater than zero.\nThis was detected by the :ref:`checkpoint<chkpoint_one-name>` tests\nwhen ``optimize`` was used to make the\ncheckpoint functions faster.\nThe bug has been fixed and the checkpoint functions now use\noptimize (and hence should be faster).\n\n08-12\n=====\n\n#. The ability to turn on and off checking for :ref:`nan-name` in\n   :ref:`Forward-name` mode results has been added; see :ref:`check_for_nan-name` .\n#. Use this option to remove the need to handle ``nan`` as a special\n   case in :ref:`checkpoint<chkpoint_one-name>` functions that\n   :ref:`optimize@Atomic Functions` in within\n   another function is optimized.\n#. Check :ref:`reverse<reverse_any-name>`  mode results when\n   :ref:`check_for_nan-name` is true.\n   (It used to be the case that only :ref:`forward<forward_order-name>` results\n   were checked for ``nan`` .)\n\n08-11\n=====\nIf an :ref:`atomic-name` function had arguments that did not affect\nthe final dependent variables in *f* ,\n:ref:`f.optimize()<optimize-name>` would fail.\nThis has been fixed.\nIn addition, documentation about using ``optimize``\nwith :ref:`optimize@Atomic Functions` has been added.\n\n08-06\n=====\nFix a case where the test ``test_more/num_limits.cpp`` failed because\n::\n\n    double inf   = std::numeric_limits<double>::infinity();\n    double check = std::complex<double>(inf) / std::complex<float>(1.)\n\ncan result in the imaginary part of ``check`` being ``- nan`` .\n\n07-26\n=====\nAllow for use of ``const::string&`` as a possible type for\n:ref:`atomic_two_ctor@atomic_base@name` in the ``atomic_base``\nconstructor.\n\n05-28\n=====\nRemove *ok* return flag from\n:ref:`checkpoint algo<chkpoint_one@algo>`\nand\n:ref:`checkpoint atom_fun<chkpoint_one@atom_fun>` .\n\n05-21\n=====\n\n#. Deprecate the :ref:`atomic_one-name` interface and replace it by the\n   :ref:`atomic_two-name` and :ref:`checkpoint<chkpoint_one-name>` interfaces.\n#. There was a problem with the :ref:`cmake-name` command\n   if the :ref:`cmake@cppad_cxx_flags` was not specified.\n   This has been fixed.\n\n05-17\n=====\n\n#. Add the :ref:`ForSparseJac@transpose` option to\n   :ref:`ForSparseJac-name` .\n#. Add the :ref:`RevSparseHes@transpose` option to\n   :ref:`RevSparseHes-name` .\n\n05-15\n=====\nChange :ref:`RevSparseJac-name` parameter names to be closer to the\n:ref:`ForSparseJac-name` names so the difference is clearer.\n\n05-14\n=====\n\n#. The :ref:`checkpoint<chkpoint_one-name>` class has been added.\n   This is a much easier way to do checkpointing than the\n   old checkpoint example.\n   The old checkpointing example is now the :ref:`rev_checkpoint.cpp-name` example.\n#. Fix bug in :ref:`RevSparseJac-name` for case when :ref:`RevSparseJac@q`\n   was not equal to *m* (range dimension) and sparsity pattern was a\n   vector of ``bool`` .\n#. Add the :ref:`RevSparseJac@transpose` option to\n   :ref:`RevSparseJac-name` .\n\n05-12\n=====\nThe sparse hessian example in old_reciprocal.cpp was not\nbeing run. This has been fixed.\n\n05-11\n=====\nThe :ref:`atomic_one-name` examples\nnames were all changed to begin with ``user`` .\n\n05-04\n=====\nThe option to compute\n:ref:`forward_order@xq@Multiple Orders` was added.\nThe old_usead_2.cpp example shows the need for this.\nThe problem is that a new atomic function interface needs to be designed\nwith checkpointing as a particular application.\nMultiple order forward mode is the first step in this direction.\n\n04-28\n=====\n\n#. The scripts ``get_eigen.sh`` and :ref:`get_sacado.sh-name` were added.\n   If you are using Unix, and you do not have\n   `Eigen <https://libeigen.gitlab.io/>`_ or\n   `Sacado <https://trilinos.github.io/sacado.html>`_\n   installed on your system, you can use the corresponding script\n   to download and install a local copy for use when testing CppAD.\n#. The code ``std::cout <<`` *X* ,\n   would generate a compile error when *X* was an Eigen matrix\n   with ``CppAD::AD<`` *Base* > elements.\n   This has been fixed.\n\n04-27\n=====\nThere was a problem using the output operator ``<<`` with\nand :ref:`eigen<cppad_eigen.hpp-name>` matrix of ``AD`` elements.\nThis has been fixed using a template partial specialization of\n::\n\n    template <class Scalar, bool IsInteger>\n    struct significant_decimals_default_impl\n\nbecause the original template requires definition of a implicit conversion\nfrom the scalar type to an ``int`` and this is dangerous for AD types\n(note that :ref:`Integer-name` is used for explicit conversions).\n\n04-26\n=====\n\n#. The example old_usead_2.cpp was completed.\n   This is a more realistic, but also more complicated, example of\n   using AD to computed derivatives inside an atomic function.\n#. The script :ref:`get_fadbad.sh-name` has been added.\n   If you are using Unix, and you do not have\n   `FADBAD <http://uning.dk/>`_\n   installed on your system, you can use this script\n   to download and install a local copy for use when testing CppAD.\n\n{xrst_end 2013}\n\n$subhead 04-20$$\nThe example old_usead_1.cpp was added.\n\n$subhead 04-16$$\nThe script $cref get_ipopt.sh$$ has been added.\nIf you are using Unix, and you do not have\n$href%https://www.coin-or.org//projects/Ipopt.xml%Ipopt%$$\ninstalled on your system, you can use this script\nto download and install a local copy for use when testing CppAD.\n\n$subhead 04-14$$\nThe following program,\nwhen executed, would cause a CppAD assertion with an unknown source:\n$codep\n    # include <cppad/cppad.hpp>\n    int main(void)\n    {   size_t min_bytes = static_cast<size_t>(-1);\n        size_t cap_bytes;\n        void *v_ptr = CppAD::thread_alloc::get_memory(min_bytes, cap_bytes);\n        return 0;\n    }\n$$\nIt now generates the following message,\n(when compiled without $cref/NDEBUG/faq/Speed/NDEBUG/$$)\"\n$codep\n    get_memory(min_bytes, cap_bytes): min_bytes is too large\n    Error detected by false result for\n        min_bytes < std::numeric_limits<size_t>::max() / 2\n$$\n\n\n$subhead 03-02$$\nThe function $cref/isnan/nan/$$ no longer allows for systems\nthat return false for $icode%x% != %x%$$ when $icode x$$ is $code NaN$$.\nThis makes the $code isnan$$ function faster.\nIn addition, it removes the need to store a static value\nwhich causes complications for parallel execution (as well as other problems).\nThus, it is no longer necessary for the first call to $code isnan$$\nto be during sequential execution and it has been removed from the\nmulti-threading $cref/initialization/multi_thread/Initialization/$$ list.\n\n$subhead 03-01$$\nRemove the $cref cmake$$ $code cppad_c11_flag$$ and instead\nautomatically detect if the compiler supports specific c++11 features.\n\n$subhead 02-27$$\nThe test $cref num_limits.cpp$$ was failing during testing of Fedora-19; see\n$href%https://bugzilla.redhat.com/show_bug.cgi?id=913929% Bug 913929%$$.\nThis has been fixed.\n\n$subhead 02-20$$\n$list number$$\nThe documentation for the $cref cmake$$ install option\n$code cppad_test_vector_namespace$$ was fixed to be\n$cref/cppad_testvector/cmake/cppad_testvector/$$.\nThis was also fixed for the\n$cref/eigen test vector/eigen/Test Vector/$$ documentation.\n$lnext\nAn option to specify that the compiler supports c++11 constructs,\n$code cppad_c11_flag$$, was added\nto the $code cmake$$ command line.\n$lend\n$subhead 01-07$$\nFix undefined $code microsoft_timer$$ when building the\n$cref speed_example.cpp$$ program.\n\n$subhead 01-06$$\n$list number$$\nThe $cref limits$$ documentation was corrected an improved.\n$lnext\nThe $cref num_limits.cpp$$ example was simplified and restricted to just testing\nfor $code AD<double>$$.\n$lnext\nTesting for types other than $code AD<double>$$\nwas moved to $code test_more/num_limits.cpp$$.\nIn addition, $code test_more/num_limits.cpp$$ was modified to avoid the\nuse of guard digits (and hence test failure) on more machines.\n$lend\n\n$subhead 01-05$$\n$list number$$\nThe $cref num_limits.cpp$$ example was failing on some machines\nbecause they were using guard digits during calculations.\nThis has been fixed by using vectors instead of scalars\nfor storing values.\n$lnext\nThe $cref speed_example.cpp$$ was not linking when using a shared\nobject library for the code in $code speed/src$$.\nThis has been fixed by not including the library when linking\nthe speed examples.\n$lend\n\n$subhead 01-02$$\n$list number$$\nA new stable version of CppAD, for 2013, was created\nand its first release $code cppad-20130000.0$$ is available\nfor download at\n$pre\n    $$\n$href%https://www.coin-or.org/download/source/CppAD/%$$\n$lnext\nAdvance version number for trunk to $code 20130102$$.\n$lend\n\n$subhead 01-01$$\nWhen compiling with $cref/NDEBUG/Faq/Speed/NDEBUG/$$ defined,\nthe following warning could be generated:\n$codei%\n%...%rev_sparse_jac.hpp:315:9: warning: unused variable 'm' [-Wunused-variable]\n%$$\nThis has been fixed.\n\n\n$end\n"
  },
  {
    "path": "appendix/whats_new/2014.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin 2014 app}\n{xrst_spell\n    autoconf\n    automake\n    autotools\n    bthread\n    cmath\n    cstdint\n    ctor\n    datadir\n    docdir\n    doxygen\n    forwardany\n    forwardone\n    forwardzero\n    ipopt\n    omhelp\n    openmp\n    pthread\n    retape\n    uj\n}\n\nRelease Notes for 2014\n######################\n\nmm-dd\n*****\n\n12-30\n=====\nThere was a bug in the :ref:`cmake-name` whereby it would sometimes mistakenly\nexit with the error message\n::\n\n    cppad_max_num_threads is not an integer greater than or equal 4\n\nThis has been fixed.\n\n12-29\n=====\nThe example ``not_complex_ad.cpp`` was using the type\n\n    ``std::complex< CppAD::AD<double> >``\n\nand was failing to compile with the ``clang`` compiler.\nThis example has been removed because it is not consistent with the\nC++ standard; see\n:ref:`complex FAQ<faq@Complex Types>` .\n\n12-28\n=====\n\n#. Fix some warnings generated by clang 3.5 about local functions\n   that were not being used; e.g., sub-tests that were not being executed.\n#. Fix ``cmake`` setting\n   ``cppad_implicit_ctor_from_any_type``\n   Note that this cmake option has since been replaced by\n   ``cppad_deprecated`` option.\n#. The ``clang++`` compiler was optimizing out the calculations\n   in the :ref:`time_test.cpp-name` and :ref:`speed_test.cpp-name` examples.\n   This caused these tests to hang while trying to determine how\n   many times to repeat the test.\n   This has been fixed.\n\n12-27\n=====\nMore work on the bug in\n:ref:`optimizing<CondExp@Optimize>`\nconditional expressions.\n\n12-26\n=====\nA minimal example for computing cross terms in atomic operation\nHessian sparsity patterns ``atomic_two_rev_sparse_hes.cpp`` was added.\n\n12-25\n=====\nMore work on the bug in\n:ref:`optimizing<CondExp@Optimize>`\nconditional expressions.\n\n12-23\n=====\nThe c++11 standard includes the error function :ref:`erf-name` in\n``cmath`` .\nIf the c++ compiler has the error function defined in ``cmath`` ,\nthe compiler version of the error function is used and it corresponds to an\natomic operation.\n\nFix typo in tangent reverse mode theory for\n:ref:`Positive Orders<tan_reverse@Positive Orders Z(t)>` .\n\n12-22\n=====\nThere was a bug related to\n:ref:`optimizing<CondExp@Optimize>`\nconditional expressions.\nThis has been fixed.\n\n12-17\n=====\nFix some compiler warnings and :ref:`speed-name` program names\nwhen using the deprecated :ref:`configure-name` install procedure.\n\n12-16\n=====\nIf the ``c++11`` include file ``<cstdint>``\ndefines all the standard types, they can be used by to specify\n:ref:`cppad_tape_addr_type<cmake@cppad_tape_addr_type@cstdint>` and\n:ref:`cppad_tape_id_type<cmake@cppad_tape_id_type@cstdint>` .\n\n12-15\n=====\nCorrect the title and index entries for :ref:`forward_two-name`\nfrom first to second order.\n\n11-28\n=====\nImprove the index and ``search`` using\na new version of the ``omhelp`` documentation tool.\n\n11-27\n=====\n\n#. Add alignment to the\n   :ref:`get_memory<ta_get_memory@Alignment>` and\n   :ref:`create_array<ta_create_array@Alignment>` specifications\n   and\n   :ref:`thread_alloc example<thread_alloc.cpp-name>` .\n#. Advance the deprecated :ref:`unix install<configure-name>` utilities to\n   autoconf-2.69 and automake-1.13.4.\n\n09-28\n=====\nFix more bugs related to optimizing condition conditional expressions.\n\n#. Using old instead of new operator indices.\n#. Not properly following dependence back through atomic operations.\n#. Aborting during forward order zero, when skipping computation for a variable\n   that was already completed (the skip is still useful for higher orders\n   and for reverse mode).\n#. Reverse mode not properly handling the variable number of arguments in the\n   conditional skip operation.\n#. Reverse mode tracing not properly handling the variable number\n   of argument operations; i.e., conditional skip and cumulative summation.\n\n09-27\n=====\nFix a bug that occurred when\n:ref:`f.optimize<optimize-name>` was used with a function *f*\nthat contained calls to user defined :ref:`atomic-name` operations\nand :ref:`conditional expressions<CondExp-name>` .\n\n09-25\n=====\nFix a bug that occurred when\n:ref:`f.optimize<optimize-name>` was used with a function *f*\nthat contained :ref:`discrete-name` functions.\n\n09-21\n=====\nFix a typo in documentation for\n:ref:`any order reverse<reverse_any-name>` .\nTo be specific, :math:`x^{(k)}` was changed to be :math:`u^{(k)}`.\n\n05-28\n=====\n\n#. Change the :ref:`speed_main@Sparsity Options@boolsparsity`\n   so that it only affects the sparsity speed tests\n   :ref:`sparse_jacobian<link_sparse_jacobian-name>` and\n   :ref:`sparse_hessian<link_sparse_hessian-name>` ;\n   i.e., it is now ignored by the other tests.\n#. Improve the :ref:`speed-name` documentation page.\n\n05-27\n=====\n\n#. The ``cppad_colpack.cpp``\n   file was not being copied to the specified directory.\n   In addition, the specified directory was changed from an include\n   directory to data directory because\n   ``cppad_colpack.cpp`` is not an include file.\n#. If :ref:`colpack_prefix-name`  was specified, the CppAD\n   :ref:`pkgconfig-name` file was missing some information.\n   This has been fixed.\n\n05-23\n=====\nThe :ref:`speed-name` test instructions were converted from using\nthe old autotools :ref:`unix install<configure-name>` instructions\nto use the :ref:`cmake-name` install instructions.\nThese instructions should work on any system, not just unix.\n\n05-22\n=====\n\n#. Add multiple direction for mode\n   :ref:`forward_dir-name` and use it to speed up the forward\n   version of :ref:`sparse_jacobian-name` .\n   Below is an example run of :ref:`cppad_sparse_jacobian.cpp-name` results\n   before this change:\n   ::\n\n        cppad_sparse_jacobian_size = [ 100, 400, 900, 1600, 2500 ]\n        cppad_sparse_jacobian_rate = [ 2973, 431.94, 142.25, 78.64, 26.87 ]\n\n    and after this change:\n    ::\n\n        cppad_sparse_jacobian_size = [ 100, 400, 900, 1600, 2500 ]\n        cppad_sparse_jacobian_rate = [ 6389, 954.26, 314.04, 180.06, 56.95 ]\n\n    Due to the success of this change,\n    ``multiple direction`` items were added to the wish list\n    (they were later removed).\n#. Improve the  forward mode tracing of arguments to,\n   and results from, user defined :ref:`atomic-name` operations.\n\n05-20\n=====\n\n#. Move ``speed/adolc/alloc_mat.hpp`` to\n   ``speed/adolc/adolc_alloc_mat.hpp`` so it has the\n   same name is its ``# ifndef`` command.\n#. Fix ``# ifndef`` command in\n   ``cppad/ipopt/solve_callback.hpp`` .\n#. Add ``# ifndef`` command to ``test_more/extern_value.hpp`` .\n\n05-19\n=====\nIn the files\n``cppad/local/asin_op.hpp`` and ``cppad/local/acos_op.hpp``\nthere were assignments of the form ``uj = 0.`` where ``u_j``\nhas type :ref:`Base<glossary@Base Type>` .\nThese may have not be defined operations in certain cases and\nhave been converted to ``uj = Base(0)`` .\n\n05-16\n=====\nThere was a mistake in printing the arguments for\n``CSumOp`` and ``CSkipOp`` when using the undocumented\n``TRACE`` option during forward mode (available in files of the form\n``include/cppad/local/`` * ``sweep.hpp/`` ).\nThis has been fixed.\n\n05-14\n=====\n\n#. There were some global variables in the file\n   ``cppad/local/op_code.hpp`` that might have caused multiple definitions\n   during link time for CppAD applications.\n   These variables have been changed to be local so that this cannot happen.\n#. There was a mistaken assert that the number of arguments for the\n   ``BeginOp`` was zero that caused an abort when using the undocumented\n   ``TRACE`` option available in files of the form\n   ``include/cppad/local/`` * ``sweep.hpp/`` .\n   This has been fixed.\n\n03-18\n=====\n\n#. The\n   :ref:`fun_deprecated@size_taylor`\n   and\n   :ref:`fun_deprecated@capacity_taylor`\n   functions were deprecated;\n   use :ref:`size_order-name` and :ref:`capacity_order-name` instead.\n#. The documentation for :ref:`forward-name` and the examples\n   :ref:`forward.cpp-name` , :ref:`forward_order.cpp-name` , have been improved.\n   To be more specific, :ref:`forward_order-name` now references the special\n   cases :ref:`forward_zero-name` , :ref:`forward_one-name` and the new case\n   :ref:`forward_two-name` .\n\n03-17\n=====\nThe\n:ref:`CppAD_vector@Assignment@Move Semantics`\nversion of the ``CppAD::vector`` assignment statement\nwas not checking vector sizes.\nThis has been fixed so that things work the same with compilers\nthat do not have move semantics.\n(Note that with move semantics, no extra memory allocation is done\neven if the target vector has a different size.)\n\n03-09\n=====\nThe documentation links\n``forwardzero`` , ``forwardone`` , and ``forwardany``\nhave been changed to\n:ref:`forward_zero-name` , :ref:`forward_one-name` ,\nand :ref:`forward_order-name` respectively.\nThis may affect links from other web pages to the CppAD documentation.\n\n03-05\n=====\nThe names *p* and *q* in the\n:ref:`forward<forward_order-name>` ,\n:ref:`reverse<reverse_any-name>` ,\n:ref:`atomic_two_forward-name` , and\n:ref:`atomic_two_reverse-name` functions\nwere reverse so that *p* <= *q* .\nThis is only a notational change to make the arguments easier to remember.\n\n03-02\n=====\n\n#. In the output for the speed\n   :ref:`speed_main@test@correct` test,\n   mention which tests are not available.\n   Note that the set of available tests can depend on the\n   :ref:`list of options<speed_main@Global Options>` .\n#. In the documentation for\n   :ref:`sparse_jacobian@n_sweep` ,\n   mention that it is equal to the number of colors determined by the\n   :ref:`sparse_jacobian@work@color_method` .\n#. The :ref:`speed_cppad-name` tests were simplified by removing the printing\n   of auxiliary information related to the\n   :ref:`speed_main@Global Options@optimize` option.\n   Future auxiliary information will be passed back in a manner similar to\n   :ref:`link_sparse_jacobian@n_color` for the sparse jacobian test.\n#. :ref:`CppAD_vector@Assignment@Move Semantics`\n   were added to the ``CppAD::vector`` assignment operator.\n\n03-01\n=====\n\n#. Change the prototype for *row* and *col* in the\n   :ref:`link_sparse_jacobian-name` speed test to be ``const`` ; i.e.,\n   they are not changed.\n#. Move *x* near end of :ref:`link_sparse_hessian-name` speed test\n   parameter list,\n   (as is the case for :ref:`link_sparse_jacobian-name` ).\n\n02-28\n=====\nThe :ref:`CppAD_vector@data` function was added to the\n``CppAD::vector`` template class.\n\n02-27\n=====\nThe CppAD developer documentation for the subdirectory\n``cppad/ipopt`` was not being built by the command\n``bin/run_doxygen.sh`` .\nThis has been fixed.\n\n02-26\n=====\n\n#. The\n   :ref:`adolc<speed_adolc-name>` and\n   :ref:`cppad<speed_cppad-name>` sparse jacobian speed tests now print out\n   :ref:`sparse_jacobian@n_sweep` .\n#. The size of some of the :ref:`speed-name` test cases has been increased\n   to test behavior for larger problems.\n#. A link to :ref:`ode_evaluate-name` was missing in the\n   :ref:`speed_utility@Speed Utility Routines` table.\n   This has been fixed.\n\n02-23\n=====\nThe :ref:`sparse_jacobian@work@color_method`\noption was added to the sparse Jacobian calculations.\nThis enables one to use :ref:`ColPack<colpack_prefix-name>`\ndo color the rows or columns.\nThe speed test :ref:`speed_main@Sparsity Options@colpack` option\nwas also added (but not yet implemented for\n:ref:`sparse_hessian<link_sparse_hessian-name>` speed tests).\n\n02-22\n=====\nThe program names in\n:ref:`thread_test.cpp-name` where changes from\n*threading* _ ``test`` to ``multi_thread_`` *threading*\nwhere *threading* is ``openmp`` , ``pthread`` or ``bthread`` .\n\n02-17\n=====\nFix ambiguous call to :ref:`nan@isnan`\nduring MS Visual Studio 2012 compilation.\n\n02-15\n=====\n\n#. The :ref:`speed_main@Sparsity Options@boolsparsity` option\n   was added to the :ref:`speed_main-name` program.\n#. The ``retape`` option what changed to\n   :ref:`speed_main@Global Options@onetape` so that the default\n   is to retape (option not present).\n   This was done because\n   :ref:`fadbad<fadbad_prefix-name>` and\n   :ref:`sacado<sacado_prefix-name>` always retape.\n#. The documentation, and example source code, for all the speed\n   :ref:`options<speed_main@Global Options>` was improved\n   (made clearer).\n#. Improve the success rate for\n   :ref:`speed_test.cpp-name` and :ref:`time_test.cpp-name` .\n\n01-26\n=====\nThe destination directory for the\n:ref:`cppad documentation<cmake@cmake_install_docdir>`\nis now set separately from the data directory\nusing the ``cmake`` option\n\n    ``-D cmake_install_docdir`` = *cmake_install_docdir*\n\nThis has increased the flexibility of the documentation installation\nand removed the need for the option\n\n    ``-D cppad_documentation`` = *yes_or_no*\n\nwhich has been removed.\n\n01-21\n=====\nThe destination directory for the\ncppad documentation\nused to be one of the following:\n\n| |tab| *prefix* / *datadir* / ``doc/cppad-`` *version*\n| |tab| *prefix* / *datadir* / ``doc/`` *postfix* ``cppad-`` *version*\n\nThis has been changed by dropping the *version* number\nat the end of the directory name.\n\n01-10\n=====\nThe change on :ref:`2013-12-27<2013@mm-dd@12-27>`\ncaused a conversion error in :ref:`atan2-name` when it was used with\n``AD< AD<double> >`` arguments (and other similar cases).\nThis has been fixed.\n\n{xrst_end 2014}\n"
  },
  {
    "path": "appendix/whats_new/2015.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin 2015 app}\n{xrst_spell\n    addon\n    adouble\n    aeps\n    asctime\n    autotools\n    chrono\n    cskip\n    datadir\n    docdir\n    erfc\n    gettimeofday\n    gmtime\n    hasnan\n    ieee\n    includedirs\n    lcppad\n    libdirs\n    runge\n    src\n    unreferenced\n}\n\nRelease Notes for 2015\n######################\n\nmm-dd\n*****\n\n12-31\n=====\nThe :ref:`download-name` instructions were modified to have more mention of\ngit and less mention of\nsubversion.\n\n12-29\n=====\nSeparate :ref:`to_string-name` from :ref:`ad_to_string-name` so that it\ncan be used without the rest of CppAD; i.e.,\nby including\n\n    # ``include <cppad/utility/to_string.hpp>``\n\n12-28\n=====\n\n#. Add the :ref:`to_string-name` utility.\n#. Add :ref:`base_to_string-name` to the Base type requirements.\n#. A :ref:`wish_list@Base Requirements` item\n   was added to the wish list.\n#. The :ref:`wish_list-name` item to\n   reorganize the include directory has been removed.\n   It was completed when the utilities was moved to ``cppad/utility`` ; see\n   :ref:`2015@mm-dd@11-30` .\n\n12-08\n=====\n\n#. A convention was included for addon\n   :ref:`addon@Library Files` .\n#. Change new :ref:`utility-name` specifications to allow for individual file\n   includes; e.g., ``<cppad/utility/vector.hpp>`` .\n\n12-01\n=====\nFix problem with :ref:`configure-name` install handling of the\ndeprecated files.\nThis included changing the autotools\n``--with-implicit_ctor`` option to :ref:`configure-name` .\nThis was removed on\n:ref:`2017-02-10<2017@mm-dd@02-10>` .\n\n11-30\n=====\n\n#. The ``library`` section has been moved to the\n   :ref:`utilities<utility-name>` section.\n   In addition, the corresponding source code files in ``cppad``\n   have been moved to ``cppad/utility`` .\n#. The individual :ref:`utility-name` include files have been deprecated; see\n   :ref:`include_deprecated-name` .\n   For example,\n   ::\n\n        # include <cppad/runge_45.hpp>\n\n    You should us the utility include instead; i.e.,\n    ::\n\n        # include <cppad/utility.hpp>\n\n#. The :ref:`numeric_ad-name` routines where moved from the ``library``\n   the a separate documentation section.\n#. Change ``cmake_install_prefix`` to\n   :ref:`cmake@cppad_prefix` and\n   Change ``cmake_install_postfix`` to\n   :ref:`cmake@cppad_postfix` .\n#. Change ``cppad_implicit_ctor_from_any_type`` to\n   the cmake ``cppad_deprecated`` option and\n   change its specifications to refer to all deprecated features.\n\n11-25\n=====\n\n#. CppAD now installs the object library\n   ::\n\n        -lcppad_lib\n\n    to be included when linking.\n    Currently, it is only required when\n    :ref:`colpack_prefix-name` is specified on the\n    :ref:`cmake@CMake Command` .\n#. It is no longer necessary to compile and link the file\n   ::\n\n        cppad_colpack.cpp\n\n    when :ref:`colpack_prefix-name`\n    is specified during the install process; see\n    :ref:`cmake@CMake Command` .\n    (It is included in ``cppad_lib`` ).\n\n11-24\n=====\n\n#. The ``check_for_nan`` output now includes the first dependent\n   variable\n   :ref:`check_for_nan@Error Message@index`\n   that is ``nan`` in its error message.\n#. Change the\n   :ref:`deprecated include<include_deprecated-name>` reference ``pow_int.h``\n   to ``pow_int.hpp`` in :ref:`pow_int-name` .\n\n11-14\n=====\nThere was a bug in the new\n:ref:`check_for_nan@get_check_for_nan`\nfeature that writes independent variable values to a temporary file;\nsee :ref:`2015@mm-dd@11-06` below.\nThis has been fixed.\n\n11-08\n=====\n\n#. Fixed a bug in the :ref:`RevSparseJac-name` routine.\n   To be specific, the argument :ref:`RevSparseJac@r`\n   was transposed from what the documentation said.\n   (This has no effect in the usual case where *r* is the identity.)\n#. Added the ``bool_sparsity.cpp`` examples which show how\n   to conserve memory when computing sparsity patterns.\n   (This has since been replaced by :ref:`rc_sparsity.cpp-name` .)\n#. Modified the :ref:`ipopt_solve-name` procedure to take\n   advantage of the memory conserving sparsity pattern calculations\n   when :ref:`ipopt_solve@options@Retape` is false.\n#. Added the :ref:`CppAD_vector@vectorBool@bit_per_unit`\n   function to the ``vectorBool`` class.\n   (This aids the memory conservation mentioned above.)\n\n11-06\n=====\nIt is often difficult to determine what cause a ``nan`` result\nduring an operation with an :ref:`ADFun-name` object.\nThe new feature\n:ref:`check_for_nan@get_check_for_nan` was\nadded to make this easier.\n\n10-21\n=====\nThere was a mistake in the documentation for :ref:`index_sort-name` ,\nthe argument :ref:`index_sort@ind` is not ``const`` .\n\n10-16\n=====\nAdd a :ref:`PrintFor-name` optimization wish list item.\nThis has been done,\nsee :ref:`optimize@options@no_print_for_op` .\n\n10-06\n=====\n\n#. Add the ``CPPAD_USE_CPLUSPLUS_2011`` ,\n   ``CPPAD_NUMERIC_LIMITS`` , and\n   ``CPPAD_STANDARD_MATH_UNARY`` , to\n   the :ref:`preprocessor-name` section.\n   In addition, remove checking that all user API preprocessor symbols\n   are in this section form the :ref:`wish_list-name` .\n#. Alphabetize and make some corrections to\n   :ref:`list of examples<list_all_examples-name>` .\n#. The documentation for some of the :ref:`deprecated-name` features\n   was missing the date when they were deprecated.\n   This has been fixed; e.g., see\n   :ref:`configure@Deprecated 2012-12-26` .\n\n10-04\n=====\n\n#. :ref:`base_require-name` :\n   Add the macro\n   :ref:`base_limits@CPPAD_NUMERIC_LIMITS`\n   to aid in setting the numeric limits for a user defined *Base* class.\n#. :ref:`base_require-name` :\n   The :ref:`numeric_limits@quiet_NaN` function has been added\n   to the CppAD ``numeric_limits`` .\n   Note the reason for not using\n   :ref:`numeric_limits@std::numeric_limits` .\n#. The :ref:`nan@nan(zero)` function computes a ``nan`` by\n   dividing zero by zero which results in a warning when using some compilers.\n   This function has been deprecated and the corresponding\n   :ref:`wish_list-name` item has been removed.\n#. Move documentation for :ref:`zdouble-name` to :ref:`deprecated-name` section\n   and documentation for :ref:`numeric_limits-name` to :ref:`ADValued-name` .\n#. Remove all uses of, and references to,\n   :ref:`zdouble-name` from the :ref:`examples<Example-name>` .\n\n10-03\n=====\n:ref:`base_require-name` :\nIt is no longer necessary to define the specialization for\n``CppAD::epsilon<`` *Base>* () for each *Base* type.\n\n10-02\n=====\nThere was a bug in ``test_more/azmul.cpp`` whereby the vector\n``z`` had the wrong dimension (in two places). This has been fixed.\n\n09-28\n=====\n\n#. Use the current :ref:`atomic_two_option-name` setting to determine\n   which type of sparsity patterns to use for\n   :ref:`dependency<dependency.cpp-name>` calculations during\n   :ref:`optimize-name` procedure.\n   It used to be that the\n   :ref:`atomic_two_option@atomic_sparsity@bool_sparsity_enum`\n   was used when\n   :ref:`atomic_two_option@atomic_sparsity@pack_sparsity_enum`\n   was specified.\n#. It is not longer an error to take the derivative of the square root function,\n   because the result may be the part of a\n   :ref:`conditional expression<CondExp-name>` that is not used.\n#. Update the :ref:`wish_list-name` section.\n\n09-27\n=====\n\n#. It is no longer necessary to use the :ref:`zdouble-name` class when\n   computing with :ref:`multiple levels of AD<mul_level-name>`\n   :ref:`conditional expressions<CondExp-name>` and\n   :ref:`reverse mode<reverse-name>` .\n#. The ``zdouble`` class has been deprecated.\n   Use the :ref:`azmul-name` function for absolute zero (when it is needed).\n\n09-25\n=====\n:ref:`base_require-name` :\n:ref:`absolute zero multiplication<base_require@Absolute Zero, azmul>`\nis now required for user defined base types.\nThis makes it possible to combine\n:ref:`conditional expression<CondExp-name>` ,\n:ref:`multiple levels<mul_level-name>` ,\n:ref:`Reverse-name` , and\na base type that has standard ieee multiplication; e.g., ``double`` .\nIn other words, not all multiplications will need to have an\nabsolute zero (as is the case with the :ref:`zdouble-name` base class.\n\n09-24\n=====\nFix some Visual Studio 2013 C++ level four ``/W4`` warnings\n(previous warnings were are level 3).\nIn addition, disable warning\n``4100`` unreferenced formal parameter,\nand warning\n``4127`` conditional expression is constant.\n\n09-23\n=====\nCppAD can optionally test its use with the external packages\neigen ,\n:ref:`ipopt<get_ipopt.sh-name>` , and\n:ref:`colpack<get_colpack.sh-name>` .\nIn addition, it can compare its :ref:`speed-name` with the external AD packages\n:ref:`adolc<get_adolc.sh-name>` ,\n:ref:`fadbad<get_fadbad.sh-name>` , and\n:ref:`sacado<get_sacado.sh-name>` .\nThe scripts that download and install a local copy of these external packages\nhave been modified to automatically skip installation\nwhen it has already been done.\n\n09-21\n=====\nImprove discussion of windows download and testing.\nThis discussion has since been removed; see\n+:ref:`2018@mm-dd@05-20` in whats new for 2018.\n\n09-20\n=====\n\n#. Add the :ref:`cmake@cppad_profile_flag`\n   to the list of possible ``cmake`` command arguments.\n#. More of the warnings generated by Visual Studio 2013 have been fixed.\n   One remaining warning is about ``asctime`` and ``gmtime`` not being\n   thread safe.\n\n09-19\n=====\n\n#. There was a bug in the :ref:`base_alloc.hpp@numeric_limits`\n   section of the example user defined base type.\n   This has been fixed.\n#. There were some compile and link errors when\n   running the tests using Visual Studio 2013.\n   These have been fixed.\n#. Many of the warnings generated by Visual Studio 2013 have been fixed.\n\n09-16\n=====\nThe conditional expressions, :ref:`CondExp-name` , were not working\nfor the type ``< CppAD::AD<adouble> >`` where ``adouble``\nis the ADOL-C AD type.\nThis has been fixed by adding a call to\n:ref:`CPPAD_COND_EXP_REL<base_adolc.hpp@CondExpRel>` in\n``base_adolc.hpp`` .\n\n09-03\n=====\n\n#. There was a bug in the :ref:`CppAD_vector@vectorBool`\n   :ref:`CppAD_vector@Assignment` .\n   To be specific,\n   it not allow a size zero vector to be assigned using a vector any other size.\n   This has been fixed.\n#. The addition of the\n   :ref:`pack<atomic_two_option@atomic_sparsity@pack_sparsity_enum>` option\n   on 08-31 introduced a bug in the calculation of :ref:`RevSparseHes-name` .\n   The ``chkpoint_one_get_started.cpp`` example was changed to demonstrate this\n   problem and the bug was fixed.\n\n09-02\n=====\nThe :ref:`dependency.cpp@Dependency Pattern`\nwas not being computed correctly for the\n:ref:`sign-name` , :ref:`Discrete-name` , and :ref:`VecAD-name` operations.\nThis has been fixed.\nThis could have caused problems using\n:ref:`checkpoint<chkpoint_one-name>` functions that used any of these operations.\n\n08-31\n=====\n\n#. Mention the fact that using checkpoint functions can make\n   :ref:`recordings faster<chkpoint_one@Purpose@Faster Recording>` .\n#. Add the\n   :ref:`pack<atomic_two_option@atomic_sparsity@pack_sparsity_enum>`\n   sparsity option for :ref:`atomic_two-name` operations.\n#. Add the pack sparsity option to\n   :ref:`chkpoint_one<chkpoint_one@sparsity>` functions.\n#. Added the ``example/atomic/sparsity.cpp`` example.\n#. Remove mention of OpenMP from :ref:`thread_alloc::thread_num<ta_thread_num-name>`\n   (:ref:`thread_alloc-name` never was OpenMP specific).\n\n08-30\n=====\n\n#. The :ref:`atomic_two_ctor@atomic_base@sparsity`\n   argument was added to the ``atomic_base`` constructor and the\n   :ref:`chkpoint_one<chkpoint_one@sparsity>` constructor.\n#. Make ``atomic_two_norm_sq.cpp`` an example with no set sparsity\n   and ``atomic_two_reciprocal.cpp`` an example with no bool sparsity.\n#. Improve discussion of ``Independent`` and\n   :ref:`Independent@Parallel Mode` .\n\n08-29\n=====\nSome asserts in the :ref:`checkpoint<chkpoint_one-name>` implementation were not using\nthe CppAD :ref:`ErrorHandler-name` . This has been fixed.\n\n08-28\n=====\nFree :ref:`checkpoint<chkpoint_one-name>` function sparsity patters during\n:ref:`forward-name` operations that use its atomic operation.\n(They kept between sparsity calculations because they do not change.)\n\n08-26\n=====\nFix a bug in :ref:`RevSparseJac-name` when used to compute sparsity pattern\nfor a subset of the rows in a :ref:`checkpoint<chkpoint_one-name>` function.\n\n08-25\n=====\nReduce the amount of memory required for :ref:`checkpoint<chkpoint_one-name>` functions\n(since sparsity patterns are now being held so they do not need to be\nrecalculated).\n\n08-20\n=====\nAdded an example that computes the sparsity pattern for a subset\nof the :ref:`Jacobian<sparsity_sub.cpp@ForSparseJac>` and a subset\nof the :ref:`Hessian<sparsity_sub.cpp@RevSparseHes>` .\n\n08-17\n=====\n\n#. Do some optimization of the\n   :ref:`checkpoint<chkpoint_one-name>` feature so that sparsity patterns are\n   stored and not recalculated.\n#. Fix a warning (introduced on 08-11) where the ``CppAD::vector``\n   :ref:`CppAD_vector@data` function was being shadowed by\n   a local variable.\n#. The source code control for CppAD has a link to ``compile`` ,\n   instead of real file.\n   This sometimes caused problems with the\n   deprecated :ref:`configure-name` install procedure and has been fixed.\n\n08-16\n=====\n\n#. Improve the documentation for checkpoint functions.\n   To be specific, change the :ref:`chkpoint_one@Syntax` to use\n   the name *atom_fun* .\n   In addition, include the fact that *atom_fun* must not\n   be destructed for as along as the corresponding atomic operations are used.\n#. Add the :ref:`chkpoint_one@size_var` function\n   to the checkpoint objects.\n\n08-09\n=====\nAdd the preservation of data to the specifications of a ``CppAD::vector``\nduring a :ref:`CppAD_vector@resize` when the\ncapacity of the vector does not change.\nIn addition, added and example of this to :ref:`cppad_vector.cpp-name` .\n\n08-06\n=====\nThe :ref:`zdouble-name`\n:ref:`numeric_limits<base_limits-name>`\nwere not being computed properly.\nThis has been fixed.\n\n07-31\n=====\nAdded the :ref:`sparse_sub_hes.cpp-name` example,\na way to compute the sparsity for a subset of variables without\nusing :ref:`multiple levels of AD<mul_level-name>` .\n\n06-16\n=====\n\n#. There were some\n   :ref:`cppad_assert@Unknown` asserts\n   when the sparsity pattern *p* in\n   :ref:`sparse_jacobian<sparse_jacobian@p>` and\n   :ref:`sparse_hessian<sparse_hessian@p>` was not properly dimensioned.\n   These have been changed to\n   :ref:`cppad_assert@Known` asserts to give better\n   error reporting.\n#. In the special case where sparse Hessian :ref:`sparse_hessian@work` or\n   sparse Jacobian :ref:`sparse_hessian@work` was specified and the\n   set of elements to be computed was empty, the work vector is empty after\n   the call (and it appears to need to be calculated on subsequent calls).\n   This resulted in a bug when the sparsity pattern was not provided\n   on subsequent calls (and has been fixed).\n\n06-11\n=====\n\n#. Some C++11 features were not being taken advantage of after the change on\n   :ref:`2015@mm-dd@05-10` . To be specific, move semantics,\n   the high resolution clock, and null pointers.\n   This has been fixed.\n#. In the example zdouble.cpp, the vector ``a1z`` was not\n   properly dimensioned.\n   This has been fixed and the dimensions of all the variables have been\n   clarified.\n\n06-09\n=====\nAdd an :ref:`Independent@abort_op_index`\nitem to the wish list. It has since been removed\n(domain errors may not affect the results due to\n:ref:`conditional expressions<CondExp-name>` ).\n\n06-07\n=====\nAdd a :ref:`absolute zero<base_require@Absolute Zero, azmul>` item\nand a :ref:`numeric_limits-name` item to the wish list.\nThe absolute zero item has been completed and the\nnumeric limit item was modified on implementation.\nRemove the multiple directions with list item.\n\n05-26: cond_exp_1\n=================\nThere was a problem using\n:ref:`conditional expressions<CondExp-name>`\nwith :ref:`multiple levels of AD<mul_level-name>` where\nthe result of the conditional expression might not be determined\nduring forward mode.\nThis would generate an assert of the form:\n\n| |tab| ``Error detected by false result for``\n| |tab| |tab| ``IdenticalCon`` ( *side* )\n| |tab| ``at line`` *number* ``in the file``\n| |tab| |tab| .../ ``include/cppad/local/cskip_op.hpp``\n\nwhere *side* was ``left`` or ``right``\nand *number* was the line number of an assert in ``cskip_op.hpp`` .\nThis has been fixed.\n\n05-26: cond_exp_2\n=================\nThere was a problem with using\n:ref:`conditional expressions<CondExp-name>` and :ref:`reverse mode<reverse-name>`\nwith :ref:`multiple levels of AD<mul_level-name>` .\nThis was problem was represented by the file ``bug/cond_exp_2.sh`` .\n\n#. The problem above has been fixed by adding the base type ``zdouble`` , see\n   :ref:`CppAD motivation<zdouble@Motivation@CppAD>` for this new type.\n   (It is no longer necessary to use ``zdouble`` to get an absolute zero\n   because CppAD now uses :ref:`azmul-name` where an absolute zero is required.)\n#. The sections\n   :ref:`mul_level-name` ,\n   :ref:`change_param.cpp-name` ,\n   :ref:`mul_level.cpp-name` ,\n   and :ref:`mul_level_ode.cpp-name` were changed to use :ref:`zdouble-name` .\n#. The :ref:`adolc-name` multi-level examples\n   :ref:`mul_level_adolc.cpp-name` and :ref:`mul_level_adolc_ode.cpp-name`\n   were changed to mention the limitations because Adolc does not have an\n   :ref:`zdouble@Absolute Zero` .\n#. The example above were also changed so that AD variable names that\n   indicated the level of AD for the variable.\n#. :ref:`base_require-name` :\n   The base type requirements were modified to include mention of\n   :ref:`absolute zero<base_require@Absolute Zero, azmul>` .\n   In addition, the base type requirements\n   :ref:`base_require@API Warning` is now more informative.\n\n05-11\n=====\nReorganize the :ref:`unary_standard_math-name` documentation.\n\n05-10\n=====\n\n#. Add the exponential minus one function :ref:`log1p-name` .\n#. :ref:`base_require-name` :\n   If you are defining your own base type,\n   note that ``log1p`` function\n   was added to the base type requirements.\n#. Use the single preprocessor flag\n   ``CPPAD_USE_CPLUSPLUS_2011`` to signal that the functions\n   asinh, acosh, atanh, erf, erfc, expm1, log1p\n   are part of the base type requirements.\n\n05-09\n=====\n\n#. Add the exponential minus one function :ref:`expm1-name` .\n   If you are defining your own base type,\n   note that expm1\n   was added to the base type requirements.\n#. Fix some warnings about comparing signed and unsigned integers\n   when using :ref:`cppad_testvector@eigen` for the CppAD test vector.\n   (The eigen vector ``size()`` function returns an ``int`` instead of a\n   ``size_t`` .)\n\n05-08\n=====\n\n#. Add the inverse hyperbolic sine function :ref:`atanh-name` .\n   If you are defining your own base type,\n   note that atanh\n   was added to the base type requirements.\n#. Fix a bug in the implementation of the ``acosh``\n   multiple direction forward mode :ref:`forward_dir-name` .\n\n05-07\n=====\nAdd the inverse hyperbolic sine function :ref:`acosh-name` .\nIf you are defining your own base type,\nnote that acosh\nwas added to the base type requirements.\n\n05-05\n=====\nAdd the inverse hyperbolic sine function :ref:`asinh-name` .\nIf you are defining your own base type,\nnote that asinh\nwas added to the base type requirements.\n\n04-18\n=====\nIn the sparse jacobian and sparse hessian calculations,\nIf *work* is present, and has already been computed,\nthe sparsity pattern *p* is not used.\nThis has been added to the documentation; see\n:ref:`sparse jacobian<sparse_jacobian@work@p>` and\n:ref:`sparse hessian<sparse_hessian@work@p>` documentation\nfor *work* and *p* .\n\n03-13\n=====\nRemove the syntax\n\n    ``AD`` < *Base* > *y* = *x*\n\nfor the :ref:`AD constructor<ad_ctor-name>` documentation because it does not\nwork when the constructor is :ref:`ad_ctor@x@explicit` .\nAlso document the restriction that the constructor in the\n:ref:`assignment<ad_assign-name>` must be implicit.\n\n03-06\n=====\nThe developers of the\n`TMB <https://github.com/kaskr/adcomp>`_ package reported that\nfor large :ref:`ADFun-name` tapes, the :ref:`optimize-name` routine uses\na large amount of memory because it allocates a standard set for\neach variable on the tape. These sets are only necessary for variables in\n:ref:`conditional expressions<condexp-name>` that can be skipped once\nthe independent variables have a set value.\nThe problem has been reduced by using a NULL pointer for the empty set\nand similar changes. It still needs more work.\n\n02-28\n=====\nIt used to be the case that the\n:ref:`Reverse mode<reverse-name>` would propagate :ref:`nan-name`\nthrough the :ref:`conditional expression<condexp-name>`\ncase that is not used.\nFor example, if\n::\n\n    Independent(ax);\n    AD<double> aeps = 1e-10;\n    ay[0] = CondExpGt( ax[0], aeps, 1.0/ax[0], 1.0/aeps );\n    ADFun<double> f(ax, ay);\n\nThe corresponding reverse mode calculation,\nat ``x[0] = 0.0`` , would result in\n::\n\n    Error detected by false result for\n    ! ( hasnan(value) && check_for_nan_ )\n\nThis has been fixed so that only the conditional expression case that is used\naffects the reverse mode results.\nThe example :ref:`cond_exp.cpp-name` was changed to reflect this\n(a check for ``nan`` was changed to a check for zero).\nNote that this fix only works when\n:ref:`base_identical@Identical@IdenticalCon` is true for the\nbase type of the result in the conditional expression; e.g.,\none can still get a ``nan`` effect from the case that is not selected\nwhen using ``AD< AD<double> >`` conditional expressions.\n\n02-18\n=====\nIf the compiler supports the c++11 feature\n``std::chrono:high_resolution_clock`` then use it for\nthe :ref:`elapsed_seconds-name` function.\n\n02-16\n=====\nThe new example :ref:`sub_sparse_hes.cpp-name` shows one way to\ncompute a Hessian for a subset of variables without having to compute\nthe sparsity pattern for the entire functions.\n\n02-14\n=====\nFix another bug in the derivative calculations for the\nc++11 version of the error function.\n\n02-11\n=====\nFix a bug in the optimization of conditional expressions. To be specific,\nif :ref:`faq@Speed@NDEBUG` is not defined, one could get\nan assert with the message:\n::\n\n    Error detected by false result for\n    var_index_ >= NumRes(op_)\n\n02-10\n=====\nThe change on :ref:`2014-12-23<2014@mm-dd@12-23>` introduced a\nbug when the c++11 version of the error function was used with\nan :ref:`optimized<optimize-name>` function.\nThere was also a bug in the sparsity calculations for when\nthis erf function was included.\nThese bugs have been fixed.\n\n02-09\n=====\nThe test ``test_more/optimize.cpp`` was failing on some systems\nbecause an exactly equality check should have been a near equal check.\nThis has been fixed.\n\n02-07\n=====\nOn some systems, the library\ncorresponding to ``speed/src`` could not be found.\nThis library is only used for testing and so has been changed to always be\nstatic (hence does not need to be found at run time).\n\n02-06\n=====\nThere was a bug in the coloring method change on\n:ref:`2015-01-07<2015@mm-dd@01-07>` .\nTo be specific, *work* . ``color_method`` was not being set\nto ``\"cppad.symmetric\"`` after *work* . ``color_method.clear`` () .\nThis has been fixed.\n\n02-04\n=====\n\n#. Enable the same install of CppAD to be used both with and without C++11\n   features; e.g., with both ``g++ --std=c++11`` and with\n   ``g++ --std=c++98`` . Previously if the\n   :ref:`cmake@cppad_cxx_flags` specified C++11,\n   then it could only be used in that way.\n#. The :ref:`cmake@CMake Command` now requires the version\n   of ``cmake`` to be greater than or equal 2.8\n   (due a bug in ``cmake`` version 2.6).\n\n02-03\n=====\nImproved the searching for the boost multi-threading library\nwhich is used for by the :ref:`team_bthread.cpp-name` case of the\n:ref:`thread_test.cpp-name` example and test.\n\n02-02\n=====\nImprove the documentation for the\n:ref:`cmake@CMake Command` line options\n\n    ``cmake_install_`` *dir*\n\nfor *dir* equal to\n``prefix`` , ``postfix`` , ``includedirs`` , ``libdirs`` ,\n``datadir`` , and ``docdir`` .\n\n01-30\n=====\nFix bug in :ref:`link_sparse_hessian-name` speed test introduced on\n:ref:`2015@mm-dd@01-09` below.\n\n01-29\n=====\nFix some warnings generated by ``g++ 4.9.2`` .\n\n01-26\n=====\nThe change of global variables to local in\n``cppad/local/op_code.hpp`` on :ref:`2014-50-14<2014@mm-dd@05-14>`\ncreated a bug in :ref:`parallel_ad-name` (some local statics needed to\nbe initialized). This has been fixed.\n\n01-23\n=====\nThere was a bug in the :ref:`cmake-name` install detection of compiler features.\nOne symptom of this bug was that on systems that had the ``gettimeofday``\nfunction, the cmake install would sometimes report\n\n    ``cppad_has_gettimeofday`` = 0\n\nThis has been fixed.\n\n01-21\n=====\nThe deprecated :ref:`configure-name` procedure had a bug in the\ndetection of when the size of an ``unsigned int``\nwas the same as the size of a ``size_t`` . This has been fixed.\n\n01-20\n=====\n\n#. The new :ref:`compare_change-name` interface has been created\n   and the old :ref:`CompareChange-name` function has been deprecated;\n   see the :ref:`compare_change.cpp-name` example.\n   This enables one to determine the source code during taping\n   that corresponds to changes in the comparisons during\n   :ref:`zero order forward<forward_zero-name>` operations; see\n   :ref:`Independent@abort_op_index` .\n\n#. This new :ref:`compare_change-name` interface can detect comparison changes\n   even if :ref:`Faq@Speed@NDEBUG` is defined and\n   even if :ref:`f.optimize()<optimize-name>` has been called.\n   The deprecated function ``CompareChange`` used to always return zero after\n\n        *f* . ``optimize`` ()\n\n    and was not even defined when ``NDEBUG`` was defined.\n    There was a resulting speed effect for this; see\n    :ref:`optimize@options@no_compare_op` .\n\n#. The date when some features where deprecated has been added to the\n   documentation. For example, see\n   :ref:`include_deprecated@Deprecated 2006-12-17` .\n\n01-09\n=====\n\n#. The change 01-07 below included (but did not mention) using\n   a sparse, instead of full, structure for the Hessian in the test.\n   This has also been done for the\n   :ref:`sparse Jacobian<link_sparse_jacobian-name>` test.\n#. For both the\n   :ref:`sparse_jacobian<link_sparse_jacobian-name>` and\n   :ref:`sparse_hessian<link_sparse_hessian-name>` tests,\n   the sparse function is only chosen once\n   (it used to be different for every repeat).\n   This reduced the amount of computation not connected what is being tested.\n   It also make the :ref:`speed_main@Global Options@onetape` a valid\n   option for these tests.\n#. There was a bug in the\n   :ref:`multiple direction forward<forward_dir-name>` routine.\n   Results for function values that are\n   :ref:`con_dyn_var@Parameter` were not being computed properly\n   (all the derivatives are zero in this case).\n   This has been fixed.\n\n01-07\n=====\nThe following changes were merged in from the ``color_hes`` branch:\n\n#. Specify the type of\n   :ref:`coloring<sparse_hessian@work@color_method>`\n   for the sparse hessian calculations.\n   To be specific, instead of ``\"cppad\"`` and ``\"colpack\"`` ,\n   the choices are ``\"cppad.symmetric\"`` , ``\"cppad.general\"`` ,\n   and ``\"colpack.star\"`` .\n   This is not compatible with the change on\n   :ref:`2015@mm-dd@01-02` , which was so recent\n   that this should not be a problem.\n#. The :ref:`link_sparse_hessian@n_color` values were\n   not being returned properly by\n   :ref:`cppad_sparse_hessian.cpp-name` and\n   :ref:`adolc_sparse_hessian.cpp-name` .\n   The CppAD version has been fixed and the ADOL-C version\n   has been set to zero.\n#. The :ref:`link_sparse_hessian-name` example case was to sparse for good\n   testing (by mistake).\n   This has been fixed.\n#. Add *n_sweep* (now *n_color* ) to\n   :ref:`link_sparse_hessian<link_sparse_hessian@n_color>` and\n   :ref:`speed_main<speed_main@Speed Results@n_color>` .\n#. Change the ``cppad`` sparse Hessian\n   :ref:`sparse_hessian@work@color_method`\n   to take advantage of the symmetry of the Hessian\n   (in a similar fashion to the ``colpack`` coloring method).\n\n01-02\n=====\nAdded to option to uses\n:ref:`colpack<colpack_prefix-name>` for the sparse Hessian\n:ref:`coloring method<sparse_hessian@work@color_method>` ;\nsee the example :ref:`colpack_hes.cpp-name` .\n\n{xrst_end 2015}\n"
  },
  {
    "path": "appendix/whats_new/2016.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin 2016 app}\n{xrst_spell\n    adouble\n    autotools\n    chkpoint\n    chrono\n    colpack\n    makefile\n    mingw\n    valgrind\n    wmisleading\n    xam\n}\n\nRelease Notes for 2016\n######################\n\nmm-dd\n*****\n\n12-23\n=====\nAdded a way for the user to determine what tests options are available; see\n:ref:`cmake@make check` .\n\n12-20\n=====\nChange the optimize :ref:`optimize@Examples` to use\n:ref:`NearEqual-name` for floating point tests (instead of exactly equal).\nThere were some other exactly equal floating point tests that were\nfailing on a ``mingw`` system. Theses have also been fixed.\n\n12-18\n=====\nAdd the :ref:`optimize@options@no_print_for_op` to the\noptimize routine.\n\n12-13\n=====\n\n#. Fix a bug in :ref:`ForSparseHes-name` . To be more specific,\n   there was a bug in handling the cumulative summations operator in this\n   routine. This could only come up when used\n   an :ref:`optimized<optimize-name>` :ref:`ForSparseHes@f` ,\n#. Add the\n   :ref:`nest_conditional.cpp<optimize_nest_conditional.cpp-name>` example.\n\n12-11\n=====\nImprove the :ref:`optimize-name` documentation.\nThis includes making examples that demonstrate\nspecific aspects of the optimization; see\n:ref:`forward_active.cpp<optimize_forward_active.cpp-name>` ,\n:ref:`reverse_active.cpp<optimize_reverse_active.cpp-name>` ,\n:ref:`compare_op.cpp<optimize_compare_op.cpp-name>` ,\n:ref:`conditional_skip.cpp<optimize_conditional_skip.cpp-name>` ,\n:ref:`cumulative_sum.cpp<optimize_cumulative_sum.cpp-name>` .\n\n12-09\n=====\nThe :ref:`optimize@options` argument was added to the\noptimize routine.\n\n11-18\n=====\nMove classes and functions that are part of the user API from the\n``cppad/local`` directory to the ``cppad/core`` directory.\nThe remaining symbols, in the ``cppad/local`` directory, are now\nin the ``CppAD::local`` namespace.\nNote that a class in the ``CppAD`` name space, may have a member\nfunction that is not part of the user API.\n\n11-14\n=====\nIncrease the speed of the ``sparse_pack`` class.\nThis improves the speed for\n:ref:`vector of boolean<glossary@Sparsity Pattern@Boolean Vector>`\nsparsity pattern calculations.\n\n11-13\n=====\nMerged in the ``sparse`` branch which has ``const_iterator`` ,\ninstead of ``next_element`` for the\n``sparse_list`` and ``sparse_pack`` classes.\nThese classes are not part of the CppAD API and hence their specifications\ncan change (as in this case).\nThey can be used to get more efficient representations of\n:ref:`sparsity patterns<glossary@Sparsity Pattern>` .\n\n10-27\n=====\nThe optional :ref:`chkpoint_one@optimize` option\nwas added to the checkpoint functions.\n\n10-12\n=====\n\n#. Change :ref:`elapsed_seconds-name` to use\n   ``std::chrono::steady_clock`` instead of\n   ``std::chrono::high_resolution_clock`` .\n#. The test for C++11 features was failing on a Mac system\n   because the elapsed time was returning as zero (between two events).\n   This test has been made more robust by add a one millisecond sleep\n   between the two clock accesses.\n\n09-29\n=====\nThe multiple directions version of\n:ref:`forward<forward_dir-name>` was missing :ref:`erf-name` function\nin the case where C++ 2011 was supported; see\n`issue 16 <https://github.com/coin-or/CppAD/issues/16>`_.\nThis has been fixed.\n\n09-27\n=====\nChange the implementation of :ref:`atomic_two_eigen_cholesky.hpp-name` so that\nthe computation of :math:`M_k` exactly agrees with the corresponding\n:ref:`theory<cholesky_theory-name>` .\n\n09-26\n=====\n\n#. A possible bug in the :ref:`optimize-name` command was fixed.\n   To be specific, a warning of the form\n   indentations;\n\n        ``warning: this`` ``'if'`` ``clause does not guard...`` [ ``-Wmisleading-indentation`` ]\n\n    using the gcc-6.2.1 compiler, was fixed and it may have fixed a bug.\n#. There was a problem with the\n   :ref:`sacado<speed_sacado-name>` where the symbol\n   ``HAS_C99_TR1_CMATH`` was being defined twice.\n   This has been fixed by leaving it up to the sacado install to determine\n   if this symbol should be defined.\n\n09-16\n=====\nFix a problem using the\n:ref:`speed_main@Sparsity Options@colpack` option to the\n``speed_cppad`` program.\n(There was a problem whereby the ``speed_cppad``\nprogram did not properly detect when ``colpack`` was available.)\n\n09-13\n=====\nTest third order and fix\nbug in :ref:`atomic_two_eigen_cholesky.hpp-name` for orders greater\nthan or equal to three.\n\n08-30\n=====\nAdd the :ref:`atomic_two_eigen_cholesky.cpp-name` example.\n\n08-25\n=====\n\n#. Fix some missing include files in\n   ``optimize.hpp`` and ``set_union.hpp``\n   (when compiling with MS Visual Studio 2015).\n#. Fix a warning in ``atanh.hpp``\n   (when compiling with MS Visual Studio 14).\n#. Fix a typo in the\n   :ref:`atomic_two_eigen_mat_inv.hpp@Theory@Reverse` section of the\n   ``eigen_mat_inv.hpp`` example.\n\n07-17\n=====\nAdd documentation for only needing to compute a\n:ref:`sparse_hessian@p@Column Subset` of the sparsity\npattern when computing a subset of a sparse Hessians.\nIn addition, improve the corresponding example\n:ref:`sparse_sub_hes.cpp-name` .\n\n07-14\n=====\nCorrect title in :ref:`ForSparseHes-name` (change Reverse to Forward).\n\n06-30\n=====\nChange the ``atomic_two_mat_mul.cpp`` example so that on atomic object\nworks for matrices of any size.\n(This has since been changed to the :ref:`atomic_three_mat_mul.cpp-name` example.)\n\n06-29\n=====\nChange the :ref:`atomic_two-name` examples so they do no longer use the\ndeprecated interfaces to\n``for_sparse_jac`` , ``rev_sparse_jac`` ,\n``for_sparse_hes`` , and ``rev_sparse_hes`` .\n\n06-27\n=====\n\n#. Improve the :ref:`atomic_two_eigen_mat_mul.hpp-name` and\n   :ref:`atomic_two_eigen_mat_inv.hpp-name` examples.\n   Most importantly, one atomic object now works for matrices of any size.\n#. Add the vector *x* ,\n   that contains the parameters in an atomic function call\n   to the user following atomic functions:\n   :ref:`for_sparse_jac<atomic_two_rev_sparse_jac@Implementation@x>` ,\n   :ref:`rev_sparse_jac<atomic_two_rev_sparse_jac@Implementation@x>` ,\n   :ref:`for_sparse_hes<atomic_two_rev_sparse_jac@Implementation@x>` ,\n   :ref:`rev_sparse_hes<atomic_two_rev_sparse_jac@Implementation@x>` .\n   This enables one to pass parameter information to these functions; e.g.,\n   the dimensions of matrices that the function operates on.\n\n06-25\n=====\nAdd more entries to the optimization\n:ref:`wish_list<wish_list@Optimization>` .\n\n06-10\n=====\nAdd a :ref:`wish_list@check_finite` wish list item.\n\n05-05\n=====\n\n#. Add documentation for redirecting output using:ref:`PrintFor@s`\n   in the ``PrintFor`` function.\n#. Change distributed version to build examples as debug instead\n   of release version.\n   (Was changed to release version while checking for compiler warnings;\n   see ``04-17`` below).\n\n04-17\n=====\nFix all some compiler warnings that occurred when compiling the\n:ref:`examples<Example-name>` with\n:ref:`faq@Speed@NDEBUG` defined.\n\n03-27\n=====\n\n#. Fix a bug in the calculation of the :ref:`atomic_two_eigen_mat_inv.hpp-name`\n   :ref:`atomic_two_eigen_mat_inv.hpp@Private@reverse` example.\n#. Use a very simple method (that over estimates variables) for calculating\n   :ref:`atomic_two_forward@vy` in the :ref:`atomic_two_eigen_mat_inv.hpp-name`\n   :ref:`atomic_two_eigen_mat_inv.hpp@Private@forward` example.\n\n03-26\n=====\n\n#. Implement and test the :ref:`atomic_two_eigen_mat_inv.cpp-name`\n   :ref:`atomic_two_eigen_mat_inv.hpp@Private@reverse` is implemented.\n#. Fix a bug in the calculation of\n   :ref:`atomic_two_forward@vy` in the :ref:`atomic_two_eigen_mat_inv.hpp-name`\n   :ref:`atomic_two_eigen_mat_inv.hpp@Private@forward` example.\n\n03-25\n=====\n\n#. Start construction of the :ref:`atomic_two_eigen_mat_inv.cpp-name` example,\n   currently only\n   :ref:`atomic_two_eigen_mat_inv.hpp@Private@forward` is implemented\n   and tested.\n#. More improvements to :ref:`atomic_two_eigen_mat_mul.cpp-name` example.\n\n03-24\n=====\n\n#. Fix build of ``example/atomic.cpp`` when\n   :ref:`eigen-name` is not available\n   (bug introduced when :ref:`atomic_two_eigen_mat_mul.cpp-name` was added).\n#. Extend :ref:`atomic_two_eigen_mat_mul.cpp-name` example to include\n   :ref:`atomic_two_eigen_mat_mul.hpp@Private@for_sparse_jac` ,\n   :ref:`atomic_two_eigen_mat_mul.hpp@Private@rev_sparse_jac` ,\n   :ref:`atomic_two_eigen_mat_mul.hpp@Private@for_sparse_hes` ,\n   :ref:`atomic_two_eigen_mat_mul.hpp@Private@rev_sparse_hes` .\n#. Fix a bug in the :ref:`ForSparseHes-name` routine.\n#. Edit :ref:`atomic_two_rev_sparse_hes-name` documentation.\n\n03-23\n=====\n\n#. Fix bug in autotools file ``example/atomic/makefile.am``\n   (introduced on 03-22).\n#. Improve the :ref:`atomic_two_eigen_mat_mul.cpp-name` example\n   and extend it to include reverse mode.\n\n03-22\n=====\n\n#. Start construction of the :ref:`atomic_two_eigen_mat_mul.cpp-name` example.\n#. change ``atomic_ode.cpp`` to ``chkpoint_one_ode.cpp`` and\n   ``atomic_extended_ode.cpp`` to ``chkpoint_one_extended_ode.cpp`` .\n\n03-21\n=====\nChange the :ref:`atomic_three_mat_mul.hpp-name` class name from ``mat_mul``\nto ``atomic_mat_mul`` . This example use of the name ``mat_mul``\nin the ``atomic_two_mat_mul.cpp`` example / test.\n(This has since been changed to the :ref:`atomic_three_mat_mul.cpp-name` example.)\n\n03-20\n=====\n\n#. Include the sub-directory name to the include guards\n   in * . ``hpp`` files. For example,\n   ::\n\n        # ifndef CPPAD_UTILITY_VECTOR_HPP\n        # define CPPAD_UTILITY_VECTOR_HPP\n\n    appears in the file ``cppad/utility/vector.hpp`` . This makes it\n    easier to avoid conflicts when choosing :ref:`addon-name` names.\n#. Add the :ref:`set_union-name` utility and use it to simplify the\n   :ref:`atomic-name` examples that use\n   :ref:`glossary@Sparsity Pattern@Vector of Sets`\n   sparsity patterns.\n\n03-19\n=====\n\n#. Move ``atomic_two_mat_mul.cpp`` to ``atomic_mat_mul_xam.cpp``\n   (moved back on :ref:`2016@mm-dd@03-21` .\n#. Move ``atomic_matrix_mul.hpp`` to :ref:`atomic_three_mat_mul.hpp-name` .\n\n03-17\n=====\nAdd the\n``atomic_ode.cpp`` and ``atomic_extended_ode.cpp`` examples.\n\n03-12\n=====\n\n#. Move the example ``reverse_any.cpp`` to :ref:`rev_checkpoint.cpp-name` .\n#. Add the ``chkpoint_one_mul_level.cpp`` example.\n\n03-05\n=====\nThe following atomic function examples were added\nThese examples are for a specific atomic operation.\nIn addition, the domain and range dimensions for these examples\nare not one and not equal to each other:\n``atomic_two_forward.cpp`` ,\n``atomic_two_reverse.cpp`` ,\n``atomic_two_for_sparse_jac.cpp`` ,\n``atomic_two_rev_sparse_jac.cpp`` ,\n``atomic_two_for_sparse_hes.cpp`` ,\n``atomic_two_rev_sparse_hes.cpp`` .\n\n03-01\n=====\n\n#. Improve documentation of implementation requirements for the atomic\n   :ref:`rev_sparse_jac<atomic_two_rev_sparse_jac@Implementation>` .\n#. Make some corrections to the :ref:`atomic_two_for_sparse_hes-name` documentation.\n   and fix a bug in how CppAD used these functions.\n\n02-29\n=====\n\n#. Merged sparse into master branch. This makes the\n   :ref:`ForSparseHes-name` routine available for use.\n#. Changed the\n   :ref:`speed_main@Global Options`\n   in the speed test main program to use one global variable with prototype\n   {xrst_spell_off}\n   {xrst_code cpp}\n       extern std::map<std::string, bool> global_option;\n   {xrst_code}\n   {xrst_spell_on}\n\n02-28\n=====\nFix a mistake in the old atomic\n``example/sparsity/sparsity.cpp`` example.\nThis example has since been changed to\n``atomic_two_set_sparsity.cpp`` .\n\n02-27\n=====\nThe ``--with-sparse_set`` and ``--with-sparse_set`` options\nwere removed from the :ref:`configure-name` install procedure.\n\n02-26\n=====\nThe condition that the operation sequence in *f* is\n:ref:`glossary@Operation@Independent` of\nthe independent variables was added to the statement about\nthe validity of the sparsity patterns; see *x* in\n:ref:`ForSparseJac<ForSparseJac@x>` ,\n:ref:`RevSparseJac<RevSparseJac@x>` , and\n:ref:`RevSparseHes<RevSparseHes@x>` .\n\n02-25\n=====\nThe :ref:`cmake-name` command line argument ``cppad_sparse_list``\nhas been removed (because it is so much better than the other option).\n\n02-23\n=====\nA new version of the\n``cppad_sparse_list`` class (not part of user API) uses\nreference counters to reduce the number of copies of sets that are equal.\nThis improved the speed of sparsity pattern computations that use\nthe :ref:`glossary@Sparsity Pattern@Vector of Sets`\nrepresentation.\nFor example, the results for the\n:ref:`cppad_sparse_hessian.cpp-name` test compare as follows:\n::\n\n    sparse_hessian_size     = [  100,    400,   900,  1600, 2500 ]\n    sparse_hessian_rate_old = [ 1480, 265.21, 93.33, 41.93, 0.86 ]\n    sparse_hessian_rate_new = [ 1328, 241.61, 92.99, 40.51, 3.80 ]\n\nNote that the improvement is only for large problems. In fact,\nfor large problems, preliminary testing indicates that\nthe new vector of sets representation preforms better than\nthe :ref:`vector of boolean<glossary@Sparsity Pattern@Boolean Vector>`\nrepresentation.\n\n01-21\n=====\nFix a ``valgrind`` warning about use of uninitialized memory\nin the test ``test_more/chkpoint_one.cpp`` (the problem was in the test).\n\n01-20\n=====\n\n#. Fix a ``valgrind`` warning about use of uninitialized memory\n   when using the :ref:`adouble<base_adolc.hpp-name>` base type.\n   This required an optional :ref:`base_hash-name` function and the special\n   :ref:`adouble hash_code<base_adolc.hpp@hash_code>` implementation.\n#. The ``adouble`` :ref:`to_string-name` functions\n   required a special implementation; see\n   :ref:`adouble to_string<base_adolc.hpp@to_string>` .\n#. Add the :ref:`base_alloc.hpp@to_string` and\n   :ref:`base_alloc.hpp@hash_code` examples\n   to the ``base_alloc.hpp`` example.\n\n01-18\n=====\n\n#. Fix ambiguity between ``CppAD::sin`` and ``std::sin`` ,\n   and other standard math functions,\n   when using\n   ::\n\n        using namespace std;\n        using namespace CppAD;\n\n    This is OK for simple programs, but not generally recommended.\n    See ``double`` version of base class definitions for\n    :ref:`base_double.hpp@Unary Standard Math`\n    for more details.\n#. Change Eigen array example\n   :ref:`eigen_array.cpp-name`\n   to use member function version of ``sin`` function\n   (as per Eigen's array class documentation).\n\n{xrst_end 2016}\n"
  },
  {
    "path": "appendix/whats_new/2017.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin 2017 app}\n{xrst_spell\n    autotools\n    deallocations\n    doxydoc\n    doxygen\n    readme\n    subgraphs\n    typedef\n    uninitialised\n    valgrind\n    wconversion\n    xq\n}\n\nRelease Notes for 2017\n######################\n\nmm-dd\n*****\n\nAPI Changes\n===========\nSpeed tests no longer automatically compile in release mode; see\n:ref:`speed@debug_which`\n\n12-14\n=====\nAdd the :ref:`subgraph_hes2jac.cpp-name` example\nwhich computes sparse Hessians using subgraphs and Jacobians.\n\n12-08\n=====\nA multi-threading\nwish list item was added.\n\n12-06\n=====\nA :ref:`wish_list-name` item to enable one to iterate through a\n``const`` :ref:`ADFun-name` operation sequence was completed.\nIn addition, the :ref:`abs_normal_fun@f` argument to the\n``abs_normal`` operation was converted to be ``const`` .\n\n12-05\n=====\nThe internal data object used to represent sparsity patterns as\nvectors of integers was improved;\nsee :ref:`for_jac_sparsity@internal_bool`\nin ``for_jac_sparsity`` and other\n:ref:`sparsity_pattern@Preferred Sparsity Pattern Calculations` .\n\n12-04\n=====\nBack out the ``hold_reverse_memory`` option.\n\n12-01\n=====\nThe ``hold_reverse_memory`` option was added.\n\n11-30\n=====\nEdit the :ref:`download-name` instructions.\n\n11-23\n=====\nThe ``ADFun`` function :ref:`optimizer<optimize-name>`\nwas not handling hash code collisions properly.\nTo be specific, only the arguments\nthat were variables where checked for a complete match.\nThe arguments that are constants need to also be checked.\nThis has been fixed.\n\n11-20\n=====\n\n#. Add the :ref:`subgraph_jac_rev-name` method for computing\n   sparse Jacobians.\n#. Add the :ref:`speed_main@Global Options@subgraph` option\n   to the CppAD speed tests.\n\n11-19\n=====\nAdd the :ref:`subgraph_reverse-name` method for computing\nsparse derivatives.\nThis was inspired by the TMB package.\n\n11-15\n=====\n\n#. Add wish list item for :ref:`subgraph sparsity<wish_list@Subgraph@Sparsity>` .\n#. Fix :ref:`cmake_check-name` when :ref:`cmake@include_ipopt`\n   is not present on the cmake command line\n   (make was trying to build some of the ipopt tests).\n\n11-13\n=====\n\n#. Add the :ref:`speed_main@Global Options@hes2jac` option\n   to the CppAD speed tests.\n#. Implement the\n   :ref:`speed_main@Sparsity Options@subsparsity` option\n   for the CppAD :ref:`sparse_hessian<link_sparse_hessian-name>` test.\n#. Fix detection of invalid options in the speed test programs; see the\n   :ref:`global<speed_main@Global Options>` and\n   :ref:`sparsity<speed_main@Sparsity Options>` options.\n\n11-12\n=====\nAdd the :ref:`speed_main@Sparsity Options@subsparsity` option\nto the CppAD speed tests.\n\n11-08\n=====\nAdd the :ref:`subgraph_sparsity-name` method for computing\ndependency and sparsity.\nThis was inspired by the\n`TMB <https://cran.r-project.org/web/packages/TMB/index.html>`_ package.\n\n11-06\n=====\nMore information has been added to the operation sequence.\nTo be specific, the extra amount of\n\n    ``f`` . *size_op* () * *sizeof* ( ``tape_addr_type`` )\n\nwas added to the value returned by\n:ref:`fun_property@size_op_seq` .\n\n11-04\n=====\nThe method for iterating through the tape has been changed.\nIt now includes an extra data structure that makes it faster,\nbut also requires slightly more memory. To be specific, the term\n\n    ``f`` . *size_op* () * *sizeof* ( ``tape_addr_type`` ) * 2\n\nwas added to the value returned by\n:ref:`fun_property@size_op_seq` .\nIn addition, some minor corrections were made to the\n:ref:`tape_addr_type<cmake@cppad_tape_addr_type>`\nrequirements.\n\n10-23\n=====\n\n#. Require ``cmake.3.1`` or greater and fix\n   a cmake warning by always using the new ``CMP0054`` policy.\n#. Fix a ``g++ 7.2.1`` warning about a possibly uninitialized value\n   in the file ``cppad/local/optimize/hash_code.hpp`` .\n\n09-16\n=====\nAn optimization memory entry\nwas added to the wish list\nand the :ref:`wish_list@check_finite` entry was modified.\n\n08-30\n=====\n\n#. If :ref:`colpack_prefix-name` was not specified, one would get the following\n   warning during the :ref:`cmake-name` command:\n\n        ``Policy CMP0046 is not set: Error on non-existent dependency in``\n\n    This has been fixed by not adding the dependency when it is not needed.\n#. There was a problem running :ref:`make check<cmake_check-name>`\n   when :ref:`cmake@cppad_cxx_flags` was not specified.\n   This has been fixed.\n   This was probably introduced on :ref:`2017@mm-dd@05-29` .\n\n08-29\n=====\nThere was a problem on some systems that created an error when\nspecializing the ``is_pod`` template function in the\n``CppAD::local`` namespace.\nThis has been fixed by testing for compatibility at during the\n:ref:`cmake-name` command and creating the file ``cppad/local/is_pod.hpp`` .\n\n08-09\n=====\nAdd the :ref:`wish_list@test_boolofvoid`\nwish list item.\n\n08-08\n=====\n\n#. The :ref:`eigen_plugin.hpp-name` was put back in the\n   :ref:`cppad_eigen.hpp-name` definitions.\n   This makes CppAD incompatible with older versions of eigen; e.g., eigen-3.2.9.\n   The plugin was removed on :ref:`2017@mm-dd@05-12` .\n#. Fix some minor typos in the documentation.\n   To be specific:\n   The font, in the :ref:`sparse_rc-name` and :ref:`sparse_rcv-name` syntax,\n   for the text\n\n        *target* = *pattern*\n\n    The font, in :ref:`capacity_order-name` , for the text\n\n        *xq* . ``size`` () == *f* . ``Domain`` ()\n\n    Remove a percent sign ``%`` , in :ref:`CppAD_vector-name` , in the text\n\n        # ``include <cppad/utility/vector.hpp>``\n\n07-25\n=====\n\n#. Fix warnings related to type conversions that\n   occurred when one used ``-Wconversion`` with\n   ``g++`` version 6.3.1.\n#. The warning were not fixed for complex AD types; e.g.,\n   :ref:`complex_poly.cpp-name` .\n   The :ref:`wno_conversion-name` include file was added to deal with\n   cases like this.\n\n07-03\n=====\n\n#. The :ref:`min_nso_linear-name` abs-normal example was added.\n#. Fix bug in :ref:`abs_normal_fun-name` , to be specific, the multiplication\n   of a variable on the left by a parameter was not handled.\n\n07-01\n=====\nthe :ref:`abs_normal<example_abs_normal-name>` examples were converted from using\nquadratic programming problems to using linear programming problems.\n\n06-28\n=====\nThe :ref:`abs-normal<abs_normal_fun-name>`\nrepresentation of non-smooth functions has been added.\nExamples and utilities that use this representation have also been included,\nsee :ref:`abs_normal<example_abs_normal-name>` .\n\n06-11\n=====\nThe atomic functions base class :ref:`atomic_two-name`\nmakes more of an effort to avoid false sharing cache misses.\nThis may the speed of multi-threaded applications with atomic functions;\ne.g., see :ref:`multi_atomic_two.cpp-name` .\n\n06-10\n=====\n\n#. Add the multi-threading atomic function example\n   :ref:`multi_atomic_two.cpp-name` .\n#. The ``example/multi_thread/test_multi`` directory used\n   to have an example using the deprecated\n   :ref:`atomic_one-name` functions in a multi-threading setting\n   (that only built with the deprecated :ref:`configure-name` ).\n   This have been removed.\n\n06-07\n=====\nThe multi-threading examples\n:ref:`harmonic.cpp-name` and :ref:`multi_newton.cpp-name` were re-organized.\nTo be specific, the source code for each example was moved to one file.\nIn addition, for each example,\nthe documentation for each of the routines has been separated\nand placed next to its source code.\n\n06-04\n=====\nMost all the :ref:`deprecated-name` features have been removed\nfrom the examples with the exception of those in the\n``example/deprecated`` directory.\n\n06-03\n=====\nAdd the fact that the pair\n( *row* , :ref:`link_sparse_hessian@col` )\nis lower triangular to the speed test\n``link_sparse_hessian`` routine.\n\n06-01\n=====\n\n#. There was a bug in the\n   :ref:`sparse_hes-name` routine and it was using the general coloring algorithm when\n   :ref:`sparse_hes@coloring@cppad.symmetric` was specified.\n   This has been fixed and improves the efficiency in this case.\n#. Some bugs were fixed in the use of\n   :ref:`colpack<colpack_prefix-name>` as the coloring algorithm for\n   sparse Jacobian and Hessian calculations.\n   This has improved the efficiency of Colpack colorings for computing Hessians\n   (when ``colpack.symmetric`` is used).\n#. The ``colpack.star`` coloring method for sparse Hessians has\n   been deprecated; see\n   :ref:`sparse_hes<sparse_hes@coloring@colpack.star Deprecated 2017-06-01>`\n   and\n   :ref:`sparse_hessian<sparse_hessian@work@colpack.star Deprecated 2017-06-01>` .\n   Use the ``colpack.symmetric`` method instead; see\n   :ref:`sparse_hes<sparse_hes@coloring@colpack.symmetric>` and\n   :ref:`sparse_hes<sparse_hes@coloring@colpack.general>` .\n\n05-29\n=====\n\n#. Add the capability to compile so that CppAD debug and release mode\n   can be mixed using ``CPPAD_DEBUG_AND_RELEASE`` .\n#. Add the :ref:`cmake@cppad_debug_which` flags\n   that determines which files are compiled for debugging versus release\n   during the CppAD testing; see :ref:`cmake_check-name` .\n#. There was a problem linking the proper libraries for using newer versions of\n   :ref:`sacado<sacado_prefix-name>` .\n   This has been fixed.\n\n05-19\n=====\nMost all the examples have been moved to ``example`` directory\nand grouped as sub-directories; e.g., the :ref:`ipopt_solve-name` examples\nare in the ``example/ipopt_solve`` directory.\n\n05-14\n=====\n\n#. The file ``build.sh`` was moved to ``bin/autotools.sh`` ,\n   and `auto tools' has been changed to :ref:`configure-name` .\n#. The README file was replace by readme.md\n   and AUTHORS was moved to authors.\n#. The NEWS, INSTALL, and ChangeLog files\n   are no longer necessary for autotools build and have been removed.\n#. The file test_more/sparse_jacobian.cpp generated a warning\n   under some gcc compiler options.\n   This has been fixed.\n#. Specifications were added so that :ref:`to_string-name` yields exact results\n   for integer types and machine precision for floating point types.\n#. Some editing was done to the :ref:`configure-name` instructions.\n\n05-12\n=====\n\n#. The :ref:`Faq-name` has been updated.\n#. Remove includes of ``cppad/cppad.hpp`` from the\n   ``include/cppad/speed/`` * . ``hpp`` files.\n   This avoids an incompatibility between sacado and newer versions of eigen,\n   when eigen is used for the :ref:`testvector-name` .\n#. The :ref:`eigen-name` package changed its requirements for\n   defining Scalar types\n   (some where between eigen-3.2.9 and eigen-3.3.3).\n   The member variable\n   :ref:`digit10<numeric_limits@digits10>` was added to the\n   ``numeric_limits`` to accommodate this change.\n#. Note that this fix required adding ``digits10`` to the\n   user defined *Base* type\n   :ref:`requirements<base_require-name>` ; see\n   :ref:`base_limits-name` .\n#. In addition, it is no longer necessary to add the typedef\n\n        ``typedef Scalar value_type`` ;\n\n    so the file ``cppad/example/eigen_plugin.hpp`` has been removed.\n    (This type definition was previously necessary for eigen vectors\n    to be :ref:`simple vectors<SimpleVector-name>` .)\n\n04-08\n=====\nThe :ref:`optimization<optimize-name>` , with a large number of\n:ref:`conditional expressions<CondExp-name>` , was performing many\nmemory allocations and deallocations. This has been reduced.\n\n04-02\n=====\nFix a bug in the optimization of conditional expressions; see,\n:ref:`optimize@options@no_conditional_skip` .\n\n03-31\n=====\nFix some ``valgrind`` errors that occurred while running the CppAD\ntest set.\n\n03-29\n=====\nThe following valgrind error might occur when the optimize skipped\nsetting values that did not affect the dependent variables:\n\n    ``Conditional jump or move depends on uninitialised value`` ( ``s`` )\n\nThis was not a bug, the code has been changed to avoid this error\nin order to make it easier to use valgrind with CppAD.\n\n03-25\n=====\n\n#. The :ref:`sparse_hes-name` function was more efficient if\n   there were more entries in each row of the requested\n   :ref:`sparse_hes@subset` . This has been changed\n   to more entries in each column, and documentation to this effect\n   was included.\n#. The :ref:`optimize-name` routine was using to much memory when\n   it was optimizing conditional skip operations; see\n   :ref:`optimize@options@no_conditional_skip` .\n   This has been fixed.\n\n03-20\n=====\nThere was a mistake in :ref:`sparse_jac-name` that caused the\nfollowing assert to mistakenly occur:\n::\n\n    sparse_jac_rev: work is non-empty and conditions have changed\n    Error detected by false result for\n    color.size() == 0 || color.size() == n\n\nA test that using a previously stores work vector\nhas been added to :ref:`sparse_jac_rev.cpp-name`\nand this bug has been fixed.\n\n03-13\n=====\nThe documentation for the Hessian in :ref:`rev_hes_sparsity-name` was\ntransposed; i.e., the sense of\n:ref:`rev_hes_sparsity@transpose` was reversed.\n\n03-11\n=====\nAdd sparse assignment statements; see *other* for\n:ref:`sparse_rc<sparse_rc@other@Assignment and Constructor>` and\n:ref:`sparse_rcv<sparse_rcv@other@Assignment and Constructor>` .\n03-10\n=====\nAdd the a sizing constructor to the\n:ref:`sparse_rc syntax<sparse_rc@Syntax>` ; i.e.,\na constructor that sets the number of row, number of columns,\nand number of possibly non-zero values in the sparsity pattern.\n\n03-06\n=====\nFix a bug in the sparsity computation using the\ninternal representation for\n:ref:`vectors of sets<glossary@Sparsity Pattern@Vector of Sets>` ;\ni.e., when *internal_bool* was false in\nany of the :ref:`sparsity_pattern-name` calculations; e.g.,\n:ref:`for_jac_sparsity<for_jac_sparsity@internal_bool>` .\n\n03-04\n=====\nFix a bug in the optimization of conditional expressions;\nsee :ref:`optimize@options@no_conditional_skip` .\n\n02-26\n=====\n\n#. Fix warning during :ref:`cmake-name` command,\n   on `cygwin <https://www.cygwin.com/>`_ systems,\n   about ``WIN32`` not being defined.\n#. Add element-wise atomic operations to the wish list.\n   This was completed by the :ref:`atomic_four_vector-name` example.\n\n02-21\n=====\n\n#. Minor improvements to syntax and documentation for\n   :ref:`sparse_rc-name` and :ref:`sparse_rcv-name` .\n#. Separate preferred sparsity versions in\n   :ref:`sparsity_pattern-name` and :ref:`sparse_derivative-name` .\n\n02-19\n=====\n\n#. Remove the ``bool_sparsity.cpp`` example and\n   add the :ref:`rc_sparsity.cpp-name` example.\n#. Check for duplicate entries during\n   :ref:`sparse_rc@row_major` and ``col_major`` in\n   ``sparse_rc`` .\n\n02-15\n=====\nFix bug when using :ref:`ForSparseHes-name` with atomic functions; i.e.,\n:ref:`atomic_two_for_sparse_hes-name` .\n\n02-13\n=====\nImprove :ref:`atomic_two_eigen_mat_mul.hpp@Private@for_sparse_jac`\ncalculation in ``eigen_mat_mul.hpp`` example.\nIt now checks for the parameter zero and does not propagate any sparsity\nin this case (because the result is always zero).\n\n02-11\n=====\n\n#. Remove the 'Under Construction' heading from the\n   :ref:`sparse_rc-name` and :ref:`sparse_rcv-name` documentation; i.e.,\n   they are ready for public use (part of the CppAD API).\n#. Fix some warning that occur when using\n   :ref:`cppad_testvector@eigen` for the CppAD test vector.\n   (The Eigen vector ``size()`` function\n   returns an ``int`` instead of ``size_t`` .)\n#. Fix a bug in :ref:`sparse_jac_rev<sparse_jac-name>` .\n\n02-10\n=====\n\n#. The subset of deprecated features corresponding to\n   the cmake command option ``cppad_deprecated=YES``\n   have been completely removed.\n#. Fix problems with :ref:`configure-name` build\n   (started near 02-01 while working on sparsity branch).\n#. Reorder (better organize) the :ref:`ADFun-name` documentation section.\n\n02-09\n=====\n\n#. Remove the sparsity pattern wish list item.\n   For sparsity patterns, this was completed by\n   :ref:`sparse_rc-name` and the sparsity pattern routines that used it;\n   e.g., :ref:`for_jac_sparsity-name` .\n   For sparse matrices, it was completed by\n   :ref:`sparse_rcv-name` and the sparse matrix routines that use it; e.g.,\n   :ref:`sparse_jac-name` .\n#. Add the Deprecated and\n   :ref:`wish_list@Example` items to the wish list.\n   (The Deprecated item was partially completed and partially removed.)\n\n02-08\n=====\n\n#. Make coloring a separate argument to\n   :ref:`sparse_jac<sparse_jac@coloring>` and\n   :ref:`sparse_hes<sparse_hes@coloring>` .\n#. Add the\n   :ref:`sparse_jac@group_max`\n   argument to the ``sparse_jac_for`` function.\n\n02-05\n=====\n\n#. Add the :ref:`sparse_jac_for<sparse_jac-name>` routine\n   which uses :ref:`sparse_rc-name` sparsity patterns\n   and :ref:`sparse_rcv-name` matrix subsets.\n#. Order for :ref:`sparse_rc-name` row-major and column-major was switched.\n   This has been fixed.\n\n02-03\n=====\nAdd the\n:ref:`rev_jac_sparsity-name`\n:ref:`rev_hes_sparsity-name` , and\n:ref:`for_hes_sparsity-name` interfaces to sparsity calculations.\nThese use :ref:`sparse_rc-name` sparsity patterns.\n\n02-02\n=====\nChange :ref:`for_jac_sparsity@f@size_forward_bool` and\nChange :ref:`for_jac_sparsity@f@size_forward_set`\nso that they are a better approximation of the number of bytes\n(unsigned characters) being used.\nThe exact same sparsity pattern might use different memory\nin two different function objects (because memory is allocated in chunks).\nThe :ref:`fun_assign.cpp-name` example has been changed to reflect this fact.\n\n02-01\n=====\nAdd the :ref:`for_jac_sparsity-name` interface for the sparse Jacobian calculations.\nThis is the first use of :ref:`sparse_rc-name` ,\na sparsity pattern class that uses row and column\n:ref:`index vectors<glossary@Sparsity Pattern@Row and Column Index Vectors>` .\n\n01-30\n=====\nMove the :ref:`sparsity_pattern-name` examples from ``example``\nto ``example/sparse`` subdirectory.\nThis included the sparse :ref:`driver<drivers-name>` examples.\n\n01-29\n=====\nMove the :ref:`utility-name` examples from ``example``\nto ``example/utility`` subdirectory.\n\n01-27\n=====\nAdd a :ref:`addon-name` link to\n`cppad_swig <https://github.com/bradbell/cppad_swig>`_ ,\na C++ AD object library and swig interface to Perl, Octave, and Python.\n\n01-19\n=====\nConvert more examples / tests to use a multiple of machine epsilon\ninstead of ``1e-10`` .\n\n01-18\n=====\n\n#. Fix developer\n   `doxydoc <https://www.coin-or.org/CppAD/Doc/doxydoc/html/>`_\n   documentation so that it works with newer version of doxygen.\n#. Fix a Visual C++ 2015 compilation problem in friend declarations\n   in the file ``cppad/local/ad_tape.hpp`` .\n\n01-17\n=====\nChange computed assignment to\n:ref:`compound assignment<compound_assign-name>` .\n\n{xrst_end 2017}\n"
  },
  {
    "path": "appendix/whats_new/2018.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin 2018 app}\n{xrst_spell\n    addons\n    enums\n    eps\n    in in\n    kasper\n    kristensen\n    mingw\n    rcv\n    tmb\n    valgrind\n    wconversion\n    wfloat\n}\n\nRelease Notes for 2018\n######################\n\nmm-dd\n*****\n\n12-30\n=====\nOn :ref:`2018@mm-dd@12-12` the directory\n``cppad`` was moved to ``include/cppad`` .\nThe ``make install`` step of the\n:ref:`install-name` instructions did not work after that.\nThis has been fixed.\n\n12-23\n=====\nThe documentation for how to run\n``multi_atomic_two`` was missing.\nThis has been fixed.\n\n12-17\n=====\nKeep the documentation for :ref:`deprecated-name` features,\nbut remove their examples.\nThe documentation is intended to help conversion\nto using features that have not been deprecated.\n\n12-16\n=====\nAdd ``bin/check_tab.sh`` and remove some remaining tab characters\nthat it found in the CppAD source code.\n\n12-15\n=====\nFix name for special version of ``cmake`` required by\n:ref:`cmake@CMake Command@msys2` ,\n``mingw-w64-x86_64-cmake`` .\n\n12-12\n=====\n\n#. Change tabs to spaces in both the source code and the examples.\n#. The ``inline`` specifiers was removed from template functions\n   and class member functions in both the source code and examples; see\n   the ``inline`` entry in the\n   :ref:`wish_list<wish_list@cppad_lib@inline>` .\n#. In the documentation and examples change the ``Vector`` *Type*\n   to *Type* ``Vector`` for *Type* denoting various types; e.g.,\n   ``Bool`` , ``Size`` , ``Double`` , ...\n#. Change the :ref:`license-name` to be ``EPL-2.0``\n   with a ``GPL-2.0`` or later alternative\n   (so one version of the source code can be used for both EPL\n   and GPL licenses).\n#. Change :math:`B^n` to :math:`\\B{R}^n` when referring to the vector\n   space that :ref:`ADFun-name` object refer to.\n   (Note that this may not be real vectors; e.g., :ref:`base_complex.hpp-name` .)\n#. Move the ``cppad`` sub-directory to ``include/cppad`` .\n#. Add a checkpoint constructor item to the wish list.\n   This has been completed; see the\n   :ref:`chkpoint_two_ctor@fun` argument to the\n   second generation checkpoint constructor.\n\n11-13\n=====\n\n#. There was a problem using\n   :ref:`elapsed_seconds-name` with the Microsoft Visual Studio compiler.\n   To be specific, ``microsoft_timer`` could be an undefined external.\n   This has been fixed.\n#. The ``# define NOMINMAX`` command was placed before\n   ``# include <windows.h>``\n   so that ``std::min`` and ``std::max`` work properly.\n   (This only matters when using the Visual Studio compiler.)\n#. For some unknown reason, the Microsoft Visual Studio compiler\n   was giving a senseless error at the variable name ``small`` .\n   This has been changed to ``eps`` in :ref:`interface2c.cpp-name` .\n#. The deprecated :ref:`cmake@CMake Command@autotools`\n   was fixed to work with the current version of CppAD.\n#. Fix a warning in ``test_more/cppad_for_tmb/multi_atomic_two.cpp``\n   when using boost vectors for testing.\n\n11-11\n=====\nFix a warning in ``test_more/cppad_for_tmb/multi_chkpoint_one.cpp``\nwhen using boost vectors for testing.\n\n11-06\n=====\nThe initial\n:ref:`size_order-name` is now zero for an :ref:`base2ad@af` created using\nthe ``base2ad`` feature.\n\n11-04\n=====\n\n#. The :ref:`cmake@CMake Command@Simple` version of the cmake command\n   is now suggested as a starting point installing CppAD.\n#. The windows install procedure has been fixed; see\n   :ref:`cmake@CMake Command@msys2` and\n   :ref:`cmake@CMake Command@Visual Studio` .\n#. The Visual Studio compiler gave a warning because the\n   ``get_record_compare`` (not in use API)\n   was returning ``size_t`` when\n   it should have returned a ``bool`` .\n   It also gave a warning in ``test_more/general/erf.cpp``\n   about conversion from ``double`` to ``size_t`` .\n   These have been fixed.\n#. The Visual Studio compiler also gave an error because it requires\n   the :ref:`ADFun-name` copy constructor for assignment to\n   a :ref:`base2ad-name` result.\n   This copy constructor has been allowed (but only for this case).\n#. The Visual Studio compiler does not seem to be able to mix\n   debug and release code. One of the tests had to be modified\n   enable the user to avoid this; see\n   :ref:`cmake@CMake Command@Visual Studio` .\n\n11-01\n=====\nThere was a bug in the\n:ref:`checkpoint<chkpoint_one-name>` functions with multiple threads\n(see :ref:`2018@mm-dd@10-29` below).\nThis has been fixed.\n\n10-31\n=====\n\n#. The items in the :ref:`wish_list-name` were re-organized\n   so that the New Atomic API entries\n   were all under one heading.\n#. A credit to Kasper Kristensen was added to the\n   :ref:`subgraph<research@Sparsity@Subgraphs>` research item.\n\n10-29\n=====\nThe following is a list of changes to the documentation:\n\n#. The :ref:`theory-name` section was moved\n   to a higher level in the documentation and the\n   :ref:`introduction-name` we put in that section.\n#. The :ref:`wish_list-name` section was brought up to date\n   and the :ref:`research-name` section was added.\n#. Some of the links to the CppAD :ref:`addons<addon-name>` section were broken.\n   This has been fixed.\n#. The wish list entries for the following items were removed\n   because they were completed:\n   :ref:`base2ad-name` ,\n   :ref:`checkpoint<chkpoint_one-name>` functions now work with\n   :ref:`multiple threads<multi_thread-name>` ,\n   the :ref:`optimize-name` memory usage has been reduced.\n#. The operations sequence wish list entry was changed to\n   the Constant entry which has since been completed; see\n   :ref:`con_dyn_var@Constant` .\n   The software guidelines entry was changed to just\n   Convert Tabs to Spaces.\n\n10-25\n=====\n\n#. There was bug in :ref:`f.optimize<optimize-name>`\n   when *f* has :ref:`dynamic parameters<new_dynamic-name>` .\n   This has been fixed.\n#. Fix warning, from old ``gcc`` compilers, that\n   ``-Wfloat-conversion`` and ``-Wfloat-conversion``\n   are not valid options.\n#. Instructions for obtaining GPL distribution were added near the\n   top of the :ref:`home page<user_guide-name>` .\n\n10-24\n=====\nThe new :ref:`user_guide-name` home pages has been edited to be a better\nintroduction to CppAD.\nIn addition, more discussion was added to the :ref:`get_started.cpp-name`\nexample.\n\n10-19\n=====\nThe speed tests for the deprecated\n:ref:`cppad_ipopt_nlp-name` now use the\n:ref:`cmake@cppad_debug_which` flag\nin the same was as other test\n(not always true).\n\n10-18\n=====\nCppAD is now including the ``-Wconversion`` in its compilation.\nThis results in warnings in more of the optional packages and so\ntheir include files are compiled like system files (without warnings);\nsee :ref:`cmake@package_prefix` .\n\n09-25\n=====\nFunctions *af* ,\ncreated by :ref:`af = f.base2ad<base2ad-name>` ,\ncould not use :ref:`af.Jacobian<Jacobian-name>` .\nThis has been fixed.\n\n09-23\n=====\nThe :ref:`checkpoint<chkpoint_one-name>` functions did not work with functions that\nwere created using :ref:`base2ad-name` .\nThis has been fixed.\n\n09-22\n=====\nThere was a bug in the :ref:`checkpoint<chkpoint_one-name>` function when they\nwere used in :ref:`in parallel mode<ta_parallel_setup-name>` .\nThe :ref:`multi_chkpoint_one.cpp-name` example was added\nto test this and demonstrate use of checkpoints in parallel mode.\n\n09-19\n=====\nAdd the :ref:`base2ad-name` capability.\nThis creates a function that computes using ``AD`` < *Base* >\nobjects from one that computes using *Base* objects.\nThis enables one to record any derivatives computations as part of another\nfunction and thereby removes the need for\n:ref:`multiple levels of AD<mul_level-name>` .\nFor example, compare :ref:`base2ad.cpp-name`\nwith :ref:`mul_level_ode.cpp-name` .\n\n09-17\n=====\nCreate a section with just the\n:ref:`atomic_two-name` specifications\nand another with the :ref:`atomic examples<atomic_two_example-name>` .\n\n09-16\n=====\nThe ``taylor_ode.cpp`` example was moved to :ref:`taylor_ode.cpp-name`\nand changed to use the same notation as :ref:`taylor_ode-name` .\n\n09-15\n=====\n\n#. Add a :ref:`fun_construct@Assignment Operator@Move Semantics`\n   version of the function assignment operator.\n#. Move AD theory for using Taylor's method to solve an ode to the separate\n   section :ref:`taylor_ode-name` .\n\n08-27\n=====\n\n#. Add a discussion about\n   :ref:`Independent@dynamic@Efficiency` for dynamic parameters.\n#. In a comment in the :ref:`new_dynamic.cpp-name` example,\n   change 'independent dynamic parameters' to 'dynamic parameter'.\n#. The :ref:`cppad_eigen.hpp@eigen_vector` class was moved\n   out of the global namespace to the CppAD namespace.\n   This class was recently introduced (:ref:`2018@mm-dd@08-12` )\n   and so this change to the API should be easy to fix in user code.\n\n08-19\n=====\n\n#. Fix dynamic parameter arguments to\n   :ref:`discrete-name` functions.\n#. Fix some detection of identically zero and one\n   for dynamic parameters.\n#. Fix an access of invalid memory during :ref:`new_dynamic-name` .\n#. Add optimization of dynamic parameters during :ref:`f.optimize<optimize-name>` .\n\n08-18\n=====\n\n#. Fix some remaining clang warnings.\n#. Fix :ref:`Integer-name` and :ref:`unary minus<unary_minus-name>` for\n   :ref:`glossary@Parameter@Dynamic` parameters.\n\n08-17\n=====\nFix :ref:`compound assignment<compound_assign-name>` operators\nwhere left operand is a\n:ref:`glossary@Parameter@Constant` parameter\nand right operand is a\n:ref:`glossary@Parameter@Dynamic` parameter.\n\n08-16\n=====\nFix :ref:`compound assignment<compound_assign-name>` operators\nwhere left operand is a\n:ref:`glossary@Parameter@Dynamic` parameter.\nand right operand is a\n:ref:`glossary@Variable` .\n\n08-14\n=====\nFix :ref:`compound assignment<compound_assign-name>` operators\nwhere both operands are parameters and one is a\n:ref:`glossary@Parameter@Dynamic` parameter.\n\n08-13\n=====\nFix conversion warnings generated by the\nversion 6.0 of the ``clang++`` compiler.\n\n08-12\n=====\nAdd the :ref:`cppad_eigen.hpp@eigen_vector`\nwrapper class so that an ``eigen_vector`` is a true\n:ref:`SimpleVector-name` ; i.e., it using ``size_t``\ninstead of ``Eigen::Index`` for its sizes and indices.\n\n08-10\n=====\nExtend the CppAD vector class to enable\n:ref:`CppAD_vector@Element Access`\nusing any index type that has a conversion to the type ``size_t`` .\n\n08-08\n=====\n\n#. Fix a bug in the ``CppAD::local::pod_vector`` template class\n   (not part of the user API) that wasted memory.\n   This bug was part of the :ref:`2018@mm-dd@06-04` change this year.\n#. Fix very recent bug in the optimization of dynamic parameters\n   in :ref:`PrintFor-name` statements.\n#. Fix some ``valgrind`` warnings about use of values that have\n   not be initialized or set.\n#. Suppress printing of :ref:`PrintFor-name` operations\n   during the :ref:`optimize-name` process.\n\n08-05\n=====\nThe amount of memory in an operation sequence has changed; see\n:ref:`f.size_op_seq<fun_property@size_op_seq>` .\n\n08-04\n=====\nRemove the restrictions on dynamic parameters.\nThey can now be used anywhere except as indices and values in\nVecAD vectors.\n(This was fixed on :ref:`2019-01-06<2020@mm-dd@01-06>` .)\n\n07-30\n=====\n\n#. The :ref:`con_dyn_var@Constant` function was added.\n#. :ref:`base_require@API Warning`\n   for uses who define there own *Base* type.\n   The function ``IdenticalPar`` was changed to\n   :ref:`base_identical@Identical@IdenticalCon`\n   and ``IdenticalEqualPar`` was change to\n   ``IdenticalEqualCon`` .\n   This was done because the value of\n   :ref:`glossary@Parameter@Dynamic` parameters can change.\n#. The some errors in the :ref:`pkgconfig-name` files\n   ``cppad.pc`` and ``cppad-uninstalled.pc`` were\n   corrected.\n\n07-27\n=====\nWe are adding the dependent dynamic parameters; i.e.,\nparameters that depend on the independent\n:ref:`Independent@dynamic` parameters\nin a call to Independent.\nFor this reason the function\n*f* . ``size_dynamic`` () has been replaced by\n:ref:`fun_property@size_dyn_ind` ,\n:ref:`fun_property@size_dyn_par` , and\n:ref:`fun_property@size_dyn_arg` .\n\n07-23\n=====\nChange the required version of :ref:`cmake-name` from greater than\nor equal 3.1 to greater than or equal 2.8.4.\n\n07-18\n=====\nFix a bug (introduced on :ref:`2018@mm-dd@07-02` )\nin :ref:`optimize-name` routine when dynamic parameters are present.\n\n07-02\n=====\nAdd a special type of parameter that can change value,\nsee :ref:`new_dynamic@Purpose` for dynamic parameters.\n\n06-27\n=====\nSimplify the process in the :ref:`optimize-name` procedure\nwhere it recognizes identical expressions\n(and do more error checking of this process).\nThis may speed up the optimization for large cases where\nmultiple expressions have the same hash code.\n\n06-22\n=====\nAdd an :ref:`wish_list@Abs-normal` wish list item.\n\n06-20\n=====\nWorked more on reducing memory and increasing the speed of the\n:ref:`optimization<optimize-name>` of ``ADFun`` < *Base* > objects.\n\n06-19\n=====\nAnother (smaller) reduction in the amount of extra memory used during the\n:ref:`optimize-name` process.\nThis time a vector of length\n:ref:`fun_property@size_op` was converted from the type\nused for C++ enums to a type that only used one byte.\n\n06-13\n=====\nReduce the amount of extra memory used during the :ref:`optimize-name` process.\nTo be more specific, two vectors that were separate now share the same memory.\nThese vectors have size equal to\n:ref:`fun_property@size_op`\nfor the old operation sequence, and element type\n:ref:`cmake@cppad_tape_addr_type` .\n\n06-12\n=====\nThere was false sharing in the\nhash table used to detect identical parameter values during\nthe recording of ``AD`` < *Base* > operations.\nThis has been fixed and should result in a speed up when multiple\nthreads are recording at the same time.\n\n06-04\n=====\nThe memory used during\n:ref:`subgraph_reverse-name` , :ref:`subgraph_sparsity-name` , and\n:ref:`optimize-name` was changed to use the smallest addressing type possible\nfor the tape in question.\nTo be specific the smallest type from the set\n``unsigned short`` ,\n``unsigned int`` ,\n``size_t`` , in that order.\n\n05-29\n=====\nThe :ref:`configure-name` install procedure was not working since 05-26.\nThis has been fixed.\n\n05-28\n=====\n\n#. The Coin download page is not longer supporting monthly version.\n   These versions are now supported by the\n   :ref:`download@Git`\n   download procedure.\n#. The windows install procedures have not been kept up to date\n   and so have been removed.\n   It has since been fixed; see\n   :ref:`cmake@CMake Command@msys2` and\n   :ref:`cmake@CMake Command@Visual Studio` .\n\n05-26\n=====\nFix some warnings when testing with ``g++ -std=c++98`` .\n\n05-20\n=====\n\n#. The amount of memory used to store each operator was changed from\n   the size of an enum type to the size of an ``unsigned char`` ; i.e.,\n   one byte.\n   This changed ``CppAD::local::OpCode`` to\n   ``CPPAD_VEC_ENUM_TYPE`` in the expression used to compute\n   :ref:`size_op_arg<fun_property@size_op_seq>` .\n   Note ``CPPAD_VEC_ENUM_TYPE`` is not in CppAD API and may change.\n#. There was a bug in the call to ``optimize`` for the CppAD\n   :ref:`speed_cppad-name` tests.\n   To be specific ``no_print_for`` was corrected to\n   :ref:`no_prior_for_op<optimize@options@no_print_for_op>` .\n\n05-17\n=====\nThe memory report for the CppAD matrix multiply speed test was changed\nto report the memory before clearing the atomic functions; see the end of\n:ref:`cppad_mat_mul.cpp-name` .\n\n05-04\n=====\nThe comparison operations were changed on\n:ref:`2015-01-20<2015@mm-dd@01-20>` when the\n:ref:`Independent@abort_op_index` option was added.\nThis change caused a slow down CppAD\nbecause the :ref:`compare-name` operators used to not be recorded when\n``NDEBUG`` was defined.\nThe :ref:`Independent@record_compare` option has been\nadded so that one can obtain this better performance\n(when one does not need  the :ref:`compare_change-name` function\nor the :ref:`Independent@abort_op_index` feature).\n\n05-03\n=====\nThe following was merged in from the ``reduce_tape`` branch:\nA change was made in the way CppAD iterated over the operation sequence\nwhen subgraph operations were first added; see the heading\n:ref:`2017@mm-dd@11-20` in whats new for 2017.\nThis caused CppAD to always use more memory for storing tapes.\nThis has been fixed so this extra memory is only allocated when it is needed.\nIn addition it can be freed; see\n:ref:`fun_property@size_random` and\n:ref:`subgraph_reverse@clear_subgraph` .\nIn addition, this changed the amount of memory returned by\n:ref:`fun_property@size_op_seq` so that it\nno longer includes the part returned by ``size_random`` .\n\n04-29\n=====\nChange the :ref:`cppad_sparse_hessian.cpp-name` speed test to support the\n:ref:`speed_main@Sparsity Options@symmetric` option\nfor sparsity calculations.\nThis was added because, even though the symmetric sparsity patterns\nare more efficient, they seem to take longer to calculation\nand hence general sparsity patterns may be faster; see the sparse hessian\n:ref:`sparse_hessian@work@color_method` .\n\n04-13\n=====\nThe :ref:`speed_cppad-name` tests were modified to report the\namount of memory allocated at the end of each tests.\nThis will aid in the reduction of CppAD memory usage.\n\n03-20\n=====\nFix bug in :ref:`optimize-name` and :ref:`subgraph_sparsity-name`\nwhen using C++11 :ref:`erf-name` function.\n\n03-19\n=====\nAdd more detail to the dynamic parameter wish list item.\nThis item has been implemented and removed from the wish list; see\n:ref:`new_dynamic-name` .\n\n03-04\n=====\nThe ``example/abs_normal`` directory was missing from the\n:ref:`example<directory@Example Directory>` sub-directory list.\nThis has been fixed.\n\n03-02\n=====\nAdd the :ref:`sparse_rcv@pat` member function to\nthe ``sparse_rcv`` template class.\n\n02-27\n=====\nDocumentation was added to state that the *work* structure for\n:ref:`sparse_jac<sparse_jac@work>` ( :ref:`sparse_hes<sparse_hes@work>` )\ncan be used a different *f* and a different *subset*\nprovided that Jacobian (Hessian) sparsity pattern for *f*\nand the sparsity pattern in *subset* are the same.\n\n02-26\n=====\nThe routine :ref:`sparse2eigen-name` , added on 02-20, only worked\nwhen the values in the matrix were integers.\nThis bug has been fixed.\n\n02-23\n=====\nThe syntax for some of the :ref:`utility-name` files were missing the\n``# include`` command (or just the ``#`` in the include command);\ne.g., see the\n:ref:`set_union@Syntax` for the ``set_union`` utility.\n\n02-20\n=====\nAdd the utility function :ref:`sparse2eigen-name` .\n\n{xrst_end 2018}\n"
  },
  {
    "path": "appendix/whats_new/2019.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin 2019 app}\n{xrst_spell\n    autotools\n    bthread\n    cholesky\n    colpack\n    goto\n    inv\n    lepp\n    mmdd\n    omhelp\n    pos\n    subgraphs\n    to to\n    usr\n    versa\n    yy\n}\n\nRelease Notes for 2019\n######################\n\nmm-dd\n*****\n\n12-27\n=====\n\n#. Add the :ref:`graph_op_enum@Print`\n   operator to the :ref:`cpp_ad_graph-name` and :ref:`json_ad_graph-name` ; see\n   :ref:`graph_print_op.cpp-name` , :ref:`json_print_op.cpp-name` .\n#. Improve the error messaging when a Json\n   :ref:`json_ad_graph@op_define_vec@op_code` in the\n   operator definition section does not start with one\n   and increment by one between definitions.\n\n12-25\n=====\n\n#. Change *pos* to :ref:`PrintFor@notpos`\n   in the ``PrintFor`` documentation because the text is printed\n   when it is not positive.\n#. Add C++ graph member functions that :ref:`cpp_graph_vector@Syntax@Find`\n   the index for an atomic or discrete function.\n\n12-24\n=====\n\n#. Add the :ref:`discrete function<json_graph_op@Discrete Functions>`\n   operator to the :ref:`json_ad_graph-name` .\n#. Fix bug when using a dynamic parameter for\n   :ref:`PrintFor@notpos` or :ref:`PrintFor@value`\n   in the ``PrintFor`` routine.\n\n12-23\n=====\nAdd the :ref:`graph_op_enum@Discrete Function`\noperator to the :ref:`cpp_ad_graph-name` ; see\n:ref:`graph_discrete_op.cpp-name` .\n\n12-21\n=====\nAdd an\n:ref:`wish_list@Abs-normal@Atomic Functions` item\nto the wish list for abs-normal functions.\n\n12-20\n=====\nAdd a\n:ref:`wish_list@Dynamic Parameters` item and a\n:ref:`wish_list@Graph Operators` item to the wish list.\n\n12-18\n=====\n\n#. The :ref:`graph_atom_op.cpp-name` *Base* type was changed from\n   ``double`` to ``float`` .\n#. Fix a bug in\n   :ref:`from_graph-name` , :ref:`from_json-name` , :ref:`to_graph-name` , and :ref:`to_json-name`\n   when the :ref:`from_json@Base` type is not ``double`` .\n\n12-16\n=====\nAdd more description in the comments for the\n:ref:`graph_op_enum values<graph_op_enum@Enum Values>` .\n\n12-15\n=====\n\n#. Added a list of the possible :ref:`ADFun-name` operators\n   that are :ref:`missing<graph_op_enum@Missing Operators>`\n   (not yet implemented) by :ref:`to_graph-name` and :ref:`to_json-name` .\n#. Absolute zero multiplication\n   :ref:`json_graph_op@Binary Operators@azmul`\n   was as added to the :ref:`json_ad_graph-name` and\n   :ref:`cpp_ad_graph-name` as ``pow_graph_op`` .\n   Functions that contain the this operator\n   can be converted to and from ``cpp_graph`` objects; e.g.,\n   see :ref:`graph_azmul_op.cpp-name` .\n   They can also be converted to and from strings containing\n   :ref:`json_ad_graph-name` representations; e.g.,\n   see :ref:`json_azmul_op.cpp-name` .\n#. Improve the\n   :ref:`graph_op_enum examples<graph_op_enum@Examples>` by removing\n   some type definitions and using statements.\n   In addition, use :ref:`cppad_testvector-name` to demonstrate that\n   any :ref:`simplevector-name` type can be used.\n\n12-14\n=====\nThe power operators was added to the :ref:`json_ad_graph-name` as\n:ref:`json_graph_op@Binary Operators@pow` and to the\n:ref:`cpp_ad_graph-name` as ``pow_graph_op`` ; see\n:ref:`graph_op_enum@Enum Values` .\nFunctions that contain the :ref:`pow-name` operators\ncan be converted to and from ``cpp_graph`` objects; e.g.,\nsee :ref:`graph_pow_op.cpp-name` .\nThey can also be converted to and from strings containing\n:ref:`json_ad_graph-name` representations; e.g.,\nsee :ref:`json_pow_op.cpp-name` .\n\n12-13\n=====\nAdd :ref:`switch_var_dyn.cpp-name` , an example that\nswitches between variables and dynamic parameters.\n\n12-12\n=====\nAdd a version of the ``from_graph`` routine that\ncan convert dynamic parameters to variables and vice versa; see\n:ref:`from_graph@dyn2var` and *var2dyn* in the\n``from_graph`` documentation.\n\n12-09\n=====\nAdd the ``Independent`` ( *x* , *dynamic* ) syntax\nto the :ref:`Independent-name` function and changes some of the\n:ref:`new_dynamic-name` example to use this syntax.\n\n12-08\n=====\nAdd wish list item for converting dynamic parameters to variables\nand vice versa. This has since been completed;\nsee :ref:`2019@mm-dd@12-12` above.\n\n11-15\n=====\nFix clang 9.0.0 mistaken uninitialized warning in\n:ref:`a11c_openmp.cpp-name` .\n\n11-10\n=====\nChange *n_independent* to *n_variable_ind* in\n:ref:`json_ad_graph<json_ad_graph@variable_ind_vec@n_variable_ind>` and\n:ref:`cpp_ad_graph<cpp_ad_graph@n_variable_ind>` .\nIn addition, the under construction warning was removed from\n:ref:`json_ad_graph-name` and :ref:`cpp_ad_graph-name` .\n\n11-09\n=====\nThe C++ data structure for an AD graph :ref:`cpp_ad_graph@cpp_graph`\nwas add the user API for CppAD.\n\n11-05\n=====\nMore work on reducing the amount of memory used by the\n:ref:`from_json-name` and :ref:`to_json-name` operations.\n\n10-28\n=====\nMore work on reducing the amount of memory used by the\n:ref:`from_json-name` and :ref:`to_json-name` operations.\n\n10-27\n=====\n\n#. Working on reducing the amount of memory used by the\n   :ref:`from_json-name` and :ref:`to_json-name` operations.\n#. Improve sparse jacobian error messaging when coloring is\n   :ref:`sparse_jac@coloring@cppad` and\n   :ref:`sparse_jac@subset`\n   has elements that are not in the sparsity\n   :ref:`sparse_jac@pattern` .\n\n10-22\n=====\nA left (right) bracket was added to the beginning of (end of) the\n:ref:`json_ad_graph@constant_vec` ,\n:ref:`json_ad_graph@op_usage_vec` ,\n:ref:`json_ad_graph@dependent_vec` values\nin a Json AD graph (to properly conform to Json format).\n\n10-21\n=====\nMove the Json AD graph discussion of\n:ref:`json_ad_graph@Node Indices`\nunder one heading and include\na diagram of all the nodes.\n\n10-17\n=====\nInclude conversion from function to graph (:ref:`to_json-name` )\nand back to function (:ref:`from_json-name` )\nin the :ref:`json operator<json_graph_op-name>` examples.\n\n10-02\n=====\nThe default value for :ref:`cmake@cppad_prefix`\nwas changed from ``/usr`` to the value of the cmake variable\n`CMAKE_INSTALL_PREFIX <https://cmake.org/cmake/help/v3.0/variable/CMAKE_INSTALL_PREFIX.html>`_.\n\n09-30\n=====\nUse a newer version of the program that generates the documentation\n``omhelp`` .\nThe search utility now shows the title and section tag in separate\nareas and hides the other keywords.\nHitting return or double clicking in the title area,\nin addition to choosing the ``Goto`` button, will go to\nthe selected section.\n\n09-24\n=====\nDiscussion of a :ref:`cmake@CMake Command@Warning`\nabout boost as added to cmake command documentation.\n\n09-23\n=====\nThe ``cppad_deprecated`` option has been completely removed from the\ncmake command :ref:`cmake@CMake Command@Options` documentation.\n\n09-18\n=====\nMerge in changes from json branch which implement the\n:ref:`json_graph_op@Compare Operators` .\n\n09-17\n=====\nThe autotools install was installing * . ``hpp.in``\ninstead of the corresponding * . ``hpp`` file.\nThis has been fixed.\n\n09-14\n=====\nFix autotools install so files get installed to\n*prefix* / ``include/cppad`` instead of\n*prefix* / ``include/include/cppad`` .\nAlso fix the autotools ``make test`` .\n\n09-12\n=====\nBring :ref:`configure-name` build and test up to date\n(this was deprecated at end of 2012 and support for this will eventually stop).\n\n09-10\n=====\nThe old Json unary operator examples were converted to be just\ntests and a single :ref:`json_unary_op.cpp-name` example was left\nin its place.\n\n09-09\n=====\nThe Json graph\n:ref:`json_graph_op@Conditional Expressions`\nwere added.\n\n08-29\n=====\n\n#. Extend :ref:`to_json-name` to handle\n   :ref:`json_graph_op@Atomic Functions` .\n   This should have been included with the atomic function change\n   on :ref:`2019@mm-dd@08-17` .\n#. Simplify the :ref:`json_atom_op.cpp-name` and add a call\n   to :ref:`to_json-name` to this example.\n#. The ``string_vec`` field was removed from the definition of an\n   Json AD graph :ref:`json_ad_graph@AD Graph@function` .\n   The corresponding operators will have strings in their\n   :ref:`op_usage<json_ad_graph@op_usage@Strings In Usage>` .\n\n#. The vector branch was merged into the master.\n   This brought in the changes below\n\n#. 08-25:\n   Change :ref:`cppad_vector.cpp-name` example to use same names as\n   in :ref:`CppAD_vector-name` documentation.\n\n#. 08-23:\n   The :ref:`CppAD_vector-name` documentation page was edited (improved).\n\n#. 08-22:\n   :ref:`CppAD_vector@Iterators` were added\n   to the CppAD vector class.\n\n08-26\n=====\nThe Json graph\n:ref:`json_graph_op@Unary Operators` were added.\n\n08-19\n=====\nThe CppAD vector\n:ref:`CppAD_vector@Include` discussion was edited.\nIn addition, the class :ref:`CppAD_vector@vectorBool`\nis now available as a separate include file.\n\n08-17\n=====\n\n#. Add a the Json addition example :ref:`json_add_op.cpp-name` .\n#. Add the :ref:`atomic function<json_graph_op@Atomic Functions>`\n   operator which enables\n   one to call atomic functions as part of a Json AD graph; see the\n   :ref:`json_atom_op.cpp-name` example.\n\n08-16\n=====\nAdd the case where :ref:`atomic_three_forward@need_y` is equal to\n``constant_enum`` during ``atomic_three`` forward mode.\nThis only needs to be implemented when by :ref:`from_json-name` is used\nwith the atomic function.\n\n08-13\n=====\nFix a bug in the calculation of\nHessian :ref:`sparsity patterns<sparsity_pattern-name>`\nwhen using :ref:`chkpoint_two-name` function.\n\n08-12\n=====\n\n#. Fix an assert error for the\n   :ref:`json_graph_op@sum` operator\n   in :ref:`from_json-name` .\n#. Improve the documentation for mixing debug and release versions\n   of CppAD in the same program using ``CPPAD_DEBUG_AND_RELEASE`` .\n\n08-10\n=====\n\n#. Remove under construction heading from the examples\n   :ref:`json_mul_op.cpp-name` , :ref:`json_sub_op.cpp-name` , :ref:`json_sum_op.cpp-name`\n   (they have been working for a while now).\n#. Add the Json :ref:`json_graph_op@Binary Operators@div` operator.\n\n08-09\n=====\n\n#. Add :ref:`json_ad_graph@AD Graph@function_name`\n   to the Json graph representation of a function.\n#. Use the function name for reporting errors in a Json graph.\n\n08-08\n=====\n\n#. Move the example include files\n   ``eigen_cholesky.hpp`` ,\n   ``eigen_mat_inv.hpp`` ,\n   ``eigen_mat_mul.hpp``\n   from the ``include/cppad/example`` directory\n   to the ``include/cppad/example/atomic_two`` directory.\n#. Move the example include file\n   ``mat_mul.hpp``\n   from the ``include/cppad/example`` directory\n   to the ``include/cppad/example/atomic_three`` directory.\n#. Improve the :ref:`atomic_three_define@Syntax` ,\n   and :ref:`atomic_three_define@parameter_x` discussion,\n   in the documentation for the ``atomic_three`` functions.\n   Furthermore, add an extra discussion of the parameters\n   to the documentation for *taylor_x* in the\n   :ref:`forward<atomic_three_forward@taylor_x@parameters>` and\n   :ref:`reverse<atomic_three_forward@taylor_x@parameters>` callback functions.\n#. Change Json *string_vec*\n   from first to second line below:\n\n    | |tab| [ *n_string* , [ *first_string* , ..., *last_string*  ] ]\n    | |tab| *n_string* , [ *first_string* , ..., *last_string*  ]\n\n    ( *string_vec* was removed on :ref:`2019@mm-dd@08-29` ).\n#. Change Json :ref:`json_ad_graph@constant_vec`\n   from first to second line below:\n\n    | |tab| [ *n_constant* , [ *first_constant* , ..., *last_constant*  ] ]\n    | |tab| *n_constant* , [ *first_constant* , ..., *last_constant*  ]\n\n#. Change Json :ref:`json_ad_graph@op_usage_vec`\n   from first to second line below:\n\n    | |tab| [ *n_op_usage* , [ *first_op_usage* , ..., *last_op_usage*  ] ]\n    | |tab| *n_op_usage* , [ *first_op_usage* , ..., *last_op_usage*  ]\n\n#. Change Json :ref:`json_ad_graph@dependent_vec`\n   from first to second line below:\n\n    | |tab| [ *n_dependent* , [ *first_dependent* , ..., *last_dependent*  ] ]\n    | |tab| *n_dependent* , [ *first_dependent* , ..., *last_dependent*  ]\n\n08-06\n=====\n\n#. Fix a bug in ``chkpoint_two`` when\n   :ref:`chkpoint_two_ctor@use_in_parallel` is true.\n#. Add the :ref:`multi_atomic_three.cpp-name` and :ref:`multi_chkpoint_two.cpp-name`\n   examples.\n#. Deprecate the :ref:`multi_atomic_two.cpp-name` and :ref:`multi_chkpoint_one.cpp-name`\n   examples\n\n07-31\n=====\nAdd an example representation of a sparse matrix using the an\n:ref:`json_ad_graph-name` ; see :ref:`json_sparse.cpp-name` .\n\n07-30\n=====\n\n#. Add the json subtraction operator\n   :ref:`json_graph_op@Binary Operators@sub` .\n#. Fix :ref:`from_json-name` addition and multiply operations\n   where the first argument is a variable and second argument is a parameter.\n#. Add simple examples for the json operators that have been implemented; e.g.,\n   :ref:`json_sum_op.cpp-name` .\n#. Fix :ref:`to_json-name` when a cumulative summation has\n   subtraction terms in its summation.\n\n07-29\n=====\nAdd the :ref:`json_sum_op.cpp-name` example and fix a bug in\n:ref:`from_json-name` that was demonstrated by this example.\nTo be specific, the json :ref:`json_graph_op@sum` operator\ndid not work when all its result was a\n:ref:`dynamic parameter<glossary@Parameter@Dynamic>` .\n\n07-25\n=====\nFix the warning (on some systems) that\n:ref:`rev_jac_sparsity-name` shadows a member of\n``CppAD::atomic_three<Base>`` .\n\n07-19\n=====\nThe ``cppad_lib`` dynamic link library version number used to be\n*yy* . *mmdd* where the major version number *yy*\nwas the year minus 2000 and the minor version number *mmdd*\nwas the month and day.\nThe value *mmdd* was to large for a Mac system minor version number.\nSee :ref:`cmake@cmake_install_libdirs@cppad_lib` for the new\nlibrary version number system.\n\n07-18\n=====\nChange some assignment operators to equality operators in a few asserts\n(``=`` to ``==`` in the files\n``optimize_run.hpp`` and ``player.hpp`` ).\nThese were not bugs because the corresponding variable\nwas being set to the value it should have been.\n\n07-05\n=====\n\n#. The :ref:`json_ad_graph@op_usage_vec@n_usage` value generated by\n   :ref:`to_json-name` was not correct. This has been fixed.\n#. All the operators that were implemented so far were included in the\n   :ref:`json_ad_graph@op_define_vec` section generated by\n   ``to_json`` .\n   Now only operators that are used are included.\n   This makes it easier for humans to understand simple example graphs\n   (especially as the number of implemented operators increases).\n#. There was a bug in :ref:`from_json-name` when one\n   of the operations was a dynamic parameter and the other was a constant.\n   This has been fixed.\n#. All of the addition and multiplication operators\n   (including cumulative sum operators) have been implemented and tested..\n\n07-04\n=====\n\n#. Improve the :ref:`from_json-name` error messages by including the\n   previous two lines of Json in error message.\n#. Working on a :ref:`to_json-name` example that outputs graph\n   for the derivative of a function.\n\n07-03\n=====\nThe format of a Json computational graph was changed to include\na section at the top that defines the mapping\nbetween integer codes in the graph and corresponding operators,\nsee the heading :ref:`json_ad_graph@op_define_vec` .\nThis is now separate from\n:ref:`json_ad_graph@op_usage_vec` which is the part\nof the graph that is expect to be very large and is now less verbose.\n\n06-29\n=====\nIt used to be the case that optimized functions with cumulative\nsummation operators could not be optimized.\nThis has been fixed and it is now acceptable to\n:ref:`optimize@Re-Optimize` an ``ADFun`` object.\n\n06-19\n=====\n\n#. Some work was done to improve the speed of sparsity calculations\n   when using the internal representation for a\n   :ref:`glossary@Sparsity Pattern@Boolean Vector` .\n#. An extra pair of braces was expected in each\n   :ref:`json_ad_graph@op_usage` of an :ref:`json_ad_graph-name` .\n   This has been fixed.\n\n06-18\n=====\nThere are some problems using as Windows DLL for the ``cppad_lib``\nlibrary. These problems have been circumvented (for the time being) by using\nas static library for Windows systems.\n\n06-17\n=====\nA new feature that constructs a ``ADFun`` object\nfrom a Json representation of a computational graph was added; see\n:ref:`json_ad_graph-name` and :ref:`from_json-name` .\nThis requires linking the ``cppad_lib`` library.\nIt is a Minimal Viable Product and is intended for testing.\nAs of yet, only has the addition and multiplication operators are\nimplemented.\n\n06-10\n=====\nSome work was done to improve the speed of sparsity calculations\nwhen using the internal representation for a\n:ref:`glossary@Sparsity Pattern@Vector of Sets` .\nThis also reduced the time required by the\n:ref:`optimize-name` operation for some cases.\n\n06-02\n=====\nThe version number in the title of the top level for the\n:ref:`user_guide-name` documentation was not being updated.\nThis started on ``20190521`` and has been fixed.\n\n05-31\n=====\nAdd the :ref:`swap<CppAD_vector-name>` operation to the\n``CppAD::vector`` template class and\n:ref:`CppAD_vector@vectorBool` class.\nIn addition, change :ref:`cppad_vector.cpp-name` example\nso it focuses on operations that are not in\n:ref:`SimpleVector-name` .\n\n05-28\n=====\nThere was a bug in optimizing conditional expressions; i.e.,\noptimizing without the option\n:ref:`optimize@options@no_conditional_skip` .\nThis was a rare case that involving sets of conditional expressions\nand conditionally skipping a specific operator.\nThe bug was reproduced in a regression test and is fixed.\n\n05-22\n=====\n\n#. Some speed improvements were made to the\n   :ref:`for_hes_sparsity-name` algorithm.\n   To be specific the forward Jacobian and Hessian patterns\n   are computed during the same pass and using the same structure.\n   This avoids an extra pass on the operation sequence.\n   In addition, when :ref:`for_hes_sparsity@internal_bool`\n   is false, it enables smart points to the forward Jacobian and Hessian\n   to share the same underlying sets of integers (when they are equal).\n#. Some minor improvements and updating was done for the\n   :ref:`directory-name` and :ref:`glossary-name` sections.\n\n05-21\n=====\nSimplify the example computation of Hessian using subgraphs\n:ref:`subgraph_hes2jac.cpp-name` .\nThis simplification was a change from using\n:ref:`multiple levels of AD<mul_level-name>` to using :ref:`base2ad-name` .\n\n05-07\n=====\nThere was a bug in the checking for correctness of the\n:ref:`adolc_sparse_hessian.cpp-name` results.\nThis was due to the fact that the sparsity patterns for ADOL-C\nmay have more entries that CppAD knows are zero.\n\n04-01\n=====\nAdd the optional\n:ref:`time_test@repeat_out` argument to the\n``time_test`` function.\n\n03-27\n=====\nImprove the speed of sparse Hessian calculations that\n:ref:`sparse_hes@coloring@colpack.symmetric`\ncoloring method by directly accessing the coloring determined by Colpack.\n\n03-19\n=====\nThere was a bug in :ref:`f.Reverse(q, w)<reverse_any-name>` when *f*\ncontained the  :ref:`pow(x,y)<pow-name>` function and *x*  == 0 .\nTo be specific, it was not reporting zero instead of ``nan``\nfor the derivative. This has been partially, but not completely fixed.\nSee the :ref:`wish_list@Reverse Mode` in the wish list.\n\n03-13\n=====\nFix a bug in :ref:`f.subgraph_jac_rev(x, subset)<subgraph_jac_rev-name>` .\nThis bug appeared in a test that only returned the upper triangle\nof a symmetric matrix (the lower triangle worked).\n\n02-26\n=====\nThere was a problem linking the boost multi-threading library\non some systems that caused the corresponding check to be skipped.\nThis has been fixed. To be specific,\n::\n\n    make check_example_multi_thread_bthread: available\n\nwas not in the :ref:`cmake@CMake Command` output.\nThis has been fixed.\n\n02-23\n=====\nThe return value *n_sweep* was changed to\n:ref:`sparse_jac@n_color` because it is not the number\nof sweeps when :ref:`sparse_jac@group_max` is not equal to one.\nThis change was also made for the\n:ref:`speed tests<speed_main@Speed Results@n_color>` .\n\n02-22\n=====\nAdd row major order specifications to the speed test routines\n:ref:`link_sparse_jacobian<link_sparse_jacobian@Row Major>` and\n:ref:`link_sparse_hessian<link_sparse_hessian@Row Major>` .\nThis reduced the overhead (increased the speed) for the\n:ref:`adolc_sparse_jacobian.cpp-name` and\n:ref:`adolc_sparse_hessian.cpp-name` test cases.\n\n02-20\n=====\n\n#. Fix bug below in the new release\n   `20190200.1 <https://codeload.github.com/coin-or/CppAD/tar.gz/refs/tags/20190200.1>`_.\n#. There was a problem locating the boost multi-threading library.\n   To be specific, the\n   :ref:`cmake@CMake Command` would report\n\n        ``Could not find boost multi-threading library``\n\n    but it would still try to use the library.\n    This was because a file name with a ``-`` in it was\n    also being used for a cmake variable name.\n    This has been fixed.\n\n02-06\n=====\nImprove the discussion of the purpose of for the different\n:ref:`subgraph<subgraph_jac_rev@Purpose>` options which computing\nsparse Jacobians.\n\n02-01\n=====\n\n#. A stable release for 2019 is now available on the\n   `release <https://github.com/coin-or/CppAD/releases>`_ page.\n#. The :ref:`download-name` page was edited to include better discussion\n   of the license and documentation.\n\n01-18\n=====\nThe documentation for :ref:`atomic_three-name` ,\nand its subsections, was improved.\n\n01-17\n=====\nThe arguments\n:ref:`atomic_three_define@parameter_x` and\n:ref:`atomic_three_define@type_x` were included\nfor all the ``atomic_three`` virtual functions.\n\n01-16\n=====\nMore improvements, and bug fixes, in the optimization of :ref:`atomic-name`\noperations.\nThis results in a reduction in the number of parameters\n:ref:`fun_property@size_par`\nand the number of variables\n:ref:`fun_property@size_var` .\n\n01-15\n=====\nFix a bug in the optimization of :ref:`atomic_three-name`\noperations with :ref:`Independent@dynamic` parameters.\n\n01-14\n=====\n\n#. The :ref:`rev_depend<atomic_three_rev_depend-name>` call back function\n   was added to ``atomic_three`` class.\n   This enables one to :ref:`optimize-name` functions that use\n   ``atomic_three`` operations; see\n   the :ref:`rev_depend.cpp<atomic_three_rev_depend.cpp-name>` example.\n#. The ability to :ref:`optimize-name` functions was extended to\n   :ref:`chkpoint_two-name` operations; e.g., a call to optimize was added\n   at the end of the\n   :ref:`get_started.cpp<chkpoint_two_get_started.cpp-name>` example.\n#. The :ref:`chkpoint_one-name` class was deprecated,\n   use :ref:`chkpoint_two-name` instead.\n\n01-06\n=====\nOne of the two atomic matrix multiply examples was converted\nfrom using :ref:`atomic_two-name` to :ref:`atomic_three_mat_mul.cpp-name` .\nThis conversion made it clear that the *type_x* argument\nneeded to be included in the\n:ref:`jac_sparsity<atomic_three_jac_sparsity@type_x>` and\n:ref:`hes_sparsity<atomic_three_hes_sparsity@type_x>` functions.\n\n01-05\n=====\nMerge in the ``atomic branch`` .\nThis completed :ref:`wish_list-name` item for the new atomic function API;\nsee :ref:`atomic_three-name` .\nThis is an improvement over the :ref:`atomic_two-name` interface,\nwhich used the ``atomic_base`` class and has been deprecated.\nIn addition the following changes were included:\n\n#. Move the checkpoint examples below the\n   :ref:`checkpoint<chkpoint_one-name>` documentation.\n#. A phantom parameter, at index zero, was added; see\n   :ref:`fun_property@size_par` .\n#. There appears to have been a bug in ``put_con_par`` (not tested for)\n   whereby a constant parameter might match a dynamic parameter\n   (and get changed). This has been fixed.\n#. There was a mistake in the ``check_variable_dag`` routine whereby\n   the operator ``LeppOp`` checked a parameter index as if it were\n   a variable index. This has been fixed.\n\n01-11\n=====\nMerge in the ``chkpoint`` branch.\n\n#. This created the :ref:`chkpoint_two-name` class as a replacement\n   for the :ref:`chkpoint_one-name` class.\n   This new checkpoint class takes advantage\n   of :ref:`dynamic parameters<glossary@Parameter@Dynamic>`\n   and can be used with :ref:`base2ad-name` .\n#. While creating the ``chkpoint_two`` class,\n   a problem was discovered in the :ref:`atomic_three-name` class.\n   To be specific, it does not yet work with :ref:`optimize-name` .\n   A reverse dependency analysis is the proper way to fix this.\n   The ``atomic_three`` ``type`` member function does a forward\n   :ref:`atomic_three_for_type@Dependency Analysis`\n   and so its name was changed from ``type`` to ``for_type`` .\n\n{xrst_end 2019}\n"
  },
  {
    "path": "appendix/whats_new/2020.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin 2020 app}\n{xrst_spell\n    autotools\n    callgrind\n    cg\n    github\n    gitlab\n    libs\n    msys\n    omh\n    optionlist\n    un\n}\n\nRelease Notes for 2020\n######################\n\nmm-dd\n*****\n\n12-28\n=====\n\n#. Add the\n   :ref:`cppadcg_sparse_jacobian.cpp@PASS_SPARSE_JACOBIAN_TO_CODE_GEN`\n   option to the cppadcg sparse jacobian speed test\n   so one can compare passing a function, or its sparse Jacobian, to\n   CppADCodeGen (for the same eventual result).\n#. Move ``compiled_fun`` to :ref:`code_gen_fun-name` ,\n   to emphasize the fact that it used the CppADCodeGen package.\n\n12-27\n=====\n\n#. Include the example implementations ``compiled_fun.hpp``\n   and ``compiled_fun.cpp`` in the documentation.\n#. Add the\n   :ref:`cppadcg_det_minor.cpp@PASS_JACOBIAN_TO_CODE_GEN`\n   option to the cppadcg det_minor speed test\n   so one can compare passing the determinant or its Jacobian to\n   CppADCodeGen (for the same eventual result).\n\n12-21\n=====\n\n#. Add a move semantics version of the copy constructor to\n   :ref:`ADFun-name` , :ref:`sparse_rc-name` , :ref:`sparse_rcv-name` , and\n   :ref:`CppAD_vector@vectorBool` template classes.\n   This should improve the speed of handling function return values\n   that have these types.\n#. The default ADFun copy constructor was deleted so that its use is now\n   a compile error (it used to generate a run time error message).\n#. Move  :ref:`poly.cpp-name` , :ref:`pow_int-name` ,\n   :ref:`runge_45.cpp-name` , and :ref:`rosen_34.cpp-name`\n   from ``example/general`` to ``example/utility/`` .\n\n12-20\n=====\n\n#. The :ref:`rosen_34.cpp-name` example was changed to use\n   :ref:`independent@dynamic` parameters so it does not\n   need to record a new function for every argument value.\n   The new version of this example also uses the\n   ADFun :ref:`fun_construct@swap` operation to avoid\n   making a separate copy of an ADFun object.\n#. Fix a bug in the\n   ADFun :ref:`fun_construct@swap` , which was added on 12-19.\n#. Add a move semantic version of the copy constructor to\n   the :ref:`cppad_vector-name` template class.\n   (This should improve the speed of handling function return values\n   that are vectors.)\n\n12-19\n=====\nMerge in ``cg`` branch which had the following changes:\n\n#. **API Change:**\n   The *SizeVector* class in\n   :ref:`sparse_rc<sparse_rc@SizeVector>` and\n   :ref:`sparse_rcv<sparse_rcv@SizeVector>`\n   must support the ``swap`` operation.\n#. The ``swap`` operator was added to the\n   :ref:`sparse_rc<sparse_rc@other@swap>` and\n   :ref:`sparse_rcv<sparse_rcv@other@swap>` template classes.\n#. A move semantics version of the assignment operator was added to the\n   :ref:`sparse_rc<sparse_rc@other@Move Semantics Assignment and Constructor>`\n   :ref:`sparse_rcv<sparse_rcv@other@Move Semantics Assignment and Constructor>` template classes.\n#. The *job* option was added to the\n   :ref:`det_minor<link_det_minor@job>` and\n   :ref:`sparse_jacobian<link_sparse_jacobian@job>` speed tests.\n#. The ``compiled_fun`` example for using CppADCodeGen was added\n   (since moved to :ref:`code_gen_fun-name` ).\n   In addition, :ref:`cppadcg_sparse_jacobian.cpp-name` and\n   :ref:`cppadcg_det_minor.cpp-name` examples were modified to use this utility.\n#. The ADFun :ref:`fun_construct@swap` operation,\n   and move semantics copy constructor, were added.\n   This ensures the move semantics assignment operator does not make any copies.\n\n12-12\n=====\nChange the location where the source code for the\n:ref:`optional<get_optional.sh-name>` packages is stored from\n``build/external`` to ``external`` .\nThis enables one to remove the old build directory\nwithout having to rebuild the optional packages.\n\n12-11\n=====\nChange the autotools :ref:`configure@Configure` script\nso that it does better detection of the microsoft cl compiler.\nIn addition, add documentation for the\n:ref:`configure@--enable-msvc` option.\n\n12-06\n=====\nFix ``bin/get_cppadcg.sh`` install of newer version\nof cppadcg.\n\n12-05\n=====\nAdvance to Oct 9, 2020 version of cppadcg.\n\n12-04\n=====\n\n#. The cppad vector :ref:`cppad_vector@resize` operation\n   now preserves the data even if the new size does not fit in the\n   old capacity of the array.\n   This makes ``cppad_vector`` more like ``std::vector`` .\n#. Fix a problem with the autotools build and the ``is_pod`` function.\n   This function, which is not in the CppAD user API, was simplified because\n   it is no longer necessary to handle the c++98 case.\n#. Fix the ``example/utility/to_string.cpp`` test; see\n   `issue 44 <https://github.com/coin-or/CppAD/issues/44>`_.\n\n12-03\n=====\n**API Change:** support of c++11 is required for this,\nand future versions of CppAD.\n\n12-02\n=====\nThe :ref:`pkgconfig-name` files were modified to make user of the fields\n``Requires.private`` and ``Libs.private`` .\nIn addition, the\n:ref:`pkgconfig@cppad.pc@Extra Definitions`\nwere added.\n\n12-01\n=====\nThere was a mistake in the 20201130 version that caused\n``CPPAD_HAS_IPOPT`` and ``CPPAD_HAS_ADOLC`` to be undefined,\ninstead of 0 or 1, this has been fixed.\n\n11-29\n=====\n\n#. Use pkg-config to determine install prefix for\n   adolc, eigen, ipopt, and cppadcg; see\n   :ref:`cmake@include_adolc` ,\n   :ref:`cmake@Eigen` ,\n   :ref:`cmake@include_ipopt` , and\n   :ref:`cmake@include_cppadcg` .\n#. Fix warning that the variable ``not_used_rec_base`` was not initialized.\n\n10-26\n=====\nImprove the documentation for building the CppAD tests using\n:ref:`cmake@CMake Command@Visual Studio` .\n\n10-23\n=====\nVersion ``cmake-3.19`` of cmake had an change that was not backward\ncompatible; see\n`CHECK_CXX_SOURCE_RUNS <https://discourse.cmake.org/t/on-windows-check-cxx-source-runs-is-calling-check-source-runs/2065/6>`_.\nThis broke the CppAD install and was fixed.\nThus versions of CppAD before 20201023 do not work with version of CMake\nat or after 3.18.\n\n10-22\n=====\nAdd ``ar-lib`` to github repository distribution.\nThis fixes a problem with autotools build when using the\nMicrosoft C++ compiler and ``msys2`` .\n\n10-21\n=====\nModify the source file ``match_op.hpp`` to avoid a\npossibly un-initialized warning on some compilers.\n\n10-20\n=====\nThe *have_ar* variable has been removed from the\n:ref:`configure-name` configuration and the configuration now exits\nif ``AM_PROG_AR`` does not find an archiving tool.\nThis was done to try and solve some configuration problems with\na combination of ``msys2`` and the Visual Studio compiler.\n\n10-17\n=====\n\n#. The :ref:`configure-name` configuration would fail when it tried\n   to compile a :ref:`cppadcg-name` include file\n   (the autotools configuration does not support ``cppadcg`` ).\n   This has been fixed.\n#. The autotools configuration for he profiling version of the\n   speed tests was out of date. It is sufficient to do speed\n   profiling using the cmake configuration, so it has\n   been removed from the autotools configuration.\n#. Add more documentation for the\n   :ref:`cmake@cppad_profile_flag`\n   and fix some problems building the\n   ``speed_profile`` program.\n   (We also use ``callgrind`` to do CppAD speed profiling.)\n\n09-05\n=====\nFix some errors and warnings when building with Visual Studio 2019; e.g. see\n`issue 60 <https://github.com/coin-or/CppAD/issues/60>`_.\n\n06-08\n=====\nFix compiler warning in ``match_op.hpp`` about\npossibly uninitialized variable.\n\n06-04\n=====\n\n#. Advance :ref:`get_ipopt.sh-name` to ipopt-3.13.2.\n#. Fix some compiler warnings generated by g++-10.1.1.\n\n05-27\n=====\nIf :ref:`cmake@include_ipopt` is on the cmake command line,\n:ref:`ipopt_solve-name` is automatically included by ``cppad/cppad.hpp`` .\nThe :ref:`sparse2eigen-name` utility can still be used even\nif ``include_eigen`` is not specified on the cmake command line.\n\n05-26\n=====\n\n#. There was a bug in conditional expressions when the\n   :ref:`condexp@left` or :ref:`condexp@right` argument is a\n   :ref:`con_dyn_var@Dynamic` parameter and the other\n   is a parameter and ``NDEBUG`` is not defined.\n   There was a mistaken assertion that has been fixed.\n#. Advance most recent release from 20200000.2 to 20200000.3.\n\n05-23\n=====\n\n#. The ``optimize`` hash coding used to remove identical expressions\n   was improved. The can make a big difference for very large programs.\n#. The :ref:`collision_limit<optimize@options@collision_limit=value>`\n   option was added to the ``optimize`` command.\n#. The :ref:`optimize@exceed_collision_limit`\n   function was added so one can check if a larger collision limit\n   might make a difference.\n\n05-01\n=====\n\n#. A problem was fixed in the :ref:`get_adolc.sh-name`\n   installation of the optional package Adolc .\n   To be specific, to be specific the Adolc source moved from Gitlab to Github.\n   In addition, advance to Adolc master on 2020-04-01.\n#. The\n   :ref:`optimize@options@no_cumulative_sum_op`\n   option was added to the ``optimize`` routine because,\n   in some cases, gathering cumulative summations\n   interferes with recognizes pieces of summations that are\n   the same in different cumulative sums.\n\n03-11\n=====\nThe ``CppAD::vector`` constructor was extended to allow its\n:ref:`size<CppAD_vector@Size Constructor>` to be a ``int``\n(this used to generate a warning when using the ``clang`` compiler).\n\n02-02\n=====\nThe ``get_optional.sh`` prefix was extended so that it could be a\n:ref:`get_optional.sh@prefix@Relative Path` .\nIn addition\n:ref:`get_optional.sh@prefix@Configuration`\ninstructions were added to cover the case where the prefix is changed.\n\n02-01\n=====\nThe :ref:`get_optional.sh@get_optional.log`\nand :ref:`get_optional.sh@get_optional.err` files\nwere added so one can see the progress of the ``get_optional.sh`` script.\n\n01-29\n=====\n\n#. Add the :ref:`cppadcg_sparse_jacobian.cpp-name` speed test.\n#. The speed main program\n   :ref:`speed_main@test@correct`\n   test results were printed as\n\n        *package* _ *test* _ *optionlist* _ ``ok`` = *result*\n\n    This has been changed to\n\n        *package* _ *test* _ *optionlist* _ ``correct`` = *result*\n\n01-24\n=====\n\n#. Add the :ref:`cppadcg_det_minor.cpp-name` speed test.\n   This is the first test using :ref:`cppadcg-name`\n   (this package generates C source code for the derivatives).\n#. The package name was removed from the speed test size output\n   (because the sizes do not depend on the package); see\n   :ref:`speed_main@Speed Results` .\n\n01-22\n=====\n\n#. Add a :ref:`json_get_started.cpp-name` example.\n#. Move the section :ref:`example_abs_normal-name` below\n   the section :ref:`abs_normal_fun-name` .\n\n01-18\n=====\nModify the option package install scripts so they all use the same\ninstall :ref:`get_optional.sh@prefix`\nthat the user can change in the file ``bin/get_optional.sh`` .\nIn addition, these scripts were updated to use more recent versions\nof the optional packages.\n\n01-17\n=====\nCreate an example / template for adding a new package to the speed tests;\nsee :ref:`speed_xpackage-name` .\n\n01-12\n=====\nDocumentation was added for the\n:ref:`base_ordered@Special Requirements`\nwhen the *Base* type does not support ordered comparison.\nAs a consequence, the reverse mode the derivative of ``pow`` ( *x* , *y* )\nmay result in zero (not nan) when *x* is zero; see the\n:ref:`wish_list@Reverse Mode` wish list item.\n\n01-06\n=====\nThe ``VecAD`` objects have been extended to work with\ndynamic parameters. However, this is not as efficient as it should be; see\n:ref:`VecAD@Efficiency` and\n:ref:`wish_list@Dynamic Parameters@VecAD Vectors`\nunder dynamic parameters in the wish list.\n\n01-04\n=====\n\n#. The :ref:`VecAD-name` documentation was re-written.\n#. An empty directory with the name ``omh`` was being\n   install below the include directory.\n   This has been fixed.\n\n{xrst_end 2020}\n"
  },
  {
    "path": "appendix/whats_new/2021.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin 2021 app}\n{xrst_spell\n    cplusplus\n    cppadcg\n    cxx\n    isdigit\n    json\n    lcppad\n    lexer\n    libs\n    ltmain\n    msys\n    rcv\n    txt\n}\n\nRelease Notes for 2021\n######################\n\nmm-dd\n*****\n\n12-17\n=====\nAdd forward mode calculations using ``AD<double>`` to the\n:ref:`atomic_four_vector-name` example.\n\n12-16\n=====\nChange ``virtual`` to ``override`` in all the\n:ref:`atomic_three_example-name` files and\n:ref:`multi_atomic_three_user-name` .\n\n12-10\n=====\n\n#. Added the example :ref:`atomic_four_vector-name` .\n#. Fix some compiler warnings when building with ``NDEBUG`` defined.\n\n12-08\n=====\nUpdate to a newer version of the :ref:`configure-name` .\n\n09-04\n=====\nThere was a bug in the :ref:`atan2-name` function.\nFor example, the derivative of ``atan2(0,1)`` was incorrect; see\n`issue 120 <https://github.com/coin-or/CppAD/issues/120>`_.\nThis has been fixed and the :ref:`atan2.cpp-name` example has been\nextended to do more testing.\n\n08-31\n=====\nThere was a bug in the CMake configuration files such that\n``make check_example_multi_thread`` was not being constructed.\nHence ``make check`` did not include the multi_thread tests.\nThis has been fixed.\n\n08-27\n=====\nThe following error occurred\n\n    ``compile_source_test: cplusplus_201100_ok is defined before expected``\n\nif the :ref:`cmake-name` command was run twice,\nwithout first removing the ``CMakeCache.txt`` file.\nThis has been fixed.\n\n08-26\n=====\nThe cmake command was extended to allow for one to specify\n:ref:`cmake@cmake_build_type` .\nThis forced changing the default for\n:ref:`cmake@cppad_debug_which` from\n``debug_all`` to the empty string.\n\n07-31\n=====\nDo more work on pkgconfig files:\nRemove duplicates and put ``-L`` entries\nbefore ``-l`` entries in ``Libs`` section.\nFurthermore, move all information from private to normal section.\n\n07-30\n=====\nFix a bug in the :ref:`pkgconfig-name` files.\nTo be specific, there was an extra ``-l`` at the front of the list\nof library flags; e.g.,\n``-l-lcppad_lib`` was changed to ``-lcppad_lib`` .\n\n07-12\n=====\n\n#. Change all the scripts called by :ref:`get_optional.sh-name` to use\n   all the processing units available on the system when compiling\n   and linking the optional packages.\n#. Fix :ref:`get_colpack.sh-name` so that it does not leave behind\n   ``ltmain.sh`` and ``test-driver`` in the top source directory.\n#. Change the :ref:`cmake-name` script use of ``CHECK_CXX_SOURCE_RUNS``\n   to ``CHECK_CXX_SOURCE_COMPILES`` .\n   This makes it easier to use CppAD in a cross compiling context.\n\n06-22\n=====\nImprove :ref:`Var2Par-name` documentation and :ref:`var2par.cpp-name` example\nby separating dynamic and constant parameters.\n\n06-06\n=====\nThe ``CppAD::vector`` assignment statement no longer requires the\nsize of the vectors to be the same; see\n:ref:`CppAD_vector@Assignment@Check Size` .\n\n06-02\n=====\n\n#. Remove ``microsoft_timer`` which is no longer needed by\n   :ref:`elapsed_seconds-name` because c++11 required (starting this year).\n#. Remove any use of ``CMAKE_SOURCE_DIR`` .\n   This allows CppAD's top source directory\n   to be used as a subdirectory of a larger CMake package.\n\n05-12\n=====\n\n#. The cmake\n   :ref:`cmake@include_cppadcg` option was not working\n   when cppadcg was the only optional package.\n   This has been fixed.\n#. The smallest size\n   for the :ref:`det_minor<link_det_minor-name>` speed test\n   was changed from one to two (a 2 by 2 matrix).\n\n04-30\n=====\n\n#. The conditional expression example :ref:`cond_exp.cpp-name` was improved.\n#. Restore the\n   :ref:`sparse_rcv copy constructor<sparse_rcv@other@Assignment and Constructor>`\n   which was removed by mistake when the ``sparse_rcv``\n   move semantics constructor was added.\n\n04-28\n=====\n\n#. The change to the :ref:`pow(x,y)<pow-name>` function on\n   :ref:`2021@mm-dd@02-06` handled the case where *x* is zero.\n   The :ref:`pow_nan.cpp-name` example was modified to show when the new\n   version of this function generates nans.\n#. Remove some uses of the deprecated\n   :ref:`nan(zero)<nan@nan(zero)@Deprecated 2015-10-04>` function.\n\n04-27\n=====\nFix the msys2 and cygwin system builds so that they use static\n(instead of dynamic) libraries.\nThis is necessary so that static variables (in include files) can not have\nmultiple instances in Windows.\n\n04-26\n=====\nThere was a problem with the :ref:`cmake-name` command when\n:ref:`ipopt-name` was the only optional package installed.\nThis was related to the ipopt\n:ref:`ipopt@Include Directories` problem.\n\n04-16\n=====\nImprove the instruction for adding a new speed test package; see\n:ref:`speed_xpackage-name` .\n\n04-09\n=====\nThe :ref:`cpp_graph_print-name` operation was failing when there were\natomic or discrete functions. This has been fixed.\n\n04-07\n=====\nDocumentation was added for the\n:ref:`cpp_ad_graph@operator_arg@print_graph_op` operator.\nThis is different from the function\n:ref:`cpp_graph_print-name` which prints an entire graph.\n\n04-05\n=====\nThe :ref:`cpp_graph_print-name` operation was modified so that it printed the\ntext corresponding to atomic function names, discrete function names,\nand print operators.\n\n04-02\n=====\nThe enum value ``dis_graph_op`` was corrected to ``discrete_graph_op``\nin the documentation for\n:ref:`cpp_ad_graph@operator_arg@discrete_graph_op` .\n\n03-29\n=====\nInclude the :ref:`cpp_ad_graph@dependent_vec`\nin the output of :ref:`cpp_graph_print-name` ; see ``y nodes`` in\n:ref:`print_graph.cpp-name` example output.\n\n03-24\n=====\nThe C++ AD graph constructor, :ref:`cpp_graph_ctor-name` ,\ncannot be called the first tile in parallel mode.\nThis condition has been added to the documentation\nand assets were added to make sure it is true.\n\n03-11\n=====\nImprove the discussion of identically equal; see\n:ref:`base_identical@EqualOpSeq@More Complicated Case` .\n\n03-09\n=====\nSimplify the :ref:`fabs.cpp-name` example.\n\n03-08\n=====\nFor years the following comment in reverse.hpp was forgotten:\n\n    // ? ``should use`` += ``here`` , ``first make test to demonstrate bug``\n\nA test case was created to demonstrate this bug and it was fixed\n(see ``duplicate_dependent_var`` in ``test_more/general/reverse.cpp`` ).\nThis only affects reverse mode when\n:ref:`reverse_any@w` has size *q* * *m* and\ntwo of the dependent variables in the range of *f*\nare identically equal (actually the same variable).\n\n03-07\n=====\n\n#. Fix bug in :ref:`f.to_graph<to_graph-name>` that occurred\n   when *f* had ``fabs`` dynamic parameter operators.\n   To be more specific, if ``NDEBUG`` was not defined,\n   an error from an unknown source would be detected in the file ``to_graph.hpp`` .\n#. Make :ref:`unary_minus-name` an atomic operation,\n   instead of using binary subtraction of zero minus the value being negated.\n   In addition, add it to the\n   :ref:`json_graph unary operators<json_graph_op@Unary Operators>` and\n   the :ref:`graph_op_enum values<graph_op_enum@Enum Values>` .\n\n02-21\n=====\nAdd specifications for what is conditionally installed by the\n:ref:`cmake@Eigen` and\n:ref:`cmake@include_ipopt` options.\nIn addition, make it clearer that\n:ref:`cmake@include_cppadcg` should only be used for testing.\n\n02-16\n=====\nThere was a problem with atomic functions, :ref:`optimize-name` , and reverse mode\nthat would lead to unexpected nans.\nThis has been fixed by changing values,\nthat the optimizer determines are not used, from nan to zero.\nA discussion of this was added below\n:ref:`atomic_three_reverse@partial_x@azmul`\nin the atomic reverse documentation.\n\n02-14\n=====\n\n#. Add the :ref:`print<cpp_graph_print-name>` command to the\n   ``cpp_graph`` class.\n#. Change the name of a documentation section form ``seq_property``\n   to :ref:`fun_property-name` .\n#. Add setting and getting a ``ADFun`` function's\n   :ref:`name<function_name-name>` .\n\n02-12\n=====\n\n#. In the case where\n   :ref:`cmake@cppad_debug_which` is\n   ``debug_all`` (``debug_none`` ) the corresponding\n   *CMAKE_BUILD_TYPE* is now specified as\n   ``Debug`` (``Release`` ).\n#. Fix the ``Policy CMP0054`` warning during the\n   :ref:`cmake@CMake Command` .\n#. Fix the :ref:`cmake@CMake Command@Visual Studio` build.\n   This included commenting out part of the CppAD vector test\n   because the MSC compiler is confused between the vector's const_iterator and\n   iterator; see ``# ifndef _MSC_VER`` in :ref:`cppad_vector.cpp-name` .\n\n02-11\n=====\nFix some problems with the linking of the ``cppad_lib`` library\nwhen using the Microsoft compiler.\n\n02-08\n=====\nFix some problems in the\n:ref:`pkgconfig@cppad.pc` file; see pull request\n`95 <https://github.com/coin-or/CppAD/pull/95/files>`_.\n\n02-06\n=====\nA special version of the :ref:`pow(x, y)<pow-name>` function was added\nfor the special case where *y* is a parameter.\nThis properly handles the special case where *x* is zero\nand *y* is greater than the order of the derivative.\nIn addition, it only requires one tape variable (instead of three)\nfor each ``pow`` operation.\n\n01-27\n=====\nThere was a bug in the converting to abs_normal form when\nthe function :ref:`abs_normal_fun@f` made use of the\n:ref:`pow-name` operator.\nTo be specific, when compiling without ``NDEBUG`` defined,\nan assert was generated even though the code was correct.\nThis has been fixed.\n\n01-26\n=====\nChange the prototype for the cmake command\n:ref:`cmake@CMake Command@Options` to use *true_or_false* ,\ninstead of ``true`` to highlight the fact that one can choose either\ntrue or false.\n\n01-08\n=====\nOn some systems, the file ``cppad_lib/json_lexer.cpp`` would not compile\nbecause the ``std::isdigit`` function was not defined.\nThis has been fixed.\n\n01-07\n=====\nThe example :ref:`pow_nan.cpp-name` was added.\n\n01-05\n=====\n\n#. Improve discussion of :ref:`cppad_cxx<cmake@cppad_cxx_flags>`\n   and make sure all uses are exactly as described.\n   In addition, change mention of optional features from C++11 to C++17.\n#. The required version of :ref:`cmake-name` was advanced from 2.8.4 to 3.0.\n   This fixes a policy CMP0042 warning on Mac systems.\n#. If the compiler, plus the flags in\n   :ref:`cmake@cppad_cxx_flags` ,\n   does not by default support C++11, cmake is used\n   to find and add the flags necessary for this support.\n\n01-03\n=====\n\n#. Fix a bug in :ref:`reverse-name` mode for an\n   ``ADFun< AD<`` *Base* > > function that has\n   :ref:`Independent@dynamic` parameters and\n   value of one of these parameters was zero or one when the function\n   was recorded.\n#. Fix a bug in the :ref:`configure-name` building of ``cppad_lib`` .\n\n{xrst_end 2021}\n"
  },
  {
    "path": "appendix/whats_new/2022.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin 2022 app}\n{xrst_spell\n    an an\n    csrc\n    div\n    dll\n    github\n    isinf\n    isnan\n    libs\n    neg\n    nullptr\n    nx\n    ny\n    omhelp\n    posix\n    rc\n    tmpnam\n    txt\n    zdouble\n}\n\nRelease Notes for 2022\n######################\n\nmm-dd\n*****\n\n12-25\n=====\n#. The column widths of some of the documentation tables were set to be equal\n   instead of adjusting to best fit the columns.\n   This has been fixed.\n#. Fix two tables that were not converted to sphinx correctly. To be specific,\n   the table below Matrix Dimension in\n   :ref:`atomic_three_mat_mul.hpp-name` and\n   :ref:`atomic_two_eigen_mat_mul.hpp-name` .\n\n12-23\n=====\nAdd documentation for the binary operation\n:ref:`ad_binary@Zero Special Cases` .\nIn addition fix a bug in these special cases\nwhen zero was multiplied by or divided by nan.\n\n12-16\n=====\nFinish conversion of CppAD documentation from omhelp\nto the sphinx\n`xrst <https://xrst.readthedocs.io/latest/purpose.html>`_  wrapper.\nThe following is a link to the\n`old documentation <http://coin-or.github.io/CppAD/doc/cppad.htm>`_ .\n\n11-05\n=====\nFix a conversion error during the tests by extending the zdouble\n:ref:`constructor<zdouble@Syntax@Constructor and Assignment>`\nto ``zdouble`` ( *i* ) where *i* is ``long`` .\n\n08-30\n=====\nThe :ref:`optimize-name` operations was not handling\ncomparison operators that only had parameters,\nwith at least one dynamic parameter.\nThis has been fixed.\n\n07-16\n=====\nAdd the option to configure eigen using ``eigen_prefix`` ,\nas well as with ``include_eigen`` .\nThe ``eigen_prefix`` option was removed on\n:ref:`2024-08-05 <2024@mm-dd@08-05>` .\nThe ``include_eigen`` options was removed on\n:ref:`2024-10-02 <2024@mm-dd@10-02>` .\n\n07-14\n=====\n\n#. There was a mistake in the implementation of the\n   :ref:`ad_ctor@x@explicit` ``AD`` < *Base* > constructor.\n   To be specific, the value was converted to ``double`` before being\n   converted to ``AD`` < *Base* > .\n   This has been fixed and the :ref:`ad_ctor-name` documentation has been\n   improved to note which result are always constant parameters.\n#. **API Change** :\n   It was necessary (due to the fix above) to add the\n   :ref:`int constructor<base_member@Constructors@int>` and\n   :ref:`double constructor<base_member@Constructors@double>` to the\n   :ref:`base_require-name` .\n   (Defining a base class is an advanced topic and only for experts).\n\n07-12\n=====\nThe :ref:`cmake@CMake Command` was not properly determining\nwhen posix threads could be used (when using a C compiler other than gcc).\nThis suppressed the running of the corresponding examples; e.g.,\n:ref:`a11c_pthread.cpp-name` .\n\n07-10\n=====\n\n#. Add the cmake_needs_dot_slash symbol to the cmake command line.\n   This has since been removed; see 2023 for\n   :ref:`2023@mm-dd@06-01`.\n#. Change the test case in ``speed/example/speed_program.cpp`` because\n   some compilers have gotten smarter and do not calculate values\n   that are not used.\n   This lead to an the repeat count overflowing and then an infinite loop.\n   The :ref:`speed_test-name` and :ref:`speedtest-name` routines now check for\n   an overflow of the repeat counter and abort.\n#. Suppress the Microsoft compiler divide by zero warning, C4723.\n\n07-08\n=====\nChange `github actions <https://github.com/coin-or/CppAD/actions>`_:\nrun on pushes to the master and stable branches, and\nrun on all pull requests.\n\n07-05\n=====\nMerge in pull_155 branch.\nThis enabled the use of binary operators with Eigen matrices of\ntype ``AD`` < *Base* > and type *Base* ;\nsee :ref:`ScalarBinaryOpTraits<cppad_eigen.hpp@Eigen ScalarBinaryOpTraits>`\nin ``cppad_eigen.hpp`` .\n\n06-23\n=====\n\n#. Change *x* to :ref:`to_csrc@u` in the ``to_csrc`` operation\n   and add specifications as the position of the independent dynamic\n   parameters and variables in *u* .\n#. Add the :ref:`jit_dynamic.cpp-name` and :ref:`jit_compile.cpp-name` examples.\n#. Remove some remaining uses of ``CPPAD_TEST_VECTOR`` .\n#. Deprecate use of the following symbols:\n   ``CPPAD_`` *package* ``VECTOR`` for *package* equal to\n   ``CPPAD`` , ``STD`` , ``BOOST`` , ``EIGEN`` .\n#. Add the :ref:`cmake@cmake_defined_ok` symbol\n   to the cmake command line.\n   This enables one to run cmake with a ``CMakeCache.txt`` file.\n\n06-22\n=====\n\n#. Modify the :ref:`cmake@CMake Command@msys2`\n   and :ref:`cmake@CMake Command@Visual Studio`\n   install suggestions.\n#. Split the JIT function type\n   *type* _ ``forward_zero`` into\n   ``jit_`` *type* for :ref:`to_csrc@JIT Functions` , and\n   ``atomic_`` *type* for :ref:`to_csrc@Atomic Callbacks` .\n#. Add the :ref:`jit_atomic.cpp-name` example.\n#. The ``CPPAD_TEST_VECTOR`` macro was removed\n   (it was deprecated on 2012-07-03).\n#. Remove the following symbols from the :ref:`testvector-name` documentation:\n   ``CPPAD_`` *package* ``VECTOR`` for *package* equal to\n   ``CPPAD`` , ``STD`` , ``BOOST`` , ``EIGEN`` .\n\n06-21\n=====\nChange the visual C++ JIT compile flag ``/Tc`` to the flag ``/TC`` ,\nso that the C source file need not follow directly after in the compile\ncommand. This fixed a test failure when using that compiler.\n\n06-20\n=====\nJIT C source code generation, compilation, and linking were added using\nthe following new features, examples, and speed tests:\n\n.. csv-table::\n    :widths: auto\n\n    to_csrc,:ref:`to_csrc-title`\n    create_dll_lib,:ref:`create_dll_lib-title`\n    link_dll_lib,:ref:`link_dll_lib-title`\n    example_jit,:ref:`example_jit-title`\n    cppad_jit_det_minor.cpp,:ref:`cppad_jit_det_minor.cpp-title`\n\nThe following improvements were made to existing features:\n\n#. Fix a clang++ compiler warning in the file check_for_nan.hpp.\n\n05-27\n=====\nAdd the theory, but not implementation, for the atomic linear ODE\nsecond order reverse mode; see\n:ref:`atomic_four_lin_ode_reverse_2-name` .\n\n05-26\n=====\n\n#. The atomic linear ODE maximum :ref:`atomic_four_lin_ode@step` size\n   was not being enforced during the reverse mode\n   :ref:`atomic_four_lin_ode_reverse.hpp@Simpson's Rule`\n   integral approximation.\n   This has been fixed.\n#. Make :ref:`atomic_four_lin_ode_forward.hpp@extend_ode`\n   a separate function in the atomic linear ODE example.\n\n05-20\n=====\nMerge in the pull_144 branch.\nThis fixed some problems with the windows visual studio build; see\nthe corresponding pull request.\n\n05-19\n=====\n\n#. The atomic four ``base_lin_ode`` function was changed to\n   :ref:`base_solver<atomic_four_lin_ode_base_solver.hpp-name>` .\n   In addition, a maximum :ref:`atomic_four_lin_ode@step`\n   size was added to this atomic linear ODE solver.\n#. Fix setting of debug and release flags in\n   ``test_more/debug_rel/CMakeLists.txt`` .\n\n05-17\n=====\nThe :ref:`atomic_four_lin_ode_rev_depend.hpp-name` example was added.\nIn addition, remove the Under Construction headings from the\n:ref:`atomic_four_lin_ode-name` sections (it is ready for use).\n\n05-16\n=====\n\n#. The :ref:`atomic_four_hes_sparsity@ident_zero_x` argument\n   was added to the atomic four Hessian sparsity callback.\n   The previous version of this callback still works but is deprecated.\n#. Add :ref:`Var2Par-name` set in the ``cppad_eigen.hpp``\n   :ref:`cppad_eigen.hpp@std Definitions` of the AD versions of\n   ``isinf`` and ``isnan`` .\n#. Change the atomic four example Hessian sparsity callbacks to use the\n   :ref:`atomic_four_hes_sparsity@ident_zero_x` .\n   In the special case of :ref:`atomic_four_norm_sq.cpp-name` ,\n   do not include *ident_zero_x* and mention that this version\n   of the callback is deprecated.\n\n05-15\n=====\n\n#. Merge in the pull_140 branch.\n   This extended CppAD :ref:`base_limits-name` and :ref:`numeric_limits-name`\n   to include ``infinity()`` .\n   In addition,  ``cppad_eigen.hpp`` added ``isinf``\n   and ``isnan`` for AD types to the std namespace; see\n   :ref:`cppad_eigen.hpp@std Definitions` .\n\n#. Fix a long standing bug in the :ref:`for_hes_sparsity-name` routine.\n   For example,\n   the function called ``case_seven`` in\n   ``test_more/general/hes_sparsity.cpp/`` tests a case\n   where this bug occurred.\n\n#. Add the :ref:`atomic_four_lin_ode_hes_sparsity.hpp-name` example.\n\n05-13\n=====\nThe :ref:`code_gen_fun examples<code_gen_fun@Examples>` were\nnot being built even when\n:ref:`cmake@include_cppadcg`\nwas specified on the cmake command line.\nThis has been fixed.\n\n05-12\n=====\nThe :ref:`cmake-name` script ``cmake/compile_source_test.cmake`` was not\nworking properly on Darwin systems which resulted in the following warning:\n\n| |tab| ``warning:`` ``'tmpnam'`` ``is deprecated:`` ...\n| |tab| |tab| ``file_name`` = ``tmpnam`` ( ``nullptr`` );\n\nThis has been fixed.\n\n05-11\n=====\nA mathematical :ref:`atomic_four_lin_ode_jac_sparsity.hpp@Theory`\nwas added to the linear ODE Jacobian sparsity pattern example.\nIn addition, the corresponding code was changed to match the theory.\nThis may, or may not, have fixed some bugs in the previous version\nof this routine.\n\n05-10\n=====\nThe :ref:`atomic_four_jac_sparsity@ident_zero_x` argument\nwas added to the atomic four Jacobian sparsity callback.\nThe previous version of this callback still works but is deprecated.\n\n05-09\n=====\n\n#. Add a theory section to the linear ODE\n   :ref:`for_type<atomic_four_lin_ode_for_type.hpp@Theory>` section.\n   In addition more the linear ODE theory for forward and reverse mode to the\n   corresponding\n   :ref:`forward<atomic_four_lin_ode_forward.hpp@Theory>` and\n   :ref:`reverse<atomic_four_lin_ode_reverse.hpp@First Order Theory>` sections.\n#. Back out an incorrect change on 04-15 to the meaning of\n   :ref:`atomic_four_jac_sparsity@select_x` and\n   :ref:`atomic_four_jac_sparsity@select_y` in the\n   atomic four Jacobian sparsity documentation.\n#. Add the specification that the atomic four\n   :ref:`atomic_four_call@for_type` callback\n   will be called once for each atomic function call and before any other\n   of the callbacks for the atomic function call.\n\n05-07\n=====\nAdd the :ref:`base2vec_ad.cpp-name` example demonstrating that :ref:`base2ad-name`\ndoes not convert :ref:`VecAD-name` operations as might be expected.\nAdd a link to this example in both the base2ad and VecAD documentation\nand a :ref:`base2ad wish_list<wish_list@base2ad>` item about this.\n\n05-06\n=====\nThere was a bug in combining the :ref:`discrete-name` functions with the\n:ref:`base2ad-name` operation.\nTo be specific, if a discrete function was used during the recording of\n*f* and *af* = *f* . ``base2ad`` () , the following assert\nwould happen during forward mode calculations using the *af* function:\n\n| |tab| ``error from unknown source``\n| |tab| ``Error detected by false result for``\n| |tab| |tab| ``index < List`` (). ``size`` ()\n| |tab| ``at line 325 in the file``\n| |tab| ... ``discrete.hpp``\n\nThis bug has been fixed.\n\n04-21\n=====\n\n#. Modify :ref:`atomic_four_lin_ode_set.hpp-name` and\n   :ref:`atomic_four_lin_ode_get.hpp-name` to re-use sparsity patterns\n   instead of creating a new one for every call.\n   This makes use of\n   :ref:`sparse_rc@set_row_major` to speed up checking\n   for equality of sparsity patterns.\n#. In the :ref:`atomic_four_lin_ode_implement-name` files, change ``assert`` to\n   :ref:`CPPAD_ASSERT_UNKNOWN<cppad_assert@Unknown>` .\n\n04-20\n=====\nAdd the\n:ref:`sparse_rc@set_row_major` ,\n:ref:`sparse_rc@get_row_major` ,\n:ref:`sparse_rc@set_col_major` ,\n:ref:`sparse_rc@get_col_major` ,\nfunctions to the ``sparse_rc`` template class.\n\n04-19\n=====\nChange the ODE solver in :ref:`atomic_four_lin_ode-name` from\n:ref:`runge45-name` to :ref:`rosen34-name` .\n\n04-15\n=====\n\n#. Add :ref:`atomic_four_lin_ode-name` an example of making the solution\n   of an ODE an atomic operation.\n   As with the other atomic four examples, the ``AD`` < *Base* >\n   version of the derivative calculations a done using atomic operations.\n#. Add the :ref:`sparse_rc@other@Equality` operator\n   to the sparsity pattern template class.\n\n03-29\n=====\nAdd the :ref:`atomic_four_lin_ode-name` example\nwhich is not yet complete.\n\n03-26\n=====\nChange ``y(nx)`` to ``y(ny)`` in\n:ref:`atomic_four_mat_mul_forward.cpp-name` .\n\n03-25\n=====\n\n#. Fix :ref:`atomic_four_mat_mul-name` by changing it's base class\n   from ``atomic_four<double>`` to ``atomic_four`` < *Base* > ;\n   see :ref:`atomic_four_mat_mul.hpp-name` .\n#. Remove under construction warning from :ref:`atomic_four_mat_mul-name` .\n#. Change ``atomic_vector`` to :ref:`atomic_four_vector-name` .\n\n03-24\n=====\nFix :ref:`atomic_four_vector-name` by changing it's base class\nfrom ``atomic_four<double>`` to ``atomic_four`` < *Base* > .\nMake some other similar corrections in :ref:`atomic_four_vector.hpp-name` .\n\n03-23\n=====\nImprove error detection and message when both\n:ref:`cmake@cmake_build_type` and\n:ref:`cmake@cppad_debug_which` are chosen\nduring the install procedure.\n\n02-21\n=====\nExtend the json graph representation to include\n:ref:`json_graph_op@Atomic Functions@Atomic Four` functions.\nFor example, see :ref:`json_atom4_op.cpp-name` .\n\n02-19\n=====\nExtend the C++ graph representation to include atomic four\n:ref:`atomic functions<graph_op_enum@Atomic Function>` .\nFor example, see :ref:`graph_atom4_op.cpp-name` .\n\n02-18\n=====\nFixed the value of *after* [ *i* ] in the\n:ref:`cpp_ad_graph@operator_arg@print_graph_op` documentation.\nTo be specific, ``- 2`` was changed to ``- 1`` .\n\n02-17\n=====\nAdd ``identical_zero`` to the possible\n:ref:`atomic_four_for_type@ad_type` values in\nthe atomic four ``for_type`` function.\nSee :ref:`atomic_four_vector_for_type.hpp-name` ,\n:ref:`atomic_four_mat_mul_for_type.hpp-name` , and\n:ref:`atomic_four_mat_mul_identical_zero.cpp-name`\nfor an examples using this feature.\n\n02-16\n=====\nUse the :ref:`atomic_four_norm_sq.cpp-name` overrides\nas examples for the virtual functions in the :ref:`atomic_four-name`\nbase class.\n\n02-13\n=====\n\n#. The :ref:`atomic_four_mat_mul-name` example class was added.\n#. The :ref:`atomic_four_vector-name` include path has changed to\n\n        # ``include <cppad/example/atomic_four/vector.hpp>``\n\n02-12\n=====\nAdd the :ref:`sparse_rc@push_back` and\noutput stream (see :ref:`sparse_rc@os` ) operations\nto the ``sparse_rc`` template class.\n\n02-11\n=====\nThe value of ``Libs:`` in the ``cppad.pc`` :ref:`pkgconfig-name` file\nwas not being set correctly for some cases. This has been fixed.\n\n02-01\n=====\nFix a possible integer overflow in the :ref:`to_string.cpp-name` example\n(might cause the test to fail).\n\n01-27\n=====\nConvert :ref:`atomic_four_forward.cpp-name` from an atomic_three\nto an atomic_four example.\n\n01-25\n=====\nConvert :ref:`atomic_four_dynamic.cpp-name` from an atomic_three\nto an atomic_four example.\n\n01-23\n=====\n\n#. Add :ref:`atomic_four-name` , a simpler interface to atomic functions.\n   This has the optional :ref:`atomic_four_call@call_id` argument\n   which can be used to attach extra information to an atomic function call.\n#. The :ref:`atomic_four_vector-name` is a good example that uses\n   *call_id* to specify which\n   element by element operator is being called; see\n   :ref:`call_id<atomic_four_vector@op>` .\n#. Remove element-by-element atomic operations from :ref:`wish_list-name`\n   (completed by the atomic_vector class).\n\n01-19\n=====\nEdit wish_list cppad_lib\n:ref:`wish_list@cppad_lib@Requirement` item.\nAdd an :ref:`wish_list@Optimization@Atomic Functions`\nitem to the optimization wish list.\n\n01-15\n=====\n\n#. Fix some conversion warnings generated by the clang compiler\n   for the :ref:`atomic_four_vector-name` example.\n#. Correct the order of p, q in function calls in\n   :ref:`atomic_four_vector_forward_op.hpp-name` .\n\n01-06\n=====\n\n#. Fix the ``[]`` operator using CppAD vector\n   :ref:`iterators<CppAD_vector@Iterators@operator[]>` .\n   In addition it was extended to include ``size_t`` indices.\n#. Add reverse mode to the :ref:`atomic_four_vector-name` ,  mul, div, operators\n   and fix some warning used ``size_t`` iterator indices.\n\n01-04\n=====\n\n#. Add the neg operator to :ref:`atomic_four_vector-name` .\n#. Add reverse mode to the atomic_vector,  add, sub, and neg operators.\n\n01-01\n=====\nThe ``example/atomic_three/vector_op.cpp`` example\n(see :ref:`atomic_four_vector-name` ) was split into multiple files and moved into the\n``example/atomic_vector`` directory.\n\n{xrst_end 2022}\n"
  },
  {
    "path": "appendix/whats_new/2023.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin 2023 app}\n{xrst_spell\n    autotools\n    cstdint\n    kludge\n    kokkos\n    mingw\n    msys\n    pacman\n    trilinos\n    uintptr\n    usr\n}\n\nRelease Notes for 2023\n######################\n\nmm-dd\n*****\n\n12-27\n=====\nFix link in :ref:`user_guide@Software Engineering` paragraph.\n\n12-24\n=====\nChange the ``CPPAD_DEBUG_AND_RELEASE`` compiler flag to the cmake\n:ref:`cmake@cppad_debug_and_release` configuration flag.\nThis changed the default behavior for compiling the CppAD library\nso that it allows for mixing debug and release code.\n\n09-08\n=====\n#. Add the :ref:`cmake@cppad_static_lib` option to the install.\n#. Fix warning (on some newer compilers) when a :ref:`CppAD_vector@vectorBool`\n   constructor specified the number of elements using a signed integer.\n\n08-19\n=====\nAdd :ref:`numeric_limits@max_digits10` to the AD numeric limits.\nIf you define your own Base type, and you do not use the\n:ref:`base_limits@CPPAD_NUMERIC_LIMITS` macro,\nyou will have to add ``max_digits10`` to your Base type's numeric limits.\n\n08-12\n=====\n#. There was a bug in the to_csrc :ref:`to_csrc@compare_change` argument.\n   To be specific, it was not adding to the input value but rather\n   reporting the number of changes during a call.\n   This has been fixed and demonstrated in the\n   :ref:`jit_compare_change.cpp-name` example.\n#. A :ref:`link_dll_lib@fun_ptr@Warning !!` was added to the documentation\n   for function pointers created by the dll linker.\n   (This fact did not stand out as much in the previous documentation.)\n\n08-10\n=====\n#. The :ref:`parallel_ad-name` routine was missing some initializations.\n   This has been fixed. In addition, a list of\n   :ref:`parallel_ad@Other Initialization` ,\n   that must be initialized before using in parallel mode,\n   was included in the documentation.\n#. There was a bug introduce on :ref:`2023@mm-dd@06-20` when the\n   val_graph branch was merged into the master. To be more specific,\n   if :ref:`cmake@cppad_tape_addr_type` was ``size_t`` ,\n   a compile error occurred one of the ``is_pod`` definitions.\n   This has been fixed.\n\n08-09\n=====\nThe :ref:`cmake@cmake_build_type` option was changed to not be case\nsensitive; e.g., you can now use ``debug`` or ``Debug`` for this option.\n\n08-06\n=====\nAdd the cumulative summation operator to the :ref:`to_csrc-name` conversion.\nThe cumulative summation operator can occur during optimization.\nNot having this operator seemed like a bug when NDEBUG was true\nbecause one got no warning that the operator did not get converted.\n\n07-29\n=====\nAdd the CppAD vector :ref:`CppAD_vector@Comparison` operators\nand size with :ref:`CppAD_vector@Size Constructor@Value` constructor.\n\n06-20\n=====\n#. Add ``unsigned int`` as a valid type for the CppAD vector\n   :ref:`CppAD_vector@Size Constructor` and\n   :ref:`CppAD_vector@resize` argument.\n\n#. Merge in the val_graph Branch:\n\n    #. Add :ref:`optimize@options@val_graph` to the\n       list of possible optimizer options.\n    #. Add the :ref:`speed_main@Global Options@val_graph`\n       option to the speed tests. This option has been implemented\n       with all of the :ref:`speed_cppad-name` tests.\n    #. Simplify :ref:`atomic_four_lin_ode_rev_depend.cpp-name`\n       and add m to the\n       `atomic_four_lin_ode_rev_depend.cpp@Problem Parameters`\n       that can be changed.\n    #. Fix the title of the\n       :ref:`atomic_four_lin_ode_base_solver.hpp-title` section.\n    #. Change all the atomic_four :ref:`examples <atomic_four_example-name>`\n       that use :ref:`optimize-name` to include the ``val_graph`` option.\n\n06-13\n=====\nChange the :ref:`cppad_det_minor.cpp-name` speed test to use the\n:ref:`optimize@options@no_cumulative_sum_op` optimization option\n(because it is faster for this case).\n\n06-10\n=====\n#. The autotools configure script has been replaced by\n   :ref:`configure-name` which just maps the configure script interface\n   to the :ref:`cmake-name` interface.\n   The corresponding autotools files were removed.\n#. In some cases there was a problem linking the adolc library to the\n   :ref:`speed_adolc-name` tests. This has been fixed.\n\n06-07\n=====\nAdd links to\n:ref:`Install@Generator`, :ref:`Install@cppad.spec`,  and :ref:`Install@xrst`\nin the CppAD install instructions.\n\n06-04\n=====\nFix a warning form the Trilinos Kokkos package when including\n:ref:`sacado_prefix-name` on the cmake command line.\n\n06-01\n=====\nThe ``cmake_needs_dot_slash`` symbol was removed from the cmake command line.\nIt was a kludge for msys2 systems.\nThe proper fix is to use\n{xrst_code sh}\n    pacman -S mingw-w64-x86_64-cmake\n{xrst_code}\n( not use ``pacman -S cmake`` )\nto install cmake on an msys2 system.\n\n05-31\n=====\nThere was an error building the old version of the sacado library using\n:ref:`get_sacado.sh-name` with g++-13.1.1.\nThis has been fixed by advancing to trilinos-14-0-0\nand patching one of its include files; see trilinos issue\n`11923 <https://github.com/trilinos/Trilinos/issues/11923>`_ .\n\n05-19\n=====\nFix ``uintptr_t`` not defined (on some systems) by adding the following\nbefore using it: ``# include <cstdint>`` .\n\n05-18\n=====\nRemove the unnecessary include directory ``/usr/include``\nfrom the :ref:`speed_cppad_jit-name` speed tests.\nThis was including multiple versions of some system include files\non the msys system.\n\n04-17\n=====\nExtend the CppAD::vector CppAD::vectorBool template classes so that the\n:ref:`CppAD_vector@resize` argument can be an ``int``\n(this was causing a warning with the clang++ compiler).\nAlso extend :ref:`CppAD_vector@vectorBool` so that any index type,\nthat can be converted to size_t, can be used to access elements\n(without a clang++ warning).\n\n04-01\n=====\nExtend index_sort so that the\n:ref:`index_sort@ind` vector can have elements of any integral type.\n\n03-04\n=====\nThere were some problems running :ref:`cmake_check-name` when\n:ref:`cmake@include_ipopt` was true\n(and certain combination of other cmake options).\nThis has been fixed.\n\n\n02-08\n=====\nA :ref:`Discrete-name` function is now initialized\nby the ``CPPAD_DISCRETE_FUNCTION`` macro instead of later\nthe first time it is used.\n\n02-07\n=====\nThe atomic four rev_depend argument\n:ref:`atomic_four_rev_depend@ident_zero_x` was not catching\nall the identically zero values.\nThis has been fixed.\nIt was not a bug but was not as efficient when\nan atomic four function used this information to reduce the work.\n\n02-05\n=====\nMerge in pull request 168.\nThis fixes an issue with :ref:`link_dll_lib-name`\non windows when building with unicode.\n\n01-15\n=====\nThe following atomic four ``rev_depend`` problems have been fixed.\n\n#. The atomic four :ref:`atomic_four_rev_depend@ident_zero_x` argument\n   can be used to reduce the number of depend_x (not depend_y) values.\n#. The *ident_zero_x* argument should have been ``const`` in the prototype.\n#. The :ref:`atomic_four_vector-name` and\n   :ref:`atomic_four_mat_mul-name` examples used the\n   :ref:`atomic_four_rev_depend@Syntax@Deprecated 2022-05-10`\n   version of the ``rev_depend`` callback; i.e., the one without\n   the *ident_zero_x* argument.\n\n01-12\n=====\nFix a problem with the documentation conversion on\n:ref:`2022@mm-dd@12-16` of 2022.\nTo be specific:\n``name_1<`` *name_2* > was converted to ``name_1`` < *name_2* >\n\n\n01-11\n=====\nThe :ref:`CppAD_vector@Initializer Constructor` was added to the\n``CppAD::vector`` template class.\n\n01-07\n=====\nPrint an error message and exit from the cmake command when a\n:ref:`cmake@package_prefix` does not contain any include directories\nor libraries.\n\n{xrst_end 2023}\n"
  },
  {
    "path": "appendix/whats_new/2024.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell  <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin 2024 app}\n{xrst_spell\n    bitwise\n    boostvector\n    bostvector\n    cassert\n    cmd\n    dismod\n    dll\n    env\n    fadbad\n    homebrew\n    iostream\n    ipopt\n    isnan\n    nul\n    nx\n    omhelp\n    py\n    sacado\n    setvec\n    svec\n    usr\n    xcode\n    yy\n    yyyy\n}\n\nRelease Notes for 2024\n######################\n\nmm-dd\n*****\n\n12-14\n=====\nAdd a separate :ref:`cmake@CMake Command@true_or_false` paragraph\nto describe *true_or_false* in the cmake command.\n\n12-09\n=====\nAn option to build a local copy of the user or developer documentation\nwas added to the install procedure; see :ref:`cmake@include_doc` .\nThis also affects the :ref:`cmake@cmake_install_docdir` option.\n\n11-23\n=====\nIn the :ref:`atomic_four_norm_sq.cpp-name` example,\nremove dead code in its forward routine.\nTo be specific, remove::\n\n    // Assume we are not using forward mode with order > 1\n    assert( ! ok );\n    return ok;\n\nAlso in its reverse routine,\nimprove the comment about the relation between G and H; to be specific::\n\n    // H( {x_j^k} ) = G[ F( {x_j^k} ), {x_j^k} ]\n\n11-19\n=====\nFix the :ref:`configure@--with-clang` and :ref:`configure@--with-verbose-make`\noptions did not have any effect in the configure script.\nThis has been fixed.\n\n11-16\n=====\nThe :ref:`for_hes_sparsity-name` and :ref:`ForSparseHes-name` routines\ndid not handle the cumulative summation operators properly.\nThese operators sum more than two variables or dynamic parameters at a time\nand may be created during ADFun :ref:`optimization <optimize-name>` .\n\n11-13\n=====\nThe :ref:`for_hes_sparsity-name` and :ref:`ForSparseHes-name` routines\ndid not handle the :ref:`VecAD-name` load and store operations properly.\nThis has been fixed.\n\n11-12\n=====\nRemove extra unintended white space below Syntax headings\nthat was introduced when the CppAD documentation was converted from\nomhelp to sphinx; see :ref:`2022-12-16<2022@mm-dd@12-16>` .\nFor example:\n\nOld Syntax\n----------\n\n    ``atomic_user`` *a_square_root*\n\n*a_square_root* ( *au* , *ay* )\n\nNew Syntax\n----------\n| ``atomic_user`` *a_square_root*\n| *a_square_root* ( *au* , *ay* )\n\n10-04\n=====\nThe :ref:`jit_compile.cpp-name` example line was missing\nCPPAD_C_COMPILER_CMD in the line (this has been fixed)::\n\n    const char* cmd = CPPAD_C_COMPILER_CMD \" --version > temp\";\n\n10-02\n=====\n#. The *include_eigen* argument was removed from the :ref:`cmake-name` command\n   because Eigen is available using most package managers;\n   see :ref:`cmake@Eigen` .\n#. Remove *boost_dir* and *eigen_dir* from :ref:`configure-name`\n   (they no longer have any effect).\n\n09-28\n=====\nFix some conversion warnings between ``size_t`` , ``int`` , and ``short``\nin the :ref:`speed_adolc-name` examples / tests.\n\n09-24\n=====\nConvert the bitwise operators & and | , when used with bool operands,\nto the logical operations && and ||; see ``bin/no_bitwise.sh``\n(this fixes many warnings).\nIn addition, fix some other warnings and put some exceptions on\n``bin/check_all.sh`` for some warnings that seem to be incorrect.\n\n09-13\n=====\n#. Make all of the get_optional.sh routines now works on MacOS with homebrew,\n   see :ref:`get_optional.sh@MacOS with Homebrew` .\n   Do not test :ref:`colpack_prefix-name` on MacOS\n   (there seems to be a problem with the ColPack install on that system).\n#. The :ref:`configure@--with-verbose-make` option was added to the\n   configure script. In addition, :ref:`configure-name` was mistakenly\n   requiring that ColPack was installed; see :ref:`colpack_prefix-name`.\n   This has been fixed.\n\n09-11\n=====\n#. The :ref:`get_ipopt.sh@Source Directory` was changed from\n   ``external/Ipopt-``\\ *version* to ``external/Ipopt,git`` .\n#. Advance get_ipopt :ref:`get_ipopt.sh@Version` from 3.13.2 to 3.14.16.\n\n09-09\n=====\n#. The :ref:`cmake@CMake Command@Visual Studio` instructions were improved.\n#. ``CppAD`` was added before ``isnan`` , see the discussion of\n   :ref:`nan@std::isnan` .\n\n08-10\n=====\nThere was a problem with :ref:`CppAD_vector@iterators` that caused\nthe sort test in :ref:`cppad_vector.cpp-name` to fail when using\nVisual C++ on Windows or Xcode C++ on MacOS.\nTo be specific, this was the case where the iterator needs to be ``const`` ,\neven though the value it points to is not ``const`` .\nThis has been fixed.\n\n\n08-09\n=====\n#. Suppress the testing of sort using CppAD vector iterators\n   on MacOs with the Xcode C++ compiler; search for CPPAD_CXX_IS_XCODE in\n   :ref:`cppad_vector.cpp-name` .\n#. The :ref:`jit_compile.cpp-name` example was hanging on some Windows\n   systems because they do not support writing to the``nul`` device.\n   This has been fixed by writing to temporary files.\n\n08-08\n=====\nAdd the :ref:`dos_build.bat-name` install example.\n\n08-05\n=====\nThe cmake ``-D eigen_prefix`` option was removed\nand ``PKG_CONFIG_PATH`` requirements were added for\n``include_eigen`` (and the other packages).\n\n08-04\n=====\nStandard threading was added to the multi-threading examples; see\n:ref:`a11c_sthread.cpp-name` ,\n:ref:`sthread_get_started.cpp-name`  ,\n:ref:`sthread_get_started.cpp-name`  ,\n:ref:`team_sthread.cpp-name` .\n\n05-12\n=====\nA bug in the use of base types that are not ordered\n(e.g., :ref:`complex <base_complex.hpp-name>` )\nwas introduced on :ref:`2023@mm-dd@08-10` of 2023,\nwhen the val_graph branch was merged in the master branch.\nThis has been fixed by requiring such base types to define the ordering\ncompare operations as resulting in an error; see\n:ref:`base_cond_exp@CondExpTemplate@Not Ordered` .\n\n04-25\n=====\nThe :ref:`configure-name` script was changed to detect when\nthe eigen package is requested and the compiler is not c++14 or greater.\nThe :ref:`configure-name` and :ref:`cmake-name` scripts\nwere changed to detect when\nthe sacado package is requested and the compiler is not c++17 or greater.\n\n04-20\n=====\nThe ``# include`` commands were missing at the top of\nsome of the valvector examples.\nThis has been fixed; e.g., see ref:`valvector_get_started-name` .\n\n04-04\n=====\nThe file example/multi_thread/bthread/get_started.cpp had an error\nwhen ``CPPAD_TESTVECTOR`` was :ref:`testvector@std::vector`\n(The elements of a standard vectors of bool may a single bits instead of\na boolean value).\nThe has been fixed.\n\n04-03\n=====\n#. Add the :ref:`valvector_llsq_obj.cpp-name` example.\n#. Add the :ref:`valvector_sum.cpp-name` member function.\n#. Fix the titles :ref:`valvector_ad_sum.cpp-title` and\n   :ref:`valvector_ad_join.cpp-name` .\n#. Add the following to :ref:`valvector_base_require.cpp-name` :\n   {xrst_code cpp}\n   x   = valvector( {0.0, 0.0} );\n   ok &= CppAD::IdenticalZero(x);\n   {xrst_code}\n\n\n03-28\n=====\nChange the get_eigen.sh\nversion from 3.3.7 to the master branch on 2024-03-24; see\n`issue 200 <https://github.com/coin-or/CppAD/issues/200>`_ .\nNote that the new version of eigen requires c++14 or higher.\n\n03-23\n=====\n#. Change the upper case one letter variable names in the\n   :ref:`interp_onetape.cpp-name` example; to be specific,\n   *X* -> *ax* and *Y* -> *ay* , *A* -> *ax_grid* , *F* -> *af_grid* ,\n   *I* -> *ay_linear* .\n#. Add the :ref:`atomic_four_bilinear.cpp-name` example.\n\n03-19\n=====\nFix broken links found using ``--external_links`` option to\nthe ``xrst`` documentation generator.\n\n03-16\n=====\nThe :ref:`ADFun constructor<fun_construct-name>` was changed to use\n*ax* instead of *x* , and *ay* instead of *y* , for AD values.\nIn addition, the :ref:`fun_construct@Sequence Constructor` discussion\nwas improved.\n\n03-15\n=====\n#. The user's choice of :ref:`ta_parallel_setup@in_parallel` routine\n   was not being called properly in some cases. This has been fixed.\n   This would cause CppAD to not properly report some usage\n   errors during parallel execution.\n#. Fixing the problem above exposed the fact that,\n   when mixing debug and release builds,\n   :ref:`CheckSimpleVector-name` must be defined.\n   This has also been fixed.\n#. The discussion, in the multi-threading get_started examples,\n   about the :ref:`openmp_get_started.cpp@ADFun Constructor` was improved.\n#. The parallel_ad routine has been improved so that it initializes\n   CheckSimpleVector for more cases; see :ref:`parallel_ad@CheckSimpleVector` .\n\n03-13\n=====\nThe :ref:`bthread_get_started.cpp-name`\nand :ref:`pthread_get_started.cpp-name`\nexamples were made simpler by\ndirectly using the threading system instead of going through the\n:ref:`team_thread.hpp-name` interface.\n\n03-12\n=====\nThe :ref:`openmp_get_started.cpp-name` example was made simpler by\ndirectly using openmp instead of going through the\n:ref:`team_thread.hpp-name` interface.\n\n03-11\n=====\nThe multi-threading ``simple_ad`` examples where changed to\n``get_started`` ; see\n:ref:`openmp_get_started.cpp-name` ,\n:ref:`pthread_get_started.cpp-name` ,\n:ref:`bthread_get_started.cpp-name` .\n\n03-09\n=====\nThe number of :ref:`parallel_ad@CheckSimpleVector` cases\ncalled by parallel_ad<Base>() was increased to include the following::\n\n    CheckSimpleVector< bool, CppAD::vectorBool >()\n    CheckSimpleVector< size_t, CppAD::vector<size_t> >()\n    CheckSimpleVector< Base, std::vector<Base> >()\n    CheckSimpleVector< AD<Base>, std::vector< AD<Base> > >()\n\nIn addition, the CheckSimpleVector :ref:`CheckSimpleVector@Parallel Mode`\ndocumentation and error message has been improved.\n\n03-06\n=====\n#. The ``to_csrc`` parameters :ref:`to_csrc@nu` and :ref:`to_csrc@u`\n   were denoted by ``nx`` and ``x`` in the generated source code.\n   This has been changed an now the generated source uses ``nu`` and ``u``\n   for these parameters.\n#. The :ref:`to_csrc-name` documentation was changed to use\n   *atomic_name* for the name of the atomic\n   (instead of reusing *function_name* which has another purpose).\n   In addition, :ref:`jit_atomic.cpp-name`\n   was also changed to use *atomic_name* .\n\n03-02\n=====\nAdd the :ref:`valvector_ad_split-name` and :ref:`valvector_ad_join-name`\nexamples.\n\n03-01\n=====\nFix bug in the optimizer :ref:`optimize@options@val_graph` option.\nTo be more specific, the following assert could occur during the optimization::\n\n    vector: index greater than or equal vector size\n\n\n02-29\n=====\nAdd the :ref:`valvector_compare_op@op@Ordered Operators`\nto the valvector class.\nThis is needed to optimize tapes where the base type is valvector.\n\n02-28\n=====\nAdd the :ref:`valvector-name` example base class.\n\n02-27\n=====\nThe omhelp package is not longer used by CppAD\n( see :ref:`2022@mm-dd@12-16` ) so the links to its documentation\nwere removed.\nIn addition, the instructions for\n:ref:`download@Git@Building Documentation` were out of date and have been\nfixed.\n\n02-26\n=====\n#. Correct some errors in the numeric type\n   :ref:`NumericType@Operators` table.\n   Also the table under :ref:`CondExp@Purpose` on the\n   conditional expression documentation.\n   (These were errors in the automatic conversion from omhelp to sphinx.)\n#. The ``<=`` operator was removed from the base type requirements\n   :ref:`base_member@Bool Operators` .\n\n02-23\n=====\nInclude more of the example drivers in the documentation;\nsee :ref:`example_driver-name` .\nIn addition, remove unnecessary includes for ``iostream`` and\n``cassert`` from these drivers.\n\n02-22\n=====\n#. The shebang in the :ref:`configure-name` script was changed from\n   ``#! /bin/bash`` to ``#! /usr/bin/env bash`` .\n   This should make it work on more systems.\n#. The configure script *eigen_dir* ,\n   *fadbad_dir* , and *sacado_dir*\n   directories were not being passed to the ``cmake`` .\n   This has been fixed.\n#. The configure ``--help`` option for using boost vectors\n   was corrected from  ``--with-bostvector`` to ``--with-boostvector`` .\n\n02-21\n=====\nFor each year, change the web page name ``whats_new_``\\ *yy*\nto *yyyy* where *yy* and *yyyy* identify the year. In addition, change the\ntitle for these pages to Release Notes for the corresponding year.\nThis breaks old links to these web pages.\nFor example, the old link to the heading directly below was::\n\n    https://cppad.readthedocs.io/latest/whats_new_24.html#whats-new-24-mm-dd-02-14\n\nIts new link, which is much shorter, is::\n\n    https://cppad.readthedocs.io/latest/2024.html#mm-dd-02-14\n\n02-14\n=====\nThe :ref:`optimize-name` routine could crash when\nchecking if an operator with the same hash code was a match with the\nargument order switched (for add and multiply).\nThis problem occurred during speed.py_ ,\nwhich is an example and test of dismod_at, which uses CppAD.\nThis crash required a very special (and improbable) case that we\nwere unable to reproduce in an automated regression test;\nsee comment that starts with 2024-02-14 in\n`include/cppad/local/optimize/match_op.hpp` .\n\n.. _speed.py: https://dismod-at.readthedocs.io/latest/user_speed.py.html\n\n01-16\n=====\nfix dll linking of jit code by changing *cppad_c_compiler_path* to\n*cppad_c_compiler_cmd* (spaces in the path were making commands fail).\n\n01-12\n=====\n#. There were some problems using the cmake C compiler for the\n   examples and tests of jit compilation, so that has been backed out for now.\n#. There was a mistake in detecting if size_t is the same as\n   :ref:`cmake@cppad_tape_addr_type`. This could cause a compile error\n   in `op_hash_table.hpp` and has been fixed.\n\n01-11\n=====\nUse the *cppad_c_compiler_path* detected by :ref:`cmake-name`\nto run the C compiler for the Clang and GNU cases; see\nthe `create_dll_lib`` defaults for\n:ref:`create_dll_lib@options@compile` and\n:ref:`create_dll_lib@options@link` .\n\n01-10\n=====\n#. Fix some problems with the install on 32 bit systems.\n   To be specific, the :ref:`thread_alloc-name` memory allocator\n   was not properly aligning doubles.\n#. Suppress the test of the ``svec_setvec`` class.\n   (The class has a bug and is not currently being used.)\n\n01-08\n=====\nOn some systems ``unsigned int`` and ``size_t`` are the same type\nand this would cause a compile error in ``vector.hpp`` and\n``vector_bool.hpp`` . This has been fixed.\n\n01-07\n=====\nThe forward_two :ref:`forward_two@Syntax` was corrected.\nTo be specific,\n``Forward`` (1, *x2* ) was changed to ``Forward`` (2, *x2* ) .\nIn addition, some other minor improvements were made to the\nforward_two documentation page.\n\n01-03\n=====\n\n#. The change on :ref:`2023@mm-dd@12-24` 2023,\n   when :ref:`cmake@cppad_debug_and_release` was implemented,\n   was not done properly and might cause a mistaken assertion.\n   This has been fixed.\n\n#. Each *file_name* in the latest documentation was moved\n   (this is important if you have links to previous web pages):\n\n    .. list-table::\n\n        *  - Old Location\n           - ``https://cppad.readthedocs.io/``\\ *file_name*\n        *  - New Location\n           - ``https://cppad.readthedocs.io/latest/``\\ *file_name*\n\n01-02\n=====\n\n#. The :ref:`compare_change.cpp-name` example/test would sometimes fail\n   when :ref:`cmake@cppad_debug_which` was ``debug_even`` or\n   ``debug_odd`` (because it was compiled for debugging and including\n   a release version of a utility). This has been fixed by making this\n   example/test a separate program.\n\n#. The :ref:`CppAD_vector@vectorBool` constructor would generate a\n   warning when called with an ``int`` for the size of the vector\n   (on some compilers). This has been fixed.\n\n\n{xrst_end 2024}\n"
  },
  {
    "path": "appendix/whats_new/2025.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell  <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-25 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin 2025 app}\n{xrst_spell\n    dll\n    jit\n    rpath\n    msys\n    dev\n    Woverloaded\n    azmul\n    toml\n}\n\nRelease Notes for 2025\n######################\n\n\n\nmm-dd\n*****\n\n12-30\n=====\nPreviously, CppAD only checked for spelling errors in the documentation.\nThe `typos`_ package was used\nto fix many spelling errors in the code (including example code).\nThis was done in two commits.\n\n#. The `first commit`_\n   only included the errors where typos provided a single correction\n   and the error had four or more letters.\n\n#. The second commit included changes that were individually reviewed.\n   In addition the file ``typos.toml`` was added\n   (this defines some CppAD typos spelling exceptions).\n\n.. _typos: https://github.com/crate-ci/typos\n\n{xrst_spell_off}\n.. _first commit: https://github.com/coin-or/CppAD/commit/\n    95146e99838fd908833846a85c72dde882b46f6a\n{xrst_spell_on}\n\n\n12-14\n=====\n#. Let p denote a dynamic parameter, z denote the constant zero,\n   and e denote the constant one.\n   The number of dynamic parameter operations was reduced by\n   recognizing the following special cases (where p is a dynamic parameter:\n   {xrst_code text}\n       p = p + z\n       p = p - z\n       p = p * e\n       p = p / e\n       e = pow(p, z)\n       z = pow(z, p)\n       z = azmul(z, p)\n       z = azmul(p, z)\n   {xrst_code}\n\n#. The :ref:`chkpoint_one-name` source code,\n   when compiled with g++ version 15.2.1,\n   was causing the following warnings:\n   {xrst_code text}\n       ... rev_sparse_hes ... was hidden [-Woverloaded-virtual=]\n       ... rev_sparse_jac ... was hidden [-Woverloaded-virtual=]\n       ... for_sparse_jac ... was hidden [-Woverloaded-virtual=]\n   {xrst_code}\n   This has been fixed.\n\n12-07\n=====\n#. The :ref:`pow-name` function was identically zero (one),\n   when the base (exponent) during recording was the dynamic parameter zero;\n   see issue 242. This has been fixed.\n\n#. Update the development tools (see dev_tools.sh in xrst repository).\n\n\n06-23\n=====\nThe default value for :ref:`cmake@cmake_install_libdirs` was changed from\n``lib`` to ``lib;lib64`` so that ``lib64`` is also searched for library files.\n\n04-18\n=====\nIncrease size of matrices in the\n:ref:`det_minor<link_det_minor-name>` speed tests.\n\n04-01\n=====\nFix a :ref:`conditional expressions<CondExp-name>`  bug that affect\n:ref:`optimize-name` and :ref:`subgraph_sparsity-name` .\noptimizing functions with\n\n03-21\n=====\nIf :ref:`cmake@cppad_tape_addr_type` was chosen to be `size_t` ,\na multiple definition of ``setup_random`` compiler error would occur.\nThis has been fixed.\n\n\n02-09\n=====\nSystems that use windows dll files,\n(msys, cygwin, and windows) would always build a static\nversion of the cppad library; i.e., the\n`cmake@cppad_static_lib` flag was ignored in this case.\nThis has been changed so that the cppad_static_lib flag is always respected.\nThe default value for *cppad_static_lib* on msys, cygwin, and windows is true\nand on other systems it is false; i.e., if you do not specify cppad_static_lib\nyou will get the same result as before this change.\n\n\n02-02\n=====\nThe rpath in may not have been set properly in\n:ref:`cmake@cmake_install_libdirs@cppad_lib` because ``CMAKE_INSTALL_RPATH``\nwas not set. This has been fixed its value is printed\nduring the cmake command.\n\n01-24\n=====\n#. Fix linking the pthread examples ( e.g. :ref:`pthread_get_started.cpp-name` )\n   when the pthread library is in a non-standard location.\n#. Fix linking the standard thread examples\n   ( e.g. :ref:`sthread_get_started.cpp-name` )\n   when the standard thread library required the pthread library.\n\n01-17\n=====\n#. The :ref:`cmake@cppad_link_flags` option was added to the cmake command.\n\n#. The detection of when ``unsigned int`` and ``size_t`` were the same,\n   by the cmake command, was incorrect in cases where\n   the compiler flags affected this result.\n\n#. Fix some errors of the form *function_name*\\ ``(unsigned int)``\n   cannot be overloaded with *function_name*\\ ``(size_t)`` .\n\n#. The :ref:`dll_lib.cpp@Restrictions` ,\n   on when the dll_lib.cpp example is tested were documented.\n\n#. The :ref:`example_jit@Restrictions` was added to the\n   jit example documentation.\n\n01-10\n=====\nSplit the external links at the top of the user guide into:\n:ref:`user_guide@Git Repository` ,\n:ref:`user_guide@Versions` ,\n:ref:`user_guide@Other Links` .\n\n{xrst_end 2025}\n"
  },
  {
    "path": "appendix/whats_new/2026.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell  <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-26 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin 2026 app}\n{xrst_spell\n    rst\n}\n\nRelease Notes for 2026\n######################\n\n\n\nmm-dd\n*****\n\n04-08\n=====\n\n#.  Change the cppad source code and documentation to use 4 spaces for\n    one tab; i.e., one level of indentation.\n    This used to be 3 spaces because that works well with rst lists\n    (the cppad documentation uses rst),\n    but 4 spaces is the most common choice used by programmers.\n\n#.  Rename the default git branch from master to main.\n\n01-03\n=====\nMore spelling corrections in the source code comments found\nby a newer version of the typos package; see\n:ref:`2025@mm-dd@12-30` whats new for 2025.\n\n\n{xrst_end 2026}\n"
  },
  {
    "path": "appendix/whats_new/whats_new.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-23 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin whats_new app}\n\nCppAD Release Notes\n###################\n\nIntroduction\n************\nThe sections listed below contain a list of the changes to CppAD\nin reverse order by date.\nThe purpose of these sections is to\nassist you in learning about changes between various versions of CppAD.\n{xrst_toc_hidden\n    appendix/whats_new/2026.xrst\n    appendix/whats_new/2025.xrst\n    appendix/whats_new/2024.xrst\n    appendix/whats_new/2023.xrst\n    appendix/whats_new/2022.xrst\n    appendix/whats_new/2021.xrst\n    appendix/whats_new/2020.xrst\n    appendix/whats_new/2019.xrst\n    appendix/whats_new/2018.xrst\n    appendix/whats_new/2017.xrst\n    appendix/whats_new/2016.xrst\n    appendix/whats_new/2015.xrst\n    appendix/whats_new/2014.xrst\n    appendix/whats_new/2013.xrst\n    appendix/whats_new/2012.xrst\n    appendix/whats_new/2011.xrst\n    appendix/whats_new/2010.xrst\n    appendix/whats_new/2009.xrst\n    appendix/whats_new/2008.xrst\n    appendix/whats_new/2007.xrst\n    appendix/whats_new/2006.xrst\n    appendix/whats_new/2005.xrst\n    appendix/whats_new/2004.xrst\n    appendix/whats_new/2003.xrst\n}\n\nThis Year\n*********\n:ref:`2026-name`\n\nPrevious Years\n**************\n:ref:`2025-name` ,\n:ref:`2024-name` ,\n:ref:`2023-name` ,\n:ref:`2022-name` ,\n:ref:`2021-name` ,\n:ref:`2020-name` ,\n:ref:`2019-name` ,\n:ref:`2018-name` ,\n:ref:`2017-name` ,\n:ref:`2016-name` ,\n:ref:`2015-name` ,\n:ref:`2014-name` ,\n:ref:`2013-name` ,\n:ref:`2012-name` ,\n:ref:`2011-name` ,\n:ref:`2010-name` ,\n:ref:`2009-name` ,\n:ref:`2008-name` ,\n:ref:`2007-name` ,\n:ref:`2006-name` ,\n:ref:`2005-name` ,\n:ref:`2004-name` ,\n:ref:`2003-name` .\n\n{xrst_end whats_new}\n"
  },
  {
    "path": "appendix/wish_list.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin wish_list app}\n{xrst_spell\n    adolc\n    grep\n    tapeless\n}\n\nThe CppAD Wish List\n###################\n\nSee Also\n********\n:ref:`research-name`\n\nPurpose\n*******\nThe items on this list are improvements and extensions to CppAD\nthat are currently being considered.\n\nbase2ad\n*******\nIt would be nice if :ref:`base2ad-name` functioned as expected with\n:ref:`VecAD-name` operations; see :ref:`base2vec_ad.cpp-name` .\n\nDynamic Parameters\n******************\n\nComparison Operators\n====================\nThe comparisons for dynamic parameters are not being included\nin the :ref:`Independent@record_compare` is true.\nThis should be fixed and included in the\n:ref:`compare_change@number` returned by\n*f* . ``compare_change`` .\nIn addition, we will need a way to know if\n:ref:`compare_change@op_index` corresponds to a\nvariable or dynamic parameter operator.\n\nVecAD Vectors\n=============\nCurrently, when a :ref:`VecAD-name` vector only depends on dynamic parameters\nit becomes a variable; see :ref:`VecAD@Efficiency` .\nThis is a simple solution to the problem of having to pass the state of\na vector, when it becomes a variable,\nfrom a dynamic sweep to a zero order forward mode sweep.\n\nGraph Operators\n***************\nThe :ref:`graph_op_enum@Missing Operators` should be\nimplemented so that they can be include in conversion between :ref:`ADFun-name`\nobjects and the AD graphs; see :ref:`cpp_ad_graph-name` , :ref:`json_ad_graph-name` .\n\nReverse Mode\n************\nReverse mode calculation of the function\n:math:`f : \\B{R} \\rightarrow \\B{R}`  defined by :math:`y = f(x)` where\n\n    *ay* [0] = ``pow`` ( *ax* [0], 0.5) * ``pow`` ( *ax* [0], 0.5)\n\nyields the result zero when :math:`x_0 = 0`;\nsee the file ``bug/pow.sh`` .\nThis is a feature of using :ref:`azmul-name` to select which components of\na function are differentiated.\nThis enables one component to yield :ref:`nan-name` for a partial derivative\nwhile another might not.\nIf a separate flag was used for which variables are selected,\nreverse mode multiplications would not need to be converted to ``azmul``\nand the function above would return ``nan`` for the derivative value.\nThis may also be faster that using ``azmul`` .\n\nAtomic Examples\n***************\nConvert the remaining\n:ref:`atomic_two_examples<atomic_two_example-name>` , and\n:ref:`atomic_three_examples<atomic_three_example-name>`\nto use the :ref:`atomic_four-name` interface.\n\n{xrst_comment -------------------------------------------------------------- }\nAbs-normal\n**********\n\nAtomic Functions\n================\nThe :ref:`abs_normal_fun-name` conversion does not handle\natomic functions. This should be fixed.\n\nReturn Functions\n================\nChange the :ref:`abs_normal_fun-name` to return the functions\n:ref:`abs_normal_fun@g@z(x, u)` and\n:ref:`abs_normal_fun@g@y(x, u)` instead of\n:math:`g(x, u)` and :math:`a(x)`.\nWe can add a utility that computes :math:`a(x)` using\n:math:`z(x, u)`, :math:`a_i (x) = | z_i (x, a(x) ) |`\nand :math:`z_i` does not depends on :math:`u_j` for :math:`j \\geq i`.\n\nCancellation\n============\nAvoid cancellation when computing the difference in the absolute value\nfunction at the current point :math:`\\hat{x}` the displaced point\n:math:`x = \\hat{x} + \\Delta x`; i.e.,\n\n.. math::\n\n    |z_i (x, \\tilde{a}(x) ) | - |z_i (\\hat{x}, a(\\hat{x}) ) |\n\n{xrst_comment -------------------------------------------------------------- }\ncppad_lib\n*********\n\nRequirement\n===========\nCurrently ``cppad_lib`` library is only needed if one uses\n:ref:`colpack<colpack_prefix-name>` ,\n:ref:`json_ad_graph-name` ,\n:ref:`cpp_ad_graph-name` , or\n:ref:`code_gen_fun-name` ..\n\ninline\n======\nThe C++ ``inline`` specifier is used to avoid multiple copies\nof functions (that are not templates) during the link process.\nPerhaps some of these functions should be regular functions and part\nin the :ref:`colpack_prefix@cppad_lib` library.\n\nCompilation Speed\n=================\nPerhaps complication speed when using ``AD<double>``\ncould significantly be increased by including some of it's member functions\nin the cppad_lib library.\n\n{xrst_comment ------------------------------------------------------------- }\ncheckpoint\n**********\n\nTapeless AD\n===========\nPerhaps there should be a version of the\n:ref:`chkpoint_two-name`\nclass that uses a tapeless AD package to compute\nthe derivative values.\nThis would allow for algorithms where the operations sequence\ndepends on the independent variable values.\nThere is a question as to how sparsity patterns would be determined\nin this case.\nPerhaps they would be passed into the constructor.\nIf it was known to be constant,\nthe user could compute the pattern using CppAD.\nOtherwise, the user could input\na conservative estimate of the pattern that would be correct.\n\nRe-taping\n=========\nPerhaps the ``checkpoint`` class should allow for re-taping\nderivative values.\nThis would also allow for algorithms where the operations sequence\ndepends on the independent variable values.\nPerhaps (as for tapeless entry above)\nthe sparsity pattern should be passed into the constructor.\n\nTesting\n=======\nThere should be some examples and tests for both speed and memory use\nthat demonstrate that checkpointing is useful.\n\n{xrst_comment -------------------------------------------------------------- }\nSubgraph\n********\n\nForward Mode\n============\nThe :ref:`subgraph_jac_rev-name` routine computes sparsity patterns\nof Jacobians using reverse mode.\nIt is possible that a forward mode version of this method would be\nbetter for some cases.\n\nSparsity\n========\nThe :ref:`subgraph_sparsity-name` calculation treats\neach atomic function call as if\nall of its outputs depend on all of its inputs;\nsee :ref:`subgraph_sparsity@Atomic Function` .\nThese sparsity patterns could be made more efficient\n(could have fewer possibly non-zeros entries)\nby using the sparsity patterns for the atomic functions.\n\n{xrst_comment -------------------------------------------------------------- }\n\ncheck_finite\n************\n\n#. Sometimes one only gets infinite value during zero order forward\n   and nan when computing corresponding derivatives.\n   Change :ref:`check_for_nan-name` to ``check_finite``\n   (not infinite or nan) so that error detection happens during zero\n   order forward instead of later.\n#. In addition, the current :ref:`check_for_nan-name` writes the corresponding\n   zero order values to a temporary file.\n   It would be nice if the ``check_finite`` routine made writing\n   the zero order values optional.\n\ntest_boolofvoid\n***************\nFor general purpose use, the :ref:`test_boolofvoid-name` should be usable\nwithout including a memory check at the end.\n\nExample\n*******\nSplit the :ref:`example list<list_all_examples-name>`\ninto separate groups by the corresponding example subdirectory.\n\n{xrst_comment ------------------------------------------------------------ }\nOptimization\n************\n\nAtomic Functions\n================\nThere is some confusion as to the value of the Taylor coefficients\nfor atomic function arguments and results that have been optimized out.\nSee :ref:`optimize@Atomic Functions` in optimize,\n:ref:`2021@mm-dd@02-16` in whats new for 2021,\n:ref:`atomic_three_rev_depend@depend_x@Optimize`\nin atomic_three, and\n:ref:`atomic_four_rev_depend@depend_x@Optimize` in atomic_four.\n\nTaping\n======\nPerhaps some of the optimization done while taping forward mode\nshould be delayed to the ``optimization`` step.\n\nSpecial Operators\n=================\nAdd special operators that can be implemented more efficiently, e.g.,\n\n    ``square`` ( *x* ) = *x* * *x*\n\nand have the optimizer recognize when they should be used.\n(They could also be in the user API, but it would not be expected\nthat the user would use them.)\n\n{xrst_comment --------------------------------------------------------------}\n\nBase Requirements\n*****************\nChange the :ref:`Base requirements<base_require-name>` to use template\nspecialization instead of functions so that there is a default value\nfor each function. The default would result in a\n:ref:`cppad_assert@Known` assert when the operation is used and not\ndefined by the base class.\nAn example of this type of template specialization can be found in\nthe implementation of :ref:`to_string-name` .\n\nAdolc\n*****\nCreate a documentation page that shows how to convert Adolc commands to\nCppAD commands.\n\nForward Mode Recomputation\n**************************\nIf the results of :ref:`forward_order-name` have already been computed and are still\nstored in the :ref:`ADFun-name` object (see :ref:`size_order-name` ),\nthen they do not need to be recomputed and the results can just be returned.\n\nIterator Interface\n******************\nAll of the CppAD simple vector interfaces should also have an\niterator version for the following reasons:\n\n#. It would not be necessary to copy information to simple vectors\n   when it was originally stored in a different type of container.\n#. It would not be necessary to reallocate memory for a result that is\n   repeatedly calculated\n   (because an iterator for the result container would be passed in).\n\nTracing\n*******\nAdd tracing the operation sequence to the user API and documentation.\nTracing the operation sequence is currently done by changing the CppAD\nsource code. Use the command\n::\n\n    grep '^# *define *CPPAD_.*_TRACE' cppad/local/sweep\\*.hpp\n\nto find all the possible tracing flags.\n\natan2\n*****\nThe :ref:`Atan2-name` function could be made faster by adding\na special operator for it.\n\n{xrst_end wish_list}\n"
  },
  {
    "path": "appveyor.yml",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n#\n# build platform, i.e. x86, x64, Any CPU. This setting is optional.\nplatform:\n  - x64\n\n# branches to build on push\nbranches:\n  only:\n    - master\n\n# msys2 environment\nenvironment:\n  matrix:\n    - HOST_ARCH_ARG: --host=x86_64-w64-mingw32\n      ADD_PATH: /mingw64/bin\n      APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019\n\n# scripts that run after cloning repository\ninstall:\n  - C:\\msys64\\usr\\bin\\bash -lc \"pacman --noconfirm -S mingw-w64-x86_64-cmake\"\n\n#\n# run custom scripts instead of automatic MSBuild\nbuild_script:\n  - C:\\msys64\\usr\\bin\\bash -lc \"\n      cd $APPVEYOR_BUILD_FOLDER;\n      export PATH=$PATH:$ADD_PATH;\n      bin/appveyor.sh make check install uninstall\n    \"\n#\nnotifications:\n  - provider: Email\n    to:\n     - bradbell@seanet.com\n    on_build_status_changed: true\n    on_build_failure: true\n    on_build_success: false\n"
  },
  {
    "path": "authors",
    "content": "             Statement of CppAD Authorship and Copyright\n             ===========================================\n\nBradley M. Bell is the sole author of CppAD.\nWhile Bradley M. Bell worked for the University of Washington during\nthe development of CppAD, the following are also true:\n\n1. The CppAD package was not written or maintained as part of any sponsored\ngrant at the University of Washington.\n\n2. Bradley M. Bell was not paid by the University of Washington for the time\nhe worked on CppAD.\n\n3. Working on CppAD was not part of Bradley M. Bell's normal duties at for the\nUniversity of Washington.\n\nThus, in accordance with Section 2 of the University of Washington's copyright\npolicy (see the file uw_copy_040507.html in this directory) Bradley M. Bell is\nthe copyright holder for CppAD.\n"
  },
  {
    "path": "batch_edit.sed",
    "content": "# ----------------------------------------------------------------------------\n# None of the lists below can have white space or a dollar sign in an entry.\n#\n# list of directories that are added to the repository by batch_edit.sh\n# new_directories='\n# '\n# list of files that are deleted by batch_edit.sh\n# delete_files='\n# '\n# List of files that are not edited by the sed commands in this file\n# (with the possible exception of the extra_seds commands).\n# The files in bin/devel.sh ignore_files are automatically in this list.\n# ignore_files='\n#  val_graph/comp_xam.cpp\n#  val_graph/test/fun2val.cpp\n#  include/cppad/local/val_graph/tape.hpp\n# '\n# list of files and or directories that are moved to new names\n# move_paths='\n# '\n# list of sed commands that map old file and directory names to new names.\n# The characters @s, @d, @n get converted to a space, dollar sign, new line.\n# move_seds='\n# '\n# list of files that get edited by the extra_seds command\n# extra_files='\n# '\n# list of sed commands that are applied to the extra files,\n# after the other sed commands in this file.\n# The characters @s, @d, @n get converted to a space, dollar sign, new line.\n# extra_seds='\n# '\n# ----------------------------------------------------------------------------\n# Put other sed commands below here and without # at start of each line\n/const tape_t<Value>\\* *tape/! b one\nN\nN\nN\nN\nN\nN\ns|const tape_t<Value>\\*\\( *\\)tape\\( *\\),|const tape_t<Value>*\\1    tape\\2 ,|\ns|\\(\\n *\\)\\([^ ]*\\)\\( *\\)\\([^ ]*\\)\\( *\\),|\\1\\2\\3    \\4\\5 ,|g\ns|\\n\\( *\\)\\([^ ]*\\)\\( *\\)\\([^ ]*\\)\\( *\\))|\\n\\1Vector< Vector<Value> >\\&  val_vec_vec   ,\\\n\\1\\2\\3    \\4\\5 )|\n\n: one\n"
  },
  {
    "path": "bin/appveyor.sh",
    "content": "#! /bin/bash -e\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\nif [ $0 != \"bin/appveyor.sh\" ]\nthen\n    echo 'bin/appveyor.sh: must be executed from its parent directory'\n    exit 1\nfi\nif [ \"$1\" != 'make' ] && [ \"$1\" != 'test_one' ]\nthen\n    echo 'usage: bin/appveyor.sh (make|test_one) target1 target2 ...'\n    echo 'target: if make specified, is one of the available make commands'\n    echo          if test_one, specified, is the path to a test file.\n    exit 1\nfi\ncmd=\"$1\"\n# -----------------------------------------------------------------------------\n# bash function that echos and executes a command\necho_eval() {\n    echo $*\n    eval $*\n}\n# -----------------------------------------------------------------------------\nif [ -e build ]\nthen\n    echo_eval rm -r build\nfi\necho_eval mkdir build\necho_eval cd build\necho_eval cmake \\\n    -G '\"Unix Makefiles\"' \\\n    -D cppad_prefix=$(pwd)/prefix \\\n    -D CMAKE_C_COMPILER=gcc \\\n    -D CMAKE_CXX_COMPILER=g++ \\\n    ..\n# -----------------------------------------------------------------------------\n# Microsoft DLLs must be in current directory or execution path\nPATH+=\":$(pwd)/cppad_lib\"\n# -----------------------------------------------------------------------------\n# build target1, target2, ...\nif [ \"$cmd\" == 'make' ]\nthen\n    shift\n    while [ \"$1\" != '' ]\n    do\n        echo_eval make \"$1\"\n        shift\n    done\nelse\n    echo_eval cd ..\n    shift\n    while [ \"$1\" != '' ]\n    do\n        echo_eval bin/test_one.sh \"$1\"\n        shift\n    done\nfi\n# -----------------------------------------------------------------------------\necho 'bin/appveyor.sh: OK'\nexit 0\n"
  },
  {
    "path": "bin/build.bat",
    "content": "if exist build ( rmdir /S build )\nmkdir build\ncd build\ncmake ^\n    -G \"NMake Makefiles\"^\n    -D cppad_cxx_flags=\"/MP /EHs /EHc /std:c++17 /Zc:__cplusplus\"^\n    -D cppad_static_lib=TRUE^\n    ..\nnmake check\n"
  },
  {
    "path": "bin/check_addon.sh",
    "content": "#! /bin/bash -e\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\nif [  \"$0\" != 'bin/check_addon.sh' ]\nthen\n    echo \"bin/check_addon.sh: must be executed from its parent directory\"\n    exit 1\nfi\n# -----------------------------------------------------------------------------\naddon_list='\n    CG\n    PY\n    TMB\n    MIXED\n'\ngrep_cmd=''\nfor addon in $addon_list\ndo\n    if [ \"$grep_cmd\" == '' ]\n    then\n        grep_cmd=\"CPPAD_${addon}_\"\n    else\n        grep_cmd+=\"|CPPAD_${addon}_\"\n    fi\ndone\n#\necho \"Checking source code for names reserved for addon packages\"\necho \"-------------------------------------------------------\"\nok=\"yes\"\nfile_list=`git ls-files`\nfor file in $file_list\ndo\n    if grep -E $grep_cmd $file > /dev/null\n    then\n        echo \"$file contains $grep_cmd\"\n        ok=\"no\"\n    fi\ndone\necho \"-------------------------------------------------------\"\nif [ \"$ok\" = \"no\" ]\nthen\n    echo 'bin/check_if.sh: Error'\n    exit 1\nelse\n    echo 'bin/check_if.sh: OK'\n    exit 0\nfi\n"
  },
  {
    "path": "bin/check_all.sh",
    "content": "#! /usr/bin/env bash\nset -e -u\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-25 Bradley M. Bell\n# ----------------------------------------------------------------------------\n#\nif [ \"$0\" != 'bin/check_all.sh' ]\nthen\n    echo \"bin/check_all.sh: must be executed from its parent directory\"\n    exit 1\nfi\nif [ $# == 1 ]\nthen\n    if [ \"$1\" == --help ]\n    then\ncat << EOF\nbin/check_all.sh flags\npossible flags\n--mixed                    mix debug and release compiles\n--debug                    only compile for debugging\n--release                  only compile for release\n--verbose_make             generate verbose makefiles\n--skip_external_links      do not check documentation external links\n--skip_check_copy          do not check copyright messages\n--suppress_spell_warnings  do not check for documentation spelling errors\nEOF\n        exit 0\n    fi\nfi\n#\n# build_type, verbose_make, skip_external_links, suppress_spell_warnings\nbuild_type='mixed'\nverbose_make='no'\nskip_external_links='no'\nskip_check_copy='no'\nsuppress_spell_warnings='no'\nwhile [ $# != 0 ]\ndo\n    case \"$1\" in\n\n        --mixed)\n        build_type=mixed\n        ;;\n\n        --debug)\n        build_type=debug\n        ;;\n\n        --release)\n        build_type=release\n        ;;\n\n        --verbose_make)\n        verbose_make='yes'\n        ;;\n\n        --skip_external_links)\n        skip_external_links='yes'\n        ;;\n\n        --skip_check_copy)\n        skip_check_copy='yes'\n        ;;\n\n        --suppress_spell_warnings)\n        suppress_spell_warnings='yes'\n        ;;\n\n        *)\n        echo \"bin/check_all.sh: command line argument \"$1\" is not valid\"\n        exit 1\n        ;;\n\n    esac\n    #\n    shift\ndone\n#\n# grep and sed\nsource bin/grep_and_sed.sh\n#\n# LD_LIBRARY_PATH\n# all linking of dynamic libraries should use rpath\nexport LD_LIBRARY_PATH=''\n#\n# top_srcdir\ntop_srcdir=`pwd`\necho \"top_srcdir = $top_srcdir\"\n#\n# echo_eval\necho_eval() {\n    echo $*\n    eval $*\n}\n#\n# echo_log_eval\necho_log_eval() {\n    echo \"$* >& check_all.tmp\"\n    echo \"$*\" > $top_srcdir/check_all.tmp\n    if ! $* >& $top_srcdir/check_all.tmp\n    then\n        tail $top_srcdir/check_all.tmp\n        echo 'Error: see check_all.tmp'\n        exit 1\n    fi\n    # 1.  If we don't have c++17 and mkstemp, then temp_file is not thread safe.\n    #\n    # 2.  If using g++ -O3 -DNDEBUG -Wall,\n    #     an improper compile time warning is generated at:\n    #     forward.hpp:187, reverse.hpp:151, independent.hpp:100-109,\n    #     base_alloc.hpp:143, abs_min_quad.hpp:424 .\n    #\n    # warning\n    warning='no'\n    if [ \"$compiler\" == '--clang' ]\n    then\n        if $sed $top_srcdir/check_all.tmp \\\n            -e '/temp_file.cpp:.*warning.*tmpnam/d' \\\n            | $grep ': *warning *:'\n        then\n            warning='yes'\n        fi\n    else\n        if $sed $top_srcdir/check_all.tmp \\\n            -e '/temp_file.cpp:.*warning.*tmpnam/d' \\\n            -e '/forward.hpp:187:.*warning.*outside array bounds/d' \\\n            -e '/reverse.hpp:151:.*warning.*outside array bounds/d' \\\n            -e '/independent.hpp:10[0-9]:.*warning.*outside array bounds/d' \\\n            -e '/base_alloc.hpp:143:.*warning.*may be used uninitialized/d' \\\n            -e '/abs_min_quad.hpp:424:.*bound.*exceeds maximum/d' \\\n            | $grep ': *warning *:'\n        then\n            warning='yes'\n        fi\n    fi\n    if [ \"$warning\" == 'yes' ]\n    then\n        echo \"The warnings above happened during the command: $*\"\n        echo \"see the file $top_srcdir/check_all.tmp\"\n        exit 1\n    fi\n    #\n    # check_all.log\n    echo '        cat check_all.tmp >> check_all.log'\n    cat $top_srcdir/check_all.tmp >> $top_srcdir/check_all.log\n}\n#\n# random_01\nrandom_01() {\n    set +e\n    eval random_01_$1=\"`expr $RANDOM % 2`\"\n    eval echo \"random_01_$1=\\$random_01_$1\"\n    set -e\n}\n#\n#  check_all.log\n# start new check_all.log\necho \"date > check_all.log\"\ndate | $sed -e 's|^|date: |' > check_all.log\n#\n# $HOME/prefix/cppad\nif [ -e \"$HOME/prefix/cppad\" ]\nthen\n    echo_log_eval rm -r $HOME/prefix/cppad\nfi\n#\n# version\nversion=$(\n    $sed -n -e '/^SET( *cppad_version *\"[0-9.]*\")/p' CMakeLists.txt | \\\n        $sed -e 's|.*\"\\([^\"]*\\)\".*|\\1|'\n)\n#\n# compiler\nrandom_01 compiler\nif [ \"$random_01_compiler\" == '0' ]\nthen\n    compiler='default'\nelse\n    compiler='--clang'\nfi\n#\n# standard\nrandom_01 standard\nif [ \"$random_01_standard\" == '0' ]\nthen\n    random_01 standard\n    if [ \"$random_01_standard\" == '0' ]\n    then\n        standard='--c++11'\n    else\n        standard='--c++17'\n    fi\nelse\n    standard='--c++17'\nfi\n#\n# use_configure\nrandom_01 use_configure\nif [ \"$random_01_use_configure\" == '0' ]\nthen\n    random_01 use_configure\n    if [ \"$random_01_use_configure\" == '0' ]\n    then\n        use_configure='yes'\n    else\n        use_configure='no'\n    fi\nelse\n    use_configure='no'\nfi\n#\n# package_vector, debug_which\nif [ \"$build_type\" == 'debug' ]\nthen\n    package_vector='--cppad_vector'\n    debug_which='--debug_all'\nelif [ \"$build_type\" == 'release' ]\nthen\n    package_vector='--cppad_vector'\n    debug_which='--debug_none'\nelse\n    if [ \"$build_type\" != 'mixed' ]\n    then\n        msg=\"build_type = $build_type not debug release or mixed\"\n        echo \"bin/check_all.sh $msg\"\n        exit 1\n    fi\n    random_01 debug_which\n    if [ \"$random_01_debug_which\" == '0' ]\n    then\n        debug_which='--debug_even'\n    else\n        debug_which='--debug_odd'\n    fi\n    #\n    random_01 package_vector\n    if [ \"$random_01_package_vector\" == '0' ]\n    then\n        package_vector='--boost_vector'\n    else\n        if [ \"$standard\" == '--c++17' ]\n        then\n            package_vector='--eigen_vector'\n        else\n            package_vector='--std_vector'\n        fi\n    fi\nfi\n#\n# debug_which\nif [ \"$use_configure\" == 'yes' ]\nthen\n    debug_which='--debug_none'\nfi\ncat << EOF\ntarball         = cppad-$version.tgz\ncompiler        = $compiler\nstandard        = $standard\ndebug_which     = $debug_which\npackage_vector  = $package_vector\nuse_configure   = $use_configure\nverbose_make    = $verbose_make\nEOF\ncat << EOF >> $top_srcdir/check_all.log\ntarball         = cppad-$version.tgz\ncompiler        = $compiler\nstandard        = $standard\ndebug_which     = $debug_which\npackage_vector  = $package_vector\nuse_configure   = $use_configure\nverbose_make    = $verbose_make\nEOF\n#\n# compiler\nif [ \"$compiler\" == 'default' ]\nthen\n    compiler=''\nfi\n#\n# standard, exclude_package\nif [ \"$standard\" == '--c++17' ]\nthen\n    standard='' # default for run_cmake.sh and configure\n    exclude_package=''\nelse\n    exclude_package='--no_sacado'\nfi\nif [ \"$(uname)\" == 'Darwin' ]\nthen\n    exclude_package+=' --no_colpack'\nfi\n#\n# prefix\n# absolute prefix where optional packages are installed\neval `$grep '^prefix=' bin/get_optional.sh`\nif [[ \"$prefix\" =~ ^[^/] ]]\nthen\n    prefix=\"$(pwd)/$prefix\"\nfi\nif [ ! -d $prefix/include/cppad/cg ]\nthen\n    echo \"Cannot find $prefix/include/cppad/cg\"\n    echo 'Probably need to run bin/get_optional.sh'\n    exit 1\nfi\n#\n# typos\nif which typos >& /dev/null\nthen\n    if ! typos\n    then\n        echo 'check_all: see typos errors above'\n        exit 1\n    fi\nfi\n#\n# check_version\nif echo $version | $grep '[0-9]\\{4\\}0000[.]' > /dev/null\nthen\n    # special interactive case for stable versions.\n    echo_eval bin/check_version.sh\nelse\n    echo_log_eval bin/check_version.sh\nfi\n#\n# bin/check_*.sh\n# Run automated checks for the form bin/check_*.sh with a few exceptions.\nlist=$(\n    ls bin/check_* | $sed \\\n    -e '/check_all.sh/d' \\\n    -e '/check_doxygen.sh/d' \\\n    -e '/check_install.sh/d' \\\n    -e '/check_copy.sh/d' \\\n    -e '/check_invisible/d'\n)\n#\necho_eval bin/check_invisible.sh\nif [ \"$skip_check_copy\" == 'no' ]\nthen\n    echo_eval bin/check_copy.sh\nfi\nfor check in $list\ndo\n    echo_log_eval $check\ndone\n#\n# run_xrst.sh\nflags=''\nif [ \"$skip_external_links\" == 'no' ]\nthen\n    flags+=' --external_links'\nfi\nif [ \"$suppress_spell_warnings\" == 'yes' ]\nthen\n    flags+=' --suppress_spell_warnings'\nfi\nbin/run_xrst.sh $flags\n#\n# build/cppad-$version.tgz\necho_log_eval bin/package.sh\n#\n# build/cppad-$version\necho_log_eval cd build\necho_log_eval tar -xzf cppad-$version.tgz\necho_log_eval cd cppad-$version\n#\n# build/cppad-$version/bin/get_optional.sh\n$sed -i bin/get_optional.sh -e \"s|^prefix=.*|prefix=$prefix|\"\n#\n# builder\nif [ \"$use_configure\" == 'yes' ]\nthen\n    builder='make'\nelif [ \"$verbose_make\" == 'yes' ]\nthen\n    builder='make'\nelse\n    builder='ninja'\nfi\n#\n# verbose_flag\nif [ \"$verbose_make\" == 'yes' ]\nthen\n    verbose_flag='--verbose_make'\nelse\n    verbose_flag=''\nfi\n#\n# configure or cmake\nif [ \"$use_configure\" == 'yes' ]\nthen\n    echo_log_eval bin/run_configure.sh \\\n        $verbose_flag \\\n        $compiler \\\n        $standard \\\n        $package_vector\nelse\n    echo_log_eval bin/run_cmake.sh \\\n        $verbose_flag \\\n        $compiler \\\n        $standard \\\n        $debug_which \\\n        $exclude_package \\\n        $package_vector\nfi\necho_log_eval cd build\n#\n# n_job\nif which nproc >& /dev/null\nthen\n    n_job=$(nproc)\nelse\n    n_job=$(sysctl -n hw.ncpu)\nfi\n#\n# build: check\necho_log_eval $builder -j $n_job check\n#\n# speed/cppad/speed_cppad\nfor option in onetape colpack optimize atomic memory boolsparsity\ndo\n    echo_eval speed/cppad/speed_cppad correct 432 $option\ndone\n#\n# speed/adolc/speed_adolc\necho_eval speed/adolc/speed_adolc correct         432 onetape\necho_eval speed/adolc/speed_adolc sparse_jacobian 432 onetape colpack\necho_eval speed/adolc/speed_adolc sparse_hessian  432 onetape colpack\n#\n# bin/test_multi_thread.sh\ncd ..\nbin/test_multi_thread.sh $builder\ncd build\n#\n# print_for test\n# redo this build in case it is commented out above\nprogram='example/print_for/example_print_for'\necho_log_eval $builder -j $n_job example_print_for\necho_log_eval $program\n$program | $sed -e '/^Test passes/,$d' > temp.1.$$\n$program | $sed -e '1,/^Test passes/d' > temp.2.$$\nif diff temp.1.$$ temp.2.$$\nthen\n    rm temp.1.$$ temp.2.$$\n    echo_log_eval echo \"print_for: OK\"\nelse\n    echo_log_eval echo \"print_for: Error\"\n    exit 1\nfi\n#\n# bin/test_install.sh\necho_log_eval cd ..\nif [ \"$standard\" == '' ]\nthen\n    echo_log_eval bin/test_install.sh $builder --c++17\nelse\n    echo_log_eval bin/test_install.sh $builder $standard\nfi\n#\n#\necho \"date >> check_all.log\"\ndate  | $sed -e 's|^|date: |' >> $top_srcdir/check_all.log\n# ----------------------------------------------------------------------------\necho \"$0: OK\" >> $top_srcdir/check_all.log\necho \"$0: OK\"\nexit 0\n"
  },
  {
    "path": "bin/check_copy.sh",
    "content": "#! /usr/bin/env bash\nset -e -u\n# !! EDITS TO THIS FILE ARE LOST DURING UPDATES BY xrst.git/bin/dev_tools.sh !!\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2023-25 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# bin/check_copy.sh\n# Checks that the copyright message, in all the source files,\n# is correct and up to date. If there were any errors, a message is printed,\n# it is automatically corrected, and this script exits with an error.\n# Files that are not checked can be specified in bin/dev_setting.sh\n# ----------------------------------------------------------------------------\nif [ \"$0\" != \"bin/check_copy.sh\" ]\nthen\n    echo \"bin/check_copy.sh: must be executed from its parent directory\"\n    exit 1\nfi\nif [ \"$#\" != 0 ]\nthen\n    echo 'check_copy does not expect any arguments'\n    exit 1\nfi\n#\n# grep, sed\nsource bin/grep_and_sed.sh\n#\n# spdx_license_id, no_copyright_list\nsource bin/dev_settings.sh\n#\n# yy\nyy=$(date +%y)\n#\n# ----------------------------------------------------------------------------\nif [ $# != 0 ]\nthen\n    echo 'bin/check_copy.sh does not expect any arguments'\n    exit 1\nfi\nif [ \"$0\" != 'bin/check_copy.sh' ]\nthen\n    echo 'bin/check_copy.sh: must be executed from its parent directory'\n    exit 1\nfi\nif [ ! -e './.git' ]\nthen\n    echo 'bin/check_copy.sh: cannot find ./.git'\n    exit 1\nfi\n# ---------------------------------------------------------------------------\n# fullname\nfullname=''\nif [ \"${USER+x}\" != '' ]\nthen\n    for contributor in $contributor_list\n    do\n        if [[ $contributor == ${USER}* ]]\n        then\n            fullname=$(echo $contributor | sed -e 's|^.*:||' -e 's|_| |g')\n        fi\n    done\n    if [ \"$fullname\" == '' ] && [ \"${USER+x}\" != '' ]\n    then\n        echo \"Cannot user name = $USER in bin/dev_settings.sh contributor_list\"\n        exit 1\n    fi\nfi\n# ---------------------------------------------------------------------------\n# copyright_all, copyright_changed\necho \"#\" > temp.sed\nfor name in $no_copyright_list\ndo\n    if [ -f $name ]\n    then\n        echo \"^$name\\$\" | $sed -e 's|/|[/]|g' -e 's|.*|/&/d|' >> temp.sed\n    elif [ -d $name ]\n    then\n        echo \"^$name/\" | $sed -e 's|/|[/]|g' -e 's|.*|/&/d|' >> temp.sed\n    else\n        echo \"$name in no_copyright_list is not a file or directory\"\n        exit 1\n    fi\ndone\ncopyright_all=$(git ls-files | $sed -f temp.sed)\ncopyright_changed=$(\n    git status --porcelain | $sed -e 's|^...||' | $sed -f temp.sed\n)\n# ---------------------------------------------------------------------------\nmissing='no'\nchanged='no'\nfor file_name in $copyright_all\ndo\n    # if file has not been deleted\n    if [ -e $file_name ]\n    then\n        # if file does not have expected license identifier\n        if ! $grep \"$spdx_license_id\\$\" $file_name > /dev/null\n        then\n            if [ \"$missing\" == 'no' ]\n            then\n                echo \"Cannot find line that ends with:\"\n                echo \"   $spdx_license_id\"\n                echo \"In the following files:\"\n            fi\n            echo \"$file_name\"\n            missing='yes'\n        fi\n    fi\ndone\n# ---------------------------------------------------------------------------\ncat << EOF > temp.sed\n/SPDX-FileContributor:[ 0-9.-]*$fullname/! b end\ns|\\\\([0-9]\\\\{4\\\\}\\\\)[-0-9]* |\\\\1-$yy |\ns|20$yy-$yy |20$yy |\n#\n: end\nEOF\nlist=''\nif [ \"$fullname\" != '' ]\nthen\n    list=\"$copyright_changed\"\nfi\nfor file_name in $list\ndo\n    if [ -e $file_name ] && [ -f $file_name ]\n    then\n        if ! $grep \"SPDX-FileContributor:[ 0-9.-]*$fullname\" $file_name \\\n            > /dev/null\n        then\n            echo \"username = $USER, fullname = $fullname\"\n            echo \"The following pattern does not appear in $file_name\"\n            echo 'SPDX-FileContributor:[ 0-9.-]*'$fullname:\n            exit 1\n        fi\n        $sed -f temp.sed $file_name > temp.$$\n        if diff $file_name temp.$$ > /dev/null\n        then\n            rm temp.$$\n        else\n            if [ \"$changed\" == 'no' ]\n            then\n                echo 'The following file contributor dates have been updated'\n            fi\n            echo $file_name\n            if diff $file_name temp.$$\n            then\n                echo 'check_version.sh: program error'\n                exit 1\n            fi\n            changed='yes'\n            if [ -x $file_name ]\n            then\n                mv temp.$$ $file_name\n                chmod +x $file_name\n            else\n                mv temp.$$ $file_name\n            fi\n        fi\n    fi\ndone\n#\nif [ \"$missing\" = 'yes' ] || [ \"$changed\" == 'yes' ]\nthen\n    echo 'check_copy.sh: The copyright messages above were updated.'\n    echo 'Re-execute bin/check_copy.sh ?'\n    exit 1\nfi\necho 'bin/check_copy.sh: OK'\nexit 0\n"
  },
  {
    "path": "bin/check_define.sh",
    "content": "#! /bin/bash -e\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\nif [ $0 != 'bin/check_define.sh' ]\nthen\n    echo 'bin/check_define.sh: must be executed from its parent directory'\n    exit 1\nfi\n# -----------------------------------------------------------------------------\necho 'Check '# define' versus '# undef' names and check for addon names'\necho '-----------------------------------------------------------------------'\nfile_list=`git ls-files '*.hpp' '*.in' |\n    sed -n -e '/^include\\/cppad\\//p'`\nadd_on_list='CG PY TMB MIXED'\n#\n# preprocessor symbols in user API\nsed -n -e \"/^# *undef /p\" xrst/preprocessor.xrst | sed \\\n    -e \"s/^# *undef  *\\([A-Za-z0-9_]*\\).*/\\1/\" > check_define.2\n#\nfor file in $file_list\ndo\n        include_guard=`echo $file | sed \\\n            -e 's|^include/||' \\\n            -e 's|\\.in||' \\\n            -e 's|/|_|g' \\\n            -e 's|\\.hpp|_hpp|' \\\n            | tr [a-z] [A-Z]\n        `\n        # define\n        if [ ! -e $file.in ]\n        then\n            sed -n -e \"/^# *define /p\" $file | sed \\\n                -e \"/^# *define *$include_guard/d\" \\\n                -e '/^# define NOMINMAX/d' \\\n                -e \"s/^# *define  *\\([A-Za-z0-9_]*\\).*/\\1/\" >> check_define.1\n        fi\n        # undef\n        if [ ! -e $file.in ]\n        then\n            # note <cppad/local/utility/cppad_vector_itr.hpp> is special\n            sed -n -e \"/^# *undef /p\" $file | sed \\\n                -e '/CPPAD_LOCAL_UTILITY_CPPAD_VECTOR_ITR_HPP/d' \\\n                -e \"s/^# *undef  *\\([A-Za-z0-9_]*\\).*/\\1/\" >> check_define.2\n        fi\n        # add_on\n        for add_on in $add_on_list\n        do\n            if grep \"CPPAD_${add_on}_\" $file\n            then\n                add_on_error='true'\n            fi\n        done\ndone\n# sort lists\nfor file in check_define.1 check_define.2\ndo\n    sort -u $file > check_define.3\n    mv check_define.3 $file\ndone\nif ! diff check_define.1 check_define.2\nthen\n    echo 'check_define.sh: Error: defines and undefs do not match'\n    rm check_define.1 check_define.2\n    exit 1\nfi\nrm check_define.1 check_define.2\necho '-----------------------------------------------------------------------'\nif [ \"$add_on_error\" == 'true' ]\nthen\n    echo 'check_define.sh: Error: add_on preprocessor symbol found'\n    exit 1\nfi\necho 'check_define.sh: OK'\nexit 0\n"
  },
  {
    "path": "bin/check_deprecated.sh",
    "content": "#! /bin/bash -eu\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# bash function that echos and executes a command\necho_eval() {\n    echo $*\n    eval $*\n}\n# -----------------------------------------------------------------------------\nif [ \"$0\" != \"bin/check_deprecated.sh\" ]\nthen\n    echo \"bin/check_deprecated.sh: must be executed from its parent directory\"\n    exit 1\nfi\nif [ \"$#\" != '0' ]\nthen\n    echo 'usage: bin/check_deprecated.sh.sh'\n    exit 1\nfi\n# -----------------------------------------------------------------------------\nfile_list=`git ls-files example speed | sed -e '/example\\/deprecated\\//d'`\n# -----------------------------------------------------------------------------\n# deprecated functions with not arguments\nlist_just_name='\n    CPPAD_TRACK_\n    CPPAD_TEST_VECTOR\n    CppADCreateUnaryBool\n    CppADCreateDiscrete\n    zdouble\n    colpack.star\n'\nlist_namespace='\n    omp_alloc\n    cppad_ipopt\n'\ntemplate_name='\n    epsilon\n'\nlist_no_argument='\n    Order\n    Memory\n    Size\n    taylor_size\n    use_VecAD\n    size_taylor\n    capacity_taylor\n    CompareChange\n    memory_leak\n'\nlist_one_argument='\n    nan\n    Dependent\n    omp_max_thread\n    memory_leak\n'\nlist_two_argument='\n'\nlist_three_argument='\n'\nfor file in $file_list\ndo\n    for name in $list_just_name\n    do\n        if grep \"$name\" $file > /dev/null\n        then\n            echo \"$name is deprecated and appreas in $file\"\n            exit 1\n        fi\n    done\n    for name in $list_namespace\n    do\n        if grep \"[^a-zA-Z_]$name::\" $file > /dev/null\n        then\n            echo \"$name:: is deprecated and appreas in $file\"\n            exit 1\n        fi\n    done\n    for name in $list_namespace\n    do\n        if grep \"using *$name[^a-zA-Z_]\" $file > /dev/null\n        then\n            echo \"using $name is deprecated and appreas in $file\"\n            exit 1\n        fi\n    done\n    for name in $template_name\n    do\n        if grep \"[^a-zA-Z_]$name *< *[a-zA-Z_][a-zA-Z_]* *>\" $file > /dev/null\n        then\n            echo \"$name<arg> is deprecated and appreas in $file\"\n            exit 1\n        fi\n    done\n    for fun in $list_no_argument\n    do\n        if grep \"[^a-zA-Z_]$fun *( *)\" $file > /dev/null\n        then\n            echo \"$fun() is deprecated and appreas in $file\"\n            exit 1\n        fi\n    done\n    for fun in $list_one_argument\n    do\n        if sed -e \"s|bool *$fun(void)||\" $file | \\\n            grep \"[^a-zA-Z_]$fun *( *[a-zA-Z_0-9.][a-zA-Z_0-9.]* *)\" > /dev/null\n        then\n            echo \"$fun(arg1) is deprecated and appreas in $file\"\n            exit 1\n        fi\n    done\n    for fun in $list_two_argument\n    do\n        if grep \"[^a-zA-Z_]$fun *([^,)]*,[^,)]*)\" $file > /dev/null\n        then\n            echo \"$fun(arg1,arg2) is deprecated and appreas in $file\"\n            exit 1\n        fi\n    done\n    for fun in $list_three_argument\n    do\n        if grep \"[^a-zA-Z_]$fun *([^,)]*,[^,)]*,[^,)]*)\" $file > /dev/null\n        then\n            echo \"$fun(arg1,arg2,arg3) is deprecated and appreas in $file\"\n            exit 1\n        fi\n    done\ndone\n# -----------------------------------------------------------------------------\necho 'bin/check_deprecated.sh: OK'\nexit 0\n"
  },
  {
    "path": "bin/check_doxygen.sh",
    "content": "#! /bin/bash -e\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\nif [ ! -e \"bin/check_doxygen.sh\" ]\nthen\n    echo \"bin/check_doxygen.sh: must be executed from its parent directory\"\n    exit 1\nfi\n# -----------------------------------------------------------------------------\nif ! bin/run_doxygen.sh\nthen\n    echo 'check_doxygen.sh: Error'\n    exit 1\nfi\necho 'check_doxygen.sh: OK'\nexit 0\n"
  },
  {
    "path": "bin/check_example.sh",
    "content": "#! /bin/bash -e\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\nif [ ! -e \"bin/check_example.sh\" ]\nthen\n    echo \"bin/check_example.sh: must be executed from its parent directory\"\n    exit 1\nfi\n#\n# grep, sed\nsource bin/grep_and_sed.sh\n# -----------------------------------------------------------------------------\necho \"Checking that all examples are in xrst/example_list.xrst\"\necho \"-------------------------------------------------------\"\nfile_list=`git ls-files | $sed -n \\\n    -e '/^example\\/deprecated\\//d' \\\n    -e '/^example\\//p'`\n#\n$sed < xrst/example_list.xrst > check_example.$$ \\\n    -n -e '/[$]begin list_all_examples\\$\\$/,/\\$end/p'\n#\n# Make sure all example names are of the form *.cpp or *.hpp\ncheck=`$sed -n -e '/$rref [0-9a-zA-Z_]*\\.[hc]pp/d' \\\n    -e '/$rref/p' check_example.$$`\nif [ \"$check\" != '' ]\nthen\n    echo $check\n    echo 'Not all examples are for *.hpp or *.cpp files'\n    exit 1\nfi\nok=\"yes\"\nfor file in $file_list\ndo\n    # only files in example directory with [$]begin *.cpp or *.hpp\n    # e.g., example/multi_thread/harmonic.xrst has [$]begin harmonic.cpp$$ in it\n    name=`$grep '[$]begin *[0-9a-zA-Z_]*\\.[hc]pp' $file |\n        $sed -e 's/.*[$]begin *//' -e 's/ *$$.*//'`\n    if [ \"$name\" != \"\" ]\n    then\n        if ! $grep \"$name\" check_example.$$ > /dev/null\n        then\n            echo \"$name is missing from xrst/example_list.xrst\"\n            ok=\"no\"\n        fi\n    fi\ndone\nrm check_example.$$\necho \"-------------------------------------------------------\"\nif [ \"$ok\" != \"yes\" ]\nthen\n    echo \"Error: nothing should be between the two dashed lines above\"\n    exit 1\nfi\n#\n# fix sort order; see\n# unix.stackexchange.com/questions/87745/what-does-lc-all-c-do/87763#87763\nexport LC_ALL='C'\n#\ndir_list='\n    example/graph\n    example/json\n    example/general\n'\nfor dir in $dir_list\ndo\n    echo \"Checking $dir file versus example names\"\n    name=`echo $dir | $sed -e 's|.*/||'`\n    #\n    ls $dir/*.cpp | $sed  \\\n        -e \"s|$dir/||\" -e \"/^$name\\\\.cpp/d\" -e 's|\\.cpp||' > check_example.1.$$\n    if [ \"$name\" == 'general' ]\n    then\n        list=`ls $dir/*.hpp \\\n            | $sed -e \"s|$dir/||\" -e 's|\\.hpp$||' -e '/^general$/d'`\n        for file in $list\n        do\n            $sed -i check_example.1.$$ -e \"/^$file\\$/d\"\n        done\n    fi\n    $sed -n -e '/^extern bool [a-z0-9A-Z_]*(void);/p' $dir/$name.cpp \\\n        | $sed -e 's/extern bool \\([a-z0-9A-Z_]*\\)(void);/\\1/' \\\n        | $sed -e 's/\\([a-z]\\)\\([A-Z]\\)/\\1_\\2/g' \\\n        | tr '[A-Z]' '[a-z]' \\\n        | sort > check_example.2.$$\n    if ! diff check_example.1.$$ check_example.2.$$\n    then\n        rm check_example.1.$$ check_example.2.$$\n        echo \"$dir: file and function names do not agree\"\n        echo 'see output above.'\n        exit 1\n    fi\ndone\nrm check_example.1.$$ check_example.2.$$\n#\necho 'bin/check_example.sh: OK'\nexit 0\n"
  },
  {
    "path": "bin/check_if.sh",
    "content": "#! /bin/bash -e\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\nif [  \"$0\" != 'bin/check_if.sh' ]\nthen\n    echo \"bin/check_if.sh: must be executed from its parent directory\"\n    exit 1\nfi\n# -----------------------------------------------------------------------------\n# CppAD uses preprocessor '# if 0' comment blocks for temporary changes\n# that will to be removed before testing for check in.\necho \"Checking for '# if 0' and '# if NDEBUG' commands in source code\"\necho \"-------------------------------------------------------\"\nok=\"yes\"\nlist=`git ls-files | sed -n \\\n    -e '/\\.cpp$/p' \\\n    -e '/\\.hpp$/p' \\\n    -e '/\\.hpp.in$/p'`\nfor file in $list\ndo\n    if grep '^# *if *0 *$' $file > /dev/null\n    then\n        # CppAD uses /* comment */ for all its block comments\n        echo \"$file has an '# if 0' preprocessor command\"\n        ok=\"no\"\n    fi\n    if grep '^# *if *NDEBUG *$' $file > /dev/null\n    then\n        # This should probably be # ifndef NDEBUG ?\n        echo \"$file has an '# if NDEBUG' preprocessor command\"\n        ok=\"no\"\n    fi\ndone\necho \"-------------------------------------------------------\"\nif [ \"$ok\" = \"no\" ]\nthen\n    echo 'bin/check_if.sh: Error'\n    exit 1\nelse\n    echo 'bin/check_if.sh: OK'\n    exit 0\nfi\n"
  },
  {
    "path": "bin/check_include_def.sh",
    "content": "#! /bin/bash -e\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\nif [ ! -e \"bin/check_include_def.sh\" ]\nthen\n    echo \"bin/check_include_def.sh: must be executed from its parent directory\"\n    exit 1\nfi\n# ---------------------------------------------------------------------------\necho \"Differences between include file names and ifndef at top directives.\"\necho \"Also make sure same ifndef not used by two different files.\"\necho \"-------------------------------------------------------------------\"\nlist=`git ls-files | sed -n -e '/\\.hpp$/p'`\ndifferent='no'\nfor file_name in $list\ndo\n    dir=`echo $file_name | sed -e 's|/[^/]*$||'`\n    name=`echo $file_name | sed -e 's|^.*/||'`\n    first_dir=`echo $dir | sed -e 's|/.*||'`\n    #\n    macro_name=`sed -n -e '/^# *ifndef *CPPAD_[0-9A-Z_]*_HPP$/p' $file_name | \\\n        sed -e 's|^# *ifndef *||'`\n    check=`echo $file_name | tr [a-zA-Z/.] [A-Za-z__]`\n    #\n    if [ \"$first_dir\" == 'include' ]\n    then\n        check=`echo $check | sed -e 's|INCLUDE_||'`\n    else\n        check=\"CPPAD_$check\"\n    fi\n    #\n    if [ \"$macro_name\" == '' ]\n    then\n        echo \"file_name=$file_name\"\n        echo 'Cannot find  ^# *ifndef *CPPAD_[0-9A-Z_]*_HPP'\n        different='yes'\n    elif [ \"$macro_name\" != \"$check\" ]\n    then\n        echo \" file_name=$file_name\"\n        echo \"macro_name=$macro_name\"\n        different='yes'\n    fi\ndone\n#\necho \"-------------------------------------------------------------------\"\nif [ $different = 'yes' ]\nthen\n    echo \"Error: nothing should be between the two dashed lines above\"\n    exit 1\nelse\n    echo \"Ok: nothing is between the two dashed lines above\"\n    exit 0\nfi\n"
  },
  {
    "path": "bin/check_include_file.sh",
    "content": "#! /bin/bash -e\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\nif [ ! -e \"bin/check_include_file.sh\" ]\nthen\n    msg=\"must be executed from its parent directory\"\n    echo \"bin/check_include_file.sh: $msg\"\n    exit 1\nfi\n#\n# $grep, sed\nsource bin/grep_and_sed.sh\n# -----------------------------------------------------------------------------\n#\necho \"Checking difference between C++ include directives and file names.\"\necho \"-------------------------------------------------------------------\"\nif [ -e check_include_file.1.$$ ]\nthen\n    echo \"bin/check_include_file.sh: unexpected check_include_file.1.$$\"\n    exit 1\nfi\nlist=`git ls-files | $sed -n \\\n    -e '/\\.cpp$/p' \\\n    -e '/\\.hpp$/p'`\nfor file in $list\ndo\n    $sed -n $file \\\n        -e '/^# *include *<cppad\\/cg\\//d' \\\n        -e '/^# *include *<cppad\\//p' \\\n        >> check_include_file.1.$$\ndone\n#\ncat check_include_file.1.$$ | \\\n    $sed -e 's%[^<]*<%%'  -e 's%>.*$%%' | \\\n    sort -u > check_include_file.2.$$\n#\n# The following files should never be included:\n#  cppad/local/var_op/prototype_op.hpp\n#  cppad/local/optimize/define_prototype.hpp\n# All other files should.\n#\n# The files cppad/configure.hpp and cppad/local/is_pod.hpp\n# are not in git repository (they are built during configuration)\ngit ls-files | $sed -n -e '/include\\/cppad\\/.*\\.hpp$/p' | \\\n    $sed \\\n        -e '1,1s|^|include/cppad/configure.hpp\\n|' \\\n        -e '1,1s|^|include/cppad/local/is_pod.hpp\\n|' \\\n        -e '/include\\/cppad\\/local\\/var_op\\/prototype_op.hpp/d' \\\n        -e '/include\\/cppad\\/example\\/eigen_plugin.hpp/d' | \\\n    $sed -e 's|^include/||' | \\\n    sort -u > check_include_file.3.$$\n#\ndifferent='no'\nif ! diff check_include_file.2.$$ check_include_file.3.$$ > /dev/null\nthen\n    found='no'\n    different='yes'\n    for file in `cat check_include_file.2.$$`\n    do\n        if ! $grep \"$file\" check_include_file.3.$$ > /dev/null\n        then\n            found='yes'\n            echo \"The file include/$file is unknown to git.\"\n            echo 'Perhaps it needs to be added with the command'\n            echo \"    git add include/$file\"\n        fi\n    done\n    for file in `cat check_include_file.3.$$`\n    do\n        if ! $grep \"$file\" check_include_file.2.$$ > /dev/null\n        then\n            found='yes'\n            echo \"The included $file is no longer included.\"\n            echo 'Perhaps it needs to be git deleted ?'\n        fi\n    done\n    if [ \"$found\" == 'no' ]\n    then\n        echo 'bin/check_include_file.sh: Cannot find reason for difference'\n        echo 'Improve this script.'\n        exit 1\n    fi\nfi\nfor index in 1 2 3\ndo\n    rm check_include_file.$index.$$\ndone\n#\necho \"-------------------------------------------------------------------\"\nif [ $different = \"yes\" ]\nthen\n    echo \"Error: nothing should be between the two dashed lines above\"\n    exit 1\nelse\n    echo \"Ok: nothing is between the two dashed lines above\"\n    exit 0\nfi\n"
  },
  {
    "path": "bin/check_include_xrst.sh",
    "content": "#! /bin/bash -e\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\nif [ ! -e \"bin/check_include_xrst.sh\" ]\nthen\n    echo \"bin/check_include_xrst.sh: must be executed from its parent directory\"\n    exit 1\nfi\n# -----------------------------------------------------------------------------\ncount=`git ls-files include/cppad | grep '/xrst/.*\\.hpp' | wc -l`\nif [ $count != '0' ]\nthen\n    git ls-files include/cppad | grep '/xrst/.*\\.hpp'\n    echo 'Cannot put *.hpp files below xrst in include directory'\n    echo 'because install of include directory will exclude them.'\n    exit 1\nfi\necho 'check_include_xrst: OK'\nexit 0\n"
  },
  {
    "path": "bin/check_invisible.sh",
    "content": "#! /usr/bin/env bash\nset -e -u\n# !! EDITS TO THIS FILE ARE LOST DURING UPDATES BY xrst.git/bin/dev_tools.sh !!\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2020-25 Bradley M. Bell\n# -----------------------------------------------------------------------------\n# bin/check_invisible.sh\n# Checks that there is no invisible white space in any of the source files.\n# If there is, a message is printed about it, it is automatically removed,\n# and this script exits with an error.\n# Files that are not checked can be specified in bin/dev_setting.sh\n# -----------------------------------------------------------------------------\nif [ \"$0\" != \"bin/check_invisible.sh\" ]\nthen\n    echo \"bin/check_invisible.sh: must be executed from its parent directory\"\n    exit 1\nfi\nif [ \"$#\" == 0 ]\nthen\n    all='false'\nelif [ \"$#\" == 1 ] && [ \"$1\" == 'all' ]\nthen\n    all='true'\nelse\n    echo 'usage: bin/check_invisible [all]'\n    exit 1\nfi\n#\n# sed\nsource bin/grep_and_sed.sh\n#\n# invisible_and_tab_ok\nsource bin/dev_settings.sh\n# ----------------------------------------------------------------------------\n#\n# sed.$$\necho '#' > sed.$$\nfor name in $no_copyright_list\ndo\n    if [ -f $name ]\n    then\n        echo \"^$name\\$\" | $sed -e 's|/|[/]|g' -e 's|.*|/&/d|' >> sed.$$\n    elif [ -d $name ]\n    then\n        echo \"^$name/\" | $sed -e 's|/|[/]|g' -e 's|.*|/&/d|' >> sed.$$\n    else\n        echo \"$name in no_copyright_list is not a file or directory\"\n        exit 1\n    fi\ndone\n#\n# file_list\nif [ \"$all\" == 'true' ]\nthen\n    file_list=$(git ls-files | $sed -f sed.$$)\nelse\n    file_list=$(git status --porcelain | \\\n        $sed -e '/^D/d' -e 's|^...||' | $sed -f sed.$$\n    )\nfi\n# ----------------------------------------------------------------------------\n#\n# sed.$$\ncat << EOF > sed.$$\ns|[ \\\\t][ \\\\t]*\\$||\ns| *\\t|\\t|g\n1{/^[ \\\\t]*\\$/d}\n\\${/^[ \\\\t]*\\$/d}\nEOF\n#\n# changed, file\nchanged='no'\nfor file in $file_list\ndo\n    if [ -f \"$file\" ]\n    then\n        $sed -f sed.$$ $file > copy.$$\n        if ! diff $file copy.$$ > diff.$$\n        then\n            changed='yes'\n            echo \"$file: original (<) invisible space removed (>)\"\n            cat diff.$$\n            if [ -x $file ]\n            then\n                chmod +x copy.$$\n            fi\n            mv copy.$$ $file\n        else\n            rm copy.$$\n        fi\n        rm diff.$$\n    fi\ndone\nrm sed.$$\nif [ \"$changed\" == 'yes' ]\nthen\n    echo 'check_invisible.sh: The invisible white space above have been fixed'\n    echo 'Re-execute bin/check_invisible.sh ?'\n    exit 1\nfi\necho 'check_invisible.sh: OK'\nexit 0\n"
  },
  {
    "path": "bin/check_nominmax.sh",
    "content": "#! /bin/bash -e\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\nif [  \"$0\" != 'bin/check_nominmax.sh' ]\nthen\n    echo \"bin/check_nominmax.sh: must be executed from its parent directory\"\n    exit 1\nfi\n# -----------------------------------------------------------------------------\nlist=$(git grep -n '^# *include *<windows.h>'  | sed -e 's|\\(:[0-9]*:\\).*|\\1|')\nfor match in $list\ndo\n    file=$(echo $match | sed -e 's|\\([^:]*\\):\\([0-9]*\\):|\\1|')\n    line=$(echo $match | sed -e 's|\\([^:]*\\):\\([0-9]*\\):|\\2|')\n    let \"line = $line - 2\"\n    if ! sed -n \"${line}p\" $file | grep '^# *define *NOMINMAX' > /dev/null\n    then\ncat << EOF\nIn $file\n    # ifndef NOMINMAX\n    # define NOMINMAX\n    # endif\nMust be the three lines before:\n    # include <windows.h>\nEOF\n    fi\ndone\n#\necho 'check_nominmax.sh: OK'\nexit 0\n"
  },
  {
    "path": "bin/check_op_code.sh",
    "content": "#! /bin/bash -e\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\nif [ ! -e \"bin/check_op_code.sh\" ]\nthen\n    echo \"bin/check_op_code.sh: must be executed from its parent directory\"\n    exit 1\nfi\nfile='include/cppad/local/op_code_var.hpp'\n# ---------------------------------------------------------------------------\n# order in enum list\nsed -n -e '/^enum/,/NumberOp/p' $file | sed \\\n    -e '/^enum/d' \\\n    -e '/NumberOp/d' \\\n    -e 's/^[ ]*//' \\\n    -e 's/,.*//' > temp.1\n# -----------------------------------------------------------------------------\n# check NumArgTable\nsed -n -e '/NumArgTable\\[\\]/,/NumberOp/p' $file | \\\n    sed \\\n        -e '/NumArgTable\\[\\]/d' \\\n        -e '/NumberOp/d' \\\n        -e 's|^ */[*] ||' \\\n        -e 's| *[*]/.*||' > temp.2\n#\nif ! diff temp.1 temp.2\nthen\n    echo 'check_op_code.sh: NumArgTable list is different from enum list'\n    exit 1\nfi\n# -----------------------------------------------------------------------------\n# check NumResTable\nsed -n -e '/NumResTable\\[\\]/,/NumberOp/p' $file | \\\n    sed \\\n        -e '/NumResTable\\[\\]/d' \\\n        -e '/NumberOp/d' \\\n        -e 's|^ */[*] ||' \\\n        -e 's| *[*]/.*||' > temp.2\n#\nif ! diff temp.1 temp.2\nthen\n    echo 'check_op_code.sh: NumResTable list is different from enum list'\n    exit 1\nfi\n# -----------------------------------------------------------------------------\n# check OpNameTable\nsed -n -e '/const char \\*OpNameTable\\[\\]/,/\"Number\"/p' $file | \\\n    sed \\\n        -e '/OpNameTable\\[\\]/d' \\\n        -e '/\"Number\"/d' \\\n        -e 's|^ *\"||' \\\n        -e 's|\".*||' \\\n        > temp.2\n#\nif ! diff temp.1 temp.2\nthen\n    echo 'check_op_code.sh: OpNameTable list is different from enum list'\n    exit 1\nfi\n# -----------------------------------------------------------------------------\n# clean up\nrm temp.1 temp.2\n# ----------------------------------------------------------------------------\necho \"$0: OK\"\nexit 0\n"
  },
  {
    "path": "bin/check_sort.sh",
    "content": "#! /usr/bin/env bash\nset -e -u\n# !! EDITS TO THIS FILE ARE LOST DURING UPDATES BY xrst.git/bin/dev_tools.sh !!\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2020-25 Bradley M. Bell\n# -----------------------------------------------------------------------------\n# bin/check_sort.sh\n# Checks that for all files, all the sections between\n#  BEGIN_SORT_THIS_LINE_PLUS_#\n#  END_SORT_THIS_LINE_MINUS_#\n# are sorted. If not, it is corrected and an error is returned.\n# -----------------------------------------------------------------------------\nif [ \"$0\" != \"bin/check_sort.sh\" ]\nthen\n    echo \"bin/check_sort.sh: must be executed from its parent directory\"\n    exit 1\nfi\nif [ \"$#\" == 0 ]\nthen\n    all='false'\nelif [ \"$#\" == 1 ] && [ \"$1\" == 'all' ]\nthen\n    all='true'\nelse\n    echo 'usage: bin/check_sort [all]'\n    echo 'see usage message forbin/sort.sh'\n    exit 1\nfi\n#\n# grep, sed\nsource bin/grep_and_sed.sh\n# ----------------------------------------------------------------------------\n# file_list\nif [ \"$all\" == 'true' ]\nthen\n    file_list=$(git grep -l 'BEGIN_SORT_THIS_LINE_PLUS_')\nelse\n    file_list=$(\\\n        git status --porcelain | \\\n            $sed -e '/^D/d' -e 's|^...||' -e 's|^.*-> *||' \\\n    )\nfi\n#\n# ok\nok='yes'\nfor file_name in $file_list\ndo\n    check='yes'\n    if [ \"$file_name\" == 'bin/sort.sh' ]\n    then\n        check='no'\n    fi\n    if [ \"$file_name\" == 'bin/check_sort.sh' ]\n    then\n        check='no'\n    fi\n    if [ -d \"$file_name\" ]\n    then\n        check='no'\n    else\n        if ! $grep BEGIN_SORT_THIS_LINE $file_name > /dev/null\n        then\n            check='no'\n        fi\n    fi\n    if [ \"$check\" == 'yes' ]\n    then\n        if ! bin/sort.sh $file_name >& temp.$$\n        then\n            cat temp.$$\n            echo 'check_sort.sh: Error'\n            rm temp.$$\n            exit 1\n        fi\n        last_line=$(tail -1 temp.$$)\n        if [ \"$last_line\" == 'sort.sh: Done' ]\n        then\n            cat temp.$$\n            ok='no'\n        fi\n    fi\ndone\n#\nif [ -e \"temp.$$\" ]\nthen\n    rm temp.$$\nfi\nif [ \"$ok\" == 'no' ]\nthen\n    echo 'check_sort.sh: Some files have been sorted (run again to get OK).'\n    exit 1\nfi\necho 'check_sort.sh: OK'\nexit 0\n"
  },
  {
    "path": "bin/check_tab.sh",
    "content": "#! /usr/bin/env bash\nset -e -u\n# !! EDITS TO THIS FILE ARE LOST DURING UPDATES BY xrst.git/bin/dev_tools.sh !!\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2020-25 Bradley M. Bell\n# -----------------------------------------------------------------------------\n# bin/check_tabls.h\n# Checks for tabs in the source and returns an error if it finds any.\n# Files that are not checked can be specified in bin/dev_settings.sh.\n# -----------------------------------------------------------------------------\nif [ \"$0\" != \"bin/check_tab.sh\" ]\nthen\n    echo \"bin/check_tab.sh: must be executed from its parent directory\"\n    exit 1\nfi\nif [ \"$#\" == 0 ]\nthen\n    all='false'\nelif [ \"$#\" == 1 ] && [ \"$1\" == 'all' ]\nthen\n    all='true'\nelse\n    echo 'usage: bin/check_tab [all]'\n    exit 1\nfi\n#\n# sed\nsource bin/grep_and_sed.sh\n#\n# invisible_and_tab_ok\nsource bin/dev_settings.sh\n# ----------------------------------------------------------------------------\n#\n# sed.$$\ncat << EOF > sed.$$\ns|.*-> *||\nEOF\nfor name in $invisible_and_tab_ok\ndo\n    if [ -f $name ]\n    then\n        echo \"^$name\\$\" | $sed -e 's|/|[/]|g' -e 's|.*|/&/d|' >> sed.$$\n    elif [ -d $name ]\n    then\n        echo \"^$name/\" | $sed -e 's|/|[/]|g' -e 's|.*|/&/d|' >> sed.$$\n    else\n        echo \"$name in no_copyright_list is not a file or directory\"\n        exit 1\n    fi\ndone\n#\n# file_list\nif [ \"$all\" == 'true' ]\nthen\n    file_list=$(git ls-files | $sed -f sed.$$)\nelse\n    file_list=$(git status --porcelain | \\\n        $sed -e '/^D/d' -e 's|^...||' | $sed -f sed.$$)\nfi\n#\n# ok\nok='yes'\nfor file in $file_list\ndo\n    if $grep -P '\\t' $file > /dev/null\n    then\n        echo \"$file has a tab\"\n        ok='no'\n    fi\ndone\nif [ \"$ok\" != 'yes' ]\nthen\n    echo 'check_tab: Error'\n    rm sed.$$\n    exit 1\nfi\n# -----------------------------------------------------------------------------\nrm sed.$$\necho 'check_tab.sh: OK'\nexit 0\n"
  },
  {
    "path": "bin/check_tempfile.sh",
    "content": "#! /bin/bash -e\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\nif [ ! -e \"bin/check_tempfile.sh\" ]\nthen\n    echo \"bin/check_tempfile.sh: must be executed from its parent directory\"\n    exit 1\nfi\n# -----------------------------------------------------------------------------\nlist=`ls | sed -n \\\n    -e '/^new.[0-9]*$/d' \\\n    -e '/^temp.[0-9]*$/d' \\\n    -e '/\\/temp.[0-9]*$/d' \\\n    -e '/\\.[0-9]*$/p'`\nif [ \"$list\" != '' ]\nthen\n    echo 'Use following command to remove temporary files:'\n    cmd='rm '\n    for file in $list\n    do\n        cmd+=\" $file\"\n    done\n    echo \"    $cmd\"\n    echo 'check_tempfile.sh: Error'\n    exit 1\nfi\necho 'check_tempfile.sh: OK'\nexit 0\n"
  },
  {
    "path": "bin/check_trace.sh",
    "content": "#! /usr/bin/env bash\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2024 Bradley M. Bell\nset -e -u\n# ----------------------------------------------------------------------------\nif [ $0 != \"bin/check_trace.sh\" ]\nthen\n    echo \"bin/check_trace.sh: must be executed from its parent directory\"\n    exit 1\nfi\nchange='no'\nfile_list=$(git ls-files include/cppad/local/sweep/*.hpp)\nfor file in $file_list\ndo\n    sed -e 's|\\(# *define *[A-Z0-9_]*\\)_TRACE 1|\\1_TRACE 0|' $file \\\n        > check_trace.$$\n    if diff $file check_trace.$$ > /dev/null\n    then\n        rm check_trace.$$\n    else\n        change='yes'\n        echo \"$file changed as follows:\"\n        set +e\n        diff $file check_trace.$$\n        set -e\n        mv check_trace.$$ $file\n    fi\ndone\nif [ \"$change\" == 'yes' ]\nthen\n    echo \"$0: Error\"\n    exit 1\nfi\n# ----------------------------------------------------------------------------\necho \"$0: OK\"\nexit 0\n"
  },
  {
    "path": "bin/check_user_def.py",
    "content": "#! /usr/bin/env python3\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\nimport re\nimport sys\nimport subprocess\n#\n# p_symbol_heading\np_symbol_heading = re.compile( r'\\n(CPPAD[A-Z_]*)\\n([^\\n]*)\\n' )\n#\n# p_symbol_undef\np_symbol_undef = re.compile( r'\\n# undef (CPPAD[A-Z_]*)\\n' )\n#\ndef main() :\n    #\n    if sys.argv[0] != 'bin/check_user_def.py' :\n        sys.exit(\n            'bin/check_user_def.py must execute from its parent directory'\n        )\n    #\n    # dev_doc_symbol_list\n    dev_doc_symbol_list=[\n        'CPPAD_VEC_AD_COMP_ASSIGN',\n        'CPPAD_FOR_HES_TRACE',\n    ]\n    #\n    # exclude_list\n    exclude_list = [\n        'include/cppad/configure.hpp.in',\n        'configure',\n]\n\n    #\n    # file_list\n    command = [ 'git', 'ls-files' ]\n    result = subprocess.run(\n            command                   ,\n            stdout = subprocess.PIPE  ,\n            stderr = subprocess.PIPE  ,\n            text   = True             ,\n    )\n    if result.returncode != 0 :\n        msg  = 'Error: ' + ' '.join(command) + '\\n'\n        msg += result.stderr\n        sys.exit(msg)\n    file_list = result.stdout.strip().split('\\n')\n    #\n    # file_list\n    file_tmp = list()\n    for file in file_list :\n        exclude = file in exclude_list\n        if not exclude :\n            file_tmp.append(file)\n    file_list = file_tmp\n    #\n    # preprocessor_data\n    file_obj          = open('xrst/preprocessor.xrst', 'r')\n    preprocessor_data = file_obj.read()\n    file_obj.close()\n    #\n    # undef_list\n    undef_list = list()\n    #\n    # m_symbol_undef\n    m_symbol_undef = p_symbol_undef.search( preprocessor_data )\n    while m_symbol_undef != None :\n        undef_list.append( m_symbol_undef.group(1) )\n        #\n        # m_symbol_undef\n        start           = m_symbol_undef.end() - 1\n        m_symbol_undef = p_symbol_undef.search( preprocessor_data , start)\n    #\n    # file\n    for file in file_tmp :\n        #\n        # file_data\n        file_obj  = open(file, 'r')\n        try :\n            file_data = file_obj.read()\n        except :\n            file_data = ''\n        file_obj.close()\n        #\n        # m_symbol_heading\n        m_symbol_heading = p_symbol_heading.search( file_data )\n        while m_symbol_heading != None :\n            #\n            # error\n            symbol    = m_symbol_heading.group(1)\n            underline = m_symbol_heading.group(2)\n            error     = False\n            if len(symbol) == len(underline) :\n                if underline == len(symbol) * underline[0] :\n                    if symbol not in undef_list :\n                            if symbol not in dev_doc_symbol_list :\n                                error = True\n            if error :\n                msg  = f'{file}:\\n'\n                msg += f'Documentation for {symbol} appears in this file '\n                msg += 'but it is supposed to be in the user API.'\n                sys.exit(msg)\n            #\n            # m_symbol_heading\n            start            = m_symbol_heading.end()\n            m_symbol_heading = p_symbol_heading.search( file_data , start)\n#\nmain()\nprint('check_user_def.py: OK')\n"
  },
  {
    "path": "bin/check_version.sh",
    "content": "#! /usr/bin/env bash\nset -e -u\n# !! EDITS TO THIS FILE ARE LOST DURING UPDATES BY xrst.git/bin/dev_tools.sh !!\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2020-26 Bradley M. Bell\n# -----------------------------------------------------------------------------\n# bin/check_verison.sh\n# Checks that the version number in the version_file_list are correct;\n# see bin/dev_settings.sh for more discussion.\n# -----------------------------------------------------------------------------\n#\n# echo_eval\necho_eval() {\n    echo $*\n    eval $*\n}\n#\n# sed\nsource bin/grep_and_sed.sh\n#\n# package_name, version_file_list\nsource bin/dev_settings.sh\n#\nif [ \"$0\" != \"bin/check_version.sh\" ]\nthen\n    echo \"bin/check_version.sh: must be executed from its parent directory\"\n    exit 1\nfi\nif [ \"$#\" != 0 ]\nthen\n    echo 'check_version does not expect any arguments'\n    exit 1\nfi\nif [ ! -e './.git' ]\nthen\n    echo 'bin/check_version.sh: cannot find ./.git'\n    exit 1\nfi\n# -----------------------------------------------------------------------------\n#\n# branch\nbranch=$(git branch --show-current)\n#\n# first_version_file\nfirst_version_file=$(echo $version_file_list | $sed -e 's|^ *||' -e 's| .*||')\n#\n# version\ncat << EOF > temp.sed\n/[\"'][0-9]{8}[\"']/b one\n/[\"'][0-9]{8}[.][0-9]{1,2}[\"']/b one\n/[\"'][0-9]{4}[.][0-9]{1,2}[.][0-9]{1,2}[\"']/b one\nb end\n#\n: one\ns|.*[\"']([0-9]{8})[\"'].*|\\\\1|\ns|.*[\"']([0-9]{8}[.][0-9]{1,2})[\"'].*|\\\\1|\ns|.*[\"']([0-9]{4}[.][0-9]{1,2}[.][0-9]{1,2})[\"'].*|\\\\1|\np\n#\n: end\nEOF\nversion=$($sed -n -r -f temp.sed $first_version_file | head -1)\n#\n# version_type\nif [[ \"$version\" =~ ^[0-9]{8}$ ]]\nthen\n    version_type=1\nelif [[ \"$version\" =~ ^[0-9]{8}[.][0-9]{1,2}$ ]]\nthen\n    version_type=2\nelif [[ \"$version\" =~ ^[0-9]{4}[.][0-9]{1,2}[.][0-9]{1,2}$ ]]\nthen\n    version_type=3\nelse\n    echo \"check_version.sh: can't find version number in $first_version_file\"\n    exit 1\nfi\nif [[ \"$branch\" =~ ^stable/.* ]]\nthen\n    if [ \"$version_type\" == 1 ]\n    then\n        echo \"check_version.sh: version in $first_version_file\"\n        echo \"is not for a release but this is the $branch branch\"\n        exit 1\n    elif [ \"$version_type\" == 3 ]\n    then\n        if [[ \"$version\" =~  ^[0-9]{4}[.][^0].*$ ]]\n        then\n            echo \"check_version.sh: version in $first_version_file\"\n            echo \"is not for a release but this is the $branch branch\"\n            exit 1\n        fi\n    fi\nfi\n#\n# version\nif [ \"$branch\" == 'master' ] || [ \"$branch\" == 'main' ]\nthen\n    if [ \"$version_type\" == 1 ]\n    then\n        version=$(date +%Y%m%d)\n    elif [ \"$version_type\" == 2 ]\n    then\n        echo \"check_version.sh: version in $first_version_file\"\n        echo \"is for a release but this is the $branch branch\"\n        exit 1\n    else\n        if [[ \"$version\" =~  ^[0-9]{4}[.]0[.][0-9]{1,2}$ ]]\n        then\n            echo \"check_version.sh: version in $first_version_file\"\n            echo \"is for a release but this is the $branch branch\"\n            exit 1\n        fi\n        version=$(date +%Y.%-m.%-d)\n    fi\nfi\n#\n# temp.sed\ncat << EOF > temp.sed\ns|([\"'])[0-9]{8}([\"'])|\\\\1$version\\\\2|\ns|([\"'])[0-9]{8}[.][0-9]{1,2}([\"'])|\\\\1$version\\\\2|\ns|([\"'])[0-9]{4}[.][0-9]{1,2}[.][0-9]{1,2}([\"'])|\\\\1$version\\\\2|\n#\ns|$package_name-[0-9]{8}\\$|$package_name-$version|\ns|$package_name-[0-9]{8}([^.])|$package_name-$version\\\\1|\ns|$package_name-[0-9]{8}[.][0-9]{1,2}|$package_name-$version|\ns|$package_name-[0-9]{4}[.][0-9]{1,2}[.][0-9]{1,2}|$package_name-$version|\nEOF\n#\n# check_version\ncheck_version() {\n    $sed -r \"$1\" -f temp.sed > temp.out\n    if ! diff \"$1\" temp.out > /dev/null\n    then\n        version_ok='no'\n        echo \"check_version.sh: changes to $1\"\n        set +e\n        diff \"$1\" temp.out\n        set -e\n        #\n        if [ -x \"$1\" ]\n        then\n            mv temp.out \"$1\"\n            chmod +x \"$1\"\n        else\n            mv temp.out \"$1\"\n        fi\n    fi\n}\n#\n# version_ok\nversion_ok='yes'\n#\n# check_version\nfor file in $version_file_list\ndo\n    check_version $file\ndone\n#\n# ----------------------------------------------------------------------------\nif [ \"$version_ok\" == 'no' ]\nthen\n    echo 'check_version.sh: The version numbers were fixed (see above).'\n    echo 'Re-execute bin/check_version.sh ?'\n    exit 1\nfi\necho 'check_version.sh OK'\nexit 0\n"
  },
  {
    "path": "bin/colpack.sh",
    "content": "#! /bin/bash -e\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\nif [ \"$1\" != 'forward' ] && [ \"$1\" != 'reverse' ]\nthen\n    echo 'usage: ./colpack.sh option'\n    echo 'where option is \"forward\" or \"reverse\"'\n    exit 1\nfi\nif [ \"$1\" == 'forward' ]\nthen\n    color_variant=\"COLUMN_PARTIAL_DISTANCE_TWO\"\nelse\n    color_variant=\"ROW_PARTIAL_DISTANCE_TWO\"\nfi\n# ----------------------------------------------------------------------------\n# bash function that echos and executes a command\necho_eval() {\n    echo $*\n    eval $*\n}\n# -----------------------------------------------\nif [ ! -e 'build/colpack' ]\nthen\n    echo_eval mkdir -p build/colpack\nfi\necho 'create: build/colpack/colpack.cpp'\ncat<< EOF > build/colpack/colpack.cpp\n// Example using BipartiteGraphPartialColoringInterface\n// to generate the seed matrix for Jacobian\n\n#include \"ColPackHeaders.h\"\n\nint main()\n{   size_t i, j, k;\n\n    using std::cout;\n    using std::endl;\n\n    //* 32x9 matrix\n    size_t       i_RowCount          = 32;\n    size_t       i_ColumnCount       = 9;\n    size_t       i_MaxNonZerosInRows = 3;\n\n    // JP[32][9]\n    std::vector<unsigned int *> JP(i_RowCount);\n    unsigned int n_data    = i_RowCount * (i_MaxNonZerosInRows + 1);\n    std::vector<unsigned int> JP_memory(n_data);\n    for(i = 0; i < i_RowCount; i++)\n        JP[i] = JP_memory.data() + i * (i_MaxNonZerosInRows + 1);\n    //\n    JP[0][0] = 0;\n    JP[1][0] = 1;   JP[1][1] = 0;\n    JP[2][0] = 1;   JP[2][1] = 1;\n    JP[3][0] = 1;   JP[3][1] = 2;\n    JP[4][0] = 1;   JP[4][1] = 0;\n    JP[5][0] = 3;   JP[5][1] = 0;   JP[5][2] = 1;   JP[5][3] = 3;\n    JP[6][0] = 3;   JP[6][1] = 1;   JP[6][2] = 2;   JP[6][3] = 4;\n    JP[7][0] = 2;   JP[7][1] = 2;   JP[7][2] = 5;\n    JP[8][0] = 1;   JP[8][1] = 3;\n    JP[9][0] = 3;   JP[9][1] = 3;   JP[9][2] = 4;   JP[9][3] = 6;\n    JP[10][0] = 3;  JP[10][1] = 4;  JP[10][2] = 5;  JP[10][3] = 7;\n    JP[11][0] = 2;  JP[11][1] = 5;  JP[11][2] = 8;\n    JP[12][0] = 1;  JP[12][1] = 6;\n    JP[13][0] = 2;  JP[13][1] = 6;  JP[13][2] = 7;\n    JP[14][0] = 2;  JP[14][1] = 7;  JP[14][2] = 8;\n    JP[15][0] = 1;  JP[15][1] = 8;\n    JP[16][0] = 1;  JP[16][1] = 0;\n    JP[17][0] = 2;  JP[17][1] = 0;  JP[17][2] = 1;\n    JP[18][0] = 2;  JP[18][1] = 1;  JP[18][2] = 2;\n    JP[19][0] = 1;  JP[19][1] = 2;\n    JP[20][0] = 2;  JP[20][1] = 0;  JP[20][2] = 3;\n    JP[21][0] = 3;  JP[21][1] = 1;  JP[21][2] = 3;  JP[21][3] = 4;\n    JP[22][0] = 3;  JP[22][1] = 2;  JP[22][2] = 4;  JP[22][3] = 5;\n    JP[23][0] = 1;  JP[23][1] = 5;\n    JP[24][0] = 2;  JP[24][1] = 3;  JP[24][2] = 6;\n    JP[25][0] = 3;  JP[25][1] = 4;  JP[25][2] = 6;  JP[25][3] = 7;\n    JP[26][0] = 3;  JP[26][1] = 5;  JP[26][2] = 7;  JP[26][3] = 8;\n    JP[27][0] = 1;  JP[27][1] = 8;\n    JP[28][0] = 1;  JP[28][1] = 6;\n    JP[29][0] = 1;  JP[29][1] = 7;\n    JP[30][0] = 1;  JP[30][1] = 8;\n    JP[31][0] = 0;\n    cout << endl << \"Sparsity pattern of Jacobian:\" << endl;\n    cout << \"    \";\n    for(k = 0; k < 9; k++)\n        cout << setw(3) << k;\n    cout << endl;\n    for(i = 0; i < i_RowCount; i++)\n    {   cout << setw(3) << i << \":\";\n        k = 0;\n        for (j = 1; j <= (int) JP[i][0]; j++)\n        {   while(k < JP[i][j])\n            {   cout << setw(3) << 0;\n                k++;\n            }\n            cout << setw(3) << 1;\n            k++;\n        }\n        while(k < 9)\n        {   cout << setw(3) << 0;\n            k++;\n        }\n        cout << endl;\n    }\n\n\n    // Step 1: Read the sparsity pattern of the given Jacobian matrix\n    // (adolc format) and create the corresponding bipartite graph\n    ColPack::BipartiteGraphPartialColoringInterface g(\n            SRC_MEM_ADOLC, JP.data(), i_RowCount, i_ColumnCount\n    );\n    g.PrintBipartiteGraph();\n\n    // Step 2: Do Partial-Distance-Two-Coloring\n    // of the bipartite graph with the specified ordering\n    g.PartialDistanceTwoColoring(\n        \"SMALLEST_LAST\", \"$color_variant\"\n    );\n    g.PrintColumnPartialColors();\n    g.PrintColumnPartialColoringMetrics();\n\n    // Step 3: From the coloring information, create and return seed matrix\n    int ip1_SeedRowCount;\n    int ip1_SeedColumnCount;\n    double** RSeed =\n        g.GetSeedMatrix(&ip1_SeedRowCount, &ip1_SeedColumnCount);\n    int rows = ip1_SeedRowCount;\n    int cols = ip1_SeedColumnCount;\n    cout << \"Seed matrix: (\" << rows << \",\" << cols << \")\" << endl;\n    cout << \"    \";\n    for(j = 0; j < cols; j++)\n        cout << setw(3) << j;\n    cout << endl;\n    for(i = 0; i < rows; i++)\n    {   cout << setw(3) << i << \":\";\n        for(j = 0; j < cols; j++)\n            cout << setw(3) << int(RSeed[i][j]);\n        cout << endl;\n    }\n\n    return 0;\n}\nEOF\n# ----------------------------------------------------------------------------\necho_eval cd build/colpack\necho_eval g++ colpack.cpp \\\n    -I$HOME/prefix/colpack/include/ColPack \\\n    -L$HOME/prefix/colpack/lib64 \\\n    -l ColPack \\\n    -o colpack\n#\necho_eval valgrind --leak-check=yes ./colpack\n# ----------------------------------------------------------------------------\necho \"$0: OK\"\nexit 0\n"
  },
  {
    "path": "bin/deprecate_xam.sh",
    "content": "#! /bin/bash -e\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\nif [  \"$0\" != 'bin/deprecate_xam.sh' ]\nthen\n    echo 'bin/deprecate_xam.sh: must be executed from its parent directory'\n    exit 1\nfi\nif [ \"$1\" == '' ]\nthen\n    echo 'bin/deprecate_xam.sh file'\n    echo 'where file is an example file that is to be deprecated'\n    exit 1\nfi\nold_file=\"$1\"\next=`echo $old_file | sed -e 's|.*\\.||'`\nif [ $ext != 'cpp' ]\nthen\n    echo 'bin/depreate_xam.sh: file name does not end in .cpp'\n    exit 1\nfi\ndir=`echo $old_file | sed -e 's|/.*||'`\nif [ $dir != 'example' ]\nthen\n    echo 'bin/depreate_xam.sh: file name does not start with example/'\n    exit 1\nfi\n# -----------------------------------------------------------------------------\n# move file\nroot_name=`echo $old_file | sed -e 's|.*/||' -e 's|\\.cpp$||'`\nnew_dir=\"test_more/deprecated\"\nnew_file=\"$new_dir/$root_name.cpp\"\necho \"$omh_name\"\nif [ -e $new_file ]\nthen\n    git reset -- $new_file $old_file\n    rm $new_file\n    git checkout $old_file\nfi\necho \"git mv $old_file $new_file\"\ngit mv $old_file $new_file\n# -----------------------------------------------------------------------------\n# change old directory\nold_dir=`echo $old_file | sed -e 's|/[^/]*$||'`\nold_program=`echo $old_dir | sed -e 's|.*/||'`\ngit checkout $old_dir/CMakeLists.txt\nsed -i $old_dir/CMakeLists.txt -e \"/$root_name.cpp/d\"\ngit checkout $old_dir/makefile.am\nsed -i $old_dir/makefile.am -e \"/$root_name.cpp/d\"\ngit checkout $old_dir/$old_program.cpp\nsed -i $old_dir/$old_program.cpp -e \"/$root_name/d\"\n# -----------------------------------------------------------------------------\n# change new directory\ngit checkout $new_dir/CMakeLists.txt\nsed -i $new_dir/CMakeLists.txt \\\n    -e \"s|deprecated.cpp|&\\\\n    $root_name.cpp|\"\ngit checkout $new_dir/makefile.am\nsed -i $new_dir/makefile.am \\\n    -e \"s|deprecated.cpp.*|&\\\\n\\\\t$root_name.cpp \\\\\\\\|\"\ngit checkout $new_dir/deprecated.cpp\nsed -i $new_dir/deprecated.cpp \\\n    -e \"s|bool old_mat_mul.*|&\\\\nextern bool $root_name(void);|\" \\\n    -e \"s|Run( old_mat_mul.*|&\\\\n    Run( $root_name, \\\"$root_name\\\" );|\"\n# -----------------------------------------------------------------------------\n# file omhelp links\nomh_name=`grep '$begin' $new_file | sed -e 's|$begin ||' -e 's|\\$\\$.*||'`\ngit checkout omh/example_list.omh\nsed -i omh/example_list.omh -e \"/$omh_name/d\"\n# -----------------------------------------------------------------------------\necho 'bin/deprecate_xam.sh: OK'\nexit 0\n"
  },
  {
    "path": "bin/dev_settings.sh",
    "content": "# ---------------------------------------------------------------------------\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-26 Bradley M. Bell\n# SPDX-FileContributor: 2025 Perry de Valpine\n# ---------------------------------------------------------------------------\n# source bin/dev_settings.sh\n# Sets the value of the the development tool variables for this package.\n#\n# Unless this is xrst.git/bin/dev_settings.sh,\n# only edit the value for each of the variables, any other changes will\n# be lost the next time xrst.git/bin/dev_tools.sh updates this file.\n# ---------------------------------------------------------------------------\n#\n# Directories\n# If an file name below is a directory it specifies all the\n# files in the directory.\n#\n# spdx_license_id\n# Each file, except those specified by no_copyright_list, should have a line\n# that ends with the following text:\nspdx_license_id='EPL-2.0 OR GPL-2.0-or-later'\n#\n# package_name\npackage_name='cppad'\n#\n# index_page_name\n# is the xrst index page_name for this projects documentation.\nindex_page_name='user_guide'\n#\n# version_file_list\n# The possible patterns for a latest version number are:\n#     yyyymmdd or yyyy.month.day\n# where yyyymmdd is an eight decimal digit representation of the date.\n# yyyy is the year (as four decimal digits yyy), month is a number\n# between 1 and 12, and the day is a number between 1 and 31\n# The possible patterns for a release version number are:\n#     yyyy0000.release or yyyy.0.release\n# where release is a number between 0 and 99.\n#\n# The patterns above without release are used for the master and main branches\n# and corresponds to the current year, month and day.\n# The patterns above with release are used for stable/* branches.\n#\n# The first version file of the list below must have one copy of its\n# version surrounded by single or double quotes. This determines the version\n# when the branch is not master or main. All occurrences of the version, in the\n# files listed below, with the following forms are updated by check_version.sh:\n#     $package_name-$version  or '$version' or \"$version\"\n#\n# We use tag for the version corresponding to the current stable release.\n# This is (is not) the same as the current version on a stable branch\n# (on the master or main branch). All occurrences of the tag, in the files\n# listed below, with the following forms are updated by new_release.sh:\n#     archive/$tag.tar.gz\n# In addition, all occurrences of stable-yyyy and release-yyyy are updated.\nversion_file_list='\n    CMakeLists.txt\n    user_guide.xrst\n'\n# All the occurrences of the version in the files above are checked to see\n# that they agree.\n#\n# contributor_list\n# This maps the system user name $USER to the contributor's full name.\n# A full name can have multiple user names, but each user name can have\n# only one full name. The colon separates the user name from the full name.\n# The entries are separate by white space, so the under bar character is used\n# for spaces in the full name.\ncontributor_list='\n    bradbell:Bradley_M._Bell\n'\n#\n# no_copyright_list\n# These files and directories do not have the spdx license id in them.\n# If an entry below is a directory it specifies all the files in the directory.\n# BEGIN_SORT_THIS_LINE_PLUS_2\nno_copyright_list='\n    .circleci/config.yml\n    .github/workflows\n    .gitignore\n    .readthedocs.yaml\n    .travis.yml\n    COPYING\n    appveyor.yml\n    authors\n    batch_edit.sed\n    bin/build.bat\n    cmake/cppad_uninstall.cmake\n    coin.png\n    epl-2.0.txt\n    typos.toml\n    uw_copy_040507.html\n    xrst.toml\n'\n# END_SORT_THIS_LINE_MINUS_2\n#\n# invisible_and_tab_ok\n# These files are not checked for invisible white space or tabs.\n# If an entry below is a directory it specifies all the files in the directory.\ninvisible_and_tab_ok='\n    batch_edit.sed\n    coin.png\n    uw_copy_040507.html\n'\n#\n# check_git_commit\n# Files that have automatic changes that should not be committed every time.\n# Including them in this list gives the user the option to abort their changes.\ncheck_git_commit='\n'\n"
  },
  {
    "path": "bin/dos_build.bat",
    "content": "echo off\nrem SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\nrem SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\nrem SPDX-FileContributor: 2024 Bradley M. Bell\nrem --------------------------------------------------------------------------\ngoto end_of_comment_block\n{xrst_begin dos_build.bat}\n{xrst_spell\n    cmd\n}\n\nCompile and Test CppAD using Dos\n################################\n\nSyntax\n******\n{xrst_code bat}\ncmd /c bin\\dos_build.bat\n{xrst_code}\n\nEigen\n*****\nThis example includes the eigen optional package.\nOther optional packages could be included in a similar fashion.\n\nSource\n******\n{xrst_literal\n    rem BEGIN SOURCE\n    rem END SOURCE\n}\n\n{xrst_end dos_build.bat}\n:end_of_comment_block\nrem ---------------------------------------------------------------------------\nrem BEGIN SOURCE\nrem .git\nif not exist .git (\n    echo Expected .git to be a subdirectory of working directory\n    exit 1\n)\nrem\nrem CONDA_PREFIX\nif defined CONDA_PREFIX (\n    echo CONDA_PREFIX = %CONDA_PREFIX%\n) else (\n    echo CONDA_PREFIX is not defined\n    exit\n)\nrem PKG_CONFIG_PATH\nset PKG_CONFIG_PATH=%CONDA_PREFIX%\\Library\\share\\pkgconfig\necho PKG_CONFIG_PATH=%PKG_CONFIG_PATH%\nif exist %PKG_CONFIG_PATH%\\eigen3.pc (\n    echo Found eigen3 in PKG_CONFIG_PATH\n) else (\n    echo Did not find eigen3 in PKG_CONFIG_PATH: suggest\n    echo conda install eigen\n    exit\n)\nrem INCLUDE_DIR\nset INCLUDE_DIR=%CONDA_PREFIX%\\Library\\include\necho INCLUDE_DIR=%INCLUDE_DIR%\nif exist %INCLUDE_DIR%\\Eigen\\Core (\n    echo Found Eigen\\Core in INCLUDE_DIR\n) else (\n    echo Did not find Eigen\\Core in INCLUDE_DIR: suggest\n    echo mklink /d %INCLUDE_DIR%\\Eigen %INCLUDE_DIR%\\eigen3\\Eigen\n    exit\n)\nrem MSVS_DIR\nset MSVS_DIR=C:\\Program Files\\Microsoft Visual Studio\necho MSVS_DIR=%MSVS_DIR%\nif exist \"%MSVS_DIR%\" (\n    echo Found MSVS_DIR\n) else (\n    echo Did not find MSVS_DIR\n    echo Install Visual Studio ?\n    exit 1\n)\nrem\nrem temp.out\nset SAVE_DIR=%cd%\ncd  %MSVS_DIR%\ndir /s vcvarsall.bat > %SAVE_DIR%/temp.out\ncd %SAVE_DIR%\nren\nrem temp.py\necho import re                            > temp.py\necho f_obj   = open('temp.out', 'r')      >> temp.py\necho data    = f_obj.read()               >> temp.py\necho pattern = '\\n *Directory *of *(.*)'  >> temp.py\necho m_obj   = re.search(pattern, data)   >> temp.py\necho if m_obj == None :                   >> temp.py\necho    print( 'not_found' )              >> temp.py\necho else :                               >> temp.py\necho    print( m_obj.group(1) )           >> temp.py\nrem rem\nrem VCVARSALL_DIR\npython temp.py > temp\nset /p VCVARSALL_DIR=<temp\necho VCVARSALL_DIR = %VCVARSALL_DIR%\nif exist \"%VCVARSALL_DIR%\\vcvarsall.bat\" (\n    echo Found vcvarsall.bat in VCVARSALL_DIR\n) else (\n    echo Could not find vcvarsall.bat below MSVS_DIR\n    exit\n)\nrem vcvarsall.bat\ncall \"%VCVARSALL_DIR%\\vcvarsall.bat\" amd64\nrem\nrem build\nif not exist build ( mkdir build )\ncd build\nif exist CMakeCache.txt ( rm CMakeCache.txt )\nrem\nrem cmakde\ncmake ^\n    -B . ^\n    -S .. ^\n    -G \"NMake Makefiles\" ^\n    -D CMAKE_CXX_COMPILER=cl ^\n    -D CMAKE_C_COMPILER=cl ^\n    -D CMAKE_BUILD_TYPE=release ^\n    -D cppad_static_lib=true ^\n    -D cppad_cxx_flags=\"/MP /EHs /EHc /std:c++17 /Zc:__cplusplus\"\nrem\nrem check\ncmake --build . --target check\nrem\necho bin/dos_build.bat: OK\nrem END SOURCE\n"
  },
  {
    "path": "bin/doxyfile.sh",
    "content": "#! /bin/bash -e\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\nif [ ! -e \"bin/doxyfile.sh\" ]\nthen\n    echo \"bin/doxyfile.sh: must be executed from its parent directory\"\n    exit 1\nfi\n# -----------------------------------------------------------------------------\nif [ \"$3\" == \"\" ]\nthen\n    echo \"usage: bin/doxyfile.sh version error_file output_directory\"\n    echo \"creates the doxygen configuration file ./doxyfile\"\n    exit 1\nfi\nversion=\"$1\"\nerror_file=\"$2\"\noutput_directory=\"$3\"\n# -----------------------------------------------------------------------------\n# convert multi-line assignments to single line assignments.\necho \"doxygen -g doxyfile > /dev/null\"\ndoxygen -g doxyfile > /dev/null\ncat << EOF > doxyfile.$$\n/^[A-Z_]* *=.*\\\\\\\\$/! b end\n: loop\nN\n/\\\\\\\\$/b loop\ns|\\\\\\\\\\\\n| |g\ns|  *| |g\n#\n:end\nEOF\nsed -i doxyfile -f doxyfile.$$\n# -----------------------------------------------------------------------------\ninclude_directory_list=`find include/cppad -type d | tr '\\n' ' ' `\n# -----------------------------------------------------------------------------\n# PREDEFINED:see http://www.stack.nl/~dimitri/doxygen/manual/preprocessing.html\n# 2DO: change EXTRACT_ALL to NO so get warnings for undocumented functions.\necho \"create doxyfile.$$\"\ncat << EOF > doxyfile.$$\nALWAYS_DETAILED_SEC     = YES\nBUILTIN_STL_SUPPORT     = YES\nENABLE_PREPROCESSING    = YES\nMACRO_EXPANSION         = YES\nEXTRACT_ALL             = YES\nEXTRACT_LOCAL_CLASSES   = YES\nEXTRACT_PRIVATE         = YES\nEXTRACT_STATIC          = YES\nEXTRACT_ANON_NSPACES    = YES\nFILE_PATTERNS           =  *.hpp  *.cpp\nFULL_PATH_NAMES         = NO\nGENERATE_HTML           = YES\nGENERATE_LATEX          = NO\nGENERATE_TREEVIEW       = YES\nINHERIT_DOCS            = NO\nINLINE_INHERITED_MEMB   = YES\nINPUT                   = $include_directory_list\nLATEX_BATCHMODE         = YES\nMACRO_EXPANSION         = YES\nMULTILINE_CPP_IS_BRIEF  = YES\nOUTPUT_DIRECTORY        = $output_directory\nPREDEFINED              = \"__cplusplus=201103\" \"CPPAD_USE_CPLUSPLUS_2011=1\"\nPROJECT_NAME            = \"CppAD: A C++ Algorithmic Differentiation Package\"\nPROJECT_NUMBER          = $version\nQT_AUTOBRIEF            = YES\nREFERENCED_BY_RELATION  = YES\nREFERENCES_LINK_SOURCE  = NO\nSEPARATE_MEMBER_PAGES   = YES\nSHOW_DIRECTORIES        = YES\nSHOW_INCLUDE_FILES      = NO\nSORT_GROUP_NAMES        = YES\nSORT_MEMBER_DOCS        = YES\nSORT_BRIEF_DOCS         = YES\nSOURCE_BROWSER          = YES\nSTRIP_CODE_COMMENTS     = NO\nSUBGROUPING             = NO\nTAB_SIZE                = 5\nVERBATIM_HEADERS        = NO\nWARN_LOGFILE            = $error_file\nWARN_NO_PARAMDOC        = YES\nEOF\nsed \\\n    -e 's/^/s|^\\\\(/' \\\n    -e 's/ *=/ *=\\\\).*|\\\\1/' \\\n    -e 's/$/|/' \\\n    -i doxyfile.$$\n#\n#\necho \"sed -f doxyfile.$$ -i doxyfile\"\nsed -f doxyfile.$$ -i doxyfile\n#\necho \"rm doxyfile.$$\"\nrm doxyfile.$$\n# ----------------------------------------------------------------------------\necho \"$0: OK\"\nexit 0\n"
  },
  {
    "path": "bin/get_adolc.sh",
    "content": "#! /bin/bash -e\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# {xrst_begin get_adolc.sh}\n# {xrst_comment_ch #}\n#\n# Download and Install Adolc in Build Directory\n# #############################################\n#\n# Syntax\n# ******\n# ``bin/get_adolc.sh``\n#\n# Purpose\n# *******\n# If you are using Unix, this command will download and install\n# :ref:`Adolc<adolc@Adolc Home Page>`\n# in the CppAD ``build`` directory.\n#\n# Requirements\n# ************\n# You must first use :ref:`get_colpack.sh-name` to download and install\n# the ColPack coloring algorithms (used for sparse matrix derivatives).\n#\n# Distribution Directory\n# **********************\n# This command must be executed in the\n# :ref:`download@Distribution Directory` .\n#\n# Source Directory\n# ****************\n# The Adolc source code is downloaded into the sub-directory\n# ``external/adolc.git`` below the distribution directory.\n#\n# Prefix\n# ******\n# The :ref:`get_optional.sh@prefix`\n# in the file ``bin/get_optional.sh`` is used for this install.\n#\n# Version\n# *******\n# This will install the following version of Adolc\n# {xrst_spell_off}\n# {xrst_code sh}\nversion='e1fe476'\n# {xrst_code}\n# {xrst_spell_on}\n# This corresponds to the git master on Nov 13, 2020.\n#\n# Configuration\n# *************\n# If the file\n#\n#     ``external/adolc-`` *version* . ``configured``\n#\n# exists, the configuration will be skipped.\n# Delete this file if you want to re-run the configuration.\n#\n# {xrst_end get_adolc.sh}\n# -----------------------------------------------------------------------------\npackage='adolc'\nif [ $0 != \"bin/get_$package.sh\" ]\nthen\n    echo \"bin/get_$package.sh: must be executed from its parent directory\"\n    exit 1\nfi\n# -----------------------------------------------------------------------------\n# bash function that echos and executes a command\necho_eval() {\n    echo $*\n    eval $*\n}\n# -----------------------------------------------------------------------------\nweb_page='https://github.com/coin-or/ADOL-C.git'\ncppad_dir=`pwd`\n# -----------------------------------------------------------------------------\n# n_job\nif which nproc > /dev/null\nthen\n    n_job=$(nproc)\nelse\n    n_job=$(sysctl -n hw.ncpu)\nfi\n# ----------------------------------------------------------------------------\n# prefix\neval `grep '^prefix=' bin/get_optional.sh`\nif [[ \"$prefix\" =~ ^[^/] ]]\nthen\n    prefix=\"$cppad_dir/$prefix\"\nfi\necho \"prefix=$prefix\"\n# -----------------------------------------------------------------------------\nconfigured_flag=\"external/$package-${version}.configured\"\necho \"Executing get_$package.sh\"\nif [ -e \"$configured_flag\" ]\nthen\n    echo \"Skipping configuration because $configured_flag exits\"\n    echo_eval cd external/$package.git/build\n    echo_eval make -j $n_job install\n    echo \"get_$package.sh: OK\"\n    exit 0\nfi\n# --------------------------------------------------------------------------\nif [ -e /usr/lib64 ]\nthen\n    libdir='lib64'\nelse\n    libdir='lib'\nfi\n# -----------------------------------------------------------------------------\nif [ ! -d external ]\nthen\n    echo_eval mkdir external\nfi\necho_eval cd external\n# -----------------------------------------------------------------------------\nif [ ! -e \"$package.git\" ]\nthen\n    echo_eval git clone $web_page $package.git\nfi\necho_eval cd $package.git\necho_eval git reset --hard\necho_eval git checkout --quiet $version\n# -----------------------------------------------------------------------------\nsystem=`uname | tr [A-Z] [a-z] | sed -e 's|\\([a-z][a-z]*\\).*|\\1|'`\n# -----------------------------------------------------------------------------\nif which autoconf >& /dev/null\nthen\n    echo_eval autoreconf --install --force\nfi\n# -----------------------------------------------------------------------------\nif [ ! -e build ]\nthen\n    echo_eval mkdir build\nfi\necho_eval cd build\n# -----------------------------------------------------------------------------\nflags=\"--prefix=$prefix --with-colpack=$prefix --libdir=$prefix/$libdir\"\nflags+=\" --enable-static --enable-shared --enable-atrig-erf\"\n#\necho_eval ../configure $flags\necho_eval make -j $n_job install\n# -----------------------------------------------------------------------------\necho_eval touch $cppad_dir/$configured_flag\necho \"get_$package: OK\"\n"
  },
  {
    "path": "bin/get_colpack.sh",
    "content": "#! /bin/bash -e\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# {xrst_begin get_colpack.sh}\n# {xrst_comment_ch #}\n#\n# Download and Install ColPack in Build Directory\n# ###############################################\n#\n# Syntax\n# ******\n# ``bin/get_colpack.sh``\n#\n# Purpose\n# *******\n# If you are using Unix, this command will download and install\n# :ref:`Colpack<colpack_prefix@Colpack Home Page>`\n# in the CppAD ``build`` directory.\n#\n# Distribution Directory\n# **********************\n# This command must be executed in the\n# :ref:`download@Distribution Directory` .\n#\n# Source Directory\n# ****************\n# The ColPack source code is downloaded into the sub-directory\n# ``external/colpack.git`` below the distribution directory.\n#\n# Prefix\n# ******\n# The :ref:`get_optional.sh@prefix`\n# in the file ``bin/get_optional.sh`` is used for this install.\n#\n# Version\n# *******\n# This will install the following version of ColPack\n# {xrst_spell_off}\n# {xrst_code sh}\nversion='1.0.10'\n# {xrst_code}\n# {xrst_spell_on}\n#\n# Configuration\n# *************\n# If the file\n#\n#     ``external/colpack-`` *version* . ``configured``\n#\n# exists, the configuration will be skipped.\n# Delete this file if you want to re-run the configuration.\n#\n# {xrst_end get_colpack.sh}\n# -----------------------------------------------------------------------------\npackage='colpack'\nif [ $0 != \"bin/get_$package.sh\" ]\nthen\n    echo \"bin/get_$package.sh: must be executed from its parent directory\"\n    exit 1\nfi\n# -----------------------------------------------------------------------------\n# bash function that echos and executes a command\necho_eval() {\n    echo $*\n    eval $*\n}\n# -----------------------------------------------------------------------------\nweb_page='https://github.com/CSCsw/ColPack.git'\ncppad_dir=`pwd`\n# -----------------------------------------------------------------------------\n# n_job\nif which nproc > /dev/null\nthen\n    n_job=$(nproc)\nelse\n    n_job=$(sysctl -n hw.ncpu)\nfi\n# ----------------------------------------------------------------------------\n# prefix\neval `grep '^prefix=' bin/get_optional.sh`\nif [[ \"$prefix\" =~ ^[^/] ]]\nthen\n    prefix=\"$cppad_dir/$prefix\"\nfi\necho \"prefix=$prefix\"\n# -----------------------------------------------------------------------------\nconfigured_flag=\"external/$package-${version}.configured\"\necho \"Executing get_$package.sh\"\nif [ -e \"$configured_flag\" ]\nthen\n    echo \"Skipping configuration because $configured_flag exits\"\n    echo_eval cd external/$package.git\n    echo_eval make -j $n_job install\n    echo \"get_$package.sh: OK\"\n    exit 0\nfi\n# --------------------------------------------------------------------------\nif [ -e /usr/lib64 ]\nthen\n    libdir='lib64'\nelse\n    libdir='lib'\nfi\n# -----------------------------------------------------------------------------\nif [ ! -d external ]\nthen\n    echo_eval mkdir external\nfi\necho_eval cd external\n# -----------------------------------------------------------------------------\nif [ ! -e \"$package.git\" ]\nthen\n    echo_eval git clone $web_page $package.git\nfi\n# -----------------------------------------------------------------------------\necho_eval cd $package.git\necho_eval git checkout --quiet v$version\n# -----------------------------------------------------------------------------\nif which autoconf >& /dev/null\nthen\n    if which libtoolize >& /dev/null\n    then\n        echo_eval libtoolize\n    else\n        echo_eval glibtoolize\n    fi\n    echo_eval autoreconf --install --force\nelse\n    echo \"Error: autoconf and libtool required for this script\"\n    exit 1\nfi\n# -----------------------------------------------------------------------------\nif [[ \"$(uname)\" == CYGWIN* ]] || [ \"$(uname)\" == Darwin ]\nthen\n    lib_type='--enable-static --disable-shared'\n    echo_eval ls -l ./configure\n    echo_eval chmod +x ./configure\nelse\n    lib_type='--disable-static --enable-shared'\nfi\necho_eval ./configure \\\n    --prefix=$prefix \\\n    --libdir=$prefix/$libdir \\\n    $lib_type\n#\necho_eval touch $cppad_dir/$configured_flag\necho_eval make -j $n_job install\n# -----------------------------------------------------------------------------\necho \"get_$package: OK\"\n"
  },
  {
    "path": "bin/get_cppadcg.sh",
    "content": "#! /bin/bash -e\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# {xrst_begin get_cppadcg.sh}\n# {xrst_spell\n#     doxygen\n# }\n# {xrst_comment_ch #}\n#\n# Download and Install CppADCodeGen in Build Directory\n# ####################################################\n#\n# Syntax\n# ******\n# ``bin/get_cppadcg.sh``\n#\n# Purpose\n# *******\n# If you are using Unix, this command will download and install\n# `cppadcg <https://github.com/joaoleal/CppADCodeGen>`_\n# in the CppAD ``build`` directory.\n#\n# Requirements\n# ************\n# You must first use your package manager to install\n# :ref:`cmake@Eigen` .\n#\n# Distribution Directory\n# **********************\n# This command must be executed in the\n# :ref:`download@Distribution Directory` .\n#\n# Source Directory\n# ****************\n# The Cppadcg source code is downloaded into the sub-directory\n# ``external/cppadcg.git`` below the distribution directory.\n#\n# Prefix\n# ******\n# The :ref:`get_optional.sh@prefix`\n# in the file ``bin/get_optional.sh`` is used for this install.\n#\n# Git Hash\n# ********\n# This will install the commit of Cppadcg with the following git hash\n# {xrst_spell_off}\n# {xrst_code sh}\ngit_hash='e15c57207ea42a9572e9ed44df1894e09f7ce67e'\n# {xrst_code}\n# {xrst_spell_on}\n# The date corresponding to this commit was 2024-06-16.\n#\n# Configuration\n# *************\n# If the file\n#\n#     ``external/cppadcg-`` *git_hash* . ``configured``\n#\n# exists, the configuration will be skipped.\n# Delete this file if you want to re-run the configuration.\n#\n# Documentation\n# *************\n# If you change the setting for ``CREATE_DOXYGEN_DOC`` to ``ON`` ,\n# the doxygen documentation for CppADCodeGen will be installed in the directory\n#\n#     *prefix* / ``share/doc/cppadcg/html``\n#\n# where *prefix* has the value specified in the\n# :ref:`get_optional.sh<get_optional.sh@prefix>` file.\n#\n# {xrst_end get_cppadcg.sh}\n# -----------------------------------------------------------------------------\npackage='cppadcg'\nif [ $0 != \"bin/get_$package.sh\" ]\nthen\n    echo \"bin/get_$package.sh: must be executed from its parent directory\"\n    exit 1\nfi\n# -----------------------------------------------------------------------------\n# echo_eval\necho_eval() {\n    echo $*\n    eval $*\n}\n#\n# grep, sed\nsource bin/grep_and_sed.sh\n# -----------------------------------------------------------------------------\nweb_page='https://github.com/joaoleal/CppADCodeGen'\ncppad_repo=$(pwd)\n# -----------------------------------------------------------------------------\n# n_job\nif which nproc > /dev/null\nthen\n    n_job=$(nproc)\nelse\n    n_job=$(sysctl -n hw.ncpu)\nfi\n# ----------------------------------------------------------------------------\n# prefix\neval `$grep '^prefix=' bin/get_optional.sh`\nif [[ \"$prefix\" =~ ^[^/] ]]\nthen\n    prefix=\"$cppad_repo/$prefix\"\nfi\necho \"prefix=$prefix\"\n# -----------------------------------------------------------------------------\nconfigured_flag=\"external/$package-${git_hash}.configured\"\necho \"Executing get_$package.sh\"\nif [ -e \"$configured_flag\" ]\nthen\n    echo \"Skipping configuration because $configured_flag exits\"\n    echo_eval cd external/$package.git/build\n    echo_eval make -j $n_job install\n    echo \"get_$package.sh: OK\"\n    exit 0\nfi\n# -----------------------------------------------------------------------------\n# Create build/cppad_lib/libcppad_lib.* to aid in cppadcg install\nif [ ! -d build ]\nthen\n    echo_eval mkdir build\nfi\necho_eval cd build\nif [ -e CMakeCache.txt ]\nthen\n    echo_eval rm CMakeCache.txt\nfi\necho_eval cmake ..\necho_eval make\necho_eval cd ..\n# -----------------------------------------------------------------------------\n# Change into external\nif [ ! -d external ]\nthen\n    echo_eval mkdir external\nfi\necho_eval cd external\n# -----------------------------------------------------------------------------\n# cppadcg.git\nif [ ! -e $package.git ]\nthen\n    echo_eval git clone $web_page $package.git\nfi\necho_eval cd $package.git\necho_eval git reset --hard\necho_eval git checkout --quiet $git_hash\n#\n# cmake/FindCppAD.cmake\n# Modify FindCppAD.cmake so can use git repository\n# version of CppAD (not yet installed).\ncat << EOF > temp.sed\ns|IF *( *DEFINED *CPPAD_HOME *)|IF (DEFINED CPPAD_GIT_REPO)\\\\\n    # This setting is used for testing before installing CppAD.\\\\\n    # CPPAD_GIT_REPO is the a CppAD git repository. It is assumed that\\\\\n    # cmake and make have been executed in CPPAD_GIT_REPO/build.\\\\\n    SET(CPPAD_INCLUDE_DIR \"\\${CPPAD_GIT_REPO}/include\" )\\\\\n    SET(CPPAD_LIBRARIES\\\\\n        \"\\${CPPAD_GIT_REPO}/build/cppad_lib\"\\\\\n    )\\\\\n    INCLUDE_DIRECTORIES(\\\\\n        \"\\${CPPAD_INCLUDE_DIR}\"\\\\\n    )\\\\\n    #\\\\\n    IF( NOT EXISTS \"\\${CPPAD_INCLUDE_DIR}/cppad/cppad.hpp\" )\\\\\n        MESSAGE(FATAL_ERROR\\\\\n            \"Cannot find CPPAD_GIT_REPO/include/cppad/cppad.hpp\"\\\\\n        )\\\\\n    ENDIF()\\\\\n    IF( NOT EXISTS \"\\${CPPAD_INCLUDE_DIR}/cppad/configure.hpp\" )\\\\\n        MESSAGE(FATAL_ERROR\\\\\n            \"Cannot find CPPAD_GIT_REPO/include/cppad/configure.hpp\"\\\\\n        )\\\\\n    ENDIF()\\\\\n    #\\\\\n    FIND_LIBRARY( CPPAD_LIB_PATH\\\\\n        cppad_lib\\\\\n        PATHS \\${CPPAD_LIBRARIES}\\\\\n        NO_DEFAULT_PATH\\\\\n    )\\\\\n    IF( NOT CPPAD_LIB_PATH  )\\\\\n        MESSAGE(FATAL_ERROR\\\\\n            \"Cannot find \\${library} library below CPPAD_GIT_REPO=\"\\\\\n            \"{CPPAD_GIT_REPO}\"\\\\\n        )\\\\\n    ENDIF()\\\\\n    #\\\\\n    SET(CPPAD_FOUND TRUE)\\\\\n\\\\\nELSEIF (DEFINED CPPAD_HOME)|\nEOF\necho_eval git checkout  cmake/FindCppAD.cmake\necho_eval $sed -i -f temp.sed cmake/FindCppAD.cmake\n# -----------------------------------------------------------------------------\n#  make install\nif [ ! -e build ]\nthen\n    echo_eval mkdir build\nfi\necho_eval cd build\nif [ -e CMakeCache.txt ]\nthen\n    rm CMakeCache.txt\nfi\necho_eval cmake \\\n    -D CPPAD_GIT_REPO=\"$cppad_repo\" \\\n    -D CMAKE_INSTALL_PREFIX=$prefix \\\n    -D GOOGLETEST_GIT=ON \\\n    -D CREATE_DOXYGEN_DOC=OFF \\\n    ..\necho_eval make -j $n_job install\n# -----------------------------------------------------------------------------\necho_eval touch $cppad_repo/$configured_flag\necho \"get_$package.sh: OK\"\n"
  },
  {
    "path": "bin/get_fadbad.sh",
    "content": "#! /bin/bash -e\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# {xrst_begin get_fadbad.sh}\n# {xrst_comment_ch #}\n#\n# Download and Install Fadbad in Build Directory\n# ##############################################\n#\n# Syntax\n# ******\n# ``bin/get_fadbad.sh``\n#\n# Purpose\n# *******\n# If you are using Unix, this command will download and install\n# :ref:`Fadbad<fadbad_prefix@Fadbad Home Page>`\n# in the CppAD ``build`` directory.\n#\n# Distribution Directory\n# **********************\n# This command must be executed in the\n# :ref:`download@Distribution Directory` .\n#\n# Source Directory\n# ****************\n# The Fadbad source code is downloaded into the sub-directory\n# ``external/FADBAD++`` below the distribution directory.\n#\n# Prefix\n# ******\n# The :ref:`get_optional.sh@prefix`\n# in the file ``bin/get_optional.sh`` is used for this install.\n#\n# Version\n# *******\n# This will install the following version of Fadbad\n# {xrst_spell_off}\n# {xrst_code sh}\nversion='2.1'\n# {xrst_code}\n# {xrst_spell_on}\n#\n# {xrst_end get_fadbad.sh}\n# -----------------------------------------------------------------------------\npackage='fadbad'\nif [ $0 != \"bin/get_$package.sh\" ]\nthen\n    echo \"bin/get_$package.sh: must be executed from its parent directory\"\n    exit 1\nfi\n# -----------------------------------------------------------------------------\n# bash function that echos and executes a command\necho_eval() {\n    echo $*\n    eval $*\n}\n# -----------------------------------------------------------------------------\nweb_page='http://uning.dk//download'\ncppad_dir=`pwd`\n# -----------------------------------------------------------------------------\n# prefix\neval `grep '^prefix=' bin/get_optional.sh`\nif [[ \"$prefix\" =~ ^[^/] ]]\nthen\n    prefix=\"$cppad_dir/$prefix\"\nfi\necho \"prefix=$prefix\"\n# -----------------------------------------------------------------------------\nif [ ! -d external ]\nthen\n    echo_eval mkdir external\nfi\necho_eval cd external\n# -----------------------------------------------------------------------------\nif [ ! -e \"FADBAD++-$version.tar.gz\" ]\nthen\n    echo_eval wget --no-check-certificate $web_page/FADBAD++-$version.tar.gz\nfi\nif [ -e \"FADBAD++\" ]\nthen\n    echo_eval rm -r FADBAD++\nfi\necho_eval tar -xzf FADBAD++-$version.tar.gz\nif [ ! -e \"$prefix/include\" ]\nthen\n    echo_eval mkdir -p \"$prefix/include\"\nfi\nif [ -e \"$prefix/include/FADBAD++\" ]\nthen\n    echo_eval rm -r \"$prefix/include/FADBAD++\"\nfi\necho_eval cp -r FADBAD++ \"$prefix/include/FADBAD++\"\n# -----------------------------------------------------------------------------\necho \"get_$package.sh: OK\"\n"
  },
  {
    "path": "bin/get_ipopt.sh",
    "content": "#! /usr/bin/env bash\nset -e -u\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# {xrst_begin get_ipopt.sh}\n# {xrst_spell\n#     blas\n#     lapack\n# }\n# {xrst_comment_ch #}\n#\n# Download and Install Ipopt in Build Directory\n# #############################################\n#\n# Syntax\n# ******\n# ``bin/get_ipopt.sh``\n#\n# Purpose\n# *******\n# If you are using Unix, this command will download and install\n# `Ipopt <https://coin-or.github.io/Ipopt/>`_ in the\n# CppAD ``build`` directory.\n#\n# Requirements\n# ************\n# This It is assumed that a copy of the Blas and Lapack is installed on\n# the system.\n#\n# Distribution Directory\n# **********************\n# This command must be executed in the\n# :ref:`download@Distribution Directory` .\n#\n# Source Directory\n# ****************\n# The Ipopt source code is downloaded and compiled in the sub-directory\n# ``external/Ipopt.git`` below the distribution directory.\n#\n# Prefix\n# ******\n# The :ref:`get_optional.sh@prefix`\n# in the file ``bin/get_optional.sh`` is used for this install.\n#\n# Version\n# *******\n# This will install the following version of Ipopt\n# {xrst_spell_off}\n# {xrst_code sh}\nipopt_version='3.14.16'\n# {xrst_code}\n# {xrst_spell_on}\n#\n# Configuration\n# *************\n# If the file\n#\n#     ``external/ipopt-`` *version* . ``configured``\n#\n# exists, the configuration will be skipped.\n# Delete this file if you want to re-run the configuration.\n#\n# {xrst_end get_ipopt.sh}\n# ----------------------------------------------------------------------------\nipopt_url='https://github.com/coin-or/Ipopt'\n# ----------------------------------------------------------------------------\n#\n# echo_eval\nfunction echo_eval() {\n    echo $*\n    eval $*\n}\n#\n# clone_url_name_version\n# creates ./name.git from corresponding url and version\n# $1 = url\n# $2 = name\n# $3 = version\nfunction clone_url_name_version() {\n    if [ ! -e $2.git ]\n    then\n        echo_eval git clone $1.git $2.git\n    fi\n    echo_eval cd $2.git\n    echo_eval git reset --hard\n    echo_eval git fetch origin\n    echo_eval git checkout --quiet $3\n    if [ ! -e build ]\n    then\n        echo_eval mkdir build\n    fi\n    cd ..\n}\n# ----------------------------------------------------------------------------\nif [ $0 != 'bin/get_ipopt.sh' ]\nthen\n    echo 'bin/get_ipopt.sh: must be executed from its parent directory'\n    exit 1\nfi\n# ----------------------------------------------------------------------------\n#\n# n_job\nif which nproc >& /dev/null\nthen\n    n_job=$(nproc)\nelse\n    n_job=$(sysctl -n hw.ncpu)\nfi\n#\n# configured_flag\nconfigured_flag=\"external/Ipopt-${ipopt_version}.configured\"\necho \"Executing get_ipopt.sh\"\nif [ -e \"$configured_flag\" ]\nthen\n    echo \"Skipping configuration because $configured_flag exits\"\n    echo_eval cd external/Ipopt.git/build\n    make -j $n_job install\n    echo \"get_ipopt.sh: OK\"\n    exit 0\nfi\nif ls external/Ipopt-*.configured > /dev/null\nthen\n    echo_eval rm -rf external/Mumps.git\n    echo_eval rm -rf external/ASL.git\n    echo_eval rm external/Ipopt-*.configured\nfi\n#\n# prefix\neval `grep '^prefix=' bin/get_optional.sh`\nif [[ \"$prefix\" =~ ^[^/] ]]\nthen\n    prefix=\"$(pwd)/$prefix\"\nfi\necho \"prefix=$prefix\"\n#\n# external\nif [ ! -e external ]\nthen\n    mkdir external\nfi\necho_eval cd external\n#\n# configure_all\nconfigure_all=\"--disable-dependency-tracking\"\nconfigure_all+=\" --prefix=$prefix\"\nconfigure_all+=\" --enable-shared\"\n#\n# external/build_type/Ipopt.git\nname='Ipopt'\nclone_url_name_version $ipopt_url $name \"releases/$ipopt_version\"\n#\n# external/build_type/ASL.git\n# external/build_type/mumps.git\nfor name in 'ASL' 'Mumps'\ndo\n    # clone_url_name_version\n    line=$(grep \"ThirdParty/$name\" 'Ipopt.git/.coin-or/Dependencies')\n    url=$(echo $line | awk '{print $2}' )\n    version=$(echo $line | awk '{print $3}' )\n    clone_url_name_version $url $name $version\n    #\n    # get.$name\n    cd $name.git\n    if [ -e \"./get.$name\" ]\n    then\n        if [ ! -e \"./get.$name.done\" ]\n        then\n            echo_eval ./get.$name\n            touch ./get.$name.done\n        fi\n    fi\n    cd ..\ndone\n#\n# Install ASL\ncd ASL.git/build\necho_eval ../configure $configure_all\necho_eval make -j $n_job install\ncd ../..\n#\n# Install Mumps\nconfigure_mumps=\"$configure_all\"\nif [ \"$(uname)\" == 'Darwin' ]\nthen\n    if which brew\n    then\n        metis_libdir=$(brew --prefix)/lib\n        metis_incdir=$(brew --prefix)/include\n        if [ ! -e \"$metis_libdir/libmetis.dylib\" ]\n        then\n            echo 'MacOS+brew: Cannot find metis library directory'\n        fi\n        if [ ! -e \"$metis_incdir/metis.h\" ]\n        then\n            echo 'MacOS+brew: Cannot find metis include directory'\n        fi\n        configure_mumps+=\" --with-metis-lflags='-L$metis_libdir -lmetis'\"\n        configure_mumps+=\" --with-metis-cflags='-I$metis_incdir'\"\n    fi\nfi\ncd Mumps.git/build\necho_eval ../configure $configure_mumps\necho_eval make -j $n_job install\ncd ../..\n#\n# Install Ipopt\ncd Ipopt.git/build\necho_eval ../configure $configure_all --disable-java\necho_eval make -j $n_job install\ncd ../..\n#\n# configured_flag\ncd ..\ntouch $configured_flag\n# ----------------------------------------------------------------------------\necho 'get_ipopt.sh: OK'\nexit 0\n"
  },
  {
    "path": "bin/get_optional.sh",
    "content": "#! /bin/bash -e\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n#\n# {xrst_begin get_optional.sh}\n# {xrst_spell\n#     ggrep\n#     grep\n#     gsed\n#     homebrew\n#     sed\n# }\n# {xrst_comment_ch #}\n#\n# Download and Install The CppAD Optional Packages\n# ################################################\n#\n# Syntax\n# ******\n# ``bin/get_optional.sh``\n#\n# Purpose\n# *******\n# If you are using Unix, this command will download and install\n# all of the optional packages that can be used with CppAD.\n#\n# Distribution Directory\n# **********************\n# This command must be executed in the\n# :ref:`download@Distribution Directory` .\n#\n# prefix\n# ******\n# This is the prefix for installing the optional packages.\n# It can be changed by editing its setting of *prefix* below\n# in the file ``bin/get_optional.sh`` .\n# Note that there can only be one setting that is not commented out with\n# a  at the start of its line.\n#\n# Absolute Path\n# =============\n# If the first character in the prefix is a ``/`` ,\n# it is an absolute path; e.g., the following setting:\n# {xrst_spell_off}\n# {xrst_code sh}\n# prefix=\"$HOME/prefix/cppad\"\n# {xrst_code}\n# {xrst_spell_on}\n#\n# Relative Path\n# =============\n# If the first character in the prefix is **not** a ``/`` ,\n# it is a path relative to the distribution directory;\n# e.g., the following setting:\n# {xrst_spell_off}\n# {xrst_code sh}\nprefix=\"build/prefix\"\n# {xrst_code}\n# {xrst_spell_on}\n#\n# Configuration\n# =============\n# If you do an install and then change the *prefix* ,\n# you should delete all the files listed by the following command:\n#\n#     ``ls external/`` * . ``configured``\n#\n# MacOS with Homebrew\n# *******************\n# If you are using MacOS with homebrew, get_optional requires\n# the gnu versions of grep and sed; i.e., ``ggrep`` and ``gsed`` .\n#\n# get_optional.log\n# ****************\n# This file contains the standard out output for each of the optional scripts\n# in the order that they are executed.\n#\n# get_optional.err\n# ****************\n# This file contains the standard error output for each of the optional scripts\n# in the order that they are executed.\n#\n# Contents\n# ********\n# {xrst_toc_table\n#    bin/get_adolc.sh\n#    bin/get_cppadcg.sh\n#    bin/get_colpack.sh\n#    bin/get_fadbad.sh\n#    bin/get_ipopt.sh\n#    bin/get_sacado.sh\n# }\n#\n# {xrst_end get_optional.sh}\n# -----------------------------------------------------------------------------\nif [ $0 != \"bin/get_optional.sh\" ]\nthen\n    echo \"bin/get_optional.sh: must be executed from its parent directory\"\n    exit 1\nfi\n# -----------------------------------------------------------------------------\n# bash function that echos and executes a command\necho_eval() {\n    echo $*\n    eval $*\n}\nif [ -e 'get_optional.log' ]\nthen\n    echo_eval rm get_optional.log\nfi\nif [ -e 'get_optional.err' ]\nthen\n    echo_eval rm get_optional.err\nfi\n# -----------------------------------------------------------------------------\nlist='colpack adolc fadbad ipopt sacado cppadcg'\nfor package in $list\ndo\n    echo \"bin/get_${package}.sh 1>> get_optional.log 2>> get_optional.err\"\n    if bin/get_${package}.sh 1>> get_optional.log 2>> get_optional.err\n    then\n        echo \"bin/get_${package}.sh: OK\"\n    else\n        echo \"bin/get_${package}.sh: Error; try following:\"\n        echo '  tail ./get_optional.err'\n        exit 1\n    fi\ndone\n# -----------------------------------------------------------------------------\necho \"get_optional: OK\"\n"
  },
  {
    "path": "bin/get_sacado.sh",
    "content": "#! /bin/bash -e\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# {xrst_begin get_sacado.sh}\n# {xrst_spell\n#     trilinos\n# }\n# {xrst_comment_ch #}\n#\n# Download and Install Sacado in Build Directory\n# ##############################################\n#\n# Syntax\n# ******\n# ``bin/get_sacado.sh``\n#\n# Purpose\n# *******\n# If you are using Unix, this command will download and install\n# :ref:`Sacado<sacado_prefix@Sacado Home Page>`\n# in the CppAD ``build`` directory.\n#\n# Distribution Directory\n# **********************\n# This command must be executed in the\n# :ref:`download@Distribution Directory` .\n#\n# Source Directory\n# ****************\n# The Sacado source code is downloaded into the sub-directory\n# ``external/trilinos.git`` below the distribution directory.\n#\n# Prefix\n# ******\n# The :ref:`get_optional.sh@prefix`\n# in the file ``bin/get_optional.sh`` is used for this install.\n#\n# Version\n# *******\n# This will install the version of Sacado corresponding to the following\n# version of Trilinos:\n# {xrst_spell_off}\n# {xrst_code sh}\nversion='14-0-0'\n# {xrst_code}\n# {xrst_spell_on}\n#\n# Configuration\n# *************\n# If the file\n#\n#     ``external/sacado-`` *version* . ``configured``\n#\n# exists, the configuration will be skipped.\n# Delete this file if you want to re-run the configuration.\n#\n# {xrst_end get_sacado.sh}\n# -----------------------------------------------------------------------------\npackage='sacado'\nif [ $0 != \"bin/get_$package.sh\" ]\nthen\n    echo \"bin/get_$package.sh: must be executed from its parent directory\"\n    exit 1\nfi\n#\n# grep, sed\nsource bin/grep_and_sed.sh\n# -----------------------------------------------------------------------------\n# bash function that echos and executes a command\necho_eval() {\n    echo $*\n    eval $*\n}\n# -----------------------------------------------------------------------------\nweb_page='https://github.com/trilinos/Trilinos/archive/refs/tags'\nrelease_name=\"trilinos-release-$version\"\ncppad_dir=`pwd`\n# -----------------------------------------------------------------------------\n# n_job\nif which nproc > /dev/null\nthen\n    n_job=$(nproc)\nelse\n    n_job=$(sysctl -n hw.ncpu)\nfi\n# ----------------------------------------------------------------------------\n# prefix\neval `$grep '^prefix=' bin/get_optional.sh`\nif [[ \"$prefix\" =~ ^[^/] ]]\nthen\n    prefix=\"$cppad_dir/$prefix\"\nfi\necho \"prefix=$prefix\"\n# -----------------------------------------------------------------------------\nconfigured_flag=\"external/$package-${version}.configured\"\necho \"Executing get_$package.sh\"\nif [ -e \"$configured_flag\" ]\nthen\n    echo \"Skipping configuration because $configured_flag exits\"\n    echo_eval cd external/$release_name/build\n    echo_eval make -j $n_job install\n    echo \"get_$package.sh: OK\"\n    exit 0\nfi\n# -----------------------------------------------------------------------------\n# libdir\nif [ -e /usr/lib64 ]\nthen\n    libdir='lib64'\nelse\n    libdir='lib'\nfi\n# -----------------------------------------------------------------------------\n# change into external directory\nif [ ! -d external ]\nthen\n    echo_eval mkdir external\nfi\necho_eval cd external\n# -----------------------------------------------------------------------------\n# create the trilions source directory and change into it\nif [ ! -e $release_name ]\nthen\n    wget \"$web_page/$release_name.tar.gz\"\n    tar -xzf \"$release_name.tar.gz\"\n    mv Trilinos-$release_name $release_name\n    #\n    # see https://github.com/trilinos/Trilinos/issues/11923\n    file=\"$release_name/packages/teuchos/core/src/Teuchos_BigUIntDecl.hpp\"\n    if ! $grep '^#include <cstdint>' $file > /dev/null\n    then\n        $sed -i $file -e 's|#include <iosfwd>|&\\n#include <cstdint>|'\n    fi\nfi\necho_eval cd $release_name\n# -----------------------------------------------------------------------------\n# change into build sub-directory\nif [ ! -e build ]\nthen\n    echo_eval mkdir build\nfi\necho_eval cd build\n# -----------------------------------------------------------------------------\ncmd=\"cmake \\\n    -D CMAKE_BUILD_TYPE=RELEASE \\\n    -D Trilinos_ENABLE_Sacado=ON \\\n    -D Sacado_ENABLE_TESTS=OFF \\\n    -D CMAKE_INSTALL_PREFIX=$prefix \\\n    -D Trilinos_INSTALL_LIB_DIR=$prefix/$libdir \\\n    ..\"\necho $cmd\n$cmd\necho_eval make -j $n_job install\n# -----------------------------------------------------------------------------\necho_eval touch $cppad_dir/$configured_flag\necho \"get_$package.sh: OK\"\n"
  },
  {
    "path": "bin/git_commit.sh",
    "content": "#! /usr/bin/env bash\nset -e -u\n# !! EDITS TO THIS FILE ARE LOST DURING UPDATES BY xrst.git/bin/dev_tools.sh !!\n# ---------------------------------------------------------------------------\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-25 Bradley M. Bell\n# ---------------------------------------------------------------------------\n# bin/git_commit.sh\n# Opens your editor with comments about this git commit.\n# 1.  The git commit log message will not include comment lines.\n# 2.  The file git_commit.log contains the message for the previous commit\n#     so that you can read it in and modify it for this commit.\n# 3.  If typos is installed on your system, it will be used to check for\n#     errors in git_commit.log. If so, you can read it and modity it\n#     when you re-run git_commit.sh.\n# 4.  The branch of the commit is automatically placed a the beginning\n#     of the first line for the message.\n# 5.  All the modified files are automatically included in the commit.\n# 6.  The variable check_git_commit in bin/dev_settings.sh can be used\n#     to selectively revert certain files before the commit.\n# ---------------------------------------------------------------------------\n# bash function that echos and executes a command\necho_eval() {\n    echo $*\n    eval $*\n}\n# -----------------------------------------------------------------------------\nif [ $# != 0 ]\nthen\n    echo 'usage: bin/git_commit.sh: does not expect arguments'\n    exit 1\nfi\nif [ \"$0\" != 'bin/git_commit.sh' ]\nthen\n    echo 'bin/git_commit.sh: must execute this script from its parent directory'\n    exit 1\nfi\nif [ ! -e './.git' ]\nthen\n    echo 'bin/git_commit.sh: cannot find ./.git'\n    exit 1\nfi\n#\n# grep, sed\nsource bin/grep_and_sed.sh\n#\n# check_git_commit\nsource bin/dev_settings.sh\n# -----------------------------------------------------------------------------\n# EDITOR\nset +u\nif [ \"$EDITOR\" == '' ]\nthen\n    echo 'bin/git_commit.sh: EDITOR is not defined.'\n    exit 1\nfi\nset -u\n# -----------------------------------------------------------------------------\n# check_git_commit\necho 's|^...||' > temp.sed\nfor name in $check_git_commit\ndo\n    if [ -f $name ]\n    then\n        echo \"^$name\\$\" | $sed -e 's|/|[/]|g' -e 's|.*|/&/p|' >> temp.sed\n    elif [ -d $name ]\n    then\n        echo \"^$name/\" | $sed -e 's|/|[/]|g' -e 's|.*|/&/p|' >> temp.sed\n    else\n        echo \"$name in check_git_commit is not a file or directory\"\n        exit 1\n    fi\ndone\nlist=$(\n    git status --porcelain | $sed -n -f temp.sed\n)\nfor file in $list\ndo\n    res=''\n    while [ \"$res\" != 'revert' ] && [ \"$res\" != 'commit' ]\n    do\n        read -p \"$file: Revert or commit changes [revert/commit] ?\" res\n    done\n    if [ \"$res\" == 'revert' ]\n    then\n        git reset    $file\n        git checkout $file\n    fi\ndone\n# -----------------------------------------------------------------------------\n# new files\n# convert spaces in file names to @@\nlist=$(\n    git status --porcelain | $sed -n -e '/^?? /p' |  \\\n        $sed -e 's|^?? ||' -e 's|\"||g' -e 's| |@@|g'\n)\nfor file in $list\ndo\n    # convert @@ in file names back to spaces\n    file=$(echo $file | $sed -e 's|@@| |g')\n    res=''\n    while [ \"$res\" != 'delete' ] && [ \"$res\" != 'add' ] && [ \"$res\" != 'abort' ]\n    do\n        read -p \"'$file' is unknown to git, [delete/add/abort] ?\" res\n    done\n    if [ \"$res\" == 'delete' ]\n    then\n        # may be spaces in file name so do not use echo_eval\n        echo \"rm '$file'\"\n        rm \"$file\"\n    elif [ \"$res\" == 'abort' ]\n    then\n        echo 'bin/git_commit.sh: aborting'\n        exit 1\n    else\n        git add \"$file\"\n    fi\ndone\n# -----------------------------------------------------------------------------\n# temp.log\nbranch=$(git branch --show-current)\ncat << EOF > temp.log\n$branch:\n# 1. Enter message for this commit above this line.\n# 2. The message for the previous commit is in git_commit.log (if it exists).\n# 3. This commit will abort if the first line does not begin with \"$branch:\"\n#    because $branch is the branch for this commit.\n# 4. Lines starting with '#' are not included in the message.\n# 5. Below is a list of the files for this commit:\nEOF\ngit status --porcelain | $sed -e 's|^|# |' >> temp.log\n$EDITOR temp.log\n$sed -i -e '/^#/d' temp.log\nif ! head -1 temp.log | $grep \"^$branch:\" > /dev/null\nthen\n    echo \"Aborting because first line does not begin with $branch:\"\n    echo 'See ./temp.log'\n    exit 1\nfi\nif ! head -1 temp.log | $grep \"^$branch:.*[^ \\t]\" > /dev/null\nthen\n    echo \"Aborting because only white space follow $branch: in first line\"\n    echo 'See ./temp.log'\n    exit 1\nfi\n#\n# git_commit.log\nmv temp.log git_commit.log\nif which typos >& /dev/null\nthen\n    typos git_commit.log\nfi\n# -----------------------------------------------------------------------------\n# git add\necho_eval git add --all\n#\n#\n# git commit\ngit commit --file=git_commit.log\n#\necho 'bin/git_commit.sh: OK'\nexit 0\n"
  },
  {
    "path": "bin/grep_and_sed.sh",
    "content": "# ---------------------------------------------------------------------------\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-25 Bradley M. Bell\n# ---------------------------------------------------------------------------\n# source bin/grep_and_sed\n# Sets the shell variables grep and sed to the gnu version for this system\n# ---------------------------------------------------------------------------\n#\n# sed, grep\nsed=sed\ngrep=grep\nif [ \"$(uname)\" == 'Darwin' ]\nthen\nif which gsed > /dev/null\n    then\n        sed=gsed\n    else\n        echo 'darwin_names.sh: cannot find gsed (gnu sed) on MacOS system'\n    fi\n    if which ggrep > /dev/null\n    then\n        grep=ggrep\n    else\n        echo 'darwin_names.sh: cannot find ggrep (gnu grep) on MacOS system'\n    fi\nfi\n"
  },
  {
    "path": "bin/group_list.sh",
    "content": "#! /usr/bin/env bash\nset -e -u\n# !! EDITS TO THIS FILE ARE LOST DURING UPDATES BY xrst.git/bin/dev_tools.sh !!\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2020-25 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# bin/group_list.sh\n# Returns a space separated list of the group names for this project.\n# The list is extracted from the [root_file] section of the xrst.toml\n# file for this project.\n# If there is no xrst.toml file for this project, the group list is just\n# the default group.\n#\n# sed\nsource bin/grep_and_sed.sh\n#\nif [ ! -e xrst.toml ]\nthen\n    echo 'default'\n    exit 0\nfi\n#\n# temp.sed\ncat << EOF > temp.sed\n/^\\\\[root_file\\\\]/ ! b end\n: loop\nN\n/\\\\n\\\\[/! b loop\ns|^\\\\[root_file\\\\]||\ns|\\\\n *#[^\\\\n]*||g\ns|\\\\n\\\\([A-Za-z0-9_.]*\\\\) *=[^\\\\n]*|\\\\1 |g\ns|\\\\n[^\\\\n]*\\$||\n#\np\n#\n: end\nEOF\n#\n# group_list\ngroup_list=$( $sed -n -f temp.sed xrst.toml)\n#\necho \"$group_list\"\n"
  },
  {
    "path": "bin/master_revert.sh",
    "content": "#! /bin/bash -e\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\nif [ \"$0\" != 'bin/master_revert.sh' ]\nthen\n    echo \"bin/master_revert.sh: must be executed from its parent directory\"\n    exit 1\nfi\n# -----------------------------------------------------------------------------\nbranch=$(git branch | sed -n '/^[*]/p' | sed -e 's/[*] *//')\nlist=$(\n    git diff master $branch | \\\n    sed -n -e '/^diff --git/p' | \\\n    sed -e 's|^diff --git a/||' -e 's| b/|@|'\n)\nfor pair in $list\ndo\n    master_file=$(echo $pair | sed -e 's|@.*||')\n    branch_file=$(echo $pair | sed -e 's|[^@]*@||')\n    if [ \"$master_file\" == \"$branch_file\" ]\n    then\n        echo \"reverting $master_file\"\n        git show master:$master_file > $branch_file\n    else\n        echo 'skipping move of'\n        echo \"$master_file -> $branch_file\"\n    fi\ndone\necho 'master_revert.sh: OK'\nexit 0\n"
  },
  {
    "path": "bin/new_release.sh",
    "content": "#! /usr/bin/env bash\nset -e -u\n# !! EDITS TO THIS FILE ARE LOST DURING UPDATES BY xrst.git/bin/dev_tools.sh !!\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2020-25 Bradley M. Bell\n# -----------------------------------------------------------------------------\n# bin/new_release.sh  [--skip_stable_check_all]\n# Creates and check a release for the year and release number specified below.\n#\n# bin/check_all.sh [--skip_external_links]\n# is used by new_release to skip checking external links.\n# new_release.sh skips this when testing before the new release (tag)  exists.\n# -----------------------------------------------------------------------------\nyear='2026' # Year for this stable version\nrelease='0' # first release for each year starts with 0\n# -----------------------------------------------------------------------------\nif [ \"$0\" != 'bin/new_release.sh' ]\nthen\n    echo 'bin/new_release.sh: must be executed from its parent directory'\n    exit 1\nfi\nif [ ! -e './.git' ]\nthen\n    echo 'bin/new_release.sh: cannot find ./.git'\n    exit 1\nfi\nif [[ \"$year\" =~ ^[0-9]{4}$ ]]\nthen\n    echo \"year = $year\"\nelse\n    echo \"new_release.sh: year = $year is not valid\"\n    exit 1\nfi\nif [[ \"$release\" =~ ^[0-9]{1,2}$ ]]\nthen\n    echo \"release = $release\"\nelse\n    echo \"new_release.sh: release = $release is not valid\"\n    exit 1\nfi\n#\n# skip_stable_check_all\nskip_stable_check_all='no'\nwhile [ $# != 0 ]\ndo\n    if [ \"$1\" == '--skip_stable_check_all' ]\n    then\n        skip_stable_check_all='yes'\n    else\n        echo 'bin/new_release.sh [--skip_stable_check_all]'\n        echo \"$1 is not a valid argument\"\n        exit 1\n    fi\n    shift\ndone\n# -----------------------------------------------------------------------------\n# bash function that echos and executes a command\necho_eval() {\n    echo $*\n    eval $*\n}\n# -----------------------------------------------------------------------------\n#\n# main_branch\nmain_branch=$(git branch --show-current)\nif [ \"$main_branch\" != 'master' ] && [ \"$main_branch\" != 'main' ]\nthen\n    echo 'bin/new_release.sh: execute using master or main branch'\n    exit 1\nfi\n#\n# sed\nsource bin/grep_and_sed.sh\n#\n# version_file_list\nsource bin/dev_settings.sh\n#\n# first_version_file\nfirst_version_file=$(echo $version_file_list | $sed -e 's|^ *||' -e 's| .*||')\n#\n# version_type\ncat << EOF > temp.sed\n/[\"'][0-9]{8}[\"']/b one\n/[\"'][0-9]{8}[.][0-9]{1,2}[\"']/b one\n/[\"'][0-9]{4}[.][0-9]{1,2}[.][0-9]{1,2}[\"']/b one\nb end\n#\n: one\ns|.*[\"']([0-9]{8})[\"'].*|\\\\1|\ns|.*[\"']([0-9]{8}[.][0-9]{1,2})[\"'].*|\\\\1|\ns|.*[\"']([0-9]{4}[.][0-9]{1,2}[.][0-9]{1,2})[\"'].*|\\\\1|\np\n#\n: end\nEOF\nversion=$($sed -n -r -f temp.sed $first_version_file)\nif [[ \"$version\" =~ ^[0-9]{8}$ ]]\nthen\n    version_type=1\nelif [[ \"$version\" =~ ^[0-9]{8}[.][0-9]{1,2}$ ]]\nthen\n    version_type=2\nelif [[ \"$version\" =~ ^[0-9]{4}[.][0-9]{1,2}[.][0-9]{1,2}$ ]]\nthen\n    version_type=3\nfi\n#\n# tag\nif [ \"$version_type\" == 1 ] || [ \"$version_type\" == 2 ]\nthen\n    tag=\"${year}0000.$release\"\nelse\n    tag=$year.0.$release\nfi\n#\n# tag_committed\ntag_committed='no'\nif git tag --list | grep \"$tag\" > /dev/null\nthen\n    tag_committed='yes'\nfi\n#\n# stable_branch\nstable_branch=stable/$year\n\n#\n# stable_local_hash\nif ! git show-ref --hash \"heads/$stable_branch\" > /dev/null\nthen\n     echo \"Cannot find local version of $stable_branch. Do the following ?\"\n     echo \"git branch $stable_branch $main_branch\"\n     exit 1\nfi\nstable_local_hash=$(git show-ref --hash \"heads/$stable_branch\" )\n#\n# stable_remote_hash\nif ! git show-ref --hash \"origin/$stable_branch\" > /dev/null\nthen\n     echo \"Cannot find remote version of $stable_branch. Do the following ?\"\n     echo \"git checkout $stable_branch\"\n     echo \"git push --set-upstream origin $stable_branch\"\n     exit 1\nfi\nstable_remote_hash=$(git show-ref --hash \"origin/$stable_branch\" )\n#\n# main_local_hash\nmain_local_hash=$(git show-ref --hash \"heads/$main_branch\" )\n#\n# main_remote_hash\nmain_remote_hash=$(git show-ref --hash \"origin/$main_branch\" )\n#\n# ----------------------------------------------------------------------------\n# Changes to main_branch\n# ----------------------------------------------------------------------------\n#\n# version_file_list\ncat << EOF > temp.sed\ns|stable-[0-9]{4}|stable-$year|g\ns|release-[0-9]{4}|release-$year|g\n#\ns|archive/[0-9]{4}[.][0-9]*[.][0-9]*[.]tar[.]gz|archive/$tag.tar.gz|\ns|archive/[0-9]{8}[.]tar[.]gz|archive/$tag.tar.gz|\ns|archive/[0-9]{8}[.][0-9]*[.]tar[.]gz|archive/$tag.tar.gz|\n#\ns|tags/[0-9]{4}[.][0-9]*[.][0-9]*>|tags/$tag>|\ns|tags/[0-9]{8}>|tags/$tag>|\ns|tags/[0-9]{8}[.][0-9]*>|tags/$tag>|\n#\ns|tags/[0-9]{4}[.][0-9]*[.][0-9]* *\\$|tags/$tag|\ns|tags/[0-9]{8} *\\$|tags/$tag|\ns|tags/[0-9]{8}[.][0-9]* *\\$|tags/$tag|\n#\nEOF\nfor file in $version_file_list\ndo\n    $sed -r -i $file -f temp.sed\ndone\n#\n# run_xrst.sh\nif [ \"$tag_committed\" == 'yes' ]\nthen\n    echo_eval bin/run_xrst.sh --external_links\nelse\n    echo_eval bin/run_xrst.sh\nfi\n#\n# git_status\ngit_status=$(git status --porcelain)\nif [ \"$git_status\" != '' ]\nthen\n    echo \"bin/new_release: git status is not empty for $main_branch branch\"\n    echo 'use bin/git_commit.sh to commit its changes ?'\n    exit 1\nfi\n# ----------------------------------------------------------------------------\n# Changes to stable branch\n# ----------------------------------------------------------------------------\nif ! git show-ref $stable_branch > /dev/null\nthen\n    echo \"bin/new_release: neither local or remove $stable_branch exists.\"\n    echo 'Use the following to create it ?'\n    echo \"   git branch $stable_branch\"\n    exit 1\nfi\nif ! git checkout $stable_branch\nthen\n    echo \"bin/new_release: should be able to checkout $stable_branch\"\n    exit 1\nfi\n#\n# version_file_list\ncat << EOF > temp.sed\ns|stable-[0-9]{4}|stable-$year|g\ns|release-[0-9]{4}|release-$year|g\n#\ns|archive/[0-9]{4}[.][0-9]*[.][0-9]*[.]tar[.]gz|archive/$tag.tar.gz|\ns|archive/[0-9]{8}[.]tar[.]gz|archive/$tag.tar.gz|\ns|archive/[0-9]{8}[.][0-9]*[.]tar[.]gz|archive/$tag.tar.gz|\n#\ns|tags/[0-9]{4}[.][0-9]*[.][0-9]*>|tags/$tag>|\ns|tags/[0-9]{8}>|tags/$tag>|\ns|tags/[0-9]{8}[.][0-9]*>|tags/$tag>|\n#\ns|tags/[0-9]{4}[.][0-9]*[.][0-9]* *\\$|tags/$tag|\ns|tags/[0-9]{8} *\\$|tags/$tag|\ns|tags/[0-9]{8}[.][0-9]* *\\$|tags/$tag|\n#\nEOF\nfor file in $version_file_list\ndo\n    $sed -r -i $file -f temp.sed\ndone\n#\n# first_version_file\ncat << EOF > temp.sed\ns|([\"'])[0-9]{8}([\"'])|\\\\1$tag\\\\2|\ns|([\"'])[0-9]{8}[.][0-9]{1,2}([\"'])|\\\\1$tag\\\\2|\ns|([\"'])[0-9]{4}[.][0-9]{1,2}[.][0-9]{1,2}([\"'])|\\\\1$tag\\\\2|\nEOF\n$sed -r -f temp.sed -i $first_version_file\nif ! grep \"['\\\"]$tag['\\\"]\" $first_version_file > /dev/null\nthen\n    echo \"bin/rew_release: branch = $stable_branch\"\n    echo \"Version number should be $tag in $first_version_file\"\n    exit 1\nfi\n#\n# check_version\n# changes to version ?\nif ! bin/check_version.sh\nthen\n    echo 'Continuing even though bin/check_version made changes.'\n    if ! bin/check_version.sh\n    then\n        echo 'Continuing even though bin/check_version made more changes.'\n    fi\nfi\n#\n# check_all.sh\nif [ \"$skip_stable_check_all\" == 'no' ]\nthen\n    if [ \"$tag_committed\" == 'yes' ]\n    then\n        echo_eval bin/check_all.sh --suppress_spell_warnings\n    else\n        echo_eval bin/check_all.sh \\\n            --suppress_spell_warnings --skip_external_links\n    fi\nfi\n#\n# git_status\ngit_status=$(git status --porcelain)\nif [ \"$git_status\" != '' ]\nthen\n    echo \"bin/new_release: git status --porcelean not empty for $stable_branch\"\n    echo 'use bin/git_commit.sh to commit its changes ?'\n    exit 1\nfi\n# -----------------------------------------------------------------------------\n#\n# stable_remote\nif [ \"$stable_remote_hash\" == '' ]\nthen\n    empty_hash='yes'\n    echo \"bin/new_release: remote $stable_branch does not exist.\"\n    echo 'Use the following to create it ?'\n    echo \"   git push origin $stable_branch\"\n    exit 1\nfi\nif [ \"$stable_local_hash\" != \"$stable_remote_hash\" ]\nthen\n    empty_hash='yes'\n    echo \"bin/new_release: local and remote $stable_branch differ.\"\n    echo \"local  $stable_local_hash\"\n    echo \"remote $stable_remote_hash\"\n    echo 'Use git push to fix this ?'\n    exit 1\nfi\n#\n# push tag\nif [ \"$tag_committed\" == 'no' ]\nthen\n    read -p 'commit release or abort [c/a] ?' response\n    if [ \"$response\" == 'a' ]\n    then\n        exit 1\n    fi\n    echo \"git tag -a -m 'created by new_release.sh' $tag $stable_remote_hash\"\n    git tag -a -m 'created by new_release.sh' $tag $stable_remote_hash\n    #\n    echo \"git push origin $tag\"\n    git push origin $tag\n    #\n    echo 'bin/new_release.sh: must be re-run to check external links'\n    exit 1\nfi\n#\n# main_remote\ngit checkout $main_branch\nif [ \"$main_local_hash\" != \"$main_remote_hash\" ]\nthen\n    empty_hash='yes'\n    echo \"bin/new_release: local and remote $main_branch differ.\"\n    echo \"local  $main_local_hash\"\n    echo \"remote $main_remote_hash\"\n    echo 'Use git push to fix this ?'\n    exit 1\nfi\n# ----------------------------------------------------------------------------\necho 'bin/new_release.sh: OK'\nexit 0\n"
  },
  {
    "path": "bin/no_bitwise.sh",
    "content": "#! /usr/bin/env bash\nset -e -u\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2020-24 Bradley M. Bell\n# -----------------------------------------------------------------------------\nif [ \"$0\" != \"bin/no_bitwise.sh\" ]\nthen\n    echo \"bin/no_bitwise.sh: must be executed from its parent directory\"\n    exit 1\nfi\nif [ \"$#\" != 0 ]\nthen\n    echo 'bin/no_bitwise.sh: does not expect any arguments'\n    exit 1\nfi\n# ----------------------------------------------------------------------------\n# git reset --hard ?\nresponse=''\nwhile [ \"$response\" != 'yes' ] && [ \"$response\" != 'abort' ]\ndo\n    read -p 'git reset --hard [yes/abort] ?' response\ndone\nif [ \"$response\" == 'abort' ]\nthen\n    echo 'bin/no_bitwise.sh: aborted'\n    exit 1\nfi\ngit reset --hard\n#\n# sed.$$\ncat << EOF > sed.$$\ns/] *& *\\\\([a-z][a-z_]*\\\\)\\\\[/] \\\\&\\\\& \\\\1[/g\ns/] *| *\\\\([a-z][a-z_]*\\\\)\\\\[/] || \\\\1[/g\n#\ns/) *& *(/) \\\\&\\\\& (/g\ns/) *| *(/) || (/g\n#\ns/] *& *\\\\([!(]\\\\)/] \\\\&\\\\& \\\\1/g\ns/] *| *\\\\([!(]\\\\)/] || \\\\1/g\n#\ns/) *& *\\\\([A-Za-z][A-Za-z_]*[[(]\\\\)/) \\\\&\\\\& \\\\1/g\ns/) *| *\\\\([A-Za-z][A-Za-z_]*[[(]\\\\)/) || \\\\1/g\n#\ns/] *\\\\& *$/] \\\\&\\\\&/\ns/] | *$/] ||/\nEOF\n#\n# file_list\nfile_list=$(git ls-files | sed -n \\\n    -e '/\\.hpp$/p' \\\n    -e '/\\.cpp/p'\\\n    -e '/example[/]abs_normal[/]qp_interior.hpp/d'\n)\n#\n# *.hpp, *.cpp\n# replace bitwise operands on logicals by logical operations.\nfor file in $file_list\ndo\n    sed -i $file -f sed.$$\ndone\n#\n# sed.$$\nrm sed.$$\necho 'no_bitwise.sh: OK'\nexit 0\n# The script above was run on 2024-09021 following by the following commands:\n#\n# git_new.sh to\n# rm build/speed/cppad/*.out\n# bin/speed_new.sh all\n#\n# Here is the results:\n#\n#     one=cur, two=new\n# det_lu_rate_one = [ 1355694, 7815, 1052, 305.70, 132.33 ]\n# det_lu_rate_two = [ 1326588, 7668, 1031, 305.01, 128.91 ]\n# det_minor_rate_one = [ 780970, 449962, 154473, 33566, 5070 ]\n# det_minor_rate_two = [ 775970, 444017, 146952, 32100, 4839 ]\n# mat_mul_rate_one = [ 1633224, 5487, 750.39, 195.23, 75.93 ]\n# mat_mul_rate_two = [ 1646152, 5404, 733.41, 199.21, 74.30 ]\n# ode_rate_one = [ 275842, 1531, 430.16, 191.22, 113.16 ]\n# ode_rate_two = [ 274601, 1508, 428.69, 192.79, 113.09 ]\n# poly_rate_one = [ 1882647, 776135, 538845, 417875, 333869 ]\n# poly_rate_two = [ 1840832, 748291, 539711, 414037, 340217 ]\n# sparse_hessian_rate_one = [ 475.58, 41.42, 7.5392, 2.1304, 0.8436 ]\n# sparse_hessian_rate_two = [ 478.50, 38.16, 7.6061, 2.1297, 0.9010 ]\n# sparse_jacobian_rate_one = [ 1434, 332.37, 124.84, 35.39, 21.27 ]\n# sparse_jacobian_rate_two = [ 1522, 338.94, 119.77, 34.85, 20.94 ]\n"
  },
  {
    "path": "bin/package.sh",
    "content": "#! /bin/bash -e\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-25 Bradley M. Bell\n# ----------------------------------------------------------------------------\nif [ \"$0\" != \"bin/package.sh\" ]\nthen\n    echo \"bin/package.sh: must be executed from its parent directory\"\n    exit 1\nfi\necho_eval() {\n      echo $*\n      eval $*\n}\n# grep, sed\nsource bin/grep_and_sed.sh\n# -----------------------------------------------------------------------------\n#\n# version\nversion=`$sed -n -e '/^SET( *cppad_version *\"[0-9.]*\"/p' CMakeLists.txt | \\\n    $sed -e 's|.*\"\\([^\"]*\\)\".*|\\1|'`\n#\n# build\nif [ ! -e 'build' ]\nthen\n    echo_eval mkdir build\nfi\n#\n# build/cppad-version\nif ls build/cppad-* >& /dev/null\nthen\n    echo_eval rm -r build/cppad-*\nfi\nmkdir build/cppad-$version\ngit ls-files -z | xargs -0 tar -czf build/cppad-$version/tar.tgz\ncd build/cppad-$version\ntar -xzf tar.tgz\nrm tar.tgz\n#\n# build/cppad-$version.tgz\ncd ..\necho_eval tar -czf cppad-$version.tgz cppad-$version\necho_eval rm -r cppad-$version\n#\necho 'package.sh: OK'\nexit 0\n"
  },
  {
    "path": "bin/run_cmake.sh",
    "content": "#! /usr/bin/env bash\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-25 Bradley M. Bell\n# ----------------------------------------------------------------------------\nset -e -u\necho $0 $*\n# ----------------------------------------------------------------------------\nif [ ! -e \"bin/run_cmake.sh\" ]\nthen\n    echo \"bin/run_cmake.sh: must be executed from its parent directory\"\n    exit 1\nfi\n# -----------------------------------------------------------------------------\n# bash function that echos and executes a command\necho_eval() {\n    echo $*\n    eval $*\n}\n# -----------------------------------------------------------------------------\nverbose_make='no'\nstandard='c++17'\nm32='no'\nprofile_speed='no'\ncallgrind='no'\nclang='no'\nstatic='no'\nyes_adolc='yes'\nyes_colpack='yes'\nyes_ipopt='yes'\nyes_fadbad='yes'\nyes_cppad_jit='yes'\nyes_cppadcg='yes'\nyes_sacado='yes'\nyes_documentation='yes'\naddr_t_type='int'\ntestvector='boost'\ndebug_which='debug_all'\nwhile [ \"$#\" != 0 ]\ndo\n    if [ \"$1\" == '--help' ]\n    then\n        cat << EOF\nusage: bin/run_cmake.sh: \\\\\n    [--help] \\\\\n    [--verbose_make] \\\\\n    [--c++11] \\\\\n    [--m32] \\\\\n    [--profile_speed] \\\\\n    [--callgrind] \\\\\n    [--clang ] \\\\\n    [--static] \\\\\n    [--no_adolc] \\\\\n    [--no_colpack] \\\\\n    [--no_ipopt] \\\\\n    [--no_fadbad] \\\\\n    [--no_cppad_jit] \\\\\n    [--no_cppadcg] \\\\\n    [--no_sacado] \\\\\n    [--no_optional] \\\\\n    [--no_documentation] \\\\\n    [--addr_t_<type>] \\\\\n    [--<package>_vector] \\\\\n    [--debug_<which>]\nThe --help option just prints this message and exits.\nThe value <package> above must be one of: cppad, boost, eigen, or std.\nThe value <which> must be one of: odd, even, all, none.\nThe value <type> must be one of: size_t, int, unsigned_int\n\nEOF\n        exit 0\n    fi\n    case \"$1\" in\n\n        --verbose_make)\n        verbose_make='yes'\n        ;;\n\n        --c++11)\n        standard='c++11'\n        ;;\n\n        --m32)\n        m32='yes'\n        ;;\n\n        --profile_speed)\n        profile_speed='yes'\n        ;;\n\n        --callgrind)\n        callgrind='yes'\n        ;;\n\n        --clang)\n        clang='yes'\n        ;;\n\n        --static)\n        static='yes'\n        ;;\n\n        --no_adolc)\n        yes_adolc='no'\n        ;;\n\n        --no_colpack)\n        yes_colpack='no'\n        ;;\n\n        --no_ipopt)\n        yes_ipopt='no'\n        ;;\n\n        --no_cppadcg)\n        yes_cppadcg='no'\n        ;;\n\n        --no_cppad_jit)\n        yes_cppad_jit='no'\n        ;;\n\n        --no_fadbad)\n        yes_fadbad='no'\n        ;;\n\n        --no_sacado)\n        yes_sacado='no'\n        ;;\n\n        --no_optional)\n        yes_adolc='no'\n        yes_colpack='no'\n        yes_ipopt='no'\n        yes_cppadcg='no'\n        yes_fadbad='no'\n        yes_sacado='no'\n        testvector='cppad'\n        ;;\n\n        --no_documentation)\n        yes_documentation='no'\n        ;;\n\n        # ----------------------------------------------------------------------\n        --addr_t_size_t)\n        addr_t_type='size_t'\n        ;;\n\n        --addr_t_int)\n        addr_t_type='int'\n        ;;\n\n        --addr_t_unsigned_int)\n        addr_t_type='unsigned int'\n        ;;\n\n        # ----------------------------------------------------------------------\n        --cppad_vector)\n        testvector='cppad'\n        ;;\n\n        --boost_vector)\n        testvector='boost'\n        ;;\n\n        --eigen_vector)\n        testvector='eigen'\n        ;;\n\n        --std_vector)\n        testvector='std'\n        ;;\n\n        # ----------------------------------------------------------------------\n        --debug_odd)\n        debug_which='debug_odd'\n        ;;\n\n        --debug_even)\n        debug_which='debug_even'\n        ;;\n\n        --debug_all)\n        debug_which='debug_all'\n        ;;\n\n        --debug_none)\n        debug_which='debug_none'\n        ;;\n\n        # ----------------------------------------------------------------------\n        *)\n        echo \"$1 is an invalid option, try bin/run_cmake.sh --help\"\n        exit 1\n    esac\n    shift\ndone\nif [ \"$standard\" == 'c++11' ]\nthen\n    # Scacdo cannot be used with c++11\n    if [ \"$yes_sacado\" == 'yes' ]\n    then\n        echo 'Cannot use sacado with c++11'\n        exit 1\n    fi\nfi\n# -----------------------------------------------------------------------------\n# prefix\neval `grep '^prefix=' bin/get_optional.sh`\nif [[ \"$prefix\" =~ ^[^/] ]]\nthen\n    prefix=\"$(pwd)/$prefix\"\nfi\necho \"prefix=$prefix\"\n# -----------------------------------------------------------------------------\n# PKG_CONFIG_PATH\nPKG_CONFIG_PATH=\"$prefix/share/pkgconfig\"\nfor libdir in lib lib64\ndo\n    PKG_CONFIG_PATH+=\":$prefix/$libdir/pkgconfig\"\ndone\nexport PKG_CONFIG_PATH\n# ---------------------------------------------------------------------------\nif [ ! -e build ]\nthen\n    echo_eval mkdir build\nfi\necho_eval cd build\nfor name in CMakeCache.txt build.ninja Makefile\ndo\n    if [ -e $name ]\n    then\n        echo_eval rm -r $name\n    fi\ndone\n# -----------------------------------------------------------------------------\n# clean all variables in cmake cache\ncmake_args='-U .+ -D cmake_defined_ok=FALSE'\n# -----------------------------------------------------------------------------\n# Generator\nif [ \"$verbose_make\" == 'yes' ]\nthen\n    cmake_args+=\"  -G 'Unix Makefiles' -D CMAKE_VERBOSE_MAKEFILE=YES\"\nelse\n    cmake_args+=\"  -G Ninja\"\nfi\n# -----------------------------------------------------------------------------\n# cppad_prefix\ncmake_args+=\"  -D cppad_prefix=$prefix\"\n#\n# cmake_install_includedirs\nif [ -d '/usr/include' ]\nthen\n    cmake_args+=\" -D cmake_install_includedirs=include\"\nfi\n#\n# cmake_install_datadir\nif [ -d '/usr/share' ]\nthen\n    cmake_args+=\" -D cmake_install_datadir=share\"\nfi\n#\n# cmake_install_docdir\nif [ -d '/usr/share' ] && [ \"$yes_documentation\" == 'yes' ]\nthen\n    cmake_args+=\" -D cmake_install_docdir=share/doc\"\n    cmake_args+=\" -D include_doc=true\"\nfi\n#\n# cmake_install_libdirs\nif [ -d '/usr/lib64' ]\nthen\n    cmake_args+=\" -D cmake_install_libdirs='lib64;lib'\"\nelif [ -d '/usr/lib' ]\nthen\n    cmake_args+=\" -D cmake_install_libdirs='lib;lib64'\"\nfi\n#\n# {package}_prefix\nprefix_list=''\ninclude_list=''\nif [ \"$yes_cppadcg\" == 'yes' ]\nthen\n    if [ ! -e \"$prefix/include/cppad/cg/cg.hpp\" ]\n    then\n        echo \"Cannot find $prefix/include/cppad/cg/cg.hpp\"\n        exit 1\n    fi\n    include_list+=\" cppadcg\"\nfi\nif [ \"$yes_fadbad\" == 'yes' ]\nthen\n    if [ ! -e \"$prefix/include/FADBAD++/badiff.h\" ]\n    then\n        echo \"Cannot find $prefix/include/FADBAD++/badiff.h\"\n        exit 1\n    fi\n    prefix_list+=\" fadbad\"\nfi\nif [ \"$yes_adolc\" == 'yes' ]\nthen\n    if [ ! -d \"$prefix/include/adolc\" ]\n    then\n        echo \"Cannot file $prefix/include/adolc\"\n        exit 1\n    fi\n    include_list+=\" adolc\"\nfi\nif [ \"$yes_colpack\" == 'yes' ]\nthen\n    if [ ! -e \"$prefix/include/ColPack\" ]\n    then\n        echo \"Cannot find $prefix/include/ColPack\"\n        exit 1\n    fi\n    prefix_list+=\" colpack\"\nfi\nif [ \"$yes_ipopt\" == 'yes' ]\nthen\n    if [ ! -e \"$prefix/include/coin-or/IpNLP.hpp\" ]\n    then\n        echo \"Cannot find $prefix/include/coin-or/IpoptConfig.hpp\"\n        exit 1\n    fi\n    include_list+=\" ipopt\"\nfi\nif [ \"$yes_sacado\" == 'yes' ]\nthen\n    if [ ! -e \"$prefix/include/Sacado_config.h\" ]\n    then\n        echo \"Cannot find $prefix/include/Sacado_config.h\"\n        exit\n    fi\n    prefix_list+=\" sacado\"\nfi\nfor package in $include_list\ndo\n    cmake_args+=\" -D include_${package}=true\"\ndone\nfor package in $prefix_list\ndo\n    cmake_args+=\"  -D ${package}_prefix=$prefix\"\ndone\n#\n# cppad_link_flags\nif [ \"$m32\" == 'yes' ]\nthen\n    cmake_args+=\" -D cppad_link_flags=-m32\"\nfi\n#\n# cppad_cxx_flags\nif [ \"$m32\" == 'yes' ]\nthen\n    cppad_cxx_flags=\"-std=$standard -m32\"\nelse\n    cppad_cxx_flags=\"-std=$standard\"\nfi\ncppad_cxx_flags+=' -Wall -pedantic-errors -Wshadow'\ncppad_cxx_flags+=' -Wfloat-conversion -Wconversion'\nif [ \"$debug_which\" == 'debug_all' ]\nthen\n    # CMAKE_CXX_FLAGS_DEBUG include -g so do not need it here\n    cppad_cxx_flags+=\" -O0\"\nelif [ \"$callgrind\" == 'yes' ]\nthen\n    # This is a quote from the Callgrind manual:\n    # 'As with Cachegrind, you probably want to compile with debugging info\n    # (the -g option) and with optimization turned on.'\n    cppad_cxx_flags+=\" -g\"\nfi\nif [ \"$(uname)\" == 'Darwin' ]\nthen\n    if which brew > /dev/null\n    then\n        cppad_cxx_flags+=\" -I $(brew --prefix)/include\"\n    fi\nfi\n#\n# cmake_args\ncmake_args+=\" -D cppad_cxx_flags='$cppad_cxx_flags'\"\n#\n# clang\nif [ \"$clang\" == 'yes' ]\nthen\n    cmake_args+=\" -D CMAKE_C_COMPILER=clang\"\n    cmake_args+=\" -D CMAKE_CXX_COMPILER=clang++\"\nfi\n#\n# static\nif [ \"$static\" == 'yes' ]\nthen\n    cmake_args+=\" -D cppad_static_lib=true\"\nfi\n#\n# profile\nif [ \"$profile_speed\" == 'yes' ]\nthen\n    cmake_args+=\" -D cppad_profile_flag=-pg\"\nfi\n#\n# debug_and_release\nif [ \"$debug_which\" == 'debug_none' ] || [ \"$debug_which\" == 'debug_all' ]\nthen\n    cmake_args+=\" -D cppad_debug_and_release=false\"\nfi\n#\n# simple options\ncmake_args+=\" -D cppad_testvector=$testvector\"\ncmake_args+=\" -D cppad_debug_which=$debug_which\"\ncmake_args+=\" -D cppad_max_num_threads=48\"\ncmake_args+=\" -D cppad_tape_id_type='$addr_t_type'\"\ncmake_args+=\" -D cppad_tape_addr_type='$addr_t_type'\"\n#\necho_eval cmake $cmake_args ..\n#\n# ----------------------------------------------------------------------------\necho \"$0: OK\"\nexit 0\n"
  },
  {
    "path": "bin/run_configure.sh",
    "content": "#! /usr/bin/env bash\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\nset -e -u\necho $0 $*\n# ----------------------------------------------------------------------------\nif [ ! -e \"bin/run_configure.sh\" ]\nthen\n    echo \"bin/run_configure.sh: must be executed from its parent directory\"\n    exit 1\nfi\n# -----------------------------------------------------------------------------\nwith_clang=''\nwith_verbose_make=''\ncpp_standard='c++17'\nwith_vector=''\nwhile [ \"$#\" != '0' ]\ndo\n    if [ \"$1\" == '--help' ]\n    then\n        cat << EOF\nusage: bin/run_configure.sh \\\\\n    [--help] \\\\\n    [--clang] \\\\\n    [--verbose_make] \\\\\n    [--c++<yy> ] \\\\\n    [--<package>_vector]\nThe value yy is two decimal digits specifying the C++ standard year.\nThe value <package> must be one of: cppad, boost, eigen, std.\n\nEOF\n        exit 0\n    fi\n    case \"$1\" in\n\n        --clang)\n        with_clang='--with-clang'\n        ;;\n\n        --verbose_make)\n        with_verbose_make='--with-verbose-make'\n        ;;\n\n        --c++*)\n        cpp_standard=$(echo \"$1\" | sed -e 's|^--||')\n        ;;\n\n        --cppad_vector)\n        with_vector=''\n        ;;\n\n        --boost_vector)\n        with_vector='--with-boostvector'\n        ;;\n\n        --eigen_vector)\n        with_vector='--with-eigenvector'\n        ;;\n\n        --std_vector)\n        with_vector='--with-stdvector'\n        ;;\n\n        *)\n        echo \"$1 is an invalid option, try bin/run_configure.sh --help\"\n        exit 1\n\n    esac\n    shift\ndone\n# -----------------------------------------------------------------------------\n# bash function that echos and executes a command\necho_eval() {\n    echo $*\n    eval $*\n}\n# -----------------------------------------------------------------------------\n# prefix\neval `grep '^prefix=' bin/get_optional.sh`\nif [[ \"$prefix\" =~ ^[^/] ]]\nthen\n    prefix=\"$(pwd)/$prefix\"\nfi\necho \"prefix=$prefix\"\n# -----------------------------------------------------------------------------\n#\n# PKG_CONFIG_PATH\nPKG_CONFIG_PATH=\"$prefix/lib64/pkgconfig:$prefix/lib/pkgconfig\"\nPKG_CONFIG_PATH=\"$prefix/share/pkgconfig:$PKG_CONFIG_PATH\"\nexport PKG_CONFIG_PATH\n#\n# cppad_cxx_flags\ncppad_cxx_flags=\"-std=$cpp_standard -Wall -pedantic-errors -Wshadow\"\ncppad_cxx_flags+=\" -Wfloat-conversion -Wconversion\"\nif [ \"$(uname)\" == 'Darwin' ]\nthen\n    if which brew > /dev/null\n    then\n        cppad_cxx_flags+=\" -I $(brew --prefix)/include\"\n    fi\nfi\n# 2DO: clang++ 14.05 is generating a lot of warnings (we should fix these)\n#\n# scaado_prefix\ncxx_standard_year=$(echo $cpp_standard | sed -e 's|c++||')\nif [ \"$cxx_standard_year\" -lt 17 ]\nthen\n    scaado_prefix=''\nelse\n    scaado_prefix=\"SACADO_DIR=$prefix\"\nfi\n#\n# ---------------------------------------------------------------------------\nif [ ! -e build ]\nthen\n    echo_eval mkdir build\nfi\necho_eval cd build\n# -----------------------------------------------------------------------------\n../configure \\\n    --prefix=$prefix \\\n    $with_clang \\\n    $with_verbose_make \\\n    $with_vector \\\n    MAX_NUM_THREADS=32 \\\n    CXX_FLAGS=\"'$cppad_cxx_flags'\" \\\n    ADOLC_DIR=$prefix \\\n    FADBAD_DIR=$prefix \\\n    IPOPT_DIR=$prefix \\\n    $scaado_prefix \\\n    TAPE_ADDR_TYPE=size_t \\\n    TAPE_ID_TYPE=size_t\n# ----------------------------------------------------------------------------\necho \"$0: OK\"\nexit 0\n"
  },
  {
    "path": "bin/run_doxygen.sh",
    "content": "#! /bin/bash -e\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\nif [ $0 != 'bin/run_doxygen.sh' ]\nthen\n    echo 'bin/run_doxygen.sh: must be executed from its parent directory'\n    exit 1\nfi\necho_eval() {\n      echo $*\n      eval $*\n}\n# -----------------------------------------------------------------------------\n# run doxygen\nversion=`version.sh get`\nerror_file='doxygen.err'\noutput_directory='doxydoc'\nfor name in doxyfile $error_file $output_directory\ndo\n    if [ -e $name ]\n    then\n        echo_eval rm -r $name\n    fi\ndone\necho_eval mkdir doxydoc\necho_eval bin/doxyfile.sh $version $error_file $output_directory\n#\necho 'doxygen doxyfile > doxygen.log'\ndoxygen doxyfile       > doxygen.log\n# -----------------------------------------------------------------------------\n# check for warnings and errors\n#\ndoxygen_version=`doxygen --version  |\n    sed -e 's|\\.|*100+|' -e 's|\\.|*10+|' -e 's|\\..*||'`\nlet doxygen_version=$doxygen_version\nif (( $doxygen_version <= 155 ))\nthen\n    doxygen_version=`doxygen --version`\n    echo \"doxygen version $doxygen_version is <= 1.5.6\"\n    echo \"Hence it is to old to check for warnings or errors.\"\n    exit 0\nfi\nif (( $doxygen_version == 163 ))\nthen\n    doxygen_version=`doxygen --version`\n    echo \"doxygen version $doxygen_version is == 1.6.3\"\n    echo \"Hence it has a problem with warnings about missing # defines;\"\n    echo \"see http://comments.gmane.org/gmane.text.doxygen.general/8594\"\n    exit 0\nfi\nlist=`head doxygen.err`\nif [ \"$list\" == \"\" ]\nthen\n    echo 'run_doxygen.sh OK'\n    exit 0\nfi\necho 'bin/run_doxygen.sh: Doxygen errors or warnings; see doxygen.err'\necho 'run_doxygen.sh: Error'\nexit 1\n"
  },
  {
    "path": "bin/run_xrst.sh",
    "content": "#! /usr/bin/env bash\nset -e -u\n# !! EDITS TO THIS FILE ARE LOST DURING UPDATES BY xrst.git/bin/dev_tools.sh !!\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2020-25 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# bin/run_xrst.sh flags\n# possible flags\n# --help                     print the run_xrst.sh help message\n# --target_tex               create tex (instead of html) files\n# --exclude_dev              exclude developer documentation\n# --suppress_spell_warnings  do not check for documentation spelling errors\n# --rst_line_numbers         sphinx errors and warnings use rst line numbers\n# --replace_spell_commands   replace xrst_spell commands assuming no errors\n# --external_links           check documentation external links\n#\n# xrst.toml\n# The group_list argument will be automatically extracted from xrst.toml\n#\n# .readthedocs\n# The index_page_name will be automatically extracted from .readthedocs.yaml\n# ----------------------------------------------------------------------------\n# bash function that echos and executes a command\necho_eval() {\n    echo $*\n    eval $*\n}\n#\n# grep, sed\nsource bin/grep_and_sed.sh\n#\n# index_page_name\nsource bin/dev_settings.sh\n# -----------------------------------------------------------------------------\nif [ \"$0\" != 'bin/run_xrst.sh' ]\nthen\n    echo 'bin/run_xrst.sh must be run from its parent directory.'\n    exit 1\nfi\nif [ $# == 1 ]\nthen\n    if [ \"$1\" == --help ]\n    then\ncat << EOF\nbin/run_xrst.sh flags\npossible flags\n--help                     print the run_xrst.sh help message\n--target_tex               create tex (instead of html) files\n--exclude_dev              exclude developer documentation (group dev)\n--suppress_spell_warnings  do not check for documentation spelling errors\n--rst_line_numbers         sphinx errors and warnings use rst line numbers\n--replace_spell_commands   replace xrst_spell commands assuming no errors\n--external_links           check documentation external links\nEOF\n        exit 0\n    fi\nfi\n#\n# exclude_dev, extra_flags\ntarget_tex='no'\nexclude_dev='no'\nextra_flags=''\nwhile [ $# != 0 ]\ndo\n    case \"$1\" in\n\n        --target_tex)\n        target_tex='yes'\n        ;;\n\n        --exclude_dev)\n        exclude_dev='yes'\n        ;;\n\n        --suppress_spell_warnings)\n        extra_flags+=\" $1\"\n        ;;\n\n        --external_links)\n        extra_flags+=\" $1 --link_timeout 5\"\n        ;;\n\n        *)\n        echo \"bin/run_xrst.sh: command line argument \"$1\" is not valid\"\n        exit 1\n        ;;\n\n    esac\n    #\n    shift\ndone\n#\n# extra_flags\nif [ \"$target_tex\" == 'yes' ]\nthen\n    extra_flags+=' --target tex'\nelse\n    extra_flags+=' --target html'\nfi\n#\n# build/html\nif [ -e build/html ]\nthen\n    rm -r build/html\nfi\n#\n# group_list\ngroup_list=$(bin/group_list.sh | $sed -e 's|^| |' -e 's|$| |' )\nif [ \"$exclude_dev\" == 'yes' ]\nthen\n    group_list=$( echo \"$group_list\" | $sed -e 's| dev | |' )\nfi\ngroup_list=$( echo $group_list | $sed -e 's|^ *||' -e s'| *$||' )\n#\n# n_job\nif which nproc >& /dev/null\nthen\n    n_job=$(nproc)\nelse\n    n_job=$(sysctl -n hw.ncpu)\nfi\n#\n# xrst\n# python3 -m will search the current working directory first\necho_eval python3 -m xrst \\\n    --local_toc \\\n    --html_theme sphinx_rtd_theme \\\n    --index_page_name $index_page_name \\\n    --group_list $group_list \\\n    --number_jobs $n_job \\\n    $extra_flags\n# -----------------------------------------------------------------------------\necho 'run_xrst.sh: OK'\nexit 0\n"
  },
  {
    "path": "bin/sort.sh",
    "content": "#! /usr/bin/env bash\nset -e -u\n# !! EDITS TO THIS FILE ARE LOST DURING UPDATES BY xrst.git/bin/dev_tools.sh !!\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2023-25 Bradley M. Bell\n# -----------------------------------------------------------------------------\n# bin/sort.sh file_name\n# Checks all the sections between\n#  BEGIN_SORT_THIS_LINE_PLUS_#\n#  END_SORT_THIS_LINE_MINUS_#\n# in file_name are sorted. If not, it is corrected and an error is returned.\n# -----------------------------------------------------------------------------\n# fix sort order; see\n# unix.stackexchange.com/questions/87745/what-does-lc-all-c-do/87763#87763\nexport LC_ALL='C'\n#\nif [ \"$#\" == 0 ]\nthen\ncat<< EOF\nusage: sort.sh file_name\nBEGIN_SORT_THIS_LINE_PLUS_nb: defines beginning line for sort.\nEND_SORT_THIS_LINE_MINUS_ne:  defines ending line for sort.\nThe tokens nb and ne are both a single non-zero decimal digit.\n\nIf the exit status is 0, the last line on standard out is one of the following:\n'sort.sh: OK'    The file was already sorted\n'sort.sh: Done'  The file was sorted\nEOF\n    exit 1\nfi\nfile_name=\"$1\"\n#\n# grep, sed\nsource bin/grep_and_sed.sh\n#\nif $grep 'BEGIN_SORT_THIS_LINE_PLUS_[1-9][0-9]' \"$file_name\"\nthen\n    echo \"in BEGIN_SORT_THIS_LINE_PLUS_nb in file $file_name\"\n    echo 'nb has more that one decial digit.'\n    exit 1\nfi\nif $grep 'END_SORT_THIS_LINE_MINUS_[1-9][0-9]' \"$file_name\"\nthen\n    echo \"in END_SORT_THIS_LINE_PLUS_ne in file $file_name\"\n    echo 'ne has more that one decial digit.'\n    exit 1\nfi\n# --------------------------------------------------------------------------\n#\n# is_file_executable\nif [ -x $file_name ]\nthen\n    is_file_executable='yes'\nelse\n    is_file_executable='no'\nfi\n#\n# begin_sum\n# is th sum for the beginning line number\nset +e\nbegin_sum=`$grep --line-number 'BEGIN_SORT_THIS_LINE_PLUS_[1-9]' $file_name | \\\n    $sed -e 's|\\([0-9]*\\):.*BEGIN_SORT_THIS_LINE_PLUS_\\([1-9]\\).*|\\1+\\2|'`\nset -e\nif [ \"$begin_sum\" == '' ]\nthen\n    echo \"sort.sh $file_name\"\n    echo \"Cannot find BEGIN_SORT_THIS_LINE_PLUS_nb in $file_name\"\n    exit 1\nfi\n#\n# begin_line\nbegin_count=0\nfor sum in $begin_sum\ndo\n    # This does the summation\n    let begin_line[$begin_count]=\"$sum\"\n    let begin_count=\"$begin_count + 1\"\ndone\n#\n# end_diff\n# ios the difference for the ending line number\nset +e\nend_diff=`$grep --line-number 'END_SORT_THIS_LINE_MINUS_[1-9]' $file_name | \\\n    $sed -e 's|\\([0-9]*\\):.*END_SORT_THIS_LINE_MINUS_\\([1-9]\\).*|\\1-\\2|'`\nset -e\nif [ \"$end_diff\" == '' ]\nthen\n    echo \"sort.sh $file_name\"\n    echo \"Cannot find END_SORT_THIS_LINE_MINUS_nb in $file_name\"\n    exit 1\nfi\n#\n# end_line\nend_count=0\nfor diff in $end_diff\ndo\n    # This does the difference\n    let end_line[$end_count]=\"$diff\"\n    let end_count=\"$end_count + 1\"\ndone\nif [ $begin_count != $end_count ]\nthen\n    echo \"sort.sh $file_name\"\n    echo 'number of BEGIN_SORT_THIS_LINE_PLUS_nb is not equal to'\n    echo 'number of END_SORT_THIS_LINE_MINUS_ne.'\n    exit 1\nfi\n#\n# first_line\nfirst_line='1'\n#\n# last_line\nlast_line=`wc -l $file_name | $sed -e 's|^ *\\([0-9]*\\) .*|\\1|'`\n#\n# count, stop_line_previous, sorted.$$\ncount=0\nstop_line_previous=0\ncp $file_name sorted.$$\nwhile [ $count -lt $begin_count ]\ndo\n    #\n    # start_line, stop_line, count\n    start_line=${begin_line[$count]}\n    stop_line=${end_line[$count]}\n    let count=\"$count + 1\"\n    echo \"sort.sh: sorting lines $start_line to $stop_line in $file_name\"\n    #\n    if [ $start_line -gt $stop_line ]\n    then\n        echo \"start_line = $start_line >= stop_line = $stop_line \"\n        rm sorted.$$\n        exit 1\n    fi\n    #\n    # stop_line_previous\n    if [ $stop_line_previous -ge $start_line ]\n    then\n        echo \"previous stop_line=$stop_line_previous >= start_line=$start_line\"\n        rm sorted.$$\n        exit 1\n    fi\n    stop_line_previous=\"$stop_line\"\n    #\n    # temp.$$\n    if [ \"$start_line\" != \"$first_line\" ]\n    then\n        let start_m1=\"$start_line - 1\"\n        $sed -n -e \"1,${start_m1}p\" sorted.$$ >> temp.$$\n    fi\n    #\n    $sed -n -e \"${start_line},${stop_line}p\" sorted.$$ | sort >> temp.$$\n    #\n    if [ \"$stop_line\" != \"$last_line\" ]\n    then\n        stop_p1=`expr $stop_line + 1`\n        $sed -n -e \"${stop_p1},${last_line}p\" sorted.$$ >> temp.$$\n    fi\n    #\n    # sorted.$$\n    mv temp.$$ sorted.$$\ndone\nif diff sorted.$$ $file_name > /dev/null\nthen\n    rm sorted.$$\n    echo 'sort.sh: OK'\nelse\n    mv sorted.$$ $file_name\n    if [ \"$is_file_executable\" == 'yes' ]\n    then\n        chmod +x $file_name\n    fi\n    echo 'sort.sh: Done'\nfi\nexit 0\n"
  },
  {
    "path": "bin/speed_branch.sh",
    "content": "#! /bin/bash -e\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-23 Bradley M. Bell\n# ----------------------------------------------------------------------------\npossible_tests='\n    all\n    det_lu\n    det_minor\n    mat_mul ode\n    poly\n    sparse_hessian\n    sparse_jacobian\n'\npossible_options='\n    atomic\n    boolsparsity\n    colpack\n    memory\n    onetape\n    optimize\n    revsparsity\n    subgraph\n'\n# ----------------------------------------------------------------------------\nprogram=\"bin/speed_branch.sh\"\nif [ \"$0\" != \"$program\" ]\nthen\n    echo \"$program: must be executed from its parent directory\"\n    exit 1\nfi\nbranch_start=$(git branch --show-current)\nif [ \"$branch_start\" != 'master' ] && [ \"$branch_start\" != 'main' ]\nthen\n    echo 'bin/speed_branch.sh: must start from master or main branch'\n    exit 1\nfi\nif [ \"$3\" == '' ]\nthen\ntests=`echo $possible_tests | sed -e 's|\\n||' -e 's|\\t| |'`\noptions=`echo $possible_options | sed -e 's|\\n||' -e 's|\\t| |'`\ncat << EOF\nusage:\n$program branch_one branch_two test_name [option_1] [option_2] ...\n\npossible tests are:\n$tests\n\npossible options are:\n$options\nEOF\n    exit 1\nfi\n#\nbranch_one=\"$1\"\nshift\nbranch_two=\"$1\"\nshift\ntest_name=\"$1\"\nif ! echo \"$possible_tests\" | grep \"$test_name\" > /dev/null\nthen\n    echo \"speed_branch.sh: $test_name is not a valid test name\"\n    exit 1\nfi\nshift\noption_list=\"$test_name\"\nfor option in $*\ndo\n    if ! echo $possible_options | grep \"$option\" > /dev/null\n    then\n        echo \"speed_branch.sh: $option is not a valid option\"\n        exit 1\n    fi\n    option_list=\"${option_list}_$option\"\ndone\nif [ \"$test_name\" == 'all' ]\nthen\n    test_name='speed'\nfi\n# ----------------------------------------------------------------------------\n# bash function that echos and executes a command\necho_eval() {\n    echo $*\n    eval $*\n}\n# -----------------------------------------------------------------------------\nif [ ! -d '.git' ]\nthen\n    echo \"$program: only implemented for git repository\"\n    exit 1\nfi\n# ----------------------------------------------------------------------------\ntarget_dir='build/speed/cppad'\nif [ ! -e $target_dir ]\nthen\n    echo_eval mkdir -p $target_dir\nfi\n# -----------------------------------------------------------------------------\nfor branch in $branch_one $branch_two\ndo\n    # for stable branches, remove stable/ from output file name\n    out_file=`echo $branch.$option_list.out | sed -e 's|stable/||'`\n    log_file=`echo $branch.log | sed -e 's|stable/||'`\n    #\n    if [ -e \"$target_dir/$out_file\" ]\n    then\n        echo \"Using existing $target_dir/$out_file\"\n    else\n        # use --quiet to suppress detached HEAD message\n        echo_eval git checkout --quiet $branch\n        #\n        # speed/main.cpp\n        echo \"git show $branch_start:speed/main.cpp > speed/main.cpp\"\n        git show $branch_start:speed/main.cpp > speed/main.cpp\n        #\n        day=`git log -1 --date=iso | grep '^Date:' | \\\n            sed -e 's|Date: *||' -e 's|-||g' -e 's| .*||'`\n        if [ \"$test_name\" == 'speed' ] || [ \"$test_name\" == 'sparse_hessian' ]\n        then\n            if [ \"$day\" -le '20150130' ]\n            then\n                echo \"test_name is all or sparse_hessian\"\n                echo \"and branch $branch came on or before 20150130\"\n                echo \"when bug was fixed in the sparse_hessian speed test.\"\n                exit 1\n            fi\n        fi\n        #\n        echo \"bin/run_cmake.sh --debug_none --no_optional >& $target_dir/$log_file\"\n        bin/run_cmake.sh --debug_none --no_optional >& $target_dir/$log_file\n        #\n        echo \"ninja check_speed_cppad >>& $target_dir/$log_file\"\n        ninja -C build check_speed_cppad >& speed_branch.log.$$\n        #\n        cat speed_branch.log.$$ >> $target_dir/$log_file\n        rm speed_branch.log.$$\n        #\n        echo \"$target_dir/speed_cppad $test_name 123 $* > $target_dir/$out_file\"\n        $target_dir/speed_cppad $test_name 123 $* > $target_dir/$out_file\n        #\n        # speed/main.cpp\n        echo_eval git checkout speed/main.cpp\n    fi\ndone\n# return to master (branch where we started)\necho_eval git checkout --quiet master\n#\n# compare the results\necho \"    one=$branch_one , two=$branch_two\"\nout_file_one=`echo $branch_one.$option_list.out | sed -e 's|stable/||'`\nout_file_two=`echo $branch_two.$option_list.out | sed -e 's|stable/||'`\nbin/speed_diff.sh $target_dir/$out_file_one $target_dir/$out_file_two\n# ----------------------------------------------------------------------------\necho \"$0: OK\"\nexit 0\n"
  },
  {
    "path": "bin/speed_diff.sh",
    "content": "#! /bin/bash -e\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-23 Bradley M. Bell\n# ----------------------------------------------------------------------------\nif [ \"$0\" != 'bin/speed_diff.sh' ]\nthen\n    echo 'bin/speed_diff.sh: must be executed from its parent directory'\n    exit 1\nfi\nif [ \"$2\" == '' ]\nthen\ncat << EOF\nusage: bin/speed_diff.sh speed_one.out speed_two.out\nwhere speed_one.out and speed_two.out are outputs from the speed_cppad program\nrunning its 'speed' test.\nEOF\n    exit 1\nfi\nspeed_one=\"$1\"\nspeed_two=\"$2\"\nif [ ! -f \"$speed_one\" ]\nthen\n    echo \"speed_diff.sh: the file $speed_one does not exist.\"\n    exit 1\nfi\nif [ ! -f \"$speed_two\" ]\nthen\n    echo \"speed_diff.sh: the file $speed_two does not exist.\"\n    exit 1\nfi\n#\n# ---------------------------------------------------------------------------\nsed -n -e'/_size *=/p' $speed_one | sort -u > speed_diff.1.$$\nsed -n -e'/_size *=/p' $speed_two | sort -u > speed_diff.2.$$\nif ! diff speed_diff.1.$$ speed_diff.2.$$\nthen\n    echo 'The sizes above do not agree'\n    echo \"< for $speed_one\"\n    echo \"> for $speed_two\"\n    rm speed_diff.1.$$ speed_diff.2.$$\n    exit 1\nfi\nrm speed_diff.1.$$ speed_diff.2.$$\n# ---------------------------------------------------------------------------\n#\nsed -n \\\n    -e 's|^[a-z]*_||' \\\n    -e 's|_rate|_rate_one|' -e '/_rate_one/p' \\\n    -e 's|available|available_one|' -e '/available_one/p' \\\n    $speed_one > speed_diff.$$\n#\nsed -n \\\n    -e 's|^[a-z]*_||' \\\n    -e 's|_rate|_rate_two|' -e '/_rate_two/p' \\\n    -e 's|available|available_two|' -e '/available_two/p' \\\n    $speed_two >> speed_diff.$$\n#\ncat speed_diff.$$ | sort -u\nrm speed_diff.$$\n# ----------------------------------------------------------------------------\necho \"$0: OK\"\nexit 0\n"
  },
  {
    "path": "bin/speed_new.sh",
    "content": "#! /bin/bash -e\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-23 Bradley M. Bell\n# ----------------------------------------------------------------------------\nprogram=\"bin/speed_new.sh\"\nif [ \"$0\" != \"$program\" ]\nthen\n    echo \"$program: must be executed from its parent directory\"\n    exit 1\nfi\nif [ \"$1\" == '' ]\nthen\ncat << EOF\nusage:\n$program test_name [option_1] [option_2] ...\n\npossible test are:\nall, det_lu, det_minor, mat_mul ode, poly, sparse_hessian, sparse_jacobian\n\npossible options are:\natomic, boolsparsity, colpack, memory, onetape, optimize, revsparsity\nEOF\n    exit 1\nfi\nif [ ! -d new ]\nthen\n    echo \"$program: the directory ./new does not exist.\"\n    echo 'It should contain the new source code.'\n    exit 1\nfi\ntest_name=\"$1\"\nshift\noption_list=\"$test_name\"\nfor option in $*\ndo\n    option_list=\"${option_list}_$option\"\ndone\nif [ \"$test_name\" == 'all' ]\nthen\n    test_name='speed'\nfi\n# ----------------------------------------------------------------------------\ntarget_dir='build/speed/cppad'\nif [ ! -e $target_dir ]\nthen\n    echo_eval mkdir -p $target_dir\nfi\n# ----------------------------------------------------------------------------\n# bash function that echos and executes a command\necho_eval() {\n    echo $*\n    eval $*\n}\n# ----------------------------------------------------------------------------\n#\nfor name in cur new\ndo\n    if [ \"$name\" == 'cur' ]\n    then\n        # revert cppad source code to the current version\n        echo_eval git reset --hard --quiet\n    else\n        echo_eval git_new.sh from\n    fi\n    echo \"bin/run_cmake.sh --debug_none --no_optional > /dev/null\"\n    bin/run_cmake.sh --debug_none --no_optional > /dev/null\n    #\n    out_file=\"$name.$option_list.out\"\n    if [ -e \"$target_dir/$out_file\" ]\n    then\n        echo \"Using existing $target_dir/$out_file\"\n    else\n        # compile the speed test\n        echo \"ninja -C build check_speed_cppad > $target_dir/$name.log\"\n        ninja -C build check_speed_cppad > $target_dir/$name.log\n        #\n        # run speed test for the current version\n        echo \"$target_dir/speed_cppad $test_name 123 $* > $target_dir/$out_file\"\n        $target_dir/speed_cppad $test_name 123 $* > $target_dir/$out_file\n        #\n    fi\ndone\n# compare the results\necho \"    one=cur, two=new\"\nbin/speed_diff.sh \\\n    $target_dir/cur.$option_list.out $target_dir/new.$option_list.out\n# ----------------------------------------------------------------------------\necho \"$0: OK\"\nexit 0\n"
  },
  {
    "path": "bin/speed_package.sh",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\nif [ \"$0\" != 'bin/speed_package.sh' ]\nthen\n    echo \"bin/run_cmake.sh: must be executed from its parent directory\"\n    exit 1\nfi\n# -----------------------------------------------------------------------------\n# bash function that echos and executes a command\necho_eval() {\n    echo $*\n    eval $*\n}\n# -----------------------------------------------------------------------------\n#! /bin/bash -e\ngit reset --hard\npackage='cppadcg'\ninclude_file='cppad/cg/cg.hpp'\nhome_page='https://github.com/joaoleal/CppADCodeGen'\n# --------------------------------------------------------\nPackage=`echo $package | sed -e 's|^.|\\U&|'`\nPACKAGE=`echo $package | sed -e 's|^.*|\\U&|'`\n# --------------------------------------------------------\n# speed/package directory\ncat << EOF > speed_package.$$\ns|XPACKAGE|$PACKAGE|g\ns|Xpackage|$Package|g\ns|xpackage|$package|g\nEOF\nif [ -e speed/$package ]\nthen\n    echo_eval rm -r speed/$package\nfi\ncp -r speed/xpackage speed/$package\ngit add speed/$package\nlist=`ls speed/$package`\nfor file in $list\ndo\n    echo_eval sed -i speed/$package/$file -f speed_package.$$\ndone\n# --------------------------------------------------------\n# omh/speed_package.omh\ncat << EOF > speed_package.$$\n/\\$head fadbad_prefix/! b one\n: loop_1\nN\n/\\\\n *\\$/! b loop_1\ns|.*|\\\\n|\nb end\n#\n: one\ns|Fadbad|$Package|g\ns|fadbad|$package|g\n: end\nEOF\nfile=\"speed/$package/speed_$package.omh\"\ncp speed/fadbad/speed_fadbad.omh $file\ngit add $file\necho_eval sed -i $file -f speed_package.$$\n# --------------------------------------------------------\n# speed/speed.xrst\ncat << EOF > speed_package.$$\ns|\\$cref/Fadbad/fadbad_prefix/Fadbad Home Page/\\$\\$,|&\\\\\n\\$cref/$Package/${package}_prefix/$Package Home Page/\\$\\$,|\ns|^\\\\( *\\\\)speed/fadbad/speed_fadbad.omh%|&\\\\\n\\\\1speed/$package/speed_$package.omh%|\ns|\\$spell|&\\\\\n    $Package|\nEOF\nfile='speed/speed.omh'\necho_eval sed -i $file -f speed_package.$$\n# --------------------------------------------------------\n# speed/main.cpp\ncat << EOF > speed_package.$$\ns|# ifdef CPPAD_XPACKAGE_SPEED|# ifdef CPPAD_${PACKAGE}_SPEED\\\\\n# define AD_PACKAGE \"$package\"\\\\\n# endif\\\\\n&|\nEOF\nfile='speed/main.cpp'\necho_eval sed -i $file -f speed_package.$$\n# --------------------------------------------------------\n# speed/CMakeLists.txt\ncat << EOF > speed_package.$$\n/ENDIF( *cppad_has_fadbad *)/! b end\ns|\\$|\\\\\nIF( cppad_has_$package )\\\\\n    ADD_SUBDIRECTORY($package)\\\\\nENDIF( cppad_has_$package )|\n: end\nEOF\nfile='speed/CMakeLists.txt'\necho_eval sed -i $file -f speed_package.$$\n# --------------------------------------------------------\n# CMakeLists.txt\ncat << EOF > speed_package.$$\n/prefix_info(fadbad/! b end\ns|\\$|\\\\\n#\\\\\n# ${package}_prefix\\\\\nprefix_info($package \\${system_include} \"$package install prefix\")|\n: end\nEOF\nfile='CMakeLists.txt'\necho_eval sed -i $file -f speed_package.$$\n# --------------------------------------------------------\n# omh/install/package_prefix\nshort_name=`echo $include_file | sed -e 's|.*/||'`\ncat << EOF > speed_package.$$\ns|http://uning.dk/|$home_page|\ns|%fadbad_prefix%/%dir%/FADBAD++/badiff.h|%${package}_prefix%/%dir%/$include_file|\ns|badiff[.]h|$short_name|\ns|Fadbad|$Package|g\ns|fadbad|$package|g\ns|\\$spell|&\\\\\n    $include_file|\nEOF\nfile=\"omh/install/${package}_prefix.omh\"\ncp omh/install/fadbad_prefix.omh $file\ngit add $file\necho_eval sed -i $file -f speed_package.$$\n# --------------------------------------------------------\n# omh/install/cmake.omh\ncat << EOF > speed_package.$$\n/^   -D fadbad_prefix=%fadbad_prefix%/! b one\ns|\\$|\\\\\n    -D ${package}_prefix=%${package}_prefix% \\\\\\\\|\nb end\n#\n:one\ns|^\\$rref fadbad_prefix\\$\\\\\\$|&\\\\\n\\$rref ${package}_prefix\\$\\$|\ns|^   omh/install/fadbad_prefix.omh%|&\\\\\n    xrst/install/${package}_prefix.omh%|\ns|\\$spell|&\\\\\n    $package|\n#\n: end\nEOF\nfile='omh/install/cmake.omh'\necho_eval sed -i $file -f speed_package.$$\n# --------------------------------------------------------\n# bin/run_cmake.sh\ncat << EOF > speed_package.$$\ns|^yes_fadbad='yes'|&\\\\\nyes_$package='yes'|\ns|^\\\\( *\\\\)\\\\[--no_fadbad\\\\].*|&\\\\\n\\\\1[--no_$package] \\\\\\\\\\\\\\\\|\ns|^\\\\( *\\\\)--no_fadbad)|\\\\1--no_$package)\\\\\n\\\\1yes_$package='no'\\\\\n\\\\1;;\\\\\n\\\\\n&|\ns|^package_list=''|&\\\\\nif [ \"\\$yes_$package\" == 'yes' ]\\\\\nthen\\\\\n    if [ ! -e \"\\$prefix/include/$include_file\" ]\\\\\n    then\\\\\n        echo \"Cannot find \\$prefix/include/$include_file\"\\\\\n        exit 1\\\\\n    fi\\\\\n    package_list=\"\\$package_list $package\"\\\\\nfi|\nEOF\nfile='bin/run_cmake.sh'\necho_eval sed -i $file -f speed_package.$$\n# --------------------------------------------------------\necho 'speed_package.sh: OK'\nexit 0\n"
  },
  {
    "path": "bin/tag_month.sh",
    "content": "#! /bin/bash -e\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\nif [ $0 != \"bin/tag_month.sh\" ]\nthen\n    echo \"bin/tag_month.sh: must be executed from its parent directory\"\n    exit 1\nfi\nsvn_repository=\"https://projects.coin-or.org/svn/CppAD\"\n# --------------------------------------------------------------------------\n# make sure that master is currently checked out\ngit_branch=`git branch | sed -e '/^\\*/! d' -e 's|^\\* *||'`\nif [ \"$git_branch\" != 'master' ]\nthen\n    echo 'tag_month.sh: master is not currently checkout out'\n    exit 1\nfi\n# --------------------------------------------------------------------------\n# make sure that version is consistent and all changes are checked in\nversion.sh check\n# --------------------------------------------------------------------------\n# make sure repo is up to date\ngit_status=`git status -s`\nif [ \"$git_status\" != '' ]\nthen\n    echo 'tag_month.sh: master has changes that are not checked in'\n    exit 1\nfi\n# --------------------------------------------------------------------------\n# check that version corresponds to first of a month\ndd=`version.sh get | sed -e 's|......\\([0-9][0-9]\\)|\\1|' `\nif [ \"$dd\" != '01' ]\nthen\n    echo 'tag_month.sh: version does not correspond to first day of a month'\n    exit 1\nfi\n# --------------------------------------------------------------------------\n# date of last change to svn repository\nsvn_date=`svn log $svn_repository/trunk --limit 1 | grep '^r[0-9]* *|' | \\\n    sed -e 's/^[^|]*|[^|]*| *\\([0-9-]*\\).*/\\1/' -e 's|-||g'`\n# --------------------------------------------------------------------------\n# get and check hash codes\n#\nlocal_hash=`git show-ref master | sed -e '/\\/origin\\//d' -e 's| refs.*||'`\nremote_hash=`git show-ref master | sed -e '/\\/origin\\//! d' -e 's| refs.*||'`\nsvn_hash=`svn log $svn_repository/trunk --limit 1 | \\\n    grep 'end *hash *code:' | sed -e 's|end *hash *code: *||'`\n#\nif [ \"$local_hash\" != \"$remote_hash\" ]\nthen\n    echo \"tag_month.sh: master changes haven't been pushed to git repository\"\n    echo \"local_hash  = $local_hash\"\n    echo \"remote_hash = $remote_hash\"\n    exit 1\nfi\nif [ \"$remote_hash\" != \"$svn_hash\" ]\nthen\n    echo \"tag_month.sh: master changes haven't been pushed to svn repository\"\n    echo \"remote_hash = $remote_hash\"\n    echo \"svn_hash    = $svn_hash\"\n    exit 1\nfi\n# -----------------------------------------------------------------------------\n# If this version has already been tagged, delete the tag\nversion=`version.sh get`\nif git tag --list | grep \"$version\"\nthen\n    read -p \"Delete preious tag for version $version [y/n] ?\" response\n    if [ \"$response\" != 'y' ]\n    then\n        echo 'tag_month.sh: aborting because tag already exists'\n        exit 1\n    fi\n    git tag -d $version\n    git push --delete origin $version\nfi\n#\necho \"git tag -a \\\\\"\necho \"-m \\\"Last changes copied to $svn_repository/trunk on $svn_date\\\" \\\\\"\necho \"$version $svn_hash\"\ngit tag -a \\\n    -m \"Last changes copied to $svn_repository/trunk on $svn_date\" \\\n    $version $svn_hash\n#\necho \"git push origin $version\"\ngit push origin $version\n# ----------------------------------------------------------------------------\necho \"$0: OK\"\nexit 0\n"
  },
  {
    "path": "bin/test_install.sh",
    "content": "#! /usr/bin/env bash\nset -e -u\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# This script name is 'test_*' instead of 'check_*' because it requires\n# that cmake has already created build/bukld.ninja or Makefile.\nprogram='bin/test_install.sh'\nif [ \"$0\" != \"$program\" ]\nthen\n    echo \"$program: must be executed from its parent directory\"\n    exit 1\nfi\nif [ \"$#\" != 2 ]\nthen\n    echo \"usage: $program builder standard\"\n    echo 'builder:   is ninja or make'\n    echo 'standard:  is --c++yy where yy is the year for the C++ standard'\n    exit 1\nfi\nbuilder=\"$1\"\nstandard=\"$2\"\nif [ \"$1\" != 'ninja' ] && [ \"$1\" != 'make' ]\nthen\n    echo \"$program: builder is not ninja or make\"\n    exit 1\nfi\nif [ \"$builder\" == 'ninja' ] && [ ! -e build/build.ninja ]\nthen\n    echo \"$program: builder is ninja and cannot find build/build.ninja\"\n    exit 1\nfi\nif [ \"$builder\" == 'make' ] && [ ! -e build/Makefile ]\nthen\n    echo \"$program: builder is make and cannot file build/Makefile\"\n    exit 1\nfi\nif ! echo \"$standard\" | grep '^--c++[0-9][0-9]' > /dev/null\nthen\n    echo \"$program: standard is not --c++yy where ecxh y is a deciman digit\"\n    eiit 1\nfi\n# -----------------------------------------------------------------------------\n# bash function that echos and executes a command\necho_eval() {\n    echo $*\n    eval $*\n}\n# -----------------------------------------------------------------------------\n# prefix\neval `grep '^prefix=' bin/get_optional.sh`\nif [[ \"$prefix\" =~ ^[^/] ]]\nthen\n    prefix=\"$(pwd)/$prefix\"\nfi\n# -----------------------------------------------------------------------------\nPKG_CONFIG_PATH=\"$prefix/share/pkgconfig\"\nLD_LIBRARY_PATH=\"\"\nfor dir in lib lib64\ndo\n    PKG_CONFIG_PATH+=\":$prefix/$dir/pkgconfig\"\n    LD_LIBRARY_PATH+=\":$prefix/$dir\"\ndone\nexport PKG_CONFIG_PATH\nexport LD_LIBRARY_PATH\n# -----------------------------------------------------------------------------\n# make install\ncd build\n$builder install\n# -----------------------------------------------------------------------------\n#\n# rpath\nrpath=$(find $prefix -name 'libcppad_lib.*' | head -1 )\nrpath=$(echo $rpath | sed -e 's|/[^/]*$||')\n#\n# cflags\ncflags=\"$(echo $standard | sed -e 's|^--c++|-std=c++|')\"\nif [ \"$(uname)\" == Darwin ]\nthen\n    if which brew > /dev/null\n    then\n        # 2DO: This flag should be added automatically by pkg-config\n        cflags+=\" -I $(brew --prefix)/include\"\n    fi\nfi\ncflags+=\" $(pkg-config cppad --cflags)\"\n#\n# libs\nlibs=$(pkg-config cppad --libs)\n#\n# test_install\nif [ ! -e test_install ]\nthen\n    mkdir test_install\nfi\ncd test_install\n#\n# CppAD get_started\ncp ../../example/get_started/get_started.cpp get_started.cpp\necho_eval g++ $cflags $libs -Wl,-rpath $rpath get_started.cpp -o get_started\necho 'CppAD: ./get_started'\nif ! ./get_started\nthen\n    echo \"$program: $(pwd)/get_started test failed.\"\n    exit 1\nfi\n#\n# ipopt_solve get_started\ncp ../../example/ipopt_solve/get_started.cpp get_started.cpp\ncat << EOF >> get_started.cpp\nint main(void)\n{   if( ! get_started() )\n        return 1;\n    return 0;\n}\nEOF\necho_eval g++ $cflags $libs -Wl,-rpath $rpath get_started.cpp -o get_started\necho 'ipopt_solve: ./get_started'\nif ! ./get_started\nthen\n    echo \"$program: $(pwd)/get_started test failed.\"\n    exit 1\nfi\n# -----------------------------------------------------------------------------\necho \"$program: OK\"\nexit 0\n"
  },
  {
    "path": "bin/test_multi_thread.sh",
    "content": "#! /usr/bin/env bash\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\nset -e -u\n# ----------------------------------------------------------------------------\n# This script is 'test_*' instead of 'check_*' because it requires\n# that cmake has already created build/bukld.ninja or Makefile.\nprogram='bin/test_multi_thread.sh'\nif [ \"$0\" != \"$program\" ]\nthen\n    echo \"$program: must be executed from its parent directory\"\n    exit 1\nfi\nif [ \"$#\" != 1 ]\nthen\n    echo \"usage: $program builder\"\n    echo 'where builder is ninja or make'\n    exit 1\nfi\nbuilder=\"$1\"\nif [ \"$1\" != 'ninja' ] && [ \"$1\" != 'make' ]\nthen\n    echo \"usage:usage:  $program builder\"\n    echo 'where builder is ninja or make'\n    exit 1\nfi\nif [ \"$builder\" == 'ninja' ] && [ ! -e build/build.ninja ]\nthen\n    echo \"$program: builder is ninja and cannot find build/build.ninja\"\n    exit 1\nfi\nif [ \"$builder\" == 'make' ] && [ ! -e build/Makefile ]\nthen\n    echo \"$program: builder is make and cannot file build/Makefile\"\n    exit 1\nfi\n# -----------------------------------------------------------------------------\n# bash function that echos and executes a command\necho_eval() {\n    echo $*\n    eval $*\n}\n# ---------------------------------------------------------------------------\n# circular shift program list and set program to first entry in list\nnext_program() {\n    program_list=`echo \"$program_list\" | sed -e 's| *\\([^ ]*\\) *\\(.*\\)|\\2 \\1|'`\n    program=`echo \"$program_list\" | sed -e 's| *\\([^ ]*\\).*|\\1|'`\n}\n# ----------------------------------------------------------------------------\n#\n# build\ncd build\n$builder check_example_multi_thread\n#\n# program_list, skip\nprogram_list=''\nskip=''\nfor threading in bthread openmp pthread sthread\ndo\n    dir=\"example/multi_thread/$threading\"\n    if [ ! -e \"$dir\" ]\n    then\n        skip+=\" $threading\"\n    else\n        program=\"$dir/example_multi_thread_${threading}\"\n        program_list+=\" $program\"\n        #\n        # all programs check the fast cases\n        echo_eval $program a11c\n        echo_eval $program get_started\n        echo_eval $program team_example\n    fi\ndone\nif [ \"$program_list\" != '' ]\nthen\n    # test_time=1,max_thread=4,mega_sum=1\n    next_program\n    echo_eval $program harmonic 1 4 1\n    #\n    # test_time=1,max_thread=4,num_solve=100\n    next_program\n    echo_eval $program atomic_two 1 4 100\n    next_program\n    echo_eval $program atomic_three 1 4 100\n    next_program\n    echo_eval $program chkpoint_one 1 4 100\n    next_program\n    echo_eval $program chkpoint_two 1 4 100\n    #\n    # test_time=2,max_thread=4,num_zero=20,num_sub=30,num_sum=50,use_ad=true\n    next_program\n    echo_eval $program multi_newton 2 4 20 30 50 true\nfi\n#\nif [ \"$skip\" != '' ]\nthen\n    echo \"Skipped following multi_treading tests: $skip\"\nfi\necho 'test_multi_thread.sh: OK'\nexit 0\n"
  },
  {
    "path": "bin/test_one.sh.in",
    "content": "#! /bin/bash -e\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\nset_libdir() {\n    my_prefix=\"$1\"\n    my_lib=\"$2\"\n    libdir=''\n    if [ -e $my_prefix/lib ]\n    then\n        if ls $my_prefix/lib | grep \"lib$my_lib\" > /dev/null\n        then\n            libdir='lib'\n        fi\n    fi\n    if [ -e $my_prefix/lib64 ]\n    then\n        if ls $my_prefix/lib64 | grep \"lib$my_lib\" > /dev/null\n        then\n            libdir='lib64'\n        fi\n    fi\n    if [ \"$libdir\" == '' ]\n    then\n        echo \"bin/test_one.sh: cannot find lib$my_lib\"\n        echo \" in $my_prefix/lib or $my_prefix/lib64\"\n        exit 1\n    fi\n    my_path=\"$my_prefix/$libdir\"\n    library_flags=\"$library_flags -L$my_path -l$my_lib\"\n    if ! echo \"$LD_LIBRARY_PATH:\" | grep \"$my_path:\" > /dev/null\n    then\n        if [ \"$LD_LIBRARY_PATH\" == '' ]\n        then\n            LD_LIBRARY_PATH=\"$my_path\"\n        else\n            LD_LIBRARY_PATH=\"$LD_LIBRARY_PATH:$my_path\"\n        fi\n    fi\n}\n# -----------------------------------------------------------------------------\n# Command line arguments\nif [ \"$0\" != 'bin/test_one.sh' ]\nthen\ncat << EOF\nusage: bin/test_one.sh dir/file [extra]\n\ndir:   directory in front of file name\nfile:  name of *.cpp file, with extension, that contains the test\nextra: extra source files and/or options for the compile command\nEOF\n    exit 1\nfi\nif ! echo \"$1\" | grep '/' > /dev/null\nthen\n    echo 'test_one.sh: dir missing in'\n    echo '    bin/test_one.sh dir/file'\n    exit 1\nfi\ndir=`echo $1 | sed -e 's|/[^/]*$||'`\nfile=`echo $1 | sed -e 's|.*/||'`\nextra=\"$2\"\n#\n# case where main program is in parent directory\nmain=`echo *$dir | sed -e 's|.*/||' -e 's|$|.cpp|'`\nif [ ! -e \"$dir/$main\" ]\nthen\n    subdir=`echo $dir | sed -e 's|.*/||'`\n    dir=`echo $dir | sed -e 's|/[^/]*$||'`\n    file=\"$subdir/$file\"\nfi\n# ---------------------------------------------------------------------------\n# Check command line arguments\nif [ \"$dir\" == '' ]\nthen\n    echo \"test_one.sh: cannot find dir/file in \\$1='$1'\"\n    exit 1\nfi\nif [ ! -e \"$dir/$file\" ]\nthen\n    echo \"test_one.sh: Cannot find the file $dir/$file\"\n    exit 1\nfi\nif [ ! -e 'build/CMakeFiles' ]\nthen\n    echo 'test_one.sh: Must first execute bin/run_cmake.sh'\n    exit 1\nfi\n# ---------------------------------------------------------------------------\n# Clean out old output files\nif [ -e test_one.exe ]\nthen\n    rm test_one.exe\nfi\nif [ -e test_one.cpp ]\nthen\n    rm test_one.cpp\nfi\ntop_srcdir=$(pwd)\n# ---------------------------------------------------------------------------\nPKG_CONFIG_PATH=\"@cppad_prefix@/share/pkgconfig\"\nPKG_CONFIG_PATH=\"$PKG_CONFIG_PATH:@cppad_prefix@/lib/pkgconfig\"\nPKG_CONFIG_PATH=\"$PKG_CONFIG_PATH:@cppad_prefix@/lib64/pkgconfig\"\nexport PKG_CONFIG_PATH\n# ---------------------------------------------------------------------------\n# initialize\nexport LD_LIBRARY_PATH=''\ninclude_flags=''\nlibrary_flags=''\n#\n# adolc\nif [ @cppad_has_adolc@ == 1 ]\nthen\n    include_flags=\"$include_flags $(pkg-config adolc --cflags)\"\n    library_flags=\"$library_flags $(pkg-config adolc --libs)\"\n    library_path=$(pkg-config adolc --libs | sed -e 's|.*-L\\([^ ]*\\).*|\\1|')\n    LD_LIBRARY_PATH=\"$library_path:$LD_LIBRARY_PATH\"\nfi\nif [ @cppad_has_eigen@ == 1 ]\nthen\n    include_flags=\"$include_flags $(pkg-config eigen3 --cflags)\"\n    library_flags=\"$library_flags $(pkg-config eigen3 --libs)\"\nfi\n#\n# ipopt\nif [ @cppad_has_ipopt@ == 1 ]\nthen\n    include_flags=\"$include_flags $(pkg-config ipopt --cflags)\"\n    library_flags=\"$library_flags $(pkg-config ipopt --libs)\"\n    library_path=$(pkg-config ipopt --libs | sed -e 's|.*-L\\([^ ]*\\).*|\\1|')\n    LD_LIBRARY_PATH=\"$library_path:$LD_LIBRARY_PATH\"\nfi\n#\nif [ @cppad_has_boost@ == 1 ]\nthen\n    library_flags=\"$library_flags -lboost_thread\"\nfi\n#\n# colpack\nif [ @cppad_has_colpack@ == 1 ]\nthen\n    include_flags=\"$include_flags -I @colpack_prefix@/include\"\n    #\n    set_libdir @colpack_prefix@ ColPack\nfi\n#\n# cppad\ninclude_flags=$(echo $include_flags | \\\n    sed -e 's|  *-I *| -isystem |g' -e 's|^-I *|-isystem |'\n)\ninclude_flags=\"-I $top_srcdir/include $include_flags\"\nif [ @is_cppad_lib_dynamic@ ==  '1' ]\nthen\n    cppad_lib_path='@PROJECT_BINARY_DIR@/cppad_lib/libcppad_lib.so'\nelse\n    cppad_lib_path='@PROJECT_BINARY_DIR@/cppad_lib/libcppad_lib.a'\nfi\nlibrary_flags=\"$library_flags $cppad_lib_path -lpthread\"\n#\ncd build\nif [ -e 'build.ninja' ] && [ -e 'Makefile' ]\nthen\n    echo \"bin/test_one.sh: Both build.ninja and Makefile are in $(pwd)\"\n    exit 1\nelif [ -e 'build.ninja' ]\nthen\n    builder=ninja\nelif [ -e 'Makefile' ]\nthen\n    builder=make\nelse\n    echo \"bin/test_one.sh: Neither build.ninja or Makefile is in $(pwd)\"\n    exit 1\nfi\nif ! $builder cppad_lib\nthen\n    echo \"test_one.sh: $builder cppad_lib failed: see errors above\"\n    exit 1\nfi\ncd ..\n# --------------------------------------------------------------------------\n# Create test_one.exe\n#\n# determine the function name\nfun=`grep \"^bool *[a-zA-Z0-9_]* *( *void *)\" $dir/$file | tail -1 | \\\n    sed -e \"s/^bool *\\([a-zA-Z0-9_]*\\) *( *void *)/\\1/\"`\n#\n# determine the main program main\nmain=`echo *$dir | sed -e 's|.*/||' -e 's|$|.cpp|'`\n#\nsed < $dir/$main > test_one.cpp \\\n-e '/^ *Run( /d' \\\n-e \"s/.*This line is used by test_one.sh.*/    Run( $fun, \\\"$fun\\\");/\"\n# --------------------------------------------------------------------------\n# Create test_one.exe\n#\n# compiler flags\ncxx_flags='@cppad_cxx_flags@'\nif [ \"$dir\" == 'test_more/cppad_for_tmb' ]\nthen\n    cxx_flags=\"$cxx_flags @OpenMP_CXX_FLAGS@ -DCPPAD_FOR_TMB\"\nfi\n#\n# compile command\ncompile_command=\"@CMAKE_CXX_COMPILER@ test_one.cpp -o test_one.exe\n    $dir/$file $extra\n    -g\n    $cxx_flags\n    $include_flags\n    $library_flags\n\"\necho \"$compile_command 2> test_one.err\"\nif ! $compile_command 2> test_one.err\nthen\n    tail test_one.err\n    echo 'test_one.sh: see test_one.err'\n    exit 1\nfi\n# --------------------------------------------------------------------------\n# LD_LIBRARY_PATH\nmy_path='@PROJECT_BINARY_DIR@/cppad_lib'\nif ! echo $LD_LIBRARY_PATH | grep \"$my_path\" > /dev/null\nthen\n    if [ \"$LD_LIBRARY_PATH\" == '' ]\n    then\n        LD_LIBRARY_PATH=\"$my_path\"\n    else\n        LD_LIBRARY_PATH=\"$LD_LIBRARY_PATH:$my_path\"\n    fi\nfi\n# --------------------------------------------------------------------------\n# Execute the test\necho \"./test_one.exe\"\nif ! ./test_one.exe\nthen\n    cat test_one.err\n    echo \"export LD_LIBRARY_PATH=$LD_LIBRARY_PATH\"\n    exit 1\nfi\n# --------------------------------------------------------------------------\n# Check for compiler warnings\ncat << EOF > test_one.sed\n# Lines that describe where error is\n/^In file included from/d\n/: note:/d\n#\n# Ipopt has sign conversion warnings\n/\\/coin\\/.*-Wsign-conversion/d\n#\n# Adolc has multiple types of conversion warnings\n/\\/adolc\\/.*-W[a-z-]*conversion/d\n/\\/adolc\\/.*-Wshorten-64-to-32/d\n#\n# Lines describing the error begin with space\n/^ /d\n#\n# Lines summarizing results\n/^[0-9]* warnings generated/d\nEOF\nsed -f test_one.sed < test_one.err > test_one.tmp\nrm test_one.sed\nif [ -s test_one.tmp ]\nthen\n    cat test_one.tmp\n    echo 'test_one.sh: unexpected warnings: see  test_one.tmp, test_one.err'\n    echo \"export LD_LIBRARY_PATH=$LD_LIBRARY_PATH\"\n    exit 1\nfi\n# --------------------------------------------------------------------------\necho 'test_one.sh: OK'\necho \"export LD_LIBRARY_PATH=$LD_LIBRARY_PATH\"\nexit 0\n"
  },
  {
    "path": "bin/trace.sh",
    "content": "#! /bin/bash -e\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\nif [ $0 != \"bin/trace.sh\" ]\nthen\n    echo \"bin/trace.sh: must be executed from its parent directory\"\n    exit 1\nfi\nfile=\"include/cppad/local/sweep/$1\"\noption=\"$2\"\n#\nok='yes'\nif [ \"$option\" != '0' ] && [ \"$option\" != '1' ]\nthen\n    ok='no'\nfi\nif [ \"$ok\" == 'yes' ]\nthen\n    if ! grep '_TRACE [01]' $file > /dev/null\n    then\n        ok='no'\n    fi\nfi\nif [ \"$ok\" == 'no' ]\nthen\n    echo 'usage: bin/trace.sh file (0|1)'\n    echo 'Sets trace in file to off (0) or on (1) where the file is one of:'\n    grep -l '_TRACE [01]' include/cppad/local/sweep/*.hpp | \\\n        sed -e 's|^include/cppad/local/sweep/||'\n    exit 1\nfi\nold=`grep '_TRACE [01]' $file`\nsed -e \"s|TRACE [01]|TRACE $option|\" -i $file\nnew=`grep '_TRACE [01]' $file`\n#\necho \"old: $old\"\necho \"new: $new\"\n#\n# ----------------------------------------------------------------------------\necho \"$0: OK\"\nexit 0\n"
  },
  {
    "path": "bin/travis.sh",
    "content": "#! /bin/bash -e\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\nif [ $0 != \"bin/travis.sh\" ]\nthen\n    echo 'bin/travis.sh: must be executed from its parent directory'\n    exit 1\nfi\nif [ \"$1\" != 'make' ] && [ \"$1\" != 'test_one' ]\nthen\n    echo 'usage: bin/travis.sh (make|test_one) target1 target2 ...'\n    echo 'target: if make specified, is one of the available make commands'\n    echo          if test_one, specified, is the path to a test file.\n    exit 1\nfi\ncmd=\"$1\"\n# -----------------------------------------------------------------------------\n# bash function that echos and executes a command\necho_eval() {\n    echo $*\n    eval $*\n}\n# -----------------------------------------------------------------------------\nif [ -e 'build' ]\nthen\n    echo_eval rm -r build\nfi\necho_eval mkdir build\necho_eval cd build\necho_eval cmake \\\n    -D cppad_prefix=$(pwd)/prefix \\\n    -D cppad_cxx_flags='-std=c++11' \\\n    ..\n# -----------------------------------------------------------------------------\nif [ \"$cmd\" == 'make' ]\nthen\n    shift\n    while [ \"$1\" != '' ]\n    do\n        echo_eval make \"$1\"\n        shift\n    done\nelse\n    echo_eval cd ..\n    shift\n    while [ \"$1\" != '' ]\n    do\n        echo_eval bin/test_one.sh \"$1\"\n        shift\n    done\nfi\n# -----------------------------------------------------------------------------\necho 'bin/travis.sh: OK'\nexit 0\n"
  },
  {
    "path": "bin/twine.sh",
    "content": "#! /usr/bin/env bash\nset -e -u\n# !! EDITS TO THIS FILE ARE LOST DURING UPDATES BY xrst.git/bin/dev_tools.sh !!\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2020-25 Bradley M. Bell\n# -----------------------------------------------------------------------------\n# bin/twine.sh branch_or_tag\n# 1. This program muse be executed from the main or master branch\n# 2. branch_or_tag can be a branch or a tag. If it is a branch, it must be\n#    main or master.\n# 3. If branch_or_tag is a tag, the corresponding version is uploaded to pypi.\n#    Otherwise it is uploaded to testpipi.\n# -----------------------------------------------------------------------------\n# bash function that echos and executes a command\necho_eval() {\n    echo $*\n    eval $*\n}\n# -----------------------------------------------------------------------------\nif [ \"$0\" != \"bin/twine.sh\" ]\nthen\n    echo \"bin/twine.sh: must be executed from its parent directory\"\n    exit 1\nfi\nif [ ! -e .git ]\nthen\n    echo 'bin/twine.sh: Cannot find .git in current working directory'\n    exit 1\nfi\n#\n# branch_or_tag\nif [ $# != 1 ]\nthen\n    echo 'usage: bin/twine.sh: branch_or_tag'\n    echo 'where branch_or_tag is master, main, or a git tag'\n    exit 1\nfi\nbranch_or_tag=\"$1\"\n#\n# branch\nbranch=$(git branch --show-current)\nif [ \"$branch\" != 'master' ] && [ \"$branch\" != 'main' ]\nthen\n    echo 'bin/twine.sh: must execute on the main or master branch'\n    exit 1\nfi\n#\n# repository\nif [ \"$branch_or_tag\" == \"$branch\" ]\nthen\n    repository='testpypi'\nelse\n    repository='pypi'\nfi\n#\n# TOKEN\nif [ -z \"${TOKEN+x}\" ]\nthen\n    echo echo \"bin/twine.sh: must export TOKEN=<API token for $repository>\"\n    echo 'see https://pypi.org/help/#apitoken'\n    exit 1\nfi\n#\n# dist\nif [ -e dist ]\nthen\n    rm -r dist\nfi\nif [ \"$branch_or_tag\" == \"$branch\" ]\nthen\n    echo_eval python -m build\nelse\n    if ! git show-ref $branch_or_tag | grep '/tags/' > /dev/null\n    then\n        echo \"bin/twine.sh: $branch_or_tag is not the current branch or a tag\"\n        exit 1\n    fi\n    git checkout --quiet $branch_or_tag\n    echo_eval python -m build\n    git checkout $branch\nfi\n#\n# twind\necho_eval twine upload --repository $repository  dist/* -u __token__ -p $TOKEN\n#\necho 'twine.sh: OK'\nexit 0\n"
  },
  {
    "path": "bin/valgrind.sh",
    "content": "#! /bin/bash -eu\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# bash function that echos and executes a command\necho_eval() {\n    echo $*\n    eval $*\n}\n# -----------------------------------------------------------------------------\nif [ \"$0\" != \"bin/valgrind.sh\" ]\nthen\n    echo \"bin/valgrind.sh: must be executed from its parent directory\"\n    exit 1\nfi\nif [ \"$#\" != '0' ]\nthen\n    echo 'usage: bin/valgrind.sh.sh'\n    exit 1\nfi\n# -----------------------------------------------------------------------------\nlist=`find build -perm -700 -type f | \\\n    sed -e '/^build\\/cppad-*/d'  -e '/\\/CMakeFiles\\//d'`\nfor program in $list\ndo\n    arguments=''\n    if echo \"$program\" | grep '\\/speed\\/' > /dev/null\n    then\n        arguments='correct none'\n    fi\n    echo \"valgrind $program $arguments 2> valgrind.log\"\n    valgrind $program $arguments 2> valgrind.log\n    if ! grep '^==[0-9]*== ERROR SUMMARY: 0' valgrind.log\n    then\n        grep 'ERROR SUMMARY' valgrind.log\n        exit 1\n    fi\n    if ! grep '^==[0-9]*== *definitely lost: 0' valgrind.log\n    then\n        if grep '^==[0-9]*== *definitely lost:' valgrind.log\n        then\n            exit 1\n        fi\n    fi\n    if ! grep '^==[0-9]*== *indirectly lost: 0' valgrind.log\n    then\n        if grep '^==[0-9]*== *indirectly lost:' valgrind.log\n        then\n            exit 1\n        fi\n    fi\n    if ! grep '^==[0-9]*== *possibly lost: 0' valgrind.log\n    then\n        if grep '^==[0-9]*== *possibly lost:' valgrind.log\n        then\n            exit 1\n        fi\n    fi\n    if ! grep '^==[0-9]*== *suppressed: 0' valgrind.log\n    then\n        if grep '^==[0-9]*== *suppressed:' valgrind.log\n        then\n            exit 1\n        fi\n    fi\ndone\n# -----------------------------------------------------------------------------\necho 'bin/valgrind.sh: OK'\nexit 0\n"
  },
  {
    "path": "bug/boost_lu.sh",
    "content": "#! /bin/bash -e\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n#!/bin/bash -e\nname=`echo $0 | sed -e 's|^bug/||' -e 's|\\.sh$||'`\nif [ \"$0\" != \"bug/$name.sh\" ]\nthen\n    echo 'usage: bug/alloc_global.sh'\n    exit 1\nfi\n# -----------------------------------------------------------------------------\nif [ -e build/bug ]\nthen\n    rm -r build/bug\nfi\nmkdir -p build/bug\ncd build/bug\ncmake ../..\n# -----------------------------------------------------------------------------\ncat << EOF\nThis test results in a very long error message with boost-1.55.0 and\ngcc-4.9.2. Here is the gist of the message:\n    /usr/include/boost/numeric/ublas/detail/matrix_assign.hpp:33:35:\n    error: no match for ‘operator<’\n    ... snip ...\n        return norm_inf (e1 - e2) < epsilon *\n                                              ^\nThe following change to\n    /usr/include/boost/numeric/ublas/detail/matrix_assign.hpp\nseems to fix the problem:\n\nOld Text:\n        return norm_inf (e1 - e2) < epsilon *\n        std::max<S> (std::max<S> (norm_inf (e1), norm_inf (e2)), min_norm);\nNew Text:\n    S norm_1    = norm_inf(e1);\n    S norm_2    = norm_inf(e2);\n    S norm_diff = norm_inf(e1 - e2);\n    return norm_diff < epsilon * std::max( std::max<S>(norm_1, norm_2) , min_norm );\nEOF\ncat << EOF > boost_lu.cpp\n#include <cppad/cppad.hpp>\n\n# define NUMERIC_LIMITS_FUN(name)                  \\\n    static CppAD::AD<double> name(void)            \\\n    {   return static_cast< CppAD::AD<double> > (  \\\n            std::numeric_limits<double>::name()    \\\n        );                                         \\\n    }\n\n# define NUMERIC_LIMITS_BOOL(name)                 \\\n    static const bool name =                       \\\n        std::numeric_limits<double>::name;\n\n# define NUMERIC_LIMITS_INT(name)                 \\\n    static const int name =                       \\\n        std::numeric_limits<double>::name;\n\n\n\nnamespace std {\n    /// Specialization of numeric_limits< CppAD::AD<double> >\n    template <>\n    class numeric_limits< CppAD::AD<double> > {\n    public:\n        // has_denorm\n        static const float_denorm_style has_denorm =\n            std::numeric_limits<double>::has_denorm;\n        // round_style\n        static const float_round_style round_style =\n            std::numeric_limits<double>::round_style;\n\n        // bool\n        NUMERIC_LIMITS_BOOL(is_specialized);\n        NUMERIC_LIMITS_BOOL(is_signed);\n        NUMERIC_LIMITS_BOOL(is_integer);\n        NUMERIC_LIMITS_BOOL(is_exact);\n        NUMERIC_LIMITS_BOOL(has_infinity);\n        NUMERIC_LIMITS_BOOL(has_quiet_NaN);\n        NUMERIC_LIMITS_BOOL(has_signaling_NaN);\n        NUMERIC_LIMITS_BOOL(has_denorm_loss);\n        NUMERIC_LIMITS_BOOL(is_iec559);\n        NUMERIC_LIMITS_BOOL(is_bounded);\n        NUMERIC_LIMITS_BOOL(is_modulo);\n        NUMERIC_LIMITS_BOOL(traps);\n        NUMERIC_LIMITS_BOOL(tinyness_before);\n\n        // int\n        NUMERIC_LIMITS_INT(digits);\n        NUMERIC_LIMITS_INT(digits10);\n        NUMERIC_LIMITS_INT(radix);\n        NUMERIC_LIMITS_INT(min_exponent);\n        NUMERIC_LIMITS_INT(min_exponent10);\n        NUMERIC_LIMITS_INT(max_exponent);\n        NUMERIC_LIMITS_INT(max_exponent10);\n\n        /// functions\n        NUMERIC_LIMITS_FUN( epsilon)\n        NUMERIC_LIMITS_FUN( min    )\n        NUMERIC_LIMITS_FUN( max    )\n    };\n}\n\n#include <boost/numeric/ublas/lu.hpp>\nint main() {\n    typedef CppAD::AD<double> T;\n    boost::numeric::ublas::matrix<T> a(5,5);\n    boost::numeric::ublas::permutation_matrix<std::size_t> pert(5);\n    // lu decomposition\n    const std::size_t s = lu_factorize(a, pert);\n\n    return 0;\n}\nEOF\necho \"g++ -I../../include --std=c++11 -g $name.cpp -o $name >& $name.log\"\nif ! g++ -I../../include --std=c++11 -g $name.cpp -o $name >& $name.log\nthen\n    cat << EOF > $name.sed\ns|\\\\[|&\\\\n|g\ns|\\\\]|&\\\\n|g\ns|[‘{}]|&\\\\n|g\ns|[a-zA-Z0-9_]* *=|\\\\n&|g\n#\ns|boost::numeric::ublas::||g\ns|/usr/include/boost/numeric/ublas/||g\n#\ns|CppAD::AD<double> *|AD|g\ns|<matrix<AD>, basic_unit_lower<> >|<matrix_AD_ulower>|g\ns|<matrix<AD>, basic_upper<> >|<matrix_AD_upper>|g\ns|scalar_minus<AD, AD>|scalar_minus_AD|g\ns|triangular_adaptor<\\\\([^<>]*\\\\)>|triangular_\\\\1|g\ns|triangular_matrix_AD_ulower|AD_ulower|g\ns|triangular_matrix_AD_upper|AD_upper|g\ns|matrix_matrix_prod<AD_ulower, AD_upper, AD> *|AD_prod_ulower_upper|g\ns|<AD_ulower, AD_upper, AD_prod_ulower_upper> *|<AD_prod_ulower_upper>|g\ns|matrix_matrix_binary<AD_prod_ulower_upper>|AD_prod_ulower_upper|g\nEOF\n    echo \"sed -f $name.sed $name.log > ../$name.log\"\n    sed -f $name.sed $name.log > ../$name.log\n    echo \"$name.sh: Compilation Error: see build/bug/$name.log\"\n    exit 1\nfi\n#\necho \"./$name\"\nif ! ./$name\nthen\n    echo\n    echo \"$name.sh: Execution Error\"\n    exit 1\nfi\necho\n# ------------------------------------------------------------------------------\necho \"$name.sh: OK\"\nexit 0\n"
  },
  {
    "path": "bug/clang_simple.sh",
    "content": "#! /bin/bash -e\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\nname='clang_simple'\nif [ \"$0\" != \"bug/$name.sh\" ]\nthen\n    echo \"usage: bug/$name.sh\"\n    exit 1\nfi\n# -----------------------------------------------------------------------------\nif [ -e build/bug ]\nthen\n    rm -r build/bug\nfi\nmkdir -p build/bug\ncd build/bug\ncmake ../..\n# -----------------------------------------------------------------------------\ncat << EOF > $name.cpp\n# include <cppad/cppad.hpp>\nint main(void)\n{   bool ok = true;\n    using std::cout;\n    using CppAD::AD;\n    //\n    std::cout << \"Test for issue 31\\n\";\n    CppAD::CheckSimpleVector<double, CppAD::vector<double> >();\n    //\n    if( ok )\n        return 0;\n    return 1;\n}\nEOF\ncxx_flags='-g -O0'\neigen_dir=\"$HOME/prefix/eigen/include\"\necho \"clang++ -I../../include -isystem $eigen_dir $cxx_flags $name.cpp -o $name\"\nclang++ -I../../include -isystem $eigen_dir $cxx_flags $name.cpp -o $name\n#\nif ! ./$name\nthen\n    echo\n    echo \"build/bug/$name: Error\"\n    exit 1\nfi\necho\n# ------------------------------------------------------------------------------\necho \"./$name.sh: OK\"\nexit 0\n"
  },
  {
    "path": "bug/cmake_target.sh",
    "content": "#! /bin/bash -e\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n#! /bin/bash -e\necho 'This script does not work properly on el6; see'\necho 'https://bugzilla.redhat.com/show_bug.cgi?id=896116'\necho\n#\nif [ -e build ]\nthen\n    rm -r build\nfi\nmkdir build\ncd    build\ncat << EOF > hello_one.cpp\n# include <iostream>\nint main(void)\n{   std::cout << \"hello_one\" << std::endl << std::endl;\n    return 0;\n}\nEOF\ncat << EOF > hello_two.cpp\n# include <iostream>\nint main(void)\n{   std::cout << \"hello_two\" << std::endl << std::endl;\n    return 0;\n}\nEOF\ncat << EOF > CMakeLists.txt\nCMAKE_MINIMUM_REQUIRED(VERSION 2.6)\n#\nPROJECT(hello)\n#\nADD_EXECUTABLE(hello_one EXCLUDE_FROM_ALL hello_one.cpp )\nADD_EXECUTABLE(hello_two EXCLUDE_FROM_ALL hello_two.cpp )\n#\nADD_CUSTOM_TARGET(check_one hello_one DEPENDS hello_one)\nADD_CUSTOM_TARGET(check_two hello_two DEPENDS hello_two)\n#\nADD_CUSTOM_TARGET(check DEPENDS check_one check_two)\nEOF\n#\nuname -a\ncmake --version\ncmake .\nmake check\n"
  },
  {
    "path": "bug/cppad_cg.sh",
    "content": "#! /bin/bash -e\n# $Id:$\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n#! /bin/bash -e\nweb_page='https://github.com/joaoleal/CppADCodeGen'\n# -----------------------------------------------------------------------------\n# bash function that echos and executes a command\necho_eval() {\n    echo $*\n    eval $*\n}\n# -----------------------------------------------------------------------------\ncat << EOF\nThis is not a bug but rather a demonstration of using conditional expressions\nwith CppADCodeGen\n    https://github.com/joaoleal/CppADCodeGen/\nEOF\n#\nif [ ! -e build ]\nthen\n    echo_eval mkdir -p build\nfi\necho_eval cd build\ncat << EOF > cppad_cg.cpp\n# include <iosfwd>\n# include <cppad/cg/cppadcg.hpp>\nint main(void)\n{   typedef CppAD::cg::CG<double> cg_double;\n    typedef CppAD::AD<cg_double>  acg_double;\n\n    // declare independent variables for f(x)\n    size_t nx = 2;\n    CppAD::vector<acg_double> ax(nx);\n    ax[0] = 2.0;\n    ax[1] = 3.0;\n    CppAD::Independent(ax);\n\n    // create dependent variables and values for f(x)\n    // f(x) = x[0] / x[1] if (x[0] > 0 and x[1] >= x[0]) else 1.0\n    size_t nz = 1;\n    CppAD::vector<acg_double> az(nz);\n    acg_double acg_zero   = acg_double(0.0);\n    acg_double acg_one    =   acg_double(1.0);\n    acg_double acg_temp_1 = CondExpGt(ax[1], ax[0], ax[0] / ax[1], acg_one);\n    acg_double acg_temp_2 = CondExpGt(ax[0], acg_zero, acg_temp_1, acg_one);\n    az[0] = acg_temp_2;\n\n    // create AD function mapping independent to dependent variables\n    CppAD::ADFun<cg_double> F(ax, az);\n\n    // create the source code generator for function g(x)\n    CppAD::cg::CodeHandler<double> G;\n\n    // declare the independent variables for g(x)\n    CppAD::vector<cg_double>   cg_x(nx);\n    G.makeVariables(cg_x);\n\n    // Compute the dependent variables and values for g(x)\n    size_t ny = nz * nx;\n    CppAD::vector<cg_double> cg_y(ny);\n    cg_y = F.Jacobian(cg_x);\n\n    // Mapping from variables in this program to variables in source_code\n    // independent variable = x\n    // dependent variable   = y\n    // temporary variable   = v\n    CppAD::cg::LanguageC<double> langC(\"double\");\n    CppAD::cg::LangCDefaultVariableNameGenerator<double> nameGen;\n\n    // generate the source code\n    std::ostringstream source_code;\n    G.generateCode(source_code, langC, cg_y, nameGen);\n\n    // string corresponding to source code\n    std::string source_str = source_code.str();\n\n    // C source code corresponding to y = g(x)\n    std::cout << source_str;\n\n    return 0;\n}\nEOF\n#\n# Compile and run cppad_cg.cpp\necho_eval g++ \\\n    -g \\\n    -std=c++11 \\\n    -I$HOME/prefix/cppad_cg/include \\\n    -I../.. \\\n    cppad_cg.cpp -o cppad_cg\n#\n# Determine the maximum v index\nv_max_index=`./cppad_cg | sed \\\n    -e '/^ *v\\[[0-9]*\\]/! d' \\\n    -e 's|^ *v\\[\\([0-9]*\\)\\].*|\\1|'  | sort | tail -1`\n#\n#\n# Wrap y = g(x) in C++ function and test it\ncat << EOF > tst_cppad_cg.cpp\n# include <cppad/cppad.hpp>\nnamespace {\n    using CppAD::zdouble;\n    typedef CppAD::vector<zdouble> zvector;\n    //\n    // f(x) = x[0] / x[1] if (x[0] > 0 and x[1] >= x[0]) else 1.0\n    // g(x) = d/dx f(x)\n    void g(const zvector& x, zvector& y)\n    {   zvector v($v_max_index + 1);\nEOF\n./cppad_cg | sed -e 's|^ *|\\t\\t|' >> tst_cppad_cg.cpp\ncat << EOF >> tst_cppad_cg.cpp\n        return;\n    }\n}\nint main(void)\n{   // initialize flag\n    bool   ok   = true;\n    // numerical precision for tests\n    zdouble eps = 10. * std::numeric_limits<double>::epsilon();\n    // number of components in vectors\n    size_t nx    = 2;\n    size_t nz    = 1;\n    size_t ny    = nz * nx;\n    zdouble zero = 0.0;\n    //\n    // compute y = g(x) case where x[0] == 0.0\n    zvector x(nx), y(ny);\n    x[0] = 0.0;\n    x[1] = 0.0;\n    g(x, y);\n    //\n    // check results\n    ok  &= CppAD::NearEqual(y[0], zero, eps, eps);\n    ok  &= CppAD::NearEqual(y[1], zero, eps, eps);\n    //\n    // compute y = g(x) case where g(x) = x[0] / x[1]\n    x[0] = 2.0;\n    x[1] = 3.0;\n    g(x, y);\n    //\n    // check results\n    ok  &= CppAD::NearEqual(y[0], 1.0/x[1], eps, eps);\n    ok  &= CppAD::NearEqual(y[1], -x[0]/(x[1]*x[1]), eps, eps);\n    //\n    if( ! ok )\n        return 1;\n    return 0;\n}\nEOF\n#\n# Compile test\necho_eval g++ \\\n    -g \\\n    -std=c++11 \\\n    -I../.. \\\n    tst_cppad_cg.cpp -o tst_cppad_cg\n#\nif ! ./tst_cppad_cg\nthen\n    file=\"$HOME/install/cppad_cg/build/tst_cppad_cg.cpp\"\n    echo \"install_cppad_cg.sh: Error\"\n    exit 1\nfi\n#\necho 'cppad_cg.sh: OK'\nexit 0\n"
  },
  {
    "path": "bug/doxy_member.sh",
    "content": "#! /bin/bash -e\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# Trying to figure out why ADFun::Forward appears twice where there is only\n# one implementation.\n#\n# ------------------------------------------------------------------------------\n# bash function that echos and executes a command\necho_eval() {\n    echo $*\n    eval $*\n}\n# -----------------------------------------------\necho \"$0\"\nname=`echo $0 | sed -e 's|.*/||' -e 's|\\..*||'`\n# -----------------------------------------------\nfor dir in build doxy_member\ndo\n    if [ ! -e $dir ]\n    then\n        mkdir $dir\n    fi\n    cd $dir\ndone\n# -------------------------------------------------------------------------\ncat << EOF > $name.hpp\n\ntemplate<class T>\nclass my_class {\nprivate:\n    T value_;\npublic:\n    void set_value(T value = 0);\n    T  get_value(void);\n};\nEOF\ncat << EOF > implement.hpp\n/*!\n\\\\file implement.hpp\nImplementation of member functions\n*/\n\n/*!\nMember function that sets the value.\n\n\\\\param value [in]\nNew value.\n*/\ntemplate<class T>\nvoid my_class<T>::set_value(T value)\n{   value_ = value; }\n\n/*!\nMember function that gets the value.\n\n\\\\return\nCurrent value.\n*/\ntemplate<class T>\nT my_class<T>::get_value(void)\n{   return value_; }\nEOF\ncat << EOF > $name.cpp\n# include <iostream>\n# include \"$name.hpp\"\n# include \"implement.hpp\"\nint main(void)\n{   my_class<int> x;\n    x.set_value(2);\n    std::cout << \"x.value = \" << x.get_value() << std::endl;\n    return 0;\n}\nEOF\n# -------------------------------------------------------------------------\n# echo_eval doxygen -g doxyfile\ncp ../../../doxyfile .\nsed \\\n    -e 's|^\\(INPUT *=\\)|& .|' \\\n    -e 's|^\\(FILE_PATTERNS *=\\)|& *.hpp *.cpp|' \\\n    -i doxyfile\n# -------------------------------------------------------------------------\necho_eval doxygen doxyfile\n# -------------------------------------------------------------------------\necho_eval g++ $name.cpp -o name\necho_eval ./name\n"
  },
  {
    "path": "bug/eigen_shadow.sh",
    "content": "#! /bin/bash -e\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# Eigen generates lots of warnings if -Wshadow is set of compile; e.g.,\n# the first warning generated by this script is:\n#\n# warning: declaration of ‘value’ shadows a member of 'this' [-Wshadow]\n#     explicit variable_if_dynamic(T value) : m_value(value) {}\n#                                ^\n# ------------------------------------------------------------------------------\n# bash function that echos and executes a command\necho_eval() {\n    echo $*\n    eval $*\n}\n# -----------------------------------------------\nif [ ! -e build ]\nthen\n    mkdir build\nfi\ncd build\necho \"$0\"\nname=`echo $0 | sed -e 's|.*/||' -e 's|\\..*||'`\n#\ncat << EOF > $name.cpp\n# include <iostream>\n# include <Eigen/Core>\n\nint main() {\n    using Eigen::Matrix;\n    using Eigen::Dynamic;\n    Matrix<double, Dynamic, Dynamic> A(1,1);\n    A(0,0) = 6.0;\n\n    if( A(0,0) != 6.0 )\n    {   std::cout << \"$name: Error\" << std::endl;\n        return 1;\n    }\n    std::cout << \"$name: OK\" << std::endl;\n    return 0;\n}\nEOF\nif [ -e \"$name\" ]\nthen\n    echo_eval rm $name\nfi\necho_eval g++ \\\n    $name.cpp \\\n    -I$HOME/prefix/eigen/include \\\n    -g \\\n    -O0 \\\n    -std=c++11 \\\n    -Wshadow \\\n    -o $name\necho_eval ./$name\n"
  },
  {
    "path": "bug/gcc_complex.sh",
    "content": "#! /bin/bash -e\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\necho_eval() {\n    echo $*\n    eval $*\n}\n# -----------------------------------------------\necho \"create gcc_complex.cpp\"\ncat << EOF > gcc_complex.cpp\n# include <complex>\n# include <iostream>\n# include <limits>\n\nint main(void)\n{   double inf = std::numeric_limits<double>::infinity();\n    std::complex<double> c_inf( inf );\n    std::complex<double> c_1( 1. );\n\n    std::cout << \"c_inf      = \" << c_inf << std::endl;\n    std::cout << \"c_1        = \"   << c_1 << std::endl;\n    std::cout << \"c_inf / c1 = \" << c_inf / c_1 << std::endl;\n\n    return 0;\n}\nEOF\necho_eval g++ gcc_complex.cpp -o gcc_complex\necho_eval ./gcc_complex\ncat << EOF\nExplanation:\n\n(x + i*y)     (x + i*y) * (a - i*b)     (x*a - y*b) + i*(y*a - x*b)\n---------  =  ---------------------  =  ---------------------------\n(a + i*b)     (a + i*b) * (a - i*b)             a*a + b*b\n\nIn our case x = inf, y = 0, a = 1, b = 0, so we have\n\n(x + i*y)    (inf*1 - 0*0) + i*(0*1 - inf*0)\n---------  =  ------------------------------ =  inf - i*nan\n(a + i*b)            1*1 + 0*0\nEOF\necho_eval rm gcc_complex.cpp gcc_complex\n"
  },
  {
    "path": "bug/numeric_limit.sh",
    "content": "#! /bin/bash -e\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\nif [ ! -e ../include/cppad/configure.hpp ]\nthen\n    echo 'numeric_limits.sh: must first run bin/run_cmake.sh'\n    echo 'from parent directory.'\n    exit 1\nfi\ncat << EOF\nThis is not a bug, but rather a test of specialization of numeric_limits\nfor AD types.\nEOF\ncat << EOF > bug.$$\n# include <cppad/cppad.hpp>\n\n/*!\n\\\\def CPPAD_STD_NUMERIC_LIMITS(Other, Base)\nThis macro defines the specialization std::numeric_limits<Base>\nto have the same values and functions as the existing specialization\nstd::numeric_limits<Other>.\n*/\n# define CPPAD_STD_NUMERIC_LIMITS(Other, Base) \\\\\nnamespace std {\\\\\n    template <> class numeric_limits<Base>\\\\\n    {\\\\\n    public:\\\\\n    static const bool is_specialized =\\\\\n        numeric_limits<Other>::is_specialized;\\\\\n    static const bool is_signed =\\\\\n        numeric_limits<Other>::is_signed;\\\\\n    static const bool is_integer =\\\\\n        numeric_limits<Other>::is_integer;\\\\\n    static const bool is_exact =\\\\\n        numeric_limits<Other>::is_exact;\\\\\n    static const bool has_infinity =\\\\\n        numeric_limits<Other>::has_infinity;\\\\\n    static const bool has_quiet_NaN =\\\\\n        numeric_limits<Other>::has_quiet_NaN;\\\\\n    static const bool has_signaling_NaN =\\\\\n        numeric_limits<Other>::has_signaling_NaN;\\\\\n    static const bool has_denorm_loss =\\\\\n        numeric_limits<Other>::has_denorm_loss;\\\\\n    static const bool is_iec559 =\\\\\n        numeric_limits<Other>::is_iec559;\\\\\n    static const bool is_bounded =\\\\\n        numeric_limits<Other>::is_bounded;\\\\\n    static const bool is_modulo =\\\\\n        numeric_limits<Other>::is_modulo;\\\\\n    static const bool traps =\\\\\n        numeric_limits<Other>::traps;\\\\\n    static const bool tinyness_before =\\\\\n        numeric_limits<Other>::tinyness_before;\\\\\n    static const int digits =\\\\\n        numeric_limits<Other>::digits;\\\\\n    static const int digits10 =\\\\\n        numeric_limits<Other>::digits10;\\\\\n    static const int radix =\\\\\n        numeric_limits<Other>::radix;\\\\\n    static const int min_exponent =\\\\\n        numeric_limits<Other>::min_exponent;\\\\\n    static const int min_exponent10 =\\\\\n        numeric_limits<Other>::min_exponent10;\\\\\n    static const int max_exponent =\\\\\n        numeric_limits<Other>::max_exponent;\\\\\n    static const int max_exponent10 =\\\\\n        numeric_limits<Other>::max_exponent10;\\\\\n    static const Base min(void)\\\\\n    {   return static_cast<Base>( numeric_limits<Other>::min() ); }\\\\\n    static const Base max(void)\\\\\n    {   return static_cast<Base>( numeric_limits<Other>::max() ); }\\\\\n    static const Base epsilon(void)\\\\\n    {   return static_cast<Base>( numeric_limits<Other>::epsilon() ); }\\\\\n    static const Base round_error(void)\\\\\n    {   return static_cast<Base>( numeric_limits<Other>::round_error() ); }\\\\\n    static const Base infinity(void)\\\\\n    {   return static_cast<Base>( numeric_limits<Other>::infinity() ); }\\\\\n    static const Base quiet_NaN(void)\\\\\n    {   return static_cast<Base>( numeric_limits<Other>::quiet_NaN() ); }\\\\\n    static const Base signaling_NaN(void)\\\\\n    {   return static_cast<Base>( numeric_limits<Other>::signaling_NaN() ); }\\\\\n    static const Base denorm_min(void)\\\\\n    {   return static_cast<Base>( numeric_limits<Other>::denorm_min() ); }\\\\\n    static const float_denorm_style has_denorm =\\\\\n        numeric_limits<Other>::has_denorm;\\\\\n    static const float_round_style round_style =\\\\\n        numeric_limits<Other>::round_style;\\\\\n    };\\\\\n}\nCPPAD_STD_NUMERIC_LIMITS(double, CppAD::AD<double>)\n\n# define PRINT_VAL(name) \\\\\nstd::cout << #name << \" = \" \\\\\n<< std::numeric_limits< CppAD::AD<double> >::name << std::endl;\n\n# define PRINT_FUN(name) \\\\\nstd::cout << #name << \" = \" \\\\\n<< std::numeric_limits< CppAD::AD<double> >::name() << std::endl;\n\nint main(void)\n{   bool ok = true;\n    //\n    PRINT_VAL(is_specialized)\n    PRINT_VAL(is_signed)\n    PRINT_VAL(is_integer)\n    PRINT_VAL(is_exact)\n    PRINT_VAL(has_infinity)\n    PRINT_VAL(has_quiet_NaN)\n    PRINT_VAL(has_signaling_NaN)\n    PRINT_VAL(has_denorm_loss)\n    PRINT_VAL(is_iec559)\n    PRINT_VAL(is_bounded)\n    PRINT_VAL(is_modulo)\n    PRINT_VAL(traps)\n    PRINT_VAL(tinyness_before)\n    // int\n    PRINT_VAL(digits)\n    PRINT_VAL(digits10)\n    PRINT_VAL(radix)\n    PRINT_VAL(min_exponent)\n    PRINT_VAL(min_exponent10)\n    PRINT_VAL(max_exponent)\n    PRINT_VAL(max_exponent10)\n    // function\n    PRINT_FUN(min)\n    PRINT_FUN(max)\n    PRINT_FUN(epsilon)\n    PRINT_FUN(round_error)\n    PRINT_FUN(infinity)\n    PRINT_FUN(quiet_NaN)\n    PRINT_FUN(signaling_NaN)\n    PRINT_FUN(denorm_min)\n    // other\n    PRINT_VAL(has_denorm)\n    PRINT_VAL(round_style)\n    // C++11 only\n    // PRINT_VAL(max_digits10)\n    // PRINT_FUN(lowest)\n    //\n    if( ok )\n        return 0;\n    return 1;\n}\nEOF\n# -----------------------------------------------------------------------------\nif [ ! -e build ]\nthen\n    mkdir build\nfi\ncd build\necho \"$0\"\nname=`echo $0 | sed -e 's|.*/||' -e 's|\\..*||'`\nmv ../bug.$$ $name.cpp\necho \"g++ -I../.. --std=c++11 -g $name.cpp -o $name\"\ng++ -I../.. --std=c++11 -g $name.cpp -o $name\n#\necho \"./$name\"\nif ! ./$name\nthen\n    echo\n    echo \"$name.sh: Error\"\n    exit 1\nfi\necho\necho \"$name.sh: OK\"\nexit 0\n"
  },
  {
    "path": "bug/pow.sh",
    "content": "#! /bin/bash -e\n# vim: set expandtab:\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\nname=`echo $0 | sed -e 's|^bug/||' -e 's|\\.sh$||'`\nif [ \"$0\" != \"bug/$name.sh\" ]\nthen\n    echo 'usage: bug/pow.sh'\n    exit 1\nfi\n# -----------------------------------------------------------------------------\nif [ -e build/bug ]\nthen\n    rm -r build/bug\nfi\nmkdir -p build/bug\ncd build/bug\n# cmake ../..\n# -----------------------------------------------------------------------------\ncat << EOF\nIssue 43:\nf(x) = (x^0.5) * (x^0.5) = x, and differentiate at x = 0.\nExpect some NaN, Inf, or possibly one, but not zero.\nEOF\ncat << EOF > $name.cpp\n# include <cstdio>\n# include \"cppad/cppad.hpp\"\n\n\nint main(int argc, char** argv)\n{   bool ok = true;\n\n    using std::cout;\n    using CppAD::AD;\n    using CppAD::vector;\n    //\n    vector< double> x(1), y(1), w(1), dw(1);\n    vector< AD<double> > ax(1), ay(1);\n    //\n    ax[0] = 0.0;\n    //\n    CppAD::Independent(ax);\n    ay[0] = pow(ax[0], 0.5) * pow(ax[0], 0.5);\n    CppAD::ADFun<double> f(ax, ay);\n    //\n    x[0]  = 0.0;\n    y     = f.Forward(0, x);\n    w[0]  = 1.0;\n    dw    = f.Reverse(1, w);\n    //\n    cout << \"dw = \" << dw << \"\\n\";\n    //\n    ok &= y[0] == 0.0;\n    ok &= dw[0] == 1.0 || ! std::isfinite( dw[0] );\n    //\n    if( ! ok )\n        return 1;\n    return 0;\n}\nEOF\ncxx_flags='-Wall -pedantic-errors -std=c++11 -Wshadow -Wconversion -g -O0'\neigen_dir=\"$HOME/prefix/eigen/include\"\necho \"g++ -I../../include -isystem $eigen_dir $cxx_flags $name.cpp -o $name\"\ng++ -I../../include -isystem $eigen_dir $cxx_flags $name.cpp -o $name\n#\necho \"build/bug/$name\"\nif ! ./$name\nthen\n    echo\n    echo \"build/bug/$name: Error\"\n    exit 1\nfi\necho\n# -----------------------------------------------------------------------------\necho \"bug/$name.sh: OK\"\nexit 0\n"
  },
  {
    "path": "bug/sparsity.sh",
    "content": "#! /bin/bash -e\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\ngigabytes='1.0'   # memory limit in gigabytes\n# -----------------------------------------------------------------------------\nkilobytes=`echo \"($gigabytes * 10^9) / 1024\" | bc`\nulimit -Sv $kilobytes\ncat << EOF\nThis is testing the idea that\n    vector< std::set<size_t> > sparsity;\nis inefficient compared to\n    vector<size_t> row, col;\nThe results on one system for this script are:\n    ./sparsity set 1e7 elapsed_seconds = 3.62206\n    ./sparsity set 2e7 std::bad_alloc\n    ./sparsity vec 2e7 elapsed_seconds = 1.34243\n    ./sparsity vec 4e7 std::bad_alloc\nEOF\ncat << EOF > bug.$$\n# include <cppad/cppad.hpp>\n\nint main(int argc, char *argv[])\n{   using CppAD::elapsed_seconds;\n    if( argc != 3 )\n    {   std::cerr << \"usage: $0 (set|vec) n\" << std::endl;\n        return 1;\n    }\n    bool set  = std::strcmp(argv[1], \"set\") == 0;\n    bool vec  = std::strcmp(argv[1], \"vec\") == 0;\n    bool ok   = vec || set;\n    if( ! ok )\n    {   std::cerr << \"usage: $0 (set|vec) n\" << std::endl;\n        return 1;\n    }\n    size_t n = size_t( std::atof( argv[2] ) );\n    const char* label;\n    elapsed_seconds();\n    try\n    {\n        if( set )\n        {   std::vector< std::set<size_t> > my_set(n);\n            for(size_t i = 0; i < n; i++)\n                my_set[i].insert(i);\n        }\n        else\n        {   std::vector<size_t> row;\n            std::vector<size_t> col;\n            for(size_t i = 0; i < n; i++)\n            {   row.push_back(i);\n                col.push_back(i);\n            }\n        }\n        for(int i = 0; i < argc; i++)\n            std::cout << argv[i] << \" \";\n        std::cout << \"elapsed_seconds = \" << elapsed_seconds() << std::endl;\n    }\n    catch( std::bad_alloc& bad )\n    {\n        for(int i = 0; i < argc; i++)\n            std::cout << argv[i] << \" \";\n        std::cout << bad.what() << std::endl;\n    }\n    return 0;\n}\nEOF\n# -----------------------------------------------------------------------------\nif [ ! -e build ]\nthen\n    mkdir build\nfi\ncd build\necho \"$0\"\nname=`echo $0 | sed -e 's|.*/||' -e 's|\\..*||'`\nmv ../bug.$$ $name.cpp\necho \"g++ -I../.. -DNDEBUG --std=c++11 $name.cpp -o $name\"\ng++ -I../.. -DNDEBUG --std=c++11 $name.cpp -o $name\n#\n./$name set 1e7\n./$name set 2e7\n./$name vec 2e7\n./$name vec 4e7\n"
  },
  {
    "path": "bug/std_vector.sh",
    "content": "#! /bin/bash -e\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# Using g++ 4.8.1 results in the following error message:\n#\n# std_vector.cpp:8:7: error: no match for ‘operator|=’ (operand types are\n# ‘std::vector<bool>::reference {aka std::_Bit_reference}’ and ‘bool’)\n#  y[1] |= true;\n#     ^\n# -----------------------------------------------------------------------------\nif [ ! -e build ]\nthen\n    mkdir build\nfi\ncd build\necho \"$0\"\nname=`echo $0 | sed -e 's|.*/||' -e 's|\\..*||'`\ncat << EOF > $name.cpp\n# include <vector>\nint main(void)\n{   int N = 1;\n    std::vector<bool> y(N);\n    for(int i = 0; i < N; i++ )\n        y[i] = false;\n    y[0]  = y[0] | true;\n    y[1] |= true;\n    return 0;\n}\nEOF\necho \"g++ -g $name.cpp -o $name\"\ng++ -g $name.cpp -o $name\n#\necho \"./$name\"\n./$name\n#\necho \"rm $name $name.cpp\"\nrm $name $name.cpp\n"
  },
  {
    "path": "bug/subgraph.sh",
    "content": "#! /bin/bash -e\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\nname=`echo $0 | sed -e 's|^bug/||' -e 's|\\.sh$||'`\nif [ \"$0\" != \"bug/$name.sh\" ]\nthen\n    echo 'usage: bug/alloc_global.sh'\n    exit 1\nfi\n# -----------------------------------------------------------------------------\nif [ -e build/bug ]\nthen\n    rm -r build/bug\nfi\nmkdir -p build/bug\ncd build/bug\ncmake ../..\n# -----------------------------------------------------------------------------\ncat << EOF\nDescription: Test for bug in subgraph_jac_rev(x, subset).\nEOF\ncat << EOF > $name.cpp\n# include <cppad/cppad.hpp>\nint main(void)\n{   bool ok = true;\n    using std::cout;\n    using CppAD::AD;\n    using CppAD::vector;\n    typedef vector<double> d_vector;\n    typedef vector<size_t> s_vector;\n    //\n    size_t n = 4;\n    d_vector x(n);\n    vector< AD<double> > ax(n), ay(n);\n    for(size_t j = 0; j < n; ++j)\n        ax[j] = x[j] = double(j);\n    CppAD::Independent(ax);\n    for(size_t i = 0; i < n; ++i)\n    {   ay[i] = 0.0;\n        for(size_t j = 0; j < n; ++j)\n            ay[i] += double(i + j + 1) * ax[j];\n    }\n    CppAD::ADFun<double> f(ax, ay);\n    //\n    size_t nnz = (n * (n + 1)) / 2;\n    CppAD::sparse_rc<s_vector> upper_triangle(n, n, nnz);\n    size_t k = 0;\n    for(size_t i = 0; i < n; ++i)\n    {   for(size_t j = i; j < n; ++j)\n            upper_triangle.set(k++, i, j);\n    }\n    ok &= k == nnz;\n    CppAD::sparse_rcv<s_vector, d_vector> subset( upper_triangle );\n    //\n    f.subgraph_jac_rev(x, subset);\n    const d_vector& val = subset.val();\n    k = 0;\n    for(size_t i = 0; i < n; ++i)\n    {   for(size_t j = i; j < n; ++j)\n            ok &= val[k++] == double(i + j + 1);\n    }\n    ok &= k == nnz;\n    //\n    if( ok )\n        return 0;\n    return 1;\n}\nEOF\ncxx_flags='-Wall -pedantic-errors -std=c++11 -Wshadow -Wconversion -g -O0'\necho \"g++ -I../../include $cxx_flags $name.cpp -o $name\"\ng++ -I../../include $cxx_flags $name.cpp -o $name\n#\necho \"build/bug/$name\"\nif ! ./$name\nthen\n    echo\n    echo \"build/bug/$name: Error\"\n    exit 1\nfi\necho\n# -----------------------------------------------------------------------------\necho \"bug/$name.sh: OK\"\nexit 0\n"
  },
  {
    "path": "bug/template.sh",
    "content": "#! /usr/bin/env bash\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-25 Bradley M. Bell\n# -----------------------------------------------------------------------------\nset -e -u\n#\n# bash function that echos and executes a command\necho_eval() {\n    echo $*\n    eval $*\n}\n# -----------------------------------------------------------------------------\n#\n# name\nname=`echo $0 | sed -e 's|^bug/||' -e 's|\\.sh$||'`\nif [ \"$0\" != \"bug/$name.sh\" ]\nthen\n    echo \"usage: bug/$name.sh\"\n    exit 1\nfi\n#\n# PKG_CONFIG_PATH, LD_LIBRARY_PATH\nprefix=\"$(pwd)/build/prefix\"\nexport PKG_CONFIG_PATH=\"$prefix/share/pkgconfig\"\nexport LD_LIBRARY_PATH=\"\"\nfor subdir in  'lib' 'lib64'\ndo\n    PKG_CONFIG_PATH+=\":$prefix/$subdir/pkgconfig\"\n    LD_LIBRARY_PATH+=\";$prefix/$subdir\"\ndone\n#\n# eigen_flags\neigen_flags=$(pkg-config -cflags eigen3)\n#\n# ipopt_flags\nipopt_flags=$(pkg-config -cflags ipopt | sed -e 's|/coin-or | |' )\n#\n# link_flags\nlink_flags=$(pkg-config -libs cppad)\n#\n# extra_flags\nextra_flags='-Wall -pedantic-errors -std=c++11 -Wshadow -Wconversion -g -O0'\n#\n# build/bug\nif [ -e build/bug ]\nthen\n    rm -r build/bug\nfi\nmkdir -p build/bug\ncd build/bug\n#\n# $name.cpp\ncat << EOF > $name.cpp\n# include <cppad/cppad.hpp>\nint main(void)\n{   bool ok = true;\n    using std::cout;\n    using CppAD::AD;\n    using CppAD::vector;\n    //\n    cout << \"Choose a name for this bug (called name below)\\n\";\n    cout << \"1. Copy bug/template.sh to bug/name.sh\\n\";\n    cout << \"2. Edit bug/name.sh replacing C++ source code\\n\";\n    cout << \"3. Run bug/name.sh\\n\";\n    cout << \"Test passes (fails) if bug/name.sh: OK (Error) echoed at end\\n\";\n    //\n    if( ok )\n        return 0;\n    return 1;\n}\nEOF\n#\n# $name\ncmd=\"\n    g++\n    $name.cpp\n    -I../../include\n    $extra_flags\n    $eigen_flags\n    $ipopt_flags\n    -o $name\n    $link_flags\n\"\n#\n$cmd\n#\necho \"build/bug/$name\"\nif ! ./$name\nthen\n    echo\n    echo \"build/bug/$name: Error\"\n    echo \"export LD_LIBRARY_PATH='$LD_LIBRARY_PATH'\"\n    exit 1\nfi\necho\n# -----------------------------------------------------------------------------\necho \"bug/$name.sh: OK\"\nexit 0\n"
  },
  {
    "path": "bug/test_install.sh",
    "content": "#! /bin/bash -e\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\ncat << EOF\nThis is not a bug but rather a test of installing with\n    cppad_prefix=$HOME/prefix\nEOF\ncat << EOF > bug.$$\n# include <cppad/cppad.hpp>\nint main(void)\n{   bool ok = true;\n    using std::cout;\n    using CppAD::AD;\n    //\n    CPPAD_TESTVECTOR( AD<double> ) ax(1), ay(1);\n    ax[0] = 1.0;\n    CppAD::Independent(ax);\n    ay[0] = sin( ax[0] );\n    CppAD::ADFun<double> f(ax, ay);\n    //\n    std::vector< std::set<size_t> > p(1);\n    p[0].insert(0);\n    CppAD::vector< size_t > row(1), col(1);\n    row[0] = 0;\n    col[0] = 0;\n    CppAD::sparse_jacobian_work work;\n    work.color_method = \"colpack\";\n    CPPAD_TESTVECTOR(double) x(1), jac(1);\n    x[0] = 2.0;\n    f.SparseJacobianForward(x, p, row, col, jac, work);\n    //\n    ok  &= jac[0] == std::cos( x[0] );\n    //\n    if( ok )\n        return 0;\n    return 1;\n}\nEOF\n# -----------------------------------------------------------------------------\nif [ ! -e build ]\nthen\n    mkdir build\nfi\ncd build\necho \"$0\"\nname=`echo $0 | sed -e 's|.*/||' -e 's|\\..*||'`\nmv ../bug.$$ $name.cpp\ncmd=\"g++ -I $HOME/prefix/cppad/include --std=c++11 -g $name.cpp -o $name\"\ncmd=\"$cmd -L $HOME/prefix/cppad/lib64 -lcppad_lib\"\ncmd=\"$cmd -L $HOME/prefix/colpack/lib64 -lColPack\"\necho \"$cmd\"\neval $cmd\n#\necho \"./$name\"\nif ! ./$name\nthen\n    echo\n    echo \"$name.sh: Error\"\n    exit 1\nfi\necho\necho \"$name.sh: OK\"\nexit 0\n"
  },
  {
    "path": "bug/vec_itr_speed.sh",
    "content": "#! /bin/bash -e\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\nname=`echo $0 | sed -e 's|^bug/||' -e 's|\\.sh$||'`\nerror='none'\nif [ \"$0\" != \"bug/$name.sh\" ]\nthen\n    echo \"program name is not bug/$name.sh\"\n    ok='no'\nfi\ncompiler=\"$1\"\nif [ \"$compiler\" != 'g++' ] && [ \"$compiler\" != 'clang++' ]\nthen\n    if [ \"$compiler\" != '' ]\n    then\n        echo 'compiler is not g++ or clang++'\n    fi\n    ok='no'\nfi\ndebug=\"$2\"\nif [ \"$debug\" != 'yes' ] && [ \"$debug\" != 'no' ]\nthen\n    if [ \"$debug\" != '' ]\n    then\n        echo 'debug is not yes or no'\n    fi\n    ok='no'\nfi\nopt_level=\"$3\"\nif [[ \"$opt_level\" =~ \"[^0-3]\" ]]\nthen\n    if [ \"$opt_level\" != '' ]\n    then\n        echo 'opt_level is not 0, 1, 2, or 3'\n    fi\n    ok='no'\nfi\nif [ \"$ok\" == 'no' ]\nthen\n    echo\n    echo \"usage: bug/$name.sh compiler debug opt_level\"\n    echo 'compiler is:  g++ or clang++'\n    echo 'debug is:     yes or no'\n    echo 'opt_level is: 0, 1, 2, or 3.'\n    exit 1\nfi\n# -----------------------------------------------------------------------------\nif [ -e build/bug ]\nthen\n    rm -r build/bug\nfi\nmkdir -p build/bug\ncd build/bug\n# cmake ../..\n# -----------------------------------------------------------------------------\ncat << EOF\nThis is speed test (not a bug report) comparing the speed using CppAD vector\niterators and raw pointer with the algorithms std::sort and std::reverse.\nEOF\ncat << EOF > $name.cpp\n# include <cppad/utility/vector.hpp>\n# include <cppad/utility/time_test.hpp>\nnamespace {\n    // declared here so setup does not include allocation\n    CppAD::vector<size_t> vec;\n    // ----------------------------------------------------------------------\n    // sort test functions\n    void sort_itr(size_t size, size_t repeat)\n    {   // size and vec.size() are equal\n        size_t* data = vec.data();\n        while( repeat-- )\n        {   // sort a vector that is not in order\n            for(size_t i = 0; i < size; ++i)\n                data[i] = (size - i) % 21;\n            std::sort(vec.begin(), vec.end());\n        }\n    }\n    void sort_ptr(size_t size, size_t repeat)\n    {   // size and vec.size() are equal\n        size_t* data = vec.data();\n        while( repeat-- )\n        {   // sort same vector as in sort_itr\n            for(size_t i = 0; i < size; ++i)\n                data[i] = (size - i) % 21;\n            std::sort(vec.data(), vec.data() + vec.size());\n        }\n    }\n    // ----------------------------------------------------------------------\n    // reverse test functions\n    void reverse_itr(size_t size, size_t repeat)\n    {   // size and vec.size() are equal\n        size_t* data = vec.data();\n        while( repeat-- )\n        {   // reverse a vector that is not in order\n            for(size_t i = 0; i < size; ++i)\n                data[i] = i;\n            std::reverse(vec.begin(), vec.end());\n        }\n    }\n    void reverse_ptr(size_t size, size_t repeat)\n    {   // size and vec.size() are equal\n        size_t* data = vec.data();\n        while( repeat-- )\n        {   // reverse same vector as in reverse_itr\n            for(size_t i = 0; i < size; ++i)\n                data[i] = i;\n            std::reverse(vec.data(), vec.data() + vec.size());\n        }\n    }\n}\nint main(void)\n{   bool ok = true;\n    using CppAD::time_test;\n    using std::cout;\n    //\n    size_t test_size = 100000; // size of vector in test\n    double time_min  = 1.0;    // minimum time in seconds for each test\n    vec.resize(test_size);     // allocate memory outsize of test\n    size_t repeat;             // output by time_test function\n    // -----------------------------------------------------------------------\n    // sort tests\n    //\n    // iterator\n    double sort_itr_sec  = time_test(sort_itr, time_min, test_size, repeat);\n    for(size_t i = 1; i < test_size; ++i)\n        ok &= vec[i-1] <= vec[i];\n    cout << \"sort_itr_sec=\" << sort_itr_sec << \", repeat=\" << repeat << \"\\n\";\n    //\n    // pointer\n    double sort_ptr_sec  = time_test(sort_ptr, time_min, test_size, repeat);\n    for(size_t i = 1; i < test_size; ++i)\n        ok &= vec[i-1] <= vec[i];\n    cout << \"sort_ptr_sec=\" << sort_ptr_sec << \", repeat=\" << repeat << \"\\n\";\n    // -----------------------------------------------------------------------\n    // reverse tests\n    //\n    // iterator\n    double rev_itr_sec  = time_test(reverse_itr, time_min, test_size, repeat);\n    for(size_t i = 1; i < test_size; ++i)\n        ok &= vec[i] == test_size - 1 - i;\n    cout << \"rev_itr_sec=\" << rev_itr_sec << \", repeat=\" << repeat << \"\\n\";\n    //\n    // pointer\n    double rev_ptr_sec  = time_test(reverse_ptr, time_min, test_size, repeat);\n    for(size_t i = 1; i < test_size; ++i)\n        ok &= vec[i] == test_size - 1 - i;\n    cout << \"rev_ptr_sec=\" << rev_ptr_sec << \", repeat=\" << repeat;\n    // -----------------------------------------------------------------------\n    if( ok )\n        return 0;\n    return 1;\n}\nEOF\ncxx_flags=\"-Wall -std=c++11 -Wshadow -Wconversion -O$opt_level\"\nif [ \"$debug\" == 'no' ]\nthen\n    cxx_flags=\"$cxx_flags -DNDEBUG\"\nfi\necho \"$compiler -I../../include $cxx_flags $name.cpp -o $name\"\n$compiler -I../../include $cxx_flags $name.cpp -o $name\n#\necho \"build/bug/$name\"\nif ! ./$name\nthen\n    echo\n    echo \"build/bug/$name: Error\"\n    exit 1\nfi\necho\n# -----------------------------------------------------------------------------\necho \"bug/$name.sh: OK\"\nexit 0\n"
  },
  {
    "path": "cmake/add_check_executable.cmake",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# add_check_executable(parent_target short_name)\n# add_check_executable(parent_target short_name arguments)\n#\n# parent_target: (in)\n# The variable containing the name of the parent check target,\n# ${parent_target} must begin with \"check\".\n#\n# short_name: (in)\n# Is the non-empty short name of the target we are adding.\n# The full name of this target is ${parent_target}_${short_name}.\n#\n# arguments: (in)\n# This argument is optional. If it is present, it is\n# a string containing the arguments to the executable.\n#\n# 1. This macro creates the target ${parent_target}_${short_name}.\n# 2. This target depends on an executable with the same name except that\n#    the \"check_\" at the beginning is removed.\n# 3. If the variable ${parent_target}_${short_name}_depends is defined,\n#    it is a list that is included in the dependencies for this target.\n# 4. This target is add to the list ${parent_target}_depends in both\n#    the current scope and its parent scope.\n#\n# This macros uses temporary variables with names that begin with\n# add_check_executable_.\n#\nMACRO(add_check_executable parent_target short_name)\n    IF( NOT ${parent_target} MATCHES \"^check\" )\n        MESSAGE(FATAL_ERROR \"add_check_executable: \"\n            \"parent_target does not begin with 'check'\"\n        )\n    ENDIF( )\n    IF( \"${short_name}\" STREQUAL \"\" )\n        MESSAGE(FATAL_ERROR \"add_check_target: short_name is empty\")\n    ENDIF( )\n    #\n    # add_check_executable_full_name\n    SET(add_check_executable_full_name \"${parent_target}_${short_name}\" )\n    #\n    # add_check_executable_no_check\n    STRING(REGEX REPLACE \"^check_\" \"\" add_check_executable_no_check\n        \"${add_check_executable_full_name}\"\n    )\n    #\n    # add_check_executable_arguments\n    IF( ${ARGC} EQUAL 2 )\n        SET(add_check_executable_arguments \"\")\n    ELSEIF( ${ARGC} EQUAL 3 )\n        STRING(\n            REGEX REPLACE \"[ ]\" \";\" add_check_executable_arguments \"${ARGV2}\"\n        )\n    ELSE( )\n        MESSAGE(FATAL_ERROR \"add_check_executable: \"\n            \"number of arguments = ${ARGC}\"\n        )\n    ENDIF( )\n    #\n    # add_check_executable_depends\n    IF( DEFINED ${add_check_executable_full_name}_depends )\n        SET(add_check_executable_depends\n            ${${add_check_executable_full_name}_depends}\n        )\n        add_to_list(add_check_executable_depends\n            ${add_check_executable_no_check}\n        )\n    ELSE ( )\n        SET(add_check_executable_depends ${add_check_executable_no_check} )\n    ENDIF( )\n    #\n    # create this target\n    ADD_CUSTOM_TARGET(\n        ${add_check_executable_full_name}\n        ${add_check_executable_no_check}\n        ${add_check_executable_arguments}\n        DEPENDS ${add_check_executable_depends}\n    )\n    IF( \"${CMAKE_GENERATOR}\" STREQUAL \"Ninja\" )\n        SET(make_cmd \"ninja\" )\n    ELSEIF( \"${CMAKE_GENERATOR}\" STREQUAL \"NMake Makefiles\" )\n        SET(make_cmd \"nmake\" )\n    ELSE( )\n        SET(make_cmd \"make\" )\n    ENDIF( )\n    MESSAGE(STATUS \"${make_cmd} ${add_check_executable_full_name}: available\")\n    #\n    # add parent dependency\n    add_to_list( ${parent_target}_depends ${add_check_executable_full_name} )\n    SET( ${parent_target}_depends ${${parent_target}_depends} PARENT_SCOPE )\n    #\nENDMACRO()\n"
  },
  {
    "path": "cmake/add_to_list.cmake",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# =============================================================================\n# add_to_list(variable_list constant_value)\n#\n# variables_list: (in/out)\n# The variable containing the list of values.\n# The original list may be \"\"; i.e., the empty list.\n#\n# constant_value: (in)\n# Is the value we are adding to the list. This value cannot be empty.\n#\nMACRO(add_to_list variable_list constant_value )\n      IF( \"${${variable_list}}\" STREQUAL \"\" )\n             SET( ${variable_list} ${constant_value} )\n      ELSE( \"${${variable_list}}\" STREQUAL \"\" )\n             SET( ${variable_list} ${${variable_list}} ${constant_value} )\n      ENDIF( \"${${variable_list}}\" STREQUAL \"\" )\nENDMACRO(add_to_list)\n"
  },
  {
    "path": "cmake/assert.cmake",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# =============================================================================\n# assert(variable)\n#\n# variable: (in)\n# The variable is checked to make sure it is true, and if it is not true\n# a fatal error message is printed.\n#\nMACRO(assert variable)\n      IF( NOT ${variable} )\n        MESSAGE(FATAL_ERROR\n            \"Error: ${variable} is false in ${CMAKE_CURRENT_LIST_FILE}\"\n        )\n      ENDIF( NOT ${variable} )\nENDMACRO(assert)\n"
  },
  {
    "path": "cmake/assert_value_in_set.cmake",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# assert_value_in_set(value element_1 ... element_n )\n#\n# value: (in)\n# is the value we are searching for.\n#\n# element_j: (in)\n# is the j-th element of the set.\n#\nMACRO(assert_value_in_set)\n    SET(argv ${ARGV})\n    LIST(GET argv 0 value)\n    LIST(REMOVE_AT argv 0)\n    SET(ok FALSE)\n    FOREACH(entry ${argv} )\n        IF( \"${${value}}\" STREQUAL \"${entry}\" )\n            SET(ok TRUE)\n        ENDIF( \"${${value}}\" STREQUAL \"${entry}\" )\n    ENDFOREACH(entry ${argv} )\n    IF(NOT ok)\n        MESSAGE(FATAL_ERROR\n            \"${value} is not one of following: ${argv}\"\n        )\n    ENDIF(NOT ok)\nENDMACRO(assert_value_in_set)\n"
  },
  {
    "path": "cmake/command_line_arg.cmake",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# command_line_arg(variable default type description)\n#\n# variable: (out)\n# is the variable we are setting to its default value.\n# The variable can be changed on the cmake command line (or in the camke gui).\n# The final value of the variable is printed with the cmake output.\n#\n# default: (in)\n# is the default value for this variable; i.e.,\n# if it is not set by the cmake command line or gui.\n#\n# type: (in)\n# must be one of the following:\n#  STRING, if the variable holds an arbitrary string.\n#  PATH, if the variable holds a directory.\n#  BOOL, if the variable only has the values true or false.\n#\n# description: (in)\n# Is a description of how the variable affects the CppAD install procedure.\n#\nMACRO(command_line_arg variable default type description)\n    IF( NOT ( ${type} STREQUAL \"STRING\" ) )\n    IF( NOT ( ${type} STREQUAL \"PATH\" ) )\n    IF( NOT ( ${type} STREQUAL \"BOOL\" ) )\n        MESSAGE(FATAL_ERROR, \"command_line_arg: bug in CppAD cmake commands\")\n    ENDIF( NOT ( ${type} STREQUAL \"BOOL\" ) )\n    ENDIF( NOT ( ${type} STREQUAL \"PATH\" ) )\n    ENDIF( NOT ( ${type} STREQUAL \"STRING\" ) )\n    #\n    IF( NOT ${variable} )\n        SET(${variable} \"${default}\" CACHE ${type} \"${description}\")\n    ENDIF( NOT ${variable} )\n    MESSAGE(STATUS \"${variable} = ${${variable}}\")\n    #\nENDMACRO( command_line_arg )\n"
  },
  {
    "path": "cmake/compile_source_test.cmake",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-25 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# compile_source_test(defined_ok source variable)\n#\n# defined_ok (in)\n# If this is true, it is OK for variable to be defined on input\n# (it will be replaced). Otherwise it is a fatal error if variable\n# is defined on input.\n#\n# source: (in)\n# contains the source for the program that will be compiled and linked.\n#\n# variable: (out)\n# Upon return, the value of this variable is 1 (0) if the program compiles\n# and links (does not compile and link).\n#\n# CMAKE_REQUIRED_name (in)\n# For name equal to DEFINITIONS, INCLUDES, LIBRARIES, FLAGS, the variable\n# CMAKE_REQUIRED_name is an input to routine; see CHECK_CXX_SOURCE_COMPILES\n# documentation.\n#\nMACRO(compile_source_test defined_ok source variable)\n    #\n    #\n    # check that variable is not yet defined\n    IF( NOT ${defined_ok} )\n        IF( DEFINED ${variable} )\n            MESSAGE(FATAL_ERROR\n                \"compile_source_test: ${variable} is defined before expected\"\n            )\n        ENDIF( DEFINED ${variable} )\n    ENDIF( NOT ${defined_ok} )\n    #\n    SET(CMAKE_REQUIRED_DEFINITIONS \"\" )\n    SET(CMAKE_REQUIRED_INCLUDES    \"\" )\n    SET(CMAKE_REQUIRED_LIBRARIES   \"\" )\n    IF( cppad_cxx_flags )\n        SET(CMAKE_REQUIRED_FLAGS   \"${cppad_cxx_flags} ${CMAKE_CXX_FLAGS}\" )\n    ELSE( cppad_cxx_flags )\n        SET(CMAKE_REQUIRED_FLAGS   \"\" )\n    ENDIF( cppad_cxx_flags )\n    #\n    # check that source code compiles\n    CHECK_CXX_SOURCE_COMPILES(\"${source}\" ${variable} )\n    #\n    # change result variable to 0 (1) for fail (succeed).\n    IF( ${variable} )\n        SET(${variable} 1)\n    ELSE( ${variable} )\n        SET(${variable} 0)\n    ENDIF( ${variable} )\n    #\n    # check that variable is defined\n    IF( NOT DEFINED ${variable} )\n        MESSAGE(FATAL_ERROR\n            \"compile_source_test: error in CMake script.\"\n        )\n    ENDIF( NOT DEFINED ${variable} )\n    #\n    MESSAGE(STATUS \"${variable} = ${${variable}}\" )\nENDMACRO( compile_source_test )\n"
  },
  {
    "path": "cmake/cppad_uninstall.cmake",
    "content": "# Copyright (C) 2010 Olivier Stasse, JRL, CNRS, 2010\n#\n# Original source:\n# https://github.com/jrl-umi3218/jrl-cmakemodules/blob/master/cmake_uninstall.cmake.in\n#\n# Contributor\n# https://jcarpent.github.io/\n#\n# This program is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\nset(MANIFEST \"${CMAKE_CURRENT_BINARY_DIR}/install_manifest.txt\")\n\nif(EXISTS ${MANIFEST})\n  file(STRINGS ${MANIFEST} files)\n  foreach(file ${files})\n    if(IS_SYMLINK ${file} OR EXISTS ${file})\n        message(STATUS \"Removing file: '${file}'\")\n\n        execute_process(\n        COMMAND ${CMAKE_COMMAND} -E remove ${file}\n        OUTPUT_VARIABLE rm_out\n        RESULT_VARIABLE rm_retval\n        )\n\n        if(NOT \"${rm_retval}\" STREQUAL 0)\n        message(FATAL_ERROR \"Failed to remove file: '${file}'.\")\n        endif()\n    else()\n        message(STATUS \"File '${file}' does not exist.\")\n    endif()\n  endforeach(file)\nelse()\n  message(FATAL_ERROR \"Cannot find install manifest: ${MANIFEST}\")\nendif()\n"
  },
  {
    "path": "cmake/dos_path_to_unix.cmake",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# dos_path_to_unix(dos_path unix_path)\n#\n# dos_path: (in)\n# is the value of the path we are converting to unix format; i.e.,\n# all \\ characters are replaced by / characters.\n#\n# unix_path: (out)\n# is the variable where the result of the conversion is placed.\n#\nMACRO(dos_path_to_unix dos_path unix_path)\n    STRING(REGEX REPLACE \"[\\\\]\" \"/\" ${unix_path} \"${dos_path}\" )\nENDMACRO(dos_path_to_unix dos_path unix_path)\n"
  },
  {
    "path": "cmake/eigen_info.cmake",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# eigen_info()\n#\n# cppad_has_eigen: (out)\n# is 1 (0) if eigen is found (not found)\n# If this is 1, the include directory for eigen will automatically be\n# added using INCLUDE_DIRECTORIES with the SYSTEM flag.\n#\n# eigen_LINK_LIBRARIES: (out)\n# if cppad_has_eigen is 1,\n# is a list of absolute paths to libraries necessary to use eigen\n# (should be empty because eigen is a header only library).\n#\n# This macro may use variables with the name eigen_*\nMACRO(eigen_info)\n    #\n    # check for pkg-config\n    IF( NOT PKG_CONFIG_FOUND )\n        FIND_PACKAGE(PkgConfig REQUIRED)\n    ENDIF( )\n    #\n    #\n    IF( NOT ${use_cplusplus_2014_ok} )\n        MESSAGE(STATUS \"Eigen not supportedL: because c++14 not supported\")\n        SET(cppad_has_eigen 0)\n    ELSE( )\n        #\n        # eigen_*\n        pkg_check_modules(eigen QUIET eigen3 )\n        #\n        IF( eigen_FOUND )\n            MESSAGE(STATUS \"Eigen found\")\n            SET(cppad_has_eigen 1)\n            INCLUDE_DIRECTORIES( SYSTEM ${eigen_INCLUDE_DIRS} )\n        ELSE( )\n            MESSAGE(STATUS \"Eigen not Found: eigen3.pc not in PKG_CONFIG_PATH\")\n            SET(cppad_has_eigen 0)\n        ENDIF( )\n    ENDIF( )\n    #\n    print_variable( cppad_has_eigen )\nENDMACRO(eigen_info)\n"
  },
  {
    "path": "cmake/pkgconfig_info.cmake",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-26 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# pkgconfig_info(package system_include)\n#\n# package: (in)\n# is the name of an optional package.\n#\n# system_include: (in)\n# If this is true (false), the include directories for this package will\n# (will not) be treated as system directories (no warnings).\n#\n# include_${package}: (in)\n# is set by this macro to a cache BOOL variable initialized as false.\n# It can be changed by the cmake command line or gui.\n# If it is true, there must be a pkg-config file for this package and\n# the corresponding include directories added using INCLUDE_DIRECTORIES.\n#\n# cppad_has_${package}: (out)\n# is 1 (0) if include_${package} is true (false).\n#\n# ${package}_LINK_LIBRARIES: (out)\n# is a list of absolute paths to libraries necessary to use this package.\n#\n# This macros uses temporary variables with names that begin with\n# pkgconfig_info_ and ${package}_.\n#\nMACRO(pkgconfig_info package system_include)\n    #\n    # include_${package}\n    SET(\n        include_${package}\n        FALSE CACHE BOOL \"include ${package} using its pkgconfig file\"\n    )\n    print_variable( include_${package} )\n    IF( NOT include_${package} )\n        SET(cppad_has_${package} 0)\n    ELSE( )\n        SET(cppad_has_${package} 1)\n        #\n        # check for pkg-config\n        IF( NOT PKG_CONFIG_FOUND )\n            FIND_PACKAGE(PkgConfig REQUIRED)\n        ENDIF( )\n        #\n        # ${package} info\n        pkg_check_modules(\n            ${package} QUIET ${package} )\n        #\n        IF( ${package}_FOUND )\n            MESSAGE(STATUS \"Found ${package} pkg-config file\")\n        ELSE( )\n            MESSAGE(FATAL_ERROR\n            \"Can't find ${package} pkg-config file or one of its requirements.\"\n            \"\\nPKG_CONFIG_PATH=$ENV{PKG_CONFIG_PATH}\"\n        )\n        ENDIF( )\n        #\n        IF( ${package} STREQUAL eigen )\n            SET( eigen_LIBRARIES \"${eigen3_LIBRARIES}\" )\n        ENDIF()\n        #\n        # pkgconfig_info_dirs\n        STRING(\n            REGEX REPLACE \"/coin-or\" \"\"\n            pkgconfig_info_dirs \"${${package}_INCLUDE_DIRS}\"\n        )\n        #\n        # INCLUDE_DIRECTORIES\n        IF( ${system_include} )\n            INCLUDE_DIRECTORIES( SYSTEM ${pkgconfig_info_dirs} )\n        ELSE( )\n            INCLUDE_DIRECTORIES( ${pkgconfig_info_dirs} )\n        ENDIF( )\n    ENDIF( )\n    #\n    print_variable( cppad_has_${package} )\nENDMACRO(pkgconfig_info)\n"
  },
  {
    "path": "cmake/prefix_info.cmake",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# prefix_info(package system_include)\n#\n# package: (in)\n# is the name of an optional package.\n#\n# system_include: (in)\n# If this is true (false), the include directories for this package will\n# (will not) be treated as system directories (no warnings).\n#\n# ${package}_prefix: (in)\n# is set by this macro to a cache PATH variable initialized as NOTFOUND.\n# It can be changed by the cmake command line or gui.\n# If it is changed, it holds the install prefix for this package.\n#\n# cppad_has_${package}: (out)\n# is 1 if ${package}_prefix is changed by the cmake command line or gui,\n# and 0 otherwise.\n#\n# If ${package}_prefix is changed, the following are done:\n# 1. All the valid include subdirectories are added using INCLUDE_DIRECTORIES.\n#    Valid include subdirectories are determined by cmake_install_includedirs.\n# 2. All the valid library subdirectories are added using LINK_DIRECTORIES.\n#    Valid library subdirectories are determined by cmake_install_libdirs.\n#\n# This macros uses temporary variables with names that begin with\n# prefix_info_.\n#\nMACRO(prefix_info package system_include)\n    #\n    # ${package}_prefix\n    SET(${package}_prefix NOTFOUND CACHE PATH \"${package} install prefix\")\n    #\n    # prefix_info_value\n    SET( prefix_info_value \"${${package}_prefix}\" )\n    #\n    SET(cppad_has_${package} 1)\n    #\n    IF( \"${prefix_info_value}\" STREQUAL \"NOTFOUND\" )\n        SET(cppad_has_${package} 0)\n    ENDIF( )\n    #\n    IF( \"${prefix_info_value}\" STREQUAL \"\" )\n        SET(cppad_has_${package} 0)\n    ENDIF( )\n    #\n    IF( cppad_has_${package} )\n        SET(cppad_has_${package} 0)\n        #\n        # prefix_info_subdir\n        FOREACH(prefix_info_subdir ${cmake_install_includedirs})\n            #\n            # prefix_info_dir\n            SET( prefix_info_dir \"${prefix_info_value}/${prefix_info_subdir}\" )\n            IF(IS_DIRECTORY \"${prefix_info_dir}\" )\n                SET(cppad_has_${package} 1)\n                MESSAGE(STATUS \"    Found ${prefix_info_dir}\")\n                IF( ${system_include} )\n                    INCLUDE_DIRECTORIES( SYSTEM \"${prefix_info_dir}\" )\n                ELSE( )\n                    INCLUDE_DIRECTORIES( \"${prefix_info_dir}\" )\n                ENDIF( )\n            ENDIF( )\n        ENDFOREACH( )\n        #\n        # prefix_info_subdir\n        FOREACH(prefix_info_subdir ${cmake_install_libdirs})\n            #\n            # prefix_info_dir\n            SET( prefix_info_dir \"${prefix_info_value}/${prefix_info_subdir}\" )\n            IF(IS_DIRECTORY \"${prefix_info_dir}\" )\n                SET(cppad_has_${package} 1)\n                MESSAGE(STATUS \"    Found ${prefix_info_dir}\")\n                LINK_DIRECTORIES( \"${prefix_info_dir}\" )\n            ENDIF( )\n        ENDFOREACH()\n        IF( NOT cppad_has_${package} )\n            MESSAGE(FATAL_ERROR\n                \"cppad_has_${package} = ${prefix_info_value} \"\n                \"but did not find any include files or libraries there\"\n            )\n        ENDIF( )\n    ENDIF( )\n    #\n    print_variable( cppad_has_${package} )\nENDMACRO( )\n"
  },
  {
    "path": "cmake/print_variable.cmake",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# =============================================================================\n# print_variable(variable)\n#\n# variable: (in)\n# The variable name and value is printed\n#\nMACRO(print_variable variable)\n    MESSAGE(STATUS \"${variable} = ${${variable}}\" )\nENDMACRO(print_variable)\n"
  },
  {
    "path": "cmake/run_source_test.cmake",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# run_source_test(source variable)\n#\n# source: (in)\n# contains the source for the program that will be run.\n#\n# variable: (out)\n# This variable must not be defined when this macro is called.\n# Upon return, the value of this variable is 1 if the program runs and\n# returns a zero status. Otherwise its value is 0.\n# Note that this is the reverse of the status flag returned by the program.\n#\n# CMAKE_REQUORED_name (out)\n# For name equal to DEFINITIONS, INCLUDES, LIBRARIES, FLAGS, the variable\n# CMAKE_REQUIRED_name is set to the empty string.\n#\nMACRO(run_source_test source variable)\n    IF( DEFINED ${variable} )\n        MESSAGE(ERROR\n            \"run_source_test: ${variable} is defined before expected\"\n        )\n    ENDIF( DEFINED ${variable} )\n    SET(CMAKE_REQUIRED_DEFINITIONS \"\" )\n    SET(CMAKE_REQUIRED_INCLUDES    \"\" )\n    SET(CMAKE_REQUIRED_LIBRARIES   \"\" )\n    IF( cppad_cxx_flags )\n        SET(CMAKE_REQUIRED_FLAGS   \"${cppad_cxx_flags} ${CMAKE_CXX_FLAGS}\" )\n    ELSE( cppad_cxx_flags )\n        SET(CMAKE_REQUIRED_FLAGS   \"\" )\n    ENDIF( cppad_cxx_flags )\n    CHECK_CXX_SOURCE_RUNS(\"${source}\" ${variable} )\n    IF( ${variable} )\n        SET(${variable} 1)\n    ELSE( ${variable} )\n        SET(${variable} 0)\n    ENDIF( ${variable} )\n    MESSAGE(STATUS \"${variable} = ${${variable}}\" )\n    #\n    SET(CMAKE_REQUIRED_FLAGS        \"\" )\nENDMACRO( run_source_test )\n"
  },
  {
    "path": "cmake/set_compile_flags.cmake",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# set_compile_flags( program_name debug_which source_list)\n#\n# program_name: (in)\n# Is the name of the program that we are building. This is only used\n# for debugging which files have debug and which have release properties.\n#\n# debug_which: (in)\n# Is one of the following cases:\n#\n# Case debug_even:\n# The files with an even (odd) index in source_list have debug (release) flags.\n#\n# Case debug_odd:\n# The files with an odd (even) index in source_list have debug (release) flags.\n#\n# Case debug_all, debug_none, or empty string:\n# The debug and release flags are not set by this routine.\n#\n# source_list: (in)\n# is a list of source files that get set to have debug or release\n# compile flags. The cppad_cxx_flags compile flags always get included.\n#\nFUNCTION(set_compile_flags program_name debug_which source_list)\n    # debug compile flags\n    SET(debug_flags \"${cppad_cxx_flags} ${CMAKE_CXX_FLAGS_DEBUG}\")\n    # release compile flags\n    SET(release_flags \"${cppad_cxx_flags} ${CMAKE_CXX_FLAGS_RELEASE}\")\n    #\n    # set alternate, report random number result,\n    # set compile flags property when not alternating.\n    IF( \"${debug_which}\" STREQUAL \"debug_even\" )\n        SET(alternate TRUE)\n        SET(count_mod_2 0)\n    ELSEIF( \"${debug_which}\" STREQUAL \"debug_odd\" )\n        SET(alternate TRUE)\n        SET(count_mod_2 1)\n    ELSE( \"${debug_which}\" )\n        SET(alternate FALSE)\n        IF( NOT \"${cppad_cxx_flags}\" STREQUAL \"\" )\n            SET(alternate FALSE)\n            SET_SOURCE_FILES_PROPERTIES(\n                ${source_list} PROPERTIES COMPILE_FLAGS \"${cppad_cxx_flags}\"\n            )\n        ENDIF( NOT \"${cppad_cxx_flags}\" STREQUAL \"\" )\n    ENDIF( \"${debug_which}\" STREQUAL \"debug_even\" )\n    #\n    IF( alternate )\n        SET(debug_list   \"\")\n        SET(release_list \"\")\n        FOREACH(source ${source_list})\n            MATH(EXPR count_mod_2 \"(${count_mod_2} + 1) % 2\")\n            IF( count_mod_2 )\n                add_to_list(debug_list ${source})\n            ELSE( count_mod_2 )\n                add_to_list(release_list ${source})\n            ENDIF( count_mod_2 )\n        ENDFOREACH(source ${source_list})\n        SET_SOURCE_FILES_PROPERTIES(\n            ${debug_list} PROPERTIES COMPILE_FLAGS \"${debug_flags}\"\n        )\n        SET_SOURCE_FILES_PROPERTIES(\n            ${release_list} PROPERTIES COMPILE_FLAGS \"${release_flags}\"\n        )\n        # IF( ${program_name} STREQUAL \"...\" )\n        #   print_variable( ... )\n        # ENDIF( )\n    ENDIF( alternate )\nENDFUNCTION(set_compile_flags program_name debug_which source_list)\n"
  },
  {
    "path": "configure",
    "content": "#! /usr/bin/env bash\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\nset -e -u\necho $0 $*\n# # ----------------------------------------------------------------------------\n# {xrst_begin configure app}\n# {xrst_spell\n#     adolc\n#     adouble\n#     ansi\n#     badiff\n#     boostvector\n#     colpack\n#     cxx\n#     cygdrive\n#     dist\n#     eigenvector\n#     fadbad\n#     fortran\n#     ip\n#     ipopt\n#     msvc\n#     nmake\n#     sacado\n#     stdvector\n#     sys\n#     ublas\n#     usr\n# }\n# {xrst_comment_ch #}\n#\n# Configure Test and Installation Script\n# ######################################\n#\n# Deprecated 2012-12-26\n# *********************\n# This install procedure is deprecated.\n# You should use the :ref:`cmake-name` instructions to\n# configure and install CppAD.\n#\n# Distribution Directory\n# **********************\n# You must first obtain a copy of the CppAD distribution directory\n# using the :ref:`download-name` instructions.\n# We refer to the corresponding\n# :ref:`download@Distribution Directory` as\n# *dist_dir* .\n#\n# Build Directory\n# ***************\n# Create the directory *dist_dir* / ``build`` ,\n# which will be referred to as the build directory below.\n# (The build directory can be in any location\n# so long as it is not the *dist_dir* .)\n#\n# Configure\n# *********\n# Execute the following command in the build directory:\n#\n# | ../ ``configure`` \\\\\n# | |tab| ``--help``                                       \\\\\n# | |tab| ``--prefix`` = *prefix_dir*                      \\\\\n# | |tab| ``--with-`` *package* ``vector``                 \\\\\n# | |tab| ``--enable-msvc``                                \\\\\n# | |tab| ``--with-clang``                                 \\\\\n# | |tab| ``--with-verbose-make``                          \\\\\n# | |tab| ``MAX_NUM_THREADS`` = *max_num_threads*          \\\\\n# | |tab| ``CXX_FLAGS`` = *cxx_flags*                      \\\\\n# | |tab| ``POSTFIX_DIR`` = *postfix_dir*                  \\\\\n# | |tab| ``ADOLC_DIR`` = *adolc_dir*                      \\\\\n# | |tab| ``FADBAD_DIR`` = *fadbad_dir*                    \\\\\n# | |tab| ``SADADO_DIR`` = *sacado_dir*                    \\\\\n# | |tab| ``IPOPT_DIR`` = *ipopt_dir*                      \\\\\n# | |tab| ``TAPE_ADDR_TYPE`` = *tape_addr_type*            \\\\\n# | |tab| ``TAPE_ID_TYPE`` = *tape_id_type*\n#\n# where only the ``configure`` line need appear; i.e.,\n# the entries in all of the other lines are optional.\n# The text in italic above is replaced values that you choose\n# (see discussion below).\n#\n# make\n# ****\n# The following command, in the build directory,\n# creates the file ``include/cppad/configure.hpp`` in\n# the source directory and then builds\n# some object libraries that are used by the tests\n# ::\n#\n#    make\n#\n# Examples and Tests\n# ==================\n# The following command will build and run all the correctness and speed tests.\n# ::\n#\n#    make test\n#\n# prefix_dir\n# **********\n# The default value for prefix directory is ``$HOME``\n# i.e., by default the CppAD include files\n# will :ref:`install<configure@make install>` below ``$HOME`` .\n# If you want to install elsewhere, you will have to use this option.\n# As an example of using the ``--prefix`` = *prefix_dir* option,\n# if you specify\n# ::\n#\n#    ./configure --prefix=/usr/local\n#\n# the CppAD include files will be installed in the directory\n#\n#    / ``usr/local/include/cppad``\n#\n# --with-<package>vector\n# **********************\n# The :ref:`CPPAD_TESTVECTOR<testvector-name>`\n# template class is used for many of the CppAD examples and tests.\n# The default for this template class is\n#\n#  |tab| ``CppAD::vector<`` *Scalar* > .\n#\n# If one, and only one, of the following command line arguments is specified:\n# ::\n#\n#    --with-stdvector\n#    --with-boostvector\n#    --with-eigenvector\n#\n# the corresponding of the following template classes is used\n#\n# | |tab| ``std::vector<`` *Scalar* >\n# | |tab| ``boost::numeric::ublas::vector<`` *Scalar* >\n# | |tab| ``Eigen::matrix<`` *Scalar* , ``Eigen::Dynamic`` , 1>\n#\n# --enable-msvc\n# *************\n# If this flag is present, the Microsoft ``cl`` compiler will be\n# placed at the front of a list of compilers to search for.\n# In addition, nmake_ make files will be generated; i.e.,\n# you will use ``nmake`` instead of ``make`` to build, test, and install.\n# The resulting C++, C, and Fortran compiler orders work Coin-OR specific;\n# see\n# `Building with Visual Studio in MSys2\n# <https://coin-or.github.io/user_introduction.html#building-with-visual-studio-in-msys2>`_ .\n#\n# .. _nmake: https://learn.microsoft.com/en-us/cpp/build/reference/nmake-reference?view=msvc-170\n#\n# --with-clang\n# ************\n# If this flag is present, ``clang++`` ( ``clang`` )\n# will be used for the C++ (C) compiler.\n# This option cannot appear when the --enable-msvc option appears.\n#\n# --with-verbose-make\n# *******************\n# This will create verbose output during the make commands.\n#\n# max_num_threads\n# ***************\n# this specifies the value for the preprocessor symbol\n# :ref:`multi_thread@CPPAD_MAX_NUM_THREADS` .\n# It must be greater than or equal to four; i.e.,\n# *max_num_threads*  >= 4 .\n# The default value for this option is 64.\n#\n# cxx_flags\n# *********\n# If the command line argument *cxx_flags* is present,\n# it specifies compiler flags.\n# For example,\n#\n#    ``CXX_FLAGS`` = ``\"-Wall -ansi\"``\n#\n# would specify that warning flags ``-Wall``\n# and ``-ansi`` should be included\n# in all the C++ compile commands.\n# The error and warning flags chosen must be valid options\n# for the C++ compiler.\n# The default value for *cxx_flags* is the\n# empty string.\n#\n# postfix_dir\n# ***********\n# The default value for this directory is empty; i.e., there\n# is no postfix directory.\n# As an example of using the ``POSTFIX_DIR`` = *postfix_dir* option,\n# if you specify\n# ::\n#\n#    ./configure --prefix=/usr/local POSTFIX_DIR=coin\n#\n# the CppAD include files will be\n# :ref:`installed<configure@make install>` in the directory\n#\n#    / ``usr/local/include/coin-or/cppad``\n#\n# adolc_dir\n# *********\n# The default value for this directory is empty; i.e., there\n# is no adolc directory.\n# If you have\n# `ADOL-C <https://github.com/coin-or/ADOL-C>`_\n# installed on your system, you can\n# specify a value for *adolc_dir* in the\n# :ref:`configure@Configure` command line.\n# The value of *adolc_dir* must be such that\n#\n#    *adolc_dir* / ``include/adolc/adouble.h``\n#\n# is a valid way to reference ``adouble.h`` .\n# In this case, you can run the Adolc speed correctness tests\n# by executing the following commands starting in the build directory\n#\n#    make check_speed_adolc\n#\n# Note that these speed tests assume Adolc has been configure with\n# its sparse matrix computations enabled using\n#\n#    ``--with-colpack`` = *colpack_dir*\n#\n# where *colpack_dir* is the same as *adolc_dir* .\n#\n# Linux\n# =====\n# If you are using Linux,\n# you may have to add *adolc_dir* / ``lib`` to ``LD_LIBRARY_PATH`` .\n# For example, if you use the ``bash`` shell to run your programs,\n# you could include\n#\n# | |tab| ``LD_LIBRARY_PATH`` = *adolc_dir* / ``lib:$`` { ``LD_LIBRARY_PATH`` }\n# | |tab| ``export LD_LIBRARY_PATH``\n#\n# in your ``$HOME/.bash_profile`` file.\n#\n# Cygwin\n# ======\n# If you are using Cygwin,\n# you will have to add to following lines to the file\n# ``.bash_profile`` in your home directory:\n#\n# | |tab| ``PATH`` = *adolc_dir* / ``bin:$`` { ``PATH`` }\n# | |tab| ``export PATH``\n#\n# in order for Adolc to run properly.\n# If *adolc_dir* begins with a disk specification,\n# you must use the Cygwin format for the disk specification.\n# For example,\n# if ``d:/adolc_base`` is the proper directory,\n# ``/cygdrive/d/adolc_base`` should be used for *adolc_dir* .\n#\n# fadbad_dir\n# **********\n# The default value for this directory is empty; i.e., there\n# is no fadbad directory.\n# If you have\n# `Fadbad 2.1 <http://uning.dk//>`_\n# installed on your system, you can\n# specify a value for *fadbad_dir* .\n# It must be such that\n#\n#    *fadbad_dir* / ``include/FADBAD`` ++/ ``badiff.h``\n#\n# is a valid reference to ``badiff.h`` .\n# In this case, you can run the Fadbad speed correctness tests\n# by executing the following commands starting in the build directory:\n#\n#    make check_speed_fadbad\n#\n#\n# ipopt_dir\n# *********\n# The default value for this directory is empty; i.e., there\n# is no ipopt directory.\n# If you have\n# `Ipopt <https://coin-or.github.io/Ipopt>`_\n# installed on your system, you can\n# specify a value for *ipopt_dir* .\n# It must be such that\n#\n#    *ipopt_dir* / ``include/coin-or/IpIpoptApplication.hpp``\n#\n# is a valid reference to ``IpIpoptApplication.hpp`` .\n# In this case, the CppAD interface to Ipopt\n# examples can be built and tested\n# by executing the following commands starting in the build directory:\n#\n#    make check_cppad_ipopt\n#\n# Once this has been done, you can execute the program\n# ``cppad_ipopt_speed`` in the ``build/cppad_ipopt/speed`` directory;\n# see ``ipopt_ode_speed.cpp`` .\n#\n# sacado_dir\n# **********\n# The default value for this directory is empty; i.e., there\n# is no sacado directory.\n# If you have\n# `Sacado <https://trilinos.github.io/sacado.html>`_\n# installed on your system, you can\n# specify a value for *sacado_dir* .\n# It must be such that\n#\n#    *sacado_dir* / ``include/Sacado.hpp``\n#\n# is a valid reference to ``Sacado.hpp`` .\n# In this case, you can run the Sacado speed correctness tests\n# by executing the following commands starting in the build directory:\n# ::\n#\n#    make check_speed_sacado\n#\n# tape_addr_type\n# **************\n# The default value for this type is ``size_t`` .\n# If the command line argument *tape_addr_type* is present,\n# it specifies the type used for address in the AD recordings (tapes).\n# The valid values for this argument are\n# ``unsigned short int`` ,\n# ``unsigned int`` ,\n# ``size_t`` .\n# The smaller the value of *sizeof* ( ``tape_addr_type`` ) ,\n# the less memory is used.\n# On the other hand, the value\n#\n#    ``std::numeric_limits<`` *tape_addr_type* >:: ``max`` ()\n#\n# must be larger than any of the following:\n# :ref:`fun_property@size_op` ,\n# :ref:`fun_property@size_op_arg` ,\n# :ref:`size_par<fun_property@size_text>` ,\n# :ref:`fun_property@size_par` ,\n# :ref:`size_par<fun_property@size_VecAD>` .\n#\n# tape_id_type\n# ************\n# The default value for this type is ``size_t`` .\n# If the command line argument *tape_id_type* is present,\n# it specifies the type used for identifying tapes.\n# The valid values for this argument are\n# ``unsigned short int`` ,\n# ``unsigned int`` ,\n# ``size_t`` .\n# The smaller the value of *sizeof* ( ``tape_id_type`` ) ,\n# the less memory is used.\n# On the other hand, the value\n#\n#    ``std::numeric_limits<`` *tape_id_type* >:: ``max`` ()\n#\n# must be larger than the maximum number of tapes per thread\n# times :ref:`configure@max_num_threads` .\n#\n# make install\n# ************\n# Once you are satisfied that the tests are giving correct results,\n# you can install CppAD into easy to use directories by executing the command\n# ::\n#\n#    make install\n#\n# This will install CppAD in the location specified by\n# :ref:`configure@prefix_dir` .\n# You must have permission to write in the *prefix_dir*\n# directory to execute this command.\n# You may optionally specify a destination directory for the install; i.e.,\n#\n#    ``make install DESTDIR`` = *DestinationDirectory*\n#\n# {xrst_end configure}\n# ----------------------------------------------------------------------------\nfunction print_variable {\n   echo \"$1 = ${!1}\"\n}\n# ----------------------------------------------------------------------------\n#\n# --help\nif echo \" $* \" | grep ' --help ' > /dev/null\nthen\n   cat << EOF\nusage: <path_to_configure>/configure \\\\\n   [--help] \\\\\n   [--prefix=<prefix_dir>] \\\\\n   [--with-<package>vector] \\\\\n   [--enable-msvc] \\\\\n   [--with-clang]  \\\\\n   [--with-verbose-make] \\\\\n   [MAX_NUM_THREADS=max_num_threads] \\\\\n   [CXX_FLAGS=cxx_flags] \\\\\n   [POSTFIX_DIR=postfix_dir] \\\\\n   [ADOLC_DIR=adolc_dir] \\\\\n   [FADBAD_DIR=fadbad_dir] \\\\\n   [SACADO_DIR=sacado_dir] \\\\\n   [IPOPT_DIR=ipopt_dir] \\\\\n   [TAPE_ADDR_TYPE=tape_addr_type] \\\\\n   [TAPE_ID_TYPE=tape_id_type]\nThe --help option just prints this message and exits.\n<package> is one of he following: boost, eigen, std\n\nEOF\n   exit 0\nfi\n# ----------------------------------------------------------------------------\nfirst_executable() {\n   first_executable_result=''\n   while [ \"$first_executable_result\" == '' ] && [ \"$1\" != '' ]\n   do\n      if which $1 >& /dev/null\n      then\n         first_executable_result=\"$(which $1)\"\n      fi\n      shift\n   done\n}\n# ----------------------------------------------------------------------------\n#\nprefix=\"$HOME\"\ntestvector='cppad'\nenable_msvc='no'\nwith_clang='n0'\nwith_verbose_make='no'\nmax_num_threads='64'\ncxx_flags=''\npostfix_dir='NOTFOUND'\nadolc_dir='NOTFOUND'\nfadbad_dir='NOTFOUND'\nsacado_dir='NOTFOUND'\nipopt_dir='NOTFOUND'\ntape_addr_type='size_t'\ntape_id_type='size_t'\nwhile [ \"$#\" != 0 ]\ndo\n   case \"$1\" in\n\n      --prefix=*)\n      prefix=$( echo $1 | sed -e 's|^--prefix=||' )\n      ;;\n\n      --with-boostvector)\n      testvector='boost'\n      ;;\n\n      --with-eigenvector)\n      testvector='eigen'\n      ;;\n\n      --with-stdvector)\n      testvector='std'\n      ;;\n\n      --with-clang)\n      with_clang='yes'\n      ;;\n\n      --enable-msvc)\n      enable_msvc='yes'\n      ;;\n\n      --with-verbose-make)\n      with_verbose_make='yes'\n      ;;\n\n      MAX_NUM_THREADS=*)\n      max_num_threads=$( echo $1 | sed -e 's|MAX_NUM_THREADS=||' )\n      ;;\n\n      CXX_FLAGS=*)\n      cxx_flags=$( echo $1 | sed -e 's|CXX_FLAGS=||' )\n      ;;\n\n      POSTFIX_DIR=*)\n      postfix_dir=$( echo $1 | sed -e 's|POSTFIX_DIR=||' )\n      ;;\n\n      ADOLC_DIR=*)\n      adolc_dir=$( echo $1 | sed -e 's|ADOLC_DIR=||' )\n      ;;\n\n      FADBAD_DIR=*)\n      fadbad_dir=$( echo $1 | sed -e 's|FADBAD_DIR=||' )\n      ;;\n\n      SACADO_DIR=*)\n      sacado_dir=$( echo $1 | sed -e 's|SACADO_DIR=||' )\n      ;;\n\n      IPOPT_DIR=*)\n      ipopt_dir=$( echo $1 | sed -e 's|IPOPT_DIR=||' )\n      ;;\n\n      TAPE_ADDR_TYPE=*)\n      tape_addr_type=$( echo $1 | sed -e 's|TAPE_ADDR_TYPE=||' )\n      ;;\n\n      TAPE_ID_TYPE=*)\n      tape_id_type=$( echo $1 | sed -e 's|TAPE_ID_TYPE=||' )\n      ;;\n\n      *)\n      echo \"configure: '$1' is not a valid option. Use following to get help:\"\n      echo \"$0 --help\"\n      exit 1\n   esac\n   shift\ndone\nif [ \"$with_clang\" == 'yes' ] && [ \"$enable_msvc\" == 'yes' ]\nthen\n   echo 'configure: cannot specify both --enable-mcvc and --with-clang'\n   exit 1\nfi\n# ----------------------------------------------------------------------------\n# type_makefile\nif [ \"$enable_msvc\" == 'yes' ]\nthen\n   type_makefile='NMake Makefiles'\nelse\n   if [[ $(uname -s) =~ ^MSYS_.* ]]\n   then\n      type_makefile='MSYS Makefiles'\n   else\n      type_makefile='Unix Makefiles'\n   fi\nfi\n#\n# cxx_standard_year\nif echo $cxx_flags | grep 'std=c++' > /dev/null\nthen\n   cxx_standard_year=$(echo $cxx_flags | sed -e 's|.*std=c++\\([0-9]*\\).*|\\1|')\n   print_variable cxx_standard_year\n   if [ \"$cxx_standard_year\"  -lt 17 ]\n   then\n      if [ \"$sacado_dir\" != 'NOTFOUND' ]\n      then\n         echo 'Sacado requires c++17 or greater'\n         exit 1\n      fi\n   fi\nfi\n#\n# cmake_cxx_compiler\ncmake_cxx_compiler=''\nif [ \"$enable_msvc\" == 'yes' ]\nthen\n   first_executable icl cl g++\nelse\n   first_executable g++ clang++ CC pgCC icpc gpp cxx cc++\nfi\nif [ \"$with_clang\" == 'yes' ]\nthen\n   cmake_cxx_compiler='-D CMAKE_CXX_COMPILER=clang++'\nelif [ \"$first_executable_result\" != '' ]\nthen\n   cmake_cxx_compiler=\"-D CMAKE_CXX_COMPILER=$first_executable_result\"\nfi\n#\n# cmake_c_compiler\ncmake_c_compiler=''\nif [ \"$enable_msvc\" == 'yes' ]\nthen\n   first_executable icl cl gcc\nelse\n   first_executable gcc clang cc pgcc icc\nfi\nif [ \"$with_clang\" == 'yes' ]\nthen\n   cmake_c_compiler='-D CMAKE_C_COMPILER=clang'\nelif [ \"$first_executable_result\" != '' ]\nthen\n   cmake_c_compiler=\"-D CMAKE_C_COMPILER=$first_executable_result\"\nfi\n#\n# CMAKE_Fortran_COMPILER\ncmake_fortran_compiler=''\nif [ \"$enable_msvc\" == 'yes' ]\nthen\n   first_executable ifort gfortran\nelse\n   first_executable gfortran ifort g95 fort77 f77 g77 pgf90 pgf77 ifc frt af77\nfi\nif [ \"$first_executable_result\" != '' ]\nthen\n   cmake_fortran_compiler=\"-D CMAKE_Fortran_COMPILER=$first_executable_result\"\nfi\n#\n# source_dir\nsource_dir=$( echo $0 | sed -e 's|/configure$||' )\nif [ \"$source_dir\" == \"$0\" ] || [ \"$source_dir\" == '.' ]\nthen\n   echo 'configure: cannot run configure in the current working directory'\n   pwd\n   exit 1\nfi\nPKG_CONFIG_PATH=''\n#\n# include_$package, PKG_CONFIG_PATH\nfor package in adolc ipopt\ndo\n   package_dir=\"${package}_dir\"\n   if [ \"${!package_dir}\" == NOTFOUND ]\n   then\n      declare include_${package}='false'\n   else\n      declare include_${package}='true'\n      pc_file=\"$package.pc\"\n      if [ \"$package\" == eigen ]\n      then\n         pc_file='eigen3.pc'\n      fi\n      pc_path=$(find ${!package_dir} -name \"$pc_file\" | head -1)\n      if [ \"$pc_path\" == '' ]\n      then\n         echo \"$package_dir = ${!package_dir}\"\n         echo \"But cannot find $pc_file below that directory\"\n         exit 1\n      fi\n      pc_dir=$(echo $pc_path | sed -e \"s|/$pc_file||\")\n      if [ -z ${PKG_CONFIG_PATH+x} ]\n      then\n         export PKG_CONFIG_PATH=\"$pc_dir\"\n      elif [ \"$PKG_CONFIG_PATH\" == '' ]\n      then\n         export PKG_CONFIG_PATH=\"$pc_dir\"\n      else\n         PKG_CONFIG_PATH=\"$PKG_CONFIG_PATH:$pc_dir\"\n      fi\n   fi\n   print_variable PKG_CONFIG_PATH\ndone\n#\n# cppad_cxx_flags\ncppad_cxx_flags=$( echo \" $cxx_flags \" | sed -e 's| -g ||' )\n#\n# cmake_install_libdirs\ncmake_install_libdirs='lib;lib64'\nif [ -d '/usr/lib64' ]\nthen\n   cmake_install_libdirs='lib64;lib'\nfi\nlist='\n   build.ninja\n   CMakeCache.txt\n   CMakeFiles\n'\nfor name in $list\ndo\n   if [ -e \"$name\" ]\n   then\n      echo_eval rm -r $name\n   fi\ndone\necho cmake \\\n   -U .+ \\\n   -S \"$source_dir\" \\\n   -B . \\\n   \\\n   -D CMAKE_VERBOSE_MAKEFILE=$with_verbose_make \\\n   -G \"'$type_makefile'\" \\\n   \\\n   $cmake_c_compiler \\\n   $cmake_fortran_compiler \\\n   \\\n   -D cppad_prefix=\"$prefix\" \\\n   -D cppad_postfix=\"$postfix_dir\" \\\n   \\\n   -D cmake_install_includedirs=include \\\n   -D cmake_install_libdirs=$cmake_install_libdirs \\\n   \\\n   -D cmake_install_datadir=share \\\n   -D cmake_install_docdir=share/doc \\\n   \\\n   -D include_adolc=$include_adolc \\\n   -D include_ipopt=$include_ipopt \\\n   -D include_cppadcg=false \\\n   \\\n   -D colpack_prefix='NOTFOUND' \\\n   -D fadbad_prefix=\"$fadbad_dir\" \\\n   -D sacado_prefix=\"$sacado_dir\" \\\n   \\\n   -D cppad_cxx_flags=\"$cxx_flags\" \\\n   -D cppad_profile_flag='' \\\n   -D cppad_testvector=\"$testvector\"  \\\n   -D cppad_max_num_threads=\"$max_num_threads\" \\\n   -D cppad_tape_id_type=\"$tape_id_type\" \\\n   -D cppad_tape_addr_type=\"$tape_addr_type\" \\\n   -D cppad_debug_which='debug_none' \\\n   -D cppad_debug_and_release='true'\n#\ncmake \\\n   -U .+ \\\n   -S \"$source_dir\" \\\n   -B . \\\n   \\\n   -D CMAKE_VERBOSE_MAKEFILE=$with_verbose_make \\\n   -G \"$type_makefile\" \\\n   \\\n   $cmake_cxx_compiler \\\n   $cmake_fortran_compiler \\\n   \\\n   -D cppad_prefix=\"$prefix\" \\\n   -D cppad_postfix=\"$postfix_dir\" \\\n   \\\n   -D cmake_install_includedirs=include \\\n   -D cmake_install_libdirs=$cmake_install_libdirs \\\n   \\\n   -D cmake_install_datadir=share \\\n   -D cmake_install_docdir=share/doc \\\n   \\\n   -D include_adolc=$include_adolc \\\n   -D include_ipopt=$include_adolc \\\n   -D include_cppadcg=false \\\n   \\\n   -D colpack_prefix='NOTFOUND' \\\n   -D fadbad_prefix=\"$fadbad_dir\" \\\n   -D sacado_prefix=\"$sacado_dir\" \\\n   \\\n   -D cppad_cxx_flags=\"$cxx_flags\" \\\n   -D cppad_profile_flag='' \\\n   -D cppad_testvector=\"$testvector\"  \\\n   -D cppad_max_num_threads=\"$max_num_threads\" \\\n   -D cppad_tape_id_type=\"$tape_id_type\" \\\n   -D cppad_tape_addr_type=\"$tape_addr_type\" \\\n   -D cppad_debug_which='debug_none' \\\n   -D cppad_debug_and_release='true'\n# ----------------------------------------------------------------------------\necho 'configure: OK'\nexit 0\n"
  },
  {
    "path": "cppad_ipopt/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n# Initialize list of tests as empty\nSET(check_cppad_ipopt_depends \"\")\n\n# assert include_ipopt\nIF ( NOT include_ipopt )\n    MESSAGE(FATAL_ERROR\n        \"include_ipopt is not on the cmake command line\"\n    )\nENDIF ( NOT include_ipopt )\n\n# The CMakeLists.txt file in the specified source directory is processed\n# before the current input file continues beyond this command.\n# add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])\nADD_SUBDIRECTORY(src)\nADD_SUBDIRECTORY(example)\nADD_SUBDIRECTORY(speed)\nADD_SUBDIRECTORY(test)\n\n# Add the check_cppad_ipopt target\nADD_CUSTOM_TARGET(check_cppad_ipopt DEPENDS ${check_cppad_ipopt_depends} )\nMESSAGE(STATUS \"make check_cppad_ipopt: available\")\n\n# Change check depends in parent environment\nadd_to_list(check_depends check_cppad_ipopt)\nSET(check_depends \"${check_depends}\" PARENT_SCOPE)\n"
  },
  {
    "path": "cppad_ipopt/example/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-23 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# Inherit build type from ../CMakeList.txt\n\n# Local include directories to search (not in package_prefix/include)\nINCLUDE_DIRECTORIES( ${CMAKE_CURRENT_SOURCE_DIR}/../src )\n\n# Local link directories to search (not in external packages)\nLINK_DIRECTORIES( ${CMAKE_CURRENT_BINARY_DIR}/../src ${ipopt_LIBRARY_DIRS} )\n\n# add_executable(<name> [WIN32] [MACOSX_BUNDLE] [EXCLUDE_FROM_ALL]\n#                 source1 source2 ... sourceN\n# )\n# BEGIN_SORT_THIS_LINE_PLUS_2\nSET(source_list\n    example.cpp\n    get_started.cpp\n    ode_check.cpp\n    ode_check.hpp\n    ode_fast.hpp\n    ode_fast_check.cpp\n    ode_problem.hpp\n    ode_run.hpp\n    ode_simple.hpp\n    ode_simple_check.cpp\n)\n# END_SORT_THIS_LINE_MINUS_2\n\nset_compile_flags( cppad_ipopt_example \"${cppad_debug_which}\" \"${source_list}\" )\n#\nADD_EXECUTABLE( cppad_ipopt_example EXCLUDE_FROM_ALL ${source_list} )\n\n# List of libraries to be linked into the specified target\nTARGET_LINK_LIBRARIES(cppad_ipopt_example\n    cppad_ipopt\n    ${cppad_lib}\n    ${ipopt_LINK_LIBRARIES}\n    ${colpack_libs}\n)\n\n#\n# check_cppad_ipopt_example\nadd_check_executable(check_cppad_ipopt example)\n"
  },
  {
    "path": "cppad_ipopt/example/example.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n// system include files used for I/O\n# include <iostream>\n\n// C style asserts\n# include <cassert>\n\n// CppAD include file\n# include <cppad/cppad.hpp>\n\n// test runner\n# include <cppad/utility/test_boolofvoid.hpp>\n\n// external complied tests\nextern bool ipopt_get_started(void);\nextern bool ode_simple_check(void);\nextern bool ode_fast_check(void);\n\n// main program that runs all the tests\nint main(void)\n{   std::string group = \"cppad_ipopt/example\";\n    size_t      width = 20;\n    CppAD::test_boolofvoid Run(group, width);\n\n    // external compiled tests\n    Run( ipopt_get_started,   \"ipopt_get_started\"  );\n    Run( ode_simple_check,    \"ode_simple_check\"   );\n    Run( ode_fast_check,      \"ode_fast_check\"     );\n    //\n    // check for memory leak\n    bool memory_ok = CppAD::thread_alloc::free_all();\n    // print summary at end\n    bool ok = Run.summary(memory_ok);\n    //\n    return static_cast<int>( ! ok );\n}\n"
  },
  {
    "path": "cppad_ipopt/example/get_started.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n\n{xrst_begin ipopt_nlp_get_started.cpp dev}\n{xrst_spell\n    lc\n}\n\nNonlinear Programming Using CppAD and Ipopt: Getting Started\n############################################################\n\nPurpose\n*******\nThis example program demonstrates how to use the class cppad_ipopt_nlp to\nsolve the example problem in the Ipopt documentation; i.e., the problem\n\n.. math::\n\n    \\begin{array}{lc}\n    {\\rm minimize \\; }      &  x_1 * x_4 * (x_1 + x_2 + x_3) + x_3\n    \\\\\n    {\\rm subject \\; to \\; } &  x_1 * x_2 * x_3 * x_4  \\geq 25\n    \\\\\n                            &  x_1^2 + x_2^2 + x_3^2 + x_4^2 = 40\n    \\\\\n                            &  1 \\leq x_1, x_2, x_3, x_4 \\leq 5\n    \\end{array}\n\nConfiguration Requirement\n*************************\nThis example will be compiled and tested provided that\na ``include_ipopt=true``\nis specified on the :ref:`cmake-name` command line.\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end ipopt_nlp_get_started.cpp}\n*/\n// BEGIN C++\n\n# include <cppad_ipopt_nlp.hpp>\n\nnamespace {\n    using namespace cppad_ipopt;\n\n    class FG_info : public cppad_ipopt_fg_info\n    {\n    private:\n        bool retape_;\n    public:\n        // derived class part of constructor\n        FG_info(bool retape_in)\n        : retape_ (retape_in)\n        { }\n        // Evaluation of the objective f(x), and constraints g(x)\n        // using an Algorithmic Differentiation (AD) class.\n        ADVector eval_r(size_t k, const ADVector&  x)\n        {   ADVector fg(3);\n\n            // Fortran style indexing\n            ADNumber x1 = x[0];\n            ADNumber x2 = x[1];\n            ADNumber x3 = x[2];\n            ADNumber x4 = x[3];\n            // f(x)\n            fg[0] = x1 * x4 * (x1 + x2 + x3) + x3;\n            // g_1 (x)\n            fg[1] = x1 * x2 * x3 * x4;\n            // g_2 (x)\n            fg[2] = x1 * x1 + x2 * x2 + x3 * x3 + x4 * x4;\n            return fg;\n        }\n        bool retape(size_t k)\n        {   return retape_; }\n    };\n}\n\nbool ipopt_get_started(void)\n{   bool ok = true;\n    size_t j;\n\n\n    // number of independent variables (domain dimension for f and g)\n    size_t n = 4;\n    // number of constraints (range dimension for g)\n    size_t m = 2;\n    // initial value of the independent variables\n    NumberVector x_i(n);\n    x_i[0] = 1.0;\n    x_i[1] = 5.0;\n    x_i[2] = 5.0;\n    x_i[3] = 1.0;\n    // lower and upper limits for x\n    NumberVector x_l(n);\n    NumberVector x_u(n);\n    for(j = 0; j < n; j++)\n    {   x_l[j] = 1.0;\n        x_u[j] = 5.0;\n    }\n    // lower and upper limits for g\n    NumberVector g_l(m);\n    NumberVector g_u(m);\n    g_l[0] = 25.0;     g_u[0] = 1.0e19;\n    g_l[1] = 40.0;     g_u[1] = 40.0;\n\n    size_t icase;\n    for(icase = 0; icase <= 1; icase++)\n    {   // Should cppad_ipopt_nlp retape the operation sequence for\n        // every new x. Can test both true and false cases because\n        // the operation sequence does not depend on x (for this case).\n        bool retape = icase != 0;\n\n        // object in derived class\n        FG_info fg_info(retape);\n\n        // create the Ipopt interface\n        cppad_ipopt_solution solution;\n        Ipopt::SmartPtr<Ipopt::TNLP> cppad_nlp = new cppad_ipopt_nlp(\n        n, m, x_i, x_l, x_u, g_l, g_u, &fg_info, &solution\n        );\n\n        // Create an instance of the IpoptApplication\n        using Ipopt::IpoptApplication;\n        Ipopt::SmartPtr<IpoptApplication> app = new IpoptApplication();\n\n        // turn off any printing\n        app->Options()->SetIntegerValue(\"print_level\", 0);\n        app->Options()->SetStringValue(\"sb\", \"yes\");\n\n        // maximum number of iterations\n        app->Options()->SetIntegerValue(\"max_iter\", 10);\n\n        // approximate accuracy in first order necessary conditions;\n        // see Mathematical Programming, Volume 106, Number 1,\n        // Pages 25-57, Equation (6)\n        app->Options()->SetNumericValue(\"tol\", 1e-9);\n\n        // derivative testing\n        app->Options()->\n        SetStringValue(\"derivative_test\", \"second-order\");\n        app->Options()-> SetNumericValue(\n            \"point_perturbation_radius\", 0.\n        );\n\n        // Initialize the IpoptApplication and process the options\n        Ipopt::ApplicationReturnStatus status = app->Initialize();\n        ok    &= status == Ipopt::Solve_Succeeded;\n\n        // Run the IpoptApplication\n        status = app->OptimizeTNLP(cppad_nlp);\n        ok    &= status == Ipopt::Solve_Succeeded;\n\n        /*\n        Check some of the solution values\n        */\n        ok &= solution.status == cppad_ipopt_solution::success;\n        //\n        double check_x[]   = { 1.000000, 4.743000, 3.82115, 1.379408 };\n        double check_z_l[] = { 1.087871, 0.,       0.,      0.       };\n        double check_z_u[] = { 0.,       0.,       0.,      0.       };\n        double rel_tol     = 1e-6;  // relative tolerance\n        double abs_tol     = 1e-6;  // absolute tolerance\n        for(j = 0; j < n; j++)\n        {   ok &= CppAD::NearEqual(\n            check_x[j],   solution.x[j],   rel_tol, abs_tol\n            );\n            ok &= CppAD::NearEqual(\n            check_z_l[j], solution.z_l[j], rel_tol, abs_tol\n            );\n            ok &= CppAD::NearEqual(\n            check_z_u[j], solution.z_u[j], rel_tol, abs_tol\n            );\n        }\n    }\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "cppad_ipopt/example/ode1.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin ipopt_nlp_ode dev}\n\nExample Simultaneous Solution of Forward and Inverse Problem\n############################################################\n\nContents\n********\n{xrst_toc_list\n    cppad_ipopt/example/get_started.cpp\n    cppad_ipopt/example/ode2.xrst\n    cppad_ipopt/example/ode_run.hpp\n    cppad_ipopt/example/ode_check.cpp\n    cppad_ipopt/speed/ode_speed.cpp\n}\n\n{xrst_end ipopt_nlp_ode}\n"
  },
  {
    "path": "cppad_ipopt/example/ode2.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin ipopt_nlp_ode_problem dev}\n{xrst_spell\n    ny\n    nz\n}\n\nAn ODE Inverse Problem Example\n##############################\n\nNotation\n********\nThe table below contains\nthe name of a variable,\nthe meaning of the variable value,\nand the value for this particular example.\nIf the value is not specified in the table below,\nthe corresponding value in ``ipopt_nlp_ode_problem.hpp``\ncan be changed and the example should still run\n(with no other changes).\n\n.. csv-table::\n    :widths: auto\n\n    **Name**,**Meaning**,**Value**\n    :math:`Na`,number of parameters to fit,3\n    :math:`Ny`,number components in ODE,2\n    :math:`Nz`,number of measurements,4\n    :math:`N(i)`,# of grid points between *i-1*-th and *i*-th measurement,\n    :math:`S(i)`,# of grid points up to an including *i*-th measurement,\n\nForward Problem\n***************\nWe consider the following ordinary differential equation:\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        \\partial_t y_0 ( t , a ) & = & - a_1 * y_0 (t, a )\n        \\\\\n        \\partial_t y_1 (t , a ) & = & + a_1 * y_0 (t, a ) - a_2 * y_1 (t, a )\n    \\end{eqnarray}\n\nwith the initial conditions\n\n.. math::\n\n    y_0 (0 , a) = F(a) = \\left( \\begin{array}{c} a_0 \\\\ 0 \\end{array} \\right)\n\nwhere :math:`Na` is the number of parameters,\n:math:`a \\in \\B{R}^{Na}` is an unknown parameter vector.\nThe function and :math:`F : \\B{R}^{Na} \\rightarrow \\B{R}^{Ny}`\nis defined by the equation above\nwhere :math:`Ny` is the number of components in :math:`y(t, a)`.\nOur forward problem is stated as follows: Given :math:`a \\in \\B{R}^{Na}`\ndetermine the value of :math:`y ( t , a )`, for :math:`t \\in R`, that\nsolves the initial value problem above.\n\nMeasurements\n************\nWe use :math:`Nz` to denote the number of measurements.\nSuppose we are also given a measurement vector :math:`z \\in \\B{R}^{Nz}`\nand for :math:`i = 1, \\ldots, Nz`,\nwe model :math:`z_i` by\n\n.. math::\n\n    z_i = y_1 ( s_i , a) + e_i\n\nwhere :math:`s_i \\in \\B{R}` is the time for the *i*-th measurement,\n:math:`e_i \\sim {\\bf N} (0 , \\sigma^2 )` is the corresponding noise,\nand :math:`\\sigma \\in \\B{R}_+` is the corresponding standard deviation.\n\nSimulation Analytic Solution\n============================\nThe following analytic solution to the forward problem is used\nto simulate a data set:\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        y_0 (t , a) & = & a_0 * \\exp( - a_1 * t )\n        \\\\\n        y_1 (t , a) & = &\n        a_0 * a_1 * \\frac{\\exp( - a_2 * t ) - \\exp( -a_1 * t )}{ a_1 - a_2 }\n    \\end{eqnarray}\n\nSimulation Parameter Values\n===========================\n\n.. list-table::\n    :widths: auto\n\n    * - :math:`\\bar{a}_0 = 1`\n      - initial value of :math:`y_0 (t, a)`\n    * - :math:`\\bar{a}_1 = 2`\n      - transfer rate from compartment zero to compartment one\n    * - :math:`\\bar{a}_2 = 1`\n      - transfer rate from compartment one to outside world\n    * - :math:`\\sigma = 0`\n      - standard deviation of measurement noise\n    * - :math:`e_i = 0`\n      - simulated measurement noise, :math:`i = 1 , \\ldots , Nz`\n    * - :math:`s_i = i * .5`\n      - time corresponding to the *i*-th measurement,\n         :math:`i = 1 , \\ldots , Nz`\n\nSimulated Measurement Values\n============================\nThe simulated measurement values are given by the equation\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    z_i\n    & = &  e_i + y_1 ( s_i , \\bar{a} )\n    \\\\\n    & = &\n    e_i + \\bar{a}_0 * \\bar{a}_1 *\n        \\frac{\\exp( - \\bar{a}_2 * s_i ) - \\exp( -\\bar{a}_1 * s_i )}\n            { \\bar{a}_1 - \\bar{a}_2 }\n    \\end{eqnarray}\n\nfor :math:`k = 1, \\ldots , Nz`.\n\nInverse Problem\n***************\nThe maximum likelihood estimate for :math:`a` given :math:`z`\nsolves the following inverse problem\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    {\\rm minimize} \\;\n        & \\sum_{i=1}^{Nz} H_i [ y( s_i , a ) , a ]\n        & \\;{\\rm w.r.t} \\; a \\in \\B{R}^{Na}\n    \\end{eqnarray}\n\nwhere the functions\n:math:`H_i : \\B{R}^{Ny} \\times \\B{R}^{Na} \\rightarrow \\B{R}` is\ndefined by\n\n.. math::\n\n    H_i (y, a) = ( z_i - y_1 )^2\n\nTrapezoidal Approximation\n*************************\nThis example uses a trapezoidal approximation to solve the ODE.\nThis approximation procedures starts with\n\n.. math::\n\n    y^0 = y(0, a) = \\left( \\begin{array}{c} a_0 \\\\ 0 \\end{array} \\right)\n\nGiven a time grid :math:`\\{ t_i \\}` and\nan approximate value :math:`y^{i-1}` for :math:`y ( t_{i-1} , a )`,\nthe a trapezoidal method approximates :math:`y ( t_i , a )`\n(denoted by :math:`y^i` ) by solving the equation\n\n.. math::\n\n    y^i  =  y^{i-1} +\n    \\left[ G( y^i , a ) + G( y^{i-1} , a ) \\right] * \\frac{t_i - t_{i-1} }{ 2 }\n\nwhere :math:`G : \\B{R}^{Ny} \\times \\B{R}^{Na} \\rightarrow \\B{R}^{Ny}` is the\nfunction representing this ODE; i.e.\n\n.. math::\n\n    G(y, a) = \\left(  \\begin{array}{c}\n        - a_1 * y_0\n        \\\\\n        + a_1 * y_0 - a_2 * y_1\n    \\end{array} \\right)\n\nThis :math:`G(y, a)` is linear with respect to :math:`y`, hence\nthe implicit equation defining :math:`y^i` can be solved\ninverting the a set of linear equations.\nIn the general case,\nwhere :math:`G(y, a)` is non-linear with respect to :math:`y`,\nan iterative procedure is used to calculate :math:`y^i`\nfrom :math:`y^{i-1}`.\n\nTrapezoidal Time Grid\n=====================\nThe discrete time grid, used for the trapezoidal approximation, is\ndenoted by :math:`\\{ t_i \\}` which is defined by:\n:math:`t_0 = 0` and\nfor :math:`i = 1 , \\ldots , Nz` and for :math:`j = 1 , \\ldots , N(i)`,\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        \\Delta t_i & = & ( s_i - s_{i-1} ) / N(i)\n        \\\\\n        t_{S(i-1)+j} & = & s_{i-1} + \\Delta t_i * j\n    \\end{eqnarray}\n\nwhere :math:`s_0 = 0`,\n:math:`N(i)` is the number of time grid points between\n:math:`s_{i-1}` and :math:`s_i`,\n:math:`S(0) = 0`, and\n:math:`S(i) = N(1) + \\ldots + N(i)`.\nNote that for :math:`i = 0 , \\ldots , S(Nz)`,\n:math:`y^i` denotes our approximation for :math:`y( t_i , a )`\nand :math:`t_{S(i)}` is equal to :math:`s_i`.\n\nBlack Box Method\n****************\nA common approach to an inverse problem is to treat the forward problem\nas a black box (that we do not look inside of or try to understand).\nIn this approach, for each value of the parameter vector :math:`a`\none uses the\n:ref:`ipopt_nlp_ode_problem@Trapezoidal Approximation`\n(on a finer grid that :math:`\\{ s_i \\}`)\nto solve for :math:`y_1 ( s_i , a )` for :math:`i = 1 , \\ldots , Nz`.\n\nTwo levels of Iteration\n=======================\nAs noted above, the trapezoidal approximation\noften requires an iterative procedure.\nThus, in this approach, there are two levels of iterations,\none with respect to the parameter values during the minimization\nand the other for solving the trapezoidal approximation equation.\n\nDerivatives\n===========\nIn addition, in the black box approach, differentiating the ODE solution\noften involves differentiating an iterative procedure.\nDirect application of AD to compute these derivatives\nrequires a huge amount of memory and calculations to differentiate the\niterative procedure.\n(There are special techniques for applying AD to the solutions of iterative\nprocedures, but that is outside the scope of this presentation).\n\nSimultaneous Method\n*******************\nThe simultaneous forward and inverse method\nuses constraints to include the solution of\nthe forward problem in the inverse problem.\nTo be specific for our example,\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    {\\rm minimize}\n    & \\sum_{i=1}^{Nz} H_i ( y^{N(i)} , a )\n    & \\; {\\rm w.r.t} \\; y^1 \\in \\B{R}^{Ny} , \\ldots , y^{S(Nz)} \\in \\B{R}^{Ny} ,\n      \\; a \\in \\B{R}^{Na}\n    \\\\\n    {\\rm subject \\; to}\n        & y^j  =  y^{j-1} +\n    \\left[ G( y^{j-1} , a ) + G( y^j , a ) \\right] * \\frac{ t_j - t_{j-1} }{ 2 }\n        & \\; {\\rm for} \\; j = 1 , \\ldots , S(Nz)\n    \\\\\n        & y^0 = F(a)\n    \\end{eqnarray}\n\nwhere for :math:`i = 1, \\ldots , Nz`,\n:math:`N(i)` is the number of time intervals between\n:math:`s_{i-1}` and :math:`s_i` (with :math:`s_0 = 0`)\nand :math:`S(i) = N(1) + \\ldots + N(i)`.\nNote that, in this form, the iterations of the optimization procedure\nalso solve the forward problem equations.\nIn addition, the functions that need to be differentiated\ndo not involve an iterative procedure.\n{xrst_toc_hidden\n    cppad_ipopt/example/ode_problem.hpp\n}\nSource\n******\nThe file ``ipopt_nlp_ode_problem.hpp`` contains\nsource code that defines the example values and functions defined above.\n\n{xrst_end ipopt_nlp_ode_problem}\n-----------------------------------------------------------------------------\n{xrst_begin ipopt_nlp_ode_simple dev}\n{xrst_spell\n    fg\n    ny\n    nz\n}\n\nODE Fitting Using Simple Representation\n#######################################\n\nPurpose\n*******\nIn this section we represent the objective and constraint functions,\n(in the simultaneous forward and reverse optimization problem)\nusing the :ref:`cppad_ipopt_nlp@Simple Representation`\nin the sense of ``cppad_ipopt_nlp`` .\n\nArgument Vector\n***************\nThe argument vector that we are optimizing with respect to\n( :math:`x` in :ref:`cppad_ipopt_nlp-name` )\nhas the following structure\n\n.. math::\n\n    x = ( y^0 , \\cdots , y^{S(Nz)} , a )\n\nNote that :math:`x \\in \\B{R}^{S(Nz) + Na}` and\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        y^i & = & ( x_{Ny * i} , \\ldots ,  x_{Ny * i + Ny - 1} )\n        \\\\\n        a   & = & ( x_{Ny *S(Nz) + Ny} , \\ldots , x_{Ny * S(Nz) + Na - 1} )\n    \\end{eqnarray}\n\nObjective Function\n******************\nThe objective function\n( :math:`fg_0 (x)` in :ref:`cppad_ipopt_nlp-name` )\nhas the following representation,\n\n.. math::\n\n    fg_0 (x) = \\sum_{i=1}^{Nz} H_i ( y^{S(i)} , a )\n\nInitial Condition Constraint\n****************************\nFor :math:`i = 1 , \\ldots , Ny`,\nwe define the component functions :math:`fg_i (x)`,\nand corresponding constraint equations, by\n\n.. math::\n\n    0 = fg_i ( x ) = y_i^0 - F_i (a)\n\nTrapezoidal Approximation Constraint\n************************************\nFor :math:`i = 1, \\ldots , S(Nz)`,\nand for :math:`j = 1 , \\ldots , Ny`,\nwe define the component functions :math:`fg_{Ny*i + j} (x)`,\nand corresponding constraint equations, by\n\n.. math::\n\n    0 = fg_{Ny*i + j } = y_j^{i}  -  y_j^{i-1} -\n        \\left[ G_j ( y^i , a ) + G_j ( y^{i-1} , a ) \\right] *\n            \\frac{t_i - t_{i-1} }{ 2 }\n\n{xrst_toc_hidden\n    cppad_ipopt/example/ode_simple.hpp\n}\nSource\n******\nThe file ``ipopt_nlp_ode_simple.hpp``\ncontains source code for this representation of the\nobjective and constraints.\n\n{xrst_end ipopt_nlp_ode_simple}\n-----------------------------------------------------------------------------\n{xrst_begin ipopt_nlp_ode_fast dev}\n{xrst_spell\n    fg\n    ny\n    nz\n}\n\nODE Fitting Using Fast Representation\n#####################################\n\nPurpose\n*******\nIn this section we represent a more complex representation of the\nsimultaneous forward and reverse ODE fitting problem (described above).\nThe representation defines the problem using\nsimpler functions that are faster to differentiate\n(either by hand coding or by using AD).\n\nObjective Function\n******************\nWe use the following representation for the\n:ref:`ipopt_nlp_ode_simple@Objective Function` :\nFor :math:`k = 0 , \\ldots , Nz - 1`,\nwe define the function :math:`r^k : \\B{R}^{Ny+Na} \\rightarrow \\B{R}`\nby\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    fg_0 (x) & = & \\sum_{i=1}^{Nz} H_i ( y^{S(i)} , a )\n    \\\\\n    fg_0 (x) & = & \\sum_{k=0}^{Nz-1} r^k ( u^{k,0} )\n    \\end{eqnarray}\n\nwhere for :math:`k = 0 , \\ldots , Nz-1`,\n:math:`u^{k,0} \\in \\B{R}^{Ny + Na}` is defined by\n:math:`u^{k,0} =   ( y^{S(k+1)} , a )`\n\nRange Indices I(k,0)\n====================\nFor :math:`k = 0 , \\ldots , Nz - 1`,\nthe range index in the vector :math:`fg (x)`\ncorresponding to :math:`r^k ( u^{k,0} )` is 0.\nThus, the range indices are given by\n:math:`I(k,0) = \\{ 0 \\}` for :math:`k = 0 , \\ldots , Nz-1`.\n\nDomain Indices J(k,0)\n=====================\nFor :math:`k = 0 , \\ldots , Nz - 1`,\nthe components of the vector :math:`x`\ncorresponding to the vector :math:`u^{k,0}` are\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    u^{k,0} & = & ( y^{S(k+1} , a )\n    \\\\\n    & = &\n    (   x_{Ny * S(k+1)} \\; , \\;\n        \\ldots \\; , \\;\n        x_{Ny * S(k+1) + Ny - 1} \\; , \\;\n        x_{Ny * S(Nz) + Ny } \\; , \\;\n        \\ldots \\; , \\;\n        x_{Ny * S(Nz) + Ny + Na - 1}\n    )\n    \\end{eqnarray}\n\nThus, the domain indices are given by\n\n.. math::\n\n    J(k,0) = \\{\n        Ny * S(k+1) \\; , \\;\n        \\ldots  \\; , \\;\n        Ny * S(k+1) + Ny - 1 \\; , \\;\n        Ny * S(Nz) + Ny \\; , \\;\n        \\ldots  \\; , \\;\n        Ny * S(Nz) + Ny + Na - 1\n    \\}\n\nInitial Condition\n*****************\nWe use the following representation for the\n:ref:`ipopt_nlp_ode_simple@Initial Condition Constraint` :\nFor :math:`k = Nz` we define the function\n:math:`r^k : \\B{R}^{Ny} \\times \\B{R}^{Na + Ny}` by\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        0 & = & fg_i ( x ) = y_i^0 - F_i (a)\n        \\\\\n        0 & = & r_{i-1}^k ( u^{k,0} ) = y_i^0 - F_i(a)\n    \\end{eqnarray}\n\nwhere :math:`i = 1 , \\ldots , Ny` and\nwhere :math:`u^{k,0} \\in \\B{R}^{Ny + Na}` is defined by\n:math:`u^{k,0}  = ( y^0 , a)`.\n\nRange Indices I(k,0)\n====================\nFor :math:`k = Nz`,\nthe range index in the vector :math:`fg (x)`\ncorresponding to :math:`r^k ( u^{k,0} )` are\n:math:`I(k,0) = \\{ 1 , \\ldots , Ny \\}`.\n\nDomain Indices J(k,0)\n=====================\nFor :math:`k = Nz`,\nthe components of the vector :math:`x`\ncorresponding to the vector :math:`u^{k,0}` are\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    u^{k,0} & = & ( y^0 , a)\n    \\\\\n    & = &\n    (   x_0 \\; , \\;\n        \\ldots \\; , \\;\n        x_{Ny-1} \\; , \\;\n        x_{Ny * S(Nz) + Ny } \\; , \\;\n        \\ldots \\; , \\;\n        x_{Ny * S(Nz) + Ny + Na - 1}\n    )\n    \\end{eqnarray}\n\nThus, the domain indices are given by\n\n.. math::\n\n    J(k,0) = \\{\n        0 \\; , \\;\n        \\ldots  \\; , \\;\n        Ny - 1 \\; , \\;\n        Ny * S(Nz) + Ny \\; , \\;\n        \\ldots  \\; , \\;\n        Ny * S(Nz) + Ny + Na - 1\n    \\}\n\nTrapezoidal Approximation\n*************************\nWe use the following representation for the\n:ref:`ipopt_nlp_ode_simple@Trapezoidal Approximation Constraint` :\nFor :math:`k = 1 , \\ldots , Nz`,\nwe define the function :math:`r^{Nz+k} : \\B{R}^{2*Ny+Na} \\rightarrow \\B{R}^{Ny}` by\n\n.. math::\n\n    r^{Nz+k} ( y , w , a )\n    =\n    y - w -  [ G( y , a ) + G( w , a ) ] * \\frac{ \\Delta t_k }{ 2 }\n\nFor :math:`\\ell = 0 , \\ldots , N(k)-1`,\nusing the notation :math:`i = Ny * S(k-1) + \\ell + 1`,\nthe corresponding trapezoidal approximation is represented by\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    0 & = & fg_{Ny+i} (x)\n    \\\\\n    & = &\n    y^i  -  y^{i-1} -\n    \\left[ G( y^i , a ) + G( y^{i-1} , a ) \\right] * \\frac{\\Delta t_k }{ 2 }\n    \\\\\n    & = &\n    r^{Nz+k} ( u^{Nz+k , \\ell} )\n    \\end{eqnarray}\n\nwhere :math:`u^{Nz+k,\\ell} \\in \\B{R}^{2*Ny + Na}` is defined by\n:math:`u^{Nz+k,\\ell}  = ( y^{i-1} , y^i , a)`.\n\nRange Indices I(k,0)\n====================\nFor :math:`k = Nz + 1, \\ldots , 2*Nz`,\nand :math:`\\ell = 0 , \\ldots , N(k)-1`,\nthe range index in the vector :math:`fg (x)`\ncorresponding to :math:`r^k ( u^{k,\\ell} )` are\n:math:`I(k,\\ell) = \\{ Ny + i , \\ldots , 2*Ny + i - 1  \\}`\nwhere :math:`i = Ny * S(k-1) + \\ell + 1`.\n\nDomain Indices J(k,0)\n=====================\nFor :math:`k = Nz + 1, \\ldots , 2*Nz`,\nand :math:`\\ell = 0 , \\ldots , N(k)-1`,\ndefine :math:`i = Ny * S(k-1) + \\ell + 1`.\nThe components of the vector :math:`x`\ncorresponding to the vector :math:`u^{k,\\ell}` are\n(and the function :math:`fg (x)` in :ref:`cppad_ipopt_nlp-name` )\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    u^{k, \\ell} & = & ( y^{i-1} , y^i , a )\n    \\\\\n    & = &\n    (   x_{Ny * (i-1)} \\; , \\;\n        \\ldots \\; , \\;\n        x_{Ny * (i+1) - 1} \\; , \\;\n        x_{Ny * S(Nz) + Ny } \\; , \\;\n        \\ldots \\; , \\;\n        x_{Ny * S(Nz) + Ny + Na - 1}\n    )\n    \\end{eqnarray}\n\nThus, the domain indices are given by\n\n.. math::\n\n    J(k,\\ell) = \\{\n        Ny * (i-1) \\; , \\;\n        \\ldots  \\; , \\;\n        Ny * (i+1) - 1 \\; , \\;\n        Ny * S(Nz) + Ny \\; , \\;\n        \\ldots  \\; , \\;\n        Ny * S(Nz) + Ny + Na - 1\n    \\}\n\n{xrst_toc_hidden\n    cppad_ipopt/example/ode_fast.hpp\n}\nSource\n******\nThe file ``ipopt_nlp_ode_fast.hpp``\ncontains source code for this representation of the objective\nand constraints.\n\n{xrst_end ipopt_nlp_ode_fast}\n------------------------------------------------------------------------------\n"
  },
  {
    "path": "cppad_ipopt/example/ode_check.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin ipopt_nlp_ode_check.cpp dev}\n\nCorrectness Check for Both Simple and Fast Representations\n##########################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end ipopt_nlp_ode_check.cpp}\n*/\n// BEGIN C++\n# include \"ode_run.hpp\"\n\nbool ode_check(const SizeVector& N, const NumberVector& x)\n{   bool ok = true;\n    size_t i, j;\n\n    // number of components of x corresponding to values for y\n    size_t ny_inx = x.size() - Na;\n\n    // compute the partial sums of the number of grid points\n    // and the maximum step size for the trapezoidal approximation\n    SizeVector S(Nz+1);\n    S[0] = 0;\n    Number max_step = 0.;\n    for(i = 1; i <= Nz; i++)\n    {   S[i] = S[i-1] + N[i];\n        max_step = std::max(max_step, Number(s[i] - s[i-1]) / Number(N[i]) );\n    }\n\n    // split out return values\n    NumberVector a(Na), y_0(Ny), y_1(Ny), y_2(Ny);\n    for(j = 0; j < Na; j++)\n        a[j] = x[ny_inx+j];\n    for(j = 0; j < Ny; j++)\n    {   y_0[j] = x[j];\n        y_1[j] = x[Ny + j];\n        y_2[j] = x[2 * Ny + j];\n    }\n\n    // Check some of the optimal a value\n    Number rel_tol = max_step * max_step;\n    Number abs_tol = rel_tol;\n    Number check_a[] = {a0, a1, a2}; // see the y_one function\n    for(j = 0; j < Na; j++)\n    {\n        ok &= CppAD::NearEqual(\n            check_a[j], a[j], rel_tol, abs_tol\n        );\n    }\n\n    // check accuracy of constraint equations\n    rel_tol = 1e-9;\n    abs_tol = 1e-9;\n\n    // check the initial value constraint\n    NumberVector F = eval_F(a);\n    for(j = 0; j < Ny; j++)\n        ok &= CppAD::NearEqual(F[j], y_0[j], rel_tol, abs_tol);\n\n    // check the first trapezoidal equation\n    NumberVector G_0 = eval_G(y_0, a);\n    NumberVector G_1 = eval_G(y_1, a);\n    Number dt = (s[1] - s[0]) / Number(N[1]);\n    Number check;\n    for(j = 0; j < Ny; j++)\n    {   check = y_1[j] - y_0[j] - (G_1[j]+G_0[j])*dt/2;\n        ok &= CppAD::NearEqual( check, 0., rel_tol, abs_tol);\n    }\n    //\n    // check the second trapezoidal equation\n    NumberVector G_2 = eval_G(y_2, a);\n    if( N[1] == 1 )\n        dt = (s[2] - s[1]) / Number(N[2]);\n    for(j = 0; j < Ny; j++)\n    {   check = y_2[j] - y_1[j] - (G_2[j]+G_1[j])*dt/2;\n        ok &= CppAD::NearEqual( check, 0., rel_tol, abs_tol);\n    }\n    //\n    // check the objective function (specialized to this case)\n    check = 0.;\n    NumberVector y_i(Ny);\n    for(size_t k = 0; k < Nz; k++)\n    {   for(j = 0; j < Ny; j++)\n            y_i[j] =  x[S[k+1] * Ny + j];\n        check += eval_H<Number>(k + 1, y_i, a);\n    }\n    Number obj_value = 0.; // optimal object (no noise in simulation)\n    ok &= CppAD::NearEqual(check, obj_value, rel_tol, abs_tol);\n\n    // Use this empty namespace function to avoid warning that it is not used\n    static size_t ode_check_count = 0;\n    ode_check_count++;\n    ok &= count_eval_r() == ode_check_count;\n\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "cppad_ipopt/example/ode_check.hpp",
    "content": "# ifndef CPPAD_CPPAD_IPOPT_EXAMPLE_ODE_CHECK_HPP\n# define CPPAD_CPPAD_IPOPT_EXAMPLE_ODE_CHECK_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\nextern bool ode_check(const SizeVector& N, const NumberVector& x);\n\n# endif\n"
  },
  {
    "path": "cppad_ipopt/example/ode_fast.hpp",
    "content": "# ifndef CPPAD_CPPAD_IPOPT_EXAMPLE_ODE_FAST_HPP\n# define CPPAD_CPPAD_IPOPT_EXAMPLE_ODE_FAST_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin ipopt_nlp_ode_fast.hpp dev}\n\nODE Fitting Using Fast Representation\n#####################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end ipopt_nlp_ode_fast.hpp}\n*/\n\n// BEGIN C++\n# include \"ode_problem.hpp\"\n\nnamespace {\n    using namespace cppad_ipopt;\n\n    class FG_fast : public cppad_ipopt_fg_info\n    {\n    private:\n        bool       retape_;\n        SizeVector N_;\n        SizeVector S_;\n    public:\n        // derived class part of constructor\n        FG_fast(bool retape_in, const SizeVector& N)\n        : retape_ (retape_in), N_(N)\n        {   assert( N_[0] == 0 );\n            S_.resize( N_.size() );\n            S_[0] = 0;\n            for(size_t i = 1; i < N_.size(); i++)\n                S_[i] = S_[i-1] + N_[i];\n        }\n        // r^k for k = 0, 1, ..., Nz-1 used for measurements\n        // r^k for k = Nz              use for initial condition\n        // r^k for k = Nz+1, ..., 2*Nz used for trapezoidal approx\n        size_t number_functions(void)\n        {   return Nz + 1 + Nz; }\n        ADVector eval_r(size_t k, const ADVector &u)\n        {   count_eval_r();\n\n            size_t j;\n            ADVector y(Ny), a(Na);\n            // objective function --------------------------------\n            if( k < Nz )\n            {   // used for measurement with index k+1\n                ADVector r(1); // return value is a scalar\n                // u is [y( s[k+1] ) , a]\n                for(j = 0; j < Ny; j++)\n                    y[j] = u[j];\n                for(j = 0; j < Na; j++)\n                    a[j] = u[Ny + j];\n                r[0] = eval_H<ADNumber>(k+1, y, a);\n                return r;\n            }\n            // initial condition ---------------------------------\n            if( k == Nz )\n            {   ADVector r(Ny), F(Ny);\n                // u is [y(t), a] at t = 0\n                for(j = 0; j < Ny; j++)\n                    y[j] = u[j];\n                for(j = 0; j < Na; j++)\n                    a[j] = u[Ny + j];\n                F    = eval_F(a);\n                for(j = 0; j < Ny; j++)\n                    r[j]   = y[j] - F[j];\n                return  r;\n            }\n            // trapezoidal approximation -------------------------\n            ADVector ym(Ny), G(Ny), Gm(Ny), r(Ny);\n            // r^k for k = Nz+1, ... , 2*Nz\n            // interval between data samples\n            Number T = s[k-Nz] - s[k-Nz-1];\n            // integration step size\n            Number dt = T / Number( N_[k-Nz] );\n            // u = [ y(t[i-1], a) , y(t[i], a), a )\n            for(j = 0; j < Ny; j++)\n            {   ym[j] = u[j];\n                y[j]  = u[Ny + j];\n            }\n            for(j = 0; j < Na; j++)\n                a[j] = u[2 * Ny + j];\n            Gm  = eval_G(ym, a);\n            G   = eval_G(y,  a);\n            for(j = 0; j < Ny; j++)\n                r[j] = y[j] - ym[j] - (G[j] + Gm[j]) * dt / 2.;\n            return r;\n        }\n        // The operations sequence for r_eval does not depend on u,\n        // hence retape = false should work and be faster.\n        bool retape(size_t k)\n        {   return retape_; }\n        // size of the vector u in eval_r\n        size_t domain_size(size_t k)\n        {   if( k < Nz )\n                return Ny + Na;   // objective function\n            if( k == Nz )\n                return Ny + Na;  // initial value constraint\n            return 2 * Ny + Na;      // trapezodial constraints\n        }\n        // size of the return value from eval_r\n        size_t range_size(size_t k)\n        {   if( k < Nz )\n                return 1;\n            return Ny;\n        }\n        // number of terms that use this value of k\n        size_t number_terms(size_t k)\n        {   if( k <= Nz )\n                return 1;  // r^k used once for k <= Nz\n            // r^k used N_[k-Nz] times for k > Nz\n            return N_[k-Nz];\n        }\n        void index(size_t k, size_t ell, SizeVector& I, SizeVector& J)\n        {   size_t i, j;\n            // # of components of x corresponding to values for y\n            size_t ny_inx = (S_[Nz] + 1) * Ny;\n            // objective function -------------------------------\n            if( k < Nz )\n            {   // index in fg corresponding to objective\n                I[0] = 0;\n                // u = [ y(t, a) , a ]\n                // The first Ny components of u is y(t) at\n                //    t = s[k+1] = t[S_[k+1]]\n                // x indices corresponding to this value of y\n                for(j = 0; j < Ny; j++)\n                    J[j] = S_[k + 1] * Ny + j;\n                // components of x corresponding to a\n                for(j = 0; j < Na; j++)\n                    J[Ny + j] = ny_inx + j;\n                return;\n            }\n            // initial conditions --------------------------------\n            if( k == Nz )\n            {   // index in fg for inidial condition constraint\n                for(j = 0; j < Ny; j++)\n                    I[j] = 1 + j;\n                // u = [ y(t, a) , a ] where t = 0\n                // x indices corresponding to this value of y\n                for(j = 0; j < Ny; j++)\n                    J[j] = j;\n                // following that, u contains the vector a\n                for(j = 0; j < Na; j++)\n                    J[Ny + j] = ny_inx + j;\n                return;\n            }\n            // trapoziodal approximation -------------------------\n            // index of first grid point in this approximation\n            i = S_[k - Nz - 1]  + ell;\n            // There are Ny difference equations for each time\n            // point.  Add one for the objective function, and Ny\n            // for the initial value constraints.\n            for(j = 0; j < Ny; j++)\n                I[j] = 1 + Ny + i * Ny + j;\n            // u = [ y(t, a) , y(t+dt, a) , a ] at t = t[i]\n            for(j = 0; j < Ny; j++)\n            {   J[j]      = i * Ny  + j; // y^i indices\n                J[Ny + j] = J[j] + Ny;   // y^{i+1} indices\n            }\n            for(j = 0; j < Na; j++)\n                J[2 * Ny + j] = ny_inx + j; // a indices\n        }\n    };\n\n}\n// END C++\n# endif\n"
  },
  {
    "path": "cppad_ipopt/example/ode_fast_check.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include \"ode_run.hpp\"\n# include \"ode_fast.hpp\"\n# include \"ode_check.hpp\"\n\nbool ode_fast_check(void)\n{   bool ok = true;\n    bool retape;\n    size_t i;\n\n    // solution vector\n    NumberVector x;\n\n    // number of time grid intervals between measurement values\n    SizeVector N(Nz + 1);\n    N[0] = 0;\n    for(i = 1; i <= Nz; i++)\n        N[i] = 5;\n\n    for(i = 0; i < 2; i++)\n    {   retape = bool(i);\n        ipopt_ode_case<FG_fast>(retape, N, x);\n        ok &= ode_check(N, x);\n    }\n\n    return ok;\n}\n"
  },
  {
    "path": "cppad_ipopt/example/ode_problem.hpp",
    "content": "# ifndef CPPAD_CPPAD_IPOPT_EXAMPLE_ODE_PROBLEM_HPP\n# define CPPAD_CPPAD_IPOPT_EXAMPLE_ODE_PROBLEM_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin ipopt_nlp_ode_problem.hpp dev}\n\nODE Inverse Problem Definitions: Source Code\n############################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end ipopt_nlp_ode_problem.hpp}\n------------------------------------------------------------------------------\n*/\n// BEGIN C++\n# include \"../src/cppad_ipopt_nlp.hpp\"\n\nnamespace {\n    //------------------------------------------------------------------\n    typedef Ipopt::Number Number;\n    Number a0 = 1.;  // simulation value for a[0]\n    Number a1 = 2.;  // simulation value for a[1]\n    Number a2 = 1.;  // simulatioln value for a[2]\n\n    // function used to simulate data\n    Number y_one(Number t)\n    {   Number y_1 =  a0*a1 * (exp(-a2*t) - exp(-a1*t)) / (a1 - a2);\n        return y_1;\n    }\n\n    // time points were we have data (no data at first point)\n    double s[] = { 0.0,        0.5,        1.0,        1.5,        2.0 };\n    // Simulated data for case with no noise (first point is not used)\n    double z[] = { 0.0,  y_one(0.5), y_one(1.0), y_one(1.5), y_one(2.0) };\n    // Number of measurement values\n    size_t Nz  = sizeof(z) / sizeof(z[0]) - 1;\n    // Number of components in the function y(t, a)\n    size_t Ny  = 2;\n    // Number of components in the vectro a\n    size_t Na  = 3;\n\n    // Initial Condition function, F(a) = y(t, a) at t = 0\n    // (for this particular example)\n    template <class Vector>\n    Vector eval_F(const Vector &a)\n    {   Vector F(Ny);\n        // y_0 (t) = a[0]*exp(-a[1] * t)\n        F[0] = a[0];\n        // y_1 (t) =\n        // a[0]*a[1]*(exp(-a[2] * t) - exp(-a[1] * t))/(a[1] - a[2])\n        F[1] = 0.;\n        return F;\n    }\n    // G(y, a) =  \\partial_t y(t, a); i.e. the differential equation\n    // (for this particular example)\n    template <class Vector>\n    Vector eval_G(const Vector &y , const Vector &a)\n    {   Vector G(Ny);\n        // y_0 (t) = a[0]*exp(-a[1] * t)\n        G[0] = -a[1] * y[0];\n        // y_1 (t) =\n        // a[0]*a[1]*(exp(-a[2] * t) - exp(-a[1] * t))/(a[1] - a[2])\n        G[1] = +a[1] * y[0] - a[2] * y[1];\n        return G;\n    }\n    // H(i, y, a) = contribution to objective at i-th data point\n    // (for this particular example)\n    template <class Scalar, class Vector>\n    Scalar eval_H(size_t i, const Vector &y, const Vector &a)\n    {   // This particular H is for a case where y_1 (t) is measured\n        Scalar diff = z[i] - y[1];\n        return diff * diff;\n    }\n    // function used to count the number of calls to eval_r\n    size_t count_eval_r(void)\n    {   static size_t count = 0;\n        ++count;\n        return count;\n    }\n}\n// END C++\n# endif\n"
  },
  {
    "path": "cppad_ipopt/example/ode_run.hpp",
    "content": "# ifndef CPPAD_CPPAD_IPOPT_EXAMPLE_ODE_RUN_HPP\n# define CPPAD_CPPAD_IPOPT_EXAMPLE_ODE_RUN_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin ipopt_nlp_ode_run.hpp dev}\n\nDriver for Running the Ipopt ODE Example\n########################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end ipopt_nlp_ode_run.hpp}\n*/\n\n// BEGIN C++\n# include \"ode_problem.hpp\"\n\nnamespace { // BEGIN empty namespace -----------------------------------------\nusing namespace cppad_ipopt;\n\ntemplate <class FG_info>\nvoid ipopt_ode_case(\n    bool  retape        ,\n    const SizeVector& N ,\n    NumberVector&     x )\n{\n    size_t i, j;\n\n    // compute the partial sums of the number of grid points\n    assert( N.size() == Nz + 1);\n    assert( N[0] == 0 );\n    SizeVector S(Nz+1);\n    S[0] = 0;\n    for(i = 1; i <= Nz; i++)\n        S[i] = S[i-1] + N[i];\n\n    // number of components of x corresponding to values for y\n    size_t ny_inx = (S[Nz] + 1) * Ny;\n    // number of constraints (range dimension of g)\n    size_t m      = ny_inx;\n    // number of components in x (domain dimension for f and g)\n    size_t n      = ny_inx + Na;\n    // the argument vector for the optimization is\n    // y(t) at t[0] , ... , t[S[Nz]] , followed by a\n    NumberVector x_i(n), x_l(n), x_u(n);\n    for(j = 0; j < ny_inx; j++)\n    {   x_i[j] = 0.;       // initial y(t) for optimization\n        x_l[j] = -1.0e19;  // no lower limit\n        x_u[j] = +1.0e19;  // no upper limit\n    }\n    for(j = 0; j < Na; j++)\n    {   x_i[ny_inx + j ] = .5;       // initiali a for optimization\n        x_l[ny_inx + j ] =  -1.e19;  // no lower limit\n        x_u[ny_inx + j ] =  +1.e19;  // no upper\n    }\n    // all of the difference equations are constrained to the value zero\n    NumberVector g_l(m), g_u(m);\n    for(i = 0; i < m; i++)\n    {   g_l[i] = 0.;\n        g_u[i] = 0.;\n    }\n\n    // object defining the objective f(x) and constraints g(x)\n    FG_info fg_info(retape, N);\n\n    // create the CppAD Ipopt interface\n    cppad_ipopt_solution solution;\n    Ipopt::SmartPtr<Ipopt::TNLP> cppad_nlp = new cppad_ipopt_nlp(\n        n, m, x_i, x_l, x_u, g_l, g_u, &fg_info, &solution\n    );\n\n    // Create an Ipopt application\n    using Ipopt::IpoptApplication;\n    Ipopt::SmartPtr<IpoptApplication> app = new IpoptApplication();\n\n    // turn off any printing\n    app->Options()->SetIntegerValue(\"print_level\", 0);\n    app->Options()->SetStringValue(\"sb\", \"yes\");\n\n    // maximum number of iterations\n    app->Options()->SetIntegerValue(\"max_iter\", 30);\n\n    // approximate accuracy in first order necessary conditions;\n    // see Mathematical Programming, Volume 106, Number 1,\n    // Pages 25-57, Equation (6)\n    app->Options()->SetNumericValue(\"tol\", 1e-9);\n\n    // Derivative testing is very slow for large problems\n    // so comment this out if you use a large value for N[].\n    app->Options()-> SetStringValue( \"derivative_test\", \"second-order\");\n    app->Options()-> SetNumericValue( \"point_perturbation_radius\", 0.);\n\n# ifndef NDEBUG\n    bool ok = true;\n    //\n    // Initialize the application and process the options\n    Ipopt::ApplicationReturnStatus status = app->Initialize();\n    ok    &= status == Ipopt::Solve_Succeeded;\n    //\n    // Run the application\n    status = app->OptimizeTNLP(cppad_nlp);\n    ok    &= status == Ipopt::Solve_Succeeded;\n    //\n    assert(ok);\n# else\n    app->Initialize();\n    app->OptimizeTNLP(cppad_nlp);\n# endif\n\n    // return the solution\n    x.resize( solution.x.size() );\n    for(j = 0; j < x.size(); j++)\n        x[j] = solution.x[j];\n\n    return;\n}\n} // END empty namespace ----------------------------------------------------\n// END C++\n\n# endif\n"
  },
  {
    "path": "cppad_ipopt/example/ode_simple.hpp",
    "content": "# ifndef CPPAD_CPPAD_IPOPT_EXAMPLE_ODE_SIMPLE_HPP\n# define CPPAD_CPPAD_IPOPT_EXAMPLE_ODE_SIMPLE_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin ipopt_nlp_ode_simple.hpp dev}\n\nODE Fitting Using Simple Representation\n#######################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end ipopt_nlp_ode_simple.hpp}\n*/\n\n// BEGIN C++\n# include \"ode_problem.hpp\"\n\n// define in the empty namespace\nnamespace {\n    using namespace cppad_ipopt;\n\n    class FG_simple : public cppad_ipopt_fg_info\n    {\n    private:\n        bool       retape_;\n        SizeVector N_;\n        SizeVector S_;\n    public:\n        // derived class part of constructor\n        FG_simple(bool retape_in, const SizeVector& N)\n        : retape_ (retape_in), N_(N)\n        {   assert( N_[0] == 0 );\n            S_.resize( N.size() );\n            S_[0] = 0;\n            for(size_t i = 1; i < N_.size(); i++)\n                S_[i] = S_[i-1] + N_[i];\n        }\n        // Evaluation of the objective f(x), and constraints g(x)\n        // using an Algorithmic Differentiation (AD) class.\n        ADVector eval_r(size_t not_used, const ADVector&  x)\n        {   count_eval_r();\n\n            // temporary indices\n            size_t i, j, k;\n            // # of components of x corresponding to values for y\n            size_t ny_inx = (S_[Nz] + 1) * Ny;\n            // # of constraints (range dimension of g)\n            size_t m = ny_inx;\n            // # of components in x (domain dimension for f and g)\n            assert ( x.size() == ny_inx + Na );\n            // vector for return value\n            ADVector fg(m + 1);\n            // vector of parameters\n            ADVector a(Na);\n            for(j = 0; j < Na; j++)\n                a[j] = x[ny_inx + j];\n            // vector for value of y(t)\n            ADVector y(Ny);\n            // objective function -------------------------------\n            fg[0] = 0.;\n            for(k = 0; k < Nz; k++)\n            {   for(j = 0; j < Ny; j++)\n                    y[j] = x[Ny*S_[k+1] + j];\n                fg[0] += eval_H<ADNumber>(k+1, y, a);\n            }\n            // initial condition ---------------------------------\n            ADVector F = eval_F(a);\n            for(j = 0; j < Ny; j++)\n            {   y[j]    = x[j];\n                fg[1+j] = y[j] - F[j];\n            }\n            // trapezoidal approximation --------------------------\n            ADVector ym(Ny), G(Ny), Gm(Ny);\n            G = eval_G(y, a);\n            ADNumber dy;\n            for(k = 0; k < Nz; k++)\n            {   // interval between data points\n                Number T  = s[k+1] - s[k];\n                // integration step size\n                Number dt = T / Number( N_[k+1] );\n                for(j = 0; j < N_[k+1]; j++)\n                {   size_t Index = (j + S_[k]) * Ny;\n                    // y(t) at end of last step\n                    ym = y;\n                    // G(y, a) at end of last step\n                    Gm = G;\n                    // value of y(t) at end of this step\n                    for(i = 0; i < Ny; i++)\n                        y[i] = x[Ny + Index + i];\n                    // G(y, a) at end of this step\n                    G = eval_G(y, a);\n                    // trapezoidal approximation residual\n                    for(i = 0; i < Ny; i++)\n                    {   dy = (G[i] + Gm[i]) * dt / 2;\n                        fg[1+Ny+Index+i] =\n                            y[i] - ym[i] - dy;\n                    }\n                }\n            }\n            return fg;\n        }\n        // The operations sequence for r_eval does not depend on u,\n        // hence retape = false should work and be faster.\n        bool retape(size_t k)\n        {   return retape_; }\n    };\n\n}\n// END C++\n# endif\n"
  },
  {
    "path": "cppad_ipopt/example/ode_simple_check.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include \"ode_run.hpp\"\n# include \"ode_simple.hpp\"\n# include \"ode_check.hpp\"\n\nbool ode_simple_check(void)\n{   bool ok = true;\n    bool retape;\n    size_t i;\n\n    // solution vector\n    NumberVector x;\n\n    // number of time grid intervals between measurement values\n    SizeVector N(Nz + 1);\n    N[0] = 0;\n    for(i = 1; i <= Nz; i++)\n        N[i] = 4;\n\n    for(i = 0; i < 2; i++)\n    {   retape = bool(i);\n        ipopt_ode_case<FG_simple>(retape, N, x);\n        ok &= ode_check(N, x);\n    }\n\n    return ok;\n}\n"
  },
  {
    "path": "cppad_ipopt/example/test.sh.in",
    "content": "#! /bin/bash -e\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\nexport LD_LIBRARY_PATH=@CPPAD_IPOPT_LD_PATH@\n./example\n"
  },
  {
    "path": "cppad_ipopt/speed/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-23 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# Build the cppad_ipopt/speed directory tests\n# Inherit build type from ../CMakeList.txt\n\n# Local include directories to search (not in package_prefix/include)\nINCLUDE_DIRECTORIES( ${CMAKE_CURRENT_SOURCE_DIR}/../src )\n\n# Local link directories to search (not in external packages)\n# (cannot use ../src/cppad_ipopt library because it is linked with debugging)\nLINK_DIRECTORIES( ${ipopt_LIBRARY_DIRS} )\n\n# add_executable(<name> [WIN32] [MACOSX_BUNDLE] [EXCLUDE_FROM_ALL]\n#                 source1 source2 ... sourceN\n# )\n# Include source for cppad_ipopt library so we build it without debugging\n# BEGIN_SORT_THIS_LINE_PLUS_2\nSET(source_list\n    ../src/cppad_ipopt_nlp.cpp\n    ../src/fun_record.hpp\n    ../src/hes_fg_map.cpp\n    ../src/jac_g_map.cpp\n    ../src/sparse_map2vec.cpp\n    ../src/vec_fun_pattern.cpp\n    ode_speed.cpp\n    speed.cpp\n)\n# END_SORT_THIS_LINE_MINUS_2\n\nset_compile_flags( cppad_ipopt_example \"${cppad_debug_which}\" \"${source_list}\" )\n#\nADD_EXECUTABLE( cppad_ipopt_speed EXCLUDE_FROM_ALL ${source_list} )\n\n# List of libraries to be linked into the specified target\nTARGET_LINK_LIBRARIES(\n    cppad_ipopt_speed\n    cppad_ipopt\n    ${cppad_lib}\n    ${ipopt_LINK_LIBRARIES}\n    ${colpack_libs}\n)\n\n# check_cppad_ipopt_speed\nadd_check_executable(check_cppad_ipopt speed)\n"
  },
  {
    "path": "cppad_ipopt/speed/ode_speed.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin ipopt_ode_speed.cpp dev}\n\nSpeed Test for Both Simple and Fast Representations\n###################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end ipopt_ode_speed.cpp}\n*/\n\n// BEGIN C++\n# include \"../example/ode_run.hpp\"\n# include \"../example/ode_simple.hpp\"\n# include \"../example/ode_fast.hpp\"\n# include <cassert>\n# include <cstring>\n\n# if CPPAD_HAS_GETTIMEOFDAY & CPPAD_NO_MICROSOFT\n# include <sys/time.h>\n# else\n# include <ctime>\n# endif\n\nnamespace {\n    double current_second(void)\n    {\n# if CPPAD_HAS_GETTIMEOFDAY & CPPAD_NOT_MICOROSOFT\n        struct timeval value;\n        gettimeofday(&value, 0);\n        return double(value.tv_sec) + double(value.tv_usec) * 1e-6;\n# else\n        return (double) clock() / (double) CLOCKS_PER_SEC;\n# endif\n    }\n}\n\ndouble ode_speed(const char* name, size_t& count)\n{\n    // determine simple and retape flags\n    bool simple = true, retape = true;\n    if( std::strcmp(name, \"simple_retape_no\") == 0 )\n    {   simple = true; retape = false; }\n    else if( std::strcmp(name, \"simple_retape_yes\") == 0 )\n    {   simple = true; retape = true; }\n    else if( std::strcmp(name, \"fast_retape_no\") == 0 )\n    {   simple = false; retape = false; }\n    else if( std::strcmp(name, \"fast_retape_yes\") == 0 )\n    {   simple = false; retape = true; }\n    else\n        assert(false);\n\n    size_t i;\n    double s0, s1;\n    size_t  c0, c1;\n\n    // solution vector\n    NumberVector x;\n\n    // number of time grid intervals between measurement values\n    SizeVector N(Nz + 1);\n    N[0] = 0;\n    for(i = 1; i <= Nz; i++)\n    {   N[i] = 10;\n        // n   += N[i] * Ny;\n    }\n    // n += Na;\n\n    s0              = current_second();\n    c0              = count_eval_r();\n    if( simple )\n        ipopt_ode_case<FG_simple>(retape, N, x);\n    else\n        ipopt_ode_case<FG_fast>(retape, N, x);\n    s1              = current_second();\n    c1              = count_eval_r();\n    count           = c1 - c0 - 1;\n    return s1 - s0;\n}\n// END C++\n"
  },
  {
    "path": "cppad_ipopt/speed/speed.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cstdio>  // system include files used for I/O\n# include <string>  // std::string\n\n// external complied tests\nextern double ode_speed(const char* name, size_t& count);\n\n// main program that runs all the cppad_ipopt speed tests\nint main(void)\n{   using std::printf;\n    const char* name;\n    double      seconds;\n    size_t      count;\n\n    name    = \"simple_retape_yes\";\n    seconds = ode_speed(name, count);\n    printf(\"ode %20s: seconds = %5.2f: eval_r_count = %d\\n\",\n        name, seconds, int(count) );\n\n    name    = \"simple_retape_no\";\n    seconds = ode_speed(name, count);\n    printf(\"ode %20s: seconds = %5.2f: eval_r_count = %d\\n\",\n        name, seconds, int(count) );\n\n    name    = \"fast_retape_yes\";\n    seconds = ode_speed(name, count);\n    printf(\"ode %20s: seconds = %5.2f: eval_r_count = %d\\n\",\n        name, seconds, int(count) );\n\n    name    = \"fast_retape_no\";\n    seconds = ode_speed(name, count);\n    printf(\"ode %20s: seconds = %5.2f: eval_r_count = %d\\n\",\n        name, seconds, int(count) );\n\n    return 0;\n}\n"
  },
  {
    "path": "cppad_ipopt/speed/test.sh.in",
    "content": "#! /bin/bash -e\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\nexport LD_LIBRARY_PATH=@CPPAD_IPOPT_LD_PATH@\n./speed\n"
  },
  {
    "path": "cppad_ipopt/src/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-25 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# Build the cppad_ipopt/src library\n# Inherit build type from ../CMakeList.txt\n\n#  add_library(<name> [STATIC | SHARED | MODULE] [EXCLUDE_FROM_ALL]\n#  source1 source2 ... sourceN)\n# )\n# BEGIN_SORT_THIS_LINE_PLUS_2\nSET(source_list\n    cppad_ipopt_nlp.cpp\n    hes_fg_map.cpp\n    jac_g_map.cpp\n    sparse_map2vec.cpp\n    vec_fun_pattern.cpp\n)\n# END_SORT_THIS_LINE_MINUS_2\n\n# set_compiler_flags\nset_compile_flags( cppad_ipopt \"${cppad_debug_which}\" \"${source_list}\" )\n#\n# add_library\nIF( \"${is_cppad_lib_dynamic}\" STREQUAL \"0\" )\n    ADD_LIBRARY( cppad_ipopt STATIC ${source_list} )\nELSEIF( \"${is_cppad_lib_dynamic}\" STREQUAL \"1\" )\n    ADD_LIBRARY( cppad_ipopt SHARED ${source_list} )\nENDIF( )\n\n# install(FILES files... DESTINATION <dir>\n#  [PERMISSIONS permissions...]\n#  [CONFIGURATIONS [Debug|Release|...]]\n#  [COMPONENT <component>]\n#  [RENAME <name>] [OPTIONAL])\nINSTALL(FILES cppad_ipopt_nlp.hpp DESTINATION ${cppad_abs_includedir})\n\n# install(TARGETS myExe mySharedLib myStaticLib\n#  RUNTIME DESTINATION bin\n#  LIBRARY DESTINATION lib\n#  ARCHIVE DESTINATION lib/static)\nINSTALL(TARGETS cppad_ipopt DESTINATION ${cppad_abs_libdir})\n"
  },
  {
    "path": "cppad_ipopt/src/cppad_ipopt_nlp.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <limits>\n\n# include \"cppad_ipopt_nlp.hpp\"\n# include \"sparse_map2vec.hpp\"\n# include \"jac_g_map.hpp\"\n# include \"hes_fg_map.hpp\"\n# include \"vec_fun_pattern.hpp\"\n# include \"fun_record.hpp\"\n\n\n/// If 0 tracing is off, otherwise tracing is on.\n# define  CPPAD_IPOPT_NLP_TRACE 0\n\n# if CPPAD_IPOPT_NLP_TRACE\n# include <cstdio>\n# endif\n\n// ---------------------------------------------------------------------------\nnamespace cppad_ipopt {\n// ---------------------------------------------------------------------------\n/*!\n\\{\n\\file cppad_ipopt_nlp.cpp\n\\brief Member functions for the cppad_ipopt_nlp class.\n*/\n\n\n/*!\nConstructor for the \\ref Nonlinear_Programming_Problem.\n\n\\param n\ndimension of the domain space for f(x) and g(x).\n\n\\param m\ndimension of the range space for g(x)\n\n\\param x_i\ninitial value of x during the optimization procedure (size n).\n\n\\param x_l\nlower limit for x (size n).\n\n\\param x_u\nupper limit for x (size n).\n\n\\param g_l\nlower limit for g(x) (size m).\n\n\\param g_u\nupper limit for g(x) (size m).\n\n\\param fg_info\npointer to base class version of derived class object used to get\ninformation about the user's representation for f(x) and g(x).\n(The object pointed to must not be deleted before this cppad_ipopt_nlp object).\n\n\\param solution\npointer to object where final results are stored.\n(The object pointed to must not be deleted before this cppad_ipopt_nlp object).\n\n\\par Constants\nThe following values are set by the constructor and are const\nor effectively const; i.e., they are set by the constructor and should\nnot be changed:\n\\verbatim\n    n_, m_, x_i_, x_l_, x_u_, g_l_, g_u_, K_, L_, p_, q_, retape_,\n    pattern_jac_r_, pattern_hes_r_, index_jac_g_, index_hes_fg_,\n    nnz_jac_g_, iRow_jac_g_, jCol_jac_g_,\n    nnz_h_lag_, iRow_h_lag_, jCol_h_lag_,\n\\endverbatim\nIn addition, the function calls <tt>fg_info->set_n(n)</tt>\nand <tt>fg_info->set_m(m)</tt> are used to set the values of n\nand m in fg_info.\n\n\\par Variables\nThe following arrays have fixed size which is set during this constructor:\n\n\\li tape_ok_ has size K_. It is initialized as true for indices\n k such that <tt>retape[k]</tt> is false.\n\n\\li r_fun_ has size K_. It is initialize with the default\n ADFun constructor. Then, for indices k such that\n<tt>retape[k]</tt> is false, the operation sequence corresponding\nto \\f$ r_k (u) \\f$ is stored in <tt>r_fun_[k]</tt>.\n\n\\li I_ has size equal to the maximum of <tt>p[k]</tt> w.r.t k.\n\n\\li J_ has size equal to the maximum of <tt>q[k]</tt> w.r.t k.\n\n\\par NDEBUG\nIf the preprocessor symbol NEBUG is not defined,\ncertain of the assumptions about the function calls of the form\n\\verbatim\n    fg_info->index(k, ell, I, J)\n\\endverbatim\nare checked to make sure they hold.\n*/\ncppad_ipopt_nlp::cppad_ipopt_nlp(\n    size_t n                         ,\n    size_t m                         ,\n    const NumberVector    &x_i       ,\n    const NumberVector    &x_l       ,\n    const NumberVector    &x_u       ,\n    const NumberVector    &g_l       ,\n    const NumberVector    &g_u       ,\n    cppad_ipopt_fg_info*   fg_info   ,\n    cppad_ipopt_solution*  solution )\n    : n_ ( n ),\n        m_ ( m ),\n        x_i_ ( x_i ),\n        x_l_ ( x_l ),\n        x_u_ ( x_u ),\n        g_l_ ( g_l ),\n        g_u_ ( g_u ),\n        fg_info_ ( fg_info ) ,\n        solution_ (solution) ,\n        infinity_ ( std::numeric_limits<Number>::infinity() )\n{   size_t k;\n\n    // set information needed in cppad_ipopt_fg_info\n    fg_info_->set_n(n);\n    fg_info_->set_m(m);\n\n    // get information from derived class version of fg_info\n    K_ = fg_info_->number_functions();\n    L_.resize(K_);\n    p_.resize(K_);\n    q_.resize(K_);\n    r_fun_.resize(K_);\n    retape_.resize(K_);\n    tape_ok_.resize(K_);\n    pattern_jac_r_.resize(K_);\n    pattern_hes_r_.resize(K_);\n    size_t max_p      = 0;\n    size_t max_q      = 0;\n    for(k = 0; k < K_; k++)\n    {   L_[k]       = fg_info_->number_terms(k);\n        p_[k]       = fg_info_->range_size(k);\n        q_[k]       = fg_info_->domain_size(k);\n        retape_[k]  = fg_info_->retape(k);\n        max_p       = std::max(max_p, p_[k]);\n        max_q       = std::max(max_q, q_[k]);\n        pattern_jac_r_[k].resize( p_[k] * q_[k] );\n        pattern_hes_r_[k].resize( q_[k] * q_[k] );\n    }\n    I_.resize(max_p);\n    J_.resize(max_q);\n# ifndef NDEBUG\n    size_t i, j, ell;\n    // check for valid range and domain indices\n    for(k = 0; k < K_; k++) for(ell = 0; ell < L_[k]; ell++)\n    {\n        for( i = 0; i < p_[k]; i++)\n            I_[i] = m+1; // an invalid range index\n        for( j = 0; j < q_[k]; j++)\n            J_[j] = n; // an invalid domain index\n        fg_info_->index(k, ell, I_, J_);\n        for( i = 0; i < p_[k]; i++) if( I_[i] > m )\n        {   std::cerr << \"k=\" << k << \", ell=\" << ell\n            << \", I[\" << i << \"]=\" << I_[i] << std::endl;\n            CPPAD_ASSERT_KNOWN( I_[i] <= m,\n            \"cppad_ipopt_nlp: invalid value in index vector I\"\n            );\n        }\n        for( j = 0; j < q_[k]; j++) if( J_[j] >= n )\n        {   std::cerr << \"k=\" << k << \", ell=\" << ell\n            << \", J[\" << j << \"]=\" << J_[j] << std::endl;\n            CPPAD_ASSERT_KNOWN( J_[j] < n,\n            \"cppad_ipopt_nlp: invalid value in index vector J\"\n            );\n        }\n    }\n# endif\n    // record r[k] for functions that do not need retaping\n    for(k = 0; k < K_; k++)\n    {   tape_ok_[k] = false;\n        if( ! retape_[k] )\n        {   // Operation sequence does not depend on value\n            // of u so record it once here in the constructor.\n            fg_info_->index(k, 0, I_, J_);\n            fun_record(\n                fg_info_        ,   // inputs\n                k               ,\n                p_              ,\n                q_              ,\n                n_              ,\n                x_i_            ,\n                J_              ,\n                r_fun_              // output\n            );\n            // take time to optimize because only recording once\n            r_fun_[k].optimize();\n            // ok and will stay that way\n            tape_ok_[k] = true;\n        }\n    }\n\n    // compute a sparsity patterns for each r_k (u)\n    vec_fun_pattern(\n        K_, p_, q_, retape_, r_fun_,      // inputs\n        pattern_jac_r_, pattern_hes_r_    // outputs\n    );\n\n    // mapping from (i,j) to Ipopt sparsity index for Jacobian of g\n    jac_g_map(\n        fg_info_, m_, n_, K_, L_, p_, q_, pattern_jac_r_,   // inputs\n        I_, J_,                                             // work\n        index_jac_g_                                        // outputs\n    );\n\n    // mapping from (i,j) to Ipopt sparsity index for Hessian of Lagragian\n    hes_fg_map(\n        fg_info_, m_, n_, K_, L_, p_, q_, pattern_hes_r_,   // inputs\n        I_, J_,                                             // work\n        index_hes_fg_                                       // outputs\n    );\n\n    // Compute Ipopt sparsity structure for Jacobian of g\n    sparse_map2vec(\n        index_jac_g_,                         // inputs\n        nnz_jac_g_, iRow_jac_g_, jCol_jac_g_  // outputs\n    );\n\n    // Compute Ipopt sparsity structure for Hessian of Lagragian\n    sparse_map2vec(\n        index_hes_fg_,                        // inputs\n        nnz_h_lag_, iRow_h_lag_, jCol_h_lag_  // outputs\n    );\n}\n\n/// The destructor takes no special action.\ncppad_ipopt_nlp::~cppad_ipopt_nlp()\n{}\n\n/*!\nReturn dimension information about optimization problem.\n\n\\param[out] n\nis set to the value n_.\n\n\\param[out] m\nis set to the value m_.\n\n\\param[out] nnz_jac_g\nis set to the value of nnz_jac_g_.\n\n\\param[out] nnz_h_lag\nis set to the value of nnz_h_lag_.\n\n\\param[out] index_style\nis set to C_STYLE; i.e., zeoro based indexing is used in the\ninformation passed to Ipopt.\n*/\nbool cppad_ipopt_nlp::get_nlp_info(Index& n, Index& m, Index& nnz_jac_g,\n                                 Index& nnz_h_lag, IndexStyleEnum& index_style)\n{\n    n = static_cast<Index>( n_ );\n    m = static_cast<Index>( m_ );\n    nnz_jac_g = static_cast<Index>( nnz_jac_g_ );\n    nnz_h_lag = static_cast<Index>( nnz_h_lag_ );\n\n    // use the fortran index style for row/col entries\n    index_style = C_STYLE;\n\n    return true;\n}\n\n/*!\nReturn bound information about optimization problem.\n\n\\param[in] n\nis the dimension of the domain space for f(x) and g(x); i.e.,\nit must be equal to n_.\n\n\\param[out] x_l\nis a vector of size n.\nThe input value of its elements does not matter.\nOn output, it is a copy of the lower bound for \\f$ x \\f$; i.e.,\n x_l_.\n\n\\param[out] x_u\nis a vector of size n.\nThe input value of its elements does not matter.\nOn output, it is a copy of the upper bound for \\f$ x \\f$; i.e.,\n x_u_.\n\n\\param[in] m\nis the dimension of the range space for g(x). i.e.,\nit must be equal to m_.\n\n\\param[out] g_l\nis a vector of size m.\nThe input value of its elements does not matter.\nOn output, it is a copy of the lower bound for \\f$ g(x) \\f$; i.e., g_l_.\n\n\\param[out] g_u\nis a vector of size m.\nThe input value of its elements does not matter.\nOn output, it is a copy of the upper bound for \\f$ g(x) \\f$; i.e, g_u_.\n*/\nbool cppad_ipopt_nlp::get_bounds_info(Index n, Number* x_l, Number* x_u,\n                            Index m, Number* g_l, Number* g_u)\n{   size_t i, j;\n    // here, the n and m we gave IPOPT in get_nlp_info are passed back\n    CPPAD_ASSERT_UNKNOWN(size_t(n) == n_);\n    CPPAD_ASSERT_UNKNOWN(size_t(m) == m_);\n\n    // pass back bounds\n    for(j = 0; j < n_; j++)\n    {   x_l[j] = x_l_[j];\n        x_u[j] = x_u_[j];\n    }\n    for(i = 0; i < m_; i++)\n    {   g_l[i] = g_l_[i];\n        g_u[i] = g_u_[i];\n    }\n\n    return true;\n}\n\n/*!\nReturn initial x value where optimization is started.\n\n\\param[in] n\nmust be equal to the domain dimension for f(x) and g(x); i.e.,\nit must be equal to n_.\n\n\\param[in] init_x\nmust be equal to true.\n\n\\param[out] x\nis a vector of size n.\nThe input value of its elements does not matter.\nOn output, it is a copy of the initial value for \\f$ x \\f$; i.e. x_i_.\n\n\\param[in] init_z\nmust be equal to false.\n\n\\param z_L\nis not used.\n\n\\param z_U\nis not used.\n\n\\param[in] m\nmust be equal to the range dimension for g(x); i.e.,\nit must be equal to m_.\n\n\\param init_lambda\nmust be equal to false.\n\n\\param lambda\nis not used.\n*/\nbool cppad_ipopt_nlp::get_starting_point(Index n, bool init_x, Number* x,\n                                         bool init_z, Number* z_L, Number* z_U,\n                                         Index m, bool init_lambda,\n                                         Number* lambda)\n{   size_t j;\n\n    CPPAD_ASSERT_UNKNOWN(size_t(n) == n_ );\n    CPPAD_ASSERT_UNKNOWN(size_t(m) == m_ );\n    CPPAD_ASSERT_UNKNOWN(init_x == true);\n    CPPAD_ASSERT_UNKNOWN(init_z == false);\n    CPPAD_ASSERT_UNKNOWN(init_lambda == false);\n\n    for(j = 0; j < n_; j++)\n        x[j] = x_i_[j];\n\n    return true;\n}\n\n/*!\nEvaluate the objective function f(x).\n\n\\param[in] n\nis the dimension of the argument space for f(x); i.e., must be equal n_.\n\n\\param[in] x\nis a vector of size n containing the point at which to evaluate\nthe function f(x).\n\n\\param[in] new_x\nis false if the previous call to any one of the\n\\ref Deprecated_Evaluation_Methods used the same value for x.\n\n\\param[out] obj_value\nis the value of the objective f(x) at this value of x.\n\n\\return\nThe return value is always true; see \\ref Deprecated_Evaluation_Methods.\n\n\\par Efficiency\nThis routine could be more efficient\n(for certain when when L[k] > 1 and retape[k] is true)\nif the users also provided a version\nof the function <tt>fg_info->eval_r(k, u)</tt> where u was of type\n NumberVector.\n*/\nbool cppad_ipopt_nlp::eval_f(\n    Index n, const Number* x, bool new_x, Number& obj_value\n)\n{\n    CPPAD_ASSERT_UNKNOWN(size_t(n) == n_ );\n\n    size_t iobj, j, k, ell;\n\n    // initialize summation\n    obj_value = 0.;\n\n    // update tape_ok_ flag\n    for(k = 0; k < K_; k++)\n    {   if( retape_[k] && (new_x || L_[k] > 1) )\n            tape_ok_[k] = false;\n    }\n\n    for(k = 0; k < K_; k++) for(ell = 0; ell < L_[k]; ell++)\n    {   fg_info_->index(k, ell, I_, J_);\n        for(iobj = 0; iobj < p_[k]; iobj++) if( I_[iobj] == 0 )\n        {   if( ! tape_ok_[k] )\n            {   // Record r_k for value of u corresponding to x\n                fun_record(\n                    fg_info_        ,   // inputs\n                    k               ,\n                    p_              ,\n                    q_              ,\n                    n_              ,\n                    x               ,\n                    J_              ,\n                    r_fun_             // output\n                );\n                tape_ok_[k] = ! (retape_[k] || L_[k] > 1);\n            }\n            NumberVector u(q_[k]);\n            NumberVector r(p_[k]);\n            for(j = 0; j < q_[k]; j++)\n            {   CPPAD_ASSERT_UNKNOWN( J_[j] < n_ );\n                u[j]   = x[ J_[j] ];\n            }\n            r          = r_fun_[k].Forward(0, u);\n            obj_value += r[iobj];\n        }\n    }\n# if CPPAD_IPOPT_NLP_TRACE\n    using std::printf;\n    for(j = 0; j < n_; j++)\n        printf(\"cppad_ipopt_nlp::eval_f::x[%d] = %20.14g\\n\", j, x[j]);\n    printf(\"cppad_ipopt_nlp::eval_f::obj_value = %20.14g\\n\", obj_value);\n# endif\n# ifndef NDEBUG\n    CPPAD_ASSERT_KNOWN(\n        (-infinity_ < obj_value) && (obj_value < infinity_),\n        \"cppad_ipopt_nlp::eval_f:: objective value is not finite\"\n    );\n# endif\n    return true;\n}\n\n/*!\nEvaluate the gradient of f(x).\n\n\\param[in] n\nis the dimension of the argument space for f(x); i.e., must be equal n_.\n\n\\param[in] x\nhas a vector of size n containing the point at which to evaluate\nthe gradient of f(x).\n\n\\param[in] new_x\nis false if the previous call to any one of the\n\\ref Deprecated_Evaluation_Methods used the same value for x.\n\n\\param[out] grad_f\nis a vector of size n.\nThe input value of its elements does not matter.\nThe output value of its elements is the gradient of f(x)\nat this value of.\n\n\\return\nThe return value is always true; see \\ref Deprecated_Evaluation_Methods.\n*/\nbool cppad_ipopt_nlp::eval_grad_f(\n    Index n, const Number* x, bool new_x, Number* grad_f\n)\n{   CPPAD_ASSERT_UNKNOWN(size_t(n) == n_ );\n\n    size_t iobj, i, j, k, ell;\n\n    // initialize summation\n    for(j = 0; j < n_; j++)\n        grad_f[j] = 0.;\n\n    // update tape_ok_ flag\n    for(k = 0; k < K_; k++)\n    {   if( retape_[k] && (new_x || L_[k] > 1) )\n            tape_ok_[k] = false;\n    }\n\n    for(k = 0; k < K_; k++) for(ell = 0; ell < L_[k]; ell++)\n    {   fg_info_->index(k, ell, I_, J_);\n        for(iobj = 0; iobj < p_[k]; iobj++) if( I_[iobj] == 0 )\n        {   if( ! tape_ok_[k] )\n            {   // Record r_k for value of u corresponding to x\n                fun_record(\n                    fg_info_        ,   // inputs\n                    k               ,\n                    p_              ,\n                    q_              ,\n                    n_              ,\n                    x               ,\n                    J_              ,\n                    r_fun_              // output\n                );\n                tape_ok_[k] = ! (retape_[k] || L_[k] > 1);\n            }\n            NumberVector u(q_[k]);\n            NumberVector w(p_[k]);\n            NumberVector r_grad(q_[k]);\n            for(j = 0; j < q_[k]; j++)\n            {   CPPAD_ASSERT_UNKNOWN( J_[j] < n_ );\n                u[j]   = x[ J_[j] ];\n            }\n            r_fun_[k].Forward(0, u);\n            for(i = 0; i < p_[k]; i++)\n                w[i] = 0.;\n            w[iobj]    = 1.;\n            r_grad     = r_fun_[k].Reverse(1, w);\n            for(j = 0; j < q_[k]; j++)\n            {   CPPAD_ASSERT_UNKNOWN( J_[j] < n_ );\n                grad_f[ J_[j] ]  += r_grad[j];\n            }\n        }\n    }\n# if CPPAD_IPOPT_NLP_TRACE\n    using std::printf;\n    for(j = 0; j < n_; j++) printf(\n    \"cppad_ipopt_nlp::eval_grad_f::x[%d] = %20.14g\\n\", j, x[j]\n    );\n    for(j = 0; j < n_; j++) printf(\n    \"cppad_ipopt_nlp::eval_grad_f::grad_f[%d] = %20.14g\\n\", j, grad_f[j]\n    );\n# endif\n# ifndef NDEBUG\n    for(j = 0; j < n_; j++) CPPAD_ASSERT_KNOWN(\n        (-infinity_ < grad_f[j]) && (grad_f[j] < infinity_),\n        \"cppad_ipopt_nlp::grad_f:: gradient of objective is not finite\"\n    );\n# endif\n    return true;\n}\n\n/*!\nEvaluate the function g(x).\n\n\\param[in] n\nis the dimension of the argument space for g(x); i.e., must be equal n_.\n\n\\param[in] x\nhas a vector of size n containing the point at which to evaluate\nthe constraint function g(x).\n\n\\param[in] new_x\nis false if the previous call to any one of the\n\\ref Deprecated_Evaluation_Methods used the same value for x.\n\n\\param[in] m\nis the dimension of the range space for g(x); i.e., must be equal to m_.\n\n\\param[out] g\nis a vector of size m.\nThe input value of its elements does not matter.\nThe output value of its elements is\nthe value of the function g(x) at this value of x.\n\n\\return\nThe return value is always true; see \\ref Deprecated_Evaluation_Methods.\n*/\nbool cppad_ipopt_nlp::eval_g(\n    Index n, const Number* x, bool new_x, Index m, Number* g\n)\n{   CPPAD_ASSERT_UNKNOWN(size_t(n) == n_ );\n\n    size_t i, j, k, ell;\n\n    // initialize summation\n    for(i = 0; i < m_; i++)\n        g[i] = 0.;\n\n    // update tape_ok_ flag\n    for(k = 0; k < K_; k++)\n    {   if( retape_[k] && (new_x || L_[k] > 1) )\n            tape_ok_[k] = false;\n    }\n\n    for(k = 0; k < K_; k++) for(ell = 0; ell < L_[k]; ell++)\n    {   fg_info_->index(k, ell, I_, J_);\n        if( ! tape_ok_[k] )\n        {   // Record r_k for value of u corresponding to x\n            fun_record(\n                fg_info_        ,   // inputs\n                k               ,\n                p_              ,\n                q_              ,\n                n_              ,\n                x               ,\n                J_              ,\n                r_fun_              // output\n            );\n        }\n        tape_ok_[k] = ! (retape_[k] || L_[k] > 1);\n        NumberVector u(q_[k]);\n        NumberVector r(p_[k]);\n        for(j = 0; j < q_[k]; j++)\n        {   CPPAD_ASSERT_UNKNOWN( J_[j] < n_ );\n            u[j]   = x[ J_[j] ];\n        }\n        r   = r_fun_[k].Forward(0, u);\n        for(i = 0; i < p_[k]; i++)\n        {   CPPAD_ASSERT_UNKNOWN( I_[i] <= m_ );\n            if( I_[i] >= 1 )\n                g[ I_[i] - 1 ] += r[i];\n        }\n    }\n# if CPPAD_IPOPT_NLP_TRACE\n    using std::printf;\n    for(j = 0; j < n_; j++)\n        printf(\"cppad_ipopt_nlp::eval_g::x[%d] = %20.14g\\n\", j, x[j]);\n    for(i = 0; i < m_; i++)\n        printf(\"cppad_ipopt_nlp::eval_g::g[%d] = %20.14g\\n\", i, g[i]);\n# endif\n# ifndef NDEBUG\n    for(i = 0; i < m_; i++) CPPAD_ASSERT_KNOWN(\n        (-infinity_ < g[i]) && (g[i] < infinity_),\n        \"cppad_ipopt_nlp::eval_g:: not all constraints are not finite\"\n    );\n# endif\n    return true;\n}\n\n/*!\nEvaluate the Jacobian of g(x).\n\n\\param[in] n\nis the dimension of the argument space for g(x); i.e., must be equal n_.\n\n\\param x\nif values is not NULL,\n x is a vector of size n containing the point at which to evaluate\nthe gradient of g(x).\n\n\\param[in] new_x\nis false if the previous call to any one of the\n\\ref Deprecated_Evaluation_Methods used the same value for x.\n\n\\param[in] m\nis the dimension of the range space for g(x); i.e., must be equal to m_.\n\n\\param[in] nele_jac\nis the number of possibly non-zero elements in the Jacobian of g(x);\ni.e., must be equal to nnz_jac_g_.\n\n\\param iRow\nif values is not NULL, iRow is not defined.\nif values is NULL, iRow\nis a vector with size nele_jac.\nThe input value of its elements does not matter.\nOn output,\nFor <tt>k = 0 , ... , nele_jac-1, iRow[k]</tt> is the\nbase zero row index for the\nk-th possibly non-zero entry in the Jacobian of g(x).\n\n\\param jCol\nif values is not NULL, jCol is not defined.\nif values is NULL, jCol\nis a vector with size nele_jac.\nThe input value of its elements does not matter.\nOn output,\nFor <tt>k = 0 , ... , nele_jac-1, jCol[k]</tt> is the\nbase zero column index for the\nk-th possibly non-zero entry in the Jacobian of g(x).\n\n\\param values\nif values is not NULL, values\nis a vector with size nele_jac.\nThe input value of its elements does not matter.\nOn output,\nFor <tt>k = 0 , ... , nele_jac-1, values[k]</tt> is the\nvalue for the\nk-th possibly non-zero entry in the Jacobian of g(x).\n\n\\return\nThe return value is always true; see \\ref Deprecated_Evaluation_Methods.\n*/\nbool cppad_ipopt_nlp::eval_jac_g(Index n, const Number* x, bool new_x,\n                              Index m, Index nele_jac, Index* iRow, Index *jCol,\n                              Number* values)\n{   CPPAD_ASSERT_UNKNOWN(size_t(m)          == m_ );\n    CPPAD_ASSERT_UNKNOWN(size_t(n)          == n_ );\n    CPPAD_ASSERT_UNKNOWN( size_t(nele_jac)  == nnz_jac_g_ );\n\n    size_t i, j, k, ell, l;\n    std::map<size_t,size_t>::iterator index_ij;\n\n\n    if (values == NULL)\n    {   for(k = 0; k < nnz_jac_g_; k++)\n        {   iRow[k] = static_cast<Index>( iRow_jac_g_[k] );\n            jCol[k] = static_cast<Index>( jCol_jac_g_[k] );\n        }\n        return true;\n    }\n\n    // initialize summation\n    l = nnz_jac_g_;\n    while(l--)\n        values[l] = 0.;\n\n    // update tape_ok_ flag\n    for(k = 0; k < K_; k++)\n    {   if( retape_[k] && (new_x || L_[k] > 1) )\n            tape_ok_[k] = false;\n    }\n\n    for(k = 0; k < K_; k++) for(ell = 0; ell < L_[k]; ell++)\n    {   fg_info_->index(k, ell, I_, J_);\n        if( ! tape_ok_[k] )\n        {   // Record r_k for value of u corresponding to x\n            fun_record(\n                fg_info_        ,   // inputs\n                k               ,\n                p_              ,\n                q_              ,\n                n_              ,\n                x               ,\n                J_              ,\n                r_fun_              // output\n            );\n        }\n        tape_ok_[k] = ! (retape_[k] || L_[k] > 1);\n        NumberVector u(q_[k]);\n        NumberVector jac_r(p_[k] * q_[k]);\n        for(j = 0; j < q_[k]; j++)\n        {   CPPAD_ASSERT_UNKNOWN( J_[j] < n_ );\n            u[j]   = x[ J_[j] ];\n        }\n        if( retape_[k] )\n            jac_r = r_fun_[k].Jacobian(u);\n        else\n            jac_r = r_fun_[k].SparseJacobian(u, pattern_jac_r_[k]);\n        for(i = 0; i < p_[k]; i++) if( I_[i] != 0 )\n        {   CPPAD_ASSERT_UNKNOWN( I_[i] <= m_ );\n            for(j = 0; j < q_[k]; j++)\n            {   index_ij = index_jac_g_[I_[i]-1].find(J_[j]);\n                if( index_ij != index_jac_g_[I_[i]-1].end() )\n                {   l          = index_ij->second;\n                    values[l] += jac_r[i * q_[k] + j];\n                }\n                else\n                    CPPAD_ASSERT_UNKNOWN(\n                    jac_r[i * q_[k] + j] == 0.\n                );\n            }\n        }\n    }\n# ifndef NDEBUG\n    for(l = 0; l < nnz_jac_g_; l++) CPPAD_ASSERT_KNOWN(\n        (-infinity_ < values[l]) && (values[l] < infinity_),\n        \"cppad_ipopt_nlp::eval_jac_g:: a component of \"\n        \"gradient of g is not finite\"\n    );\n# endif\n\n    return true;\n}\n\n/*!\nEvaluate the Hessian of the Lagragian\n\n\\section Deprecated_Hessian_of_the_Lagragian The Hessian of the Lagragian\nThe Hessian of the Lagragian is defined as\n\\f[\nH(x, \\sigma, \\lambda )\n=\n\\sigma \\nabla^2 f(x) + \\sum_{i=0}^{m-1} \\lambda_i \\nabla^2 g(x)_i\n\\f]\n\n\\param[in] n\nis the dimension of the argument space for g(x); i.e., must be equal n_.\n\n\\param x\nif values is not NULL, x\nis a vector of size n containing the point at which to evaluate\nthe Hessian of the Lagrangian.\n\n\\param[in] new_x\nis false if the previous call to any one of the\n\\ref Deprecated_Evaluation_Methods used the same value for x.\n\n\\param[in] obj_factor\nthe value \\f$ \\sigma \\f$ multiplying the Hessian of\nf(x) in the expression for \\ref Deprecated_Hessian_of_the_Lagragian.\n\n\\param[in] m\nis the dimension of the range space for g(x); i.e., must be equal to m_.\n\n\\param[in] lambda\nif values is not NULL, lambda\nis a vector of size m specifying the value of \\f$ \\lambda \\f$\nin the expression for \\ref Deprecated_Hessian_of_the_Lagragian.\n\n\\param[in] new_lambda\nis true if the previous call to eval_h had the same value for\n lambda and false otherwise.\n(Not currently used.)\n\n\\param[in] nele_hess\nis the number of possibly non-zero elements in the Hessian of the Lagragian;\ni.e., must be equal to nnz_h_lag_.\n\n\\param iRow\nif values is not NULL, iRow is not defined.\nif values is NULL, iRow\nis a vector with size nele_jac.\nThe input value of its elements does not matter.\nOn output,\nFor <tt>k = 0 , ... , nele_jac-1, iRow[k]</tt> is the\nbase zero row index for the\nk-th possibly non-zero entry in the Hessian of the Lagragian.\n\n\\param jCol\nif values is not NULL, jCol is not defined.\nif values is NULL, jCol\nis a vector with size nele_jac.\nThe input value of its elements does not matter.\nOn output,\nFor <tt>k = 0 , ... , nele_jac-1, jCol[k]</tt> is the\nbase zero column index for the\nk-th possibly non-zero entry in the Hessian of the Lagragian.\n\n\\param values\nif values is not NULL, it\nis a vector with size nele_jac.\nThe input value of its elements does not matter.\nOn output,\nFor <tt>k = 0 , ... , nele_jac-1, values[k]</tt> is the\nvalue for the\nk-th possibly non-zero entry in the Hessian of the Lagragian.\n\n\\return\nThe return value is always true; see \\ref Deprecated_Evaluation_Methods.\n*/\nbool cppad_ipopt_nlp::eval_h(Index n, const Number* x, bool new_x,\n                         Number obj_factor, Index m, const Number* lambda,\n                         bool new_lambda, Index nele_hess, Index* iRow,\n                         Index* jCol, Number* values)\n{   CPPAD_ASSERT_UNKNOWN(size_t(m) == m_ );\n    CPPAD_ASSERT_UNKNOWN(size_t(n) == n_ );\n\n    size_t i, j, k, ell, l;\n    std::map<size_t,size_t>::iterator index_ij;\n\n    if (values == NULL)\n    {   for(k = 0; k < nnz_h_lag_; k++)\n        {   iRow[k] = static_cast<Index>( iRow_h_lag_[k] );\n            jCol[k] = static_cast<Index>( jCol_h_lag_[k] );\n        }\n        return true;\n    }\n\n    // initialize summation\n    l = nnz_h_lag_;\n    while(l--)\n        values[l] = 0.;\n\n    // update tape_ok_ flag\n    for(k = 0; k < K_; k++)\n    {   if( retape_[k] && (new_x || L_[k] > 1) )\n            tape_ok_[k] = false;\n    }\n\n    for(k = 0; k < K_; k++) for(ell = 0; ell < L_[k]; ell++)\n    {   fg_info_->index(k, ell, I_, J_);\n        bool in_use = false;\n        for(i = 0; i < p_[k]; i++)\n        {   if( I_[i] == 0 )\n                in_use |= obj_factor > 0.;\n            else\n                in_use |= lambda[ I_[i] - 1 ] > 0;\n        }\n        if( in_use )\n        {\n            if( ! tape_ok_[k]  )\n            {   // Record r_k for value of u corresponding to x\n                fun_record(\n                    fg_info_        ,   // inputs\n                    k               ,\n                    p_              ,\n                    q_              ,\n                    n_              ,\n                    x               ,\n                    J_              ,\n                    r_fun_              // output\n                );\n                tape_ok_[k] = ! (retape_[k] || L_[k] > 1);\n            }\n            NumberVector w(p_[k]);\n            NumberVector r_hes(q_[k] * q_[k]);\n            NumberVector u(q_[k]);\n            for(j = 0; j < q_[k]; j++)\n            {   CPPAD_ASSERT_UNKNOWN( J_[j] < n_ );\n                u[j]   = x[ J_[j] ];\n            }\n            for(i = 0; i < p_[k]; i++)\n            {   CPPAD_ASSERT_UNKNOWN( I_[i] <= m_ );\n                if( I_[i] == 0 )\n                    w[i] = obj_factor;\n                else\n                    w[i] = lambda[ I_[i] - 1 ];\n            }\n            if( retape_[k] )\n                r_hes = r_fun_[k].Hessian(u, w);\n            else\n                r_hes = r_fun_[k].SparseHessian(\n                    u, w, pattern_hes_r_[k]\n            );\n            for(i = 0; i < q_[k]; i++) for(j = 0; j < q_[k]; j++)\n            if( J_[j] <= J_[i] )\n            {   index_ij = index_hes_fg_[J_[i]].find(J_[j]);\n                if( index_ij != index_hes_fg_[J_[i]].end() )\n                {   l          = index_ij->second;\n                    values[l] += r_hes[i * q_[k] + j];\n                }\n                else\n                    CPPAD_ASSERT_UNKNOWN(\n                    r_hes[i * q_[k] + j] == 0.\n                );\n            }\n        }\n    }\n# ifndef NDEBUG\n    for(l = 0; l < nnz_h_lag_; l++) CPPAD_ASSERT_KNOWN(\n        (-infinity_ < values[l]) && (values[l] < infinity_),\n        \"cppad_ipopt_nlp::eval_h:: a component of \"\n        \"Hessian of Lagragian is not finite\"\n    );\n# endif\n    return true;\n}\n\n/*!\nPass solution information from Ipopt to users solution structure.\n\n\\param[in] status\nis value that the Ipopt solution status\nwhich gets mapped to a corresponding value for\n\\n\n<tt>solution_->status</tt>.\n\n\\param[in] n\nis the dimension of the domain space for f(x) and g(x); i.e.,\nit must be equal to n_.\n\n\\param[in] x\nis a vector with size n specifying the final solution.\n\\n\n<tt>solution_->x</tt> is set to be a vector with size n\nand to have the same element values.\n\n\\param[in] z_L\nis a vector with size n specifying the Lagragian multipliers for the\nconstraint \\f$ x^l \\leq x \\f$.\n\\n\n<tt>solution_->z_l</tt> is set to be a vector with size n\nand to have the same element values.\n\n\\param[in] z_U\nis a vector with size n specifying the Lagragian multipliers for the\nconstraint \\f$ x \\leq x^u \\f$.\n\\n\n<tt>solution_->z_u</tt> is set to be a vector with size n\nand to have the same element values.\n\n\\param[in] m\nis the dimension of the range space for g(x). i.e.,\nit must be equal to m_.\n\n\\param[in] g\nis a vector with size m containing the value of the constraint function\ng(x) at the final solution for x.\n\\n\n<tt>solution_->g</tt> is set to be a vector with size m\nand to have the same element values.\n\n\\param[in] lambda\nis a vector with size m specifying the Lagragian multipliers for the\nconstraints \\f$ g^l \\leq g(x) \\leq g^u \\f$.\n\\n\n<tt>solution_->lambda</tt> is set to be a vector with size m\nand to have the same element values.\n\n\\param[in] obj_value\nis the value of the objective function f(x) at the final solution for x.\n\\n\n<tt>solution_->obj_value</tt> is set to have the same value.\n\n\\param[in] ip_data\nis unspecified (by Ipopt) and hence not used.\n\n\\param[in] ip_cq\nis unspecified (by Ipopt) and hence not used.\n\n\\par solution_[out]\nthe pointer solution_ , which is equal to the pointer solution\nin the constructor for cppad_ipopt_nlp,\nis used to set output values (see documentation above).\n*/\nvoid cppad_ipopt_nlp::finalize_solution(\n    Ipopt::SolverReturn               status    ,\n    Index                             n         ,\n    const Number*                     x         ,\n    const Number*                     z_L       ,\n    const Number*                     z_U       ,\n    Index                             m         ,\n    const Number*                     g         ,\n    const Number*                     lambda    ,\n    Number                            obj_value ,\n    const Ipopt::IpoptData*           ip_data   ,\n    Ipopt::IpoptCalculatedQuantities* ip_cq\n)\n{   size_t i, j;\n\n    CPPAD_ASSERT_UNKNOWN(size_t(n) == n_ );\n    CPPAD_ASSERT_UNKNOWN(size_t(m) == m_ );\n\n    switch(status)\n    {   // convert status from Ipopt enum to cppad_ipopt_solution enum\n        case Ipopt::SUCCESS:\n        solution_->status =\n            cppad_ipopt_solution::success;\n        break;\n\n        case Ipopt::MAXITER_EXCEEDED:\n        solution_->status =\n            cppad_ipopt_solution::maxiter_exceeded;\n        break;\n\n        case Ipopt::STOP_AT_TINY_STEP:\n        solution_->status =\n            cppad_ipopt_solution::stop_at_tiny_step;\n        break;\n\n        case Ipopt::STOP_AT_ACCEPTABLE_POINT:\n        solution_->status =\n            cppad_ipopt_solution::stop_at_acceptable_point;\n        break;\n\n        case Ipopt::LOCAL_INFEASIBILITY:\n        solution_->status =\n            cppad_ipopt_solution::local_infeasibility;\n        break;\n\n        case Ipopt::USER_REQUESTED_STOP:\n        solution_->status =\n            cppad_ipopt_solution::user_requested_stop;\n        break;\n\n        case Ipopt::DIVERGING_ITERATES:\n        solution_->status =\n            cppad_ipopt_solution::diverging_iterates;\n        break;\n\n        case Ipopt::RESTORATION_FAILURE:\n        solution_->status =\n            cppad_ipopt_solution::restoration_failure;\n        break;\n\n        case Ipopt::ERROR_IN_STEP_COMPUTATION:\n        solution_->status =\n            cppad_ipopt_solution::error_in_step_computation;\n        break;\n\n        case Ipopt::INVALID_NUMBER_DETECTED:\n        solution_->status =\n            cppad_ipopt_solution::invalid_number_detected;\n        break;\n\n        case Ipopt::INTERNAL_ERROR:\n        solution_->status =\n            cppad_ipopt_solution::internal_error;\n        break;\n\n        default:\n        solution_->status =\n            cppad_ipopt_solution::unknown;\n    }\n\n    solution_->x.resize(n_);\n    solution_->z_l.resize(n_);\n    solution_->z_u.resize(n_);\n    for(j = 0; j < n_; j++)\n    {   solution_->x[j]    = x[j];\n        solution_->z_l[j]  = z_L[j];\n        solution_->z_u[j]  = z_U[j];\n    }\n    solution_->g.resize(m_);\n    solution_->lambda.resize(m_);\n    for(i = 0; i < m_; i++)\n    {   solution_->g[i]      = g[i];\n        solution_->lambda[i] = lambda[i];\n    }\n    solution_->obj_value = obj_value;\n    return;\n}\n\n// This routine is defined, but not yet used\n// (trying to figure out a problem with Ipopt-3.9.1 and dismod4).\nbool cppad_ipopt_nlp::intermediate_callback(\n    Ipopt::AlgorithmMode              mode,\n    Index                             iter,\n    Number                            obj_value,\n    Number                            inf_pr,\n    Number                            inf_du,\n    Number                            mu,\n    Number                            d_norm,\n    Number                            regularization_size,\n    Number                            alpha_du,\n    Number                            alpha_pr,\n    Index                             ls_trials,\n    const Ipopt::IpoptData*           ip_data,\n    Ipopt::IpoptCalculatedQuantities* ip_cq\n)\n{\n    // std::cout << \"intermediate_callback called\" << std::endl;\n    return true;\n}\n\n// ---------------------------------------------------------------------------\n} // end namespace cppad_ipopt\n// ---------------------------------------------------------------------------\n"
  },
  {
    "path": "cppad_ipopt/src/cppad_ipopt_nlp.hpp",
    "content": "# ifndef CPPAD_CPPAD_IPOPT_SRC_CPPAD_IPOPT_NLP_HPP\n# define CPPAD_CPPAD_IPOPT_SRC_CPPAD_IPOPT_NLP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin cppad_ipopt_nlp app}\n{xrst_spell\n    doesn\n    fg\n    libs\n    lipopt\n    maxiter\n    naninf\n    retape\n    rll\n}\nNonlinear Programming Using the CppAD Interface to Ipopt\n########################################################\n\nDeprecated 2012-11-28\n*********************\nThis interface to Ipopt is deprecated, use :ref:`ipopt_solve-name` instead.\n\nSyntax\n******\n| # ``include`` ``\"cppad_ipopt_nlp.hpp\"``\n| ``cppad_ipopt_solution`` *solution* ;\n| ``cppad_ipopt_nlp`` *cppad_nlp* (\n| |tab| *n* , *m* , *x_i* , *x_l* , *x_u* , *g_l* , *g_u* , & *fg_info* , & *solution*\n| )\n| ``export LD_LIBRARY_PATH`` = ``$LD_LIBRARY_PATH:`` *ipopt_library_paths*\n\nPurpose\n*******\nThe class ``cppad_ipopt_nlp`` is used to solve nonlinear programming\nproblems of the form\n\n.. math::\n\n    \\begin{array}{rll}\n    {\\rm minimize}      & f(x)\n    \\\\\n    {\\rm subject \\; to} & g^l \\leq g(x) \\leq g^u\n    \\\\\n                        & x^l  \\leq x   \\leq x^u\n    \\end{array}\n\nThis is done using\n`Ipopt <https://coin-or.github.io/Ipopt>`_\noptimizer and\n`CppAD <https://www.coin-or.org/CppAD/>`_\nAlgorithmic Differentiation package.\n\ncppad_ipopt namespace\n*********************\nAll of the declarations for these routines\nare in the ``cppad_ipopt`` namespace\n(not the ``CppAD`` namespace).\nFor example; :ref:`cppad_ipopt_nlp@SizeVector` below\nactually denotes the type ``cppad_ipopt::SizeVector`` .\n\nipopt_library_paths\n*******************\nIf you are linking to a shared version of the Ipopt library,\nyou may have to add a path to the ``LD_LIBRARY_PATH`` .\nYou can determine the directory you need to add using the command\n\n    ``pkg-config ipopt --libs``\n\nThe output will have the following form\n\n    ``-L`` *dir* ``-lipopt``\n\nYou may need to add the directory %dir% to ``LD_LIBRARY_PATH%`` ; e.g.,\n\n    ``export LD_LIBRARY_PATH`` =\" *dir* : ``$LD_LIBRARY_PATH`` \"\n\nfg(x)\n*****\nThe function :math:`fg : \\B{R}^n \\rightarrow \\B{R}^{m+1}` is defined by\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        fg_0 (x)     & = & f(x)         \\\\\n        fg_1 (x)     & = & g_0 (x)      \\\\\n                          & \\vdots &         \\\\\n        fg_m (x)     & = & g_{m-1} (x)\n        \\end{eqnarray}\n\nIndex Vector\n============\nWe define an *index vector* as a vector of non-negative integers\nfor which none of the values are equal; i.e.,\nit is both a vector and a set.\nIf :math:`I` is an index vector :math:`|I|` is used to denote the\nnumber of elements in :math:`I` and :math:`\\| I \\|` is used\nto denote the value of the maximum element in :math:`I`.\n\nProjection\n==========\nGiven an index vector :math:`J` and a positive integer :math:`n`\nwhere :math:`n > \\| J \\|`, we use :math:`J \\otimes n` for\nthe mapping :math:`( J \\otimes n ) : \\B{R}^n \\rightarrow \\B{R}^{|J|}` defined by\n\n.. math::\n\n    [ J \\otimes n ] (x)_j = x_{J(j)}\n\nfor :math:`j = 0 , \\ldots |J| - 1`.\n\nInjection\n=========\nGiven an index vector :math:`I` and a positive integer :math:`m`\nwhere :math:`m > \\| I \\|`, we use :math:`m \\otimes I` for\nthe mapping :math:`( m \\otimes I ): \\B{R}^{|I|} \\rightarrow \\B{R}^m` defined by\n\n.. math::\n\n    [ m \\otimes I ] (y)_i = \\left\\{ \\begin{array}{ll}\n    y_k & {\\rm if} \\; i = I(k) \\; {\\rm for \\; some} \\;\n        k \\in \\{ 0 , \\cdots, |I|-1 \\}\n    \\\\\n    0   & {\\rm otherwise}\n    \\end{array} \\right.\n\nRepresentation\n==============\nIn many applications, each of the component functions of :math:`fg(x)`\nonly depend on a few of the components of :math:`x`.\nIn this case, expressing :math:`fg(x)` in terms of simpler functions\nwith fewer arguments can greatly reduce the amount of work required\nto compute its derivatives.\n\nWe use the functions\n:math:`r_k : \\B{R}^{q(k)} \\rightarrow \\B{R}^{p(k)}`\nfor :math:`k = 0 , \\ldots , K` to express our\nrepresentation of :math:`fg(x)` in terms of simpler functions\nas follows\n\n.. math::\n\n    fg(x) = \\sum_{k=0}^{K-1} \\; \\sum_{\\ell=0}^{L(k) - 1}\n    [ (m+1) \\otimes I_{k,\\ell} ] \\; \\circ\n          \\; r_k \\; \\circ \\; [ J_{k,\\ell} \\otimes n ] \\; (x)\n\nwhere :math:`\\circ` represents function composition,\nfor :math:`k = 0 , \\ldots , K - 1`, and :math:`\\ell = 0 , \\ldots , L(k)`,\n:math:`I_{k,\\ell}` and  :math:`J_{k,\\ell}` are index vectors with\n:math:`| J_{k,\\ell} | = q(k)`,\n:math:`\\| J_{k,\\ell} \\| < n`,\n:math:`| I_{k,\\ell} | = p(k)`, and\n:math:`\\| I_{k,\\ell} \\| \\leq m`.\n\nSimple Representation\n*********************\nIn the simple representation,\n:math:`r_0 (x) = fg(x)`,\n:math:`K = 1`,\n:math:`q(0) = n`,\n:math:`p(0) = m+1`,\n:math:`L(0) = 1`,\n:math:`I_{0,0} = (0 , \\ldots , m)`,\nand :math:`J_{0,0} = (0 , \\ldots , n-1)`.\n\nSizeVector\n**********\nThe type ``SizeVector`` is defined by the\n``cppad_ipopt_nlp.hpp`` include file to be a\n:ref:`SimpleVector-name` class with elements of type\n``size_t`` .\n\nNumberVector\n************\nThe type ``NumberVector`` is defined by the\n``cppad_ipopt_nlp.hpp`` include file to be a\n:ref:`SimpleVector-name` class with elements of type\n``Ipopt::Number`` .\n\nADNumber\n********\nThe type ``ADNumber`` is defined by the\n``cppad_ipopt_nlp.hpp`` include file to be a\nan AD type that can be used to compute derivatives.\n\nADVector\n********\nThe type ``ADVector`` is defined by the\n``cppad_ipopt_nlp.hpp`` include file to be a\n:ref:`SimpleVector-name` class with elements of type\n``ADNumber`` .\n\nn\n*\nThe argument *n* has prototype\n\n    ``size_t`` *n*\n\nIt specifies the dimension of the argument space;\ni.e., :math:`x \\in \\B{R}^n`.\n\nm\n*\nThe argument *m* has prototype\n\n    ``size_t`` *m*\n\nIt specifies the dimension of the range space for :math:`g`;\ni.e., :math:`g : \\B{R}^n \\rightarrow \\B{R}^m`.\n\nx_i\n***\nThe argument *x_i* has prototype\n\n    ``const NumberVector&`` *x_i*\n\nand its size is equal to :math:`n`.\nIt specifies the initial point where Ipopt starts the optimization process.\n\nx_l\n***\nThe argument *x_l* has prototype\n\n    ``const NumberVector&`` *x_l*\n\nand its size is equal to :math:`n`.\nIt specifies the lower limits for the argument in the optimization problem;\ni.e., :math:`x^l`.\n\nx_u\n***\nThe argument *x_u* has prototype\n\n    ``const NumberVector&`` *x_u*\n\nand its size is equal to :math:`n`.\nIt specifies the upper limits for the argument in the optimization problem;\ni.e., :math:`x^u`.\n\ng_l\n***\nThe argument *g_l* has prototype\n\n    ``const NumberVector&`` *g_l*\n\nand its size is equal to :math:`m`.\nIt specifies the lower limits for the constraints in the optimization problem;\ni.e., :math:`g^l`.\n\ng_u\n***\nThe argument *g_u* has prototype\n\n    ``const NumberVector&`` *g_u*\n\nand its size is equal to :math:`n`.\nIt specifies the upper limits for the constraints in the optimization problem;\ni.e., :math:`g^u`.\n\nfg_info\n*******\nThe argument *fg_info* has prototype\n\n    *FG_info fg_info*\n\nwhere the class *FG_info* is derived from the\nbase class ``cppad_ipopt_fg_info`` .\nCertain virtual member functions of *fg_info* are used to\ncompute the value of :math:`fg(x)`.\nThe specifications for these member functions are given below:\n\nfg_info.number_functions\n========================\nThis member function has prototype\n\n    ``virtual size_t cppad_ipopt_fg_info::number_functions`` ( ``void`` )\n\nIf *K* has type ``size_t`` , the syntax\n\n    *K* = *fg_info* . ``number_functions`` ()\n\nsets *K* to the number of functions used in the\nrepresentation of :math:`fg(x)`; i.e., :math:`K` in\nthe :ref:`cppad_ipopt_nlp@fg(x)@Representation` above.\n\nThe ``cppad_ipopt_fg_info`` implementation of this function\ncorresponds to the simple representation mentioned above; i.e.\n*K*  = 1 .\n\nfg_info.eval_r\n==============\nThis member function has the prototype\n\n    ``virtual ADVector cppad_ipopt_fg_info::eval_r`` ( ``size_t`` *k* , ``const ADVector&`` *u* ) = 0;\n\nThus it is a pure virtual function and must be defined in the\nderived class *FG_info* .\n\nThis function computes the value of :math:`r_k (u)`\nused in the :ref:`cppad_ipopt_nlp@fg(x)@Representation`\nfor :math:`fg(x)`.\nIf *k* in :math:`\\{0 , \\ldots , K-1 \\}` has type ``size_t`` ,\n*u* is an ``ADVector`` of size *q* ( *k* )\nand *r* is an ``ADVector`` of size *p* ( *k* )\nthe syntax\n\n    *r* = *fg_info* . ``eval_r`` ( *k* , *u* )\n\nset *r* to the vector :math:`r_k (u)`.\n\nfg_info.retape\n==============\nThis member function has the prototype\n\n    ``virtual bool cppad_ipopt_fg_info::retape`` ( ``size_t`` *k* )\n\nIf *k* in :math:`\\{0 , \\ldots , K-1 \\}` has type ``size_t`` ,\nand *retape* has type ``bool`` ,\nthe syntax\n\n    *retape* = *fg_info* . ``retape`` ( *k* )\n\nsets *retape* to true or false.\nIf *retape* is true,\n``cppad_ipopt_nlp`` will retape the operation sequence\ncorresponding to :math:`r_k (u)` for\nevery value of *u* .\nAn ``cppad_ipopt_nlp`` object\nshould use much less memory and run faster if *retape* is false.\nYou can test both the true and false cases to make sure\nthe operation sequence does not depend on *u* .\n\nThe ``cppad_ipopt_fg_info`` implementation of this function\nsets *retape* to true\n(while slower it is also safer to always retape).\n\nfg_info.domain_size\n===================\nThis member function has prototype\n\n    ``virtual size_t cppad_ipopt_fg_info::domain_size`` ( ``size_t`` *k* )\n\nIf *k* in :math:`\\{0 , \\ldots , K-1 \\}` has type ``size_t`` ,\nand *q* has type ``size_t`` , the syntax\n\n    *q* = *fg_info* . ``domain_size`` ( *k* )\n\nsets *q* to the dimension of the domain space for :math:`r_k (u)`;\ni.e., :math:`q(k)` in\nthe :ref:`cppad_ipopt_nlp@fg(x)@Representation` above.\n\nThe ``cppad_ipopt_h_base`` implementation of this function\ncorresponds to the simple representation mentioned above; i.e.,\n:math:`q = n`.\n\nfg_info.range_size\n==================\nThis member function has prototype\n\n    ``virtual size_t cppad_ipopt_fg_info::range_size`` ( ``size_t`` *k* )\n\nIf *k* in :math:`\\{0 , \\ldots , K-1 \\}` has type ``size_t`` ,\nand *p* has type ``size_t`` , the syntax\n\n    *p* = *fg_info* . ``range_size`` ( *k* )\n\nsets *p* to the dimension of the range space for :math:`r_k (u)`;\ni.e., :math:`p(k)` in\nthe :ref:`cppad_ipopt_nlp@fg(x)@Representation` above.\n\nThe ``cppad_ipopt_h_base`` implementation of this function\ncorresponds to the simple representation mentioned above; i.e.,\n:math:`p = m+1`.\n\nfg_info.number_terms\n====================\nThis member function has prototype\n\n    ``virtual size_t cppad_ipopt_fg_info::number_terms`` ( ``size_t`` *k* )\n\nIf *k* in :math:`\\{0 , \\ldots , K-1 \\}` has type ``size_t`` ,\nand *L* has type ``size_t`` , the syntax\n\n    *L* = *fg_info* . ``number_terms`` ( *k* )\n\nsets *L* to the number of terms in representation\nfor this value of *k* ;\ni.e., :math:`L(k)` in\nthe :ref:`cppad_ipopt_nlp@fg(x)@Representation` above.\n\nThe ``cppad_ipopt_h_base`` implementation of this function\ncorresponds to the simple representation mentioned above; i.e.,\n:math:`L = 1`.\n\nfg_info.index\n=============\nThis member function has prototype\n\n| |tab| ``virtual void cppad_ipopt_fg_info::index`` (\n| |tab| |tab| ``size_t`` *k* , ``size_t`` *ell* , ``SizeVector&`` *I* , ``SizeVector&`` *J*\n| |tab| )\n\nThe argument\n\n    *k*\n\nhas type ``size_t``\nand is a value between zero and :math:`K-1` inclusive.\nThe argument\n\n    *ell*\n\nhas type ``size_t``\nand is a value between zero and :math:`L(k)-1` inclusive.\nThe argument\n\n    *I*\n\nis a :ref:`SimpleVector-name` with elements\nof type ``size_t`` and size greater than or equal to :math:`p(k)`.\nThe input value of the elements of *I* does not matter.\nThe output value of\nthe first :math:`p(k)` elements of *I*\nmust be the corresponding elements of :math:`I_{k,ell}`\nin the :ref:`cppad_ipopt_nlp@fg(x)@Representation` above.\nThe argument\n\n    *J*\n\nis a :ref:`SimpleVector-name` with elements\nof type ``size_t`` and size greater than or equal to :math:`q(k)`.\nThe input value of the elements of *J* does not matter.\nThe output value of\nthe first :math:`q(k)` elements of *J*\nmust be the corresponding elements of :math:`J_{k,ell}`\nin the :ref:`cppad_ipopt_nlp@fg(x)@Representation` above.\n\nThe ``cppad_ipopt_h_base`` implementation of this function\ncorresponds to the simple representation mentioned above; i.e.,\nfor :math:`i = 0 , \\ldots , m`,\n*I* [ *i* ] = *i* ,\nand  for :math:`j = 0 , \\ldots , n-1`,\n*J* [ *j* ] = *j* .\n\nsolution\n********\nAfter the optimization process is completed, *solution* contains\nthe following information:\n\nstatus\n======\nThe *status* field of *solution* has prototype\n\n    ``cppad_ipopt_solution::solution_status`` *solution* . ``status``\n\nIt is the final Ipopt status for the optimizer.\nHere is a list of the possible values for the status:\n\n.. list-table::\n    :widths: auto\n\n    * - *status*\n      - Meaning\n    * - not_defined\n      - The optimizer did not return a final status to this ``cppad_ipopt_nlp``\n         object.\n    * - unknown\n      - The status returned by the optimizer is not defined in the Ipopt\n         documentation for ``finalize_solution`` .\n    * - success\n      - Algorithm terminated successfully at a point satisfying the convergence\n         tolerances (see Ipopt options).\n    * - maxiter_exceeded\n      - The maximum number of iterations was exceeded (see Ipopt options).\n    * - stop_at_tiny_step\n      - Algorithm terminated because progress was very slow.\n    * - stop_at_acceptable_point\n      - Algorithm stopped at a point that was converged,\n         not to the 'desired' tolerances, but to 'acceptable' tolerances\n         (see Ipopt options).\n    * - local_infeasibility\n      - Algorithm converged to a non-feasible point\n         (problem may have no solution).\n    * - user_requested_stop\n      - This return value should not happen.\n    * - diverging_iterates\n      - It the iterates are diverging.\n    * - restoration_failure\n      - Restoration phase failed, algorithm doesn't know how to proceed.\n    * - error_in_step_computation\n      - An unrecoverable error occurred while Ipopt tried to\n         compute the search direction.\n    * - invalid_number_detected\n      - Algorithm received an invalid number (such as ``nan`` or ``inf`` )\n         from the users function *fg_info* . ``eval`` or from the CppAD evaluations\n         of its derivatives\n         (see the Ipopt option ``check_derivatives_for_naninf`` ).\n    * - internal_error\n      - An unknown Ipopt internal error occurred.\n         Contact the Ipopt authors through the mailing list.\n\nx\n=\nThe ``x`` field of *solution* has prototype\n\n    ``NumberVector`` *solution* . ``x``\n\nand its size is equal to :math:`n`.\nIt is the final :math:`x` value for the optimizer.\n\nz_l\n===\nThe ``z_l`` field of *solution* has prototype\n\n    ``NumberVector`` *solution* . ``z_l``\n\nand its size is equal to :math:`n`.\nIt is the final Lagrange multipliers for the\nlower bounds on :math:`x`.\n\nz_u\n===\nThe ``z_u`` field of *solution* has prototype\n\n    ``NumberVector`` *solution* . ``z_u``\n\nand its size is equal to :math:`n`.\nIt is the final Lagrange multipliers for the\nupper bounds on :math:`x`.\n\ng\n=\nThe ``g`` field of *solution* has prototype\n\n    ``NumberVector`` *solution* . ``g``\n\nand its size is equal to :math:`m`.\nIt is the final value for the constraint function :math:`g(x)`.\n\nlambda\n======\nThe ``lambda`` field of *solution* has prototype\n\n    ``NumberVector`` *solution* . ``lambda``\n\nand its size is equal to :math:`m`.\nIt is the final value for the\nLagrange multipliers corresponding to the constraint function.\n\nobj_value\n=========\nThe ``obj_value`` field of *solution* has prototype\n\n    ``Number`` *solution* . ``obj_value``\n\nIt is the final value of the objective function :math:`f(x)`.\n\n{xrst_end cppad_ipopt_nlp}\n-----------------------------------------------------------------------------\n*/\n# include <cppad/cppad.hpp>\n# include <coin-or/IpIpoptApplication.hpp>\n# include <coin-or/IpTNLP.hpp>\n\n/*!\n\\file cppad_ipopt_nlp.hpp\n\\brief CppAD interface to Ipopt\n\n\\ingroup cppad_ipopt_nlp_cpp\n*/\n\n// ---------------------------------------------------------------------------\nnamespace cppad_ipopt {\n// ---------------------------------------------------------------------------\n\n/// A scalar value used to record operation sequence.\ntypedef CppAD::AD<Ipopt::Number>       ADNumber;\n/// A simple vector of values used to record operation sequence\ntypedef CppAD::vector<ADNumber>        ADVector;\n/// A simple vector of size_t values.\ntypedef CppAD::vector<size_t>          SizeVector;\n/// A simple vector of values used by Ipopt\ntypedef CppAD::vector<Ipopt::Number>   NumberVector;\n\n/*!\nAbstract base class user derives from to define the functions in the problem.\n*/\nclass cppad_ipopt_fg_info\n{\n    /// allow cppad_ipopt_nlp class complete access to this class\n    friend class cppad_ipopt_nlp;\nprivate:\n    /// domain space dimension for the functions f(x), g(x)\n    size_t n_;\n    /// range space dimension for the function g(x)\n    size_t m_;\n    /// the cppad_ipopt_nlp constructor uses this method to set n_\n    void set_n(size_t n)\n    {   n_ = n; }\n    /// the cppad_ipopt_nlp constructor uses this method to set m_\n    void set_m(size_t m)\n    {   m_ = m; }\n\npublic:\n    /// destructor virtual so user derived class destructor gets called\n    virtual ~cppad_ipopt_fg_info(void)\n    { }\n    /// number_functions; i.e. K (simple representation uses 1)\n    virtual size_t number_functions(void)\n    {   return 1; }\n    /// function that evaluates the users representation for f(x) and\n    /// and g(x) is pure virtual so user must define it in derived class\n    virtual ADVector eval_r(size_t k, const ADVector& u) = 0;\n    /// should the function r_k (u) be retaped when ever the argument\n    /// u changes (default is true which is safe but slow)\n    virtual bool retape(size_t k)\n    {   return true; }\n    /// domain_size q[k] for r_k (u) (simple representation uses n)\n    virtual size_t domain_size(size_t k)\n    {   return n_; }\n    /// range_size p[k] for r_k (u) (simple representation uses m+1)\n    virtual size_t range_size(size_t k)\n    {   return m_ + 1; }\n    /// number_terms that use r_k (u) (simple representation uses 1)\n    virtual size_t number_terms(size_t k)\n    {   return 1; }\n    /// return the index vectors I_{k,ell} and J_{k,ell}\n    /// (simple representation uses I[i] = i and J[j] = j)\n    virtual void index(size_t k, size_t ell, SizeVector& I, SizeVector& J)\n    {   assert( I.size() >= m_ + 1 );\n        assert( J.size() >= n_ );\n        for(size_t i = 0; i <= m_; i++)\n            I[i] = i;\n        for(size_t j = 0; j < n_; j++)\n            J[j] = j;\n    }\n};\n\n/*!\nClass that contains information about the problem solution\n\n\\section Nonlinear_Programming_Problem Nonlinear Programming Problem\nWe are give smooth functions\n\\f$ f : {\\bf R}^n \\rightarrow {\\bf R} \\f$\nand\n\\f$ g : {\\bf R}^n \\rightarrow {\\bf R}^m \\f$\nand wish to solve the problem\n\\f[\n\\begin{array}{rcl}\n{\\rm minimize} & f(x) & {\\rm w.r.t.} \\; x \\in {\\bf R}^n\n\\\\\n{\\rm subject \\; to} & g^l \\leq g(x) \\leq g^u\n\\\\\n& x^l \\leq x \\leq x^u\n\\end{array}\n\\f]\n\n\n\\section Users_Representation Users Representation\nThe functions\n\\f$ f : {\\bf R}^n \\rightarrow {\\bf R} \\f$ and\n\\f$ g : {\\bf R}^n \\rightarrow {\\bf R}^m \\f$ are defined by\n\\f[\n\\left( \\begin{array}{c} f(x) \\\\ g(x) \\end{array} \\right)\n=\n\\sum_{k=0}^{K-1} \\; \\sum_{\\ell=0}^{L(k) - 1}\n[ (m+1) \\otimes I_{k,\\ell} ] \\; \\circ\n      \\; r_k \\; \\circ \\; [ J_{k,\\ell} \\otimes n ] \\; (x)\n\\f]\nwhere for \\f$ k = 0 , \\ldots , K-1\\f$,\n\\f$ r_k : {\\bf R}^{q(k)} \\rightarrow {\\bf R}^{p(k)} \\f$.\n\n\\section Deprecated_Evaluation_Methods Evaluation Methods\nThe set of evaluation methods for this class is\n\\verbatim\n    { eval_f, eval_grad_f, eval_g, eval_jac_g, eval_h }\n\\endverbatim\nNote that the bool return flag for the evaluations methods\ndoes not appear in the Ipopt documentation.\nLooking at the code, it seems to be a flag telling Ipopt to abort\nwhen the flag is false.\n\n*/\nclass cppad_ipopt_solution\n{\npublic:\n    /// possible values for he solution status\n    enum solution_status {\n        not_defined,\n        success,\n        maxiter_exceeded,\n        stop_at_tiny_step,\n        stop_at_acceptable_point,\n        local_infeasibility,\n        user_requested_stop,\n        feasible_point_found,\n        diverging_iterates,\n        restoration_failure,\n        error_in_step_computation,\n        invalid_number_detected,\n        too_few_degrees_of_freedom,\n        internal_error,\n        unknown\n    }  status;\n    /// the approximation solution\n    NumberVector      x;\n    /// Lagrange multipliers corresponding to lower bounds on x\n    NumberVector      z_l;\n    /// Lagrange multipliers corresponding to upper bounds on x\n    NumberVector      z_u;\n    /// value of g(x)\n    NumberVector      g;\n    /// Lagrange multipliers correspondiing constraints on g(x)\n    NumberVector      lambda;\n    /// value of f(x)\n    Ipopt::Number     obj_value;\n    /// constructor initializes solution status as not yet defined\n    cppad_ipopt_solution(void)\n    {   status = not_defined; }\n};\n\n/*!\nClass connects Ipopt to CppAD for derivative and sparsity pattern calculations.\n*/\nclass cppad_ipopt_nlp : public Ipopt::TNLP\n{\nprivate:\n    /// A Scalar value used by Ipopt\n    typedef Ipopt::Number                         Number;\n    /// An index value used by Ipopt\n    typedef Ipopt::Index                          Index;\n    /// Indexing style used in Ipopt sparsity structure\n    typedef Ipopt::TNLP::IndexStyleEnum           IndexStyleEnum;\n    /// A simple vector of boolean values\n    typedef CppAD::vectorBool                     BoolVector;\n    /// A simple vector of AD function objects\n    typedef CppAD::vector< CppAD::ADFun<Number> > ADFunVector;\n    /// A simple vector of simple vectors of boolean values\n    typedef CppAD::vector<BoolVector>             BoolVectorVector;\n    /// A mapping that is dense in i, sparse in j, and maps (i, j)\n    /// to the corresponding sparsity index in Ipopt.\n    typedef CppAD::vector< std::map<size_t,size_t> > IndexMap;\n\n    // ------------------------------------------------------------------\n    // Values directly passed in to constructor\n    // ------------------------------------------------------------------\n    /// dimension of the domain space for f(x) and g(x)\n    /// (passed to ctor)\n    const size_t                    n_;\n    /// dimension of the range space for g(x)\n    /// (passed to ctor)\n    const size_t                    m_;\n    /// dimension of the range space for g(x)\n    /// (passed to ctor)\n    const NumberVector              x_i_;\n    /// lower limit for x\n    /// (size n_), (passed to ctor)\n    const NumberVector              x_l_;\n    /// upper limit for x\n    /// (size n_) (passed to ctor)\n    const NumberVector              x_u_;\n    /// lower limit for g(x)\n    /// (size m_) (passed to ctor)\n    const NumberVector              g_l_;\n    /// upper limit for g(x)\n    /// (size m_) (passed to ctor)\n    const NumberVector              g_u_;\n    /// pointer to base class version of derived class object used to get\n    /// information about the user's representation for f(x) and g(x)\n    /// (passed to ctor)\n    cppad_ipopt_fg_info* const      fg_info_;\n    /// pointer to object where final results are stored\n    /// (passed to ctor)\n    cppad_ipopt_solution* const     solution_;\n    /// plus infinity as a value of type Number\n    const Number                    infinity_;\n\n    // ------------------------------------------------------------------\n    // Effectively const values determined during constructor using calls\n    // to fg_info:\n    // ------------------------------------------------------------------\n    /// The value of \\f$ K \\f$ in the representation.\n    /// (effectively const)\n    size_t                 K_;\n    /// Does operation sequence for \\f$ r_k (u) \\f$ depend on \\f$ u \\f$.\n    /// (size K_) (effectively const)\n    BoolVector             retape_;\n    /// <tt>q_[k]</tt> is the domain space dimension for \\f$ r_k (u) \\f$\n    /// (size K_) (effectively const)\n    SizeVector             q_;\n    /// <tt>p_[k]</tt> is the range space dimension for \\f$ r_k (u) \\f$\n    /// (size K_) (effectively const)\n    SizeVector             p_;\n    /// <tt>L_[k]</tt> is number of times \\f$ r_k (u) \\f$ appears in\n    /// the representation summation\n    /// (size K_) (effectively const)\n    SizeVector             L_;\n    // -------------------------------------------------------------------\n    // Other effectively const values determined by the constructor:\n    // -------------------------------------------------------------------\n    /*!\n    CppAD sparsity patterns for \\f$ \\{ r_k^{(1)} (u) \\} \\f$ (set by ctor).\n\n    For <tt>k = 0 , ... , K_-1, pattern_jac_r_[k]</tt>\n    is a CppAD sparsity pattern for the Jacobian of \\f$ r_k (u) \\f$\n    and as such it has size <tt>p_[k]*q_[k]</tt>.\n    (effectively const)\n    */\n    BoolVectorVector                 pattern_jac_r_;\n\n    /*!\n    CppAD sparsity patterns for \\f$ \\{ r_k^{(2)} (u) \\} \\f$ (set by ctor).\n\n    For <tt>k = 0 , ... , K_-1, pattern_jac_r_[k]</tt>\n    is a CppAD sparsity pattern for the Hessian of\n    \\f[\n        R(u) = \\sum_{i=0}^{p[k]-1}  r_k (u)_i\n    \\f]\n    and as such it has size <tt>q_[k]*q_[k]</tt>.\n    (effectively const)\n    */\n    BoolVectorVector                 pattern_hes_r_;\n\n    /// number non-zero is Ipopt sparsity structor for Jacobian of g(x)\n    /// (effectively const)\n    size_t                           nnz_jac_g_;\n    /// row indices in Ipopt sparsity structor for Jacobian of g(x)\n    /// (effectively const)\n    SizeVector                       iRow_jac_g_;\n    /// column indices in Ipopt sparsity structor for Jacobian of g(x)\n    /// (effectively const)\n    SizeVector                       jCol_jac_g_;\n\n    /// number non-zero is Ipopt sparsity structor for Hessian of Lagragian\n    /// (effectively const)\n    size_t                           nnz_h_lag_;\n    /// row indices in Ipopt sparsity structor for Hessian of Lagragian\n    /// (effectively const)\n    SizeVector                       iRow_h_lag_;\n    /// column indices in Ipopt sparsity structor for Hessian of Lagragian\n    /// (effectively const)\n    SizeVector                       jCol_h_lag_;\n\n    /*!\n    Mapping from (i, j) in Jacobian of g(x) to Ipopt sparsity structure\n\n    For <tt>i = 0 , ... , m_-1, index_jac_g_[i]</tt>\n    is a standard map from column index values j to the corresponding\n    index in the Ipopt sparsity structure for the Jacobian of g(x).\n    */\n    IndexMap                         index_jac_g_;\n\n    /*!\n    Mapping from (i, j) in Hessian of fg(x) to Ipopt sparsity structure\n\n    For <tt>i = 0 , ... , n_-1, index_hes_fg_[i]</tt>\n    is a standard map from column index values j to the corresponding\n    index in the Ipopt sparsity structure for the Hessian of the Lagragian.\n    */\n    IndexMap                         index_hes_fg_;\n    // -----------------------------------------------------------------\n    // Values that are changed by routine other than the constructor:\n    // -----------------------------------------------------------------\n\n    /// For <tt>k = 0 , ... , K_-1, r_fun_[k]</tt>\n    /// is a the CppAD function object corresponding to \\f$ r_k (u) \\f$.\n    ADFunVector                      r_fun_;\n    /*!\n    Is r_fun[k] OK for current x.\n\n    For <tt>k = 0 , ... , K_-1, tape_ok_[k]</tt>\n    is true if current operations sequence in <tt>r_fun_[k]</tt>\n    OK for this value of \\f$ x \\f$.\n    Note that \\f$ u = [ J_{k,\\ell} \\otimes n ] (x) \\f$ may depend on the\n    value of \\f$ \\ell \\f$.\n    */\n    BoolVector             tape_ok_;\n\n    /// work space of size equal maximum of <tt>q[k]</tt> w.r.t k.\n    SizeVector             J_;\n    /// work space of size equal maximum of <tt>p[k]</tt> w.r.t k.\n    SizeVector             I_;\n    // ------------------------------------------------------------\n    // Private Methods\n    // ------------------------------------------------------------\n    /// block the default constructor from use\n    cppad_ipopt_nlp(const cppad_ipopt_nlp&);\n    /// blocks the assignment operator from use\n    cppad_ipopt_nlp& operator=(const cppad_ipopt_nlp&);\npublic:\n    // ----------------------------------------------------------------\n    // See cppad_ipopt_nlp.cpp for doxygen documentation of these methods\n    // ----------------------------------------------------------------\n\n    /// only constructor for cppad_ipopot_nlp\n    cppad_ipopt_nlp(\n        size_t n                         ,\n        size_t m                         ,\n        const NumberVector    &x_i       ,\n        const NumberVector    &x_l       ,\n        const NumberVector    &x_u       ,\n        const NumberVector    &g_l       ,\n        const NumberVector    &g_u       ,\n        cppad_ipopt_fg_info*   fg_info   ,\n        cppad_ipopt_solution*  solution\n    );\n\n    // use virtual so that derived class destructor gets called.\n    virtual ~cppad_ipopt_nlp();\n\n    // return info about the nlp\n    virtual bool get_nlp_info(\n        Index&          n           ,\n        Index&          m           ,\n        Index&          nnz_jac_g   ,\n        Index&          nnz_h_lag   ,\n        IndexStyleEnum& index_style\n    );\n\n    // return bounds for my problem\n    virtual bool get_bounds_info(\n        Index           n   ,\n        Number*         x_l ,\n        Number*         x_u ,\n        Index           m   ,\n        Number*         g_l ,\n        Number*         g_u\n    );\n\n    // return the starting point for the algorithm\n    virtual bool get_starting_point(\n        Index          n            ,\n        bool           init_x       ,\n        Number*        x            ,\n        bool           init_z       ,\n        Number*        z_L          ,\n        Number*        z_U          ,\n        Index          m            ,\n        bool           init_lambda  ,\n        Number*        lambda\n    );\n\n    // return the objective value\n    virtual bool eval_f(\n        Index          n           ,\n        const Number*  x           ,\n        bool           new_x       ,\n        Number&        obj_value\n    );\n\n    // Method to return the gradient of the objective\n    virtual bool eval_grad_f(\n        Index          n           ,\n        const Number*  x           ,\n        bool           new_x       ,\n        Number*        grad_f\n    );\n\n    // return the constraint residuals\n    virtual bool eval_g(\n        Index          n           ,\n        const Number*  x           ,\n        bool           new_x       ,\n        Index          m           ,\n        Number*        g\n    );\n\n    // Method to return:\n    // 1) The structure of the jacobian (if \"values\" is NULL)\n    // 2) The values of the jacobian (if \"values\" is not NULL)\n    virtual bool eval_jac_g(\n        Index          n           ,\n        const Number*  x           ,\n        bool           new_x       ,\n        Index          m           ,\n        Index          nele_jac    ,\n        Index*         iRow        ,\n        Index*         jCol        ,\n        Number*        values\n    );\n\n    // Method to return:\n    //  1) structure of hessian of the lagrangian (if \"values\" is NULL)\n    //  2) values of hessian of the lagrangian (if \"values\" is not NULL)\n    virtual bool eval_h(\n        Index          n           ,\n        const Number*  x           ,\n        bool           new_x       ,\n        Number         obj_factor  ,\n        Index          m           ,\n        const Number*  lambda      ,\n        bool           new_lambda  ,\n        Index          nele_hess   ,\n        Index*         iRow        ,\n        Index*         jCol        ,\n        Number*        values\n    );\n\n    // called when the algorithm is completed so the TNLP can\n    // store/write the solution\n    virtual void finalize_solution(\n        Ipopt::SolverReturn       status      ,\n        Index                      n          ,\n        const Number*              x          ,\n        const Number*              z_L        ,\n        const Number*              z_U        ,\n        Index                      m          ,\n        const Number*              g          ,\n        const Number*              lambda     ,\n        Number                     obj_value  ,\n        const Ipopt::IpoptData*           ip_data    ,\n        Ipopt::IpoptCalculatedQuantities* ip_cq\n    );\n\n    virtual bool intermediate_callback(\n        Ipopt::AlgorithmMode              mode,\n        Index                             iter,\n        Number                            obj_value,\n        Number                            inf_pr,\n        Number                            inf_du,\n        Number                            mu,\n        Number                            d_norm,\n        Number                            regularization_size,\n        Number                            alpha_du,\n        Number                            alpha_pr,\n        Index                             ls_trials,\n        const Ipopt::IpoptData*           ip_data,\n        Ipopt::IpoptCalculatedQuantities* ip_cq\n    );\n\n};\n\n\n// ---------------------------------------------------------------------------\n} // end namespace cppad_ipopt\n// ---------------------------------------------------------------------------\n\n# endif\n"
  },
  {
    "path": "cppad_ipopt/src/fun_record.hpp",
    "content": "# ifndef CPPAD_CPPAD_IPOPT_SRC_FUN_RECORD_HPP\n# define CPPAD_CPPAD_IPOPT_SRC_FUN_RECORD_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include \"cppad_ipopt_nlp.hpp\"\n\n// ---------------------------------------------------------------------------\nnamespace cppad_ipopt {\n// ---------------------------------------------------------------------------\n/*!\n\\{\n\\file fun_record.hpp\n\\brief Records operation sequence for r_k (u)\n*/\n\n/*!\nRecords operation sequence for \\f$ r_k (u) \\f$ at \\f$u = [ J \\circ n ] (x)\\f$.\n\n\\tparam NumVector\nis the type of the argument x. It can either be\n<tt>Ipopt::Number*</tt> or\n<tt>CppAD::vector<Ipopt::Number></tt>; i.e., <tt>NumberVector</tt>.\n\n\\param fg_info\nGiven a value \\f$ u \\in {\\bf R}^{q[k]} \\f$,\n fg_info returns the value \\f$ r_k (u) \\in {\\bf R}^{p[k]} \\f$.\nusing the syntax\n\\verbatim\n    fg_info->eval_r(k, u);\n\\endverbatim\nNo other use is made of fg_info.\n\n\\param k\nis a value less that K specifying\nthe index value for k in the evaluation <tt>eval_r</tt>.\n\n\\param p\n<tt>p[k]</tt> is dimension of the range space for \\f$ r_k (u) \\f$; i.e.,\n\\f$ r_k (u) \\in {\\bf R}^{p(k)} \\f$.\n\n\\param q\n<tt>q[k]</tt> is dimension of the domain space for \\f$ r_k (u) \\f$; i.e.,\n\\f$ u \\in {\\bf R}^{q(k)} \\f$.\n\n\\param n\nis the length of the vector x.\n\n\\param x\nthe length of x is equal to n and the point\n\\f[\n    u = [ J \\circ n ] (x)\n\\f]\nis the point at which the operation sequence for \\f$ r_k \\f$ is recorded.\n\n\\param J\nis a vector with length <tt>q[k]</tt> that projects from \\f$ {\\bf R}^n \\f$\nto \\f$ {\\bf R}^{q[k]} \\f$\nby selecting an ordered subset of the possible indices\n\\f$ \\{ 0 , \\ldots , n-1 \\} \\f$.\nHence, <tt>0 <= J[j] < n</tt> for <tt>j = 0 , ... , q[k]-1</tt>.\n\n\\param r_fun\nis the vector of AD function objects which has size size greater than k.\nOnly the function object <tt>r_fun[k]</tt> is referenced.\nThe input value of this function object does not matter.\nOn output it is a recording of the function \\f$ r_k (u) \\f$\nat the value of \\f$ u \\f$ specified by x and J.\n*/\n\ntemplate <class NumVector>\nvoid fun_record(\n    cppad_ipopt_fg_info*                              fg_info ,\n    size_t                                            k       ,\n    const SizeVector&                                 p       ,\n    const SizeVector&                                 q       ,\n    size_t                                            n       ,\n    const NumVector&                                  x       ,\n    const SizeVector&                                 J       ,\n    CppAD::vector< CppAD::ADFun<Ipopt::Number> >&     r_fun   )\n{   size_t j;\n\n    // extract u from x\n    ADVector u(q[k]);\n    for(j = 0; j < q[k]; j++)\n    {   // when NDEBUG is not defined, this error should be caught\n        // during the cppad_ipopt_nlp constructor.\n        CPPAD_ASSERT_UNKNOWN( J[j] < n );\n        u[j] = x[ J[j] ];\n    }\n\n    // start the recording\n    CppAD::Independent(u);\n\n    // record the evaluation of r_k (u)\n    ADVector r_k = fg_info->eval_r(k, u);\n    CPPAD_ASSERT_KNOWN( r_k.size() == p[k] ,\n    \"cppad_ipopt_nlp: eval_r return value size not equal to p[k].\"\n    );\n\n    // stop the recording and store operation sequence in\n    r_fun[k].Dependent(u, r_k);\n}\n// ---------------------------------------------------------------------------\n} // end namespace cppad_ipopt\n// ---------------------------------------------------------------------------\n# endif\n"
  },
  {
    "path": "cppad_ipopt/src/hes_fg_map.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include \"cppad_ipopt_nlp.hpp\"\n# include \"hes_fg_map.hpp\"\n\n// ---------------------------------------------------------------------------\nnamespace cppad_ipopt {\n// ---------------------------------------------------------------------------\n/*!\n\\{\n\\file hes_fg_map.cpp\n\\brief Creates a mapping between two representations for Hessian of fg.\n*/\n\n\n/*!\nCreate mapping from CppAD to Ipopt sparse representations of Hessian of F(x).\n\nThe functions\n\\f$ f : {\\bf R}^n \\rightarrow {\\bf R} \\f$ and\n\\f$ g : {\\bf R}^n \\rightarrow {\\bf R}^m \\f$ are defined by the\n\\ref Users_Representation.\nWe define the function\n\\f$ F : {\\bf R}^n \\rightarrow {\\bf R} \\f$ by\n\\f[\n    F(x) = \\sum_{i=0}^m fg(x)_i\n\\f]\n\n\\param fg_info\nFor <tt>k = 0 , ... , K-1</tt>,\nfor <tt>ell = 0 , ... , L[k]</tt>,\nthe function call\n\\verbatim\n    fg_info->index(k, ell, I, J);\n\\endverbatim\nis made by hes_fg_map.\nThe values k and ell are inputs.\nThe input size of I ( J )\nis greater than or equal <tt>p[k] ( q[k] )</tt>\nand this size is not changed.\nThe input values of the elements of I and J are not specified.\nThe output value of the elements of I define\n\\f[\nI_{k, \\ell} = ( {\\rm I[0]} , \\cdots , {\\rm I[p[k]-1]} )\n\\f]\nThe output value of the elements of J define\n\\f[\nJ_{k, \\ell} = ( {\\rm J[0]} , \\cdots , {\\rm J[q[k]-1]} )\n\\f]\n\n\\param m\nis the dimension of the range space for \\f$ g(x) \\f$; i.e.,\n\\f$ g(x) \\in {\\bf R}^m \\f$.\n\n\\param n\nis the dimension of the domain space for \\f$ f(x) \\f$ and \\f$ g(x) \\f$;\ni.e., \\f$ x \\in {\\bf R}^n \\f$.\n\n\\param K\nis the number of functions \\f$ r_k ( u ) \\f$ used for the representation of\n\\f$ f(x) \\f$ and \\f$ g(x) \\f$.\n\n\\param L\nis a vector with size K.\nFor <tt>k = 0 , ... , K-1, L[k]</tt>\nis the number of terms that use \\f$ r_k (u) \\f$\nin the representation of \\f$ f(x) \\f$ and \\f$ g(x) \\f$.\n\n\\param p\nis a vector with size K.\nFor <tt>k = 0 , ... , K-1, p[k]</tt>\nis dimension of the range space for \\f$ r_k (u) \\f$; i.e.,\n\\f$ r_k (u) \\in {\\bf R}^{p(k)} \\f$.\n\n\\param q\nis a vector with size K.\nFor <tt>k = 0 , ... , K-1, q[k]</tt>\nis dimension of the domain space for \\f$ r_k (u) \\f$; i.e.,\n\\f$ u \\in {\\bf R}^{q(k)} \\f$.\n\n\\param pattern_hes_r\nis a vector with size K.\nFor <tt>k = 0 , ... , K-1, pattern_jac_r[k]</tt>\nis a CppAD sparsity pattern for the Hessian of the function\n\\f[\n    R(u) = \\sum_{i=0}^{p[k]-1} r_k (u)_i\n\\f]\nAs such, <tt>pattern_hes_r[k].size() == q[k] * q[k]</tt>.\n\n\\param I\nis a work vector of length greater than or equal <tt>p[k]</tt> for all k.\nThe input and output value of its elements are unspecified.\nThe size of I is not changed.\n\n\\param J\nis a work vector of length greater than or equal <tt>q[k]</tt> for all k.\nThe input and output value of its elements are unspecified.\nThe size of J is not changed.\n\n\\param index_hes_fg:\nOn input, this is empty; i.e., <tt>index_jac_g.size() == 0</tt>.\nOn output, it is the index mapping from \\f$ (i, j) \\f$ in the Jacobian of\n\\f$ g(x) \\f$ to the corresponding index value used by Ipopt to represent\nthe Jacobian.\nFurthermore, if <tt>index_jac_g[i].find(j) == index_jac_g[i].end()</tt>,\nthen the \\f$ (i, j)\\f$ entry in the Jacobian of \\f$ g(x) \\f$ is always zero.\n*/\nvoid hes_fg_map(\n    cppad_ipopt_fg_info*  fg_info                                  ,\n    size_t                                          m              ,\n    size_t                                          n              ,\n    size_t                                          K              ,\n    const CppAD::vector<size_t>&                    L              ,\n    const CppAD::vector<size_t>&                    p              ,\n    const CppAD::vector<size_t>&                    q              ,\n    const CppAD::vector<CppAD::vectorBool>&         pattern_hes_r  ,\n    CppAD::vector<size_t>&                          I              ,\n    CppAD::vector<size_t>&                          J              ,\n    CppAD::vector< std::map<size_t,size_t> >&       index_hes_fg   )\n{\n    using CppAD::vectorBool;\n    size_t i, j, ij, k, ell;\n\n    CPPAD_ASSERT_UNKNOWN( K == L.size() );\n    CPPAD_ASSERT_UNKNOWN( K == p.size() );\n    CPPAD_ASSERT_UNKNOWN( K == q.size() );\n    CPPAD_ASSERT_UNKNOWN( K == pattern_hes_r.size() );\n# ifndef NDEBUG\n    for(k = 0; k < K; k++)\n    {     CPPAD_ASSERT_UNKNOWN( p[k] <= I.size() );\n            CPPAD_ASSERT_UNKNOWN( q[k] <= J.size() );\n            CPPAD_ASSERT_UNKNOWN( q[k]*q[k] == pattern_hes_r[k].size() );\n    }\n# endif\n\n    // Now compute pattern for fg\n    // (use standard set representation because can be huge).\n    CppAD::vector< std::set<size_t> > pattern_hes_fg(n);\n    for(k = 0; k < K; k++) for(ell = 0; ell < L[k]; ell++)\n    {   fg_info->index(k, ell, I, J);\n        for(i = 0; i < q[k]; i++)\n        {   for(j = 0; j < q[k]; j++)\n            {   ij  = i * q[k] + j;\n                if( pattern_hes_r[k][ij] )\n                    pattern_hes_fg[J[i]].insert(J[j]);\n            }\n        }\n    }\n\n    // Now compute the mapping from (i, j) in the Hessian of fg to the\n    // corresponding index value used by Ipopt to represent the Hessian.\n    CPPAD_ASSERT_UNKNOWN( index_hes_fg.size() == 0 );\n    index_hes_fg.resize(n);\n    std::set<size_t>::const_iterator itr;\n    ell = 0;\n    for(i = 0; i < n; i++)\n    {   for(itr = pattern_hes_fg[i].begin();\n            itr != pattern_hes_fg[i].end();\n            itr++)\n        {\n            index_hes_fg[i][*itr] = ell++;\n        }\n    }\n    return;\n}\n\n// ---------------------------------------------------------------------------\n} // end namespace cppad_ipopt\n// ---------------------------------------------------------------------------\n"
  },
  {
    "path": "cppad_ipopt/src/hes_fg_map.hpp",
    "content": "# ifndef CPPAD_CPPAD_IPOPT_SRC_HES_FG_MAP_HPP\n# define CPPAD_CPPAD_IPOPT_SRC_HES_FG_MAP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include \"cppad_ipopt_nlp.hpp\"\n/*!\n\\file hes_fg_map.hpp\n\\brief Create a mapping between two representations for Hessian of fg.\n\n\\ingroup hes_fg_map_cpp\n*/\n// ---------------------------------------------------------------------------\nnamespace cppad_ipopt {\n// ---------------------------------------------------------------------------\n\n\nextern void hes_fg_map(\n    cppad_ipopt_fg_info*  fg_info                                  ,\n    size_t                                          m              ,\n    size_t                                          n              ,\n    size_t                                          K              ,\n    const CppAD::vector<size_t>&                    L              ,\n    const CppAD::vector<size_t>&                    p              ,\n    const CppAD::vector<size_t>&                    q              ,\n    const CppAD::vector<CppAD::vectorBool>&         pattern_hes_r  ,\n    CppAD::vector<size_t>&                          I              ,\n    CppAD::vector<size_t>&                          J              ,\n    CppAD::vector< std::map<size_t,size_t> >&       index_hes_fg\n);\n\n// ---------------------------------------------------------------------------\n} // end namespace cppad_ipopt\n// ---------------------------------------------------------------------------\n\n# endif\n"
  },
  {
    "path": "cppad_ipopt/src/jac_g_map.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include \"cppad_ipopt_nlp.hpp\"\n# include \"jac_g_map.hpp\"\n// ---------------------------------------------------------------------------\nnamespace cppad_ipopt {\n// ---------------------------------------------------------------------------\n/*!\n\\{\n\\file jac_g_map.cpp\n\\brief Creates a mapping between two representations for Jacobian of g.\n*/\n\n\n/*!\nCreate mapping from CppAD to Ipopt sparse representations of Jacobian of g.\n\nThe functions\n\\f$ f : {\\bf R}^n \\rightarrow {\\bf R} \\f$ and\n\\f$ g : {\\bf R}^n \\rightarrow {\\bf R}^m \\f$ are defined by\nthe \\ref Users_Representation.\n\n\\param fg_info\nFor <tt>k = 0 , ... , K-1</tt>,\nfor <tt>ell = 0 , ... , L[k]</tt>,\nthe function call\n\\verbatim\n    fg_info->index(k, ell, I, J);\n\\endverbatim\nis made by jac_g_map.\nThe values k and ell are inputs.\nThe input size of I ( J )\nis greater than or equal <tt>p[k] ( q[k] )</tt>\nand this size is not changed.\nThe input values of the elements of I and J are not specified.\nThe output value of the elements of I define\n\\f[\nI_{k, \\ell} = ( {\\rm I[0]} , \\cdots , {\\rm I[p[k]-1]} )\n\\f]\nThe output value of the elements of J define\n\\f[\nJ_{k, \\ell} = ( {\\rm J[0]} , \\cdots , {\\rm J[q[k]-1]} )\n\\f]\n\n\\param m\nis the dimension of the range space for \\f$ g(x) \\f$; i.e.,\n\\f$ g(x) \\in {\\bf R}^m \\f$.\n\n\\param n\nis the dimension of the domain space for \\f$ f(x) \\f$ and \\f$ g(x) \\f$;\ni.e., \\f$ x \\in {\\bf R}^n \\f$.\n\n\\param K\nis the number of functions \\f$ r_k ( u ) \\f$ used for the representation of\n\\f$ f(x) \\f$ and \\f$ g(x) \\f$.\n\n\\param L\nis a vector with size K.\nFor <tt>k = 0 , ... , K-1, L[k]</tt>\nis the number of terms that use \\f$ r_k (u) \\f$\nin the representation of \\f$ f(x) \\f$ and \\f$ g(x) \\f$.\n\n\\param p\nis a vector with size K.\nFor <tt>k = 0 , ... , K-1, p[k]</tt>\nis dimension of the range space for \\f$ r_k (u) \\f$; i.e.,\n\\f$ r_k (u) \\in {\\bf R}^{p(k)} \\f$.\n\n\\param q\nis a vector with size K.\nFor <tt>k = 0 , ... , K-1, q[k]</tt>\nis dimension of the domain space for \\f$ r_k (u) \\f$; i.e.,\n\\f$ u \\in {\\bf R}^{q(k)} \\f$.\n\n\\param pattern_jac_r\nis a vector with size K.\nFor <tt>k = 0 , ... , K-1, pattern_jac_r[k]</tt>\nis a CppAD sparsity pattern for the Jacobian of the function\n\\f$ r_k : {\\bf R}^{q(k)} \\rightarrow {\\bf R}^{p(k)} \\f$.\nAs such, <tt>pattern_jac_r[k].size() == p[k] * q[k]</tt>.\n\n\\param I\nis a work vector of length greater than or equal <tt>p[k]</tt> for all k.\nThe input and output value of its elements are unspecified.\nThe size of I is not changed.\n\n\\param J\nis a work vector of length greater than or equal <tt>q[k]</tt> for all k.\nThe input and output value of its elements are unspecified.\nThe size of J is not changed.\n\n\\param index_jac_g:\nOn input, this is empty; i.e., <tt>index_jac_g.size() == 0</tt>.\nOn output, it is the index mapping from \\f$ (i, j) \\f$ in the Jacobian of\n\\f$ g(x) \\f$ to the corresponding index value used by Ipopt to represent\nthe Jacobian.\nFurthermore, if <tt>index_jac_g[i].find(j) == index_jac_g[i].end()</tt>,\nthen the \\f$ (i, j)\\f$ entry in the Jacobian of \\f$ g(x) \\f$ is always zero.\n*/\nvoid jac_g_map(\n    cppad_ipopt_fg_info*  fg_info                                  ,\n    size_t                                          m              ,\n    size_t                                          n              ,\n    size_t                                          K              ,\n    const CppAD::vector<size_t>&                    L              ,\n    const CppAD::vector<size_t>&                    p              ,\n    const CppAD::vector<size_t>&                    q              ,\n    const CppAD::vector<CppAD::vectorBool>&         pattern_jac_r  ,\n    CppAD::vector<size_t>&                          I              ,\n    CppAD::vector<size_t>&                          J              ,\n    CppAD::vector< std::map<size_t,size_t> >&       index_jac_g    )\n{\n    using CppAD::vectorBool;\n    size_t i, j, ij, k, ell;\n\n    CPPAD_ASSERT_UNKNOWN( K == L.size() );\n    CPPAD_ASSERT_UNKNOWN( K == p.size() );\n    CPPAD_ASSERT_UNKNOWN( K == q.size() );\n    CPPAD_ASSERT_UNKNOWN( K == pattern_jac_r.size() );\n# ifndef NDEBUG\n    for(k = 0; k < K; k++)\n    {   CPPAD_ASSERT_UNKNOWN( p[k] <= I.size() );\n        CPPAD_ASSERT_UNKNOWN( q[k] <= J.size() );\n        CPPAD_ASSERT_UNKNOWN( p[k]*q[k] == pattern_jac_r[k].size() );\n    }\n# endif\n    // Now compute pattern for g\n    // (use standard set representation because can be huge).\n    CppAD::vector< std::set<size_t> > pattern_jac_g(m);\n    for(k = 0; k < K; k++) for(ell = 0; ell < L[k]; ell++)\n    {   fg_info->index(k, ell, I, J);\n        for(i = 0; i < p[k]; i++) if( I[i] != 0 )\n        {   for(j = 0; j < q[k]; j++)\n            {   ij  = i * q[k] + j;\n                if( pattern_jac_r[k][ij] )\n                    pattern_jac_g[I[i]-1].insert(J[j]);\n            }\n        }\n    }\n\n    // Now compute the mapping from (i, j) in the Jacobian of g to the\n    // corresponding index value used by Ipopt to represent the Jacobian.\n    CPPAD_ASSERT_UNKNOWN( index_jac_g.size() == 0 );\n    index_jac_g.resize(m);\n    std::set<size_t>::const_iterator itr;\n    ell = 0;\n    for(i = 0; i < m; i++)\n    {   for(itr = pattern_jac_g[i].begin();\n            itr != pattern_jac_g[i].end();\n            itr++)\n        {\n            index_jac_g[i][*itr] = ell++;\n        }\n    }\n    return;\n}\n\n// ---------------------------------------------------------------------------\n} // end namespace cppad_ipopt\n// ---------------------------------------------------------------------------\n"
  },
  {
    "path": "cppad_ipopt/src/jac_g_map.hpp",
    "content": "# ifndef CPPAD_CPPAD_IPOPT_SRC_JAC_G_MAP_HPP\n# define CPPAD_CPPAD_IPOPT_SRC_JAC_G_MAP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include \"cppad_ipopt_nlp.hpp\"\n/*!\n\\file jac_g_map.hpp\n\\brief Create a mapping between two representations for Jacobian of g.\n\n\\ingroup jac_g_map_cpp\n*/\n// ---------------------------------------------------------------------------\nnamespace cppad_ipopt {\n// ---------------------------------------------------------------------------\n\n\nextern void jac_g_map(\n    cppad_ipopt_fg_info*  fg_info                                  ,\n    size_t                                          m              ,\n    size_t                                          n              ,\n    size_t                                          K              ,\n    const CppAD::vector<size_t>&                    L              ,\n    const CppAD::vector<size_t>&                    p              ,\n    const CppAD::vector<size_t>&                    q              ,\n    const CppAD::vector<CppAD::vectorBool>&         pattern_jac_r  ,\n    CppAD::vector<size_t>&                          I              ,\n    CppAD::vector<size_t>&                          J              ,\n    CppAD::vector< std::map<size_t,size_t> >&       index_jac_g\n);\n\n// ---------------------------------------------------------------------------\n} // end namespace cppad_ipopt\n// ---------------------------------------------------------------------------\n\n# endif\n"
  },
  {
    "path": "cppad_ipopt/src/sparse_map2vec.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include \"cppad_ipopt_nlp.hpp\"\n# include \"sparse_map2vec.hpp\"\n\n// ---------------------------------------------------------------------------\nnamespace cppad_ipopt {\n// ---------------------------------------------------------------------------\n/*!\n\\{\n\\file sparse_map2vec.cpp\n\\brief Create a two vector sparsity representation from a vector of maps.\n*/\n\n\n/*!\nCreate a two vector sparsity representation from a vector of maps.\n\n\\param sparse\nIs a vector of maps representation of sparsity as well as\nthe index in the two vector representation. To be specific;\n\\verbatim\nfor(i = 0; i < sparse.size(); i++)\n{   for(itr = sparse[i].begin(); itr != sparse[i].end(); itr++)\n    {   j   = itr->first;\n        // (i, j) is a possibly non-zero entry in sparsity pattern\n        // k == itr->second, is corresponding index in i_row and j_col\n        k++;\n    }\n}\n\\endverbatim\n\n\\param n_nz\nis the total number of possibly non-zero entries.\n\n\\param i_row\nThe input size and element values for i_row do not matter.\nOn output, it has size n_nz\nand <tt>i_row[k]</tt> contains the row index corresponding to the\n k-th possibly non-zero entry.\n\n\\param j_col\nThe input size and element values for j_col do not matter.\nOn output, it has size n_nz\nand <tt>j_col[k]</tt> contains the column index corresponding to the\n k-th possibly non-zero entry.\n*/\nvoid sparse_map2vec(\n    const CppAD::vector< std::map<size_t, size_t> > sparse,\n    size_t&                                         n_nz  ,\n    CppAD::vector<size_t>&                          i_row ,\n    CppAD::vector<size_t>&                          j_col )\n{\n    size_t i, j, k, m;\n\n    // number of rows in sparse\n    m    = sparse.size();\n\n    // itererator for one row\n    std::map<size_t, size_t>::const_iterator itr;\n\n    // count the number of possibly non-zeros in sparse\n    n_nz = 0;\n    for(i = 0; i < m; i++)\n        for(itr = sparse[i].begin(); itr != sparse[i].end(); itr++)\n            ++n_nz;\n\n    // resize the return vectors to accommodate n_nz entries\n    i_row.resize(n_nz);\n    j_col.resize(n_nz);\n\n    // set the row and column indices and check assumptions on sparse\n    k = 0;\n    for(i = 0; i < m; i++)\n    {   for(itr = sparse[i].begin(); itr != sparse[i].end(); itr++)\n        {   j = itr->first;\n            CPPAD_ASSERT_UNKNOWN( k == itr->second );\n            i_row[k] = i;\n            j_col[k] = j;\n            ++k;\n        }\n    }\n    return;\n}\n\n// ---------------------------------------------------------------------------\n} // end namespace cppad_ipopt\n// ---------------------------------------------------------------------------\n"
  },
  {
    "path": "cppad_ipopt/src/sparse_map2vec.hpp",
    "content": "# ifndef CPPAD_CPPAD_IPOPT_SRC_SPARSE_MAP2VEC_HPP\n# define CPPAD_CPPAD_IPOPT_SRC_SPARSE_MAP2VEC_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n// ---------------------------------------------------------------------------\nnamespace cppad_ipopt {\n// ---------------------------------------------------------------------------\n/*!\n\\file sparse_map2vec.hpp\n\\brief Create a two vector sparsity representation from a vector of maps.\n\n\\ingroup sparese_map2vec_cpp\n*/\n\nextern void sparse_map2vec(\n    const CppAD::vector< std::map<size_t, size_t> > sparse,\n    size_t&                                         n_nz  ,\n    CppAD::vector<size_t>&                          i_row ,\n    CppAD::vector<size_t>&                          j_col\n);\n\n// ---------------------------------------------------------------------------\n} // end namespace cppad_ipopt\n// ---------------------------------------------------------------------------\n# endif\n"
  },
  {
    "path": "cppad_ipopt/src/vec_fun_pattern.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include \"cppad_ipopt_nlp.hpp\"\n# include \"vec_fun_pattern.hpp\"\n// ---------------------------------------------------------------------------\nnamespace cppad_ipopt {\n// ---------------------------------------------------------------------------\n/*!\n\\{\n\\file vec_fun_pattern.cpp\n\\brief Determine a sparsity pattern for a vector of AD function objects.\n*/\n\n/*!\nDetermine a sparsity patterns for each function in a vector of functions.\n\n\\param K\nis the number of functions that we are computing the sparsity pattern for.\n\n\\param p\nis a vector with size K.\nFor <tt>k = 0 , ... , K-1, p[k]</tt>\nis dimension of the range space for \\f$ r_k (u) \\f$; i.e.,\n\\f$ r_k (u) \\in {\\bf R}^{p(k)} \\f$.\n\n\\param q\nis a vector with size K.\nFor <tt>k = 0 , ... , K-1, q[k]</tt>\nis dimension of the domain space for \\f$ r_k (u) \\f$; i.e.,\n\\f$ u \\in {\\bf R}^{q(k)} \\f$.\n\n\\param retape\nis a vector with size K.\nFor <tt>k = 0 , ... , K-1</tt>,\nif <tt>retape[k]</tt> is true,\nthe function object <tt>r[k]</tt> is a valid representation\nfor \\f$ r_k (u) \\f$ for all \\f$ u \\in {\\bf R}^{q(k)} \\f$.\nOtherwise, the function object must be retaped for each\nvalue of \\f$ u \\f$.\n\n\\param r_fun\nis the vector of AD function objects which has size size K.\nFor <tt>k = 0 , ... , K-1</tt>,\nif <tt>retape[k]</tt> is true, <tt>r_fun[k]</tt> is not used.\nIf <tt>retape[k]</tt> is false, <tt>r_fun[k]</tt> is not used.\nis a CppAD function object correspopnding to the function\n\\f$ r_k : {\\bf R}^{q[k]} \\rightarrow {\\bf R}^{p[k]} \\f$.\nThe following non-constant member functions will be called:\n\\verbatim\n    r_fun[k].ForSparseJac(q[k], pattern_domain)\n    r_fun[k].RevSparseHes(p[k], pattern_range)\n\\endverbatim\nThe following const member functions <tt>r_fun[k].Range()</tt>\nand <tt>r_fun[k].Domain()</tt> may also be called.\n\n\\param pattern_jac_r\nis a vector with size K.\nOn input, For <tt>k = 0 , ... , K-1, pattern_jac_r[k]</tt>\nis a vector of length p[k] * q[k]\nand the value of its elements does not matter.\nOn output it is a CppAD sparsity pattern for the Jacobian of\n\\f$ r_k (u) \\f$.\n\n\\param pattern_hes_r\nis a vector with size K.\nOn input, For <tt>k = 0 , ... , K-1, pattern_hes_r[k]</tt>\nis a vector of length q[k] * q[k]\nand the value of its elements does not matter.\nOn output it is a CppAD sparsity pattern for the Hessian of\n\\f$ R : {\\bf R}^{q[k]} \\rightarrow {\\bf R} \\f$ which is defined by\n\\f[\n    R(u) = \\sum_{i=0}^{p[k]-1} r_k (u)_i\n\\f]\n*/\nvoid vec_fun_pattern(\n    size_t                                          K              ,\n    const CppAD::vector<size_t>&                    p              ,\n    const CppAD::vector<size_t>&                    q              ,\n    const CppAD::vectorBool&                        retape         ,\n    CppAD::vector< CppAD::ADFun<Ipopt::Number> >&   r_fun          ,\n    CppAD::vector<CppAD::vectorBool>&               pattern_jac_r  ,\n    CppAD::vector<CppAD::vectorBool>&               pattern_hes_r  )\n{   // check some assumptions\n    CPPAD_ASSERT_UNKNOWN( K == p.size() );\n    CPPAD_ASSERT_UNKNOWN( K == q.size() );\n    CPPAD_ASSERT_UNKNOWN( K == retape.size() );\n    CPPAD_ASSERT_UNKNOWN( K == r_fun.size() );\n    CPPAD_ASSERT_UNKNOWN( K == pattern_jac_r.size() );\n    CPPAD_ASSERT_UNKNOWN( K == pattern_hes_r.size() );\n\n    using CppAD::vectorBool;\n    size_t i, j, k;\n\n    for(k = 0; k < K; k++)\n    {   // check some k specific assumptions\n        CPPAD_ASSERT_UNKNOWN( pattern_jac_r[k].size() == p[k] * q[k] );\n        CPPAD_ASSERT_UNKNOWN( pattern_hes_r[k].size() == q[k] * q[k] );\n\n        if( retape[k] )\n        {   for(i = 0; i < p[k]; i++)\n            {   for(j = 0; j < q[k]; j++)\n                    pattern_jac_r[k][i*q[k] + j] = true;\n            }\n            for(i = 0; i < q[k]; i++)\n            {   for(j = 0; j < q[k]; j++)\n                    pattern_hes_r[k][i*q[k] + j] = true;\n            }\n        }\n        else\n        {   // check assumptions about r_k\n            CPPAD_ASSERT_UNKNOWN( r_fun[k].Range() == p[k] );\n            CPPAD_ASSERT_UNKNOWN( r_fun[k].Domain() == q[k] );\n\n            // pattern for the identity matrix\n            CppAD::vectorBool pattern_domain(q[k] * q[k]);\n            for(i = 0; i < q[k]; i++)\n            {   for(j = 0; j < q[k]; j++)\n                    pattern_domain[i*q[k] + j] = (i == j);\n            }\n            // use forward mode to compute Jacobian sparsity\n            pattern_jac_r[k] =\n                r_fun[k].ForSparseJac(q[k], pattern_domain);\n            // user reverse mode to compute Hessian sparsity\n            CppAD::vectorBool pattern_ones(p[k]);\n            for(i = 0; i < p[k]; i++)\n                pattern_ones[i] = true;\n            pattern_hes_r[k] =\n                r_fun[k].RevSparseHes(q[k], pattern_ones);\n        }\n    }\n}\n// ---------------------------------------------------------------------------\n} // end namespace cppad_ipopt\n// ---------------------------------------------------------------------------\n"
  },
  {
    "path": "cppad_ipopt/src/vec_fun_pattern.hpp",
    "content": "# ifndef CPPAD_CPPAD_IPOPT_SRC_VEC_FUN_PATTERN_HPP\n# define CPPAD_CPPAD_IPOPT_SRC_VEC_FUN_PATTERN_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include \"cppad_ipopt_nlp.hpp\"\n// ---------------------------------------------------------------------------\nnamespace cppad_ipopt {\n// ---------------------------------------------------------------------------\n/*!\n\\file vec_fun_pattern.hpp\n\\brief Determine sparsity pattern for a vector of AD function objects.\n\n\\ingroup vec_fun_pattern_cpp\n*/\n\nextern void vec_fun_pattern(\n    size_t                                          K              ,\n    const CppAD::vector<size_t>&                    p              ,\n    const CppAD::vector<size_t>&                    q              ,\n    const CppAD::vectorBool&                        retape         ,\n    CppAD::vector< CppAD::ADFun<Ipopt::Number> >&   r_fun          ,\n    CppAD::vector<CppAD::vectorBool>&               pattern_jac_r  ,\n    CppAD::vector<CppAD::vectorBool>&               pattern_hes_r\n);\n\n// ---------------------------------------------------------------------------\n} // end namespace cppad_ipopt\n// ---------------------------------------------------------------------------\n# endif\n"
  },
  {
    "path": "cppad_ipopt/test/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-23 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# Build the cppad_ipopt/test directory tests\n# Inherit build type from ../CMakeList.txt\n\n# Local include directories to search (not in package_prefix/include)\nINCLUDE_DIRECTORIES( ${CMAKE_CURRENT_SOURCE_DIR}/../src )\n\n# Local link directories to search (not in external packages)\nLINK_DIRECTORIES( ${CMAKE_CURRENT_BINARY_DIR}/../src ${ipopt_LIBRARY_DIRS} )\n\n# add_executable(<name> [WIN32] [MACOSX_BUNDLE] [EXCLUDE_FROM_ALL]\n#                 source1 source2 ... sourceN\n# )\nSET(source_list test_more.cpp\n    k_gt_one.cpp\n    multiple_solution.cpp\n    retape_k1_l1.cpp\n    retape_k1_l2.cpp\n)\nset_compile_flags( cppad_ipopt_test \"${cppad_debug_which}\" \"${source_list}\" )\n#\nADD_EXECUTABLE( cppad_ipopt_test EXCLUDE_FROM_ALL ${source_list} )\n\n# List of libraries to be linked into the specified target\nTARGET_LINK_LIBRARIES(cppad_ipopt_test\n    cppad_ipopt\n    ${cppad_lib}\n    ${ipopt_LINK_LIBRARIES}\n    ${colpack_libs}\n)\n\n# check_cppad_ipopt_test\nadd_check_executable(check_cppad_ipopt test)\n"
  },
  {
    "path": "cppad_ipopt/test/k_gt_one.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad_ipopt_nlp.hpp>\n\nnamespace { // Begin empty namespace\nusing namespace cppad_ipopt;\n\n// ---------------------------------------------------------------------------\n/*\nThis solve the same problem as\n../cppad_ipopt/cppad_ipopt_simple.cpp (repository revision\n1276) in a convoluted way in order to test the representation code.\n*/\nclass FG_K_gt_one : public cppad_ipopt_fg_info\n{\nprivate:\n    bool retape_;\npublic:\n    // derived class part of constructor\n    FG_K_gt_one(bool retape_in)\n    : retape_ (retape_in)\n    { }\n    // Evaluation of the objective f(x), and constraints g(x)\n    // using an Algorithmic Differentiation (AD) class.\n    ADVector eval_r(size_t k, const ADVector&  u)\n    {\n\n        // Fortran style indexing\n        ADNumber x1 = u[3];\n        ADNumber x2 = u[2];\n        ADNumber x3 = u[1];\n        ADNumber x4 = u[0];\n        if( k == 0 )\n        {   ADVector r(1);\n            // f(x)\n            r[0] = x1 * x4 * (x1 + x2 + x3) + x3;\n            return r;\n        }\n        ADVector r(2);\n        // g_1 (x)\n        r[0] = x1 * x2 * x3 * x4;\n        // g_2 (x)\n        r[1] = x1 * x1 + x2 * x2 + x3 * x3 + x4 * x4;\n        return r;\n    }\n    bool retape(size_t k)\n    {   return retape_; }\n    size_t number_functions(void)\n    {   return 2; }\n    size_t domain_size(size_t k)\n    {   return 4; }\n    size_t range_size(size_t k)\n    {   if( k == 0 )\n            return 1;\n        return 2;\n    }\n    size_t number_terms(size_t k)\n    {   return 1; }\n    void index(size_t k, size_t ell, SizeVector& I, SizeVector& J)\n    {\n        if( k == 0 )\n            I[0] = 0;\n        else\n        {   I[0] = 1;\n            I[1] = 2;\n        }\n        // reverse the order of the variables in u from that in x\n        for(size_t j = 0; j < 4; j++)\n            J[j] = 3-j;\n    }\n};\n} // end empty namespace\n\nbool k_gt_one(void)\n{   bool ok = true;\n    size_t j;\n\n\n    // number of independent variables (domain dimension for f and g)\n    size_t n = 4;\n    // number of constraints (range dimension for g)\n    size_t m = 2;\n    // initial value of the independent variables\n    NumberVector x_i(n);\n    x_i[0] = 1.0;\n    x_i[1] = 5.0;\n    x_i[2] = 5.0;\n    x_i[3] = 1.0;\n    // lower and upper limits for x\n    NumberVector x_l(n);\n    NumberVector x_u(n);\n    for(j = 0; j < n; j++)\n    {   x_l[j] = 1.0;\n        x_u[j] = 5.0;\n    }\n    // lower and upper limits for g\n    NumberVector g_l(m);\n    NumberVector g_u(m);\n    g_l[0] = 25.0;     g_u[0] = 1.0e19;\n    g_l[1] = 40.0;     g_u[1] = 40.0;\n\n    // known solution to check against\n    double check_x[]   = { 1.000000, 4.743000, 3.82115, 1.379408 };\n\n    size_t icase;\n    for(icase = 0; icase <= 1; icase++)\n    {   // Should cppad_ipopt_nlp retape the operation sequence for\n        // every new x. Can test both true and false cases because\n        // the operation sequence does not depend on x (for this case).\n        bool retape = bool(icase);\n\n        // check case where upper and lower limits are equal\n        if( icase == 1 )\n        {   x_l[2] = check_x[2];\n            x_u[2] = check_x[2];\n        }\n\n        // object in derived class\n        FG_K_gt_one my_fg_info(retape);\n        cppad_ipopt_fg_info *fg_info = &my_fg_info;\n\n        // create the Ipopt interface\n        cppad_ipopt_solution solution;\n        Ipopt::SmartPtr<Ipopt::TNLP> cppad_nlp = new cppad_ipopt_nlp(\n        n, m, x_i, x_l, x_u, g_l, g_u, fg_info, &solution\n        );\n\n        // Create an instance of the IpoptApplication\n        using Ipopt::IpoptApplication;\n        Ipopt::SmartPtr<IpoptApplication> app = new IpoptApplication();\n\n        // turn off any printing\n        app->Options()->SetIntegerValue(\"print_level\", 0);\n        app->Options()->SetStringValue(\"sb\", \"yes\");\n\n        // maximum number of iterations\n        app->Options()->SetIntegerValue(\"max_iter\", 10);\n\n        // approximate accuracy in first order necessary conditions;\n        // see Mathematical Programming, Volume 106, Number 1,\n        // Pages 25-57, Equation (6)\n        app->Options()->SetNumericValue(\"tol\", 1e-9);\n\n        // derivative testing\n        app->Options()->\n        SetStringValue(\"derivative_test\", \"second-order\");\n\n        // Initialize the IpoptApplication and process the options\n        Ipopt::ApplicationReturnStatus status = app->Initialize();\n        ok    &= status == Ipopt::Solve_Succeeded;\n\n        // Run the IpoptApplication\n        status = app->OptimizeTNLP(cppad_nlp);\n        ok    &= status == Ipopt::Solve_Succeeded;\n\n        /*\n        Check some of the solution values\n        */\n        ok &= solution.status == cppad_ipopt_solution::success;\n        //\n        double check_z_l[] = { 1.087871, 0.,       0.,      0.       };\n        double check_z_u[] = { 0.,       0.,       0.,      0.       };\n        double rel_tol     = 1e-6;  // relative tolerance\n        double abs_tol     = 1e-6;  // absolute tolerance\n        for(j = 0; j < n; j++)\n        {   ok &= CppAD::NearEqual(\n            check_x[j],   solution.x[j],   rel_tol, abs_tol\n            );\n            ok &= CppAD::NearEqual(\n            check_z_l[j], solution.z_l[j], rel_tol, abs_tol\n            );\n            ok &= CppAD::NearEqual(\n            check_z_u[j], solution.z_u[j], rel_tol, abs_tol\n            );\n        }\n    }\n\n    return ok;\n}\n"
  },
  {
    "path": "cppad_ipopt/test/multiple_solution.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad_ipopt_nlp.hpp>\n\nnamespace { // Begin empty namespace\nusing namespace cppad_ipopt;\n\n// ---------------------------------------------------------------------------\n/*\nf(x)    = x[1]; k=0, ell=0, I[0] = 0, J[0] = 1\ng_0 (x) = x[0]; k=0, ell=1, I[0] = 1, J[0] = 0\ng_1 (x) = x[1]; k=0, ell=2, I[0] = 2, J[0] = 1\n\nminimize   f(x)\nsubject to -1 <= g_0(x)  <= 0\n            0 <= g_1 (x) <= 1\n\nThe solution is x[1] = 0 and x[0] arbitrary.\n*/\n\nclass FG_J_changes : public cppad_ipopt_fg_info\n{\nprivate:\n    bool retape_;\npublic:\n    // constructor\n    FG_J_changes(bool retape_in)\n    : retape_ (retape_in)\n    { }\n    size_t number_functions(void)\n    {   return 1; }\n    size_t domain_size(size_t k)\n    {   size_t q = 1;\n        assert(k == 0);\n        return q;\n    }\n    size_t range_size(size_t k)\n    {   size_t p = 1;\n        assert(k == 0);\n        return p;\n    }\n    size_t number_terms(size_t k)\n    {   size_t L = 3;\n        assert(k == 0);\n        return L;\n    }\n    void index(size_t k, size_t ell, SizeVector&I, SizeVector& J)\n    {   assert( I.size() >= 1 );\n        assert( J.size() >= 1 );\n        I[0] = ell;\n        if( ell == 0 )\n        {   J[0] = 1;\n            return;\n        }\n        J[0] = ell - 1;\n        return;\n    }\n    // retape function\n    bool retape(size_t k)\n    {   return retape_; }\n    ADVector eval_r(size_t k, const ADVector&  u)\n    {\n        assert( u.size() == 1 );\n        ADVector r(1);\n        r[0] = u[0] ;\n        return r;\n    }\n};\n} // end empty namespace\n\nbool multiple_solution(void)\n{\n    bool ok = true;\n    // number of independent variables (domain dimension for f and g)\n    size_t n = 2;\n    // number of constraints (range dimension for g)\n    size_t m = 2;\n    // initial value of the independent variables\n    NumberVector x_i(n);\n    NumberVector x_l(n);\n    NumberVector x_u(n);\n\n    size_t i = 0;\n    for(i = 0; i < n; i++)\n    {   x_i[i] = 0.;\n        x_l[i] = -1.0;\n        x_u[i] = +1.0;\n    }\n\n    // lower and upper limits for g\n    NumberVector g_l(m);\n    NumberVector g_u(m);\n    g_l[0] = -1; g_u[0] = 0.;\n    g_l[1] = 0.; g_u[1] = 1.;\n\n    // object for evaluating function\n    bool retape = false;\n    FG_J_changes my_fg_info(retape);\n    cppad_ipopt_fg_info *fg_info = &my_fg_info;\n\n    cppad_ipopt_solution solution;\n    Ipopt::SmartPtr<Ipopt::TNLP> cppad_nlp = new cppad_ipopt_nlp(\n        n, m, x_i, x_l, x_u, g_l, g_u, fg_info, &solution\n    );\n\n    // Create an instance of the IpoptApplication\n    using Ipopt::IpoptApplication;\n    Ipopt::SmartPtr<IpoptApplication> app = new IpoptApplication();\n\n    // turn off any printing\n    app->Options()->SetIntegerValue(\"print_level\", 0);\n    app->Options()->SetStringValue(\"sb\", \"yes\");\n\n    // approximate accuracy in first order necessary conditions;\n    // see Mathematical Programming, Volume 106, Number 1,\n    // Pages 25-57, Equation (6)\n    app->Options()->SetNumericValue(\"tol\", 1e-9);\n    app->Options()-> SetStringValue(\"derivative_test\", \"second-order\");\n\n    // Initialize the IpoptApplication and process the options\n    Ipopt::ApplicationReturnStatus status = app->Initialize();\n    ok    &= status == Ipopt::Solve_Succeeded;\n\n    // Run the IpoptApplication\n    status = app->OptimizeTNLP(cppad_nlp);\n    ok    &= status == Ipopt::Solve_Succeeded;\n\n    /*\n      Check solution status\n      */\n    ok &= solution.status == cppad_ipopt_solution::success;\n    ok &= CppAD::NearEqual(solution.x[1], 0., 1e-6, 1e-6);\n\n    return ok;\n}\n"
  },
  {
    "path": "cppad_ipopt/test/retape_k1_l1.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad_ipopt_nlp.hpp>\n\nnamespace { // Begin empty namespace\nusing namespace cppad_ipopt;\n\n// ---------------------------------------------------------------------------\nclass FG_retape : public cppad_ipopt_fg_info\n{\npublic:\n    // derived class part of constructor\n    FG_retape(void)\n    { }\n    // Evaluation of the objective f(x), and constraints g(x)\n    // using an Algorithmic Differentiation (AD) class.\n    ADVector eval_r(size_t k, const ADVector&  x)\n    {   ADVector fg(2);\n\n        // f(x)\n        if( x[0] >= 1. )\n            fg[0] = .5 * (x[0] * x[0] + x[1] * x[1]);\n        else\n            fg[0] = x[0] + .5 * x[1] * x[1];\n        // g (x)\n        fg[1] = x[0];\n\n        return fg;\n    }\n    bool retape(size_t k)\n    {   return true; }\n};\n} // end of empty namespace\n\nbool retape_k1_l1(void)\n{   bool ok = true;\n    size_t j;\n\n\n    // number of independent variables (domain dimension for f and g)\n    size_t n = 2;\n    // number of constraints (range dimension for g)\n    size_t m = 1;\n    // initial value of the independent variables\n    NumberVector x_i(n);\n    x_i[0] = 2.0;\n    x_i[1] = 2.0;\n    // lower and upper limits for x\n    NumberVector x_l(n);\n    NumberVector x_u(n);\n    for(j = 0; j < n; j++)\n    {   x_l[j] = -10.; x_u[j] = +10.;\n    }\n    // lower and upper limits for g\n    NumberVector g_l(m);\n    NumberVector g_u(m);\n    g_l[0] = -1.;     g_u[0] = 1.0e19;\n\n    // object in derived class\n    FG_retape fg_retape;\n    cppad_ipopt_fg_info *fg_info = &fg_retape;\n\n    // create the Ipopt interface\n    cppad_ipopt_solution solution;\n    Ipopt::SmartPtr<Ipopt::TNLP> cppad_nlp = new cppad_ipopt_nlp(\n        n, m, x_i, x_l, x_u, g_l, g_u, fg_info, &solution\n    );\n\n    // Create an instance of the IpoptApplication\n    using Ipopt::IpoptApplication;\n    Ipopt::SmartPtr<IpoptApplication> app = new IpoptApplication();\n\n    // turn off any printing\n    app->Options()->SetIntegerValue(\"print_level\", 0);\n    app->Options()->SetStringValue(\"sb\", \"yes\");\n\n    // maximum number of iterations\n    app->Options()->SetIntegerValue(\"max_iter\", 10);\n\n    // approximate accuracy in first order necessary conditions;\n    // see Mathematical Programming, Volume 106, Number 1,\n    // Pages 25-57, Equation (6)\n    app->Options()->SetNumericValue(\"tol\", 1e-9);\n\n    // derivative testing\n    app->Options()->\n    SetStringValue(\"derivative_test\", \"second-order\");\n\n    // Initialize the IpoptApplication and process the options\n    Ipopt::ApplicationReturnStatus status = app->Initialize();\n    ok    &= status == Ipopt::Solve_Succeeded;\n\n    // Run the IpoptApplication\n    status = app->OptimizeTNLP(cppad_nlp);\n    ok    &= status == Ipopt::Solve_Succeeded;\n\n    /*\n    Check some of the solution values\n    */\n    ok &= solution.status == cppad_ipopt_solution::success;\n    //\n    double check_x[]   = { -1., 0. };\n    double rel_tol     = 1e-6;  // relative tolerance\n    double abs_tol     = 1e-6;  // absolute tolerance\n    for(j = 0; j < n; j++)\n    {   ok &= CppAD::NearEqual(\n            check_x[j],   solution.x[j],   rel_tol, abs_tol\n        );\n    }\n\n    return ok;\n}\n"
  },
  {
    "path": "cppad_ipopt/test/retape_k1_l2.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad_ipopt_nlp.hpp>\n\nnamespace { // Begin empty namespace\nusing namespace cppad_ipopt;\n\n// ---------------------------------------------------------------------------\n/*\nA test case were retaping is required, no constraints, and L[0] > 1.\n*/\nclass FG_info : public cppad_ipopt_fg_info\n{\npublic:\n    // derived class part of constructor\n    FG_info (void)\n    { }\n    // r_0 (u) = u if u > 1 and u^2 otherwise.\n    ADVector eval_r(size_t k, const ADVector&  u)\n    {   ADVector r(1);\n        if( u[0] > 1 )\n            r[0] = u[0];\n        else\n            r[0] = u[0] * u[0];\n        return r;\n    }\n    // operation sequence depends on u\n    bool retape(size_t k)\n    {   return true; }\n    // K = 1\n    size_t number_functions(void)\n    {   return 1; }\n    // q[k] = 1\n    size_t domain_size(size_t k)\n    {   return 1; }\n    // p[k] = 1\n    size_t range_size(size_t k)\n    {   return 1; }\n    // L[k] = 2\n    size_t number_terms(size_t k)\n    {   return 2; }\n    // I_{k,ell} = 0     // objective function index\n    // J_{k,ell} = ell   // argument index\n    void index(size_t k, size_t ell, SizeVector& I, SizeVector& J)\n    {   I[0] = 0;\n        J[0] = ell;\n    }\n};\n} // end empty namespace\n\nbool retape_k1_l2(void)\n{   bool ok = true;\n    size_t j;\n\n    // number of independent variables (domain dimension for f and g)\n    size_t n = 2;\n    // no constraints (range dimension for g)\n    size_t m = 0;\n    // initial value of the independent variables\n    NumberVector x_i(n);\n    x_i[0] = 0.0;    // below break in eval_r definition\n    x_i[1] = 2.0;    // above break in eval_r definition\n    // lower and upper limits for x\n    NumberVector x_l(n);\n    NumberVector x_u(n);\n    for(j = 0; j < n; j++)\n    {   x_l[j] = -5.0;\n        x_u[j] = +5.0;\n    }\n    // lower and upper limits for g\n    NumberVector g_l;\n    NumberVector g_u;\n\n    // object in derived class\n    FG_info my_fg_info;\n    cppad_ipopt_fg_info *fg_info = &my_fg_info;\n\n    // create the Ipopt interface\n    cppad_ipopt_solution solution;\n    Ipopt::SmartPtr<Ipopt::TNLP> cppad_nlp = new cppad_ipopt_nlp(\n        n, m, x_i, x_l, x_u, g_l, g_u, fg_info, &solution\n    );\n\n    // Create an instance of the IpoptApplication\n    using Ipopt::IpoptApplication;\n    Ipopt::SmartPtr<IpoptApplication> app = new IpoptApplication();\n\n    // turn off any printing\n    app->Options()->SetIntegerValue(\"print_level\", 0);\n    app->Options()->SetStringValue(\"sb\", \"yes\");\n\n    // maximum number of iterations\n    app->Options()->SetIntegerValue(\"max_iter\", 10);\n\n    // approximate accuracy in first order necessary conditions;\n    // see Mathematical Programming, Volume 106, Number 1,\n    // Pages 25-57, Equation (6)\n    app->Options()->SetNumericValue(\"tol\", 1e-9);\n\n    // derivative testing\n    app->Options()-> SetStringValue(\"derivative_test\", \"second-order\");\n    app->Options()-> SetNumericValue(\"point_perturbation_radius\", 0.);\n\n    // Initialize the IpoptApplication and process the options\n    Ipopt::ApplicationReturnStatus status = app->Initialize();\n    ok    &= status == Ipopt::Solve_Succeeded;\n\n    // Run the IpoptApplication\n    status = app->OptimizeTNLP(cppad_nlp);\n    ok    &= status == Ipopt::Solve_Succeeded;\n\n    /*\n    Check the solution values\n    */\n    ok &= solution.status == cppad_ipopt_solution::success;\n    //\n    double rel_tol     = 1e-6;  // relative tolerance\n    double abs_tol     = 1e-6;  // absolute tolerance\n    for(j = 0; j < n; j++)\n        ok &= CppAD::NearEqual( 0., solution.x[j], rel_tol, abs_tol);\n\n    return ok;\n}\n"
  },
  {
    "path": "cppad_ipopt/test/test.sh.in",
    "content": "#! /bin/bash -e\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\nexport LD_LIBRARY_PATH=@CPPAD_IPOPT_LD_PATH@\n./test_more\n"
  },
  {
    "path": "cppad_ipopt/test/test_more.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n// system include files used for I/O\n# include <iostream>\n\n// C style asserts\n# include <cassert>\n\n// CppAD include file\n# include <cppad/cppad.hpp>\n\n// test runner\n# include <cppad/utility/test_boolofvoid.hpp>\n\n// external complied tests\nextern bool k_gt_one(void);\nextern bool multiple_solution(void);\nextern bool retape_k1_l1(void);\nextern bool retape_k1_l2(void);\n\n// main program that runs all the tests\nint main(void)\n{   std::string group = \"cppad_ipopt/test\";\n    size_t      width = 20;\n    CppAD::test_boolofvoid Run(group, width);\n\n    // external compiled tests\n    Run( k_gt_one,            \"k_gt_one\"           );\n    Run( multiple_solution,   \"multiple_solution\"  );\n    Run( retape_k1_l1,        \"retape_k1_l1\"       );\n    Run( retape_k1_l2,        \"retape_k1_l2\"       );\n    //\n    // check for memory leak\n    bool memory_ok = CppAD::thread_alloc::free_all();\n    // print summary at end\n    bool ok = Run.summary(memory_ok);\n    //\n    return static_cast<int>( ! ok );\n}\n"
  },
  {
    "path": "cppad_lib/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-25 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# Build and install the cppad_lib shared library\n#\n# split cppad_version into year;month;day;release\nSTRING(REGEX REPLACE\n    \"([0-9][0-9][0-9][0-9])([0-9][0-9])([0-9][0-9])[.]*([0-9]*)\"\n    \"\\\\1;\\\\2;\\\\3;\\\\4\"\n    version_list\n    ${cppad_version}\n)\nLIST(GET version_list 0 year)\nLIST(GET version_list 1 month)\nLIST(GET version_list 2 day)\nLIST(GET version_list 3 release)\n#\n# soversion: dynamic library version number\nMATH(EXPR major \"${day} - 1 + 31 * ( ${month} - 1 + 12 * ( ${year} - 2019))\")\nIF( \"${release}\" STREQUAL \"\" )\n    SET(soversion \"${major}\")\nELSE( \"${release}\" STREQUAL \"\" )\n    SET(soversion \"${major}.${release}\")\nENDIF( \"${release}\" STREQUAL \"\" )\nprint_variable(soversion)\n#\n# BEGIN_SORT_THIS_LINE_PLUS_2\nSET(source_list\n    cpp_graph_op.cpp\n    cppad_colpack.cpp\n    csrc_writer.cpp\n    json_lexer.cpp\n    json_parser.cpp\n    json_writer.cpp\n    link_dll_lib.cpp\n    temp_file.cpp\n)\n# END_SORT_THIS_LINE_MINUS_2\nIF( cppad_has_cppadcg )\n    SET(source_list ${source_list} code_gen_fun.cpp)\nENDIF( cppad_has_cppadcg )\n#\n# set_compile_flags\nset_compile_flags(cppad_lib \"${cppad_debug_which}\" \"${source_list}\" )\n#\n# add_library\nIF( \"${is_cppad_lib_dynamic}\" STREQUAL \"0\" )\n    MESSAGE( STATUS \"Building static cppad_lib\")\n    ADD_LIBRARY( cppad_lib STATIC ${source_list} )\nELSEIF( \"${is_cppad_lib_dynamic}\" STREQUAL \"1\" )\n    MESSAGE( STATUS \"Building shared cppad_lib\")\n    ADD_LIBRARY( cppad_lib SHARED ${source_list} )\n    SET_TARGET_PROPERTIES( cppad_lib PROPERTIES\n        SOVERSION ${soversion}\n        LINK_OPTIONS \"${cppad_link_flags}\"\n    )\n    #\n    FIND_LIBRARY(dl_LIBRARY dl)\n    IF( dl_LIBRARY )\n        TARGET_LINK_LIBRARIES(cppad_lib ${dl_LIBRARY})\n    ENDIF( dl_LIBRARY )\nELSE( )\n    MESSAGE(FATAL_ERROR \"CMkakeLists.txt Error: invalid is_cppad_lib_dynamic\")\nENDIF( )\n#\n# install(TARGETS myExe mySharedLib myStaticLib\n#  RUNTIME DESTINATION bin\n#  LIBRARY DESTINATION lib\n#  ARCHIVE DESTINATION lib/static)\nINSTALL(TARGETS cppad_lib DESTINATION ${cppad_abs_libdir})\n"
  },
  {
    "path": "cppad_lib/code_gen_fun.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin code_gen_fun}\n{xrst_spell\n    cg\n    jrcv\n}\n\nGenerate Source Code and Compile an AD Function\n###############################################\n\nSyntax\n******\n| # ``include <cppad/example/code_gen_fun.hpp>``\n\nConstructors\n============\n\n| ``code_gen_fun`` *fun_name* ()\n| ``code_gen_fun`` *fun_name* ( *file_name* )\n| ``code_gen_fun`` *fun_name* ( *file_name* , *cg_fun* )\n| ``code_gen_fun`` *fun_name* ( *file_name* , *cg_fun* , *eval_jac* )\n\nswap\n====\n*fun_name* . ``swap`` ( *other_fun* )\n\nfunction\n========\n*y* = *fun_name* ( *x* )\n\njacobian\n========\n*J* = *fun_name* . ``jacobian`` ( *x* )\n\nsparse_jacobian\n===============\n*Jrcv* = *fun_name* . ``sparse_jacobian`` ( *x* )\n\nPrototype\n*********\n\nConstructors\n============\n{xrst_literal\n    // BEGIN_CTOR_VOID\n    // END_CTOR_VOID\n}\n{xrst_literal\n    // BEGIN_CTOR_FILE_NAME\n    // END_CTOR_FILE_NAME\n}\n{xrst_literal\n    // BEGIN_CTOR_CG_FUN\n    // END_CTOR_CG_FUN\n}\n\nOperations\n==========\n{xrst_literal\n    // BEGIN_SWAP_OTHER_FUN\n    // END_SWAP_OTHER_FUN\n}\n{xrst_literal\n    // BEGIN_FUN_NAME_X\n    // END_FUN_NAME_X\n}\n{xrst_literal\n    // BEGIN_JACOBIAN\n    // END_JACOBIAN\n}\n{xrst_literal\n    // BEGIN_SPARSE_JACOBIAN\n    // END_SPARSE_JACOBIAN\n}\n\nCppAD::cg::CG<double>\n*********************\nThis is the CppAD *Base* type for the function\n*cg_fun* .\nIt is defined by\n`CppADCodeGen <https://github.com/joaoleal/CppADCodeGen>`_.\nand used to convert the *cg_fun* function object to source code,\ncompile the source code, and then link the corresponding function evaluation\n\n    *y* = ``cg_fun.Forward`` (0, *x* )\n\nSpeed\n*****\nThe conversion to source and linking is expected to take a significant\namount of time and the evaluation of the function is expected to be\nmuch faster; see the following speed tests:\n\n.. csv-table::\n    :widths: auto\n\n    cppadcg_det_minor.cpp,:ref:`cppadcg_det_minor.cpp-title`\n    cppadcg_sparse_jacobian.cpp,:ref:`cppadcg_sparse_jacobian.cpp-title`\n\nfun_name\n********\nThis is the name of the ``code_gen_fun`` object.\n\nother_fun\n*********\nThis is the name of another ``code_gen_fun`` object.\n\nfile_name\n*********\nThis is the absolute or relative path for the\nfile that contains the dynamic library.\nIt does not include the files extension at the end that is used\nfor dynamic libraries on this system.\nIf *cg_fun* is not present in the constructor,\nit must have been present in a previous constructor with the same\n*file_name* .\n\ncg_fun\n******\nThis is a CppAD function object that corresponds to a function\n:math:`f : \\B{R}^n \\rightarrow \\B{R}^m`.\nIf this arguments is present in the constructor,\na new dynamic library is created.\n\neval_jac\n********\nIf this argument is present in the constructor,\nit determines which type of Jacobian :math:`f'(x)` will be enabled.\nThe possible choices for *eval_jac* are:\n\n.. csv-table::\n    :widths: auto\n\n    *eval_jac*,Available Jacobian\n    ``code_gen_fun::none_enum``,none\n    ``code_gen_fun::dense_enum``,*fun_name* . ``jacobian``\n\nThe default value for *eval_jac* is none.\n\nswap\n****\nThis exchanges the library in *fun_name* with the library in\n*other_fun* .\n\nx\n*\nis a vector of size *n* specifying the argument value\nat which the function will be evaluated.\n\ny\n*\nThis return value has size *m* and is the value of :math:`f(x)`.\n\njacobian\n********\n\nJ\n=\nThis return value has size *m* * *n* and is the value of\nthe Jacobian :math:`f'(x)` where\n\n.. math::\n\n    J[ i \\cdot n + j ] =  ( \\partial f_i / \\partial x_j )  (x)\n\nSpeed\n=====\nThe speed test :ref:`cppadcg_det_minor.cpp-name` has the option to pass\nthe determinant function, or the Jacobian of the determinant function,\nto CppADCodeGen (for the same eventual calculation); see\n:ref:`cppadcg_det_minor.cpp@PASS_JACOBIAN_TO_CODE_GEN` .\nThis test indicates that both methods have similar setup\nand derivative calculation times.\n\nsparse_jacobian\n***************\n\nJrcv\n****\nThis return value is a :ref:`sparse_rcv-name` sparse matrix representation\nof the Jacobian.\n\nSpeed\n=====\nThe speed test :ref:`cppadcg_sparse_jacobian.cpp-name` has the option to pass\na function (:ref:`sparse_jac_fun-name` ) or it's Jacobian to CppADCodeGen\n(for the same eventual calculation); see\n:ref:`cppadcg_sparse_jacobian.cpp@PASS_SPARSE_JACOBIAN_TO_CODE_GEN` .\nTHis test indicates that both methods have similar setup\nand derivative calculation times.\n{xrst_toc_hidden\n    example/cppad_code_gen/function.cpp\n    example/cppad_code_gen/file.cpp\n    example/cppad_code_gen/jacobian.cpp\n    example/cppad_code_gen/jac_as_fun.cpp\n    example/cppad_code_gen/sparse_jacobian.cpp\n    example/cppad_code_gen/sparse_jac_as_fun.cpp\n}\nExamples\n********\n\n.. csv-table::\n    :widths: auto\n\n    code_gen_fun_function.cpp,:ref:`code_gen_fun_function.cpp-title`\n    code_gen_fun_file.cpp,:ref:`code_gen_fun_file.cpp-title`\n    code_gen_fun_jacobian.cpp,:ref:`code_gen_fun_jacobian.cpp-title`\n    code_gen_fun_jac_as_fun.cpp,:ref:`code_gen_fun_jac_as_fun.cpp-title`\n    code_gen_fun_sparse_jacobian.cpp,:ref:`code_gen_fun_sparse_jacobian.cpp-title`\n    code_gen_fun_sparse_jac_as_fun.cpp,:ref:`code_gen_fun_sparse_jac_as_fun.cpp-title`\n\nImplementation\n**************\nsee :ref:`code_gen_fun.hpp-name` and :ref:`code_gen_fun.cpp-name`\n\n{xrst_end code_gen_fun}\n-----------------------------------------------------------------------------\n{xrst_begin code_gen_fun.hpp}\n\ncode_gen_fun Class Include File\n###############################\n\nSee Also\n********\n:ref:`code_gen_fun-name` , :ref:`code_gen_fun.cpp-name`\n\nSource\n******\n{xrst_literal\n    include/cppad/example/code_gen_fun.hpp\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end code_gen_fun.hpp}\n-----------------------------------------------------------------------------\n{xrst_begin code_gen_fun.cpp}\n\ncode_gen_fun Class Member Implementation\n########################################\n\nSee Also\n********\n:ref:`code_gen_fun-name` , :ref:`code_gen_fun.hpp-name`\n\nSource\n******\n{xrst_literal\n    // BEGIN_C++\n    // END_C++\n}\n\n{xrst_end code_gen_fun.cpp}\n*/\n// BEGIN_C++\n# include <cppad/example/code_gen_fun.hpp>\n\n// ---------------------------------------------------------------------------\n// code_gen_fun fun_name(file_name, cg_name, eval_jac)\n// ---------------------------------------------------------------------------\n// BEGIN_CTOR_CG_FUN\ncode_gen_fun::code_gen_fun(\n    const std::string&                     file_name  ,\n    CppAD::ADFun< CppAD::cg::CG<double> >& cg_fun     ,\n    evaluation_enum                        eval_jac   )\n// END_CTOR_CG_FUN\n{   // Generate source code\n    CppAD::cg::ModelCSourceGen<double> cgen(cg_fun, \"model\");\n    switch(eval_jac)\n    {   case none_enum:\n        break;\n\n        case dense_enum:\n        cgen.setCreateJacobian(true);\n        break;\n\n        case sparse_enum:\n        cgen.setCreateSparseJacobian(true);\n        break;\n    }\n    CppAD::cg::ModelLibraryCSourceGen<double> libcgen(cgen);\n\n    // Compile source, create the library file, and load the library\n    CppAD::cg::DynamicModelLibraryProcessor<double> proc(libcgen, file_name);\n    CppAD::cg::ClangCompiler<double> compiler;\n    bool loadLib = true;\n    dynamic_lib_ = proc.createDynamicLibrary(compiler, loadLib);\n    //\n    // create the model object\n    model_        = dynamic_lib_->model(\"model\");\n}\n// ---------------------------------------------------------------------------\n// code_gen_fun fun_name(file_name)\n// ---------------------------------------------------------------------------\n// BEGIN_CTOR_FILE_NAME\ncode_gen_fun::code_gen_fun(const std::string&  file_name )\n// END_CTOR_FILE_NAME\n{   // file name plus extension used for dynamic libraries on this system\n    std::string file_name_ext = file_name +\n        CppAD::cg::system::SystemInfo<>::DYNAMIC_LIB_EXTENSION;\n\n    // load the library\n    CppAD::cg::DynamicLib<double>* ptr =\n        new CppAD::cg::LinuxDynamicLib<double>(file_name_ext);\n    dynamic_lib_  = std::unique_ptr< CppAD::cg::DynamicLib<double> >(ptr);\n    //\n    // create the model object\n    model_        = dynamic_lib_->model(\"model\");\n}\n// ---------------------------------------------------------------------------\n// code_gen_fun fun_name\n// ---------------------------------------------------------------------------\n// BEGIN_CTOR_VOID\ncode_gen_fun::code_gen_fun(void)\n// END_CTOR_VOID\n{ }\n// --------------------------------------------------------------------------\n// fun_name.swap(other_fun)\n// --------------------------------------------------------------------------\n// BEGIN_SWAP_OTHER_FUN\nvoid code_gen_fun::swap(code_gen_fun& other_fun)\n// END_SWAP_OTHER_FUN\n{   std::swap(dynamic_lib_, other_fun.dynamic_lib_);\n    std::swap(model_, other_fun.model_ );\n}\n// --------------------------------------------------------------------------\n// y = fun_name(x)\n// --------------------------------------------------------------------------\n// BEGIN_FUN_NAME_X\nCppAD::vector<double>\ncode_gen_fun::operator()(const CppAD::vector<double>& x)\n// END_FUN_NAME_X\n{   return model_->ForwardZero(x);\n}\n// --------------------------------------------------------------------------\n// J = fun_name.jacobian(x)\n// --------------------------------------------------------------------------\n// BEGIN_JACOBIAN\nCppAD::vector<double>\ncode_gen_fun::jacobian(const CppAD::vector<double>& x)\n// END_JACOBIAN\n{   CPPAD_ASSERT_KNOWN( model_->isJacobianAvailable() ,\n        \"code_gen_fun: dense jacobian not enables during constructor\"\n    );\n    return model_-> Jacobian(x);\n}\n// --------------------------------------------------------------------------\n// Jrcv = fun_name.sparse_jacobian(x)\n// --------------------------------------------------------------------------\n// BEGIN_SPARSE_JACOBIAN\nCppAD::sparse_rcv< CppAD::vector<size_t>, CppAD::vector<double> >\ncode_gen_fun::sparse_jacobian(const CppAD::vector<double>& x)\n// END_SPARSE_JACOBIAN\n{   CPPAD_ASSERT_KNOWN( model_->isSparseJacobianAvailable() ,\n        \"code_gen_fun: sparse jacobian not enabled during constructor\"\n    );\n    // x_std\n    size_t n = model_->Domain();\n    std::vector<double> x_std(n);\n    for(size_t j = 0; j < n; ++j)\n        x_std[j] = x[j];\n    //\n    // 2DO: Prepahs CppAD should have a sparse_rcv constructor (jac, row, col)\n    // that uses swap to swap the vectors\n    //\n    // jac, row, col\n    std::vector<double> jac;\n    std::vector<size_t> row, col;\n    model_-> SparseJacobian(x_std, jac, row, col);\n    //\n    // sparse_rc\n    size_t nr  = model_->Range();\n    size_t nc  = model_->Domain();\n    size_t nnz = row.size();\n    CppAD::sparse_rc< CppAD::vector<size_t> > pattern(nr, nc, nnz);\n    for(size_t k = 0; k < nnz; ++k)\n        pattern.set(k, row[k], col[k]);\n    // sparse_rcv\n    CppAD::sparse_rcv< CppAD::vector<size_t>, CppAD::vector<double> >\n    Jrcv(pattern);\n    for(size_t k = 0; k < nnz; ++k)\n        Jrcv.set(k, jac[k]);\n    //\n    return Jrcv;\n}\n// END_C++\n"
  },
  {
    "path": "cppad_lib/cpp_graph_op.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/core/cppad_assert.hpp>\n# include <utility>\n\n// documentations for this routintes are in the file below\n# include <cppad/local/graph/cpp_graph_op.hpp>\n\n// BEGIN_CPPAD_LOCAL_GRAPH_NAMESPACE\nnamespace CppAD { namespace local { namespace graph {\n\n// mapping from operator name to graph_op_enum value\nstd::map<std::string, graph_op_enum> op_name2enum;\n\n// map from operator enum to name\nconst char* op_enum2name[n_graph_op];\n\n// map from operator enum to n_arg (when fixed number of arguments)\nsize_t op_enum2fixed_n_arg[n_graph_op];\n\n// This routine is called by the first use of the cpp_graph constructor\n// see cpp_graph.hpp.\nvoid set_operator_info(void)\n{   // This routine cannot be called in parallel mode\n    CPPAD_ASSERT_UNKNOWN( ! ( CppAD::thread_alloc::in_parallel() ));\n    //\n    typedef std::pair<std::string, graph_op_enum> pair;\n    struct op_info {\n        graph_op_enum code;\n        const char*  name;\n        size_t       n_arg;\n    };\n    /*\n    If n_arg is zero in the table below, the table contains a comment as to\n    the heading in graph_op_enum.hpp below which you can find the\n    specifications for n_arg, n_result for the corresponding operator.\n    */\n    // BEGIN_SORT_THIS_LINE_PLUS_2\n    op_info op_info_vec[] = {\n        { abs_graph_op,      \"abs\",      1 }, // 1 result\n        { acos_graph_op,     \"acos\",     1 }, // 1 result\n        { acosh_graph_op,    \"acosh\",    1 }, // 1 result\n        { add_graph_op,      \"add\",      2 }, // 1 result\n        { asin_graph_op,     \"asin\",     1 }, // 1 result\n        { asinh_graph_op,    \"asinh\",    1 }, // 1 result\n        { atan_graph_op,     \"atan\",     1 }, // 1 result\n        { atanh_graph_op,    \"atanh\",    1 }, // 1 result\n        { atom4_graph_op,    \"atom4\",    0 }, // See Atomic Function\n        { atom_graph_op,     \"atom\",     0 }, // See Atomic Function\n        { azmul_graph_op,    \"azmul\",    2 }, // 1 result\n        { cexp_eq_graph_op,  \"cexp_eq\",  4 }, // 1 result\n        { cexp_le_graph_op,  \"cexp_le\",  4 }, // 1 result\n        { cexp_lt_graph_op,  \"cexp_lt\",  4 }, // 1 result\n        { comp_eq_graph_op,  \"comp_eq\",  0 }, // See Comparisons\n        { comp_le_graph_op,  \"comp_le\",  0 }, // ...\n        { comp_lt_graph_op,  \"comp_lt\",  0 }, // ...\n        { comp_ne_graph_op,  \"comp_ne\",  0 }, // ...\n        { cos_graph_op,      \"cos\",      1 }, // 1 result\n        { cosh_graph_op,     \"cosh\",     1 }, // 1 result\n        { discrete_graph_op, \"discrete\", 0 }, // See Discrete Function\n        { div_graph_op,      \"div\",      2 }, // 1 result\n        { erf_graph_op,      \"erf\",      1 }, // 1 result\n        { erfc_graph_op,     \"erfc\",     1 }, // 1 result\n        { exp_graph_op,      \"exp\",      1 }, // 1 result\n        { expm1_graph_op,    \"expm1\",    1 }, // 1 result\n        { log1p_graph_op,    \"log1p\",    1 }, // 1 result\n        { log_graph_op,      \"log\",      1 }, // 1 result\n        { mul_graph_op,      \"mul\",      2 }, // 1 result\n        { neg_graph_op,      \"neg\",      1 }, // 1 result\n        { pow_graph_op,      \"pow\",      2 }, // 1 result\n        { print_graph_op,    \"print\",    0 }, // See Print\n        { sign_graph_op,     \"sign\",     1 }, // 1 result\n        { sin_graph_op,      \"sin\",      1 }, // 1 result\n        { sinh_graph_op,     \"sinh\",     1 }, // 1 result\n        { sqrt_graph_op,     \"sqrt\",     1 }, // 1 result\n        { sub_graph_op,      \"sub\",      2 }, // 1 result\n        { sum_graph_op,      \"sum\",      0 }, // See Summation\n        { tan_graph_op,      \"tan\",      1 }, // 1 result\n        { tanh_graph_op,     \"tanh\",     1 }  // 1 result\n    };\n    // END_SORT_THIS_LINE_MINUS_2\n    CPPAD_ASSERT_UNKNOWN(\n        size_t(n_graph_op) == sizeof(op_info_vec) / sizeof(op_info_vec[0])\n    );\n    for(size_t i = 0; i < size_t(n_graph_op); ++i)\n    {   graph_op_enum code              = op_info_vec[i].code;\n        const char*  name              = op_info_vec[i].name;\n        size_t       n_arg             = op_info_vec[i].n_arg;\n        CPPAD_ASSERT_UNKNOWN( size_t(code) == i );\n        //\n        op_enum2name[code]        = name;\n        op_enum2fixed_n_arg[code] = n_arg;\n        op_name2enum.insert( pair(name, code) );\n    }\n}\n\n} } } // END_CPPAD_LOCAL_GRAPH_NAMESPACE\n"
  },
  {
    "path": "cppad_lib/cppad_colpack.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <vector>\n# include <cppad/utility/vector.hpp>\n# include <cppad/configure.hpp>\n# include <cppad/local/define.hpp>\n# include <cppad/core/cppad_assert.hpp>\n\n# if CPPAD_HAS_COLPACK == 0\nnamespace CppAD { namespace local {\n    void this_routine_should_never_get_called(void)\n    {   CPPAD_ASSERT_UNKNOWN(false); }\n} }\n# else // CPPAD_HAS_COLPACK\n# include <ColPack/ColPackHeaders.h>\n\nnamespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE\n\n/*!\n\\file cppad_colpack.cpp\nThe CppAD interface to the Colpack coloring algorithms.\n*/\n\n/*!\nDetermine which rows of a general sparse matrix can be computed together.\n\n\\param color\nis a vector with color.size() == m.\nFor i = 0 , ... , m-1, color[i] is the color for the corresponding row\nof the matrix. If color[i1]==color[i2], (i1, j1) is in sparsity pattern,\nand (i2, j2) is in sparsity pattern, then j1 is not equal to j2.\n\n\\param m\nis the number of rows in the matrix.\n\n\\param n\nis the number of columns in the matrix.\n\n\\param adolc_pattern\nis a vector with adolc_pattern.size() == m.\nFor i = 0 , ... , m-1, and for k = 1, ... ,adolc_pattern[i][0],\nthe entry with index (i, adolc_pattern[i][k]) is a non-zero\nin the sparsity pattern for the matrix.\n*/\n// ----------------------------------------------------------------------\nvoid cppad_colpack_general(\n    CppAD::vector<size_t>&               color         ,\n    size_t                               m             ,\n    size_t                               n             ,\n    const CppAD::vector<unsigned int*>&  adolc_pattern )\n{   size_t i, k;\n    CPPAD_ASSERT_UNKNOWN( adolc_pattern.size() == m );\n    CPPAD_ASSERT_UNKNOWN( color.size() == m );\n\n    // Use adolc sparsity pattern to create corresponding bipartite graph\n    ColPack::BipartiteGraphPartialColoringInterface graph(\n            SRC_MEM_ADOLC,\n            adolc_pattern.data(),\n            m,\n            n\n    );\n\n    // row ordered Partial-Distance-Two-Coloring of the bipartite graph\n    graph.PartialDistanceTwoColoring(\n        \"SMALLEST_LAST\", \"ROW_PARTIAL_DISTANCE_TWO\"\n    );\n\n    // ----------------------------------------------------------------------\n    // If we had access to BipartiteGraphPartialColoring::m_vi_LeftVertexColors\n    // we could access the coloring and not need to go through seed matrix; see\n    // BipartiteGraphPartialColoring::GetLeftSeedMatrix_unmanaged in colpack\n    // and cppad_colpack_symmetric below.\n    // ----------------------------------------------------------------------\n\n    // Use coloring information to create seed matrix\n    int n_seed_row;\n    int n_seed_col;\n    double** seed_matrix = graph.GetSeedMatrix(&n_seed_row, &n_seed_col);\n    CPPAD_ASSERT_UNKNOWN( size_t(n_seed_col) == m );\n\n    // now return coloring in format required by CppAD\n    for(i = 0; i < m; i++)\n        color[i] = m;\n    for(k = 0; k < size_t(n_seed_row); k++)\n    {   for(i = 0; i < m; i++)\n        {   if( seed_matrix[k][i] != 0.0 )\n            {   // check that entries in the seed matrix are zero or one\n                CPPAD_ASSERT_UNKNOWN( seed_matrix[k][i] == 1.0 );\n                // check that no row appears twice in the coloring\n                CPPAD_ASSERT_UNKNOWN( color[i] == m );\n                // only need include rows with non-zero entries\n                if( adolc_pattern[i][0] != 0 )\n                {   // set color for this row\n                    color[i] = k;\n                }\n            }\n        }\n    }\n# ifndef NDEBUG\n    // check non-zero versus color for each row\n    for(i = 0; i < m; i++)\n    {\n        // if there is a color for row i, check that it has non-zero entries\n        if(color[i] < m )\n            CPPAD_ASSERT_UNKNOWN( adolc_pattern[i][0] != 0 );\n\n        // if there is no color for row i, check that it is empty\n        if( color[i] == m )\n            CPPAD_ASSERT_UNKNOWN( adolc_pattern[i][0] == 0 );\n    }\n\n    // check that no rows with the same color have non-zero entries\n    // with the same column index\n    CppAD::vector<bool> found(n);\n    for(k = 0; k < size_t(n_seed_row); k++)\n    {   // k is the color index\n        // found: column already has a non-zero entries for this color\n        for(size_t j = 0; j < n; j++)\n            found[j] = false;\n        // for each row with color k\n        for(i = 0; i < m; i++) if( color[i] == k )\n        {   // for each non-zero entry in this row\n            for(size_t ell = 0; ell < adolc_pattern[i][0]; ell++)\n            {   // column index for this entry\n                size_t j = adolc_pattern[i][1 + ell];\n                // check that this is the first non-zero in this column\n                CPPAD_ASSERT_UNKNOWN( ! found[j] );\n                // found a non-zero in this column\n                found[j] = true;\n            }\n        }\n    }\n# endif\n    return;\n}\n// ----------------------------------------------------------------------\n/*!\nDetermine which rows of a symmetrix sparse matrix can be computed together.\n\n\\param color\nis a vector with color.size() == m.\nFor i = 0 , ... , m-1, color[i] is the color for the corresponding row\nof the matrix. We say that a sparsity pattern entry (i, j) is valid if\nfor all i1, such that i1 != i and color[i1]==color[i],\nand all j1, such that (i1, j1) is in sparsity pattern, j1 != j.\nThe coloring is chosen so that for all (i, j) in the sparsity pattern;\neither (i, j) or (j, i) is valid (possibly both).\n\n\\param m\nis the number of rows (and columns) in the matrix.\n\n\\param adolc_pattern\nis a vector with adolc_pattern.size() == m.\nFor i = 0 , ... , m-1, and for k = 1, ... ,adolc_pattern[i][0],\nthe entry with index (i, adolc_pattern[i][k]) is\nin the sparsity pattern for the symmetric matrix.\n*/\nvoid cppad_colpack_symmetric(\n    CppAD::vector<size_t>&               color         ,\n    size_t                               m             ,\n    const CppAD::vector<unsigned int*>&  adolc_pattern )\n{   size_t i;\n    CPPAD_ASSERT_UNKNOWN( adolc_pattern.size() == m );\n    CPPAD_ASSERT_UNKNOWN( color.size() == m );\n\n    // Use adolc sparsity pattern to create corresponding bipartite graph\n    ColPack::GraphColoringInterface graph(\n            SRC_MEM_ADOLC,\n            adolc_pattern.data(),\n            m\n    );\n\n    // Use STAR coloring because it has a direct recovery scheme; i.e.,\n    // not necessary to solve equations to extract values.\n    graph.Coloring(\"SMALLEST_LAST\", \"STAR\");\n\n    // pointer to Colpack coloring solution\n    const std::vector<int>* vertex_colors_ptr = graph.GetVertexColorsPtr();\n    CPPAD_ASSERT_UNKNOWN( vertex_colors_ptr->size() == m );\n\n    // now return coloring in format required by CppAD\n    for(i = 0; i < m; i++)\n    {   if( adolc_pattern[i][0] == 0 )\n        {   // no entries in row of of sparsity patter\n            color[i] = m;\n        }\n        else\n        {   // there are non-zero entries in row i\n            color[i] = size_t( (*vertex_colors_ptr)[i] );\n            CPPAD_ASSERT_UNKNOWN( color[i] < m );\n        }\n    }\n\n# ifndef NDEBUG\n    // check that every entry in the symmetric matrix can be directly recovered\n    size_t i1, i2, j1, j2, k1, k2, nz1, nz2;\n    for(i1 = 0; i1 < m; i1++)\n    {   nz1 = size_t(adolc_pattern[i1][0]);\n        for(k1 = 1; k1 <= nz1; k1++)\n        {   j1 = adolc_pattern[i1][k1];\n            // (i1, j1) is a non-zero in the sparsity pattern\n\n            // check of a forward on color[i1] followed by a reverse\n            // can recover entry (i1, j1)\n            bool color_i1_ok = true;\n            for(i2 = 0; i2 < m; i2++) if( i1 != i2 && color[i1] == color[i2] )\n            {   nz2 = adolc_pattern[i2][0];\n                for(k2 = 1; k2 <= nz2; k2++)\n                {   j2 = adolc_pattern[i2][k2];\n                    color_i1_ok &= (j1 != j2);\n                }\n            }\n\n            // check of a forward on color[j1] followed by a reverse\n            // can recover entry (j1, i1)\n            bool color_j1_ok = true;\n            for(j2 = 0; j2 < m; j2++) if( j1 != j2 && color[j1] == color[j2] )\n            {   nz2 = adolc_pattern[j2][0];\n                for(k2 = 1; k2 <= nz2; k2++)\n                {   i2 = adolc_pattern[j2][k2];\n                    color_j1_ok &= (i1 != i2);\n                }\n            }\n\n            CPPAD_ASSERT_UNKNOWN( color_i1_ok || color_j1_ok );\n        }\n    }\n# endif\n    return;\n}\n\n} } // END_CPPAD_LOCAL_NAMESPACE\n\n# endif // CPPAD_HAS_COLPACK\n"
  },
  {
    "path": "cppad_lib/csrc_writer.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin cpp_csrc_writer dev}\n\nConverts Cpp Graph to C Source\n##############################\n\nSyntax\n******\n| ``csrc_writer`` ( *os* , *graph_obj* , *c_type* )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_PROTOTYPE\n    // END_PROTOTYPE\n}\n\nos\n**\nThe C source code corresponding to the function is written to *os* .\n\ngraph\n*****\nis the C++ graph representation of the function.\n\nc_type\n******\nthis specifies the type corresponding to the C source code and must\nbe one of the following:\n``float`` , ``double`` , or ``long_double`` .\n\n{xrst_end cpp_csrc_writer}\n*/\n\n# include <cppad/local/pod_vector.hpp>\n# include <cppad/core/cppad_assert.hpp>\n# include <cppad/core/graph/cpp_graph.hpp>\n# include <cppad/utility/to_string.hpp>\n\n// documentation for this routine is in the file below\n# include <cppad/local/graph/csrc_writer.hpp>\n\n/* Optimizations 2DO:\n1. Reduce size of v by removing x and y from the v vector.\n2. Reduce size of v by reusing elements when they are no longer needed.\n*/\n\n\nnamespace {\n    //\n    // element\n    std::string element(const std::string& array_name, size_t array_index)\n    {   return array_name + \"[\" + CppAD::to_string(array_index) + \"]\"; }\n    //\n    // binary_function\n    void binary_function(\n        std::ostream&  os           ,\n        const char*    op_csrc      ,\n        size_t         result_node  ,\n        size_t         left_node    ,\n        size_t         right_node   )\n    {   os << \"\\t\" + element(\"v\", result_node) + \" = \";\n        os << op_csrc;\n        os << \"( \" + element(\"v\", left_node);\n        os << \", \" + element(\"v\", right_node) + \" );\\n\";\n    }\n    //\n    // binary_operator\n    void binary_operator(\n        std::ostream&  os           ,\n        const char*    op_csrc      ,\n        size_t         result_node  ,\n        size_t         left_node    ,\n        size_t         right_node   )\n    {   os << \"\\t\" + element(\"v\", result_node) + \" = \";\n        os << element(\"v\", left_node) + \" \" + op_csrc + \" \";\n        os << element(\"v\", right_node) + \";\\n\";\n    }\n    //\n    // compare_operator\n    void compare_operator(\n        std::ostream&  os           ,\n        const char*    op_csrc      ,\n        size_t         left_node    ,\n        size_t         right_node   )\n    {   os << \"\\tif( \" + element(\"v\", left_node) + \" \" + op_csrc + \" \";\n        os << element(\"v\", right_node) + \" )\\n\";\n        os << \"\\t\\t++(*compare_change);\\n\";\n    }\n    //\n    // unary_function\n    void unary_function(\n        std::ostream&  os           ,\n        const char*    op_csrc      ,\n        size_t         result_node  ,\n        size_t         arg_node     )\n    {   os << \"\\t\" + element(\"v\", result_node) + \" = \";\n        os << op_csrc;\n        os << \"( \" + element(\"v\", arg_node) + \" );\\n\";\n    }\n    //\n    // sum_operator\n    void sum_operator(\n        std::ostream&                os                  ,\n        size_t                       result_node         ,\n        const CppAD::vector<size_t>& arg_node            )\n    {   std::string rhs = \"\\t\" + element(\"v\", result_node) + \" = \";\n        os << rhs;\n        if( arg_node.size() == 1 )\n        {   // can have subtraction terms with no addition terms\n            os << \"(float_point_t) 0;\\n\";\n            return;\n        }\n        for(size_t i = 0; i < arg_node.size(); ++i)\n        {   if( i % 5 == 0 && i != 0 )\n            {   os << \"\\n\\t\";\n                for(size_t j = 0;  j < rhs.size() - 4; ++j)\n                    os << ' ';\n            }\n            if( 0 < i )\n                os << \" + \";\n            os << element(\"v\", arg_node[i]);\n        }\n        os << \";\\n\";\n    }\n    //\n    // atomic_function\n    void atomic_function(\n        std::ostream&                os                  ,\n        size_t                       result_node         ,\n        const std::string&           atomic_name         ,\n        size_t                       call_id             ,\n        size_t                       n_result            ,\n        const CppAD::vector<size_t>& arg_node            )\n    {   using CppAD::to_string;\n        std::string complete_name = \"cppad_atomic_\" + atomic_name;\n        size_t nu = arg_node.size();\n        size_t nw = n_result;\n        os << \"\\t{\\t// call \" + atomic_name + \"\\n\";\n        os << \"\\t\\tint flag;\\n\";\n        os << \"\\t\\tfloat_point_t \" + element(\"u\", nu) + \";\\n\";\n        os << \"\\t\\tfloat_point_t* w = v + \" + to_string(result_node) + \";\\n\";\n        for(size_t j = 0; j < nu; ++j)\n        {   size_t i = arg_node[j];\n            os << \"\\t\\t\" + element(\"u\",j) + \" = \" + element(\"v\",i) + \";\\n\";\n        }\n        //\n        os << \"\\t\\tflag = \" + complete_name + \"(\";\n        os << to_string(call_id) + \", \";\n        os << to_string(nu) + \", u, \";\n        os << to_string(nw) + \", w, \";\n        os << \"compare_change);\\n\";\n        os << \"\\t\\tif( flag == 1 || flag == 2 ) return 3;\\n\";\n        os << \"\\t\\tif( flag != 0 ) return flag;\\n\";\n        //\n        os << \"\\t}\\n\";\n    }\n    //\n    // discrete_function\n    void discrete_function(\n        std::ostream&                os                  ,\n        size_t                       result_node         ,\n        const std::string&           discrete_name       ,\n        size_t                       arg_node            )\n    {   using CppAD::to_string;\n        std::string complete_name = \"cppad_discrete_\" + discrete_name;\n        os << \"\\t{\\t// call \" + discrete_name + \"\\n\";\n        os << \"\\t\\t\" + element(\"v\", result_node) + \" = \";\n        os << complete_name + \"( \" + element(\"v\", arg_node) + \" );\\n\";\n        os << \"\\t}\\n\";\n    }\n\n}\n\n// BEGIN_PROTOTYPE\nvoid CppAD::local::graph::csrc_writer(\n    std::ostream&                             os                     ,\n    const cpp_graph&                          graph_obj              ,\n    const std::string&                        c_type                 )\n// END_PROTOTYPE\n{   using std::string;\n    using CppAD::to_string;\n    //\n    // --------------------------------------------------------------------\n    string function_name  = graph_obj.function_name_get();\n    size_t n_dynamic_ind  = graph_obj.n_dynamic_ind_get();\n    size_t n_variable_ind = graph_obj.n_variable_ind_get();\n    size_t n_constant     = graph_obj.constant_vec_size();\n    size_t n_dependent    = graph_obj.dependent_vec_size();\n    size_t n_usage        = graph_obj.operator_vec_size();\n    // --------------------------------------------------------------------\n    CPPAD_ASSERT_KNOWN( function_name != \"\" ,\n        \"to_csrc: Cannot convert a function with no name\"\n    );\n    //\n    // graph_itr\n    // defined here because not using as loop index\n    cpp_graph::const_iterator graph_itr;\n    //\n    // first_result_node\n    size_t first_result_node = 1 + n_dynamic_ind + n_variable_ind + n_constant;\n    //\n    // n_node\n    size_t n_node = first_result_node;\n    for(size_t op_index = 0; op_index < n_usage; ++op_index)\n    {   // graph_itr\n        if( op_index == 0 )\n            graph_itr = graph_obj.begin();\n        else\n            ++graph_itr;\n        //\n        // nv\n        cpp_graph::const_iterator::value_type itr_value = *graph_itr;\n        n_node += itr_value.n_result;\n    }\n    //\n    // includes\n    os <<\n        \"// includes\\n\"\n        \"# include <stddef.h>\\n\"\n        \"# include <math.h>\\n\"\n        \"\\n\"\n    ;\n    //\n    // typedefs\n    string tmp_type = c_type;\n    if( c_type == \"long_double\" )\n        tmp_type = \"long double\";\n    os <<\n        \"// typedefs\\n\"\n        \"typedef \" + tmp_type + \" float_point_t;\\n\"\n        \"\\n\"\n    ;\n    //\n    // externals\n    os << \"// externals\\n\";\n    size_t n_atomic = graph_obj.atomic_name_vec_size();\n    for(size_t i_atomic = 0; i_atomic < n_atomic; ++i_atomic)\n    {   string atomic_name = graph_obj.atomic_name_vec_get(i_atomic);\n        os << \"extern int cppad_atomic_\" + atomic_name + \"(\\n\";\n        os <<\n            \"\\tsize_t               call_id           ,\\n\"\n            \"\\tsize_t               nu                ,\\n\"\n            \"\\tconst float_point_t* u                 ,\\n\"\n            \"\\tsize_t               ny                ,\\n\"\n            \"\\tfloat_point_t*       y                 ,\\n\"\n            \"\\tsize_t*              compare_change\\n\"\n            \");\\n\"\n        ;\n    }\n    size_t n_discrete = graph_obj.discrete_name_vec_size();\n    for(size_t i_discrete = 0; i_discrete < n_discrete; ++i_discrete)\n    {   string discrete_name = graph_obj.discrete_name_vec_get(i_discrete);\n        os << \"extern float_point_t cppad_discrete_\" + discrete_name;\n        os << \"( float_point_t x );\\n\";\n    }\n    //\n    // azmul\n    os <<\n        \"// azmul\\n\"\n        \"static float_point_t azmul(float_point_t x, float_point_t y)\\n\"\n        \"{\\tif( x == 0.0 ) return 0.0;\\n\"\n        \"\\treturn x * y;\\n\"\n        \"}\\n\\n\"\n    ;\n    //\n    // sign\n    os <<\n        \"// sign\\n\"\n        \"static float_point_t sign(float_point_t x)\\n\"\n        \"{\\tif( x > 0.0 ) return 1.0;\\n\"\n        \"\\tif( x == 0.0 ) return 0.0;\\n\"\n        \"\\treturn -1.0;\\n\"\n        \"}\\n\\n\"\n    ;\n    //\n    // This JIT function\n    os <<\n        \"// This JIT function\\n\"\n# ifdef _MSC_VER\n        \"__declspec(dllexport) int __cdecl \"\n# else\n        \"int \"\n# endif\n        \"cppad_jit_\" + function_name + \"(\\n\"\n        \"\\tsize_t               nu              ,\\n\"\n        \"\\tconst float_point_t* u               ,\\n\"\n        \"\\tsize_t               ny              ,\\n\"\n        \"\\tfloat_point_t*       y               ,\\n\"\n        \"\\tsize_t*              compare_change  )\\n\"\n    ;\n    //\n    // begin function body\n    os <<\n        \"{\\t// begin function body \\n\"\n        \"\\n\"\n    ;\n    //\n    // declare variables\n    // v, i, nan\n    os <<\n        \"\\t// declare variables\\n\"\n        \"\\tfloat_point_t v[\" + to_string(n_node) + \"];\\n\"\n        \"\\tsize_t i;\\n\"\n        \"\\n\"\n        \"\\t// check nu, ny\\n\"\n    ;\n    //\n    // nx\n    size_t nu = n_dynamic_ind + n_variable_ind;\n    os << \"\\tif( nu != \" + to_string(nu) + \") return 1;\\n\";\n    //\n    // ny\n    size_t ny = n_dependent;\n    os << \"\\tif( ny != \" + to_string(ny) + \") return 2;\\n\";\n    //\n    // initialize\n    // compare_change, v[0]\n    os <<\n        \"\\n\"\n        \"\\t// initialize\\n\"\n        \"\\tv[0]            = NAN; // const \\n\"\n    ;\n    //\n    // independent variables\n    // set v[1+i] for i = 0, ..., nx-1\"\n    os <<\n        \"\\n\"\n        \"\\t// independent variables\\n\"\n        \"\\t// set v[1+i] for i = 0, ..., nu-1\\n\"\n        \"\\tfor(i = 0; i < nu; ++i)\\n\"\n        \"\\t\\tv[1+i] = u[i];\\n\"\n    ;\n    //\n    // cosntants\n    // set v[1+nu+i] for i = 0, ..., nc-1\n    size_t nc = n_constant;\n    os <<\n        \"\\n\"\n        \"\\t// constants\\n\"\n        \"\\t// set v[1+nu+i] for i = 0, ..., nc-1\\n\"\n        \"\\t// nc = \" + to_string(nc) + \"\\n\"\n    ;\n    for(size_t i = 0; i < nc; ++i)\n    {   double c_i = graph_obj.constant_vec_get(i);\n        os <<\n            \"\\tv[1+nu+\" + to_string(i) + \"] = \" + to_string(c_i) + \";\\n\"\n        ;\n    }\n    //\n    // result nodes\n    // set v[1+nu+nc+i] for i = 0, ..., n_result_node-1\n    size_t n_result_node = n_node - first_result_node;\n    os <<\n        \"\\n\"\n        \"\\t// result nodes\\n\"\n        \"\\t// set v[1+nu+nc+i] for i = 0, ..., n_result_node-1\\n\"\n        \"\\t// n_result_node = \" + to_string(n_result_node) + \"\\n\"\n    ;\n    //\n    // result_node\n    size_t result_node = first_result_node;\n    //\n    // op_index\n    for(size_t op_index = 0; op_index < n_usage; ++op_index)\n    {   //\n        // graph_itr\n        if( op_index == 0 )\n            graph_itr = graph_obj.begin();\n        else\n            ++graph_itr;\n        //\n        // str_index, op_enum, call_id, n_result, arg_node\n        cpp_graph::const_iterator::value_type itr_value = *graph_itr;\n        const vector<size_t>& str_index( *itr_value.str_index_ptr );\n        const vector<size_t>& arg_node(  *itr_value.arg_node_ptr  );\n        graph_op_enum op_enum    = itr_value.op_enum;\n        size_t        call_id    = itr_value.call_id;\n        size_t        n_result   = itr_value.n_result;\n        CPPAD_ASSERT_UNKNOWN( arg_node.size() > 0 );\n        //\n        // op_csrc\n        const char* op_csrc = nullptr;\n        switch( op_enum )\n        {\n            // -------------------------------------------------------------\n            // binary functions\n            // -------------------------------------------------------------\n            case azmul_graph_op:\n            case pow_graph_op:\n            op_csrc = op_enum2name[op_enum];\n            break;\n            // -------------------------------------------------------------\n            // binary operators\n            // -------------------------------------------------------------\n            case add_graph_op:\n            op_csrc = \"+\";\n            break;\n            case div_graph_op:\n            op_csrc = \"/\";\n            break;\n            case mul_graph_op:\n            op_csrc = \"*\";\n            break;\n            case sub_graph_op:\n            op_csrc = \"-\";\n            break;\n            // -------------------------------------------------------------\n            // comparison operators\n            // -------------------------------------------------------------\n            case comp_eq_graph_op:\n            op_csrc = \"!=\"; // not eq\n            break;\n            case comp_le_graph_op:\n            op_csrc = \">\";  // not le\n            break;\n            case comp_lt_graph_op:\n            op_csrc = \">=\"; // not lt\n            break;\n            case comp_ne_graph_op:\n            op_csrc = \"==\"; // not ne\n            break;\n            // -------------------------------------------------------------\n            // unary functions\n            // -------------------------------------------------------------\n            case abs_graph_op:\n            op_csrc = \"fabs\";\n            break;\n            //\n            case acos_graph_op:\n            case acosh_graph_op:\n            case asin_graph_op:\n            case asinh_graph_op:\n            case atan_graph_op:\n            case atanh_graph_op:\n            case cos_graph_op:\n            case cosh_graph_op:\n            case erf_graph_op:\n            case erfc_graph_op:\n            case exp_graph_op:\n            case expm1_graph_op:\n            case log1p_graph_op:\n            case log_graph_op:\n            case sign_graph_op:\n            case sin_graph_op:\n            case sinh_graph_op:\n            case sqrt_graph_op:\n            case tan_graph_op:\n            case tanh_graph_op:\n            op_csrc = op_enum2name[op_enum];\n            break;\n\n            // ---------------------------------------------------------------\n            // operators that do not use op_csrc\n            // ---------------------------------------------------------------\n            case atom4_graph_op:\n            case discrete_graph_op:\n            case sum_graph_op:\n            op_csrc = \"\";\n            break;\n\n            default:\n            {   string msg = op_enum2name[op_enum];\n                msg = \"f.to_csrc: The \" + msg + \" is not yet implemented.\";\n                CPPAD_ASSERT_KNOWN(false, msg.c_str() );\n            }\n            break;\n        }\n        //\n        // csrc\n        switch( op_enum )\n        {   //\n            // binary functions\n            case azmul_graph_op:\n            case pow_graph_op:\n            CPPAD_ASSERT_UNKNOWN( arg_node.size() == 2 );\n            CPPAD_ASSERT_UNKNOWN( n_result == 1 );\n            binary_function(\n                os, op_csrc, result_node, arg_node[0], arg_node[1]\n            );\n            break;\n            //\n            // binary operators\n            case add_graph_op:\n            case div_graph_op:\n            case mul_graph_op:\n            case sub_graph_op:\n            CPPAD_ASSERT_UNKNOWN( arg_node.size() == 2 );\n            CPPAD_ASSERT_UNKNOWN( n_result == 1 );\n            binary_operator(\n                os, op_csrc, result_node, arg_node[0], arg_node[1]\n            );\n            break;\n            //\n            // comparison operators\n            case comp_eq_graph_op:\n            case comp_le_graph_op:\n            case comp_lt_graph_op:\n            case comp_ne_graph_op:\n            CPPAD_ASSERT_UNKNOWN( arg_node.size() == 2 );\n            CPPAD_ASSERT_UNKNOWN( n_result == 0 );\n            compare_operator(\n                os, op_csrc, arg_node[0], arg_node[1])\n            ;\n            break;\n            //\n            // unary functions\n            case abs_graph_op:\n            case acos_graph_op:\n            case acosh_graph_op:\n            case asin_graph_op:\n            case asinh_graph_op:\n            case atan_graph_op:\n            case atanh_graph_op:\n            case cos_graph_op:\n            case cosh_graph_op:\n            case erf_graph_op:\n            case erfc_graph_op:\n            case exp_graph_op:\n            case expm1_graph_op:\n            case log1p_graph_op:\n            case log_graph_op:\n            case sign_graph_op:\n            case sin_graph_op:\n            case sinh_graph_op:\n            case sqrt_graph_op:\n            case tan_graph_op:\n            case tanh_graph_op:\n            CPPAD_ASSERT_UNKNOWN( arg_node.size() == 1 );\n            CPPAD_ASSERT_UNKNOWN( n_result == 1 );\n            unary_function(\n                os, op_csrc, result_node, arg_node[0]\n            );\n            break;\n            //\n            // atom4\n            case atom4_graph_op:\n            {   size_t index       = str_index[0];\n                string atomic_name = graph_obj.atomic_name_vec_get(index);\n                atomic_function(os,\n                    result_node, atomic_name, call_id, n_result, arg_node\n                );\n            }\n            break;\n            //\n            // discrete\n            case discrete_graph_op:\n            CPPAD_ASSERT_UNKNOWN( arg_node.size() == 1 );\n            CPPAD_ASSERT_UNKNOWN( n_result == 1 );\n            {   size_t index         = str_index[0];\n                string discrete_name = graph_obj.discrete_name_vec_get(index);\n                discrete_function(os,\n                    result_node, discrete_name, arg_node[0]\n                );\n            }\n            break;\n            //\n            // sum\n            case sum_graph_op:\n            CPPAD_ASSERT_UNKNOWN( n_result == 1 );\n            sum_operator(os, result_node, arg_node);\n            break;\n            //\n            // default\n            default:\n            CPPAD_ASSERT_UNKNOWN(false);\n            break;\n        }\n        //\n        // result_node\n        result_node += n_result;\n    }\n    // ----------------------------------------------------------------------\n    // dependent\n    os <<\n        \"\\n\"\n        \"\\t// dependent variables\\n\"\n        \"\\t// set y[i] for i = 0, ny-1\\n\"\n    ;\n    for(size_t i = 0; i < ny; ++i)\n    {   size_t node = graph_obj.dependent_vec_get(i);\n        os << \"\\t\" + element(\"y\", i) + \" = \" + element(\"v\", node) + \";\\n\";\n    }\n    // ----------------------------------------------------------------------\n    // end function body\n    os << \"\\n\";\n    os << \"\\treturn 0;\\n\";\n    os << \"}\\n\";\n    //\n    return;\n}\n"
  },
  {
    "path": "cppad_lib/json_lexer.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cctype>\n# include <cppad/local/graph/json_lexer.hpp>\n# include <cppad/local/graph/cpp_graph_op.hpp>\n# include <cppad/utility/error_handler.hpp>\n# include <cppad/utility/to_string.hpp>\n# include <cppad/utility/thread_alloc.hpp>\n\n\n// BEGIN_CPPAD_LOCAL_GRAPH_NAMESPACE\nnamespace CppAD { namespace local { namespace graph {\n\n// report_error\nvoid json_lexer::report_error(\n    const std::string& expected ,\n    const std::string& found    )\n{   size_t pos = index_;\n    size_t count_newline = 0;\n    while(0 < pos && count_newline < 2 )\n    {   --pos;\n        count_newline += json_[pos] == '\\n';\n    }\n    std::string recent_input = json_.substr( pos, index_ - pos + 1);\n\n    std::string msg = \"Error occurred while parsing Json AD graph\";\n    if( function_name_ != \"\" )\n        msg += \" for the function \" + function_name_;\n    msg += \".\\n\";\n    msg += \"Expected a \" + expected + \" token but found \" + found + \"\\n\";\n    msg += \"Detected at end of following input:\";\n    msg += recent_input + \"\\n\";\n    msg += \"This end is character \" + to_string(char_number_);\n    msg += \" in line \" + to_string(line_number_) + \" of the json.\\n\";\n    msg += \"See https://coin-or.github.io/CppAD/doc/json_ad_graph.htm.\";\n    //\n    // use this source code as point of detection\n    bool known       = true;\n    int  line        = __LINE__;\n    const char* file = __FILE__;\n    const char* exp  = \"false\";\n    //\n    // CppAD error handler\n    ErrorHandler::Call(known, line, file, exp, msg.c_str());\n}\n\n// next_index\nvoid json_lexer::next_index(void)\n{   CPPAD_ASSERT_UNKNOWN( index_ < json_.size() );\n    if( json_[index_] == '\\n' )\n    {   ++line_number_;\n        char_number_ = 0;\n    }\n    ++index_;\n    ++char_number_;\n}\n\n// skip_white_space\nvoid json_lexer::skip_white_space(void)\n{   while( index_ < json_.size() && isspace( json_[index_] ) )\n        next_index();\n}\n\n// constructor\njson_lexer::json_lexer(const std::string& json)\n:\njson_(json),\nindex_(0),\nline_number_(1),\nchar_number_(1),\ntoken_(\"\"),\nfunction_name_(\"\")\n{\n    skip_white_space();\n    if( index_ < json_.size() )\n        token_ = json_[index_];\n    if( token_ != \"{\" )\n    {   std::string expected = \"'{'\";\n        std::string found    = \"'\";\n        if( index_ < json_.size() )\n            found += json_[index_];\n        found += \"'\";\n        report_error(expected, found);\n    }\n    return;\n}\n\n\n// token\nconst std::string& json_lexer::token(void) const\n{   return token_; }\n\n// line_number\nsize_t json_lexer::line_number(void) const\n{   return line_number_; }\n\n// char_number\nsize_t json_lexer::char_number(void) const\n{   return char_number_; }\n\n// set_function_name\nvoid json_lexer::set_function_name(const std::string& function_name)\n{   function_name_ = function_name; }\n\n// token2size_t\nsize_t json_lexer::token2size_t(void) const\n{   return size_t( std::atoi( token_.c_str() ) ); }\n\n// token2double\ndouble json_lexer::token2double(void) const\n{   return std::atof( token_.c_str() ); }\n\n// check_next_char\nvoid json_lexer::check_next_char(char ch)\n{   // advance to next character\n    if( index_ < json_.size() )\n        next_index();\n    skip_white_space();\n    //\n    bool ok = false;\n    if( index_ < json_.size() )\n    {   token_.resize(1);\n        token_[0] = json_[index_];\n        ok = (token_[0] == ch) || (ch == '\\0');\n    }\n    if( ! ok )\n    {   std::string expected = \"a character that is not white space\";\n        if( ch != '\\0' )\n        {   expected  = \"'\";\n            expected += ch;\n            expected += \"'\";\n        }\n        //\n        std::string found = \"'\";\n        if( index_ < json_.size() )\n            found += json_[index_];;\n        found += \"'\";\n        report_error(expected, found);\n    }\n}\n\n// check_next_string\nvoid json_lexer::check_next_string(const std::string& expected)\n{   // advance to next character\n    bool found_first_quote = index_ < json_.size();\n    if( found_first_quote )\n    {   next_index();\n        skip_white_space();\n        found_first_quote = index_ < json_.size();\n    }\n    // check for \"\n    if( found_first_quote )\n        found_first_quote = json_[index_] == '\"';\n    //\n    // set value of token\n    token_.resize(0);\n    if( found_first_quote )\n    {   next_index();\n        while( index_ < json_.size() && json_[index_] != '\"' )\n        {   token_.push_back( json_[index_] );\n            next_index();\n        }\n    }\n    // check for \"\n    bool found_second_quote = false;\n    if( found_first_quote && index_ < json_.size() )\n        found_second_quote = json_[index_] == '\"';\n    //\n    bool ok = found_first_quote & found_second_quote;\n    if( ok & (expected != \"\" ) )\n        ok = expected == token_;\n    if( ! ok )\n    {   std::string expected_token;\n        if( expected == \"\" )\n            expected_token = \"string\";\n        else\n        {   expected_token = '\"';\n            expected_token += expected;\n            expected_token += '\"';\n        }\n        //\n        std::string found;\n        if( ! found_first_quote )\n        {   found = \"'\";\n            if( index_ < json_.size() )\n                found += json_[index_];\n            found += \"'\";\n        }\n        else\n        {   found += '\"';\n            found += token_;\n            if( found_second_quote )\n                found += '\"';\n        }\n        report_error(expected_token, found);\n    }\n}\n\n// next_non_neg_int\nvoid json_lexer::next_non_neg_int(void)\n{   // advance to next character\n    bool ok = index_ < json_.size();\n    if( ok )\n    {   next_index();\n        skip_white_space();\n        ok = index_ < json_.size();\n    }\n    if( ok )\n        ok = std::isdigit( json_[index_] );\n    if( ! ok )\n    {   std::string expected_token = \"non-negative integer\";\n        std::string found = \"'\";\n        if( index_ < json_.size() )\n            found += json_[index_];\n        found += \"'\";\n        report_error(expected_token, found);\n    }\n    //\n    token_.resize(0);\n    while( ok )\n    {   token_.push_back( json_[index_] );\n        ok = index_ + 1 < json_.size();\n        if( ok )\n            ok = isdigit( json_[index_ + 1] );\n        if( ok )\n            next_index();\n    }\n}\n\n// next_float\nvoid json_lexer::next_float(void)\n{   // advance to next character\n    bool ok = index_ < json_.size();\n    if( ok )\n    {   next_index();\n        skip_white_space();\n        ok = index_ < json_.size();\n    }\n    if( ok )\n    {   char ch = json_[index_];\n        ok = std::isdigit(ch);\n        ok |= (ch == '.') || (ch == '+') || (ch == '-');\n        ok |= (ch == 'e') || (ch == 'E');\n    }\n    if( ! ok )\n    {   std::string expected_token = \"floating point number\";\n        std::string found = \"'\";\n        if( index_ < json_.size() )\n            found += json_[index_];\n        found += \"'\";\n        report_error(expected_token, found);\n    }\n    //\n    token_.resize(0);\n    while( ok )\n    {   token_.push_back( json_[index_] );\n        ok = index_ + 1 < json_.size();\n        if( ok )\n        {   char ch  = json_[index_ + 1];\n            ok  = isdigit(ch);\n            ok |= (ch == '.') || (ch == '+') || (ch == '-');\n            ok |= (ch == 'e') || (ch == 'E');\n        }\n        if( ok )\n            next_index();\n    }\n    return;\n}\n\n} } } // END_CPPAD_LOCAL_GRAPH_NAMESPACE\n"
  },
  {
    "path": "cppad_lib/json_parser.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n\n# include <cppad/core/graph/cpp_graph.hpp>\n# include <cppad/local/graph/json_lexer.hpp>\n# include <cppad/local/define.hpp>\n# include <cppad/local/atomic_index.hpp>\n# include <cppad/utility/to_string.hpp>\n\n// documentation for this routine is in the file below\n# include <cppad/local/graph/json_parser.hpp>\n\nvoid CppAD::local::graph::json_parser(\n    const std::string& json      ,\n    cpp_graph&         graph_obj )\n{   using std::string;\n    //\n    //\n    // match_any_string\n    const string match_any_string = \"\";\n    //\n    // initialize atomic_name_vec\n    graph_obj.initialize();\n    //\n    // The values in this vector will be set while parsing op_define_vec.\n    // Note that the values in op_code2enum[0] are not used.\n    CppAD::vector<graph_op_enum> op_code2enum(1);\n    //\n    // -----------------------------------------------------------------------\n    // json_lexer constructor checks for { at beginning\n    CppAD::local::graph::json_lexer json_lexer(json);\n    //\n    // \"function_name\" : function_name\n    json_lexer.check_next_string(\"function_name\");\n    json_lexer.check_next_char(':');\n    json_lexer.check_next_string(match_any_string);\n    std::string function_name = json_lexer.token();\n    graph_obj.function_name_set(function_name);\n    json_lexer.set_function_name(function_name);\n    json_lexer.check_next_char(',');\n    //\n    // -----------------------------------------------------------------------\n    // \"op_define_vec\" : [ n_define, [\n    json_lexer.check_next_string(\"op_define_vec\");\n    json_lexer.check_next_char(':');\n    json_lexer.check_next_char('[');\n    //\n    json_lexer.next_non_neg_int();\n    size_t n_define = json_lexer.token2size_t();\n    json_lexer.check_next_char(',');\n    //\n    json_lexer.check_next_char('[');\n    for(size_t i = 0; i < n_define; ++i)\n    {   // {\n        json_lexer.check_next_char('{');\n        //\n        // \"op_code\" : op_code,\n        json_lexer.check_next_string(\"op_code\");\n        json_lexer.check_next_char(':');\n        json_lexer.next_non_neg_int();\n# ifndef NDEBUG\n        size_t op_code = json_lexer.token2size_t();\n        CPPAD_ASSERT_UNKNOWN( op_code == op_code2enum.size() );\n# endif\n        json_lexer.check_next_char(',');\n        //\n        // \"name\" : name\n        json_lexer.check_next_string(\"name\");\n        json_lexer.check_next_char(':');\n        json_lexer.check_next_string(match_any_string);\n        string name = json_lexer.token();\n        graph_op_enum op_enum = op_name2enum[name];\n        //\n        // op_code2enum for this op_code\n        op_code2enum.push_back(op_enum);\n        //\n        size_t n_arg = op_enum2fixed_n_arg[op_enum];\n        if( n_arg > 0 )\n        {   // , \"narg\" : n_arg\n            json_lexer.check_next_char(',');\n            json_lexer.check_next_string(\"n_arg\");\n            json_lexer.check_next_char(':');\n            json_lexer.next_non_neg_int();\n            if( n_arg != json_lexer.token2size_t() )\n            {   string expected = CppAD::to_string(n_arg);\n                string found    = json_lexer.token();\n                json_lexer.report_error(expected, found);\n            }\n        }\n        json_lexer.check_next_char('}');\n        //\n        // , (if not last entry)\n        if( i + 1 < n_define )\n            json_lexer.check_next_char(',');\n    }\n    json_lexer.check_next_char(']');\n    // ],\n    json_lexer.check_next_char(']');\n    json_lexer.check_next_char(',');\n    //\n    // -----------------------------------------------------------------------\n    // \"n_dynamic_ind\" : n_dynamic_ind ,\n    json_lexer.check_next_string(\"n_dynamic_ind\");\n    json_lexer.check_next_char(':');\n    //\n    json_lexer.next_non_neg_int();\n    size_t n_dynamic_ind = json_lexer.token2size_t();\n    graph_obj.n_dynamic_ind_set(n_dynamic_ind);\n    //\n    json_lexer.check_next_char(',');\n    // -----------------------------------------------------------------------\n    // \"n_variable_ind\" : n_variable_ind ,\n    json_lexer.check_next_string(\"n_variable_ind\");\n    json_lexer.check_next_char(':');\n    //\n    json_lexer.next_non_neg_int();\n    size_t n_variable_ind = json_lexer.token2size_t();\n    graph_obj.n_variable_ind_set(n_variable_ind);\n    //\n    json_lexer.check_next_char(',');\n    // -----------------------------------------------------------------------\n    // \"constant_vec\": [ n_constant, [ first_constant, ..., last_constant ] ],\n    json_lexer.check_next_string(\"constant_vec\");\n    json_lexer.check_next_char(':');\n    json_lexer.check_next_char('[');\n    //\n    json_lexer.next_non_neg_int();\n    size_t n_constant = json_lexer.token2size_t();\n    //\n    json_lexer.check_next_char(',');\n    //\n    // [ first_constant, ... , last_constant ]\n    json_lexer.check_next_char('[');\n    for(size_t i = 0; i < n_constant; ++i)\n    {   json_lexer.next_float();\n        graph_obj.constant_vec_push_back( json_lexer.token2double() );\n        //\n        if( i + 1 < n_constant )\n            json_lexer.check_next_char(',');\n    }\n    json_lexer.check_next_char(']');\n    json_lexer.check_next_char(']');\n    json_lexer.check_next_char(',');\n    // -----------------------------------------------------------------------\n    // \"op_usage_vec\": [ n_usage, [ first_op_usage, ..., last_op_usage ] ],\n    json_lexer.check_next_string(\"op_usage_vec\");\n    json_lexer.check_next_char(':');\n    json_lexer.check_next_char('[');\n    //\n    json_lexer.next_non_neg_int();\n    size_t n_usage = json_lexer.token2size_t();\n    //\n    json_lexer.check_next_char(',');\n    json_lexer.check_next_char('[');\n    //\n    // index for strings in current operator\n    CppAD::vector<size_t> str_index;\n    for(size_t i = 0; i < n_usage; ++i)\n    {   str_index.resize(0);\n        //\n        // [ op_code,\n        json_lexer.check_next_char('[');\n        //\n        // op_enum\n        json_lexer.next_non_neg_int();\n        graph_op_enum op_enum    = op_code2enum[ json_lexer.token2size_t() ];\n        json_lexer.check_next_char(',');\n        //\n        size_t call_id  = std::numeric_limits<size_t>::max();\n        size_t n_result = 1;\n        size_t n_arg    = op_enum2fixed_n_arg[op_enum];\n        //\n        // check if number of arguments is fixed\n        bool fixed        = n_arg > 0;\n        if( ! fixed )\n        {   if( op_enum == discrete_graph_op )\n            {   // name,\n                json_lexer.check_next_string(match_any_string);\n                string name = json_lexer.token();\n                json_lexer.check_next_char(',');\n                //\n                size_t name_index = graph_obj.discrete_name_vec_find(name);\n                if( name_index == graph_obj.discrete_name_vec_size() )\n                    graph_obj.discrete_name_vec_push_back( name );\n                str_index.push_back(name_index);\n            }\n            else if( op_enum == atom_graph_op || op_enum == atom4_graph_op )\n            {   // name\n                json_lexer.check_next_string(match_any_string);\n                string name = json_lexer.token();\n                json_lexer.check_next_char(',');\n                //\n                size_t name_index = graph_obj.atomic_name_vec_find(name);\n                if( name_index == graph_obj.atomic_name_vec_size() )\n                    graph_obj.atomic_name_vec_push_back( name );\n                str_index.push_back(name_index);\n            }\n            else if( op_enum == print_graph_op )\n            {   // before\n                json_lexer.check_next_string(match_any_string);\n                string before = json_lexer.token();\n                json_lexer.check_next_char(',');\n                //\n                size_t before_index = graph_obj.print_text_vec_find(before);\n                if( before_index == graph_obj.print_text_vec_size() )\n                    graph_obj.print_text_vec_push_back(before);\n                str_index.push_back(before_index);\n                //\n                // aftere\n                json_lexer.check_next_string(match_any_string);\n                string after = json_lexer.token();\n                json_lexer.check_next_char(',');\n                //\n                size_t after_index = graph_obj.print_text_vec_find(after);\n                if( after_index == graph_obj.print_text_vec_size() )\n                    graph_obj.print_text_vec_push_back(after);\n                str_index.push_back(after_index);\n            }\n            else CPPAD_ASSERT_UNKNOWN(\n                op_enum == comp_eq_graph_op ||\n                op_enum == comp_le_graph_op ||\n                op_enum == comp_lt_graph_op ||\n                op_enum == comp_ne_graph_op ||\n                op_enum == sum_graph_op\n            );\n            if( op_enum == atom4_graph_op )\n            {   json_lexer.next_non_neg_int();\n                call_id = json_lexer.token2size_t();\n                json_lexer.check_next_char(',');\n            }\n            // n_result,\n            json_lexer.next_non_neg_int();\n            n_result = json_lexer.token2size_t();\n            json_lexer.check_next_char(',');\n            //\n            // n_arg, [\n            json_lexer.next_non_neg_int();\n            n_arg = json_lexer.token2size_t();\n            json_lexer.check_next_char(',');\n            json_lexer.check_next_char('[');\n        }\n        //\n        // atom_graph_op: name_index, n_result, n_arg\n        // come before first function argument\n        //\n        // atom4_graph_op: name_index, call_id, n_result, n_arg\n        // come before first function argument\n        if( op_enum == atom_graph_op || op_enum == atom4_graph_op )\n        {   // name_index, n_result, n_arg come before first_node\n            size_t name_index = str_index[0];\n            CPPAD_ASSERT_UNKNOWN(\n                name_index < graph_obj.atomic_name_vec_size()\n            );\n            if( op_enum == atom4_graph_op )\n                graph_obj.operator_arg_push_back( call_id );\n            graph_obj.operator_arg_push_back( name_index );\n            graph_obj.operator_arg_push_back( n_result );\n            graph_obj.operator_arg_push_back( n_arg );\n        }\n        // discrete_op: name_index comes before first argument\n        if( op_enum == discrete_graph_op )\n        {   size_t name_index = str_index[0];\n            graph_obj.operator_arg_push_back( name_index );\n        }\n        // print_op: before_index, after_index come before first argument\n        if( op_enum == print_graph_op )\n        {   size_t before_index = str_index[0];\n            size_t after_index  = str_index[1];\n            graph_obj.operator_arg_push_back( before_index );\n            graph_obj.operator_arg_push_back( after_index );\n        }\n        //\n        // sum_graph_op: n_arg comes before first argument\n        if( op_enum == sum_graph_op )\n            graph_obj.operator_arg_push_back( n_arg );\n        //\n        // operator_vec\n        graph_op_enum op_usage;\n        op_usage = op_enum;\n        graph_obj.operator_vec_push_back( op_usage );\n        for(size_t j = 0; j < n_arg; ++j)\n        {   // next_arg\n            json_lexer.next_non_neg_int();\n            size_t argument_node = json_lexer.token2size_t();\n            graph_obj.operator_arg_push_back( argument_node );\n            //\n            // , (if not last entry)\n            if( j + 1 < n_arg )\n                json_lexer.check_next_char(',');\n        }\n        json_lexer.check_next_char(']');\n        if( ! fixed )\n            json_lexer.check_next_char(']');\n        //\n        // , (if not last entry)\n        if( i + 1 < n_usage )\n            json_lexer.check_next_char(',');\n    }\n    json_lexer.check_next_char(']');\n    json_lexer.check_next_char(']');\n    json_lexer.check_next_char(',');\n    // -----------------------------------------------------------------------\n    // \"dependent_vec\": [ n_dependent, [first_dependent, ..., last_dependent] ]\n    json_lexer.check_next_string(\"dependent_vec\");\n    json_lexer.check_next_char(':');\n    json_lexer.check_next_char('[');\n    //\n    json_lexer.next_non_neg_int();\n    size_t n_dependent = json_lexer.token2size_t();\n    json_lexer.check_next_char(',');\n    //\n    json_lexer.check_next_char('[');\n    for(size_t i = 0; i < n_dependent; ++i)\n    {   json_lexer.next_float();\n        graph_obj.dependent_vec_push_back( json_lexer.token2size_t() );\n        //\n        if( i + 1 < n_dependent )\n            json_lexer.check_next_char(',');\n    }\n    json_lexer.check_next_char(']');\n    json_lexer.check_next_char(']');\n    // -----------------------------------------------------------------------\n    // end of Json object\n    json_lexer.check_next_char('}');\n    //\n    return;\n}\n"
  },
  {
    "path": "cppad_lib/json_writer.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/local/pod_vector.hpp>\n# include <cppad/core/cppad_assert.hpp>\n# include <cppad/core/graph/cpp_graph.hpp>\n# include <cppad/utility/to_string.hpp>\n# include <cppad/utility/vector.hpp>\n\n// documentation for this routine is in the file below\n# include <cppad/local/graph/json_writer.hpp>\n\nvoid CppAD::local::graph::json_writer(\n    std::string&                              json                   ,\n    const cpp_graph&                          graph_obj              )\n{   using std::string;\n    // --------------------------------------------------------------------\n    const string&  function_name( graph_obj.function_name_get() );\n    const size_t&  n_dynamic_ind( graph_obj.n_dynamic_ind_get() );\n    const size_t&  n_variable_ind( graph_obj.n_variable_ind_get() );\n    // --------------------------------------------------------------------\n    //\n    // set: n_usage\n    size_t n_usage = graph_obj.operator_vec_size();\n    //\n    // set: is_graph_op_used\n    pod_vector<bool> is_graph_op_used(n_graph_op);\n    for(size_t i = 0; i < n_graph_op; ++i)\n        is_graph_op_used[i] = false;\n    for(size_t i = 0; i < n_usage; ++i)\n        is_graph_op_used[ graph_obj.operator_vec_get(i) ] = true;\n    //\n    // set: n_define and graph_code\n    size_t n_define = 0;\n    pod_vector<size_t> graph_code(n_graph_op);\n    for(size_t i = 0; i < n_graph_op; ++i)\n    {   graph_code[i] = 0;\n        if( is_graph_op_used[i] )\n            graph_code[i] = ++n_define;\n    }\n    // ----------------------------------------------------------------------\n    // output: starting '{' for this graph\n    json = \"{\\n\";\n    //\n    // output: function_name\n    json += \"'function_name' : '\" + function_name + \"',\\n\";\n    //\n    // output: op_define_vec\n    json += \"'op_define_vec' : [ \" + to_string(n_define) + \", [\\n\";\n    size_t count_define = 0;\n    for(size_t i = 0; i < n_graph_op; ++i)\n    {   if( is_graph_op_used[i] )\n        {   ++count_define;\n            const string name = op_enum2name[i];\n            size_t op_code    = graph_code[i];\n            size_t n_arg      = op_enum2fixed_n_arg[i];\n            json += \"{ 'op_code':\" + to_string(op_code);\n            json += \", 'name':'\" + name + \"'\";\n            if( n_arg != 0 )\n                json += \", 'n_arg':\" + to_string(n_arg);\n            json += \" }\";\n            if( count_define < n_define )\n                json += \",\\n\";\n        }\n    }\n    json += \" ]\\n] ,\\n\";\n    //\n    // output: n_dynamic_ind\n    json += \"'n_dynamic_ind' : \" + to_string( n_dynamic_ind ) + \",\\n\";\n    //\n    // output: n_variable_ind\n    json += \"'n_variable_ind' : \" + to_string( n_variable_ind ) + \",\\n\";\n    //\n    // output: constant_vec\n    size_t n_constant = graph_obj.constant_vec_size();\n    json += \"'constant_vec' : [ \" + to_string(n_constant) + \", [\\n\";\n    for(size_t i = 0; i < n_constant; ++i)\n    {   json += to_string( graph_obj.constant_vec_get(i) );\n        if( i + 1 < n_constant )\n            json += \",\\n\";\n    }\n    json += \" ] ],\\n\";\n    // -----------------------------------------------------------------------\n    //\n    // defined here to avoid memory re-allocation for each operator\n    vector<size_t> arg;\n    //\n    // defined here because not using as loop index\n    cpp_graph::const_iterator graph_itr;\n    //\n    // output: op_usage_vec\n    json += \"'op_usage_vec' : [ \" + to_string(n_usage) + \", [\\n\";\n    for(size_t op_index = 0; op_index < n_usage; ++op_index)\n    {   // op_enum, str_index, n_result, arg_node\n        if( op_index == 0 )\n            graph_itr = graph_obj.begin();\n        else\n            ++graph_itr;\n        //\n        cpp_graph::const_iterator::value_type itr_value = *graph_itr;\n        const vector<size_t>& str_index( *itr_value.str_index_ptr );\n        graph_op_enum op_enum    = itr_value.op_enum;\n        size_t        call_id    = itr_value.call_id;\n        size_t        n_result   = itr_value.n_result;\n        size_t        n_arg      = itr_value.arg_node_ptr->size();\n        arg.resize(n_arg);\n        arg                      = *(itr_value.arg_node_ptr);\n        CPPAD_ASSERT_UNKNOWN( n_arg > 0 );\n        //\n        // op_code\n        size_t op_code = graph_code[op_enum];\n        //\n        switch( op_enum )\n        {\n            // --------------------------------------------------------------\n            // sum\n            case sum_graph_op:\n            json += \"[ \" + to_string(op_code) + \", 1, \";\n            json += to_string(n_arg) + \", [ \";\n            for(size_t j = 0; j < n_arg; ++j)\n            {   json += to_string( arg[j] );\n                if( j + 1 < n_arg )\n                    json += \", \";\n            }\n            json += \"] ]\";\n            break;\n\n            // --------------------------------------------------------------\n            // atom, atom4\n            case atom_graph_op:\n            case atom4_graph_op:\n            {   size_t name_index = str_index[0];\n                string name = graph_obj.atomic_name_vec_get(name_index);\n                json += \"[ \" + to_string(op_code) + \", \";\n                json += \"'\" + name + \"', \";\n            }\n            if( op_enum == atom4_graph_op )\n                json += to_string(call_id) + \", \";\n            json += to_string(n_result) + \", \";\n            json += to_string(n_arg) + \", [\";\n            for(size_t j = 0; j < n_arg; ++j)\n            {   json += to_string( arg[j] );\n                if( j + 1 < n_arg )\n                    json += \", \";\n                      else\n                    json += \" ]\";\n            }\n            json += \" ]\";\n            break;\n\n            // --------------------------------------------------------------\n            // comparison operators\n            case comp_eq_graph_op:\n            case comp_ne_graph_op:\n            case comp_lt_graph_op:\n            case comp_le_graph_op:\n            CPPAD_ASSERT_UNKNOWN( n_result == 0 );\n            CPPAD_ASSERT_UNKNOWN( n_arg == 2 );\n            json += \"[ \" + to_string(op_code) + \", 0, 2, [ \";\n            json += to_string( arg[0] ) + \", \";\n            json += to_string( arg[1] ) + \" ] ]\";\n            break;\n\n            // --------------------------------------------------------------\n            // discrete\n            case discrete_graph_op:\n            CPPAD_ASSERT_UNKNOWN( n_result == 1 );\n            CPPAD_ASSERT_UNKNOWN( n_arg == 1 );\n            {   size_t name_index = str_index[0];\n                string name = graph_obj.discrete_name_vec_get(name_index);\n                json += \"[ \" + to_string(op_code) + \", \";\n                json += \"'\" + name + \"', \";\n            }\n            json += to_string(n_result) + \", \";\n            json += to_string(n_arg) + \", [ \";\n            json += to_string( arg[0] ) + \" ] ]\";\n            break;\n            // --------------------------------------------------------------\n            // print_op\n            case print_graph_op:\n            CPPAD_ASSERT_UNKNOWN( n_result == 0 );\n            CPPAD_ASSERT_UNKNOWN( n_arg == 2 );\n            {   size_t before_index = str_index[0];\n                size_t after_index  = str_index[1];\n                string before  = graph_obj.print_text_vec_get(before_index);\n                string after   = graph_obj.print_text_vec_get(after_index);\n                json += \"[ \" + to_string(op_code) + \", \";\n                json += \"'\" + before + \"', \";\n                json += \"'\" + after + \"', 0, 2, [ \";\n                json += to_string( arg[0] ) + \", \";\n                json += to_string( arg[1] ) + \" ] ]\";\n            }\n            break;\n\n            // --------------------------------------------------------------\n            default:\n            CPPAD_ASSERT_UNKNOWN( n_result == 1 );\n            CPPAD_ASSERT_UNKNOWN( op_enum2fixed_n_arg[op_enum] == n_arg );\n            json += \"[ \" + to_string(op_code) + \", \";\n            for(size_t j = 0; j < n_arg; ++j)\n            {   json += to_string( arg[j] );\n                if( j + 1 < n_arg )\n                    json += \", \";\n                      else\n                    json += \" ]\";\n            }\n            break;\n\n        } // end switch\n        if( op_index + 1 < n_usage )\n            json += \",\\n\";\n    }\n    json += \"\\n] ],\\n\";\n    // ----------------------------------------------------------------------\n    // output: dependent_vec\n    size_t n_dependent = graph_obj.dependent_vec_size();\n    json += \"'dependent_vec' : [ \" + to_string(n_dependent) + \", [ \";\n    for(size_t i = 0; i < n_dependent; ++i)\n    {   json += to_string( graph_obj.dependent_vec_get(i) );\n        if( i + 1 < n_dependent )\n            json += \", \";\n    }\n    json += \" ] ]\\n\";\n    //\n    // output: ending '}' for this graph\n    json += \"}\\n\";\n    // ----------------------------------------------------------------------\n    // Convert the single quote to double quote\n    for(size_t i = 0; i < json.size(); ++i)\n        if( json[i] == '\\'' ) json[i] = '\"';\n    //\n    return;\n}\n"
  },
  {
    "path": "cppad_lib/link_dll_lib.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-23 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/utility/to_string.hpp>\n# include <cppad/utility/link_dll_lib.hpp>\n\n# ifndef _WIN32\n//  dlopen, dlsym, dlerror, dlclose, RTLD_LAZY\n# include <dlfcn.h>\n# else\n//  LoadLibrary, GetProcAddress, FreeLibrary, GetLastError, RTLD_LAZY\n# ifndef NOMINMAX\n# define NOMINMAX\n# endif\n# include <windows.h>\n# define RTLD_LAZY 0\n# endif\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n\n# ifdef _WIN32\n//\n//  dlopen\nvoid* link_dll_lib::dlopen(const char *filename, int flag)\n{   HINSTANCE hinstance = LoadLibraryA(filename);\n    return reinterpret_cast<void*>( hinstance );\n}\n// dlsym\nvoid* link_dll_lib::dlsym(void* handle, const char* symbol)\n{   HINSTANCE hinstance = reinterpret_cast<HINSTANCE>( handle );\n    FARPROC   farproc   = GetProcAddress(hinstance, symbol);\n    return reinterpret_cast<void*>( farproc );\n}\n// dlclose\nint link_dll_lib::dlclose(void* handle)\n{   HINSTANCE hinstance = reinterpret_cast<HINSTANCE>( handle );\n    int result          = FreeLibrary(hinstance);\n    return result;\n}\n// dlerror\nconst char* link_dll_lib::dlerror(void)\n{   // should have a different result for each thread\n    static char result[100];\n    //\n    DWORD dw        = GetLastError();\n    std::string str = CppAD::to_string(dw);\n    str             = \"Microsoft GetLastError() = \" + str;\n    size_t  i = 0;\n    while(i < 99 && i < str.size())\n        result[i] = str[i];\n    result[i] = '\\0';\n    //\n    return result;\n}\n# endif\n//\nlink_dll_lib::link_dll_lib(const std::string& dll_file, std::string& err_msg)\n{   handle_ = dlopen(dll_file.c_str(), RTLD_LAZY);\n    if( handle_ != nullptr )\n        err_msg = \"\";\n    else\n    {   const char *err_str = dlerror();\n        err_msg = \"Error opening dll_file =\" + dll_file;\n        if( err_str != nullptr )\n        {   err_msg += \"\\n\";\n            err_msg += err_str;\n        }\n    }\n    ctor_err_msg_ = err_msg;\n}\nlink_dll_lib::~link_dll_lib(void)\n{   if( handle_ != nullptr )\n        dlclose(handle_);\n}\nvoid* link_dll_lib::operator()\n(const std::string& function_name, std::string& err_msg) const\n// END_OPERATOR\n{   if( handle_ == nullptr )\n    {   err_msg = ctor_err_msg_;\n        return nullptr;\n    }\n    void* fun_ptr = dlsym(handle_, function_name.c_str());\n    if( fun_ptr == nullptr )\n        err_msg = \"Error finding function_name = \" + function_name;\n    else\n        err_msg = \"\";\n    return fun_ptr;\n}\n\n} // END_CPPAD_NAMESPACE\n"
  },
  {
    "path": "cppad_lib/temp_file.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin temp_file dev}\n{xrst_spell\n    mkstemp\n}\n\nCreate a New Empty Temporary File\n#################################\n\nSyntax\n******\n| *file_name* = ``temp_file`` ()\n\nfile_name\n*********\nIs the name of a new temporary file.\nThis file did not exist when ``temp_file`` was called.\nIt has been created and is empty upon return.\n\nEmpty\n=====\nThis routine failed if the return value *file_name* is empty.\n\nThread Safe\n***********\nThis routine is thread safe when C++17 and ``mkstemp`` are available\nto CppAD.\n\n{xrst_end temp_file}\n*/\n# include <vector>\n# include <stdio.h>\n# include <cppad/configure.hpp>\n# include <cppad/local/temp_file.hpp>\n\n# if CPPAD_HAS_MKSTEMP && CPPAD_USE_CPLUSPLUS_2017\n# include <filesystem>\n# else\n# include <stdio.h>\n# endif\n\n# if _MSC_VER\n# include <io.h>\n# else\n# include <unistd.h>\n# endif\n\n# ifdef _WIN32\n# define DIR_SEP '\\\\'\n# else\n# define DIR_SEP '/'\n# endif\n\nnamespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE\n\nstd::string temp_file(void)\n# if CPPAD_HAS_MKSTEMP && CPPAD_USE_CPLUSPLUS_2017\n{   // path\n    using std::filesystem::path;\n    //\n    // tmp_dir_path\n    path tmp_dir_path = std::filesystem::temp_directory_path();\n    //\n    // tmp_dir_str\n    std::string tmp_dir_str = tmp_dir_path.string();\n    if( tmp_dir_str.back() != DIR_SEP )\n        tmp_dir_str += DIR_SEP;\n    //\n    // pattern_str\n    std::string pattern_str = tmp_dir_str;\n    pattern_str            += \"fileXXXXXX\";\n    //\n    // pattern_vec\n    std::vector<char> pattern_vec( pattern_str.size() + 1 );\n    for(size_t i = 0; i < pattern_str.size(); ++i)\n        pattern_vec[i] = pattern_str[i];\n    pattern_vec[ pattern_str.size() ] = '\\0';\n    //\n    // fd, pattrern_vec\n    int fd = mkstemp( pattern_vec.data() );\n    if( fd < 0 )\n        return \"\";\n    close(fd);\n    //\n    // file_name\n    std::string file_name = pattern_vec.data();\n    return file_name;\n}\n# else // CPPAD_HAS_MKSTEMP && CPPAD_USE_CPLUSPLUS_2017\n{\n# if CPPAD_HAS_TMPNAM_S\n    char c_str[L_tmpnam_s];\n    tmpnam_s(c_str, L_tmpnam_s );\n# else\n    char c_str[L_tmpnam];\n    tmpnam(c_str);\n# endif\n# ifdef __MINGW32__\n    // https://stackoverflow.com/questions/38868858/\n    // fopen-of-file-name-created-by-tmpnam-fails-on-mingw\n    std::string file_name = c_str + 1;\n# else\n    std::string file_name = c_str;\n# endif\n    FILE* fp = fopen(file_name.c_str(), \"r\");\n    if( fp != NULL )\n        return \"\";\n    fp = fopen(file_name.c_str(), \"w\");\n    if( fp == NULL )\n        return \"\";\n    fclose(fp);\n    return file_name;\n}\n# endif // CPPAD_HAS_MKSTEMP && CPPAD_USE_CPLUSPLUS_2017\n\n} } // END_CPPAD_LOCAL_NAMESPACE\n"
  },
  {
    "path": "epl-2.0.txt",
    "content": "Eclipse Public License - v 2.0\n\n   THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE\n   PUBLIC LICENSE (\"AGREEMENT\"). ANY USE, REPRODUCTION OR DISTRIBUTION\n   OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.\n\n1. DEFINITIONS\n\n\"Contribution\" means:\n\n  a) in the case of the initial Contributor, the initial content\n     Distributed under this Agreement, and\n\n  b) in the case of each subsequent Contributor:\n     i) changes to the Program, and\n     ii) additions to the Program;\n  where such changes and/or additions to the Program originate from\n  and are Distributed by that particular Contributor. A Contribution\n  \"originates\" from a Contributor if it was added to the Program by\n  such Contributor itself or anyone acting on such Contributor's behalf.\n  Contributions do not include changes or additions to the Program that\n  are not Modified Works.\n\n\"Contributor\" means any person or entity that Distributes the Program.\n\n\"Licensed Patents\" mean patent claims licensable by a Contributor which\nare necessarily infringed by the use or sale of its Contribution alone\nor when combined with the Program.\n\n\"Program\" means the Contributions Distributed in accordance with this\nAgreement.\n\n\"Recipient\" means anyone who receives the Program under this Agreement\nor any Secondary License (as applicable), including Contributors.\n\n\"Derivative Works\" shall mean any work, whether in Source Code or other\nform, that is based on (or derived from) the Program and for which the\neditorial revisions, annotations, elaborations, or other modifications\nrepresent, as a whole, an original work of authorship.\n\n\"Modified Works\" shall mean any work in Source Code or other form that\nresults from an addition to, deletion from, or modification of the\ncontents of the Program, including, for purposes of clarity any new file\nin Source Code form that contains any contents of the Program. Modified\nWorks shall not include works that contain only declarations,\ninterfaces, types, classes, structures, or files of the Program solely\nin each case in order to link to, bind by name, or subclass the Program\nor Modified Works thereof.\n\n\"Distribute\" means the acts of a) distributing or b) making available\nin any manner that enables the transfer of a copy.\n\n\"Source Code\" means the form of a Program preferred for making\nmodifications, including but not limited to software source code,\ndocumentation source, and configuration files.\n\n\"Secondary License\" means either the GNU General Public License,\nVersion 2.0, or any later versions of that license, including any\nexceptions or additional permissions as identified by the initial\nContributor.\n\n2. GRANT OF RIGHTS\n\n  a) Subject to the terms of this Agreement, each Contributor hereby\n  grants Recipient a non-exclusive, worldwide, royalty-free copyright\n  license to reproduce, prepare Derivative Works of, publicly display,\n  publicly perform, Distribute and sublicense the Contribution of such\n  Contributor, if any, and such Derivative Works.\n\n  b) Subject to the terms of this Agreement, each Contributor hereby\n  grants Recipient a non-exclusive, worldwide, royalty-free patent\n  license under Licensed Patents to make, use, sell, offer to sell,\n  import and otherwise transfer the Contribution of such Contributor,\n  if any, in Source Code or other form. This patent license shall\n  apply to the combination of the Contribution and the Program if, at\n  the time the Contribution is added by the Contributor, such addition\n  of the Contribution causes such combination to be covered by the\n  Licensed Patents. The patent license shall not apply to any other\n  combinations which include the Contribution. No hardware per se is\n  licensed hereunder.\n\n  c) Recipient understands that although each Contributor grants the\n  licenses to its Contributions set forth herein, no assurances are\n  provided by any Contributor that the Program does not infringe the\n  patent or other intellectual property rights of any other entity.\n  Each Contributor disclaims any liability to Recipient for claims\n  brought by any other entity based on infringement of intellectual\n  property rights or otherwise. As a condition to exercising the\n  rights and licenses granted hereunder, each Recipient hereby\n  assumes sole responsibility to secure any other intellectual\n  property rights needed, if any. For example, if a third party\n  patent license is required to allow Recipient to Distribute the\n  Program, it is Recipient's responsibility to acquire that license\n  before distributing the Program.\n\n  d) Each Contributor represents that to its knowledge it has\n  sufficient copyright rights in its Contribution, if any, to grant\n  the copyright license set forth in this Agreement.\n\n  e) Notwithstanding the terms of any Secondary License, no\n  Contributor makes additional grants to any Recipient (other than\n  those set forth in this Agreement) as a result of such Recipient's\n  receipt of the Program under the terms of a Secondary License\n  (if permitted under the terms of Section 3).\n\n3. REQUIREMENTS\n\n3.1 If a Contributor Distributes the Program in any form, then:\n\n  a) the Program must also be made available as Source Code, in\n  accordance with section 3.2, and the Contributor must accompany\n  the Program with a statement that the Source Code for the Program\n  is available under this Agreement, and informs Recipients how to\n  obtain it in a reasonable manner on or through a medium customarily\n  used for software exchange; and\n\n  b) the Contributor may Distribute the Program under a license\n  different than this Agreement, provided that such license:\n     i) effectively disclaims on behalf of all other Contributors all\n     warranties and conditions, express and implied, including\n     warranties or conditions of title and non-infringement, and\n     implied warranties or conditions of merchantability and fitness\n     for a particular purpose;\n\n     ii) effectively excludes on behalf of all other Contributors all\n     liability for damages, including direct, indirect, special,\n     incidental and consequential damages, such as lost profits;\n\n     iii) does not attempt to limit or alter the recipients' rights\n     in the Source Code under section 3.2; and\n\n     iv) requires any subsequent distribution of the Program by any\n     party to be under a license that satisfies the requirements\n     of this section 3.\n\n3.2 When the Program is Distributed as Source Code:\n\n  a) it must be made available under this Agreement, or if the\n  Program (i) is combined with other material in a separate file or\n  files made available under a Secondary License, and (ii) the initial\n  Contributor attached to the Source Code the notice described in\n  Exhibit A of this Agreement, then the Program may be made available\n  under the terms of such Secondary Licenses, and\n\n  b) a copy of this Agreement must be included with each copy of\n  the Program.\n\n3.3 Contributors may not remove or alter any copyright, patent,\ntrademark, attribution notices, disclaimers of warranty, or limitations\nof liability (\"notices\") contained within the Program from any copy of\nthe Program which they Distribute, provided that Contributors may add\ntheir own appropriate notices.\n\n4. COMMERCIAL DISTRIBUTION\n\nCommercial distributors of software may accept certain responsibilities\nwith respect to end users, business partners and the like. While this\nlicense is intended to facilitate the commercial use of the Program,\nthe Contributor who includes the Program in a commercial product\noffering should do so in a manner which does not create potential\nliability for other Contributors. Therefore, if a Contributor includes\nthe Program in a commercial product offering, such Contributor\n(\"Commercial Contributor\") hereby agrees to defend and indemnify every\nother Contributor (\"Indemnified Contributor\") against any losses,\ndamages and costs (collectively \"Losses\") arising from claims, lawsuits\nand other legal actions brought by a third party against the Indemnified\nContributor to the extent caused by the acts or omissions of such\nCommercial Contributor in connection with its distribution of the Program\nin a commercial product offering. The obligations in this section do not\napply to any claims or Losses relating to any actual or alleged\nintellectual property infringement. In order to qualify, an Indemnified\nContributor must: a) promptly notify the Commercial Contributor in\nwriting of such claim, and b) allow the Commercial Contributor to control,\nand cooperate with the Commercial Contributor in, the defense and any\nrelated settlement negotiations. The Indemnified Contributor may\nparticipate in any such claim at its own expense.\n\nFor example, a Contributor might include the Program in a commercial\nproduct offering, Product X. That Contributor is then a Commercial\nContributor. If that Commercial Contributor then makes performance\nclaims, or offers warranties related to Product X, those performance\nclaims and warranties are such Commercial Contributor's responsibility\nalone. Under this section, the Commercial Contributor would have to\ndefend claims against the other Contributors related to those performance\nclaims and warranties, and if a court requires any other Contributor to\npay any damages as a result, the Commercial Contributor must pay\nthose damages.\n\n5. NO WARRANTY\n\nEXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT\nPERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN \"AS IS\"\nBASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR\nIMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF\nTITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR\nPURPOSE. Each Recipient is solely responsible for determining the\nappropriateness of using and distributing the Program and assumes all\nrisks associated with its exercise of rights under this Agreement,\nincluding but not limited to the risks and costs of program errors,\ncompliance with applicable laws, damage to or loss of data, programs\nor equipment, and unavailability or interruption of operations.\n\n6. DISCLAIMER OF LIABILITY\n\nEXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT\nPERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS\nSHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\nEXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST\nPROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\nCONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\nARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE\nEXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGES.\n\n7. GENERAL\n\nIf any provision of this Agreement is invalid or unenforceable under\napplicable law, it shall not affect the validity or enforceability of\nthe remainder of the terms of this Agreement, and without further\naction by the parties hereto, such provision shall be reformed to the\nminimum extent necessary to make such provision valid and enforceable.\n\nIf Recipient institutes patent litigation against any entity\n(including a cross-claim or counterclaim in a lawsuit) alleging that the\nProgram itself (excluding combinations of the Program with other software\nor hardware) infringes such Recipient's patent(s), then such Recipient's\nrights granted under Section 2(b) shall terminate as of the date such\nlitigation is filed.\n\nAll Recipient's rights under this Agreement shall terminate if it\nfails to comply with any of the material terms or conditions of this\nAgreement and does not cure such failure in a reasonable period of\ntime after becoming aware of such noncompliance. If all Recipient's\nrights under this Agreement terminate, Recipient agrees to cease use\nand distribution of the Program as soon as reasonably practicable.\nHowever, Recipient's obligations under this Agreement and any licenses\ngranted by Recipient relating to the Program shall continue and survive.\n\nEveryone is permitted to copy and distribute copies of this Agreement,\nbut in order to avoid inconsistency the Agreement is copyrighted and\nmay only be modified in the following manner. The Agreement Steward\nreserves the right to publish new versions (including revisions) of\nthis Agreement from time to time. No one other than the Agreement\nSteward has the right to modify this Agreement. The Eclipse Foundation\nis the initial Agreement Steward. The Eclipse Foundation may assign the\nresponsibility to serve as the Agreement Steward to a suitable separate\nentity. Each new version of the Agreement will be given a distinguishing\nversion number. The Program (including Contributions) may always be\nDistributed subject to the version of the Agreement under which it was\nreceived. In addition, after a new version of the Agreement is published,\nContributor may elect to Distribute the Program (including its\nContributions) under the new version.\n\nExcept as expressly stated in Sections 2(a) and 2(b) above, Recipient\nreceives no rights or licenses to the intellectual property of any\nContributor under this Agreement, whether expressly, by implication,\nestoppel or otherwise. All rights in the Program not expressly granted\nunder this Agreement are reserved. Nothing in this Agreement is intended\nto be enforceable by any entity that is not a Contributor or Recipient.\nNo third-party beneficiary rights are created under this Agreement.\n\nExhibit A - Form of Secondary Licenses Notice\n\n\"This Source Code may also be made available under the following\nSecondary Licenses when the conditions for such availability set forth\nin the Eclipse Public License, v. 2.0 are satisfied: {name license(s),\nversion(s), and exceptions or additional permissions here}.\"\n\n  Simply including a copy of this Agreement, including this Exhibit A\n  is not sufficient to license the Source Code under Secondary Licenses.\n\n  If it is not possible or desirable to put the notice in a particular\n  file, then You may include the notice in a location (such as a LICENSE\n  file in a relevant directory) where a recipient would be likely to\n  look for such a notice.\n\n  You may add additional accurate notices of copyright ownership."
  },
  {
    "path": "example/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-25 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# Build the example directory tests\n# Inherit environment from ../CMakeList.txt\n\n# initialize check_example_depends\nSET(check_example_depends \"\")\n#\n# BEGIN_SORT_THIS_LINE_PLUS_1\nADD_SUBDIRECTORY(abs_normal)\nADD_SUBDIRECTORY(atomic_four)\nADD_SUBDIRECTORY(atomic_three)\nADD_SUBDIRECTORY(atomic_two)\nADD_SUBDIRECTORY(chkpoint_two)\nADD_SUBDIRECTORY(compare_change)\nADD_SUBDIRECTORY(general)\nADD_SUBDIRECTORY(get_started)\nADD_SUBDIRECTORY(graph)\nADD_SUBDIRECTORY(json)\nADD_SUBDIRECTORY(multi_thread)\nADD_SUBDIRECTORY(optimize)\nADD_SUBDIRECTORY(print_for)\nADD_SUBDIRECTORY(sparse)\nADD_SUBDIRECTORY(utility)\nADD_SUBDIRECTORY(valvector)\n# END_SORT_THIS_LINE_MINUS_1\n#\n# cppad_code_gen examples\nIF( cppad_has_cppadcg )\n    ADD_SUBDIRECTORY(cppad_code_gen)\nENDIF( cppad_has_cppadcg )\n#\n# ipopt_solve examples\nIF( cppad_has_ipopt)\n    ADD_SUBDIRECTORY(ipopt_solve)\nENDIF( cppad_has_ipopt)\n#\n# jit examples\nIF( NOT cppad_link_flags_has_m32 )\n    ADD_SUBDIRECTORY(jit)\nENDIF( )\n\n\n\n# Add the check_example target\nADD_CUSTOM_TARGET(check_example \"\" DEPENDS ${check_example_depends})\nMESSAGE(STATUS \"make check_example: available\")\n\n# Change check depends in parent environment\nadd_to_list(check_depends check_example)\nSET(check_depends \"${check_depends}\" PARENT_SCOPE)\n"
  },
  {
    "path": "example/abs_normal/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# Build the example/print_for directory tests\n#\n# BEGIN_SORT_THIS_LINE_PLUS_2\nSET(source_list\n    abs_eval.cpp\n    abs_min_linear.cpp\n    abs_min_quad.cpp\n    abs_normal.cpp\n    get_started.cpp\n    lp_box.cpp\n    min_nso_linear.cpp\n    min_nso_quad.cpp\n    qp_box.cpp\n    qp_interior.cpp\n    simplex_method.cpp\n)\n# END_SORT_THIS_LINE_MINUS_2\n\n#\nset_compile_flags( example_abs_normal \"${cppad_debug_which}\" \"${source_list}\" )\n#\nADD_EXECUTABLE(example_abs_normal EXCLUDE_FROM_ALL ${source_list})\n#\n# List of libraries to be linked into the specified target\nTARGET_LINK_LIBRARIES(example_abs_normal\n    ${cppad_lib}\n    ${colpack_libs}\n)\n#\n# check_example_abs_normal\nadd_check_executable(check_example abs_normal)\n"
  },
  {
    "path": "example/abs_normal/abs_eval.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin abs_eval.cpp}\n\nabs_eval: Example and Test\n##########################\n\nPurpose\n*******\nThe function\n:math:`f : \\B{R}^3 \\rightarrow \\B{R}` defined by\n\n.. math::\n\n    f( x_0, x_1, x_2  ) = | x_0 + x_1 | + | x_1 + x_2 |\n\nis affine, except for its absolute value terms.\nFor this case, the abs_normal approximation should be equal\nto the function itself.\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end abs_eval.cpp}\n-------------------------------------------------------------------------------\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n# include \"abs_eval.hpp\"\n\nnamespace {\n    CPPAD_TESTVECTOR(double) join(\n        const CPPAD_TESTVECTOR(double)& x ,\n        const CPPAD_TESTVECTOR(double)& u )\n    {   size_t n = x.size();\n        size_t s = u.size();\n        CPPAD_TESTVECTOR(double) xu(n + s);\n        for(size_t j = 0; j < n; j++)\n            xu[j] = x[j];\n        for(size_t j = 0; j < s; j++)\n            xu[n + j] = u[j];\n        return xu;\n    }\n}\nbool abs_eval(void)\n{   bool ok = true;\n    //\n    using CppAD::AD;\n    using CppAD::ADFun;\n    //\n    typedef CPPAD_TESTVECTOR(double)       d_vector;\n    typedef CPPAD_TESTVECTOR( AD<double> ) ad_vector;\n    //\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    //\n    size_t n = 3; // size of x\n    size_t m = 1; // size of y\n    size_t s = 2; // number of absolute value terms\n    //\n    // record the function f(x)\n    ad_vector ad_x(n), ad_y(m);\n    for(size_t j = 0; j < n; j++)\n        ad_x[j] = double(j + 1);\n    Independent( ad_x );\n    // for this example, we ensure first absolute value is | x_0 + x_1 |\n    AD<double> ad_0 = abs( ad_x[0] + ad_x[1] );\n    // and second absolute value is | x_1 + x_2 |\n    AD<double> ad_1 = abs( ad_x[1] + ad_x[2] );\n    ad_y[0]         = ad_0 + ad_1;\n    ADFun<double> f(ad_x, ad_y);\n\n    // create its abs_normal representation in g, a\n    ADFun<double> g, a;\n    f.abs_normal_fun(g, a);\n\n    // check dimension of domain and range space for g\n    ok &= g.Domain() == n + s;\n    ok &= g.Range()  == m + s;\n\n    // check dimension of domain and range space for a\n    ok &= a.Domain() == n;\n    ok &= a.Range()  == s;\n\n    // --------------------------------------------------------------------\n    // Choose a point x_hat\n    d_vector x_hat(n);\n    for(size_t j = 0; j < n; j++)\n        x_hat[j] = double(j - 1);\n\n    // value of a_hat = a(x_hat)\n    d_vector a_hat = a.Forward(0, x_hat);\n\n    // (x_hat, a_hat)\n    d_vector xu_hat = join(x_hat, a_hat);\n\n    // value of g[ x_hat, a_hat ]\n    d_vector g_hat = g.Forward(0, xu_hat);\n\n    // Jacobian of g[ x_hat, a_hat ]\n    d_vector g_jac = g.Jacobian(xu_hat);\n\n    // value of delta_x\n    d_vector delta_x(n);\n    delta_x[0] =  1.0;\n    delta_x[1] = -2.0;\n    delta_x[2] = +2.0;\n\n    // value of x\n    d_vector x(n);\n    for(size_t j = 0; j < n; j++)\n        x[j] = x_hat[j] + delta_x[j];\n\n    // value of f(x)\n    d_vector y = f.Forward(0, x);\n\n    // value of g_tilde\n    d_vector g_tilde = CppAD::abs_eval(n, m, s, g_hat, g_jac, delta_x);\n\n    // should be equal because f is affine, except for abs terms\n    ok &= CppAD::NearEqual(y[0], g_tilde[0], eps99, eps99);\n\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/abs_normal/abs_eval.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_ABS_NORMAL_ABS_EVAL_HPP\n# define CPPAD_EXAMPLE_ABS_NORMAL_ABS_EVAL_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin abs_eval}\nabs_normal: Evaluate First Order Approximation\n##############################################\n\nSyntax\n******\n| *g_tilde* = ``abs_eval`` ( *n* , *m* , *s* , *g_hat* , *g_jac* , *delta_x* )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN PROTOTYPE\n    // END PROTOTYPE\n}\n\nSource\n******\nThis following is a link to the source code for this example:\n:ref:`abs_eval.hpp-name` .\n\nPurpose\n*******\nGiven a current that abs-normal representation at a point\n:math:`\\hat{x} \\in \\B{R}^n`,\nand a :math:`\\Delta x \\in \\B{R}^n`,\nthis routine evaluates the abs-normal\n:ref:`approximation for f(x)<abs_normal_fun@Abs-normal Approximation@Approximating f(x)>`\nwhere :math:`x = \\hat{x} + \\Delta x`.\n\nVector\n******\nThe type *Vector* is a\nsimple vector with elements of type ``double`` .\n\nf\n*\nWe use the notation *f* for the original function; see\n:ref:`abs_normal_fun@f` .\n\nn\n*\nThis is the dimension of the domain space for *f* ; see\n:ref:`abs_normal_fun@f@n` .\n\nm\n*\nThis is the dimension of the range space for *f* ; see\n:ref:`abs_normal_fun@f@m` .\n\ns\n*\nThis is the number of absolute value terms in *f* ; see\n\ng\n*\nWe use the notation *g* for the abs-normal representation of *f* ;\nsee :ref:`abs_normal_fun@g` .\n\ng_hat\n*****\nThis vector has size *m* + *s* and is the value of\n*g* ( *x* , *u* ) at :math:`x = \\hat{x}` and :math:`u = a( \\hat{x} )`.\n\ng_jac\n*****\nThis vector has size ( *m* + *s* ) * ( *n* + *s* ) and is the Jacobian of\n:math:`g(x, u)` at :math:`x = \\hat{x}` and :math:`u = a( \\hat{x} )`.\n\ndelta_x\n*******\nThis vector has size *n* and is the difference\n:math:`\\Delta x = x - \\hat{x}`,\nwhere :math:`x` is the point that we are approximating :math:`f(x)`.\n\ng_tilde\n*******\nThis vector has size *m* + *s* and is a the\nfirst order approximation for\n:ref:`abs_normal_fun@g`\nthat corresponds to the point\n:math:`x = \\hat{x} + \\Delta x` and :math:`u = a(x)`.\n{xrst_toc_hidden\n    example/abs_normal/abs_eval.cpp\n    example/abs_normal/abs_eval.xrst\n}\nExample\n*******\nThe file :ref:`abs_eval.cpp-name` contains an example and test of\n``abs_eval`` .\n\n{xrst_end abs_eval}\n-----------------------------------------------------------------------------\n*/\n\n// BEGIN C++\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n// BEGIN PROTOTYPE\ntemplate <class Vector>\nVector abs_eval(\n    size_t        n       ,\n    size_t        m       ,\n    size_t        s       ,\n    const Vector& g_hat   ,\n    const Vector& g_jac   ,\n    const Vector& delta_x )\n// END PROTOTYPE\n{   using std::fabs;\n    //\n    CPPAD_ASSERT_KNOWN(\n        size_t(delta_x.size()) == n,\n        \"abs_eval: size of delta_x not equal to n\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t(g_hat.size()) == m + s,\n        \"abs_eval: size of g_hat not equal to m + s\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t(g_jac.size()) == (m + s) * (n + s),\n        \"abs_eval: size of g_jac not equal to (m + s)*(n + s)\"\n    );\n# ifndef NDEBUG\n    // Check that partial_u z(x, u) is strictly lower triangular\n    for(size_t i = 0; i < s; i++)\n    {   for(size_t j = i; j < s; j++)\n        {   // index in g_jac of partial of z_i w.r.t u_j\n            // (note that g_jac has n + s elements in each row)\n            size_t index = (m + i) * (n + s) + (n + j);\n            CPPAD_ASSERT_KNOWN(\n                g_jac[index] == 0.0,\n                \"abs_eval: partial z_i w.r.t u_j non-zero for i <= j\"\n            );\n        }\n    }\n# endif\n    // return value\n    Vector g_tilde(m + s);\n    //\n    // compute z_tilde, the last s components of g_tilde\n    for(size_t i = 0; i < s; i++)\n    {   // start at z_hat_i\n        g_tilde[m + i] = g_hat[m + i];\n        // contribution for change x\n        for(size_t j = 0; j < n; j++)\n        {   // index in g_jac of partial of z_i w.r.t x_j\n            size_t index = (m + i) * (n + s) + j;\n            // add contribution for delta_x_j to z_tilde_i\n            g_tilde[m + i] += g_jac[index] * delta_x[j];\n        }\n        // contribution for change in u_j for j < i\n        for(size_t j = 0; j < i; j++)\n        {   // approixmation for change in absolute value\n            double delta_a_j = fabs(g_tilde[m + j]) - fabs(g_hat[m + j]);\n            // index in g_jac of partial of z_i w.r.t u_j\n            size_t index = (m + i) * (n + s) + n + j;\n            // add contribution for delta_a_j to s_tilde_i\n            g_tilde[m + i] += g_jac[index] * delta_a_j;\n        }\n    }\n    //\n    // compute y_tilde, the first m components of g_tilde\n    for(size_t i = 0; i < m; i++)\n    {   // start at y_hat_i\n        g_tilde[i] = g_hat[i];\n        // contribution for change x\n        for(size_t j = 0; j < n; j++)\n        {   // index in g_jac of partial of y_i w.r.t x_j\n            size_t index = i * (n + s) + j;\n            // add contribution for delta_x_j to y_tilde_i\n            g_tilde[i] += g_jac[index] * delta_x[j];\n        }\n        // contribution for change in u_j\n        for(size_t j = 0; j < s; j++)\n        {   // approximation for change in absolute value\n            double delta_a_j = fabs(g_tilde[m + j]) - fabs(g_hat[m + j]);\n            // index in g_jac of partial of y_i w.r.t u_j\n            size_t index = i * (n + s) + n + j;\n            // add contribution for delta_a_j to s_tilde_i\n            g_tilde[i] += g_jac[index] * delta_a_j;\n        }\n    }\n    return g_tilde;\n}\n} // END_CPPAD_NAMESPACE\n// END C++\n\n# endif\n"
  },
  {
    "path": "example/abs_normal/abs_eval.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin abs_eval.hpp}\n\nabs_eval Source Code\n####################\n\n{xrst_literal\n    example/abs_normal/abs_eval.hpp\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end abs_eval.hpp}\n"
  },
  {
    "path": "example/abs_normal/abs_min_linear.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin abs_min_linear.cpp}\n\nabs_min_linear: Example and Test\n################################\n\nPurpose\n*******\nThe function\n:math:`f : \\B{R}^3 \\rightarrow \\B{R}` defined by\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    f( x_0, x_1  )\n    & = &\n    | d_0 - x_0 | + | d_1 - x_0 | + | d_2 - x_0 |\n    \\\\\n    & + &\n    | d_3 - x_1 | + | d_4 - x_1 | + | d_5 - x_1 |\n    \\\\\n    \\end{eqnarray}\n\nis affine, except for its absolute value terms.\nFor this case, the abs_normal approximation should be equal\nto the function itself.\nIn addition, the function is convex and\n:ref:`abs_min_linear-name` should find its global minimizer.\nThe minimizer of this function is\n:math:`x_0 = \\R{median}( d_0, d_1, d_2 )`\nand\n:math:`x_1 = \\R{median}( d_3, d_4, d_5 )`\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end abs_min_linear.cpp}\n-------------------------------------------------------------------------------\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n# include \"abs_min_linear.hpp\"\n\nnamespace {\n    CPPAD_TESTVECTOR(double) join(\n        const CPPAD_TESTVECTOR(double)& x ,\n        const CPPAD_TESTVECTOR(double)& u )\n    {   size_t n = x.size();\n        size_t s = u.size();\n        CPPAD_TESTVECTOR(double) xu(n + s);\n        for(size_t j = 0; j < n; j++)\n            xu[j] = x[j];\n        for(size_t j = 0; j < s; j++)\n            xu[n + j] = u[j];\n        return xu;\n    }\n}\nbool abs_min_linear(void)\n{   bool ok = true;\n    //\n    using CppAD::AD;\n    using CppAD::ADFun;\n    //\n    typedef CPPAD_TESTVECTOR(size_t)       s_vector;\n    typedef CPPAD_TESTVECTOR(double)       d_vector;\n    typedef CPPAD_TESTVECTOR( AD<double> ) ad_vector;\n    //\n    size_t dpx   = 3;          // number of data points per x variable\n    size_t level = 0;          // level of tracing\n    size_t n     = 2;          // size of x\n    size_t m     = 1;          // size of y\n    size_t s     = dpx * n;    // number of data points and absolute values\n    // data points\n    d_vector  data(s);\n    for(size_t i = 0; i < s; i++)\n        data[i] = double(s - i) + 5.0 - double(i % 2) / 2.0;\n    //\n    // record the function f(x)\n    ad_vector ad_x(n), ad_y(m);\n    for(size_t j = 0; j < n; j++)\n        ad_x[j] = double(j + 1);\n    Independent( ad_x );\n    AD<double> sum = 0.0;\n    for(size_t j = 0; j < n; j++)\n        for(size_t k = 0; k < dpx; k++)\n            sum += abs( data[j * dpx + k] - ad_x[j] );\n    ad_y[0] = sum;\n    ADFun<double> f(ad_x, ad_y);\n\n    // create its abs_normal representation in g, a\n    ADFun<double> g, a;\n    f.abs_normal_fun(g, a);\n\n    // check dimension of domain and range space for g\n    ok &= g.Domain() == n + s;\n    ok &= g.Range()  == m + s;\n\n    // check dimension of domain and range space for a\n    ok &= a.Domain() == n;\n    ok &= a.Range()  == s;\n\n    // --------------------------------------------------------------------\n    // Choose a point x_hat\n    d_vector x_hat(n);\n    for(size_t j = 0; j < n; j++)\n        x_hat[j] = double(0.0);\n\n    // value of a_hat = a(x_hat)\n    d_vector a_hat = a.Forward(0, x_hat);\n\n    // (x_hat, a_hat)\n    d_vector xu_hat = join(x_hat, a_hat);\n\n    // value of g[ x_hat, a_hat ]\n    d_vector g_hat = g.Forward(0, xu_hat);\n\n    // Jacobian of g[ x_hat, a_hat ]\n    d_vector g_jac = g.Jacobian(xu_hat);\n\n    // trust region bound (make large enough to include solutuion)\n    d_vector bound(n);\n    for(size_t j = 0; j < n; j++)\n        bound[j] = 10.0;\n\n    // convergence criteria\n    d_vector epsilon(2);\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    epsilon[0]   = eps99;\n    epsilon[1]   = eps99;\n\n    // maximum number of iterations\n    s_vector maxitr(2);\n    maxitr[0] = 10; // maximum number of abs_min_linear iterations\n    maxitr[1] = 35; // maximum number of qp_interior iterations\n\n    // minimize the approximation for f, which is equal to f because\n    // f is affine, except for absolute value terms\n    d_vector delta_x(n);\n    ok &= CppAD::abs_min_linear(\n        level, n, m, s, g_hat, g_jac, bound, epsilon, maxitr, delta_x\n    );\n\n    // number of data points per variable is odd\n    ok &= dpx % 2 == 1;\n\n    // check that the solution is the median of the corresponding data`\n    for(size_t j = 0; j < n; j++)\n    {   // data[j * dpx + 0] , ... , data[j * dpx + dpx - 1] corresponds to x[j]\n        // the median of this data has index j * dpx + dpx / 2\n        size_t j_median = j * dpx + (dpx / 2);\n        //\n        ok &= CppAD::NearEqual( delta_x[j], data[j_median], eps99, eps99 );\n    }\n\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/abs_normal/abs_min_linear.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_ABS_NORMAL_ABS_MIN_LINEAR_HPP\n# define CPPAD_EXAMPLE_ABS_NORMAL_ABS_MIN_LINEAR_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin abs_min_linear}\n{xrst_spell\n    dbl\n    lll\n    maxitr\n}\nabs_normal: Minimize a Linear Abs-normal Approximation\n######################################################\n\nSyntax\n******\n| *ok* = ``abs_min_linear`` (\n| |tab| *level* , *n* , *m* , *s* ,\n| |tab| *g_hat* , *g_jac* , *bound* , *epsilon* , *maxitr* , *delta_x*\n| )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN PROTOTYPE\n    // END PROTOTYPE\n}\n\nSource\n******\nThis following is a link to the source code for this example:\n:ref:`abs_min_linear.hpp-name` .\n\nPurpose\n*******\nWe are given a point :math:`\\hat{x} \\in \\B{R}^n` and\nuse the notation :math:`\\tilde{f} (x)` for the abs-normal\n:ref:`approximation for f(x)<abs_normal_fun@Abs-normal Approximation@Approximating f(x)>`\nnear :math:`\\hat{x}`.\nWe are also given a vector :math:`b \\in \\B{R}_+^n`.\nThis routine solves the problem\n\n.. math::\n\n    \\begin{array}{lll}\n    \\R{minimize} & \\tilde{f}(x) & \\R{w.r.t} \\; x \\in \\B{R}^n\n    \\\\\n    \\R{subject \\; to} & | x_j - \\hat{x}_j | \\leq b_j & j = 0 , \\ldots , n-1\n    \\end{array}\n\nDblVector\n*********\nis a :ref:`SimpleVector-name` class with elements of type ``double`` .\n\nSizeVector\n**********\nis a :ref:`SimpleVector-name` class with elements of type ``size_t`` .\n\nf\n*\nWe use the notation *f* for the original function; see\n:ref:`abs_normal_fun@f` .\n\nlevel\n*****\nThis value is less that or equal 4.\nIf *level*  == 0 ,\nno tracing of the optimization is printed.\nIf *level*  >= 1 ,\na trace of each iteration of ``abs_min_linear`` is printed.\nIf *level*  >= 2 ,\na trace of the :ref:`lp_box-name` sub-problem is printed.\nIf *level*  >= 3 ,\na trace of the objective and primal variables :math:`x` are printed\nat each :ref:`simplex_method-name` iteration.\nIf *level*  == 4 ,\nthe simplex tableau is printed at each simplex iteration.\n\nn\n*\nThis is the dimension of the domain space for *f* ; see\n:ref:`abs_normal_fun@f@n` .\n\nm\n*\nThis is the dimension of the range space for *f* ; see\n:ref:`abs_normal_fun@f@m` . This must be one so that :math:`f`\nis an objective function.\n\ns\n*\nThis is the number of absolute value terms in *f* ; see\n:ref:`abs_normal_fun@f@s` .\n\ng\n*\nWe use the notation *g* for the abs-normal representation of *f* ;\nsee :ref:`abs_normal_fun@g` .\n\ng_hat\n*****\nThis vector has size *m* + *s* and is the value of\n*g* ( *x* , *u* ) at :math:`x = \\hat{x}` and :math:`u = a( \\hat{x} )`.\n\ng_jac\n*****\nThis vector has size ( *m* + *s* ) * ( *n* + *s* ) and is the Jacobian of\n:math:`g(x, u)` at :math:`x = \\hat{x}` and :math:`u = a( \\hat{x} )`.\n\nbound\n*****\nThis vector has size *n*\nand we denote its value by :math:`b \\in \\B{R}^n`.\nThe trust region is defined as the set of :math:`x` such that\n\n.. math::\n\n    | x_j - \\hat{x}_j | \\leq b_j\n\nfor :math:`j = 0 , \\ldots , n-1`,\nwhere :math:`x` is the point that we are approximating :math:`f(x)`.\n\nepsilon\n*******\nThe value *epsilon* [0] is convergence criteria in terms\nof the infinity norm of the difference of *delta_x*\nbetween iterations.\nThe value *epsilon* [1] is convergence criteria in terms\nof the derivative of the objective; i.e., :math:`\\tilde{f}(x)`.\n\nmaxitr\n******\nThis is a vector with size 2.\nThe value *maxitr* [0] is the maximum number of\n``abs_min_linear`` iterations to try before giving up on convergence.\nThe value *maxitr* [1] is the maximum number of iterations in\nthe :ref:`simplex_method<simplex_method@maxitr>` sub-problems.\n\ndelta_x\n*******\nThis vector :math:`\\Delta x` has size *n* .\nThe input value of its elements does not matter.\nUpon return,\nthe approximate minimizer of :math:`\\tilde{f}(x)`\nwith respect to the trust region\nis :math:`x = \\hat{x} + \\Delta x`.\n\nMethod\n******\n\nsigma\n=====\nWe use the notation\n\n.. math::\n\n    \\sigma (x) = \\R{sign} ( z[ x , a(x) ] )\n\nwhere\n:ref:`abs_normal_fun@a@a(x)` and\n:ref:`abs_normal_fun@g@z(x, u)`\nare as defined in the abs-normal representation of :math:`f(x)`.\n\nCutting Planes\n==============\nAt each iteration,\nwe are given affine functions :math:`p_k (x)`\nsuch that :math:`p_k ( x_k ) = \\tilde{f}( x_k )`  and\n:math:`p_k^{(1)} ( x_k )` is the derivative\n:math:`\\tilde{f}^{(1)} ( x_k )`\ncorresponding to :math:`\\sigma ( x_k )`.\n\nIteration\n=========\nAt iteration :math:`k`, we solve the problem\n\n.. math::\n\n    \\begin{array}{lll}\n    \\R{minimize}\n        & \\max \\{ p_k (x) \\W{:} k = 0 , \\ldots , K-1 \\}\n        & \\R{w.r.t} \\; x\n    \\\\\n    \\R{subject \\; to} & - b \\leq x \\leq + b\n    \\end{array}\n\nThe solution is the new point :math:`x_K`\nat which the new affine approximation\n:math:`p_K (x)` is constructed.\nThis process is iterated until the difference\n:math:`x_K - x_{K-1}` is small enough.\n{xrst_toc_hidden\n    example/abs_normal/abs_min_linear.cpp\n    example/abs_normal/abs_min_linear.xrst\n}\nExample\n*******\nThe file :ref:`abs_min_linear.cpp-name` contains an example and test of\n``abs_min_linear`` .\n\n{xrst_end abs_min_linear}\n-----------------------------------------------------------------------------\n*/\n# include <cppad/cppad.hpp>\n# include \"lp_box.hpp\"\n# include \"abs_eval.hpp\"\n\n// BEGIN C++\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n\n// BEGIN PROTOTYPE\ntemplate <class DblVector, class SizeVector>\nbool abs_min_linear(\n    size_t            level   ,\n    size_t            n       ,\n    size_t            m       ,\n    size_t            s       ,\n    const DblVector&  g_hat   ,\n    const DblVector&  g_jac   ,\n    const DblVector&  bound   ,\n    const DblVector&  epsilon ,\n    const SizeVector& maxitr  ,\n    DblVector&        delta_x )\n// END PROTOTYPE\n{   using std::fabs;\n    bool ok    = true;\n    double inf = std::numeric_limits<double>::infinity();\n    //\n    CPPAD_ASSERT_KNOWN(\n        level <= 4,\n        \"abs_min_linear: level is not less that or equal 4\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t(epsilon.size()) == 2,\n        \"abs_min_linear: size of epsilon not equal to 2\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t(maxitr.size()) == 2,\n        \"abs_min_linear: size of maxitr not equal to 2\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        m == 1,\n        \"abs_min_linear: m is not equal to 1\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t(delta_x.size()) == n,\n        \"abs_min_linear: size of delta_x not equal to n\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t(bound.size()) == n,\n        \"abs_min_linear: size of bound not equal to n\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t(g_hat.size()) == m + s,\n        \"abs_min_linear: size of g_hat not equal to m + s\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t(g_jac.size()) == (m + s) * (n + s),\n        \"abs_min_linear: size of g_jac not equal to (m + s)*(n + s)\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t(bound.size()) == n,\n        \"abs_min_linear: size of bound is not equal to n\"\n    );\n    if( level > 0 )\n    {   std::cout << \"start abs_min_linear\\n\";\n        CppAD::abs_print_mat(\"bound\", n, 1, bound);\n        CppAD::abs_print_mat(\"g_hat\", m + s, 1, g_hat);\n        CppAD::abs_print_mat(\"g_jac\", m + s, n + s, g_jac);\n\n    }\n    // partial y(x, u) w.r.t x (J in reference)\n    DblVector py_px(n);\n    for(size_t j = 0; j < n; j++)\n        py_px[ j ] = g_jac[ j ];\n    //\n    // partial y(x, u) w.r.t u (Y in reference)\n    DblVector py_pu(s);\n    for(size_t j = 0; j < s; j++)\n        py_pu[ j ] = g_jac[ n + j ];\n    //\n    // partial z(x, u) w.r.t x (Z in reference)\n    DblVector pz_px(s * n);\n    for(size_t i = 0; i < s; i++)\n    {   for(size_t j = 0; j < n; j++)\n        {   pz_px[ i * n + j ] = g_jac[ (n + s) * (i + m) + j ];\n        }\n    }\n    // partial z(x, u) w.r.t u (L in reference)\n    DblVector pz_pu(s * s);\n    for(size_t i = 0; i < s; i++)\n    {   for(size_t j = 0; j < s; j++)\n        {   pz_pu[ i * s + j ] = g_jac[ (n + s) * (i + m) + n + j ];\n        }\n    }\n    // initialize delta_x\n    for(size_t j = 0; j < n; j++)\n        delta_x[j] = 0.0;\n    //\n    // value of approximation for g(x, u) at current delta_x\n    DblVector g_tilde = CppAD::abs_eval(n, m, s, g_hat, g_jac, delta_x);\n    //\n    // value of sigma at delta_x = 0; i.e., sign( z(x, u) )\n    CppAD::vector<double> sigma(s);\n    for(size_t i = 0; i < s; i++)\n        sigma[i] = CppAD::sign( g_tilde[m + i] );\n    //\n    // current set of cutting planes\n    DblVector C(maxitr[0] * n), c(maxitr[0]);\n    //\n    //\n    size_t n_plane = 0;\n    for(size_t itr = 0; itr < maxitr[0]; itr++)\n    {\n        // Equation (5), Proposition 3.1 of reference\n        // dy_dx = py_px + py_pu * Sigma * (I - pz_pu * Sigma)^-1 * pz_px\n        //\n        // tmp_ss = I - pz_pu * Sigma\n        DblVector tmp_ss(s * s);\n        for(size_t i = 0; i < s; i++)\n        {   for(size_t j = 0; j < s; j++)\n                tmp_ss[i * s + j] = - pz_pu[i * s + j] * sigma[j];\n            tmp_ss[i * s + i] += 1.0;\n        }\n        // tmp_sn = (I - pz_pu * Sigma)^-1 * pz_px\n        double logdet;\n        DblVector tmp_sn(s * n);\n        LuSolve(s, n, tmp_ss, pz_px, tmp_sn, logdet);\n        //\n        // tmp_sn = Sigma * (I - pz_pu * Sigma)^-1 * pz_px\n        for(size_t i = 0; i < s; i++)\n        {   for(size_t j = 0; j < n; j++)\n                tmp_sn[i * n + j] *= sigma[i];\n        }\n        // dy_dx = py_px + py_pu * Sigma * (I - pz_pu * Sigma)^-1 * pz_px\n        DblVector dy_dx(n);\n        for(size_t j = 0; j < n; j++)\n        {   dy_dx[j] = py_px[j];\n            for(size_t k = 0; k < s; k++)\n                dy_dx[j] += py_pu[k] * tmp_sn[ k * n + j];\n        }\n        //\n        // check for case where derivative of hyperplane is zero\n        // (in convex case, this is the minimizer)\n        bool near_zero = true;\n        for(size_t j = 0; j < n; j++)\n            near_zero &= std::fabs( dy_dx[j] ) < epsilon[1];\n        if( near_zero )\n        {   if( level > 0 )\n                std::cout << \"end abs_min_linear: local derivative near zero\\n\";\n            return true;\n        }\n\n        // value of hyperplane at delta_x\n        double plane_at_zero = g_tilde[0];\n        // value of hyperplane at 0\n        for(size_t j = 0; j < n; j++)\n            plane_at_zero -= dy_dx[j] * delta_x[j];\n        //\n        // add a cutting plane with value g_tilde[0] at delta_x\n        // and derivative dy_dx\n        c[n_plane] = plane_at_zero;\n        for(size_t j = 0; j < n; j++)\n            C[n_plane * n + j] = dy_dx[j];\n        ++n_plane;\n        //\n        // variables for cutting plane problem are (dx, w)\n        // c[i] + C[i,:]*dx <= w\n        DblVector b_box(n_plane), A_box(n_plane * (n + 1));\n        for(size_t i = 0; i < n_plane; i++)\n        {   b_box[i] = c[i];\n            for(size_t j = 0; j < n; j++)\n                A_box[i * (n+1) + j] = C[i * n + j];\n            A_box[i *(n+1) + n] = -1.0;\n        }\n        // w is the objective\n        DblVector c_box(n + 1);\n        for(size_t i = 0; i < size_t(c_box.size()); i++)\n            c_box[i] = 0.0;\n        c_box[n] = 1.0;\n        //\n        // d_box\n        DblVector d_box(n+1);\n        for(size_t j = 0; j < n; j++)\n            d_box[j] = bound[j];\n        d_box[n] = inf;\n        //\n        // solve the cutting plane problem\n        DblVector xout_box(n + 1);\n        size_t level_box = 0;\n        if( level > 0 )\n            level_box = level - 1;\n        ok &= CppAD::lp_box(\n            level_box,\n            A_box,\n            b_box,\n            c_box,\n            d_box,\n            maxitr[1],\n            xout_box\n        );\n        if( ! ok )\n        {   if( level > 0 )\n            {   CppAD::abs_print_mat(\"delta_x\", n, 1, delta_x);\n                std::cout << \"end abs_min_linear: lp_box failed\\n\";\n            }\n            return false;\n        }\n        //\n        // check for convergence\n        double max_diff = 0.0;\n        for(size_t j = 0; j < n; j++)\n        {   double diff = delta_x[j] - xout_box[j];\n            max_diff    = std::max( max_diff, std::fabs(diff) );\n        }\n        //\n        // check for descent in value of approximation objective\n        DblVector delta_new(n);\n        for(size_t j = 0; j < n; j++)\n            delta_new[j] = xout_box[j];\n        DblVector g_new = CppAD::abs_eval(n, m, s, g_hat, g_jac, delta_new);\n        if( level > 0 )\n        {   std::cout << \"itr = \" << itr << \", max_diff = \" << max_diff\n                << \", y_cur = \" << g_tilde[0] << \", y_new = \" << g_new[0]\n                << \"\\n\";\n            CppAD::abs_print_mat(\"delta_new\", n, 1, delta_new);\n        }\n        //\n        g_tilde = g_new;\n        delta_x = delta_new;\n        //\n        // value of sigma at new delta_x; i.e., sign( z(x, u) )\n        for(size_t i = 0; i < s; i++)\n            sigma[i] = CppAD::sign( g_tilde[m + i] );\n        //\n        if( max_diff < epsilon[0] )\n        {   if( level > 0 )\n                std::cout << \"end abs_min_linear: change in delta_x near zero\\n\";\n            return true;\n        }\n    }\n    if( level > 0 )\n        std::cout << \"end abs_min_linear: maximum number of iterations exceeded\\n\";\n    return false;\n}\n} // END_CPPAD_NAMESPACE\n// END C++\n\n# endif\n"
  },
  {
    "path": "example/abs_normal/abs_min_linear.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin abs_min_linear.hpp}\n\nabs_min_linear Source Code\n##########################\n\n{xrst_literal\n    example/abs_normal/abs_min_linear.hpp\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end abs_min_linear.hpp}\n"
  },
  {
    "path": "example/abs_normal/abs_min_quad.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin abs_min_quad.cpp}\n\nabs_min_quad: Example and Test\n##############################\n\nPurpose\n*******\nThe function\n:math:`f : \\B{R}^3 \\rightarrow \\B{R}` defined by\n\n.. math::\n\n    f( x_0, x_1  )\n    =\n    ( x_0^2 + x_1^2 ) / 2 +  | x_0 - 5 | + | x_1 + 5 |\n\nFor this case, the :ref:`abs_min_quad-name` object should be equal\nto the function itself.\nIn addition, the function is convex and\n:ref:`abs_min_quad-name` should find its global minimizer.\nThe minimizer of this function is\n:math:`x_0 = 1`, :math:`x_1 = -1`.\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end abs_min_quad.cpp}\n-------------------------------------------------------------------------------\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n# include \"abs_min_quad.hpp\"\n\nnamespace {\n    CPPAD_TESTVECTOR(double) join(\n        const CPPAD_TESTVECTOR(double)& x ,\n        const CPPAD_TESTVECTOR(double)& u )\n    {   size_t n = x.size();\n        size_t s = u.size();\n        CPPAD_TESTVECTOR(double) xu(n + s);\n        for(size_t j = 0; j < n; j++)\n            xu[j] = x[j];\n        for(size_t j = 0; j < s; j++)\n            xu[n + j] = u[j];\n        return xu;\n    }\n}\nbool abs_min_quad(void)\n{   bool ok = true;\n    //\n    using CppAD::AD;\n    using CppAD::ADFun;\n    //\n    typedef CPPAD_TESTVECTOR(size_t)       s_vector;\n    typedef CPPAD_TESTVECTOR(double)       d_vector;\n    typedef CPPAD_TESTVECTOR( AD<double> ) ad_vector;\n    //\n    size_t level = 0;     // level of tracing\n    size_t n     = 2;     // size of x\n    size_t m     = 1;     // size of y\n    size_t s     = 2 ;    // number of data points and absolute values\n    //\n    // record the function f(x)\n    ad_vector ad_x(n), ad_y(m);\n    for(size_t j = 0; j < n; j++)\n        ad_x[j] = double(j + 1);\n    Independent( ad_x );\n    AD<double> sum = 0.0;\n    sum += ad_x[0] * ad_x[0] / 2.0 + abs( ad_x[0] - 5 );\n    sum += ad_x[1] * ad_x[1] / 2.0 + abs( ad_x[1] + 5 );\n    ad_y[0] = sum;\n    ADFun<double> f(ad_x, ad_y);\n\n    // create its abs_normal representation in g, a\n    ADFun<double> g, a;\n    f.abs_normal_fun(g, a);\n\n    // check dimension of domain and range space for g\n    ok &= g.Domain() == n + s;\n    ok &= g.Range()  == m + s;\n\n    // check dimension of domain and range space for a\n    ok &= a.Domain() == n;\n    ok &= a.Range()  == s;\n\n    // --------------------------------------------------------------------\n    // Choose the point x_hat = 0\n    d_vector x_hat(n);\n    for(size_t j = 0; j < n; j++)\n        x_hat[j] = 0.0;\n\n    // value of a_hat = a(x_hat)\n    d_vector a_hat = a.Forward(0, x_hat);\n\n    // (x_hat, a_hat)\n    d_vector xu_hat = join(x_hat, a_hat);\n\n    // value of g[ x_hat, a_hat ]\n    d_vector g_hat = g.Forward(0, xu_hat);\n\n    // Jacobian of g[ x_hat, a_hat ]\n    d_vector g_jac = g.Jacobian(xu_hat);\n\n    // trust region bound\n    d_vector bound(n);\n    for(size_t j = 0; j < n; j++)\n        bound[j] = 10.0;\n\n    // convergence criteria\n    d_vector epsilon(2);\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    epsilon[0]   = eps99;\n    epsilon[1]   = eps99;\n\n    // maximum number of iterations\n    s_vector maxitr(2);\n    maxitr[0] = 10; // maximum number of abs_min_quad iterations\n    maxitr[1] = 35; // maximum number of qp_interior iterations\n\n    // set Hessian equal to identity matrix I\n    d_vector hessian(n * n);\n    for(size_t i = 0; i < n; i++)\n    {   for(size_t j = 0; j < n; j++)\n            hessian[i * n + j] = 0.0;\n        hessian[i * n + i] = 1.0;\n    }\n\n    // minimize the approximation for f (which is equal to f for this case)\n    d_vector delta_x(n);\n    ok &= CppAD::abs_min_quad(\n        level, n, m, s,\n        g_hat, g_jac, hessian, bound, epsilon, maxitr, delta_x\n    );\n\n    // check that the solution\n    ok &= CppAD::NearEqual( delta_x[0], +1.0, eps99, eps99 );\n    ok &= CppAD::NearEqual( delta_x[1], -1.0, eps99, eps99 );\n\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/abs_normal/abs_min_quad.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_ABS_NORMAL_ABS_MIN_QUAD_HPP\n# define CPPAD_EXAMPLE_ABS_NORMAL_ABS_MIN_QUAD_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin abs_min_quad}\n{xrst_spell\n    dbl\n    lll\n    maxitr\n}\nabs_normal: Minimize a Linear Abs-normal Approximation\n######################################################\n\nSyntax\n******\n| *ok* = ``abs_min_quad`` (\n| |tab| *level* , *n* , *m* , *s* ,\n| |tab| *g_hat* , *g_jac* , *hessian* , *bound* , *epsilon* , *maxitr* , *delta_x*\n| )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN PROTOTYPE\n    // END PROTOTYPE\n}\n\nSource\n******\nThis following is a link to the source code for this example:\n:ref:`abs_min_quad.hpp-name` .\n\nPurpose\n*******\nWe are given a point :math:`\\hat{x} \\in \\B{R}^n` and\nuse the notation :math:`\\tilde{f} (x)` for the abs-normal\n:ref:`approximation for f(x)<abs_normal_fun@Abs-normal Approximation@Approximating f(x)>`\nnear :math:`\\hat{x}`.\nWe are also given a vector :math:`b \\in \\B{R}_+^n`\nand a positive definite matrix :math:`H \\in \\B{R}^{n \\times n}`.\nThis routine solves the problem\n\n.. math::\n\n    \\begin{array}{lll}\n    \\R{minimize} &\n        \\Delta x^T H \\Delta x / 2 + \\tilde{f}( \\hat{x} + \\Delta x ) &\n        \\R{w.r.t} \\; \\Delta x \\in \\B{R}^n\n    \\\\\n    \\R{subject \\; to} & | \\Delta x_j | \\leq b_j & j = 0 , \\ldots , n-1\n    \\end{array}\n\nDblVector\n*********\nis a :ref:`SimpleVector-name` class with elements of type ``double`` .\n\nSizeVector\n**********\nis a :ref:`SimpleVector-name` class with elements of type ``size_t`` .\n\nf\n*\nWe use the notation *f* for the original function; see\n:ref:`abs_normal_fun@f` .\n\nlevel\n*****\nThis value is less that or equal 3.\nIf *level*  == 0 ,\nno tracing of the optimization is printed.\nIf *level*  >= 1 ,\na trace of each iteration of ``abs_min_quad`` is printed.\nIf *level*  >= 2 ,\na trace of the :ref:`qp_box-name` sub-problem is printed.\nIf *level*  >= 3 ,\na trace of the :ref:`qp_interior-name` sub-problem is printed.\n\nn\n*\nThis is the dimension of the domain space for *f* ; see\n:ref:`abs_normal_fun@f@n` .\n\nm\n*\nThis is the dimension of the range space for *f* ; see\n:ref:`abs_normal_fun@f@m` . This must be one so that :math:`f`\nis an objective function.\n\ns\n*\nThis is the number of absolute value terms in *f* ; see\n:ref:`abs_normal_fun@f@s` .\n\ng\n*\nWe use the notation *g* for the abs-normal representation of *f* ;\nsee :ref:`abs_normal_fun@g` .\n\ng_hat\n*****\nThis vector has size *m* + *s* and is the value of\n*g* ( *x* , *u* ) at :math:`x = \\hat{x}` and :math:`u = a( \\hat{x} )`.\n\ng_jac\n*****\nThis vector has size ( *m* + *s* ) * ( *n* + *s* ) and is the Jacobian of\n:math:`g(x, u)` at :math:`x = \\hat{x}` and :math:`u = a( \\hat{x} )`.\n\nhessian\n*******\nThis vector has size *n* * *n* .\nIt is a :ref:`row-major<glossary@Row-major Representation>` representation\nof the matrix :math:`H \\in \\B{R}^{n \\times n}`.\n\nbound\n*****\nThis vector has size *n* and is the vector :math:`b \\in \\B{R}^n`.\nThe trust region is defined as the set of :math:`\\Delta x` such that\n\n.. math::\n\n    | \\Delta x | \\leq b_j\n\nfor :math:`j = 0 , \\ldots , n-1`.\n\nepsilon\n*******\nThe value *epsilon* [0] is convergence criteria in terms\nof the infinity norm of the difference of *delta_x*\nbetween iterations.\nThe value *epsilon* [1] is convergence criteria in terms\nof the derivative of the objective; i.e.\n\n.. math::\n\n    \\Delta x^T H \\Delta x / 2 + \\tilde{f}( \\hat{x} + \\Delta x)\n\nmaxitr\n******\nThis is a vector with size 2.\nThe value *maxitr* [0] is the maximum number of\n``abs_min_quad`` iterations to try before giving up on convergence.\nThe value *maxitr* [1] is the maximum number of iterations in\nthe :ref:`qp_interior<qp_interior@maxitr>` sub-problems.\n\ndelta_x\n*******\nThis vector :math:`\\Delta x` has size *n* .\nThe input value of its elements does not matter.\nUpon return,\nthe approximate minimizer of the objective with respect to the trust region.\n\nMethod\n******\n\nsigma\n=====\nWe use the notation\n\n.. math::\n\n    \\sigma (x) = \\R{sign} ( z[ x , a(x) ] )\n\nwhere\n:ref:`abs_normal_fun@a@a(x)` and\n:ref:`abs_normal_fun@g@z(x, u)`\nare as defined in the abs-normal representation of :math:`f(x)`.\n\nCutting Planes\n==============\nAt each iteration,\nwe are given affine functions :math:`p_k (x)`\nsuch that :math:`p_k ( x_k ) = \\tilde{f}( x_k )`  and\n:math:`p_k^{(1)} ( x_k )` is the derivative :math:`\\tilde{f}^{(1)} ( x_k )`\ncorresponding to :math:`\\sigma ( x_k )`.\n\nIteration\n=========\nAt iteration :math:`k`, we solve the problem\n\n.. math::\n\n    \\begin{array}{lll}\n    \\R{minimize}\n    & \\Delta x^T H \\Delta x / 2 +\n        \\max \\{ p_k ( \\hat{x} + \\Delta x) \\W{:} k = 0 , \\ldots , K-1 \\}\n    & \\R{w.r.t} \\; \\Delta x\n    \\\\\n    \\R{subject \\; to} & - b \\leq \\Delta x \\leq + b\n    \\end{array}\n\nThe solution is the new point :math:`x_K`\nat which the new affine approximation\n:math:`p_K (x)` is constructed.\nThis process is iterated until the difference\n:math:`x_K - x_{K-1}` is small enough.\n{xrst_toc_hidden\n    example/abs_normal/abs_min_quad.cpp\n    example/abs_normal/abs_min_quad.xrst\n}\nExample\n*******\nThe file :ref:`abs_min_quad.cpp-name` contains an example and test of\n``abs_min_quad`` .\n\n{xrst_end abs_min_quad}\n-----------------------------------------------------------------------------\n*/\n# include <cppad/cppad.hpp>\n# include \"qp_box.hpp\"\n# include \"abs_eval.hpp\"\n\n// BEGIN C++\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n\n// BEGIN PROTOTYPE\ntemplate <class DblVector, class SizeVector>\nbool abs_min_quad(\n    size_t            level   ,\n    size_t            n       ,\n    size_t            m       ,\n    size_t            s       ,\n    const DblVector&  g_hat   ,\n    const DblVector&  g_jac   ,\n    const DblVector&  hessian ,\n    const DblVector&  bound   ,\n    const DblVector&  epsilon ,\n    const SizeVector& maxitr  ,\n    DblVector&        delta_x )\n// END PROTOTYPE\n{   using std::fabs;\n    bool ok    = true;\n    double inf = std::numeric_limits<double>::infinity();\n    //\n    CPPAD_ASSERT_KNOWN(\n        level <= 4,\n        \"abs_min_quad: level is not less that or equal 3\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t(epsilon.size()) == 2,\n        \"abs_min_quad: size of epsilon not equal to 2\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t(maxitr.size()) == 2,\n        \"abs_min_quad: size of maxitr not equal to 2\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        m == 1,\n        \"abs_min_quad: m is not equal to 1\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t(delta_x.size()) == n,\n        \"abs_min_quad: size of delta_x not equal to n\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t(bound.size()) == n,\n        \"abs_min_quad: size of bound not equal to n\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t(g_hat.size()) == m + s,\n        \"abs_min_quad: size of g_hat not equal to m + s\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t(g_jac.size()) == (m + s) * (n + s),\n        \"abs_min_quad: size of g_jac not equal to (m + s)*(n + s)\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t(hessian.size()) == n * n,\n        \"abs_min_quad: size of hessian not equal to n * n\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t(bound.size()) == n,\n        \"abs_min_quad: size of bound is not equal to n\"\n    );\n    if( level > 0 )\n    {   std::cout << \"start abs_min_quad\\n\";\n        CppAD::abs_print_mat(\"g_hat\", m + s, 1, g_hat);\n        CppAD::abs_print_mat(\"g_jac\", m + s, n + s, g_jac);\n        CppAD::abs_print_mat(\"hessian\", n, n, hessian);\n        CppAD::abs_print_mat(\"bound\", n, 1, bound);\n    }\n    // partial y(x, u) w.r.t x (J in reference)\n    DblVector py_px(n);\n    for(size_t j = 0; j < n; j++)\n        py_px[ j ] = g_jac[ j ];\n    //\n    // partial y(x, u) w.r.t u (Y in reference)\n    DblVector py_pu(s);\n    for(size_t j = 0; j < s; j++)\n        py_pu[ j ] = g_jac[ n + j ];\n    //\n    // partial z(x, u) w.r.t x (Z in reference)\n    DblVector pz_px(s * n);\n    for(size_t i = 0; i < s; i++)\n    {   for(size_t j = 0; j < n; j++)\n        {   pz_px[ i * n + j ] = g_jac[ (n + s) * (i + m) + j ];\n        }\n    }\n    // partial z(x, u) w.r.t u (L in reference)\n    DblVector pz_pu(s * s);\n    for(size_t i = 0; i < s; i++)\n    {   for(size_t j = 0; j < s; j++)\n        {   pz_pu[ i * s + j ] = g_jac[ (n + s) * (i + m) + n + j ];\n        }\n    }\n    // initialize delta_x\n    for(size_t j = 0; j < n; j++)\n        delta_x[j] = 0.0;\n    //\n    // current set of cutting planes\n    DblVector C(maxitr[0] * n), c(maxitr[0]);\n    //\n    // value of abs-normal approximation at x_hat + delta_x\n    DblVector g_tilde = CppAD::abs_eval(n, m, s, g_hat, g_jac, delta_x);\n    //\n    // value of sigma at delta_x = 0; i.e., sign( z(x, u) )\n    CppAD::vector<double> sigma(s);\n    for(size_t i = 0; i < s; i++)\n        sigma[i] = CppAD::sign( g_tilde[m + i] );\n    //\n    // initial value of the objective\n    double obj_cur =  g_tilde[0];\n    //\n    // initial number of cutting planes\n    size_t n_plane = 0;\n    //\n    if( level > 0 )\n    {   std::cout << \"obj = \" << obj_cur << \"\\n\";\n        CppAD::abs_print_mat(\"delta_x\", n, 1, delta_x);\n    }\n    for(size_t itr = 0; itr < maxitr[0]; itr++)\n    {\n        // Equation (5), Proposition 3.1 of reference\n        // dy_dx = py_px + py_pu * Sigma * (I - pz_pu * Sigma)^-1 * pz_px\n        //\n        // tmp_ss = I - pz_pu * Sigma\n        DblVector tmp_ss(s * s);\n        for(size_t i = 0; i < s; i++)\n        {   for(size_t j = 0; j < s; j++)\n                tmp_ss[i * s + j] = - pz_pu[i * s + j] * sigma[j];\n            tmp_ss[i * s + i] += 1.0;\n        }\n        // tmp_sn = (I - pz_pu * Sigma)^-1 * pz_px\n        double logdet;\n        DblVector tmp_sn(s * n);\n        LuSolve(s, n, tmp_ss, pz_px, tmp_sn, logdet);\n        //\n        // tmp_sn = Sigma * (I - pz_pu * Sigma)^-1 * pz_px\n        for(size_t i = 0; i < s; i++)\n        {   for(size_t j = 0; j < n; j++)\n                tmp_sn[i * n + j] *= sigma[i];\n        }\n        // dy_dx = py_px + py_pu * Sigma * (I - pz_pu * Sigma)^-1 * pz_px\n        DblVector dy_dx(n);\n        for(size_t j = 0; j < n; j++)\n        {   dy_dx[j] = py_px[j];\n            for(size_t k = 0; k < s; k++)\n                dy_dx[j] += py_pu[k] * tmp_sn[ k * n + j];\n        }\n        //\n        // compute derivative of the quadratic term\n        DblVector dq_dx(n);\n        for(size_t j = 0; j < n; j++)\n        {   dq_dx[j] = 0.0;\n            for(size_t i = 0; i < n; i++)\n                dq_dx[j] += delta_x[i] * hessian[i * n + j];\n        }\n        //\n        // check for case where derivative of objective is zero\n        // (in convex case, this is the minimizer)\n        bool near_zero = true;\n        for(size_t j = 0; j < n; j++)\n            near_zero &= std::fabs( dq_dx[j] + dy_dx[j] ) < epsilon[1];\n        if( near_zero )\n        {   if( level > 0 )\n                std::cout << \"end abs_min_quad: local derivative near zero\\n\";\n            return true;\n        }\n        // value of hyperplane at delta_x\n        double plane_at_zero = g_tilde[0];\n        //\n        // value of hyperplane at 0\n        for(size_t j = 0; j < n; j++)\n            plane_at_zero -= dy_dx[j] * delta_x[j];\n        //\n        // add a cutting plane with value g_tilde[0] at delta_x\n        // and derivative dy_dx\n        c[n_plane] = plane_at_zero;\n        for(size_t j = 0; j < n; j++)\n            C[n_plane * n + j] = dy_dx[j];\n        ++n_plane;\n        //\n        // variables for cutting plane problem are (dx, w)\n        // c[i] + C[i,:] * dx <= w\n        DblVector c_box(n_plane), C_box(n_plane * (n + 1));\n        for(size_t i = 0; i < n_plane; i++)\n        {   c_box[i] = c[i];\n            for(size_t j = 0; j < n; j++)\n                C_box[i * (n+1) + j] = C[i * n + j];\n            C_box[i * (n+1) + n] = -1.0;\n        }\n        //\n        // w is the objective\n        DblVector g_box(n + 1);\n        for(size_t i = 0; i < size_t(c_box.size()); i++)\n            g_box[i] = 0.0;\n        g_box[n] = 1.0;\n        //\n        // a_box, b_box\n        DblVector a_box(n+1), b_box(n+1);\n        for(size_t j = 0; j < n; j++)\n        {   a_box[j] = - bound[j];\n            b_box[j] = + bound[j];\n        }\n        a_box[n] = - inf;\n        b_box[n] = + inf;\n        //\n        // initial delta_x in qp_box is zero\n        DblVector xin_box(n + 1);\n        for(size_t j = 0; j < n; j++)\n            xin_box[j] = 0.0;\n        // initial w in qp_box is 1 + max_i c[i]\n        xin_box[n] = 1.0 + c_box[0];\n        for(size_t i = 1; i < n_plane; i++)\n            xin_box[n] = std::max( xin_box[n], 1.0 + c_box[i] );\n        //\n        DblVector hessian_box( (n+1) * (n+1) );\n        for(size_t i = 0; i < n+1; i++)\n        {   for(size_t j = 0; j < n+1; j++)\n            {   if( i == n || j == n )\n                    hessian_box[i * (n+1) + j] = 0.0;\n                else\n                    hessian_box[i * (n+1) + j] = hessian[i * n + j];\n            }\n        }\n        //\n        // solve the cutting plane problem\n        DblVector xout_box(n + 1);\n        size_t level_box = 0;\n        if( level > 0 )\n            level_box = level - 1;\n        ok &= CppAD::qp_box(\n            level_box,\n            a_box,\n            b_box,\n            c_box,\n            C_box,\n            g_box,\n            hessian_box,\n            epsilon[1],\n            maxitr[1],\n            xin_box,\n            xout_box\n        );\n        if( ! ok )\n        {   if( level > 0 )\n            {   CppAD::abs_print_mat(\"delta_x\", n, 1, delta_x);\n                std::cout << \"end abs_min_quad: qp_box failed\\n\";\n            }\n            return false;\n        }\n        DblVector delta_new(n);\n        for(size_t j = 0; j < n; j++)\n            delta_new[j] = xout_box[j];\n        //\n        // check for convergence\n        double max_diff = 0.0;\n        for(size_t j = 0; j < n; j++)\n        {   double diff = delta_x[j] - delta_new[j];\n            max_diff    = std::max( max_diff, std::fabs(diff) );\n        }\n        //\n        // new value of the objective\n        DblVector g_new   = CppAD::abs_eval(n, m, s, g_hat, g_jac, delta_new);\n        double    obj_new = g_new[0];\n        for(size_t i = 0; i < n; i++)\n        {   for(size_t j = 0; j < n; j++)\n                obj_new += delta_new[i] * hessian[i * n + j] * delta_new[j];\n        }\n        g_tilde = g_new;\n        obj_cur = obj_new;\n        delta_x = delta_new;\n        //\n        if( level > 0 )\n        {   std::cout << \"itr = \" << itr << \", max_diff = \" << max_diff\n                << \", obj_cur = \" << obj_cur << \"\\n\";\n            CppAD::abs_print_mat(\"delta_x\", n, 1, delta_x);\n        }\n        //\n        // value of sigma at new delta_x; i.e., sign( z(x, u) )\n        for(size_t i = 0; i < s; i++)\n            sigma[i] = CppAD::sign( g_tilde[m + i] );\n        //\n        if( max_diff < epsilon[0] )\n        {   if( level > 0 )\n                std::cout << \"end abs_min_quad: change in delta_x near zero\\n\";\n            return true;\n        }\n    }\n    if( level > 0 )\n        std::cout << \"end abs_min_quad: maximum number of iterations exceeded\\n\";\n    return false;\n}\n} // END_CPPAD_NAMESPACE\n// END C++\n\n# endif\n"
  },
  {
    "path": "example/abs_normal/abs_min_quad.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin abs_min_quad.hpp}\n\nabs_min_quad Source Code\n########################\n\n{xrst_literal\n    example/abs_normal/abs_min_quad.hpp\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end abs_min_quad.hpp}\n"
  },
  {
    "path": "example/abs_normal/abs_normal.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin abs_normal.cpp}\n\nAbs-Normal Form Examples and Tests Driver\n#########################################\n\nRunning These Tests\n*******************\nAfter executing the :ref:`cmake-name` command\nform the :ref:`download@Distribution Directory`,\nyou can build and run these tests with the commands::\n\n    cd build\n    make check_example_abs_normal\n\nNote that your choice of :ref:`cmake@generator` may require using\nan different version of make; e.g., ``ninja`` .\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end abs_normal.cpp}\n-------------------------------------------------------------------------------\n*/\n// BEGIN C++\n\n// CPPAD_HAS_* defines\n# include <cppad/configure.hpp>\n\n// for thread_alloc\n# include <cppad/utility/thread_alloc.hpp>\n\n// test runner\n# include <cppad/utility/test_boolofvoid.hpp>\n\n// external complied tests\nextern bool abs_eval(void);\nextern bool abs_min_linear(void);\nextern bool abs_min_quad(void);\nextern bool get_started(void);\nextern bool lp_box(void);\nextern bool min_nso_linear(void);\nextern bool min_nso_quad(void);\nextern bool qp_box(void);\nextern bool qp_interior(void);\nextern bool simplex_method(void);\n\n// main program that runs all the tests\nint main(void)\n{   std::string group = \"example/abs_norml\";\n    size_t      width = 20;\n    CppAD::test_boolofvoid Run(group, width);\n\n    // This line is used by test_one.sh\n\n    // external compiled tests\n    Run( abs_eval,            \"abs_eval\"           );\n    Run( abs_min_linear,      \"abs_min_linear\"     );\n    Run( abs_min_quad,        \"abs_min_quad\"       );\n    Run( get_started,         \"get_started\"        );\n    Run( lp_box,              \"lp_box\"             );\n    Run( min_nso_linear,      \"min_nso_linear\"     );\n    Run( min_nso_quad,         \"min_nso_quad\"      );\n    Run( qp_box,              \"qp_box\"             );\n    Run( qp_interior,         \"qp_interior\"        );\n    Run( simplex_method,      \"simplex_method\"     );\n\n    // check for memory leak\n    bool memory_ok = CppAD::thread_alloc::free_all();\n    // print summary at end\n    bool ok = Run.summary(memory_ok);\n    //\n    return static_cast<int>( ! ok );\n}\n// END C++\n"
  },
  {
    "path": "example/abs_normal/abs_normal.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin example_abs_normal}\n{xrst_spell\n    andreas\n    bernt\n    griewank\n    jens\n    radons\n    streubel\n    uwe\n    vol\n}\n\nExamples and Tests: Abs-normal Representation of Non-Smooth Functions\n#####################################################################\n\nReference\n*********\nAndreas Griewank, Jens-Uwe Bernt, Manuel Radons, Tom Streubel,\n*Solving piecewise linear systems in abs-normal form* ,\nLinear Algebra and its Applications,\nvol. 471 (2015), pages 500-530.\n\nContents\n********\n{xrst_toc_table\n    example/abs_normal/get_started.cpp\n    example/abs_normal/abs_print_mat.hpp\n    example/abs_normal/abs_eval.hpp\n    example/abs_normal/simplex_method.hpp\n    example/abs_normal/lp_box.hpp\n    example/abs_normal/abs_min_linear.hpp\n    example/abs_normal/min_nso_linear.hpp\n    example/abs_normal/qp_interior.hpp\n    example/abs_normal/qp_box.hpp\n    example/abs_normal/abs_min_quad.hpp\n    example/abs_normal/min_nso_quad.hpp\n}\n\n{xrst_end example_abs_normal}\n"
  },
  {
    "path": "example/abs_normal/abs_print_mat.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_ABS_NORMAL_ABS_PRINT_MAT_HPP\n# define CPPAD_EXAMPLE_ABS_NORMAL_ABS_PRINT_MAT_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin abs_print_mat}\n{xrst_spell\n    cout\n    nr\n}\nabs_normal: Print a Vector or Matrix\n####################################\n\nSyntax\n******\n| ``abs_print_mat`` ( *name* , *nr* , *nc* , *mat* )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN PROTOTYPE\n    // END PROTOTYPE\n}\n\nPurpose\n*******\nThis routine is used by the :ref:`abs_normal<example_abs_normal-name>` examples to print\nvectors and matrices.\nA new-line is printed at the end of this output.\n\nname\n****\nThis is a name that is printed before the vector or matrix.\n\nnr\n**\nThis is the number of rows in the matrix. Use *nr*  = 1 for\nrow vectors.\n\nnc\n**\nThis is the number of columns in the matrix. Use *nc*  = 1 for\ncolumn vectors.\n\nmat\n***\nThis is a\n:ref:`row-major<glossary@Row-major Representation>` representation\nof the matrix (hence a :ref:`SimpleVector-name` ).\nThe syntax\n\n    *std::cout <<* ``mat`` [ ``i`` ]\n\nmust output the *i*-th element of the simple vector *mat* .\n\n{xrst_end abs_print_mat}\n-----------------------------------------------------------------------------\n*/\n# include <cppad/cppad.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n\n// BEGIN PROTOTYPE\ntemplate <class Vector>\nvoid abs_print_mat(\n    const std::string& name ,\n    size_t             nr   ,\n    size_t             nc   ,\n    const Vector&      mat  )\n// END PROTOTYPE\n{\n    CPPAD_ASSERT_KNOWN(\n        size_t(mat.size()) == nr * nc,\n        \"abs_print_mat: size of mat is not nr * nc\"\n    );\n    // output name\n    std::cout << name << \" =\";\n    //\n    // handle empty case\n    if( nr == 0 || nc == 0 )\n    {   std::cout << \" \" << nr << \" by \" << nc << \" empty matrix\\n\";\n        return;\n    }\n    //\n    // handle vector case\n    if( nr == 1 || nc == 1 )\n    {   std::cout << \" [\";\n        for(size_t i = 0; i < nr * nc; i++)\n        {   if( i > 0 )\n                std::cout << \", \";\n            std::cout << mat[i];\n        }\n        std::cout << \"]\";\n        //\n        // column vectors are printed as row vectors with a transpose at end\n        if( nr > 1 )\n            std::cout << \"^T\";\n        //\n        std::cout << \"\\n\";\n        return;\n    }\n    // non-empty matrix\n    std::cout << \"\\n\";\n    for(size_t i = 0; i < nr; i++)\n    {   std::cout << \"[\";\n        for(size_t j = 0; j < nc; j++)\n        {   if( j > 0 )\n                std::cout << \", \";\n            std::cout << mat[i * nc + j];\n        }\n        std::cout << \"]\\n\";\n    }\n    return;\n}\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "example/abs_normal/get_started.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin abs_get_started.cpp}\n{xrst_spell\n    rclrcl\n}\n\nabs_normal Getting Started: Example and Test\n############################################\n\nPurpose\n*******\nCreates an :ref:`abs_normal<abs_normal_fun-name>`\nrepresentation :math:`g` for the function\n:math:`f : \\B{R}^3 \\rightarrow \\B{R}` defined by\n\n.. math::\n\n    f( x_0, x_1, x_2  ) = | x_0 + x_1 | + | x_1 + x_2 |\n\nThe corresponding\n:ref:`abs_normal_fun@g` :math:`: \\B{R}^5 \\rightarrow \\B{R}^3` is\ngiven by\n\n.. math::\n\n    \\begin{array}{rclrcl}\n        g_0 ( x_0, x_1, x_2, u_0, u_1 ) & = & u_0 + u_1 & = & y_0 (x, u)\n        \\\\\n        g_1 ( x_0, x_1, x_2, u_0, u_1 ) & = & x_0 + x_1 & = & z_0 (x, u)\n        \\\\\n        g_1 ( x_0, x_1, x_2, u_0, u_1 ) & = & x_1 + x_2 & = & z_1 (x, u)\n    \\end{array}\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end abs_get_started.cpp}\n-------------------------------------------------------------------------------\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\nnamespace {\n    CPPAD_TESTVECTOR(double) join(\n        const CPPAD_TESTVECTOR(double)& x ,\n        const CPPAD_TESTVECTOR(double)& u )\n    {   size_t n = x.size();\n        size_t s = u.size();\n        CPPAD_TESTVECTOR(double) xu(n + s);\n        for(size_t j = 0; j < n; j++)\n            xu[j] = x[j];\n        for(size_t j = 0; j < s; j++)\n            xu[n + j] = u[j];\n        return xu;\n    }\n}\nbool get_started(void)\n{   bool ok = true;\n    //\n    using CppAD::AD;\n    using CppAD::ADFun;\n    //\n    size_t n = 3; // size of x\n    size_t m = 1; // size of y\n    size_t s = 2; // size of u and z\n    //\n    // record the function f(x)\n    CPPAD_TESTVECTOR( AD<double> ) ax(n), ay(m);\n    for(size_t j = 0; j < n; j++)\n        ax[j] = double(j + 1);\n    Independent( ax );\n    // for this example, we ensure first absolute value is | x_0 + x_1 |\n    AD<double> a0 = abs( ax[0] + ax[1] );\n    // and second absolute value is | x_1 + x_2 |\n    AD<double> a1 = abs( ax[1] + ax[2] );\n    ay[0]         = a0 + a1;\n    ADFun<double> f(ax, ay);\n\n    // create its abs_normal representation in g, a\n    ADFun<double> g, a;\n    f.abs_normal_fun(g, a);\n\n    // check dimension of domain and range space for g\n    ok &= g.Domain() == n + s;\n    ok &= g.Range() == m + s;\n\n    // check dimension of domain and range space for a\n    ok &= a.Domain() == n;\n    ok &= a.Range() == s;\n\n    // --------------------------------------------------------------------\n    // a(x) has all the operations used to compute f(x), but the sum of the\n    // absolute values is not needed for a(x), so optimize it out.\n    size_t n_op = f.size_op();\n    ok         &= a.size_op() == n_op;\n    a.optimize();\n    ok         &= a.size_op() < n_op;\n\n    // --------------------------------------------------------------------\n    // zero order forward mode calculation using g(x, u)\n    CPPAD_TESTVECTOR(double) x(n), u(s), xu(n+s), yz(m+s);\n    for(size_t j = 0; j < n; j++)\n        x[j] = double(j + 2);\n    for(size_t j = 0; j < s; j++)\n        u[j] = double(j + n + 2);\n    xu = join(x, u);\n    yz = g.Forward(0, xu);\n\n    // check y_0(x, u)\n    double y0 = u[0] + u[1];\n    ok       &= y0 == yz[0];\n\n    // check z_0 (x, u)\n    double z0 = x[0] + x[1];\n    ok       &= z0 == yz[1];\n\n    // check z_1 (x, u)\n    double z1 = x[1] + x[2];\n    ok       &= z1 == yz[2];\n\n\n    // --------------------------------------------------------------------\n    // check that y(x, a(x) ) == f(x)\n    CPPAD_TESTVECTOR(double) y(m);\n    y  = f.Forward(0, x);  // y  = f(x)\n    u  = a.Forward(0, x);  // u  = a(x)\n    xu = join(x, u);       // xu = ( x, a(x) )\n    yz = g.Forward(0, xu); // yz = ( y(x, a(x)), z(x, a(x)) )\n    ok &= yz[0] == y[0];\n\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/abs_normal/lp_box.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin lp_box.cpp}\n{xrst_spell\n    rl\n}\n\nabs_normal lp_box: Example and Test\n###################################\n\nProblem\n*******\nOur original problem is\n\n.. math::\n\n    \\begin{array}{rl}\n    \\R{minimize}      & x_0 - x_1 \\; \\R{w.r.t} \\; x \\in \\B{R}^2 \\\\\n    \\R{subject \\; to} & -2 \\leq x_0 \\leq +2 \\; \\R{and} \\; -2 \\leq x_1 \\leq +2\n    \\end{array}\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end lp_box.cpp}\n*/\n// BEGIN C++\n# include <limits>\n# include <cppad/utility/vector.hpp>\n# include \"lp_box.hpp\"\n\nbool lp_box(void)\n{   bool ok = true;\n    typedef CppAD::vector<double> vector;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    //\n    size_t n = 2;\n    size_t m = 0;\n    vector A(m), b(m), c(n), d(n), xout(n);\n    c[0] = +1.0;\n    c[1] = -1.0;\n    //\n    d[0] = +2.0;\n    d[1] = +2.0;\n    //\n    size_t level   = 0;\n    size_t maxitr  = 20;\n    //\n    ok &= CppAD::lp_box(level, A, b, c, d, maxitr, xout);\n    //\n    // check optimal value for x\n    ok &= std::fabs( xout[0] + 2.0 ) < eps99;\n    ok &= std::fabs( xout[1] - 2.0 ) < eps99;\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/abs_normal/lp_box.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_ABS_NORMAL_LP_BOX_HPP\n# define CPPAD_EXAMPLE_ABS_NORMAL_LP_BOX_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin lp_box}\n{xrst_spell\n    maxitr\n    rl\n    xout\n}\nabs_normal: Solve a Linear Program With Box Constraints\n#######################################################\n\nSyntax\n******\n| *ok* = ``lp_box`` (\n| |tab| *level* , *A* , *b* , *c* , *d* , *maxitr* , *xout*\n| )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN PROTOTYPE\n    // END PROTOTYPE\n}\n\nSource\n******\nThis following is a link to the source code for this example:\n:ref:`lp_box.hpp-name` .\n\nProblem\n*******\nWe are given\n:math:`A \\in \\B{R}^{m \\times n}`,\n:math:`b \\in \\B{R}^m`,\n:math:`c \\in \\B{R}^n`,\n:math:`d \\in \\B{R}^n`,\nThis routine solves the problem\n\n.. math::\n\n    \\begin{array}{rl}\n    \\R{minimize} &\n    c^T x \\; \\R{w.r.t} \\; x \\in \\B{R}^n\n    \\\\\n    \\R{subject \\; to} & A x + b \\leq 0 \\; \\R{and} \\; - d \\leq x \\leq d\n    \\end{array}\n\nVector\n******\nThe type *Vector* is a\nsimple vector with elements of type ``double`` .\n\nlevel\n*****\nThis value is less that or equal two.\nIf *level*  == 0 ,\nno tracing is printed.\nIf *level*  >= 1 ,\na trace of the ``lp_box`` operations is printed.\nIf *level*  >= 2 ,\nthe objective and primal variables :math:`x` are printed\nat each :ref:`simplex_method-name` iteration.\nIf *level*  == 3 ,\nthe simplex tableau is printed at each simplex iteration.\n\nA\n*\nThis is a :ref:`row-major<glossary@Row-major Representation>` representation\nof the matrix :math:`A` in the problem.\n\nb\n*\nThis is the vector :math:`b` in the problem.\n\nc\n*\nThis is the vector :math:`c` in the problem.\n\nd\n*\nThis is the vector :math:`d` in the problem.\nIf :math:`d_j` is infinity, there is no limit for the size of\n:math:`x_j`.\n\nmaxitr\n******\nThis is the maximum number of newton iterations to try before giving up\non convergence.\n\nxout\n****\nThis argument has size is *n* and\nthe input value of its elements does no matter.\nUpon return it is the primal variables\n:math:`x` corresponding to the problem solution.\n\nok\n**\nIf the return value *ok* is true, an optimal solution was found.\n{xrst_toc_hidden\n    example/abs_normal/lp_box.cpp\n    example/abs_normal/lp_box.xrst\n}\nExample\n*******\nThe file :ref:`lp_box.cpp-name` contains an example and test of\n``lp_box`` .\n\n{xrst_end lp_box}\n-----------------------------------------------------------------------------\n*/\n# include \"simplex_method.hpp\"\n\n// BEGIN C++\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n\n// BEGIN PROTOTYPE\ntemplate <class Vector>\nbool lp_box(\n    size_t        level   ,\n    const Vector& A       ,\n    const Vector& b       ,\n    const Vector& c       ,\n    const Vector& d       ,\n    size_t        maxitr  ,\n    Vector&       xout    )\n// END PROTOTYPE\n{   double inf = std::numeric_limits<double>::infinity();\n    //\n    size_t m = b.size();\n    size_t n = c.size();\n    //\n    CPPAD_ASSERT_KNOWN(\n        level <= 3, \"lp_box: level is greater than 3\");\n    CPPAD_ASSERT_KNOWN(\n        size_t(A.size()) == m * n, \"lp_box: size of A is not m * n\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t(d.size()) == n, \"lp_box: size of d is not n\"\n    );\n    if( level > 0 )\n    {   std::cout << \"start lp_box\\n\";\n        CppAD::abs_print_mat(\"A\", m, n, A);\n        CppAD::abs_print_mat(\"b\", m, 1, b);\n        CppAD::abs_print_mat(\"c\", n, 1, c);\n        CppAD::abs_print_mat(\"d\", n, 1, d);\n    }\n    //\n    // count number of limits\n    size_t n_limit = 0;\n    for(size_t j = 0; j < n; j++)\n    {   if( d[j] < inf )\n            n_limit += 1;\n    }\n    //\n    // A_simplex and b_simplex define the extended constraints\n    Vector A_simplex((m + 2 * n_limit) * (2 * n) ), b_simplex(m + 2 * n_limit);\n    for(size_t i = 0; i < size_t(A_simplex.size()); i++)\n        A_simplex[i] = 0.0;\n    //\n    // put A * x + b <= 0 in A_simplex, b_simplex\n    for(size_t i = 0; i < m; i++)\n    {   b_simplex[i] = b[i];\n        for(size_t j = 0; j < n; j++)\n        {   // x_j^+ coefficient (positive component)\n            A_simplex[i * (2 * n) + 2 * j]     =   A[i * n + j];\n            // x_j^- coefficient (negative component)\n            A_simplex[i * (2 * n) + 2 * j + 1] = - A[i * n + j];\n        }\n    }\n    //\n    // put | x_j | <= d_j in A_simplex, b_simplex\n    size_t i_limit = 0;\n    for(size_t j = 0; j < n; j++) if( d[j] < inf )\n    {\n        // x_j^+ <= d_j constraint\n        b_simplex[ m + 2 * i_limit]                         = - d[j];\n        A_simplex[(m + 2 * i_limit) * (2 * n) + 2 * j]      = 1.0;\n        //\n        // x_j^- <= d_j constraint\n        b_simplex[ m + 2 * i_limit + 1]                         = - d[j];\n        A_simplex[(m + 2 * i_limit + 1) * (2 * n) + 2 * j + 1]  = 1.0;\n        //\n        ++i_limit;\n    }\n    //\n    // c_simples\n    Vector c_simplex(2 * n);\n    for(size_t j = 0; j < n; j++)\n    {   // x_j+ component\n        c_simplex[2 * j]     = c[j];\n        // x_j^- component\n        c_simplex[2 * j + 1] = - c[j];\n    }\n    size_t level_simplex = 0;\n    if( level >= 2 )\n        level_simplex = level - 1;\n    //\n    Vector x_simplex(2 * n);\n    bool ok = CppAD::simplex_method(\n        level_simplex, A_simplex, b_simplex, c_simplex, maxitr, x_simplex\n    );\n    for(size_t j = 0; j < n; j++)\n        xout[j] = x_simplex[2 * j] - x_simplex[2 * j + 1];\n    if( level > 0 )\n    {   CppAD::abs_print_mat(\"xout\", n, 1, xout);\n        if( ok )\n            std::cout << \"end lp_box: ok = true\\n\";\n        else\n            std::cout << \"end lp_box: ok = false\\n\";\n    }\n    return ok;\n}\n\n} // END_CPPAD_NAMESPACE\n// END C++\n\n# endif\n"
  },
  {
    "path": "example/abs_normal/lp_box.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin lp_box.hpp}\n\nlp_box Source Code\n##################\n\n{xrst_literal\n    example/abs_normal/lp_box.hpp\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end lp_box.hpp}\n"
  },
  {
    "path": "example/abs_normal/min_nso_linear.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin min_nso_linear.cpp}\n\nabs_normal min_nso_linear: Example and Test\n###########################################\n\nPurpose\n*******\nWe minimize the function\n:math:`f : \\B{R}^3 \\rightarrow \\B{R}` defined by\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    f( x_0, x_1, x_2  ) & = & x_0^2 + 2 (x_0 + x_1)^2 + | x_2 |\n    \\end{eqnarray}\n\nDiscussion\n**********\nThis routine uses :ref:`abs_min_linear-name` which uses :ref:`lp_box-name` ,\na linear programming algorithm.\nIt is mean to be compared with :ref:`min_nso_quad.cpp-name` which uses\na quadratic programing algorithm for the same problem.\nTo see this comparison, set *level*  = 1 is both examples.\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end min_nso_linear.cpp}\n-------------------------------------------------------------------------------\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n# include \"min_nso_linear.hpp\"\n\nbool min_nso_linear(void)\n{   bool ok = true;\n    //\n    using CppAD::AD;\n    using CppAD::ADFun;\n    //\n    typedef CPPAD_TESTVECTOR(size_t)       s_vector;\n    typedef CPPAD_TESTVECTOR(double)       d_vector;\n    typedef CPPAD_TESTVECTOR( AD<double> ) ad_vector;\n    //\n    size_t level = 0;    // level of tracing\n    size_t n     = 3;    // size of x\n    size_t m     = 1;    // size of y\n    size_t s     = 1;    // number of data points and absolute values\n    //\n    // start recording the function f(x)\n    ad_vector ax(n), ay(m);\n    for(size_t j = 0; j < n; j++)\n        ax[j] = double(j + 1);\n    Independent( ax );\n    //\n    ay[0]  =  ax[0] * ax[0];\n    ay[0] += 2.0 * (ax[0] + ax[1]) * (ax[0] + ax[1]);\n    ay[0] += fabs( ax[2] );\n    ADFun<double> f(ax, ay);\n    //\n    // create its abs_normal representation in g, a\n    ADFun<double> g, a;\n    f.abs_normal_fun(g, a);\n\n    // check dimension of domain and range space for g\n    ok &= g.Domain() == n + s;\n    ok &= g.Range()  == m + s;\n\n    // check dimension of domain and range space for a\n    ok &= a.Domain() == n;\n    ok &= a.Range()  == s;\n\n    // epsilon\n    d_vector epsilon(2);\n    double eps = 1e-3;\n    epsilon[0] = eps;\n    epsilon[1] = eps;\n\n    // maxitr\n    s_vector maxitr(3);\n    maxitr[0] = 100;\n    maxitr[1] = 20;\n    maxitr[2] = 20;\n\n    // b_in\n    double b_in = 1.0;\n\n    // call min_nso_linear\n    d_vector x_in(n), x_out(n);\n    for(size_t j = 0; j < n; j++)\n        x_in[j]  = double(j + 1);\n\n    //\n    ok &= CppAD::min_nso_linear(\n        level, g, a, epsilon, maxitr, b_in, x_in, x_out\n    );\n    //\n    for(size_t j = 0; j < n; j++)\n        ok &= std::fabs( x_out[j] ) < eps;\n\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/abs_normal/min_nso_linear.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_ABS_NORMAL_MIN_NSO_LINEAR_HPP\n# define CPPAD_EXAMPLE_ABS_NORMAL_MIN_NSO_LINEAR_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin min_nso_linear}\n{xrst_spell\n    dbl\n    maxitr\n}\nNon-Smooth Optimization Using Abs-normal Linear Approximations\n##############################################################\n\nSyntax\n******\n| *ok* = ``min_nso_linear`` (\n| |tab| *level* , *g* , *a* , *epsilon* , *maxitr* , *b_in* , *x_in* , *x_out*\n| )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN PROTOTYPE\n    // END PROTOTYPE\n}\n\nSource\n******\nThis following is a link to the source code for this example:\n:ref:`min_nso_linear.hpp-name` .\n\nPurpose\n*******\nGiven a current that abs-normal representation\n:ref:`abs_normal_fun@g` , :ref:`abs_normal_fun@a` ,\nfor a function :math:`f(x)`,\nthis routine minimizes :math:`f(x)`.\n\nDblVector\n*********\nis a :ref:`SimpleVector-name` class with elements of type ``double`` .\n\nSizeVector\n**********\nis a :ref:`SimpleVector-name` class with elements of type ``size_t`` .\n\nf\n*\nWe use the notation *f* for the original function; see\n:ref:`abs_normal_fun@f` .\n\nn\n=\nWe use *n* to denote the dimension of the domain for *f* ; i.e.,\n*f* . ``Domain`` () .\n\nm\n=\nWe use *m* to denote the dimension of the range for *f* ; i.e.,\n*f* . ``Range`` () .\nThis must be equal to one.\n\ns\n=\nWe use\n:ref:`abs_normal_fun@f@s` to denote the number absolute terms in *f* .\n\nlevel\n*****\nThis value is less that or equal 5.\nIf *level*  == 0 ,\nno tracing of the optimization is printed.\nIf *level*  >= 1 ,\na trace of each iteration of ``min_nso_linear`` is printed.\nIf *level*  >= 2 ,\na trace of each iteration of the ``abs_min_linear`` sub-problem is printed.\nIf *level*  >= 3 ,\na trace of the :ref:`lp_box-name` sub-problem is printed.\nIf *level*  >= 4 ,\na trace of the objective and primal variables :math:`x` are printed\nat each :ref:`simplex_method-name` iteration.\nIf *level*  == 5 ,\nthe simplex tableau is printed at each simplex iteration.\n\ng\n*\nThis is the function :ref:`abs_normal_fun@g`\nin the abs-normal representation of *f* .\n\na\n*\nThis is the function :ref:`abs_normal_fun@a`\nin the abs-normal representation of *f* .\n\nepsilon\n*******\nThis is a vector with size 2.\nThe value *epsilon* [0] is convergence criteria in terms\nof the infinity norm of the difference of *x_out*\nbetween iterations.\nThe value *epsilon* [1] is convergence criteria in terms\nof the derivative of :math:`f(x)`.\nThis derivative is actually the average of the directional derivative\nin the direction of the sub-problem minimizer.\n\nmaxitr\n******\nThis is a vector with size 3.\nThe value *maxitr* [0] is the maximum number of\n``min_nso_linear`` iterations to try before giving up on convergence.\nThe value *maxitr* [1] is the maximum number of iterations in the\n``abs_min_linear`` sub-problem.\nThe value *maxitr* [2] is the maximum number of iterations in\nthe :ref:`simplex_method<simplex_method@maxitr>` sub-problems.\n\nb_in\n****\nThis the initial bound on the trust region size.\nTo be specific, if :math:`b` is the current trust region size,\nat each iteration affine approximation is minimized with respect to\n:math:`\\Delta x` and subject to\n\n.. math::\n\n    -b \\leq \\Delta x_j \\leq b\n\nfor *j* = 0 , ..., *n* ``-1`` .\nIt must hold that *b_in* > *epsilon* [0] .\n\nx_in\n****\nThis vector *x_out* has size *n* .\nIt is the starting point for the optimization procedure; i.e.,\nthe ``min_nso_linear`` iterations.\n\nx_out\n*****\nThis vector *x_out* has size *n* .\nThe input value of its elements does not matter.\nUpon return,\nit is the approximate minimizer\nof the abs-normal approximation for :math:`f(x)` over the trust region\nis :math:`x = \\hat{x} + \\Delta x`.\n{xrst_toc_hidden\n    example/abs_normal/min_nso_linear.cpp\n    example/abs_normal/min_nso_linear.xrst\n}\nExample\n*******\nThe file :ref:`min_nso_linear.cpp-name` contains an example and test of\n``min_nso_linear`` .\n\n{xrst_end min_nso_linear}\n-----------------------------------------------------------------------------\n*/\n# include <cppad/cppad.hpp>\n# include \"abs_min_linear.hpp\"\n# include \"abs_eval.hpp\"\n\n// BEGIN C++\nnamespace {\n    CPPAD_TESTVECTOR(double) min_nso_linear_join(\n        const CPPAD_TESTVECTOR(double)& x ,\n        const CPPAD_TESTVECTOR(double)& u )\n    {   size_t n = x.size();\n        size_t s = u.size();\n        CPPAD_TESTVECTOR(double) xu(n + s);\n        for(size_t j = 0; j < n; j++)\n            xu[j] = x[j];\n        for(size_t j = 0; j < s; j++)\n            xu[n + j] = u[j];\n        return xu;\n    }\n}\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n\n// BEGIN PROTOTYPE\ntemplate <class DblVector, class SizeVector>\nbool min_nso_linear(\n    size_t           level     ,\n    ADFun<double>&   g         ,\n    ADFun<double>&   a         ,\n    const DblVector& epsilon   ,\n    SizeVector       maxitr    ,\n    double           b_in      ,\n    const DblVector& x_in      ,\n    DblVector&       x_out     )\n// END PROTOTYPE\n{\n    using std::fabs;\n    //\n    // number of absolute value terms\n    size_t s  = a.Range();\n    //\n    // size of domain for f\n    size_t n  = g.Domain() - s;\n    //\n    // size of range space for f\n    size_t m = g.Range() - s;\n    //\n    CPPAD_ASSERT_KNOWN(\n        level <= 5,\n        \"min_nso_linear: level is not less that or equal 5\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t(epsilon.size()) == 2,\n        \"min_nso_linear: size of epsilon not equal to 2\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t(maxitr.size()) == 3,\n        \"min_nso_linear: size of maxitr not equal to 3\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        g.Domain() > s && g.Range() > s,\n        \"min_nso_linear: g, a is not an abs-normal representation\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        m == 1,\n        \"min_nso_linear: m is not equal to 1\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t(x_in.size()) == n,\n        \"min_nso_linear: size of x_in not equal to n\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t(x_out.size()) == n,\n        \"min_nso_linear: size of x_out not equal to n\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        epsilon[0] < b_in,\n        \"min_nso_linear: b_in <= epsilon[0]\"\n    );\n    if( level > 0 )\n    {   std::cout << \"start min_nso_linear\\n\";\n        std::cout << \"b_in = \" << b_in << \"\\n\";\n        CppAD::abs_print_mat(\"x_in\", n, 1, x_in);\n    }\n    // level in abs_min_linear sub-problem\n    size_t level_tilde = 0;\n    if( level > 0 )\n        level_tilde = level - 1;\n    //\n    // maxitr in abs_min_linear sub-problem\n    SizeVector maxitr_tilde(2);\n    maxitr_tilde[0] = maxitr[1];\n    maxitr_tilde[1] = maxitr[2];\n    //\n    // epsilon in abs_min_linear sub-problem\n    DblVector eps_tilde(2);\n    eps_tilde[0] = epsilon[0] / 10.;\n    eps_tilde[1] = epsilon[1] / 10.;\n    //\n    // current bound\n    double b_cur = b_in;\n    //\n    // initialize the current x\n    x_out = x_in;\n    //\n    // value of a(x) at current x\n    DblVector a_cur = a.Forward(0, x_out);\n    //\n    // (x_out, a_cur)\n    DblVector xu_cur = min_nso_linear_join(x_out, a_cur);\n    //\n    // value of g[ x_cur, a_cur ]\n    DblVector g_cur = g.Forward(0, xu_cur);\n    //\n    for(size_t itr = 0; itr < maxitr[0]; itr++)\n    {\n        // Jacobian of g[ x_cur, a_cur ]\n        DblVector g_jac = g.Jacobian(xu_cur);\n        //\n        // bound in abs_min_linear sub-problem\n        DblVector bound_tilde(n);\n        for(size_t j = 0; j < n; j++)\n            bound_tilde[j] = b_cur;\n        //\n        DblVector delta_x(n);\n        bool ok = abs_min_linear(\n            level_tilde, n, m, s,\n            g_cur, g_jac, bound_tilde, eps_tilde, maxitr_tilde, delta_x\n        );\n        if( ! ok )\n        {   if( level > 0 )\n                std::cout << \"end min_nso_linear: abs_min_linear failed\\n\";\n            return false;\n        }\n        //\n        // new candidate value for x\n        DblVector x_new(n);\n        double max_delta_x = 0.0;\n        for(size_t j = 0; j < n; j++)\n        {   x_new[j] = x_out[j] + delta_x[j];\n            max_delta_x = std::max(max_delta_x, std::fabs( delta_x[j] ) );\n        }\n        //\n        if( max_delta_x < b_cur && max_delta_x < epsilon[0] )\n        {   if( level > 0 )\n                std::cout << \"end min_nso_linear: delta_x is near zero\\n\";\n            return true;\n        }\n        // value of abs-normal approximation at minimizer\n        DblVector g_tilde = CppAD::abs_eval(n, m, s, g_cur, g_jac, delta_x);\n        //\n        double derivative = (g_tilde[0] - g_cur[0]) / max_delta_x;\n        CPPAD_ASSERT_UNKNOWN( derivative <= 0.0 )\n        if( - epsilon[1] < derivative )\n        {   if( level > 0 )\n                std::cout << \"end min_nso_linear: derivative near zero\\n\";\n            return true;\n        }\n        //\n        // value of a(x) at new x\n        DblVector a_new = a.Forward(0, x_new);\n        //\n        // (x_new, a_new)\n        DblVector xu_new = min_nso_linear_join(x_new, a_new);\n        //\n        // value of g[ x_new, a_new ]\n        DblVector g_new = g.Forward(0, xu_new);\n        //\n        //\n        // check for descent of objective\n        double rate_new = (g_new[0] - g_cur[0]) / max_delta_x;\n        if( - epsilon[1] < rate_new )\n        {   // did not get sufficient descent\n            b_cur /= 2.0;\n            if( level > 0 )\n                std::cout << \"itr = \" << itr\n                << \", rate_new = \" << rate_new\n                << \", b_cur = \" << b_cur << \"\\n\";\n            //\n        }\n        else\n        {   // got sufficient descent so accept candidate for x\n            x_out  = x_new;\n            a_cur  = a_new;\n            g_cur  = g_new;\n            xu_cur = xu_new;\n            //\n            if( level >  0 )\n            {   std::cout << \"itr = \" << itr\n                << \", derivative = \"<< derivative\n                << \", max_delta_x = \"<< max_delta_x\n                << \", objective = \" << g_cur[0] << \"\\n\";\n                abs_print_mat(\"x_out\", n, 1, x_out);\n            }\n        }\n    }\n    if( level > 0 )\n        std::cout << \"end min_nso_linear: maximum number of iterations exceeded\\n\";\n    return false;\n}\n} // END_CPPAD_NAMESPACE\n// END C++\n\n# endif\n"
  },
  {
    "path": "example/abs_normal/min_nso_linear.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin min_nso_linear.hpp}\n\nmin_nso_linear Source Code\n##########################\n\n{xrst_literal\n    example/abs_normal/min_nso_linear.hpp\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end min_nso_linear.hpp}\n"
  },
  {
    "path": "example/abs_normal/min_nso_quad.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin min_nso_quad.cpp}\n\nabs_normal min_nso_quad: Example and Test\n#########################################\n\nPurpose\n*******\nWe minimize the function\n:math:`f : \\B{R}^3 \\rightarrow \\B{R}` defined by\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    f( x_0, x_1, x_2  ) & = & x_0^2 + 2 (x_0 + x_1)^2 + | x_2 |\n    \\end{eqnarray}\n\nDiscussion\n**********\nThis routine uses :ref:`abs_min_quad-name` which uses :ref:`qp_box-name` ,\na quadratic programming algorithm.\nIt is mean to be compared with :ref:`min_nso_linear.cpp-name` which uses\na linear programing algorithm for the same problem.\nTo see this comparison, set *level*  = 1 is both examples.\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end min_nso_quad.cpp}\n-------------------------------------------------------------------------------\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n# include \"min_nso_quad.hpp\"\n\nbool min_nso_quad(void)\n{   bool ok = true;\n    //\n    using CppAD::AD;\n    using CppAD::ADFun;\n    //\n    typedef CPPAD_TESTVECTOR(size_t)       s_vector;\n    typedef CPPAD_TESTVECTOR(double)       d_vector;\n    typedef CPPAD_TESTVECTOR( AD<double> ) ad_vector;\n    //\n    size_t level = 0;    // level of tracing\n    size_t n     = 3;    // size of x\n    size_t m     = 1;    // size of y\n    size_t s     = 1;    // number of data points and absolute values\n    //\n    // start recording the function f(x)\n    ad_vector ax(n), ay(m);\n    for(size_t j = 0; j < n; j++)\n        ax[j] = double(j + 1);\n    Independent( ax );\n    //\n    ay[0]  =  ax[0] * ax[0];\n    ay[0] += 2.0 * (ax[0] + ax[1]) * (ax[0] + ax[1]);\n    ay[0] += fabs( ax[2] );\n    ADFun<double> f(ax, ay);\n    //\n    // create its abs_normal representation in g, a\n    ADFun<double> g, a;\n    f.abs_normal_fun(g, a);\n\n    // check dimension of domain and range space for g\n    ok &= g.Domain() == n + s;\n    ok &= g.Range()  == m + s;\n\n    // check dimension of domain and range space for a\n    ok &= a.Domain() == n;\n    ok &= a.Range()  == s;\n\n    // epsilon\n    d_vector epsilon(2);\n    double eps = 1e-3;\n    epsilon[0] = eps;\n    epsilon[1] = eps;\n\n    // maxitr\n    s_vector maxitr(3);\n    maxitr[0] = 100;\n    maxitr[1] = 20;\n    maxitr[2] = 20;\n\n    // b_in\n    double b_in = 1.0;\n\n    // call min_nso_quad\n    d_vector x_in(n), x_out(n);\n    for(size_t j = 0; j < n; j++)\n        x_in[j]  = double(j + 1);\n\n    //\n    ok &= CppAD::min_nso_quad(\n        level, f, g, a, epsilon, maxitr, b_in, x_in, x_out\n    );\n    //\n    for(size_t j = 0; j < n; j++)\n        ok &= std::fabs( x_out[j] ) < eps;\n\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/abs_normal/min_nso_quad.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_ABS_NORMAL_MIN_NSO_QUAD_HPP\n# define CPPAD_EXAMPLE_ABS_NORMAL_MIN_NSO_QUAD_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin min_nso_quad}\n{xrst_spell\n    dbl\n    maxitr\n}\nNon-Smooth Optimization Using Abs-normal Quadratic Approximations\n#################################################################\n\nSyntax\n******\n| *ok* = ``min_nso_quad`` (\n| |tab| *level* , *f* , *g* , *a* , *epsilon* , *maxitr* , *b_in* , *x_in* , *x_out*\n| )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN PROTOTYPE\n    // END PROTOTYPE\n}\n\nSource\n******\nThis following is a link to the source code for this example:\n:ref:`min_nso_quad.hpp-name` .\n\nPurpose\n*******\nGiven a current that abs-normal representation\n:ref:`abs_normal_fun@g` , :ref:`abs_normal_fun@a` ,\nfor a function :math:`f(x)`,\nthis routine minimizes :math:`f(x)`.\n\nDblVector\n*********\nis a :ref:`SimpleVector-name` class with elements of type ``double`` .\n\nSizeVector\n**********\nis a :ref:`SimpleVector-name` class with elements of type ``size_t`` .\n\nlevel\n*****\nThis value is less that or equal 5.\nIf *level*  == 0 ,\nno tracing of the optimization is printed.\nIf *level*  >= 1 ,\na trace of each iteration of ``min_nso_quad`` is printed.\nIf *level*  >= 2 ,\na trace of each iteration of the ``abs_min_quad`` sub-problem is printed.\nIf *level*  >= 3 ,\na trace of the :ref:`qp_box-name` sub-problem is printed.\nIf *level*  >= 4 ,\na trace of the :ref:`qp_interior-name` sub-problem is printed.\n\nf\n*\nThis is the original function for the abs-normal form; see\n:ref:`abs_normal_fun@f` .\n\nn\n=\nWe use *n* to denote the dimension of the domain for *f* ; i.e.,\n*f* . ``Domain`` () .\n\nm\n=\nWe use *m* to denote the dimension of the range for *f* ; i.e.,\n*f* . ``Range`` () .\nThis must be equal to one.\n\ns\n=\nWe use\n:ref:`abs_normal_fun@f@s` to denote the number absolute terms in *f* .\n\ng\n*\nThis is the function :ref:`abs_normal_fun@g`\nin the abs-normal representation of *f* .\n\na\n*\nThis is the function :ref:`abs_normal_fun@a`\nin the abs-normal representation of *f* .\n\nepsilon\n*******\nThis is a vector with size 2.\nThe value *epsilon* [0] is convergence criteria in terms\nof the infinity norm of the difference of *x_out*\nbetween iterations.\nThe value *epsilon* [1] is convergence criteria in terms\nof the derivative of :math:`f(x)`.\nThis derivative is actually the average of the directional derivative\nin the direction of the sub-problem minimizer.\n\nmaxitr\n******\nThis is a vector with size 3.\nThe value *maxitr* [0] is the maximum number of\n``min_nso_quad`` iterations to try before giving up on convergence.\nThe value *maxitr* [1] is the maximum number of iterations in the\n``abs_min_quad`` sub-problem.\nThe value *maxitr* [2] is the maximum number of iterations in\nthe :ref:`qp_interior<qp_interior@maxitr>` sub-problems.\n\nb_in\n****\nThis the initial bound on the trust region size.\nTo be specific, if :math:`b` is the current trust region size,\nat each iteration affine approximation is minimized with respect to\n:math:`\\Delta x` and subject to\n\n.. math::\n\n    -b \\leq \\Delta x_j \\leq b\n\nfor *j* = 0 , ..., *n* ``-1`` .\nIt must hold that *b_in* > *epsilon* [0] .\n\nx_in\n****\nThis vector *x_out* has size *n* .\nIt is the starting point for the optimization procedure; i.e.,\nthe ``min_nso_quad`` iterations.\n\nx_out\n*****\nThis vector *x_out* has size *n* .\nThe input value of its elements does not matter.\nUpon return,\nit is the approximate minimizer\nof the abs-normal approximation for :math:`f(x)` over the trust region\nis :math:`x = \\hat{x} + \\Delta x`.\n{xrst_toc_hidden\n    example/abs_normal/min_nso_quad.cpp\n    example/abs_normal/min_nso_quad.xrst\n}\nExample\n*******\nThe file :ref:`min_nso_quad.cpp-name` contains an example and test of\n``min_nso_quad`` .\n\n{xrst_end min_nso_quad}\n-----------------------------------------------------------------------------\n*/\n# include <cppad/cppad.hpp>\n# include \"abs_min_quad.hpp\"\n# include \"abs_eval.hpp\"\n\n// BEGIN C++\nnamespace {\n    CPPAD_TESTVECTOR(double) min_nso_quad_join(\n        const CPPAD_TESTVECTOR(double)& x ,\n        const CPPAD_TESTVECTOR(double)& u )\n    {   size_t n = x.size();\n        size_t s = u.size();\n        CPPAD_TESTVECTOR(double) xu(n + s);\n        for(size_t j = 0; j < n; j++)\n            xu[j] = x[j];\n        for(size_t j = 0; j < s; j++)\n            xu[n + j] = u[j];\n        return xu;\n    }\n}\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n\n// BEGIN PROTOTYPE\ntemplate <class DblVector, class SizeVector>\nbool min_nso_quad(\n    size_t           level     ,\n    ADFun<double>&   f         ,\n    ADFun<double>&   g         ,\n    ADFun<double>&   a         ,\n    const DblVector& epsilon   ,\n    SizeVector       maxitr    ,\n    double           b_in      ,\n    const DblVector& x_in      ,\n    DblVector&       x_out     )\n// END PROTOTYPE\n{\n    using std::fabs;\n    //\n    // number of absolute value terms\n    size_t s  = a.Range();\n    //\n    // size of domain for f\n    size_t n  = f.Domain();\n    //\n    // size of range space for f\n    size_t m = f.Range();\n    //\n    CPPAD_ASSERT_KNOWN( g.Domain() == n + s,\n        \"min_nso_quad: (g, a) is not an abs-normal for for f\"\n    );\n    CPPAD_ASSERT_KNOWN( g.Range() == m + s,\n        \"min_nso_quad: (g, a) is not an abs-normal for for f\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        level <= 5,\n        \"min_nso_quad: level is not less that or equal 5\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t(epsilon.size()) == 2,\n        \"min_nso_quad: size of epsilon not equal to 2\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t(maxitr.size()) == 3,\n        \"min_nso_quad: size of maxitr not equal to 3\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        g.Domain() > s && g.Range() > s,\n        \"min_nso_quad: g, a is not an abs-normal representation\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        m == 1,\n        \"min_nso_quad: m is not equal to 1\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t(x_in.size()) == n,\n        \"min_nso_quad: size of x_in not equal to n\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t(x_out.size()) == n,\n        \"min_nso_quad: size of x_out not equal to n\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        epsilon[0] < b_in,\n        \"min_nso_quad: b_in <= epsilon[0]\"\n    );\n    if( level > 0 )\n    {   std::cout << \"start min_nso_quad\\n\";\n        std::cout << \"b_in = \" << b_in << \"\\n\";\n        CppAD::abs_print_mat(\"x_in\", n, 1, x_in);\n    }\n    // level in abs_min_quad sub-problem\n    size_t level_tilde = 0;\n    if( level > 0 )\n        level_tilde = level - 1;\n    //\n    // maxitr in abs_min_quad sub-problem\n    SizeVector maxitr_tilde(2);\n    maxitr_tilde[0] = maxitr[1];\n    maxitr_tilde[1] = maxitr[2];\n    //\n    // epsilon in abs_min_quad sub-problem\n    DblVector eps_tilde(2);\n    eps_tilde[0] = epsilon[0] / 10.;\n    eps_tilde[1] = epsilon[1] / 10.;\n    //\n    // current bound\n    double b_cur = b_in;\n    //\n    // initialize the current x\n    x_out = x_in;\n    //\n    // value of a(x) at current x\n    DblVector a_cur = a.Forward(0, x_out);\n    //\n    // (x_out, a_cur)\n    DblVector xu_cur = min_nso_quad_join(x_out, a_cur);\n    //\n    // value of g[ x_cur, a_cur ]\n    DblVector g_cur = g.Forward(0, xu_cur);\n    //\n    for(size_t itr = 0; itr < maxitr[0]; itr++)\n    {\n        // Jacobian of g[ x_cur, a_cur ]\n        DblVector g_jac = g.Jacobian(xu_cur);\n        //\n        // Hessian at x_cur\n        DblVector f_hes = f.Hessian(x_out, 0);\n        //\n        // bound in abs_min_quad sub-problem\n        DblVector bound_tilde(n);\n        for(size_t j = 0; j < n; j++)\n            bound_tilde[j] = b_cur;\n        //\n        DblVector delta_x(n);\n        bool ok = abs_min_quad(\n            level_tilde, n, m, s,\n            g_cur, g_jac, f_hes, bound_tilde, eps_tilde, maxitr_tilde, delta_x\n        );\n        if( ! ok )\n        {   if( level > 0 )\n                std::cout << \"end min_nso_quad: abs_min_quad failed\\n\";\n            return false;\n        }\n        //\n        // new candidate value for x\n        DblVector x_new(n);\n        double max_delta_x = 0.0;\n        for(size_t j = 0; j < n; j++)\n        {   x_new[j] = x_out[j] + delta_x[j];\n            max_delta_x = std::max(max_delta_x, std::fabs( delta_x[j] ) );\n        }\n        //\n        if( max_delta_x < 0.75 * b_cur && max_delta_x < epsilon[0] )\n        {   if( level > 0 )\n                std::cout << \"end min_nso_quad: delta_x is near zero\\n\";\n            return true;\n        }\n        // value of abs-normal approximation at minimizer\n        DblVector g_tilde = CppAD::abs_eval(n, m, s, g_cur, g_jac, delta_x);\n        //\n        double derivative = (g_tilde[0] - g_cur[0]) / max_delta_x;\n        CPPAD_ASSERT_UNKNOWN( derivative <= 0.0 )\n        if( - epsilon[1] < derivative )\n        {   if( level > 0 )\n                std::cout << \"end min_nso_quad: derivative near zero\\n\";\n            return true;\n        }\n        //\n        // value of a(x) at new x\n        DblVector a_new = a.Forward(0, x_new);\n        //\n        // (x_new, a_new)\n        DblVector xu_new = min_nso_quad_join(x_new, a_new);\n        //\n        // value of g[ x_new, a_new ]\n        DblVector g_new = g.Forward(0, xu_new);\n        //\n        // check for descent of objective\n        double rate_new = (g_new[0] - g_cur[0]) / max_delta_x;\n        if( - epsilon[1] < rate_new )\n        {   // did not get sufficient descent\n            b_cur /= 2.0;\n            if( level > 0 )\n                std::cout << \"itr = \" << itr\n                << \", rate_new = \" << rate_new\n                << \", b_cur = \" << b_cur << \"\\n\";\n            //\n        }\n        else\n        {   // got sufficient descent so accept candidate for x\n            x_out  = x_new;\n            a_cur  = a_new;\n            g_cur  = g_new;\n            xu_cur = xu_new;\n            //\n            if( level >  0 )\n            {   std::cout << \"itr = \" << itr\n                << \", derivative = \"<< derivative\n                << \", max_delta_x = \"<< max_delta_x\n                << \", objective = \" << g_cur[0] << \"\\n\";\n                abs_print_mat(\"x_out\", n, 1, x_out);\n            }\n        }\n    }\n    if( level > 0 )\n        std::cout << \"end min_nso_quad: maximum number of iterations exceeded\\n\";\n    return false;\n}\n} // END_CPPAD_NAMESPACE\n// END C++\n\n# endif\n"
  },
  {
    "path": "example/abs_normal/min_nso_quad.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin min_nso_quad.hpp}\n\nmin_nso_quad Source Code\n########################\n\n{xrst_literal\n    example/abs_normal/min_nso_quad.hpp\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end min_nso_quad.hpp}\n"
  },
  {
    "path": "example/abs_normal/qp_box.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin qp_box.cpp}\n{xrst_spell\n    rl\n}\n\nabs_normal qp_box: Example and Test\n###################################\n\nProblem\n*******\nOur original problem is\n\n.. math::\n\n    \\begin{array}{rl}\n    \\R{minimize}      & x_0 - x_1 \\; \\R{w.r.t} \\; x \\in \\B{R}^2 \\\\\n    \\R{subject \\; to} & -2 \\leq x_0 \\leq +2 \\; \\R{and} \\; -2 \\leq x_1 \\leq +2\n    \\end{array}\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end qp_box.cpp}\n*/\n// BEGIN C++\n# include <limits>\n# include <cppad/utility/vector.hpp>\n# include \"qp_box.hpp\"\n\nbool qp_box(void)\n{   bool ok = true;\n    typedef CppAD::vector<double> vector;\n    //\n    size_t n = 2;\n    size_t m = 0;\n    vector a(n), b(n), c(m), C(m), g(n), G(n*n), xin(n), xout(n);\n    a[0] = -2.0;\n    a[1] = -2.0;\n    b[0] = +2.0;\n    b[1] = +2.0;\n    g[0] = +1.0;\n    g[1] = -1.0;\n    for(size_t i = 0; i < n * n; i++)\n        G[i] = 0.0;\n    //\n    // (0, 0) is feasible.\n    xin[0] = 0.0;\n    xin[1] = 0.0;\n    //\n    size_t level   = 0;\n    double epsilon = 99.0 * std::numeric_limits<double>::epsilon();\n    size_t maxitr  = 20;\n    //\n    ok &= CppAD::qp_box(\n        level, a, b, c, C, g, G, epsilon, maxitr, xin, xout\n    );\n    //\n    // check optimal value for x\n    ok &= std::fabs( xout[0] + 2.0 ) < epsilon;\n    ok &= std::fabs( xout[1] - 2.0 ) < epsilon;\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/abs_normal/qp_box.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_ABS_NORMAL_QP_BOX_HPP\n# define CPPAD_EXAMPLE_ABS_NORMAL_QP_BOX_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin qp_box}\n{xrst_spell\n    maxitr\n    rl\n    xin\n    xout\n}\nabs_normal: Solve a Quadratic Program With Box Constraints\n##########################################################\n\nSyntax\n******\n| *ok* = ``qp_box`` (\n| |tab| *level* , *a* , *b* , *c* , *C* , *g* , *G* , *epsilon* , *maxitr* , *xin* , *xout*\n| )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN PROTOTYPE\n    // END PROTOTYPE\n}\n\nSource\n******\nThis following is a link to the source code for this example:\n:ref:`qp_box.hpp-name` .\n\nPurpose\n*******\nThis routine could be used to create a version of :ref:`abs_min_linear-name`\nthat solved quadratic programs (instead of linear programs).\n\nProblem\n*******\nWe are given\n:math:`a \\in \\B{R}^n`,\n:math:`b \\in \\B{R}^n`,\n:math:`c \\in \\B{R}^m`,\n:math:`C \\in \\B{R}^{m \\times n}`,\n:math:`g \\in \\B{R}^n`,\n:math:`G \\in \\B{R}^{n \\times n}`,\nwhere :math:`G` is positive semi-definite.\nThis routine solves the problem\n\n.. math::\n\n    \\begin{array}{rl}\n    \\R{minimize} &\n    \\frac{1}{2} x^T G x + g^T x \\; \\R{w.r.t} \\; x \\in \\B{R}^n\n    \\\\\n    \\R{subject \\; to} & C x + c \\leq 0 \\; \\R{and} \\; a \\leq x \\leq b\n    \\end{array}\n\nThe matrix :math:`G + C^T C` must be positive definite on components\nof the vector :math:`x` where the lower limit minus infinity\nand the upper limit is plus infinity; see *a* and *b* below.\n\nVector\n******\nThe type *Vector* is a\nsimple vector with elements of type ``double`` .\n\nlevel\n*****\nThis value is less that or equal two.\nIf *level*  == 0 ,\nno tracing is printed.\nIf *level*  >= 1 ,\na trace of the ``qp_box`` operations is printed.\nIf *level*  == 2 ,\na trace of the :ref:`qp_interior-name` sub-problem is printed.\n\na\n*\nThis is the vector of lower limits for :math:`x` in the problem.\nIf *a* [ *j* ] is minus infinity, there is no lower limit\nfor :math:`x_j`.\n\nb\n*\nThis is the vector of upper limits for :math:`x` in the problem.\nIf *a* [ *j* ] is plus infinity, there is no upper limit\nfor :math:`x_j`.\n\nLower c\n*******\nThis is the value of the inequality constraint function at :math:`x = 0`.\n\nUpper C\n*******\nThis is a :ref:`row-major<glossary@Row-major Representation>` representation\nof thee the inequality constraint matrix :math:`C`.\n\nLower g\n*******\nThis is the gradient of the objective function.\n\nUpper G\n*******\nThis is a row-major representation of the Hessian of the objective function.\nFor :math:`j = 0 , \\ldots , n-1`,\n:math:`- \\infty < a_j` or\n:math:`b_j < + \\infty` or\n:math:`G_{j,j} > 0.0`.\n\nepsilon\n*******\nThis argument is the convergence criteria;\nsee :ref:`qp_box@KKT Conditions` below.\nIt must be greater than zero.\n\nmaxitr\n******\nThis is the maximum number of\n:ref:`qp_interior-name` iterations to try before giving up\non convergence.\n\nxin\n***\nThis argument has size *n* and is the initial point for the algorithm.\nIt must strictly satisfy the constraints; i.e.,\n\n    *a* < *xin* , *xin* < *b* , *C* * *xin* ``-`` *c*  < 0\n\nxout\n****\nThis argument has size is *n* and\nthe input value of its elements does no matter.\nUpon return it is the primal variables\n:math:`x` corresponding to the problem solution.\n\nok\n**\nIf the return value *ok* is true, convergence is obtained; i.e.,\n\n.. math::\n\n    | F ( x , y_a, s_a, y_b, s_b, y_c, s_c ) |_\\infty < \\varepsilon\n\nwhere :math:`|v|_\\infty` is the infinity norm of the vector :math:`v`,\n:math:`\\varepsilon` is *epsilon* ,\n:math:`x` is equal to *xout* ,\n:math:`y_a, s_a \\in \\B{R}_+^n`,\n:math:`y_b, s_b \\in \\B{R}_+^n` and\n:math:`y_c, s_c \\in \\B{R}_+^m`.\n\nKKT Conditions\n**************\nGive a vector :math:`v \\in \\B{R}^m` we define\n:math:`D(v) \\in \\B{R}^{m \\times m}` as the corresponding diagonal matrix.\nWe also define :math:`1_m \\in \\B{R}^m` as the vector of ones.\nWe define\n\n.. math::\n\n    F ( x , y_a, s_a, y_b, s_b, y_c, s_c )\n    =\n    \\left(\n    \\begin{array}{c}\n    g + G x - y_a + y_b + y_c^T C         \\\\\n    a + s_a - x                           \\\\\n    x + s_b - b                           \\\\\n    C x + c + s_c                         \\\\\n    D(s_a) D(y_a) 1_m                     \\\\\n    D(s_b) D(y_b) 1_m                     \\\\\n    D(s_c) D(y_c) 1_m\n    \\end{array}\n    \\right)\n\nwhere\n:math:`x \\in \\B{R}^n`,\n:math:`y_a, s_a \\in \\B{R}_+^n`,\n:math:`y_b, s_b \\in \\B{R}_+^n` and\n:math:`y_c, s_c \\in \\B{R}_+^m`.\nThe KKT conditions for a solution of this problem is\n\n.. math::\n\n    F ( x , y_a, s_a, y_b, s_b, y_c, s_c ) = 0\n\n{xrst_toc_hidden\n    example/abs_normal/qp_box.cpp\n    example/abs_normal/qp_box.xrst\n}\nExample\n*******\nThe file :ref:`qp_box.cpp-name` contains an example and test of\n``qp_box`` .\n\n{xrst_end qp_box}\n-----------------------------------------------------------------------------\n*/\n# include \"qp_interior.hpp\"\n\n// BEGIN C++\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n\n// BEGIN PROTOTYPE\ntemplate <class Vector>\nbool qp_box(\n    size_t        level   ,\n    const Vector& a       ,\n    const Vector& b       ,\n    const Vector& c       ,\n    const Vector& C       ,\n    const Vector& g       ,\n    const Vector& G       ,\n    double        epsilon ,\n    size_t        maxitr  ,\n    const Vector& xin     ,\n    Vector&       xout    )\n// END PROTOTYPE\n{   double inf = std::numeric_limits<double>::infinity();\n    //\n    size_t n = a.size();\n    size_t m = c.size();\n    //\n    CPPAD_ASSERT_KNOWN(level <= 2, \"qp_interior: level is greater than 2\");\n    CPPAD_ASSERT_KNOWN(\n        size_t(b.size()) == n, \"qp_box: size of b is not n\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t(C.size()) == m * n, \"qp_box: size of C is not m * n\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t(g.size()) == n, \"qp_box: size of g is not n\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t(G.size()) == n * n, \"qp_box: size of G is not n * n\"\n    );\n    if( level > 0 )\n    {   std::cout << \"start qp_box\\n\";\n        CppAD::abs_print_mat(\"a\", n, 1, a);\n        CppAD::abs_print_mat(\"b\", n, 1, b);\n        CppAD::abs_print_mat(\"c\", m, 1, c);\n        CppAD::abs_print_mat(\"C\", m, n, C);\n        CppAD::abs_print_mat(\"g\", 1, n, g);\n        CppAD::abs_print_mat(\"G\", n, n, G);\n        CppAD::abs_print_mat(\"xin\", n, 1, xin);\n    }\n    //\n    // count number of lower and upper limits\n    size_t n_limit = 0;\n    for(size_t j = 0; j < n; j++)\n    {   CPPAD_ASSERT_KNOWN(G[j * n + j] >= 0.0, \"qp_box: G_{j,j} < 0.0\");\n        if( -inf < a[j] )\n            ++n_limit;\n        if( b[j] < inf )\n            ++n_limit;\n    }\n    //\n    // C_int and c_int define the extended constraints\n    Vector C_int((m + n_limit) * n ), c_int(m + n_limit);\n    for(size_t i = 0; i < size_t(C_int.size()); i++)\n        C_int[i] = 0.0;\n    //\n    // put C * x + c <= 0 in C_int, c_int\n    for(size_t i = 0; i < m; i++)\n    {   c_int[i] = c[i];\n        for(size_t j = 0; j < n; j++)\n            C_int[i * n + j] = C[i * n + j];\n    }\n    //\n    // put I * x - b <= 0 in C_int, c_int\n    size_t i_limit = 0;\n    for(size_t j = 0; j < n; j++) if( b[j] < inf )\n    {   c_int[m + i_limit]            = - b[j];\n        C_int[(m + i_limit) * n + j]  = 1.0;\n        ++i_limit;\n    }\n    //\n    // put a - I * x <= 0 in C_int, c_int\n    for(size_t j = 0; j < n; j++) if( -inf < a[j] )\n    {   c_int[m + i_limit]           = a[j];\n        C_int[(m + i_limit) * n + j] = -1.0;\n        ++i_limit;\n    }\n    Vector yout(m + n_limit), sout(m + n_limit);\n    size_t level_int = 0;\n    if( level == 2 )\n        level_int = 1;\n    bool ok = qp_interior( level_int,\n        c_int, C_int, g, G, epsilon, maxitr, xin, xout, yout, sout\n    );\n    if( level > 0 )\n    {   if( level < 2 )\n            CppAD::abs_print_mat(\"xout\", n, 1, xout);\n        if( ok )\n            std::cout << \"end q_box: ok = true\\n\";\n        else\n            std::cout << \"end q_box: ok = false\\n\";\n    }\n    return ok;\n}\n\n} // END_CPPAD_NAMESPACE\n// END C++\n\n# endif\n"
  },
  {
    "path": "example/abs_normal/qp_box.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin qp_box.hpp}\n\nqp_box Source Code\n##################\n\n{xrst_literal\n    example/abs_normal/qp_box.hpp\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end qp_box.hpp}\n"
  },
  {
    "path": "example/abs_normal/qp_interior.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin qp_interior.cpp}\n{xrst_spell\n    rlr\n}\n\nabs_normal qp_interior: Example and Test\n########################################\n\nProblem\n*******\nOur original problem is\n\n.. math::\n\n    \\R{minimize} \\; | u - 1| \\; \\R{w.r.t} \\; u \\in \\B{R}\n\nWe reformulate this as the following problem\n\n.. math::\n\n    \\begin{array}{rlr}\n        \\R{minimize}      & v             & \\R{w.r.t} \\; (u,v) \\in \\B{R}^2 \\\\\n        \\R{subject \\; to} &  u - 1 \\leq v \\\\\n                                 &  1 - u \\leq v\n    \\end{array}\n\nThis is equivalent to\n\n.. math::\n\n    \\begin{array}{rlr}\n        \\R{minimize}\n        & (0, 1) \\cdot (u, v)^T  & \\R{w.r.t} \\; (u,v) \\in \\B{R}^2 \\\\\n        \\R{subject \\; to}\n        &\n        \\left( \\begin{array}{cc} 1 & -1 \\\\ -1 & -1 \\end{array} \\right)\n        \\left( \\begin{array}{c} u \\\\ v \\end{array} \\right)\n        +\n        \\left( \\begin{array}{c} -1 \\\\ 1 \\end{array} \\right)\n        \\leq\n        0\n    \\end{array}\n\nwhich is in the form expected by :ref:`qp_interior-name` .\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end qp_interior.cpp}\n*/\n// BEGIN C++\n# include <limits>\n# include <cppad/utility/vector.hpp>\n# include \"qp_interior.hpp\"\n\nbool qp_interior(void)\n{   bool ok = true;\n    typedef CppAD::vector<double> vector;\n    //\n    size_t n = 2;\n    size_t m = 2;\n    vector C(m*n), c(m), G(n*n), g(n), xin(n), xout(n), yout(m), sout(m);\n    C[ 0 * n + 0 ] =  1.0; // C(0,0)\n    C[ 0 * n + 1 ] = -1.0; // C(0,1)\n    C[ 1 * n + 0 ] = -1.0; // C(1,0)\n    C[ 1 * n + 1 ] = -1.0; // C(1,1)\n    //\n    c[0]           = -1.0;\n    c[1]           =  1.0;\n    //\n    g[0]           =  0.0;\n    g[1]           =  1.0;\n    //\n    // G = 0\n    for(size_t i = 0; i < n * n; i++)\n        G[i] = 0.0;\n    //\n    // If (u, v) = (0,2), C * (u, v) + c = (-2,-2)^T + (1,-1)^T < 0\n    // Hence (0, 2) is feasible.\n    xin[0] = 0.0;\n    xin[1] = 2.0;\n    //\n    double epsilon = 99.0 * std::numeric_limits<double>::epsilon();\n    size_t maxitr  = 10;\n    size_t level   = 0;\n    //\n    ok &= CppAD::qp_interior(\n        level, c, C, g, G, epsilon, maxitr, xin, xout, yout, sout\n    );\n    //\n    // check optimal value for u\n    ok &= std::fabs( xout[0] - 1.0 ) < epsilon;\n    // check optimal value for v\n    ok &= std::fabs( xout[1] ) < epsilon;\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/abs_normal/qp_interior.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_ABS_NORMAL_QP_INTERIOR_HPP\n# define CPPAD_EXAMPLE_ABS_NORMAL_QP_INTERIOR_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin qp_interior}\n{xrst_spell\n    maxitr\n    rl\n    sout\n    xin\n    xout\n    yout\n}\n\nSolve a Quadratic Program Using Interior Point Method\n#####################################################\n\nSyntax\n******\n| *ok* = ``qp_interior`` (\n| *level* , *c* , *C* , *g* , *G* , *epsilon* , *maxitr* , *xin* , *xout* , *yout* , *sout*\n| )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN PROTOTYPE\n    // END PROTOTYPE\n}\n\nSource\n******\nThis following is a link to the source code for this example:\n:ref:`qp_interior.hpp-name` .\n\nPurpose\n*******\nThis routine could be used to create a version of :ref:`abs_min_linear-name`\nthat solved Quadratic programs (instead of linear programs).\n\nProblem\n*******\nWe are given\n:math:`C \\in \\B{R}^{m \\times n}`,\n:math:`c \\in \\B{R}^m`,\n:math:`G \\in \\B{R}^{n \\times n}`,\n:math:`g \\in \\B{R}^n`,\nwhere :math:`G` is positive semi-definite\nand :math:`G + C^T C` is positive definite.\nThis routine solves the problem\n\n.. math::\n\n    \\begin{array}{rl}\n    \\R{minimize} &\n    \\frac{1}{2} x^T G x + g^T x \\; \\R{w.r.t} \\; x \\in \\B{R}^n\n    \\\\\n    \\R{subject \\; to} &\n    C x + c \\leq 0\n    \\end{array}\n\nVector\n******\nThe type *Vector* is a\nsimple vector with elements of type ``double`` .\n\nlevel\n*****\nThis value is zero or one.\nIf *level*  == 0 ,\nno tracing is printed.\nIf *level*  == 1 ,\na trace of the ``qp_interior`` optimization is printed.\n\nLower c\n*******\nThis is the vector :math:`c` in the problem.\n\nUpper C\n*******\nThis is a :ref:`row-major<glossary@Row-major Representation>`\nof the matrix :math:`C` in the problem.\n\nLower g\n*******\nThis is the vector :math:`g` in the problem.\n\nUpper G\n*******\nThis is a :ref:`row-major<glossary@Row-major Representation>`\nof the matrix :math:`G` in the problem.\n\nepsilon\n*******\nThis argument is the convergence criteria;\nsee :ref:`qp_interior@KKT Conditions` below.\nIt must be greater than zero.\n\nmaxitr\n******\nThis is the maximum number of newton iterations to try before giving up\non convergence.\n\nxin\n***\nThis argument has size *n* and is the initial point for the algorithm.\nIt must strictly satisfy the constraints; i.e.,\n:math:`C x - c < 0`  for *x* = *xin* .\n\nxout\n****\nThis argument has size is *n* and\nthe input value of its elements does no matter.\nUpon return it is the primal variables corresponding to the problem solution.\n\nyout\n****\nThis argument has size is *m* and\nthe input value of its elements does no matter.\nUpon return it the components of *yout* are all positive\nand it is the dual variables corresponding to the program solution.\n\nsout\n****\nThis argument has size is *m* and\nthe input value of its elements does no matter.\nUpon return it the components of *sout* are all positive\nand it is the slack variables corresponding to the program solution.\n\nok\n**\nIf the return value *ok* is true, convergence is obtained; i.e.,\n\n.. math::\n\n    | F_0 (xout , yout, sout) |_\\infty \\leq epsilon\n\nwhere :math:`| v |_\\infty` is the maximum absolute element\nfor the vector :math:`v` and :math:`F_\\mu (x, y, s)` is defined below.\n\nKKT Conditions\n**************\nGive a vector :math:`v \\in \\B{R}^m` we define\n:math:`D(v) \\in \\B{R}^{m \\times m}` as the corresponding diagonal matrix.\nWe also define :math:`1_m \\in \\B{R}^m` as the vector of ones.\nWe define\n:math:`F_\\mu : \\B{R}^{n + m + m } \\rightarrow \\B{R}^{n + m + m}`\nby\n\n.. math::\n\n    F_\\mu ( x , y , s )\n    =\n    \\left(\n    \\begin{array}{c}\n    g + G x + y^T C             \\\\\n    C x + c + s                           \\\\\n    D(s) D(y) 1_m - \\mu 1_m\n    \\end{array}\n    \\right)\n\nThe KKT conditions for a solution of this problem is\n:math:`0 \\leq y`,\n:math:`0 \\leq s`, and\n:math:`F_0 (x , y, s) = 0`.\n\nNewton Step\n***********\nThe derivative of :math:`F_\\mu` is given by\n\n.. math::\n\n    F_\\mu^{(1)} (x, y, s)  =\n    \\left( \\begin{array}{ccc}\n    G       & C^T  & 0_{n,m} \\\\\n    C       & 0    & I_{m,m} \\\\\n    0_{m,m} & D(s) && D(y)\n    \\end{array} \\right)\n\nThe Newton step solves the following equation for\n:math:`\\Delta x`, :math:`\\Delta y`, and :math:`\\Delta z`\n\n.. math::\n\n    F_\\mu^{(1)} (x, y, s)\n    \\left( \\begin{array}{c} \\Delta x \\\\ \\Delta y \\\\ \\Delta s \\end{array} \\right)\n    =\n    - F_\\mu (x, y, s)\n\nTo simplify notation, we define\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    r_x (x, y, s) & = & g + G x + y^T C \\\\\n    r_y (x, y, s) & = & C x + c + s          \\\\\n    r_s (x, y, s) & = & D(s) D(y) 1_m - \\mu 1_m\n    \\end{eqnarray}\n\nIt follows that\n\n.. math::\n\n    \\left( \\begin{array}{ccc}\n    G       & C^T  & 0_{n,m} \\\\\n    C       & 0    & I_{m,m} \\\\\n    0_{m,m} & D(s) && D(y)\n    \\end{array} \\right)\n    \\left( \\begin{array}{c} \\Delta x \\\\ \\Delta y \\\\ \\Delta s \\end{array} \\right)\n    =\n    -\n    \\left( \\begin{array}{c}\n        r_x (x, y, s) \\\\\n        r_y (x, y, s) \\\\\n        r_s (x, y, s)\n    \\end{array} \\right)\n\nElementary Row Reduction\n========================\nSubtracting :math:`D(y)` times the second row from the third row\nwe obtain:\n\n.. math::\n\n    \\left( \\begin{array}{ccc}\n    G        & C^T  & 0_{n,m} \\\\\n    C        & 0    & I_{m,m} \\\\\n    - D(y) C & D(s) & 0_{m,m}\n    \\end{array} \\right)\n    \\left( \\begin{array}{c} \\Delta x \\\\ \\Delta y \\\\ \\Delta s \\end{array} \\right)\n    =\n    -\n    \\left( \\begin{array}{c}\n        r_x (x, y, s) \\\\\n        r_y (x, y, s) \\\\\n        r_s (x, y, s) - D(y) r_y(x, y, s)\n    \\end{array} \\right)\n\nMultiplying the third row by :math:`D(s)^{-1}` we obtain:\n\n.. math::\n\n    \\left( \\begin{array}{ccc}\n    G          & C^T     & 0_{n,m} \\\\\n    C          & 0       & I_{m,m} \\\\\n    - D(y/s) C & I_{m,m} & 0_{m,m}\n    \\end{array} \\right)\n    \\left( \\begin{array}{c} \\Delta x \\\\ \\Delta y \\\\ \\Delta s \\end{array} \\right)\n    =\n    -\n    \\left( \\begin{array}{c}\n        r_x (x, y, s) \\\\\n        r_y (x, y, s) \\\\\n        D(s)^{-1} r_s (x, y, s) - D(y/s) r_y(x, y, s)\n    \\end{array} \\right)\n\nwhere :math:`y/s` is the vector in :math:`\\B{R}^m` defined by\n:math:`(y/s)_i = y_i / s_i`.\nSubtracting :math:`C^T` times the third row from the first row we obtain:\n\n.. math::\n\n    \\left( \\begin{array}{ccc}\n    G + C^T D(y/s) C & 0_{n,m} & 0_{n,m} \\\\\n    C                & 0       & I_{m,m} \\\\\n    - D(y/s) C       & I_{m,m} & 0_{m,m}\n    \\end{array} \\right)\n    \\left( \\begin{array}{c} \\Delta x \\\\ \\Delta y \\\\ \\Delta s \\end{array} \\right)\n    =\n    -\n    \\left( \\begin{array}{c}\n        r_x (x, y, s)\n            - C^T D(s)^{-1} \\left[ r_s (x, y, s) - D(y) r_y(x, y, s) \\right] \\\\\n        r_y (x, y, s) \\\\\n        D(s)^{-1} r_s (x, y, s) - D(y/s) r_y(x, y, s)\n    \\end{array} \\right)\n\nSolution\n********\nIt follows that :math:`G + C^T D(y/s) C` is invertible and\nwe can determine :math:`\\Delta x` by solving the equation\n\n.. math::\n\n    [ G + C^T D(y/s) C ] \\Delta x\n    =\n    C^T D(s)^{-1} \\left[ r_s (x, y, s) - D(y) r_y(x, y, s) \\right] - r_x (x, y, s)\n\nGiven :math:`\\Delta x` we have that\n\n.. math::\n\n    \\Delta s = - r_y (x, y, s) - C \\Delta x\n\n.. math::\n\n    \\Delta y =\n    D(s)^{-1}[ D(y) r_y(x, y, s) - r_s (x, y, s) + D(y) C \\Delta x ]\n\n{xrst_toc_hidden\n    example/abs_normal/qp_interior.cpp\n    example/abs_normal/qp_interior.xrst\n}\nExample\n*******\nThe file :ref:`qp_interior.cpp-name` contains an example and test of\n``qp_interior`` .\n\n{xrst_end qp_interior}\n-----------------------------------------------------------------------------\n*/\n# include <cmath>\n# include <cppad/utility/lu_solve.hpp>\n# include \"abs_print_mat.hpp\"\n\n// BEGIN C++\nnamespace {\n    // ------------------------------------------------------------------------\n    template <class Vector>\n    double qp_interior_max_abs(const Vector& v)\n    {   double max_abs = 0.0;\n        for(size_t j = 0; j < size_t(v.size()); j++)\n            max_abs = std::max( max_abs, std::fabs(v[j]) );\n        return max_abs;\n    }\n    // ------------------------------------------------------------------------\n    template <class Vector>\n    void qp_interior_split(\n        const Vector& v, Vector& v_x, Vector& v_y, Vector& v_s\n    )\n    {   size_t n = v_x.size();\n        size_t m = v_y.size();\n        CPPAD_ASSERT_UNKNOWN( size_t(v_s.size()) == m );\n        CPPAD_ASSERT_UNKNOWN( size_t(v.size()) == n + m + m );\n        for(size_t i = 0; i < n; i++)\n            v_x[i] = v[i];\n        for(size_t i = 0; i < m; i++)\n        {   v_y[i] = v[n + i];\n            v_s[i] = v[n + m + i];\n        }\n        return;\n    }\n    // ------------------------------------------------------------------------\n    template <class Vector>\n    void qp_interior_join(\n        Vector& v, const Vector& v_x, const Vector& v_y, const Vector& v_s\n    )\n    {   size_t n = v_x.size();\n        size_t m = v_y.size();\n        CPPAD_ASSERT_UNKNOWN( size_t(v_s.size()) == m );\n        CPPAD_ASSERT_UNKNOWN( size_t(v.size()) == n + m + m );\n        for(size_t i = 0; i < n; i++)\n            v[i] = v_x[i];\n        for(size_t i = 0; i < m; i++)\n            v[n + i] = v_y[i];\n        for(size_t i = 0; i < m; i++)\n            v[n + m + i] = v_s[i];\n        return;\n    }\n    // ------------------------------------------------------------------------\n    template <class Vector>\n    Vector qp_interior_F_0(\n        const Vector& c       ,\n        const Vector& C       ,\n        const Vector& g       ,\n        const Vector& G       ,\n        const Vector& x       ,\n        const Vector& y       ,\n        const Vector& s       )\n    {   size_t n = g.size();\n        size_t m = c.size();\n        // compute r_x(x, y, s) = g + G x + y^T C\n        Vector r_x(n);\n        for(size_t j = 0; j < n; j++)\n        {   r_x[j] = g[j];\n            for(size_t i = 0; i < n; i++)\n                r_x[j] += G[j * n + i] * x[i];\n            for(size_t i = 0; i < m; i++)\n                r_x[j] += y[i] * C[i * n + j];\n        }\n        // compute r_y(x, y, s) = C x + c + s\n        Vector r_y(m);\n        for(size_t i = 0; i < m; i++)\n        {   r_y[i] = c[i] + s[i];\n            for(size_t j = 0; j < n; j++)\n                r_y[i] += C[i * n + j] * x[j];\n        }\n        // compute r_s(x, y, s) = D(s) * D(y) * 1_m - mu * 1_m\n        // where mu = 0\n        Vector r_s(m);\n        for(size_t i = 0; i < m; i++)\n            r_s[i] = s[i] * y[i];\n        //\n        // combine into one vector\n        Vector F_0(n + m + m);\n        qp_interior_join(F_0, r_x, r_y, r_s);\n        //\n        return F_0;\n    }\n}\n//\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n\n// BEGIN PROTOTYPE\ntemplate <class Vector>\nbool qp_interior(\n    size_t        level   ,\n    const Vector& c       ,\n    const Vector& C       ,\n    const Vector& g       ,\n    const Vector& G       ,\n    double        epsilon ,\n    size_t        maxitr  ,\n    const Vector& xin     ,\n    Vector&       xout    ,\n    Vector&       yout    ,\n    Vector&       sout    )\n// END PROTOTYPE\n{   size_t m = c.size();\n    size_t n = g.size();\n    CPPAD_ASSERT_KNOWN(\n        level <= 1,\n        \"qp_interior: level is greater than one\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t(C.size()) == m * n,\n        \"qp_interior: size of C is not m * n\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t(G.size()) == n * n,\n        \"qp_interior: size of G is not n * n\"\n    );\n    if( level > 0 )\n    {   std::cout << \"start qp_interior\\n\";\n        CppAD::abs_print_mat(\"c\", m, 1, c);\n        CppAD::abs_print_mat(\"C\", m, n, C);\n        CppAD::abs_print_mat(\"g\", n, 1, g);\n        CppAD::abs_print_mat(\"G\", n, n, G);\n        CppAD::abs_print_mat(\"xin\", n, 1, xin);\n    }\n    //\n    // compute the maximum absolute element of the problem vectors and matrices\n    double max_element = 0.0;\n    for(size_t i = 0; i < size_t(C.size()); i++)\n        max_element = std::max(max_element , std::fabs(C[i]) );\n    for(size_t i = 0; i < size_t(c.size()); i++)\n        max_element = std::max(max_element , std::fabs(c[i]) );\n    for(size_t i = 0; i < size_t(G.size()); i++)\n        max_element = std::max(max_element , std::fabs(G[i]) );\n    for(size_t i = 0; i < size_t(g.size()); i++)\n        max_element = std::max(max_element , std::fabs(g[i]) );\n    //\n    double mu = 1e-1 * max_element;\n    //\n    if( max_element == 0.0 )\n    {   if( level > 0 )\n            std::cout << \"end qp_interior: line_search failed\\n\";\n        return false;\n    }\n    //\n    // initialize x, y, s\n    xout = xin;\n    for(size_t i = 0; i < m; i++)\n    {   double sum = c[i];\n        for(size_t j = 0; j < n; j++)\n            sum += C[ i * n + j ] * xout[j];\n        if( sum > 0.0 )\n        {   if( level > 0 ) std::cout <<\n                \"end qp_interior: xin is not in interior of feasible set\\n\";\n            return false;\n        }\n        //\n        sout[i] = std::sqrt(mu);\n        yout[i] = std::sqrt(mu);\n    }\n    // ----------------------------------------------------------------------\n    // initial F_0(xout, yout, sout)\n    Vector F_0       = qp_interior_F_0(c, C, g, G, xout, yout, sout);\n    double F_max_abs = qp_interior_max_abs( F_0 );\n    for(size_t itr = 0; itr <= maxitr; itr++)\n    {\n        // check for convergence\n        if( F_max_abs <= epsilon )\n        {   if( level > 0 )\n                std::cout << \"end qp_interior: ok = true\\n\";\n            return true;\n        }\n        if( itr == maxitr )\n        {   if( level > 0 ) std::cout <<\n                \"end qp_interior: max # iterations without convergence\\n\";\n            return false;\n        }\n        //\n        // compute F_mu(xout, yout, sout)\n        Vector F_mu  = F_0;\n        for(size_t i = 0; i < m; i++)\n            F_mu[n + m + i] -= mu;\n        //\n        // r_x, r_y, r_s (xout, yout, sout)\n        Vector r_x(n), r_y(m), r_s(m);\n        qp_interior_split(F_mu, r_x, r_y, r_s);\n        //\n        // tmp_m = D(s)^{-1} * [ r_s - D(y) r_y ]\n        Vector tmp_m(m);\n        for(size_t i = 0; i < m; i++)\n            tmp_m[i]  = ( r_s[i] - yout[i] * r_y[i] ) / sout[i];\n        //\n        // right_x = C^T * D(s)^{-1} * [ r_s - D(y) r_y ] - r_x\n        Vector right_x(n);\n        for(size_t j = 0; j < n; j++)\n        {   right_x[j] = 0.0;\n            for(size_t i = 0; i < m; i++)\n                right_x[j] += C[ i * n + j ] * tmp_m[i];\n            right_x[j] -= r_x[j];\n        }\n        //\n        // Left_x = G + C^T * D(y / s) * C\n        Vector Left_x = G;\n        for(size_t i = 0; i < n; i++)\n        {   for(size_t j = 0; j < n; j++)\n            {   for(size_t k = 0; k < m; k++)\n                {   double y_s = yout[k] / sout[k];\n                    Left_x[ i * n + j] += C[k * n + j] * y_s * C[k * n + i];\n                }\n            }\n        }\n        // delta_x\n        Vector delta_x(n);\n        double logdet;\n        LuSolve(n, 1, Left_x, right_x, delta_x, logdet);\n        //\n        // C_delta_x = C * delta_x\n        Vector C_delta_x(m);\n        for(size_t i = 0; i < m; i++)\n        {   C_delta_x[i] = 0.0;\n            for(size_t j = 0; j < n; j++)\n                C_delta_x[i] += C[ i * n + j ] * delta_x[j];\n        }\n        //\n        // delta_y = D(s)^-1 * [D(y) * r_y - r_s + D(y) * C * delta_x]\n        Vector delta_y(m);\n        for(size_t i = 0; i < m; i++)\n        {   delta_y[i] = yout[i] * r_y[i] - r_s[i] + yout[i] * C_delta_x[i];\n            delta_y[i] /= sout[i];\n        }\n        // delta_s = - r_y - C * delta_x\n        Vector delta_s(m);\n        for(size_t i = 0; i < m; i++)\n            delta_s[i] = - r_y[i] - C_delta_x[i];\n        //\n        // delta_xys\n        Vector delta_xys(n + m + m);\n        qp_interior_join(delta_xys, delta_x, delta_y, delta_s);\n        // -------------------------------------------------------------------\n        //\n        // The initial derivative in direction  Delta_xys is equal to\n        // the negative of the norm square of F_mu\n        //\n        // line search parameter lam\n        Vector x(n), y(m), s(m);\n        double  lam = 2.0;\n        bool lam_ok = false;\n        while( ! lam_ok && lam > 1e-5 )\n        {   lam = lam / 2.0;\n            for(size_t j = 0; j < n; j++)\n                x[j] = xout[j] + lam * delta_xys[j];\n            lam_ok = true;\n            for(size_t i = 0; i < m; i++)\n            {   y[i] = yout[i] + lam * delta_xys[n + i];\n                s[i] = sout[i] + lam * delta_xys[n + m + i];\n                lam_ok &= s[i] > 0.0 && y[i] > 0.0;\n            }\n            if( lam_ok )\n            {   Vector F_mu_tmp = qp_interior_F_0(c, C, g, G, x, y, s);\n                for(size_t i = 0; i < m; i++)\n                    F_mu_tmp[n + m + i] -= mu;\n                // avoid cancellation roundoff in difference of norm squared\n                // |v + dv|^2         = v^T * v + 2 * v^T * dv + dv^T * dv\n                // |v + dv|^2 - |v|^2 =           2 * v^T * dv + dv^T * dv\n                double F_norm_sq    = 0.0;\n                double diff_norm_sq = 0.0;\n                for(size_t i = 0; i < n + m + m; i++)\n                {   double dv     = F_mu_tmp[i] - F_mu[i];\n                    F_norm_sq    += F_mu[i] * F_mu[i];\n                    diff_norm_sq += 2.0 * F_mu[i] * dv + dv * dv;\n                }\n                lam_ok &= diff_norm_sq < - lam * F_norm_sq / 4.0;\n            }\n        }\n        if( ! lam_ok )\n        {   if( level > 0 )\n                std::cout << \"end qp_interior: line search failed\\n\";\n            return false;\n        }\n        //\n        // update current solution\n        xout = x;\n        yout = y;\n        sout = s;\n        //\n        // updage F_0\n        F_0       = qp_interior_F_0(c, C, g, G, xout, yout, sout);\n        F_max_abs = qp_interior_max_abs( F_0 );\n        //\n        // update mu\n        if( F_max_abs <= 1e1 *  mu )\n            mu = mu / 1e2;\n        if( level > 0 )\n        {   std::cout << \"itr = \" << itr\n                << \", mu = \" << mu\n                << \", lam = \" << lam\n                << \", F_max_abs = \" << F_max_abs << \"\\n\";\n            abs_print_mat(\"xout\", 1, n, xout);\n        }\n    }\n    if( level > 0 )\n        std::cout << \"end qp_interior: program error\\n\";\n    return false;\n}\n} // END_CPPAD_NAMESPACE\n// END C++\n\n# endif\n"
  },
  {
    "path": "example/abs_normal/qp_interior.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin qp_interior.hpp}\n\nqp_interior Source Code\n#######################\n\n{xrst_literal\n    example/abs_normal/qp_interior.hpp\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end qp_interior.hpp}\n"
  },
  {
    "path": "example/abs_normal/simplex_method.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin simplex_method.cpp}\n{xrst_spell\n    rlr\n}\n\nabs_normal simplex_method: Example and Test\n###########################################\n\nProblem\n*******\nOur original problem is\n\n.. math::\n\n    \\R{minimize} \\; | u - 1| \\; \\R{w.r.t} \\; u \\in \\B{R}\n\nWe reformulate this as the following problem\n\n.. math::\n\n    \\begin{array}{rlr}\n        \\R{minimize}      & v             & \\R{w.r.t} \\; (u,v) \\in \\B{R}^2 \\\\\n        \\R{subject \\; to} &  u - 1 \\leq v \\\\\n                                 &  1 - u \\leq v\n    \\end{array}\n\nWe know that the value of :math:`v` at the solution is greater than\nor equal zero. Hence we can reformulate this problem as\n\n.. math::\n\n    \\begin{array}{rlr}\n    \\R{minimize}      & v             & \\R{w.r.t} \\; ( u_- , u_+ , v) \\in \\B{R}_+^3 \\\\\n    \\R{subject \\; to} & u_+ - u_- - 1  \\leq v \\\\\n                            &  1 - u_+ + u_- \\leq v\n    \\end{array}\n\nThis is equivalent to\n\n.. math::\n\n    \\begin{array}{rlr}\n        \\R{minimize}\n        & (0, 0, 1) \\cdot ( u_+, u_- , v)^T  & \\R{w.r.t} \\; (u,v) \\in \\B{R}_+^3 \\\\\n    \\R{subject \\; to}\n        &\n        \\left( \\begin{array}{ccc}\n            +1 & -1 & -1 \\\\\n            -1 & +1 & +1\n        \\end{array} \\right)\n        \\left( \\begin{array}{c} u_+ \\\\ u_- \\\\ v \\end{array} \\right)\n        +\n        \\left( \\begin{array}{c} -1 \\\\ 1 \\end{array} \\right)\n        \\leq\n        0\n    \\end{array}\n\nwhich is in the form expected by :ref:`simplex_method-name` .\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end simplex_method.cpp}\n*/\n// BEGIN C++\n# include <limits>\n# include <cppad/utility/vector.hpp>\n# include \"simplex_method.hpp\"\n\nbool simplex_method(void)\n{   bool ok = true;\n    typedef CppAD::vector<double> vector;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    //\n    size_t n = 3;\n    size_t m = 2;\n    vector A(m * n), b(m), c(n), xout(n);\n    A[ 0 * n + 0 ] =  1.0; // A(0,0)\n    A[ 0 * n + 1 ] = -1.0; // A(0,1)\n    A[ 0 * n + 2 ] = -1.0; // A(0,2)\n    //\n    A[ 1 * n + 0 ] = -1.0; // A(1,0)\n    A[ 1 * n + 1 ] = +1.0; // A(1,1)\n    A[ 1 * n + 2 ] = -1.0; // A(1,2)\n    //\n    b[0]           = -1.0;\n    b[1]           =  1.0;\n    //\n    c[0]           =  0.0;\n    c[1]           =  0.0;\n    c[2]           =  1.0;\n    //\n    size_t maxitr  = 10;\n    size_t level   = 0;\n    //\n    ok &= CppAD::simplex_method(level, A, b, c,  maxitr, xout);\n    //\n    // check optimal value for u\n    ok &= std::fabs( xout[0] - 1.0 ) < eps99;\n    //\n    // check optimal value for v\n    ok &= std::fabs( xout[1] ) < eps99;\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/abs_normal/simplex_method.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_ABS_NORMAL_SIMPLEX_METHOD_HPP\n# define CPPAD_EXAMPLE_ABS_NORMAL_SIMPLEX_METHOD_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin simplex_method}\n{xrst_spell\n    maxitr\n    rl\n    xout\n}\n\nabs_normal: Solve a Linear Program Using Simplex Method\n#######################################################\n\nSyntax\n******\n| *ok* = ``simplex_method`` ( *level* , *b* , *A* , *c* , *maxitr* , *xout* )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN PROTOTYPE\n    // END PROTOTYPE\n}\n\nSource\n******\nThis following is a link to the source code for this example:\n:ref:`simplex_method.hpp-name` .\n\nProblem\n*******\nWe are given\n:math:`A \\in \\B{R}^{m \\times n}`,\n:math:`b \\in \\B{R}^m`,\n:math:`c \\in \\B{R}^n`.\nThis routine solves the problem\n\n.. math::\n\n    \\begin{array}{rl}\n    \\R{minimize} &\n    g^T x \\; \\R{w.r.t} \\; x \\in \\B{R}_+^n\n    \\\\\n    \\R{subject \\; to} & A x + b \\leq 0\n    \\end{array}\n\nVector\n******\nThe type *Vector* is a\nsimple vector with elements of type ``double`` .\n\nlevel\n*****\nThis value is less than or equal two.\nIf *level*  == 0 ,\nno tracing is printed.\nIf *level*  >= 1 ,\na trace :math:`x` and the corresponding objective :math:`z`\nis printed at each iteration.\nIf *level*  == 2 ,\na trace of the simplex Tableau is printed at each iteration.\n\nA\n*\nThis is a :ref:`row-major<glossary@Row-major Representation>` representation\nof the matrix :math:`A` in the problem.\n\nb\n*\nThis is the vector :math:`b` in the problem.\n\nc\n*\nThis is the vector :math:`c` in the problem.\n\nmaxitr\n******\nThis is the maximum number of simplex iterations to try before giving up\non convergence.\n\nxout\n****\nThis argument has size is *n* and\nthe input value of its elements does no matter.\nUpon return it is the primal variables corresponding to the problem solution.\n\nok\n**\nIf the return value *ok* is true, a solution has been found.\n{xrst_toc_hidden\n    example/abs_normal/simplex_method.cpp\n    example/abs_normal/simplex_method.xrst\n}\nExample\n*******\nThe file :ref:`simplex_method.cpp-name` contains an example and test of\n``simplex_method`` .\n\n{xrst_end simplex_method}\n-----------------------------------------------------------------------------\n*/\n# include <cmath>\n# include <cppad/utility/error_handler.hpp>\n# include \"abs_print_mat.hpp\"\n\n// BEGIN C++\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n\n// BEGIN PROTOTYPE\ntemplate <class Vector>\nbool simplex_method(\n    size_t        level   ,\n    const Vector& A       ,\n    const Vector& b       ,\n    const Vector& c       ,\n    size_t        maxitr  ,\n    Vector&       xout    )\n// END PROTOTYPE\n{   // number of equations\n    size_t ne  = b.size();\n    // number of x variables\n    size_t nx = c.size();\n    CPPAD_ASSERT_UNKNOWN( size_t(A.size()) == ne * nx );\n    CPPAD_ASSERT_UNKNOWN( level <= 2 );\n    //\n    if( level > 0 )\n    {   std::cout << \"start simplex_method\\n\";\n        CppAD::abs_print_mat(\"A\", ne, nx, A);\n        CppAD::abs_print_mat(\"b\", ne,  1, b);\n        CppAD::abs_print_mat(\"c\", nx, 1, c);\n    }\n    //\n    // variables (columns) in the Tableau:\n    // x: the original primary variables with size n\n    // s: slack variables, one for each equation\n    // a: auxiliary variables, one for each negative right hand size\n    // r: right hand size for equations\n    //\n    // Determine number of auxiliary variables\n    size_t na = 0;\n    for(size_t i = 0; i < ne; i++)\n    {   if( b[i] > 0.0 )\n            ++na;\n    }\n    // size of columns in the Tableau\n    size_t nc = nx + ne + na + 1;\n\n    // number of rows in Tableau, the equations plust two objectives\n    size_t nr = ne + 2;\n\n    // Initialize Tableau as zero\n    Vector T(nr * nc);\n    for(size_t i = 0; i < nr * nc; i++)\n        T[i] = 0.0;\n\n    // initialize basic variable flag as false\n    CppAD::vector<size_t> basic(nc);\n    for(size_t j = 0; j < nc; j++)\n        basic[j] = false;\n\n    // For i = 0 , ... , m-1, place the Equations\n    // sum_j A_{i,j} * x_j + b_i <= 0 in Tableau\n    na = 0; // use as index of next auxiliary variable\n    for(size_t i = 0; i < ne; i++)\n    {   if( b[i] > 0.0)\n        {   // convert to - sum_j A_{i,j} x_j - b_i >= 0\n            for(size_t j = 0; j < nx; j++)\n                T[i * nc + j] = - A[i * nx + j];\n            // slack variable has negative coefficient\n            T[i * nc + (nx + i)] = -1.0;\n            // auxiliary variable is basic for this constraint\n            T[i * nc + (nx + ne + na)] = 1.0;\n            basic[nx + ne + na]        = true;\n            // right hand side\n            T[i * nc + (nc - 1)] = b[i];\n            //\n            ++na;\n        }\n        else\n        {   // sum_j A_{i,j} x_j + b_i <= 0\n            for(size_t j = 0; j < nx; j++)\n                T[i * nc + j] = A[i * nx + j];\n            //  slack variable is also basic\n            T[ i * nc + (nx + i) ]  = 1.0;\n            basic[nx + i]           = true;\n            // right hand side for equations\n            T[ i * nc + (nc - 1) ] = - b[i];\n        }\n    }\n    // na is back to its original value\n    CPPAD_ASSERT_UNKNOWN( nc == nx + ne + na + 1 );\n    //\n    // place the equation objective equation in Tablueau\n    // row ne corresponds to the equation z - sum_j c_j x_j = 0\n    // column index for z is nx + ne + na\n    for(size_t j = 0; j < nx; j++)\n        T[ne * nc + j] = - c[j];\n    //\n    // row ne+1 corresponds to the equation w - a_0 - ... - a_{na-1} = 0\n    // column index for w is nx + ne + na +1\n    for(size_t j = 0; j < na; j++)\n        T[(ne + 1) * nc + (nx + ne + j)] = -1.0;\n    //\n    // fix auxiliary objective so coefficients in w\n    // for auxiliary variables are zero\n    for(size_t k = 0; k < na; k++)\n    {   size_t ja  = nx + ne + k;\n        size_t ia  = ne;\n        for(size_t i = 0; i < ne; i++)\n        {   if( T[i * nc + ja] != 0.0 )\n            {   CPPAD_ASSERT_UNKNOWN( T[i * nc + ja] == 1.0 );\n                CPPAD_ASSERT_UNKNOWN( T[(ne + 1) * nc + ja] == -1.0 )\n                CPPAD_ASSERT_UNKNOWN( ia == ne );\n                ia = i;\n            }\n        }\n        CPPAD_ASSERT_UNKNOWN( ia < ne );\n        for(size_t j = 0; j < nc; j++)\n            T[(ne + 1) * nc + j] += T[ia * nc + j];\n        // The result in column ja is zero, avoid roundoff\n        T[(ne + 1) * nc + ja] = 0.0;\n    }\n    //\n    // index of current objective\n    size_t iobj = ne;  // original objective z\n    if( na > 0 )\n        iobj = ne + 1; // auxiliary objective w\n    //\n    // simplex iterations\n    for(size_t itr = 0; itr < maxitr; itr++)\n    {   // current value for xout\n        for(size_t j = 0; j < nx; j++)\n        {   xout[j] = 0.0;\n            if( basic[j] )\n            {   // determine which row of column j is non-zero\n                xout[j] = std::numeric_limits<double>::quiet_NaN();\n                for(size_t i = 0; i < ne; i++)\n                {   double T_ij = T[i * nc + j];\n                    CPPAD_ASSERT_UNKNOWN( T_ij == 0.0 || T_ij == 1.0 );\n                    if( T_ij == 1.0 )\n                    {   // corresponding value in right hand side\n                        xout[j] = T[ i * nc + (nc-1) ];\n                    }\n                }\n            }\n        }\n        if( level > 1 )\n            CppAD::abs_print_mat(\"T\", nr, nc, T);\n        if( level > 0 )\n        {   CppAD::abs_print_mat(\"x\", nx, 1, xout);\n            std::cout << \"itr = \" << itr;\n            if( iobj > ne )\n                std::cout << \", auxiliary objective w = \";\n            else\n                std::cout << \", objective z = \";\n            std::cout << T[iobj * nc + (nc - 1)] << \"\\n\";\n        }\n        //\n        // number of variables depends on objective\n        size_t nv = nx + ne;   // (x, s)\n        if( iobj == ne + 1 )\n        {   // check if we have solved the auxiliary problem\n            bool done = true;\n            for(size_t k = 0; k < na; k++)\n                if( basic[nx + ne + k] )\n                    done = false;\n            if( done )\n            {   // switch to optimizing the original objective\n                iobj = ne;\n            }\n            else\n                nv = nx + ne + na; // (x, s, a)\n        }\n        //\n        // determine variable with maximum coefficient in objective row\n        double cmax = 0.0;\n        size_t jmax = nv;\n        for(size_t j = 0; j < nv; j++)\n        {   if( T[iobj * nc + j] > cmax )\n            {   CPPAD_ASSERT_UNKNOWN( ! basic[j] );\n                cmax = T[ iobj * nc + j];\n                jmax = j;\n            }\n        }\n        // check for solution\n        if( jmax == nv )\n        {   if( iobj == ne )\n            {   if( level > 0 )\n                    std::cout << \"end simplex_method\\n\";\n                return true;\n            }\n            if( level > 0 )\n                std::cout << \"end_simples_method: no feasible solution\\n\";\n            return false;\n        }\n        //\n        // We will increase the j-th variable.\n        // Determine which row will be the pivot row.\n        double rmin = std::numeric_limits<double>::infinity();\n        size_t imin = ne;\n        for(size_t i = 0; i < ne; i++)\n        {   if( T[i * nc + jmax] > 0.0 )\n            {   double r = T[i * nc + (nc-1) ] / T[i * nc + jmax];\n                if( r < rmin )\n                {   rmin = r;\n                    imin = i;\n                }\n            }\n        }\n        if( imin == ne )\n        {   // not auxiliary objective\n            CPPAD_ASSERT_UNKNOWN( iobj == ne );\n            if( level > 0 ) std::cout\n                << \"end simplex_method: objective is unbounded below\\n\";\n            return false;\n        }\n        double pivot = T[imin * nc + jmax];\n        //\n        // Which variable is changing from basic to non-basic.\n        // Initialize as not yet determined.\n        size_t basic2not = nc;\n        //\n        // Divide row imin by pivot element\n        for(size_t j = 0; j < nc; j++)\n        {   if( basic[j] && T[imin * nc + j] == 1.0 )\n            {   CPPAD_ASSERT_UNKNOWN( basic2not == nc );\n                basic2not = j;\n            }\n            T[imin * nc + j] /= pivot;\n        }\n        // The result in column jmax is one, avoid roundoff\n        T[imin * nc + jmax ] = 1.0;\n        //\n        // Check that we found the variable going from basic to non-basic\n        CPPAD_ASSERT_UNKNOWN( basic2not < nv && basic2not != jmax );\n        //\n        // convert variable for column jmax to basic\n        // and for column basic2not to non-basic\n        for(size_t i = 0; i < nr; i++) if( i != imin )\n        {   double r = T[i * nc + jmax ] / T[imin * nc + jmax];\n            // row_i = row_i - r * row_imin\n            for(size_t j = 0; j < nc; j++)\n                T[i * nc + j] -= r * T[imin * nc + j];\n            // The result in column jmax is zero, avoid roundoff\n            T[i * nc + jmax] = 0.0;\n        }\n        // update flag for basic variables\n        basic[ basic2not ] = false;\n        basic[ jmax ]      = true;\n    }\n    if( level > 0 ) std::cout\n        << \"end simplex_method: maximum # iterations without solution\\n\";\n    return false;\n}\n} // END_CPPAD_NAMESPACE\n// END C++\n\n# endif\n"
  },
  {
    "path": "example/abs_normal/simplex_method.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin simplex_method.hpp}\n\nsimplex_method Source Code\n##########################\n\n{xrst_literal\n    example/abs_normal/simplex_method.hpp\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end simplex_method.hpp}\n"
  },
  {
    "path": "example/abs_normal/talk.tex",
    "content": "% SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n% SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n% SPDX-FileContributor: 2003-22 Bradley M. Bell\n% ----------------------------------------------------------------------------\n\\documentclass{beamer}\n\n% needed for fonts; see %https://tex.stackexchange.com/questions/58087/\n% how-to-remove-the-warnings-font-shape-ot1-cmss-m-n-in-size-4-not-available\n\\usepackage{lmodern}% http://ctan.org/pkg/lm\n\n% macros\n\\newcommand{\\B}[1]{{\\bf #1}}\n\n\n\\title[CppAD]{CppAD's Abs-normal Representation}\n\\institute{\n    \\begin{tabular}{c}\n        {\\Large Bradley M. Bell} \\\\\n        \\\\\n        Applied Physics Laboratory and \\\\\n        Institute for Health Metrics and Evaluation, \\\\\n        University of Washington, \\\\\n        \\texttt{bradbell@uw.edu} \\\\\n    \\end{tabular}\n}\n\n\\begin{document}\n\n\\begin{frame}\n    \\titlepage\n\\end{frame}\n\n\n\n% ----------------------------------------------------------------------------\n\\begin{frame}{Non-Smooth Functions}\n\n\\begin{block}{$f(x)$}\n$ f : \\B{R}^n \\rightarrow \\B{R}^m $ where the only non-smooth\nnodes in its computational graph are $| \\cdot |$.\n\\end{block}\n\\pause\n\n\\begin{block}{$a(x)$}\nLet $s$ be number of $| \\cdot |$ in $f$.\nWe define\n$a : \\B{R}^n \\rightarrow \\B{R}^s$ where\n$a_i (x)$ is the result for the $i$-th absolute value.\n\\end{block}\n\n\\end{frame}\n% ----------------------------------------------------------------------------\n\\begin{frame}{Smooth Functions}\n\n\\begin{block}{$z(x,u)$}\nThere is a smooth\n$z : \\B{R}^{n + s} \\rightarrow \\B{R}^s$ where\n$z_i (x, u)$ is argument to $i$-th absolute value\nwhen $u_j = a_j (x)$ for $j < i$.\n\\end{block}\n\\pause\n\n\\begin{block}{$y(x,u)$}\nThere is a smooth\n$y : \\B{R}^{n + s} \\rightarrow \\B{R}^m$ where\n$y(x , u) = f(x)$ when $u = a (x)$ for all $i$.\n\\end{block}\n\\pause\n\n\\begin{block}{$g(x,u)$}\nThe function\n$g : \\B{R}^{n + s} \\rightarrow \\B{R}^{m + s}$ is defined by\n\\[\ng(x, u) = \\left[ \\begin{array}{c} y(x, u) \\\\ z(x, y) \\end{array} \\right]\n\\]\n\\end{block}\n\n\\end{frame}\n% ----------------------------------------------------------------------------\n\\begin{frame}{Approximating $a(x)$}\n\n\\[\nz[ \\hat{x} ]( x , u )\n=\nz ( \\hat{x}, a( \\hat{x} ) )\n    + \\partial_x z ( \\hat{x}, a( \\hat{x} ) ) ( x - \\hat{x} )\n    + \\partial_u z ( \\hat{x}, a( \\hat{x} ) ) ( u - a( \\hat{x} ) )\n\\]\n\\pause\n\nNote that $z_0 ( x , u )$ does not depend on $u$:\n\\[\na_0 [ \\hat{x} ]( x )\n=\n\\left|\n    z_0 ( \\hat{x}, a( \\hat{x} ) )\n    + \\partial_x z_0 ( \\hat{x}, a( \\hat{x} ) ) ( x - \\hat{x} )\n\\right|\n\\]\n\\pause\n\n\\begin{eqnarray*}\na_i [ \\hat{x} ]( x )\n& = &\n\\left | \\vphantom{ \\sum_{j < i} } z_i ( \\hat{x}, a( \\hat{x} ) )\n    + \\partial_x z_i ( \\hat{x}, a( \\hat{x} ) ) ( x - \\hat{x} )\n\\right.\n\\\\\n& + &\n\\left. \\sum_{j < i} \\partial_{u(j)} z_i ( \\hat{x}, a( \\hat{x} ) )\n            ( a_j [ \\hat{x} ] ( x )  - a_j ( \\hat{x} ) )\n\\right|\n\\end{eqnarray*}\n\\pause\n\n\\[\na(x) = a[ \\hat{x} ]( x ) + o( x - \\hat{x} )\n\\phantom{\\rule{1in}{1pt}}\n\\]\n\n\n\\end{frame}\n% ----------------------------------------------------------------------------\n\\begin{frame}{Representation}\n\n\\begin{block}{ \\texttt{f.abs\\_normal\\_fun(g, a)} }\nGiven the \\texttt{ADFun<Base>} object \\texttt{f} for $f(x)$,\nthis creates the two \\texttt{ADFun<Base>} objects \\texttt{g}, \\texttt{a}\nfor $g(x, u)$ and $a(x)$ respectively.\n\\end{block}\n\\pause\n\n\\begin{block}{Advantages}\nAny AD operation can be computed for the smooth function \\texttt{g}; e.g.,\nany order forward and reverse mode, sparsity patterns, and sparse derivatives.\n\\end{block}\n\n\\end{frame}\n% ----------------------------------------------------------------------------\n\\begin{frame}{Approximating $f(x)$}\n\n\\[\ny[ \\hat{x} ]( x , u )\n=\ny ( \\hat{x}, a( \\hat{x} ) )\n    + \\partial_x y ( \\hat{x}, a( \\hat{x} ) ) ( x - \\hat{x} )\n    + \\partial_u y ( \\hat{x}, a( \\hat{x} ) ) ( u - a( \\hat{x} ) )\n\\]\n\\pause\n\n\n\\[\nf(x) = y[ \\hat{x} ] ( x , a[ \\hat{x} ] (x) ) + o ( x - \\hat{x} )\n\\phantom{\\rule{1.3in}{1pt}}\n\\]\n\n\\begin{block}{ \\texttt{abs\\_eval(n, m, s, g\\_hat , g\\_jac , delta\\_x)} }\nEvaluates $y[ \\hat{x} ] ( x , a[ \\hat{x} ] (x) )$\n\\end{block}\n\\pause\n\n\\begin{itemize}\n\n\\item\n\\texttt{g\\_hat} is $g[ \\hat{x} , a( \\hat{x} ) ]$\n\\pause\n\n\\item\n\\texttt{g\\_jac} is $g^{(1)} [ \\hat{x} , a( \\hat{x} ) ]$\n\\pause\n\n\\item\n\\texttt{delta\\_x} is $x - \\hat{x}$\n\n\\end{itemize}\n\n\n\\end{frame}\n% ----------------------------------------------------------------------------\n\n\\begin{frame}{ \\texttt{abs\\_min\\_linear} }\n\n\\begin{block}{Problem}\nminimize $\\tilde{f} ( x ) = y[ \\hat{x} ] ( x , a( \\hat{x} ) )$ w.r.t\n$x$ subject to $-b \\leq x \\leq b$ using the assumption\nthat $\\tilde{f} (x)$ is convex.\n\\end{block}\n\\pause\n\n\n\\begin{block}{Algorithm}\n\\begin{enumerate}\n\n\\item\nStart at with point  $x = \\hat{x}$ and $C$ an empty set of\ncutting planes.\n\\pause\n\n\\item\n\\label{NextIterationItem}\nAdd affine apprimation for $\\tilde{f} ( x )$ at $x$ to $C$.\n\\pause\n\n\n\\item\nMinimize w.r.t $x$ the maximum of the affine functions in $C$\nsubject to $-b \\leq x \\leq b$ (this is an LP).\n\\pause\n\n\n\\item\nIf change in $x$ for this this iteration is small, return $x$ as solution.\nOtherwise, goto step \\ref{NextIterationItem}.\n\n\\end{enumerate}\n\\end{block}\n\n\n\\end{frame}\n\n\n\\end{document}\n"
  },
  {
    "path": "example/atomic_four/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n#\n# initialize check_example_atomic_four_depends\nSET(check_example_atomic_four_depends \"\")\n#\nADD_SUBDIRECTORY(lin_ode)\nADD_SUBDIRECTORY(mat_mul)\nADD_SUBDIRECTORY(vector)\n#\n# BEGIN_SORT_THIS_LINE_PLUS_2\nSET(source_list\n    atomic_four.cpp\n    bilinear.cpp\n    dynamic.cpp\n    forward.cpp\n    get_started.cpp\n    norm_sq.cpp\n)\n# END_SORT_THIS_LINE_MINUS_2\n\nset_compile_flags(example_atomic_four \"${cppad_debug_which}\" \"${source_list}\" )\n#\nADD_EXECUTABLE(example_atomic_four EXCLUDE_FROM_ALL ${source_list})\n#\n# List of libraries to be linked into the specified target\nTARGET_LINK_LIBRARIES(example_atomic_four\n    ${cppad_lib}\n    ${colpack_libs}\n)\n#\n# check_example_atomic_four\nadd_check_executable(check_example atomic_four)\n"
  },
  {
    "path": "example/atomic_four/atomic_four.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_four.cpp}\n\natomic_four Examples and Tests Driver\n#####################################\n\nRunning These Tests\n*******************\nAfter executing the :ref:`cmake-name` command\nform the :ref:`download@Distribution Directory`,\nyou can build and run these tests with the commands::\n\n    cd build\n    make check_example_atomic_four\n\nNote that your choice of :ref:`cmake@generator` may require using\nan different version of make; e.g., ``ninja`` .\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end atomic_four.cpp}\n-------------------------------------------------------------------------------\n*/\n// BEGIN C++\n\n// CPPAD_HAS_* defines\n# include <cppad/configure.hpp>\n\n// for thread_alloc\n# include <cppad/utility/thread_alloc.hpp>\n\n// test runner\n# include <cppad/utility/test_boolofvoid.hpp>\n\n// BEGIN_SORT_THIS_LINE_PLUS_1\nextern bool bilinear(void);\nextern bool dynamic(void);\nextern bool forward(void);\nextern bool get_started(void);\nextern bool norm_sq(void);\n// END_SORT_THIS_LINE_MINUS_1\n\n// main program that runs all the tests\nint main(void)\n{   std::string group = \"example/atomic\";\n    size_t      width = 20;\n    CppAD::test_boolofvoid Run(group, width);\n\n    // This line is used by test_one.sh\n\n    // BEGIN_SORT_THIS_LINE_PLUS_1\n    Run( bilinear,            \"bilinear\"       );\n    Run( dynamic,             \"dynamic\"        );\n    Run( forward,             \"forward\"        );\n    Run( get_started,         \"get_started\"    );\n    Run( norm_sq,             \"norm_sq\"        );\n    // END_SORT_THIS_LINE_MINUS_1\n\n    // check for memory leak\n    bool memory_ok = CppAD::thread_alloc::free_all();\n    // print summary at end\n    bool ok = Run.summary(memory_ok);\n    //\n    return static_cast<int>( ! ok );\n}\n// END C++\n"
  },
  {
    "path": "example/atomic_four/atomic_four.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin atomic_four_example}\n\nExamples Defining Atomic Functions: Fourth Generation\n#####################################################\n\nContents\n********\n{xrst_toc_table\n    example/atomic_four/get_started.cpp\n    example/atomic_four/norm_sq.cpp\n    example/atomic_four/bilinear.cpp\n    example/atomic_four/forward.cpp\n    example/atomic_four/dynamic.cpp\n    include/cppad/example/atomic_four/vector/vector.xrst\n    include/cppad/example/atomic_four/mat_mul/mat_mul.xrst\n    include/cppad/example/atomic_four/lin_ode/lin_ode.xrst\n}\n\n{xrst_end atomic_four_example}\n"
  },
  {
    "path": "example/atomic_four/bilinear.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin atomic_four_bilinear.cpp}\n\nBilinear Interpolation Atomic Function: Example and Test\n########################################################\n\nSee Also\n********\n:ref:`interp_onetape.cpp-name` .\n\nDefine Atomic Function\n**********************\n{xrst_literal\n    // BEGIN_DEFINE_ATOMIC_FUNCTION\n    // END_DEFINE_ATOMIC_FUNCTION\n}\n\nUse Atomic Function\n*******************\n{xrst_literal\n    // BEGIN_USE_ATOMIC_FUNCTION\n    // END_USE_ATOMIC_FUNCTION\n}\n\n{xrst_end atomic_four_bilinear.cpp}\n*/\n# include <cppad/cppad.hpp>  // CppAD include file\n\n// BEGIN_DEFINE_ATOMIC_FUNCTION\n// empty namespace\nnamespace {\n    // atomic_bilinear\n    class atomic_bilinear : public CppAD::atomic_four<double> {\n    private:\n        // u_grid_, v_grid_; y_grid_\n        CppAD::vector<double>& u_grid_;\n        CppAD::vector<double>& v_grid_;\n        CppAD::vector<double>& y_grid_;\n        //\n        // u_index_, v_index\n        size_t u_index_;\n        size_t v_index_;\n        //\n        // set_index\n        void set_index(double u, double v)\n        {   //\n            // u_index_\n            while( u < u_grid_[u_index_] && u_index_ > 0 )\n                --u_index_;\n            while( u > u_grid_[u_index_+1] && u_index_ < u_grid_.size() - 2 )\n                ++u_index_;\n            //\n            // v_index_\n            while( v < v_grid_[v_index_] && v_index_ > 0 )\n                --v_index_;\n            while( v > v_grid_[v_index_+1] && v_index_ < v_grid_.size() - 2 )\n                ++v_index_;\n        }\n    public:\n        // can use const char* name when calling this constructor\n        atomic_bilinear(\n            const std::string&     name   ,\n            CppAD::vector<double>& u_grid ,\n            CppAD::vector<double>& v_grid ,\n            CppAD::vector<double>& y_grid )  :\n        CppAD::atomic_four<double>(name) , // inform base class of name\n        u_grid_(u_grid)                  ,\n        v_grid_(v_grid)                  ,\n        y_grid_(y_grid)                  ,\n        u_index_(0)                      ,\n        v_index_(0)\n        {   assert( u_grid_.size() >= 2 );\n            assert( v_grid_.size() >= 2 );\n            assert( y_grid_.size() == u_grid_.size() * v_grid_.size() );\n        }\n    private:\n        // for_type\n        bool for_type(\n            size_t                                     call_id     ,\n            const CppAD::vector<CppAD::ad_type_enum>&  type_x      ,\n            CppAD::vector<CppAD::ad_type_enum>&        type_y      ) override\n        {\n            assert( call_id == 0 );       // default value\n            assert( type_x.size() == 2 ); // n\n            assert( type_y.size() == 1 ); // m\n            //\n            type_y[0] = std::max(type_x[0], type_x[1]);\n            return true;\n        }\n        // forward\n        bool forward(\n            size_t                              call_id      ,\n            const CppAD::vector<bool>&          select_y     ,\n            size_t                              order_low    ,\n            size_t                              order_up     ,\n            const CppAD::vector<double>&        taylor_x     ,\n            CppAD::vector<double>&              taylor_y     ) override\n        {\n            // ok\n            bool ok = order_up <= 1;\n            if( ! ok )\n                return ok;\n            //\n            // q\n            size_t q = order_up + 1;\n            //\n# ifndef NDEBUG\n            size_t n = taylor_x.size() / q;\n            size_t m = taylor_y.size() / q;\n            assert( call_id == 0 );\n            assert( n == 2 );\n            assert( m == 1 );\n            assert( m == select_y.size() );\n# endif\n            // u, v\n            double u = taylor_x[0 * q + 0];\n            double v = taylor_x[1 * q + 0];\n            //\n            // u_index_, v_index_\n            set_index(u, v);\n            //\n            // u_0, u_1, v_0, v_1\n            double u_0 = u_grid_[ u_index_ + 0 ];\n            double u_1 = u_grid_[ u_index_ + 1 ];\n            double v_0 = v_grid_[ v_index_ + 0 ];\n            double v_1 = v_grid_[ v_index_ + 1 ];\n            //\n            // y_00, y_01, y_10, y_11\n            double y_00 = y_grid_[ (u_index_+0) * v_grid_.size() + v_index_+0 ];\n            double y_01 = y_grid_[ (u_index_+0) * v_grid_.size() + v_index_+1 ];\n            double y_10 = y_grid_[ (u_index_+1) * v_grid_.size() + v_index_+0 ];\n            double y_11 = y_grid_[ (u_index_+1) * v_grid_.size() + v_index_+1 ];\n            //\n            // taylor_y\n            // function value\n            if( order_low <= 0 )\n            {   double sum  = 0.0;\n                sum        += y_00 * (u_1 - u)   * (v_1 - v);\n                sum        += y_01 * (u_1 - u)   * (v   - v_0);\n                sum        += y_10 * (u   - u_0) * (v_1 - v);\n                sum        += y_11 * (u   - u_0) * (v   - v_0);\n                taylor_y[0] = sum / ( (u_1 - u_0) * (v_1 - v_0) );\n            }\n            //\n            // taylor_y\n            // first order derivatives\n            if( order_low <= 1 && 1 <= order_up )\n            {   //\n                // du, dv\n                double du   = taylor_x[0 * q + 1];\n                double dv   = taylor_x[1 * q + 1];\n                double dsum = 0.0;\n                //\n                dsum        -= y_00 * du * (v_1 - v);\n                dsum        -= y_01 * du * (v   - v_0);\n                dsum        += y_10 * du * (v_1 - v);\n                dsum        += y_11 * du * (v   - v_0);\n\n                dsum        -= y_00 * (u_1 - u)   * dv;\n                dsum        += y_01 * (u_1 - u)   * dv;\n                dsum        -= y_10 * (u   - u_0) * dv;\n                dsum        += y_11 * (u   - u_0) * dv;\n                taylor_y[1] = dsum / ( (u_1 - u_0) * (v_1 - v_0) );\n            }\n            //\n            return ok;\n        }\n    };\n}\n// END_DEFINE_ATOMIC_FUNCTION\n\n// BEGIN_USE_ATOMIC_FUNCTION\nbool bilinear(void)\n{   //\n    // ok, eps\n    bool ok = true;\n    double eps = 10. * CppAD::numeric_limits<double>::epsilon();\n    //\n    // nu, u_grid\n    size_t nu = 4;\n    CppAD::vector<double> u_grid(nu);\n    for(size_t i = 0; i < nu; ++i)\n        u_grid[i] = double(i) * 2.0;\n    //\n    // nv, v_grid\n    size_t nv = 5;\n    CppAD::vector<double> v_grid(nv);\n    for(size_t j = 0; j < nv; ++j)\n        v_grid[j] = double(j) * 3.0;\n    //\n    // y_grid\n    CppAD::vector<double> y_grid( u_grid.size() * v_grid.size() );\n    for(size_t i = 0; i < nu; ++i)\n    {   for(size_t j = 0; j < nv; ++j)\n        {   double u = u_grid[i];\n            double v = v_grid[j];\n            y_grid[i * v_grid.size() + j] = u * u + v * v;\n        }\n    }\n    //\n    // afun\n    std::string name = \"atomic_bilinear\";\n    atomic_bilinear afun(name, u_grid, v_grid, y_grid);\n    //\n    // n, m\n    size_t n = 2;\n    size_t m = 1;\n    //\n    // ax\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) ax(n);\n    ax[0]     = 0.0;\n    ax[1]     = 0.0;\n    CppAD::Independent(ax);\n    //\n    // ay\n    // call atomic function and store result in ay\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) ay(m);\n    afun(ax, ay);\n    //\n    // f\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(ax, ay);\n    //\n    // y\n    CPPAD_TESTVECTOR( double ) x(n), y(m);\n    x[0] = 1.0;\n    x[1] = 3.5;\n    y    = f.Forward(0, x);\n    //\n    // u_0, u_1\n    double u_0 = u_grid[0];\n    double u_1 = u_grid[1];\n    assert( u_0 < x[0] && x[0] < u_1 );\n    //\n    // v_0, v_1\n    double v_0 = v_grid[1];\n    double v_1 = v_grid[2];\n    assert( v_0 < x[1] && x[1] < v_1 );\n    //\n    // y_00, y_01, y_10, y_11\n    double y_00 = y_grid[ 0 * v_grid.size() + 1 ];\n    double y_01 = y_grid[ 0 * v_grid.size() + 2 ];\n    double y_10 = y_grid[ 1 * v_grid.size() + 1 ];\n    double y_11 = y_grid[ 1 * v_grid.size() + 2 ];\n    //\n    // check, ok\n    double sum   = 0.0;\n    sum         += y_00 * (u_1  - x[0]) * (v_1  - x[1]);\n    sum         += y_01 * (u_1  - x[0]) * (x[1] - v_0);\n    sum         += y_10 * (x[0] - u_0)  * (v_1  - x[1]);\n    sum         += y_11 * (x[0] - u_0)  * (x[1] - v_0);\n    double check = sum / ( (u_1 - u_0)  * (v_1 - v_0) );\n    ok          &= CppAD::NearEqual(y[0] , check,  eps, eps);\n    //\n    // dy\n    CPPAD_TESTVECTOR( double ) dx(n), dy(m);\n    dx[0] = 1.0;\n    dx[1] = 0.0;\n    dy   = f.Forward(1, dx);\n    //\n    // check\n    sum    = 0.0;\n    sum   -= y_00 * (v_1  - x[1]);\n    sum   -= y_01 * (x[1] - v_0);\n    sum   += y_10 * (v_1  - x[1]);\n    sum   += y_11 * (x[1] - v_0);\n    check  = sum / ( (u_1 - u_0)  * (v_1 - v_0) );\n    ok    &= CppAD::NearEqual(dy[0] , check,  eps, eps);\n    //\n    // dy\n    dx[0] = 0.0;\n    dx[1] = 1.0;\n    dy   = f.Forward(1, dx);\n    //\n    // check\n    sum    = 0.0;\n    sum   -= y_00 * (u_1  - x[0]);\n    sum   += y_01 * (u_1  - x[0]);\n    sum   -= y_10 * (x[0] - u_0);\n    sum   += y_11 * (x[0] - u_0);\n    check  = sum / ( (u_1 - u_0)  * (v_1 - v_0) );\n    ok    &= CppAD::NearEqual(dy[0] , check,  eps, eps);\n    //\n    return ok;\n}\n// END_USE_ATOMIC_FUNCTION\n"
  },
  {
    "path": "example/atomic_four/dynamic.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin atomic_four_dynamic.cpp}\n\nAtomic Functions with Dynamic Parameters: Example and Test\n##########################################################\n\nPurpose\n*******\nThis example demonstrates using dynamic parameters with an\n:ref:`atomic_four-name` function.\n\nFunction\n********\nFor this example, the atomic function\n:math:`g : \\B{R}^3 \\rightarrow \\B{R}^3` is defined by\n:math:`g_0 (x) = x_0 * x_ 0`,\n:math:`g_1 (x) = x_0 * x_ 1`,\n:math:`g_2 (x) = x_1 * x_ 2`.\n\nDefine Atomic Function\n**********************\n{xrst_literal\n    // BEGIN_DEFINE_ATOMIC_FUNCTION\n    // END_DEFINE_ATOMIC_FUNCTION\n}\n\nUse Atomic Function\n*******************\n{xrst_literal\n    // BEGIN_USE_ATOMIC_FUNCTION\n    // END_USE_ATOMIC_FUNCTION\n}\n\n{xrst_end atomic_four_dynamic.cpp}\n*/\n\n# include <cppad/cppad.hpp>\n\n// BEGIN_DEFINE_ATOMIC_FUNCTION\n// empty namespace\nnamespace {\n    // atomic_dynamic\n    class atomic_dynamic : public CppAD::atomic_four<double> {\n    public:\n        atomic_dynamic(const std::string& name) :\n        CppAD::atomic_four<double>(name)\n        { }\n    private:\n        // for_type\n        bool for_type(\n        size_t                                     call_id     ,\n        const CppAD::vector<CppAD::ad_type_enum>&  type_x      ,\n        CppAD::vector<CppAD::ad_type_enum>&        type_y      ) override\n        {   assert( call_id == 0 );       // default value\n            assert( type_x.size() == 3 ); // n\n            assert( type_y.size() == 3 ); // m\n            //\n            // type_y\n            type_y[0] = type_x[0];\n            type_y[1] = std::max( type_x[0], type_x[1] );\n            type_y[2] = std::max( type_x[1], type_x[2] );\n            return true;\n        }\n        // forward\n        bool forward(\n            size_t                        call_id      ,\n            const CppAD::vector<bool>&    select_y     ,\n            size_t                        order_low    ,\n            size_t                        order_up     ,\n            const CppAD::vector<double>&  taylor_x     ,\n            CppAD::vector<double>&        taylor_y     ) override\n        {\n# ifndef NDEBUG\n            size_t q = order_up + 1;\n            size_t n = taylor_x.size() / q;\n            size_t m = taylor_y.size() / q;\n            assert( n == 3 );\n            assert( m == 3 );\n# endif\n            // ok\n            bool ok = order_low == 0 && order_up == 0;\n            if( ! ok )\n                return ok;\n            //\n            // taylor_y[0] = g_0 = x_0 * x_0\n            if( select_y[0] )\n                taylor_y[0] = taylor_x[0] * taylor_x[0];\n            //\n            // taylor_y[1] = g_1 = x_0 * x_1\n            if( select_y[1] )\n                taylor_y[1] = taylor_x[0] * taylor_x[1];\n            //\n            // taylor_y[2] = g_2 = x_1 * x_2\n            if( select_y[2] )\n                taylor_y[2] = taylor_x[1] * taylor_x[2];\n            //\n            return ok;\n        }\n    };\n}\n// END_DEFINE_ATOMIC_FUNCTION\n\n// BEGIN_USE_ATOMIC_FUNCTION\nbool dynamic(void)\n{   // ok, eps\n    bool ok = true;\n    double eps = 10. * CppAD::numeric_limits<double>::epsilon();\n    //\n    // afun\n    atomic_dynamic afun(\"atomic_dynamic\");\n    //\n    // c, p, u\n    CPPAD_TESTVECTOR(double) c(1), p(1), u(1);\n    c[0] = 2.0;\n    p[0] = 3.0;\n    u[0] = 4.0;\n    //\n    //\n    // np, nu, ny\n    size_t np = 1;\n    size_t nu = 1;\n    size_t nx = 3;\n    size_t ny = 3;\n    //\n    // ap\n    // independent dynamic parameter vector\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) ap(np);\n    ap[0] = p[0];\n    //\n    // au\n    // independent variable vector\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) au(nu);\n    au[0] = u[0];\n    //\n    // Independent\n    CppAD::Independent(au, ap);\n    //\n    // ay\n    // y = ( c * c, c * p, p * x )\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) ax(nx), ay(ny);\n    ax[0] = c[0];  // x_0\n    ax[1] = ap[0]; // x_1\n    ax[2] = au[0]; // x_2\n    afun(ax, ay);\n    //\n    // ay\n    // check type of result\n    ok &= Constant( ay[0] );\n    ok &= Dynamic(  ay[1] );\n    ok &= Variable( ay[2] );\n    //\n    // f\n    // f(u) = (c * c, c * p, p * u)\n    CppAD::ADFun<double> f;\n    f.Dependent (au, ay);\n    //\n    // ay[0]\n    double check = c[0] * c[0];\n    ok &= CppAD::NearEqual( Value(ay[0]) , check,  eps, eps);\n    //\n    // ay[1]\n    check = c[0] * p[0];\n    ok &= CppAD::NearEqual( Value(ay[1]) , check,  eps, eps);\n    //\n    // ay[2]\n    check = p[0] * u[0];\n    ok &= CppAD::NearEqual( Value(ay[2]) , check,  eps, eps);\n    //\n    // y = f.Forward(0, u)\n    CPPAD_TESTVECTOR(double) y(ny);\n    y     = f.Forward(0, u);\n    check = c[0] * c[0];\n    ok    &= CppAD::NearEqual(y[0] , check,  eps, eps);\n    check = c[0] * p[0];\n    ok    &= CppAD::NearEqual(y[1] , check,  eps, eps);\n    check = p[0] * u[0];\n    ok    &= CppAD::NearEqual(y[2] , check,  eps, eps);\n    //\n    // p\n    p[0]   = 2.0 * p[0];\n    f.new_dynamic(p);\n    //\n    // y = f.Forward(0, u)\n    y     = f.Forward(0, u);\n    check = c[0] * c[0];\n    ok    &= CppAD::NearEqual(y[0] , check,  eps, eps);\n    check = c[0] * p[0];\n    ok    &= CppAD::NearEqual(y[1] , check,  eps, eps);\n    check = p[0] * u[0];\n    ok    &= CppAD::NearEqual(y[2] , check,  eps, eps);\n    //\n    return ok;\n}\n// END_USE_ATOMIC_FUNCTION\n"
  },
  {
    "path": "example/atomic_four/forward.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_four_forward.cpp}\n\nAtomic Functions and Forward Mode: Example and Test\n###################################################\n\nPurpose\n*******\nThis example demonstrates forward mode derivative calculation\nusing an :ref:`atomic_four-name` function.\n\nFunction\n********\nFor this example, the atomic function\n:math:`g : \\B{R}^3 \\rightarrow \\B{R}^2` is defined by\n\n.. math::\n\n    g(x) = \\left( \\begin{array}{c}\n        x_2 * x_2 \\\\\n        x_0 * x_1\n    \\end{array} \\right)\n\nJacobian\n********\nThe corresponding Jacobian is\n\n.. math::\n\n    g^{(1)} (x) = \\left( \\begin{array}{ccc}\n      0  &   0 & 2 x_2 \\\\\n    x_1  & x_0 & 0\n    \\end{array} \\right)\n\nHessian\n*******\nThe Hessians of the component functions are\n\n.. math::\n\n    g_0^{(2)} ( x ) = \\left( \\begin{array}{ccc}\n        0 & 0 & 0  \\\\\n        0 & 0 & 0  \\\\\n        0 & 0 & 2\n    \\end{array} \\right)\n    \\W{,}\n    g_1^{(2)} ( x ) = \\left( \\begin{array}{ccc}\n        0 & 1 & 0 \\\\\n        1 & 0 & 0 \\\\\n        0 & 0 & 0\n    \\end{array} \\right)\n\nDefine Atomic Function\n**********************\n{xrst_literal\n    // BEGIN_DEFINE_ATOMIC_FUNCTION\n    // END_DEFINE_ATOMIC_FUNCTION\n}\n\nUse Atomic Function\n*******************\n{xrst_literal\n    // BEGIN_USE_ATOMIC_FUNCTION\n    // END_USE_ATOMIC_FUNCTION\n}\n\n{xrst_end atomic_four_forward.cpp}\n*/\n# include <cppad/cppad.hpp>\n\n// BEGIN_DEFINE_ATOMIC_FUNCTION\n// empty namespace\nnamespace {\n    //\n    class atomic_forward : public CppAD::atomic_four<double> {\n    public:\n        atomic_forward(const std::string& name) :\n        CppAD::atomic_four<double>(name)\n        { }\n    private:\n        // for_type\n        bool for_type(\n            size_t                                     call_id     ,\n            const CppAD::vector<CppAD::ad_type_enum>&  type_x      ,\n            CppAD::vector<CppAD::ad_type_enum>&        type_y      ) override\n        {\n            bool ok = type_x.size() == 3; // n\n            ok     &= type_y.size() == 2; // m\n            if( ! ok )\n                return false;\n            type_y[0] = type_x[2];\n            type_y[1] = std::max(type_x[0], type_x[1]);\n            return true;\n        }\n        // forward\n        bool forward(\n            size_t                                    call_id      ,\n            const CppAD::vector<bool>&                select_y     ,\n            size_t                                    order_low    ,\n            size_t                                    order_up     ,\n            const CppAD::vector<double>&              tx           ,\n            CppAD::vector<double>&                    ty           ) override\n        {\n            size_t q = order_up + 1;\n# ifndef NDEBUG\n            size_t n = tx.size() / q;\n            size_t m = ty.size() / q;\n# endif\n            assert( n == 3 );\n            assert( m == 2 );\n            assert( order_low <= order_up );\n\n            // this example only implements up to second order forward mode\n            bool ok = order_up <=  2;\n            if( ! ok )\n                return ok;\n\n            // --------------------------------------------------------------\n            // Zero forward mode.\n            // This case must always be implemented\n            // g(x) = [ x_2 * x_2 ]\n            //        [ x_0 * x_1 ]\n            // y^0  = f( x^0 )\n            if( order_low <= 0 )\n            {   // y_0^0 = x_2^0 * x_2^0\n                ty[0 * q + 0] = tx[2 * q + 0] * tx[2 * q + 0];\n                // y_1^0 = x_0^0 * x_1^0\n                ty[1 * q + 0] = tx[0 * q + 0] * tx[1 * q + 0];\n            }\n            if( order_up <=  0 )\n                return ok;\n            // --------------------------------------------------------------\n            // First order forward mode.\n            // This case is needed if first order forward mode is used.\n            // g'(x) = [   0,   0, 2 * x_2 ]\n            //         [ x_1, x_0,       0 ]\n            // y^1 =  f'(x^0) * x^1\n            if( order_low <= 1 )\n            {   // y_0^1 = 2 * x_2^0 * x_2^1\n                ty[0 * q + 1] = 2.0 * tx[2 * q + 0] * tx[2 * q + 1];\n                // y_1^1 = x_1^0 * x_0^1 + x_0^0 * x_1^1\n                ty[1 * q + 1]  = tx[1 * q + 0] * tx[0 * q + 1];\n                ty[1 * q + 1] += tx[0 * q + 0] * tx[1 * q + 1];\n            }\n            if( order_up <=  1 )\n                return ok;\n            // --------------------------------------------------------------\n            // Second order forward mode.\n            // This case is needed if second order forward mode is used.\n            // g'(x) = [   0,   0, 2 x_2 ]\n            //         [ x_1, x_0,     0 ]\n            //\n            //            [ 0 , 0 , 0 ]                  [ 0 , 1 , 0 ]\n            // g_0''(x) = [ 0 , 0 , 0 ]  g_1^{(2)} (x) = [ 1 , 0 , 0 ]\n            //            [ 0 , 0 , 2 ]                  [ 0 , 0 , 0 ]\n            //\n            //  y_0^2 = x^1 * g_0''( x^0 ) x^1 / 2! + g_0'( x^0 ) x^2\n            //        = ( x_2^1 * 2.0 * x_2^1 ) / 2!\n            //        + 2.0 * x_2^0 * x_2^2\n            ty[0 * q + 2]  = tx[2 * q + 1] * tx[2 * q + 1];\n            ty[0 * q + 2] += 2.0 * tx[2 * q + 0] * tx[2 * q + 2];\n            //\n            //  y_1^2 = x^1 * g_1''( x^0 ) x^1 / 2! + g_1'( x^0 ) x^2\n            //        = ( x_1^1 * x_0^1 + x_0^1 * x_1^1) / 2\n            //        + x_1^0 * x_0^2 + x_0^0 + x_1^2\n            ty[1 * q + 2]  = tx[1 * q + 1] * tx[0 * q + 1];\n            ty[1 * q + 2] += tx[1 * q + 0] * tx[0 * q + 2];\n            ty[1 * q + 2] += tx[0 * q + 0] * tx[1 * q + 2];\n            // --------------------------------------------------------------\n            return ok;\n        }\n    };\n}\n// END_DEFINE_ATOMIC_FUNCTION\n\n// BEGIN_USE_ATOMIC_FUNCTION\nbool forward(void)\n{   // ok, eps\n    bool ok = true;\n    double eps = 10. * CppAD::numeric_limits<double>::epsilon();\n    //\n    // AD, NearEqual\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    //\n    // afun\n    atomic_forward afun(\"atomic_forward\");\n    //\n    // Create the function f(u) = g(u) for this example.\n    //\n    // n, u, au\n    size_t n  = 3;\n    CPPAD_TESTVECTOR(double)       u(n);\n    u[0] = 1.00;\n    u[1] = 2.00;\n    u[2] = 3.00;\n    CPPAD_TESTVECTOR( AD<double> ) au(n);\n    for(size_t j = 0; j < n; ++j)\n        au[j] = u[j];\n    CppAD::Independent(au);\n    //\n    // m, ay\n    size_t m = 2;\n    CPPAD_TESTVECTOR( AD<double> ) ay(m);\n    CPPAD_TESTVECTOR( AD<double> ) ax = au;\n    afun(ax, ay);\n    //\n    // f\n    CppAD::ADFun<double> f;\n    f.Dependent(au, ay);\n    //\n    // check function value\n    double check = u[2] * u[2];\n    ok &= NearEqual( Value(ay[0]) , check,  eps, eps);\n    check = u[0] * u[1];\n    ok &= NearEqual( Value(ay[1]) , check,  eps, eps);\n\n    // ----------------------------------------------------------------\n    // zero order forward\n    //\n    // u0, y0\n    CPPAD_TESTVECTOR(double) u0(n), y0(m);\n    u0 = u;\n    y0   = f.Forward(0, u0);\n    check = u[2] * u[2];\n    ok &= NearEqual(y0[0] , check,  eps, eps);\n    check = u[0] * u[1];\n    ok &= NearEqual(y0[1] , check,  eps, eps);\n    // ----------------------------------------------------------------\n    // first order forward\n    //\n    // check_jac\n    double check_jac[] = {\n        0.0, 0.0, 2.0 * u[2],\n        u[1], u[0],       0.0\n    };\n    //\n    // u1\n    CPPAD_TESTVECTOR(double) u1(n);\n    for(size_t j = 0; j < n; j++)\n        u1[j] = 0.0;\n    //\n    // y1, j\n    CPPAD_TESTVECTOR(double) y1(m);\n    for(size_t j = 0; j < n; j++)\n    {   //\n        // u1, y1\n        // compute partial in j-th component direction\n        u1[j] = 1.0;\n        y1    = f.Forward(1, u1);\n        u1[j] = 0.0;\n        //\n        // check this partial\n        for(size_t i = 0; i < m; i++)\n            ok &= NearEqual(y1[i], check_jac[i * n + j], eps, eps);\n    }\n    // ----------------------------------------------------------------\n    // second order forward\n    //\n    // check_hes_0\n    double check_hes_0[] = {\n        0.0, 0.0, 0.0,\n        0.0, 0.0, 0.0,\n        0.0, 0.0, 2.0\n    };\n    //\n    // check_hes_1\n    double check_hes_1[] = {\n        0.0, 1.0, 0.0,\n        1.0, 0.0, 0.0,\n        0.0, 0.0, 0.0\n    };\n    //\n    // u2\n    CPPAD_TESTVECTOR(double) u2(n);\n    for(size_t j = 0; j < n; j++)\n        u2[j] = 0.0;\n    //\n    // y2, j\n    CPPAD_TESTVECTOR(double) y2(m);\n    for(size_t j = 0; j < n; j++)\n    {   //\n        // u1, y2\n        // first order forward in j-th direction\n        u1[j] = 1.0;\n        f.Forward(1, u1);\n        y2 = f.Forward(2, u2);\n        //\n        // check y2 element of Hessian diagonal\n        ok &= NearEqual(y2[0], check_hes_0[j * n + j] / 2.0, eps, eps);\n        ok &= NearEqual(y2[1], check_hes_1[j * n + j] / 2.0, eps, eps);\n        //\n        // k\n        for(size_t k = 0; k < n; k++) if( k != j )\n        {   //\n            // u1, y2\n            u1[k] = 1.0;\n            f.Forward(1, u1);\n            y2 = f.Forward(2, u2);\n            //\n            // y2 = (H_jj + H_kk + H_jk + H_kj) / 2.0\n            // y2 = (H_jj + H_kk) / 2.0 + H_jk\n            //\n            // check y2[0]\n            double H_jj = check_hes_0[j * n + j];\n            double H_kk = check_hes_0[k * n + k];\n            double H_jk = y2[0] - (H_kk + H_jj) / 2.0;\n            ok &= NearEqual(H_jk, check_hes_0[j * n + k], eps, eps);\n            //\n            // check y2[1]\n            H_jj = check_hes_1[j * n + j];\n            H_kk = check_hes_1[k * n + k];\n            H_jk = y2[1] - (H_kk + H_jj) / 2.0;\n            ok &= NearEqual(H_jk, check_hes_1[j * n + k], eps, eps);\n            //\n            // u1\n            u1[k] = 0.0;\n        }\n        // u1\n        u1[j] = 0.0;\n    }\n    // ----------------------------------------------------------------\n    return ok;\n}\n// END_USE_ATOMIC_FUNCTION\n"
  },
  {
    "path": "example/atomic_four/get_started.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin atomic_four_get_started.cpp}\n\nGetting Started with Atomic Functions: Example and Test\n#######################################################\n\nPurpose\n*******\nThis example demonstrates the minimal amount of information\nnecessary for a :ref:`atomic_four-name` function.\n\nDefine Atomic Function\n**********************\n{xrst_literal\n    // BEGIN_DEFINE_ATOMIC_FUNCTION\n    // END_DEFINE_ATOMIC_FUNCTION\n}\n\nUse Atomic Function\n*******************\n{xrst_literal\n    // BEGIN_USE_ATOMIC_FUNCTION\n    // END_USE_ATOMIC_FUNCTION\n}\n\n{xrst_end atomic_four_get_started.cpp}\n*/\n# include <cppad/cppad.hpp>  // CppAD include file\n\n// BEGIN_DEFINE_ATOMIC_FUNCTION\n// empty namespace\nnamespace {\n    // atomic_get_started\n    class atomic_get_started : public CppAD::atomic_four<double> {\n    public:\n        // can use const char* name when calling this constructor\n        atomic_get_started(const std::string& name) :\n        CppAD::atomic_four<double>(name) // inform base class of name\n        { }\n    private:\n        // for_type\n        bool for_type(\n            size_t                                     call_id     ,\n            const CppAD::vector<CppAD::ad_type_enum>&  type_x      ,\n            CppAD::vector<CppAD::ad_type_enum>&        type_y      ) override\n        {\n            assert( call_id == 0 );       // default value\n            assert( type_x.size() == 1 ); // n\n            assert( type_y.size() == 1 ); // m\n            //\n            type_y[0] = type_x[0];\n            return true;\n        }\n        // forward\n        bool forward(\n            size_t                              call_id      ,\n            const CppAD::vector<bool>&          select_y     ,\n            size_t                              order_low    ,\n            size_t                              order_up     ,\n            const CppAD::vector<double>&        taylor_x     ,\n            CppAD::vector<double>&              taylor_y     ) override\n        {\n# ifndef NDEBUG\n            size_t q = order_up + 1;\n            size_t n = taylor_x.size() / q;\n            size_t m = taylor_y.size() / q;\n            assert( call_id == 0 );\n            assert( order_low == 0);\n            assert( order_up == 0);\n            assert( n == 1 );\n            assert( m == 1 );\n            assert( m == select_y.size() );\n# endif\n            // return flag\n            bool ok = order_up == 0;\n            if( ! ok )\n                return ok;\n\n            // taylor_y\n            // Order zero forward mode: y^0 = g( x^0 ) = 1 / x^0\n            taylor_y[0] = 1.0 / taylor_x[0];\n            //\n            return ok;\n        }\n    };\n}\n// END_DEFINE_ATOMIC_FUNCTION\n\n// BEGIN_USE_ATOMIC_FUNCTION\nbool get_started(void)\n{\n    // ok, eps\n    bool ok = true;\n    double eps = 10. * CppAD::numeric_limits<double>::epsilon();\n    //\n    // afun\n    atomic_get_started afun(\"atomic_get_started\");\n    //\n    // n, m\n    size_t n = 1;\n    size_t m = 1;\n    //\n    // x0\n    double  x0 = 0.5;\n    //\n    // ax\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) ax(n);\n    ax[0]     = x0;\n    CppAD::Independent(ax);\n    //\n    // au\n    // call atomic function and store result in au\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) au(m);\n    afun(ax, au);\n    //\n    // ay\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) ay(m);\n    ay[0] = 1.0 + au[0];\n    //\n    // f\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(ax, ay);\n    //\n    // check\n    double check = 1.0 + 1.0 / x0;\n    //\n    // ok\n    // check ay[0]\n    ok &= CppAD::NearEqual( Value(ay[0]) , check,  eps, eps);\n    //\n    // ok\n    // check zero order forward mode\n    CPPAD_TESTVECTOR( double ) x(n), y(m);\n    x[0] = x0;\n    y    = f.Forward(0, x);\n    ok    &= CppAD::NearEqual(y[0] , check,  eps, eps);\n    //\n    return ok;\n}\n// END_USE_ATOMIC_FUNCTION\n"
  },
  {
    "path": "example/atomic_four/lin_ode/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n#\n# BEGIN_SORT_THIS_LINE_PLUS_2\nSET(source_list\n    forward.cpp\n    lin_ode.cpp\n    rev_depend.cpp\n    reverse.cpp\n    sparsity.cpp\n)\n# END_SORT_THIS_LINE_MINUS_2\n\nset_compile_flags(example_atomic_four_lin_ode\n    \"${cppad_debug_which}\" \"${source_list}\"\n)\n#\nADD_EXECUTABLE(example_atomic_four_lin_ode EXCLUDE_FROM_ALL ${source_list})\n#\n# List of libraries to be linked into the specified target\nTARGET_LINK_LIBRARIES(example_atomic_four_lin_ode\n    ${cppad_lib}\n    ${colpack_libs}\n)\n#\n# check_example_atomic_four_lin_ode\nadd_check_executable(check_example_atomic_four lin_ode)\n"
  },
  {
    "path": "example/atomic_four/lin_ode/forward.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_four_lin_ode_forward.cpp}\n{xrst_spell\n    cccc\n}\n\nAtomic Linear ODE Forward Mode: Example and Test\n################################################\n\nPurpose\n*******\nThis example demonstrates using forward mode with\nthe :ref:`atomic_four_lin_ode-name` class.\n\nf(u)\n****\nFor this example, the function :math:`f(u) = z(r, u)` where\n:math:`z(t, u)` solves the following ODE\n\n.. math::\n\n    z_t (t, u) =\n    \\left( \\begin{array}{cccc}\n    0   & 0  & 0    & 0   \\\\\n    u_4 & 0  & 0    & 0   \\\\\n    0   & u_5 & 0   & 0   \\\\\n    0   & 0   & u_6 & 0   \\\\\n    \\end{array} \\right)\n    z(t, u)\n    \\W{,}\n    z(0, u) =\n    \\left( \\begin{array}{c}\n    u_0 \\\\\n    u_1 \\\\\n    u_2 \\\\\n    u_3 \\\\\n    \\end{array} \\right)\n\nz(t, u)\n*******\nThe actual solution to this ODE is\n\n.. math::\n\n    z(t, u) =\n    \\left( \\begin{array}{l}\n    u_0  \\\\\n    u_1 + u_4 u_0 t \\\\\n    u_2 + u_5 u_1 t + u_5 u_4 u_0 t^2 / 2  \\\\\n    u_3 + u_6 u_2 t + u_6 u_5 u_1 t^2 / 2 + u_6 u_5 u_4 u_0 t^3 / 6\n    \\end{array} \\right)\n\ng(u)\n****\nWe define :math:`g(u) = \\partial_{u0} f(u)`.\nIt follows that\n\n.. math::\n\n    g (u) =\n    \\left( \\begin{array}{l}\n    1  \\\\\n    u_4 r \\\\\n    u_5 u_4 r^2 / 2  \\\\\n    u_6 u_5 u_4 r^3 / 6\n    \\end{array} \\right)\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end atomic_four_lin_ode_forward.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n# include <cppad/example/atomic_four/lin_ode/lin_ode.hpp>\n\nnamespace { // BEGIN_EMPTY_NAMESPACE\n\ntemplate <class Scalar, class Vector>\nVector Z(Scalar t, const Vector& u)\n{   size_t nz = 4;\n    Vector z(nz);\n    //\n    z[0]  = u[0];\n    z[1]  = u[1] + u[4]*u[0]*t;\n    z[2]  = u[2] + u[5]*u[1]*t + u[5]*u[4]*u[0]*t*t/2.0;\n    z[3]  = u[3] + u[6]*u[2]*t + u[6]*u[5]*u[1]*t*t/2.0\n             + u[6]*u[5]*u[4]*u[0]*t*t*t/6.0;\n    //\n    return z;\n}\n\ntemplate <class Scalar, class Vector>\nVector G(Scalar t, const Vector& u)\n{   size_t ng = 4;\n    Vector g(ng);\n    //\n    g[0]  = Scalar(1.0);\n    g[1]  = u[4]*t;\n    g[2]  = u[5]*u[4]*t*t/2.0;\n    g[3]  = u[6]*u[5]*u[4]*t*t*t/6.0;\n    //\n    return g;\n}\n\n} // END_EMPTY_NAMESPACE\n\nbool forward(void)\n{   // ok\n    bool ok = true;\n    //\n    // AD, NearEqual, eps99\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps99 = std::numeric_limits<double>::epsilon() * 99.0;\n    // -----------------------------------------------------------------------\n    // Record f\n    // -----------------------------------------------------------------------\n    //\n    // afun\n    CppAD::atomic_lin_ode<double> afun(\"atomic_lin_ode\");\n    //\n    // m, r\n    size_t m      = 4;\n    double r      = 2.0;\n    double step   = 1.0;\n    //\n    // pattern, transpose\n    size_t nr  = m;\n    size_t nc  = m;\n    size_t nnz = 3;\n    CppAD::sparse_rc< CppAD::vector<size_t> > pattern(nr, nc, nnz);\n    for(size_t k = 0; k < nnz; ++k)\n    {   size_t i = k + 1;\n        size_t j = k;\n        pattern.set(k, i, j);\n    }\n    bool transpose = false;\n    //\n    // ny, ay\n    size_t ny = m;\n    CPPAD_TESTVECTOR( AD<double> ) ay(ny);\n    //\n    // nu, au\n    size_t nu = nnz + m;\n    CPPAD_TESTVECTOR( AD<double> ) au(nu);\n    for(size_t j = 0; j < nu; ++j)\n        au[j] = AD<double>(j + 1);\n    CppAD::Independent(au);\n    //\n    // ax\n    CPPAD_TESTVECTOR( AD<double> ) ax(nnz + m);\n    for(size_t k = 0; k < nnz; ++k)\n        ax[k] = au[m + k];\n    for(size_t i = 0; i < m; ++i)\n        ax[nnz + i] = au[i];\n    //\n    // ay\n    size_t call_id = afun.set(r, step, pattern, transpose);\n    afun(call_id, ax, ay);\n    //\n    // f\n    CppAD::ADFun<double> f(au, ay);\n    // -----------------------------------------------------------------------\n    // ar, check_f\n    CppAD::Independent(au);\n    AD<double> ar = r;\n    ay = Z(ar, au);\n    CppAD::ADFun<double> check_f(au, ay);\n    // -----------------------------------------------------------------------\n    // forward mode on f\n    // -----------------------------------------------------------------------\n    //\n    // u\n    CPPAD_TESTVECTOR(double) u(nu);\n    for(size_t j = 0; j < nu; ++j)\n        u[j] = double( j + 2 );\n    //\n    // y\n    // zero order forward mode computation of f(u)\n    CPPAD_TESTVECTOR(double) y(ny);\n    y = f.Forward(0, u);\n    //\n    // ok\n    CPPAD_TESTVECTOR(double) z = check_f.Forward(0, u);\n    for(size_t i = 0; i < ny; ++i)\n        ok &= NearEqual(y[i], z[i], eps99, eps99);\n    //\n    // du, ok\n    CPPAD_TESTVECTOR(double) du(nu), dy(ny), dz(ny);\n    for(size_t j = 0; j < nu; ++j)\n        du[j] = 0.0;\n    for(size_t j = 0; j < nu; ++j)\n    {   du[j] = 1.0;\n        dy    = f.Forward(1, du);\n        dz    = check_f.Forward(1, du);\n        for(size_t i = 0; i < ny; ++i)\n            ok &= NearEqual(dy[i], dz[i], eps99, eps99);\n        du[j] = 0.0;\n    }\n    // -----------------------------------------------------------------------\n    // Record g\n    // -----------------------------------------------------------------------\n    //\n    // af\n    CppAD::ADFun< AD<double>, double> af = f.base2ad();\n    //\n    // az\n    CppAD::Independent(au);\n    CPPAD_TESTVECTOR( AD<double> ) dau(nu), day(ny);\n    af.Forward(0, au);\n    for(size_t j = 0; j < nu; ++j)\n        dau[j] = 0.0;\n    dau[0] = 1.0;\n    day    = af.Forward(1, dau);\n    // g\n    CppAD::ADFun<double> g(au, day);\n    // -----------------------------------------------------------------------\n    // check_g\n    CppAD::Independent(au);\n    ay = G(ar, au);\n    CppAD::ADFun<double> check_g(au, ay);\n    // -----------------------------------------------------------------------\n    // forward mode on g\n    // -----------------------------------------------------------------------\n    //\n    // y\n    // zero order forward mode computation of g(u)\n    dy = g.Forward(0, u);\n    //\n    // ok\n    CPPAD_TESTVECTOR(double) v = check_g.Forward(0, u);\n    for(size_t i = 0; i < ny; ++i)\n        ok &= NearEqual(dy[i], v[i], eps99, eps99);\n    //\n    // du, ok\n    CPPAD_TESTVECTOR(double) ddy(ny), ddz(ny);\n    for(size_t j = 0; j < nu; ++j)\n        du[j] = 0.0;\n    for(size_t j = 0; j < nu; ++j)\n    {   du[j] = 1.0;\n        ddy    = g.Forward(1, du);\n        ddz    = check_g.Forward(1, du);\n        for(size_t i = 0; i < ny; ++i)\n            ok &= NearEqual(ddy[i], ddz[i], eps99, eps99);\n        du[j] = 0.0;\n    }\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/atomic_four/lin_ode/lin_ode.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n// CPPAD_HAS_* defines\n# include <cppad/configure.hpp>\n\n// system include files used for I/O\n# include <iostream>\n\n// C style asserts\n# include <cassert>\n\n// for thread_alloc\n# include <cppad/utility/thread_alloc.hpp>\n\n// test runner\n# include <cppad/utility/test_boolofvoid.hpp>\n\n// BEGIN_SORT_THIS_LINE_PLUS_1\nextern bool forward(void);\nextern bool rev_depend(void);\nextern bool reverse(void);\nextern bool sparsity(void);\n// END_SORT_THIS_LINE_MINUS_1\n\n// main program that runs all the tests\nint main(void)\n{   std::string group = \"example/atomic_four/lin_ode\";\n    size_t      width = 20;\n    CppAD::test_boolofvoid Run(group, width);\n\n    // This line is used by test_one.sh\n\n    // BEGIN_SORT_THIS_LINE_PLUS_1\n    Run( forward,             \"forward\"        );\n    Run( rev_depend,          \"rev_depend\"     );\n    Run( reverse,             \"reverse\"        );\n    Run( sparsity,            \"sparsity\"       );\n    // END_SORT_THIS_LINE_MINUS_1\n\n\n    // check for memory leak\n    bool memory_ok = CppAD::thread_alloc::free_all();\n    // print summary at end\n    bool ok = Run.summary(memory_ok);\n    //\n    return static_cast<int>( ! ok );\n}\n"
  },
  {
    "path": "example/atomic_four/lin_ode/rev_depend.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_four_lin_ode_rev_depend.cpp}\n{xrst_spell\n    cccc\n}\n\nAtomic Linear ODE Reverse Dependency Analysis: Example and Test\n###############################################################\n\nPurpose\n*******\nThis example demonstrates calculating reverse dependency with\nthe :ref:`atomic_four_lin_ode-name` class; see\n:ref:`atomic_four_lin_ode_rev_depend.hpp-name` .\n\ny(t, x)\n*******\nWe are given a positive integer m and define\n:math:`y : \\B{R} \\times \\B{R}^m \\rightarrow \\B{R}^m` by\n\n.. math::\n\n    y(t, x) = \\prod_{i=0}^m x_i t^i / i !\n\nIt follows that\n\n.. math::\n\n    \\partial_t y_i (t, x) = \\left \\{ \\begin{array}{ll}\n        0                   & \\R{if} \\; i = 0 \\\\\n        x_i y_{i-1} (t, x)  & \\R{otherwise}\n    \\end{array} \\right .\n    \\\\\n    \\partial_t y (t, x) =\n    \\left( \\begin{array}{cccc}\n    0        & 0        & \\cdots & 0        \\\\\n    x_1      & 0        & \\cdots & 0        \\\\\n    0        & x_2      &        & 0        \\\\\n    \\vdots   &          & \\ddots & \\vdots   \\\\\n    0        & 0        & \\cdots & x_m\n    \\end{array} \\right)\n    y (t, x)\n    \\W{,}\n    y (0, x) =\n    \\left( \\begin{array}{c}\n    x_0      \\\\\n    0        \\\\\n    \\vdots   \\\\\n    0        \\\\\n    \\end{array} \\right)\n\nProblem Parameters\n******************\nThe following problem parameters can be changed:\n{xrst_literal\n    // BEGIN_PROBLEM_PARAMETERS\n    // END_PROBLEM_PARAMETERS\n}\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end atomic_four_lin_ode_rev_depend.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n# include <cppad/example/atomic_four/lin_ode/lin_ode.hpp>\n\nnamespace { // BEGIN_EMPTY_NAMESPACE\n\n// y(t, x)\ntemplate <class Scalar, class Vector>\nVector Y(Scalar t, const Vector& x)\n{   size_t m = x.size();\n    Vector y(m);\n    //\n    // y\n    y[0]               = x[0];\n    for(size_t i = 1; i < m; ++i)\n        y[i] = x[i] * y[i-1] * t / Scalar(i);\n\n    return y;\n}\n\n} // END_EMPTY_NAMESPACE\n\nbool rev_depend(void)\n{   // ok, eps\n    bool ok = true;\n    //\n    // sparse_rc, AD, eps99\n    typedef CppAD::sparse_rc< CppAD::vector<size_t> > sparse_rc;\n    using CppAD::AD;\n    double eps99 = std::numeric_limits<double>::epsilon() * 99.0;\n    // -----------------------------------------------------------------------\n    // Record f\n    // -----------------------------------------------------------------------\n    //\n    // afun\n    CppAD::atomic_lin_ode<double> afun(\"atomic_lin_ode\");\n    //\n    // BEGIN_PROBLEM_PARAMETERS\n    // m, r, step\n    size_t m      = 5;       // number of components in x and y\n    double r      = 2.0;     // final time in the ODE\n    double step   = 1.0;     // step size used to approximation ODE solution\n    // END_PROBLEM_PARAMETERS\n    //\n    // pattern, transpose\n    size_t nr  = m;\n    size_t nc  = m;\n    size_t nnz = m - 1;\n    sparse_rc pattern(nr, nc, nnz);\n    for(size_t k = 0; k < nnz; ++k)\n    {   size_t i = k + 1;\n        size_t j = k;\n        pattern.set(k, i, j);\n    }\n    bool transpose = false;\n    //\n    // ax\n    CPPAD_TESTVECTOR( AD<double> ) ax(m);\n    for(size_t k = 0; k < m; ++k)\n        ax[k] = double(k + 1);\n    CppAD::Independent(ax);\n    //\n    // au\n    // au = (x[1], ..., x[nnz-1], x[0], 0, ..., 0)\n    CPPAD_TESTVECTOR( AD<double> ) au(nnz + m);\n    for(size_t k = 0; k < nnz; ++k)\n        au[k] = ax[k+1];\n    for(size_t i = 0; i < m; ++i)\n    {   if( i == 0 )\n            au[nnz + i] = ax[0];\n        else\n            au[nnz + i] = 0.0;\n    }\n    //\n    // ay\n    CPPAD_TESTVECTOR( AD<double> ) ay(m);\n    size_t call_id = afun.set(r, step, pattern, transpose);\n    afun(call_id, au, ay);\n    //\n    // z_index\n    // Fourth order Rosen34 method is exact approximation of y[i] for i <= 4\n    size_t z_index = m - 1;\n    assert(z_index <= 4);\n    //\n    // az\n    CPPAD_TESTVECTOR( AD<double> ) az(1);\n    az[0] = ay[z_index];\n    //\n    // f\n    // optimize uses rev_depend\n    CppAD::ADFun<double> f(ax, az);\n    f.optimize(\"val_graph no_conditional_skip\");\n    // -----------------------------------------------------------------------\n    // check_f\n    // -----------------------------------------------------------------------\n    CppAD::Independent(ax);\n    AD<double> ar = r;\n    ay    = Y(ar, ax);\n    az[0] = ay[z_index];\n    CppAD::ADFun<double> check_f(ax, az);\n    // -----------------------------------------------------------------------\n    // rev_depend\n    // use test_rev_depend to call rev_depend directly\n    // -----------------------------------------------------------------------\n    //\n    // depend_u\n    CppAD::vector<bool> ident_zero_u(nnz + m), depend_u(nnz + m), depend_y(m);\n    for(size_t i = 0; i < m; ++i)\n    {   depend_y[i]     = i == z_index;\n        ident_zero_u[i] = false;\n    }\n    for(size_t i = 1; i < m; ++i)\n        ident_zero_u[nnz + i] = true;\n    afun.test_rev_depend(call_id, ident_zero_u, depend_u, depend_y);\n    //\n    // depend_x\n    CppAD::vector<bool> depend_x(m);\n    depend_x[0] = depend_u[m-1];\n    for(size_t j = 1; j < m; ++j)\n        depend_x[j] = depend_u[j-1];\n    //\n    // x\n    CPPAD_TESTVECTOR(double) x(m);\n    for(size_t j = 0; j < m; ++j)\n        x[j] = double( j + 2 );\n    //\n    // dw\n    check_f.Forward(0, x);\n    CPPAD_TESTVECTOR(double) w(1), dw(m);\n    w[0] = 1.0;\n    dw = check_f.Reverse(1, w);\n    //\n    // ok\n    // note that for this x, partial w.r.t x[j] is non-zero if and only if\n    // y[z_index] depends on x[j]\n    for(size_t j = 0; j < m; ++j)\n        ok &= depend_x[j] == (dw[j] != 0.0);\n    //\n    // -----------------------------------------------------------------------\n    // forward mode on f\n    // Check that the optimized version of agrees with check_f.\n    // -----------------------------------------------------------------------\n    //\n    // z\n    // zero order forward mode computation of f(x)\n    CPPAD_TESTVECTOR(double) z = f.Forward(0, x);\n    //\n    // ok\n    CPPAD_TESTVECTOR(double) check_z = check_f.Forward(0, x);\n    ok &= CppAD::NearEqual(z[0], check_z[0], eps99, eps99);\n    //\n    // du, ok\n    CPPAD_TESTVECTOR(double) dx(m), dz(1), check_dz(1);\n    for(size_t j = 0; j < m; ++j)\n        dx[j] = 0.0;\n    //\n    for(size_t j = 0; j < m; ++j)\n    {   dx[j]     = 1.0;\n        dz        = f.Forward(1, dx);\n        check_dz  = check_f.Forward(1, dx);\n        ok       &= CppAD::NearEqual(dz[0], check_dz[0], eps99, eps99);\n        dx[j]     = 0.0;\n    }\n    // -----------------------------------------------------------------------\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/atomic_four/lin_ode/reverse.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_four_lin_ode_reverse.cpp}\n{xrst_spell\n    cccc\n}\n\nAtomic Linear ODE Reverse Mode: Example and Test\n################################################\n\nPurpose\n*******\nThis example demonstrates using reverse mode with\nthe :ref:`atomic_four_lin_ode-name` class.\n\nf(u)\n****\nFor this example, the function :math:`f(u) = z(r, u)` where\n:math:`z(t, u)` solves the following ODE\n\n.. math::\n\n    z_t (t, u) =\n    \\left( \\begin{array}{cccc}\n    0   & 0  & 0    & 0   \\\\\n    u_4 & 0  & 0    & 0   \\\\\n    0   & u_5 & 0   & 0   \\\\\n    0   & 0   & u_6 & 0   \\\\\n    \\end{array} \\right)\n    z(t, u)\n    \\W{,}\n    z(0, u) =\n    \\left( \\begin{array}{c}\n    u_0 \\\\\n    u_1 \\\\\n    u_2 \\\\\n    u_3 \\\\\n    \\end{array} \\right)\n\nSolution\n********\nThe actual solution to this ODE is\n\n.. math::\n\n    z(t, u) =\n    \\left( \\begin{array}{l}\n    u_0  \\\\\n    u_1 + u_4 u_0 t \\\\\n    u_2 + u_5 u_1 t + u_5 u_4 u_0 t^2 / 2  \\\\\n    u_3 + u_6 u_2 t + u_6 u_5 u_1 t^2 / 2 + u_6 u_5 u_4 u_0 t^3 / 6\n    \\end{array} \\right)\n\ng(u)\n****\n\n.. math::\n\n    z_2 (t, u) = u_2 + u_5 u_1 t + u_5 u_4 u_0 t^2 / 2\n\nFix :math:`r` and define :math:`g(u) = [ \\partial_u z(r, u) ]^\\R{T}`.\nIt follows that\n\n.. math::\n\n    g(u)\n    =\n    \\left( \\begin{array}{c}\n    u_5 u_4 r^2 / 2 \\\\\n    u_5 r \\\\\n    1 \\\\\n    0 \\\\\n    u_5 u_0 r^2 / 2 \\\\\n    u_t r + u_4 u_0 r^2 / 2 \\\\\n    0\n    \\end{array} \\right)\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end atomic_four_lin_ode_reverse.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n# include <cppad/example/atomic_four/lin_ode/lin_ode.hpp>\n\nnamespace { // BEGIN_EMPTY_NAMESPACE\n\ntemplate <class Scalar, class Vector>\nVector Z(Scalar t, const Vector& u)\n{   size_t nz = 4;\n    Vector z(nz);\n    //\n    z[0]  = u[0];\n    z[1]  = u[1] + u[4]*u[0]*t;\n    z[2]  = u[2] + u[5]*u[1]*t + u[5]*u[4]*u[0]*t*t/2.0;\n    z[3]  = u[3] + u[6]*u[2]*t + u[6]*u[5]*u[1]*t*t/2.0\n             + u[6]*u[5]*u[4]*u[0]*t*t*t/6.0;\n    //\n    return z;\n}\n\ntemplate <class Scalar, class Vector>\nVector G(Scalar t, const Vector& u)\n{   size_t nu = 7;\n    Vector g(nu);\n    //\n    g[0]  = u[5]*u[4]*t*t/2.0;\n    g[1]  = u[5]*t;\n    g[2]  = Scalar(1.0);\n    g[3]  = Scalar(0.0);\n    g[4]  = u[5]*u[0]*t*t/2.0;\n    g[5]  = u[1]*t + u[4]*u[0]*t*t/2.0;\n    g[6]  = Scalar(0.0);\n    //\n    return g;\n}\n\n} // END_EMPTY_NAMESPACE\n\nbool reverse(void)\n{   // ok\n    bool ok = true;\n    //\n    // AD, NearEqual, eps99\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps99 = std::numeric_limits<double>::epsilon() * 99.0;\n    // -----------------------------------------------------------------------\n    // Record f\n    // -----------------------------------------------------------------------\n    //\n    // afun\n    CppAD::atomic_lin_ode<double> afun(\"atomic_lin_ode\");\n    //\n    // m, r\n    size_t m      = 4;\n    double r      = 2.0;\n    double step   = 2.0;\n    //\n    // pattern, transpose\n    size_t nr  = m;\n    size_t nc  = m;\n    size_t nnz = 3;\n    CppAD::sparse_rc< CppAD::vector<size_t> > pattern(nr, nc, nnz);\n    for(size_t k = 0; k < nnz; ++k)\n    {   size_t i = k + 1;\n        size_t j = k;\n        pattern.set(k, i, j);\n    }\n    bool transpose = false;\n    //\n    // ny, ay\n    size_t ny = m;\n    CPPAD_TESTVECTOR( AD<double> ) ay(ny);\n    //\n    // nu, au\n    size_t nu = nnz + m;\n    CPPAD_TESTVECTOR( AD<double> ) au(nu);\n    for(size_t j = 0; j < nu; ++j)\n        au[j] = AD<double>(j + 1);\n    CppAD::Independent(au);\n    //\n    // ax\n    CPPAD_TESTVECTOR( AD<double> ) ax(nnz + m);\n    for(size_t k = 0; k < nnz; ++k)\n        ax[k] = au[m + k];\n    for(size_t i = 0; i < m; ++i)\n        ax[nnz + i] = au[i];\n    //\n    // ay\n    size_t call_id = afun.set(r, step, pattern, transpose);\n    afun(call_id, ax, ay);\n    //\n    // f\n    CppAD::ADFun<double> f(au, ay);\n    // -----------------------------------------------------------------------\n    // ar, check_f\n    CppAD::Independent(au);\n    AD<double> ar = r;\n    ay = Z(ar, au);\n    CppAD::ADFun<double> check_f(au, ay);\n    // -----------------------------------------------------------------------\n    // reverse mode on f\n    // -----------------------------------------------------------------------\n    //\n    // u\n    CPPAD_TESTVECTOR(double) u(nu);\n    for(size_t j = 0; j < nu; ++j)\n        u[j] = double( j + 2 );\n    //\n    // y\n    // zero order forward mode computation of f(u)\n    CPPAD_TESTVECTOR(double) y(ny);\n    y = f.Forward(0, u);\n    //\n    // ok\n    CPPAD_TESTVECTOR(double) check_y = check_f.Forward(0, u);\n    for(size_t i = 0; i < ny; ++i)\n        ok &= NearEqual(y[i], check_y[i], eps99, eps99);\n    //\n    // w, ok\n    CPPAD_TESTVECTOR(double) w(ny), dw(nu), check_dw(nu);\n    for(size_t i = 0; i < ny; ++i)\n        w[i] = 0.0;\n    for(size_t i = 0; i < ny; ++i)\n    {   w[i] = 1.0;\n        dw        = f.Reverse(1, w);\n        check_dw  = check_f.Reverse(1, w);\n        for(size_t j = 0; j < nu; ++j)\n            ok &= NearEqual(dw[j], check_dw[j], eps99, eps99);\n        w[i] = 0.0;\n    }\n    // -----------------------------------------------------------------------\n    // Record g\n    // -----------------------------------------------------------------------\n    //\n    // af\n    CppAD::ADFun< AD<double>, double> af = f.base2ad();\n    //\n    // au\n    CppAD::Independent(au);\n    CPPAD_TESTVECTOR( AD<double> ) aw(ny), adw(nu);\n    af.Forward(0, au);\n    for(size_t i = 0; i < ny; ++i)\n        aw[i] = 0.0;\n    aw[2] = 1.0;\n    adw = af.Reverse(1, aw);\n    // g\n    CppAD::ADFun<double> g(au, adw);\n    // -----------------------------------------------------------------------\n    // check_g\n    CppAD::Independent(au);\n    ay = G(ar, au);\n    CppAD::ADFun<double> check_g(au, ay);\n    // -----------------------------------------------------------------------\n    //\n    // v\n    // zero order forward mode computation of g(u)\n    CPPAD_TESTVECTOR(double) v(nu);\n    v = g.Forward(0, u);\n    //\n    // ok\n    CPPAD_TESTVECTOR(double) check_v = check_g.Forward(0, u);\n    for(size_t i = 0; i < nu; ++i)\n        ok &= NearEqual(v[i], check_v[i], eps99, eps99);\n    //\n    // w, ok\n    w.resize(nu);\n    for(size_t i = 0; i < nu; ++i)\n        w[i] = 0.0;\n    for(size_t i = 0; i < nu; ++i)\n    {   w[i] = 1.0;\n        dw        = g.Reverse(1, w);\n        check_dw  = check_g.Reverse(1, w);\n        for(size_t j = 0; j < nu; ++j)\n            ok &= NearEqual(dw[j], check_dw[j], eps99, eps99);\n        w[i] = 0.0;\n    }\n    // -----------------------------------------------------------------------\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/atomic_four/lin_ode/sparsity.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_four_lin_ode_sparsity.cpp}\n{xrst_spell\n    cccc\n}\n\nAtomic Linear ODE Sparsity Calculations: Example and Test\n#########################################################\n\nPurpose\n*******\nThis example demonstrates calculating sparsity patterns with\nthe :ref:`atomic_four_lin_ode-name` class.\n\nf(u)\n****\nFor this example, the function :math:`f(u) = z(r, u)` where\n:math:`z(t, u)` solves the following ODE\n\n.. math::\n\n    z_t (t, u) =\n    \\left( \\begin{array}{cccc}\n    0   & 0  & 0    & 0   \\\\\n    u_4 & 0  & 0    & 0   \\\\\n    0   & u_5 & 0   & 0   \\\\\n    0   & 0   & u_6 & 0   \\\\\n    \\end{array} \\right)\n    z(t, u)\n    \\W{,}\n    z(0, u) =\n    \\left( \\begin{array}{c}\n    u_0 \\\\\n    u_1 \\\\\n    u_2 \\\\\n    u_3 \\\\\n    \\end{array} \\right)\n\nSolution\n********\nThe actual solution to this ODE is\n\n.. math::\n\n    z(t, u) =\n    \\left( \\begin{array}{l}\n    u_0  \\\\\n    u_1 + u_4 u_0 t \\\\\n    u_2 + u_5 u_1 t + u_5 u_4 u_0 t^2 / 2  \\\\\n    u_3 + u_6 u_2 t + u_6 u_5 u_1 t^2 / 2 + u_6 u_5 u_4 u_0 t^3 / 6\n    \\end{array} \\right)\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end atomic_four_lin_ode_sparsity.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n# include <cppad/example/atomic_four/lin_ode/lin_ode.hpp>\n\nnamespace { // BEGIN_EMPTY_NAMESPACE\n\ntemplate <class Scalar, class Vector>\nVector Z(Scalar t, const Vector& u)\n{   size_t nz = 4;\n    Vector z(nz);\n    //\n    z[0]  = u[0];\n    z[1]  = u[1] + u[4]*u[0]*t;\n    z[2]  = u[2] + u[5]*u[1]*t + u[5]*u[4]*u[0]*t*t/2.0;\n    z[3]  = u[3] + u[6]*u[2]*t + u[6]*u[5]*u[1]*t*t/2.0\n             + u[6]*u[5]*u[4]*u[0]*t*t*t/6.0;\n    //\n    return z;\n}\n\n} // END_EMPTY_NAMESPACE\n\nbool sparsity(void)\n{   // ok\n    bool ok = true;\n    //\n    // sparse_rc, AD\n    typedef CppAD::sparse_rc< CppAD::vector<size_t> > sparse_rc;\n    using CppAD::AD;\n    // -----------------------------------------------------------------------\n    // Record f\n    // -----------------------------------------------------------------------\n    //\n    // afun\n    CppAD::atomic_lin_ode<double> afun(\"atomic_lin_ode\");\n    //\n    // m, r\n    size_t m      = 4;\n    double r      = 2.0;\n    double step   = 0.5;\n    //\n    // pattern, transpose\n    size_t nr  = m;\n    size_t nc  = m;\n    size_t nnz = 3;\n    CppAD::sparse_rc< CppAD::vector<size_t> > pattern(nr, nc, nnz);\n    for(size_t k = 0; k < nnz; ++k)\n    {   size_t i = k + 1;\n        size_t j = k;\n        pattern.set(k, i, j);\n    }\n    bool transpose = false;\n    //\n    // ny, ay\n    size_t ny = m;\n    CPPAD_TESTVECTOR( AD<double> ) ay(ny);\n    //\n    // nu, au\n    size_t nu = nnz + m;\n    CPPAD_TESTVECTOR( AD<double> ) au(nu);\n    for(size_t j = 0; j < nu; ++j)\n        au[j] = AD<double>(j + 1);\n    CppAD::Independent(au);\n    //\n    // ax\n    CPPAD_TESTVECTOR( AD<double> ) ax(nnz + m);\n    for(size_t k = 0; k < nnz; ++k)\n        ax[k] = au[m + k];\n    for(size_t i = 0; i < m; ++i)\n        ax[nnz + i] = au[i];\n    //\n    // ay\n    size_t call_id = afun.set(r, step, pattern, transpose);\n    afun(call_id, ax, ay);\n    //\n    // f\n    CppAD::ADFun<double> f(au, ay);\n    // -----------------------------------------------------------------------\n    // ar, check_f\n    CppAD::Independent(au);\n    AD<double> ar = r;\n    ay = Z(ar, au);\n    CppAD::ADFun<double> check_f(au, ay);\n    // -----------------------------------------------------------------------\n    // Jacobian Sparsity\n    // -----------------------------------------------------------------------\n    //\n    // eye_sparsity\n    // nu by nu identitty matrix\n    sparse_rc eye_sparsity(nu, nu, nu);\n    for(size_t i = 0; i < nu; ++i)\n        eye_sparsity.set(i, i, i);\n    //\n    // internal_bool\n    bool internal_bool = false;\n    //\n    // jac_sparsity\n    transpose          = false;\n    bool dependency    = false;\n    sparse_rc jac_sparsity;\n    f.for_jac_sparsity(\n        eye_sparsity, transpose, dependency, internal_bool, jac_sparsity\n    );\n    //\n    // check_jac_sparsity\n    sparse_rc check_jac_sparsity;\n    check_f.for_jac_sparsity(\n        eye_sparsity, transpose, dependency, internal_bool, check_jac_sparsity\n    );\n    //\n    // ok\n    ok &= jac_sparsity == check_jac_sparsity;\n    // -----------------------------------------------------------------------\n    // Hessian Sparsity\n    // -----------------------------------------------------------------------\n    //\n    // select_domain\n    CPPAD_TESTVECTOR(bool) select_domain(nu);\n    for(size_t j = 0; j < nu; ++j)\n        select_domain[j] = true;\n    //\n    // select_range\n    CPPAD_TESTVECTOR(bool) select_range(ny);\n    for(size_t i = 0; i < ny; ++i)\n        select_range[i]  = false;\n    select_range[1] = true;\n    //\n    // hes_sparsity\n    sparse_rc hes_sparsity;\n    f.for_hes_sparsity(\n        select_domain, select_range, internal_bool, hes_sparsity\n    );\n    //\n    // check_hes_sparsity\n    sparse_rc check_hes_sparsity;\n    check_f.for_hes_sparsity(\n        select_domain, select_range, internal_bool, check_hes_sparsity\n    );\n    //\n    // ok\n    ok &= hes_sparsity == check_hes_sparsity;\n    // -----------------------------------------------------------------------\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/atomic_four/mat_mul/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n#\n# BEGIN_SORT_THIS_LINE_PLUS_2\nSET(source_list\n    forward.cpp\n    identical_zero.cpp\n    mat_mul.cpp\n    rev_depend.cpp\n    reverse.cpp\n    sparsity.cpp\n)\n# END_SORT_THIS_LINE_MINUS_2\n\nset_compile_flags(example_atomic_four_mat_mul\n    \"${cppad_debug_which}\" \"${source_list}\"\n)\n#\nADD_EXECUTABLE(example_atomic_four_mat_mul EXCLUDE_FROM_ALL ${source_list})\n#\n# List of libraries to be linked into the specified target\nTARGET_LINK_LIBRARIES(example_atomic_four_mat_mul\n    ${cppad_lib}\n    ${colpack_libs}\n)\n#\n# check_example_atomic_four_mat_mul\nadd_check_executable(check_example_atomic_four mat_mul)\n"
  },
  {
    "path": "example/atomic_four/mat_mul/forward.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_four_mat_mul_forward.cpp}\n{xrst_spell\n    cccccccc\n}\n\nAtomic Matrix Multiply Forward Mode: Example and Test\n#####################################################\n\nPurpose\n*******\nThis example demonstrates using forward mode with\nthe :ref:`atomic_four_mat_mul-name` class.\n\nf(x)\n****\nFor this example, the function :math:`f(x)` is\n\n.. math::\n\n    f(x) =\n    \\left( \\begin{array}{cc}\n    x_0 & x_1  \\\\\n    x_2 & x_3  \\\\\n    x_4 & x_5\n    \\end{array} \\right)\n    \\left( \\begin{array}{c}\n    x_6  \\\\\n    x_7\n    \\end{array} \\right)\n    =\n    \\left( \\begin{array}{c}\n    x_0 x_6 + x_1 x_7  \\\\\n    x_2 x_6 + x_3 x_7  \\\\\n    x_4 x_6 + x_5 x_7\n    \\end{array} \\right)\n\nJacobian of f(x)\n****************\nThe Jacobian of :math:`f(x)` is\n\n.. math::\n\n    f^{(1)} (x) = \\left( \\begin{array}{cccccccc}\n    x_6 & x_7 & 0   & 0    & 0    & 0   & x_0  & x_1 \\\\\n    0   & 0   & x_6 & x_7  & 0    & 0   & x_2  & x_3 \\\\\n    0   & 0   & 0   & 0    & x_6  & x_7 & x_4  & x_5\n    \\end{array} \\right)\n\ng(x)\n****\nWe define the function :math:`g(x) = f_1^{(1)} (x)^\\R{T}`; i.e.,\n\n.. math::\n\n    g(x) = ( 0,  0,  x_6,  x_7,  0,  0,  x_2,  x_3 )^\\R{T}\n\nHessian\n*******\nThe Hessian of :math:`f_1(x)` is the Jacobian\nof :math:`g(x)`; i.e.,\n\n.. math::\n\n    f_1^{(2)} (x)\n    =\n    g^{(1)} (x)\n    =\n    \\left( \\begin{array}{cccccccc}\n        0   & 0   & 0   & 0    & 0    & 0   & 0    & 0   \\\\\n        0   & 0   & 0   & 0    & 0    & 0   & 0    & 0   \\\\\n        0   & 0   & 0   & 0    & 0    & 0   & 1    & 0   \\\\\n        0   & 0   & 0   & 0    & 0    & 0   & 0    & 1   \\\\\n        0   & 0   & 0   & 0    & 0    & 0   & 0    & 0   \\\\\n        0   & 0   & 0   & 0    & 0    & 0   & 0    & 0   \\\\\n        0   & 0   & 1   & 0    & 0    & 0   & 0    & 0   \\\\\n        0   & 0   & 0   & 1    & 0    & 0   & 0    & 0   \\\\\n    \\end{array} \\right)\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end atomic_four_mat_mul_forward.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n# include <cppad/example/atomic_four/mat_mul/mat_mul.hpp>\n\nbool forward(void)\n{   // ok, eps\n    bool ok = true;\n    //\n    // AD, NearEqual\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    // -----------------------------------------------------------------------\n    // Record f\n    // -----------------------------------------------------------------------\n    //\n    // afun\n    CppAD::atomic_mat_mul<double> afun(\"atomic_mat_mul\");\n    //\n    // nleft, n_middle, n_right\n    size_t n_left = 3, n_middle = 2, n_right = 1;\n    //\n    // nx, ax\n    size_t nx = n_middle * (n_left + n_right);\n    CPPAD_TESTVECTOR( AD<double> ) ax(nx);\n    for(size_t j = 0; j < nx; ++j)\n        ax[j] = AD<double>(j + 2);\n    CppAD::Independent(ax);\n    //\n    // ny, ay\n    size_t ny = n_left * n_right;\n    CPPAD_TESTVECTOR( AD<double> ) ay(ny);\n    //\n    // ay\n    size_t call_id = afun.set(n_left, n_middle, n_right);\n    afun(call_id, ax, ay);\n    //\n    // f\n    CppAD::ADFun<double> f(ax, ay);\n    // -----------------------------------------------------------------------\n    // Forward mode on f\n    // -----------------------------------------------------------------------\n    //\n    // x\n    CPPAD_TESTVECTOR(double) x(nx);\n    for(size_t j = 0; j < nx; ++j)\n        x[j] = double(3 + nx - j);\n    //\n    // y\n    // zero order forward mode computation of f(x)\n    CPPAD_TESTVECTOR(double) y(ny);\n    y = f.Forward(0, x);\n    //\n    // check_y\n    double check_y[] = {\n        x[0] * x[6] + x[1] * x[7],\n        x[2] * x[6] + x[3] * x[7],\n        x[4] * x[6] + x[5] * x[7]\n    };\n    for(size_t i = 0; i < ny; ++i)\n        ok &= y[i] == check_y[i];\n    //\n    // J\n    // first order forward mode computation of f'(x)\n    CPPAD_TESTVECTOR(double) x1(nx), y1(ny), J(ny * nx);\n    for(size_t j = 0; j < nx; ++j)\n        x1[j] = 0.0;\n    for(size_t j = 0; j < nx; ++j)\n    {   x1[j] = 1.0;\n        y1    = f.Forward(1, x1);\n        x1[j] = 0.0;\n        for(size_t i = 0; i < ny; ++i)\n            J[i * nx + j] = y1[i];\n    }\n    //\n    // check_J\n    double check_J[] = {\n        x[6], x[7],  0.0,  0.0,  0.0,  0.0, x[0], x[1],\n            0.0,  0.0, x[6], x[7],  0.0,  0.0, x[2], x[3],\n            0.0,  0.0,  0.0,  0.0, x[6], x[7], x[4], x[5]\n    };\n    for(size_t ij = 0; ij < ny * nx; ij++)\n        ok &= J[ij] == check_J[ij];\n    //\n    // H_1\n    // Second order forward mode computaiton of f_1^2 (x)\n    // (use the fact that the diagonal of this Hessian is zero).\n    CPPAD_TESTVECTOR(double) x2(nx), y2(nx), H_1(nx * nx);\n    for(size_t j = 0; j < nx; ++j)\n        x2[j] = 0.0;\n    for(size_t i = 0; i < nx; ++i)\n    {   for(size_t j = 0; j < nx; ++j)\n        {   x1[i] = 1.0;\n            x1[j] = 1.0;\n            f.Forward(1, x1);\n            x1[i] = 0.0;\n            x1[j] = 0.0;\n            y2 = f.Forward(2, x2);\n            H_1[i * nx + j] = y2[1];\n        }\n    }\n    //\n    // check_H_1\n    double check_H_1[] = {\n        0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,\n        0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,\n        0.,  0.,  0.,  0.,  0.,  0.,  1.,  0.,\n        0.,  0.,  0.,  0.,  0.,  0.,  0.,  1.,\n        0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,\n        0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,\n        0.,  0.,  1.,  0.,  0.,  0.,  0.,  0.,\n        0.,  0.,  0.,  1.,  0.,  0.,  0.,  0.\n    };\n    for(size_t ij = 0; ij < nx * nx; ij++)\n        ok &= H_1[ij] == check_H_1[ij];\n    // -----------------------------------------------------------------------\n    // Record g\n    // -----------------------------------------------------------------------\n    //\n    // af\n    CppAD::ADFun< AD<double>, double> af = f.base2ad();\n    //\n    // az\n    CppAD::Independent(ax);\n    CPPAD_TESTVECTOR( AD<double> ) ax1(nx), ay1(ny), az(nx);\n    af.Forward(0, ax);\n    for(size_t j = 0; j < nx; ++j)\n        ax1[j] = 0.0;\n    for(size_t j = 0; j < nx; ++j)\n    {   ax1[j]    = 1.0;\n        ay1       = af.Forward(1, ax1);\n        ax1[j]    = 0.0;\n        az[j]    = ay1[1];\n    }\n    // g\n    CppAD::ADFun<double> g(ax, az);\n    // -----------------------------------------------------------------------\n    // Forward mode on g\n    // -----------------------------------------------------------------------\n    //\n    // z\n    // zero order forward mode computation of g(x)\n    CPPAD_TESTVECTOR(double) z(nx);\n    z = g.Forward(0, x);\n    //\n    // check z\n    for(size_t j = 0; j < nx; ++j)\n        ok &= z[j] == J[1 * nx + j];\n    //\n    // z1\n    CPPAD_TESTVECTOR(double) z1(nx);\n    for(size_t j = 0; j < nx; ++j)\n    {   x1[j] = 1.0;\n        z1    = g.Forward(1, x1);\n        x1[j] = 0.0;\n        for(size_t i = 0; i < nx; ++i)\n            ok &= z1[i] == check_H_1[i * nx + j];\n    }\n    // ----------------------------------------------------------------\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/atomic_four/mat_mul/identical_zero.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_four_mat_mul_identical_zero.cpp}\n\nAtomic Matrix Multiply Identical Zero: Example and Test\n#######################################################\n\nPurpose\n*******\nThis example demonstrates how the\n:ref:`atomic_four_mat_mul_for_type.hpp-name`\nroutine uses the *identical_zero_enum* type to reduce the number\nof variables.\n\nZero\n****\nThe first case computes the following matrix product\n\n.. math::\n\n    \\left( \\begin{array}{ccc}\n    u_0 & 0   & 0 \\\\\n    0   & u_1 & 0 \\\\\n    0   & 0   & u_2\n    \\end{array} \\right)\n    \\left( \\begin{array}{ccc}\n    u_3 & 0   & 0 \\\\\n    0   & u_4 & 0 \\\\\n    0   & 0   & u_5\n    \\end{array} \\right)\n    =\n    \\left( \\begin{array}{ccc}\n    u_0 u_3 & 0       & 0 \\\\\n    0       & u_1 u_4 & 0 \\\\\n    0       & 0       & u_2 u_5\n    \\end{array} \\right)\n\nThe result matrix for this case has three variables,\none for each product on the diagonal.\n\nOne\n***\nThe second case computes the following matrix product\n\n.. math::\n\n    \\left( \\begin{array}{ccc}\n    u_0 & 1   & 1 \\\\\n    1   & u_1 & 1 \\\\\n    1   & 1   & u_2\n    \\end{array} \\right)\n    \\left( \\begin{array}{ccc}\n    u_3 & 1   & 1 \\\\\n    1   & u_4 & 1 \\\\\n    1   & 1   & u_5\n    \\end{array} \\right)\n    =\n    \\left( \\begin{array}{ccc}\n    u_0 u_3 + 2   & u_0 + u_3 + 1 & u_0 + u_5 + 1 \\\\\n    u_1 + u_3 + 1 & u_1 u_4 + 2   & u_1 + u_5 + 1  \\\\\n    u_2 + u_3 + 1 & u_2 + u_4 + 1 & u_2 u_5 + 2\n    \\end{array} \\right)\n\nThe result matrix for this case has nine variables,\none for each of its elements.\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end atomic_four_mat_mul_identical_zero.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n# include <cppad/example/atomic_four/mat_mul/mat_mul.hpp>\n\nbool identical_zero(void)\n{   // ok, eps\n    bool ok = true;\n    //\n    // AD, NearEqual\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    // -----------------------------------------------------------------------\n    // Record f\n    // -----------------------------------------------------------------------\n    //\n    // afun\n    CppAD::atomic_mat_mul<double> afun(\"atomic_mat_mul\");\n    //\n    // nleft\n    size_t size = 3;\n    //\n    // size_var\n    size_t size_var[2];\n    //\n    // zero_one\n    for(size_t zero_one = 0; zero_one < 2; ++zero_one)\n    {   //\n        // n_right, n_middle\n        size_t n_left = size, n_middle = size, n_right = size;\n        //\n        // nu, au\n        size_t nu = 2 * size;\n        CPPAD_TESTVECTOR( AD<double> ) au(nu);\n        for(size_t j = 0; j < nu; ++j)\n            au[j] = AD<double>(j + 2);\n        CppAD::Independent(au);\n        //\n        // offset\n        size_t offset = size * size;\n        //\n        // nx, ax\n        size_t nx = size * (size + size);\n        CPPAD_TESTVECTOR( AD<double> ) ax(nx);\n        for(size_t i = 0; i < size; ++i)\n        {   for(size_t j = 0; j < size; ++j)\n            {   // left\n                size_t ij = i * size + j;\n                if( i == j )\n                    ax[ij] = au[j];\n                else\n                    ax[ij] = AD<double>(zero_one);\n                // right\n                ij = offset + i * n_right + j;\n                if( i == j )\n                    ax[ij] = au[i];\n                else\n                    ax[ij] = AD<double>(zero_one);\n            }\n        }\n        //\n        // ay\n        size_t ny = size * size;\n        CPPAD_TESTVECTOR( AD<double> ) ay(ny);\n        size_t call_id = afun.set(n_left, n_middle, n_right);\n        afun(call_id, ax, ay);\n        //\n        // av\n        size_t nv = size;\n        CPPAD_TESTVECTOR( AD<double> ) av(nv);\n        for(size_t i = 0; i < nv; ++i)\n            av[i] += ay[i * size + i];\n        //\n        // f\n        CppAD::ADFun<double> f(au, av);\n        //\n        // size_var\n        size_var[zero_one] = f.size_var();\n    }\n    // ok\n    ok = size_var[1] - size_var[0] == size * size - size;\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/atomic_four/mat_mul/mat_mul.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n// CPPAD_HAS_* defines\n# include <cppad/configure.hpp>\n\n// system include files used for I/O\n# include <iostream>\n\n// C style asserts\n# include <cassert>\n\n// for thread_alloc\n# include <cppad/utility/thread_alloc.hpp>\n\n// test runner\n# include <cppad/utility/test_boolofvoid.hpp>\n\n// BEGIN_SORT_THIS_LINE_PLUS_1\nextern bool forward(void);\nextern bool identical_zero(void);\nextern bool rev_depend(void);\nextern bool reverse(void);\nextern bool sparsity(void);\n// END_SORT_THIS_LINE_MINUS_1\n\n// main program that runs all the tests\nint main(void)\n{   std::string group = \"example/atomic_four/mat_mul\";\n    size_t      width = 20;\n    CppAD::test_boolofvoid Run(group, width);\n\n    // This line is used by test_one.sh\n\n    // BEGIN_SORT_THIS_LINE_PLUS_1\n    Run( forward,             \"forward\"        );\n    Run( identical_zero,      \"identical_zero\" );\n    Run( rev_depend,          \"rev_depend\"     );\n    Run( reverse,             \"reverse\"        );\n    Run( sparsity,            \"sparsity\"       );\n    // END_SORT_THIS_LINE_MINUS_1\n\n    // check for memory leak\n    bool memory_ok = CppAD::thread_alloc::free_all();\n    // print summary at end\n    bool ok = Run.summary(memory_ok);\n    //\n    return static_cast<int>( ! ok );\n}\n"
  },
  {
    "path": "example/atomic_four/mat_mul/rev_depend.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-23 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_four_mat_mul_rev_depend.cpp}\n\nAtomic Matrix Multiply Reverse Dependency: Example and Test\n###########################################################\n\nPurpose\n*******\nThis example uses the atomic matrix multiply\n``rev_depend`` function to reduce the number of variables in\nthe recording of :math:`g(u)`.\n\nf(u)\n****\n\n.. math::\n\n    f(u) =\n    \\left( \\begin{array}{cc}\n    2 u_0 & 2 u_1  \\\\\n    2 u_2 & 2 u_3  \\\\\n    \\end{array} \\right)\n    \\left( \\begin{array}{cc}\n    2 u_4 & 2 u_5  \\\\\n    2 u_6 & 2 u_7\n    \\end{array} \\right)\n    =\n    \\left( \\begin{array}{cc}\n    4( u_0 u_4 + u_1 u_6 )  & 4( u_0 u_5 + u_1 u_7 )  \\\\\n    4( u_2 u_4 + u_3 u_6 )  & 4( u_2 u_5 + u_3 u_7 )  \\\\\n    \\end{array} \\right)\n\n.. math::\n\n    f_{0,0} (u)\n    =\n    4 ( u_0 u_4 + u_1 u_6 )\n\nForward Analysis\n****************\nForward dependency analysis determines that there\nis a new variable for each of the 8 multiplications by 2.0.\nIt also determines, using :ref:`for_type<atomic_four_mat_mul_for_type.hpp-name>`\nthat each of the 4 elements in the matrix product result is a new variable.\n\nReverse Analysis\n****************\nReverse analysis detect that only 1 of the 4 elements\nin the matrix product is used.\nIn addition it determines,\nusing :ref:`rev_depend<atomic_four_mat_mul_rev_depend.hpp-name>` ,\nthat only 4 of the 8 multiplications by 2.0 are used.\n\nsize_var\n********\nThe difference in :ref:`fun_property@size_var`\nis the difference between only using forward dependency and using both; i.e.,\n(8 - 4) + (4 - 1) = 7.\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end atomic_four_mat_mul_rev_depend.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n# include <cppad/example/atomic_four/mat_mul/mat_mul.hpp>\n\nbool rev_depend(void)\n{   // ok, eps\n    bool ok = true;\n    //\n    // AD\n    using CppAD::AD;\n    using CppAD::sparse_rc;\n    // -----------------------------------------------------------------------\n    // Record g\n    // -----------------------------------------------------------------------\n    //\n    // afun\n    CppAD::atomic_mat_mul<double> afun(\"atomic_mat_mul\");\n    //\n    // nleft, n_middle, n_right\n    size_t n_left = 2, n_middle = 2, n_right = 2;\n    //\n    // nu, au\n    size_t nu = n_middle * (n_left + n_right);\n    CPPAD_TESTVECTOR( AD<double> ) au(nu);\n    for(size_t j = 0; j < nu; ++j)\n        au[j] = AD<double>(j + 2);\n    CppAD::Independent(au);\n    //\n    // nx, ax\n    CPPAD_TESTVECTOR( AD<double> ) ax(nu);\n    for(size_t j = 0; j < nu; ++j)\n        ax[j] = 2.0 * au[j];\n    //\n    // ny, ay\n    size_t ny = n_left * n_right;\n    CPPAD_TESTVECTOR( AD<double> ) ay(ny);\n    size_t call_id = afun.set(n_left, n_middle, n_right);\n    afun(call_id, ax, ay);\n    //\n    // az = f_{0,0} (x)\n    CPPAD_TESTVECTOR( AD<double> ) az(1);\n    az[0] = ay[ 0 * n_right + 0 ];\n    //\n    // g\n    CppAD::ADFun<double> g(au, az);\n    //\n    // size_var_before\n    size_t size_var_before = g.size_var();\n    //\n    //\n    // optimize\n    g.optimize(\"val_graph no_conditional_skip\");\n    //\n    // size_var_after\n    size_t size_var_after = g.size_var();\n    //\n    // ok\n    ok &= size_var_before - size_var_after == 7;\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/atomic_four/mat_mul/reverse.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_four_mat_mul_reverse.cpp}\n{xrst_spell\n    ccccccccc\n    cccccccccc\n}\n\nAtomic Matrix Multiply Reverse Mode: Example and Test\n#####################################################\n\nPurpose\n*******\nThis example demonstrates using reverse mode\nwith the :ref:`atomic_four_mat_mul-name` class.\n\nf(x)\n****\nFor this example, the function :math:`f(x)` is\n\n.. math::\n\n    f(x) =\n    \\left( \\begin{array}{ccc}\n    x_0 & x_1 & x_2  \\\\\n    x_3 & x_4 & x_5\n    \\end{array} \\right)\n    \\left( \\begin{array}{c}\n    x_6 \\\\\n    x_7 \\\\\n    x_8\n    \\end{array} \\right)\n    =\n    \\left( \\begin{array}{c}\n    x_0 * x_6 + x_1 * x_7 + x_2 * x_8 \\\\\n    x_3 * x_6 + x_4 * x_7 + x_5 * x_8\n    \\end{array} \\right)\n\nJacobian of f(x)\n****************\nThe Jacobian of :math:`f(x)` is\n\n.. math::\n\n    f^{(1)} (x) = \\left( \\begin{array}{cccccccccc}\n        x_6 & x_7 & x_8 & 0   & 0   & 0   & x_0 & x_1 & x_2 \\\\\n        0   & 0   & 0   & x_6 & x_7 & x_8 & x_3 & x_4 & x_5\n    \\end{array} \\right)\n\ng(x)\n****\nWe define the function :math:`g(x) = f_0^{(1)} (x)^\\R{T}`; i.e.,\n\n.. math::\n\n    g(x) = ( x_6, x_7, x_8, 0, 0, 0, x_0, x_1, x_2 )^\\R{T}\n\nHessian\n*******\nThe Hessian of :math:`f_1(x)` is the Jacobian\nof :math:`g(x)`; i.e.,\n\n.. math::\n\n    f_1^{(2)} (x)\n    =\n    g^{(1)} (x)\n    =\n    \\left( \\begin{array}{ccccccccc}\n        % 0   1   2   3   4   5   6   7   8\n            0 & 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0   \\\\ % 0\n            0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 & 0   \\\\ % 1\n            0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 1   \\\\ % 2\n            0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0   \\\\ % 3\n            0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0   \\\\ % 4\n            0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0   \\\\ % 5\n            1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0   \\\\ % 6\n            0 & 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0   \\\\ % 7\n            0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 & 0   \\\\ % 8\n    \\end{array} \\right)\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end atomic_four_mat_mul_reverse.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n# include <cppad/example/atomic_four/mat_mul/mat_mul.hpp>\n\nbool reverse(void)\n{   // ok, eps\n    bool ok = true;\n    //\n    // AD, NearEqual\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    // -----------------------------------------------------------------------\n    // Record f\n    // -----------------------------------------------------------------------\n    //\n    // afun\n    CppAD::atomic_mat_mul<double> afun(\"atomic_mat_mul\");\n    //\n    // nleft, n_middle, n_right\n    size_t n_left = 2, n_middle = 3, n_right = 1;\n    //\n    // nx, ax\n    size_t nx = n_middle * (n_left + n_right);\n    CPPAD_TESTVECTOR( AD<double> ) ax(nx);\n    for(size_t j = 0; j < nx; ++j)\n        ax[j] = AD<double>(j + 2);\n    CppAD::Independent(ax);\n    //\n    // ny, ay\n    size_t ny = n_left * n_right;\n    CPPAD_TESTVECTOR( AD<double> ) ay(ny);\n    //\n    // ay\n    size_t call_id = afun.set(n_left, n_middle, n_right);\n    afun(call_id, ax, ay);\n    //\n    // f\n    CppAD::ADFun<double> f(ax, ay);\n    // -----------------------------------------------------------------------\n    // Reverse mode on f\n    // -----------------------------------------------------------------------\n    //\n    // x\n    CPPAD_TESTVECTOR(double) x(nx);\n    for(size_t j = 0; j < nx; ++j)\n        x[j] = double(3 + nx - j);\n    //\n    // y\n    // zero order forward mode computation of f(x)\n    CPPAD_TESTVECTOR(double) y(nx);\n    y = f.Forward(0, x);\n    //\n    // check_y\n    double check_y[] = {\n        x[0] * x[6] + x[1] * x[7] + x[2] * x[8],\n        x[3] * x[6] + x[4] * x[7] + x[5] * x[8]\n    };\n    for(size_t i = 0; i < ny; ++i)\n        ok &= y[i] == check_y[i];\n    //\n    // J\n    // first order reverse mode computation of f'(x)\n    CPPAD_TESTVECTOR(double) w1(ny), dw1(nx), J(ny * nx);\n    for(size_t i = 0; i < ny; ++i)\n        w1[i] = 0.0;\n    for(size_t i = 0; i < ny; ++i)\n    {   w1[i] = 1.0;\n        dw1   = f.Reverse(1, w1);\n        w1[i] = 0.0;\n        for(size_t j = 0; j < nx; ++j)\n            J[i * nx + j] = dw1[j];\n    }\n    //\n    // check_J\n    double check_J[] = {\n        x[6], x[7], x[8],  0.0,  0.0,  0.0, x[0], x[1], x[2],\n            0.0,  0.0,  0.0, x[6], x[7], x[8], x[3], x[4], x[5]\n    };\n    for(size_t ij = 0; ij < ny * nx; ij++)\n        ok &= J[ij] == check_J[ij];\n    //\n    // H_0\n    // Second order reverse mode computaiton of f_0^2 (x)\n    CPPAD_TESTVECTOR(double) x1(nx), w2(ny), dw2(2 * nx), H_0(nx * nx);\n    for(size_t i = 0; i < ny; ++i)\n        w2[i] = 0.0;\n    w2[0] = 1.0;\n    for(size_t j = 0; j < nx; ++j)\n        x1[j] = 0.0;\n    for(size_t i = 0; i < nx; ++i)\n    {   x1[i] = 1.0;\n        f.Forward(1, x1);\n        x1[i] = 0.0;\n        dw2 = f.Reverse(2, w2);\n        for(size_t j = 0; j < nx; ++j)\n            H_0[i * nx + j] = dw2[2 * j + 1];\n    }\n    //\n    // check_H_0\n    assert( nx == 9 );\n    double check_H_0[] = {\n        0.,  0.,  0.,  0.,  0.,  0.,  1.,  0.,  0.,\n        0.,  0.,  0.,  0.,  0.,  0.,  0.,  1.,  0.,\n        0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  1.,\n        0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,\n        0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,\n        0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,\n        1.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,\n        0.,  1.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,\n        0.,  0.,  1.,  0.,  0.,  0.,  0.,  0.,  0,\n    };\n    for(size_t ij = 0; ij < nx * nx; ij++)\n        ok &= H_0[ij] == check_H_0[ij];\n    // -----------------------------------------------------------------------\n    // Record g\n    // -----------------------------------------------------------------------\n    //\n    // af\n    CppAD::ADFun< AD<double>, double> af = f.base2ad();\n    //\n    // az\n    CppAD::Independent(ax);\n    CPPAD_TESTVECTOR( AD<double> ) aw(ny), az(nx);\n    af.Forward(0, ax);\n    for(size_t i = 0; i < ny; ++i)\n        aw[i] = 0.0;\n    aw[0] = 1.0;\n    az = af.Reverse(1, aw);\n    // g\n    CppAD::ADFun<double> g(ax, az);\n    // -----------------------------------------------------------------------\n    // Forward mode on g\n    // -----------------------------------------------------------------------\n    //\n    // z\n    // zero order forward mode computation of g(x)\n    CPPAD_TESTVECTOR(double) z(nx);\n    z = g.Forward(0, x);\n    //\n    // check z\n    for(size_t j = 0; j < nx; ++j)\n        ok &= z[j] == J[0 * nx + j];\n    //\n    // z1\n    CPPAD_TESTVECTOR(double) w(nx), dw(nx);\n    for(size_t i = 0; i < nx; ++i)\n        w[i] = 0.0;\n    for(size_t i = 0; i < nx; ++i)\n    {   w[i] = 1.0;\n        dw   = g.Reverse(1, w);\n        w[i] = 0.0;\n        for(size_t j = 0; j < nx; ++j)\n            ok &= dw[j] == check_H_0[i * nx + j];\n    }\n    // ----------------------------------------------------------------\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/atomic_four/mat_mul/sparsity.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_four_mat_mul_sparsity.cpp}\n{xrst_spell\n    cccccccc\n    cccccccccc\n    rvec\n}\n\nAtomic Matrix Multiply Sparsity Patterns: Example and Test\n##########################################################\n\nPurpose\n*******\nThis example demonstrates computing sparsity patterns with\nthe :ref:`atomic_four_mat_mul-name` class.\n\nf(x)\n****\nFor a matrix :math:`A` we define the function :math:`\\R{rvec} ( A )`\nto be the elements of :math:`A` in row major order.\nFor this example, the function :math:`f(x)` is\n\n.. math::\n\n    f(x) =\n    \\R{rvec} \\left[\n    \\left( \\begin{array}{cc}\n    x_0 & x_1  \\\\\n    x_2 & x_3  \\\\\n    \\end{array} \\right)\n    \\left( \\begin{array}{cc}\n    x_4 & x_5  \\\\\n    x_6 & x_7\n    \\end{array} \\right)\n    \\right]\n    =\n    \\R{rvec}\n    \\left( \\begin{array}{cc}\n    x_0 x_4 + x_1 x_6 & x_0 x_5 + x_1 x_7  \\\\\n    x_2 x_4 + x_3 x_6 & x_2 x_5 + x_3 x_7  \\\\\n    \\end{array} \\right)\n\n.. math::\n\n    f(x)\n    =\n    \\left( \\begin{array}{c}\n    x_0 x_4 + x_1 x_6 \\\\\n    x_0 x_5 + x_1 x_7 \\\\\n    x_2 x_4 + x_3 x_6 \\\\\n    x_2 x_5 + x_3 x_7\n    \\end{array} \\right)\n\nJacobian of f(x)\n****************\nThe Jacobian of :math:`f(x)` is\n\n.. math::\n\n    f^{(1)} (x) = \\left( \\begin{array}{cccccccc}\n    % 0   1     2     3      4      5     6      7\n    x_4 & x_6 & 0   & 0    & x_0  & 0   & x_1  & 0   \\\\ % 0\n    x_5 & x_7 & 0   & 0    & 0    & x_0 & 0    & x_1 \\\\ % 1\n    0   & 0   & x_4 & x_6  & x_2  & 0   & x_3  & 0   \\\\ % 2\n    0   & 0   & x_5 & x_7  & 0    & x_2 & 0    & x_3 \\\\ % 3\n    \\end{array} \\right)\n\nHessian\n*******\nThe function :math:`f_2 (x)` is\n\n.. math::\n\n    f_2 (x) = x_2 x_4 + x_3 x_6\n\nThe Hessian of :math:`f_2(x)` is\n\n.. math::\n\n    f_2^{(2)} (x)\n    =\n    \\left( \\begin{array}{cccccccccc}\n                & 0    & 1    & 2    & 3    & 4    & 5    & 6    & 7    \\\\\n                & -    & -    & -    & -    & -    & -    & -    & -    \\\\\n        0 \\; |  & 0    & 0    & 0    & 0    & 0    & 0    & 0    & 0    \\\\\n        1 \\; |  & 0    & 0    & 0    & 0    & 0    & 0    & 0    & 0    \\\\\n        2 \\; |  & 0    & 0    & 0    & 0    & 1    & 0    & 0    & 0    \\\\\n        3 \\; |  & 0    & 0    & 0    & 0    & 0    & 0    & 1    & 0    \\\\\n        4 \\; |  & 0    & 0    & 1    & 0    & 0    & 0    & 0    & 0    \\\\\n        5 \\; |  & 0    & 0    & 0    & 0    & 0    & 0    & 0    & 0    \\\\\n        6 \\; |  & 0    & 0    & 0    & 1    & 0    & 0    & 0    & 0    \\\\\n        7 \\; |  & 0    & 0    & 0    & 0    & 0    & 0    & 0    & 0    \\\\\n    \\end{array} \\right)\n\nwhere the first row is the column index,\nand the first column is the row index,\nfor the corresponding matrix entries above.\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end atomic_four_mat_mul_sparsity.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n# include <cppad/example/atomic_four/mat_mul/mat_mul.hpp>\n\nbool sparsity(void)\n{   // ok, eps\n    bool ok = true;\n    //\n    // AD\n    using CppAD::AD;\n    using CppAD::sparse_rc;\n    // -----------------------------------------------------------------------\n    // Record f\n    // -----------------------------------------------------------------------\n    //\n    // afun\n    CppAD::atomic_mat_mul<double> afun(\"atomic_mat_mul\");\n    //\n    // nleft, n_middle, n_right\n    size_t n_left = 2, n_middle = 2, n_right = 2;\n    //\n    // nx, ax\n    size_t nx = n_middle * (n_left + n_right);\n    CPPAD_TESTVECTOR( AD<double> ) ax(nx);\n    for(size_t j = 0; j < nx; ++j)\n        ax[j] = AD<double>(j + 2);\n    CppAD::Independent(ax);\n    //\n    // ny, ay\n    size_t ny = n_left * n_right;\n    CPPAD_TESTVECTOR( AD<double> ) ay(ny);\n    //\n    // ay\n    size_t call_id = afun.set(n_left, n_middle, n_right);\n    afun(call_id, ax, ay);\n    //\n    // f\n    CppAD::ADFun<double> f(ax, ay);\n    //\n    // s_vector\n    typedef CPPAD_TESTVECTOR(size_t) s_vector;\n    //\n    // eye_sparsity\n    // nx by nx identitty matrix\n    sparse_rc<s_vector> eye_sparsity;\n    eye_sparsity.resize(nx, nx, nx);\n    for(size_t i = 0; i < nx; ++i)\n        eye_sparsity.set(i, i, i);\n    //\n    // -----------------------------------------------------------------------\n    // jac_sparsity\n    bool transpose     = false;\n    bool dependency    = false;\n    bool internal_bool = false;\n    sparse_rc<s_vector> jac_sparsity;\n    f.for_jac_sparsity(\n        eye_sparsity, transpose, dependency, internal_bool, jac_sparsity\n    );\n    {   // check jac_sparsity\n        //\n        // row, col\n        const s_vector& row       = jac_sparsity.row();\n        const s_vector& col       = jac_sparsity.col();\n        s_vector        row_major = jac_sparsity.row_major();\n        //\n        // ok\n        ok &= jac_sparsity.nnz() == 16;\n        for(size_t k = 0; k < jac_sparsity.nnz(); ++k)\n            ok &= row[ row_major[k] ] == k / 4;\n        // row 0\n        ok &= col[ row_major[0] ]  == 0;\n        ok &= col[ row_major[1] ]  == 1;\n        ok &= col[ row_major[2] ]  == 4;\n        ok &= col[ row_major[3] ]  == 6;\n        // row 1\n        ok &= col[ row_major[4] ]  == 0;\n        ok &= col[ row_major[5] ]  == 1;\n        ok &= col[ row_major[6] ]  == 5;\n        ok &= col[ row_major[7] ]  == 7;\n        // row 2\n        ok &= col[ row_major[8] ]  == 2;\n        ok &= col[ row_major[9] ]  == 3;\n        ok &= col[ row_major[10] ] == 4;\n        ok &= col[ row_major[11] ] == 6;\n        // row 3\n        ok &= col[ row_major[12] ] == 2;\n        ok &= col[ row_major[13] ] == 3;\n        ok &= col[ row_major[14] ] == 5;\n        ok &= col[ row_major[15] ] == 7;\n    }\n    // ----------------------------------------------------------------\n    //\n    // select_y\n    // corresponding to f_2\n    CPPAD_TESTVECTOR(bool) select_y(ny);\n    for(size_t i = 0; i < ny; ++i)\n        select_y[i] = false;\n    select_y[2]   = true;\n    //\n    // hes_sparsity\n    transpose     = false;\n    internal_bool = false;\n    sparse_rc<s_vector> hes_sparsity;\n    f.rev_hes_sparsity(select_y, transpose, internal_bool, hes_sparsity);\n    {   // check hes_sparsity\n        //\n        // row, col\n        const s_vector& row       = hes_sparsity.row();\n        const s_vector& col       = hes_sparsity.col();\n        s_vector        row_major = hes_sparsity.row_major();\n        //\n        // ok\n        ok &= hes_sparsity.nnz() == 4;\n        //\n        ok &= row[ row_major[0] ] == 2;\n        ok &= col[ row_major[0] ] == 4;\n        //\n        ok &= row[ row_major[1] ] == 3;\n        ok &= col[ row_major[1] ] == 6;\n        //\n        ok &= row[ row_major[2] ] == 4;\n        ok &= col[ row_major[2] ] == 2;\n        //\n        ok &= row[ row_major[3] ] == 6;\n        ok &= col[ row_major[3] ] == 3;\n    }\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/atomic_four/norm_sq.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin atomic_four_norm_sq.cpp}\n\nAtomic Euclidean Norm Squared: Example and Test\n###############################################\n\nFunction\n********\nThis example demonstrates using :ref:`atomic_four-name`\nto define the operation\n:math:`g : \\B{R}^n \\rightarrow \\B{R}` where\n\n.. math::\n\n    g(x) =  x_0^2 + \\cdots + x_{n-1}^2\n\nPurpose\n*******\nThis atomic function demonstrates the following cases:\n\n#. an arbitrary number of arguments *n*\n#. zero and first order forward mode.\n#. first order derivatives using reverse mode.\n\nDefine Atomic Function\n**********************\n{xrst_literal\n    // BEGIN_DEFINE_ATOMIC_FUNCTION\n    // END_DEFINE_ATOMIC_FUNCTION\n}\n\nUse Atomic Function\n*******************\n{xrst_literal\n    // BEGIN_USE_ATOMIC_FUNCTION\n    // END_USE_ATOMIC_FUNCTION\n}\n\n{xrst_end atomic_four_norm_sq.cpp}\n*/\n# include <cppad/cppad.hpp>\n\n// BEGIN_DEFINE_ATOMIC_FUNCTION\n// empty namespace\nnamespace {\n    // BEGIN CONSTRUCTOR\n    class atomic_norm_sq : public CppAD::atomic_four<double> {\n    public:\n        atomic_norm_sq(const std::string& name) :\n        CppAD::atomic_four<double>(name)\n        { }\n    // END CONSTRUCTOR\n    private:\n        // BEGIN FOR_TYPE\n        bool for_type(\n            size_t                                     call_id     ,\n            const CppAD::vector<CppAD::ad_type_enum>&  type_x      ,\n            CppAD::vector<CppAD::ad_type_enum>&        type_y      ) override\n        {   assert( call_id == 0 );       // default value\n            assert(type_y.size() == 1 );  // m\n            //\n            // type_y\n            size_t n     = type_x.size();\n            type_y[0] = CppAD::constant_enum;\n            for(size_t j = 0; j < n; ++j)\n                type_y[0] = std::max(type_y[0], type_x[j]);\n            return true;\n        }\n        // END FOR_TYPE\n        // BEGIN FORWARD\n        bool forward(\n            size_t                             call_id     ,\n            const CppAD::vector<bool>&         select_y    ,\n            size_t                             order_low   ,\n            size_t                             order_up    ,\n            const CppAD::vector<double>&       tx          ,\n            CppAD::vector<double>&             ty          ) override\n        {\n            size_t q = order_up + 1;\n            size_t n = tx.size() / q;\n    # ifndef NDEBUG\n            size_t m = ty.size() / q;\n            assert( call_id == 0 );\n            assert( m == 1 );\n            assert( m == select_y.size() );\n    # endif\n            // ok\n            bool ok = order_up <= 1 && order_low <= order_up;\n            if ( ! ok )\n                return ok;\n            //\n            // sum = x_0^0 * x_0^0 + x_1^0 * x_1^0 + ...\n            double sum = 0.0;\n            for(size_t j = 0; j < n; ++j)\n            {   double xj0 = tx[ j * q + 0];\n                sum       += xj0 * xj0;\n            }\n            //\n            // ty[0] = sum\n            if( order_low <= 0 )\n                ty[0] = sum;\n            if( order_up < 1 )\n                return ok;\n\n            // sum = x_0^0 * x_0^1 + x_1^0 ^ x_1^1 + ...\n            sum   = 0.0;\n            for(size_t j = 0; j < n; ++j)\n            {   double xj0 = tx[ j * q + 0];\n                double xj1 = tx[ j * q + 1];\n                sum       += xj0 * xj1;\n            }\n            // ty[1] = 2.0 * sum\n            assert( order_up == 1 );\n            ty[1] = 2.0 * sum;\n            return ok;\n        }\n        // END FORWARD\n        // BEGIN REVERSE\n        bool reverse(\n            size_t                              call_id     ,\n            const CppAD::vector<bool>&          select_x    ,\n            size_t                              order_up    ,\n            const CppAD::vector<double>&        tx          ,\n            const CppAD::vector<double>&        ty          ,\n            CppAD::vector<double>&              px          ,\n            const CppAD::vector<double>&        py          ) override\n        {\n            size_t q = order_up + 1;\n            size_t n = tx.size() / q;\n    # ifndef NDEBUG\n            size_t m = ty.size() / q;\n            assert( call_id == 0 );\n            assert( m == 1 );\n            assert( px.size() == tx.size() );\n            assert( py.size() == ty.size() );\n            assert( n == select_x.size() );\n    # endif\n            // ok\n            bool ok = order_up == 0;\n            if ( ! ok )\n                return ok;\n\n            // first order reverse mode\n            for(size_t j = 0; j < n; ++j)\n            {   // x_0^0\n                double xj0 = tx[ j * q + 0];\n                //\n                // H( {x_j^k} ) = G[ F( {x_j^k} ), {x_j^k} ]\n                double dF = 2.0 * xj0; // partial F w.r.t x_j^0\n                double dG = py[0];     // partial of G w.r.t. y[0]\n                double dH = dG * dF;   // partial of H w.r.t. x_j^0\n\n                // px[j]\n                px[j] = dH;\n            }\n            return ok;\n        }\n        // END REVERSE\n        // BEGIN JAC_SPARSITY\n        // Use deprecated version of this callback to test that is still works\n        // (missing the ident_zero_x argument).\n        bool jac_sparsity(\n            size_t                                     call_id     ,\n            bool                                       dependency  ,\n            // const CppAD::vector<bool>&              ident_zero_x,\n            const CppAD::vector<bool>&                 select_x    ,\n            const CppAD::vector<bool>&                 select_y    ,\n            CppAD::sparse_rc< CppAD::vector<size_t> >& pattern_out ) override\n        {   size_t n = select_x.size();\n            size_t m = select_y.size();\n# ifndef NDEBUG\n            assert( call_id == 0 );\n            assert( m == 1 );\n# endif\n            // nnz\n            size_t nnz = 0;\n            if( select_y[0] )\n            {   for(size_t j = 0; j < n; ++j)\n                {   if( select_x[j] )\n                        ++nnz;\n                }\n            }\n            // pattern_out\n            pattern_out.resize(m, n, nnz);\n            size_t k = 0;\n            if( select_y[0] )\n            {   for(size_t j = 0; j < n; ++j)\n                {   if( select_x[j] )\n                        pattern_out.set(k++, 0, j);\n                }\n            }\n            assert( k == nnz );\n            return true;\n        }\n        // END JAC_SPARSITY\n        // BEGIN HES_SPARSITY\n        // Use deprecated version of this callback to test that is still works\n        // (missing the ident_zero_x argument).\n        bool hes_sparsity(\n            size_t                                     call_id     ,\n            // const CppAD::vector<bool>&              ident_zero_x,\n            const CppAD::vector<bool>&                 select_x    ,\n            const CppAD::vector<bool>&                 select_y    ,\n            CppAD::sparse_rc< CppAD::vector<size_t> >& pattern_out ) override\n        {   size_t n = select_x.size();\n# ifndef NDEBUG\n            size_t m = select_y.size();\n            assert( call_id == 0 );\n            assert( m == 1 );\n# endif\n            // nnz\n            size_t nnz = 0;\n            if( select_y[0] )\n            {   for(size_t j = 0; j < n; ++j)\n                {   if( select_x[j] )\n                        ++nnz;\n                }\n            }\n            // pattern_out\n            pattern_out.resize(n, n, nnz);\n            size_t k = 0;\n            if( select_y[0] )\n            {   for(size_t j = 0; j < n; ++j)\n                {   if( select_x[j] )\n                        pattern_out.set(k++, j, j);\n                }\n            }\n            return true;\n        }\n        // END HES_SPARSITY\n        // BEGIN REV_DEPEND\n        bool rev_depend(\n            size_t                                     call_id     ,\n            CppAD::vector<bool>&                       depend_x    ,\n            const CppAD::vector<bool>&                 depend_y    ) override\n        {   size_t n = depend_x.size();\n# ifndef NDEBUG\n            size_t m = depend_y.size();\n            assert( call_id == 0 );\n            assert( m == 1 );\n# endif\n            for(size_t j = 0; j < n; ++j)\n                depend_x[j] = depend_y[0];\n            //\n            return true;\n        }\n        // END REV_DEPEND\n    };\n}\n// END_DEFINE_ATOMIC_FUNCTION\n\n// BEGIN_USE_ATOMIC_FUNCTION\nbool norm_sq(void)\n{   // ok, eps\n    bool ok    = true;\n    double eps = 10. * CppAD::numeric_limits<double>::epsilon();\n    //\n    // atom_norm_sq\n    atomic_norm_sq afun(\"atomic_norm_sq\");\n    //\n    // n, m\n    size_t n = 2;\n    size_t m = 1;\n    //\n    // x\n    CPPAD_TESTVECTOR(double) x(n);\n    for(size_t j = 0; j < n; ++j)\n        x[j] = 1.0 / (double(j) + 1.0);\n    //\n    // ax\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) ax(n);\n    for(size_t j = 0; j < n; ++j)\n        ax[j] = x[j];\n    CppAD::Independent(ax);\n    //\n    // ay\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) ay(m);\n    afun(ax, ay);\n    //\n    // f\n    CppAD::ADFun<double> f;\n    f.Dependent (ax, ay);\n    //\n    // check\n    double check = 0.0;\n    for(size_t j = 0; j < n; ++j)\n        check += x[j] * x[j];\n    //\n    // ok\n    // check ay[0]\n    ok &= CppAD::NearEqual( Value(ay[0]) , check,  eps, eps);\n    //\n    // ok\n    // check zero order forward mode\n    CPPAD_TESTVECTOR(double) y(m);\n    y   = f.Forward(0, x);\n    ok &= CppAD::NearEqual(y[0] , check,  eps, eps);\n    //\n    // n2, check\n    size_t n2  = n / 2;\n    check      = 2.0 * x[n2];\n    //\n    // ok\n    // check first order forward mode partial w.r.t. x[n2]\n    CPPAD_TESTVECTOR(double) x1(n), y1(m);\n    for(size_t j = 0; j < n; ++j)\n            x1[j] = 0.0;\n    x1[n2] = 1.0;\n    y1     = f.Forward(1, x1);\n    ok    &= CppAD::NearEqual(y1[0] , check,  eps, eps);\n    //\n    // ok\n    // first order reverse mode\n    size_t q = 1;\n    CPPAD_TESTVECTOR(double)  w(m), dw(n * q);\n    w[0]  = 1.;\n    dw    = f.Reverse(q, w);\n    for(size_t j = 0; j < n; ++j)\n    {   check = 2.0 * x[j];\n        ok &= CppAD::NearEqual(dw[j] , check,  eps, eps);\n    }\n    //\n    // pattern_out\n    // reverse mode Jacobian sparstiy pattern\n    CppAD::sparse_rc< CPPAD_TESTVECTOR(size_t) > pattern_in, pattern_out;\n    pattern_in.resize(m, m, m);\n    for(size_t i = 0; i < m; ++i)\n        pattern_in.set(i, i, i);\n    bool transpose     = false;\n    bool dependency    = false;\n    bool internal_bool = false;\n    f.rev_jac_sparsity(\n        pattern_in, transpose, dependency, internal_bool, pattern_out\n    );\n    //\n    // ok\n    ok &= pattern_out.nnz() == n;\n    CPPAD_TESTVECTOR(size_t) row_major  = pattern_out.row_major();\n    for(size_t j = 0; j < n; ++j)\n    {   size_t r = pattern_out.row()[ row_major[j] ];\n        size_t c = pattern_out.col()[ row_major[j] ];\n        ok      &= r == 0 && c == j;\n    }\n    //\n    // pattern_out\n    // forward mode Hessian sparsity pattern\n    CPPAD_TESTVECTOR(bool) select_x(n), select_y(m);\n    for(size_t j = 0; j < n; ++j)\n        select_x[j] = true;\n    for(size_t i = 0; i < m; ++i)\n        select_y[i] = true;\n    internal_bool = false;\n    f.for_hes_sparsity(\n        select_x, select_y, internal_bool, pattern_out\n    );\n    //\n    // ok\n    ok &= pattern_out.nnz() == n;\n    row_major  = pattern_out.row_major();\n    for(size_t j = 0; j < n; ++j)\n    {   size_t r   = pattern_out.row()[ row_major[j] ];\n        size_t c   = pattern_out.col()[ row_major[j] ];\n        ok        &= r == j && c == j;\n    }\n    //\n    // optimize\n    // this uses the rev_depend override above\n    f.optimize(\"val_graph no_conditional_skip\");\n    //\n    // ok\n    // check zero order forward mode (on optimized version of f)\n    y     = f.Forward(0, x);\n    check = 0.0;\n    for(size_t j = 0; j < n; ++j)\n        check += x[j] * x[j];\n    ok &= CppAD::NearEqual(y[0] , check,  eps, eps);\n    //\n    return ok;\n}\n// END_USE_ATOMIC_FUNCTION\n"
  },
  {
    "path": "example/atomic_four/vector/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n#\n# BEGIN_SORT_THIS_LINE_PLUS_2\nSET(source_list\n    add.cpp\n    div.cpp\n    hes_sparsity.cpp\n    jac_sparsity.cpp\n    mul.cpp\n    neg.cpp\n    rev_depend.cpp\n    sub.cpp\n    vector.cpp\n)\n# END_SORT_THIS_LINE_MINUS_2\n\nset_compile_flags(example_atomic_four_vector \"${cppad_debug_which}\" \"${source_list}\" )\n#\nADD_EXECUTABLE(example_atomic_four_vector EXCLUDE_FROM_ALL ${source_list})\n#\n# List of libraries to be linked into the specified target\nTARGET_LINK_LIBRARIES(example_atomic_four_vector\n    ${cppad_lib}\n    ${colpack_libs}\n)\n#\n# check_example_atomic_four vector\nadd_check_executable(check_example_atomic_four vector)\n"
  },
  {
    "path": "example/atomic_four/vector/add.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_four_vector_add.cpp}\n\nAtomic Vector Addition Example\n##############################\n\nf(u, v, w)\n**********\nFor this example,\n:math:`f : \\B{R}^{3m} \\rightarrow \\B{R}^m`\nis defined by :math:`f(u, v, w) = u + v + w`.\nwhere *u* , *v* , and *w* are in :math:`\\B{R}^m`.\n\ng(u, v, w)\n**********\nFor this example :math:`g : \\B{R}^{3m} \\rightarrow \\B{R}^m`\nis defined by :math:`g_i (u, v, w) = \\partial_{v[i]}  f_i (u, v, w)`\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end atomic_four_vector_add.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n# include <cppad/example/atomic_four/vector/vector.hpp>\nbool add(void)\n{   bool ok = true;\n    using CppAD::NearEqual;\n    using CppAD::AD;\n    double eps99 = 99.0 * CppAD::numeric_limits<double>::epsilon();\n    //\n    // vec_op\n    // atomic vector_op object\n    CppAD::atomic_vector<double> vec_op(\"atomic_vector\");\n    //\n    // m\n    // size of u, v, and w\n    size_t m = 5;\n    //\n    // add_op\n    typedef CppAD::atomic_vector<double>::op_enum_t op_enum_t;\n    op_enum_t add_op = CppAD::atomic_vector<double>::add_enum;\n    // -----------------------------------------------------------------------\n    // Record f(u, v, w) = u + v + w\n    // -----------------------------------------------------------------------\n    // Independent variable vector\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) auvw(3 * m);\n    for(size_t j = 0; j < 3 * m; ++j)\n        auvw[j] = AD<double>(1 + j);\n    CppAD::Independent(auvw);\n    //\n    // au, av, aw\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) au(m), av(m), aw(m);\n    for(size_t i = 0; i < m; ++i)\n    {   au[i] = auvw[0 * m + i];\n        av[i] = auvw[1 * m + i];\n        aw[i] = auvw[2 * m + i];\n    }\n    //\n    // ax = (au, av)\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) ax(2 * m);\n    for(size_t i = 0; i < m; ++i)\n    {   ax[i]     = au[i];\n        ax[m + i] = av[i];\n    }\n    //\n    // ay = u + v\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) ay(m);\n    vec_op(add_op, ax, ay);\n    //\n    // ax = (ay, aw)\n    for(size_t i = 0; i < m; ++i)\n    {   ax[i]     = ay[i];\n        ax[m + i] = aw[i];\n    }\n    //\n    // az = ay + w\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) az(m);\n    vec_op(add_op, ax, az);\n    //\n    // f\n    CppAD::ADFun<double> f(auvw, az);\n    // -----------------------------------------------------------------------\n    // check forward mode on f\n    // -----------------------------------------------------------------------\n    //\n    // uvw, duvw\n    CPPAD_TESTVECTOR(double) uvw(3 * m), duvw(3 * m);\n    for(size_t j = 0; j < 3 * m; ++j)\n    {   uvw[j]  = double(1 + j);\n        duvw[j] = double(j);\n    }\n    //\n    // z, dz\n    CPPAD_TESTVECTOR(double) z(m), dz(m);\n    z  = f.Forward(0, uvw);\n    dz = f.Forward(1, duvw);\n    //\n    // ok\n    for(size_t i = 0; i < m; ++i)\n    {   double check_z  = uvw[0 * m + i] + uvw[1 * m + i] + uvw[2 * m + i];\n        ok             &= NearEqual( z[i] ,  check_z,  eps99, eps99);\n        double check_dz = double( (0 * m + i)  + (1 * m + i) + (2 * m + i) );\n        ok             &= NearEqual( dz[i] ,  check_dz,  eps99, eps99);\n    }\n    // -----------------------------------------------------------------------\n    // check reverse mode on f\n    // -----------------------------------------------------------------------\n    //\n    // weight\n    CPPAD_TESTVECTOR(double) weight(m);\n    for(size_t i = 0; i < m; ++i)\n        weight[i] = 1.0;\n    //\n    // dweight\n    CPPAD_TESTVECTOR(double) dweight(3 * m);\n    f.Forward(0, uvw);\n    dweight = f.Reverse(1, weight);\n    //\n    // ok\n    for(size_t j = 0; j < 3 * m; ++j)\n    {   double check  = 1.0;\n        ok           &= NearEqual(dweight[j], check, eps99, eps99);\n    }\n    // -----------------------------------------------------------------------\n    // Record g_i (u, v, w) = \\partial d/dv[i] f_i (u , v , w)\n    // -----------------------------------------------------------------------\n    //\n    // af\n    CppAD::ADFun< AD<double>, double > af = f.base2ad();\n    //\n    // auvw\n    CppAD::Independent(auvw);\n    //\n    // aduvw\n    CPPAD_TESTVECTOR( AD<double> ) aduvw(3 * m);\n    for(size_t i = 0; i < m; ++i)\n    {   aduvw[0 * m + i]  = 0.0; // du[i]\n        aduvw[1 * m + i]  = 1.0; // dv[i]\n        aduvw[2 * m + i]  = 0.0; // dw[i]\n    }\n    //\n    // az\n    // use the fact that d_v[i] f_k (u, v, w) is zero when i != k\n    af.Forward(0, auvw);\n    az = af.Forward(1, aduvw);\n    CppAD::ADFun<double> g(auvw, az);\n    // -----------------------------------------------------------------------\n    // Record h (u, v, w) = sum f_i^(1) (u , v , w)\n    // -----------------------------------------------------------------------\n    //\n    // auvw\n    CppAD::Independent(auvw);\n    //\n    // aweight\n    CPPAD_TESTVECTOR( AD<double> ) aweight(m);\n    for(size_t i = 0; i < m; ++i)\n        aweight[i] = 1.0;\n    //\n    // az\n    CPPAD_TESTVECTOR( AD<double> ) adweight(3 * m);\n    af.Forward(0, auvw);\n    az = af.Reverse(1, aweight);\n    CppAD::ADFun<double> h(auvw, az);\n    // -----------------------------------------------------------------------\n    // check forward mode on g\n    // -----------------------------------------------------------------------\n    //\n    // z\n    z = g.Forward(0, uvw);\n    //\n    // ok\n    for(size_t i = 0; i < m; ++i)\n    {   double check_z  = 1.0;\n        ok             &= NearEqual( z[i] ,  check_z,  eps99, eps99);\n    }\n    // -----------------------------------------------------------------------\n    // check forward mode on h\n    // -----------------------------------------------------------------------\n    //\n    // z\n    z = h.Forward(0, uvw);\n    //\n    // ok\n    for(size_t j = 0; j < 3 * m; ++j)\n    {   double check_z  = 1.0;\n        ok             &= NearEqual( z[j] ,  check_z,  eps99, eps99);\n    }\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/atomic_four/vector/div.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_four_vector_div.cpp}\n\nAtomic Vector Division Example\n##############################\n\nf(u, v, w)\n**********\nFor this example,\n:math:`f : \\B{R}^{2m} \\rightarrow \\B{R}^m`\nis defined by :math:`f(u, v) = u * u / v`.\nwhere *u* and *v* are in :math:`\\B{R}^m`.\n\ng(u, v)\n*******\nFor this example :math:`g : \\B{R}^{2m} \\rightarrow \\B{R}^m`\nis defined by :math:`g_i (u, v) = \\partial_{v[i]}  f_i (u, v)`\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end atomic_four_vector_div.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n# include <cppad/example/atomic_four/vector/vector.hpp>\nbool div(void)\n{   bool ok = true;\n    using CppAD::NearEqual;\n    using CppAD::AD;\n    double eps99 = 99.0 * CppAD::numeric_limits<double>::epsilon();\n    //\n    // vec_op\n    // atomic vector_op object\n    CppAD::atomic_vector<double> vec_op(\"atomic_vector\");\n    //\n    // m\n    // size of u and v\n    size_t m = 4;\n    //\n    // mul_op, div_op\n    typedef CppAD::atomic_vector<double>::op_enum_t op_enum_t;\n    op_enum_t mul_op = CppAD::atomic_vector<double>::mul_enum;\n    op_enum_t div_op = CppAD::atomic_vector<double>::div_enum;\n    // -----------------------------------------------------------------------\n    // Record f(u, v) = u * u / v\n    // -----------------------------------------------------------------------\n    // Independent variable vector\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) auv(2 * m);\n    for(size_t j = 0; j < 2 * m; ++j)\n        auv[j] = AD<double>(1 + j);\n    CppAD::Independent(auv);\n    //\n    // au, av, aw\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) au(m), av(m);\n    for(size_t i = 0; i < m; ++i)\n    {   au[i] = auv[0 * m + i];\n        av[i] = auv[1 * m + i];\n    }\n    //\n    // ax = (mul_op, au, au)\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) ax(2 * m);\n    for(size_t i = 0; i < m; ++i)\n    {   ax[i]     = au[i];\n        ax[m + i] = au[i];\n    }\n    //\n    // ay = u * u\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) ay(m);\n    vec_op(mul_op, ax, ay);\n    //\n    // ax = (ay, av)\n    for(size_t i = 0; i < m; ++i)\n    {   ax[i]     = ay[i];\n        ax[m + i] = av[i];\n    }\n    //\n    // az = au / ay\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) az(m);\n    vec_op(div_op, ax, az);\n    //\n    // f\n    CppAD::ADFun<double> f(auv, az);\n    // -----------------------------------------------------------------------\n    // check forward mode on f\n    // -----------------------------------------------------------------------\n    //\n    // uv, duv\n    CPPAD_TESTVECTOR(double) uv(2 * m), duv(2 * m);\n    for(size_t j = 0; j < 2 * m; ++j)\n    {   uv[j]  = double(2 + j);\n        duv[j] = 1.0;\n    }\n    //\n    // z, dz\n    CPPAD_TESTVECTOR(double) z(m), dz(m);\n    z  = f.Forward(0, uv);\n    dz = f.Forward(1, duv);\n    //\n    // ok\n    for(size_t i = 0; i < m; ++i)\n    {   double ui     = uv[0 * m + i];\n        double vi     = uv[1 * m + i];\n        double check  = ui * ui / vi;\n        ok           &= NearEqual( z[i] ,  check,  eps99, eps99);\n        check         = 2.0 * ui / vi - ui * ui / (vi * vi);\n        ok         &= NearEqual( dz[i] ,  check,  eps99, eps99);\n    }\n    // -----------------------------------------------------------------------\n    // check reverse mode on f\n    // -----------------------------------------------------------------------\n    //\n    // weight\n    CPPAD_TESTVECTOR(double) weight(m);\n    for(size_t i = 0; i < m; ++i)\n        weight[i] = 1.0;\n    //\n    // dweight\n    CPPAD_TESTVECTOR(double) dweight(2 * m);\n    f.Forward(0, uv);\n    dweight = f.Reverse(1, weight);\n    //\n    // ok\n    for(size_t i = 0; i < m; ++i)\n    {   double ui      = uv[0 * m + i];\n        double vi      = uv[1 * m + i];\n        double dfi_dui = 2.0 * ui / vi;\n        ok           &= NearEqual(dweight[0 * m + i], dfi_dui, eps99, eps99);\n        double dfi_dvi = - ui * ui / (vi * vi);\n        ok           &= NearEqual(dweight[1 * m + i], dfi_dvi, eps99, eps99);\n    }\n    // -----------------------------------------------------------------------\n    // Record g_i (u, v) = \\partial d/dv[i] f_i (u, v)\n    // -----------------------------------------------------------------------\n    //\n    // af\n    CppAD::ADFun< AD<double>, double > af = f.base2ad();\n    //\n    // auv\n    CppAD::Independent(auv);\n    //\n    // aduv\n    CPPAD_TESTVECTOR( AD<double> ) aduv(2 * m);\n    for(size_t i = 0; i < m; ++i)\n    {   aduv[0 * m + i]  = 0.0; // du[i]\n        aduv[1 * m + i]  = 1.0; // dv[i]\n    }\n    //\n    // az\n    // use the fact that d_u[i] f_k (u, v, w) is zero when i != k\n    af.Forward(0, auv);\n    az = af.Forward(1, aduv);\n    CppAD::ADFun<double> g(auv, az);\n    // -----------------------------------------------------------------------\n    // Record h (u, v) = sum f_i^(1) (u , v)\n    // -----------------------------------------------------------------------\n    //\n    // auv\n    CppAD::Independent(auv);\n    //\n    // aweight\n    CPPAD_TESTVECTOR( AD<double> ) aweight(m);\n    for(size_t i = 0; i < m; ++i)\n        aweight[i] = 1.0;\n    //\n    // az\n    CPPAD_TESTVECTOR( AD<double> ) adweight(3 * m);\n    af.Forward(0, auv);\n    az = af.Reverse(1, aweight);\n    CppAD::ADFun<double> h(auv, az);\n    // -----------------------------------------------------------------------\n    // check forward mode on g\n    // -----------------------------------------------------------------------\n    //\n    // z\n    z = g.Forward(0, uv);\n    //\n    // ok\n    for(size_t i = 0; i < m; ++i)\n    {   double ui      = uv[0 * m + i];\n        double vi      = uv[1 * m + i];\n        double check   = - ui * ui / (vi * vi);\n        ok           &= NearEqual( z[i] ,  check,  eps99, eps99);\n    }\n    // -----------------------------------------------------------------------\n    // check forward mode on h\n    // -----------------------------------------------------------------------\n    //\n    // z\n    z = h.Forward(0, uv);\n    //\n    // ok\n    for(size_t i = 0; i < m; ++i)\n    {   double ui  = uv[0 * m + i];\n        double vi  = uv[1 * m + i];\n        //\n        double dfi_dui  = 2.0 * ui / vi;\n        ok             &= NearEqual(z[0 * m + i] ,  dfi_dui,  eps99, eps99);\n        //\n        double dfi_dvi  = - ui * ui / (vi * vi);\n        ok             &= NearEqual(z[1 * m + i] ,  dfi_dvi,  eps99, eps99);\n    }\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/atomic_four/vector/hes_sparsity.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_four_vector_hes_sparsity.cpp}\n\nAtomic Vector Sparsity Patterns Example\n#######################################\n\nf(u, v)\n*******\nFor this example,\n:math:`f : \\B{R}^{3m} \\rightarrow \\B{R}^m`\nis defined by :math:`f(u, v, w) = - u * v * w`.\nwhere *u* , *v* , and *w* are in :math:`\\B{R}^m`.\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end atomic_four_vector_hes_sparsity.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n# include <cppad/example/atomic_four/vector/vector.hpp>\nbool hes_sparsity(void)\n{   bool ok = true;\n    using CppAD::NearEqual;\n    using CppAD::AD;\n    //\n    // vec_op\n    // atomic vector_op object\n    CppAD::atomic_vector<double> vec_op(\"atomic_vector\");\n    //\n    // m\n    // size of u, v, and w\n    size_t m = 6;\n    //\n    // n\n    size_t n = 3 * m;\n    //\n    // mul_op, neg_op\n    typedef CppAD::atomic_vector<double>::op_enum_t op_enum_t;\n    op_enum_t mul_op = CppAD::atomic_vector<double>::mul_enum;\n    op_enum_t neg_op = CppAD::atomic_vector<double>::neg_enum;\n    // -----------------------------------------------------------------------\n    // Record f(u, v, w) = - u * v * w\n    // -----------------------------------------------------------------------\n    // Independent variable vector\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) auvw(n);\n    for(size_t j = 0; j < n; ++j)\n        auvw[j] = AD<double>(1 + j);\n    CppAD::Independent(auvw);\n    //\n    // au, av, aw\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) au(m), av(m), aw(m);\n    for(size_t i = 0; i < m; ++i)\n    {   au[i] = auvw[0 * m + i];\n        av[i] = auvw[1 * m + i];\n        aw[i] = auvw[2 * m + i];\n    }\n    //\n    // ax = (au, av)\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) ax(2 * m);\n    for(size_t i = 0; i < m; ++i)\n    {   ax[i]     = au[i];\n        ax[m + i] = av[i];\n    }\n    //\n    // ay = u * v\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) ay(m);\n    vec_op(mul_op, ax, ay);\n    //\n    // ax = (ay, aw)\n    for(size_t i = 0; i < m; ++i)\n    {   ax[i]     = ay[i];\n        ax[m + i] = aw[i];\n    }\n    //\n    // az = ay * w\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) az(m);\n    vec_op(mul_op, ax, az);\n    //\n    // ay = - az\n    vec_op(neg_op, az, ay);\n    //\n    // f\n    CppAD::ADFun<double> f(auvw, ay);\n    //\n    // size_vector, sparsity_pattern\n    typedef CPPAD_TESTVECTOR(size_t) size_vector;\n    typedef CppAD::sparse_rc<size_vector> sparsity_pattern;\n    // -----------------------------------------------------------------------\n    // Hessian sparsity\n    // -----------------------------------------------------------------------\n    for(size_t direction = 0; direction < 2; ++direction)\n    {   sparsity_pattern pattern_out;\n        //\n        // select_range\n        CPPAD_TESTVECTOR(bool) select_range(m);\n        for(size_t i = 0; i < m; ++i)\n            select_range[i] = true;\n        //\n        if( direction == 0 )\n        {   // Forward\n            //\n            // select_domain\n            CPPAD_TESTVECTOR(bool) select_domain(n);\n            for(size_t j = 0; j < n; ++j)\n                select_domain[j] = true;\n            //\n            // pattern_out\n            bool internal_bool = false;\n            f.for_hes_sparsity(\n                select_domain, select_range, internal_bool, pattern_out\n            );\n        }\n        else\n        {   // Reverse\n            //\n            // transpose, internal_bool\n            bool transpose     = false;\n            bool dependency    = false;\n            bool internal_bool = false;\n            //\n            // pattern_in\n            sparsity_pattern pattern_in(n, n, n);\n            for(size_t j = 0; j < n; ++j)\n                pattern_in.set(j, j, j);\n            //\n            // f stores forward Jacobian\n            f.for_jac_sparsity(\n                pattern_in, transpose, dependency, internal_bool, pattern_out\n            );\n            //\n            // pattern_out\n            f.rev_hes_sparsity(\n                select_range, transpose, internal_bool, pattern_out\n            );\n        }\n        //\n        // ok\n        ok &= pattern_out.nnz() == 2 * n;\n        ok &= pattern_out.nr()  == n;\n        ok &= pattern_out.nc()  == n;\n        //\n        // row, col, row_major\n        const size_vector& row = pattern_out.row();\n        const size_vector& col = pattern_out.col();\n        size_vector row_major  = pattern_out.row_major();\n        //\n        // ok\n        size_t ell = 0;\n        for(size_t i = 0; i < m; ++i)\n        {   // first non-zero in row i\n            size_t k = row_major[ell++];\n            ok      &= row[k] == i;\n            ok      &= col[k] == m + i;\n            // second non-zero in row i\n            k        = row_major[ell++];\n            ok      &= row[k] == i;\n            ok      &= col[k] == 2 * m + i;\n        }\n        for(size_t i = m; i < 2 * m; ++i)\n        {   // first non-zero in row i\n            size_t k = row_major[ell++];\n            ok      &= row[k] == i;\n            ok      &= col[k] == i - m;\n            // second non-zero in row i\n            k        = row_major[ell++];\n            ok      &= row[k] == i;\n            ok      &= col[k] == i + m;\n        }\n        for(size_t i = 2 * m; i < 3 * m; ++i)\n        {   // first non-zero in row i\n            size_t k = row_major[ell++];\n            ok      &= row[k] == i;\n            ok      &= col[k] == i - 2 * m;\n            // second non-zero in row i\n            k        = row_major[ell++];\n            ok      &= row[k] == i;\n            ok      &= col[k] == i - m;\n        }\n    }\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/atomic_four/vector/jac_sparsity.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_four_vector_jac_sparsity.cpp}\n\nAtomic Vector Sparsity Patterns Example\n#######################################\n\nf(u, v)\n*******\nFor this example,\n:math:`f : \\B{R}^{3m} \\rightarrow \\B{R}^m`\nis defined by :math:`f(u, v, w) = - u * v * w`.\nwhere *u* , *v* , and *w* are in :math:`\\B{R}^m`.\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end atomic_four_vector_jac_sparsity.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n# include <cppad/example/atomic_four/vector/vector.hpp>\nbool jac_sparsity(void)\n{   bool ok = true;\n    using CppAD::NearEqual;\n    using CppAD::AD;\n    //\n    // vec_op\n    // atomic vector_op object\n    CppAD::atomic_vector<double> vec_op(\"atomic_vector\");\n    //\n    // m\n    // size of u, v, and w\n    size_t m = 6;\n    //\n    // n\n    size_t n = 3 * m;\n    //\n    // mul_op, neg_op\n    typedef CppAD::atomic_vector<double>::op_enum_t op_enum_t;\n    op_enum_t mul_op = CppAD::atomic_vector<double>::mul_enum;\n    op_enum_t neg_op = CppAD::atomic_vector<double>::neg_enum;\n    // -----------------------------------------------------------------------\n    // Record f(u, v, w) = - u * v * w\n    // -----------------------------------------------------------------------\n    // Independent variable vector\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) auvw(n);\n    for(size_t j = 0; j < n; ++j)\n        auvw[j] = AD<double>(1 + j);\n    CppAD::Independent(auvw);\n    //\n    // au, av, aw\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) au(m), av(m), aw(m);\n    for(size_t i = 0; i < m; ++i)\n    {   au[i] = auvw[0 * m + i];\n        av[i] = auvw[1 * m + i];\n        aw[i] = auvw[2 * m + i];\n    }\n    //\n    // ax = (au, av)\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) ax(2 * m);\n    for(size_t i = 0; i < m; ++i)\n    {   ax[i]     = au[i];\n        ax[m + i] = av[i];\n    }\n    //\n    // ay = u * v\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) ay(m);\n    vec_op(mul_op, ax, ay);\n    //\n    // ax = (ay, aw)\n    for(size_t i = 0; i < m; ++i)\n    {   ax[i]     = ay[i];\n        ax[m + i] = aw[i];\n    }\n    //\n    // az = ay * w\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) az(m);\n    vec_op(mul_op, ax, az);\n    //\n    // ay = - az\n    vec_op(neg_op, az, ay);\n    //\n    // f\n    CppAD::ADFun<double> f(auvw, ay);\n    //\n    // size_vector, sparsity_pattern\n    typedef CPPAD_TESTVECTOR(size_t) size_vector;\n    typedef CppAD::sparse_rc<size_vector> sparsity_pattern;\n    // -----------------------------------------------------------------------\n    // Jacobian sparsity\n    // -----------------------------------------------------------------------\n    for(size_t direction = 0; direction < 2; ++direction)\n    {   sparsity_pattern pattern_out;\n        bool transpose     = false;\n        bool dependency    = false;\n        bool internal_bool = false;\n        if( direction == 0 )\n        {   // Forward direction\n            //\n            // pattern_in\n            // sparsity pattern for identity matrix\n            sparsity_pattern pattern_in(n, n, n);\n            for(size_t k = 0; k < n; ++k)\n                pattern_in.set(k, k, k);\n            //\n            // pattern_out\n            f.for_jac_sparsity(\n                pattern_in, transpose, dependency, internal_bool, pattern_out\n            );\n        }\n        else\n        {   // Reverse direction\n            //\n            // pattern_in\n            // sparsity pattern for identity matrix\n            sparsity_pattern pattern_in(m, m, m);\n            for(size_t k = 0; k < m; ++k)\n                pattern_in.set(k, k, k);\n            //\n            // pattern_out\n            f.rev_jac_sparsity(\n                pattern_in, transpose, dependency, internal_bool, pattern_out\n            );\n        }\n        //\n        // ok\n        ok &= pattern_out.nnz() == 3 * m;\n        ok &= pattern_out.nr()  == m;\n        ok &= pattern_out.nc()  == n;\n        //\n        // row, col, row_major\n        const size_vector& row = pattern_out.row();\n        const size_vector& col = pattern_out.col();\n        size_vector row_major  = pattern_out.row_major();\n        //\n        // ok\n        size_t ell = 0;\n        for(size_t i = 0; i < m; ++i)\n        {   // first non-zero in row i\n            size_t k = row_major[ell++];\n            ok      &= row[k] == i;\n            ok      &= col[k] == i;\n            // second non-zero in row i\n            k        = row_major[ell++];\n            ok      &= row[k] == i;\n            ok      &= col[k] == m + i;\n            // third non-zero in row i\n            k        = row_major[ell++];\n            ok      &= row[k] == i;\n            ok      &= col[k] == 2 * m + i;\n        }\n    }\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/atomic_four/vector/mul.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_four_vector_mul.cpp}\n\nAtomic Vector Multiplication Example\n####################################\n\nf(u, v, w)\n**********\nFor this example,\n:math:`f : \\B{R}^{3m} \\rightarrow \\B{R}^m`\nis defined by :math:`f(u, v, w) = u * v * w`.\nwhere *u* , *v* , and *w* are in :math:`\\B{R}^m`.\n\ng(u, v, w)\n**********\nFor this example :math:`g : \\B{R}^{3m} \\rightarrow \\B{R}^m`\nis defined by :math:`g_i (u, v, w) = \\partial_{u[i]}  f_i (u, v, w)`\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end atomic_four_vector_mul.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n# include <cppad/example/atomic_four/vector/vector.hpp>\nbool mul(void)\n{   bool ok = true;\n    using CppAD::NearEqual;\n    using CppAD::AD;\n    double eps99 = 99.0 * CppAD::numeric_limits<double>::epsilon();\n    //\n    // vec_op\n    // atomic vector_op object\n    CppAD::atomic_vector<double> vec_op(\"atomic_vector\");\n    //\n    // m\n    // size of u, v, and w\n    size_t m = 5;\n    //\n    // mul_op\n    typedef CppAD::atomic_vector<double>::op_enum_t op_enum_t;\n    op_enum_t mul_op = CppAD::atomic_vector<double>::mul_enum;\n    // -----------------------------------------------------------------------\n    // Record f(u, v, w) = u * v * w\n    // -----------------------------------------------------------------------\n    // Independent variable vector\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) auvw(3 * m);\n    for(size_t j = 0; j < 3 * m; ++j)\n        auvw[j] = AD<double>(1 + j);\n    CppAD::Independent(auvw);\n    //\n    // au, av, aw\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) au(m), av(m), aw(m);\n    for(size_t i = 0; i < m; ++i)\n    {   au[i] = auvw[0 * m + i];\n        av[i] = auvw[1 * m + i];\n        aw[i] = auvw[2 * m + i];\n    }\n    //\n    // ax = (mul_op, au, av)\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) ax(2 * m);\n    for(size_t i = 0; i < m; ++i)\n    {   ax[i]     = au[i];\n        ax[m + i] = av[i];\n    }\n    //\n    // ay = u * v\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) ay(m);\n    vec_op(mul_op, ax, ay);\n    //\n    // ax = (ay, aw)\n    for(size_t i = 0; i < m; ++i)\n    {   ax[i]     = ay[i];\n        ax[m + i] = aw[i];\n    }\n    //\n    // az = ay * aw\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) az(m);\n    vec_op(mul_op, ax, az);\n    //\n    // f\n    CppAD::ADFun<double> f(auvw, az);\n    // -----------------------------------------------------------------------\n    // check forward mode on f\n    // -----------------------------------------------------------------------\n    //\n    // uvw, duvw\n    CPPAD_TESTVECTOR(double) uvw(3 * m), duvw(3 * m);\n    for(size_t j = 0; j < 3 * m; ++j)\n    {   uvw[j]  = double(1 + j);\n        duvw[j] = 1.0;\n    }\n    //\n    // z, dz\n    CPPAD_TESTVECTOR(double) z(m), dz(m);\n    z  = f.Forward(0, uvw);\n    dz = f.Forward(1, duvw);\n    //\n    // ok\n    for(size_t i = 0; i < m; ++i)\n    {   double ui  = uvw[0 * m + i];\n        double vi  = uvw[1 * m + i];\n        double wi  = uvw[2 * m + i];\n        //\n        double check_z  = ui * vi * wi;\n        ok             &= NearEqual( z[i] ,  check_z,  eps99, eps99);\n        //\n        double check_dz = (vi * wi) + (ui * wi) + (ui * vi);\n        ok             &= NearEqual( dz[i] ,  check_dz,  eps99, eps99);\n    }\n    // -----------------------------------------------------------------------\n    // check reverse mode on f\n    // -----------------------------------------------------------------------\n    //\n    // weight\n    CPPAD_TESTVECTOR(double) weight(m);\n    for(size_t i = 0; i < m; ++i)\n        weight[i] = 1.0;\n    //\n    // dweight\n    CPPAD_TESTVECTOR(double) dweight(3 * m);\n    f.Forward(0, uvw);\n    dweight = f.Reverse(1, weight);\n    //\n    // ok\n    for(size_t i = 0; i < m; ++i)\n    {   double ui  = uvw[0 * m + i];\n        double vi  = uvw[1 * m + i];\n        double wi  = uvw[2 * m + i];\n        //\n        double dfi_dui = vi * wi;\n        ok           &= NearEqual(dweight[0 * m + i], dfi_dui, eps99, eps99);\n        double dfi_dvi = ui * wi;\n        ok           &= NearEqual(dweight[1 * m + i], dfi_dvi, eps99, eps99);\n        double dfi_dwi = ui * vi;\n        ok           &= NearEqual(dweight[2 * m + i], dfi_dwi, eps99, eps99);\n    }\n    // -----------------------------------------------------------------------\n    // Record g_i (u, v, w) = \\partial d/dv[i] f_i (u , v , w)\n    // -----------------------------------------------------------------------\n    //\n    // af\n    CppAD::ADFun< AD<double>, double > af = f.base2ad();\n    //\n    // auvw\n    CppAD::Independent(auvw);\n    //\n    // aduvw\n    CPPAD_TESTVECTOR( AD<double> ) aduvw(3 * m);\n    for(size_t i = 0; i < m; ++i)\n    {   aduvw[0 * m + i]  = 1.0; // du[i]\n        aduvw[1 * m + i]  = 0.0; // dv[i]\n        aduvw[2 * m + i]  = 0.0; // dw[i]\n    }\n    //\n    // az\n    // use the fact that d_u[i] f_k (u, v, w) is zero when i != k\n    af.Forward(0, auvw);\n    az = af.Forward(1, aduvw);\n    CppAD::ADFun<double> g(auvw, az);\n    // -----------------------------------------------------------------------\n    // Record h (u, v, w) = sum f_i^(1) (u , v , w)\n    // -----------------------------------------------------------------------\n    //\n    // auvw\n    CppAD::Independent(auvw);\n    //\n    // aweight\n    CPPAD_TESTVECTOR( AD<double> ) aweight(m);\n    for(size_t i = 0; i < m; ++i)\n        aweight[i] = 1.0;\n    //\n    // az\n    CPPAD_TESTVECTOR( AD<double> ) adweight(3 * m);\n    af.Forward(0, auvw);\n    az = af.Reverse(1, aweight);\n    CppAD::ADFun<double> h(auvw, az);\n    // -----------------------------------------------------------------------\n    // check forward mode on g\n    // -----------------------------------------------------------------------\n    //\n    // z\n    z = g.Forward(0, uvw);\n    //\n    // ok\n    for(size_t i = 0; i < m; ++i)\n    {   double vi       = uvw[1 * m + i];\n        double wi       = uvw[2 * m + i];\n        double check_z  = vi * wi;\n        ok             &= NearEqual( z[i] ,  check_z,  eps99, eps99);\n    }\n    return ok;\n    // -----------------------------------------------------------------------\n    // check forward mode on h\n    // -----------------------------------------------------------------------\n    //\n    // z\n    z = h.Forward(0, uvw);\n    //\n    // ok\n    for(size_t i = 0; i < m; ++i)\n    {   double ui  = uvw[0 * m + i];\n        double vi  = uvw[1 * m + i];\n        double wi  = uvw[2 * m + i];\n        //\n        double dfi_dui  = vi * wi;\n        ok             &= NearEqual(z[0 * m + i] ,  dfi_dui,  eps99, eps99);\n        //\n        double dfi_dvi  = ui * wi;\n        ok             &= NearEqual(z[1 * m + i] ,  dfi_dvi,  eps99, eps99);\n        //\n        double dfi_dwi  = ui * vi;\n        ok             &= NearEqual(z[2 * m + i] ,  dfi_dwi,  eps99, eps99);\n    }\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/atomic_four/vector/neg.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_four_vector_neg.cpp}\n\nAtomic Vector Negation Example\n##############################\n\nf(u, w)\n*******\nFor this example,\n:math:`f : \\B{R}^{2m} \\rightarrow \\B{R}^m`\nis defined by :math:`f(u, w) = u - w`.\nwhere *u* and *w* are in :math:`\\B{R}^m`.\n\ng(u, w)\n*******\nFor this example :math:`g : \\B{R}^{2m} \\rightarrow \\B{R}^m`\nis defined by :math:`g_i (u, w) = \\partial_{w[i]}  f_i (u, w)`\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end atomic_four_vector_neg.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n# include <cppad/example/atomic_four/vector/vector.hpp>\nbool neg(void)\n{   bool ok = true;\n    using CppAD::NearEqual;\n    using CppAD::AD;\n    double eps99 = 99.0 * CppAD::numeric_limits<double>::epsilon();\n    //\n    // vec_op\n    // atomic vector_op object\n    CppAD::atomic_vector<double> vec_op(\"atomic_vector\");\n    //\n    // m\n    // size of u, v\n    size_t m = 5;\n    //\n    // add_op, neg_op\n    typedef CppAD::atomic_vector<double>::op_enum_t op_enum_t;\n    op_enum_t add_op = CppAD::atomic_vector<double>::add_enum;\n    op_enum_t neg_op = CppAD::atomic_vector<double>::neg_enum;\n    // -----------------------------------------------------------------------\n    // Record f(u, v) = u - v\n    // -----------------------------------------------------------------------\n    // Independent variable vector\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) auv(2 * m);\n    for(size_t j = 0; j < 2 * m; ++j)\n        auv[j] = AD<double>(1 + j);\n    CppAD::Independent(auv);\n    //\n    // au, av\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) au(m), av(m);\n    for(size_t i = 0; i < m; ++i)\n    {   au[i] = auv[0 * m + i];\n        av[i] = auv[1 * m + i];\n    }\n    //\n    // ax = av\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) ax(m);\n    for(size_t i = 0; i < m; ++i)\n        ax[i] = av[i];\n    //\n    // ay = - av\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) ay(m);\n    vec_op(neg_op, ax, ay);\n    //\n    // ax = (au, ay)\n    ax.resize(2 * m);\n    for(size_t i = 0; i < m; ++i)\n    {   ax[i]     = au[i];\n        ax[m + i] = ay[i];\n    }\n    //\n    // az = au + ay\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) az(m);\n    vec_op(add_op, ax, az);\n    //\n    // f\n    CppAD::ADFun<double> f(auv, az);\n    // -----------------------------------------------------------------------\n    // check forward mode on f\n    // -----------------------------------------------------------------------\n    //\n    // uv, duv\n    CPPAD_TESTVECTOR(double) uv(2 * m), duv(2 * m);\n    for(size_t j = 0; j < 2 * m; ++j)\n    {   uv[j]  = double(1 + j);\n        duv[j] = double(j);\n    }\n    //\n    // z, dz\n    CPPAD_TESTVECTOR(double) z(m), dz(m);\n    z  = f.Forward(0, uv);\n    dz = f.Forward(1, duv);\n    //\n    // ok\n    for(size_t i = 0; i < m; ++i)\n    {   double check_z  = uv[0 * m + i] - uv[1 * m + i];\n        ok             &= NearEqual( z[i] ,  check_z,  eps99, eps99);\n        double check_dz = double(0 * m + i) - double(1 * m + i);\n        ok             &= NearEqual( dz[i] ,  check_dz,  eps99, eps99);\n    }\n    // -----------------------------------------------------------------------\n    // Record g_i (u, v) = \\partial d/dv[i] f_i (u , v)\n    // -----------------------------------------------------------------------\n    //\n    // af\n    CppAD::ADFun< AD<double>, double > af = f.base2ad();\n    //\n    // auv\n    CppAD::Independent(auv);\n    //\n    // aduv\n    CPPAD_TESTVECTOR( AD<double> ) aduv(2 * m);\n    for(size_t i = 0; i < m; ++i)\n    {   aduv[0 * m + i]  = 0.0; // du[i]\n        aduv[1 * m + i]  = 1.0; // dv[i]\n    }\n    //\n    // az\n    // use the fact that d_v[i] f_k (u, v) is zero when i != k\n    af.Forward(0, auv);\n    az = af.Forward(1, aduv);\n    CppAD::ADFun<double> g(auv, az);\n    // -----------------------------------------------------------------------\n    // check forward mode on g\n    // -----------------------------------------------------------------------\n    //\n    // z\n    z = g.Forward(0, uv);\n    //\n    // ok\n    for(size_t i = 0; i < m; ++i)\n    {   double check_z  = - 1.0;\n        ok             &= NearEqual( z[i] ,  check_z,  eps99, eps99);\n    }\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/atomic_four/vector/rev_depend.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-23 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_four_vector_rev_depend.cpp}\n\nExample Optimizing Atomic Vector Usage\n######################################\n\nf(u, v)\n*******\nFor this example,\n:math:`f : \\B{R}^{3m} \\rightarrow \\B{R}`\nis defined by :math:`f(u, v, w) = - ( u_0 + v_0 ) * w_0`.\nwhere *u* , *v* , and *w* are in :math:`\\B{R}^m`.\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end atomic_four_vector_rev_depend.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n# include <cppad/example/atomic_four/vector/vector.hpp>\nbool rev_depend(void)\n{   bool ok = true;\n    using CppAD::NearEqual;\n    using CppAD::AD;\n    //\n    // vec_op\n    // atomic vector_op object\n    CppAD::atomic_vector<double> vec_op(\"atomic_vector\");\n    //\n    // m\n    // size of u, v, and w\n    size_t m = 6;\n    //\n    // n\n    size_t n = 3 * m;\n    //\n    // add_op, mul_op, neg_op\n    typedef CppAD::atomic_vector<double>::op_enum_t op_enum_t;\n    op_enum_t add_op = CppAD::atomic_vector<double>::add_enum;\n    op_enum_t mul_op = CppAD::atomic_vector<double>::mul_enum;\n    op_enum_t neg_op = CppAD::atomic_vector<double>::neg_enum;\n    // -----------------------------------------------------------------------\n    // Record f(u, v, w) = - (u + v) * w\n    // -----------------------------------------------------------------------\n    // Independent variable vector\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) a_ind(n);\n    for(size_t j = 0; j < n; ++j)\n        a_ind[j] = AD<double>(1 + j);\n    CppAD::Independent(a_ind);\n    //\n    // au, av, aw\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) au(m), av(m), aw(m);\n    for(size_t i = 0; i < m; ++i)\n    {   au[i] = a_ind[0 * m + i];\n        av[i] = a_ind[1 * m + i];\n        aw[i] = a_ind[2 * m + i];\n    }\n    //\n    // ax = (au, av)\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) ax(2 * m);\n    for(size_t i = 0; i < m; ++i)\n    {   ax[i]     = au[i];\n        ax[m + i] = av[i];\n    }\n    //\n    // ay = u + v\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) ay(m);\n    vec_op(add_op, ax, ay);\n    //\n    // ax = (ay, aw)\n    for(size_t i = 0; i < m; ++i)\n    {   ax[i]     = ay[i];\n        ax[m + i] = aw[i];\n    }\n    //\n    // az = ay * w\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) az(m);\n    vec_op(mul_op, ax, az);\n    //\n    // ay = - az\n    vec_op(neg_op, az, ay);\n    //\n    // f\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) a_dep(1);\n    a_dep[0] = ay[0];\n    CppAD::ADFun<double> f(a_ind, a_dep);\n    //\n    // size_var\n    // phantom variable, independent variables, operator results\n    ok   &= f.size_var() == 1 + n + 3 * m;\n    //\n    // optimize\n    // The atomic function rev_depend routine is called by optimizer\n    f.optimize(\"val_graph no_conditional_skip\");\n    //\n    // size_var\n    // phantom variablem, independent variables, operator variables\n    ok &= f.size_var() == 1 + n + 3;\n    //\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/atomic_four/vector/sub.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_four_vector_sub.cpp}\n\nAtomic Vector Subtraction Example\n#################################\n\nf(u, v, w)\n**********\nFor this example,\n:math:`f : \\B{R}^{3m} \\rightarrow \\B{R}^m`\nis defined by :math:`f(u, v, w) = u - (v + w)`.\nwhere *u* , *v* , and *w* are in :math:`\\B{R}^m`.\n\ng(u, v, w)\n**********\nFor this example :math:`g : \\B{R}^{3m} \\rightarrow \\B{R}^m`\nis defined by :math:`g_i (u, v, w) = \\partial_{v[i]}  f_i (u, v, w)`\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end atomic_four_vector_sub.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n# include <cppad/example/atomic_four/vector/vector.hpp>\nbool sub(void)\n{   bool ok = true;\n    using CppAD::NearEqual;\n    using CppAD::AD;\n    double eps99 = 99.0 * CppAD::numeric_limits<double>::epsilon();\n    //\n    // vec_op\n    // atomic vector_op object\n    CppAD::atomic_vector<double> vec_op(\"atomic_vector\");\n    //\n    // m\n    // size of u, v, and w\n    size_t m = 5;\n    //\n    // add_op, sub_op\n    typedef CppAD::atomic_vector<double>::op_enum_t op_enum_t;\n    op_enum_t add_op = CppAD::atomic_vector<double>::add_enum;\n    op_enum_t sub_op = CppAD::atomic_vector<double>::sub_enum;\n    // -----------------------------------------------------------------------\n    // Record f(u, v, w) = u - (v + w)\n    // -----------------------------------------------------------------------\n    // Independent variable vector\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) auvw(3 * m);\n    for(size_t j = 0; j < 3 * m; ++j)\n        auvw[j] = AD<double>(1 + j);\n    CppAD::Independent(auvw);\n    //\n    // au, av, aw\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) au(m), av(m), aw(m);\n    for(size_t i = 0; i < m; ++i)\n    {   au[i] = auvw[0 * m + i];\n        av[i] = auvw[1 * m + i];\n        aw[i] = auvw[2 * m + i];\n    }\n    //\n    // ax = (av, aw)\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) ax(2 * m);\n    for(size_t i = 0; i < m; ++i)\n    {   ax[i]     = av[i];\n        ax[m + i] = aw[i];\n    }\n    //\n    // ay = v + w\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) ay(m);\n    vec_op(add_op, ax, ay);\n    //\n    // ax = (sub_op, au, ay)\n    for(size_t i = 0; i < m; ++i)\n    {   ax[i]     = au[i];\n        ax[m + i] = ay[i];\n    }\n    //\n    // az = au - ay\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) az(m);\n    vec_op(sub_op, ax, az);\n    //\n    // f\n    CppAD::ADFun<double> f(auvw, az);\n    // -----------------------------------------------------------------------\n    // check forward mode on f\n    // -----------------------------------------------------------------------\n    //\n    // uvw, duvw\n    CPPAD_TESTVECTOR(double) uvw(3 * m), duvw(3 * m);\n    for(size_t j = 0; j < 3 * m; ++j)\n    {   uvw[j]  = double(1 + j);\n        duvw[j] = double(j);\n    }\n    //\n    // z, dz\n    CPPAD_TESTVECTOR(double) z(m), dz(m);\n    z  = f.Forward(0, uvw);\n    dz = f.Forward(1, duvw);\n    //\n    // ok\n    for(size_t i = 0; i < m; ++i)\n    {   double check_z  = uvw[0 * m + i] - ( uvw[1 * m + i] + uvw[2 * m + i] );\n        ok             &= NearEqual( z[i] ,  check_z,  eps99, eps99);\n        double check_dz = double(0 * m + i) - double(1 * m + i + 2 * m + i);\n        ok             &= NearEqual( dz[i] ,  check_dz,  eps99, eps99);\n    }\n    // -----------------------------------------------------------------------\n    // Record g_i (u, v, w) = \\partial d/dv[i] f_i (u , v , w)\n    // -----------------------------------------------------------------------\n    //\n    // af\n    CppAD::ADFun< AD<double>, double > af = f.base2ad();\n    //\n    // auvw\n    CppAD::Independent(auvw);\n    //\n    // aduvw\n    CPPAD_TESTVECTOR( AD<double> ) aduvw(3 * m);\n    for(size_t i = 0; i < m; ++i)\n    {   aduvw[0 * m + i]  = 0.0; // du[i]\n        aduvw[1 * m + i]  = 1.0; // dv[i]\n        aduvw[2 * m + i]  = 0.0; // dw[i]\n    }\n    //\n    // az\n    // use the fact that d_v[i] f_k (u, v, w) is zero when i != k\n    af.Forward(0, auvw);\n    az = af.Forward(1, aduvw);\n    CppAD::ADFun<double> g(auvw, az);\n    // -----------------------------------------------------------------------\n    // Record h (u, v, w) = sum f_i^(1) (u , v , w)\n    // -----------------------------------------------------------------------\n    //\n    // auvw\n    CppAD::Independent(auvw);\n    //\n    // aweight\n    CPPAD_TESTVECTOR( AD<double> ) aweight(m);\n    for(size_t i = 0; i < m; ++i)\n        aweight[i] = 1.0;\n    //\n    // az\n    CPPAD_TESTVECTOR( AD<double> ) adweight(3 * m);\n    af.Forward(0, auvw);\n    az = af.Reverse(1, aweight);\n    CppAD::ADFun<double> h(auvw, az);\n    // -----------------------------------------------------------------------\n    // check forward mode on g\n    // -----------------------------------------------------------------------\n    //\n    // z\n    z = g.Forward(0, uvw);\n    //\n    // ok\n    for(size_t i = 0; i < m; ++i)\n    {   double check_z  = - 1.0;\n        ok             &= NearEqual( z[i] ,  check_z,  eps99, eps99);\n    }\n    return ok;\n    // -----------------------------------------------------------------------\n    // check forward mode on h\n    // -----------------------------------------------------------------------\n    //\n    // z\n    z = h.Forward(0, uvw);\n    //\n    // ok\n    for(size_t i = 0; i < m; ++i)\n    {   double check_z  =  1.0;\n        ok             &= NearEqual( z[0 * m + i] ,  check_z,  eps99, eps99);\n        check_z         =  - 1.0;\n        ok             &= NearEqual( z[1 * m + i] ,  check_z,  eps99, eps99);\n        ok             &= NearEqual( z[2 * m + i] ,  check_z,  eps99, eps99);\n    }\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/atomic_four/vector/vector.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n// CPPAD_HAS_* defines\n# include <cppad/configure.hpp>\n\n// system include files used for I/O\n# include <iostream>\n\n// C style asserts\n# include <cassert>\n\n// for thread_alloc\n# include <cppad/utility/thread_alloc.hpp>\n\n// test runner\n# include <cppad/utility/test_boolofvoid.hpp>\n\n// BEGIN_SORT_THIS_LINE_PLUS_1\nextern bool add(void);\nextern bool div(void);\nextern bool hes_sparsity(void);\nextern bool jac_sparsity(void);\nextern bool mul(void);\nextern bool neg(void);\nextern bool rev_depend(void);\nextern bool sub(void);\n// END_SORT_THIS_LINE_MINUS_1\n\n// main program that runs all the tests\nint main(void)\n{   std::string group = \"example/atomic_four/vector\";\n    size_t      width = 20;\n    CppAD::test_boolofvoid Run(group, width);\n\n    // This line is used by test_one.sh\n\n    // BEGIN_SORT_THIS_LINE_PLUS_1\n    Run( add,                 \"add\"            );\n    Run( div,                 \"div\"            );\n    Run( hes_sparsity,        \"hes_sparsity\"   );\n    Run( jac_sparsity,        \"jac_sparsity\"   );\n    Run( mul,                 \"mul\"            );\n    Run( neg,                 \"neg\"            );\n    Run( rev_depend,          \"rev_depend\"     );\n    Run( sub,                 \"sub\"            );\n    // END_SORT_THIS_LINE_MINUS_1\n\n    // check for memory leak\n    bool memory_ok = CppAD::thread_alloc::free_all();\n    // print summary at end\n    bool ok = Run.summary(memory_ok);\n    //\n    return static_cast<int>( ! ok );\n}\n"
  },
  {
    "path": "example/atomic_three/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n#\n# BEGIN_SORT_THIS_LINE_PLUS_2\nSET(source_list\n    atomic_three.cpp\n    base2ad.cpp\n    dynamic.cpp\n    forward.cpp\n    get_started.cpp\n    hes_sparsity.cpp\n    jac_sparsity.cpp\n    mat_mul.cpp\n    norm_sq.cpp\n    reciprocal.cpp\n    rev_depend.cpp\n    reverse.cpp\n    tangent.cpp\n)\n# END_SORT_THIS_LINE_MINUS_2\n\nset_compile_flags(example_atomic_three \"${cppad_debug_which}\" \"${source_list}\" )\n#\nADD_EXECUTABLE(example_atomic_three EXCLUDE_FROM_ALL ${source_list})\n#\n# List of libraries to be linked into the specified target\nTARGET_LINK_LIBRARIES(example_atomic_three\n    ${cppad_lib}\n    ${colpack_libs}\n)\n#\n# check_example_atomic_three\nadd_check_executable(check_example atomic_three)\n"
  },
  {
    "path": "example/atomic_three/atomic_three.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_three.cpp}\n\natomic_three Examples and Tests Driver\n######################################\n\nRunning These Tests\n*******************\nAfter executing the :ref:`cmake-name` command\nform the :ref:`download@Distribution Directory`,\nyou can build and run these tests with the commands::\n\n    cd build\n    make check_example_atomic_three\n\nNote that your choice of :ref:`cmake@generator` may require using\nan different version of make; e.g., ``ninja`` .\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end atomic_three.cpp}\n-------------------------------------------------------------------------------\n*/\n// BEGIN C++\n\n// CPPAD_HAS_* defines\n# include <cppad/configure.hpp>\n\n// for thread_alloc\n# include <cppad/utility/thread_alloc.hpp>\n\n// test runner\n# include <cppad/utility/test_boolofvoid.hpp>\n\n// BEGIN_SORT_THIS_LINE_PLUS_1\nextern bool base2ad(void);\nextern bool dynamic(void);\nextern bool forward(void);\nextern bool get_started(void);\nextern bool hes_sparsity(void);\nextern bool jac_sparsity(void);\nextern bool mat_mul(void);\nextern bool norm_sq(void);\nextern bool reciprocal(void);\nextern bool rev_depend(void);\nextern bool reverse(void);\nextern bool tangent(void);\n// END_SORT_THIS_LINE_MINUS_1\n\n// main program that runs all the tests\nint main(void)\n{   std::string group = \"example/atomic\";\n    size_t      width = 20;\n    CppAD::test_boolofvoid Run(group, width);\n\n    // This line is used by test_one.sh\n\n    // BEGIN_SORT_THIS_LINE_PLUS_1\n    Run( base2ad,             \"base2ad\"        );\n    Run( dynamic,             \"dynamic\"        );\n    Run( forward,             \"forward\"        );\n    Run( get_started,         \"get_started\"    );\n    Run( hes_sparsity,        \"hes_sparsity\"   );\n    Run( jac_sparsity,        \"jac_sparsity\"   );\n    Run( mat_mul,             \"mat_mul\"        );\n    Run( norm_sq,             \"norm_sq\"        );\n    Run( reciprocal,          \"reciprocal\"     );\n    Run( rev_depend,          \"rev_depend\"     );\n    Run( reverse,             \"reverse\"        );\n    Run( tangent,             \"tangent\"        );\n    // END_SORT_THIS_LINE_MINUS_1\n\n    // check for memory leak\n    bool memory_ok = CppAD::thread_alloc::free_all();\n    // print summary at end\n    bool ok = Run.summary(memory_ok);\n    //\n    return static_cast<int>( ! ok );\n}\n// END C++\n"
  },
  {
    "path": "example/atomic_three/atomic_three.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin atomic_three_example}\n\nExample Defining Atomic Functions: Third Generation\n###################################################\n\nContents\n********\n{xrst_toc_table\n    example/atomic_three/get_started.cpp\n    example/atomic_three/norm_sq.cpp\n    example/atomic_three/tangent.cpp\n    example/atomic_three/base2ad.cpp\n    example/atomic_three/reciprocal.cpp\n    example/atomic_three/mat_mul.cpp\n}\n\n{xrst_end atomic_three_example}\n"
  },
  {
    "path": "example/atomic_three/base2ad.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin atomic_three_base2ad.cpp}\n\nbase2ad with Atomic Operations: Example and Test\n################################################\n\nSource Code\n***********\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end atomic_three_base2ad.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\nnamespace {          // isolate items below to this file\n//\n// abbreviations\nusing CppAD::AD;\nusing CppAD::vector;\n//\nclass atomic_base2ad : public CppAD::atomic_three<double> {\n//\npublic:\n    atomic_base2ad(const std::string& name) :\n    CppAD::atomic_three<double>(name)\n    { }\nprivate:\n    // ------------------------------------------------------------------------\n    // type\n    bool for_type(\n        const vector<double>&               parameter_x ,\n        const vector<CppAD::ad_type_enum>&  type_x      ,\n        vector<CppAD::ad_type_enum>&        type_y      ) override\n    {   assert( parameter_x.size() == type_x.size() );\n        bool ok = type_x.size() == 1; // n\n        ok     &= type_y.size() == 1; // m\n        if( ! ok )\n            return false;\n        type_y[0] = type_x[0];\n        return true;\n    }\n    // ----------------------------------------------------------------------\n    // forward mode\n    // ----------------------------------------------------------------------\n    template <class Scalar>\n    bool template_forward(\n        size_t                             p      ,\n        size_t                             q      ,\n        const vector<Scalar>&              tx     ,\n        vector<Scalar>&                    ty     )\n    {\n# ifndef NDEBUG\n        size_t n = tx.size() / (q + 1);\n        size_t m = ty.size() / (q + 1);\n# endif\n        assert( n == 1 );\n        assert( m == 1 );\n\n        // return flag\n        bool ok = q == 0;\n        if( ! ok )\n            return ok;\n\n        // Order zero forward mode.\n        // This case must always be implemented\n        // y^0 = g( x^0 ) = 1 / x^0\n        Scalar g = 1. / tx[0];\n        if( p <= 0 )\n            ty[0] = g;\n        return ok;\n    }\n    // forward mode routines called by ADFun<Base> objects\n    bool forward(\n        const vector<double>&              parameter_x ,\n        const vector<CppAD::ad_type_enum>& type_x      ,\n        size_t                             need_y      ,\n        size_t                             p           ,\n        size_t                             q           ,\n        const vector<double>&              tx          ,\n        vector<double>&                    ty          ) override\n    {   return template_forward(p, q, tx, ty);\n    }\n    // forward mode routines called by ADFun< AD<Base> , Base> objects\n    bool forward(\n        const vector< AD<double> >&        aparameter_x ,\n        const vector<CppAD::ad_type_enum>& type_x      ,\n        size_t                             need_y      ,\n        size_t                             p           ,\n        size_t                             q           ,\n        const vector< AD<double> >&        atx         ,\n        vector< AD<double> >&              aty         ) override\n    {   return template_forward(p, q, atx, aty);\n    }\n    // ----------------------------------------------------------------------\n    // reverse mode\n    // ----------------------------------------------------------------------\n    template <class Scalar>\n    bool template_reverse(\n        size_t                   q  ,\n        const vector<Scalar>&    tx ,\n        const vector<Scalar>&    ty ,\n        vector<Scalar>&          px ,\n        const vector<Scalar>&    py )\n    {\n# ifndef NDEBUG\n        size_t n = tx.size() / (q + 1);\n        size_t m = ty.size() / (q + 1);\n# endif\n        assert( n == 1 );\n        assert( m == 1 );\n\n        // return flag\n        bool ok = q == 0;\n        if( ! ok )\n            return ok;\n\n        // Order zero reverse mode.\n        // y^0 = g( x^0 ) = 1 / x^0\n        // y^1 = g'( x^0 ) * x^1 = - x^1 / (x^0 * x^0)\n        px[0] = - py[0] / ( tx[0] * tx[0] );\n        return ok;\n    }\n    // reverse mode routines called by ADFun<Base> objects\n    bool reverse(\n        const vector<double>&              parameter_x ,\n        const vector<CppAD::ad_type_enum>& type_x      ,\n        size_t                             q           ,\n        const vector<double>&              tx          ,\n        const vector<double>&              ty          ,\n        vector<double>&                    px          ,\n        const vector<double>&              py          ) override\n    {   return template_reverse(q, tx, ty, px, py);\n    }\n    // reverse mode routines called by ADFun<Base> objects\n    bool reverse(\n        const vector< AD<double> >&        aparameter_x ,\n        const vector<CppAD::ad_type_enum>& type_x       ,\n        size_t                             q            ,\n        const vector< AD<double> >&        atx          ,\n        const vector< AD<double> >&        aty          ,\n        vector< AD<double> >&              apx          ,\n        const vector< AD<double> >&        apy          ) override\n    {   return template_reverse(q, atx, aty, apx, apy);\n    }\n}; // End of atomic_base2ad class\n}  // End empty namespace\n\nbool base2ad(void)\n{   bool ok = true;\n    using CppAD::NearEqual;\n    double eps = 10. * CppAD::numeric_limits<double>::epsilon();\n    //\n    // Create the atomic base2ad object\n    atomic_base2ad afun(\"atomic_base2ad\");\n    //\n    // Create the function f(x) = 1 / g(x) = x\n    //\n    size_t n  = 1;\n    double x0 = 0.5;\n    vector< AD<double> > ax(n);\n    ax[0]     = x0;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(ax);\n\n    // range space vector\n    size_t m = 1;\n    vector< AD<double> > av(m);\n\n    // call atomic function and store g(x) in au[0]\n    vector< AD<double> > au(m);\n    afun(ax, au);        // u = 1 / x\n\n    // now use AD division to invert to invert the operation\n    av[0] = 1.0 / au[0]; // v = 1 / u = x\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f;\n    f.Dependent (ax, av);  // g(x) = x\n\n    // check function value\n    double check = x0;\n    ok &= NearEqual( Value(av[0]) , check,  eps, eps);\n\n    // check zero order forward mode\n    size_t q;\n    vector<double> x_q(n), v_q(m);\n    q      = 0;\n    x_q[0] = x0;\n    v_q    = f.Forward(q, x_q);\n    ok &= NearEqual(v_q[0] , check,  eps, eps);\n\n    // check first order reverse\n    vector<double> dw(n), w(m);\n    w[0]  = 1.0;\n    dw    = f.Reverse(q+1, w);\n    check = 1.0;\n    ok &= NearEqual(dw[0] , check,  eps, eps);\n\n    // create ag : x -> y\n    CppAD::ADFun< AD<double> , double > af ( f.base2ad() );\n\n    // check zero order forward mode\n    vector< AD<double> > ax_q(n), av_q(m);\n    q      = 0;\n    ax_q[0] = x0;\n    av_q    = af.Forward(q, ax_q);\n    check   = x0;\n    ok &= NearEqual( Value(av_q[0]) , check,  eps, eps);\n\n    // check first order reverse\n    vector< AD<double> > adw(n), aw(m);\n    aw[0]  = 1.0;\n    adw    = af.Reverse(q+1, aw);\n    check = 1.0;\n    ok &= NearEqual( Value(adw[0]) , check,  eps, eps);\n\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/atomic_three/dynamic.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin atomic_three_dynamic.cpp}\n\nAtomic Functions with Dynamic Parameters: Example and Test\n##########################################################\n\nPurpose\n*******\nThis example demonstrates using dynamic parameters with an\n:ref:`atomic_three-name` function.\n\nFunction\n********\nFor this example, the atomic function\n:math:`g : \\B{R}^3 \\rightarrow \\B{R}^3` is defined by\n:math:`g_0 (x) = x_0 * x_ 0`,\n:math:`g_1 (x) = x_0 * x_ 1`,\n:math:`g_2 (x) = x_1 * x_ 2`.\n\nStart Class Definition\n**********************\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <cppad/cppad.hpp>  // CppAD include file\nnamespace {                  // start empty namespace\nusing CppAD::vector;         // abbreviate CppAD::vector using vector\n// start definition of atomic derived class using atomic_three interface\nclass atomic_dynamic : public CppAD::atomic_three<double> {\n/* {xrst_code}\n{xrst_spell_on}\nConstructor\n***********\n{xrst_spell_off}\n{xrst_code cpp} */\npublic:\n    // can use const char* name when calling this constructor\n    atomic_dynamic(const std::string& name) : // can have more arguments\n    CppAD::atomic_three<double>(name)             // inform base class of name\n    { }\n\nprivate:\n/* {xrst_code}\n{xrst_spell_on}\nfor_type\n********\n{xrst_spell_off}\n{xrst_code cpp} */\n    // calculate type_y\n    bool for_type(\n        const vector<double>&               parameter_x ,\n        const vector<CppAD::ad_type_enum>&  type_x      ,\n        vector<CppAD::ad_type_enum>&        type_y      ) override\n    {  assert( parameter_x.size() == type_x.size() );\n        bool ok = type_x.size() == 3; // n\n        ok     &= type_y.size() == 3; // m\n        if( ! ok )\n            return false;\n        type_y[0] = type_x[0];\n        type_y[1] = std::max( type_x[0], type_x[1] );\n        type_y[2] = std::max( type_x[1], type_x[2] );\n        return true;\n    }\n/* {xrst_code}\n{xrst_spell_on}\nforward\n*******\n{xrst_spell_off}\n{xrst_code cpp} */\n    // forward mode routine called by CppAD\n    bool forward(\n        const vector<double>&               parameter_x  ,\n        const vector<CppAD::ad_type_enum>&  type_x       ,\n        size_t                              need_y       ,\n        size_t                              order_low    ,\n        size_t                              order_up     ,\n        const vector<double>&               taylor_x     ,\n        vector<double>&                     taylor_y     ) override\n    {\n# ifndef NDEBUG\n        size_t n = taylor_x.size() / (order_up + 1);\n        size_t m = taylor_y.size() / (order_up + 1);\n# endif\n        assert( n == 3 );\n        assert( m == 3 );\n        assert( order_low <= order_up );\n\n        // return flag\n        bool ok = order_up == 0;\n        if( ! ok )\n            return ok;\n\n        // Order zero forward mode.\n        // This case must always be implemented\n        if( need_y > size_t(CppAD::variable_enum) )\n        {  // g_0 = x_0 * x_0\n            taylor_y[0] = taylor_x[0] * taylor_x[0];\n            // g_1 = x_0 * x_1\n            taylor_y[1] = taylor_x[0] * taylor_x[1];\n            // g_2 = x_1 * x_2\n            taylor_y[2] = taylor_x[1] * taylor_x[2];\n        }\n        else\n        {  // This uses need_y to reduce amount of computation.\n            // It is probably faster, for this case, to ignore need_y.\n            vector<CppAD::ad_type_enum> type_y( taylor_y.size() );\n            for_type(taylor_x, type_x, type_y);\n            // g_0 = x_0 * x_0\n            if( size_t(type_y[0]) == need_y )\n                taylor_y[0] = taylor_x[0] * taylor_x[0];\n            // g_1 = x_0 * x_1\n            if( size_t(type_y[1]) == need_y )\n                taylor_y[1] = taylor_x[0] * taylor_x[1];\n            // g_2 = x_1 * x_2\n            if( size_t(type_y[2]) == need_y )\n                taylor_y[2] = taylor_x[1] * taylor_x[2];\n        }\n\n        return ok;\n    }\n/* {xrst_code}\n{xrst_spell_on}\nEnd Class Definition\n********************\n{xrst_spell_off}\n{xrst_code cpp} */\n}; // End of atomic_dynamic class\n}  // End empty namespace\n\n/* {xrst_code}\n{xrst_spell_on}\nUse Atomic Function\n*******************\n{xrst_spell_off}\n{xrst_code cpp} */\nbool dynamic(void)\n{  bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps = 10. * CppAD::numeric_limits<double>::epsilon();\n/* {xrst_code}\n{xrst_spell_on}\nConstructor\n===========\n{xrst_spell_off}\n{xrst_code cpp} */\n    // Create the atomic dynamic object corresponding to g(x)\n    atomic_dynamic afun(\"atomic_dynamic\");\n/* {xrst_code}\n{xrst_spell_on}\nRecording\n=========\n{xrst_spell_off}\n{xrst_code cpp} */\n    // Create the function f(u) = g(c, p, u) for this example.\n    //\n    // constant parameter\n    double c_0 = 2.0;\n    //\n    // independent dynamic parameter vector\n    size_t np = 1;\n    CPPAD_TESTVECTOR(double) p(np);\n    CPPAD_TESTVECTOR( AD<double> ) ap(np);\n    ap[0] = p[0] = 3.0;\n    //\n    // independent variable vector\n    size_t  nu  = 1;\n    double  u_0 = 0.5;\n    CPPAD_TESTVECTOR( AD<double> ) au(nu);\n    au[0] = u_0;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(au, ap);\n\n    // range space vector\n    size_t ny = 3;\n    CPPAD_TESTVECTOR( AD<double> ) ay(ny);\n\n    // call atomic function and store result in ay\n    // y = ( c * c, c * p, p * x )\n    CPPAD_TESTVECTOR( AD<double> ) ax(3);\n    ax[0] = c_0;   // x_0\n    ax[1] = ap[0]; // x_1\n    ax[2] = au[0]; // x_2\n    afun(ax, ay);\n\n    // check type of result\n    ok &= Constant( ay[0] );\n    ok &= Dynamic(  ay[1] );\n    ok &= Variable( ay[2] );\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f;\n    f.Dependent (au, ay);  // f(u) = (c * c, c * p, p * u)\n/* {xrst_code}\n{xrst_spell_on}\nforward\n=======\n{xrst_spell_off}\n{xrst_code cpp} */\n    // check function value\n    double check = c_0 * c_0;\n    ok &= NearEqual( Value(ay[0]) , check,  eps, eps);\n    check = c_0 * p[0];\n    ok &= NearEqual( Value(ay[1]) , check,  eps, eps);\n    check = p[0] * u_0;\n    ok &= NearEqual( Value(ay[2]) , check,  eps, eps);\n\n    // check zero order forward mode\n    size_t q;\n    CPPAD_TESTVECTOR( double ) u_q(nu), y_q(ny);\n    q      = 0;\n    u_q[0] = u_0;\n    y_q    = f.Forward(q, u_q);\n    check = c_0 * c_0;\n    ok    &= NearEqual(y_q[0] , check,  eps, eps);\n    check = c_0 * p[0];\n    ok    &= NearEqual(y_q[1] , check,  eps, eps);\n    check = p[0] * u_0;\n    ok    &= NearEqual(y_q[2] , check,  eps, eps);\n\n    // set new value for dynamic parameters\n    p[0]   = 2.0 * p[0];\n    f.new_dynamic(p);\n    y_q    = f.Forward(q, u_q);\n    check = c_0 * c_0;\n    ok    &= NearEqual(y_q[0] , check,  eps, eps);\n    check = c_0 * p[0];\n    ok    &= NearEqual(y_q[1] , check,  eps, eps);\n    check = p[0] * u_0;\n    ok    &= NearEqual(y_q[2] , check,  eps, eps);\n\n/* {xrst_code}\n{xrst_spell_on}\nReturn Test Result\n==================\n{xrst_spell_off}\n{xrst_code cpp} */\n    return ok;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end atomic_three_dynamic.cpp}\n*/\n"
  },
  {
    "path": "example/atomic_three/forward.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_three_forward.cpp}\n\nAtomic Functions and Forward Mode: Example and Test\n###################################################\n\nPurpose\n*******\nThis example demonstrates forward mode derivative calculation\nusing an :ref:`atomic_three-name` function.\n\nFunction\n********\nFor this example, the atomic function\n:math:`g : \\B{R}^3 \\rightarrow \\B{R}^2` is defined by\n\n.. math::\n\n    g(x) = \\left( \\begin{array}{c}\n        x_2 * x_2 \\\\\n        x_0 * x_1\n    \\end{array} \\right)\n\nJacobian\n********\nThe corresponding Jacobian is\n\n.. math::\n\n    g^{(1)} (x) = \\left( \\begin{array}{ccc}\n      0  &   0 & 2 x_2 \\\\\n    x_1  & x_0 & 0\n    \\end{array} \\right)\n\nHessian\n*******\nThe Hessians of the component functions are\n\n.. math::\n\n    g_0^{(2)} ( x ) = \\left( \\begin{array}{ccc}\n        0 & 0 & 0  \\\\\n        0 & 0 & 0  \\\\\n        0 & 0 & 2\n    \\end{array} \\right)\n    \\W{,}\n    g_1^{(2)} ( x ) = \\left( \\begin{array}{ccc}\n        0 & 1 & 0 \\\\\n        1 & 0 & 0 \\\\\n        0 & 0 & 0\n    \\end{array} \\right)\n\nStart Class Definition\n**********************\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <cppad/cppad.hpp>\nnamespace {          // begin empty namespace\nusing CppAD::vector; // abbreviate CppAD::vector using vector\n//\nclass atomic_forward : public CppAD::atomic_three<double> {\n/* {xrst_code}\n{xrst_spell_on}\nConstructor\n***********\n{xrst_spell_off}\n{xrst_code cpp} */\npublic:\n    atomic_forward(const std::string& name) :\n    CppAD::atomic_three<double>(name)\n    { }\nprivate:\n/* {xrst_code}\n{xrst_spell_on}\nfor_type\n********\n{xrst_spell_off}\n{xrst_code cpp} */\n    // calculate type_y\n    bool for_type(\n        const vector<double>&               parameter_x ,\n        const vector<CppAD::ad_type_enum>&  type_x      ,\n        vector<CppAD::ad_type_enum>&        type_y      ) override\n    {  assert( parameter_x.size() == type_x.size() );\n        bool ok = type_x.size() == 3; // n\n        ok     &= type_y.size() == 2; // m\n        if( ! ok )\n            return false;\n        type_y[0] = type_x[2];\n        type_y[1] = std::max(type_x[0], type_x[1]);\n        return true;\n    }\n/* {xrst_code}\n{xrst_spell_on}\nforward\n*******\n{xrst_spell_off}\n{xrst_code cpp} */\n    // forward mode routine called by CppAD\n    bool forward(\n        const vector<double>&              parameter_x  ,\n        const vector<CppAD::ad_type_enum>& type_x       ,\n        size_t                             need_y       ,\n        size_t                             order_low    ,\n        size_t                             order_up     ,\n        const vector<double>&              taylor_x     ,\n        vector<double>&                    taylor_y     ) override\n    {\n        size_t q1 = order_up + 1;\n# ifndef NDEBUG\n        size_t n = taylor_x.size() / q1;\n        size_t m = taylor_y.size() / q1;\n# endif\n        assert( n == 3 );\n        assert( m == 2 );\n        assert( order_low <= order_up );\n\n        // this example only implements up to second order forward mode\n        bool ok = order_up <=  2;\n        if( ! ok )\n            return ok;\n\n        // ------------------------------------------------------------------\n        // Zero forward mode.\n        // This case must always be implemented\n        // g(x) = [ x_2 * x_2 ]\n        //        [ x_0 * x_1 ]\n        // y^0  = f( x^0 )\n        if( order_low <= 0 )\n        {  // y_0^0 = x_2^0 * x_2^0\n            taylor_y[0*q1+0] = taylor_x[2*q1+0] * taylor_x[2*q1+0];\n            // y_1^0 = x_0^0 * x_1^0\n            taylor_y[1*q1+0] = taylor_x[0*q1+0] * taylor_x[1*q1+0];\n        }\n        if( order_up <=  0 )\n            return ok;\n        // ------------------------------------------------------------------\n        // First order forward mode.\n        // This case is needed if first order forward mode is used.\n        // g'(x) = [   0,   0, 2 * x_2 ]\n        //         [ x_1, x_0,       0 ]\n        // y^1 =  f'(x^0) * x^1\n        if( order_low <= 1 )\n        {  // y_0^1 = 2 * x_2^0 * x_2^1\n            taylor_y[0*q1+1] = 2.0 * taylor_x[2*q1+0] * taylor_x[2*q1+1];\n            // y_1^1 = x_1^0 * x_0^1 + x_0^0 * x_1^1\n            taylor_y[1*q1+1]  = taylor_x[1*q1+0] * taylor_x[0*q1+1];\n            taylor_y[1*q1+1] += taylor_x[0*q1+0] * taylor_x[1*q1+1];\n        }\n        if( order_up <=  1 )\n            return ok;\n        // ------------------------------------------------------------------\n        // Second order forward mode.\n        // This case is needed if second order forward mode is used.\n        // g'(x) = [   0,   0, 2 x_2 ]\n        //         [ x_1, x_0,     0 ]\n        //\n        //            [ 0 , 0 , 0 ]                  [ 0 , 1 , 0 ]\n        // g_0''(x) = [ 0 , 0 , 0 ]  g_1^{(2)} (x) = [ 1 , 0 , 0 ]\n        //            [ 0 , 0 , 2 ]                  [ 0 , 0 , 0 ]\n        //\n        //  y_0^2 = x^1 * g_0''( x^0 ) x^1 / 2! + g_0'( x^0 ) x^2\n        //        = ( x_2^1 * 2.0 * x_2^1 ) / 2!\n        //        + 2.0 * x_2^0 * x_2^2\n        taylor_y[0*q1+2]  = taylor_x[2*q1+1] * taylor_x[2*q1+1];\n        taylor_y[0*q1+2] += 2.0 * taylor_x[2*q1+0] * taylor_x[2*q1+2];\n        //\n        //  y_1^2 = x^1 * g_1''( x^0 ) x^1 / 2! + g_1'( x^0 ) x^2\n        //        = ( x_1^1 * x_0^1 + x_0^1 * x_1^1) / 2\n        //        + x_1^0 * x_0^2 + x_0^0 + x_1^2\n        taylor_y[1*q1+2]  = taylor_x[1*q1+1] * taylor_x[0*q1+1];\n        taylor_y[1*q1+2] += taylor_x[1*q1+0] * taylor_x[0*q1+2];\n        taylor_y[1*q1+2] += taylor_x[0*q1+0] * taylor_x[1*q1+2];\n        // ------------------------------------------------------------------\n        return ok;\n    }\n};\n}  // End empty namespace\n/* {xrst_code}\n{xrst_spell_on}\nUse Atomic Function\n*******************\n{xrst_spell_off}\n{xrst_code cpp} */\nbool forward(void)\n{  bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps = 10. * CppAD::numeric_limits<double>::epsilon();\n    //\n    // Create the atomic_forward object corresponding to g(x)\n    atomic_forward afun(\"atomic_forward\");\n    //\n    // Create the function f(u) = g(u) for this example.\n    //\n    // domain space vector\n    size_t n  = 3;\n    double u_0 = 1.00;\n    double u_1 = 2.00;\n    double u_2 = 3.00;\n    vector< AD<double> > au(n);\n    au[0] = u_0;\n    au[1] = u_1;\n    au[2] = u_2;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(au);\n\n    // range space vector\n    size_t m = 2;\n    vector< AD<double> > ay(m);\n\n    // call atomic function\n    vector< AD<double> > ax = au;\n    afun(ax, ay);\n\n    // create f: u -> y and stop tape recording\n    CppAD::ADFun<double> f;\n    f.Dependent (au, ay);  // y = f(u)\n    //\n    // check function value\n    double check = u_2 * u_2;\n    ok &= NearEqual( Value(ay[0]) , check,  eps, eps);\n    check = u_0 * u_1;\n    ok &= NearEqual( Value(ay[1]) , check,  eps, eps);\n\n    // --------------------------------------------------------------------\n    // zero order forward\n    //\n    vector<double> u0(n), y0(m);\n    u0[0] = u_0;\n    u0[1] = u_1;\n    u0[2] = u_2;\n    y0   = f.Forward(0, u0);\n    check = u_2 * u_2;\n    ok &= NearEqual(y0[0] , check,  eps, eps);\n    check = u_0 * u_1;\n    ok &= NearEqual(y0[1] , check,  eps, eps);\n    // --------------------------------------------------------------------\n    // first order forward\n    //\n    // value of Jacobian of f\n    double check_jac[] = {\n        0.0, 0.0, 2.0 * u_2,\n        u_1, u_0,       0.0\n    };\n    vector<double> u1(n), y1(m);\n    // check first order forward mode\n    for(size_t j = 0; j < n; j++)\n        u1[j] = 0.0;\n    for(size_t j = 0; j < n; j++)\n    {  // compute partial in j-th component direction\n        u1[j] = 1.0;\n        y1    = f.Forward(1, u1);\n        u1[j] = 0.0;\n        // check this direction\n        for(size_t i = 0; i < m; i++)\n            ok &= NearEqual(y1[i], check_jac[i * n + j], eps, eps);\n    }\n    // --------------------------------------------------------------------\n    // second order forward\n    //\n    // value of Hessian of g_0\n    double check_hes_0[] = {\n        0.0, 0.0, 0.0,\n        0.0, 0.0, 0.0,\n        0.0, 0.0, 2.0\n    };\n    //\n    // value of Hessian of g_1\n    double check_hes_1[] = {\n        0.0, 1.0, 0.0,\n        1.0, 0.0, 0.0,\n        0.0, 0.0, 0.0\n    };\n    vector<double> u2(n), y2(m);\n    for(size_t j = 0; j < n; j++)\n        u2[j] = 0.0;\n    // compute diagonal elements of the Hessian\n    for(size_t j = 0; j < n; j++)\n    {  // first order forward in j-th direction\n        u1[j] = 1.0;\n        f.Forward(1, u1);\n        y2 = f.Forward(2, u2);\n        // check this element of Hessian diagonal\n        ok &= NearEqual(y2[0], check_hes_0[j * n + j] / 2.0, eps, eps);\n        ok &= NearEqual(y2[1], check_hes_1[j * n + j] / 2.0, eps, eps);\n        //\n        for(size_t k = 0; k < n; k++) if( k != j )\n        {  u1[k] = 1.0;\n            f.Forward(1, u1);\n            y2 = f.Forward(2, u2);\n            //\n            // y2 = (H_jj + H_kk + H_jk + H_kj) / 2.0\n            // y2 = (H_jj + H_kk) / 2.0 + H_jk\n            //\n            double H_jj = check_hes_0[j * n + j];\n            double H_kk = check_hes_0[k * n + k];\n            double H_jk = y2[0] - (H_kk + H_jj) / 2.0;\n            ok &= NearEqual(H_jk, check_hes_0[j * n + k], eps, eps);\n            //\n            H_jj = check_hes_1[j * n + j];\n            H_kk = check_hes_1[k * n + k];\n            H_jk = y2[1] - (H_kk + H_jj) / 2.0;\n            ok &= NearEqual(H_jk, check_hes_1[j * n + k], eps, eps);\n            //\n            u1[k] = 0.0;\n        }\n        u1[j] = 0.0;\n    }\n    // --------------------------------------------------------------------\n    return ok;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end atomic_three_forward.cpp}\n*/\n"
  },
  {
    "path": "example/atomic_three/get_started.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin atomic_three_get_started.cpp}\n\nGetting Started with Atomic Functions: Example and Test\n#######################################################\n\nPurpose\n*******\nThis example demonstrates the minimal amount of information\nnecessary for a :ref:`atomic_three-name` function.\n\nStart Class Definition\n**********************\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <cppad/cppad.hpp>  // CppAD include file\nnamespace {                  // start empty namespace\nusing CppAD::vector;         // abbreviate CppAD::vector using vector\n// start definition of atomic derived class using atomic_three interface\nclass atomic_get_started : public CppAD::atomic_three<double> {\n/* {xrst_code}\n{xrst_spell_on}\nConstructor\n***********\n{xrst_spell_off}\n{xrst_code cpp} */\npublic:\n    // can use const char* name when calling this constructor\n    atomic_get_started(const std::string& name) : // can have more arguments\n    CppAD::atomic_three<double>(name)             // inform base class of name\n    { }\n\nprivate:\n/* {xrst_code}\n{xrst_spell_on}\nfor_type\n********\n{xrst_spell_off}\n{xrst_code cpp} */\n    // calculate type_y\n    bool for_type(\n        const vector<double>&               parameter_x ,\n        const vector<CppAD::ad_type_enum>&  type_x      ,\n        vector<CppAD::ad_type_enum>&        type_y      ) override\n    {  assert( parameter_x.size() == type_x.size() );\n        bool ok = type_x.size() == 1; // n\n        ok     &= type_y.size() == 1; // m\n        if( ! ok )\n            return false;\n        type_y[0] = type_x[0];\n        return true;\n    }\n/* {xrst_code}\n{xrst_spell_on}\nforward\n*******\n{xrst_spell_off}\n{xrst_code cpp} */\n    // forward mode routine called by CppAD\n    bool forward(\n        const vector<double>&               parameter_x  ,\n        const vector<CppAD::ad_type_enum>&  type_x       ,\n        size_t                              need_y       ,\n        size_t                              order_low    ,\n        size_t                              order_up     ,\n        const vector<double>&               taylor_x     ,\n        vector<double>&                     taylor_y     ) override\n    {\n# ifndef NDEBUG\n        size_t n = taylor_x.size() / (order_up + 1);\n        size_t m = taylor_y.size() / (order_up + 1);\n# endif\n        assert( n == 1 );\n        assert( m == 1 );\n        assert( order_low <= order_up );\n\n        // return flag\n        bool ok = order_up == 0;\n        if( ! ok )\n            return ok;\n\n        // Order zero forward mode.\n        // This case must always be implemented\n        // y^0 = g( x^0 ) = 1 / x^0\n        taylor_y[0] = 1. / taylor_x[0];\n        //\n        return ok;\n    }\n/* {xrst_code}\n{xrst_spell_on}\nEnd Class Definition\n********************\n{xrst_spell_off}\n{xrst_code cpp} */\n}; // End of atomic_get_started class\n}  // End empty namespace\n\n/* {xrst_code}\n{xrst_spell_on}\nUse Atomic Function\n*******************\n{xrst_spell_off}\n{xrst_code cpp} */\nbool get_started(void)\n{  bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps = 10. * CppAD::numeric_limits<double>::epsilon();\n/* {xrst_code}\n{xrst_spell_on}\nConstructor\n===========\n{xrst_spell_off}\n{xrst_code cpp} */\n    // Create the atomic get_started object corresponding to g(x)\n    atomic_get_started afun(\"atomic_get_started\");\n/* {xrst_code}\n{xrst_spell_on}\nRecording\n=========\n{xrst_spell_off}\n{xrst_code cpp} */\n    // Create the function f(x) which is equal to g(x) for this example.\n    //\n    // domain space vector\n    size_t  n  = 1;\n    double  x0 = 0.5;\n    CPPAD_TESTVECTOR( AD<double> ) ax(n);\n    ax[0]     = x0;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(ax);\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR( AD<double> ) ay(m);\n\n    // call atomic function and store result in au[0]\n    // u = 1 / x\n    CPPAD_TESTVECTOR( AD<double> ) au(m);\n    afun(ax, au);\n\n    // now use AD division to invert to invert the operation\n    ay[0] = 1.0 / au[0]; // y = 1 / u = x\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f;\n    f.Dependent (ax, ay);  // f(x) = x\n/* {xrst_code}\n{xrst_spell_on}\nforward\n=======\n{xrst_spell_off}\n{xrst_code cpp} */\n    // check function value\n    double check = x0;\n    ok &= NearEqual( Value(ay[0]) , check,  eps, eps);\n\n    // check zero order forward mode\n    size_t q;\n    CPPAD_TESTVECTOR( double ) x_q(n), y_q(m);\n    q      = 0;\n    x_q[0] = x0;\n    y_q    = f.Forward(q, x_q);\n    ok    &= NearEqual(y_q[0] , check,  eps, eps);\n\n/* {xrst_code}\n{xrst_spell_on}\nReturn Test Result\n==================\n{xrst_spell_off}\n{xrst_code cpp} */\n    return ok;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end atomic_three_get_started.cpp}\n*/\n"
  },
  {
    "path": "example/atomic_three/hes_sparsity.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_three_hes_sparsity.cpp}\n\nAtomic Forward Hessian Sparsity: Example and Test\n#################################################\n\nPurpose\n*******\nThis example demonstrates calculation of the Hessian sparsity pattern\nfor an atomic operation.\n\nFunction\n********\nFor this example, the atomic function\n:math:`g : \\B{R}^3 \\rightarrow \\B{R}^2` is defined by\n\n.. math::\n\n    g( x ) = \\left( \\begin{array}{c}\n        x_2 * x_2 \\\\\n        x_0 * x_1\n    \\end{array} \\right)\n\nJacobian\n********\nThe corresponding Jacobian is\n\n.. math::\n\n    g^{(1)} (x) = \\left( \\begin{array}{ccc}\n      0  &   0 & 2 x_2 \\\\\n    x_1  & x_0 & 0\n    \\end{array} \\right)\n\nHessians\n********\nThe Hessians of the component functions are\n\n.. math::\n\n    g_0^{(2)} ( x ) = \\left( \\begin{array}{ccc}\n        0 & 0 & 0  \\\\\n        0 & 0 & 0  \\\\\n        0 & 0 & 2\n    \\end{array} \\right)\n    \\W{,}\n    g_1^{(2)} ( x ) = \\left( \\begin{array}{ccc}\n        0 & 1 & 0 \\\\\n        1 & 0 & 0 \\\\\n        0 & 0 & 0\n    \\end{array} \\right)\n\nStart Class Definition\n**********************\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <cppad/cppad.hpp>\nnamespace {          // begin empty namespace\nusing CppAD::vector; // abbreviate CppAD::vector as vector\n//\nclass atomic_hes_sparsity : public CppAD::atomic_three<double> {\n/* {xrst_code}\n{xrst_spell_on}\nConstructor\n***********\n{xrst_spell_off}\n{xrst_code cpp} */\npublic:\n    atomic_hes_sparsity(const std::string& name) :\n    CppAD::atomic_three<double>(name)\n    { }\nprivate:\n/* {xrst_code}\n{xrst_spell_on}\nfor_type\n********\n{xrst_spell_off}\n{xrst_code cpp} */\n    // calculate type_y\n    bool for_type(\n        const vector<double>&               parameter_x ,\n        const vector<CppAD::ad_type_enum>&  type_x      ,\n        vector<CppAD::ad_type_enum>&        type_y      ) override\n    {  assert( parameter_x.size() == type_x.size() );\n        bool ok = type_x.size() == 3; // n\n        ok     &= type_y.size() == 2; // m\n        if( ! ok )\n            return false;\n\n        type_y[0]  = type_x[2];\n        type_y[1] = std::max(type_x[0], type_x[1]);\n        return true;\n    }\n/* {xrst_code}\n{xrst_spell_on}\nforward\n*******\n{xrst_spell_off}\n{xrst_code cpp} */\n    // forward mode routine called by CppAD\n    bool forward(\n        const vector<double>&              parameter_x  ,\n        const vector<CppAD::ad_type_enum>& type_x       ,\n        size_t                             need_y       ,\n        size_t                             order_low    ,\n        size_t                             order_up     ,\n        const vector<double>&              taylor_x     ,\n        vector<double>&                    taylor_y     ) override\n    {\n# ifndef NDEBUG\n        size_t n = taylor_x.size() / (order_up + 1);\n        size_t m = taylor_y.size() / (order_up + 1);\n# endif\n        assert( n == 3 );\n        assert( m == 2 );\n        assert( order_low <= order_up );\n\n        // return flag\n        bool ok = order_up == 0;\n        if( ! ok )\n            return ok;\n\n        // Order zero forward mode must always be implemented\n        taylor_y[0] = taylor_x[2] * taylor_x[2];\n        taylor_y[1] = taylor_x[0] * taylor_x[1];\n\n        return ok;\n    }\n/* {xrst_code}\n{xrst_spell_on}\njac_sparsity\n************\n{xrst_spell_off}\n{xrst_code cpp} */\n    // Jacobian sparsity routine called by CppAD\n    bool jac_sparsity(\n        const vector<double>&               parameter_x ,\n        const vector<CppAD::ad_type_enum>&  type_x      ,\n        bool                                dependency  ,\n        const vector<bool>&                 select_x    ,\n        const vector<bool>&                 select_y    ,\n        CppAD::sparse_rc< vector<size_t> >& pattern_out ) override\n    {\n        size_t n = select_x.size();\n        size_t m = select_y.size();\n        assert( n == 3 );\n        assert( m == 2 );\n        assert( parameter_x.size() == n );\n\n        // count number of non-zeros in sparsity pattern\n        size_t nnz = 0;\n        // row 0\n        if( select_y[0] && select_x[2] )\n            ++nnz;\n        // row 1\n        if( select_y[1] )\n        {  // column 0\n            if( select_x[0] )\n                ++nnz;\n            // column 1\n            if( select_x[1] )\n                ++nnz;\n        }\n\n        // size of pattern_out\n        size_t nr = m;\n        size_t nc = n;\n        pattern_out.resize(nr, nc, nnz);\n        //\n        // set the values in pattern_out using index k\n        size_t k = 0;\n        //\n        // y_0 depends and has possibly non-zeron partial w.r.t x_2\n        if( select_y[0] && select_x[2] )\n            pattern_out.set(k++, 0, 2);\n        if( select_y[1] )\n        {  // y_1 depends and has possibly non-zero partial w.r.t x_0\n            if( select_x[0] )\n                pattern_out.set(k++, 1, 0);\n            // y_1 depends and has possibly non-zero partial w.r.t x_1\n            if( select_x[1] )\n                pattern_out.set(k++, 1, 1);\n        }\n        assert( k == nnz );\n        //\n        return true;\n    }\n/* {xrst_code}\n{xrst_spell_on}\nhes_sparsity\n************\n{xrst_spell_off}\n{xrst_code cpp} */\n    // Hessian sparsity routine called by CppAD\n    bool hes_sparsity(\n        const vector<double>&               parameter_x ,\n        const vector<CppAD::ad_type_enum>&  type_x      ,\n        const vector<bool>&                 select_x    ,\n        const vector<bool>&                 select_y    ,\n        CppAD::sparse_rc< vector<size_t> >& pattern_out ) override\n    {  assert( parameter_x.size() == select_x.size() );\n        assert( select_y.size() == 2 );\n        size_t n = select_x.size();\n        assert( n == 3 );\n        //\n        //            [ 0 , 0 , 0 ]               [ 0 , 1 , 0 ]\n        // g_0''(x) = [ 0 , 0 , 0 ]  g_1^'' (x) = [ 1 , 0 , 0 ]\n        //            [ 0 , 0 , 2 ]               [ 0 , 0 , 0 ]\n        //\n        //\n        // count number of non-zeros in sparsity pattern\n        size_t nnz = 0;\n        if( select_y[0] )\n        {  if( select_x[2] )\n                ++nnz;\n        }\n        if( select_y[1] )\n        {  if( select_x[0] && select_x[1] )\n                nnz += 2;\n        }\n        //\n        // size of pattern_out\n        size_t nr = n;\n        size_t nc = n;\n        pattern_out.resize(nr, nc, nnz);\n        //\n        // set the values in pattern_out using index k\n        size_t k = 0;\n        //\n        // y[1] has possible non-zero second partial w.r.t. x[0], x[1]\n        if( select_y[1] )\n        {  if( select_x[0] && select_x[1] )\n            {  pattern_out.set(k++, 0, 1);\n                pattern_out.set(k++, 1, 0);\n            }\n        }\n        //\n        // y[0] has possibly non-zero second partial w.r.t x[2], x[2]\n        if( select_y[0] )\n        {  if( select_x[2] )\n                pattern_out.set(k++, 2, 2);\n        }\n        return true;\n    }\n}; // End of atomic_for_sparse_hes class\n\n/* {xrst_code}\n{xrst_spell_on}\nUse Atomic Function\n*******************\n{xrst_spell_off}\n{xrst_code cpp} */\nbool use_hes_sparsity(bool u_1_variable, bool forward)\n{  bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps = 10. * CppAD::numeric_limits<double>::epsilon();\n    //\n    // Create the atomic_hes_sparsity object corresponding to g(x)\n    atomic_hes_sparsity afun(\"atomic_hes_sparsity\");\n    //\n    // Create the function f(u) = g(u) for this example.\n    //\n    // domain space vector\n    size_t n  = 3;\n    double u_0 = 1.00;\n    double u_1 = 2.00;\n    double u_2 = 3.00;\n    vector< AD<double> > au(n);\n    au[0] = u_0;\n    au[1] = u_1;\n    au[2] = u_2;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(au);\n\n    // range space vector\n    size_t m = 2;\n    vector< AD<double> > ay(m);\n\n    // call atomic function\n    vector< AD<double> > ax(n);\n    ax[0] = au[0];\n    ax[2] = au[2];\n    if( u_1_variable )\n    {  ok   &= Variable( au[1] );\n        ax[1] = au[1];\n    }\n    else\n    {  AD<double> ap = u_1;\n        ok   &= Parameter(ap);\n        ok   &= ap == au[1];\n        ax[1] = u_1;\n    }\n    // u_1_variable true:  y = [ u_2 * u_2 ,  u_0 * u_1 ]^T\n    // u_1_variable false: y = [ u_2 * u_2 ,  u_0 * p   ]^T\n    afun(ax, ay);\n\n    // create f: u -> y and stop tape recording\n    CppAD::ADFun<double> f;\n    f.Dependent (au, ay);  // f(u) = y\n    //\n    // check function value\n    double check = u_2 * u_2;\n    ok &= NearEqual( Value(ay[0]) , check,  eps, eps);\n    check = u_0 * u_1;\n    ok &= NearEqual( Value(ay[1]) , check,  eps, eps);\n\n    // check zero order forward mode\n    size_t q;\n    vector<double> xq(n), yq(m);\n    q     = 0;\n    xq[0] = u_0;\n    xq[1] = u_1;\n    xq[2] = u_2;\n    yq    = f.Forward(q, xq);\n    check = u_2 * u_2;\n    ok &= NearEqual(yq[0] , check,  eps, eps);\n    check = u_0 * u_1;\n    ok &= NearEqual(yq[1] , check,  eps, eps);\n\n    // select_u\n    CPPAD_TESTVECTOR(bool) select_u(n);\n    for(size_t j = 0; j < n; j++)\n        select_u[j] = true;\n\n    // select_y\n    CPPAD_TESTVECTOR(bool) select_y(m);\n    for(size_t i = 0; i < m; i++)\n        select_y[i] = true;\n\n    // for_hes_sparsity\n    bool internal_bool = false;\n    CppAD::sparse_rc< CPPAD_TESTVECTOR(size_t) > pattern_out;\n    if( forward )\n    {  f.for_hes_sparsity(\n            select_u, select_y, internal_bool, pattern_out\n        );\n    }\n    else\n    {  // pattern for indepentity matrix\n        CppAD::sparse_rc< CPPAD_TESTVECTOR(size_t) > pattern_in(n, n, n);\n        bool transpose  = false;\n        bool dependency = false;\n        for(size_t k = 0; k < n; ++k)\n            pattern_in.set(k, k, k);\n        // for_jac_sparsity (ignore pattern_out)\n        f.for_jac_sparsity(\n            pattern_in, transpose, dependency, internal_bool, pattern_out\n        );\n        // rev_jac_sparsity\n        f.rev_hes_sparsity(\n            select_y, transpose, internal_bool, pattern_out\n        );\n    }\n    const CPPAD_TESTVECTOR(size_t)& row = pattern_out.row();\n    const CPPAD_TESTVECTOR(size_t)& col = pattern_out.col();\n    CPPAD_TESTVECTOR(size_t) row_major  = pattern_out.row_major();\n    //\n    // in row major order first element  has index (0, 1) and second has\n    // index (1, 0).  These are only included when u_1 is a variable.\n    size_t k = 0, r, c;\n    if( u_1_variable )\n    {  r   = row[ row_major[k] ];\n        c   = col[ row_major[k] ];\n        ok &= r == 0 && c == 1;\n        ++k;\n        r   = row[ row_major[k] ];\n        c   = col[ row_major[k] ];\n        ok &= r == 1 && c == 0;\n        ++k;\n    }\n    // in row major order next element, in lower triangle of Hessians,\n    // has index (2, 2). This element is always included\n    r   = row[ row_major[k] ];\n    c   = col[ row_major[k] ];\n    ok &= r == 2 && c == 2;\n    //\n    // k + 1 should be the number of values in sparsity pattern\n    ok &= k + 1 == pattern_out.nnz();\n    //\n    return ok;\n}\n}  // End empty namespace\n/* {xrst_code}\n{xrst_spell_on}\nTest with u_1 Both a Variable and a Parameter\n*********************************************\n{xrst_spell_off}\n{xrst_code cpp} */\nbool hes_sparsity(void)\n{  bool ok = true;\n    //\n    bool u_1_variable = true;\n    bool forward      = true;\n    ok               &= use_hes_sparsity(u_1_variable, forward);\n    //\n    u_1_variable      = true;\n    forward           = false;\n    ok               &= use_hes_sparsity(u_1_variable, forward);\n    //\n    u_1_variable      = false;\n    forward           = true;\n    ok               &= use_hes_sparsity(u_1_variable, forward);\n    //\n    u_1_variable      = false;\n    forward           = false;\n    ok               &= use_hes_sparsity(u_1_variable, forward);\n    //\n    return ok;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end atomic_three_hes_sparsity.cpp}\n*/\n"
  },
  {
    "path": "example/atomic_three/jac_sparsity.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_three_jac_sparsity.cpp}\n\nAtomic Function Jacobian Sparsity: Example and Test\n###################################################\n\nPurpose\n*******\nThis example demonstrates calculation of a Jacobian sparsity pattern\nusing an atomic operation.\n\nFunction\n********\nFor this example, the atomic function\n:math:`g : \\B{R}^3 \\rightarrow \\B{R}^2` is defined by\n\n.. math::\n\n    g(x) = \\left( \\begin{array}{c}\n        x_2 * x_2 \\\\\n        x_0 * x_1\n    \\end{array} \\right)\n\nJacobian\n********\nThe corresponding Jacobian is\n\n.. math::\n\n    g^{(1)} (x) = \\left( \\begin{array}{ccc}\n      0  &   0 & 2 x_2 \\\\\n    x_1  & x_0 & 0\n    \\end{array} \\right)\n\nStart Class Definition\n**********************\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <cppad/cppad.hpp>\nnamespace {          // begin empty namespace\nusing CppAD::vector; // abbreviate CppAD::vector as vector\n//\nclass atomic_jac_sparsity : public CppAD::atomic_three<double> {\n/* {xrst_code}\n{xrst_spell_on}\nConstructor\n***********\n{xrst_spell_off}\n{xrst_code cpp} */\npublic:\n    atomic_jac_sparsity(const std::string& name) :\n    CppAD::atomic_three<double>(name)\n    { }\nprivate:\n/* {xrst_code}\n{xrst_spell_on}\nfor_type\n********\n{xrst_spell_off}\n{xrst_code cpp} */\n    // calculate type_y\n    bool for_type(\n        const vector<double>&               parameter_x ,\n        const vector<CppAD::ad_type_enum>&  type_x      ,\n        vector<CppAD::ad_type_enum>&        type_y      ) override\n    {  assert( parameter_x.size() == type_x.size() );\n        bool ok = type_x.size() == 3; // n\n        ok     &= type_y.size() == 2; // m\n        if( ! ok )\n            return false;\n\n        type_y[0]  = type_x[2];\n        type_y[1] = std::max(type_x[0], type_x[1]);\n        return true;\n    }\n/* {xrst_code}\n{xrst_spell_on}\nforward\n*******\n{xrst_spell_off}\n{xrst_code cpp} */\n    // forward mode routine called by CppAD\n    bool forward(\n        const vector<double>&              parameter_x  ,\n        const vector<CppAD::ad_type_enum>& type_x       ,\n        size_t                             need_y       ,\n        size_t                             order_low    ,\n        size_t                             order_up     ,\n        const vector<double>&              taylor_x     ,\n        vector<double>&                    taylor_y     ) override\n    {\n# ifndef NDEBUG\n        size_t n = taylor_x.size() / (order_up + 1);\n        size_t m = taylor_y.size() / (order_up + 1);\n# endif\n        assert( n == 3 );\n        assert( m == 2 );\n        assert( order_low <= order_up );\n\n        // return flag\n        bool ok = order_up == 0;\n        if( ! ok )\n            return ok;\n\n        // Order zero forward mode must always be implemented\n        taylor_y[0] = taylor_x[2] * taylor_x[2];\n        taylor_y[1] = taylor_x[0] * taylor_x[1];\n\n        return ok;\n    }\n/* {xrst_code}\n{xrst_spell_on}\njac_sparsity\n************\n{xrst_spell_off}\n{xrst_code cpp} */\n    // Jacobian sparsity routine called by CppAD\n    bool jac_sparsity(\n        const vector<double>&               parameter_x ,\n        const vector<CppAD::ad_type_enum>&  type_x      ,\n        bool                                dependency  ,\n        const vector<bool>&                 select_x    ,\n        const vector<bool>&                 select_y    ,\n        CppAD::sparse_rc< vector<size_t> >& pattern_out ) override\n    {\n        size_t n = select_x.size();\n        size_t m = select_y.size();\n        assert( parameter_x.size() == n );\n        assert( n == 3 );\n        assert( m == 2 );\n\n        // count number of non-zeros in sparsity pattern\n        size_t nnz = 0;\n        // row 0\n        if( select_y[0] && select_x[2] )\n            ++nnz;\n        // row 1\n        if( select_y[1] )\n        {  // column 0\n            if( select_x[0] )\n                ++nnz;\n            // column 1\n            if( select_x[1] )\n                ++nnz;\n        }\n\n        // size of pattern_out\n        size_t nr = m;\n        size_t nc = n;\n        pattern_out.resize(nr, nc, nnz);\n\n        // set the values in pattern_out using index k\n        size_t k = 0;\n\n        // y_0 depends and has possibly non-zeron partial w.r.t x_2\n        if( select_y[0] && select_x[2] )\n            pattern_out.set(k++, 0, 2);\n        if( select_y[1] )\n        {  // y_1 depends and has possibly non-zero partial w.r.t x_0\n            if( select_x[0] )\n                pattern_out.set(k++, 1, 0);\n            // y_1 depends and has possibly non-zero partial w.r.t x_1\n            if( select_x[1] )\n                pattern_out.set(k++, 1, 1);\n        }\n        assert( k == nnz );\n        //\n        return true;\n    }\n}; // End of atomic_three_jac_sparsity class\n\n/* {xrst_code}\n{xrst_spell_on}\nUse Atomic Function\n*******************\n{xrst_spell_off}\n{xrst_code cpp} */\nbool use_jac_sparsity(bool x_1_variable, bool forward)\n{  bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps = 10. * CppAD::numeric_limits<double>::epsilon();\n    //\n    // Create the atomic_jac_sparsity object corresponding to g(x)\n    atomic_jac_sparsity afun(\"atomic_jac_sparsity\");\n    //\n    // Create the function f(u) = g(u) for this example.\n    //\n    // domain space vector\n    size_t n  = 3;\n    double u_0 = 1.00;\n    double u_1 = 2.00;\n    double u_2 = 3.00;\n    vector< AD<double> > au(n);\n    au[0] = u_0;\n    au[1] = u_1;\n    au[2] = u_2;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(au);\n\n    // range space vector\n    size_t m = 2;\n    vector< AD<double> > ay(m);\n\n    // call atomic function\n    vector< AD<double> > ax(n);\n    ax[0] = au[0];\n    ax[2] = au[2];\n    if( x_1_variable )\n    {  ok   &= Variable( au[1] );\n        ax[1] = au[1];\n    }\n    else\n    {  AD<double> ap = u_1;\n        ok   &= Parameter(ap);\n        ok   &= ap == au[1];\n        ax[1] = u_1;\n    }\n    // x_1_variable true:  y = [ u_2 * u_2 ,  u_0 * u_1 ]^T\n    // x_1_variable false: y = [ u_2 * u_2 ,  u_0 * p   ]^T\n    afun(ax, ay);\n\n    // create f: u -> y and stop tape recording\n    CppAD::ADFun<double> f;\n    f.Dependent (au, ay);  // f(u) = y\n    //\n    // check function value\n    double check = u_2 * u_2;\n    ok &= NearEqual( Value(ay[0]) , check,  eps, eps);\n    check = u_0 * u_1;\n    ok &= NearEqual( Value(ay[1]) , check,  eps, eps);\n\n    // check zero order forward mode\n    size_t q;\n    vector<double> xq(n), yq(m);\n    q     = 0;\n    xq[0] = u_0;\n    xq[1] = u_1;\n    xq[2] = u_2;\n    yq    = f.Forward(q, xq);\n    check = u_2 * u_2;\n    ok &= NearEqual(yq[0] , check,  eps, eps);\n    check = u_0 * u_1;\n    ok &= NearEqual(yq[1] , check,  eps, eps);\n\n    // sparsity pattern for identity matrix\n    size_t nnz;\n    if( forward )\n        nnz = n;\n    else\n        nnz = m;\n    CppAD::sparse_rc< CPPAD_TESTVECTOR(size_t) > pattern_in(nnz, nnz, nnz);\n    for(size_t k = 0; k < nnz; ++k)\n        pattern_in.set(k, k, k);\n\n    // Jacobian sparsity for f(u)\n    bool transpose     = false;\n    bool dependency    = false;\n    bool internal_bool = false;\n    CppAD::sparse_rc< CPPAD_TESTVECTOR(size_t) > pattern_out;\n    if( forward )\n    {  f.for_jac_sparsity(\n            pattern_in, transpose, dependency, internal_bool, pattern_out\n        );\n    }\n    else\n    {  f.rev_jac_sparsity(\n            pattern_in, transpose, dependency, internal_bool, pattern_out\n        );\n    }\n    const CPPAD_TESTVECTOR(size_t)& row = pattern_out.row();\n    const CPPAD_TESTVECTOR(size_t)& col = pattern_out.col();\n    CPPAD_TESTVECTOR(size_t) row_major  = pattern_out.row_major();\n    //\n    // first element in row major order has index (0, 2)\n    size_t k = 0;\n    size_t r = row[ row_major[k] ];\n    size_t c = col[ row_major[k] ];\n    ok      &= r == 0 && c == 2;\n    //\n    // second element in row major order has index (1, 0)\n    ++k;\n    r   = row[ row_major[k] ];\n    c   = col[ row_major[k] ];\n    ok &= r == 1 && c == 0;\n    //\n    if( x_1_variable )\n    {  // third element in row major order has index (1, 1)\n        ++k;\n        r   = row[ row_major[k] ];\n        c   = col[ row_major[k] ];\n        ok &= r == 1 && c == 1;\n    }\n    // k + 1 should be the number of values in sparsity pattern\n    ok &= k + 1 == pattern_out.nnz();\n    //\n    return ok;\n}\n}  // End empty namespace\n/* {xrst_code}\n{xrst_spell_on}\nTest with u_1 Both a Variable and a Parameter\n*********************************************\n{xrst_spell_off}\n{xrst_code cpp} */\nbool jac_sparsity(void)\n{  bool ok           = true;\n    //\n    bool u_1_variable = true;\n    bool forward      = true;\n    ok               &= use_jac_sparsity(u_1_variable, forward);\n    //\n    u_1_variable      = true;\n    forward           = false;\n    ok               &= use_jac_sparsity(u_1_variable, forward);\n    //\n    u_1_variable      = false;\n    forward           = true;\n    ok               &= use_jac_sparsity(u_1_variable, forward);\n    //\n    u_1_variable      = false;\n    forward           = false;\n    ok               &= use_jac_sparsity(u_1_variable, forward);\n    //\n    return ok;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end atomic_three_jac_sparsity.cpp}\n*/\n"
  },
  {
    "path": "example/atomic_three/mat_mul.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin atomic_three_mat_mul.cpp}\n\nUser Atomic Matrix Multiply: Example and Test\n#############################################\n\nSee Also\n********\n:ref:`atomic_two_eigen_mat_mul.cpp-name`\n{xrst_toc_hidden\n    include/cppad/example/atomic_three/mat_mul.hpp\n}\n\nClass Definition\n****************\nThis example uses the file :ref:`atomic_three_mat_mul.hpp-name`\nwhich defines matrix multiply as a :ref:`atomic_three-name` operation.\n\nUse Atomic Function\n*******************\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <cppad/cppad.hpp>\n# include <cppad/example/atomic_three/mat_mul.hpp>\n\nbool mat_mul(void)\n{  bool ok = true;\n    using CppAD::AD;\n    using CppAD::vector;\n    size_t i, j;\n/* {xrst_code}\n{xrst_spell_on}\nConstructor\n===========\n{xrst_spell_off}\n{xrst_code cpp} */\n    // -------------------------------------------------------------------\n    // object that multiplies  2 x 2  matrices\n    atomic_mat_mul afun;\n/* {xrst_code}\n{xrst_spell_on}\nRecording\n=========\n{xrst_spell_off}\n{xrst_code cpp} */\n    // start recording with four independent variables\n    size_t n = 4;\n    vector<double> x(n);\n    vector< AD<double> > ax(n);\n    for(j = 0; j < n; j++)\n        ax[j] = x[j] = double(j + 1);\n    CppAD::Independent(ax);\n\n    // ------------------------------------------------------------------\n    size_t nr_left   = 2;\n    size_t n_middle  = 2;\n    size_t nc_right  = 2;\n    vector< AD<double> > atom_x(3 + (nr_left + nc_right) * n_middle );\n\n    // matrix dimensions\n    atom_x[0] = AD<double>( nr_left );\n    atom_x[1] = AD<double>( n_middle );\n    atom_x[2] = AD<double>( nc_right );\n\n    // left matrix\n    atom_x[3] = ax[0];  // left[0, 0] = x0\n    atom_x[4] = ax[1];  // left[0, 1] = x1\n    atom_x[5] = 5.;     // left[1, 0] = 5\n    atom_x[6] = 6.;     // left[1, 1] = 6\n\n    // right matrix\n    atom_x[7] = ax[2];  // right[0, 0] = x2\n    atom_x[8] = 7.;     // right[0, 1] = 7\n    atom_x[9] = ax[3];  // right[1, 0] = x3\n    atom_x[10] = 8.;     // right[1, 1] = 8\n    // ------------------------------------------------------------------\n    /*\n    [ x0 , x1 ] * [ x2 , 7 ] = [ x0*x2 + x1*x3 , x0*7 + x1*8 ]\n    [ 5  , 6  ]   [ x3 , 8 ]   [  5*x2 +  6*x3 ,  5*7 +  6*8 ]\n    */\n    vector< AD<double> > atom_y(nr_left * nc_right);\n    afun(atom_x, atom_y);\n\n    ok &= (atom_y[0] == x[0]*x[2] + x[1]*x[3]) && Variable(atom_y[0]);\n    ok &= (atom_y[1] == x[0]*7.   + x[1]*8.  ) && Variable(atom_y[1]);\n    ok &= (atom_y[2] ==   5.*x[2] +   6.*x[3]) && Variable(atom_y[2]);\n    ok &= (atom_y[3] ==   5.*7.   +   6.*8.  ) && Parameter(atom_y[3]);\n\n    // ------------------------------------------------------------------\n    // define the function g : x -> atom_y\n    // g(x) = [ x0*x2 + x1*x3 , x0*7 + x1*8 , 5*x2  + 6*x3  , 5*7 + 6*8 ]^T\n    CppAD::ADFun<double> g(ax, atom_y);\n/* {xrst_code}\n{xrst_spell_on}\nforward\n=======\n{xrst_spell_off}\n{xrst_code cpp} */\n    // Test zero order forward mode evaluation of g(x)\n    size_t m = atom_y.size();\n    vector<double> y(m);\n    for(j = 0; j <  n; j++)\n        x[j] = double(j + 2);\n    y = g.Forward(0, x);\n    ok &= y[0] == x[0] * x[2] + x[1] * x[3];\n    ok &= y[1] == x[0] * 7.   + x[1] * 8.;\n    ok &= y[2] == 5. * x[2]   + 6. * x[3];\n    ok &= y[3] == 5. * 7.     + 6. * 8.;\n\n    //----------------------------------------------------------------------\n    // Test first order forward mode evaluation of g'(x) * [1, 2, 3, 4]^T\n    // g'(x) = [ x2, x3, x0, x1 ]\n    //         [ 7 ,  8,  0, 0  ]\n    //         [ 0 ,  0,  5, 6  ]\n    //         [ 0 ,  0,  0, 0  ]\n    CppAD::vector<double> dx(n), dy(m);\n    for(j = 0; j <  n; j++)\n        dx[j] = double(j + 1);\n    dy = g.Forward(1, dx);\n    ok &= dy[0] == 1. * x[2] + 2. * x[3] + 3. * x[0] + 4. * x[1];\n    ok &= dy[1] == 1. * 7.   + 2. * 8.   + 3. * 0.   + 4. * 0.;\n    ok &= dy[2] == 1. * 0.   + 2. * 0.   + 3. * 5.   + 4. * 6.;\n    ok &= dy[3] == 1. * 0.   + 2. * 0.   + 3. * 0.   + 4. * 0.;\n\n    //----------------------------------------------------------------------\n    // Test second order forward mode\n    // g_0^2 (x) = [ 0, 0, 1, 0 ], g_0^2 (x) * [1] = [3]\n    //             [ 0, 0, 0, 1 ]              [2]   [4]\n    //             [ 1, 0, 0, 0 ]              [3]   [1]\n    //             [ 0, 1, 0, 0 ]              [4]   [2]\n    CppAD::vector<double> ddx(n), ddy(m);\n    for(j = 0; j <  n; j++)\n        ddx[j] = 0.;\n    ddy = g.Forward(2, ddx);\n\n    // [1, 2, 3, 4] * g_0^2 (x) * [1, 2, 3, 4]^T = 1*3 + 2*4 + 3*1 + 4*2\n    ok &= 2. * ddy[0] == 1. * 3. + 2. * 4. + 3. * 1. + 4. * 2.;\n\n    // for i > 0, [1, 2, 3, 4] * g_i^2 (x) * [1, 2, 3, 4]^T = 0\n    ok &= ddy[1] == 0.;\n    ok &= ddy[2] == 0.;\n    ok &= ddy[3] == 0.;\n/* {xrst_code}\n{xrst_spell_on}\nreverse\n=======\n{xrst_spell_off}\n{xrst_code cpp} */\n    // Test second order reverse mode\n    CppAD::vector<double> w(m), dw(2 * n);\n    for(i = 0; i < m; i++)\n        w[i] = 0.;\n    w[0] = 1.;\n    dw = g.Reverse(2, w);\n\n    // g_0'(x) = [ x2, x3, x0, x1 ]\n    ok &= dw[0*2 + 0] == x[2];\n    ok &= dw[1*2 + 0] == x[3];\n    ok &= dw[2*2 + 0] == x[0];\n    ok &= dw[3*2 + 0] == x[1];\n\n    // g_0'(x)   * [1, 2, 3, 4]  = 1 * x2 + 2 * x3 + 3 * x0 + 4 * x1\n    // g_0^2 (x) * [1, 2, 3, 4]  = [3, 4, 1, 2]\n    ok &= dw[0*2 + 1] == 3.;\n    ok &= dw[1*2 + 1] == 4.;\n    ok &= dw[2*2 + 1] == 1.;\n    ok &= dw[3*2 + 1] == 2.;\n/* {xrst_code}\n{xrst_spell_on}\njac_sparsity\n============\n{xrst_spell_off}\n{xrst_code cpp} */\n    // sparsity pattern for the Jacobian\n    // g'(x) = [ x2, x3, x0, x1  ]\n    //         [  7,  8,  0,  0  ]\n    //         [  0,  0,  5,  6  ]\n    //         [  0,  0,  0,  0  ]\n    CppAD::sparse_rc< CPPAD_TESTVECTOR(size_t) > pattern_in, pattern_out;\n    bool transpose     = false;\n    bool dependency    = false;\n    bool internal_bool = false;\n    // test both forward and reverse mode\n    for(size_t forward_mode = 0; forward_mode <= 1; ++forward_mode)\n    {  if( bool(forward_mode) )\n        {  pattern_in.resize(n, n, n);\n            for(j = 0; j < n; ++j)\n                pattern_in.set(j, j, j);\n            g.for_jac_sparsity(\n                pattern_in, transpose, dependency, internal_bool, pattern_out\n            );\n        }\n        else\n        {  pattern_in.resize(m, m, m);\n            for(i = 0; i < m; ++i)\n                pattern_in.set(i, i, i);\n            g.rev_jac_sparsity(\n                pattern_in, transpose, dependency, internal_bool, pattern_out\n            );\n        }\n        const CPPAD_TESTVECTOR(size_t)& row = pattern_out.row();\n        const CPPAD_TESTVECTOR(size_t)& col = pattern_out.col();\n        CPPAD_TESTVECTOR(size_t) row_major  = pattern_out.row_major();\n        size_t k = 0;\n        for(j = 0; j < n; ++j)\n        {  ok &= row[ row_major[k] ] == 0; // (0, j)\n            ok &= col[ row_major[k] ] == j;\n            ++k;\n        }\n        ok &= row[ row_major[k] ] == 1; // (1, 0)\n        ok &= col[ row_major[k] ] == 0; //\n        ++k;\n        ok &= row[ row_major[k] ] == 1; // (1, 1)\n        ok &= col[ row_major[k] ] == 1; //\n        ++k;\n        ok &= row[ row_major[k] ] == 2; // (2, 2)\n        ok &= col[ row_major[k] ] == 2; //\n        ++k;\n        ok &= row[ row_major[k] ] == 2; // (2, 3)\n        ok &= col[ row_major[k] ] == 3; //\n        ++k;\n        ok &= pattern_out.nnz() == k;\n    }\n/* {xrst_code}\n{xrst_spell_on}\nhes_sparsity\n============\n{xrst_spell_off}\n{xrst_code cpp} */\n    /* Hessian sparsity pattern\n    g_0^2 (x) = [ 0, 0, 1, 0 ] and for i > 0, g_i^2 = 0\n                [ 0, 0, 0, 1 ]\n                [ 1, 0, 0, 0 ]\n                [ 0, 1, 0, 0 ]\n    */\n    CPPAD_TESTVECTOR(bool) select_x(n), select_y(m);\n    for(j = 0; j < n; ++j)\n        select_x[j] = true;\n    for(i = 0; i < m; ++i)\n        select_y[i] = true;\n    for(size_t forward_mode = 0; forward_mode <= 1; ++forward_mode)\n    {  if( bool(forward_mode) )\n        {  g.for_hes_sparsity(\n                select_y, select_x, internal_bool, pattern_out\n            );\n        }\n        else\n        {  // results for for_jac_sparsity are stored in g\n            g.rev_hes_sparsity(\n                select_y, transpose, internal_bool, pattern_out\n            );\n        }\n        const CPPAD_TESTVECTOR(size_t)& row = pattern_out.row();\n        const CPPAD_TESTVECTOR(size_t)& col = pattern_out.col();\n        CPPAD_TESTVECTOR(size_t) row_major  = pattern_out.row_major();\n        size_t k = 0;\n        ok &= row[ row_major[k] ] == 0; // (0, 2)\n        ok &= col[ row_major[k] ] == 2;\n        ++k;\n        ok &= row[ row_major[k] ] == 1; // (1, 3)\n        ok &= col[ row_major[k] ] == 3;\n        ++k;\n        ok &= row[ row_major[k] ] == 2; // (2, 0)\n        ok &= col[ row_major[k] ] == 0;\n        ++k;\n        ok &= row[ row_major[k] ] == 3; // (3, 1)\n        ok &= col[ row_major[k] ] == 1;\n        ++k;\n        ok &= pattern_out.nnz() == k;\n    }\n\n    return ok;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end atomic_three_mat_mul.cpp}\n*/\n"
  },
  {
    "path": "example/atomic_three/norm_sq.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin atomic_three_norm_sq.cpp}\n\nAtomic Euclidean Norm Squared: Example and Test\n###############################################\n\nFunction\n********\nThis example demonstrates using :ref:`atomic_three-name`\nto define the operation\n:math:`g : \\B{R}^n \\rightarrow \\B{R}^m` where\n:math:`n = 2`, :math:`m = 1`, where\n\n.. math::\n\n    g(x) =  x_0^2 + x_1^2\n\nStart Class Definition\n**********************\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <cppad/cppad.hpp>\nnamespace {           // isolate items below to this file\nusing CppAD::vector;  // abbreviate CppAD::vector as vector\n//\nclass atomic_norm_sq : public CppAD::atomic_three<double> {\n/* {xrst_code}\n{xrst_spell_on}\nConstructor\n***********\n{xrst_spell_off}\n{xrst_code cpp} */\npublic:\n    atomic_norm_sq(const std::string& name) :\n    CppAD::atomic_three<double>(name)\n    { }\nprivate:\n/* {xrst_code}\n{xrst_spell_on}\nfor_type\n********\n{xrst_spell_off}\n{xrst_code cpp} */\n    // calculate type_y\n    bool for_type(\n        const vector<double>&               parameter_x ,\n        const vector<CppAD::ad_type_enum>&  type_x      ,\n        vector<CppAD::ad_type_enum>&        type_y      ) override\n    {  assert( parameter_x.size() == type_x.size() );\n        bool ok = type_x.size() == 2; // n\n        ok     &= type_y.size() == 1; // m\n        if( ! ok )\n            return false;\n        type_y[0] = std::max(type_x[0], type_x[1]);\n        return true;\n    }\n/* {xrst_code}\n{xrst_spell_on}\nforward\n*******\n{xrst_spell_off}\n{xrst_code cpp} */\n    // forward mode routine called by CppAD\n    bool forward(\n        const vector<double>&              parameter_x ,\n        const vector<CppAD::ad_type_enum>& type_x      ,\n        size_t                             need_y      ,\n        size_t                             p           ,\n        size_t                             q           ,\n        const vector<double>&              tx          ,\n        vector<double>&                    ty          ) override\n    {\n# ifndef NDEBUG\n        size_t n = tx.size() / (q+1);\n        size_t m = ty.size() / (q+1);\n# endif\n        assert( type_x.size() == n );\n        assert( n == 2 );\n        assert( m == 1 );\n        assert( p <= q );\n\n        // return flag\n        bool ok = q <= 1;\n\n        // Order zero forward mode must always be implemented.\n        // y^0 = g( x^0 )\n        double x_00 = tx[ 0*(q+1) + 0];        // x_0^0\n        double x_10 = tx[ 1*(q+1) + 0];        // x_10\n        double g = x_00 * x_00 + x_10 * x_10;  // g( x^0 )\n        if( p <= 0 )\n            ty[0] = g;   // y_0^0\n        if( q <= 0 )\n            return ok;\n\n        // Order one forward mode.\n        // This case needed if first order forward mode is used.\n        // y^1 = g'( x^0 ) x^1\n        double x_01 = tx[ 0*(q+1) + 1];   // x_0^1\n        double x_11 = tx[ 1*(q+1) + 1];   // x_1^1\n        double gp_0 = 2.0 * x_00;         // partial f w.r.t x_0^0\n        double gp_1 = 2.0 * x_10;         // partial f w.r.t x_1^0\n        if( p <= 1 )\n            ty[1] = gp_0 * x_01 + gp_1 * x_11; // g'( x^0 ) * x^1\n        if( q <= 1 )\n            return ok;\n\n        // Assume we are not using forward mode with order > 1\n        assert( ! ok );\n        return ok;\n    }\n/* {xrst_code}\n{xrst_spell_on}\nreverse\n*******\n{xrst_spell_off}\n{xrst_code cpp} */\n    // reverse mode routine called by CppAD\n    bool reverse(\n        const vector<double>&               parameter_x ,\n        const vector<CppAD::ad_type_enum>&  type_x      ,\n        size_t                              q           ,\n        const vector<double>&               tx          ,\n        const vector<double>&               ty          ,\n        vector<double>&                     px          ,\n        const vector<double>&               py          ) override\n    {\n# ifndef NDEBUG\n        size_t n = tx.size() / (q+1);\n        size_t m = ty.size() / (q+1);\n# endif\n        assert( px.size() == tx.size() );\n        assert( py.size() == ty.size() );\n        assert( n == 2 );\n        assert( m == 1 );\n        bool ok = q <= 1;\n\n        double gp_0, gp_1;\n        switch(q)\n        {  case 0:\n            // This case needed if first order reverse mode is used\n            // F ( {x} ) = g( x^0 ) = y^0\n            gp_0  =  2.0 * tx[0];  // partial F w.r.t. x_0^0\n            gp_1  =  2.0 * tx[1];  // partial F w.r.t. x_0^1\n            px[0] = py[0] * gp_0;; // partial G w.r.t. x_0^0\n            px[1] = py[0] * gp_1;; // partial G w.r.t. x_0^1\n            assert(ok);\n            break;\n\n            default:\n            // Assume we are not using reverse with order > 1 (q > 0)\n            assert(!ok);\n        }\n        return ok;\n    }\n/* {xrst_code}\n{xrst_spell_on}\njac_sparsity\n************\n{xrst_spell_off}\n{xrst_code cpp} */\n    // Jacobian sparsity routine called by CppAD\n    bool jac_sparsity(\n        const vector<double>&               parameter_x ,\n        const vector<CppAD::ad_type_enum>&  type_x      ,\n        bool                                dependency  ,\n        const vector<bool>&                 select_x    ,\n        const vector<bool>&                 select_y    ,\n        CppAD::sparse_rc< vector<size_t> >& pattern_out ) override\n    {  size_t n = select_x.size();\n        size_t m = select_y.size();\n        assert( n == 2 );\n        assert( m == 1 );\n        assert( parameter_x.size() == select_x.size() );\n        //\n        // count number non-zeros\n        size_t nnz = 0;\n        if( select_y[0] )\n        {  if( select_x[0] )\n                ++nnz;\n            if( select_x[1] )\n                ++nnz;\n        }\n        // sparsity pattern\n        pattern_out.resize(m, n, nnz);\n        size_t k = 0;\n        if( select_y[0] )\n        {  if( select_x[0] )\n                pattern_out.set(k++, 0, 0);\n            if( select_x[1] )\n                pattern_out.set(k++, 0, 1);\n        }\n        return true;\n    }\n/* {xrst_code}\n{xrst_spell_on}\nhes_sparsity\n************\n{xrst_spell_off}\n{xrst_code cpp} */\n    // Hessian sparsity routine called by CppAD\n    bool hes_sparsity(\n        const vector<double>&               parameter_x ,\n        const vector<CppAD::ad_type_enum>&  type_x      ,\n        const vector<bool>&                 select_x    ,\n        const vector<bool>&                 select_y    ,\n        CppAD::sparse_rc< vector<size_t> >& pattern_out ) override\n    {  size_t n = select_x.size();\n        assert( n == 2 );\n        assert( select_y.size() == 1 ); // m\n        assert( parameter_x.size() == select_x.size() );\n        //\n        // count number non-zeros\n        size_t nnz = 0;\n        if( select_y[0] )\n        {  if( select_x[0] )\n                ++nnz;\n            if( select_x[1] )\n                ++nnz;\n        }\n        // sparsity pattern\n        pattern_out.resize(n, n, nnz);\n        size_t k = 0;\n        if( select_y[0] )\n        {  if( select_x[0] )\n                pattern_out.set(k++, 0, 0);\n            if( select_x[1] )\n                pattern_out.set(k++, 1, 1);\n        }\n        return true;\n    }\n/* {xrst_code}\n{xrst_spell_on}\nEnd Class Definition\n********************\n{xrst_spell_off}\n{xrst_code cpp} */\n}; // End of atomic_norm_sq class\n}  // End empty namespace\n\n/* {xrst_code}\n{xrst_spell_on}\nUse Atomic Function\n*******************\n{xrst_spell_off}\n{xrst_code cpp} */\nbool norm_sq(void)\n{  bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps = 10. * CppAD::numeric_limits<double>::epsilon();\n/* {xrst_code}\n{xrst_spell_on}\nConstructor\n===========\n{xrst_spell_off}\n{xrst_code cpp} */\n    // --------------------------------------------------------------------\n    // Create the atomic reciprocal object\n    atomic_norm_sq afun(\"atomic_norm_sq\");\n/* {xrst_code}\n{xrst_spell_on}\nRecording\n=========\n{xrst_spell_off}\n{xrst_code cpp} */\n    // Create the function f(x) = g(x)\n    //\n    // domain space vector\n    size_t  n  = 2;\n    double  x0 = 0.25;\n    double  x1 = 0.75;\n    vector< AD<double> > ax(n);\n    ax[0]      = x0;\n    ax[1]      = x1;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(ax);\n\n    // range space vector\n    size_t m = 1;\n    vector< AD<double> > ay(m);\n\n    // call atomic function and store norm_sq(x) in au[0]\n    afun(ax, ay);        // y_0 = x_0 * x_0 + x_1 * x_1\n\n    // create g: x -> y and stop tape recording\n    CppAD::ADFun<double> f;\n    f.Dependent (ax, ay);\n/* {xrst_code}\n{xrst_spell_on}\nforward\n=======\n{xrst_spell_off}\n{xrst_code cpp} */\n    // check function value\n    double check = x0 * x0 + x1 * x1;\n    ok &= NearEqual( Value(ay[0]) , check,  eps, eps);\n\n    // check zero order forward mode\n    size_t q;\n    vector<double> x_q(n), y_q(m);\n    q      = 0;\n    x_q[0] = x0;\n    x_q[1] = x1;\n    y_q    = f.Forward(q, x_q);\n    ok &= NearEqual(y_q[0] , check,  eps, eps);\n\n    // check first order forward mode\n    q      = 1;\n    x_q[0] = 0.3;\n    x_q[1] = 0.7;\n    y_q    = f.Forward(q, x_q);\n    check  = 2.0 * x0 * x_q[0] + 2.0 * x1 * x_q[1];\n    ok &= NearEqual(y_q[0] , check,  eps, eps);\n\n/* {xrst_code}\n{xrst_spell_on}\nreverse\n=======\n{xrst_spell_off}\n{xrst_code cpp} */\n    // first order reverse mode\n    q     = 1;\n    vector<double> w(m), dw(n * q);\n    w[0]  = 1.;\n    dw    = f.Reverse(q, w);\n    check = 2.0 * x0;\n    ok &= NearEqual(dw[0] , check,  eps, eps);\n    check = 2.0 * x1;\n    ok &= NearEqual(dw[1] , check,  eps, eps);\n/* {xrst_code}\n{xrst_spell_on}\nrev_jac_sparsity\n================\n{xrst_spell_off}\n{xrst_code cpp} */\n    // reverse mode Jacobian sparstiy pattern\n    CppAD::sparse_rc< CPPAD_TESTVECTOR(size_t) > pattern_in, pattern_out;\n    pattern_in.resize(m, m, m);\n    for(size_t i = 0; i < m; ++i)\n        pattern_in.set(i, i, i);\n    bool transpose     = false;\n    bool dependency    = false;\n    bool internal_bool = false;\n    f.rev_jac_sparsity(\n        pattern_in, transpose, dependency, internal_bool, pattern_out\n    );\n    CPPAD_TESTVECTOR(size_t) row_major  = pattern_out.row_major();\n    //\n    // first element in row major order is (0, 0)\n    size_t k = 0;\n    size_t r = pattern_out.row()[ row_major[k] ];\n    size_t c = pattern_out.col()[ row_major[k] ];\n    ok      &= r == 0 && c == 0;\n    //\n    // second element in row major order is (0, 1)\n    ++k;\n    r        = pattern_out.row()[ row_major[k] ];\n    c        = pattern_out.col()[ row_major[k] ];\n    ok      &= r == 0 && c == 1;\n    //\n    // k + 1 should be number of values in sparsity pattern\n    ok      &= k + 1 == pattern_out.nnz();\n/* {xrst_code}\n{xrst_spell_on}\nfor_hes_sparsity\n================\n{xrst_spell_off}\n{xrst_code cpp} */\n    // forward mode Hessian sparsity pattern\n    CPPAD_TESTVECTOR(bool) select_x(n), select_y(m);\n    for(size_t j = 0; j < n; ++j)\n        select_x[j] = true;\n    for(size_t i = 0; i < m; ++i)\n        select_y[i] = true;\n    f.for_hes_sparsity(\n        select_x, select_y, internal_bool, pattern_out\n    );\n    CPPAD_TESTVECTOR(size_t) order  = pattern_out.row_major();\n    //\n    // first element in row major order is (0, 0)\n    k   = 0;\n    r   = pattern_out.row()[ order[k] ];\n    c   = pattern_out.col()[ order[k] ];\n    ok &= r == 0 && c == 0;\n    //\n    // second element in row major order is (1, 1)\n    ++k;\n    r   = pattern_out.row()[ order[k] ];\n    c   = pattern_out.col()[ order[k] ];\n    ok &= r == 1 && c == 1;\n    //\n    // k + 1 should be number of values in sparsity pattern\n    ok &= k + 1 == pattern_out.nnz();\n    //\n    return ok;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end atomic_three_norm_sq.cpp}\n*/\n"
  },
  {
    "path": "example/atomic_three/reciprocal.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin atomic_three_reciprocal.cpp}\n\nReciprocal as an Atomic Operation: Example and Test\n###################################################\n\nFunction\n********\nThis example demonstrates using :ref:`atomic_three-name`\nto define the operation\n:math:`g : \\B{R}^n \\rightarrow \\B{R}^m` where\n:math:`n = 1`, :math:`m = 1`, and :math:`g(x) = 1 / x`.\n\nStart Class Definition\n**********************\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <cppad/cppad.hpp>\nnamespace {           // isolate items below to this file\nusing CppAD::vector;  // abbreviate CppAD::vector as vector\n//\nclass atomic_reciprocal : public CppAD::atomic_three<double> {\n/* {xrst_code}\n{xrst_spell_on}\nConstructor\n***********\n{xrst_spell_off}\n{xrst_code cpp} */\npublic:\n    atomic_reciprocal(const std::string& name) :\n    CppAD::atomic_three<double>(name)\n    { }\nprivate:\n/* {xrst_code}\n{xrst_spell_on}\nfor_type\n********\n{xrst_spell_off}\n{xrst_code cpp} */\n    // calculate type_y\n    bool for_type(\n        const vector<double>&               parameter_x ,\n        const vector<CppAD::ad_type_enum>&  type_x      ,\n        vector<CppAD::ad_type_enum>&        type_y      ) override\n    {  assert( parameter_x.size() == type_x.size() );\n        bool ok = type_x.size() == 1; // n\n        ok     &= type_y.size() == 1; // m\n        if( ! ok )\n            return false;\n        type_y[0] = type_x[0];\n        return true;\n    }\n/* {xrst_code}\n{xrst_spell_on}\nforward\n*******\n{xrst_spell_off}\n{xrst_code cpp} */\n    // forward mode routine called by CppAD\n    bool forward(\n        const vector<double>&              parameter_x ,\n        const vector<CppAD::ad_type_enum>& type_x      ,\n        size_t                             need_y      ,\n        size_t                             p           ,\n        size_t                             q           ,\n        const vector<double>&              tx          ,\n        vector<double>&                    ty          ) override\n    {\n# ifndef NDEBUG\n        size_t n = tx.size() / (q + 1);\n        size_t m = ty.size() / (q + 1);\n# endif\n        assert( type_x.size() == n );\n        assert( n == 1 );\n        assert( m == 1 );\n        assert( p <= q );\n\n        // return flag\n        bool ok = q <= 2;\n\n        // Order zero forward mode.\n        // This case must always be implemented\n        // y^0 = g( x^0 ) = 1 / x^0\n        double g = 1. / tx[0];\n        if( p <= 0 )\n            ty[0] = g;\n        if( q <= 0 )\n            return ok;\n\n        // Order one forward mode.\n        // This case needed if first order forward mode is used.\n        // y^1 = g'( x^0 ) x^1\n        double gp = - g / tx[0];\n        if( p <= 1 )\n            ty[1] = gp * tx[1];\n        if( q <= 1 )\n            return ok;\n\n        // Order two forward mode.\n        // This case needed if second order forward mode is used.\n        // Y''(t) = X'(t)^\\R{T} g''[X(t)] X'(t) + g'[X(t)] X''(t)\n        // 2 y^2  = x^1 * g''( x^0 ) x^1 + 2 g'( x^0 ) x^2\n        double gpp  = - 2.0 * gp / tx[0];\n        ty[2] = tx[1] * gpp * tx[1] / 2.0 + gp * tx[2];\n        if( q <= 2 )\n            return ok;\n\n        // Assume we are not using forward mode with order > 2\n        assert( ! ok );\n        return ok;\n    }\n/* {xrst_code}\n{xrst_spell_on}\nreverse\n*******\n{xrst_spell_off}\n{xrst_code cpp} */\n    // reverse mode routine called by CppAD\n    bool reverse(\n        const vector<double>&               parameter_x ,\n        const vector<CppAD::ad_type_enum>&  type_x      ,\n        size_t                              q           ,\n        const vector<double>&               tx           ,\n        const vector<double>&               ty           ,\n        vector<double>&                     px           ,\n        const vector<double>&               py           ) override\n    {\n# ifndef NDEBUG\n        size_t n = tx.size() / (q + 1);\n        size_t m = ty.size() / (q + 1);\n# endif\n        assert( px.size() == tx.size() );\n        assert( py.size() == ty.size() );\n        assert( n == 1 );\n        assert( m == 1 );\n        bool ok = q <= 2;\n\n        double g, gp, gpp, gppp;\n        switch(q)\n        {  case 0:\n            // This case needed if first order reverse mode is used\n            // reverse: F^0 ( tx ) = y^0 = g( x^0 )\n            g     = ty[0];\n            gp    = - g / tx[0];\n            px[0] = py[0] * gp;;\n            assert(ok);\n            break;\n\n            case 1:\n            // This case needed if second order reverse mode is used\n            // reverse: F^1 ( tx ) = y^1 = g'( x^0 ) x^1\n            g      = ty[0];\n            gp     = - g / tx[0];\n            gpp    = - 2.0 * gp / tx[0];\n            px[1]  = py[1] * gp;\n            px[0]  = py[1] * gpp * tx[1];\n            // reverse: F^0 ( tx ) = y^0 = g( x^0 );\n            px[0] += py[0] * gp;\n            assert(ok);\n            break;\n\n            case 2:\n            // This needed if third order reverse mode is used\n            // reverse: F^2 ( tx ) = y^2 =\n            //          = x^1 * g''( x^0 ) x^1 / 2 + g'( x^0 ) x^2\n            g      = ty[0];\n            gp     = - g / tx[0];\n            gpp    = - 2.0 * gp / tx[0];\n            gppp   = - 3.0 * gpp / tx[0];\n            px[2]  = py[2] * gp;\n            px[1]  = py[2] * gpp * tx[1];\n            px[0]  = py[2] * tx[1] * gppp * tx[1] / 2.0 + gpp * tx[2];\n            // reverse: F^1 ( tx ) = y^1 = g'( x^0 ) x^1\n            px[1] += py[1] * gp;\n            px[0] += py[1] * gpp * tx[1];\n            // reverse: F^0 ( tx ) = y^0 = g( x^0 );\n            px[0] += py[0] * gp;\n            assert(ok);\n            break;\n\n            default:\n            assert(!ok);\n        }\n        return ok;\n    }\n/* {xrst_code}\n{xrst_spell_on}\njac_sparsity\n************\n{xrst_spell_off}\n{xrst_code cpp} */\n    // Jacobian sparsity routine called by CppAD\n    bool jac_sparsity(\n        const vector<double>&               parameter_x ,\n        const vector<CppAD::ad_type_enum>&  type_x      ,\n        bool                                dependency  ,\n        const vector<bool>&                 select_x    ,\n        const vector<bool>&                 select_y    ,\n        CppAD::sparse_rc< vector<size_t> >& pattern_out ) override\n    {\n        size_t n = select_x.size();\n        size_t m = select_y.size();\n        assert( parameter_x.size() == n );\n        assert( n == 1 );\n        assert( m == 1 );\n\n        // size of pattern_out\n        size_t nr  = m;\n        size_t nc  = n;\n        size_t nnz = 0;\n        if( select_x[0] && select_y[0] )\n            ++nnz;\n        pattern_out.resize(nr, nc, nnz);\n\n        // set values in pattern_out\n        size_t k = 0;\n        if( select_x[0] && select_y[0] )\n            pattern_out.set(k++, 0, 0);\n        assert( k == nnz );\n\n        return true;\n    }\n/* {xrst_code}\n{xrst_spell_on}\nhes_sparsity\n************\n{xrst_spell_off}\n{xrst_code cpp} */\n    // Hessian sparsity routine called by CppAD\n    bool hes_sparsity(\n        const vector<double>&               parameter_x ,\n        const vector<CppAD::ad_type_enum>&  type_x      ,\n        const vector<bool>&                 select_x    ,\n        const vector<bool>&                 select_y    ,\n        CppAD::sparse_rc< vector<size_t> >& pattern_out ) override\n    {\n        assert( parameter_x.size() == select_x.size() );\n        assert( select_y.size() == 1 );\n        size_t n = select_x.size();\n        assert( n == 1 );\n\n        // size of pattern_out\n        size_t nr  = n;\n        size_t nc  = n;\n        size_t nnz = 0;\n        if( select_x[0] && select_y[0] )\n            ++nnz;\n        pattern_out.resize(nr, nc, nnz);\n\n        // set values in pattern_out\n        size_t k = 0;\n        if( select_x[0] && select_y[0] )\n            pattern_out.set(k++, 0, 0);\n        assert( k == nnz );\n\n        return true;\n    }\n/* {xrst_code}\n{xrst_spell_on}\nEnd Class Definition\n********************\n{xrst_spell_off}\n{xrst_code cpp} */\n}; // End of atomic_reciprocal class\n}  // End empty namespace\n\n/* {xrst_code}\n{xrst_spell_on}\nUse Atomic Function\n*******************\n{xrst_spell_off}\n{xrst_code cpp} */\nbool reciprocal(void)\n{  bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps = 10. * CppAD::numeric_limits<double>::epsilon();\n/* {xrst_code}\n{xrst_spell_on}\nConstructor\n===========\n{xrst_spell_off}\n{xrst_code cpp} */\n    // --------------------------------------------------------------------\n    // Create the atomic reciprocal object\n    atomic_reciprocal afun(\"atomic_reciprocal\");\n/* {xrst_code}\n{xrst_spell_on}\nRecording\n=========\n{xrst_spell_off}\n{xrst_code cpp} */\n    // Create the function f(x) = 1 / g(x) = x\n    //\n    // domain space vector\n    size_t n  = 1;\n    double x0 = 0.5;\n    vector< AD<double> > ax(n);\n    ax[0]     = x0;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(ax);\n\n    // range space vector\n    size_t m = 1;\n    vector< AD<double> > av(m);\n\n    // call atomic function and store g(x) in au[0]\n    vector< AD<double> > au(m);\n    afun(ax, au);        // u = 1 / x\n\n    // now use AD division to invert to invert the operation\n    av[0] = 1.0 / au[0]; // v = 1 / u = x\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f;\n    f.Dependent (ax, av);  // g(x) = x\n/* {xrst_code}\n{xrst_spell_on}\nforward\n=======\n{xrst_spell_off}\n{xrst_code cpp} */\n    // check function value\n    double check = x0;\n    ok &= NearEqual( Value(av[0]) , check,  eps, eps);\n\n    // check zero order forward mode\n    size_t q;\n    vector<double> x_q(n), v_q(m);\n    q      = 0;\n    x_q[0] = x0;\n    v_q    = f.Forward(q, x_q);\n    ok &= NearEqual(v_q[0] , check,  eps, eps);\n\n    // check first order forward mode\n    q      = 1;\n    x_q[0] = 1;\n    v_q    = f.Forward(q, x_q);\n    check  = 1.0;\n    ok &= NearEqual(v_q[0] , check,  eps, eps);\n\n    // check second order forward mode\n    q      = 2;\n    x_q[0] = 0;\n    v_q    = f.Forward(q, x_q);\n    check  = 0.;\n    ok &= NearEqual(v_q[0] , check,  eps, eps);\n/* {xrst_code}\n{xrst_spell_on}\nreverse\n=======\n{xrst_spell_off}\n{xrst_code cpp} */\n    // third order reverse mode\n    q     = 3;\n    vector<double> w(m), dw(n * q);\n    w[0]  = 1.;\n    dw    = f.Reverse(q, w);\n    check = 1.;\n    ok &= NearEqual(dw[0] , check,  eps, eps);\n    check = 0.;\n    ok &= NearEqual(dw[1] , check,  eps, eps);\n    ok &= NearEqual(dw[2] , check,  eps, eps);\n/* {xrst_code}\n{xrst_spell_on}\nfor_jac_sparsity\n================\n{xrst_spell_off}\n{xrst_code cpp} */\n    // forward mode Jacobian sparstiy pattern\n    CppAD::sparse_rc< CPPAD_TESTVECTOR(size_t) > pattern_in, pattern_out;\n    pattern_in.resize(1, 1, 1);\n    pattern_in.set(0, 0, 0);\n    bool transpose     = false;\n    bool dependency    = false;\n    bool internal_bool = false;\n    f.for_jac_sparsity(\n        pattern_in, transpose, dependency, internal_bool, pattern_out\n    );\n    ok &= pattern_out.nnz() == 1;\n    ok &= pattern_out.row()[0] == 0;\n    ok &= pattern_out.col()[0] == 0;\n/* {xrst_code}\n{xrst_spell_on}\nrev_sparse_jac\n==============\n{xrst_spell_off}\n{xrst_code cpp} */\n    // reverse mode Jacobian sparstiy pattern\n    f.rev_jac_sparsity(\n        pattern_in, transpose, dependency, internal_bool, pattern_out\n    );\n    ok &= pattern_out.nnz() == 1;\n    ok &= pattern_out.row()[0] == 0;\n    ok &= pattern_out.col()[0] == 0;\n/* {xrst_code}\n{xrst_spell_on}\nrev_sparse_hes\n==============\n{xrst_spell_off}\n{xrst_code cpp} */\n    // Hessian sparsity (using previous for_jac_sparsity call)\n    CPPAD_TESTVECTOR(bool) select_y(m);\n    select_y[0] = true;\n    f.rev_hes_sparsity(\n        select_y, transpose, internal_bool, pattern_out\n    );\n    ok &= pattern_out.nnz() == 1;\n    ok &= pattern_out.row()[0] == 0;\n    ok &= pattern_out.col()[0] == 0;\n/* {xrst_code}\n{xrst_spell_on}\nfor_sparse_hes\n==============\n{xrst_spell_off}\n{xrst_code cpp} */\n    // Hessian sparsity\n    CPPAD_TESTVECTOR(bool) select_x(n);\n    select_x[0] = true;\n    f.for_hes_sparsity(\n        select_x, select_y, internal_bool, pattern_out\n    );\n    ok &= pattern_out.nnz() == 1;\n    ok &= pattern_out.row()[0] == 0;\n    ok &= pattern_out.col()[0] == 0;\n    return ok;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end atomic_three_reciprocal.cpp}\n*/\n"
  },
  {
    "path": "example/atomic_three/rev_depend.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin atomic_three_rev_depend.cpp}\n\nAtomic Functions Reverse Dependency Analysis: Example and Test\n##############################################################\n\nPurpose\n*******\nThis example demonstrates using :ref:`atomic_three-name` function\nin the definition of a function that is optimized.\n\nFunction\n********\nFor this example, the atomic function\n:math:`g : \\B{R}^3 \\rightarrow \\B{R}^3` is defined by\n:math:`g_0 (x) = x_0 * x_0`,\n:math:`g_1 (x) = x_0 * x_1`,\n:math:`g_2 (x) = x_1 * x_2`.\n\nStart Class Definition\n**********************\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <cppad/cppad.hpp>  // CppAD include file\nnamespace {                  // start empty namespace\nusing CppAD::vector;         // abbreviate CppAD::vector using vector\n// start definition of atomic derived class using atomic_three interface\nclass atomic_optimize : public CppAD::atomic_three<double> {\n/* {xrst_code}\n{xrst_spell_on}\nConstructor\n***********\n{xrst_spell_off}\n{xrst_code cpp} */\npublic:\n    // can use const char* name when calling this constructor\n    atomic_optimize(const std::string& name) : // can have more arguments\n    CppAD::atomic_three<double>(name)          // inform base class of name\n    { }\n\nprivate:\n/* {xrst_code}\n{xrst_spell_on}\nfor_type\n********\n{xrst_spell_off}\n{xrst_code cpp} */\n    // calculate type_y\n    bool for_type(\n        const vector<double>&               parameter_x ,\n        const vector<CppAD::ad_type_enum>&  type_x      ,\n        vector<CppAD::ad_type_enum>&        type_y      ) override\n    {  assert( parameter_x.size() == type_x.size() );\n        bool ok = type_x.size() == 3; // n\n        ok     &= type_y.size() == 3; // m\n        if( ! ok )\n            return false;\n        type_y[0] = type_x[0];\n        type_y[1] = std::max( type_x[0], type_x[1] );\n        type_y[2] = std::max( type_x[1], type_x[2] );\n        return true;\n    }\n/* {xrst_code}\n{xrst_spell_on}\nrev_depend\n**********\n{xrst_spell_off}\n{xrst_code cpp} */\n    // calculate depend_x\n    bool rev_depend(\n        const vector<double>&               parameter_x ,\n        const vector<CppAD::ad_type_enum>&  type_x      ,\n        vector<bool>&                       depend_x    ,\n        const vector<bool>&                 depend_y    ) override\n    {  assert( parameter_x.size() == depend_x.size() );\n        bool ok = depend_x.size() == 3; // n\n        ok     &= depend_y.size() == 3; // m\n        if( ! ok )\n            return false;\n        depend_x[0] = depend_y[0] || depend_y[1];\n        depend_x[1] = depend_y[1] || depend_y[2];\n        depend_x[2] = depend_y[2];\n        return true;\n    }\n/* {xrst_code}\n{xrst_spell_on}\nforward\n*******\n{xrst_spell_off}\n{xrst_code cpp} */\n    // forward mode routine called by CppAD\n    bool forward(\n        const vector<double>&               parameter_x ,\n        const vector<CppAD::ad_type_enum>&  type_x      ,\n        size_t                              need_y      ,\n        size_t                              order_low   ,\n        size_t                              order_up    ,\n        const vector<double>&               taylor_x    ,\n        vector<double>&                     taylor_y\n    ) override\n    {\n# ifndef NDEBUG\n        size_t n = taylor_x.size() / (order_up + 1);\n        size_t m = taylor_y.size() / (order_up + 1);\n# endif\n        assert( n == 3 );\n        assert( m == 3 );\n        assert( order_low <= order_up );\n\n        // return flag\n        bool ok = order_up == 0;\n        if( ! ok )\n            return ok;\n\n        // Order zero forward mode.\n        // This case must always be implemented\n        if( need_y > size_t(CppAD::variable_enum) )\n        {  // g_0 = x_0 * x_0\n            taylor_y[0] = taylor_x[0] * taylor_x[0];\n            // g_1 = x_0 * x_1\n            taylor_y[1] = taylor_x[0] * taylor_x[1];\n            // g_2 = x_1 * x_2\n            taylor_y[2] = taylor_x[1] * taylor_x[2];\n        }\n        else\n        {  // This uses need_y to reduce amount of computation.\n            // It is probably faster, for this case, to ignore need_y.\n            vector<CppAD::ad_type_enum> type_y( taylor_y.size() );\n            for_type(taylor_x, type_x, type_y);\n            // g_0 = x_0 * x_0\n            if( size_t(type_y[0]) == need_y )\n                taylor_y[0] = taylor_x[0] * taylor_x[0];\n            // g_1 = x_0 * x_1\n            if( size_t(type_y[1]) == need_y )\n                taylor_y[1] = taylor_x[0] * taylor_x[1];\n            // g_2 = x_1 * x_2\n            if( size_t(type_y[2]) == need_y )\n                taylor_y[2] = taylor_x[1] * taylor_x[2];\n        }\n\n        return ok;\n    }\n/* {xrst_code}\n{xrst_spell_on}\nEnd Class Definition\n********************\n{xrst_spell_off}\n{xrst_code cpp} */\n}; // End of atomic_optimize class\n}  // End empty namespace\n\n/* {xrst_code}\n{xrst_spell_on}\nUse Atomic Function\n*******************\n{xrst_spell_off}\n{xrst_code cpp} */\nbool rev_depend(void)\n{  bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps = 10. * CppAD::numeric_limits<double>::epsilon();\n/* {xrst_code}\n{xrst_spell_on}\nConstructor\n===========\n{xrst_spell_off}\n{xrst_code cpp} */\n    // Create the atomic dynamic object corresponding to g(x)\n    atomic_optimize afun(\"atomic_optimize\");\n/* {xrst_code}\n{xrst_spell_on}\nRecording\n=========\n{xrst_spell_off}\n{xrst_code cpp} */\n    // Create the function f(u) = g(c, p, u) for this example.\n    //\n    // constant parameter\n    double c_0 = 2.0;\n    //\n    // independent dynamic parameter vector\n    size_t np = 1;\n    CPPAD_TESTVECTOR(double) p(np);\n    CPPAD_TESTVECTOR( AD<double> ) ap(np);\n    ap[0] = p[0] = 3.0;\n    //\n    // independent variable vector\n    size_t  nu  = 1;\n    double  u_0 = 0.5;\n    CPPAD_TESTVECTOR( AD<double> ) au(nu);\n    au[0] = u_0;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(au, ap);\n\n    // range space vector\n    size_t ny = 3;\n    CPPAD_TESTVECTOR( AD<double> ) ay(ny);\n\n    // call atomic function and store result in ay\n    // y = ( c * c, c * p, p * u )\n    CPPAD_TESTVECTOR( AD<double> ) ax(3);\n    ax[0] = c_0;   // x_0 = c\n    ax[1] = ap[0]; // x_1 = p\n    ax[2] = au[0]; // x_2 = u\n    afun(ax, ay);\n\n    // check type of result\n    ok &= Constant( ay[0] ); // c * c\n    ok &= Dynamic(  ay[1] ); // c * p\n    ok &= Variable( ay[2] ); // p * u\n\n    // create f: u -> y and stop tape recording\n    CppAD::ADFun<double> f;\n    f.Dependent (au, ay);  // f(u) = (c * c, c * p, p * u)\n/* {xrst_code}\n{xrst_spell_on}\noptimize\n========\nThis operation does a callback to\n:ref:`atomic_three_rev_depend.cpp@rev_depend` defined above\n{xrst_spell_off}\n{xrst_code cpp} */\n    f.optimize();\n/* {xrst_code}\n{xrst_spell_on}\nforward\n=======\n{xrst_spell_off}\n{xrst_code cpp} */\n    // check function value\n    double check = c_0 * c_0;\n    ok &= NearEqual( Value(ay[0]) , check,  eps, eps);\n    check = c_0 * p[0];\n    ok &= NearEqual( Value(ay[1]) , check,  eps, eps);\n    check = p[0] * u_0;\n    ok &= NearEqual( Value(ay[2]) , check,  eps, eps);\n\n    // check zero order forward mode\n    size_t q;\n    CPPAD_TESTVECTOR( double ) u_q(nu), y_q(ny);\n    q      = 0;\n    u_q[0] = u_0;\n    y_q    = f.Forward(q, u_q);\n    check = c_0 * c_0;\n    ok    &= NearEqual(y_q[0] , check,  eps, eps);\n    check = c_0 * p[0];\n    ok    &= NearEqual(y_q[1] , check,  eps, eps);\n    check = p[0] * u_0;\n    ok    &= NearEqual(y_q[2] , check,  eps, eps);\n\n    // set new value for dynamic parameters\n    p[0]   = 2.0 * p[0];\n    f.new_dynamic(p);\n    y_q    = f.Forward(q, u_q);\n    check = c_0 * c_0;\n    ok    &= NearEqual(y_q[0] , check,  eps, eps);\n    check = c_0 * p[0];\n    ok    &= NearEqual(y_q[1] , check,  eps, eps);\n    check = p[0] * u_0;\n    ok    &= NearEqual(y_q[2] , check,  eps, eps);\n\n/* {xrst_code}\n{xrst_spell_on}\nReturn Test Result\n==================\n{xrst_spell_off}\n{xrst_code cpp} */\n    return ok;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end atomic_three_rev_depend.cpp}\n*/\n"
  },
  {
    "path": "example/atomic_three/reverse.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_three_reverse.cpp}\n\nAtomic Functions and Reverse Mode: Example and Test\n###################################################\n\nPurpose\n*******\nThis example demonstrates reverse mode derivative calculation\nusing an :ref:`atomic_three-name` function.\n\nFunction\n********\nFor this example, the atomic function\n:math:`g : \\B{R}^3 \\rightarrow \\B{R}^2` is defined by\n\n.. math::\n\n    g(x) = \\left( \\begin{array}{c}\n        x_2 * x_2 \\\\\n        x_0 * x_1\n    \\end{array} \\right)\n\nJacobian\n********\nThe corresponding Jacobian is\n\n.. math::\n\n    g^{(1)} (x) = \\left( \\begin{array}{ccc}\n      0  &   0 & 2 x_2 \\\\\n    x_1  & x_0 & 0\n    \\end{array} \\right)\n\nHessian\n*******\nThe Hessians of the component functions are\n\n.. math::\n\n    g_0^{(2)} ( x ) = \\left( \\begin{array}{ccc}\n        0 & 0 & 0  \\\\\n        0 & 0 & 0  \\\\\n        0 & 0 & 2\n    \\end{array} \\right)\n    \\W{,}\n    g_1^{(2)} ( x ) = \\left( \\begin{array}{ccc}\n        0 & 1 & 0 \\\\\n        1 & 0 & 0 \\\\\n        0 & 0 & 0\n    \\end{array} \\right)\n\nStart Class Definition\n**********************\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <cppad/cppad.hpp>\nnamespace {          // isolate items below to this file\nusing CppAD::vector; // abbreviate as vector\n//\nclass atomic_reverse : public CppAD::atomic_three<double> {\n/* {xrst_code}\n{xrst_spell_on}\nConstructor\n***********\n{xrst_spell_off}\n{xrst_code cpp} */\npublic:\n    atomic_reverse(const std::string& name) :\n    CppAD::atomic_three<double>(name)\n    { }\nprivate:\n/* {xrst_code}\n{xrst_spell_on}\nfor_type\n********\n{xrst_spell_off}\n{xrst_code cpp} */\n    // calculate type_y\n    bool for_type(\n        const vector<double>&               parameter_x ,\n        const vector<CppAD::ad_type_enum>&  type_x      ,\n        vector<CppAD::ad_type_enum>&        type_y      ) override\n    {  assert( parameter_x.size() == type_x.size() );\n        bool ok = type_x.size() == 3; // n\n        ok     &= type_y.size() == 2; // m\n        if( ! ok )\n            return false;\n        type_y[0] = type_x[2];\n        type_y[1] = std::max(type_x[0], type_x[1]);\n        return true;\n    }\n/* {xrst_code}\n{xrst_spell_on}\nforward\n*******\n{xrst_spell_off}\n{xrst_code cpp} */\n    // forward mode routine called by CppAD\n    bool forward(\n        const vector<double>&                   parameter_x ,\n        const vector<CppAD::ad_type_enum>&      type_x      ,\n        size_t                                  need_y      ,\n        size_t                                  order_low   ,\n        size_t                                  order_up    ,\n        const vector<double>&                   taylor_x    ,\n        vector<double>&                         taylor_y    ) override\n    {\n        size_t q1 = order_up + 1;\n# ifndef NDEBUG\n        size_t n = taylor_x.size() / q1;\n        size_t m = taylor_y.size() / q1;\n# endif\n        assert( n == 3 );\n        assert( m == 2 );\n        assert( order_low <= order_up );\n\n        // this example only implements up to first order forward mode\n        bool ok = order_up <= 1;\n        if( ! ok )\n            return ok;\n\n        // ------------------------------------------------------------------\n        // Zero forward mode.\n        // This case must always be implemented\n        // g(x) = [ x_2 * x_2 ]\n        //        [ x_0 * x_1 ]\n        // y^0  = f( x^0 )\n        if( order_low <= 0 )\n        {  // y_0^0 = x_2^0 * x_2^0\n            taylor_y[0*q1+0] = taylor_x[2*q1+0] * taylor_x[2*q1+0];\n            // y_1^0 = x_0^0 * x_1^0\n            taylor_y[1*q1+0] = taylor_x[0*q1+0] * taylor_x[1*q1+0];\n        }\n        if( order_up <= 0 )\n            return ok;\n        // ------------------------------------------------------------------\n        // First order one forward mode.\n        // This case is needed if first order forward mode is used.\n        // g'(x) = [   0,   0, 2 * x_2 ]\n        //         [ x_1, x_0,       0 ]\n        // y^1 =  f'(x^0) * x^1\n        if( order_low <= 1 )\n        {  // y_0^1 = 2 * x_2^0 * x_2^1\n            taylor_y[0*q1+1] = 2.0 * taylor_x[2*q1+0] * taylor_x[2*q1+1];\n\n            // y_1^1 = x_1^0 * x_0^1 + x_0^0 * x_1^1\n            taylor_y[1*q1+1]  = taylor_x[1*q1+0] * taylor_x[0*q1+1];\n            taylor_y[1*q1+1] += taylor_x[0*q1+0] * taylor_x[1*q1+1];\n        }\n        return ok;\n    }\n/* {xrst_code}\n{xrst_spell_on}\nreverse\n*******\n{xrst_spell_off}\n{xrst_code cpp} */\n    // reverse mode routine called by CppAD\n    bool reverse(\n        const vector<double>&               parameter_x ,\n        const vector<CppAD::ad_type_enum>&  type_x      ,\n        size_t                              order_up    ,\n        const vector<double>&               taylor_x    ,\n        const vector<double>&               taylor_y    ,\n        vector<double>&                     partial_x   ,\n        const vector<double>&               partial_y   ) override\n    {\n        size_t q1 = order_up + 1;\n        size_t n = taylor_x.size() / q1;\n# ifndef NDEBUG\n        size_t m = taylor_y.size() / q1;\n# endif\n        assert( n == 3 );\n        assert( m == 2 );\n\n        // this example only implements up to second order reverse mode\n        bool ok = q1 <= 2;\n        if( ! ok )\n            return ok;\n        //\n        // initialize summation as zero\n        for(size_t j = 0; j < n; j++)\n            for(size_t k = 0; k < q1; k++)\n                partial_x[j * q1 + k] = 0.0;\n        //\n        if( q1 == 2 )\n        {  // --------------------------------------------------------------\n            // Second order reverse first compute partials of first order\n            // We use the notation pg_ij^k for partial of F_i^1 w.r.t. x_j^k\n            //\n            // y_0^1    = 2 * x_2^0 * x_2^1\n            // pg_02^0  = 2 * x_2^1\n            // pg_02^1  = 2 * x_2^0\n            //\n            // y_1^1    = x_1^0 * x_0^1 + x_0^0 * x_1^1\n            // pg_10^0  = x_1^1\n            // pg_11^0  = x_0^1\n            // pg_10^1  = x_1^0\n            // pg_11^1  = x_0^0\n            //\n            // px_0^0 += py_0^1 * pg_00^0 + py_1^1 * pg_10^0\n            //        += py_1^1 * x_1^1\n            partial_x[0*q1+0] += partial_y[1*q1+1] * taylor_x[1*q1+1];\n            //\n            // px_0^1 += py_0^1 * pg_00^1 + py_1^1 * pg_10^1\n            //        += py_1^1 * x_1^0\n            partial_x[0*q1+1] += partial_y[1*q1+1] * taylor_x[1*q1+0];\n            //\n            // px_1^0 += py_0^1 * pg_01^0 + py_1^1 * pg_11^0\n            //        += py_1^1 * x_0^1\n            partial_x[1*q1+0] += partial_y[1*q1+1] * taylor_x[0*q1+1];\n            //\n            // px_1^1 += py_0^1 * pg_01^1 + py_1^1 * pg_11^1\n            //        += py_1^1 * x_0^0\n            partial_x[1*q1+1] += partial_y[1*q1+1] * taylor_x[0*q1+0];\n            //\n            // px_2^0 += py_0^1 * pg_02^0 + py_1^1 * pg_12^0\n            //        += py_0^1 * 2 * x_2^1\n            partial_x[2*q1+0] += partial_y[0*q1+1] * 2.0 * taylor_x[2*q1+1];\n            //\n            // px_2^1 += py_0^1 * pg_02^1 + py_1^1 * pg_12^1\n            //        += py_0^1 * 2 * x_2^0\n            partial_x[2*q1+1] += partial_y[0*q1+1] * 2.0 * taylor_x[2*q1+0];\n        }\n        // --------------------------------------------------------------\n        // First order reverse computes partials of zero order coefficients\n        // We use the notation pg_ij for partial of F_i^0 w.r.t. x_j^0\n        //\n        // y_0^0 = x_2^0 * x_2^0\n        // pg_00 = 0,     pg_01 = 0,  pg_02 = 2 * x_2^0\n        //\n        // y_1^0 = x_0^0 * x_1^0\n        // pg_10 = x_1^0, pg_11 = x_0^0,  pg_12 = 0\n        //\n        // px_0^0 += py_0^0 * pg_00 + py_1^0 * pg_10\n        //        += py_1^0 * x_1^0\n        partial_x[0*q1+0] += partial_y[1*q1+0] * taylor_x[1*q1+0];\n        //\n        // px_1^0 += py_1^0 * pg_01 + py_1^0 * pg_11\n        //        += py_1^0 * x_0^0\n        partial_x[1*q1+0] += partial_y[1*q1+0] * taylor_x[0*q1+0];\n        //\n        // px_2^0 += py_1^0 * pg_02 + py_1^0 * pg_12\n        //        += py_0^0 * 2.0 * x_2^0\n        partial_x[2*q1+0] += partial_y[0*q1+0] * 2.0 * taylor_x[2*q1+0];\n        // --------------------------------------------------------------\n        return ok;\n    }\n};\n}  // End empty namespace\n/* {xrst_code}\n{xrst_spell_on}\nUse Atomic Function\n*******************\n{xrst_spell_off}\n{xrst_code cpp} */\nbool reverse(void)\n{  bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps = 10. * CppAD::numeric_limits<double>::epsilon();\n    //\n    // Create the atomic_reverse object corresponding to g(x)\n    atomic_reverse afun(\"atomic_reverse\");\n    //\n    // Create the function f(u) = g(u) for this example.\n    //\n    // domain space vector\n    size_t n  = 3;\n    double u_0 = 1.00;\n    double u_1 = 2.00;\n    double u_2 = 3.00;\n    vector< AD<double> > au(n);\n    au[0] = u_0;\n    au[1] = u_1;\n    au[2] = u_2;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(au);\n\n    // range space vector\n    size_t m = 2;\n    vector< AD<double> > ay(m);\n\n    // call atomic function\n    vector< AD<double> > ax = au;\n    afun(ax, ay);\n\n    // create f: u -> y and stop tape recording\n    CppAD::ADFun<double> f;\n    f.Dependent (au, ay);  // y = f(u)\n    //\n    // check function value\n    double check = u_2 * u_2;\n    ok &= NearEqual( Value(ay[0]) , check,  eps, eps);\n    check = u_0 * u_1;\n    ok &= NearEqual( Value(ay[1]) , check,  eps, eps);\n\n    // --------------------------------------------------------------------\n    // zero order forward\n    //\n    vector<double> u0(n), y0(m);\n    u0[0] = u_0;\n    u0[1] = u_1;\n    u0[2] = u_2;\n    y0   = f.Forward(0, u0);\n    check = u_2 * u_2;\n    ok &= NearEqual(y0[0] , check,  eps, eps);\n    check = u_0 * u_1;\n    ok &= NearEqual(y0[1] , check,  eps, eps);\n    // --------------------------------------------------------------------\n    // first order reverse\n    //\n    // value of Jacobian of f\n    double check_jac[] = {\n        0.0, 0.0, 2.0 * u_2,\n        u_1, u_0,       0.0\n    };\n    vector<double> w(m), dw(n);\n    //\n    // check derivative of f_0 (x)\n    for(size_t i = 0; i < m; i++)\n    {  w[i]   = 1.0;\n        w[1-i] = 0.0;\n        dw = f.Reverse(1, w);\n        for(size_t j = 0; j < n; j++)\n        {  // compute partial in j-th component direction\n            ok &= NearEqual(dw[j], check_jac[i * n + j], eps, eps);\n        }\n    }\n    // --------------------------------------------------------------------\n    // second order reverse\n    //\n    // value of Hessian of f_0\n    double check_hes_0[] = {\n        0.0, 0.0, 0.0,\n        0.0, 0.0, 0.0,\n        0.0, 0.0, 2.0\n    };\n    //\n    // value of Hessian of f_1\n    double check_hes_1[] = {\n        0.0, 1.0, 0.0,\n        1.0, 0.0, 0.0,\n        0.0, 0.0, 0.0\n    };\n    vector<double> u1(n), dw2( 2 * n );\n    for(size_t j = 0; j < n; j++)\n    {  for(size_t j1 = 0; j1 < n; j1++)\n            u1[j1] = 0.0;\n        u1[j] = 1.0;\n        // first order forward\n        f.Forward(1, u1);\n        w[0] = 1.0;\n        w[1] = 0.0;\n        dw2  = f.Reverse(2, w);\n        for(size_t i = 0; i < n; i++)\n            ok &= NearEqual(dw2[i * 2 + 1], check_hes_0[i * n + j], eps, eps);\n        w[0] = 0.0;\n        w[1] = 1.0;\n        dw2  = f.Reverse(2, w);\n        for(size_t i = 0; i < n; i++)\n            ok &= NearEqual(dw2[i * 2 + 1], check_hes_1[i * n + j], eps, eps);\n    }\n    // --------------------------------------------------------------------\n    return ok;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end atomic_three_reverse.cpp}\n*/\n"
  },
  {
    "path": "example/atomic_three/tangent.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin atomic_three_tangent.cpp}\n\nTan and Tanh as User Atomic Operations: Example and Test\n########################################################\n\nDiscussion\n**********\nThe code below uses the :ref:`tan_forward-name` and :ref:`tan_reverse-name`\nto implement the tangent and hyperbolic tangent\nfunctions as atomic function operations.\nIt also uses ``AD<float>`` ,\nwhile most atomic examples use ``AD<double>`` .\n\nStart Class Definition\n**********************\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <cppad/cppad.hpp>\nnamespace { // Begin empty namespace\nusing CppAD::vector;\n//\nclass atomic_tangent : public CppAD::atomic_three<float> {\n/* {xrst_code}\n{xrst_spell_on}\nConstructor\n***********\n{xrst_spell_off}\n{xrst_code cpp} */\nprivate:\n    const bool hyperbolic_; // is this hyperbolic tangent\npublic:\n    // constructor\n    atomic_tangent(const char* name, bool hyperbolic)\n    : CppAD::atomic_three<float>(name),\n    hyperbolic_(hyperbolic)\n    { }\nprivate:\n/* {xrst_code}\n{xrst_spell_on}\nfor_type\n********\n{xrst_spell_off}\n{xrst_code cpp} */\n    // calculate type_y\n    bool for_type(\n        const vector<float>&                parameter_x ,\n        const vector<CppAD::ad_type_enum>&  type_x      ,\n        vector<CppAD::ad_type_enum>&        type_y      ) override\n    {  assert( parameter_x.size() == type_x.size() );\n        bool ok = type_x.size() == 1; // n\n        ok     &= type_y.size() == 2; // m\n        if( ! ok )\n            return false;\n        type_y[0] = type_x[0];\n        type_y[1] = type_x[0];\n        return true;\n    }\n/* {xrst_code}\n{xrst_spell_on}\nforward\n*******\n{xrst_spell_off}\n{xrst_code cpp} */\n    // forward mode routine called by CppAD\n    bool forward(\n        const vector<float>&               parameter_x ,\n        const vector<CppAD::ad_type_enum>& type_x      ,\n        size_t                             need_y      ,\n        size_t                             p           ,\n        size_t                             q           ,\n        const vector<float>&               tx          ,\n        vector<float>&                     tzy         ) override\n    {  size_t q1 = q + 1;\n# ifndef NDEBUG\n        size_t n  = tx.size()  / q1;\n        size_t m  = tzy.size() / q1;\n# endif\n        assert( type_x.size() == n );\n        assert( n == 1 );\n        assert( m == 2 );\n        assert( p <= q );\n        size_t j, k;\n\n        if( p == 0 )\n        {  // z^{(0)} = tan( x^{(0)} ) or tanh( x^{(0)} )\n            if( hyperbolic_ )\n                tzy[0] = float( tanh( tx[0] ) );\n            else\n                tzy[0] = float( tan( tx[0] ) );\n\n            // y^{(0)} = z^{(0)} * z^{(0)}\n            tzy[q1 + 0] = tzy[0] * tzy[0];\n\n            p++;\n        }\n        for(j = p; j <= q; j++)\n        {  float j_inv = 1.f / float(j);\n            if( hyperbolic_ )\n                j_inv = - j_inv;\n\n            // z^{(j)} = x^{(j)} +- sum_{k=1}^j k x^{(k)} y^{(j-k)} / j\n            tzy[j] = tx[j];\n            for(k = 1; k <= j; k++)\n                tzy[j] += tx[k] * tzy[q1 + j-k] * float(k) * j_inv;\n\n            // y^{(j)} = sum_{k=0}^j z^{(k)} z^{(j-k)}\n            tzy[q1 + j] = 0.;\n            for(k = 0; k <= j; k++)\n                tzy[q1 + j] += tzy[k] * tzy[j-k];\n        }\n\n        // All orders are implemented and there are no possible errors\n        return true;\n    }\n/* {xrst_code}\n{xrst_spell_on}\nreverse\n*******\n{xrst_spell_off}\n{xrst_code cpp} */\n    // reverse mode routine called by CppAD\n    bool reverse(\n        const vector<float>&               parameter_x ,\n        const vector<CppAD::ad_type_enum>& type_x      ,\n        size_t                             q           ,\n        const vector<float>&               tx          ,\n        const vector<float>&               tzy         ,\n        vector<float>&                     px          ,\n        const vector<float>&               pzy         ) override\n    {  size_t q1 = q + 1;\n# ifndef NDEBUG\n        size_t n  = tx.size()  / q1;\n        size_t m  = tzy.size() / q1;\n# endif\n        assert( px.size()  == n * q1 );\n        assert( pzy.size() == m * q1 );\n        assert( n == 1 );\n        assert( m == 2 );\n\n        size_t j, k;\n\n        // copy because partials w.r.t. y and z need to change\n        vector<float> qzy = pzy;\n\n        // initialize accumultion of reverse mode partials\n        for(k = 0; k < q1; k++)\n            px[k] = 0.;\n\n        // eliminate positive orders\n        for(j = q; j > 0; j--)\n        {  float j_inv = 1.f / float(j);\n            if( hyperbolic_ )\n                j_inv = - j_inv;\n\n            // H_{x^{(k)}} += delta(j-k) +- H_{z^{(j)} y^{(j-k)} * k / j\n            px[j] += qzy[j];\n            for(k = 1; k <= j; k++)\n                px[k] += qzy[j] * tzy[q1 + j-k] * float(k) * j_inv;\n\n            // H_{y^{j-k)} += +- H_{z^{(j)} x^{(k)} * k / j\n            for(k = 1; k <= j; k++)\n                qzy[q1 + j-k] += qzy[j] * tx[k] * float(k) * j_inv;\n\n            // H_{z^{(k)}} += H_{y^{(j-1)}} * z^{(j-k-1)} * 2.\n            for(k = 0; k < j; k++)\n                qzy[k] += qzy[q1 + j-1] * tzy[j-k-1] * 2.f;\n        }\n\n        // eliminate order zero\n        if( hyperbolic_ )\n            px[0] += qzy[0] * (1.f - tzy[q1 + 0]);\n        else\n            px[0] += qzy[0] * (1.f + tzy[q1 + 0]);\n\n        return true;\n    }\n/* {xrst_code}\n{xrst_spell_on}\njac_sparsity\n************\n{xrst_spell_off}\n{xrst_code cpp} */\n    // Jacobian sparsity routine called by CppAD\n    bool jac_sparsity(\n        const vector<float>&                parameter_x ,\n        const vector<CppAD::ad_type_enum>&  type_x      ,\n        bool                                dependency  ,\n        const vector<bool>&                 select_x    ,\n        const vector<bool>&                 select_y    ,\n        CppAD::sparse_rc< vector<size_t> >& pattern_out ) override\n    {\n        size_t n = select_x.size();\n        size_t m = select_y.size();\n        assert( parameter_x.size() == n );\n        assert( n == 1 );\n        assert( m == 2 );\n\n        // number of non-zeros in sparsity pattern\n        size_t nnz = 0;\n        if( select_x[0] )\n        {  if( select_y[0] )\n                ++nnz;\n            if( select_y[1] )\n                ++nnz;\n        }\n\n        // sparsity pattern\n        pattern_out.resize(m, n, nnz);\n        size_t k = 0;\n        if( select_x[0] )\n        {  if( select_y[0] )\n                pattern_out.set(k++, 0, 0);\n            if( select_y[1] )\n                pattern_out.set(k++, 1, 0);\n        }\n        assert( k == nnz );\n\n        return true;\n    }\n/* {xrst_code}\n{xrst_spell_on}\nhes_sparsity\n************\n{xrst_spell_off}\n{xrst_code cpp} */\n    // Hessian sparsity routine called by CppAD\n    bool hes_sparsity(\n        const vector<float>&                parameter_x ,\n        const vector<CppAD::ad_type_enum>&  type_x      ,\n        const vector<bool>&                 select_x    ,\n        const vector<bool>&                 select_y    ,\n        CppAD::sparse_rc< vector<size_t> >& pattern_out ) override\n    {\n        assert( parameter_x.size() == select_x.size() );\n        assert( select_y.size() == 2 );\n        size_t n = select_x.size();\n        assert( n == 1 );\n\n        // number of non-zeros in sparsity pattern\n        size_t nnz = 0;\n        if( select_x[0] && (select_y[0] || select_y[1]) )\n            nnz = 1;\n        // sparsity pattern\n        pattern_out.resize(n, n, nnz);\n        if( select_x[0] && (select_y[0] || select_y[1]) )\n            pattern_out.set(0, 0, 0);\n\n        return true;\n    }\n/* {xrst_code}\n{xrst_spell_on}\nEnd Class Definition\n********************\n{xrst_spell_off}\n{xrst_code cpp} */\n}; // End of atomic_tangent class\n}  // End empty namespace\n\n/* {xrst_code}\n{xrst_spell_on}\nUse Atomic Function\n*******************\n{xrst_spell_off}\n{xrst_code cpp} */\nbool tangent(void)\n{  bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    float eps = 10.f * CppAD::numeric_limits<float>::epsilon();\n/* {xrst_code}\n{xrst_spell_on}\nConstructor\n===========\n{xrst_spell_off}\n{xrst_code cpp} */\n    // --------------------------------------------------------------------\n    // Create a tan and tanh object\n    atomic_tangent my_tan(\"my_tan\", false), my_tanh(\"my_tanh\", true);\n/* {xrst_code}\n{xrst_spell_on}\nRecording\n=========\n{xrst_spell_off}\n{xrst_code cpp} */\n    // domain space vector\n    size_t n  = 1;\n    float  x0 = 0.5;\n    CppAD::vector< AD<float> > ax(n);\n    ax[0]     = x0;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(ax);\n\n    // range space vector\n    size_t m = 3;\n    CppAD::vector< AD<float> > av(m);\n\n    // temporary vector for computations\n    // (my_tan and my_tanh computes tan or tanh and its square)\n    CppAD::vector< AD<float> > au(2);\n\n    // call atomic tan function and store tan(x) in f[0], ignore tan(x)^2\n    my_tan(ax, au);\n    av[0] = au[0];\n\n    // call atomic tanh function and store tanh(x) in f[1], ignore tanh(x)^2\n    my_tanh(ax, au);\n    av[1] = au[0];\n\n    // put a constant in f[2] = tanh(1.),  for sparsity pattern testing\n    CppAD::vector< AD<float> > one(1);\n    one[0] = 1.;\n    my_tanh(one, au);\n    av[2] = au[0];\n\n    // create f: x -> v and stop tape recording\n    CppAD::ADFun<float> f;\n    f.Dependent(ax, av);\n/* {xrst_code}\n{xrst_spell_on}\nforward\n=======\n{xrst_spell_off}\n{xrst_code cpp} */\n    // check function value\n    float tan = std::tan(x0);\n    ok &= NearEqual(av[0] , tan,  eps, eps);\n    float tanh = std::tanh(x0);\n    ok &= NearEqual(av[1] , tanh,  eps, eps);\n\n    // check zero order forward\n    CppAD::vector<float> x(n), v(m);\n    x[0] = x0;\n    v    = f.Forward(0, x);\n    ok &= NearEqual(v[0] , tan,  eps, eps);\n    ok &= NearEqual(v[1] , tanh,  eps, eps);\n\n    // tan'(x)   = 1 + tan(x)  * tan(x)\n    // tanh'(x)  = 1 - tanh(x) * tanh(x)\n    float tanp  = 1.f + tan * tan;\n    float tanhp = 1.f - tanh * tanh;\n\n    // compute first partial of f w.r.t. x[0] using forward mode\n    CppAD::vector<float> dx(n), dv(m);\n    dx[0] = 1.;\n    dv    = f.Forward(1, dx);\n    ok   &= NearEqual(dv[0] , tanp,   eps, eps);\n    ok   &= NearEqual(dv[1] , tanhp,  eps, eps);\n    ok   &= NearEqual(dv[2] , 0.f,    eps, eps);\n\n    // tan''(x)   = 2 *  tan(x) * tan'(x)\n    // tanh''(x)  = - 2 * tanh(x) * tanh'(x)\n    // Note that second order Taylor coefficient for u half the\n    // corresponding second derivative.\n    float two    = 2;\n    float tanpp  =   two * tan * tanp;\n    float tanhpp = - two * tanh * tanhp;\n\n    // compute second partial of f w.r.t. x[0] using forward mode\n    CppAD::vector<float> ddx(n), ddv(m);\n    ddx[0] = 0.;\n    ddv    = f.Forward(2, ddx);\n    ok   &= NearEqual(two * ddv[0], tanpp, eps, eps);\n    ok   &= NearEqual(two * ddv[1], tanhpp, eps, eps);\n    ok   &= NearEqual(two * ddv[2], 0.f, eps, eps);\n\n/* {xrst_code}\n{xrst_spell_on}\nreverse\n=======\n{xrst_spell_off}\n{xrst_code cpp} */\n    // compute derivative of tan - tanh using reverse mode\n    CppAD::vector<float> w(m), dw(n);\n    w[0]  = 1.;\n    w[1]  = 1.;\n    w[2]  = 0.;\n    dw    = f.Reverse(1, w);\n    ok   &= NearEqual(dw[0], w[0]*tanp + w[1]*tanhp, eps, eps);\n\n    // compute second derivative of tan - tanh using reverse mode\n    CppAD::vector<float> ddw(2);\n    ddw   = f.Reverse(2, w);\n    ok   &= NearEqual(ddw[0], w[0]*tanp  + w[1]*tanhp , eps, eps);\n    ok   &= NearEqual(ddw[1], w[0]*tanpp + w[1]*tanhpp, eps, eps);\n/* {xrst_code}\n{xrst_spell_on}\nfor_jac_sparsity\n================\n{xrst_spell_off}\n{xrst_code cpp} */\n    // forward mode Jacobian sparstiy pattern\n    CppAD::sparse_rc< CPPAD_TESTVECTOR(size_t) > pattern_in, pattern_out;\n    pattern_in.resize(1, 1, 1);\n    pattern_in.set(0, 0, 0);\n    bool transpose     = false;\n    bool dependency    = false;\n    bool internal_bool = false;\n    f.for_jac_sparsity(\n        pattern_in, transpose, dependency, internal_bool, pattern_out\n    );\n    // (0, 0) and (1, 0) are in sparsity pattern\n    ok &= pattern_out.nnz() == 2;\n    ok &= pattern_out.row()[0] == 0;\n    ok &= pattern_out.col()[0] == 0;\n    ok &= pattern_out.row()[1] == 1;\n    ok &= pattern_out.col()[1] == 0;\n/* {xrst_code}\n{xrst_spell_on}\nrev_sparse_hes\n==============\n{xrst_spell_off}\n{xrst_code cpp} */\n    // Hesian sparsity (using previous for_jac_sparsity call)\n    CPPAD_TESTVECTOR(bool) select_y(m);\n    select_y[0] = true;\n    select_y[1] = false;\n    select_y[2] = false;\n    f.rev_hes_sparsity(\n        select_y, transpose, internal_bool, pattern_out\n    );\n    ok &= pattern_out.nnz() == 1;\n    ok &= pattern_out.row()[0] == 0;\n    ok &= pattern_out.col()[0] == 0;\n/* {xrst_code}\n{xrst_spell_on}\nLarge x Values\n==============\n{xrst_spell_off}\n{xrst_code cpp} */\n    // check tanh results for a large value of x\n    x[0]  = std::numeric_limits<float>::max() / two;\n    v     = f.Forward(0, x);\n    tanh  = 1.;\n    ok   &= NearEqual(v[1], tanh, eps, eps);\n    dv    = f.Forward(1, dx);\n    tanhp = 0.;\n    ok   &= NearEqual(dv[1], tanhp, eps, eps);\n\n    return ok;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end atomic_three_tangent.cpp}\n*/\n"
  },
  {
    "path": "example/atomic_two/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n#\n# eigen_sources and CPPAD_HAS_EIGEN\nIF( cppad_has_eigen )\n    SET(eigen_sources eigen_mat_inv.cpp eigen_cholesky.cpp eigen_mat_mul.cpp)\nELSE( cppad_has_eigen )\n    SET(eigen_sources \"\")\nENDIF( cppad_has_eigen )\n#\n# BEGIN_SORT_THIS_LINE_PLUS_2\nSET(source_list\n    ${eigen_sources}\n    atomic_two.cpp\n)\n# END_SORT_THIS_LINE_MINUS_2\n\nset_compile_flags( example_atomic_two \"${cppad_debug_which}\" \"${source_list}\" )\n#\nADD_EXECUTABLE(example_atomic_two EXCLUDE_FROM_ALL ${source_list})\n#\n# List of libraries to be linked into the specified target\nTARGET_LINK_LIBRARIES(example_atomic_two\n    ${cppad_lib}\n    ${colpack_libs}\n)\n#\n# check_example_atomic_two\nadd_check_executable(check_example atomic_two)\n"
  },
  {
    "path": "example/atomic_two/atomic_two.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_two.cpp}\n\natomic_two Examples and Tests Driver\n####################################\n\nRunning These Tests\n*******************\nAfter executing the :ref:`cmake-name` command\nform the :ref:`download@Distribution Directory`,\nyou can build and run these tests with the commands::\n\n    cd build\n    make check_example_atomic_two\n\nNote that your choice of :ref:`cmake@generator` may require using\nan different version of make; e.g., ``ninja`` .\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end atomic_two.cpp}\n-------------------------------------------------------------------------------\n*/\n// BEGIN C++\n\n// CPPAD_HAS_* defines\n# include <cppad/configure.hpp>\n\n// for thread_alloc\n# include <cppad/utility/thread_alloc.hpp>\n\n// test runner\n# include <cppad/utility/test_boolofvoid.hpp>\n\n// external complied tests\nextern bool eigen_cholesky(void);\nextern bool eigen_mat_inv(void);\nextern bool eigen_mat_mul(void);\n\n// main program that runs all the tests\nint main(void)\n{   std::string group = \"example/atomic_two\";\n    size_t      width = 20;\n    CppAD::test_boolofvoid Run(group, width);\n\n    // This line is used by test_one.sh\n\n    // external compiled tests\n# if CPPAD_HAS_EIGEN\n    Run( eigen_cholesky,      \"eigen_cholesky\" );\n    Run( eigen_mat_inv,       \"eigen_mat_inv\"  );\n    Run( eigen_mat_mul,       \"eigen_mat_mul\"  );\n# endif\n    // check for memory leak\n    bool memory_ok = CppAD::thread_alloc::free_all();\n    // print summary at end\n    bool ok = Run.summary(memory_ok);\n    //\n    return static_cast<int>( ! ok );\n}\n// END C++\n"
  },
  {
    "path": "example/atomic_two/eigen_cholesky.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin atomic_two_eigen_cholesky.cpp app}\n{xrst_spell\n    chol\n}\n\nAtomic Eigen Cholesky Factorization: Example and Test\n#####################################################\n\nDescription\n***********\nThe :ref:`ADFun-name` function object *f* for this example is\n\n.. math::\n\n    f(x)\n    =\n    \\R{chol} \\left( \\begin{array}{cc}\n        x_0   & x_1 \\\\\n        x_1   & x_2\n    \\end{array} \\right)\n    =\n    \\frac{1}{ \\sqrt{x_0} }\n    \\left( \\begin{array}{cc}\n        x_0 & 0 \\\\\n        x_1 & \\sqrt{ x_0 x_2 - x_1 x_1 }\n    \\end{array} \\right)\n\nwhere the matrix is positive definite; i.e.,\n:math:`x_0 > 0`, :math:`x_2 > 0` and\n:math:`x_0 x_2 - x_1 x_1 > 0`.\n\nContents\n********\n{xrst_toc_table\n    xrst/theory/cholesky.xrst\n    include/cppad/example/atomic_two/eigen_cholesky.hpp\n}\n\nUse Atomic Function\n*******************\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <cppad/cppad.hpp>\n# include <cppad/example/atomic_two/eigen_cholesky.hpp>\n\nbool eigen_cholesky(void)\n{\n    typedef double scalar;\n    typedef atomic_eigen_cholesky<scalar>::ad_scalar ad_scalar;\n    typedef atomic_eigen_cholesky<scalar>::ad_matrix ad_matrix;\n    //\n    bool ok    = true;\n    scalar eps = 10. * std::numeric_limits<scalar>::epsilon();\n    using CppAD::NearEqual;\n    //\n/* {xrst_code}\n{xrst_spell_on}\nConstructor\n===========\n{xrst_spell_off}\n{xrst_code cpp} */\n    // -------------------------------------------------------------------\n    // object that computes cholesky factor of a matrix\n    atomic_eigen_cholesky<scalar> cholesky;\n    // -------------------------------------------------------------------\n    // declare independent variable vector x\n    size_t n = 3;\n    CPPAD_TESTVECTOR(ad_scalar) ad_x(n);\n    ad_x[0] = 2.0;\n    ad_x[1] = 0.5;\n    ad_x[2] = 3.0;\n    CppAD::Independent(ad_x);\n    // -------------------------------------------------------------------\n    // A = [ x[0]  x[1] ]\n    //     [ x[1]  x[2] ]\n    size_t nr  = 2;\n    ad_matrix ad_A(nr, nr);\n    ad_A(0, 0) = ad_x[0];\n    ad_A(1, 0) = ad_x[1];\n    ad_A(0, 1) = ad_x[1];\n    ad_A(1, 1) = ad_x[2];\n    // -------------------------------------------------------------------\n    // use atomic operation to L such that A = L * L^T\n    ad_matrix ad_L = cholesky.op(ad_A);\n    // -------------------------------------------------------------------\n    // declare the dependent variable vector y\n    size_t m = 3;\n    CPPAD_TESTVECTOR(ad_scalar) ad_y(m);\n    ad_y[0] = ad_L(0, 0);\n    ad_y[1] = ad_L(1, 0);\n    ad_y[2] = ad_L(1, 1);\n    CppAD::ADFun<scalar> f(ad_x, ad_y);\n    // -------------------------------------------------------------------\n    // check zero order forward mode\n    CPPAD_TESTVECTOR(scalar) x(n), y(m);\n    x[0] = 2.0;\n    x[1] = 0.5;\n    x[2] = 5.0;\n    y   = f.Forward(0, x);\n    scalar check;\n    check = std::sqrt( x[0] );\n    ok   &= NearEqual(y[0], check, eps, eps);\n    check = x[1] / std::sqrt( x[0] );\n    ok   &= NearEqual(y[1], check, eps, eps);\n    check = std::sqrt( x[2] - x[1] * x[1] / x[0] );\n    ok   &= NearEqual(y[2], check, eps, eps);\n    // -------------------------------------------------------------------\n    // check first order forward mode\n    CPPAD_TESTVECTOR(scalar) x1(n), y1(m);\n    //\n    // partial w.r.t. x[0]\n    x1[0] = 1.0;\n    x1[1] = 0.0;\n    x1[2] = 0.0;\n    //\n    y1    = f.Forward(1, x1);\n    check = 1.0 / (2.0 * std::sqrt( x[0] ) );\n    ok   &= NearEqual(y1[0], check, eps, eps);\n    //\n    check = - x[1] / (2.0 * x[0] * std::sqrt( x[0] ) );\n    ok   &= NearEqual(y1[1], check, eps, eps);\n    //\n    check = std::sqrt( x[2] - x[1] * x[1] / x[0] );\n    check = x[1] * x[1] / (x[0] * x[0] * 2.0 * check);\n    ok   &= NearEqual(y1[2], check, eps, eps);\n    //\n    // partial w.r.t. x[1]\n    x1[0] = 0.0;\n    x1[1] = 1.0;\n    x1[2] = 0.0;\n    //\n    y1    = f.Forward(1, x1);\n    ok   &= NearEqual(y1[0], 0.0, eps, eps);\n    //\n    check = 1.0 / std::sqrt( x[0] );\n    ok   &= NearEqual(y1[1], check, eps, eps);\n    //\n    check = std::sqrt( x[2] - x[1] * x[1] / x[0] );\n    check = - 2.0 * x[1] / (2.0 * check * x[0] );\n    ok   &= NearEqual(y1[2], check, eps, eps);\n    //\n    // partial w.r.t. x[2]\n    x1[0] = 0.0;\n    x1[1] = 0.0;\n    x1[2] = 1.0;\n    //\n    y1    = f.Forward(1, x1);\n    ok   &= NearEqual(y1[0], 0.0, eps, eps);\n    ok   &= NearEqual(y1[1], 0.0, eps, eps);\n    //\n    check = std::sqrt( x[2] - x[1] * x[1] / x[0] );\n    check = 1.0 / (2.0 * check);\n    ok   &= NearEqual(y1[2], check, eps, eps);\n    // -------------------------------------------------------------------\n    // check second order forward mode\n    CPPAD_TESTVECTOR(scalar) x2(n), y2(m);\n    //\n    // second partial w.r.t x[2]\n    x2[0] = 0.0;\n    x2[1] = 0.0;\n    x2[2] = 0.0;\n    y2    = f.Forward(2, x2);\n    ok   &= NearEqual(y2[0], 0.0, eps, eps);\n    ok   &= NearEqual(y2[1], 0.0, eps, eps);\n    //\n    check = std::sqrt( x[2] - x[1] * x[1] / x[0] );  // function value\n    check = - 1.0 / ( 4.0 * check * check * check ); // second derivative\n    check = 0.5 * check;                             // taylor coefficient\n    ok   &= NearEqual(y2[2], check, eps, eps);\n    // -------------------------------------------------------------------\n    // check first order reverse mode\n    CPPAD_TESTVECTOR(scalar) w(m), d1w(n);\n    w[0] = 0.0;\n    w[1] = 0.0;\n    w[2] = 1.0;\n    d1w  = f.Reverse(1, w);\n    //\n    // partial of f[2] w.r.t x[0]\n    scalar f2    = std::sqrt( x[2] - x[1] * x[1] / x[0] );\n    scalar f2_x0 = x[1] * x[1] / (2.0 * f2 * x[0] * x[0] );\n    ok          &= NearEqual(d1w[0], f2_x0, eps, eps);\n    //\n    // partial of f[2] w.r.t x[1]\n    scalar f2_x1 = - x[1] / (f2 * x[0] );\n    ok          &= NearEqual(d1w[1], f2_x1, eps, eps);\n    //\n    // partial of f[2] w.r.t x[2]\n    scalar f2_x2 = 1.0 / (2.0 * f2 );\n    ok          &= NearEqual(d1w[2], f2_x2, eps, eps);\n    // -------------------------------------------------------------------\n    // check second order reverse mode\n    CPPAD_TESTVECTOR(scalar) d2w(2 * n);\n    d2w  = f.Reverse(2, w);\n    //\n    // check first order results\n    ok &= NearEqual(d2w[0 * 2 + 0], f2_x0, eps, eps);\n    ok &= NearEqual(d2w[1 * 2 + 0], f2_x1, eps, eps);\n    ok &= NearEqual(d2w[2 * 2 + 0], f2_x2, eps, eps);\n    //\n    // check second order results\n    scalar f2_x2_x0 = - 0.5 * f2_x0 / (f2 * f2 );\n    ok             &= NearEqual(d2w[0 * 2 + 1], f2_x2_x0, eps, eps);\n    scalar f2_x2_x1 = - 0.5 * f2_x1 / (f2 * f2 );\n    ok             &= NearEqual(d2w[1 * 2 + 1], f2_x2_x1, eps, eps);\n    scalar f2_x2_x2 = - 0.5 * f2_x2 / (f2 * f2 );\n    ok             &= NearEqual(d2w[2 * 2 + 1], f2_x2_x2, eps, eps);\n    // -------------------------------------------------------------------\n    // check third order reverse mode\n    CPPAD_TESTVECTOR(scalar) d3w(3 * n);\n    d3w  = f.Reverse(3, w);\n    //\n    // check first order results\n    ok &= NearEqual(d3w[0 * 3 + 0], f2_x0, eps, eps);\n    ok &= NearEqual(d3w[1 * 3 + 0], f2_x1, eps, eps);\n    ok &= NearEqual(d3w[2 * 3 + 0], f2_x2, eps, eps);\n    //\n    // check second order results\n    ok             &= NearEqual(d3w[0 * 3 + 1], f2_x2_x0, eps, eps);\n    ok             &= NearEqual(d3w[1 * 3 + 1], f2_x2_x1, eps, eps);\n    ok             &= NearEqual(d3w[2 * 3 + 1], f2_x2_x2, eps, eps);\n    // -------------------------------------------------------------------\n    scalar f2_x2_x2_x0 = - 0.5 * f2_x2_x0 / (f2 * f2);\n    f2_x2_x2_x0 += f2_x2 * f2_x0 / (f2 * f2 * f2);\n    ok          &= NearEqual(d3w[0 * 3 + 2], 0.5 * f2_x2_x2_x0, eps, eps);\n    scalar f2_x2_x2_x1 = - 0.5 * f2_x2_x1 / (f2 * f2);\n    f2_x2_x2_x1 += f2_x2 * f2_x1 / (f2 * f2 * f2);\n    ok          &= NearEqual(d3w[1 * 3 + 2], 0.5 * f2_x2_x2_x1, eps, eps);\n    scalar f2_x2_x2_x2 = - 0.5 * f2_x2_x2 / (f2 * f2);\n    f2_x2_x2_x2 += f2_x2 * f2_x2 / (f2 * f2 * f2);\n    ok          &= NearEqual(d3w[2 * 3 + 2], 0.5 * f2_x2_x2_x2, eps, eps);\n    return ok;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end atomic_two_eigen_cholesky.cpp}\n*/\n"
  },
  {
    "path": "example/atomic_two/eigen_mat_inv.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin atomic_two_eigen_mat_inv.cpp app}\n\nAtomic Eigen Matrix Inverse: Example and Test\n#############################################\n\nDescription\n***********\nThe :ref:`ADFun-name` function object *f* for this example is\n\n.. math::\n\n    f(x) =\n    \\left( \\begin{array}{cc}\n        x_0   & 0 \\\\\n        0   & x_1\n    \\end{array} \\right)^{-1}\n    \\left( \\begin{array}{c}\n        0   \\\\\n        x_2\n    \\end{array} \\right)\n    =\n    \\left( \\begin{array}{c}\n        0 \\\\\n        x_2 / x_1 )\n    \\end{array} \\right)\n\n{xrst_toc_hidden\n    include/cppad/example/atomic_two/eigen_mat_inv.hpp\n}\n\nClass Definition\n****************\nThis example uses the file :ref:`atomic_two_eigen_mat_inv.hpp-name`\nwhich defines matrix multiply as a :ref:`atomic_two-name` operation.\n\nUse Atomic Function\n*******************\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <cppad/cppad.hpp>\n# include <cppad/example/atomic_two/eigen_mat_inv.hpp>\n# include <cppad/example/atomic_two/eigen_mat_mul.hpp>\n\nbool eigen_mat_inv(void)\n{\n    typedef double                                   scalar;\n    typedef CppAD::AD<scalar>                        ad_scalar;\n    typedef atomic_eigen_mat_inv<scalar>::ad_matrix  ad_matrix;\n    //\n    bool ok    = true;\n    scalar eps = 10. * std::numeric_limits<scalar>::epsilon();\n    using CppAD::NearEqual;\n    //\n/* {xrst_code}\n{xrst_spell_on}\nConstructor\n===========\n{xrst_spell_off}\n{xrst_code cpp} */\n    // -------------------------------------------------------------------\n    // object that multiplies matrices\n    atomic_eigen_mat_mul<scalar> mat_mul;\n    // -------------------------------------------------------------------\n    // object that computes inverse of a square matrix\n    atomic_eigen_mat_inv<scalar> mat_inv;\n    // -------------------------------------------------------------------\n    // declare independent variable vector x\n    size_t n = 3;\n    CPPAD_TESTVECTOR(ad_scalar) ad_x(n);\n    for(size_t j = 0; j < n; j++)\n        ad_x[j] = ad_scalar(j + 1);\n    CppAD::Independent(ad_x);\n    // -------------------------------------------------------------------\n    // left = [ x[0]  0    ]\n    //        [ 0     x[1] ]\n    size_t nr_left  = 2;\n    ad_matrix ad_left(nr_left, nr_left);\n    ad_left(0, 0) = ad_x[0];\n    ad_left(0, 1) = ad_scalar(0.0);\n    ad_left(1, 0) = ad_scalar(0.0);\n    ad_left(1, 1) = ad_x[1];\n    // -------------------------------------------------------------------\n    // right = [ 0 , x[2] ]^T\n    size_t nc_right = 1;\n    ad_matrix ad_right(nr_left, nc_right);\n    ad_right(0, 0) = ad_scalar(0.0);\n    ad_right(1, 0) = ad_x[2];\n    // -------------------------------------------------------------------\n    // use atomic operation to compute left^{-1}\n    ad_matrix ad_left_inv = mat_inv.op(ad_left);\n    // use atomic operation to multiply left^{-1} * right\n    ad_matrix ad_result   = mat_mul.op(ad_left_inv, ad_right);\n    // -------------------------------------------------------------------\n    // declare the dependent variable vector y\n    size_t m = 2;\n    CPPAD_TESTVECTOR(ad_scalar) ad_y(2);\n    for(size_t i = 0; i < m; i++)\n        ad_y[i] = ad_result( long(i), 0);\n    CppAD::ADFun<scalar> f(ad_x, ad_y);\n    // -------------------------------------------------------------------\n    // check zero order forward mode\n    CPPAD_TESTVECTOR(scalar) x(n), y(m);\n    for(size_t i = 0; i < n; i++)\n        x[i] = scalar(i + 2);\n    y   = f.Forward(0, x);\n    ok &= NearEqual(y[0], 0.0,          eps, eps);\n    ok &= NearEqual(y[1], x[2] / x[1],  eps, eps);\n    // -------------------------------------------------------------------\n    // check first order forward mode\n    CPPAD_TESTVECTOR(scalar) x1(n), y1(m);\n    x1[0] = 1.0;\n    x1[1] = 0.0;\n    x1[2] = 0.0;\n    y1    = f.Forward(1, x1);\n    ok   &= NearEqual(y1[0], 0.0,        eps, eps);\n    ok   &= NearEqual(y1[1], 0.0,        eps, eps);\n    x1[0] = 0.0;\n    x1[1] = 0.0;\n    x1[2] = 1.0;\n    y1    = f.Forward(1, x1);\n    ok   &= NearEqual(y1[0], 0.0,        eps, eps);\n    ok   &= NearEqual(y1[1], 1.0 / x[1], eps, eps);\n    x1[0] = 0.0;\n    x1[1] = 1.0;\n    x1[2] = 0.0;\n    y1    = f.Forward(1, x1);\n    ok   &= NearEqual(y1[0], 0.0,                  eps, eps);\n    ok   &= NearEqual(y1[1], - x[2] / (x[1]*x[1]), eps, eps);\n    // -------------------------------------------------------------------\n    // check second order forward mode\n    CPPAD_TESTVECTOR(scalar) x2(n), y2(m);\n    x2[0] = 0.0;\n    x2[1] = 0.0;\n    x2[2] = 0.0;\n    scalar  f1_x1_x1 = 2.0 * x[2] / (x[1] * x[1] * x[1] );\n    y2    = f.Forward(2, x2);\n    ok   &= NearEqual(y2[0], 0.0,            eps, eps);\n    ok   &= NearEqual(y2[1], f1_x1_x1 / 2.0, eps, eps);\n    // -------------------------------------------------------------------\n    // check first order reverse\n    CPPAD_TESTVECTOR(scalar) w(m), d1w(n);\n    w[0] = 1.0;\n    w[1] = 0.0;\n    d1w  = f.Reverse(1, w);\n    ok  &= NearEqual(d1w[0], 0.0, eps, eps);\n    ok  &= NearEqual(d1w[1], 0.0, eps, eps);\n    ok  &= NearEqual(d1w[2], 0.0, eps, eps);\n    w[0] = 0.0;\n    w[1] = 1.0;\n    d1w  = f.Reverse(1, w);\n    ok  &= NearEqual(d1w[0], 0.0,                  eps, eps);\n    ok  &= NearEqual(d1w[1], - x[2] / (x[1]*x[1]), eps, eps);\n    ok  &= NearEqual(d1w[2], 1.0 / x[1],           eps, eps);\n    // -------------------------------------------------------------------\n    // check second order reverse\n    CPPAD_TESTVECTOR(scalar) d2w(2 * n);\n    d2w  = f.Reverse(2, w);\n    // partial f_1 w.r.t x_0\n    ok  &= NearEqual(d2w[0 * 2 + 0], 0.0,                  eps, eps);\n    // partial f_1 w.r.t x_1\n    ok  &= NearEqual(d2w[1 * 2 + 0], - x[2] / (x[1]*x[1]), eps, eps);\n    // partial f_1 w.r.t x_2\n    ok  &= NearEqual(d2w[2 * 2 + 0], 1.0 / x[1],           eps, eps);\n    // partial f_1 w.r.t x_1, x_0\n    ok  &= NearEqual(d2w[0 * 2 + 1], 0.0,                  eps, eps);\n    // partial f_1 w.r.t x_1, x_1\n    ok  &= NearEqual(d2w[1 * 2 + 1], f1_x1_x1,             eps, eps);\n    // partial f_1 w.r.t x_1, x_2\n    ok  &= NearEqual(d2w[2 * 2 + 1], - 1.0 / (x[1]*x[1]),  eps, eps);\n    // -------------------------------------------------------------------\n    return ok;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end atomic_two_eigen_mat_inv.cpp}\n*/\n"
  },
  {
    "path": "example/atomic_two/eigen_mat_mul.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin atomic_two_eigen_mat_mul.cpp app}\n\nAtomic Eigen Matrix Multiply: Example and Test\n##############################################\n\nDescription\n***********\nThe :ref:`ADFun-name` function object *f* for this example is\n\n.. math::\n\n    f(x) =\n    \\left( \\begin{array}{cc}\n        0   & 0 \\\\\n        1   & 2 \\\\\n        x_0 & x_1\n    \\end{array} \\right)\n    \\left( \\begin{array}{c}\n        x_0 \\\\\n        x_1\n    \\end{array} \\right)\n    =\n    \\left( \\begin{array}{c}\n        0 \\\\\n        x_0 + 2 x_1 \\\\\n        x_0 x_0 + x_1 x_1 )\n    \\end{array} \\right)\n\n{xrst_toc_hidden\n    include/cppad/example/atomic_two/eigen_mat_mul.hpp\n}\n\nClass Definition\n****************\nThis example uses the file :ref:`atomic_two_eigen_mat_mul.hpp-name`\nwhich defines matrix multiply as a :ref:`atomic_two-name` operation.\n\nUse Atomic Function\n*******************\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <cppad/cppad.hpp>\n# include <cppad/example/atomic_two/eigen_mat_mul.hpp>\n\nbool eigen_mat_mul(void)\n{  //\n    typedef double                                   scalar;\n    typedef CppAD::AD<scalar>                        ad_scalar;\n    typedef atomic_eigen_mat_mul<scalar>::ad_matrix  ad_matrix;\n    //\n    bool ok    = true;\n    scalar eps = 10. * std::numeric_limits<scalar>::epsilon();\n    using CppAD::NearEqual;\n    //\n/* {xrst_code}\n{xrst_spell_on}\nConstructor\n===========\n{xrst_spell_off}\n{xrst_code cpp} */\n    // -------------------------------------------------------------------\n    // object that multiplies arbitrary matrices\n    atomic_eigen_mat_mul<scalar> mat_mul;\n    // -------------------------------------------------------------------\n    // declare independent variable vector x\n    size_t n = 2;\n    CPPAD_TESTVECTOR(ad_scalar) ad_x(n);\n    for(size_t j = 0; j < n; j++)\n        ad_x[j] = ad_scalar(j);\n    CppAD::Independent(ad_x);\n    // -------------------------------------------------------------------\n    //        [ 0     0    ]\n    // left = [ 1     2    ]\n    //        [ x[0]  x[1] ]\n    size_t nr_left  = 3;\n    size_t n_middle   = 2;\n    ad_matrix ad_left(nr_left, n_middle);\n    ad_left(0, 0) = ad_scalar(0.0);\n    ad_left(0, 1) = ad_scalar(0.0);\n    ad_left(1, 0) = ad_scalar(1.0);\n    ad_left(1, 1) = ad_scalar(2.0);\n    ad_left(2, 0) = ad_x[0];\n    ad_left(2, 1) = ad_x[1];\n    // -------------------------------------------------------------------\n    // right = [ x[0] , x[1] ]^T\n    size_t nc_right = 1;\n    ad_matrix ad_right(n_middle, nc_right);\n    ad_right(0, 0) = ad_x[0];\n    ad_right(1, 0) = ad_x[1];\n    // -------------------------------------------------------------------\n    // use atomic operation to multiply left * right\n    ad_matrix ad_result = mat_mul.op(ad_left, ad_right);\n    // -------------------------------------------------------------------\n    // check that first component of result is a parameter\n    // and the other components are variables.\n    ok &= Parameter( ad_result(0, 0) );\n    ok &= Variable(  ad_result(1, 0) );\n    ok &= Variable(  ad_result(2, 0) );\n    // -------------------------------------------------------------------\n    // declare the dependent variable vector y\n    size_t m = 3;\n    CPPAD_TESTVECTOR(ad_scalar) ad_y(m);\n    for(size_t i = 0; i < m; i++)\n        ad_y[i] = ad_result(long(i), 0);\n    CppAD::ADFun<scalar> f(ad_x, ad_y);\n    // -------------------------------------------------------------------\n    // check zero order forward mode\n    CPPAD_TESTVECTOR(scalar) x(n), y(m);\n    for(size_t i = 0; i < n; i++)\n        x[i] = scalar(i + 2);\n    y   = f.Forward(0, x);\n    ok &= NearEqual(y[0], 0.0,                       eps, eps);\n    ok &= NearEqual(y[1], x[0] + 2.0 * x[1],         eps, eps);\n    ok &= NearEqual(y[2], x[0] * x[0] + x[1] * x[1], eps, eps);\n    // -------------------------------------------------------------------\n    // check first order forward mode\n    CPPAD_TESTVECTOR(scalar) x1(n), y1(m);\n    x1[0] = 1.0;\n    x1[1] = 0.0;\n    y1    = f.Forward(1, x1);\n    ok   &= NearEqual(y1[0], 0.0,        eps, eps);\n    ok   &= NearEqual(y1[1], 1.0,        eps, eps);\n    ok   &= NearEqual(y1[2], 2.0 * x[0], eps, eps);\n    x1[0] = 0.0;\n    x1[1] = 1.0;\n    y1    = f.Forward(1, x1);\n    ok   &= NearEqual(y1[0], 0.0,        eps, eps);\n    ok   &= NearEqual(y1[1], 2.0,        eps, eps);\n    ok   &= NearEqual(y1[2], 2.0 * x[1], eps, eps);\n    // -------------------------------------------------------------------\n    // check second order forward mode\n    CPPAD_TESTVECTOR(scalar) x2(n), y2(m);\n    x2[0] = 0.0;\n    x2[1] = 0.0;\n    y2    = f.Forward(2, x2);\n    ok   &= NearEqual(y2[0], 0.0, eps, eps);\n    ok   &= NearEqual(y2[1], 0.0, eps, eps);\n    ok   &= NearEqual(y2[2], 1.0, eps, eps); // 1/2 * f_1''(x)\n    // -------------------------------------------------------------------\n    // check first order reverse mode\n    CPPAD_TESTVECTOR(scalar) w(m), d1w(n);\n    w[0]  = 0.0;\n    w[1]  = 1.0;\n    w[2]  = 0.0;\n    d1w   = f.Reverse(1, w);\n    ok   &= NearEqual(d1w[0], 1.0, eps, eps);\n    ok   &= NearEqual(d1w[1], 2.0, eps, eps);\n    w[0]  = 0.0;\n    w[1]  = 0.0;\n    w[2]  = 1.0;\n    d1w   = f.Reverse(1, w);\n    ok   &= NearEqual(d1w[0], 2.0 * x[0], eps, eps);\n    ok   &= NearEqual(d1w[1], 2.0 * x[1], eps, eps);\n    // -------------------------------------------------------------------\n    // check second order reverse mode\n    CPPAD_TESTVECTOR(scalar) d2w(2 * n);\n    d2w   = f.Reverse(2, w);\n    // partial f_2 w.r.t. x_0\n    ok   &= NearEqual(d2w[0 * 2 + 0], 2.0 * x[0], eps, eps);\n    // partial f_2 w.r.t  x_1\n    ok   &= NearEqual(d2w[1 * 2 + 0], 2.0 * x[1], eps, eps);\n    // partial f_2 w.r.t x_1, x_0\n    ok   &= NearEqual(d2w[0 * 2 + 1], 0.0,        eps, eps);\n    // partial f_2 w.r.t x_1, x_1\n    ok   &= NearEqual(d2w[1 * 2 + 1], 2.0,        eps, eps);\n    // -------------------------------------------------------------------\n    // check forward Jacobian sparsity\n    CPPAD_TESTVECTOR( std::set<size_t> ) r(n), s(m);\n    std::set<size_t> check_set;\n    for(size_t j = 0; j < n; j++)\n        r[j].insert(j);\n    s      = f.ForSparseJac(n, r);\n    check_set.clear();\n    ok    &= s[0] == check_set;\n    check_set.insert(0);\n    check_set.insert(1);\n    ok    &= s[1] == check_set;\n    ok    &= s[2] == check_set;\n    // -------------------------------------------------------------------\n    // check reverse Jacobian sparsity\n    r.resize(m);\n    for(size_t i = 0; i < m; i++)\n        r[i].insert(i);\n    s  = f.RevSparseJac(m, r);\n    check_set.clear();\n    ok    &= s[0] == check_set;\n    check_set.insert(0);\n    check_set.insert(1);\n    ok    &= s[1] == check_set;\n    ok    &= s[2] == check_set;\n    // -------------------------------------------------------------------\n    // check forward Hessian sparsity for f_2 (x)\n    CPPAD_TESTVECTOR( std::set<size_t> ) r2(1), s2(1), h(n);\n    for(size_t j = 0; j < n; j++)\n        r2[0].insert(j);\n    s2[0].clear();\n    s2[0].insert(2);\n    h = f.ForSparseHes(r2, s2);\n    check_set.clear();\n    check_set.insert(0);\n    ok &= h[0] == check_set;\n    check_set.clear();\n    check_set.insert(1);\n    ok &= h[1] == check_set;\n    // -------------------------------------------------------------------\n    // check reverse Hessian sparsity for f_2 (x)\n    CPPAD_TESTVECTOR( std::set<size_t> ) s3(1);\n    s3[0].clear();\n    s3[0].insert(2);\n    h = f.RevSparseHes(n, s3);\n    check_set.clear();\n    check_set.insert(0);\n    ok &= h[0] == check_set;\n    check_set.clear();\n    check_set.insert(1);\n    ok &= h[1] == check_set;\n    // -------------------------------------------------------------------\n    return ok;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end atomic_two_eigen_mat_mul.cpp}\n*/\n"
  },
  {
    "path": "example/chkpoint_two/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n#\n# BEGIN_SORT_THIS_LINE_PLUS_2\nSET(source_list\n    base2ad.cpp\n    chkpoint_two.cpp\n    compare.cpp\n    dynamic.cpp\n    get_started.cpp\n    ode.cpp\n)\n# END_SORT_THIS_LINE_MINUS_2\n\nset_compile_flags( example_chkpoint_two \"${cppad_debug_which}\" \"${source_list}\" )\n#\nADD_EXECUTABLE(example_chkpoint_two EXCLUDE_FROM_ALL ${source_list})\n#\n# List of libraries to be linked into the specified target\nTARGET_LINK_LIBRARIES(example_chkpoint_two\n    ${cppad_lib}\n    ${colpack_libs}\n)\n#\n# check_example_chkpoint_two\nadd_check_executable(check_example chkpoint_two)\n"
  },
  {
    "path": "example/chkpoint_two/base2ad.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin chkpoint_two_base2ad.cpp}\n\nCheckpointing With base2ad: Example and Test\n############################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end chkpoint_two_base2ad.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n\nnamespace {\n    using CppAD::AD;\n    typedef CPPAD_TESTVECTOR(AD<double>)            ADVector;\n    typedef CPPAD_TESTVECTOR(size_t)                size_vector;\n\n    // f(y) = ( 3*y[0], 3*y[1] )\n    void f_algo(const ADVector& y, ADVector& z)\n    {   z[0] = 0.0;\n        z[1] = 0.0;\n        for(size_t k = 0; k < 3; k++)\n        {   z[0] += y[0];\n            z[1] += y[1];\n        }\n        return;\n    }\n    // g(x) = ( x[0]^3, x[1]^3 )\n    void g_algo(const ADVector& x, ADVector& y)\n    {   y[0] = 1.0;\n        y[1] = 1.0;\n        for(size_t k = 0; k < 3; k++)\n        {   y[0] *= x[0];\n            y[1] *= x[1];\n        }\n        return;\n    }\n}\nbool base2ad(void)\n{   bool ok = true;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // AD vectors holding x, y, and z values\n    size_t nx = 2, ny = 2, nz = 2;\n    ADVector ax(nx), ay(ny), az(nz);\n\n    // record the function g_fun(x)\n    for(size_t j = 0; j < nx; j++)\n        ax[j] = double(j + 1);\n    Independent(ax);\n    g_algo(ax, ay);\n    CppAD::ADFun<double> g_fun(ax, ay);\n\n    // record the function f_fun(y)\n    Independent(ay);\n    f_algo(ay, az);\n    CppAD::ADFun<double> f_fun(ay, az);\n\n    // create checkpoint versions of f and g\n    bool internal_bool    = true;\n    bool use_hes_sparsity = true;\n    bool use_base2ad      = true;\n    bool use_in_parallel  = false;\n    CppAD::chkpoint_two<double> f_chk(f_fun, \"f_chk\",\n        internal_bool, use_hes_sparsity, use_base2ad, use_in_parallel\n    );\n    CppAD::chkpoint_two<double> g_chk(g_fun, \"g_chk\",\n        internal_bool, use_hes_sparsity, use_base2ad, use_in_parallel\n    );\n\n    // Record a version of z = f[g(x)] = h(x) with checkpointing\n    // h(x) = [ 3*x[0]^3 , 3*x[1]^3 ]\n    Independent(ax);\n    g_chk(ax, ay);\n    f_chk(ay, az);\n    CppAD::ADFun<double> h_fun(ax, az);\n\n    // Use base2ad to create and AD<double> version of h\n    CppAD::ADFun< AD<double>, double> ah_fun = h_fun.base2ad();\n\n    // start recording AD<Base> operations\n    Independent(ax);\n\n    // record evaluate derivative of h_0 (x)\n    az = ah_fun.Forward(0, ax);\n    ADVector aw(nz), adw(nx);\n    aw[0] = 1.0;\n    for(size_t i = 1; i < nz; ++i)\n        aw[i] = 0.0;\n    adw = ah_fun.Reverse(1, aw);\n    // k(x) = h_0 '(x) = [ 9*x[0]^2 , 0.0 ]\n    CppAD::ADFun<double> k_fun(ax, adw);\n\n    // Evaluate the Jacobian of k(x)\n    CPPAD_TESTVECTOR(double) x(nx);\n    for(size_t j = 0; j < nx; ++j)\n        x[j] = 2.0 + double(nx - j);\n    CPPAD_TESTVECTOR(double) J = k_fun.Jacobian(x);\n\n    // check result\n    for(size_t i = 0; i < nz; ++i)\n    {   for(size_t j = 0; j < nx; ++j)\n        {   double Jij = J[i * nx + j];\n            if( i == 0 && j == 0 )\n            {   double check = 18.0 * x[0];\n                ok &= CppAD::NearEqual(Jij, check, eps99, eps99);\n            }\n            else\n                ok &= Jij == 0.0;\n        }\n    }\n\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/chkpoint_two/chkpoint_two.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin chkpoint_two.cpp}\n\nchkpoint_two Examples and Tests Driver\n######################################\n\nRunning These Tests\n*******************\nAfter executing the :ref:`cmake-name` command\nform the :ref:`download@Distribution Directory`,\nyou can build and run these tests with the commands::\n\n    cd build\n    make check_example_chkpoint_two\n\nNote that your choice of :ref:`cmake@generator` may require using\nan different version of make; e.g., ``ninja`` .\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end chkpoint_two.cpp}\n-------------------------------------------------------------------------------\n*/\n// BEGIN C++\n\n// CPPAD_HAS_* defines\n# include <cppad/configure.hpp>\n\n// for thread_alloc\n# include <cppad/utility/thread_alloc.hpp>\n\n// test runner\n# include <cppad/utility/test_boolofvoid.hpp>\n\n// external complied tests\nextern bool base2ad(void);\nextern bool compare(void);\nextern bool dynamic(void);\nextern bool get_started(void);\nextern bool ode(void);\n\n// main program that runs all the tests\nint main(void)\n{   std::string group = \"example/chkpoint_two\";\n    size_t      width = 20;\n    CppAD::test_boolofvoid Run(group, width);\n\n    // This line is used by test_one.sh\n\n    // external compiled tests\n    Run( base2ad,             \"base2ad\"        );\n    Run( compare,             \"compare\"        );\n    Run( dynamic,             \"dynamic\"        );\n    Run( get_started,         \"get_started\"    );\n    Run( ode,                 \"ode\"            );\n    //\n    // check for memory leak\n    bool memory_ok = CppAD::thread_alloc::free_all();\n    // print summary at end\n    bool ok = Run.summary(memory_ok);\n    //\n    return static_cast<int>( ! ok );\n}\n// END C++\n"
  },
  {
    "path": "example/chkpoint_two/compare.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin chkpoint_two_compare.cpp}\n\nCompare With and Without Checkpointing: Example and Test\n########################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end chkpoint_two_compare.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n\nnamespace {\n    using CppAD::AD;\n    typedef CPPAD_TESTVECTOR(AD<double>)            ADVector;\n    typedef CPPAD_TESTVECTOR(size_t)                size_vector;\n\n    void f_algo(const ADVector& y, ADVector& z)\n    {   z[0] = 0.0;\n        z[1] = 0.0;\n        for(size_t k = 0; k < 3; k++)\n        {   z[0] += y[0];\n            z[1] += y[1];\n        }\n        return;\n    }\n    void g_algo(const ADVector& x, ADVector& y)\n    {   y[0] = 1.0;\n        y[1] = 1.0;\n        for(size_t k = 0; k < 3; k++)\n        {   y[0] *= x[0];\n            y[1] *= x[1];\n        }\n        return;\n    }\n    bool equal(\n         const CppAD::sparse_rc<size_vector>& pattern_left  ,\n         const CppAD::sparse_rc<size_vector>& pattern_right )\n    {\n        size_vector row_major_left = pattern_left.row_major();\n        size_vector row_major_right = pattern_right.row_major();\n        bool ok = pattern_left.nnz() == pattern_right.nnz();\n        if( ! ok )\n            return ok;\n        for(size_t k = 0; k < pattern_left.nnz(); ++k)\n        {   size_t r_left = pattern_left.row()[ row_major_left[k] ];\n            size_t c_left = pattern_left.col()[ row_major_left[k] ];\n            size_t r_right = pattern_right.row()[ row_major_right[k] ];\n            size_t c_right = pattern_right.col()[ row_major_right[k] ];\n            ok &= (r_left == r_right) && (c_left == c_right);\n        }\n        return ok;\n    }\n}\nbool compare(void)\n{   bool ok = true;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // AD vectors holding x, y, and z values\n    size_t nx = 2, ny = 2, nz = 2;\n    ADVector ax(nx), ay(ny), az(nz);\n\n    // record the function g_fun(x)\n    for(size_t j = 0; j < nx; j++)\n        ax[j] = double(j + 1);\n    Independent(ax);\n    g_algo(ax, ay);\n    CppAD::ADFun<double> g_fun(ax, ay);\n\n    // record the function f_fun(y)\n    Independent(ay);\n    f_algo(ay, az);\n    CppAD::ADFun<double> f_fun(ay, az);\n\n    // create checkpoint versions of f and g\n    bool internal_bool    = true;\n    bool use_hes_sparsity = true;\n    bool use_base2ad      = false;\n    bool use_in_parallel  = false;\n    CppAD::chkpoint_two<double> f_chk(f_fun, \"f_chk\",\n        internal_bool, use_hes_sparsity, use_base2ad, use_in_parallel\n    );\n    CppAD::chkpoint_two<double> g_chk(g_fun, \"g_chk\",\n        internal_bool, use_hes_sparsity, use_base2ad, use_in_parallel\n    );\n\n    // Record a version of z = f[g(x)] without checkpointing\n    Independent(ax);\n    g_algo(ax, ay);\n    f_algo(ay, az);\n    CppAD::ADFun<double> check_not(ax, az);\n\n    // Record a version of z = f[g(x)] with checkpointing\n    Independent(ax);\n    g_chk(ax, ay);\n    f_chk(ay, az);\n    CppAD::ADFun<double> check_yes(ax, az);\n\n    // checkpointing should use fewer operations\n    ok &= check_not.size_var() > check_yes.size_var();\n\n    // this does not really save space because f and g are only used once\n    ok &= check_not.size_var() <= check_yes.size_var()\n        + f_fun.size_var() + g_fun.size_var();\n\n    // compare forward mode results for orders 0, 1, 2\n    size_t q1 = 3; // order_up + 1\n    CPPAD_TESTVECTOR(double) x_q(nx*q1), z_not(nz*q1), z_yes(nz*q1);\n    for(size_t j = 0; j < nx; j++)\n    {   for(size_t k = 0; k < q1; k++)\n            x_q[ j * q1 + k ] = 1.0 / double(q1 - k);\n    }\n    z_not = check_not.Forward(q1-1, x_q);\n    z_yes = check_yes.Forward(q1-1, x_q);\n    for(size_t i = 0; i < nz; i++)\n    {   for(size_t k = 0; k < q1; k++)\n        {   double zik_not = z_not[ i * q1 + k];\n            double zik_yes = z_yes[ i * q1 + k];\n            ok &= NearEqual(zik_not, zik_yes, eps99, eps99);\n        }\n    }\n\n    // compare reverse mode results for orders 0, 1, 2\n    CPPAD_TESTVECTOR(double) w(nz*q1), dw_not(nx*q1), dw_yes(nx*q1);\n    for(size_t i = 0; i < nz * q1; i++)\n        w[i] = 1.0 / double(i + 1);\n    dw_not = check_not.Reverse(q1, w);\n    dw_yes = check_yes.Reverse(q1, w);\n    for(size_t j = 0; j < nx; j++)\n    {   for(size_t k = 0; k < q1; k++)\n        {   double dwjk_not = dw_not[ j * q1 + k];\n            double dwjk_yes = dw_yes[ j * q1 + k];\n            ok &= NearEqual(dwjk_not, dwjk_yes, eps99, eps99);\n        }\n    }\n\n    // compare Jacobian sparsity patterns\n    CppAD::sparse_rc<size_vector> pattern_in, pattern_not, pattern_yes;\n    pattern_in.resize(nx, nx, nx);\n    for(size_t k = 0; k < nx; ++k)\n        pattern_in.set(k, k, k);\n    bool transpose     = false;\n    bool dependency    = false;\n    internal_bool      = false;\n    // for_jac_sparsity (not internal_bool is false)\n    check_not.for_jac_sparsity(\n        pattern_in, transpose, dependency, internal_bool, pattern_not\n    );\n    pattern_in.resize(nz, nz, nz);\n    for(size_t k = 0; k < nz; ++k)\n        pattern_in.set(k, k, k);\n    // forward and reverse Jacobian sparsity should give same answer\n    check_yes.rev_jac_sparsity(\n        pattern_in, transpose, dependency, internal_bool, pattern_yes\n    );\n    ok &= equal(pattern_not, pattern_yes );\n\n    // compare Hessian sparsity patterns\n    CPPAD_TESTVECTOR(bool) select_x(nx), select_z(nz);\n    for(size_t j = 0; j < nx; ++j)\n        select_x[j] = true;\n    for(size_t i = 0; i < nz; ++i)\n        select_z[i] = true;\n    transpose       = false;\n    // Reverse should give same results as forward because\n    // previous for_jac_sparsity used identity for pattern_in.\n    // Note that internal_bool must be same as in call to for_sparse_jac.\n    check_not.rev_hes_sparsity(\n        select_z, transpose, internal_bool, pattern_yes\n    );\n    // internal_bool need not be the same during a call to for_hes_sparsity\n    internal_bool = ! internal_bool;\n    check_yes.for_hes_sparsity(\n        select_x, select_z, internal_bool, pattern_not\n    );\n    ok &= equal(pattern_not, pattern_yes);\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/chkpoint_two/dynamic.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin chkpoint_two_dynamic.cpp}\n\nCheckpoint Functions with Dynamic Parameters: Example and Test\n##############################################################\n\nPurpose\n*******\nThis example demonstrates using dynamic parameters with a\n:ref:`chkpoint_two-name` function.\n\ng(x)\n****\nFor this example, the checkpoint function\n:math:`g : \\B{R}^2 \\rightarrow \\B{R}^3` is defined by\n\n.. math::\n\n    g(x)\n    =\n    \\left( \\begin{array}{c}\n        x_0 \\cdot p_0 \\\\\n        x_0 \\cdot x_ 0 \\\\\n        x_1 \\cdot x_ 0\n    \\end{array} \\right)\n\nwhere :math:`p_0` is a dynamic parameter in the definition of :math:`g(x)`\n\nf(x)\n****\nThe function :math:`f(x) : \\B{R}^2 \\rightarrow \\B{R}^3`\nis defined by :math:`f(x) = q_0 \\cdot g(x)` where :math:`q_0`\nis a dynamic parameter in the definition of :math:`f(x)`.\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end chkpoint_two_dynamic.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\nbool dynamic(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * CppAD::numeric_limits<double>::epsilon();\n    //\n    //\n    // record the function g(x)\n    size_t nx = 2, ny = 3, np = 1, nq = 1;\n    CPPAD_TESTVECTOR( AD<double> ) ax(nx), ay(ny), ap(np), aq(nq);\n    for(size_t j = 0; j < nx; j++)\n        ax[j] = double(j);\n    ap[0] = 2.0;\n    size_t abort_op_index = 0;\n    bool   record_compare = true;\n    Independent(ax, abort_op_index, record_compare, ap);\n    ay[0] = ax[0] * ap[0];\n    ay[1] = ax[0] * ax[0];\n    ay[2] = ax[1] * ax[0];\n    CppAD::ADFun<double> g_fun(ax, ay);\n    //\n    // make a checkpoint version of g\n    std::string name             = \"g(x)\";\n    bool        internal_bool    = true;\n    bool        use_hes_sparsity = false;\n    bool        use_base2ad      = false;\n    bool        use_in_parallel  = false;\n    CppAD::chkpoint_two<double> g_chk(g_fun, name,\n        internal_bool, use_hes_sparsity, use_base2ad, use_in_parallel\n    );\n    //\n    // record f(x) using checkpoint version of g(x)\n    aq[0] = 3.0;\n    Independent(ax, abort_op_index, record_compare, aq);\n    g_chk(ax, ay);\n    for(size_t i = 0; i < ny; ++i)\n        ay[i] = aq[0] * ay[i];\n    CppAD::ADFun<double> f_fun(ax, ay);\n    //\n    // vectors of doubles\n    CPPAD_TESTVECTOR(double) x(nx), y(ny), p(np), q(nq);\n    //\n    // set dynamic parameters in g_chk\n    p[0] = 4.0;\n    g_chk.new_dynamic(p);\n    //\n    // set dynamic parameters in f_fun\n    q[0] = 5.0;\n    f_fun.new_dynamic(q);\n    //\n    // evaluate f(x)\n    for(size_t j = 0; j < nx; ++j)\n        x[j] = 6.0 + double(j);\n    y = f_fun.Forward(0, x);\n    //\n    // check result\n    double check;\n    check = q[0] * x[0] * p[0];\n    ok   &= NearEqual(check, y[0], eps99, eps99);\n    check = q[0] * x[0] * x[0];\n    ok   &= NearEqual(check, y[1], eps99, eps99);\n    check = q[0] * x[1] * x[0];\n    ok   &= NearEqual(check, y[2], eps99, eps99);\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/chkpoint_two/get_started.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin chkpoint_two_get_started.cpp}\n\nGet Started Checkpointing: Example and Test\n###########################################\n\nPurpose\n*******\nBreak a large computation into pieces and only store values at the\ninterface of the pieces.\nIn actual applications, there may many uses of each function\nand many more functions.\n\nf\n*\nThe function :math:`f : \\B{R}^2 \\rightarrow \\B{R}^2`\nis defined by\n\n.. math::\n\n    f(y) = \\left( \\begin{array}{c}\n        y_0 + y_0 + y_0\n        \\\\\n        y_1 + y_1 + y_1\n    \\end{array} \\right)\n\ng\n*\nThe function :math:`g : \\B{R}^2 \\rightarrow \\B{R}^2`\ndefined by\n\n.. math::\n\n    g(x) = \\left( \\begin{array}{c}\n        x_0 \\cdot x_0 \\cdot x_0\n        \\\\\n        x_1 \\cdot x_1 \\cdot x_1\n    \\end{array} \\right)\n\nf[g(x)]\n*******\nThe function :math:`f[g(x)]` is given by\n\n.. math::\n\n    f[g(x)]\n    =\n    f \\left[ \\begin{array}{c}\n        x_0^3 \\\\\n        x_1^3\n    \\end{array} \\right]\n    =\n    \\left[ \\begin{array}{c}\n        3 x_0^3 \\\\\n        3 x_1^3\n    \\end{array} \\right]\n\nSource Code\n***********\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end chkpoint_two_get_started.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n\nnamespace {\n    using CppAD::AD;\n    typedef CPPAD_TESTVECTOR(AD<double>)            ADVector;\n\n    void f_algo(const ADVector& y, ADVector& z)\n    {   z[0] = 0.0;\n        z[1] = 0.0;\n        for(size_t k = 0; k < 3; k++)\n        {   z[0] += y[0];\n            z[1] += y[1];\n        }\n        return;\n    }\n    void g_algo(const ADVector& x, ADVector& y)\n    {   y[0] = 1.0;\n        y[1] = 1.0;\n        for(size_t k = 0; k < 3; k++)\n        {   y[0] *= x[0];\n            y[1] *= x[1];\n        }\n        return;\n    }\n}\nbool get_started(void)\n{   bool ok = true;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // AD vectors holding x, y, and z values\n    size_t nx = 2, ny = 2, nz = 2;\n    ADVector ax(nx), ay(ny), az(nz);\n\n    // record the function g_fun(x)\n    for(size_t j = 0; j < nx; j++)\n        ax[j] = double(j + 1);\n    Independent(ax);\n    g_algo(ax, ay);\n    CppAD::ADFun<double> g_fun(ax, ay);\n\n    // record the function f_fun(y)\n    Independent(ay);\n    f_algo(ay, az);\n    CppAD::ADFun<double> f_fun(ay, az);\n\n    // create checkpoint versions of f and g\n    bool internal_bool    = false;\n    bool use_hes_sparsity = false;\n    bool use_base2ad      = false;\n    bool use_in_parallel  = false;\n    CppAD::chkpoint_two<double> f_chk( f_fun, \"f_chk\",\n        internal_bool, use_hes_sparsity, use_base2ad, use_in_parallel\n    );\n    CppAD::chkpoint_two<double> g_chk( g_fun, \"g_chk\",\n        internal_bool, use_hes_sparsity, use_base2ad, use_in_parallel\n    );\n\n    // Record a version of z = f[g(x)] using checkpointing\n    Independent(ax);\n    g_chk(ax, ay);\n    f_chk(ay, az);\n    CppAD::ADFun<double> fg(ax, az);\n\n    // zero order forward mode\n    CPPAD_TESTVECTOR(double) x(nx), z(nz);\n    for(size_t j = 0; j < nx; j++)\n        x[j] = 1.0 / double(1 + j);\n    z = fg.Forward(0, x);\n    for(size_t i = 0; i < nz; i++)\n    {   double check = 3.0 * x[i] * x[i] * x[i];\n        ok &= NearEqual(z[i], check, eps99, eps99);\n    }\n\n    // optimize fg and check that results do not change\n    fg.optimize();\n    for(size_t i = 0; i < nz; i++)\n    {   double check = 3.0 * x[i] * x[i] * x[i];\n        ok &= NearEqual(z[i], check, eps99, eps99);\n    }\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/chkpoint_two/ode.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin chkpoint_two_ode.cpp}\n{xrst_spell\n    kutta\n    runge\n}\n\nCheckpointing an ODE Solver: Example and Test\n#############################################\n\nPurpose\n*******\nIn this example we :ref:`checkpoint<chkpoint_two-name>` one step of an ODE solver.\n\nProblem\n*******\nWe consider the initial value problem with parameter :math:`x` defined by,\n:math:`z(0, x) = z_0 (x)`,\n\n.. math::\n\n    \\partial_t z(t, x ) = h [ x , z(t, x) ]\n\nNote that if :math:`t` needs to be in the equation, one can define\nthe first component of :math:`z(t, x)` to be equal to :math:`t`.\n\nODE Solver\n**********\nFor this example, we consider the Fourth order Runge-Kutta ODE solver.\nGiven an approximation solution at time :math:`t_k` denoted by\n:math:`\\tilde{z}_k (x)`, and :math:`\\Delta t = t_{k+1} - t_k`,\nit defines the approximation solution :math:`\\tilde{z}_{k+1} (x)`\nat time :math:`t_{k+1}` by\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    h_1 & =  & h [ x , \\tilde{z}_k (x) ]\n    \\\\\n    h_2 & =  & h [ x , \\tilde{z}_k (x) + \\Delta t \\; h_1 / 2 ]\n    \\\\\n    h_3 & =  & h [ x , \\tilde{z}_k (x) + \\Delta t \\; h_2 / 2 ]\n    \\\\\n    h_4 & =  & h [ x , \\tilde{z}_k (x) + \\Delta t \\; h_3 ]\n    \\\\\n    \\tilde{z}_{k+1} (x) & = &\n        \\tilde{z}_k (x) + \\Delta t \\; ( h_1 +  2 h_2 + 2 h_3 + h_4 ) / 6\n    \\end{eqnarray}\n\nIf :math:`\\tilde{z}_k (x) = z_k (x)`,\n:math:`\\tilde{z}_{k+1} (x) = z_{k+1} (x) + O( \\Delta t^5 )`.\nOther ODE solvers can use a similar method to the one used below.\n\nODE\n***\nFor this example the ODE is defined by\n:math:`z(0, x) = 0` and\n\n.. math::\n\n    h[ x, z(t, x) ] =\n    \\left( \\begin{array}{c}\n            x_0                     \\\\\n            x_1 z_0 (t, x)          \\\\\n            \\vdots                  \\\\\n            x_{n-1} z_{n-2} (t, x)\n    \\end{array} \\right)\n    =\n    \\left( \\begin{array}{c}\n            \\partial_t z_0 (t , x)      \\\\\n            \\partial_t z_1 (t , x)      \\\\\n            \\vdots                      \\\\\n            \\partial_t z_{n-1} (t , x)\n    \\end{array} \\right)\n\nSolution\n********\nThe solution of the ODE for this example,\nwhich is used to check the results,\ncan be calculated by\nstarting with the first row and then using the solution\nfor the first row to solve the second and so on.\nDoing this we obtain\n\n.. math::\n\n    z(t, x) =\n    \\left( \\begin{array}{c}\n        x_0 t                  \\\\\n        x_1 x_0 t^2 / 2        \\\\\n        \\vdots                 \\\\\n        x_{n-1} x_{n-2} \\ldots x_0 t^n / n !\n    \\end{array} \\right)\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end chkpoint_two_ode.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n\nnamespace {\n    using CppAD::AD;\n    typedef AD<double>                     a1double;\n    typedef AD<a1double>                   a2double;\n    //\n    typedef CPPAD_TESTVECTOR(   double )   a0vector;\n    typedef CPPAD_TESTVECTOR( a1double )   a1vector;\n    typedef CPPAD_TESTVECTOR( a2double )   a2vector;\n    //\n    // set once by main and kept that way\n    double delta_t_ = std::numeric_limits<double>::quiet_NaN();\n    size_t n_       = 0;\n    //\n    // The function h( x , y)\n    template <class FloatVector>\n    FloatVector h(const FloatVector& x, const FloatVector& y)\n    {   assert( size_t( x.size() ) == n_ );\n        assert( size_t( y.size() ) == n_ );\n        FloatVector result(n_);\n        result[0] = x[0];\n        for(size_t i = 1; i < n_; i++)\n            result[i] = x[i] * y[i-1];\n        return result;\n    }\n\n    // The 4-th Order Runge-Kutta Step\n    template <class FloatVector>\n    FloatVector Runge4(const FloatVector& x, const FloatVector& z0\n    )\n    {   assert( size_t( x.size() ) == n_ );\n        assert( size_t( z0.size() ) == n_ );\n        //\n        typedef typename FloatVector::value_type Float;\n        //\n        Float  dt = Float(delta_t_);\n        size_t m  = z0.size();\n        //\n        FloatVector h1(m), h2(m), h3(m), h4(m), result(m);\n        h1 = h( x, z0 );\n        //\n        for(size_t i = 0; i < m; i++)\n            h2[i] = z0[i] + dt * h1[i] / 2.0;\n        h2 = h( x, h2 );\n        //\n        for(size_t i = 0; i < m; i++)\n            h3[i] = z0[i] + dt * h2[i] / 2.0;\n        h3 = h( x, h3 );\n        //\n        for(size_t i = 0; i < m; i++)\n            h4[i] = z0[i] + dt * h3[i];\n        h4 = h( x, h4 );\n        //\n        for(size_t i = 0; i < m; i++)\n        {   Float dz = dt * ( h1[i] + 2.0*h2[i] + 2.0*h3[i] + h4[i] ) / 6.0;\n            result[i] = z0[i] + dz;\n        }\n        return result;\n    }\n\n    // pack x and z into an axz vector\n    template <class FloatVector>\n    void pack(\n        FloatVector&         axz      ,\n        const FloatVector&   x        ,\n        const FloatVector&   z        )\n    {   assert( size_t( axz.size() ) == n_ + n_ );\n        assert( size_t( x.size()        ) == n_      );\n        assert( size_t( z.size()        ) == n_      );\n        //\n        size_t offset = 0;\n        for(size_t i = 0; i < n_; i++)\n            axz[offset + i] = x[i];\n        offset += n_;\n        for(size_t i = 0; i < n_; i++)\n            axz[offset + i] = z[i];\n    }\n\n    // unpack an axz vector\n    template <class FloatVector>\n    void unpack(\n        const FloatVector&         axz      ,\n        FloatVector&               x        ,\n        FloatVector&               z        )\n    {   assert( size_t( axz.size() ) == n_ + n_ );\n        assert( size_t( x.size()        ) == n_      );\n        assert( size_t( z.size()        ) == n_      );\n        //\n        size_t offset = 0;\n        for(size_t i = 0; i < n_; i++)\n            x[i] = axz[offset + i];\n        offset += n_;\n        for(size_t i = 0; i < n_; i++)\n            z[i] = axz[offset + i];\n    }\n\n    // Algorithm that z(t, x)\n    void ode_algo(const a1vector& axz_in, a1vector& axz_out)\n    {   assert( size_t( axz_in.size()  ) == n_ + n_ );\n        assert( size_t( axz_out.size() ) == n_ + n_ );\n        //\n        // initial ode information\n        a1vector x(n_), z0(n_);\n        unpack(axz_in, x, z0);\n        //\n        // advance z(t, x)\n        a1vector z1 = Runge4(x, z0);\n        //\n        // final ode information\n        pack(axz_out, x, z1);\n        //\n        return;\n    }\n}\n//\nbool ode(void)\n{   bool ok = true;\n    using CppAD::NearEqual;\n    double eps = std::numeric_limits<double>::epsilon();\n    //\n    // number of terms in the differential equation\n    n_ = 6;\n    //\n    // step size for the differentiail equation\n    size_t n_step = 10;\n    double T      = 1.0;\n    delta_t_ = T / double(n_step);\n    //\n    // set parameter value and initial value of the ode\n    a1vector ax(n_), az0(n_);\n    for(size_t i = 0; i < n_; i++)\n    {   ax[i]  = a1double(i + 1);\n        az0[i] = a1double(0);\n    }\n    //\n    // pack ode information input vector\n    //\n    // function corresponding to one step of the ode Algorithm\n    a1vector axz_in(2 * n_), axz_out(2 * n_);\n    pack(axz_in, ax, az0);\n    CppAD::Independent(axz_in);\n    ode_algo(axz_in, axz_out);\n    CppAD::ADFun<double> ode_fun(axz_in, axz_out);\n    //\n    // create checkpoint version of the algorithm\n    bool internal_bool    = false;\n    bool use_hes_sparsity = false;\n    bool use_base2ad      = false;\n    bool use_in_parallel  = false;\n    CppAD::chkpoint_two<double> ode_check(ode_fun, \"ode\",\n        internal_bool, use_hes_sparsity, use_base2ad, use_in_parallel\n    );\n    //\n    // set the independent variables for recording\n    CppAD::Independent( ax );\n    //\n    // repack to get dependence on ax\n    pack(axz_in, ax, az0);\n    //\n    // Now run the checkpoint algorithm n_step times\n    for(size_t k = 0; k < n_step; k++)\n    {   ode_check(axz_in, axz_out);\n        axz_in = axz_out;\n    }\n    //\n    // Unpack the results (must use ax1 so do not overwrite ax)\n    a1vector ax1(n_), az1(n_);\n    unpack(axz_out, ax1, az1);\n    //\n    // We could record a complicated function of x and z(T, x) in f,\n    // but make this example simpler we record x -> z(T, x).\n    CppAD::ADFun<double> f(ax, az1);\n    //\n    // check function values\n    a0vector x(n_), z1(n_);\n    for(size_t j = 0; j < n_; j++)\n        x[j] = double(j + 1);\n    z1 = f.Forward(0, x);\n    //\n    // separate calculation of z(t, x)\n    a0vector check_z1(n_);\n    check_z1[0] = x[0] * T;\n    for(size_t i = 1; i < n_; i++)\n        check_z1[i] = x[i] * T * check_z1[i-1] / double(i+1);\n    //\n    // expected accuracy for each component of of z(t, x)\n    a0vector acc(n_);\n    for(size_t i = 0; i < n_; i++)\n    {   if( i < 4 )\n        {   // Runge-Kutta methods is exact for this case\n            acc[i] = 10. * eps;\n        }\n        else\n        {   acc[i] = 1.0;\n            for(size_t k = 0; k < 5; k++)\n                    acc[i] *= x[k] * delta_t_;\n        }\n    }\n    // check z1(T, x)\n    for(size_t i = 0; i < n_; i++)\n        ok &= NearEqual(z1[i] , check_z1[i], acc[i], acc[i]);\n    //\n    // Now use f to compute a derivative. For this 'simple' example it is\n    // the derivative of z_{n-1} (T, x) respect to x of the\n    a0vector w(n_), dw(n_);\n    for(size_t i = 0; i < n_; i++)\n    {   w[i] = 0.0;\n        if( i == n_ - 1 )\n            w[i] = 1.0;\n    }\n    dw = f.Reverse(1, w);\n    for(size_t j = 0; j < n_; j++)\n    {   double check = z1[n_ - 1] / x[j];\n        ok &= NearEqual(dw[j] , check, 100.*eps, 100.*eps);\n    }\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/compare_change/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# Build the example/compare_change directory tests\n#\n# source_list\nSET(source_list compare_change.cpp)\n#\n# compile_flags\nset_compile_flags(\n    example_compare_change \"${cppad_debug_which}\" \"${source_list}\"\n)\n#\n# example_compare_change\nADD_EXECUTABLE(example_compare_change EXCLUDE_FROM_ALL ${source_list})\n#\n# List of libraries to be linked into the specified target\nTARGET_LINK_LIBRARIES(example_compare_change\n    ${cppad_lib}\n    ${colpack_libs}\n)\n#\n# check_example_compare_change\nadd_check_executable(check_example compare_change)\n"
  },
  {
    "path": "example/compare_change/compare_change.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin compare_change.cpp}\n\nCompareChange and Re-Tape: Example and Test\n###########################################\nThis test is run as a separate program so that it does not\nmix debug and release versions of the template functions it calls.\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end compare_change.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n\n// empty namespace\nnamespace {\n    //\n    // Minimum\n    template <class Type>\n    Type Minimum(const Type &x, const Type &y)\n    {   // Use a comparison to compute the min(x, y)\n        // (note that CondExp would never require retaping).\n        if( x < y )\n            return x;\n        return y;\n    }\n    //\n    // error_info\n    struct error_info {\n        bool known;\n        int  line;\n        std::string file;\n        std::string exp;\n        std::string msg;\n    };\n    //\n    // error_handler\n    void error_handler(\n        bool        known       ,\n        int         line        ,\n        const char *file        ,\n        const char *exp         ,\n        const char *msg         )\n    {   // error handler must not return, so throw an exception\n        error_info info;\n        info.known = known;\n        info.line  = line;\n        info.file  = file;\n        info.exp   = exp;\n        info.msg   = msg;\n        throw info;\n    }\n\n}\n//\n// compare_change\nbool compare_change(void)\n{   bool ok = true;\n    using CppAD::AD;\n\n    // domain space vector\n    size_t n = 2;\n    CPPAD_TESTVECTOR(AD<double>) ax(n);\n    ax[0] = 3.;\n    ax[1] = 4.;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(ax);\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) ay(m);\n    ay[0] = Minimum(ax[0], ax[1]);\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(ax, ay);\n\n    // set count to one (not necessry because is its default value)\n    f.compare_change_count(1);\n\n    // evaluate zero mode Forward where comparison has the same result\n    // as during taping; i.e., x[0] < x[1].\n    CPPAD_TESTVECTOR(double) x(n), y(m);\n    x[0] = 2.;\n    x[1] = 3.;\n    y    = f.Forward(0, x);\n    ok  &= (y[0] == x[0]);\n    ok  &= (y[0] == Minimum(x[0], x[1]));\n    ok  &= (f.compare_change_number() == 0);\n    ok  &= (f.compare_change_op_index() == 0);\n\n    // evaluate zero mode Forward where comparison has different result\n    // as during taping; i.e., x[0] >= x[1].\n    x[0] = 3.;\n    x[1] = 2.;\n    y    = f.Forward(0, x);\n    ok  &= (y[0] == x[0]);\n    ok  &= (y[0] != Minimum(x[0], x[1]));\n    ok  &= (f.compare_change_number() == 1);\n    ok  &= (f.compare_change_op_index() > 0 );\n    size_t op_index = f.compare_change_op_index();\n\n    // Local block during which default CppAD error handler is replaced.\n    // If you do not replace the default CppAD error handler,\n    // and you run in the debugger, you will be able to inspect the\n    // call stack and see that 'if( x < y )' is where the comparison is.\n    bool missed_error = true;\n    {   CppAD::ErrorHandler local_error_handler(error_handler);\n\n        std::string check_msg =\n            \"Operator index equals abort_op_index in Independent\";\n        try {\n            // determine the operation index where the change occurred\n            CppAD::Independent(ax, op_index);\n            ay[0] = Minimum(ax[0], ax[1]);\n# ifdef NDEBUG\n            // CppAD does not spend time checking operator index when\n            // NDEBUG is defined\n            missed_error = false;\n            AD<double>::abort_recording();\n# endif\n        }\n        catch( error_info info )\n        {   missed_error = false;\n            ok          &= info.known;\n            ok          &= info.msg == check_msg;\n            // Must abort the recording so we can start a new one\n            // (and to avoid a memory leak).\n            AD<double>::abort_recording();\n        }\n    }\n    ok &= ! missed_error;\n\n    // set count to zero to demonstrate case where comparisons are not checked\n    f.compare_change_count(0);\n    y    = f.Forward(0, x);\n    ok  &= (y[0] == x[0]);\n    ok  &= (y[0] != Minimum(x[0], x[1]));\n    ok  &= (f.compare_change_number()   == 0);\n    ok  &= (f.compare_change_op_index() == 0);\n\n    // now demonstrate that compare_change_number works for an optimized\n    // tape (note that compare_change_op_index is always zero after optimize)\n    f.optimize();\n    f.compare_change_count(1);\n    y    = f.Forward(0, x);\n    ok  &= (y[0] == x[0]);\n    ok  &= (y[0] != Minimum(x[0], x[1]));\n    ok  &= (f.compare_change_number()   == 1);\n    ok  &= (f.compare_change_op_index() == 0);\n\n    // now retape to get the a tape that agrees with the algorithm\n    ax[0] = x[0];\n    ax[1] = x[1];\n    Independent(ax);\n    ay[0] = Minimum(ax[0], ax[1]);\n    f.Dependent(ax, ay);\n    y    = f.Forward(0, x);\n    ok  &= (y[0] == x[1]);\n    ok  &= (y[0] == Minimum(x[0], x[1]));\n    ok  &= (f.compare_change_number()   == 0);\n    ok  &= (f.compare_change_op_index() == 0);\n\n    return ok;\n}\n\n// main program that runs this test\nint main(void)\n{   std::string group = \"example/compare_change\";\n    size_t      width = 20;\n    CppAD::test_boolofvoid Run(group, width);\n\n    // This line is used by test_one.sh\n\n    Run( compare_change,    \"compare_change\"   );\n    //\n    // check for memory leak\n    bool memory_ok = CppAD::thread_alloc::free_all();\n    // print summary at end\n    bool ok = Run.summary(memory_ok);\n    //\n    return static_cast<int>( ! ok );\n}\n\n// END C++\n"
  },
  {
    "path": "example/cppad_code_gen/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n#\n# BEGIN_SORT_THIS_LINE_PLUS_2\nSET(source_list\n    cppad_code_gen.cpp\n    file.cpp\n    function.cpp\n    jac_as_fun.cpp\n    jacobian.cpp\n    sparse_jac_as_fun.cpp\n    sparse_jacobian.cpp\n)\n# END_SORT_THIS_LINE_MINUS_2\n\nset_compile_flags(\n    example_cppad_code_gen \"${cppad_debug_which}\" \"${source_list}\"\n)\n#\nADD_EXECUTABLE(example_cppad_code_gen EXCLUDE_FROM_ALL ${source_list})\n\n# List of libraries to be linked into the specified target\nTARGET_LINK_LIBRARIES(example_cppad_code_gen\n    ${cppad_lib}\n    ${colpack_libs}\n)\n#\n# check_example_cppad_code_gen\nadd_check_executable(check_example cppad_code_gen)\n"
  },
  {
    "path": "example/cppad_code_gen/cppad_code_gen.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin cppad_code_gen.cpp}\n\nCppADCodeGen Examples and Tests Driver\n######################################\n\nRunning These Tests\n*******************\nAfter executing the :ref:`cmake-name` command\nform the :ref:`download@Distribution Directory`,\nyou can build and run these tests with the commands::\n\n    cd build\n    make check_example_cppad_code_gen\n\nNote that your choice of :ref:`cmake@generator` may require using\nan different version of make; e.g., ``ninja`` .\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end cppad_code_gen.cpp}\n-------------------------------------------------------------------------------\n*/\n// BEGIN C++\n\n// CPPAD_HAS_* defines\n# include <cppad/configure.hpp>\n\n// for thread_alloc\n# include <cppad/utility/thread_alloc.hpp>\n\n// test runner\n# include <cppad/utility/test_boolofvoid.hpp>\n\n// BEGIN_SORT_THIS_LINE_PLUS_2\n// external compiled tests\nextern bool file(void);\nextern bool function(void);\nextern bool jac_as_fun(void);\nextern bool jacobian(void);\nextern bool sparse_jac_as_fun(void);\nextern bool sparse_jacobian(void);\n// END_SORT_THIS_LINE_MINUS_1\n\n// main program that runs all the tests\nint main(void)\n{   std::string group = \"example/cppad_code_gen\";\n    size_t      width = 20;\n    CppAD::test_boolofvoid Run(group, width);\n\n    // This line is used by test_one.sh\n\n    // BEGIN_SORT_THIS_LINE_PLUS_2\n    // external compiled tests\n    Run( file,                 \"file\"              );\n    Run( function,             \"function\"          );\n    Run( jac_as_fun,           \"jac_as_fun\"        );\n    Run( jacobian,             \"jacobian\"          );\n    Run( sparse_jac_as_fun,    \"sparse_jac_as_fun\" );\n    Run( sparse_jacobian,      \"sparse_jacobian\"   );\n    // END_SORT_THIS_LINE_MINUS_1\n\n    // check for memory leak\n    bool memory_ok = CppAD::thread_alloc::free_all();\n    // print summary at end\n    bool ok = Run.summary(memory_ok);\n    //\n    return static_cast<int>( ! ok );\n}\n// END C++\n"
  },
  {
    "path": "example/cppad_code_gen/file.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin code_gen_fun_file.cpp}\n\nFile Store and Retrieve a Code Gen Function: Example and Test\n#############################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end code_gen_fun_file.cpp}\n*/\n// BEGIN C++\n# include <cppad/example/code_gen_fun.hpp>\n\nnamespace {\n    void store(const std::string& file_name)\n    {   //\n        typedef CppAD::cg::CG<double>     c_double;\n        typedef CppAD::AD<c_double>      ac_double;\n        typedef CppAD::vector<ac_double> ac_vector;\n        //\n\n        // domain space vector\n        size_t n  = 2;\n        ac_vector ac_x(n);\n        for(size_t j = 0; j < n; ++j)\n            ac_x[j] = 1.0 / double(j + 1);\n\n        // declare independent variables and start tape recording\n        CppAD::Independent(ac_x);\n\n        // range space vector\n        size_t m = 3;\n        ac_vector ac_y(m);\n        for(size_t i = 0; i < m; ++i)\n            ac_y[i] = double(i + 1) * sin( ac_x[i % n] );\n\n        // create c_f: x -> y and stop tape recording\n        CppAD::ADFun<c_double> c_f(ac_x, ac_y);\n\n        // create compiled version of c_f\n        code_gen_fun f(file_name, c_f);\n    }\n}\n\nbool file(void)\n{   bool ok      = true;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    //\n    // Store the compiled file in a dynamic link library\n    std::string file_name = \"example_lib\";\n    store(file_name);\n    //\n    // retrieve the compled function from the file\n    // (compiling take much longer than retrieving the file)\n    code_gen_fun f(file_name);\n\n    // evaluate the compiled function\n    size_t n = 2, m = 3;\n    CppAD::vector<double> x(n), y(m);\n    for(size_t j = 0; j < n; ++j)\n        x[j] = 1.0 / double(j + 2);\n    y = f(x);\n\n    // check function values\n    for(size_t i = 0; i < m; ++i)\n    {   double check = double(i + 1) * std::sin( x[i % n] );\n        ok &= CppAD::NearEqual(y[i] , check, eps99, eps99);\n    }\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/cppad_code_gen/function.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin code_gen_fun_function.cpp}\n\nEvaluate a Code Gen Function: Example and Test\n##############################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end code_gen_fun_function.cpp}\n*/\n// BEGIN C++\n# include <cppad/example/code_gen_fun.hpp>\n\nbool function(void)\n{   bool ok = true;\n    //\n    typedef CppAD::cg::CG<double>     c_double;\n    typedef CppAD::AD<c_double>      ac_double;\n    //\n    typedef CppAD::vector<double>     d_vector;\n    typedef CppAD::vector<ac_double> ac_vector;\n    //\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n  = 2;\n    ac_vector ac_x(n);\n    for(size_t j = 0; j < n; ++j)\n        ac_x[j] = 1.0 / double(j + 1);\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(ac_x);\n\n    // range space vector\n    size_t m = 3;\n    ac_vector ac_y(m);\n    for(size_t i = 0; i < m; ++i)\n        ac_y[i] = double(i + 1) * sin( ac_x[i % n] );\n\n    // create c_f: x -> y and stop tape recording\n    CppAD::ADFun<c_double> c_f(ac_x, ac_y);\n\n    // create compiled version of c_f\n    std::string file_name = \"example_lib\";\n    code_gen_fun f(file_name, c_f);\n\n    // evaluate the compiled function\n    d_vector x(n), y(m);\n    for(size_t j = 0; j < n; ++j)\n        x[j] = 1.0 / double(j + 2);\n    y = f(x);\n\n    // check function values\n    for(size_t i = 0; i < m; ++i)\n    {   double check = double(i + 1) * std::sin( x[i % n] );\n        ok &= CppAD::NearEqual(y[i] , check, eps99, eps99);\n    }\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/cppad_code_gen/jac_as_fun.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin code_gen_fun_jac_as_fun.cpp}\n\nPass Jacobian as Code Gen Function: Example and Test\n####################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end code_gen_fun_jac_as_fun.cpp}\n*/\n// BEGIN C++\n# include <cppad/example/code_gen_fun.hpp>\n\nbool jac_as_fun(void)\n{   bool ok = true;\n    //\n    typedef CppAD::cg::CG<double>     c_double;\n    typedef CppAD::AD<c_double>      ac_double;\n    //\n    typedef CppAD::vector<double>     d_vector;\n    typedef CppAD::vector<ac_double> ac_vector;\n    //\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n  = 2;\n    ac_vector ac_x(n);\n    for(size_t j = 0; j < n; ++j)\n        ac_x[j] = 1.0 / double(j + 1);\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(ac_x);\n\n    // range space vector\n    size_t m = 3;\n    ac_vector ac_y(m);\n    for(size_t i = 0; i < m; ++i)\n        ac_y[i] = double(i + 1) * sin( ac_x[i % n] );\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<c_double> c_f(ac_x, ac_y);\n\n    // create a version of f that evaluates using ac_double\n    CppAD::ADFun<ac_double, c_double> ac_f = c_f.base2ad();\n\n    // Independent variables while evaluating Jacobian\n    CppAD::Independent(ac_x);\n\n    // Evaluate the Jacobian using any CppAD method\n    // (for this example we just use the simplest thing)\n    ac_vector ac_J = ac_f.Jacobian(ac_x);\n\n    // create g: x -> f'(x)\n    CppAD::ADFun<c_double> c_g(ac_x, ac_J);\n\n    // create compiled version of c_g\n    std::string file_name = \"example_lib\";\n    code_gen_fun g(file_name, c_g);\n\n    // evaluate the compiled jacobian\n    d_vector x(n), J(m * n);\n    for(size_t j = 0; j < n; ++j)\n        x[j] = 1.0 / double(j + 2);\n    J = g(x);\n\n    // check Jaociban values\n    for(size_t i = 0; i < m; ++i)\n    {   for(size_t j = 0; j < n; ++j)\n        {   double check = 0.0;\n            if( j == i % n )\n                check = double(i + 1) * cos( x[i % n] );\n            ok &= CppAD::NearEqual(J[i * n + j] , check, eps99, eps99);\n        }\n    }\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/cppad_code_gen/jacobian.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin code_gen_fun_jacobian.cpp}\n\nEvaluate Jacobian of a Code Gen Function: Example and Test\n##########################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end code_gen_fun_jacobian.cpp}\n*/\n// BEGIN C++\n# include <cppad/example/code_gen_fun.hpp>\n\nbool jacobian(void)\n{   bool ok = true;\n    //\n    typedef CppAD::cg::CG<double>     c_double;\n    typedef CppAD::AD<c_double>      ac_double;\n    //\n    typedef CppAD::vector<double>     d_vector;\n    typedef CppAD::vector<ac_double> ac_vector;\n    //\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n  = 2;\n    ac_vector ac_x(n);\n    for(size_t j = 0; j < n; ++j)\n        ac_x[j] = 1.0 / double(j + 1);\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(ac_x);\n\n    // range space vector\n    size_t m = 3;\n    ac_vector ac_y(m);\n    for(size_t i = 0; i < m; ++i)\n        ac_y[i] = double(i + 1) * sin( ac_x[i % n] );\n\n    // create c_f: x -> y and stop tape recording\n    CppAD::ADFun<c_double> c_f(ac_x, ac_y);\n\n    // create compiled version of c_f\n    std::string file_name = \"example_lib\";\n    code_gen_fun::evaluation_enum eval_jac = code_gen_fun::dense_enum;\n    code_gen_fun f(file_name, c_f, eval_jac);\n\n    // evaluate the compiled jacobian\n    d_vector x(n), J;\n    for(size_t j = 0; j < n; ++j)\n        x[j] = 1.0 / double(j + 2);\n    J = f.jacobian(x);\n\n    // check Jaociban values\n    for(size_t i = 0; i < m; ++i)\n    {   for(size_t j = 0; j < n; ++j)\n        {   double check = 0.0;\n            if( j == i % n )\n                check = double(i + 1) * cos( x[i % n] );\n            ok &= CppAD::NearEqual(J[i * n + j] , check, eps99, eps99);\n        }\n    }\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/cppad_code_gen/sparse_jac_as_fun.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin code_gen_fun_sparse_jac_as_fun.cpp}\n\nPass Sparse Jacobian as Code Gen Function: Example and Test\n###########################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end code_gen_fun_sparse_jac_as_fun.cpp}\n*/\n// BEGIN C++\n# include <cppad/example/code_gen_fun.hpp>\n\nbool sparse_jac_as_fun(void)\n{   bool ok = true;\n    //\n    typedef CppAD::cg::CG<double>     c_double;\n    typedef CppAD::AD<c_double>      ac_double;\n    //\n    typedef CppAD::vector<size_t>     s_vector;\n    typedef CppAD::vector<double>     d_vector;\n    typedef CppAD::vector<ac_double> ac_vector;\n    //\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n  = 2;\n    ac_vector ac_x(n);\n    for(size_t j = 0; j < n; ++j)\n        ac_x[j] = 1.0 / double(j + 1);\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(ac_x);\n\n    // range space vector\n    size_t m = 3;\n    ac_vector ac_y(m);\n    for(size_t i = 0; i < m; ++i)\n        ac_y[i] = double(i + 1) * sin( ac_x[i % n] );\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<c_double> c_f(ac_x, ac_y);\n\n    // create a version of f that evaluates using ac_double\n    CppAD::ADFun<ac_double, c_double> ac_f = c_f.base2ad();\n\n    // Independent variables while evaluating Jacobian\n    CppAD::Independent(ac_x);\n\n    // ----------------------------------------------------------------\n    // Sparse Jacobian evaluation using any CppAD method\n    // (there are lots of choices here)\n    //\n    // pattern_eye (pattern for identity matrix)\n    CppAD::sparse_rc<s_vector> pattern_eye(n, n, n);\n    for(size_t k = 0; k < n; ++k)\n        pattern_eye.set(k, k, k);\n    //\n    // pattern_jac\n    bool transpose     = false;\n    bool dependency    = false;\n    bool internal_bool = true;\n    CppAD::sparse_rc<s_vector> pattern_jac;\n    // note that c_f and ac_f have the same sparsity pattern\n    c_f.for_jac_sparsity(\n        pattern_eye, transpose, dependency, internal_bool, pattern_jac\n    );\n    //\n    // ac_Jrcv\n    CppAD::sparse_rcv<s_vector, ac_vector> ac_Jrcv( pattern_jac );\n    CppAD::sparse_jac_work work;\n    std::string coloring = \"cppad\";\n    size_t group_max = n;\n    ac_f.sparse_jac_for(\n        group_max, ac_x, ac_Jrcv, pattern_jac, coloring, work\n    );\n    //\n    // create g: x -> non-zero elements of Jacobian\n    CppAD::ADFun<c_double> c_g(ac_x, ac_Jrcv.val());\n\n    // create compiled version of c_g\n    std::string file_name = \"example_lib\";\n    code_gen_fun g(file_name, c_g);\n\n    // evaluate the compiled jacobian\n    d_vector x(n);\n    for(size_t j = 0; j < n; ++j)\n        x[j] = 1.0 / double(j + 2);\n    d_vector val = g(x);\n\n    // check Jaociban values\n    size_t nnz = pattern_jac.nnz();\n    const s_vector& row(pattern_jac.row());\n    const s_vector& col(pattern_jac.col());\n    s_vector row_major = pattern_jac.row_major();\n    //\n    size_t k = 0;\n    ok &= val.size() == nnz;\n    for(size_t i = 0; i < m; ++i)\n    {   for(size_t j = 0; j < n; ++j)\n        {   if( j == i % n )\n            {   size_t ell = row_major[k];\n                double check = double(i + 1) * cos( x[i % n] );\n                ok &= i == row[ell];\n                ok &= j == col[ell];\n                ok &= CppAD::NearEqual(val[k], check, eps99, eps99);\n                ++k;\n            }\n        }\n    }\n    ok &= k == nnz;\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/cppad_code_gen/sparse_jacobian.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin code_gen_fun_sparse_jacobian.cpp}\n\nEvaluate Sparse Jacobian of a Code Gen Function: Example and Test\n#################################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end code_gen_fun_sparse_jacobian.cpp}\n*/\n// BEGIN C++\n# include <cppad/example/code_gen_fun.hpp>\n\nbool sparse_jacobian(void)\n{   bool ok = true;\n    //\n    typedef CppAD::cg::CG<double>     c_double;\n    typedef CppAD::AD<c_double>      ac_double;\n    //\n    typedef CppAD::vector<double>     d_vector;\n    typedef CppAD::vector<ac_double> ac_vector;\n    //\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n  = 2;\n    ac_vector ac_x(n);\n    for(size_t j = 0; j < n; ++j)\n        ac_x[j] = 1.0 / double(j + 1);\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(ac_x);\n\n    // range space vector\n    size_t m = 3;\n    ac_vector ac_y(m);\n    for(size_t i = 0; i < m; ++i)\n        ac_y[i] = double(i + 1) * sin( ac_x[i % n] );\n\n    // create c_f: x -> y and stop tape recording\n    CppAD::ADFun<c_double> c_f(ac_x, ac_y);\n\n    // create compiled version of c_f\n    std::string file_name = \"example_lib\";\n    code_gen_fun::evaluation_enum eval_jac = code_gen_fun::sparse_enum;\n    code_gen_fun f(file_name, c_f, eval_jac);\n\n    // evaluate the compiled sparse_jacobian\n    d_vector x(n);\n    for(size_t j = 0; j < n; ++j)\n        x[j] = 1.0 / double(j + 2);\n    CppAD::sparse_rcv< CppAD::vector<size_t>, CppAD::vector<double> > Jrcv;\n    // This assignment uses move semantics\n    Jrcv = f.sparse_jacobian(x);\n\n    // check Jaociban values\n    ok &= Jrcv.nr() == m;\n    ok &= Jrcv.nc() == n;\n    const CppAD::vector<size_t>& row( Jrcv.row() );\n    const CppAD::vector<size_t>& col( Jrcv.col() );\n    const CppAD::vector<double>& val( Jrcv.val() );\n    CppAD::vector<size_t> row_major = Jrcv.row_major();\n    size_t k = 0;\n    for(size_t i = 0; i < m; ++i)\n    {   for(size_t j = 0; j < n; ++j)\n        {   if( j == i % n )\n            {   double check = double(i + 1) * cos( x[i % n] );\n                size_t ell = row_major[k];\n                ok &= row[ell] == i;\n                ok &= col[ell] == j;\n                ok &= CppAD::NearEqual(val[ell] , check, eps99, eps99);\n                ++k;\n            }\n        }\n    }\n    ok &= Jrcv.nnz() == k;\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/general/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-23 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# Build the example/general directory tests\n#\n# adolc_sources\nIF( cppad_has_adolc )\n    SET(adolc_sources mul_level_adolc.cpp mul_level_adolc_ode.cpp)\nELSE( cppad_has_adolc )\n    SET(adolc_sources \"\")\nENDIF( cppad_has_adolc )\n#\n# eigen_sources\nIF( cppad_has_eigen )\n    SET(eigen_sources eigen_det.cpp eigen_array.cpp)\nELSE( cppad_has_eigen )\n    SET(eigen_sources \"\")\nENDIF( cppad_has_eigen )\n#\n# BEGIN_SORT_THIS_LINE_PLUS_4\nSET(source_list\n    ${adolc_sources}\n    ${eigen_sources}\n    abort_recording.cpp\n    acos.cpp\n    acosh.cpp\n    ad_assign.cpp\n    ad_ctor.cpp\n    ad_fun.cpp\n    ad_in_c.cpp\n    ad_input.cpp\n    ad_output.cpp\n    add.cpp\n    add_eq.cpp\n    asin.cpp\n    asinh.cpp\n    atan.cpp\n    atan2.cpp\n    atanh.cpp\n    azmul.cpp\n    base2ad.cpp\n    base2vec_ad.cpp\n    base_alloc.hpp\n    base_require.cpp\n    bender_quad.cpp\n    bool_fun.cpp\n    capacity_order.cpp\n    change_param.cpp\n    check_for_nan.cpp\n    compare.cpp\n    complex_poly.cpp\n    con_dyn_var.cpp\n    cond_exp.cpp\n    cos.cpp\n    cosh.cpp\n    div.cpp\n    div_eq.cpp\n    equal_op_seq.cpp\n    erf.cpp\n    erfc.cpp\n    exp.cpp\n    expm1.cpp\n    fabs.cpp\n    for_one.cpp\n    for_two.cpp\n    forward.cpp\n    forward_dir.cpp\n    forward_order.cpp\n    fun_assign.cpp\n    fun_check.cpp\n    fun_property.cpp\n    function_name.cpp\n    general.cpp\n    hes_lagrangian.cpp\n    hes_lu_det.cpp\n    hes_minor_det.cpp\n    hes_times_dir.cpp\n    hessian.cpp\n    independent.cpp\n    integer.cpp\n    interface2c.cpp\n    interp_onetape.cpp\n    interp_retape.cpp\n    jac_lu_det.cpp\n    jac_minor_det.cpp\n    jacobian.cpp\n    log.cpp\n    log10.cpp\n    log1p.cpp\n    lu_ratio.cpp\n    lu_vec_ad.cpp\n    lu_vec_ad.hpp\n    lu_vec_ad_ok.cpp\n    mul.cpp\n    mul_eq.cpp\n    mul_level.cpp\n    mul_level_ode.cpp\n    near_equal_ext.cpp\n    new_dynamic.cpp\n    num_limits.cpp\n    number_skip.cpp\n    numeric_type.cpp\n    ode_stiff.cpp\n    opt_val_hes.cpp\n    pow.cpp\n    pow_nan.cpp\n    print_for.cpp\n    rev_checkpoint.cpp\n    rev_one.cpp\n    rev_two.cpp\n    reverse_one.cpp\n    reverse_three.cpp\n    reverse_two.cpp\n    sign.cpp\n    sin.cpp\n    sinh.cpp\n    sqrt.cpp\n    stack_machine.cpp\n    sub.cpp\n    sub_eq.cpp\n    tan.cpp\n    tanh.cpp\n    tape_index.cpp\n    taylor_ode.cpp\n    unary_minus.cpp\n    unary_plus.cpp\n    value.cpp\n    var2par.cpp\n    vec_ad.cpp\n)\n# END_SORT_THIS_LINE_MINUS_2\n\nset_compile_flags( example_general \"${cppad_debug_which}\" \"${source_list}\" )\n#\nADD_EXECUTABLE(example_general EXCLUDE_FROM_ALL ${source_list})\n#\n# List of libraries to be linked into the specified target\nTARGET_LINK_LIBRARIES(example_general\n    ${adolc_LINK_LIBRARIES}\n    ${cppad_lib}\n    ${colpack_libs}\n)\n#\n# check_example_general\nadd_check_executable(check_example general)\n"
  },
  {
    "path": "example/general/abort_recording.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin abort_recording.cpp}\n\nAbort Current Recording: Example and Test\n#########################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end abort_recording.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n# include <limits>\n\nbool abort_recording(void)\n{   bool ok = true;\n    double eps = 10. * CppAD::numeric_limits<double>::epsilon();\n\n    using CppAD::AD;\n\n    try\n    {   // domain space vector\n        size_t n = 1;\n        CPPAD_TESTVECTOR(AD<double>) x(n);\n        x[0]     = 0.;\n\n        // declare independent variables and start tape recording\n        CppAD::Independent(x);\n\n        // simulate an error during calculation of y and the execution\n        // stream was aborted\n        throw 1;\n    }\n    catch (int e)\n    {   ok &= (e == 1);\n\n        // do this in case throw occurred after the call to Independent\n        // (for case above this is known, but in general it is unknown)\n        AD<double>::abort_recording();\n    }\n    /*\n    Now make sure that we can start another recording\n    */\n\n    // declare independent variables and start tape recording\n    size_t n  = 1;\n    double x0 = 0.5;\n    CPPAD_TESTVECTOR(AD<double>) x(n);\n    x[0]      = x0;\n    CppAD::Independent(x);\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) y(m);\n    y[0] = 2 * x[0];\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(x, y);\n\n    // forward computation of partials w.r.t. x[0]\n    CPPAD_TESTVECTOR(double) dx(n);\n    CPPAD_TESTVECTOR(double) dy(m);\n    dx[0] = 1.;\n    dy    = f.Forward(1, dx);\n    ok   &= CppAD::NearEqual(dy[0], 2., eps, eps);\n\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/general/acos.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin acos.cpp}\n\nThe AD acos Function: Example and Test\n######################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end acos.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n\nbool acos(void)\n{   bool ok = true;\n\n    using CppAD::AD;\n    using CppAD::NearEqual;\n\n    // 10 times machine epsilon\n    double eps = 10. * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n  = 1;\n    double x0 = 0.5;\n    CPPAD_TESTVECTOR(AD<double>) x(n);\n    x[0]      = x0;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(x);\n\n    // a temporary value\n    AD<double> cos_of_x0 = CppAD::cos(x[0]);\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) y(m);\n    y[0] = CppAD::acos(cos_of_x0);\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(x, y);\n\n    // check value\n    ok &= NearEqual(y[0] , x0,  eps, eps);\n\n    // forward computation of first partial w.r.t. x[0]\n    CPPAD_TESTVECTOR(double) dx(n);\n    CPPAD_TESTVECTOR(double) dy(m);\n    dx[0] = 1.;\n    dy    = f.Forward(1, dx);\n    ok   &= NearEqual(dy[0], 1., eps, eps);\n\n    // reverse computation of derivative of y[0]\n    CPPAD_TESTVECTOR(double)  w(m);\n    CPPAD_TESTVECTOR(double) dw(n);\n    w[0]  = 1.;\n    dw    = f.Reverse(1, w);\n    ok   &= NearEqual(dw[0], 1., eps, eps);\n\n    // use a VecAD<Base>::reference object with acos\n    CppAD::VecAD<double> v(1);\n    AD<double> zero(0);\n    v[zero] = cos_of_x0;\n    AD<double> result = CppAD::acos(v[zero]);\n    ok     &= NearEqual(result, x0, eps, eps);\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/acosh.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin acosh.cpp}\n\nThe AD acosh Function: Example and Test\n#######################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end acosh.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n\nbool acosh(void)\n{   bool ok = true;\n\n    using CppAD::AD;\n    using CppAD::NearEqual;\n\n    // 10 times machine epsilon\n    double eps = 10. * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n  = 1;\n    double x0 = 0.5;\n    CPPAD_TESTVECTOR(AD<double>) x(n);\n    x[0]      = x0;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(x);\n\n    // a temporary value\n    AD<double> cosh_of_x0 = CppAD::cosh(x[0]);\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) y(m);\n    y[0] = CppAD::acosh(cosh_of_x0);\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(x, y);\n\n    // check value\n    ok &= NearEqual(y[0] , x0,  eps, eps);\n\n    // forward computation of first partial w.r.t. x[0]\n    CPPAD_TESTVECTOR(double) dx(n);\n    CPPAD_TESTVECTOR(double) dy(m);\n    dx[0] = 1.;\n    dy    = f.Forward(1, dx);\n    ok   &= NearEqual(dy[0], 1., eps, eps);\n\n    // reverse computation of derivative of y[0]\n    CPPAD_TESTVECTOR(double)  w(m);\n    CPPAD_TESTVECTOR(double) dw(n);\n    w[0]  = 1.;\n    dw    = f.Reverse(1, w);\n    ok   &= NearEqual(dw[0], 1., eps, eps);\n\n    // use a VecAD<Base>::reference object with acosh\n    CppAD::VecAD<double> v(1);\n    AD<double> zero(0);\n    v[zero] = cosh_of_x0;\n    AD<double> result = CppAD::acosh(v[zero]);\n    ok     &= NearEqual(result, x0, eps, eps);\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/ad_assign.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin ad_assign.cpp}\n\nAD Assignment: Example and Test\n###############################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end ad_assign.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n\nbool ad_assign(void)\n{   bool ok = true;   // initialize test result flag\n    using CppAD::AD;  // so can use AD in place of CppAD::AD\n\n    // assignment to base value\n    AD<double> a;\n    a = 1.;\n    ok &= a == 1.;\n\n    // assignment to a value that converts to the base type\n    a = 2;\n    ok &= a == 2.;\n\n    // assignment to an AD<Base>\n    AD<double> b(3.);\n    a = b;\n    ok &= a == 3.;\n\n    // assignment to an VecAD<Base> element\n    CppAD::VecAD<double> v(1);\n    v[0] = 4.;\n    a = v[0];\n    ok &= a == 4.;\n\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/general/ad_ctor.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin ad_ctor.cpp}\n\nAD Constructors: Example and Test\n#################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end ad_ctor.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n\nbool ad_ctor(void)\n{   bool ok = true;   // initialize test result flag\n    using CppAD::AD;  // so can use AD in place of CppAD::AD\n\n    // default constructor\n    AD<double> a;\n    a = 0.;\n    ok &= a == 0.;\n    ok &= Constant(a);\n\n    // constructor from base type\n    AD<double> b(1.);\n    ok &= b == 1.;\n    ok &= Constant(b);\n\n    // constructor from another type that converts to the base type\n    AD<double> c(2);\n    ok &= c == 2.;\n    ok &= Constant(c);\n\n    // constructor from AD<Base>\n    AD<double> d(c);\n    ok &= d == c;\n\n    // constructor from a VecAD<Base> element\n    CppAD::VecAD<double> v(1);\n    v[0] = 3.;\n    AD<double> e( v[0] );\n    ok &= e == 3.;\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/ad_fun.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin ad_fun.cpp}\n\nCreating Your Own Interface to an ADFun Object\n##############################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end ad_fun.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n\nnamespace {\n\n    // This class is an example of a different interface to an AD function object\n    template <class Base>\n    class my_ad_fun {\n\n    private:\n        CppAD::ADFun<Base> f;\n\n    public:\n        // default constructor\n        my_ad_fun(void)\n        { }\n\n        // destructor\n        ~ my_ad_fun(void)\n        { }\n\n        // Construct an my_ad_fun object with an operation sequence.\n        // This is the same as for ADFun<Base> except that no zero\n        // order forward sweep is done. Note Hessian and Jacobian do\n        // their own zero order forward mode sweep.\n        template <class ADvector>\n        my_ad_fun(const ADvector& x, const ADvector& y)\n        {   f.Dependent(x, y); }\n\n        // same as ADFun<Base>::Jacobian\n        template <class BaseVector>\n        BaseVector jacobian(const BaseVector& x)\n        {   return f.Jacobian(x); }\n\n        // same as ADFun<Base>::Hessian\n            template <class BaseVector>\n        BaseVector hessian(const BaseVector &x, const BaseVector &w)\n        {   return f.Hessian(x, w); }\n    };\n\n} // End empty namespace\n\nbool ad_fun(void)\n{   // This example is similar to example/jacobian.cpp, except that it\n    // uses my_ad_fun instead of ADFun.\n\n    bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    using CppAD::exp;\n    using CppAD::sin;\n    using CppAD::cos;\n\n    // domain space vector\n    size_t n = 2;\n    CPPAD_TESTVECTOR(AD<double>)  X(n);\n    X[0] = 1.;\n    X[1] = 2.;\n\n    // declare independent variables and starting recording\n    CppAD::Independent(X);\n\n    // a calculation between the domain and range values\n    AD<double> Square = X[0] * X[0];\n\n    // range space vector\n    size_t m = 3;\n    CPPAD_TESTVECTOR(AD<double>)  Y(m);\n    Y[0] = Square * exp( X[1] );\n    Y[1] = Square * sin( X[1] );\n    Y[2] = Square * cos( X[1] );\n\n    // create f: X -> Y and stop tape recording\n    my_ad_fun<double> f(X, Y);\n\n    // new value for the independent variable vector\n    CPPAD_TESTVECTOR(double) x(n);\n    x[0] = 2.;\n    x[1] = 1.;\n\n    // compute the derivative at this x\n    CPPAD_TESTVECTOR(double) jac( m * n );\n    jac = f.jacobian(x);\n\n    /*\n    F'(x) = [ 2 * x[0] * exp(x[1]) ,  x[0] * x[0] * exp(x[1]) ]\n            [ 2 * x[0] * sin(x[1]) ,  x[0] * x[0] * cos(x[1]) ]\n            [ 2 * x[0] * cos(x[1]) , -x[0] * x[0] * sin(x[i]) ]\n    */\n    ok &=  NearEqual( 2.*x[0]*exp(x[1]), jac[0*n+0], eps99, eps99);\n    ok &=  NearEqual( 2.*x[0]*sin(x[1]), jac[1*n+0], eps99, eps99);\n    ok &=  NearEqual( 2.*x[0]*cos(x[1]), jac[2*n+0], eps99, eps99);\n\n    ok &=  NearEqual( x[0] * x[0] *exp(x[1]), jac[0*n+1], eps99, eps99);\n    ok &=  NearEqual( x[0] * x[0] *cos(x[1]), jac[1*n+1], eps99, eps99);\n    ok &=  NearEqual(-x[0] * x[0] *sin(x[1]), jac[2*n+1], eps99, eps99);\n\n    return ok;\n}\n\n\n// END C++\n"
  },
  {
    "path": "example/general/ad_in_c.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin ad_in_c.cpp}\n\nExample and Test Linking CppAD to Languages Other than C++\n##########################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end ad_in_c.cpp}\n*/\n// BEGIN C++\n# include <cstdio>\n# include <cppad/cppad.hpp>\n# include <list>\n\nnamespace { // Begin empty namespace *****************************************\n\n/*\nvoid debug_print(const char *label, double d)\n{   using std::printf;\n\n    unsigned char *byte = reinterpret_cast<unsigned char *>(&d);\n    size_t n_byte = sizeof(d);\n    printf(\"%s\", label);\n    for(size_t i = 0; i < n_byte; i++)\n        printf(\"%x\", byte[i]);\n    printf(\"\\n\");\n}\n*/\n\n// type in C corresponding to an AD<double> object\ntypedef struct { void*  p_void; } cad;\n\n// type in C corresponding to a an ADFun<double>\ntypedef struct { void* p_void; } cad_fun;\n\n// type in C corresponding to a C AD binary operator\ntypedef enum { op_add, op_sub, op_mul, op_div } cad_binary_op;\n\n// type in C corresponding to a C AD unary operator\ntypedef enum {\n    op_abs, op_acos, op_asin, op_atan, op_cos, op_cosh,\n    op_exp, op_log,  op_sin,  op_sinh, op_sqrt\n} cad_unary_op;\n\n// --------------------------------------------------------------------------\n// helper code not intended for use by C code  ------------------------------\nusing CppAD::AD;\nusing CppAD::ADFun;\nusing CppAD::vector;\nusing CppAD::NearEqual;\n\nvoid cad2vector(size_t n, cad* p_cad, vector< AD<double> >& v)\n{   assert( n == v.size() );\n    for(size_t j = 0; j < n; j++)\n    {   AD<double>* p_ad =\n            reinterpret_cast< AD<double>* > (p_cad[j].p_void);\n        v[j] = *p_ad;\n    }\n}\n\nvoid vector2cad(size_t n, vector< AD<double> >& v, cad* p_cad)\n{   assert( n == v.size() );\n    for(size_t j = 0; j < n; j++)\n    {   AD<double>* p_ad =\n            reinterpret_cast< AD<double>* > (p_cad[j].p_void);\n        *p_ad = v[j];\n    }\n}\n\nvoid double2vector(size_t n, double* p_dbl, vector<double>& v)\n{   assert( n == v.size() );\n    for(size_t j = 0; j < n; j++)\n        v[j] = p_dbl[j];\n}\n\nvoid vector2double(size_t n, vector<double>& v, double *p_dbl)\n{   assert( n == v.size() );\n    for(size_t j = 0; j < n; j++)\n        p_dbl[j] = v[j];\n}\n\nstd::list<void*> allocated;\n# ifdef NDEBUG\ninline void push_allocated(void *p)\n{ }\ninline void pop_allocated(void *p)\n{ }\n# else\ninline void push_allocated(void *p)\n{   assert( p != 0 );\n    allocated.push_front(p);\n}\ninline void pop_allocated(void *p)\n{   std::list<void*>::iterator i;\n    for(i = allocated.begin(); i != allocated.end(); ++i)\n    {   if( *i == p )\n        {   allocated.erase(i);\n            return;\n        }\n    }\n    assert( 0 );\n}\n\n# endif\n// --------------------------------------------------------------------------\n// Here is the code that links C to CppAD. You will have to add more\n// functions and operators to make a complete language link.\n//\nextern \"C\"\nbool cad_near_equal(double x, double y)\n{   double eps = 10. * std::numeric_limits<double>::epsilon();\n    return NearEqual(x, y, eps, 0.);\n}\n\n// create a C++ AD object\n// value is the value that the C++ AD object will have\n// p_cad->p_void: on input is 0, on output points to C++ AD object\nextern \"C\"\nvoid cad_new_ad(cad *p_cad, double value)\n{   // make sure pointer is not currently allocated\n    assert( p_cad->p_void == 0 );\n\n    AD<double>* p_ad   = new AD<double>(value);\n    p_cad->p_void      = reinterpret_cast<void*>(p_ad);\n\n    // put in list of allocate pointers\n    push_allocated( p_cad->p_void );\n}\n\n// delete a C++ AD object\n// p_cad->value: not used\n// p_cad->p_void: on input points to C++ AD object, on output is 0\nextern \"C\"\nvoid cad_del_ad(cad* p_cad)\n{   // make sure that p_cad has been allocated\n    pop_allocated( p_cad->p_void );\n\n    AD<double>* p_ad   = reinterpret_cast< AD<double>* >( p_cad->p_void );\n    delete p_ad;\n\n    // special value for pointers that are not allocated\n    p_cad->p_void = 0;\n}\n\n// extract the value from a C++ AD object\n// extern \"C\"\ndouble cad_value(cad* p_cad)\n{   AD<double>* p_ad = reinterpret_cast< AD<double>* > (p_cad->p_void);\n    return Value( Var2Par(*p_ad) );\n}\n\n// preform a C AD unary operation\nextern \"C\"\nvoid cad_unary(cad_unary_op op, cad* p_operand, cad* p_result)\n{   AD<double> *operand, *result;\n    result  = reinterpret_cast< AD<double>* > (p_result->p_void);\n    operand = reinterpret_cast< AD<double>* > (p_operand->p_void);\n    switch(op)\n    {\n        case op_abs:\n        *result = fabs( *operand );\n        break;\n\n        case op_acos:\n        *result = acos( *operand );\n        break;\n\n        case op_asin:\n        *result = asin( *operand );\n        break;\n\n        case op_atan:\n        *result = atan( *operand );\n        break;\n\n        case op_cos:\n        *result = cos( *operand );\n        break;\n\n        case op_cosh:\n        *result = cosh( *operand );\n        break;\n\n        case op_exp:\n        *result = exp( *operand );\n        break;\n\n        case op_log:\n        *result = log( *operand );\n        break;\n\n        case op_sin:\n        *result = sin( *operand );\n        break;\n\n        case op_sinh:\n        *result = sinh( *operand );\n        break;\n\n        case op_sqrt:\n        *result = sqrt( *operand );\n        break;\n\n        default:\n        // not a unary operator\n        assert(0);\n        break;\n\n    }\n    return;\n}\n\n// perform a C AD binary operation\nextern \"C\"\nvoid cad_binary(cad_binary_op op, cad* p_left, cad* p_right, cad* p_result)\n{   AD<double> *result, *left, *right;\n    result = reinterpret_cast< AD<double>* > (p_result->p_void);\n    left   = reinterpret_cast< AD<double>* > (p_left->p_void);\n    right  = reinterpret_cast< AD<double>* > (p_right->p_void);\n    assert( result != 0 );\n    assert( left != 0 );\n    assert( right != 0 );\n\n    switch(op)\n    {   case op_add:\n        *result         = *left + (*right);\n        break;\n\n        case op_sub:\n        *result         = *left - (*right);\n        break;\n\n        case op_mul:\n        *result         = *left * (*right);\n        break;\n\n        case op_div:\n        *result         = *left / (*right);\n        break;\n\n        default:\n        // not a binary operator\n        assert(0);\n    }\n    return;\n}\n\n// declare the independent variables in C++\nextern \"C\"\nvoid cad_independent(size_t n, cad* px_cad)\n{   vector< AD<double> > x(n);\n    cad2vector(n, px_cad, x);\n    CppAD::Independent(x);\n    vector2cad(n, x, px_cad);\n}\n\n// create an ADFun object in C++\nextern \"C\"\ncad_fun cad_new_fun(size_t n, size_t m, cad* px_cad, cad* py_cad)\n{   cad_fun fun;\n\n    ADFun<double>* p_adfun = new ADFun<double>;\n    vector< AD<double> > x(n);\n    vector< AD<double> > y(m);\n    cad2vector(n, px_cad, x);\n    cad2vector(m, py_cad, y);\n    p_adfun->Dependent(x, y);\n\n    fun.p_void = reinterpret_cast<void*>( p_adfun );\n\n    // put in list of allocate pointers\n    push_allocated( fun.p_void );\n\n    return fun;\n}\n\n// delete an AD function object in C\nextern \"C\"\nvoid cad_del_fun(cad_fun *fun)\n{   // make sure this pointer has been allocated\n    pop_allocated( fun->p_void );\n\n    ADFun<double>* p_adfun\n        = reinterpret_cast< ADFun<double>* > (fun->p_void);\n    delete p_adfun;\n\n    // special value for pointers that are not allocated\n    fun->p_void = 0;\n}\n\n// evaluate the Jacobian corresponding to a function object\nextern \"C\"\nvoid cad_jacobian(cad_fun fun,\n    size_t n, size_t m, double* px, double* pjac )\n{   assert( fun.p_void != 0 );\n\n    ADFun<double>* p_adfun =\n        reinterpret_cast< ADFun<double>* >(fun.p_void);\n    vector<double> x(n), jac(n * m);\n\n    double2vector(n, px, x);\n    jac = p_adfun->Jacobian(x);\n    vector2double(n * m, jac, pjac);\n}\n\n// forward mode\nextern \"C\"\nvoid cad_forward(cad_fun fun,\n    size_t order, size_t n, size_t m, double* px, double* py )\n{   assert( fun.p_void != 0 );\n\n    ADFun<double>* p_adfun =\n        reinterpret_cast< ADFun<double>* >(fun.p_void);\n    vector<double> x(n), y(m);\n\n    double2vector(n, px, x);\n    y = p_adfun->Forward(order, x);\n    vector2double(m, y, py);\n}\n\n// check that allocated list has been completely freed\nextern \"C\"\nbool cad_allocated_empty(void)\n{   return allocated.empty();\n}\n\n} // End empty namespace ****************************************************\n\n# include <math.h> // used to check results in c code below\n\n# define N 2       // number of independent variables in example\n# define M 5       // number of dependent variables in example\n\n// -------------------------------------------------------------------------\n// Here is the C code that uses the CppAD link above\nbool ad_in_c(void)\n{   // This routine is intentionally coded as if it were written in C\n    // as an example of how you can link C, and other languages to CppAD\n    bool ok = true;\n\n    // x vector of AD objects in C\n    double value;\n    size_t j, n = N;\n    cad X[N];\n    for(j = 0; j < n; j++)\n    {   value       = (double) (j+1) / (double) n;\n        X[j].p_void = 0;\n        cad_new_ad(X + j, value);\n    }\n\n    // y vector of AD objects in C\n    size_t i, m = M;\n    cad Y[M];\n    for(i = 0; i < m; i++)\n    {   value       = 0.; // required, but not used\n        Y[i].p_void = 0;\n        cad_new_ad(Y + i, value);\n    }\n\n    // declare X as the independent variable vector\n    cad_independent(n, X);\n\n    // y[0] = x[0] + x[1]\n    cad_binary(op_add, X+0, X+1, Y+0);\n    ok &= cad_near_equal( cad_value(Y+0), cad_value(X+0)+cad_value(X+1) );\n\n    // y[1] = x[0] - x[1]\n    cad_binary(op_sub, X+0, X+1, Y+1);\n    ok &= cad_near_equal( cad_value(Y+1), cad_value(X+0)-cad_value(X+1) );\n\n    // y[2] = x[0] * x[1]\n    cad_binary(op_mul, X+0, X+1, Y+2);\n    ok &= cad_near_equal( cad_value(Y+2), cad_value(X+0)*cad_value(X+1) );\n\n    // y[3] = x[0] * x[1]\n    cad_binary(op_div, X+0, X+1, Y+3);\n    ok &= cad_near_equal( cad_value(Y+3), cad_value(X+0)/cad_value(X+1) );\n\n    // y[4] = sin(x[0]) + asin(sin(x[0]))\n    cad sin_x0 = { 0 };       // initialize p_void as zero\n    cad_new_ad( &sin_x0, 0.);\n    cad_unary(op_sin, X+0, &sin_x0);\n    ok &= cad_near_equal(cad_value(&sin_x0), sin(cad_value(X+0)) );\n\n    cad asin_sin_x0 = { 0 };  // initialize p_void as zero\n    cad_new_ad( &asin_sin_x0, 0.);\n    cad_unary(op_asin, &sin_x0, &asin_sin_x0);\n    ok &= cad_near_equal(\n        cad_value(&asin_sin_x0),\n        asin( cad_value(&sin_x0) )\n    );\n\n    cad_binary(op_add, &sin_x0, &asin_sin_x0, Y+4);\n    ok &= cad_near_equal(\n        cad_value(Y+4),\n        cad_value(&sin_x0) + cad_value(&asin_sin_x0)\n    );\n\n    // declare y as the dependent variable vector and stop recording\n    // and store function object in f\n    cad_fun f = cad_new_fun(n, m, X, Y);\n\n    // now use the function object\n    double x[N], jac[N * M];\n    x[0] = 1.;\n    x[1] = .5;\n\n    // compute the Jacobian\n    cad_jacobian(f, n, m, x, jac);\n\n    // check the Jacobian values\n    size_t k = 0;\n    // partial y[0] w.r.t. x[0]\n    ok &= cad_near_equal(jac[k++], 1.);\n    // partial y[0] w.r.t. x[1]\n    ok &= cad_near_equal(jac[k++], 1.);\n    // partial y[1] w.r.t. x[0]\n    ok &= cad_near_equal(jac[k++], 1.);\n    // partial y[1] w.r.t. x[1]\n    ok &= cad_near_equal(jac[k++], -1.);\n    // partial y[2] w.r.t. x[0]\n    ok &= cad_near_equal(jac[k++], x[1]);\n    // partial y[2] w.r.t. x[1]\n    ok &= cad_near_equal(jac[k++], x[0]);\n    // partial y[3] w.r.t. x[0]\n    ok &= cad_near_equal(jac[k++], 1./x[1]);\n    // partial y[3] w.r.t. x[1]\n    ok &= cad_near_equal(jac[k++], -x[0]/(x[1]*x[1]));\n    // partial y[4] w.r.t x[0]\n    ok &= cad_near_equal(jac[k++],  cos(x[0]) + 1.);\n    // partial y[4] w.r.t x[1]\n    ok &= cad_near_equal(jac[k++],  0.);\n\n    // evaluate the function f at a different x\n    size_t order = 0;\n    double y[M];\n    x[0] = .5;\n    x[1] = 1.;\n    cad_forward(f, order, n, m, x, y);\n\n    // check the function values\n    ok &= cad_near_equal(y[0] , x[0] + x[1] );\n    ok &= cad_near_equal(y[1] , x[0] - x[1] );\n    ok &= cad_near_equal(y[2] , x[0] * x[1] );\n    ok &= cad_near_equal(y[3] , x[0] / x[1] );\n    ok &= cad_near_equal(y[4] , sin(x[0]) + asin(sin(x[0])) );\n\n    // delete All C++ copies of the AD objects\n    cad_del_fun( &f );\n    cad_del_ad( &sin_x0 );\n    cad_del_ad( &asin_sin_x0 );\n    for(j = 0; j < n; j++)\n        cad_del_ad(X + j);\n    for(i = 0; i < m; i++)\n        cad_del_ad(Y + i);\n\n    ok     &= cad_allocated_empty();\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/ad_input.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin ad_input.cpp}\n\nAD Output Operator: Example and Test\n####################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end ad_input.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n\n# include <sstream>  // std::istringstream\n# include <string>   // std::string\n\nbool ad_input(void)\n{   bool ok = true;\n\n    // create the input string stream is.\n    std::string str (\"123 456\");\n    std::istringstream is(str);\n\n    // start and AD<double> recording\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) x(1), y(1);\n    x[0] = 1.0;\n    CppAD::Independent(x);\n    CppAD::AD<double> z = x[0];\n    ok &= Variable(z);\n\n    // read first number into z and second into y[0]\n    is >> z >> y[0];\n    ok   &= Parameter(z);\n    ok   &= (z == 123.);\n    ok   &= Parameter(y[0]);\n    ok   &= (y[0] == 456.);\n    //\n    // terminate recording starting by call to Independent\n    CppAD::ADFun<double> f(x, y);\n\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/general/ad_output.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin ad_output.cpp}\n\nAD Output Operator: Example and Test\n####################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end ad_output.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n\n# include <sstream>  // std::ostringstream\n# include <string>   // std::string\n# include <iomanip>  // std::setprecision, setw, setfill, right\n\nnamespace {\n    template <class S>\n    void set_ostream(S &os)\n    {   os\n        << std::setprecision(4) // 4 digits of precision\n        << std::setw(6)         // 6 characters per field\n        << std::setfill(' ')    // fill with spaces\n        << std::right;          // adjust value to the right\n    }\n}\n\nbool ad_output(void)\n{   bool ok = true;\n\n    // This output stream is an ostringstream for testing purposes.\n    // You can use << with other types of streams; i.e., std::cout.\n    std::ostringstream stream;\n\n    // output an AD<double> object\n    CppAD::AD<double>  pi = 4. * atan(1.); // 3.1415926536\n    set_ostream(stream);\n    stream << pi;\n\n    // output a VecAD<double>::reference object\n    CppAD::VecAD<double> v(1);\n    CppAD::AD<double> zero(0);\n    v[zero]   = exp(1.);                  // 2.7182818285\n    set_ostream(stream);\n    stream << v[zero];\n\n    // convert output from stream to string\n    std::string str = stream.str();\n\n    // check the output\n    ok      &= (str == \" 3.142 2.718\");\n\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/general/add.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin add.cpp}\n\nAD Binary Addition: Example and Test\n####################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end add.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nbool Add(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n  = 1;\n    double x0 = 0.5;\n    CPPAD_TESTVECTOR(AD<double>) x(n);\n    x[0]      = x0;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(x);\n\n    // some binary addition operations\n    AD<double> a = x[0] + 1.; // AD<double> + double\n    AD<double> b = a    + 2;  // AD<double> + int\n    AD<double> c = 3.   + b;  // double     + AD<double>\n    AD<double> d = 4    + c;  // int        + AD<double>\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) y(m);\n    y[0] = d + x[0];          // AD<double> + AD<double>\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(x, y);\n\n    // check value\n    ok &= NearEqual(y[0] , 2. * x0 + 10, eps99, eps99);\n\n    // forward computation of partials w.r.t. x[0]\n    CPPAD_TESTVECTOR(double) dx(n);\n    CPPAD_TESTVECTOR(double) dy(m);\n    dx[0] = 1.;\n    dy    = f.Forward(1, dx);\n    ok   &= NearEqual(dy[0], 2., eps99, eps99);\n\n    // reverse computation of derivative of y[0]\n    CPPAD_TESTVECTOR(double)  w(m);\n    CPPAD_TESTVECTOR(double) dw(n);\n    w[0]  = 1.;\n    dw    = f.Reverse(1, w);\n    ok   &= NearEqual(dw[0], 2., eps99, eps99);\n\n    // use a VecAD<Base>::reference object with addition\n    CppAD::VecAD<double> v(1);\n    AD<double> zero(0);\n    v[zero] = a;\n    AD<double> result = v[zero] + 2;\n    ok     &= (result == b);\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/add_eq.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin add_eq.cpp}\n\nAD Compound Assignment Addition: Example and Test\n#################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end add_eq.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nbool AddEq(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t  n = 1;\n    double x0 = .5;\n    CPPAD_TESTVECTOR(AD<double>) x(n);\n    x[0]      = x0;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(x);\n\n    // range space vector\n    size_t m = 2;\n    CPPAD_TESTVECTOR(AD<double>) y(m);\n    y[0] = x[0];         // initial value\n    y[0] += 2;           // AD<double> += int\n    y[0] += 4.;          // AD<double> += double\n    y[1] = y[0] += x[0]; // use the result of a compound assignment\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(x, y);\n\n    // check value\n    ok &= NearEqual(y[0] , x0+2.+4.+x0, eps99, eps99);\n    ok &= NearEqual(y[1] ,        y[0], eps99, eps99);\n\n    // forward computation of partials w.r.t. x[0]\n    CPPAD_TESTVECTOR(double) dx(n);\n    CPPAD_TESTVECTOR(double) dy(m);\n    dx[0] = 1.;\n    dy    = f.Forward(1, dx);\n    ok   &= NearEqual(dy[0], 2., eps99, eps99);\n    ok   &= NearEqual(dy[1], 2., eps99, eps99);\n\n    // reverse computation of derivative of y[0]\n    CPPAD_TESTVECTOR(double)  w(m);\n    CPPAD_TESTVECTOR(double) dw(n);\n    w[0]  = 1.;\n    w[1]  = 0.;\n    dw    = f.Reverse(1, w);\n    ok   &= NearEqual(dw[0], 2., eps99, eps99);\n\n    // use a VecAD<Base>::reference object with computed addition\n    CppAD::VecAD<double> v(1);\n    AD<double> zero(0);\n    AD<double> result = 1;\n    v[zero] = 2;\n    result += v[zero];\n    ok     &= (result == 3);\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/asin.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin asin.cpp}\n\nThe AD asin Function: Example and Test\n######################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end asin.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n\nbool asin(void)\n{   bool ok = true;\n\n    using CppAD::AD;\n    using CppAD::NearEqual;\n\n    // 10 times machine epsilon\n    double eps = 10. * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n  = 1;\n    double x0 = 0.5;\n    CPPAD_TESTVECTOR(AD<double>) x(n);\n    x[0]      = x0;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(x);\n\n    // a temporary value\n    AD<double> sin_of_x0 = CppAD::sin(x[0]);\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) y(m);\n    y[0] = CppAD::asin(sin_of_x0);\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(x, y);\n\n    // check value\n    ok &= NearEqual(y[0] , x0,  eps, eps);\n\n    // forward computation of first partial w.r.t. x[0]\n    CPPAD_TESTVECTOR(double) dx(n);\n    CPPAD_TESTVECTOR(double) dy(m);\n    dx[0] = 1.;\n    dy    = f.Forward(1, dx);\n    ok   &= NearEqual(dy[0], 1., eps, eps);\n\n    // reverse computation of derivative of y[0]\n    CPPAD_TESTVECTOR(double)  w(m);\n    CPPAD_TESTVECTOR(double) dw(n);\n    w[0]  = 1.;\n    dw    = f.Reverse(1, w);\n    ok   &= NearEqual(dw[0], 1., eps, eps);\n\n    // use a VecAD<Base>::reference object with asin\n    CppAD::VecAD<double> v(1);\n    AD<double> zero(0);\n    v[zero] = sin_of_x0;\n    AD<double> result = CppAD::asin(v[zero]);\n    ok     &= NearEqual(result, x0, eps, eps);\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/asinh.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin asinh.cpp}\n\nThe AD asinh Function: Example and Test\n#######################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end asinh.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n\nbool asinh(void)\n{   bool ok = true;\n\n    using CppAD::AD;\n    using CppAD::NearEqual;\n\n    // 10 times machine epsilon\n    double eps = 10. * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n  = 1;\n    double x0 = 0.5;\n    CPPAD_TESTVECTOR(AD<double>) x(n);\n    x[0]      = x0;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(x);\n\n    // a temporary value\n    AD<double> sinh_of_x0 = CppAD::sinh(x[0]);\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) y(m);\n    y[0] = CppAD::asinh(sinh_of_x0);\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(x, y);\n\n    // check value\n    ok &= NearEqual(y[0] , x0,  eps, eps);\n\n    // forward computation of first partial w.r.t. x[0]\n    CPPAD_TESTVECTOR(double) dx(n);\n    CPPAD_TESTVECTOR(double) dy(m);\n    dx[0] = 1.;\n    dy    = f.Forward(1, dx);\n    ok   &= NearEqual(dy[0], 1., eps, eps);\n\n    // reverse computation of derivative of y[0]\n    CPPAD_TESTVECTOR(double)  w(m);\n    CPPAD_TESTVECTOR(double) dw(n);\n    w[0]  = 1.;\n    dw    = f.Reverse(1, w);\n    ok   &= NearEqual(dw[0], 1., eps, eps);\n\n    // use a VecAD<Base>::reference object with asinh\n    CppAD::VecAD<double> v(1);\n    AD<double> zero(0);\n    v[zero] = sinh_of_x0;\n    AD<double> result = CppAD::asinh(v[zero]);\n    ok     &= NearEqual(result, x0, eps, eps);\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/atan.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin atan.cpp}\n\nThe AD atan Function: Example and Test\n######################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end atan.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n\nbool atan(void)\n{   bool ok = true;\n\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n  = 1;\n    double x0 = 0.5;\n    CPPAD_TESTVECTOR(AD<double>) x(n);\n    x[0]      = x0;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(x);\n\n    // a temporary value\n    AD<double> tan_of_x0 = CppAD::tan(x[0]);\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) y(m);\n    y[0] = CppAD::atan(tan_of_x0);\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(x, y);\n\n    // check value\n    ok &= NearEqual(y[0] , x0, eps99, eps99);\n\n    // forward computation of first partial w.r.t. x[0]\n    CPPAD_TESTVECTOR(double) dx(n);\n    CPPAD_TESTVECTOR(double) dy(m);\n    dx[0] = 1.;\n    dy    = f.Forward(1, dx);\n    ok   &= NearEqual(dy[0], 1., eps99, eps99);\n\n    // reverse computation of derivative of y[0]\n    CPPAD_TESTVECTOR(double)  w(m);\n    CPPAD_TESTVECTOR(double) dw(n);\n    w[0]  = 1.;\n    dw    = f.Reverse(1, w);\n    ok   &= NearEqual(dw[0], 1., eps99, eps99);\n\n    // use a VecAD<Base>::reference object with atan\n    CppAD::VecAD<double> v(1);\n    AD<double> zero(0);\n    v[zero] = tan_of_x0;\n    AD<double> result = CppAD::atan(v[zero]);\n    ok     &= NearEqual(result, x0, eps99, eps99);\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/atan2.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin atan2.cpp}\n\nThe AD atan2 Function: Example and Test\n#######################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end atan2.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n# define N_THETA 20\n\nbool atan2(void)\n{   bool ok = true;\n    //\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    double pi    = 2.0 * std::atan(1.0);\n    //\n    for(size_t k = 0; k < N_THETA; ++k)\n    {   // theta\n        double theta =  2.0 * pi * double(k+1) / double(N_THETA) - pi;\n        //\n        // radius\n        double radius = 1.0 + double(k) / double(N_THETA);\n        //\n        // x, y\n        double x = radius * std::cos(theta);\n        double y = radius * std::sin(theta);\n        //\n        // au\n        CPPAD_TESTVECTOR(AD<double>) au(2);\n        au[0] = x;\n        au[1] = y;\n        CppAD::Independent(au);\n        //\n        // av\n        CPPAD_TESTVECTOR(AD<double>) av(1);\n        av[0] = CppAD::atan2(au[1], au[0]);\n        //\n        // f(x, y) = atan2(y, x)\n        CppAD::ADFun<double> f(au, av);\n        //\n        // check value\n        ok &= NearEqual(av[0] , theta, eps99, eps99);\n        //\n        // partial_x, partial_y\n        // see https://en.wikipedia.org/wiki/Atan2#Derivative\n        double partial_x = - y / (radius * radius);\n        double partial_y =   x / (radius * radius);\n        //\n        // check forward mode\n        CPPAD_TESTVECTOR(double) du(2), dv(1);\n        du[0] = 1.0;\n        du[1] = 0.0;\n        dv    = f.Forward(1, du);\n        ok   &= NearEqual(dv[0], partial_x, eps99, eps99);\n        du[0] = 0.0;\n        du[1] = 1.0;\n        dv    = f.Forward(1, du);\n        ok   &= NearEqual(dv[0], partial_y, eps99, eps99);\n        //\n        // check reverse mode\n        CPPAD_TESTVECTOR(double)  w(1);\n        CPPAD_TESTVECTOR(double) dw(2);\n        w[0]  = 1.;\n        dw    = f.Reverse(1, w);\n        ok   &= NearEqual(dw[0], partial_x, eps99, eps99);\n        ok   &= NearEqual(dw[1], partial_y, eps99, eps99);\n        //\n    }\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/atanh.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin atanh.cpp}\n\nThe AD atanh Function: Example and Test\n#######################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end atanh.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n\nbool atanh(void)\n{   bool ok = true;\n\n    using CppAD::AD;\n    using CppAD::NearEqual;\n\n    // 10 times machine epsilon\n    double eps = 10. * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n  = 1;\n    double x0 = 0.5;\n    CPPAD_TESTVECTOR(AD<double>) x(n);\n    x[0]      = x0;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(x);\n\n    // a temporary value\n    AD<double> tanh_of_x0 = CppAD::tanh(x[0]);\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) y(m);\n    y[0] = CppAD::atanh(tanh_of_x0);\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(x, y);\n\n    // check value\n    ok &= NearEqual(y[0] , x0,  eps, eps);\n\n    // forward computation of first partial w.r.t. x[0]\n    CPPAD_TESTVECTOR(double) dx(n);\n    CPPAD_TESTVECTOR(double) dy(m);\n    dx[0] = 1.;\n    dy    = f.Forward(1, dx);\n    ok   &= NearEqual(dy[0], 1., eps, eps);\n\n    // reverse computation of derivative of y[0]\n    CPPAD_TESTVECTOR(double)  w(m);\n    CPPAD_TESTVECTOR(double) dw(n);\n    w[0]  = 1.;\n    dw    = f.Reverse(1, w);\n    ok   &= NearEqual(dw[0], 1., eps, eps);\n\n    // use a VecAD<Base>::reference object with atanh\n    CppAD::VecAD<double> v(1);\n    AD<double> zero(0);\n    v[zero] = tanh_of_x0;\n    AD<double> result = CppAD::atanh(v[zero]);\n    ok     &= NearEqual(result, x0, eps, eps);\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/azmul.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin azmul.cpp}\n\nAD Absolute Zero Multiplication: Example and Test\n#################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end azmul.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n# include <cmath>\n\nbool azmul(void)\n{   bool ok = true;\n\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double inf = std::numeric_limits<double>::infinity();\n    double eps = 10. * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n  = 2;\n    double x = 0.5;\n    double y = 2.0;\n    CPPAD_TESTVECTOR(AD<double>) axy(n);\n    axy[0]      = x;\n    axy[1]      = y;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(axy);\n\n    // range space vector\n    size_t m = 5;\n    CPPAD_TESTVECTOR(AD<double>) az(m);\n    az[0] = CppAD::azmul(axy[0], axy[1]); // azmul(variable, variable)\n    az[1] = CppAD::azmul(axy[0], inf);    // azmul(variable, parameter=inf)\n    az[2] = CppAD::azmul(axy[0], 3.0);    // azmul(variable, parameter=3.0)\n    az[3] = CppAD::azmul(0.0, axy[1]);    // azmul(parameter=0.0, variable)\n    az[4] = CppAD::azmul(4.0, axy[1]);    // azmul(parameter=4.0, variable)\n\n    // create f: axy -> az and stop tape recording\n    CppAD::ADFun<double> f(axy, az);\n\n    // check value when x is not zero\n    ok &= NearEqual(az[0] , x * y,  eps, eps);\n    ok &= az[1] == inf;\n    ok &= NearEqual(az[2] , x * 3.0,  eps, eps);\n    ok &= az[3] == 0.0;\n    ok &= NearEqual(az[4] , 4.0 * y,  eps, eps);\n\n\n    // check value x is zero and y is infinity\n    CPPAD_TESTVECTOR(double) xy(n), z(m);\n    xy[0] = 0.0;\n    xy[1] = inf;\n    z     = f.Forward(0, xy);\n    ok &= z[0] == 0.0;\n    ok &= z[1] == 0.0;\n    ok &= z[2] == 0.0;\n    ok &= z[3] == 0.0;\n    ok &= z[4] == inf;\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/base2ad.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin base2ad.cpp}\n{xrst_spell\n    cccc\n}\n\nTaylor's Ode Solver: base2ad Example and Test\n#############################################\n\nSee Also\n********\n:ref:`taylor_ode.cpp-name` , :ref:`mul_level_ode.cpp-name`\n\nPurpose\n*******\nThis is a realistic example using :ref:`base2ad-name` to create\nan ``AD`` < *Base* > function from an *Base* function.\nThe function represents an ordinary differential equation.\nIt is differentiated with respect to\nits :ref:`variables<glossary@Variable>` .\nThese derivatives are used by the :ref:`taylor_ode-name` method.\nThis solution is then differentiated with respect to\nthe functions :ref:`dynamic parameters<glossary@Parameter@Dynamic>` .\n\nODE\n***\nFor this example the function\n:math:`y : \\B{R} \\times \\B{R}^n \\rightarrow \\B{R}^n` is defined by\n:math:`y(0, x) = 0` and\n:math:`\\partial_t y(t, x) = g(y, x)` where\n:math:`g : \\B{R}^n \\times \\B{R}^n \\rightarrow \\B{R}^n` is defined by\n\n.. math::\n\n    g(y, x) =\n    \\left( \\begin{array}{c}\n            x_0     \\\\\n            x_1 y_0 \\\\\n            \\vdots  \\\\\n            x_{n-1} y_{n-2}\n    \\end{array} \\right)\n\nODE Solution\n************\nThe solution for this example can be calculated by\nstarting with the first row and then using the solution\nfor the first row to solve the second and so on.\nDoing this we obtain\n\n.. math::\n\n    y(t, x ) =\n    \\left( \\begin{array}{c}\n        x_0 t                  \\\\\n        x_1 x_0 t^2 / 2        \\\\\n        \\vdots                 \\\\\n        x_{n-1} x_{n-2} \\ldots x_0 t^n / n !\n    \\end{array} \\right)\n\nDerivative of ODE Solution\n**************************\nDifferentiating the solution above,\nwith respect to the parameter vector :math:`x`,\nwe notice that\n\n.. math::\n\n    \\partial_x y(t, x ) =\n    \\left( \\begin{array}{cccc}\n    y_0 (t,x) / x_0      & 0                   & \\cdots & 0      \\\\\n    y_1 (t,x) / x_0      & y_1 (t,x) / x_1     & 0      & \\vdots \\\\\n    \\vdots               & \\vdots              & \\ddots & 0      \\\\\n    y_{n-1} (t,x) / x_0  & y_{n-1} (t,x) / x_1 & \\cdots & y_{n-1} (t,x) / x_{n-1}\n    \\end{array} \\right)\n\nTaylor's Method Using AD\n************************\nWe define the function :math:`z(t, x)` by the equation\n\n.. math::\n\n    z ( t , x ) = g[ y ( t , x ), x ]\n\nsee :ref:`taylor_ode-name` for the method used to compute the\nTaylor coefficients w.r.t :math:`t` of :math:`y(t, x)`.\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end base2ad.cpp}\n--------------------------------------------------------------------------\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n\n// =========================================================================\nnamespace { // BEGIN empty namespace\n\ntypedef CppAD::AD<double>                  a_double;\n\ntypedef CPPAD_TESTVECTOR(double)           d_vector;\ntypedef CPPAD_TESTVECTOR(a_double)         a_vector;\n\ntypedef CppAD::ADFun<double>               fun_double;\ntypedef CppAD::ADFun<a_double, double>     afun_double;\n\n// -------------------------------------------------------------------------\n// class definition for C++ function object that defines ODE\nclass Ode {\nprivate:\n    // copy of x that is set by constructor and used by g(y)\n    a_vector x_;\npublic:\n    // constructor\n    Ode(const a_vector& x) : x_(x)\n    { }\n    // the function g(y) given the parameter vector x\n    a_vector operator() (const a_vector& y) const\n    {   size_t n = y.size();\n        a_vector g(n);\n        g[0] = x_[0];\n        for(size_t i = 1; i < n; i++)\n            g[i] = x_[i] * y[i-1];\n        //\n        return g;\n    }\n};\n\n// -------------------------------------------------------------------------\n// Routine that uses Taylor's method to solve ordinary differential equaitons\na_vector taylor_ode(\n    afun_double&     fun_g   ,  // function that defines the ODE\n    size_t           order   ,  // order of Taylor's method used\n    size_t           nstep   ,  // number of steps to take\n    const a_double&  dt      ,  // Delta t for each step\n    const a_vector&  y_ini)     // y(t) at the initial time\n{\n    // number of variables in the ODE\n    size_t n = y_ini.size();\n\n    // initialize y\n    a_vector y = y_ini;\n\n    // loop with respect to each step of Taylors method\n    for(size_t s = 0; s < nstep; s++)\n    {\n        // initialize\n        a_vector y_k   = y;\n        a_double dt_k  = a_double(1.0);\n        a_vector next  = y;\n\n        for(size_t k = 0; k < order; k++)\n        {\n            // evaluate k-th order Taylor coefficient z^{(k)} (t)\n            a_vector z_k = fun_g.Forward(k, y_k);\n\n            // dt^{k+1}\n            dt_k *= dt;\n\n            // y^{(k+1)}\n            for(size_t i = 0; i < n; i++)\n            {   // y^{(k+1)}\n                y_k[i] = z_k[i] / a_double(k + 1);\n\n                // add term for k+1 Taylor coefficient\n                // to solution for next y\n                next[i] += y_k[i] * dt_k;\n            }\n        }\n\n        // take step\n        y = next;\n    }\n    return y;\n}\n} // END empty namespace\n\n// ==========================================================================\n// Routine that tests algorithmic differentiation of solutions computed\n// by the routine taylor_ode.\nbool base2ad(void)\n{   bool ok = true;\n    double eps = 100. * std::numeric_limits<double>::epsilon();\n\n    // number of components in differential equation\n    size_t n = 4;\n\n    // record function g(y, x)\n    // with y as the independent variables and x as dynamic parameters\n    a_vector  ay(n), ax(n);\n    for(size_t i = 0; i < n; i++)\n        ay[i] = ax[i] = double(i + 1);\n    CppAD::Independent(ay, ax);\n\n    // fun_g\n    Ode G(ax);\n    a_vector ag = G(ay);\n    fun_double fun_g(ay, ag);\n\n\n    // afun_g\n    afun_double afun_g( fun_g.base2ad() ); // differential equation\n\n    // other arguments to taylor_ode\n    size_t   order = n;       // order of Taylor's method used\n    size_t   nstep = 2;       // number of steps to take\n    a_double adt   = 1.;      // Delta t for each step\n    a_vector ay_ini(n);       // initial value of y\n    for(size_t i = 0; i < n; i++)\n        ay_ini[i] = 0.;\n\n    // declare x as independent variables\n    CppAD::Independent(ax);\n\n    // the independent variables if this function are\n    // the dynamic parameters in afun_g\n    afun_g.new_dynamic(ax);\n\n    // integrate the differential equation\n    a_vector ay_final;\n    ay_final = taylor_ode(afun_g, order, nstep, adt, ay_ini);\n\n    // define differentiable function object f(x) = y_final(x)\n    // that computes its derivatives in double\n    CppAD::ADFun<double> fun_f(ax, ay_final);\n\n    // double version of ax\n    d_vector x(n);\n    for(size_t i = 0; i < n; i++)\n        x[i] = Value( ax[i] );\n\n    // check function values\n    double check = 1.;\n    double t     = double(nstep) * Value(adt);\n    for(size_t i = 0; i < n; i++)\n    {   check *= x[i] * t / double(i + 1);\n        ok &= CppAD::NearEqual(Value(ay_final[i]), check, eps, eps);\n    }\n\n    // There appears to be a bug in g++ version 4.4.2 because it generates\n    // a warning for the equivalent form\n    // d_vector jac = fun_f.Jacobian(x);\n    d_vector jac ( fun_f.Jacobian(x) );\n\n    // check Jacobian\n    for(size_t i = 0; i < n; i++)\n    {   for(size_t j = 0; j < n; j++)\n        {   double jac_ij = jac[i * n + j];\n            if( i < j )\n                check = 0.;\n            else\n                check = Value( ay_final[i] ) / x[j];\n            ok &= CppAD::NearEqual(jac_ij, check, eps, eps);\n        }\n    }\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/base2vec_ad.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin base2vec_ad.cpp}\n\nUsing base2ad and VecAD together: Example and Test\n##################################################\n\nPurpose\n*******\nThis example demonstrate that :ref:`base2ad-name` does not convert\n:ref:`VecAD-name` operations as might be expected.\nTo be specific, this indexing into a VecAD object gets fixed\nwhen zero order forward mode is run for a ``base2ad`` result; e.g.\n*af* below.\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end base2vec_ad.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nbool base2vec_ad(void)\n{   using CppAD::vector;\n    using CppAD::AD;\n    //\n    bool ok = true;\n    //\n    // f(x) = x[0] if 0 <= x[2] < 1\n    //      = x[1] if 1 <= x[2] < 2\n    vector< AD<double> > ax(3), ay(1);\n    ax[0] = 3.0;\n    ax[1] = 2.0;\n    ax[2] = 1.0;\n    Independent(ax);\n    CppAD::VecAD<double> av(2);\n    av[ AD<double>(0) ] = ax[0];\n    av[ AD<double>(1) ] = ax[1];\n    ay[0] = av[ ax[2] ];\n    CppAD::ADFun<double> f(ax, ay);\n    //\n    // ok\n    // value during recording of f\n    ok &= ay[0] == ax[1];\n    //\n    // ok\n    // f zero order forward mode, the VecAD commands give expected result\n    vector<double> x(3), y(1);\n    x[0] = 2.0;\n    x[1] = 1.0;\n    x[2] = 0.0;\n    y = f.Forward(0, x);\n    ok &= y[0] == x[0];\n    //\n    // af\n    CppAD::ADFun< AD<double>, double > af = f.base2ad();\n    //\n    // g\n    ax[0] = 3.0;\n    ax[1] = 2.0;\n    ax[2] = 1.0;\n    Independent(ax);\n    ay = af.Forward(0, ax);\n    CppAD::ADFun<double> g(ax, ay);\n    //\n    // ok\n    // value during recording of g\n    ok &= ay[0] == ax[1];\n    //\n    // ok\n    // g zero order forward mode\n    // Note that this index does not change, but the value does\n    x[0] = 5.0;\n    x[1] = 4.0;\n    x[2] = 0.0;\n    y = g.Forward(0, x);\n    ok &= y[0] == x[1];\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/general/base_alloc.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_GENERAL_BASE_ALLOC_HPP\n# define CPPAD_EXAMPLE_GENERAL_BASE_ALLOC_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin base_alloc.hpp}\n{xrst_spell\n    azmul\n    isnan\n}\nExample AD<Base> Where Base Constructor Allocates Memory\n########################################################\n\nPurpose\n*******\nDemonstrate use of ``AD`` < *Base* >\nwhere memory is allocated for each element of the type *Base* .\nIn addition, this is a complete example where all the\n:ref:`required Base<base_require-name>` type\noperations are defined (as apposed to other examples where\nsome of the operations for the Base type are already defined).\n\nInclude File\n************\nThis file uses some of the definitions in :ref:`base_require-name`\nand :ref:`thread_alloc-name` .\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <cppad/base_require.hpp>\n# include <cppad/utility/thread_alloc.hpp>\n/* {xrst_code}\n{xrst_spell_on}\n\nCompound Assignment Macro\n*************************\nThis macro is used for the\n``base_alloc`` compound assignment operators; to be specific,\nused with *op* equal to\n``+=`` ,\n``-=`` ,\n``*=`` ,\n``/=`` .\n{xrst_spell_off}\n{xrst_code cpp} */\n# define BASE_ALLOC_ASSIGN_OPERATOR(op) \\\n    void operator op (const base_alloc& x) \\\n    {  *ptrdbl_ op *x.ptrdbl_; }\n/* {xrst_code}\n{xrst_spell_on}\n\nBinary Operator Macro\n*********************\nThis macro is used for the\n``base_alloc`` binary operators (as member functions); to be specific,\nused with *op* equal to\n``+`` ,\n``-`` ,\n``*`` ,\n``/`` .\n{xrst_spell_off}\n{xrst_code cpp} */\n# define BASE_ALLOC_BINARY_OPERATOR(op) const \\\n    base_alloc operator op (const base_alloc& x) const \\\n    {  base_alloc result; \\\n        double   dbl = *ptrdbl_; \\\n        double x_dbl = *x.ptrdbl_; \\\n        *result.ptrdbl_ = dbl op x_dbl; \\\n        return result; \\\n    }\n/* {xrst_code}\n{xrst_spell_on}\n\nBoolean Operator Macro\n**********************\nThis macro can be used for the\n``base_alloc`` binary operators that have a\n``bool`` result; to be specific,\nused with *op* equal to\n``==`` ,\n``!=`` ,\n``<`` ,\n``<=`` ,\n``>=`` , and\n``>`` ,\n{xrst_spell_off}\n{xrst_code cpp} */\n# define BASE_ALLOC_BOOL_OPERATOR(op) const \\\n    bool operator op (const base_alloc& x) const \\\n    {  double   dbl = *ptrdbl_; \\\n        double x_dbl = *x.ptrdbl_; \\\n        return dbl op x_dbl; \\\n    }\n/* {xrst_code}\n{xrst_spell_on}\n\nClass Definition\n****************\nThe following example class\ndefines the necessary :ref:`base_member-name` functions.\nIt is made more complicated by storing a pointer to a ``double``\ninstead of the ``double`` value itself.\n{xrst_spell_off}\n{xrst_code cpp} */\n\nclass base_alloc {\npublic:\n    double* ptrdbl_;\n\n    base_alloc(void)\n    {  size_t cap;\n        void* v  = CppAD::thread_alloc::get_memory(sizeof(double), cap);\n        ptrdbl_  = static_cast<double*>(v);\n        //\n        // Avoid warning about possible use of uninitialized value\n        *ptrdbl_ = CppAD::numeric_limits<double>::quiet_NaN();\n    }\n    base_alloc(double dbl)\n    {  size_t cap;\n        void *v  = CppAD::thread_alloc::get_memory(sizeof(double), cap);\n        ptrdbl_  = static_cast<double*>(v);\n        *ptrdbl_ = dbl;\n    }\n    base_alloc(const base_alloc& x)\n    {  size_t cap;\n        void *v  = CppAD::thread_alloc::get_memory(sizeof(double), cap);\n        ptrdbl_  = static_cast<double*>(v);\n        *ptrdbl_ = *x.ptrdbl_;\n    }\n    ~base_alloc(void)\n    {  void* v  = static_cast<void*>(ptrdbl_);\n        CppAD::thread_alloc::return_memory(v);\n    }\n    base_alloc operator-(void) const\n    {  base_alloc result;\n        *result.ptrdbl_ = - *ptrdbl_;\n        return result;\n    }\n    base_alloc operator+(void) const\n    {  return *this; }\n    void operator=(const base_alloc& x)\n    {  *ptrdbl_ = *x.ptrdbl_; }\n    BASE_ALLOC_ASSIGN_OPERATOR(+=)\n    BASE_ALLOC_ASSIGN_OPERATOR(-=)\n    BASE_ALLOC_ASSIGN_OPERATOR(*=)\n    BASE_ALLOC_ASSIGN_OPERATOR(/=)\n    BASE_ALLOC_BINARY_OPERATOR(+)\n    BASE_ALLOC_BINARY_OPERATOR(-)\n    BASE_ALLOC_BINARY_OPERATOR(*)\n    BASE_ALLOC_BINARY_OPERATOR(/)\n    BASE_ALLOC_BOOL_OPERATOR(==)\n    BASE_ALLOC_BOOL_OPERATOR(!=)\n    // The <= operator is not necessary for the base type requirements\n    // (needed so we can use NearEqual with base_alloc arguments).\n    BASE_ALLOC_BOOL_OPERATOR(<=)\n};\n/* {xrst_code}\n{xrst_spell_on}\n\nCondExpOp\n*********\nThe type ``base_alloc`` does not use :ref:`CondExp-name` operations.\nHence its ``CondExpOp`` function is defined by\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    inline base_alloc CondExpOp(\n        enum CompareOp     cop          ,\n        const base_alloc&       left         ,\n        const base_alloc&       right        ,\n        const base_alloc&       exp_if_true  ,\n        const base_alloc&       exp_if_false )\n    {  // not used\n        assert(false);\n\n        // to void compiler error\n        return base_alloc();\n    }\n}\n/* {xrst_code}\n{xrst_spell_on}\n\nCondExpRel\n**********\nThe :ref:`CPPAD_COND_EXP_REL<base_cond_exp@CondExpRel>` macro invocation\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    CPPAD_COND_EXP_REL(base_alloc)\n}\n/* {xrst_code}\n{xrst_spell_on}\nuses ``CondExpOp`` above to\ndefine ``CondExp`` *Rel* for ``base_alloc`` arguments\nand *Rel* equal to\n``Lt`` , ``Le`` , ``Eq`` , ``Ge`` , and ``Gt`` .\n\nEqualOpSeq\n**********\nThe type ``base_alloc`` is simple (in this respect) and so we define\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    inline bool EqualOpSeq(const base_alloc& x, const base_alloc& y)\n    {  return *x.ptrdbl_ == *y.ptrdbl_; }\n}\n/* {xrst_code}\n{xrst_spell_on}\n\nIdentical\n*********\nThe type ``base_alloc`` is simple (in this respect) and so we define\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    inline bool IdenticalCon(const base_alloc& x)\n    {  return true; }\n    inline bool IdenticalZero(const base_alloc& x)\n    {  return (*x.ptrdbl_ == 0.0); }\n    inline bool IdenticalOne(const base_alloc& x)\n    {  return (*x.ptrdbl_ == 1.0); }\n    inline bool IdenticalEqualCon(const base_alloc& x, const base_alloc& y)\n    {  return (*x.ptrdbl_ == *y.ptrdbl_); }\n}\n/* {xrst_code}\n{xrst_spell_on}\n\nOutput Operator\n***************\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    inline std::ostream& operator << (std::ostream &os, const base_alloc& x)\n    {  os << *x.ptrdbl_;\n        return os;\n    }\n}\n/* {xrst_code}\n{xrst_spell_on}\n\nInteger\n*******\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    inline int Integer(const base_alloc& x)\n    {  return static_cast<int>(*x.ptrdbl_); }\n}\n/* {xrst_code}\n{xrst_spell_on}\n\nazmul\n*****\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    CPPAD_AZMUL( base_alloc )\n}\n/* {xrst_code}\n{xrst_spell_on}\n\nOrdered\n*******\nThe ``base_alloc`` type supports ordered comparisons\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    inline bool GreaterThanZero(const base_alloc& x)\n    {  return *x.ptrdbl_ > 0.0; }\n    inline bool GreaterThanOrZero(const base_alloc& x)\n    {  return *x.ptrdbl_ >= 0.0; }\n    inline bool LessThanZero(const base_alloc& x)\n    {  return *x.ptrdbl_ < 0.0; }\n    inline bool LessThanOrZero(const base_alloc& x)\n    {  return *x.ptrdbl_ <= 0.f; }\n    inline bool abs_geq(const base_alloc& x, const base_alloc& y)\n    {  return std::fabs(*x.ptrdbl_) >= std::fabs(*y.ptrdbl_); }\n}\n/* {xrst_code}\n{xrst_spell_on}\n\nUnary Standard Math\n*******************\nThe macro\n:ref:`base_std_math@CPPAD_STANDARD_MATH_UNARY`\nwould not work with the type ``base_alloc`` so we define\na special macro for this type:\n{xrst_spell_off}\n{xrst_code cpp} */\n# define BASE_ALLOC_STD_MATH(fun) \\\n    inline base_alloc fun (const base_alloc& x) \\\n    { return   std::fun(*x.ptrdbl_); }\n/* {xrst_code}\n{xrst_spell_on}\nThe following invocations of the macro above define the\n:ref:`base_std_math@Unary Standard Math` functions\n(except for ``abs`` ):\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    BASE_ALLOC_STD_MATH(acos)\n    BASE_ALLOC_STD_MATH(acosh)\n    BASE_ALLOC_STD_MATH(asin)\n    BASE_ALLOC_STD_MATH(asinh)\n    BASE_ALLOC_STD_MATH(atan)\n    BASE_ALLOC_STD_MATH(atanh)\n    BASE_ALLOC_STD_MATH(cos)\n    BASE_ALLOC_STD_MATH(cosh)\n    BASE_ALLOC_STD_MATH(erf)\n    BASE_ALLOC_STD_MATH(erfc)\n    BASE_ALLOC_STD_MATH(exp)\n    BASE_ALLOC_STD_MATH(expm1)\n    BASE_ALLOC_STD_MATH(fabs)\n    BASE_ALLOC_STD_MATH(log)\n    BASE_ALLOC_STD_MATH(log1p)\n    BASE_ALLOC_STD_MATH(log10)\n    BASE_ALLOC_STD_MATH(sin)\n    BASE_ALLOC_STD_MATH(sinh)\n    BASE_ALLOC_STD_MATH(sqrt)\n    BASE_ALLOC_STD_MATH(tan)\n    BASE_ALLOC_STD_MATH(tanh)\n}\n/* {xrst_code}\n{xrst_spell_on}\nThe absolute value function is special because it ``std`` name is\n``fabs``\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    inline base_alloc abs(const base_alloc& x)\n    {  return fabs(*x.ptrdbl_); }\n}\n/* {xrst_code}\n{xrst_spell_on}\nThe isnan function is special because it returns a bool\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    inline bool isnan(const base_alloc& x)\n    {  return *x.ptrdbl_ != *x.ptrdbl_; }\n}\n/* {xrst_code}\n{xrst_spell_on}\n\nsign\n****\nThe following defines the ``CppAD::sign`` function that\nis required to use ``AD<base_alloc>`` :\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    inline base_alloc sign(const base_alloc& x)\n    {  if( *x.ptrdbl_ > 0.0 )\n            return 1.0;\n        if( *x.ptrdbl_ == 0.0 )\n            return 0.0;\n        return -1.0;\n    }\n}\n/* {xrst_code}\n{xrst_spell_on}\n\npow\n***\nThe following defines a ``CppAD::pow`` function that\nis required to use ``AD<base_alloc>`` :\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    inline base_alloc pow(const base_alloc& x, const base_alloc& y)\n    { return std::pow(*x.ptrdbl_, *y.ptrdbl_); }\n}\n/* {xrst_code}\n{xrst_spell_on}\n\nnumeric_limits\n**************\nThe following defines the CppAD :ref:`numeric_limits-name`\nfor the type ``base_alloc`` :\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    CPPAD_NUMERIC_LIMITS(double, base_alloc)\n}\n/* {xrst_code}\n{xrst_spell_on}\n\nto_string\n*********\nThe following defines the CppAD :ref:`to_string-name` function\nfor the type ``base_alloc`` :\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    CPPAD_TO_STRING(base_alloc)\n}\n/* {xrst_code}\n{xrst_spell_on}\n\nhash_code\n*********\nThe :ref:`base_hash@Default` hashing function does\nnot work well for this case because two different pointers can\nhave the same value.\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    inline unsigned short hash_code(const base_alloc& x)\n    {  unsigned short code = 0;\n        if( *x.ptrdbl_ == 0.0 )\n            return code;\n        double log_x = log( std::fabs( *x.ptrdbl_ ) );\n        // assume log( std::numeric_limits<double>::max() ) is near 700\n        code = static_cast<unsigned short>(\n            (CPPAD_HASH_TABLE_SIZE / 700 + 1) * log_x\n        );\n        code = code % CPPAD_HASH_TABLE_SIZE;\n        return code;\n    }\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end base_alloc.hpp}\n*/\n# endif\n"
  },
  {
    "path": "example/general/base_require.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-23 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin base_require.cpp}\n\nUsing a User Defined AD Base Type: Example and Test\n###################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\nPurpose\n*******\nThe type ``base_alloc`` , defined in :ref:`base_alloc.hpp-name` ,\nmeets the requirements specified by :ref:`base_require-name`\nfor *Base* in ``AD`` < *Base* > .\nThe program below is an example use of ``AD<base_alloc>`` .\n\n{xrst_end base_require.cpp}\n*/\n// BEGIN C++\n// suppress conversion warnings before other includes\n# include <cppad/wno_conversion.hpp>\n//\n# include \"base_alloc.hpp\"\n# include <cppad/cppad.hpp>\n\nbool base_require(void)\n{   bool ok = true;\n    using CppAD::thread_alloc;\n    typedef CppAD::AD<base_alloc> ad_base_alloc;\n\n    // check the amount of memory inuse by this thread (thread zero)\n    size_t thread = thread_alloc::thread_num();\n    ok &= thread == 0;\n\n    // y = x^2\n    size_t n = 1, m = 1;\n    CPPAD_TESTVECTOR(ad_base_alloc) a_x(n), a_y(m);\n    a_x[0] = ad_base_alloc(1.);\n    CppAD::Independent(a_x);\n    a_y[0] = a_x[0] * a_x[0];\n    CppAD::ADFun<base_alloc> f(a_x, a_y);\n\n    // check function value f(x) = x^2\n    CPPAD_TESTVECTOR(base_alloc) x(n), y(m);\n    base_alloc eps =\n        base_alloc(100.) * CppAD::numeric_limits<base_alloc>::epsilon();\n    x[0] = base_alloc(3.);\n    y    = f.Forward(0, x);\n    ok  &= CppAD::NearEqual(y[0], x[0] * x[0], eps, eps);\n\n    // check derivative value f'(x) = 2 * x\n    CPPAD_TESTVECTOR(base_alloc) dy(m * n);\n    dy   = f.Jacobian(x);\n    ok  &= CppAD::NearEqual(dy[0], base_alloc(2.) * x[0], eps, eps);\n\n    // check the abs function\n    ok  &= abs( - a_x[0] ) == abs( a_x[0] );\n\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/general/bender_quad.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin bender_quad.cpp app}\n{xrst_spell\n    argmin\n}\n\nBenderQuad: Example and Test\n############################\n\nDefine\n:math:`F : \\B{R} \\times \\B{R} \\rightarrow \\B{R}` by\n\n.. math::\n\n    F(x, y)\n    =\n    \\frac{1}{2} \\sum_{i=1}^N [ y * \\sin ( x * t_i ) - z_i ]^2\n\nwhere :math:`z \\in \\B{R}^N` is a fixed vector.\nIt follows that\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    \\partial_y F(x, y)\n    & = &\n    \\sum_{i=1}^N [ y * \\sin ( x * t_i ) - z_i ] \\sin( x * t_i )\n    \\\\\n    \\partial_y \\partial_y F(x, y)\n    & = &\n    \\sum_{i=1}^N \\sin ( x t_i )^2\n    \\end{eqnarray}\n\nFurthermore if we define :math:`Y(x)`\nas the argmin of :math:`F(x, y)` with respect to :math:`y`,\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    Y(x)\n    & = &\n    y - [ \\partial_y \\partial_y F(x, y) ]^{-1} \\partial_y F[x,  y]\n    \\\\\n    & = &\n    \\left.\n        \\sum_{i=1}^N z_i \\sin ( x t_i )\n            \\right/\n                \\sum_{i=1}^N z_i \\sin ( x * t_i )^2\n    \\end{eqnarray}\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end bender_quad.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n\nnamespace {\n    using CppAD::AD;\n    typedef CPPAD_TESTVECTOR(double)         BAvector;\n    typedef CPPAD_TESTVECTOR(AD<double>)   ADvector;\n\n    class Fun {\n    private:\n        BAvector t_; // measurement times\n        BAvector z_; // measurement values\n    public:\n        // constructor\n        Fun(const BAvector &t, const BAvector &z)\n        : t_(t), z_(z)\n        { }\n        // Fun.f(x, y) = F(x, y)\n        ADvector f(const ADvector &x, const ADvector &y)\n        {   size_t i;\n            size_t N = size_t(z_.size());\n\n            ADvector F(1);\n            F[0] = 0.;\n\n            AD<double> residual;\n            for(i = 0; i < N; i++)\n            {   residual = y[0] * sin( x[0] * t_[i] ) - z_[i];\n                F[0]    += .5 * residual * residual;\n            }\n            return F;\n        }\n        // Fun.h(x, y) = H(x, y) = F_y (x, y)\n        ADvector h(const ADvector &x, const BAvector &y)\n        {   size_t i;\n            size_t N = size_t(z_.size());\n\n            ADvector fy(1);\n            fy[0] = 0.;\n\n            AD<double> residual;\n            for(i = 0; i < N; i++)\n            {   residual = y[0] * sin( x[0] * t_[i] ) - z_[i];\n                fy[0]   += residual * sin( x[0] * t_[i] );\n            }\n            return fy;\n        }\n        // Fun.dy(x, y, h) = - H_y (x,y)^{-1} * h\n        //                 = - F_yy (x, y)^{-1} * h\n        ADvector dy(\n            const BAvector &x ,\n            const BAvector &y ,\n            const ADvector &H )\n        {   size_t i;\n            size_t N = size_t(z_.size());\n\n            ADvector Dy(1);\n            AD<double> fyy = 0.;\n\n            for(i = 0; i < N; i++)\n            {   fyy += sin( x[0] * t_[i] ) * sin( x[0] * t_[i] );\n            }\n            Dy[0] = - H[0] / fyy;\n\n            return Dy;\n        }\n    };\n\n    // Used to test calculation of Hessian of G\n    AD<double> G(const ADvector& x, const BAvector& t, const BAvector& z)\n    {   // compute Y(x)\n        AD<double> numerator = 0.;\n        AD<double> denominator = 0.;\n        size_t k;\n        for(k = 0; k < size_t(t.size()); k++)\n        {   numerator   += sin( x[0] * t[k] ) * z[k];\n            denominator += sin( x[0] * t[k] ) * sin( x[0] * t[k] );\n        }\n        AD<double> y = numerator / denominator;\n\n        // V(x) = F[x, Y(x)]\n        AD<double> sum = 0;\n        for(k = 0; k < size_t(t.size()); k++)\n        {   AD<double> residual = y * sin( x[0] * t[k] ) - z[k];\n            sum += .5 * residual * residual;\n        }\n        return sum;\n    }\n}\n\nbool BenderQuad(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n\n    // temporary indices\n    size_t i, j;\n\n    // x space vector\n    size_t n = 1;\n    BAvector x(n);\n    x[0] = 2. * 3.141592653;\n\n    // y space vector\n    size_t m = 1;\n    BAvector y(m);\n    y[0] = 1.;\n\n    // t and z vectors\n    size_t N = 10;\n    BAvector t(N);\n    BAvector z(N);\n    for(i = 0; i < N; i++)\n    {   t[i] = double(i) / double(N);       // time of measurement\n        z[i] = y[0] * sin( x[0] * t[i] );   // data without noise\n    }\n\n    // construct the function object\n    Fun fun(t, z);\n\n    // evaluate the G(x), G'(x) and G''(x)\n    BAvector g(1), gx(n), gxx(n * n);\n    CppAD::BenderQuad(x, y, fun, g, gx, gxx);\n\n\n    // create ADFun object Gfun corresponding to G(x)\n    ADvector a_x(n), a_g(1);\n    for(j = 0; j < n; j++)\n        a_x[j] = x[j];\n    Independent(a_x);\n    a_g[0] = G(a_x, t, z);\n    CppAD::ADFun<double> Gfun(a_x, a_g);\n\n    // accuracy for checks\n    double eps = 10. * CppAD::numeric_limits<double>::epsilon();\n\n    // check Jacobian\n    BAvector check_gx = Gfun.Jacobian(x);\n    for(j = 0; j < n; j++)\n        ok &= NearEqual(gx[j], check_gx[j], eps, eps);\n\n    // check Hessian\n    BAvector check_gxx = Gfun.Hessian(x, 0);\n    for(j = 0; j < n*n; j++)\n        ok &= NearEqual(gxx[j], check_gxx[j], eps, eps);\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/bool_fun.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin bool_fun.cpp}\n\nAD Boolean Functions: Example and Test\n######################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end bool_fun.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n# include <complex>\n\n\n// define abbreviation for double precision complex\ntypedef std::complex<double> Complex;\n\nnamespace {\n    // a unary bool function with Complex argument\n    static bool IsReal(const Complex &x)\n    {   return x.imag() == 0.; }\n\n    // a binary bool function with Complex arguments\n    static bool AbsGeq(const Complex &x, const Complex &y)\n    {   double axsq = x.real() * x.real() + x.imag() * x.imag();\n        double aysq = y.real() * y.real() + y.imag() * y.imag();\n\n        return axsq >= aysq;\n    }\n\n    // Create version of IsReal with AD<Complex> argument\n    // inside of namespace and outside of any other function.\n    CPPAD_BOOL_UNARY(Complex, IsReal)\n\n    // Create version of AbsGeq with AD<Complex> arguments\n    // inside of namespace and outside of any other function.\n    CPPAD_BOOL_BINARY(Complex, AbsGeq)\n\n}\nbool BoolFun(void)\n{   bool ok = true;\n\n    CppAD::AD<Complex> x = Complex(1.,  0.);\n    CppAD::AD<Complex> y = Complex(1.,  1.);\n\n    ok &= IsReal(x);\n    ok &= ! AbsGeq(x, y);\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/capacity_order.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin capacity_order.cpp}\n\nControlling Taylor Coefficient Memory Allocation: Example and Test\n##################################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end capacity_order.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nnamespace {\n    bool test(void)\n    {   bool ok = true;\n        using CppAD::AD;\n        using CppAD::NearEqual;\n        using CppAD::thread_alloc;\n\n        // domain space vector\n        size_t n(1), m(1);\n        CPPAD_TESTVECTOR(AD<double>) ax(n), ay(n);\n\n        // declare independent variables and start tape recording\n        ax[0]  = 1.0;\n        CppAD::Independent(ax);\n\n        // Set y = x^3, use enough variables so more that the minimal amount\n        // of memory is allocated for Taylor coefficients\n        ay[0] = 0.;\n        for( size_t i = 0; i < 10; i++)\n            ay[0] += ax[0] * ax[0] * ax[0];\n        ay[0] = ay[0] / 10.;\n\n        // create f: x -> y and stop tape recording\n        // (without running zero order forward mode).\n        CppAD::ADFun<double> f;\n        f.Dependent(ax, ay);\n\n        // check that this is master thread\n        size_t thread = thread_alloc::thread_num();\n        ok           &= thread == 0; // this should be master thread\n\n        // The highest order forward mode calculation below is first order.\n        // This corresponds to two Taylor coefficient per variable,direction\n        // (orders zero and one). Preallocate memory for speed.\n        size_t inuse  = thread_alloc::inuse(thread);\n        f.capacity_order(2);\n        ok &= thread_alloc::inuse(thread) > inuse;\n\n        // zero order forward mode\n        CPPAD_TESTVECTOR(double) x(n), y(m);\n        x[0] = 0.5;\n        y    = f.Forward(0, x);\n        double eps = 10. * CppAD::numeric_limits<double>::epsilon();\n        ok  &= NearEqual(y[0], x[0] * x[0] * x[0], eps, eps);\n\n        // forward computation of partials w.r.t. x\n        CPPAD_TESTVECTOR(double) dx(n), dy(m);\n        dx[0] = 1.;\n        dy    = f.Forward(1, dx);\n        ok   &= NearEqual(dy[0], 3. * x[0] * x[0], eps, eps);\n\n        // Suppose we no longer need the first order Taylor coefficients.\n        inuse = thread_alloc::inuse(thread);\n        f.capacity_order(1); // just keep zero order coefficients\n        ok   &= thread_alloc::inuse(thread) < inuse;\n\n        // Suppose we no longer need the zero order Taylor coefficients\n        // (could have done this first and not used f.capacity_order(1)).\n        inuse = thread_alloc::inuse(thread);\n        f.capacity_order(0);\n        ok   &= thread_alloc::inuse(thread) < inuse;\n\n        // turn off memory holding\n        thread_alloc::hold_memory(false);\n\n        return ok;\n    }\n}\nbool capacity_order(void)\n{   bool ok = true;\n    using CppAD::thread_alloc;\n\n    // original amount of memory inuse\n    size_t thread = thread_alloc::thread_num();\n    ok           &= thread == 0; // this should be master thread\n    size_t inuse  = thread_alloc::inuse(thread);\n\n    // do test in separate routine so all objects are destroyed\n    ok &= test();\n\n    // check that the amount of memory inuse has not changed\n    ok &= thread_alloc::inuse(thread) == inuse;\n\n    // Test above uses hold_memory, so return available memory\n    thread_alloc::free_available(thread);\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/change_param.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/cppad.hpp>\n\n/*\n{xrst_begin change_param.cpp}\n\nComputing a Jacobian With Constants that Change\n###############################################\n\nPurpose\n*******\nIn this example we use two levels of taping so that a derivative\ncan have constant parameters that can be changed. To be specific,\nwe consider the function :math:`f : \\B{R}^2 \\rightarrow \\B{R}^2`\n\n.. math::\n\n    f(x) = p \\left( \\begin{array}{c}\n        \\sin( x_0 ) \\\\\n        \\sin( x_1 )\n    \\end{array} \\right)\n\nwere :math:`p \\in \\B{R}` is a parameter.\nThe Jacobian of this function is\n\n.. math::\n\n    g(x,p) = p \\left( \\begin{array}{cc}\n        \\cos( x_0 ) & 0 \\\\\n        0           & \\cos( x_1 )\n    \\end{array} \\right)\n\nIn this example we use two levels of AD to avoid computing\nthe partial of :math:`f(x)` with respect to :math:`p`,\nbut still allow for the evaluation of :math:`g(x, p)`\nat different values of :math:`p`.\n\n{xrst_end change_param.cpp}\n\n*/\n\nbool change_param(void)\n{   bool ok = true;                     // initialize test result\n\n    typedef CppAD::AD<double> a1type;   // for first level of taping\n    typedef CppAD::AD<a1type> a2type;  // for second level of taping\n\n    size_t nu = 3;       // number components in u\n    size_t nx = 2;       // number components in x\n    size_t ny = 2;       // num components in f(x)\n    size_t nJ = ny * nx; // number components in Jacobian of f(x)\n\n    // temporary indices\n    size_t j;\n\n    // declare first level of independent variables\n    // (Start taping now so can record dependency of a1f on a1p.)\n    CPPAD_TESTVECTOR(a1type) a1u(nu);\n    for(j = 0; j < nu; j++)\n        a1u[j] = 0.;\n    CppAD::Independent(a1u);\n\n    // parameter in computation of Jacobian\n    a1type a1p = a1u[2];\n\n    // declare second level of independent variables\n    CPPAD_TESTVECTOR(a2type) a2x(nx);\n    for(j = 0; j < nx; j++)\n        a2x[j] = 0.;\n    CppAD::Independent(a2x);\n\n    // compute dependent variables at second level\n    CPPAD_TESTVECTOR(a2type) a2y(ny);\n    a2y[0] = sin( a2x[0] ) * a1p;\n    a2y[1] = sin( a2x[1] ) * a1p;\n\n    // declare function object that computes values at the first level\n    // (make sure we do not run zero order forward during constructor)\n    CppAD::ADFun<a1type> a1f;\n    a1f.Dependent(a2x, a2y);\n\n    // compute the Jacobian of a1f at a1u[0], a1u[1]\n    CPPAD_TESTVECTOR(a1type) a1x(nx);\n    a1x[0] = a1u[0];\n    a1x[1] = a1u[1];\n    CPPAD_TESTVECTOR(a1type) a1J(nJ);\n    a1J = a1f.Jacobian( a1x );\n\n    // declare function object that maps u = (x, p) to Jacobian of f\n    // (make sure we do not run zero order forward during constructor)\n    CppAD::ADFun<double> g;\n    g.Dependent(a1u, a1J);\n\n    // remove extra variables used during the reconding of a1f,\n    // but not needed any more.\n    g.optimize();\n\n    // compute the Jacobian of f using zero order forward\n    // sweep with double values\n    CPPAD_TESTVECTOR(double) J(nJ), u(nu);\n    for(j = 0; j < nu; j++)\n        u[j] = double(j+1);\n    J = g.Forward(0, u);\n\n    // accuracy for tests\n    double eps = 100. * CppAD::numeric_limits<double>::epsilon();\n\n    // y[0] = sin( x[0] ) * p\n    // y[1] = sin( x[1] ) * p\n    CPPAD_TESTVECTOR(double) x(nx);\n    x[0]      = u[0];\n    x[1]      = u[1];\n    double p  = u[2];\n\n    // J[0] = partial y[0] w.r.t x[0] = cos( x[0] ) * p\n    double check = cos( x[0] ) * p;\n    ok   &= fabs( check - J[0] ) <= eps;\n\n    // J[1] = partial y[0] w.r.t x[1] = 0.;\n    check = 0.;\n    ok   &= fabs( check - J[1] ) <= eps;\n\n    // J[2] = partial y[1] w.r.t. x[0] = 0.\n    check = 0.;\n    ok   &= fabs( check - J[2] ) <= eps;\n\n    // J[3] = partial y[1] w.r.t x[1] = cos( x[1] ) * p\n    check = cos( x[1] ) * p;\n    ok   &= fabs( check - J[3] ) <= eps;\n\n    return ok;\n}\n// END PROGRAM\n"
  },
  {
    "path": "example/general/check_for_nan.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin check_for_nan.cpp}\n\nADFun Checking For Nan: Example and Test\n########################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end check_for_nan.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n# include <cctype>\n\nnamespace {\n    void myhandler(\n        bool known       ,\n        int  line        ,\n        const char *file ,\n        const char *exp  ,\n        const char *msg  )\n    {   // error handler must not return, so throw an exception\n        std::string message = msg;\n        throw message;\n    }\n}\n\nbool check_for_nan(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using std::string;\n    double eps = 10. * std::numeric_limits<double>::epsilon();\n\n    // replace the default CppAD error handler\n    CppAD::ErrorHandler info(myhandler);\n\n    CPPAD_TESTVECTOR(AD<double>) ax(2), ay(2);\n    ax[0] = 2.0;\n    ax[1] = 1.0;\n    CppAD::Independent(ax);\n    ay[0] = sqrt( ax[0] );\n    ay[1] = sqrt( ax[1] );\n    CppAD::ADFun<double> f(ax, ay);\n\n    CPPAD_TESTVECTOR(double) x(2), y(2);\n    x[0] = 2.0;\n    x[1] = -1.0;\n\n    // use try / catch because this causes an exception\n    // (assuming that NDEBUG is not defined)\n    f.check_for_nan(true);\n    try {\n        y = f.Forward(0, x);\n\n# ifndef NDEBUG\n        // When compiled with NDEBUG defined,\n        // CppAD does not spend time checking for nan.\n        ok = false;\n# endif\n    }\n    catch(std::string msg)\n    {\n        // get and check size of the independent variable vector\n        string pattern = \"vector_size = \";\n        size_t start   = msg.find(pattern) + pattern.size();\n        string number;\n        for(size_t i = start; msg[i] != '\\n'; i++)\n            number += msg[i];\n        size_t vector_size = size_t( std::atoi(number.c_str()) );\n        ok &= vector_size == 2;\n\n        // get and check first dependent variable index that is nan\n        pattern = \"index = \";\n        start   = msg.find(pattern) + pattern.size();\n        number  = \"\";\n        for(size_t i = start; msg[i] != '\\n'; i++)\n            number += msg[i];\n        size_t index = size_t( std::atoi(number.c_str()) );\n        ok &= index == 1;\n\n        // get the name of the file\n        pattern = \"file_name = \";\n        start   = msg.find(pattern) + pattern.size();\n        string file_name;\n        for(size_t i = start; msg[i] != '\\n'; i++)\n            file_name += msg[i];\n\n        // get and check independent variable vector that resulted in the nan\n        CppAD::vector<double> vec(vector_size);\n        CppAD::get_check_for_nan(vec, file_name);\n        for(size_t i = 0; i < vector_size; i++)\n            ok &= vec[i] == x[i];\n    }\n\n    // now do calculation without an exception\n    f.check_for_nan(false);\n    y = f.Forward(0, x);\n    ok &= CppAD::NearEqual(y[0], std::sqrt(x[0]), eps, eps);\n    ok &= CppAD::isnan( y[1] );\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/compare.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin compare.cpp}\n\nAD Binary Comparison Operators: Example and Test\n################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end compare.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nbool Compare(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // declare independent variables and start tape recording\n    size_t n  = 2;\n    double x0 = 0.5;\n    double x1 = 1.5;\n    CPPAD_TESTVECTOR(AD<double>) x(n);\n    x[0]      = x0;\n    x[1]      = x1;\n    CppAD::Independent(x);\n\n    // some binary comparison operations\n    AD<double> p;\n    if( x[0] < x[1] )\n        p = x[0];   // values in x choose this case\n    else\n        p = x[1];\n    if( x[0] <= x[1] )\n        p *= x[0];  // values in x choose this case\n    else\n        p *= x[1];\n    if( x[0] >  x[1] )\n        p *= x[0];\n    else\n        p *= x[1];  // values in x choose this case\n    if( x[0] >= x[1] )\n        p *= x[0];\n    else\n        p *= x[1];  // values in x choose this case\n    if( x[0] == x[1] )\n        p *= x[0];\n    else\n        p *= x[1];  // values in x choose this case\n    if( x[0] != x[1] )\n        p *= x[0];  // values in x choose this case\n    else\n        p *= x[1];\n\n    // dependent variable vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) y(m);\n    y[0] = p;\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(x, y);\n\n    // check value\n    ok &= NearEqual(y[0] , x0*x0*x1*x1*x1*x0, eps99, eps99);\n\n    // forward computation of partials w.r.t. x[0]\n    CPPAD_TESTVECTOR(double) dx(n);\n    CPPAD_TESTVECTOR(double) dy(m);\n    dx[0] = 1.;\n    dx[1] = 0.;\n    dy    = f.Forward(1, dx);\n    ok   &= NearEqual(dy[0], 3.*x0*x0*x1*x1*x1, eps99, eps99);\n\n    // forward computation of partials w.r.t. x[1]\n    dx[0] = 0.;\n    dx[1] = 1.;\n    dy    = f.Forward(1, dx);\n    ok   &= NearEqual(dy[0], 3.*x0*x0*x1*x1*x0, eps99, eps99);\n\n    // reverse computation of derivative of y[0]\n    CPPAD_TESTVECTOR(double)  w(m);\n    CPPAD_TESTVECTOR(double) dw(n);\n    w[0]  = 1.;\n    dw    = f.Reverse(1, w);\n    ok   &= NearEqual(dw[0], 3.*x0*x0*x1*x1*x1, eps99, eps99);\n    ok   &= NearEqual(dw[1], 3.*x0*x0*x1*x1*x0, eps99, eps99);\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/complex_poly.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin complex_poly.cpp}\n\nComplex Polynomial: Example and Test\n####################################\n\nPoly\n****\nSelect this link to view specifications for :ref:`Poly-name` :\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end complex_poly.cpp}\n*/\n// BEGIN C++\n// Complex examples should suppress conversion warnings\n# include <cppad/wno_conversion.hpp>\n\n# include <cppad/cppad.hpp>\n# include <complex>\n\nbool complex_poly(void)\n{   bool ok    = true;\n    size_t deg = 4;\n\n    using CppAD::AD;\n    using CppAD::Poly;\n    typedef std::complex<double> Complex;\n\n    // polynomial coefficients\n    CPPAD_TESTVECTOR( Complex )   a   (deg + 1); // coefficients for p(z)\n    CPPAD_TESTVECTOR(AD<Complex>) A   (deg + 1);\n    size_t i;\n    for(i = 0; i <= deg; i++)\n        A[i] = a[i] = Complex(double(i), double(i));\n\n    // independent variable vector\n    CPPAD_TESTVECTOR(AD<Complex>) Z(1);\n    Complex z = Complex(1., 2.);\n    Z[0]      = z;\n    Independent(Z);\n\n    // dependent variable vector and indices\n    CPPAD_TESTVECTOR(AD<Complex>) P(1);\n\n    // dependent variable values\n    P[0] = Poly(0, A, Z[0]);\n\n    // create f: Z -> P and vectors used for derivative calculations\n    CppAD::ADFun<Complex> f(Z, P);\n    CPPAD_TESTVECTOR(Complex) v( f.Domain() );\n    CPPAD_TESTVECTOR(Complex) w( f.Range() );\n\n    // check first derivative w.r.t z\n    v[0]      = 1.;\n    w         = f.Forward(1, v);\n    Complex p = Poly(1, a, z);\n    ok &= ( w[0]  == p );\n\n    // second derivative w.r.t z is 2 times its second order Taylor coeff\n    v[0] = 0.;\n    w    = f.Forward(2, v);\n    p    = Poly(2, a, z);\n    ok &= ( 2. * w[0]  == p );\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/con_dyn_var.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin con_dyn_var.cpp}\n\nAD Parameter and Variable Functions: Example and Test\n#####################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end con_dyn_var.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n\nbool con_dyn_var(void)\n{   bool ok = true;\n\n    using CppAD::AD;\n    using CppAD::VecAD;\n    using CppAD::Parameter;\n    using CppAD::Variable;\n\n    // No recording active\n    CPPAD_TESTVECTOR(AD<double>) x(1), y(1), dynamic(1);\n    x[0]        = 0.0;\n    y[0]        = 1.0;\n    dynamic[0]  = 2.0;\n    //\n    ok &= Constant(x[0]);\n    ok &= Parameter(x[0]);\n    ok &= ! Dynamic(x[0]);\n    ok &= ! Variable(x[0]);\n    //\n    ok &= Constant(y[0]);\n    ok &= Parameter(y[0]);\n    ok &= ! Dynamic(y[0]);\n    ok &= ! Variable(y[0]);\n    //\n    ok &= Constant(dynamic[0]);\n    ok &= Parameter(dynamic[0]);\n    ok &= ! Dynamic(dynamic[0]);\n    ok &= ! Variable(dynamic[0]);\n\n    // declare independent variables and start recording\n    CppAD::Independent(x, dynamic);\n    //\n    ok &= Variable(x[0]);\n    ok &= ! Constant(x[0]);\n    ok &= ! Dynamic(x[0]);\n    ok &= ! Parameter(x[0]);\n    //\n    ok &= Constant(y[0]);\n    ok &= Parameter(y[0]);\n    ok &= ! Dynamic(y[0]);\n    ok &= ! Variable(y[0]);\n    //\n    ok &= Dynamic(dynamic[0]);\n    ok &= Parameter(dynamic[0]);\n    ok &= ! Constant(dynamic[0]);\n    ok &= ! Variable(dynamic[0]);\n\n    // a dependent variable\n    y[0] = fabs(x[0]) * dynamic[0];\n    ok  &= Variable(y[0]);\n    ok  &= ! Constant(y[0]);\n    ok  &= ! Dynamic(y[0]);\n    ok  &= ! Parameter(y[0]);\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(x, y);\n    //\n    ok &= Constant(x[0]);\n    ok &= Parameter(x[0]);\n    ok &= ! Dynamic(x[0]);\n    ok &= ! Variable(x[0]);\n    //\n    ok &= Constant(y[0]);\n    ok &= Parameter(y[0]);\n    ok &= ! Dynamic(y[0]);\n    ok &= ! Variable(y[0]);\n    //\n    ok &= Constant(dynamic[0]);\n    ok &= Parameter(dynamic[0]);\n    ok &= ! Dynamic(dynamic[0]);\n    ok &= ! Variable(dynamic[0]);\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/cond_exp.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin cond_exp.cpp}\n\nConditional Expressions: Example and Test\n#########################################\n\nSee Also\n********\n:ref:`optimize_conditional_skip.cpp-name`\n\nDescription\n***********\nUse ``CondExp`` to compute\n\n.. math::\n\n    f(x) = \\sum_{j=0}^{m-1} x_j \\log( x_j )\n\nand its derivative at various argument values\n( where :math:`x_j \\geq 0` )\nwith out having to re-tape; i.e.,\nusing only one :ref:`ADFun-name` object.\nNote that :math:`x_j \\log ( x_j ) \\rightarrow 0`\nas :math:`x_j \\downarrow 0` and\nwe need to handle the case :math:`x_j = 0`\nin a special way to avoid returning zero times minus infinity.\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end cond_exp.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n# include <limits>\n\nbool CondExp(void)\n{   bool ok = true;\n\n    using CppAD::isnan;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    using CppAD::log;\n    double eps  = 100. * CppAD::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n = 5;\n    CPPAD_TESTVECTOR(AD<double>) ax(n);\n    size_t j;\n    for(j = 0; j < n; j++)\n        ax[j] = 1.;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(ax);\n\n    AD<double> asum  = 0.;\n    AD<double> azero = 0.;\n    for(j = 0; j < n; j++)\n    {   // if x_j > 0, add x_j * log( x_j ) to the sum\n        asum += CppAD::CondExpGt(ax[j], azero, ax[j] * log(ax[j]), azero);\n    }\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) ay(m);\n    ay[0] = asum;\n\n    // create f: x -> ay and stop tape recording\n    CppAD::ADFun<double> f(ax, ay);\n\n    // vectors for arguments to the function object f\n    CPPAD_TESTVECTOR(double) x(n);   // argument values\n    CPPAD_TESTVECTOR(double) y(m);   // function values\n    CPPAD_TESTVECTOR(double) w(m);   // function weights\n    CPPAD_TESTVECTOR(double) dw(n);  // derivative of weighted function\n\n    // a case where x[j] > 0 for all j\n    double check  = 0.;\n    for(j = 0; j < n; j++)\n    {   x[j]   = double(j + 1);\n        check += x[j] * log( x[j] );\n    }\n\n    // function value\n    y  = f.Forward(0, x);\n    ok &= NearEqual(y[0], check, eps, eps);\n\n    // compute derivative of y[0]\n    w[0] = 1.;\n    dw   = f.Reverse(1, w);\n    for(j = 0; j < n; j++)\n        ok &= NearEqual(dw[j], log(x[j]) + 1., eps, eps);\n\n    // a case where x[3] is equal to zero\n    check -= x[3] * log( x[3] );\n    x[3]   = 0.;\n    ok &= std::isnan( x[3] * log( x[3] ) );\n\n    // function value\n    y   = f.Forward(0, x);\n    ok &= NearEqual(y[0], check, eps, eps);\n\n    // check derivative of y[0]\n    w[0] = 1.;\n    dw   = f.Reverse(1, w);\n    for(j = 0; j < n; j++)\n    {   if( x[j] > 0 )\n            ok &= NearEqual(dw[j], log(x[j]) + 1., eps, eps);\n        else\n            ok &= NearEqual(dw[j], 0.0, eps, eps);\n    }\n\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/general/cos.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin cos.cpp}\n\nThe AD cos Function: Example and Test\n#####################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end cos.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n# include <cmath>\n\nbool Cos(void)\n{   bool ok = true;\n\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n  = 1;\n    double x0 = 0.5;\n    CPPAD_TESTVECTOR(AD<double>) x(n);\n    x[0]      = x0;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(x);\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) y(m);\n    y[0] = CppAD::cos(x[0]);\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(x, y);\n\n    // check value\n    double check = std::cos(x0);\n    ok &= NearEqual(y[0] , check, eps99, eps99);\n\n    // forward computation of first partial w.r.t. x[0]\n    CPPAD_TESTVECTOR(double) dx(n);\n    CPPAD_TESTVECTOR(double) dy(m);\n    dx[0] = 1.;\n    dy    = f.Forward(1, dx);\n    check = - std::sin(x0);\n    ok   &= NearEqual(dy[0], check, eps99, eps99);\n\n    // reverse computation of derivative of y[0]\n    CPPAD_TESTVECTOR(double)  w(m);\n    CPPAD_TESTVECTOR(double) dw(n);\n    w[0]  = 1.;\n    dw    = f.Reverse(1, w);\n    ok   &= NearEqual(dw[0], check, eps99, eps99);\n\n    // use a VecAD<Base>::reference object with cos\n    CppAD::VecAD<double> v(1);\n    AD<double> zero(0);\n    v[zero]           = x0;\n    AD<double> result = CppAD::cos(v[zero]);\n    check = std::cos(x0);\n    ok   &= NearEqual(result, check, eps99, eps99);\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/cosh.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin cosh.cpp}\n\nThe AD cosh Function: Example and Test\n######################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end cosh.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n# include <cmath>\n\nbool Cosh(void)\n{   bool ok = true;\n\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n  = 1;\n    double x0 = 0.5;\n    CPPAD_TESTVECTOR(AD<double>) x(n);\n    x[0]      = x0;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(x);\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) y(m);\n    y[0] = CppAD::cosh(x[0]);\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(x, y);\n\n    // check value\n    double check = std::cosh(x0);\n    ok &= NearEqual(y[0] , check, eps99, eps99);\n\n    // forward computation of first partial w.r.t. x[0]\n    CPPAD_TESTVECTOR(double) dx(n);\n    CPPAD_TESTVECTOR(double) dy(m);\n    dx[0] = 1.;\n    dy    = f.Forward(1, dx);\n    check = std::sinh(x0);\n    ok   &= NearEqual(dy[0], check, eps99, eps99);\n\n    // reverse computation of derivative of y[0]\n    CPPAD_TESTVECTOR(double)  w(m);\n    CPPAD_TESTVECTOR(double) dw(n);\n    w[0]  = 1.;\n    dw    = f.Reverse(1, w);\n    ok   &= NearEqual(dw[0], check, eps99, eps99);\n\n    // use a VecAD<Base>::reference object with cosh\n    CppAD::VecAD<double> v(1);\n    AD<double> zero(0);\n    v[zero]           = x0;\n    AD<double> result = CppAD::cosh(v[zero]);\n    check = std::cosh(x0);\n    ok   &= NearEqual(result, check, eps99, eps99);\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/div.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin div.cpp}\n\nAD Binary Division: Example and Test\n####################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end div.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nbool Div(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n\n    // domain space vector\n    size_t n  = 1;\n    double x0 = 0.5;\n    CPPAD_TESTVECTOR(AD<double>) x(n);\n    x[0]      = x0;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(x);\n\n    // some binary division operations\n    AD<double> a = x[0] / 1.; // AD<double> / double\n    AD<double> b = a  / 2;    // AD<double> / int\n    AD<double> c = 3. / b;    // double     / AD<double>\n    AD<double> d = 4  / c;    // int        / AD<double>\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) y(m);\n    y[0] = (x[0] * x[0]) / d;   // AD<double> / AD<double>\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(x, y);\n\n    // check value\n    ok &= NearEqual(y[0], x0*x0*3.*2.*1./(4.*x0), eps99, eps99);\n\n    // forward computation of partials w.r.t. x[0]\n    CPPAD_TESTVECTOR(double) dx(n);\n    CPPAD_TESTVECTOR(double) dy(m);\n    dx[0] = 1.;\n    dy    = f.Forward(1, dx);\n    ok   &= NearEqual(dy[0], 3.*2.*1./4., eps99, eps99);\n\n    // reverse computation of derivative of y[0]\n    CPPAD_TESTVECTOR(double)  w(m);\n    CPPAD_TESTVECTOR(double) dw(n);\n    w[0]  = 1.;\n    dw    = f.Reverse(1, w);\n    ok   &= NearEqual(dw[0], 3.*2.*1./4., eps99, eps99);\n\n    // use a VecAD<Base>::reference object with division\n    CppAD::VecAD<double> v(1);\n    AD<double> zero(0);\n    v[zero] = d;\n    AD<double> result = (x[0] * x[0]) / v[zero];\n    ok     &= (result == y[0]);\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/div_eq.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin div_eq.cpp}\n\nAD Compound Assignment Division: Example and Test\n#################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end div_eq.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nbool DivEq(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t  n = 1;\n    double x0 = .5;\n    CPPAD_TESTVECTOR(AD<double>) x(n);\n    x[0]      = x0;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(x);\n\n    // range space vector\n    size_t m = 2;\n    CPPAD_TESTVECTOR(AD<double>) y(m);\n    y[0] = x[0] * x[0];  // initial value\n    y[0] /= 2;           // AD<double> /= int\n    y[0] /= 4.;          // AD<double> /= double\n    y[1] = y[0] /= x[0]; // use the result of a compound assignment\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(x, y);\n\n    // check value\n    ok &= NearEqual(y[0] , x0*x0/(2.*4.*x0), eps99, eps99);\n    ok &= NearEqual(y[1] ,             y[0], eps99, eps99);\n\n    // forward computation of partials w.r.t. x[0]\n    CPPAD_TESTVECTOR(double) dx(n);\n    CPPAD_TESTVECTOR(double) dy(m);\n    dx[0] = 1.;\n    dy    = f.Forward(1, dx);\n    ok   &= NearEqual(dy[0], 1./8., eps99, eps99);\n    ok   &= NearEqual(dy[1], 1./8., eps99, eps99);\n\n    // reverse computation of derivative of y[0]\n    CPPAD_TESTVECTOR(double)  w(m);\n    CPPAD_TESTVECTOR(double) dw(n);\n    w[0]  = 1.;\n    w[1]  = 0.;\n    dw    = f.Reverse(1, w);\n    ok   &= NearEqual(dw[0], 1./8., eps99, eps99);\n\n    // use a VecAD<Base>::reference object with computed division\n    CppAD::VecAD<double> v(1);\n    AD<double> zero(0);\n    AD<double> result = 2;\n    v[zero] = 1;\n    result /= v[zero];\n    ok     &= (result == 2);\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/eigen_array.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin eigen_array.cpp}\n\nUsing Eigen Arrays: Example and Test\n####################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end eigen_array.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n# include <cppad/example/cppad_eigen.hpp>\n\nbool eigen_array(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    //\n    typedef CppAD::eigen_vector< AD<double> > a_vector;\n    //\n    // domain and range space vectors\n    size_t n  = 10, m = n;\n    a_vector a_x(n), a_y(m);\n\n    // set and declare independent variables and start tape recording\n    for(size_t j = 0; j < n; j++)\n        a_x[j] = double(1 + j);\n    CppAD::Independent(a_x);\n\n    // evaluate a component wise function\n    for(size_t j = 0; j < n; j++)\n        a_y[j] = a_x[j] + sin( a_x[j] );\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(a_x, a_y);\n\n    // compute the derivative of y w.r.t x using CppAD\n    CPPAD_TESTVECTOR(double) x(n);\n    for(size_t j = 0; j < n; j++)\n        x[j] = double(j) + 1.0 / double(j+1);\n    CPPAD_TESTVECTOR(double) jac = f.Jacobian(x);\n\n    // check Jacobian\n    double eps = 100. * CppAD::numeric_limits<double>::epsilon();\n    for(size_t i = 0; i < m; i++)\n    {   for(size_t j = 0; j < n; j++)\n        {   double check = 1.0 + cos(x[i]);\n            if( i != j )\n                check = 0.0;\n            ok &= NearEqual(jac[i * n + j], check, eps, eps);\n        }\n    }\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/eigen_det.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin eigen_det.cpp}\n\nUsing Eigen To Compute Determinant: Example and Test\n####################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end eigen_det.cpp}\n*/\n// BEGIN C++\n# include <cppad/example/cppad_eigen.hpp>\n# include <cppad/speed/det_by_minor.hpp>\n# include <Eigen/Dense>\n\nbool eigen_det(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    using Eigen::Matrix;\n    using Eigen::Dynamic;\n    using Eigen::Index;\n    //\n    typedef Matrix< double     , Dynamic, Dynamic > matrix;\n    typedef Matrix< AD<double> , Dynamic, Dynamic > a_matrix;\n    //\n    typedef CppAD::eigen_vector<double>          vector;\n    typedef CppAD::eigen_vector< AD<double> >    a_vector;\n    //\n\n    // domain and range space vectors\n    size_t size = 3, n  = size * size, m = 1;\n    a_vector a_x(n), a_y(m);\n    vector x(n);\n\n    // set and declare independent variables and start tape recording\n    for(size_t i = 0; i < size; i++)\n    {   for(size_t j = 0; j < size; j++)\n        {   // lower triangular matrix\n            a_x[i * size + j] = x[i * size + j] = 0.0;\n            if( j <= i )\n                a_x[i * size + j] = x[i * size + j] = double(1 + i + j);\n        }\n    }\n    CppAD::Independent(a_x);\n\n    // copy independent variable vector to a matrix\n    Index Size = Index(size);\n    a_matrix a_X(Size, Size);\n    matrix     X(Size, Size);\n    for(size_t i = 0; i < size; i++)\n    {   for(size_t j = 0; j < size; j++)\n        {   Index I = Index(i);\n            Index J = Index(j);\n            X(I ,J)   = x[i * size + j];\n            // If we used a_X(i, j) = X(i, j), a_X would not depend on a_x.\n            a_X(I, J) = a_x[i * size + j];\n        }\n    }\n\n    // Compute the log of determinant of X\n    a_y[0] = log( a_X.determinant() );\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(a_x, a_y);\n\n    // check function value\n    double eps = 100. * CppAD::numeric_limits<double>::epsilon();\n    CppAD::det_by_minor<double> det(size);\n    ok &= NearEqual(Value(a_y[0]) , log(det(x)), eps, eps);\n\n    // compute the derivative of y w.r.t x using CppAD\n    vector jac = f.Jacobian(x);\n\n    // check the derivative using the formula\n    // d/dX log(det(X)) = transpose( inv(X) )\n    matrix inv_X = X.inverse();\n    for(size_t i = 0; i < size; i++)\n    {   for(size_t j = 0; j < size; j++)\n        {   Index I = Index(i);\n            Index J = Index(j);\n            ok &= NearEqual(jac[i * size + j], inv_X(J, I), eps, eps);\n        }\n    }\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/equal_op_seq.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin equal_op_seq.cpp}\n\nEqualOpSeq: Example and Test\n############################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end equal_op_seq.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nbool EqualOpSeq(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::EqualOpSeq;\n\n    // domain space vector\n    size_t n  = 1;\n    double x0 = 1.;\n    CPPAD_TESTVECTOR(AD<double>) x(n);\n    x[0]      = x0;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(x);\n\n    AD<double> a = 1. + x[0];  // this variable is 1 + x0\n    AD<double> b = 2. * x[0];  // this variable is 2 * x0\n\n    // both a and b are variables\n    ok &= (a == b);            // 1 + 1     == 2 * 1\n    ok &= ! EqualOpSeq(a, b);  // 1 + x[0]  != 2 * x[0]\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) y(m);\n    y[0] = a;\n\n    // both y[0] and a are variables\n    EqualOpSeq(y[0], a);       // 2 * x[0] == 2 * x[0]\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(x, y);\n\n    // both a and b are parameters (after the creation of f above)\n    ok &= EqualOpSeq(a, b);    // 1 + 1 == 2 * 1\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/erf.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin erf.cpp}\n\nThe AD erf Function: Example and Test\n#####################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end erf.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n# include <cmath>\n# include <limits>\n\nbool erf(void)\n{   bool ok = true;\n\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps = 10. * CppAD::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n  = 1;\n    double x0 = 0.5;\n    CPPAD_TESTVECTOR(AD<double>) ax(n);\n    ax[0]     = x0;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(ax);\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) ay(m);\n    ay[0] = CppAD::erf(ax[0]);\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(ax, ay);\n\n    // check relative error\n    double erf_x0 = 0.5204998778130465;\n    ok &= NearEqual(ay[0] , erf_x0,  0.,    4e-4);\n    double tmp = std::max(1e-15, eps);\n    ok &= NearEqual(ay[0] , erf_x0,  0.,    tmp);\n\n    // value of derivative of erf at x0\n    double pi     = 4. * std::atan(1.);\n    double factor = 2. / sqrt(pi);\n    double check  = factor * std::exp(-x0 * x0);\n\n    // forward computation of first partial w.r.t. x[0]\n    CPPAD_TESTVECTOR(double) dx(n);\n    CPPAD_TESTVECTOR(double) dy(m);\n    dx[0] = 1.;\n    dy    = f.Forward(1, dx);\n    ok   &= NearEqual(dy[0], check,  0.,  1e-3);\n    ok   &= NearEqual(dy[0], check,  0.,  eps);\n\n    // reverse computation of derivative of y[0]\n    CPPAD_TESTVECTOR(double)  w(m);\n    CPPAD_TESTVECTOR(double) dw(n);\n    w[0]  = 1.;\n    dw    = f.Reverse(1, w);\n    ok   &= NearEqual(dw[0], check,  0., 1e-1);\n    ok   &= NearEqual(dw[0], check,  0., eps);\n\n    // use a VecAD<Base>::reference object with erf\n    CppAD::VecAD<double> v(1);\n    AD<double> zero(0);\n    v[zero]           = x0;\n    AD<double> result = CppAD::erf(v[zero]);\n    ok   &= NearEqual(result, ay[0], eps, eps);\n\n    // use a double with erf\n    ok   &= NearEqual(CppAD::erf(x0), ay[0], eps, eps);\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/erfc.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin erfc.cpp}\n\nThe AD erfc Function: Example and Test\n######################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end erfc.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n# include <cmath>\n# include <limits>\n\nbool erfc(void)\n{   bool ok = true;\n\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps = 10. * CppAD::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n  = 1;\n    double x0 = 0.5;\n    CPPAD_TESTVECTOR(AD<double>) ax(n);\n    ax[0]     = x0;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(ax);\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) ay(m);\n    ay[0] = CppAD::erfc(ax[0]);\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(ax, ay);\n\n    // check relative error\n    double erfc_x0 = 0.4795001221869534;\n    ok &= NearEqual(ay[0] , erfc_x0,  0.,    4e-4);\n    double tmp = std::max(1e-15, eps);\n    ok &= NearEqual(ay[0] , erfc_x0,  0.,    tmp);\n\n    // value of derivative of erfc at x0\n    double pi     = 4. * std::atan(1.);\n    double factor = 2. / sqrt(pi);\n    double check  = - factor * std::exp(-x0 * x0);\n\n    // forward computation of first partial w.r.t. x[0]\n    CPPAD_TESTVECTOR(double) dx(n);\n    CPPAD_TESTVECTOR(double) dy(m);\n    dx[0] = 1.;\n    dy    = f.Forward(1, dx);\n    ok   &= NearEqual(dy[0], check,  0.,  1e-3);\n    ok   &= NearEqual(dy[0], check,  0.,  eps);\n\n    // reverse computation of derivative of y[0]\n    CPPAD_TESTVECTOR(double)  w(m);\n    CPPAD_TESTVECTOR(double) dw(n);\n    w[0]  = 1.;\n    dw    = f.Reverse(1, w);\n    ok   &= NearEqual(dw[0], check,  0., 1e-1);\n    ok   &= NearEqual(dw[0], check,  0., eps);\n\n    // use a VecAD<Base>::reference object with erfc\n    CppAD::VecAD<double> v(1);\n    AD<double> zero(0);\n    v[zero]           = x0;\n    AD<double> result = CppAD::erfc(v[zero]);\n    ok   &= NearEqual(result, ay[0], eps, eps);\n\n    // use a double with erfc\n    ok   &= NearEqual(CppAD::erfc(x0), ay[0], eps, eps);\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/exp.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin exp.cpp}\n\nThe AD exp Function: Example and Test\n#####################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end exp.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n# include <cmath>\n\nbool exp(void)\n{   bool ok = true;\n\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps = 10. * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n  = 1;\n    double x0 = 0.5;\n    CPPAD_TESTVECTOR(AD<double>) ax(n);\n    ax[0]     = x0;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(ax);\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) ay(m);\n    ay[0] = CppAD::exp(ax[0]);\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(ax, ay);\n\n    // check value\n    double check = std::exp(x0);\n    ok &= NearEqual(ay[0], check,  eps, eps);\n\n    // forward computation of first partial w.r.t. x[0]\n    CPPAD_TESTVECTOR(double) dx(n);\n    CPPAD_TESTVECTOR(double) dy(m);\n    dx[0] = 1.;\n    dy    = f.Forward(1, dx);\n    ok   &= NearEqual(dy[0], check, eps, eps);\n\n    // reverse computation of derivative of y[0]\n    CPPAD_TESTVECTOR(double)  w(m);\n    CPPAD_TESTVECTOR(double) dw(n);\n    w[0]  = 1.;\n    dw    = f.Reverse(1, w);\n    ok   &= NearEqual(dw[0], check, eps, eps);\n\n    // use a VecAD<Base>::reference object with exp\n    CppAD::VecAD<double> v(1);\n    AD<double> zero(0);\n    v[zero]           = x0;\n    AD<double> result = CppAD::exp(v[zero]);\n    ok   &= NearEqual(result, check, eps, eps);\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/expm1.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin expm1.cpp}\n\nThe AD exp Function: Example and Test\n#####################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end expm1.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n# include <cmath>\n\nbool expm1(void)\n{   bool ok = true;\n\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps = 10. * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n  = 1;\n    double x0 = 0.5;\n    CPPAD_TESTVECTOR(AD<double>) ax(n);\n    ax[0]     = x0;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(ax);\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) ay(m);\n    ay[0] = CppAD::expm1(ax[0]);\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(ax, ay);\n\n    // expx0 value\n    double expx0 = std::exp(x0);\n    ok &= NearEqual(ay[0], expx0-1.0,  eps, eps);\n\n    // forward computation of first partial w.r.t. x[0]\n    CPPAD_TESTVECTOR(double) dx(n);\n    CPPAD_TESTVECTOR(double) dy(m);\n    dx[0] = 1.;\n    dy    = f.Forward(1, dx);\n    ok   &= NearEqual(dy[0], expx0, eps, eps);\n\n    // reverse computation of derivative of y[0]\n    CPPAD_TESTVECTOR(double)  w(m);\n    CPPAD_TESTVECTOR(double) dw(n);\n    w[0]  = 1.;\n    dw    = f.Reverse(1, w);\n    ok   &= NearEqual(dw[0], expx0, eps, eps);\n\n    // use a VecAD<Base>::reference object with exp\n    CppAD::VecAD<double> v(1);\n    AD<double> zero(0);\n    v[zero]           = x0;\n    AD<double> result = CppAD::expm1(v[zero]);\n    ok   &= NearEqual(result, expx0-1.0, eps, eps);\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/fabs.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin fabs.cpp}\n\nAD Absolute Value Function: Example and Test\n############################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end fabs.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n\nbool fabs(void)\n{   bool ok = true;\n\n    using CppAD::AD;\n    using CppAD::NearEqual;\n\n    // domain space vector\n    size_t n = 1;\n    CPPAD_TESTVECTOR(AD<double>) ax(n);\n    ax[0] = 0.;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(ax);\n\n    // range space vector\n    size_t m = 3;\n    CPPAD_TESTVECTOR(AD<double>) ay(m);\n    ay[0]     = fabs(ax[0] - 1.);\n    ay[1]     = fabs(ax[0]);\n    ay[2]     = fabs(ax[0] + 1.);\n    //\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(ax, ay);\n\n    // check values\n    ok &= (ay[0] == 1.);\n    ok &= (ay[1] == 0.);\n    ok &= (ay[2] == 1.);\n    //\n    // forward computation of partials w.r.t. a positive x[0] direction\n    size_t p = 1;\n    CPPAD_TESTVECTOR(double) dx(n), dy(m);\n    dx[0] = 1.;\n    dy    = f.Forward(p, dx);\n    ok  &= (dy[0] == - dx[0]);\n    ok  &= (dy[1] ==   0.   );\n    ok  &= (dy[2] == + dx[0]);\n    //\n    // forward computation of partials w.r.t. a negative x[0] direction\n    dx[0] = -1.;\n    dy    = f.Forward(p, dx);\n    ok  &= (dy[0] == - dx[0]);\n    ok  &= (dy[1] ==   0.   );\n    ok  &= (dy[2] == + dx[0]);\n    //\n    // reverse computation of derivative of y[0]\n    p    = 1;\n    CPPAD_TESTVECTOR(double)  w(m), dw(n);\n    w[0] = 1.; w[1] = 0.; w[2] = 0;\n    dw   = f.Reverse(p, w);\n    ok  &= (dw[0] == -1.);\n\n    // reverse computation of derivative of y[1]\n    w[0] = 0.; w[1] = 1.; w[2] = 0;\n    dw   = f.Reverse(p, w);\n    ok  &= (dw[0] == 0.);\n\n    // reverse computation of derivative of y[3]\n    w[0] = 0.; w[1] = 0.; w[2] = 1;\n    dw   = f.Reverse(p, w);\n    ok  &= (dw[0] == 1.);\n\n    // use a VecAD<Base>::reference object with fabs\n    CppAD::VecAD<double> av(1);\n    AD<double> az(0);\n    av[az]   = -1;\n    AD<double> a_result = fabs(av[az]);\n    ok  &= a_result == 1.0;\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/for_one.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin for_one.cpp}\n\nFirst Order Partial Driver: Example and Test\n############################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end for_one.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\nnamespace { // -------------------------------------------------------\n// define the template function ForOneCases<Vector> in empty namespace\ntemplate <class Vector>\nbool ForOneCases()\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    using CppAD::exp;\n    using CppAD::sin;\n    using CppAD::cos;\n\n    // domain space vector\n    size_t n = 2;\n    CPPAD_TESTVECTOR(AD<double>)  X(n);\n    X[0] = 1.;\n    X[1] = 2.;\n\n    // declare independent variables and starting recording\n    CppAD::Independent(X);\n\n    // range space vector\n    size_t m = 3;\n    CPPAD_TESTVECTOR(AD<double>)  Y(m);\n    Y[0] = X[0] * exp( X[1] );\n    Y[1] = X[0] * sin( X[1] );\n    Y[2] = X[0] * cos( X[1] );\n\n    // create f: X -> Y and stop tape recording\n    CppAD::ADFun<double> f(X, Y);\n\n    // new value for the independent variable vector\n    Vector x(n);\n    x[0] = 2.;\n    x[1] = 1.;\n\n    // compute partial of y w.r.t x[0]\n    Vector dy(m);\n    dy  = f.ForOne(x, 0);\n    ok &= NearEqual( dy[0], exp(x[1]), eps99, eps99); // for y[0]\n    ok &= NearEqual( dy[1], sin(x[1]), eps99, eps99); // for y[1]\n    ok &= NearEqual( dy[2], cos(x[1]), eps99, eps99); // for y[2]\n\n    // compute partial of F w.r.t x[1]\n    dy  = f.ForOne(x, 1);\n    ok &= NearEqual( dy[0],  x[0]*exp(x[1]), eps99, eps99);\n    ok &= NearEqual( dy[1],  x[0]*cos(x[1]), eps99, eps99);\n    ok &= NearEqual( dy[2], -x[0]*sin(x[1]), eps99, eps99);\n\n    return ok;\n}\n} // End empty namespace\n# include <vector>\n# include <valarray>\nbool ForOne(void)\n{   bool ok = true;\n    // Run with Vector equal to three different cases\n    // all of which are Simple Vectors with elements of type double.\n    ok &= ForOneCases< CppAD::vector  <double> >();\n    ok &= ForOneCases< std::vector    <double> >();\n    ok &= ForOneCases< std::valarray  <double> >();\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/general/for_two.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin for_two.cpp}\n\nSubset of Second Order Partials: Example and Test\n#################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end for_two.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\nnamespace { // -----------------------------------------------------\n// define the template function in empty namespace\n// bool ForTwoCases<BaseVector, SizeVector_t>(void)\ntemplate <class BaseVector, class SizeVector_t>\nbool ForTwoCases()\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    using CppAD::exp;\n    using CppAD::sin;\n    using CppAD::cos;\n\n    // domain space vector\n    size_t n = 2;\n    CPPAD_TESTVECTOR(AD<double>)  X(n);\n    X[0] = 1.;\n    X[1] = 2.;\n\n    // declare independent variables and starting recording\n    CppAD::Independent(X);\n\n    // a calculation between the domain and range values\n    AD<double> Square = X[0] * X[0];\n\n    // range space vector\n    size_t m = 3;\n    CPPAD_TESTVECTOR(AD<double>)  Y(m);\n    Y[0] = Square * exp( X[1] );\n    Y[1] = Square * sin( X[1] );\n    Y[2] = Square * cos( X[1] );\n\n    // create f: X -> Y and stop tape recording\n    CppAD::ADFun<double> f(X, Y);\n\n    // new value for the independent variable vector\n    BaseVector x(n);\n    x[0] = 2.;\n    x[1] = 1.;\n\n    // set j and k to compute specific second partials of y\n    size_t p = 2;\n    SizeVector_t j(p);\n    SizeVector_t k(p);\n    j[0] = 0; k[0] = 0; // for second partial w.r.t. x[0] and x[0]\n    j[1] = 0; k[1] = 1; // for second partial w.r.t x[0] and x[1]\n\n    // compute the second partials\n    BaseVector ddy(m * p);\n    ddy = f.ForTwo(x, j, k);\n    /*\n    partial of y w.r.t x[0] is\n    [ 2 * x[0] * exp(x[1]) ]\n    [ 2 * x[0] * sin(x[1]) ]\n    [ 2 * x[0] * cos(x[1]) ]\n    */\n    // second partial of y w.r.t x[0] and x[1]\n    ok &=  NearEqual( 2.*exp(x[1]), ddy[0*p+0], eps99, eps99);\n    ok &=  NearEqual( 2.*sin(x[1]), ddy[1*p+0], eps99, eps99);\n    ok &=  NearEqual( 2.*cos(x[1]), ddy[2*p+0], eps99, eps99);\n\n    // second partial of F w.r.t x[0] and x[1]\n    ok &=  NearEqual( 2.*x[0]*exp(x[1]), ddy[0*p+1], eps99, eps99);\n    ok &=  NearEqual( 2.*x[0]*cos(x[1]), ddy[1*p+1], eps99, eps99);\n    ok &=  NearEqual(-2.*x[0]*sin(x[1]), ddy[2*p+1], eps99, eps99);\n\n    return ok;\n}\n} // End empty namespace\n# include <vector>\n# include <valarray>\nbool ForTwo(void)\n{   bool ok = true;\n        // Run with BaseVector equal to three different cases\n        // all of which are Simple Vectors with elements of type double.\n    ok &= ForTwoCases< CppAD::vector <double>, std::vector<size_t> >();\n    ok &= ForTwoCases< std::vector   <double>, std::vector<size_t> >();\n    ok &= ForTwoCases< std::valarray <double>, std::vector<size_t> >();\n\n        // Run with SizeVector_t equal to two other cases\n        // which are Simple Vectors with elements of type size_t.\n    ok &= ForTwoCases< std::vector <double>, CppAD::vector<size_t> >();\n    ok &= ForTwoCases< std::vector <double>, std::valarray<size_t> >();\n\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/general/forward.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin forward.cpp}\n\nForward Mode: Example and Test\n##############################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end forward.cpp}\n*/\n// BEGIN C++\n# include <limits>\n# include <cppad/cppad.hpp>\nnamespace { // --------------------------------------------------------\n// define the template function ForwardCases<Vector> in empty namespace\ntemplate <class Vector>\nbool ForwardCases(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps = 10. * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n = 2;\n    CPPAD_TESTVECTOR(AD<double>) ax(n);\n    ax[0] = 0.;\n    ax[1] = 1.;\n\n    // declare independent variables and starting recording\n    CppAD::Independent(ax);\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) ay(m);\n    ay[0] = ax[0] * ax[0] * ax[1];\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(ax, ay);\n\n    // initially, the variable values during taping are stored in f\n    ok &= f.size_order() == 1;\n\n    // zero order forward mode using notation in forward_zero\n    // use the template parameter Vector for the vector type\n    Vector x0(n), y0(m);\n    x0[0] = 3.;\n    x0[1] = 4.;\n    y0    = f.Forward(0, x0);\n    ok  &= NearEqual(y0[0] , x0[0]*x0[0]*x0[1], eps, eps);\n    ok  &= f.size_order() == 1;\n\n    // first order forward mode using notation in forward_one\n    // X(t)           = x0 + x1 * t\n    // Y(t) = F[X(t)] = y0 + y1 * t + o(t)\n    Vector x1(n), y1(m);\n    x1[0] = 1.;\n    x1[1] = 0.;\n    y1    = f.Forward(1, x1); // partial F w.r.t. x_0\n    ok   &= NearEqual(y1[0] , 2.*x0[0]*x0[1], eps, eps);\n    ok   &= f.size_order() == 2;\n\n    // second order forward mode using notation in forward_order\n    // X(t) =           x0 + x1 * t + x2 * t^2\n    // Y(t) = F[X(t)] = y0 + y1 * t + y2 * t^2 + o(t^3)\n    Vector x2(n), y2(m);\n    x2[0]      = 0.;\n    x2[1]      = 0.;\n    y2         = f.Forward(2, x2);\n    double F_00 = 2. * y2[0]; // second partial F w.r.t. x_0, x_0\n    ok         &= NearEqual(F_00, 2.*x0[1], eps, eps);\n    ok         &= f.size_order() == 3;\n\n    return ok;\n}\n} // End empty namespace\n# include <vector>\n# include <valarray>\nbool Forward(void)\n{   bool ok = true;\n    // Run with Vector equal to three different cases\n    // all of which are Simple Vectors with elements of type double.\n    ok &= ForwardCases< CppAD::vector  <double> >();\n    ok &= ForwardCases< std::vector    <double> >();\n    ok &= ForwardCases< std::valarray  <double> >();\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/general/forward_dir.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin forward_dir.cpp}\n\nForward Mode: Example and Test of Multiple Directions\n#####################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end forward_dir.cpp}\n*/\n// BEGIN C++\n# include <limits>\n# include <cppad/cppad.hpp>\nbool forward_dir(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps = 10. * std::numeric_limits<double>::epsilon();\n    size_t j;\n\n    // domain space vector\n    size_t n = 3;\n    CPPAD_TESTVECTOR(AD<double>) ax(n);\n    ax[0] = 0.;\n    ax[1] = 1.;\n    ax[2] = 2.;\n\n    // declare independent variables and starting recording\n    CppAD::Independent(ax);\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) ay(m);\n    ay[0] = ax[0] * ax[1] * ax[2];\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(ax, ay);\n\n    // initially, the variable values during taping are stored in f\n    ok &= f.size_order() == 1;\n\n    // zero order Taylor coefficients\n    CPPAD_TESTVECTOR(double) x0(n), y0;\n    for(j = 0; j < n; j++)\n        x0[j] = double(j+1);\n    y0          = f.Forward(0, x0);\n    ok         &= size_t( y0.size() ) == m;\n    double y_0  = 1.*2.*3.;\n    ok         &= NearEqual(y0[0], y_0, eps, eps);\n\n    // first order Taylor coefficients\n    size_t r = 2, ell;\n    CPPAD_TESTVECTOR(double) x1(r*n), y1;\n    for(ell = 0; ell < r; ell++)\n    {   for(j = 0; j < n; j++)\n            x1[ r * j + ell ] = double(j + 1 + ell);\n    }\n    y1  = f.Forward(1, r, x1);\n    ok &= size_t( y1.size() ) == r*m;\n\n    // secondorder Taylor coefficients\n    CPPAD_TESTVECTOR(double) x2(r*n), y2;\n    for(ell = 0; ell < r; ell++)\n    {   for(j = 0; j < n; j++)\n            x2[ r * j + ell ] = 0.0;\n    }\n    y2  = f.Forward(2, r, x2);\n    ok &= size_t( y2.size() ) == r*m;\n    //\n    // Y_0 (t)     = F[X_0(t)]\n    //             =  (1 + 1t)(2 + 2t)(3 + 3t)\n    double y_1_0   = 1.*2.*3. + 2.*1.*3. + 3.*1.*2.;\n    double y_2_0   = 1.*2.*3. + 2.*1.*3. + 3.*1.*2.;\n    //\n    // Y_1 (t)     = F[X_1(t)]\n    //             =  (1 + 2t)(2 + 3t)(3 + 4t)\n    double y_1_1   = 2.*2.*3. + 3.*1.*3. + 4.*1.*2.;\n    double y_2_1   = 1.*3.*4. + 2.*2.*4. + 3.*2.*3.;\n    //\n    ok  &= NearEqual(y1[0] , y_1_0, eps, eps);\n    ok  &= NearEqual(y1[1] , y_1_1, eps, eps);\n    ok  &= NearEqual(y2[0] , y_2_0, eps, eps);\n    ok  &= NearEqual(y2[1] , y_2_1, eps, eps);\n    //\n    // check number of orders\n    ok   &= f.size_order() == 3;\n    //\n    // check number of directions\n    ok   &= f.size_direction() == 2;\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/general/forward_order.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin forward_order.cpp}\n\nForward Mode: Example and Test of Multiple Orders\n#################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end forward_order.cpp}\n*/\n// BEGIN C++\n# include <limits>\n# include <cppad/cppad.hpp>\nbool forward_order(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps = 10. * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n = 2;\n    CPPAD_TESTVECTOR(AD<double>) ax(n);\n    ax[0] = 0.;\n    ax[1] = 1.;\n\n    // declare independent variables and starting recording\n    CppAD::Independent(ax);\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) ay(m);\n    ay[0] = ax[0] * ax[0] * ax[1];\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(ax, ay);\n\n    // initially, the variable values during taping are stored in f\n    ok &= f.size_order() == 1;\n\n    // Compute three forward orders at once\n    size_t q = 2, q1 = q+1;\n    CPPAD_TESTVECTOR(double) xq(n*q1), yq;\n    xq[q1*0 + 0] = 3.;    xq[q1*1 + 0] = 4.; // x^0 (order zero)\n    xq[q1*0 + 1] = 1.;    xq[q1*1 + 1] = 0.; // x^1 (order one)\n    xq[q1*0 + 2] = 0.;    xq[q1*1 + 2] = 0.; // x^2 (order two)\n    // X(t) =   x^0 + x^1 * t + x^2 * t^2\n    //      = [ 3 + t, 4 ]\n    yq  = f.Forward(q, xq);\n    ok &= size_t( yq.size() ) == m*q1;\n    // Y(t) = F[X(t)]\n    //      = (3 + t) * (3 + t) * 4\n    //      = y^0 + y^1 * t + y^2 * t^2 + o(t^3)\n    //\n    // check y^0 (order zero)\n    CPPAD_TESTVECTOR(double) x0(n);\n    x0[0] = xq[q1*0 + 0];\n    x0[1] = xq[q1*1 + 0];\n    ok  &= NearEqual(yq[q1*0 + 0] , x0[0]*x0[0]*x0[1], eps, eps);\n    //\n    // check y^1 (order one)\n    ok  &= NearEqual(yq[q1*0 + 1] , 2.*x0[0]*x0[1], eps, eps);\n    //\n    // check y^2 (order two)\n    double F_00 = 2. * yq[q1*0 + 2]; // second partial F w.r.t. x_0, x_0\n    ok   &= NearEqual(F_00, 2.*x0[1], eps, eps);\n    //\n    // check number of orders per variable\n    ok   &= f.size_order() == 3;\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/general/fun_assign.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin fun_assign.cpp}\n\nADFun Assignment: Example and Test\n##################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end fun_assign.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n# include <limits>\n\nbool fun_assign(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    size_t i, j;\n\n    // ten times machine precision\n    double eps = 10. * CppAD::numeric_limits<double>::epsilon();\n\n    // an empty ADFun<double> object\n    CppAD::ADFun<double> g;\n\n    // domain space vector\n    size_t n  = 3;\n    CPPAD_TESTVECTOR(AD<double>) x(n);\n    for(j = 0; j < n; j++)\n        x[j] = AD<double>(j + 2);\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(x);\n\n    // range space vector\n    size_t m = 2;\n    CPPAD_TESTVECTOR(AD<double>) y(m);\n    y[0] = x[0] + x[0] * x[1];\n    y[1] = x[1] * x[2] + x[2];\n\n    // Store operation sequence, and order zero forward results, in f.\n    // This assignment will use move semantics\n    CppAD::ADFun<double> f;\n    f = CppAD::ADFun<double>(x, y);\n\n    // sparsity pattern for the identity matrix\n    CPPAD_TESTVECTOR(std::set<size_t>) r(n);\n    for(j = 0; j < n; j++)\n        r[j].insert(j);\n\n    // Store forward mode sparsity pattern in f\n    f.ForSparseJac(n, r);\n\n    // make a copy of f in g\n    g = f;\n\n    // check values that should be equal\n    ok &= ( g.size_order() == f.size_order() );\n    ok &= ( (g.size_forward_bool() > 0) == (f.size_forward_bool() > 0) );\n    ok &= ( (g.size_forward_set() > 0)  == (f.size_forward_set() > 0) );\n\n    // Use zero order Taylor coefficient from f for first order\n    // calculation using g.\n    CPPAD_TESTVECTOR(double) dx(n), dy(m);\n    for(i = 0; i < n; i++)\n        dx[i] = 0.;\n    dx[1] = 1;\n    dy    = g.Forward(1, dx);\n    ok &= NearEqual(dy[0], x[0], eps, eps); // partial y[0] w.r.t x[1]\n    ok &= NearEqual(dy[1], x[2], eps, eps); // partial y[1] w.r.t x[1]\n\n    // Use forward Jacobian sparsity pattern from f to calculate\n    // Hessian sparsity pattern using g.\n    CPPAD_TESTVECTOR(std::set<size_t>) s(1), h(n);\n    s[0].insert(0); // Compute sparsity pattern for Hessian of y[0]\n    h =  f.RevSparseHes(n, s);\n\n    // check sparsity pattern for Hessian of y[0] = x[0] + x[0] * x[1]\n    ok  &= ( h[0].find(0) == h[0].end() ); // zero     w.r.t x[0], x[0]\n    ok  &= ( h[0].find(1) != h[0].end() ); // non-zero w.r.t x[0], x[1]\n    ok  &= ( h[0].find(2) == h[0].end() ); // zero     w.r.t x[0], x[2]\n\n    ok  &= ( h[1].find(0) != h[1].end() ); // non-zero w.r.t x[1], x[0]\n    ok  &= ( h[1].find(1) == h[1].end() ); // zero     w.r.t x[1], x[1]\n    ok  &= ( h[1].find(2) == h[1].end() ); // zero     w.r.t x[1], x[2]\n\n    ok  &= ( h[2].find(0) == h[2].end() ); // zero     w.r.t x[2], x[0]\n    ok  &= ( h[2].find(1) == h[2].end() ); // zero     w.r.t x[2], x[1]\n    ok  &= ( h[2].find(2) == h[2].end() ); // zero     w.r.t x[2], x[2]\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/fun_check.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n! WARNING: This file is used as an example by fun_construct and Dependent\n\n{xrst_begin fun_check.cpp}\n\nADFun Check and Re-Tape: Example and Test\n#########################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end fun_check.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nnamespace { // -----------------------------------------------------------\n// define the template function object Fun<Type,Vector> in empty namespace\ntemplate <class Type, class Vector>\nclass Fun {\nprivate:\n    size_t n;\npublic:\n    // function constructor\n    Fun(size_t n_) : n(n_)\n    { }\n    // function evaluator\n    Vector operator() (const Vector &x)\n    {   Vector y(n);\n        size_t i;\n        for(i = 0; i < n; i++)\n        {   // This operation sequence depends on x\n            if( x[i] >= 0 )\n                y[i] = exp(x[i]);\n            else\n                y[i] = exp(-x[i]);\n        }\n        return y;\n    }\n};\n// template function FunCheckCases<Vector, ADVector> in empty namespace\ntemplate <class Vector, class ADVector>\nbool FunCheckCases(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::ADFun;\n    using CppAD::Independent;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // use the ADFun default constructor\n    ADFun<double> f;\n\n    // domain space vector\n    size_t n = 2;\n    ADVector X(n);\n    X[0] = -1.;\n    X[1] = 1.;\n\n    // declare independent variables and starting recording\n    Independent(X);\n\n    // create function object to use with AD<double>\n    Fun< AD<double>, ADVector > G(n);\n\n    // range space vector\n    size_t m = n;\n    ADVector Y(m);\n    Y = G(X);\n\n    // stop tape and store operation sequence in f : X -> Y\n    f.Dependent(X, Y);\n    ok &= (f.size_order() == 0);  // no implicit forward operation\n\n    // create function object to use with double\n    Fun<double, Vector> g(n);\n\n    // function values should agree when the independent variable\n    // values are the same as during recording\n    Vector x(n);\n    size_t j;\n    for(j = 0; j < n; j++)\n        x[j] = Value(X[j]);\n    double r = eps99;\n    double a = eps99;\n    ok      &= FunCheck(f, g, x, a, r);\n\n    // function values should not agree when the independent variable\n    // values are the negative of values during recording\n    for(j = 0; j < n; j++)\n        x[j] = - Value(X[j]);\n    ok      &= ! FunCheck(f, g, x, a, r);\n\n    // re-tape to obtain the new AD of double operation sequence\n    for(j = 0; j < n; j++)\n        X[j] = x[j];\n    Independent(X);\n    Y = G(X);\n\n    // stop tape and store operation sequence in f : X -> Y\n    f.Dependent(X, Y);\n    ok &= (f.size_order() == 0);  // no implicit forward with this x\n\n    // function values should agree now\n    ok      &= FunCheck(f, g, x, a, r);\n\n    return ok;\n}\n} // End empty namespace\n# include <vector>\n# include <valarray>\nbool FunCheck(void)\n{   bool ok = true;\n    typedef CppAD::vector<double>                Vector1;\n    typedef CppAD::vector< CppAD::AD<double> > ADVector1;\n    typedef   std::vector<double>                Vector2;\n    typedef   std::vector< CppAD::AD<double> > ADVector2;\n    typedef std::valarray<double>                Vector3;\n    typedef std::valarray< CppAD::AD<double> > ADVector3;\n    // Run with Vector and ADVector equal to three different cases\n    // all of which are Simple Vectors with elements of type\n    // double and AD<double> respectively.\n    ok &= FunCheckCases< Vector1, ADVector2 >();\n    ok &= FunCheckCases< Vector2, ADVector3 >();\n    ok &= FunCheckCases< Vector3, ADVector1 >();\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/general/fun_property.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin fun_property.cpp}\n\nADFun Function Properties: Example and Test\n###########################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end fun_property.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n\n// Note that CPPAD_VEC_ENUM_TYPE is not part of CppAD API and may change\n# define CPPAD_VEC_ENUM_TYPE unsigned char\n\nbool fun_property(void)\n{   bool ok = true;\n    using CppAD::AD;\n\n    // Use nvar to track the number of variables in the operation sequence.\n    // Start with one for the phantom variable at tape address zero.\n    size_t nvar = 1;\n\n    // Use npar to track the number of parameters in the operation sequence.\n    // Start with one for the phantom parameter at index zero.\n    size_t npar = 1;\n\n    // Use ndyn to track the number of dynamic parameters.\n    size_t ndyn = 0;\n\n    // Use ndyn to track number of arguments to dynamic parameter operators.\n    size_t ndyn_arg = 0;\n\n    // Start with one for operator corresponding to phantom variable\n    size_t nop  = 1;\n\n    // Start with one for operator corresponding to phantom argument\n    size_t narg = 1;\n\n    // Use ntext to track the number of characters used to label\n    // output generated using PrintFor commands.\n    size_t ntext = 0;\n\n    // Use nvecad to track the number of VecAD vectors, plus the number\n    // of VecAD vector elements, in the operation sequence.\n    size_t nvecad = 0;\n\n    // a VecAD vector\n    CppAD::VecAD<double> v(2);\n    v[0]     = 0; // requires the parameter 0, when becomes a variable\n    v[1]     = 1; // requires the parameter 1, when becomes a variable\n\n    // domain space vector\n    size_t n = 2;\n    CPPAD_TESTVECTOR(AD<double>) x(n);\n    x[0]     = 0.;\n    x[1]     = 1.;\n\n    // dynamic parameter vector\n    CPPAD_TESTVECTOR(AD<double>) dynamic(1);\n    dynamic[0] = 1.;\n\n\n    // declare independent variables and start tape recording\n    size_t abort_op_index = 0;\n    bool   record_compare = true;\n    CppAD::Independent(x, abort_op_index, record_compare, dynamic);\n    nvar    += n;\n    nop     += n;\n    ndyn    += dynamic.size();\n    npar    += ndyn;\n\n    // a computation that adds to the operation sequence\n    AD<double> I = 0;\n    v[I]         = x[0];\n    nvecad      +=   3;  // one for vector, two for its elements\n    npar        +=   2;  // need parameters 0 and 1 for initial v\n    nop         +=   1;  // operator for storing in a VecAD object\n    narg        +=   3;  // the three arguments are v, I, and x[0]\n\n    // some operations that do not add to the operation sequence\n    AD<double> u = x[0];  // use same variable as x[0]\n    AD<double> w = x[1];  // use same variable as x[1]\n\n    // a computation that adds to the operation sequence\n    w      = w * (u + w);\n    nop   += 2;   // requires two new operators, an add and a multiply\n    nvar  += 2;   // each operator results in its own variable\n    narg  += 4;   // each operator has two arguments\n\n    // range space vector\n    size_t m = 3;\n    CPPAD_TESTVECTOR(AD<double>) y(m);\n\n    // operations that do not add to the operation sequence\n    y[0]   = 1.;  // re-use the parameter 1\n    y[1]   = u;   // use same variable as u\n\n    // a computation that adds to the operation sequence\n    y[2]   = w + 2.;\n    nop   += 1;   // requires a new add operator\n    npar  += 1;   // new parameter 2 is new, so it must be included\n    nvar  += 1;   // variable corresponding to the result\n    narg  += 2;   // operator has two arguments\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(x, y);\n    nop   += 1;   // special operator for y[0] because it is a parameter\n    nvar  += 1;   // special variable for y[0] because it is a parameter\n    narg  += 1;   // identifies which parameter corresponds to y[0]\n    nop   += 1;   // special operator at the end of operation sequence\n\n    // check the sequence property functions\n    ok &= f.Domain()        == n;\n    ok &= f.Range()         == m;\n    ok &= f.Parameter(0)    == true;\n    ok &= f.Parameter(1)    == false;\n    ok &= f.Parameter(2)    == false;\n    ok &= f.size_var()      == nvar;\n    ok &= f.size_op()       == nop;\n    ok &= f.size_op_arg()   == narg;\n    ok &= f.size_par()      == npar;\n    ok &= f.size_text()     == ntext;\n    ok &= f.size_VecAD()    == nvecad;\n    ok &= f.size_dyn_ind()  == ndyn;\n    ok &= f.size_dyn_par()  == ndyn;\n    ok &= f.size_dyn_arg()  == ndyn_arg;\n\n    //\n    size_t sum = 0;\n    sum += nop        * sizeof(CPPAD_VEC_ENUM_TYPE);\n    sum += narg       * sizeof(CPPAD_TAPE_ADDR_TYPE);\n    sum += npar       * sizeof(double);\n    sum += npar       * sizeof(bool);\n    sum += ndyn       * sizeof(CPPAD_VEC_ENUM_TYPE);\n    sum += ndyn       * sizeof(CPPAD_TAPE_ADDR_TYPE);\n    sum += ndyn_arg   * sizeof(CPPAD_TAPE_ADDR_TYPE);\n    sum += ntext      * sizeof(char);\n    sum += nvecad     * sizeof(CPPAD_TAPE_ADDR_TYPE);\n    ok &= f.size_op_seq() == sum;\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/function_name.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin function_name.cpp}\n\nADFun Function Name: Example and Test\n#####################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end function_name.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n\nbool function_name(void)\n{   bool ok = true;\n    using CppAD::AD;\n\n    // create empty function\n    CppAD::ADFun<double> f;\n\n    // check its name\n    ok &= f.function_name_get() == \"\";\n\n    // set and check a new name\n    f.function_name_set(\"empty_function\");\n    ok &= f.function_name_get() == \"empty_function\";\n\n    // store an operation sequence in f\n    size_t nx = 1;\n    size_t ny = 1;\n    CPPAD_TESTVECTOR( AD<double> ) ax(nx), ay(ny);\n    ax[0] = 1.0;\n    CppAD::Independent(ax);\n    ay[0] = sin(ax[0]);\n    f.Dependent(ax, ay);\n\n    // check function name has not changed\n    ok &= f.function_name_get() == \"empty_function\";\n\n    // now set a better name for this function\n    f.function_name_set(\"sin\");\n    ok &= f.function_name_get() == \"sin\";\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/general.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin general.cpp}\n\nGeneral Examples and Tests Driver\n#################################\n\nRunning These Tests\n*******************\nAfter executing the :ref:`cmake-name` command\nform the :ref:`download@Distribution Directory`,\nyou can build and run these tests with the commands::\n\n    cd build\n    make check_example_general\n\nNote that your choice of :ref:`cmake@generator` may require using\nan different version of make; e.g., ``ninja`` .\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end general.cpp}\n-------------------------------------------------------------------------------\n*/\n// BEGIN C++\n\n// CPPAD_HAS_* defines\n# include <cppad/configure.hpp>\n\n// standard string\n# include <string>\n\n// memory utility\n# include <cppad/utility/thread_alloc.hpp>\n\n// test runner\n# include <cppad/utility/test_boolofvoid.hpp>\n\n// BEGIN_SORT_THIS_LINE_PLUS_1\nextern bool Add(void);\nextern bool AddEq(void);\nextern bool BenderQuad(void);\nextern bool BoolFun(void);\nextern bool Compare(void);\nextern bool CondExp(void);\nextern bool Cos(void);\nextern bool Cosh(void);\nextern bool Div(void);\nextern bool DivEq(void);\nextern bool EqualOpSeq(void);\nextern bool ForOne(void);\nextern bool ForTwo(void);\nextern bool Forward(void);\nextern bool FunCheck(void);\nextern bool HesLagrangian(void);\nextern bool HesLuDet(void);\nextern bool HesMinorDet(void);\nextern bool HesTimesDir(void);\nextern bool Hessian(void);\nextern bool Independent(void);\nextern bool Integer(void);\nextern bool Interface2C(void);\nextern bool JacLuDet(void);\nextern bool JacMinorDet(void);\nextern bool Jacobian(void);\nextern bool LuRatio(void);\nextern bool Mul(void);\nextern bool MulEq(void);\nextern bool NumericType(void);\nextern bool OdeStiff(void);\nextern bool RevOne(void);\nextern bool RevTwo(void);\nextern bool Sin(void);\nextern bool Sinh(void);\nextern bool Sqrt(void);\nextern bool StackMachine(void);\nextern bool Sub(void);\nextern bool SubEq(void);\nextern bool Tan(void);\nextern bool Tanh(void);\nextern bool TapeIndex(void);\nextern bool Value(void);\nextern bool Var2Par(void);\nextern bool abort_recording(void);\nextern bool acos(void);\nextern bool acosh(void);\nextern bool ad_assign(void);\nextern bool ad_ctor(void);\nextern bool ad_fun(void);\nextern bool ad_in_c(void);\nextern bool ad_input(void);\nextern bool ad_output(void);\nextern bool asin(void);\nextern bool asinh(void);\nextern bool atan(void);\nextern bool atan2(void);\nextern bool atanh(void);\nextern bool azmul(void);\nextern bool base2ad(void);\nextern bool base2vec_ad(void);\nextern bool base_require(void);\nextern bool capacity_order(void);\nextern bool change_param(void);\nextern bool check_for_nan(void);\nextern bool complex_poly(void);\nextern bool con_dyn_var(void);\nextern bool eigen_array(void);\nextern bool eigen_det(void);\nextern bool erf(void);\nextern bool erfc(void);\nextern bool exp(void);\nextern bool expm1(void);\nextern bool fabs(void);\nextern bool forward_dir(void);\nextern bool forward_order(void);\nextern bool fun_assign(void);\nextern bool fun_property(void);\nextern bool function_name(void);\nextern bool interp_onetape(void);\nextern bool interp_retape(void);\nextern bool log(void);\nextern bool log10(void);\nextern bool log1p(void);\nextern bool lu_vec_ad_ok(void);\nextern bool mul_level(void);\nextern bool mul_level_adolc(void);\nextern bool mul_level_adolc_ode(void);\nextern bool mul_level_ode(void);\nextern bool near_equal_ext(void);\nextern bool new_dynamic(void);\nextern bool num_limits(void);\nextern bool number_skip(void);\nextern bool opt_val_hes(void);\nextern bool pow(void);\nextern bool pow_nan(void);\nextern bool print_for(void);\nextern bool rev_checkpoint(void);\nextern bool reverse_one(void);\nextern bool reverse_three(void);\nextern bool reverse_two(void);\nextern bool sign(void);\nextern bool taylor_ode(void);\nextern bool unary_minus(void);\nextern bool unary_plus(void);\nextern bool vec_ad(void);\n// END_SORT_THIS_LINE_MINUS_1\n\n// main program that runs all the tests\nint main(void)\n{   std::string group = \"example/general\";\n    size_t      width = 20;\n    CppAD::test_boolofvoid Run(group, width);\n\n    // This line is used by test_one.sh\n\n    // BEGIN_SORT_THIS_LINE_PLUS_1\n    Run( Add,               \"Add\"              );\n    Run( AddEq,             \"AddEq\"            );\n    Run( BenderQuad,        \"BenderQuad\"       );\n    Run( BoolFun,           \"BoolFun\"          );\n    Run( Compare,           \"Compare\"          );\n    Run( CondExp,           \"CondExp\"          );\n    Run( Cos,               \"Cos\"              );\n    Run( Cosh,              \"Cosh\"             );\n    Run( Div,               \"Div\"              );\n    Run( DivEq,             \"DivEq\"            );\n    Run( EqualOpSeq,        \"EqualOpSeq\"       );\n    Run( ForOne,            \"ForOne\"           );\n    Run( ForTwo,            \"ForTwo\"           );\n    Run( Forward,           \"Forward\"          );\n    Run( FunCheck,          \"FunCheck\"         );\n    Run( HesLagrangian,     \"HesLagrangian\"    );\n    Run( HesLuDet,          \"HesLuDet\"         );\n    Run( HesMinorDet,       \"HesMinorDet\"      );\n    Run( HesTimesDir,       \"HesTimesDir\"      );\n    Run( Hessian,           \"Hessian\"          );\n    Run( Independent,       \"Independent\"      );\n    Run( Integer,           \"Integer\"          );\n    Run( Interface2C,       \"Interface2C\"      );\n    Run( JacLuDet,          \"JacLuDet\"         );\n    Run( JacMinorDet,       \"JacMinorDet\"      );\n    Run( Jacobian,          \"Jacobian\"         );\n    Run( LuRatio,           \"LuRatio\"          );\n    Run( Mul,               \"Mul\"              );\n    Run( MulEq,             \"MulEq\"            );\n    Run( NumericType,       \"NumericType\"      );\n    Run( OdeStiff,          \"OdeStiff\"         );\n    Run( RevOne,            \"RevOne\"           );\n    Run( RevTwo,            \"RevTwo\"           );\n    Run( Sin,               \"Sin\"              );\n    Run( Sinh,              \"Sinh\"             );\n    Run( Sqrt,              \"Sqrt\"             );\n    Run( StackMachine,      \"StackMachine\"     );\n    Run( Sub,               \"Sub\"              );\n    Run( SubEq,             \"SubEq\"            );\n    Run( Tan,               \"Tan\"              );\n    Run( Tanh,              \"Tanh\"             );\n    Run( TapeIndex,         \"TapeIndex\"        );\n    Run( Value,             \"Value\"            );\n    Run( Var2Par,           \"Var2Par\"          );\n    Run( abort_recording,   \"abort_recording\"  );\n    Run( acos,              \"acos\"             );\n    Run( acosh,             \"acosh\"            );\n    Run( ad_assign,         \"ad_assign\"        );\n    Run( ad_ctor,           \"ad_ctor\"          );\n    Run( ad_fun,            \"ad_fun\"           );\n    Run( ad_in_c,           \"ad_in_c\"          );\n    Run( ad_input,          \"ad_input\"         );\n    Run( ad_output,         \"ad_output\"        );\n    Run( asin,              \"asin\"             );\n    Run( asinh,             \"asinh\"            );\n    Run( atan,              \"atan\"             );\n    Run( atan2,             \"atan2\"            );\n    Run( atanh,             \"atanh\"            );\n    Run( azmul,             \"azmul\"            );\n    Run( base2ad,           \"base2ad\"          );\n    Run( base2vec_ad,       \"base2vec_ad\"      );\n    Run( base_require,      \"base_require\"     );\n    Run( capacity_order,    \"capacity_order\"   );\n    Run( change_param,      \"change_param\"     );\n    Run( complex_poly,      \"complex_poly\"     );\n    Run( con_dyn_var,       \"con_dyn_var\"      );\n    Run( erf,               \"erf\"              );\n    Run( erfc,              \"erfc\"             );\n    Run( exp,               \"exp\"              );\n    Run( expm1,             \"expm1\"            );\n    Run( fabs,              \"fabs\"             );\n    Run( forward_dir,       \"forward_dir\"      );\n    Run( forward_order,     \"forward_order\"    );\n    Run( fun_assign,        \"fun_assign\"       );\n    Run( fun_property,      \"fun_property\"     );\n    Run( function_name,     \"function_name\"    );\n    Run( interp_onetape,    \"interp_onetape\"   );\n    Run( interp_retape,     \"interp_retape\"    );\n    Run( log,               \"log\"              );\n    Run( log10,             \"log10\"            );\n    Run( log1p,             \"log1p\"            );\n    Run( lu_vec_ad_ok,      \"lu_vec_ad_ok\"     );\n    Run( mul_level,         \"mul_level\"        );\n    Run( mul_level_ode,     \"mul_level_ode\"    );\n    Run( near_equal_ext,    \"near_equal_ext\"   );\n    Run( new_dynamic,       \"new_dynamic\"      );\n    Run( num_limits,        \"num_limits\"       );\n    Run( number_skip,       \"number_skip\"      );\n    Run( opt_val_hes,       \"opt_val_hes\"      );\n    Run( pow,               \"pow\"              );\n    Run( pow_nan,           \"pow_nan\"          );\n    Run( rev_checkpoint,    \"rev_checkpoint\"   );\n    Run( reverse_one,       \"reverse_one\"      );\n    Run( reverse_three,     \"reverse_three\"    );\n    Run( reverse_two,       \"reverse_two\"      );\n    Run( sign,              \"sign\"             );\n    Run( taylor_ode,        \"ode_taylor\"       );\n    Run( unary_minus,       \"unary_minus\"      );\n    Run( unary_plus,        \"unary_plus\"       );\n    Run( vec_ad,            \"vec_ad\"           );\n    // END_SORT_THIS_LINE_MINUS_1\n# if ! CPPAD_DEBUG_AND_RELEASE\n    Run( check_for_nan,     \"check_for_nan\"    );\n# endif\n# if CPPAD_HAS_ADOLC\n    Run( mul_level_adolc,      \"mul_level_adolc\"     );\n    Run( mul_level_adolc_ode,  \"mul_level_adolc_ode\" );\n# endif\n# if CPPAD_HAS_EIGEN\n    Run( eigen_array,       \"eigen_array\"      );\n    Run( eigen_det,         \"eigen_det\"        );\n# endif\n    //\n    // check for memory leak\n    bool memory_ok = CppAD::thread_alloc::free_all();\n    // print summary at end\n    bool ok = Run.summary(memory_ok);\n    //\n    return static_cast<int>( ! ok );\n}\n// END C++\n"
  },
  {
    "path": "example/general/hes_lagrangian.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin hes_lagrangian.cpp}\n\n{xrst_comment ! NOTE the title states that this example is used two places !}\nHessian of Lagrangian and ADFun Default Constructor: Example and Test\n#####################################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end hes_lagrangian.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n# include <cassert>\n\nnamespace {\n    CppAD::AD<double> Lagragian(\n        const CppAD::vector< CppAD::AD<double> > &xyz )\n    {   using CppAD::AD;\n        assert( xyz.size() == 6 );\n\n        AD<double> x0 = xyz[0];\n        AD<double> x1 = xyz[1];\n        AD<double> x2 = xyz[2];\n        AD<double> y0 = xyz[3];\n        AD<double> y1 = xyz[4];\n        AD<double> z  = xyz[5];\n\n        // compute objective function\n        AD<double> f = x0 * x0;\n        // compute constraint functions\n        AD<double> g0 = 1. + 2.*x1 + 3.*x2;\n        AD<double> g1 = log( x0 * x2 );\n        // compute the Lagragian\n        AD<double> L = y0 * g0 + y1 * g1 + z * f;\n\n        return L;\n\n    }\n    CppAD::vector< CppAD::AD<double> > fg(\n        const CppAD::vector< CppAD::AD<double> > &x )\n    {   using CppAD::AD;\n        using CppAD::vector;\n        assert( x.size() == 3 );\n\n        vector< AD<double> > fg(3);\n        fg[0] = x[0] * x[0];\n        fg[1] = 1. + 2. * x[1] + 3. * x[2];\n        fg[2] = log( x[0] * x[2] );\n\n        return fg;\n    }\n    bool CheckHessian(\n    CppAD::vector<double> H ,\n    double x0, double x1, double x2, double y0, double y1, double z )\n    {   using CppAD::NearEqual;\n        double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n        bool ok  = true;\n        size_t n = 3;\n        assert( H.size() == n * n );\n        /*\n        L   =    z*x0*x0 + y0*(1 + 2*x1 + 3*x2) + y1*log(x0*x2)\n\n        L_0 = 2 * z * x0 + y1 / x0\n        L_1 = y0 * 2\n        L_2 = y0 * 3 + y1 / x2\n        */\n        // L_00 = 2 * z - y1 / ( x0 * x0 )\n        double check = 2. * z - y1 / (x0 * x0);\n        ok &= NearEqual(H[0 * n + 0], check, eps99, eps99);\n        // L_01 = L_10 = 0\n        ok &= NearEqual(H[0 * n + 1], 0., eps99, eps99);\n        ok &= NearEqual(H[1 * n + 0], 0., eps99, eps99);\n        // L_02 = L_20 = 0\n        ok &= NearEqual(H[0 * n + 2], 0., eps99, eps99);\n        ok &= NearEqual(H[2 * n + 0], 0., eps99, eps99);\n        // L_11 = 0\n        ok &= NearEqual(H[1 * n + 1], 0., eps99, eps99);\n        // L_12 = L_21 = 0\n        ok &= NearEqual(H[1 * n + 2], 0., eps99, eps99);\n        ok &= NearEqual(H[2 * n + 1], 0., eps99, eps99);\n        // L_22 = - y1 / (x2 * x2)\n        check = - y1 / (x2 * x2);\n        ok &= NearEqual(H[2 * n + 2], check, eps99, eps99);\n\n        return ok;\n    }\n    bool UseL()\n    {   using CppAD::AD;\n        using CppAD::vector;\n\n        // double values corresponding to x, y, and z vectors\n        double x0(.5), x1(1e3), x2(1), y0(2.), y1(3.), z(4.);\n\n        // domain space vector\n        size_t n = 3;\n        vector< AD<double> >  a_x(n);\n        a_x[0] = x0;\n        a_x[1] = x1;\n        a_x[2] = x2;\n\n        // declare a_x as independent variable vector and start recording\n        CppAD::Independent(a_x);\n\n        // vector including x, y, and z\n        vector< AD<double> > a_xyz(n + 2 + 1);\n        a_xyz[0] = a_x[0];\n        a_xyz[1] = a_x[1];\n        a_xyz[2] = a_x[2];\n        a_xyz[3] = y0;\n        a_xyz[4] = y1;\n        a_xyz[5] = z;\n\n        // range space vector\n        size_t m = 1;\n        vector< AD<double> >  a_L(m);\n        a_L[0] = Lagragian(a_xyz);\n\n        // create K: x -> L and stop tape recording.\n        // Use default ADFun construction for example purposes.\n        CppAD::ADFun<double> K;\n        K.Dependent(a_x, a_L);\n\n        // Operation sequence corresponding to K depends on\n        // value of y0, y1, and z. Must redo calculations above when\n        // y0, y1, or z changes.\n\n        // declare independent variable vector and Hessian\n        vector<double> x(n);\n        vector<double> H( n * n );\n\n        // point at which we are computing the Hessian\n        // (must redo calculations below each time x changes)\n        x[0] = x0;\n        x[1] = x1;\n        x[2] = x2;\n        H = K.Hessian(x, 0);\n\n        // check this Hessian calculation\n        return CheckHessian(H, x0, x1, x2, y0, y1, z);\n    }\n    bool Usefg()\n    {   using CppAD::AD;\n        using CppAD::vector;\n\n        // parameters defining problem\n        double x0(.5), x1(1e3), x2(1), y0(2.), y1(3.), z(4.);\n\n        // domain space vector\n        size_t n = 3;\n        vector< AD<double> >  a_x(n);\n        a_x[0] = x0;\n        a_x[1] = x1;\n        a_x[2] = x2;\n\n        // declare a_x as independent variable vector and start recording\n        CppAD::Independent(a_x);\n\n        // range space vector\n        size_t m = 3;\n        vector< AD<double> >  a_fg(m);\n        a_fg = fg(a_x);\n\n        // create K: x -> fg and stop tape recording\n        CppAD::ADFun<double> K;\n        K.Dependent(a_x, a_fg);\n\n        // Operation sequence corresponding to K does not depend on\n        // value of x0, x1, x2, y0, y1, or z.\n\n        // forward and reverse mode arguments and results\n        vector<double> x(n);\n        vector<double> H( n * n );\n        vector<double>  dx(n);\n        vector<double>   w(m);\n        vector<double>  dw(2*n);\n\n        // compute Hessian at this value of x\n        // (must redo calculations below each time x changes)\n        x[0] = x0;\n        x[1] = x1;\n        x[2] = x2;\n        K.Forward(0, x);\n\n        // set weights to Lagrange multiplier values\n        // (must redo calculations below each time y0, y1, or z changes)\n        w[0] = z;\n        w[1] = y0;\n        w[2] = y1;\n\n        // initialize dx as zero\n        size_t i, j;\n        for(i = 0; i < n; i++)\n            dx[i] = 0.;\n        // loop over components of x\n        for(i = 0; i < n; i++)\n        {   dx[i] = 1.;             // dx is i-th elementary vector\n            K.Forward(1, dx);       // partial w.r.t dx\n            dw = K.Reverse(2, w);   // deritavtive of partial\n            for(j = 0; j < n; j++)\n                H[ i * n + j ] = dw[ j * 2 + 1 ];\n            dx[i] = 0.;             // dx is zero vector\n        }\n\n        // check this Hessian calculation\n        return CheckHessian(H, x0, x1, x2, y0, y1, z);\n    }\n}\n\nbool HesLagrangian(void)\n{   bool ok = true;\n\n    // UseL is simpler, but must retape every time that y of z changes\n    ok     &= UseL();\n\n    // Usefg does not need to retape unless operation sequence changes\n    ok     &= Usefg();\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/hes_lu_det.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin hes_lu_det.cpp}\n\nGradient of Determinant Using LU Factorization: Example and Test\n################################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end hes_lu_det.cpp}\n*/\n// BEGIN C++\n// Complex examples should suppress conversion warnings\n# include <cppad/wno_conversion.hpp>\n\n# include <cppad/cppad.hpp>\n# include <cppad/speed/det_by_lu.hpp>\n\n// The AD complex case is used by this example so must\n// define a specializatgion of LeqZero,AbsGeq for the AD<Complex> case\nnamespace CppAD {\n    CPPAD_BOOL_BINARY( std::complex<double> ,  AbsGeq   )\n    CPPAD_BOOL_UNARY(  std::complex<double> ,  LeqZero )\n}\n\n\nbool HesLuDet(void)\n{   bool ok = true;\n\n    using namespace CppAD;\n    typedef std::complex<double> Complex;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    size_t n = 2;\n\n    // object for computing determinants\n    det_by_lu< AD<Complex> > Det(n);\n\n    // independent and dependent variable vectors\n    CPPAD_TESTVECTOR(AD<Complex>)  X(n * n);\n    CPPAD_TESTVECTOR(AD<Complex>)  D(1);\n\n    // value of the independent variable\n    size_t i;\n    for(i = 0; i < n * n; i++)\n        X[i] = Complex( double(i), -double(i) );\n\n    // set the independent variables\n    Independent(X);\n\n    D[0]  = Det(X);\n\n    // create the function object\n    ADFun<Complex> f(X, D);\n\n    // argument value\n    CPPAD_TESTVECTOR(Complex)     x( n * n );\n    for(i = 0; i < n * n; i++)\n        x[i] = Complex( double(2 * i) , double(i) );\n\n    // first derivative of the determinant\n    CPPAD_TESTVECTOR(Complex) H( n * n * n * n );\n    H = f.Hessian(x, 0);\n\n    /*\n    f(x)     = x[0] * x[3] - x[1] * x[2]\n    f'(x)    = ( x[3], -x[2], -x[1], x[0] )\n    */\n    Complex zero(0., 0.);\n    Complex one(1., 0.);\n    Complex Htrue[]  = {\n        zero, zero, zero,  one,\n        zero, zero, -one, zero,\n        zero, -one, zero, zero,\n            one, zero, zero, zero\n    };\n    for( i = 0; i < n*n*n*n; i++)\n        ok &= NearEqual( Htrue[i], H[i], eps99 , eps99 );\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/hes_minor_det.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin hes_minor_det.cpp}\n\nGradient of Determinant Using Expansion by Minors: Example and Test\n###################################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end hes_minor_det.cpp}\n*/\n// BEGIN C++\n// Complex examples should suppress conversion warnings\n# include <cppad/wno_conversion.hpp>\n\n# include <cppad/cppad.hpp>\n# include <cppad/speed/det_by_minor.hpp>\n# include <complex>\n\ntypedef std::complex<double>     Complex;\ntypedef CppAD::AD<Complex>       ADComplex;\ntypedef CPPAD_TESTVECTOR(ADComplex)   ADVector;\n\n// ----------------------------------------------------------------------------\n\nbool HesMinorDet(void)\n{   bool ok = true;\n\n    using namespace CppAD;\n\n    size_t n = 2;\n\n    // object for computing determinants\n    det_by_minor<ADComplex> Det(n);\n\n    // independent and dependent variable vectors\n    CPPAD_TESTVECTOR(ADComplex)  X(n * n);\n    CPPAD_TESTVECTOR(ADComplex)  D(1);\n\n    // value of the independent variable\n    size_t i;\n    for(i = 0; i < n * n; i++)\n        X[i] = Complex( double(i), -double(i) );\n\n    // set the independent variables\n    Independent(X);\n\n    // comupute the determinant\n    D[0] = Det(X);\n\n    // create the function object\n    ADFun<Complex> f(X, D);\n\n    // argument value\n    CPPAD_TESTVECTOR(Complex)     x( n * n );\n    for(i = 0; i < n * n; i++)\n        x[i] = Complex( double(2 * i) , double(i) );\n\n    // first derivative of the determinant\n    CPPAD_TESTVECTOR(Complex) H( n * n * n * n);\n    H = f.Hessian(x, 0);\n\n    /*\n    f(x)     = x[0] * x[3] - x[1] * x[2]\n    f'(x)    = ( x[3], -x[2], -x[1], x[0] )\n    */\n    Complex zero(0., 0.);\n    Complex one(1., 0.);\n    Complex Htrue[]  = {\n        zero, zero, zero,  one,\n        zero, zero, -one, zero,\n        zero, -one, zero, zero,\n            one, zero, zero, zero\n    };\n    for( i = 0; i < n*n*n*n; i++)\n        ok &= Htrue[i] == H[i];\n\n    return ok;\n\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/hes_times_dir.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin hes_times_dir.cpp}\n\nHessian Times Direction: Example and Test\n#########################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end hes_times_dir.cpp}\n*/\n// BEGIN C++\n// Example and test of computing the Hessian times a direction; i.e.,\n// given F : R^n -> R and a direction dx in R^n, we compute F''(x) * dx\n\n# include <cppad/cppad.hpp>\n\nnamespace { // put this function in the empty namespace\n    // F(x) = |x|^2 = x[0]^2 + ... + x[n-1]^2\n    template <class Type>\n    Type F(CPPAD_TESTVECTOR(Type) &x)\n    {   Type sum = 0;\n        size_t i = x.size();\n        while(i--)\n            sum += x[i] * x[i];\n        return sum;\n    }\n}\n\nbool HesTimesDir(void)\n{   bool ok = true;                   // initialize test result\n    size_t j;                         // a domain variable variable\n\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n = 5;\n    CPPAD_TESTVECTOR(AD<double>)  X(n);\n    for(j = 0; j < n; j++)\n        X[j] = AD<double>(j);\n\n    // declare independent variables and start recording\n    CppAD::Independent(X);\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) Y(m);\n    Y[0] = F(X);\n\n    // create f : X -> Y and stop recording\n    CppAD::ADFun<double> f(X, Y);\n\n    // choose a direction dx and compute dy(x) = F'(x) * dx\n    CPPAD_TESTVECTOR(double) dx(n);\n    CPPAD_TESTVECTOR(double) dy(m);\n    for(j = 0; j < n; j++)\n        dx[j] = double(n - j);\n    dy = f.Forward(1, dx);\n\n    // compute ddw = F''(x) * dx\n    CPPAD_TESTVECTOR(double) w(m);\n    CPPAD_TESTVECTOR(double) ddw(2 * n);\n    w[0] = 1.;\n    ddw  = f.Reverse(2, w);\n\n    // F(x)        = x[0]^2 + x[1]^2 + ... + x[n-1]^2\n    // F''(x)      = 2 * Identity_Matrix\n    // F''(x) * dx = 2 * dx\n    for(j = 0; j < n; j++)\n        ok &= NearEqual(ddw[j * 2 + 1], 2.*dx[j], eps99, eps99);\n\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/general/hessian.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin hessian.cpp}\n\nHessian: Example and Test\n#########################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end hessian.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\nnamespace { // ---------------------------------------------------------\n// define the template function HessianCases<Vector> in empty namespace\ntemplate <class Vector>\nbool HessianCases()\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    using CppAD::exp;\n    using CppAD::sin;\n    using CppAD::cos;\n\n    // domain space vector\n    size_t n = 2;\n    CPPAD_TESTVECTOR(AD<double>)  X(n);\n    X[0] = 1.;\n    X[1] = 2.;\n\n    // declare independent variables and starting recording\n    CppAD::Independent(X);\n\n    // a calculation between the domain and range values\n    AD<double> Square = X[0] * X[0];\n\n    // range space vector\n    size_t m = 3;\n    CPPAD_TESTVECTOR(AD<double>)  Y(m);\n    Y[0] = Square * exp( X[1] );\n    Y[1] = Square * sin( X[1] );\n    Y[2] = Square * cos( X[1] );\n\n    // create f: X -> Y and stop tape recording\n    CppAD::ADFun<double> f(X, Y);\n\n    // new value for the independent variable vector\n    Vector x(n);\n    x[0] = 2.;\n    x[1] = 1.;\n\n    // second derivative of y[1]\n    Vector hes( n * n );\n    hes = f.Hessian(x, 1);\n    /*\n    F_1       = x[0] * x[0] * sin(x[1])\n\n    F_1^{(1)} = [ 2 * x[0] * sin(x[1]) , x[0] * x[0] * cos(x[1]) ]\n\n    F_1^{(2)} = [        2 * sin(x[1]) ,      2 * x[0] * cos(x[1]) ]\n                [ 2 * x[0] * cos(x[1]) , - x[0] * x[0] * sin(x[1]) ]\n    */\n    ok &=  NearEqual(          2.*sin(x[1]), hes[0*n+0], eps99, eps99);\n    ok &=  NearEqual(     2.*x[0]*cos(x[1]), hes[0*n+1], eps99, eps99);\n    ok &=  NearEqual(     2.*x[0]*cos(x[1]), hes[1*n+0], eps99, eps99);\n    ok &=  NearEqual( - x[0]*x[0]*sin(x[1]), hes[1*n+1], eps99, eps99);\n\n    return ok;\n}\n} // End empty namespace\n# include <vector>\n# include <valarray>\nbool Hessian(void)\n{   bool ok = true;\n    // Run with Vector equal to three different cases\n    // all of which are Simple Vectors with elements of type double.\n    ok &= HessianCases< CppAD::vector  <double> >();\n    ok &= HessianCases< std::vector    <double> >();\n    ok &= HessianCases< std::valarray  <double> >();\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/general/independent.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\nWARNING: This file is used an an example by fun_construct.\n\n{xrst_begin independent.cpp}\n\n{xrst_comment ! NOTE the title states that this example is used two places !}\nIndependent and ADFun Constructor: Example and Test\n###################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end independent.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nnamespace { // --------------------------------------------------------\n// define the template function Test<ADVector>(void) in empty namespace\ntemplate <class ADVector>\nbool Test(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t  n  = 2;\n    ADVector X(n);  // ADVector is the template parameter in call to Test\n    X[0] = 0.;\n    X[1] = 1.;\n\n    // declare independent variables and start recording\n    // use the template parameter ADVector for the vector type\n    CppAD::Independent(X);\n\n    AD<double> a = X[0] + X[1];      // first AD operation\n    AD<double> b = X[0] * X[1];      // second AD operation\n\n    // range space vector\n    size_t m = 2;\n    ADVector Y(m);  // ADVector is the template paraemter in call to Test\n    Y[0] = a;\n    Y[1] = b;\n\n    // create f: X -> Y and stop tape recording\n    // use the template parameter ADVector for the vector type\n    CppAD::ADFun<double> f(X, Y);\n\n    // check value\n    ok &= NearEqual(Y[0] , 1.,  eps99 , eps99);\n    ok &= NearEqual(Y[1] , 0.,  eps99 , eps99);\n\n    // compute f(1, 2)\n    CPPAD_TESTVECTOR(double) x(n);\n    CPPAD_TESTVECTOR(double) y(m);\n    x[0] = 1.;\n    x[1] = 2.;\n    y    = f.Forward(0, x);\n    ok &= NearEqual(y[0] , 3.,  eps99 , eps99);\n    ok &= NearEqual(y[1] , 2.,  eps99 , eps99);\n\n    // compute partial of f w.r.t x[0] at (1, 2)\n    CPPAD_TESTVECTOR(double) dx(n);\n    CPPAD_TESTVECTOR(double) dy(m);\n    dx[0] = 1.;\n    dx[1] = 0.;\n    dy    = f.Forward(1, dx);\n    ok &= NearEqual(dy[0] ,   1.,  eps99 , eps99);\n    ok &= NearEqual(dy[1] , x[1],  eps99 , eps99);\n\n    // compute partial of f w.r.t x[1] at (1, 2)\n    dx[0] = 0.;\n    dx[1] = 1.;\n    dy    = f.Forward(1, dx);\n    ok &= NearEqual(dy[0] ,   1.,  eps99 , eps99);\n    ok &= NearEqual(dy[1] , x[0],  eps99 , eps99);\n\n    return ok;\n}\n} // End of empty namespace -------------------------------------------\n\n# include <vector>\n# include <valarray>\nbool Independent(void)\n{   bool ok = true;\n    typedef CppAD::AD<double> ADdouble;\n    // Run with ADVector equal to three different cases\n    // all of which are Simple Vectors with elements of type AD<double>.\n    ok &= Test< CppAD::vector  <ADdouble> >();\n    ok &= Test< std::vector    <ADdouble> >();\n    ok &= Test< std::valarray  <ADdouble> >();\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/integer.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin integer.cpp}\n\nConvert From AD to Integer: Example and Test\n############################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end integer.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n\nbool Integer(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::Integer;\n\n    // domain space vector\n    size_t n = 2;\n    CPPAD_TESTVECTOR(AD<double>) x(n);\n    x[0] = 3.5;\n    x[1] = 4.5;\n\n    // check integer before recording\n    ok &= (Integer(x[0]) == 3);\n    ok &= (Integer(x[1]) == 4);\n\n    // start recording\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(x);\n\n    // check integer during recording\n    ok &= (Integer(x[0]) == 3);\n    ok &= (Integer(x[1]) == 4);\n\n    // check integer for VecAD element\n    CppAD::VecAD<double> v(1);\n    AD<double> zero(0);\n    v[zero] = 2;\n    ok &= (Integer(v[zero]) == 2);\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) y(m);\n    y[0] = - x[1];\n\n    // create f: x -> y and stop recording\n    CppAD::ADFun<double> f(x, y);\n\n    // check integer after recording\n    ok &= (Integer(x[0]) ==  3.);\n    ok &= (Integer(x[1]) ==  4.);\n    ok &= (Integer(y[0]) == -4.);\n\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/general/interface2c.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin interface2c.cpp}\n\nInterfacing to C: Example and Test\n##################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end interface2c.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>  // CppAD utilities\n# include <cassert>        // assert macro\n\nnamespace { // Begin empty namespace\n/*\nCompute the value of a sum of Gaussians defined by a and evaluated at x\n    y = sum_{i=1}^n a[3*i] exp( (x - a[3*i+1])^2 / a[3*i+2])^2 )\nwhere the floating point type is a template parameter\n*/\ntemplate <class Float>\nFloat sumGauss(const Float &x, const CppAD::vector<Float> &a)\n{\n    // number of components in a\n    size_t na = a.size();\n\n    // number of Gaussians\n    size_t n = na / 3;\n\n    // check the restrictions on na\n    assert( na == n * 3 );\n\n    // declare temporaries used inside of loop\n    Float ex, arg;\n\n    // initialize sum\n    Float y = 0.;\n\n    // loop with respect to Gaussians\n    size_t i;\n    for(i = 0; i < n; i++)\n    {\n        arg =   (x - a[3*i+1]) / a[3*i+2];\n        ex  =   exp(-arg * arg);\n        y  +=   a[3*i] * ex;\n    }\n    return y;\n}\n/*\nCreate a C function interface that computes both\n    y = sum_{i=1}^n a[3*i] exp( (x - a[3*i+1])^2 / a[3*i+2])^2 )\nand its derivative with respect to the parameter vector a.\n*/\nextern \"C\"\nvoid sumGauss(float x, float a[], float *y, float dyda[], size_t na)\n{   // Note that any simple vector could replace CppAD::vector;\n    // for example, std::vector, std::valarray\n\n    // check the restrictions on na\n    assert( na % 3 == 0 );  // mod(na, 3) = 0\n\n    // use the shorthand ADfloat for the type CppAD::AD<float>\n    typedef CppAD::AD<float> ADfloat;\n\n    // vector for independent variables\n    CppAD::vector<ADfloat> A(na);      // used with template function above\n    CppAD::vector<float>   acopy(na);  // used for derivative calculations\n\n    // vector for the dependent variables (there is only one)\n    CppAD::vector<ADfloat> Y(1);\n\n    // copy the independent variables from C vector to CppAD vectors\n    size_t i;\n    for(i = 0; i < na; i++)\n        A[i] = acopy[i] = a[i];\n\n    // declare that A is the independent variable vector\n    CppAD::Independent(A);\n\n    // value of x as an ADfloat object\n    ADfloat X = x;\n\n    // Evaluate template version of sumGauss with ADfloat as the template\n    // parameter. Set the independent variable to the resulting value\n    Y[0] = sumGauss(X, A);\n\n    // create the AD function object F : A -> Y\n    CppAD::ADFun<float> F(A, Y);\n\n    // use Value to convert Y[0] to float and return y = F(a)\n    *y = CppAD::Value(Y[0]);\n\n    // evaluate the derivative F'(a)\n    CppAD::vector<float> J(na);\n    J = F.Jacobian(acopy);\n\n    // return the value of dyda = F'(a) as a C vector\n    for(i = 0; i < na; i++)\n        dyda[i] = J[i];\n\n    return;\n}\n/*\nLink CppAD::NearEqual so do not have to use namespace notation in Interface2C\n*/\nbool NearEqual(float x, float y, float r, float a)\n{   return CppAD::NearEqual(x, y, r, a);\n}\n\n} // End empty namespace\n\nbool Interface2C(void)\n{   // This routine is intentionally coded as if it were a C routine\n    // except for the fact that it uses the predefined type bool.\n    bool ok = true;\n\n    // declare variables\n    float x, a[6], y, dyda[6], tmp[6];\n    size_t na, i;\n\n    // number of parameters (3 for each Gaussian)\n    na = 6;\n\n    // number of Gaussians: n  = na / 3;\n\n    // value of x\n    x = 1.;\n\n    // value of the parameter vector a\n    for(i = 0; i < na; i++)\n        a[i] = (float) (i+1);\n\n    // evaluate function and derivative\n    sumGauss(x, a, &y, dyda, na);\n\n    // compare dyda to central difference approximation for deriative\n    for(i = 0; i < na; i++)\n    {   // local variables\n        float eps, ai, yp, ym, dy_da;\n\n        // We assume that the type float has at least 7 digits of\n        // precision, so we choose eps to be about pow(10., -7./2.).\n        eps  = (float) 3e-4;\n\n        // value of this component of a\n        ai    = a[i];\n\n        // evaluate F( a + eps * ei )\n        a[i]  = ai + eps;\n        sumGauss(x, a, &yp, tmp, na);\n\n        // evaluate F( a - eps * ei )\n        a[i]  = ai - eps;\n        sumGauss(x, a, &ym, tmp, na);\n\n        // evaluate central difference approximates for partial\n        dy_da = (yp - ym) / (2 * eps);\n\n        // restore this component of a\n        a[i]  = ai;\n\n        ok   &= NearEqual(dyda[i], dy_da, eps, eps);\n    }\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/general/interp_onetape.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin interp_onetape.cpp}\n{xrst_spell\n    retaping\n}\n\nInterpolation With Out Retaping: Example and Test\n#################################################\n\nSee Also\n********\n:ref:`interp_retape.cpp-name` , :ref:`atomic_four_bilinear.cpp-name`\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end interp_onetape.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n# include <cassert>\n# include <cmath>\n\nnamespace {\n    double ArgumentValue[] = {\n        .0 ,\n        .2 ,\n        .4 ,\n        .8 ,\n        1.\n    };\n    double FunctionValue[] = {\n        std::sin( ArgumentValue[0] ) ,\n        std::sin( ArgumentValue[1] ) ,\n        std::sin( ArgumentValue[2] ) ,\n        std::sin( ArgumentValue[3] ) ,\n        std::sin( ArgumentValue[4] )\n    };\n    size_t TableLength = 5;\n\n    size_t Index(const double &x)\n    {   // determine the index j such that x is between\n        // ArgumentValue[j] and ArgumentValue[j+1]\n        static size_t j = 0;\n        while ( x < ArgumentValue[j] && j > 0 )\n            j--;\n        while ( x > ArgumentValue[j+1] && j < TableLength - 2)\n            j++;\n        // assert conditions that must be true given logic above\n        assert( j >= 0 && j < TableLength - 1 );\n        return j;\n    }\n\n    double Argument(const double &x)\n    {   size_t j = Index(x);\n        return ArgumentValue[j];\n    }\n    double Function(const double &x)\n    {   size_t j = Index(x);\n        return FunctionValue[j];\n    }\n\n    double Slope(const double &x)\n    {   size_t j  = Index(x);\n        double dx = ArgumentValue[j+1] - ArgumentValue[j];\n        double dy = FunctionValue[j+1] - FunctionValue[j];\n        return dy / dx;\n    }\n    CPPAD_DISCRETE_FUNCTION(double, Argument)\n    CPPAD_DISCRETE_FUNCTION(double, Function)\n    CPPAD_DISCRETE_FUNCTION(double, Slope)\n}\n\n\nbool interp_onetape(void)\n{   bool ok = true;\n\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n = 1;\n    CPPAD_TESTVECTOR(AD<double>) ax(n);\n    ax[0] = .4 * ArgumentValue[1] + .6 * ArgumentValue[2];\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(ax);\n\n    // evaluate piecewise linear interpolant at ax[0]\n    AD<double> ax_grid   = Argument(ax[0]);\n    AD<double> af_grid   = Function(ax[0]);\n    AD<double> as_grid   = Slope(ax[0]);\n    AD<double> ay_linear = af_grid + (ax[0] - ax_grid) * as_grid;\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) ay(m);\n    ay[0] = ay_linear;\n\n    // create f: x -> ay and stop tape recording\n    CppAD::ADFun<double> f(ax, ay);\n\n    // vectors for arguments to the function object f\n    CPPAD_TESTVECTOR(double) x(n);   // argument values\n    CPPAD_TESTVECTOR(double) y(m);   // function values\n    CPPAD_TESTVECTOR(double) dx(n);  // differentials in x space\n    CPPAD_TESTVECTOR(double) dy(m);  // differentials in y space\n\n    // to check function value we use the fact that ax[0] is between\n    // ArgumentValue[1] and ArgumentValue[2]\n    x[0]          = Value(ax[0]);\n    double delta  = ArgumentValue[2] - ArgumentValue[1];\n    double check  = FunctionValue[2] * (x[0] - ArgumentValue[1]) / delta\n                        + FunctionValue[1] * (ArgumentValue[2] - x[0]) / delta;\n    ok  &= NearEqual(ay[0], check, eps99, eps99);\n\n    // evaluate f where x has different value\n    x[0]   = .7 * ArgumentValue[2] + .3 * ArgumentValue[3];\n    y      = f.Forward(0, x);\n\n    // check function value\n    delta  = ArgumentValue[3] - ArgumentValue[2];\n    check  = FunctionValue[3] * (x[0] - ArgumentValue[2]) / delta\n                        + FunctionValue[2] * (ArgumentValue[3] - x[0]) / delta;\n    ok  &= NearEqual(y[0], check, eps99, eps99);\n\n    // evaluate partials w.r.t. x[0]\n    dx[0] = 1.;\n    dy    = f.Forward(1, dx);\n\n    // check that the derivative is the slope\n    check = (FunctionValue[3] - FunctionValue[2])\n             / (ArgumentValue[3] - ArgumentValue[2]);\n    ok   &= NearEqual(dy[0], check, eps99, eps99);\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/interp_retape.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin interp_retape.cpp}\n{xrst_spell\n    retaping\n}\n\nInterpolation With Retaping: Example and Test\n#############################################\n\nSee Also\n********\n:ref:`interp_onetape.cpp-name`\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end interp_retape.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n# include <cassert>\n# include <cmath>\n\nnamespace {\n    double ArgumentValue[] = {\n        .0 ,\n        .2 ,\n        .4 ,\n        .8 ,\n        1.\n    };\n    double FunctionValue[] = {\n        std::sin( ArgumentValue[0] ) ,\n        std::sin( ArgumentValue[1] ) ,\n        std::sin( ArgumentValue[2] ) ,\n        std::sin( ArgumentValue[3] ) ,\n        std::sin( ArgumentValue[4] )\n    };\n    size_t TableLength = 5;\n\n    size_t Index(const CppAD::AD<double> &x)\n    {   // determine the index j such that x is between\n        // ArgumentValue[j] and ArgumentValue[j+1]\n        static size_t j = 0;\n        while ( x < ArgumentValue[j] && j > 0 )\n            j--;\n        while ( x > ArgumentValue[j+1] && j < TableLength - 2)\n            j++;\n        // assert conditions that must be true given logic above\n        assert( j >= 0 && j < TableLength - 1 );\n        return j;\n    }\n    double Argument(const CppAD::AD<double> &x)\n    {   size_t j = Index(x);\n        return ArgumentValue[j];\n    }\n    double Function(const CppAD::AD<double> &x)\n    {   size_t j = Index(x);\n        return FunctionValue[j];\n    }\n    double Slope(const CppAD::AD<double> &x)\n    {   size_t j  = Index(x);\n        double dx = ArgumentValue[j+1] - ArgumentValue[j];\n        double dy = FunctionValue[j+1] - FunctionValue[j];\n        return dy / dx;\n    }\n}\n\nbool interp_retape(void)\n{   bool ok = true;\n\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n = 1;\n    CPPAD_TESTVECTOR(AD<double>) X(n);\n\n    // loop over argument values\n    size_t k;\n    for(k = 0; k < TableLength - 1; k++)\n    {\n        X[0] = .4 * ArgumentValue[k] + .6 * ArgumentValue[k+1];\n\n        // declare independent variables and start tape recording\n        // (use a different tape for each argument value)\n        CppAD::Independent(X);\n\n        // evaluate piecewise linear interpolant at X[0]\n        AD<double> A = Argument(X[0]);\n        AD<double> F = Function(X[0]);\n        AD<double> S = Slope(X[0]);\n        AD<double> I = F + (X[0] - A) * S;\n\n        // range space vector\n        size_t m = 1;\n        CPPAD_TESTVECTOR(AD<double>) Y(m);\n        Y[0] = I;\n\n        // create f: X -> Y and stop tape recording\n        CppAD::ADFun<double> f(X, Y);\n\n        // vectors for arguments to the function object f\n        CPPAD_TESTVECTOR(double) x(n);   // argument values\n        CPPAD_TESTVECTOR(double) y(m);   // function values\n        CPPAD_TESTVECTOR(double) dx(n);  // differentials in x space\n        CPPAD_TESTVECTOR(double) dy(m);  // differentials in y space\n\n        // to check function value we use the fact that X[0] is between\n        // ArgumentValue[k] and ArgumentValue[k+1]\n        double delta, check;\n        x[0]   = Value(X[0]);\n        delta  = ArgumentValue[k+1] - ArgumentValue[k];\n        check  = FunctionValue[k+1] * (x[0]-ArgumentValue[k]) / delta\n                         + FunctionValue[k] * (ArgumentValue[k+1]-x[0]) / delta;\n        ok    &= NearEqual(Y[0], check, eps99, eps99);\n\n        // evaluate partials w.r.t. x[0]\n        dx[0] = 1.;\n        dy    = f.Forward(1, dx);\n\n        // check that the derivative is the slope\n        check = (FunctionValue[k+1] - FunctionValue[k])\n                  / (ArgumentValue[k+1] - ArgumentValue[k]);\n        ok   &= NearEqual(dy[0], check, eps99, eps99);\n    }\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/jac_lu_det.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin jac_lu_det.cpp}\n\nGradient of Determinant Using Lu Factorization: Example and Test\n################################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end jac_lu_det.cpp}\n*/\n// BEGIN C++\n// Complex examples should suppress conversion warnings\n# include <cppad/wno_conversion.hpp>\n\n# include <cppad/cppad.hpp>\n# include <cppad/speed/det_by_lu.hpp>\n\n// The AD complex case is used by this example so must\n// define a specializatgion of LeqZero,AbsGeq for the AD<Complex> case\nnamespace CppAD {\n    CPPAD_BOOL_BINARY( std::complex<double> ,  AbsGeq   )\n    CPPAD_BOOL_UNARY(  std::complex<double> ,  LeqZero )\n}\n\nbool JacLuDet(void)\n{   bool ok = true;\n    using namespace CppAD;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    typedef std::complex<double> Complex;\n    typedef AD<Complex>          ADComplex;\n\n    size_t n = 2;\n\n    // object for computing determinants\n    det_by_lu<ADComplex> Det(n);\n\n    // independent and dependent variable vectors\n    CPPAD_TESTVECTOR(ADComplex)  X(n * n);\n    CPPAD_TESTVECTOR(ADComplex)  D(1);\n\n    // value of the independent variable\n    size_t i;\n    for(i = 0; i < n * n; i++)\n        X[i] = Complex( double(i), -double(i) );\n\n    // set the independent variables\n    Independent(X);\n\n    // compute the determinant\n    D[0]  = Det(X);\n\n    // create the function object\n    ADFun<Complex> f(X, D);\n\n    // argument value\n    CPPAD_TESTVECTOR(Complex)     x( n * n );\n    for(i = 0; i < n * n; i++)\n        x[i] = Complex( double(2 * i) , double(i) );\n\n    // first derivative of the determinant\n    CPPAD_TESTVECTOR(Complex) J( n * n );\n    J = f.Jacobian(x);\n\n    /*\n    f(x)     = x[0] * x[3] - x[1] * x[2]\n    */\n    Complex Jtrue[]  = { x[3], -x[2], -x[1], x[0] };\n    for( i = 0; i < n*n; i++)\n        ok &= NearEqual( Jtrue[i], J[i], eps99 , eps99 );\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/jac_minor_det.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin jac_minor_det.cpp}\n\nGradient of Determinant Using Expansion by Minors: Example and Test\n###################################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end jac_minor_det.cpp}\n*/\n// BEGIN C++\n// Complex examples should suppress conversion warnings\n# include <cppad/wno_conversion.hpp>\n\n# include <cppad/cppad.hpp>\n# include <cppad/speed/det_by_minor.hpp>\n# include <complex>\n\n\ntypedef std::complex<double>     Complex;\ntypedef CppAD::AD<Complex>       ADComplex;\ntypedef CPPAD_TESTVECTOR(ADComplex)   ADVector;\n\n// ----------------------------------------------------------------------------\n\nbool JacMinorDet(void)\n{   bool ok = true;\n\n    using namespace CppAD;\n\n    size_t n = 2;\n\n    // object for computing determinant\n    det_by_minor<ADComplex> Det(n);\n\n    // independent and dependent variable vectors\n    CPPAD_TESTVECTOR(ADComplex)  X(n * n);\n    CPPAD_TESTVECTOR(ADComplex)  D(1);\n\n    // value of the independent variable\n    size_t i;\n    for(i = 0; i < n * n; i++)\n        X[i] = Complex( double(i), -double(i) );\n\n    // set the independent variables\n    Independent(X);\n\n    // comupute the determinant\n    D[0] = Det(X);\n\n    // create the function object\n    ADFun<Complex> f(X, D);\n\n    // argument value\n    CPPAD_TESTVECTOR(Complex)     x( n * n );\n    for(i = 0; i < n * n; i++)\n        x[i] = Complex( double(2 * i) , double(i) );\n\n    // first derivative of the determinant\n    CPPAD_TESTVECTOR(Complex) J( n * n );\n    J = f.Jacobian(x);\n\n    /*\n    f(x)     = x[0] * x[3] - x[1] * x[2]\n    f'(x)    = ( x[3], -x[2], -x[1], x[0] )\n    */\n    Complex Jtrue[] = { x[3], -x[2], -x[1], x[0] };\n    for(i = 0; i < n * n; i++)\n        ok &= Jtrue[i] == J[i];\n\n    return ok;\n\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/jacobian.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin jacobian.cpp}\n\nJacobian: Example and Test\n##########################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end jacobian.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\nnamespace { // ---------------------------------------------------------\n// define the template function JacobianCases<Vector> in empty namespace\ntemplate <class Vector>\nbool JacobianCases()\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    using CppAD::exp;\n    using CppAD::sin;\n    using CppAD::cos;\n\n    // domain space vector\n    size_t n = 2;\n    CPPAD_TESTVECTOR(AD<double>)  X(n);\n    X[0] = 1.;\n    X[1] = 2.;\n\n    // declare independent variables and starting recording\n    CppAD::Independent(X);\n\n    // a calculation between the domain and range values\n    AD<double> Square = X[0] * X[0];\n\n    // range space vector\n    size_t m = 3;\n    CPPAD_TESTVECTOR(AD<double>)  Y(m);\n    Y[0] = Square * exp( X[1] );\n    Y[1] = Square * sin( X[1] );\n    Y[2] = Square * cos( X[1] );\n\n    // create f: X -> Y and stop tape recording\n    CppAD::ADFun<double> f(X, Y);\n\n    // new value for the independent variable vector\n    Vector x(n);\n    x[0] = 2.;\n    x[1] = 1.;\n\n    // compute the derivative at this x\n    Vector jac( m * n );\n    jac = f.Jacobian(x);\n\n    /*\n    F'(x) = [ 2 * x[0] * exp(x[1]) ,  x[0] * x[0] * exp(x[1]) ]\n            [ 2 * x[0] * sin(x[1]) ,  x[0] * x[0] * cos(x[1]) ]\n            [ 2 * x[0] * cos(x[1]) , -x[0] * x[0] * sin(x[i]) ]\n    */\n    ok &=  NearEqual( 2.*x[0]*exp(x[1]), jac[0*n+0], eps99, eps99);\n    ok &=  NearEqual( 2.*x[0]*sin(x[1]), jac[1*n+0], eps99, eps99);\n    ok &=  NearEqual( 2.*x[0]*cos(x[1]), jac[2*n+0], eps99, eps99);\n\n    ok &=  NearEqual( x[0] * x[0] *exp(x[1]), jac[0*n+1], eps99, eps99);\n    ok &=  NearEqual( x[0] * x[0] *cos(x[1]), jac[1*n+1], eps99, eps99);\n    ok &=  NearEqual(-x[0] * x[0] *sin(x[1]), jac[2*n+1], eps99, eps99);\n\n    return ok;\n}\n} // End empty namespace\n# include <vector>\n# include <valarray>\nbool Jacobian(void)\n{   bool ok = true;\n    // Run with Vector equal to three different cases\n    // all of which are Simple Vectors with elements of type double.\n    ok &= JacobianCases< CppAD::vector  <double> >();\n    ok &= JacobianCases< std::vector    <double> >();\n    ok &= JacobianCases< std::valarray  <double> >();\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/general/log.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin log.cpp}\n\nThe AD log Function: Example and Test\n#####################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end log.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n\nbool log(void)\n{   bool ok = true;\n\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n  = 1;\n    double x0 = 0.5;\n    CPPAD_TESTVECTOR(AD<double>) x(n);\n    x[0]      = x0;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(x);\n\n    // a temporary value\n    AD<double> exp_of_x0 = CppAD::exp(x[0]);\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) y(m);\n    y[0] = CppAD::log(exp_of_x0);\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(x, y);\n\n    // check value\n    ok &= NearEqual(y[0] , x0, eps99, eps99);\n\n    // forward computation of first partial w.r.t. x[0]\n    CPPAD_TESTVECTOR(double) dx(n);\n    CPPAD_TESTVECTOR(double) dy(m);\n    dx[0] = 1.;\n    dy    = f.Forward(1, dx);\n    ok   &= NearEqual(dy[0], 1., eps99, eps99);\n\n    // reverse computation of derivative of y[0]\n    CPPAD_TESTVECTOR(double)  w(m);\n    CPPAD_TESTVECTOR(double) dw(n);\n    w[0]  = 1.;\n    dw    = f.Reverse(1, w);\n    ok   &= NearEqual(dw[0], 1., eps99, eps99);\n\n    // use a VecAD<Base>::reference object with log\n    CppAD::VecAD<double> v(1);\n    AD<double> zero(0);\n    v[zero]           = exp_of_x0;\n    AD<double> result = CppAD::log(v[zero]);\n    ok   &= NearEqual(result, x0, eps99, eps99);\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/log10.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin log10.cpp}\n\nThe AD log10 Function: Example and Test\n#######################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end log10.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n\nbool log10(void)\n{   bool ok = true;\n\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n  = 1;\n    double x0 = 0.5;\n    CPPAD_TESTVECTOR(AD<double>) x(n);\n    x[0]      = x0;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(x);\n\n    // ten raised to the x0 power\n    AD<double> ten = 10.;\n    AD<double> pow_10_x0 = CppAD::pow(ten, x[0]);\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) y(m);\n    y[0] = CppAD::log10(pow_10_x0);\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(x, y);\n\n    // check value\n    ok &= NearEqual(y[0] , x0, eps99, eps99);\n\n    // forward computation of first partial w.r.t. x[0]\n    CPPAD_TESTVECTOR(double) dx(n);\n    CPPAD_TESTVECTOR(double) dy(m);\n    dx[0] = 1.;\n    dy    = f.Forward(1, dx);\n    ok   &= NearEqual(dy[0], 1., eps99, eps99);\n\n    // reverse computation of derivative of y[0]\n    CPPAD_TESTVECTOR(double)  w(m);\n    CPPAD_TESTVECTOR(double) dw(n);\n    w[0]  = 1.;\n    dw    = f.Reverse(1, w);\n    ok   &= NearEqual(dw[0], 1., eps99, eps99);\n\n    // use a VecAD<Base>::reference object with log10\n    CppAD::VecAD<double> v(1);\n    AD<double> zero(0);\n    v[zero]           = pow_10_x0;\n    AD<double> result = CppAD::log10(v[zero]);\n    ok   &= NearEqual(result, x0, eps99, eps99);\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/log1p.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin log1p.cpp}\n\nThe AD log1p Function: Example and Test\n#######################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end log1p.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n\nbool log1p(void)\n{   bool ok = true;\n\n    using CppAD::AD;\n    using CppAD::NearEqual;\n\n    // 10 times machine epsilon\n    double eps = 10. * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n  = 1;\n    double x0 = 0.5;\n    CPPAD_TESTVECTOR(AD<double>) x(n);\n    x[0]      = x0;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(x);\n\n    // a temporary value\n    AD<double> expm1_of_x0 = CppAD::expm1(x[0]);\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) y(m);\n    y[0] = CppAD::log1p(expm1_of_x0);\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(x, y);\n\n    // check value\n    ok &= NearEqual(y[0] , x0,  eps, eps);\n\n    // forward computation of first partial w.r.t. x[0]\n    CPPAD_TESTVECTOR(double) dx(n);\n    CPPAD_TESTVECTOR(double) dy(m);\n    dx[0] = 1.;\n    dy    = f.Forward(1, dx);\n    ok   &= NearEqual(dy[0], 1., eps, eps);\n\n    // reverse computation of derivative of y[0]\n    CPPAD_TESTVECTOR(double)  w(m);\n    CPPAD_TESTVECTOR(double) dw(n);\n    w[0]  = 1.;\n    dw    = f.Reverse(1, w);\n    ok   &= NearEqual(dw[0], 1., eps, eps);\n\n    // use a VecAD<Base>::reference object with log1p\n    CppAD::VecAD<double> v(1);\n    AD<double> zero(0);\n    v[zero] = expm1_of_x0;\n    AD<double> result = CppAD::log1p(v[zero]);\n    ok     &= NearEqual(result, x0, eps, eps);\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/lu_ratio.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin lu_ratio.cpp app}\n\nLuRatio: Example and Test\n#########################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end lu_ratio.cpp}\n*/\n\n// BEGIN C++\n# include <cstdlib>               // for rand function\n# include <cassert>\n# include <cppad/cppad.hpp>\n\nnamespace { // Begin empty namespace\n\nCppAD::ADFun<double> *NewFactor(\n    size_t                           n ,\n    const CPPAD_TESTVECTOR(double) &x ,\n    bool                           &ok ,\n    CPPAD_TESTVECTOR(size_t)      &ip ,\n    CPPAD_TESTVECTOR(size_t)      &jp )\n{   using CppAD::AD;\n    using CppAD::ADFun;\n    size_t i, j, k;\n\n    // values for independent and dependent variables\n    CPPAD_TESTVECTOR(AD<double>) Y(n*n+1), X(n*n);\n\n    // values for the LU factor\n    CPPAD_TESTVECTOR(AD<double>) LU(n*n);\n\n    // record the LU factorization corresponding to this value of x\n    AD<double> Ratio;\n    for(k = 0; k < n*n; k++)\n        X[k] = x[k];\n    Independent(X);\n    for(k = 0; k < n*n; k++)\n        LU[k] = X[k];\n    CppAD::LuRatio(ip, jp, LU, Ratio);\n    for(k = 0; k < n*n; k++)\n        Y[k] = LU[k];\n    Y[n*n] = Ratio;\n\n    // use a function pointer so can return ADFun object\n    ADFun<double> *FunPtr = new ADFun<double>(X, Y);\n\n    // check value of ratio during recording\n    ok &= (Ratio == 1.);\n\n    // check that ip and jp are permutations of the indices 0, ... , n-1\n    for(i = 0; i < n; i++)\n    {   ok &= (ip[i] < n);\n        ok &= (jp[i] < n);\n        for(j = 0; j < n; j++)\n        {   if( i != j )\n            {   ok &= (ip[i] != ip[j]);\n                ok &= (jp[i] != jp[j]);\n            }\n        }\n    }\n    return FunPtr;\n}\nbool CheckLuFactor(\n    size_t                           n  ,\n    const CPPAD_TESTVECTOR(double) &x  ,\n    const CPPAD_TESTVECTOR(double) &y  ,\n    const CPPAD_TESTVECTOR(size_t) &ip ,\n    const CPPAD_TESTVECTOR(size_t) &jp )\n{   bool     ok = true;\n\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    double  sum;                          // element of L * U\n    double  pij;                          // element of permuted x\n    size_t  i, j, k;                      // temporary indices\n\n    // L and U factors\n    CPPAD_TESTVECTOR(double)  L(n*n), U(n*n);\n\n    // Extract L from LU factorization\n    for(i = 0; i < n; i++)\n    {   // elements along and below the diagonal\n        for(j = 0; j <= i; j++)\n            L[i * n + j] = y[ ip[i] * n + jp[j] ];\n        // elements above the diagonal\n        for(j = i+1; j < n; j++)\n            L[i * n + j] = 0.;\n    }\n\n    // Extract U from LU factorization\n    for(i = 0; i < n; i++)\n    {   // elements below the diagonal\n        for(j = 0; j < i; j++)\n            U[i * n + j] = 0.;\n        // elements along the diagonal\n        U[i * n + i] = 1.;\n        // elements above the diagonal\n        for(j = i+1; j < n; j++)\n            U[i * n + j] = y[ ip[i] * n + jp[j] ];\n    }\n\n    // Compute L * U\n    for(i = 0; i < n; i++)\n    {   for(j = 0; j < n; j++)\n        {   // compute element (i,j) entry in L * U\n            sum = 0.;\n            for(k = 0; k < n; k++)\n                sum += L[i * n + k] * U[k * n + j];\n            // element (i,j) in permuted version of A\n            pij  = x[ ip[i] * n + jp[j] ];\n            // compare\n            ok  &= NearEqual(pij, sum, eps99, eps99);\n        }\n    }\n    return ok;\n}\n\n} // end Empty namespace\n\nbool LuRatio(void)\n{   bool  ok = true;\n\n    size_t  n = 2; // number rows in A\n    double  ratio;\n\n    // values for independent and dependent variables\n    CPPAD_TESTVECTOR(double)  x(n*n), y(n*n+1);\n\n    // pivot vectors\n    CPPAD_TESTVECTOR(size_t) ip(n), jp(n);\n\n    // set x equal to the identity matrix\n    x[0] = 1.; x[1] = 0;\n    x[2] = 0.; x[3] = 1.;\n\n    // create a function object corresponding to this value of x\n    CppAD::ADFun<double> *FunPtr = NewFactor(n, x, ok, ip, jp);\n\n    // use function object to factor matrix\n    y     = FunPtr->Forward(0, x);\n    ratio = y[n*n];\n    ok   &= (ratio == 1.);\n    ok   &= CheckLuFactor(n, x, y, ip, jp);\n\n    // set x so that the pivot ratio will be infinite\n    x[0] = 0. ; x[1] = 1.;\n    x[2] = 1. ; x[3] = 0.;\n\n    // try to use old function pointer to factor matrix\n    y     = FunPtr->Forward(0, x);\n    ratio = y[n*n];\n\n    // check to see if we need to refactor matrix\n    ok &= (ratio > 10.);\n    if( ratio > 10. )\n    {   delete FunPtr; // to avoid a memory leak\n        FunPtr = NewFactor(n, x, ok, ip, jp);\n    }\n\n    //  now we can use the function object to factor matrix\n    y     = FunPtr->Forward(0, x);\n    ratio = y[n*n];\n    ok    &= (ratio == 1.);\n    ok    &= CheckLuFactor(n, x, y, ip, jp);\n\n    delete FunPtr;  // avoid memory leak\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/general/lu_vec_ad.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin lu_vec_ad.cpp}\n{xrst_spell\n    logdet\n    rhs\n    signdet\n}\n\nLu Factor and Solve with Recorded Pivoting\n##########################################\n\nSyntax\n******\n| ``int lu_vec_ad`` (\n| |tab| ``size_t`` *n* ,\n| |tab| ``size_t`` *m* ,\n| |tab| ``VecAD`` < *double* > & *Matrix* ,\n| |tab| ``VecAD`` < *double* > & *Rhs* ,\n| |tab| ``VecAD`` < *double* > & *Result* ,\n| |tab| *AD* < ``double`` > & ``logdet`` )\n\nPurpose\n*******\nSolves the linear equation\n\n.. math::\n\n    Matrix * Result = Rhs\n\nwhere *Matrix* is an :math:`n \\times n` matrix,\n*Rhs* is an :math:`n x m` matrix, and\n*Result* is an :math:`n x m` matrix.\n\nThe routine :ref:`LuSolve-name` uses an arbitrary vector type,\ninstead of :ref:`VecAD-name` ,\nto hold its elements.\nThe pivoting operations for a ``ADFun`` object\ncorresponding to an ``lu_vec_ad`` solution\nwill change to be optimal for the matrix being factored.\n\nIt is often the case that\n``LuSolve`` is faster than ``lu_vec_ad`` when ``LuSolve``\nuses a simple vector class with\n:ref:`elements of type double<SimpleVector@Elements of Specified Type>` ,\nbut the corresponding :ref:`ADFun-name` objects have a fixed\nset of pivoting operations.\n\nStorage Convention\n******************\nThe matrices stored in row major order.\nTo be specific, if :math:`A` contains the vector storage for an\n:math:`n x m` matrix,\n:math:`i` is between zero and :math:`n-1`,\nand :math:`j` is between zero and :math:`m-1`,\n\n.. math::\n\n    A_{i,j} = A[ i * m + j ]\n\n(The length of :math:`A` must be equal to :math:`n * m`.)\n\nn\n*\nis the number of rows in\n*Matrix* ,\n*Rhs* ,\nand *Result* .\n\nm\n*\nis the number of columns in\n*Rhs*\nand *Result* .\nIt is ok for *m* to be zero which is reasonable when\nyou are only interested in the determinant of *Matrix* .\n\nMatrix\n******\nOn input, this is an\n:math:`n \\times n` matrix containing the variable coefficients for\nthe equation we wish to solve.\nOn output, the elements of *Matrix* have been overwritten\nand are not specified.\n\nRhs\n***\nOn input, this is an\n:math:`n \\times m` matrix containing the right hand side\nfor the equation we wish to solve.\nOn output, the elements of *Rhs* have been overwritten\nand are not specified.\nIf *m* is zero, *Rhs* is not used.\n\nResult\n******\nOn input, this is an\n:math:`n \\times m` matrix and the value of its elements do not matter.\nOn output, the elements of *Rhs* contain the solution\nof the equation we wish to solve\n(unless the value returned by ``lu_vec_ad`` is equal to zero).\nIf *m* is zero, *Result* is not used.\n\nlogdet\n******\nOn input, the value of *logdet* does not matter.\nOn output, it has been set to the\nlog of the determinant of *Matrix* (but not quite).\nTo be more specific,\nif *signdet* is the value returned by ``lu_vec_ad`` ,\nthe determinant of *Matrix* is given by the formula\n\n.. math::\n\n    det = signdet \\exp( logdet )\n\nThis enables ``lu_vec_ad`` to use logs of absolute values.\n\nExample\n*******\n{xrst_toc_hidden\n    example/general/lu_vec_ad_ok.cpp\n}\nThe file\n:ref:`lu_vec_ad_ok.cpp-name`\ncontains an example and test of ``lu_vec_ad`` .\n\n{xrst_end lu_vec_ad.cpp}\n------------------------------------------------------------------------------\n*/\n\n# include \"lu_vec_ad.hpp\"\n# include <cppad/cppad.hpp>\n\n// BEGIN CppAD namespace\nnamespace CppAD {\n\nAD<double> lu_vec_ad(\n    size_t                           n,\n    size_t                           m,\n    CppAD::VecAD<double>             &Matrix,\n    CppAD::VecAD<double>             &Rhs,\n    CppAD::VecAD<double>             &Result,\n    CppAD::AD<double>                &logdet)\n{\n    using namespace CppAD;\n    typedef AD<double> Type;\n\n    // temporary index\n    Type index;\n    Type jndex;\n\n    // index and maximum element value\n    Type   imax;\n    Type   jmax;\n    Type   itmp;\n    Type   jtmp;\n    Type   emax;\n\n    // some temporary indices\n    Type i;\n    Type j;\n    Type k;\n\n    // count pivots\n    Type p;\n\n    // sign of the determinant\n    Type  signdet;\n\n    // temporary values\n    Type  etmp;\n    Type  diff;\n\n    // pivot element\n    Type  pivot;\n\n    // singular matrix\n    Type  singular = 0.;\n\n    // some constants\n    Type M(m);\n    Type N(n);\n    Type One(1);\n    Type Zero(0);\n\n    // pivot row and column order in the matrix\n    VecAD<double> ip(n);\n    VecAD<double> jp(n);\n\n    // -------------------------------------------------------\n\n    // initialize row and column order in matrix not yet pivoted\n    for(i = 0; i < N; i += 1.)\n    {   ip[i] = i;\n        jp[i] = i;\n    }\n\n    // initialize the log determinant\n    logdet  = 0.;\n    signdet = 1;\n\n    for(p = 0; p < N; p += 1.)\n    {\n        // determine row and column corresponding to element of\n        // maximum absolute value in remaining part of Matrix\n        imax = N;\n        jmax = N;\n        emax = 0.;\n        for(i = p; i < N; i += 1.)\n        {   itmp = ip[i] * N;\n            for(j = p; j < N; j += 1.)\n            {   assert(\n                    (ip[i] < N) && (jp[j] < N)\n                );\n                index = itmp + jp[j];\n                etmp  = Matrix[ index ];\n\n                // compute absolute value of element\n                etmp = fabs(etmp);\n\n                // update maximum absolute value so far\n                emax = CondExpGe(etmp, emax, etmp, emax);\n                imax = CondExpGe(etmp, emax,    i, imax);\n                jmax = CondExpGe(etmp, emax,    j, jmax);\n            }\n        }\n        assert( (imax < N) && (jmax < N) );\n\n\n        // switch rows so max absolute element is in row p\n        index    = ip[p];\n        ip[p]    = ip[imax];\n        ip[imax] = index;\n\n        // if imax != p, switch sign of determinant\n        signdet  = CondExpEq(imax, p, signdet,  -signdet);\n\n        // switch columns so max absolute element is in column p\n        jndex    = jp[p];\n        jp[p]    = jp[jmax];\n        jp[jmax] = jndex;\n\n        // if imax != p, switch sign of determinant\n        signdet  = CondExpEq(jmax, p, signdet,  -signdet);\n\n        // pivot using the max absolute element\n        itmp    = ip[p] * N;\n        index   = itmp + jp[p];\n        pivot   = Matrix[ index ];\n\n        // update the singular matrix flag\n        singular = CondExpEq(pivot, Zero, One, singular);\n\n        // update the log of absolute determinant and its sign\n        etmp     = fabs(pivot);\n        logdet   = logdet + log( etmp );\n        signdet  = CondExpGe(pivot, Zero, signdet, - signdet);\n\n        /*\n        Reduce by the elementary transformations that maps\n        Matrix( ip[p], jp[p] ) to one and Matrix( ip[i], jp[p] )\n        to zero for i = p + 1., ... , n-1\n        */\n\n        // divide row number ip[p] by pivot element\n        for(j = p + 1.; j < N; j += 1.)\n        {\n            index           = itmp + jp[j];\n            Matrix[ index ] = Matrix[ index ] / pivot;\n        }\n\n        // not used anymore so no need to set to 1\n        // Matrix[ ip[p] * N + jp[p] ] = Type(1);\n\n        // divide corresponding row of right hand side by pivot element\n        itmp = ip[p] * M;\n        for(k = 0; k < M; k += 1.)\n        {\n            index = itmp + k;\n            Rhs[ index ] = Rhs[ index ] / pivot;\n        }\n\n        for(i = p + 1.; i < N; i += 1. )\n        {   itmp  = ip[i] * N;\n            jtmp  = ip[p] * N;\n\n            index = itmp + jp[p];\n            etmp  = Matrix[ index ];\n\n            for(j = p + 1.; j < N; j += 1.)\n            {   index = itmp + jp[j];\n                jndex = jtmp + jp[j];\n                Matrix[ index ] = Matrix[ index ]\n                            - etmp * Matrix[ jndex ];\n            }\n\n            itmp = ip[i] * M;\n            jtmp = ip[p] * M;\n            for(k = 0; k < M; k += 1.)\n            {\n                index = itmp + k;\n                jndex = jtmp + k;\n                Rhs[ index ] = Rhs[ index ]\n                                      - etmp * Rhs[ jndex ];\n            }\n\n            // not used any more so no need to set to zero\n            // Matrix[ ip[i] * N + jp[p] ] = 0.;\n        }\n\n    }\n\n    // loop over equations\n    for(k = 0; k < M; k += 1.)\n    {   // loop over variables\n        p = N;\n        while( p > 0. )\n        {   p -= 1.;\n            index = ip[p] * M + k;\n            jndex = jp[p] * M + k;\n            etmp            = Rhs[ index ];\n            Result[ jndex ] = etmp;\n            for(i = 0; i < p; i += 1. )\n            {\n                index = ip[i] * M + k;\n                jndex = ip[i] * N + jp[p];\n                Rhs[ index ] = Rhs[ index ]\n                                      - etmp * Matrix[ jndex ];\n            }\n        }\n    }\n\n    // make sure return zero in the singular case\n    return (1. - singular) * signdet;\n}\n\n} // END CppAD namespace\n"
  },
  {
    "path": "example/general/lu_vec_ad.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_GENERAL_LU_VEC_AD_HPP\n# define CPPAD_EXAMPLE_GENERAL_LU_VEC_AD_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/cppad.hpp>\n\nnamespace CppAD {\n    extern CppAD::AD<double> lu_vec_ad(\n        size_t                           n,\n        size_t                           m,\n        CppAD::VecAD<double>             &Matrix,\n        CppAD::VecAD<double>             &Rhs,\n        CppAD::VecAD<double>             &Result,\n        CppAD::AD<double>                &logdet\n    );\n}\n\n# endif\n"
  },
  {
    "path": "example/general/lu_vec_ad_ok.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin lu_vec_ad_ok.cpp}\n\nLu Factor and Solve With Recorded Pivoting: Example and Test\n############################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end lu_vec_ad_ok.cpp}\n*/\n\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n# include \"lu_vec_ad.hpp\"\n# include <cppad/speed/det_by_minor.hpp>\n\nbool lu_vec_ad_ok(void)\n{   bool  ok = true;\n\n    using namespace CppAD;\n    typedef AD<double> ADdouble;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    size_t              n = 3;\n    size_t              m = 2;\n    double a1[] = {\n        3., 0., 0., // (1,1) is first  pivot\n        1., 2., 1., // (2,2) is second pivot\n        1., 0., .5  // (3,3) is third  pivot\n    };\n    double a2[] = {\n        1., 2., 1., // (1,2) is second pivot\n        3., 0., 0., // (2,1) is first  pivot\n        1., 0., .5  // (3,3) is third  pivot\n    };\n    double rhs[] = {\n        1., 3.,\n        2., 2.,\n        3., 1.\n    };\n\n    VecAD<double>       Copy    (n * n);\n    VecAD<double>       Rhs     (n * m);\n    VecAD<double>       Result  (n * m);\n    ADdouble            logdet;\n    ADdouble            signdet;\n\n    // routine for checking determinants using expansion by minors\n    det_by_minor<ADdouble> Det(n);\n\n    // matrix we are computing the determinant of\n    CPPAD_TESTVECTOR(ADdouble) A(n * n);\n\n    // dependent variable values\n    CPPAD_TESTVECTOR(ADdouble) Y(1 + n * m);\n\n    size_t  i;\n    size_t  j;\n    size_t  k;\n\n    // Original matrix\n    for(i = 0; i < n * n; i++)\n        A[i] = a1[i];\n\n    // right hand side\n    for(j = 0; j < n; j++)\n        for(k = 0; k < m; k++)\n            Rhs[ j * m + k ] = rhs[ j * m + k ];\n\n    // Declare independent variables\n    Independent(A);\n\n    // Copy the matrix\n    ADdouble index(0);\n    for(i = 0; i < n*n; i++)\n    {   Copy[index] = A[i];\n        index += 1.;\n    }\n\n    // Solve the equation\n    signdet = lu_vec_ad(n, m, Copy, Rhs, Result, logdet);\n\n    // Result is the first n * m dependent variables\n    index = 0.;\n    for(i = 0; i < n * m; i++)\n    {   Y[i] = Result[index];\n        index += 1.;\n    }\n\n    // Determinant is last component of the solution\n    Y[ n * m ] = signdet * exp( logdet );\n\n    // construct f: A -> Y\n    ADFun<double> f(A, Y);\n\n    // check determinant using minors routine\n    ADdouble determinant = Det( A );\n    ok &= NearEqual(Y[n * m], determinant, eps99, eps99);\n\n\n    // Check solution of Rhs = A * Result\n    double sum;\n    for(k = 0; k < m; k++)\n    {   for(i = 0; i < n; i++)\n        {   sum = 0.;\n            for(j = 0; j < n; j++)\n                sum += a1[i * n + j] * Value( Y[j * m + k] );\n            ok &= NearEqual( rhs[i * m + k], sum, eps99, eps99);\n        }\n    }\n\n    CPPAD_TESTVECTOR(double) y2(1 + n * m);\n    CPPAD_TESTVECTOR(double) A2(n * n);\n    for(i = 0; i < n * n; i++)\n        A[i] = A2[i] = a2[i];\n\n\n    y2          = f.Forward(0, A2);\n    determinant = Det(A);\n    ok &= NearEqual(y2[ n * m], Value(determinant), eps99, eps99);\n\n    // Check solution of Rhs = A2 * Result\n    for(k = 0; k < m; k++)\n    {   for(i = 0; i < n; i++)\n        {   sum = 0.;\n            for(j = 0; j < n; j++)\n                sum += a2[i * n + j] * y2[j * m + k];\n            ok &= NearEqual( rhs[i * m + k], sum, eps99, eps99);\n        }\n    }\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/mul.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin mul.cpp}\n\nAD Binary Multiplication: Example and Test\n##########################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end mul.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nbool Mul(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n  = 1;\n    double x0 = .5;\n    CPPAD_TESTVECTOR(AD<double>) x(n);\n    x[0]      = x0;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(x);\n\n    // some binary multiplication operations\n    AD<double> a = x[0] * 1.; // AD<double> * double\n    AD<double> b = a    * 2;  // AD<double> * int\n    AD<double> c = 3.   * b;  // double     * AD<double>\n    AD<double> d = 4    * c;  // int        * AD<double>\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) y(m);\n    y[0] = x[0] * d;          // AD<double> * AD<double>\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(x, y);\n\n    // check value\n    ok &= NearEqual(y[0] , x0*(4.*3.*2.*1.)*x0,  eps99 , eps99);\n\n    // forward computation of partials w.r.t. x[0]\n    CPPAD_TESTVECTOR(double) dx(n);\n    CPPAD_TESTVECTOR(double) dy(m);\n    dx[0] = 1.;\n    dy    = f.Forward(1, dx);\n    ok   &= NearEqual(dy[0], (4.*3.*2.*1.)*2.*x0, eps99 , eps99);\n\n    // reverse computation of derivative of y[0]\n    CPPAD_TESTVECTOR(double)  w(m);\n    CPPAD_TESTVECTOR(double) dw(n);\n    w[0]  = 1.;\n    dw    = f.Reverse(1, w);\n    ok   &= NearEqual(dw[0], (4.*3.*2.*1.)*2.*x0, eps99 , eps99);\n\n    // use a VecAD<Base>::reference object with multiplication\n    CppAD::VecAD<double> v(1);\n    AD<double> zero(0);\n    v[zero] = c;\n    AD<double> result = 4 * v[zero];\n    ok     &= (result == d);\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/mul_eq.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin mul_eq.cpp}\n\nAD Compound Assignment Multiplication: Example and Test\n#######################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end mul_eq.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nbool MulEq(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t  n = 1;\n    double x0 = .5;\n    CPPAD_TESTVECTOR(AD<double>) x(n);\n    x[0]      = x0;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(x);\n\n    // range space vector\n    size_t m = 2;\n    CPPAD_TESTVECTOR(AD<double>) y(m);\n    y[0] = x[0];         // initial value\n    y[0] *= 2;           // AD<double> *= int\n    y[0] *= 4.;          // AD<double> *= double\n    y[1] = y[0] *= x[0]; // use the result of a compound assignment\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(x, y);\n\n    // check value\n    ok &= NearEqual(y[0] , x0*2.*4.*x0, eps99, eps99);\n    ok &= NearEqual(y[1] ,        y[0], eps99, eps99);\n\n    // forward computation of partials w.r.t. x[0]\n    CPPAD_TESTVECTOR(double) dx(n);\n    CPPAD_TESTVECTOR(double) dy(m);\n    dx[0] = 1.;\n    dy    = f.Forward(1, dx);\n    ok   &= NearEqual(dy[0], 8.*2.*x0, eps99, eps99);\n    ok   &= NearEqual(dy[1], 8.*2.*x0, eps99, eps99);\n\n    // reverse computation of derivative of y[0]\n    CPPAD_TESTVECTOR(double)  w(m);\n    CPPAD_TESTVECTOR(double) dw(n);\n    w[0]  = 1.;\n    w[1]  = 0.;\n    dw    = f.Reverse(1, w);\n    ok   &= NearEqual(dw[0], 8.*2.*x0, eps99, eps99);\n\n    // use a VecAD<Base>::reference object with computed multiplication\n    CppAD::VecAD<double> v(1);\n    AD<double> zero(0);\n    AD<double> result = 1;\n    v[zero] = 2;\n    result *= v[zero];\n    ok     &= (result == 2);\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/mul_level.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin mul_level.cpp}\n{xrst_spell\n    adouble\n    dx\n}\n\nMultiple Level of AD: Example and Test\n######################################\n\nSee Also\n********\n:ref:`base2ad.cpp-name`\n\nPurpose\n*******\nIn this example, we use ``AD< AD<double> >`` (level two taping),\nthe compute values of the function :math:`f : \\B{R}^n \\rightarrow \\B{R}` where\n\n.. math::\n\n    f(x) = \\frac{1}{2} \\left( x_0^2 + \\cdots + x_{n-1}^2 \\right)\n\nWe then use ``AD<double>`` (level one taping) to compute\nthe directional derivative\n\n.. math::\n\n    f^{(1)} (x) * v  = x_0 v_0 + \\cdots + x_{n-1} v_{n-1}\n\nwhere :math:`v \\in \\B{R}^n`.\nWe then use ``double`` (no taping) to compute\n\n.. math::\n\n    \\frac{d}{dx} \\left[ f^{(1)} (x) * v \\right] = v\n\nThis is only meant as an example of multiple levels of taping.\nThe example :ref:`hes_times_dir.cpp-name` computes the same value more\nefficiently by using the identity:\n\n.. math::\n\n    \\frac{d}{dx} \\left[ f^{(1)} (x) * v \\right] = f^{(2)} (x) * v\n\nThe example :ref:`mul_level_adolc.cpp-name` computes the same values using\nAdolc's type ``adouble`` and CppAD's type ``AD<adouble>`` .\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end mul_level.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n\nnamespace {\n    // f(x) = |x|^2 / 2 = .5 * ( x[0]^2 + ... + x[n-1]^2 )\n    template <class Type>\n    Type f(const CPPAD_TESTVECTOR(Type)& x)\n    {   Type sum;\n\n        sum  = 0.;\n        size_t i = size_t(x.size());\n        for(i = 0; i < size_t(x.size()); i++)\n            sum += x[i] * x[i];\n\n        return .5 * sum;\n    }\n}\n\nbool mul_level(void)\n{   bool ok = true;                          // initialize test result\n\n    typedef CppAD::AD<double>   a1type;    // for one level of taping\n    typedef CppAD::AD<a1type>    a2type;    // for two levels of taping\n    size_t n = 5;                           // dimension for example\n    size_t j;                               // a temporary index variable\n\n    // 10 times machine epsilon\n    double eps = 10. * std::numeric_limits<double>::epsilon();\n\n    CPPAD_TESTVECTOR(double) x(n);\n    CPPAD_TESTVECTOR(a1type)  a1x(n), a1v(n), a1dy(1) ;\n    CPPAD_TESTVECTOR(a2type)  a2x(n), a2y(1);\n\n    // Values for the independent variables while taping the function f(x)\n    for(j = 0; j < n; j++)\n        a2x[j] = a1x[j] = x[j] = double(j);\n    // Declare the independent variable for taping f(x)\n    CppAD::Independent(a2x);\n\n    // Use AD< AD<double> > to tape the evaluation of f(x)\n    a2y[0] = f(a2x);\n\n    // Declare a1f as the corresponding ADFun< AD<double> >\n    // (make sure we do not run zero order forward during constructor)\n    CppAD::ADFun<a1type> a1f;\n    a1f.Dependent(a2x, a2y);\n\n    // Values for the independent variables while taping f'(x) * v\n    // Declare the independent variable for taping f'(x) * v\n    // (Note we did not have to tape the creation of a1f.)\n    CppAD::Independent(a1x);\n\n    // set the argument value x for computing f'(x) * v\n    a1f.Forward(0, a1x);\n    // compute f'(x) * v\n    for(j = 0; j < n; j++)\n        a1v[j] = double(n - j);\n    a1dy = a1f.Forward(1, a1v);\n\n    // declare g as ADFun<double> function corresponding to f'(x) * v\n    CppAD::ADFun<double> g;\n    g.Dependent(a1x, a1dy);\n\n    // optimize out operations not necessary for function f'(x) * v\n    g.optimize();\n\n    // Evaluate f'(x) * v\n    g.Forward(0, x);\n\n    // compute the d/dx of f'(x) * v = f''(x) * v = v\n    CPPAD_TESTVECTOR(double) w(1);\n    CPPAD_TESTVECTOR(double) dw(n);\n    w[0] = 1.;\n    dw   = g.Reverse(1, w);\n\n    for(j = 0; j < n; j++)\n        ok &= CppAD::NearEqual(dw[j], a1v[j], eps, eps);\n\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/general/mul_level_adolc.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin mul_level_adolc.cpp}\n{xrst_spell\n    adouble\n    dx\n}\n\nUsing Adolc with Multiple Levels of Taping: Example and Test\n############################################################\n\nPurpose\n*******\nIn this example, we use ``AD< adouble> >`` (level two taping),\nthe compute values of the function :math:`f : \\B{R}^n \\rightarrow \\B{R}` where\n\n.. math::\n\n    f(x) = \\frac{1}{2} \\left( x_0^2 + \\cdots + x_{n-1}^2 \\right)\n\nWe then use Adolc's ``adouble`` (level one taping) to compute\nthe directional derivative\n\n.. math::\n\n    f^{(1)} (x) * v  = x_0 v_0 + \\cdots + x_{n-1} v_{n-1}\n\nwhere :math:`v \\in \\B{R}^n`.\nWe then use ``double`` (no taping) to compute\n\n.. math::\n\n    \\frac{d}{dx} \\left[ f^{(1)} (x) * v \\right] = v\n\nThis is only meant as an example of multiple levels of taping.\nThe example :ref:`hes_times_dir.cpp-name` computes the same value more\nefficiently by using the identity:\n\n.. math::\n\n    \\frac{d}{dx} \\left[ f^{(1)} (x) * v \\right] = f^{(2)} (x) * v\n\nThe example :ref:`mul_level.cpp-name` computes the same values using\n``AD< AD<double> >`` and ``AD<double>`` .\n\nMemory Management\n*****************\nAdolc uses raw memory arrays that depend on the number of\ndependent and independent variables.\nThe memory management utility :ref:`thread_alloc-name`\nis used to manage this memory allocation.\n\nConfiguration Requirement\n*************************\nThis example will be compiled and tested provided\n:ref:`cmake@include_adolc` is true on the cmake command line.\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end mul_level_adolc.cpp}\n*/\n// BEGIN C++\n// suppress conversion warnings before other includes\n# include <cppad/wno_conversion.hpp>\n//\n\n# include <adolc/adouble.h>\n# include <adolc/taping.h>\n# include <adolc/interfaces.h>\n\n// adouble definitions not in Adolc distribution and\n// required in order to use CppAD::AD<adouble>\n# include <cppad/example/base_adolc.hpp>\n\n# include <cppad/cppad.hpp>\n\nnamespace {\n    // f(x) = |x|^2 / 2 = .5 * ( x[0]^2 + ... + x[n-1]^2 )\n    template <class Type>\n    Type f(const CPPAD_TESTVECTOR(Type)& x)\n    {   Type sum;\n\n        sum  = 0.;\n        size_t i = size_t(x.size());\n        for(i = 0; i < size_t(x.size()); i++)\n            sum += x[i] * x[i];\n\n        return .5 * sum;\n    }\n}\n\nbool mul_level_adolc(void)\n{   bool ok = true;                // initialize test result\n    using CppAD::thread_alloc;        // The CppAD memory allocator\n\n    typedef adouble           a1type;  // for first level of taping\n    typedef CppAD::AD<a1type> a2type; // for second level of taping\n    size_t n = 5;                          // number independent variables\n    size_t j;\n\n    // 10 times machine epsilon\n    double eps = 10. * std::numeric_limits<double>::epsilon();\n\n    CPPAD_TESTVECTOR(double) x(n);\n    CPPAD_TESTVECTOR(a1type) a1x(n);\n    CPPAD_TESTVECTOR(a2type) a2x(n);\n\n    // Values for the independent variables while taping the function f(x)\n    for(j = 0; j < n; j++)\n        a2x[j] = double(j);\n    // Declare the independent variable for taping f(x)\n    CppAD::Independent(a2x);\n\n    // Use AD<adouble> to tape the evaluation of f(x)\n    CPPAD_TESTVECTOR(a2type) a2y(1);\n    a2y[0] = f(a2x);\n\n    // Declare a1f as the corresponding ADFun<adouble> function f(x)\n    // (make sure we do not run zero order forward during constructor)\n    CppAD::ADFun<a1type> a1f;\n    a1f.Dependent(a2x, a2y);\n\n    // Value of the independent variables whitle taping f'(x) * v\n    short tag = 0;\n    int keep = 1;\n    trace_on(tag, keep);\n    for(j = 0; j < n; j++)\n        a1x[j] <<= double(j);\n\n    // set the argument value x for computing f'(x) * v\n    a1f.Forward(0, a1x);\n\n    // compute f'(x) * v\n    CPPAD_TESTVECTOR(a1type) a1v(n);\n    CPPAD_TESTVECTOR(a1type) a1df(1);\n    for(j = 0; j < n; j++)\n        a1v[j] = double(n - j);\n    a1df = a1f.Forward(1, a1v);\n\n    // declare Adolc function corresponding to f'(x) * v\n    double df;\n    a1df[0] >>= df;\n    trace_off();\n\n    // compute the d/dx of f'(x) * v = f''(x) * v\n    size_t m      = 1;                     // # dependent in f'(x) * v\n\n    // w = new double[capacity] where capacity >= m\n    size_t capacity;\n    double* w  = thread_alloc::create_array<double>(m, capacity);\n\n    // dw = new double[capacity] where capacity >= n\n    double* dw = thread_alloc::create_array<double>(n, capacity);\n\n    w[0]  = 1.;\n    fos_reverse(tag, int(m), int(n), w, dw);\n\n    for(j = 0; j < n; j++)\n    {   double vj = a1v[j].value();\n        ok &= CppAD::NearEqual(dw[j], vj, eps, eps);\n    }\n\n    // make memory available for other use by this thread\n    thread_alloc::delete_array(w);\n    thread_alloc::delete_array(dw);\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/general/mul_level_adolc_ode.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin mul_level_adolc_ode.cpp}\n{xrst_spell\n    adouble\n    cccc\n}\n\nTaylor's Ode Solver: A Multi-Level Adolc Example and Test\n#########################################################\n\nSee Also\n********\n:ref:`taylor_ode.cpp-name` , :ref:`mul_level_ode.cpp-name`\n\nPurpose\n*******\nThis is a realistic example using\ntwo levels of AD; see :ref:`mul_level-name` .\nThe first level uses Adolc's ``adouble`` type\nto tape the solution of an ordinary differential equation.\nThis solution is then differentiated with respect to a parameter vector.\nThe second level uses CppAD's type ``AD<adouble>``\nto take derivatives during the solution of the differential equation.\nThese derivatives are used in the application\nof Taylor's method to the solution of the ODE.\n\nODE\n***\nFor this example the function\n:math:`y : \\B{R} \\times \\B{R}^n \\rightarrow \\B{R}^n` is defined by\n:math:`y(0, x) = 0` and\n:math:`\\partial_t y(t, x) = g(y, x)` where\n:math:`g : \\B{R}^n \\times \\B{R}^n \\rightarrow \\B{R}^n` is defined by\n\n.. math::\n\n    g(y, x) =\n    \\left( \\begin{array}{c}\n            x_0     \\\\\n            x_1 y_0 \\\\\n            \\vdots  \\\\\n            x_{n-1} y_{n-2}\n    \\end{array} \\right)\n\nODE Solution\n************\nThe solution for this example can be calculated by\nstarting with the first row and then using the solution\nfor the first row to solve the second and so on.\nDoing this we obtain\n\n.. math::\n\n    y(t, x ) =\n    \\left( \\begin{array}{c}\n        x_0 t                  \\\\\n        x_1 x_0 t^2 / 2        \\\\\n        \\vdots                 \\\\\n        x_{n-1} x_{n-2} \\ldots x_0 t^n / n !\n    \\end{array} \\right)\n\nDerivative of ODE Solution\n**************************\nDifferentiating the solution above,\nwith respect to the parameter vector :math:`x`,\nwe notice that\n\n.. math::\n\n    \\partial_x y(t, x ) =\n    \\left( \\begin{array}{cccc}\n    y_0 (t,x) / x_0      & 0                   & \\cdots & 0      \\\\\n    y_1 (t,x) / x_0      & y_1 (t,x) / x_1     & 0      & \\vdots \\\\\n    \\vdots               & \\vdots              & \\ddots & 0      \\\\\n    y_{n-1} (t,x) / x_0  & y_{n-1} (t,x) / x_1 & \\cdots & y_{n-1} (t,x) / x_{n-1}\n    \\end{array} \\right)\n\nTaylor's Method Using AD\n************************\nWe define the function :math:`z(t, x)` by the equation\n\n.. math::\n\n    z ( t , x ) = g[ y ( t , x ) ] = h [ x , y( t , x ) ]\n\nsee :ref:`taylor_ode-name` for the method used to compute the\nTaylor coefficients w.r.t :math:`t` of :math:`y(t, x)`.\n\nbase_adolc.hpp\n**************\nThe file :ref:`base_adolc.hpp-name` is implements the\n:ref:`Base type requirements<base_require-name>` where *Base*\nis ``adolc`` .\n\nMemory Management\n*****************\nAdolc uses raw memory arrays that depend on the number of\ndependent and independent variables.\nThe :ref:`thread_alloc-name` memory management utilities\n:ref:`create_array<ta_create_array-name>` and\n:ref:`delete_array<ta_delete_array-name>`\nare used to manage this memory allocation.\n\nConfiguration Requirement\n*************************\nThis example will be compiled and tested provided\n:ref:`cmake@include_ipopt` is on the cmake command line.\n\nSource\n******\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end mul_level_adolc_ode.cpp}\n--------------------------------------------------------------------------\n*/\n// BEGIN C++\n// suppress conversion warnings before other includes\n# include <cppad/wno_conversion.hpp>\n//\n\n# include <adolc/adouble.h>\n# include <adolc/taping.h>\n# include <adolc/drivers/drivers.h>\n\n// definitions not in Adolc distribution and required to use CppAD::AD<adouble>\n# include <cppad/example/base_adolc.hpp>\n\n# include <cppad/cppad.hpp>\n// ==========================================================================\nnamespace { // BEGIN empty namespace\n// define types for each level\ntypedef adouble           a1type;\ntypedef CppAD::AD<a1type> a2type;\n\n// -------------------------------------------------------------------------\n// class definition for C++ function object that defines ODE\nclass Ode {\nprivate:\n    // copy of a that is set by constructor and used by g(y)\n    CPPAD_TESTVECTOR(a1type) a1x_;\npublic:\n    // constructor\n    Ode(const CPPAD_TESTVECTOR(a1type)& a1x) : a1x_(a1x)\n    { }\n    // the function g(y) is evaluated with two levels of taping\n    CPPAD_TESTVECTOR(a2type) operator()\n    ( const CPPAD_TESTVECTOR(a2type)& a2y) const\n    {   size_t n = a2y.size();\n        CPPAD_TESTVECTOR(a2type) a2g(n);\n        size_t i;\n        a2g[0] = a1x_[0];\n        for(i = 1; i < n; i++)\n            a2g[i] = a1x_[i] * a2y[i-1];\n\n        return a2g;\n    }\n};\n\n// -------------------------------------------------------------------------\n// Routine that uses Taylor's method to solve ordinary differential equaitons\n// and allows for algorithmic differentiation of the solution.\nCPPAD_TESTVECTOR(a1type) taylor_ode_adolc(\n    Ode                            G       ,  // function that defines the ODE\n    size_t                         order   ,  // order of Taylor's method used\n    size_t                         nstep   ,  // number of steps to take\n    const a1type                   &a1dt   ,  // Delta t for each step\n    const CPPAD_TESTVECTOR(a1type) &a1y_ini)  // y(t) at the initial time\n{\n    // some temporary indices\n    size_t i, k, ell;\n\n    // number of variables in the ODE\n    size_t n = a1y_ini.size();\n\n    // copies of x and g(y) with two levels of taping\n    CPPAD_TESTVECTOR(a2type)   a2y(n), Z(n);\n\n    // y, y^{(k)} , z^{(k)}, and y^{(k+1)}\n    CPPAD_TESTVECTOR(a1type)  a1y(n), a1y_k(n), a1z_k(n), a1y_kp(n);\n\n    // initialize x\n    for(i = 0; i < n; i++)\n        a1y[i] = a1y_ini[i];\n\n    // loop with respect to each step of Taylors method\n    for(ell = 0; ell < nstep; ell++)\n    {   // prepare to compute derivatives using a1type\n        for(i = 0; i < n; i++)\n            a2y[i] = a1y[i];\n        CppAD::Independent(a2y);\n\n        // evaluate ODE using a2type\n        Z = G(a2y);\n\n        // define differentiable version of g: X -> Y\n        // that computes its derivatives using a1type\n        CppAD::ADFun<a1type> a1g(a2y, Z);\n\n        // Use Taylor's method to take a step\n        a1y_k            = a1y;     // initialize y^{(k)}\n        a1type dt_kp = a1dt;    // initialize dt^(k+1)\n        for(k = 0; k <= order; k++)\n        {   // evaluate k-th order Taylor coefficient of y\n            a1z_k = a1g.Forward(k, a1y_k);\n\n            for(i = 0; i < n; i++)\n            {   // convert to (k+1)-Taylor coefficient for x\n                a1y_kp[i] = a1z_k[i] / a1type(k + 1);\n\n                // add term for to this Taylor coefficient\n                // to solution for y(t, x)\n                a1y[i]    += a1y_kp[i] * dt_kp;\n            }\n            // next power of t\n            dt_kp *= a1dt;\n            // next Taylor coefficient\n            a1y_k   = a1y_kp;\n        }\n    }\n    return a1y;\n}\n} // END empty namespace\n// ==========================================================================\n// Routine that tests algorithmic differentiation of solutions computed\n// by the routine taylor_ode.\nbool mul_level_adolc_ode(void)\n{   bool ok = true;\n    double eps = 100. * std::numeric_limits<double>::epsilon();\n\n    // number of components in differential equation\n    size_t n = 4;\n\n    // some temporary indices\n    size_t i, j;\n\n    // set up for thread_alloc memory allocator\n    using CppAD::thread_alloc; // the allocator\n    size_t capacity;           // capacity of an allocation\n\n    // the vector x with length n (or greater) in double\n    double* x = thread_alloc::create_array<double>(n, capacity);\n\n    // the vector x with length n in a1type\n    CPPAD_TESTVECTOR(a1type) a1x(n);\n    for(i = 0; i < n; i++)\n        a1x[i] = x[i] = double(i + 1);\n\n    // declare the parameters as the independent variable\n    short tag = 0;                     // Adolc setup\n    int keep = 1;\n    trace_on(tag, keep);\n    for(i = 0; i < n; i++)\n        a1x[i] <<= double(i + 1);  // a1x is independent for adouble type\n\n    // arguments to taylor_ode_adolc\n    Ode G(a1x);                // function that defines the ODE\n    size_t   order = n;      // order of Taylor's method used\n    size_t   nstep = 2;      // number of steps to take\n    a1type   a1dt  = 1.;     // Delta t for each step\n    // value of y(t, x) at the initial time\n    CPPAD_TESTVECTOR(a1type) a1y_ini(n);\n    for(i = 0; i < n; i++)\n        a1y_ini[i] = 0.;\n\n    // integrate the differential equation\n    CPPAD_TESTVECTOR(a1type) a1y_final(n);\n    a1y_final = taylor_ode_adolc(G, order, nstep, a1dt, a1y_ini);\n\n    // declare the differentiable function f : x -> y_final\n    // (corresponding to the tape of adouble operations)\n    double* y_final = thread_alloc::create_array<double>(n, capacity);\n    for(i = 0; i < n; i++)\n        a1y_final[i] >>= y_final[i];\n    trace_off();\n\n    // check function values\n    double check = 1.;\n    double t     = nstep * a1dt.value();\n    for(i = 0; i < n; i++)\n    {   check *= x[i] * t / double(i + 1);\n        ok &= CppAD::NearEqual(y_final[i], check, eps, eps);\n    }\n\n    // memory where Jacobian will be returned\n    double* jac_ = thread_alloc::create_array<double>(n * n, capacity);\n    double** jac = thread_alloc::create_array<double*>(n, capacity);\n    for(i = 0; i < n; i++)\n        jac[i] = jac_ + i * n;\n\n    // evaluate Jacobian of h at a\n    size_t m = n;              // # dependent variables\n    jacobian(tag, int(m), int(n), x, jac);\n\n    // check Jacobian\n    for(i = 0; i < n; i++)\n    {   for(j = 0; j < n; j++)\n        {   if( i < j )\n                check = 0.;\n            else\n                check = y_final[i] / x[j];\n            ok &= CppAD::NearEqual(jac[i][j], check, eps, eps);\n        }\n    }\n\n    // make memory available for other use by this thread\n    thread_alloc::delete_array(x);\n    thread_alloc::delete_array(y_final);\n    thread_alloc::delete_array(jac_);\n    thread_alloc::delete_array(jac);\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/mul_level_ode.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin mul_level_ode.cpp}\n{xrst_spell\n    cccc\n}\n\nTaylor's Ode Solver: A Multi-Level AD Example and Test\n######################################################\n\nSee Also\n********\n:ref:`taylor_ode.cpp-name` , :ref:`base2ad.cpp-name` , :ref:`mul_level_adolc_ode.cpp-name`\n\nPurpose\n*******\nThis is a realistic example using\ntwo levels of AD; see :ref:`mul_level-name` .\nThe first level uses ``AD<double>`` to tape the solution of an\nordinary differential equation.\nThis solution is then differentiated with respect to a parameter vector.\nThe second level uses ``AD< AD<double> >``\nto take derivatives during the solution of the differential equation.\nThese derivatives are used in the application\nof Taylor's method to the solution of the ODE.\n\nODE\n***\nFor this example the function\n:math:`y : \\B{R} \\times \\B{R}^n \\rightarrow \\B{R}^n` is defined by\n:math:`y(0, x) = 0` and\n:math:`\\partial_t y(t, x) = g(y, x)` where\n:math:`g : \\B{R}^n \\times \\B{R}^n \\rightarrow \\B{R}^n` is defined by\n\n.. math::\n\n    g(y, x) =\n    \\left( \\begin{array}{c}\n            x_0     \\\\\n            x_1 y_0 \\\\\n            \\vdots  \\\\\n            x_{n-1} y_{n-2}\n    \\end{array} \\right)\n\nODE Solution\n************\nThe solution for this example can be calculated by\nstarting with the first row and then using the solution\nfor the first row to solve the second and so on.\nDoing this we obtain\n\n.. math::\n\n    y(t, x ) =\n    \\left( \\begin{array}{c}\n        x_0 t                  \\\\\n        x_1 x_0 t^2 / 2        \\\\\n        \\vdots                 \\\\\n        x_{n-1} x_{n-2} \\ldots x_0 t^n / n !\n    \\end{array} \\right)\n\nDerivative of ODE Solution\n**************************\nDifferentiating the solution above,\nwith respect to the parameter vector :math:`x`,\nwe notice that\n\n.. math::\n\n    \\partial_x y(t, x ) =\n    \\left( \\begin{array}{cccc}\n    y_0 (t,x) / x_0      & 0                   & \\cdots & 0      \\\\\n    y_1 (t,x) / x_0      & y_1 (t,x) / x_1     & 0      & \\vdots \\\\\n    \\vdots               & \\vdots              & \\ddots & 0      \\\\\n    y_{n-1} (t,x) / x_0  & y_{n-1} (t,x) / x_1 & \\cdots & y_{n-1} (t,x) / x_{n-1}\n    \\end{array} \\right)\n\nTaylor's Method Using AD\n************************\nWe define the function :math:`z(t, x)` by the equation\n\n.. math::\n\n    z ( t , x ) = g[ y ( t , x ) ] = h [ x , y( t , x ) ]\n\nsee :ref:`taylor_ode-name` for the method used to compute the\nTaylor coefficients w.r.t :math:`t` of :math:`y(t, x)`.\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end mul_level_ode.cpp}\n--------------------------------------------------------------------------\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n\n// =========================================================================\n// define types for each level\nnamespace { // BEGIN empty namespace\n\ntypedef CppAD::AD<double>          a1double;\ntypedef CppAD::AD<a1double>        a2double;\n\ntypedef CPPAD_TESTVECTOR(double)    d_vector;\ntypedef CPPAD_TESTVECTOR(a1double)  a1vector;\ntypedef CPPAD_TESTVECTOR(a2double)  a2vector;\n\n// -------------------------------------------------------------------------\n// class definition for C++ function object that defines ODE\nclass Ode {\nprivate:\n    // copy of a that is set by constructor and used by g(y)\n    a1vector a1x_;\npublic:\n    // constructor\n    Ode(const a1vector& a1x) : a1x_(a1x)\n    { }\n    // the function g(y) is evaluated with two levels of taping\n    a2vector operator()\n    ( const a2vector& a2y) const\n    {   size_t n = a2y.size();\n        a2vector a2g(n);\n        size_t i;\n        a2g[0] = a1x_[0];\n        for(i = 1; i < n; i++)\n            a2g[i] = a1x_[i] * a2y[i-1];\n\n        return a2g;\n    }\n};\n\n// -------------------------------------------------------------------------\n// Routine that uses Taylor's method to solve ordinary differential equaitons\n// and allows for algorithmic differentiation of the solution.\na1vector taylor_ode(\n    Ode                            G       ,  // function that defines the ODE\n    size_t                         order   ,  // order of Taylor's method used\n    size_t                         nstep   ,  // number of steps to take\n    const a1double&                a1dt    ,  // Delta t for each step\n    const a1vector& a1y_ini)  // y(t) at the initial time\n{\n    // some temporary indices\n    size_t i, k, ell;\n\n    // number of variables in the ODE\n    size_t n = a1y_ini.size();\n\n    // copies of x and g(y) with two levels of taping\n    a2vector   a2y(n), a2z(n);\n\n    // y, y^{(k)} , z^{(k)}, and y^{(k+1)}\n    a1vector  a1y(n), a1y_k(n), a1z_k(n), a1y_kp(n);\n\n    // initialize x\n    for(i = 0; i < n; i++)\n        a1y[i] = a1y_ini[i];\n\n    // loop with respect to each step of Taylors method\n    for(ell = 0; ell < nstep; ell++)\n    {   // prepare to compute derivatives using a1double\n        for(i = 0; i < n; i++)\n            a2y[i] = a1y[i];\n        CppAD::Independent(a2y);\n\n        // evaluate ODE in a2double\n        a2z = G(a2y);\n\n        // define differentiable version of a1g: y -> z\n        // that computes its derivatives using a1double objects\n        CppAD::ADFun<a1double> a1g(a2y, a2z);\n\n        // Use Taylor's method to take a step\n        a1y_k            = a1y;     // initialize y^{(k)}\n        a1double a1dt_kp = a1dt;  // initialize dt^(k+1)\n        for(k = 0; k <= order; k++)\n        {   // evaluate k-th order Taylor coefficient of y\n            a1z_k = a1g.Forward(k, a1y_k);\n\n            for(i = 0; i < n; i++)\n            {   // convert to (k+1)-Taylor coefficient for x\n                a1y_kp[i] = a1z_k[i] / a1double(k + 1);\n\n                // add term for to this Taylor coefficient\n                // to solution for y(t, x)\n                a1y[i]    += a1y_kp[i] * a1dt_kp;\n            }\n            // next power of t\n            a1dt_kp *= a1dt;\n            // next Taylor coefficient\n            a1y_k   = a1y_kp;\n        }\n    }\n    return a1y;\n}\n} // END empty namespace\n// ==========================================================================\n// Routine that tests algorithmic differentiation of solutions computed\n// by the routine taylor_ode.\nbool mul_level_ode(void)\n{   bool ok = true;\n    double eps = 100. * std::numeric_limits<double>::epsilon();\n\n    // number of components in differential equation\n    size_t n = 4;\n\n    // some temporary indices\n    size_t i, j;\n\n    // parameter vector in both double and a1double\n    d_vector  x(n);\n    a1vector  a1x(n);\n    for(i = 0; i < n; i++)\n        a1x[i] = x[i] = double(i + 1);\n\n    // declare the parameters as the independent variable\n    CppAD::Independent(a1x);\n\n    // arguments to taylor_ode\n    Ode G(a1x);                // function that defines the ODE\n    size_t   order = n;      // order of Taylor's method used\n    size_t   nstep = 2;      // number of steps to take\n    a1double a1dt  = double(1.);     // Delta t for each step\n    // value of y(t, x) at the initial time\n    a1vector a1y_ini(n);\n    for(i = 0; i < n; i++)\n        a1y_ini[i] = 0.;\n\n    // integrate the differential equation\n    a1vector a1y_final(n);\n    a1y_final = taylor_ode(G, order, nstep, a1dt, a1y_ini);\n\n    // define differentiable function object f : x -> y_final\n    // that computes its derivatives in double\n    CppAD::ADFun<double> f(a1x, a1y_final);\n\n    // check function values\n    double check = 1.;\n    double t     = double(nstep) * Value(a1dt);\n    for(i = 0; i < n; i++)\n    {   check *= x[i] * t / double(i + 1);\n        ok &= CppAD::NearEqual(Value(a1y_final[i]), check, eps, eps);\n    }\n\n    // evaluate the Jacobian of h at a\n    d_vector jac ( f.Jacobian(x) );\n    // There appears to be a bug in g++ version 4.4.2 because it generates\n    // a warning for the equivalent form\n    // d_vector jac = f.Jacobian(x);\n\n    // check Jacobian\n    for(i = 0; i < n; i++)\n    {   for(j = 0; j < n; j++)\n        {   double jac_ij = jac[i * n + j];\n            if( i < j )\n                check = 0.;\n            else\n                check = Value( a1y_final[i] ) / x[j];\n            ok &= CppAD::NearEqual(jac_ij, check, eps, eps);\n        }\n    }\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/near_equal_ext.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin near_equal_ext.cpp}\n\nCompare AD with Base Objects: Example and Test\n##############################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end near_equal_ext.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n# include <complex>\n\nbool near_equal_ext(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n\n    // double\n    double x    = 1.00000;\n    double y    = 1.00001;\n    double a    =  .00005;\n    double r    =  .00005;\n    double zero = 0.;\n\n    // AD<double>\n    AD<double> ax(x);\n    AD<double> ay(y);\n\n    ok &= NearEqual(ax, ay, zero, a);\n    ok &= NearEqual(ax, y,  r, zero);\n    ok &= NearEqual(x, ay,  r,    a);\n\n    // std::complex<double>\n    AD<double> cx(x);\n    AD<double> cy(y);\n\n    // AD< std::complex<double> >\n    AD<double> acx(x);\n    AD<double> acy(y);\n\n    ok &= NearEqual(acx, acy, zero, a);\n    ok &= NearEqual(acx,  cy, r, zero);\n    ok &= NearEqual(acx,   y, r,    a);\n    ok &= NearEqual( cx, acy, r,    a);\n    ok &= NearEqual(  x, acy, r,    a);\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/new_dynamic.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin new_dynamic.cpp}\n\nDynamic Parameters: Example and Test\n####################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end new_dynamic.cpp}\n*/\n// BEGIN C++\n# include <limits>\n# include <cppad/cppad.hpp>\n\nbool new_dynamic(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps = 10. * std::numeric_limits<double>::epsilon();\n\n    // independent dynamic parameter vector\n    size_t nd = 3;\n    CPPAD_TESTVECTOR(AD<double>) adynamic(nd);\n    adynamic[0] = 1.0;\n    adynamic[1] = 1.0;\n    adynamic[2] = 1.0;\n\n    // domain space vector\n    size_t nx = 2;\n    CPPAD_TESTVECTOR(AD<double>) ax(nx);\n    ax[0] = 0.;\n    ax[1] = 1.;\n\n    // declare independent variables, dynamic parameters, starting recording\n    CppAD::Independent(ax, adynamic);\n\n    // create a dependent dynamic parameter\n    AD<double> adependent_dyn = adynamic[0] + 2.0;\n\n    // check that elements of adynamic are currently dynamic parameters\n    for(size_t j = 0; j < nd; ++j)\n        ok &= Dynamic( adynamic[j] );\n    ok &= Dynamic( adependent_dyn );\n\n    // range space vector\n    size_t ny = 1;\n    CPPAD_TESTVECTOR(AD<double>) ay(ny);\n    ay[0]  = adependent_dyn  + ax[0];\n    ay[0] *= adynamic[1]     + ax[0];\n    ay[0] *= adynamic[2]     + ax[1];\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(ax, ay);\n\n    // check the number of independent dynamic parameters in f\n    ok &= f.size_dyn_ind() == nd;\n\n    // total number of dynamic parameters in f\n    ok &= f.size_dyn_par() == nd + 1;\n\n    // check that these are no longer dynamic parameters\n    for(size_t j = 0; j < nd; ++j)\n        ok &= ! Dynamic( adynamic[j] );\n    ok &= ! Dynamic( adependent_dyn );\n\n    // zero order forward mode\n    CPPAD_TESTVECTOR(double) x(nx), y(ny);\n    x[0] = 3.;\n    x[1] = 4.;\n    y    = f.Forward(0, x);\n    ok  &= f.size_order() == 1;\n    double check;\n    check  = Value( adynamic[0] ) + 2.0 + x[0];\n    check *= Value( adynamic[1] ) + x[0];\n    check *= Value( adynamic[2] ) + x[1];\n    ok  &= NearEqual(y[0] , check, eps, eps);\n\n    // change the dynamic parameter values\n    CPPAD_TESTVECTOR(double) dynamic(nd);\n    dynamic[0] = 2.0;\n    dynamic[1] = 3.0;\n    dynamic[2] = 4.0;\n    f.new_dynamic(dynamic);\n    ok  &= f.size_order() == 0;\n    //\n    y    = f.Forward(0, x);\n    ok  &= f.size_order() == 1;\n    check  = dynamic[0] + 2.0 + x[0];\n    check *= dynamic[1] + x[0];\n    check *= dynamic[2] + x[1];\n    ok  &= NearEqual(y[0] , check, eps, eps);\n\n    // use first order forward mode to compute partial of f w.r.t x[0]\n    CPPAD_TESTVECTOR(double) dx(nx), dy(ny);\n    dx[0] = 1.0;\n    dx[1] = 0.0;\n    dy    = f.Forward(1, dx);\n    ok   &= f.size_order() == 2;\n    check = (dynamic[2] + x[1])*(dynamic[0] + 2.0 + x[0] + dynamic[1] + x[0]);\n    ok  &= NearEqual(dy[0] , check, eps, eps);\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/general/num_limits.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-23 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin num_limits.cpp}\n\nNumeric Limits: Example and Test\n################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end num_limits.cpp}\n*/\n// BEGIN C++\n\n# ifdef _MSC_VER\n// Suppress Microsoft compiler warning about possible loss of precision,\n// in the constructors (when converting to std::complex<float>)\n//    Float one = 1\n//    Float two = 2\n// 1 and 2 are small enough so no loss of precision when converting to float.\n# pragma warning(disable:4244)\n# endif\n\n# include <cppad/cppad.hpp>\n# include <complex>\n\nnamespace {\n    typedef CppAD::AD<double> Float;\n    //\n    // -----------------------------------------------------------------\n    bool check_epsilon(void)\n    {   bool ok    = true;\n        Float eps   = CppAD::numeric_limits<Float>::epsilon();\n        Float eps2  = eps / 2.0;\n        Float check = 1.0 + eps;\n        ok         &= 1.0 !=  check;\n        check       = 1.0 + eps2;\n        ok         &= 1.0 == check;\n        return ok;\n    }\n    // -----------------------------------------------------------------\n    bool check_min(void)\n    {   bool ok     = true;\n        Float min   = CppAD::numeric_limits<Float>::min();\n        Float eps   = CppAD::numeric_limits<Float>::epsilon();\n        //\n        Float match = (min / 100.) * 100.;\n        ok         &= fabs(match / min - 1.0)  > 3.0 * eps;\n        //\n        match       = (min * 100.) / 100.;\n        ok         &= fabs(match / min - 1.0)  < 3.0 * eps;\n        return ok;\n    }\n    // -----------------------------------------------------------------\n    bool check_max(void)\n    {   bool ok     = true;\n        Float max   = CppAD::numeric_limits<Float>::max();\n        Float eps   = CppAD::numeric_limits<Float>::epsilon();\n        //\n        Float match = (max * 100.) / 100.;\n        ok         &= fabs(match / max - 1.0) > 3.0 * eps;\n        //\n        match       = (max / 100.) * 100.;\n        ok         &= fabs(match / max - 1.0) < 3.0 * eps;\n        return ok;\n    }\n    // -----------------------------------------------------------------\n    bool check_nan(void)\n    {   bool ok     = true;\n        Float nan   = CppAD::numeric_limits<Float>::quiet_NaN();\n        ok         &= nan != nan;\n        return ok;\n    }\n    // -----------------------------------------------------------------\n    bool check_infinity(void)\n    {   bool ok    = true;\n        Float inf  = CppAD::numeric_limits<Float>::infinity();\n        Float hun  = Float(100);\n        Float tmp  = Float(0);\n        tmp        = inf + hun;\n        ok        &= inf == tmp;\n        tmp        = inf - inf;\n        ok        &= CppAD::isnan( tmp );\n        return ok;\n    }\n    // -----------------------------------------------------------------\n    bool check_digits10(void)\n    {   bool ok     = true;\n        Float neg_log_eps =\n            - log10( CppAD::numeric_limits<Float>::epsilon() );\n        int ceil_neg_log_eps =\n            Integer( neg_log_eps );\n        ok &= ceil_neg_log_eps == CppAD::numeric_limits<Float>::digits10;\n        return ok;\n    }\n    // -----------------------------------------------------------------\n    bool check_max_digits10(void)\n    {   bool ok          = true;\n        int max_digits10 = CppAD::numeric_limits<Float>::max_digits10;\n        Float pi         = 4.0 * atan( Float(1.0) );\n        //\n        std::stringstream ss;\n        ss << std::setprecision( max_digits10 ) << pi;\n        //\n        Float check = Float( std::atof( ss.str().c_str() ) );\n        ok         &= pi == check;\n        return ok;\n    }\n}\n\nbool num_limits(void)\n{   bool ok = true;\n\n    ok &= check_epsilon();\n    ok &= check_min();\n    ok &= check_max();\n    ok &= check_nan();\n    ok &= check_infinity();\n    ok &= check_digits10();\n    ok &= check_max_digits10();\n\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/general/number_skip.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin number_skip.cpp}\n\nNumber of Variables That Can be Skipped: Example and Test\n#########################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end number_skip.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\nbool number_skip(void)\n{   bool ok = true;\n    using CppAD::AD;\n\n    // independent variable vector\n    CppAD::vector< AD<double> > ax(2);\n    ax[0] = 0.;\n    ax[1] = 1.;\n    Independent(ax);\n\n    // Use a conditional expression\n    CppAD::vector< AD<double> > ay(1);\n\n    // variable that gets optimized out\n    AD<double> az = ax[0] * ax[0];\n\n\n    // conditional expression\n    ay[0] = CondExpLt(ax[0], ax[1], ax[0] + ax[1], ax[0] - ax[1]);\n\n    // create function object F : x -> ay\n    CppAD::ADFun<double> f;\n    f.Dependent(ax, ay);\n\n    // use zero order to evaluate F[ (3, 4) ]\n    CppAD::vector<double>  x( f.Domain() );\n    CppAD::vector<double>  y( f.Range() );\n    x[0]    = 3.;\n    x[1]    = 4.;\n    y   = f.Forward(0, x);\n    ok &= (y[0] == x[0] + x[1]);\n\n    // before call to optimize\n    ok &= f.number_skip() == 0;\n    size_t n_var = f.size_var();\n\n    // now optimize the operation sequence\n    f.optimize();\n\n    // after optimize, check forward mode result\n    x[0]    = 4.;\n    x[1]    = 3.;\n    y   = f.Forward(0, x);\n    ok &= (y[0] == x[0] - x[1]);\n\n    // after optimize, check amount of optimization\n    ok &= f.size_var() == n_var - 1;\n    ok &= f.number_skip() == 1;\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/numeric_type.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin numeric_type.cpp}\n\nThe NumericType: Example and Test\n#################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end numeric_type.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n\nnamespace { // Empty namespace\n\n    // -------------------------------------------------------------------\n    class MyType {\n    private:\n        double d;\n    public:\n        // constructor from void\n        MyType(void) : d(0.)\n        { }\n        // constructor from an int\n        MyType(int d_) : d(d_)\n        { }\n        // copy constructor\n        MyType(const MyType &x)\n        {   d = x.d; }\n        // assignment operator\n        void operator = (const MyType &x)\n        {   d = x.d; }\n        // member function that converts to double\n        double Double(void) const\n        {   return d; }\n        // unary plus\n        MyType operator + (void) const\n        {   MyType x;\n            x.d =  d;\n            return x;\n        }\n        // unary plus\n        MyType operator - (void) const\n        {   MyType x;\n            x.d = - d;\n            return x;\n        }\n        // binary addition\n        MyType operator + (const MyType &x) const\n        {   MyType y;\n            y.d = d + x.d ;\n            return y;\n        }\n        // binary subtraction\n        MyType operator - (const MyType &x) const\n        {   MyType y;\n            y.d = d - x.d ;\n            return y;\n        }\n        // binary multiplication\n        MyType operator * (const MyType &x) const\n        {   MyType y;\n            y.d = d * x.d ;\n            return y;\n        }\n        // binary division\n        MyType operator / (const MyType &x) const\n        {   MyType y;\n            y.d = d / x.d ;\n            return y;\n        }\n        // compound assignment addition\n        void operator += (const MyType &x)\n        {   d += x.d; }\n        // compound assignment subtraction\n        void operator -= (const MyType &x)\n        {   d -= x.d; }\n        // compound assignment multiplication\n        void operator *= (const MyType &x)\n        {   d *= x.d; }\n        // compound assignment division\n        void operator /= (const MyType &x)\n        {   d /= x.d; }\n    };\n}\nbool NumericType(void)\n{   bool ok  = true;\n    using CppAD::AD;\n    using CppAD::CheckNumericType;\n\n    CheckNumericType<MyType>            ();\n\n    CheckNumericType<int>               ();\n    CheckNumericType<double>            ();\n    CheckNumericType< AD<double> >      ();\n    CheckNumericType< AD< AD<double> > >();\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/ode_stiff.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin ode_stiff.cpp}\n{xrst_spell\n    rosen\n}\n\nA Stiff Ode: Example and Test\n#############################\n\nDefine\n:math:`x : \\B{R} \\rightarrow \\B{R}^2` by\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        x_0 (0)        & = & 1 \\\\\n        x_1 (0)        & = & 0 \\\\\n        x_0^\\prime (t) & = & - a_0 x_0 (t) \\\\\n        x_1^\\prime (t) & = & + a_0 x_0 (t) - a_1 x_1 (t)\n    \\end{eqnarray}\n\nIf :math:`a_0 \\gg a_1 > 0`, this is a stiff Ode and\nthe analytic solution is\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    x_0 (t)    & = & \\exp( - a_0 t ) \\\\\n    x_1 (t)    & = & a_0 [ \\exp( - a_1 t ) - \\exp( - a_0 t ) ] / ( a_0 - a_1 )\n    \\end{eqnarray}\n\nThe example tests Rosen34 using the relations above:\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end ode_stiff.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n\n// To print the comparison, change the 0 to 1 on the next line.\n# define CPPAD_ODE_STIFF_PRINT 0\n\nnamespace {\n    // --------------------------------------------------------------\n    class Fun {\n    private:\n        CPPAD_TESTVECTOR(double) a;\n    public:\n        // constructor\n        Fun(const CPPAD_TESTVECTOR(double)& a_) : a(a_)\n        { }\n        // compute f(t, x)\n        void Ode(\n            const double                    &t,\n            const CPPAD_TESTVECTOR(double) &x,\n            CPPAD_TESTVECTOR(double)       &f)\n        {   f[0]  = - a[0] * x[0];\n            f[1]  = + a[0] * x[0] - a[1] * x[1];\n        }\n        // compute partial of f(t, x) w.r.t. t\n        void Ode_ind(\n            const double                    &t,\n            const CPPAD_TESTVECTOR(double) &x,\n            CPPAD_TESTVECTOR(double)       &f_t)\n        {   f_t[0] = 0.;\n            f_t[1] = 0.;\n        }\n        // compute partial of f(t, x) w.r.t. x\n        void Ode_dep(\n            const double                    &t,\n            const CPPAD_TESTVECTOR(double) &x,\n            CPPAD_TESTVECTOR(double)       &f_x)\n        {   f_x[0] = -a[0];\n            f_x[1] = 0.;\n            f_x[2] = +a[0];\n            f_x[3] = -a[1];\n        }\n    };\n    // --------------------------------------------------------------\n    class RungeMethod {\n    private:\n        Fun F;\n    public:\n        // constructor\n        RungeMethod(const CPPAD_TESTVECTOR(double) &a_) : F(a_)\n        { }\n        void step(\n            double                     ta ,\n            double                     tb ,\n            CPPAD_TESTVECTOR(double) &xa ,\n            CPPAD_TESTVECTOR(double) &xb ,\n            CPPAD_TESTVECTOR(double) &eb )\n        {   xb = CppAD::Runge45(F, 1, ta, tb, xa, eb);\n        }\n        size_t order(void)\n        {   return 5; }\n    };\n    class RosenMethod {\n    private:\n        Fun F;\n    public:\n        // constructor\n        RosenMethod(const CPPAD_TESTVECTOR(double) &a_) : F(a_)\n        { }\n        void step(\n            double                     ta ,\n            double                     tb ,\n            CPPAD_TESTVECTOR(double) &xa ,\n            CPPAD_TESTVECTOR(double) &xb ,\n            CPPAD_TESTVECTOR(double) &eb )\n        {   xb = CppAD::Rosen34(F, 1, ta, tb, xa, eb);\n        }\n        size_t order(void)\n        {   return 4; }\n    };\n}\n\nbool OdeStiff(void)\n{   bool ok = true;     // initial return value\n\n    CPPAD_TESTVECTOR(double) a(2);\n    a[0] = 1e3;\n    a[1] = 1.;\n    RosenMethod rosen(a);\n    RungeMethod runge(a);\n    Fun          gear(a);\n\n    CPPAD_TESTVECTOR(double) xi(2);\n    xi[0] = 1.;\n    xi[1] = 0.;\n\n    CPPAD_TESTVECTOR(double) eabs(2);\n    eabs[0] = 1e-6;\n    eabs[1] = 1e-6;\n\n    CPPAD_TESTVECTOR(double) ef(2);\n    CPPAD_TESTVECTOR(double) xf(2);\n    CPPAD_TESTVECTOR(double) maxabs(2);\n    size_t                nstep;\n\n    size_t k;\n    for(k = 0; k < 3; k++)\n    {\n        size_t M    = 5;\n        double ti   = 0.;\n        double tf   = 1.;\n        double smin = 1e-7;\n        double sini = 1e-7;\n        double smax = 1.;\n        double scur = .5;\n        double erel = 0.;\n\n        if( k == 0 )\n        {   xf = CppAD::OdeErrControl(rosen, ti, tf,\n            xi, smin, smax, scur, eabs, erel, ef, maxabs, nstep);\n        }\n        else if( k == 1 )\n        {   xf = CppAD::OdeErrControl(runge, ti, tf,\n            xi, smin, smax, scur, eabs, erel, ef, maxabs, nstep);\n        }\n        else if( k == 2 )\n        {   xf = CppAD::OdeGearControl(gear, M, ti, tf,\n            xi, smin, smax, sini, eabs, erel, ef, maxabs, nstep);\n        }\n        double x0 = exp(-a[0]*tf);\n        ok &= CppAD::NearEqual(x0, xf[0], 0., eabs[0]);\n        ok &= CppAD::NearEqual(0., ef[0], 0., eabs[0]);\n\n        double x1 = a[0] *\n            (exp(-a[1]*tf) - exp(-a[0]*tf))/(a[0] - a[1]);\n        ok &= CppAD::NearEqual(x1, xf[1], 0., eabs[1]);\n        ok &= CppAD::NearEqual(0., ef[1], 0., eabs[0]);\n# if CPPAD_ODE_STIFF_PRINT\n        const char* method[]={ \"Rosen34\", \"Runge45\", \"Gear5\" };\n        std::cout << std::endl;\n        std::cout << \"method     = \" << method[k] << std::endl;\n        std::cout << \"nstep      = \" << nstep  << std::endl;\n        std::cout << \"x0         = \" << x0 << std::endl;\n        std::cout << \"xf[0]      = \" << xf[0] << std::endl;\n        std::cout << \"x0 - xf[0] = \" << x0 - xf[0] << std::endl;\n        std::cout << \"ef[0]      = \" << ef[0] << std::endl;\n        std::cout << \"x1         = \" << x1 << std::endl;\n        std::cout << \"xf[1]      = \" << xf[1] << std::endl;\n        std::cout << \"x1 - xf[1] = \" << x1 - xf[1] << std::endl;\n        std::cout << \"ef[1]      = \" << ef[1] << std::endl;\n# endif\n    }\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/opt_val_hes.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin opt_val_hes.cpp app}\n\nopt_val_hes: Example and Test\n#############################\n\nFix :math:`z \\in \\B{R}^\\ell` and define the functions\n:math:`S_k : \\B{R} \\times \\B{R} \\rightarrow \\B{R}^\\ell` by and\n:math:`F : \\B{R} \\times \\B{R} \\rightarrow \\B{R}` by\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    S_k (x, y) & = & \\frac{1}{2} [ y * \\sin ( x * t_k ) - z_k ]^2\n    \\\\\n    F(x, y)    & = &  \\sum_{k=0}^{\\ell-1} S_k (x, y)\n    \\end{eqnarray}\n\nIt follows that\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    \\partial_y F(x, y)\n    & = &\n    \\sum_{k=0}^{\\ell-1} [ y * \\sin ( x * t_k ) - z_k ] \\sin( x * t_k )\n    \\\\\n    \\partial_y \\partial_y F(x, y)\n    & = &\n    \\sum_{k=0}^{\\ell-1} \\sin ( x t_k )^2\n    \\end{eqnarray}\n\nFurthermore if we define :math:`Y(x)`\nas solving the equation :math:`\\partial F[ x, Y(x) ] = 0` we have\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    0 & = &\n    \\sum_{k=0}^{\\ell-1} [ Y(x) * \\sin ( x * t_k ) - z_k ] \\sin( x * t_k )\n    \\\\\n    Y(x) \\sum_{k=0}^{\\ell-1} \\sin ( x * t_k )^2\n    - \\sum_{k=0}^{\\ell-1} \\sin ( x * t_k ) z_k\n    \\\\\n    Y(x) & = & \\frac{\n        \\sum_{k=0}^{\\ell-1} \\sin( x * t_k ) z_k\n        }{\n        \\sum_{k=0}^{\\ell-1} \\sin ( x * t_k )^2\n    }\n    \\end{eqnarray}\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end opt_val_hes.cpp}\n*/\n// BEGIN C++\n\n# include <limits>\n# include <cppad/cppad.hpp>\n\nnamespace {\n    using CppAD::AD;\n    typedef CPPAD_TESTVECTOR(double)       BaseVector;\n    typedef CPPAD_TESTVECTOR(AD<double>) ADVector;\n\n    class Fun {\n    private:\n        const BaseVector t_;    // measurement times\n        const BaseVector z_;    // measurement values\n    public:\n        typedef ADVector ad_vector;\n        // constructor\n        Fun(const BaseVector &t, const BaseVector &z)\n        : t_(t) , z_(z)\n        {   assert( t.size() == z.size() ); }\n        // ell\n        size_t ell(void) const\n        {   return t_.size(); }\n        // Fun.s\n        AD<double> s(size_t k, const ad_vector& x, const ad_vector& y) const\n        {\n            AD<double> residual = y[0] * sin( x[0] * t_[k] ) - z_[k];\n            AD<double> s_k      = .5 * residual * residual;\n\n            return s_k;\n        }\n        // Fun.sy\n        ad_vector sy(size_t k, const ad_vector& x, const ad_vector& y) const\n        {   assert( y.size() == 1);\n            ad_vector sy_k(1);\n\n            AD<double> residual = y[0] * sin( x[0] * t_[k] ) - z_[k];\n            sy_k[0] = residual * sin( x[0] * t_[k] );\n\n            return sy_k;\n        }\n    };\n    // Used to test calculation of Hessian of V\n    AD<double> V(const ADVector& x, const BaseVector& t, const BaseVector& z)\n    {   // compute Y(x)\n        AD<double> numerator = 0.;\n        AD<double> denominator = 0.;\n        size_t k;\n        for(k = 0; k < size_t(t.size()); k++)\n        {   numerator   += sin( x[0] * t[k] ) * z[k];\n            denominator += sin( x[0] * t[k] ) * sin( x[0] * t[k] );\n        }\n        AD<double> y = numerator / denominator;\n\n        // V(x) = F[x, Y(x)]\n        AD<double> sum = 0;\n        for(k = 0; k < size_t(t.size()); k++)\n        {   AD<double> residual = y * sin( x[0] * t[k] ) - z[k];\n            sum += .5 * residual * residual;\n        }\n        return sum;\n    }\n}\n\nbool opt_val_hes(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n\n    // temporary indices\n    size_t j, k;\n\n    // x space vector\n    size_t n = 1;\n    BaseVector x(n);\n    x[0] = 2. * 3.141592653;\n\n    // y space vector\n    size_t m = 1;\n    BaseVector y(m);\n    y[0] = 1.;\n\n    // t and z vectors\n    size_t ell = 10;\n    BaseVector t(ell);\n    BaseVector z(ell);\n    for(k = 0; k < ell; k++)\n    {   t[k] = double(k) / double(ell);       // time of measurement\n        z[k] = y[0] * sin( x[0] * t[k] );     // data without noise\n    }\n\n    // construct the function object\n    Fun fun(t, z);\n\n    // evaluate the Jacobian and Hessian\n    BaseVector jac(n), hes(n * n);\n# ifndef NDEBUG\n    int signdet =\n# endif\n    CppAD::opt_val_hes(x, y, fun, jac, hes);\n\n    // we know that F_yy is positive definite for this case\n    assert( signdet == 1 );\n\n    // create ADFun object g corresponding to V(x)\n    ADVector a_x(n), a_v(1);\n    for(j = 0; j < n; j++)\n        a_x[j] = x[j];\n    Independent(a_x);\n    a_v[0] = V(a_x, t, z);\n    CppAD::ADFun<double> g(a_x, a_v);\n\n    // accuracy for checks\n    double eps = 10. * CppAD::numeric_limits<double>::epsilon();\n\n    // check Jacobian\n    BaseVector check_jac = g.Jacobian(x);\n    for(j = 0; j < n; j++)\n        ok &= NearEqual(jac[j], check_jac[j], eps, eps);\n\n    // check Hessian\n    BaseVector check_hes = g.Hessian(x, 0);\n    for(j = 0; j < n*n; j++)\n        ok &= NearEqual(hes[j], check_hes[j], eps, eps);\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/pow.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin pow.cpp}\n\nThe AD Power Function: Example and Test\n#######################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end pow.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n# include <cmath>\n\nbool pow(void)\n{   bool ok = true;\n\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps = 10. * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n  = 2;\n    double x = 0.5;\n    double y = 2.;\n    CPPAD_TESTVECTOR(AD<double>) axy(n);\n    axy[0]      = x;\n    axy[1]      = y;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(axy);\n\n    // range space vector\n    size_t m = 3;\n    CPPAD_TESTVECTOR(AD<double>) az(m);\n    az[0] = CppAD::pow(axy[0], axy[1]); // pow(variable, variable)\n    az[1] = CppAD::pow(axy[0], y);      // pow(variable, parameter)\n    az[2] = CppAD::pow(x,     axy[1]);  // pow(parameter, variable)\n\n    // create f: axy -> az and stop tape recording\n    CppAD::ADFun<double> f(axy, az);\n\n    // check value\n    double check = std::pow(x, y);\n    size_t i;\n    for(i = 0; i < m; i++)\n        ok &= NearEqual(az[i] , check,  eps, eps);\n\n    // forward computation of first partial w.r.t. x\n    CPPAD_TESTVECTOR(double) dxy(n);\n    CPPAD_TESTVECTOR(double) dz(m);\n    dxy[0] = 1.;\n    dxy[1] = 0.;\n    dz    = f.Forward(1, dxy);\n    check = y * std::pow(x, y-1.);\n    ok   &= NearEqual(dz[0], check, eps, eps);\n    ok   &= NearEqual(dz[1], check, eps, eps);\n    ok   &= NearEqual(dz[2],    0., eps, eps);\n\n    // forward computation of first partial w.r.t. y\n    dxy[0] = 0.;\n    dxy[1] = 1.;\n    dz    = f.Forward(1, dxy);\n    check = std::log(x) * std::pow(x, y);\n    ok   &= NearEqual(dz[0], check, eps, eps);\n    ok   &= NearEqual(dz[1],    0., eps, eps);\n    ok   &= NearEqual(dz[2], check, eps, eps);\n\n    // reverse computation of derivative of z[0] + z[1] + z[2]\n    CPPAD_TESTVECTOR(double)  w(m);\n    CPPAD_TESTVECTOR(double) dw(n);\n    w[0]  = 1.;\n    w[1]  = 1.;\n    w[2]  = 1.;\n    dw    = f.Reverse(1, w);\n    check = y * std::pow(x, y-1.);\n    ok   &= NearEqual(dw[0], 2. * check, eps, eps);\n    check = std::log(x) * std::pow(x, y);\n    ok   &= NearEqual(dw[1], 2. * check, eps, eps);\n\n    // use a VecAD<Base>::reference object with pow\n    CppAD::VecAD<double> v(2);\n    AD<double> zero(0);\n    AD<double> one(1);\n    v[zero]           = axy[0];\n    v[one]            = axy[1];\n    AD<double> result = CppAD::pow(v[zero], v[one]);\n    ok               &= NearEqual(result, az[0], eps, eps);\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/pow_nan.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin pow_nan.cpp}\n\npow: Nan in Result of Pow Function: Example and Test\n####################################################\n\nPurpose\n*******\nThe :ref:`pow(x, y)<pow-name>` function will work when :math:`x < 0` and\n:math:`y`  is a parameter. It will often generate nan or infinity when\n:math:`x < 0` and one tries to compute a derivatives\n(even if :math:`y` is a positive integer).\nThis is because the derivative of the log is :math:`1 / x`\nand the power function uses the representation\n\n.. math::\n\n    \\R{pow}(x, y) = \\exp [ y \\cdot \\log(x) ]\n\nProblem\n*******\nThere is a problem with this representation when :math:`y` is a parameter\nand :math:`x = 0`. For example,\nwhen :math:`x = 0` and :math:`y = 1`, it returns zero for the derivative,\nbut the actual derivative w.r.t :math:`x` is one.\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end pow_nan.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n# include <cmath>\n\nbool pow_nan(void)\n{   bool ok = true;\n\n    using std::cout;\n    using CppAD::AD;\n    using CppAD::vector;\n    //\n    vector<double>       x(2), y(2), dx(2), dy(2), ddx(2), ddy(2);\n    vector< AD<double> > ax(2), ay(2);\n    //\n    // variable vector\n    ax[0] = x[0]  = -1.0;\n    ax[1] = x[1] = 2.0;\n    //\n    CppAD::Independent(ax);\n    //\n    ay[0] = pow( ax[0], ax[1] );\n    ay[1] = pow( ax[0], 2.0 );\n    //\n    CppAD::ADFun<double> f(ax, ay);\n    //\n    // check_for_nan is set false so it does not generate an assert\n    // when compiling with debugging\n    f.check_for_nan(false);\n    //\n    // Zero order forward does not generate nan\n    y  = f.Forward(0, x);\n    ok &= y[0] == 1.0;\n    ok &= y[1] == 1.0;\n    //\n    // First order forward generates a nan\n    dx[0] = 1.0;\n    dx[1] = 1.0;\n    dy = f.Forward(1, dx);\n    ok &= std::isnan( dy[0] );\n    ok &= dy[1] == -2.0;\n    //\n    // Second order Taylor coefficient is 1/2 times second derivative\n    ddx[0] = 0.0;\n    ddx[1] = 0.0;\n    ddy = f.Forward(2, ddx);\n    ok &= std::isnan( ddy[0] );\n    ok &= ddy[1] == 1.0;\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/general/print_for.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin print_for_string.cpp}\n\nPrint During Zero Order Forward Mode: Example and Test\n######################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end print_for_string.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nnamespace {\n    using std::endl;\n    using CppAD::AD;\n\n    // use of PrintFor to check for invalid function arguments\n    AD<double> check_log(const AD<double>& u, std::ostream& s_out)\n    {   // check AD<double> value during recording\n        if( u <= 0 )\n            s_out << \"check_log: u = \" << u << \" which is <= 0\\n\";\n\n        // check double value during zero order forward calculation\n        PrintFor(u, \"check_log: u = \", u , \" which is <= 0\\n\");\n\n        return log(u);\n    }\n}\n\nbool print_for(void)\n{   bool ok = true;\n    using CppAD::PrintFor;\n    std::stringstream stream_out;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // independent variable vector\n    size_t np = 1;\n    size_t nx = 1;\n    size_t ny = 1;\n    CPPAD_TESTVECTOR(AD<double>) ap(np), ax(nx), ay(ny);\n    ap[0] = 1.0;\n    ax[0] = 2.0;\n    Independent(ax, ap);\n    //\n    // define f(x, p) = log(p) + log(x)\n    ay[0] = check_log(ap[0], stream_out) + check_log(ax[0], stream_out);\n    CppAD::ADFun<double> f(ax, ay);\n    //\n    // zero order forward\n    // both x and p are positive so no output generated\n    CPPAD_TESTVECTOR(double) p(np), x(nx), y(ny);\n    p[0] = 1.0;\n    x[0] = 2.0;\n    f.new_dynamic(p);\n    f.check_for_nan(false);\n    y = f.Forward(0, x, stream_out);\n    ok &= stream_out.str() == \"\";\n    ok &= CppAD::NearEqual(y[0], std::log(p[0]) + std::log(x[0]), eps99, eps99);\n    //\n    // zero order forward\n    // p is negative so output generated\n    p[0] = -1.0;\n    x[0] = 2.0;\n    f.new_dynamic(p);\n    f.check_for_nan(false);\n    y = f.Forward(0, x, stream_out);\n    ok &= stream_out.str() == \"check_log: u = -1 which is <= 0\\n\";\n    ok &= std::isnan(y[0]);\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/general/rev_checkpoint.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin rev_checkpoint.cpp}\n\nReverse Mode General Case (Checkpointing): Example and Test\n###########################################################\n\nSee Also\n********\n:ref:`checkpoint<chkpoint_one-name>`\n\nPurpose\n*******\nBreak a large computation into pieces and only store values at the\ninterface of the pieces (this is much easier to do using :ref:`checkpoint<chkpoint_one-name>` ).\nIn actual applications, there may be many functions, but\nfor this example there are only two.\nThe functions\n:math:`F : \\B{R}^2 \\rightarrow \\B{R}^2`\nand\n:math:`G : \\B{R}^2 \\rightarrow \\B{R}^2`\ndefined by\n\n.. math::\n\n    F(x) = \\left( \\begin{array}{c} x_0 x_1   \\\\ x_1 - x_0 \\end{array} \\right)\n    \\; , \\;\n    G(y) = \\left( \\begin{array}{c} y_0 - y_1 \\\\ y_1  y_0   \\end{array} \\right)\n\nProcessing Steps\n****************\nWe apply reverse mode to compute the derivative of\n:math:`H : \\B{R}^2 \\rightarrow \\B{R}`\nis defined by\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        H(x)\n        & = & G_0 [ F(x) ] + G_1 [ F(x)  ]\n        \\\\\n        & = & x_0 x_1 - ( x_1 - x_0 ) + x_0 x_1 ( x_1 - x_0 )\n        \\\\\n        & = & x_0 x_1 ( 1 - x_0 + x_1 ) - x_1 + x_0\n    \\end{eqnarray}\n\nGiven the zero and first order Taylor coefficients\n:math:`x^{(0)}` and :math:`x^{(1)}`,\nwe use :math:`X(t)`, :math:`Y(t)` and :math:`Z(t)`\nfor the corresponding functions; i.e.,\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        X(t) & = & x^{(0)} + x^{(1)} t\n        \\\\\n        Y(t) & = & F[X(t)] = y^{(0)} + y^{(1)} t  + O(t^2)\n        \\\\\n        Z(t) & = & G \\{ F [ X(t) ] \\} = z^{(0)} + z^{(1)} t  + O(t^2)\n        \\\\\n        h^{(0)} & = & z^{(0)}_0 + z^{(0)}_1\n        \\\\\n        h^{(1)} & = & z^{(1)}_0 + z^{(1)}_1\n    \\end{eqnarray}\n\nHere are the processing steps:\n\n#. Use forward mode on :math:`F(x)` to compute\n   :math:`y^{(0)}` and :math:`y^{(1)}`.\n#. Free some, or all, of the memory corresponding to :math:`F(x)`.\n#. Use forward mode on :math:`G(y)` to compute\n   :math:`z^{(0)}` and :math:`z^{(1)}`\n#. Use reverse mode on :math:`G(y)` to compute the derivative of\n   :math:`h^{(1)}` with respect to\n   :math:`y^{(0)}` and :math:`y^{(1)}`.\n#. Free all the memory corresponding to :math:`G(y)`.\n#. Use reverse mode on :math:`F(x)` to compute the derivative of\n   :math:`h^{(1)}` with respect to\n   :math:`x^{(0)}` and :math:`x^{(1)}`.\n\nThis uses the following relations:\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        \\partial_{x(0)} h^{(1)} [ x^{(0)} , x^{(1)} ]\n        & = &\n        \\partial_{y(0)} h^{(1)} [ y^{(0)} , y^{(1)} ]\n        \\partial_{x(0)} y^{(0)} [ x^{(0)} , x^{(1)} ]\n        \\\\\n        & + &\n        \\partial_{y(1)} h^{(1)} [ y^{(0)} , y^{(1)} ]\n        \\partial_{x(0)} y^{(1)} [ x^{(0)} , x^{(1)} ]\n        \\\\\n        \\partial_{x(1)} h^{(1)} [ x^{(0)} , x^{(1)} ]\n        & = &\n        \\partial_{y(0)} h^{(1)} [ y^{(0)} , y^{(1)} ]\n        \\partial_{x(1)} y^{(0)} [ x^{(0)} , x^{(1)} ]\n        \\\\\n        & + &\n        \\partial_{y(1)} h^{(1)} [ y^{(0)} , y^{(1)} ]\n        \\partial_{x(1)} y^{(1)} [ x^{(0)} , x^{(1)} ]\n    \\end{eqnarray}\n\nwhere :math:`\\partial_{x(0)}` denotes the partial with respect\nto :math:`x^{(0)}`.\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end rev_checkpoint.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n\nnamespace {\n    template <class Vector>\n    Vector F(const Vector& x)\n    {   Vector y(2);\n        y[0] = x[0] * x[1];\n        y[1] = x[1] - x[0];\n        return y;\n    }\n    template <class Vector>\n    Vector G(const Vector& y)\n    {   Vector z(2);\n        z[0] = y[0] - y[1];\n        z[1] = y[1] * y[0];\n        return z;\n    }\n}\n\nnamespace {\n    bool rev_checkpoint_case(bool free_all)\n    {   bool ok = true;\n    double eps = 10. * CppAD::numeric_limits<double>::epsilon();\n\n        using CppAD::AD;\n        using CppAD::NearEqual;\n        CppAD::ADFun<double> f, g, empty;\n\n        // specify the Taylor coefficients for X(t)\n        size_t n    = 2;\n        CPPAD_TESTVECTOR(double) x0(n), x1(n);\n        x0[0] = 1.; x0[1] = 2.;\n        x1[0] = 3.; x1[1] = 4.;\n\n        // record the function F(x)\n        CPPAD_TESTVECTOR(AD<double>) X(n), Y(n);\n        size_t i;\n        for(i = 0; i < n; i++)\n            X[i] = x0[i];\n        CppAD::Independent(X);\n        Y = F(X);\n        f.Dependent(X, Y);\n\n        // a function object with an almost empty operation sequence\n        CppAD::Independent(X);\n        empty.Dependent(X, X);\n\n        // compute the Taylor coefficients for Y(t)\n        CPPAD_TESTVECTOR(double) y0(n), y1(n);\n        y0 = f.Forward(0, x0);\n        y1 = f.Forward(1, x1);\n        if( free_all )\n            f = empty;\n        else\n        {   // free all the Taylor coefficients stored in f\n            f.capacity_order(0);\n        }\n\n        // record the function G(x)\n        CPPAD_TESTVECTOR(AD<double>) Z(n);\n        CppAD::Independent(Y);\n        Z = G(Y);\n        g.Dependent(Y, Z);\n\n        // compute the Taylor coefficients for Z(t)\n        CPPAD_TESTVECTOR(double) z0(n), z1(n);\n        z0 = g.Forward(0, y0);\n        z1 = g.Forward(1, y1);\n\n        // check zero order Taylor coefficient for h^0 = z_0^0 + z_1^0\n        double check = x0[0] * x0[1] * (1. - x0[0] + x0[1]) - x0[1] + x0[0];\n        double h0    = z0[0] + z0[1];\n        ok          &= NearEqual(h0, check, eps, eps);\n\n        // check first order Taylor coefficient h^1\n        check     = x0[0] * x0[1] * (- x1[0] + x1[1]) - x1[1] + x1[0];\n        check    += x1[0] * x0[1] * (1. - x0[0] + x0[1]);\n        check    += x0[0] * x1[1] * (1. - x0[0] + x0[1]);\n        double h1 = z1[0] + z1[1];\n        ok       &= NearEqual(h1, check, eps, eps);\n\n        // compute the derivative with respect to y^0 and y^0 of h^1\n        size_t p = 2;\n        CPPAD_TESTVECTOR(double) w(n*p), dw(n*p);\n        w[0*p+0] = 0.; // coefficient for z_0^0\n        w[0*p+1] = 1.; // coefficient for z_0^1\n        w[1*p+0] = 0.; // coefficient for z_1^0\n        w[1*p+1] = 1.; // coefficient for z_1^1\n        dw       = g.Reverse(p, w);\n\n        // We are done using g, so we can free its memory.\n        g = empty;\n        // We need to use f next.\n        if( free_all )\n        {   // we must again record the operation sequence for F(x)\n            CppAD::Independent(X);\n            Y = F(X);\n            f.Dependent(X, Y);\n        }\n        // now recompute the Taylor coefficients corresponding to F(x)\n        // (we already know the result; i.e., y0 and y1).\n        f.Forward(0, x0);\n        f.Forward(1, x1);\n\n        // compute the derivative with respect to x^0 and x^0 of\n        //    h^1 = z_0^1 + z_1^1\n        CPPAD_TESTVECTOR(double) dv(n*p);\n        dv   = f.Reverse(p, dw);\n\n        // check partial of h^1 w.r.t x^0_0\n        check  = x0[1] * (- x1[0] + x1[1]);\n        check -= x1[0] * x0[1];\n        check += x1[1] * (1. - x0[0] + x0[1]) - x0[0] * x1[1];\n        ok    &= NearEqual(dv[0*p+0], check, eps, eps);\n\n        // check partial of h^1 w.r.t x^0_1\n        check  = x0[0] * (- x1[0] + x1[1]);\n        check += x1[0] * (1. - x0[0] + x0[1]) + x1[0] * x0[1];\n        check += x0[0] * x1[1];\n        ok    &= NearEqual(dv[1*p+0], check, eps, eps);\n\n        // check partial of h^1 w.r.t x^1_0\n        check  = 1. - x0[0] * x0[1];\n        check += x0[1] * (1. - x0[0] + x0[1]);\n        ok    &= NearEqual(dv[0*p+1], check, eps, eps);\n\n        // check partial of h^1 w.r.t x^1_1\n        check  = x0[0] * x0[1] - 1.;\n        check += x0[0] * (1. - x0[0] + x0[1]);\n        ok    &= NearEqual(dv[1*p+1], check, eps, eps);\n\n        return ok;\n    }\n}\nbool rev_checkpoint(void)\n{   bool ok = true;\n    ok     &= rev_checkpoint_case(true);\n    ok     &= rev_checkpoint_case(false);\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/rev_one.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin rev_one.cpp}\n\nFirst Order Derivative Driver: Example and Test\n###############################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end rev_one.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\nnamespace { // -------------------------------------------------------\n// define the template function RevOneCases<Vector> in empty namespace\ntemplate <class Vector>\nbool RevOneCases()\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    using CppAD::exp;\n    using CppAD::sin;\n    using CppAD::cos;\n\n    // domain space vector\n    size_t n = 2;\n    CPPAD_TESTVECTOR(AD<double>)  X(n);\n    X[0] = 1.;\n    X[1] = 2.;\n\n    // declare independent variables and starting recording\n    CppAD::Independent(X);\n\n    // range space vector\n    size_t m = 3;\n    CPPAD_TESTVECTOR(AD<double>)  Y(m);\n    Y[0] = X[0] * exp( X[1] );\n    Y[1] = X[0] * sin( X[1] );\n    Y[2] = X[0] * cos( X[1] );\n\n    // create f: X -> Y and stop tape recording\n    CppAD::ADFun<double> f(X, Y);\n\n    // new value for the independent variable vector\n    Vector x(n);\n    x[0] = 2.;\n    x[1] = 1.;\n\n    // compute and check derivative of y[0]\n    Vector dw(n);\n    dw  = f.RevOne(x, 0);\n    ok &= NearEqual(dw[0],      exp(x[1]), eps99, eps99); // w.r.t x[0]\n    ok &= NearEqual(dw[1], x[0]*exp(x[1]), eps99, eps99); // w.r.t x[1]\n\n    // compute and check derivative of y[1]\n    dw  = f.RevOne(x, 1);\n    ok &= NearEqual(dw[0],      sin(x[1]), eps99, eps99);\n    ok &= NearEqual(dw[1], x[0]*cos(x[1]), eps99, eps99);\n\n    // compute and check derivative of y[2]\n    dw  = f.RevOne(x, 2);\n    ok &= NearEqual(dw[0],        cos(x[1]), eps99, eps99);\n    ok &= NearEqual(dw[1], - x[0]*sin(x[1]), eps99, eps99);\n\n    return ok;\n}\n} // End empty namespace\n# include <vector>\n# include <valarray>\nbool RevOne(void)\n{   bool ok = true;\n    // Run with Vector equal to three different cases\n    // all of which are Simple Vectors with elements of type double.\n    ok &= RevOneCases< CppAD::vector  <double> >();\n    ok &= RevOneCases< std::vector    <double> >();\n    ok &= RevOneCases< std::valarray  <double> >();\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/general/rev_two.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin rev_two.cpp}\n\nSecond Partials Reverse Driver: Example and Test\n################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end rev_two.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\nnamespace { // -----------------------------------------------------\n// define the template function in empty namespace\n// bool RevTwoCases<BaseVector, SizeVector_t>(void)\ntemplate <class BaseVector, class SizeVector_t>\nbool RevTwoCases()\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    using CppAD::exp;\n    using CppAD::sin;\n    using CppAD::cos;\n\n    // domain space vector\n    size_t n = 2;\n    CPPAD_TESTVECTOR(AD<double>)  X(n);\n    X[0] = 1.;\n    X[1] = 2.;\n\n    // declare independent variables and starting recording\n    CppAD::Independent(X);\n\n    // a calculation between the domain and range values\n    AD<double> Square = X[0] * X[0];\n\n    // range space vector\n    size_t m = 3;\n    CPPAD_TESTVECTOR(AD<double>)  Y(m);\n    Y[0] = Square * exp( X[1] );\n    Y[1] = Square * sin( X[1] );\n    Y[2] = Square * cos( X[1] );\n\n    // create f: X -> Y and stop tape recording\n    CppAD::ADFun<double> f(X, Y);\n\n    // new value for the independent variable vector\n    BaseVector x(n);\n    x[0] = 2.;\n    x[1] = 1.;\n\n    // set i and j to compute specific second partials of y\n    size_t p = 2;\n    SizeVector_t i(p);\n    SizeVector_t j(p);\n    i[0] = 0; j[0] = 0; // for partials y[0] w.r.t x[0] and x[k]\n    i[1] = 1; j[1] = 1; // for partials y[1] w.r.t x[1] and x[k]\n\n    // compute the second partials\n    BaseVector ddw(n * p);\n    ddw = f.RevTwo(x, i, j);\n\n    // partials of y[0] w.r.t x[0] is 2 * x[0] * exp(x[1])\n    // check partials of y[0] w.r.t x[0] and x[k] for k = 0, 1\n    ok &=  NearEqual(      2.*exp(x[1]), ddw[0*p+0], eps99, eps99);\n    ok &=  NearEqual( 2.*x[0]*exp(x[1]), ddw[1*p+0], eps99, eps99);\n\n    // partials of y[1] w.r.t x[1] is x[0] * x[0] * cos(x[1])\n    // check partials of F_1 w.r.t x[1] and x[k] for k = 0, 1\n    ok &=  NearEqual(    2.*x[0]*cos(x[1]), ddw[0*p+1], eps99, eps99);\n    ok &=  NearEqual( -x[0]*x[0]*sin(x[1]), ddw[1*p+1], eps99, eps99);\n\n    return ok;\n}\n} // End empty namespace\n# include <vector>\n# include <valarray>\nbool RevTwo(void)\n{   bool ok = true;\n        // Run with BaseVector equal to three different cases\n        // all of which are Simple Vectors with elements of type double.\n    ok &= RevTwoCases< CppAD::vector <double>, std::vector<size_t> >();\n    ok &= RevTwoCases< std::vector   <double>, std::vector<size_t> >();\n    ok &= RevTwoCases< std::valarray <double>, std::vector<size_t> >();\n\n        // Run with SizeVector_t equal to two other cases\n        // which are Simple Vectors with elements of type size_t.\n    ok &= RevTwoCases< std::vector <double>, CppAD::vector<size_t> >();\n    ok &= RevTwoCases< std::vector <double>, std::valarray<size_t> >();\n\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/general/reverse_one.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin reverse_one.cpp}\n\nFirst Order Reverse Mode: Example and Test\n##########################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end reverse_one.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\nnamespace { // ----------------------------------------------------------\n// define the template function reverse_one_cases<Vector> in empty namespace\ntemplate <class Vector>\nbool reverse_one_cases(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n = 2;\n    CPPAD_TESTVECTOR(AD<double>) ax(n);\n    ax[0] = 0.;\n    ax[1] = 1.;\n\n    // declare independent variables and start recording\n    CppAD::Independent(ax);\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) ay(m);\n    ay[0] = ax[0] * ax[0] * ax[1];\n\n    // create f : x -> y and stop recording\n    CppAD::ADFun<double> f(ax, ay);\n\n    // use first order reverse mode to evaluate derivative of y[0]\n    // and use the values in x for the independent variables.\n    CPPAD_TESTVECTOR(double) w(m), dw(n);\n    w[0] = 1.;\n    dw   = f.Reverse(1, w);\n    ok  &= NearEqual(dw[0] , 2.*ax[0]*ax[1], eps99, eps99);\n    ok  &= NearEqual(dw[1] ,    ax[0]*ax[0], eps99, eps99);\n\n    // use zero order forward mode to evaluate y at x = (3, 4)\n    // and use the template parameter Vector for the vector type\n    Vector x(n), y(m);\n    x[0]    = 3.;\n    x[1]    = 4.;\n    y       = f.Forward(0, x);\n    ok     &= NearEqual(y[0] , x[0]*x[0]*x[1], eps99, eps99);\n\n    // use first order reverse mode to evaluate derivative of y[0]\n    // and using the values in x for the independent variables.\n    w[0] = 1.;\n    dw   = f.Reverse(1, w);\n    ok  &= NearEqual(dw[0] , 2.*x[0]*x[1], eps99, eps99);\n    ok  &= NearEqual(dw[1] ,    x[0]*x[0], eps99, eps99);\n\n    return ok;\n}\n} // End empty namespace\n# include <vector>\n# include <valarray>\nbool reverse_one(void)\n{   bool ok = true;\n    // Run with Vector equal to three different cases\n    // all of which are Simple Vectors with elements of type double.\n    ok &= reverse_one_cases< CppAD::vector  <double> >();\n    ok &= reverse_one_cases< std::vector    <double> >();\n    ok &= reverse_one_cases< std::valarray  <double> >();\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/general/reverse_three.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin reverse_three.cpp}\n\nThird Order Reverse Mode: Example and Test\n##########################################\n\nTaylor Coefficients\n*******************\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        X(t) & = & x^{(0)} + x^{(1)} t + x^{(2)} t^2\n        \\\\\n        X^{(1)} (t) & = &  x^{(1)} + 2 x^{(2)} t\n        \\\\\n        X^{(2)} (t) & = &   2 x^{(2)}\n    \\end{eqnarray}\n\nThus, we need to be careful to properly account for the fact that\n:math:`X^{(2)} (0) = 2 x^{(2)}`\n(and similarly :math:`Y^{(2)} (0) = 2 y^{(2)}`).\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end reverse_three.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\nnamespace { // ----------------------------------------------------------\n// define the template function cases<Vector> in empty namespace\ntemplate <class Vector>\nbool cases(void)\n{   bool ok    = true;\n    double eps = 10. * CppAD::numeric_limits<double>::epsilon();\n    using CppAD::AD;\n    using CppAD::NearEqual;\n\n    // domain space vector\n    size_t n = 2;\n    CPPAD_TESTVECTOR(AD<double>) X(n);\n    X[0] = 0.;\n    X[1] = 1.;\n\n    // declare independent variables and start recording\n    CppAD::Independent(X);\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) Y(m);\n    Y[0] = X[0] * X[1];\n\n    // create f : X -> Y and stop recording\n    CppAD::ADFun<double> f(X, Y);\n\n    // define x^0 and compute y^0 using user zero order forward\n    Vector x0(n), y0(m);\n    x0[0]    = 2.;\n    x0[1]    = 3.;\n    y0       = f.Forward(0, x0);\n\n    // y^0 = F(x^0)\n    double check;\n    check    =  x0[0] * x0[1];\n    ok      &= NearEqual(y0[0] , check, eps, eps);\n\n    // define x^1 and compute y^1 using first order forward mode\n    Vector x1(n), y1(m);\n    x1[0] = 4.;\n    x1[1] = 5.;\n    y1    = f.Forward(1, x1);\n\n    // Y^1 (x) = partial_t F( x^0 + x^1 * t )\n    // y^1     = Y^1 (0)\n    check = x1[0] * x0[1] + x0[0] * x1[1];\n    ok   &= NearEqual(y1[0], check, eps, eps);\n\n    // define x^2 and compute y^2 using second order forward mode\n    Vector x2(n), y2(m);\n    x2[0] = 6.;\n    x2[1] = 7.;\n    y2    = f.Forward(2, x2);\n\n    // Y^2 (x) = partial_tt F( x^0 + x^1 * t + x^2 * t^2 )\n    // y^2     = (1/2) *  Y^2 (0)\n    check  = x2[0] * x0[1] + x1[0] * x1[1] + x0[0] * x2[1];\n    ok    &= NearEqual(y2[0], check, eps, eps);\n\n    // W(x)  = Y^0 (x) + 2 * Y^1 (x) + 3 * (1/2) * Y^2 (x)\n    size_t p = 3;\n    Vector dw(n*p), w(m*p);\n    w[0] = 1.;\n    w[1] = 2.;\n    w[2] = 3.;\n    dw   = f.Reverse(p, w);\n\n    // check partial w.r.t x^0_0 of W(x)\n    check = x0[1] + 2. * x1[1] + 3. * x2[1];\n    ok   &= NearEqual(dw[0*p+0], check, eps, eps);\n\n    // check partial w.r.t x^0_1 of W(x)\n    check = x0[0] + 2. * x1[0] + 3. * x2[0];\n    ok   &= NearEqual(dw[1*p+0], check, eps, eps);\n\n    // check partial w.r.t x^1_0 of W(x)\n    check = 2. * x0[1] + 3. * x1[1];\n    ok   &= NearEqual(dw[0*p+1], check, eps, eps);\n\n    // check partial w.r.t x^1_1 of W(x)\n    check = 2. * x0[0] + 3. * x1[0];\n    ok   &= NearEqual(dw[1*p+1], check, eps, eps);\n\n    // check partial w.r.t x^2_0 of W(x)\n    check = 3. * x0[1];\n    ok   &= NearEqual(dw[0*p+2], check, eps, eps);\n\n    // check partial w.r.t x^2_1 of W(x)\n    check = 3. * x0[0];\n    ok   &= NearEqual(dw[1*p+2], check, eps, eps);\n\n    return ok;\n}\n} // End empty namespace\n# include <vector>\n# include <valarray>\nbool reverse_three(void)\n{   bool ok = true;\n    ok &= cases< CppAD::vector  <double> >();\n    ok &= cases< std::vector    <double> >();\n    ok &= cases< std::valarray  <double> >();\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/general/reverse_two.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin reverse_two.cpp}\n\nSecond Order Reverse ModeExample and Test\n#########################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end reverse_two.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\nnamespace { // ----------------------------------------------------------\n// define the template function reverse_two_cases<Vector> in empty namespace\ntemplate <class Vector>\nbool reverse_two_cases(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n = 2;\n    CPPAD_TESTVECTOR(AD<double>) X(n);\n    X[0] = 0.;\n    X[1] = 1.;\n\n    // declare independent variables and start recording\n    CppAD::Independent(X);\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) Y(m);\n    Y[0] = X[0] * X[0] * X[1];\n\n    // create f : X -> Y and stop recording\n    CppAD::ADFun<double> f(X, Y);\n\n    // use zero order forward mode to evaluate y at x = (3, 4)\n    // use the template parameter Vector for the vector type\n    Vector x(n), y(m);\n    x[0]  = 3.;\n    x[1]  = 4.;\n    y     = f.Forward(0, x);\n    ok    &= NearEqual(y[0] , x[0]*x[0]*x[1], eps99, eps99);\n\n    // use first order forward mode in x[0] direction\n    // (all second order partials below involve x[0])\n    Vector dx(n), dy(m);\n    dx[0] = 1.;\n    dx[1] = 1.;\n    dy    = f.Forward(1, dx);\n    double check = 2.*x[0]*x[1]*dx[0] + x[0]*x[0]*dx[1];\n    ok   &= NearEqual(dy[0], check, eps99, eps99);\n\n    // use second order reverse mode to evalaute second partials of y[0]\n    // with respect to (x[0], x[0]) and with respect to (x[0], x[1])\n    Vector w(m), dw( n * 2 );\n    w[0]  = 1.;\n    dw    = f.Reverse(2, w);\n\n    // check derivative of f\n    ok   &= NearEqual(dw[0*2+0] , 2.*x[0]*x[1], eps99, eps99);\n    ok   &= NearEqual(dw[1*2+0] ,    x[0]*x[0], eps99, eps99);\n\n    // check derivative of f^{(1)} (x) * dx\n    check = 2.*x[1]*dx[1] + 2.*x[0]*dx[1];\n    ok   &= NearEqual(dw[0*2+1] , check, eps99, eps99);\n    check = 2.*x[0]*dx[1];\n    ok   &= NearEqual(dw[1*2+1] , check, eps99, eps99);\n\n    return ok;\n}\n} // End empty namespace\n# include <vector>\n# include <valarray>\nbool reverse_two(void)\n{   bool ok = true;\n    ok &= reverse_two_cases< CppAD::vector  <double> >();\n    ok &= reverse_two_cases< std::vector    <double> >();\n    ok &= reverse_two_cases< std::valarray  <double> >();\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/general/sign.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin sign.cpp}\n\nSign Function: Example and Test\n###############################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end sign.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n\nbool sign(void)\n{   bool ok = true;\n\n    using CppAD::AD;\n    using CppAD::NearEqual;\n\n    // create f: x -> y where f(x) = sign(x)\n    size_t n = 1;\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) ax(n), ay(m);\n    ax[0]     = 0.;\n    CppAD::Independent(ax);\n    ay[0]     = sign(ax[0]);\n    CppAD::ADFun<double> f(ax, ay);\n\n    // check value during recording\n    ok &= (ay[0] == 0.);\n\n    // use f(x) to evaluate the sign function and its derivatives\n    CPPAD_TESTVECTOR(double) x(n), y(m), dx(n), dy(m), w(m), dw(n);\n    dx[0] = 1.;\n    w[0] = 1.;\n    //\n    x[0]  = 2.;\n    y     = f.Forward(0, x);\n    ok   &= (y[0] == 1.);\n    dy    = f.Forward(1, dx);\n    ok   &= (dy[0] == 0.);\n    dw   = f.Reverse(1, w);\n    ok  &= (dw[0] == 0.);\n    //\n    x[0]  = 0.;\n    y     = f.Forward(0, x);\n    ok   &= (y[0] == 0.);\n    dy    = f.Forward(1, dx);\n    ok   &= (dy[0] == 0.);\n    dw   = f.Reverse(1, w);\n    ok  &= (dw[0] == 0.);\n    //\n    x[0]  = -2.;\n    y     = f.Forward(0, x);\n    ok   &= (y[0] == -1.);\n    dy    = f.Forward(1, dx);\n    ok   &= (dy[0] == 0.);\n    dw   = f.Reverse(1, w);\n    ok  &= (dw[0] == 0.);\n\n    // use a VecAD<Base>::reference object with sign\n    CppAD::VecAD<double> v(1);\n    AD<double> zero(0);\n    v[zero]           = 2.;\n    AD<double> result = sign(v[zero]);\n    ok   &= (result == 1.);\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/sin.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin sin.cpp}\n\nThe AD sin Function: Example and Test\n#####################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end sin.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n# include <cmath>\n\nbool Sin(void)\n{   bool ok = true;\n\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n  = 1;\n    double x0 = 0.5;\n    CPPAD_TESTVECTOR(AD<double>) x(n);\n    x[0]      = x0;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(x);\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) y(m);\n    y[0] = CppAD::sin(x[0]);\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(x, y);\n\n    // check value\n    double check = std::sin(x0);\n    ok &= NearEqual(y[0] , check, eps99, eps99);\n\n    // forward computation of first partial w.r.t. x[0]\n    CPPAD_TESTVECTOR(double) dx(n);\n    CPPAD_TESTVECTOR(double) dy(m);\n    dx[0] = 1.;\n    dy    = f.Forward(1, dx);\n    check = std::cos(x0);\n    ok   &= NearEqual(dy[0], check, eps99, eps99);\n\n    // reverse computation of derivative of y[0]\n    CPPAD_TESTVECTOR(double)  w(m);\n    CPPAD_TESTVECTOR(double) dw(n);\n    w[0]  = 1.;\n    dw    = f.Reverse(1, w);\n    ok   &= NearEqual(dw[0], check, eps99, eps99);\n\n    // use a VecAD<Base>::reference object with sin\n    CppAD::VecAD<double> v(1);\n    AD<double> zero(0);\n    v[zero]           = x0;\n    AD<double> result = CppAD::sin(v[zero]);\n    check = std::sin(x0);\n    ok   &= NearEqual(result, check, eps99, eps99);\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/sinh.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin sinh.cpp}\n\nThe AD sinh Function: Example and Test\n######################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end sinh.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n# include <cmath>\n\nbool Sinh(void)\n{   bool ok = true;\n\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n  = 1;\n    double x0 = 0.5;\n    CPPAD_TESTVECTOR(AD<double>) x(n);\n    x[0]      = x0;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(x);\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) y(m);\n    y[0] = CppAD::sinh(x[0]);\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(x, y);\n\n    // check value\n    double check = std::sinh(x0);\n    ok &= NearEqual(y[0] , check, eps99, eps99);\n\n    // forward computation of first partial w.r.t. x[0]\n    CPPAD_TESTVECTOR(double) dx(n);\n    CPPAD_TESTVECTOR(double) dy(m);\n    dx[0] = 1.;\n    dy    = f.Forward(1, dx);\n    check = std::cosh(x0);\n    ok   &= NearEqual(dy[0], check, eps99, eps99);\n\n    // reverse computation of derivative of y[0]\n    CPPAD_TESTVECTOR(double)  w(m);\n    CPPAD_TESTVECTOR(double) dw(n);\n    w[0]  = 1.;\n    dw    = f.Reverse(1, w);\n    ok   &= NearEqual(dw[0], check, eps99, eps99);\n\n    // use a VecAD<Base>::reference object with sinh\n    CppAD::VecAD<double> v(1);\n    AD<double> zero(0);\n    v[zero]           = x0;\n    AD<double> result = CppAD::sinh(v[zero]);\n    check = std::sinh(x0);\n    ok   &= NearEqual(result, check, eps99, eps99);\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/sqrt.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin sqrt.cpp}\n\nThe AD sqrt Function: Example and Test\n######################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end sqrt.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n# include <cmath>\n\nbool Sqrt(void)\n{   bool ok = true;\n\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n  = 1;\n    double x0 = 0.5;\n    CPPAD_TESTVECTOR(AD<double>) x(n);\n    x[0]      = x0;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(x);\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) y(m);\n    y[0] = CppAD::sqrt(x[0]);\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(x, y);\n\n    // check value\n    double check = std::sqrt(x0);\n    ok &= NearEqual(y[0] , check, eps99, eps99);\n\n    // forward computation of first partial w.r.t. x[0]\n    CPPAD_TESTVECTOR(double) dx(n);\n    CPPAD_TESTVECTOR(double) dy(m);\n    dx[0] = 1.;\n    dy    = f.Forward(1, dx);\n    check = 1. / (2. * std::sqrt(x0) );\n    ok   &= NearEqual(dy[0], check, eps99, eps99);\n\n    // reverse computation of derivative of y[0]\n    CPPAD_TESTVECTOR(double)  w(m);\n    CPPAD_TESTVECTOR(double) dw(n);\n    w[0]  = 1.;\n    dw    = f.Reverse(1, w);\n    ok   &= NearEqual(dw[0], check, eps99, eps99);\n\n    // use a VecAD<Base>::reference object with sqrt\n    CppAD::VecAD<double> v(1);\n    AD<double> zero(0);\n    v[zero]           = x0;\n    AD<double> result = CppAD::sqrt(v[zero]);\n    check = std::sqrt(x0);\n    ok   &= NearEqual(result, check, eps99, eps99);\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/stack_machine.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin stack_machine.cpp}\n\nExample Differentiating a Stack Machine Interpreter\n###################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end stack_machine.cpp}\n*/\n// BEGIN C++\n\n# include <cstring>\n# include <cstddef>\n# include <cstdlib>\n# include <cctype>\n# include <cassert>\n# include <stack>\n\n# include <cppad/cppad.hpp>\n\nnamespace {\n// Begin empty namespace ------------------------------------------------\n\nbool is_number( const std::string &s )\n{   char ch = s[0];\n    bool number = (std::strchr(\"0123456789.\", ch) != 0);\n    return number;\n}\nbool is_binary( const std::string &s )\n{   char ch = s[0];\n    bool binary = (strchr(\"+-*/.\", ch) != 0);\n    return binary;\n}\nbool is_variable( const std::string &s )\n{   char ch = s[0];\n    bool variable = ('a' <= ch) && (ch <= 'z');\n    return variable;\n}\n\nvoid StackMachine(\n    std::stack< std::string >          &token_stack  ,\n    CppAD::vector< CppAD::AD<double> > &variable     )\n{   using std::string;\n    using std::stack;\n\n    using CppAD::AD;\n\n    stack< AD<double> > value_stack;\n    string              token;\n    AD<double>          value_one;\n    AD<double>          value_two;\n\n    while( ! token_stack.empty() )\n    {   string s = token_stack.top();\n        token_stack.pop();\n\n        if( is_number(s) )\n        {   value_one = std::atof( s.c_str() );\n            value_stack.push( value_one );\n        }\n        else if( is_variable(s) )\n        {   value_one = variable[ size_t(s[0]) - size_t('a') ];\n            value_stack.push( value_one );\n        }\n        else if( is_binary(s) )\n        {   assert( value_stack.size() >= 2 );\n            value_one = value_stack.top();\n            value_stack.pop();\n            value_two = value_stack.top();\n            value_stack.pop();\n\n            switch( s[0] )\n            {\n                case '+':\n                value_stack.push(value_one + value_two);\n                break;\n\n                case '-':\n                value_stack.push(value_one - value_two);\n                break;\n\n                case '*':\n                value_stack.push(value_one * value_two);\n                break;\n\n                case '/':\n                value_stack.push(value_one / value_two);\n                break;\n\n                default:\n                assert(0);\n            }\n        }\n        else if( s[0] == '=' )\n        {   assert( value_stack.size() >= 1 );\n            assert( token_stack.size() >= 1 );\n            //\n            s = token_stack.top();\n            token_stack.pop();\n            //\n            assert( is_variable( s ) );\n            value_one = value_stack.top();\n            value_stack.pop();\n            //\n            variable[ size_t(s[0]) - size_t('a') ] = value_one;\n        }\n        else assert(0);\n    }\n    return;\n}\n\n// End empty namespace -------------------------------------------------------\n}\n\nbool StackMachine(void)\n{   bool ok = true;\n\n    using std::string;\n    using std::stack;\n\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    using CppAD::vector;\n\n    // The users program in that stack machine language\n    const char *program[] = {\n        \"1.0\", \"a\", \"+\", \"=\", \"b\",  // b = a + 1\n        \"2.0\", \"b\", \"*\", \"=\", \"c\",  // c = b * 2\n        \"3.0\", \"c\", \"-\", \"=\", \"d\",  // d = c - 3\n        \"4.0\", \"d\", \"/\", \"=\", \"e\"   // e = d / 4\n    };\n    size_t n_program = sizeof( program ) / sizeof( program[0] );\n\n    // put the program in the token stack\n    stack< string > token_stack;\n    size_t i = n_program;\n    while(i--)\n        token_stack.push( program[i] );\n\n    // domain space vector\n    size_t n = 1;\n    vector< AD<double> > X(n);\n    X[0] = 0.;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(X);\n\n    // x[0] corresponds to a in the stack machine\n    vector< AD<double> > variable(26);\n    variable[0] = X[0];\n\n    // calculate the results of the program\n    StackMachine( token_stack , variable);\n\n    // range space vector\n    size_t m = 4;\n    vector< AD<double> > Y(m);\n    Y[0] = variable[1];   // b = a + 1\n    Y[1] = variable[2];   // c = (a + 1) * 2\n    Y[2] = variable[3];   // d = (a + 1) * 2 - 3\n    Y[3] = variable[4];   // e = ( (a + 1) * 2 - 3 ) / 4\n\n    // create f : X -> Y and stop tape recording\n    CppAD::ADFun<double> f(X, Y);\n\n    // use forward mode to evaluate function at different argument value\n    size_t p = 0;\n    vector<double> x(n);\n    vector<double> y(m);\n    x[0] = 1.;\n    y    = f.Forward(p, x);\n\n    // check function values\n    ok &= (y[0] == x[0] + 1.);\n    ok &= (y[1] == (x[0] + 1.) * 2.);\n    ok &= (y[2] == (x[0] + 1.) * 2. - 3.);\n    ok &= (y[3] == ( (x[0] + 1.) * 2. - 3.) / 4.);\n\n    // Use forward mode (because x is shorter than y) to calculate Jacobian\n    p = 1;\n    vector<double> dx(n);\n    vector<double> dy(m);\n    dx[0] = 1.;\n    dy    = f.Forward(p, dx);\n    ok   &= NearEqual(dy[0], 1., eps99, eps99);\n    ok   &= NearEqual(dy[1], 2., eps99, eps99);\n    ok   &= NearEqual(dy[2], 2., eps99, eps99);\n    ok   &= NearEqual(dy[3], .5, eps99, eps99);\n\n    // Use Jacobian routine (which automatically decides which mode to use)\n    dy = f.Jacobian(x);\n    ok   &= NearEqual(dy[0], 1., eps99, eps99);\n    ok   &= NearEqual(dy[1], 2., eps99, eps99);\n    ok   &= NearEqual(dy[2], 2., eps99, eps99);\n    ok   &= NearEqual(dy[3], .5, eps99, eps99);\n\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/general/sub.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin sub.cpp}\n\nAD Binary Subtraction: Example and Test\n#######################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end sub.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nbool Sub(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t  n =  1;\n    double x0 = .5;\n    CPPAD_TESTVECTOR(AD<double>) x(1);\n    x[0]      = x0;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(x);\n\n    AD<double> a = 2. * x[0] - 1.; // AD<double> - double\n    AD<double> b = a  - 2;         // AD<double> - int\n    AD<double> c = 3. - b;         // double     - AD<double>\n    AD<double> d = 4  - c;         // int        - AD<double>\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) y(m);\n    y[0] = x[0] - d;              // AD<double> - AD<double>\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(x, y);\n\n    // check value\n    ok &= NearEqual(y[0], x0-4.+3.+2.-2.*x0+1., eps99, eps99);\n\n    // forward computation of partials w.r.t. x[0]\n    CPPAD_TESTVECTOR(double) dx(n);\n    CPPAD_TESTVECTOR(double) dy(m);\n    dx[0] = 1.;\n    dy    = f.Forward(1, dx);\n    ok   &= NearEqual(dy[0], -1., eps99, eps99);\n\n    // reverse computation of derivative of y[0]\n    CPPAD_TESTVECTOR(double)  w(m);\n    CPPAD_TESTVECTOR(double) dw(n);\n    w[0]  = 1.;\n    dw    = f.Reverse(1, w);\n    ok   &= NearEqual(dw[0], -1., eps99, eps99);\n\n    // use a VecAD<Base>::reference object with subtraction\n    CppAD::VecAD<double> v(1);\n    AD<double> zero(0);\n    v[zero] = b;\n    AD<double> result = 3. - v[zero];\n    ok     &= (result == c);\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/sub_eq.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin sub_eq.cpp}\n\nAD Compound Assignment Subtraction: Example and Test\n####################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end sub_eq.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nbool SubEq(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t  n = 1;\n    double x0 = .5;\n    CPPAD_TESTVECTOR(AD<double>) x(n);\n    x[0]      = x0;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(x);\n\n    // range space vector\n    size_t m = 2;\n    CPPAD_TESTVECTOR(AD<double>) y(m);\n    y[0] = 3. * x[0];    // initial value\n    y[0] -= 2;           // AD<double> -= int\n    y[0] -= 4.;          // AD<double> -= double\n    y[1] = y[0] -= x[0]; // use the result of a compound assignment\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(x, y);\n\n    // check value\n    ok &= NearEqual(y[0] , 3.*x0-(2.+4.+x0), eps99, eps99);\n    ok &= NearEqual(y[1] ,             y[0], eps99, eps99);\n\n    // forward computation of partials w.r.t. x[0]\n    CPPAD_TESTVECTOR(double) dx(n);\n    CPPAD_TESTVECTOR(double) dy(m);\n    dx[0] = 1.;\n    dy    = f.Forward(1, dx);\n    ok   &= NearEqual(dy[0], 2., eps99, eps99);\n    ok   &= NearEqual(dy[1], 2., eps99, eps99);\n\n    // reverse computation of derivative of y[0]\n    CPPAD_TESTVECTOR(double)  w(m);\n    CPPAD_TESTVECTOR(double) dw(n);\n    w[0]  = 1.;\n    w[1]  = 0.;\n    dw    = f.Reverse(1, w);\n    ok   &= NearEqual(dw[0], 2., eps99, eps99);\n\n    // use a VecAD<Base>::reference object with computed subtraction\n    CppAD::VecAD<double> v(1);\n    AD<double> zero(0);\n    AD<double> result = 1;\n    v[zero] = 2;\n    result -= v[zero];\n    ok     &= (result == -1);\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/tan.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin tan.cpp}\n\nThe AD tan Function: Example and Test\n#####################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end tan.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n# include <cmath>\n# include <limits>\n\nbool Tan(void)\n{   bool ok = true;\n\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps = 10. * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n  = 1;\n    double x0 = 0.5;\n    CPPAD_TESTVECTOR(AD<double>) x(n);\n    x[0]      = x0;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(x);\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) y(m);\n    y[0] = CppAD::tan(x[0]);\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(x, y);\n\n    // check value\n    double check = std::tan(x0);\n    ok &= NearEqual(y[0] , check,  eps, eps);\n\n    // forward computation of first partial w.r.t. x[0]\n    CPPAD_TESTVECTOR(double) dx(n);\n    CPPAD_TESTVECTOR(double) dy(m);\n    dx[0] = 1.;\n    dy    = f.Forward(1, dx);\n    check = 1. + std::tan(x0) * std::tan(x0);\n    ok   &= NearEqual(dy[0], check, eps, eps);\n\n    // reverse computation of derivative of y[0]\n    CPPAD_TESTVECTOR(double)  w(m);\n    CPPAD_TESTVECTOR(double) dw(n);\n    w[0]  = 1.;\n    dw    = f.Reverse(1, w);\n    ok   &= NearEqual(dw[0], check, eps, eps);\n\n    // use a VecAD<Base>::reference object with tan\n    CppAD::VecAD<double> v(1);\n    AD<double> zero(0);\n    v[zero]           = x0;\n    AD<double> result = CppAD::tan(v[zero]);\n    check = std::tan(x0);\n    ok   &= NearEqual(result, check, eps, eps);\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/tanh.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin tanh.cpp}\n\nThe AD tanh Function: Example and Test\n######################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end tanh.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n# include <cmath>\n# include <limits>\n\nbool Tanh(void)\n{   bool ok = true;\n\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps = 10. * CppAD::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n  = 1;\n    double x0 = 0.5;\n    CPPAD_TESTVECTOR(AD<double>) x(n);\n    x[0]      = x0;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(x);\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) y(m);\n    y[0] = CppAD::tanh(x[0]);\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(x, y);\n\n    // check value\n    double check = std::tanh(x0);\n    ok &= NearEqual(y[0] , check,  eps, eps);\n\n    // forward computation of first partial w.r.t. x[0]\n    CPPAD_TESTVECTOR(double) dx(n);\n    CPPAD_TESTVECTOR(double) dy(m);\n    dx[0] = 1.;\n    dy    = f.Forward(1, dx);\n    check = 1. - std::tanh(x0) * std::tanh(x0);\n    ok   &= NearEqual(dy[0], check, eps, eps);\n\n    // reverse computation of derivative of y[0]\n    CPPAD_TESTVECTOR(double)  w(m);\n    CPPAD_TESTVECTOR(double) dw(n);\n    w[0]  = 1.;\n    dw    = f.Reverse(1, w);\n    ok   &= NearEqual(dw[0], check, eps, eps);\n\n    // use a VecAD<Base>::reference object with tan\n    CppAD::VecAD<double> v(1);\n    AD<double> zero(0);\n    v[zero]           = x0;\n    AD<double> result = CppAD::tanh(v[zero]);\n    check = std::tanh(x0);\n    ok   &= NearEqual(result, check, eps, eps);\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/tape_index.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin tape_index.cpp}\n\nTaping Array Index Operation: Example and Test\n##############################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end tape_index.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nnamespace {\n    double Array(const double &index)\n    {   static double array[] = {\n            5.,\n            4.,\n            3.,\n            2.,\n            1.\n        };\n        static size_t number = sizeof(array) / sizeof(array[0]);\n        if( index < 0. )\n            return array[0];\n\n        size_t i = static_cast<size_t>(index);\n        if( i >= number )\n            return array[number-1];\n\n        return array[i];\n    }\n    // in empty namespace and outside any other routine\n    CPPAD_DISCRETE_FUNCTION(double, Array)\n}\n\nbool TapeIndex(void)\n{   bool ok = true;\n    using CppAD::AD;\n\n    // domain space vector\n    size_t n = 2;\n    CPPAD_TESTVECTOR(AD<double>) X(n);\n    X[0] = 2.;   // array index value\n    X[1] = 3.;   // multiplier of array index value\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(X);\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) Y(m);\n    Y[0] = X[1] * Array( X[0] );\n\n    // create f: X -> Y and stop tape recording\n    CppAD::ADFun<double> f(X, Y);\n\n    // vectors for arguments to the function object f\n    CPPAD_TESTVECTOR(double) x(n);   // argument values\n    CPPAD_TESTVECTOR(double) y(m);   // function values\n    CPPAD_TESTVECTOR(double) w(m);   // function weights\n    CPPAD_TESTVECTOR(double) dw(n);  // derivative of weighted function\n\n    // check function value\n    x[0] = Value(X[0]);\n    x[1] = Value(X[1]);\n    y[0] = Value(Y[0]);\n    ok  &= y[0] == x[1] * Array(x[0]);\n\n    // evaluate f where x has different values\n    x[0] = x[0] + 1.;  // new array index value\n    x[1] = x[1] + 1.;  // new multiplier value\n    y    = f.Forward(0, x);\n    ok  &= y[0] == x[1] * Array(x[0]);\n\n    // evaluate derivaitve of y[0]\n    w[0] = 1.;\n    dw   = f.Reverse(1, w);\n    ok   &= dw[0] == 0.;              // partial w.r.t array index\n    ok   &= dw[1] == Array(x[0]);     // partial w.r.t multiplier\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/taylor_ode.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin taylor_ode.cpp}\n\nTaylor's Ode Solver: An Example and Test\n########################################\n\nPurpose\n*******\nThis example uses the method described in :ref:`taylor_ode-name`\nto solve an ODE.\n\nODE\n***\nThe ODE is defined by\n:math:`y(0) = 0` and :math:`y^1 (t) = g[ y(t) ]`\nwhere the function\n:math:`g : \\B{R}^n \\rightarrow \\B{R}^n` is defined by\n\n.. math::\n\n    g(y)\n    =\n    \\left( \\begin{array}{c}\n            1                       \\\\\n            y_1                     \\\\\n            \\vdots                  \\\\\n            y_{n-1}\n    \\end{array} \\right)\n\nand the initial condition is :math:`z(0) = 0`.\n\nODE Solution\n************\nThe solution for this example can be calculated by\nstarting with the first row and then using the solution\nfor the first row to solve the second and so on.\nDoing this we obtain\n\n.. math::\n\n    y(t) =\n    \\left( \\begin{array}{c}\n        t           \\\\\n        t^2 / 2     \\\\\n        \\vdots      \\\\\n        t^n / n !\n    \\end{array} \\right)\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end taylor_ode.cpp}\n--------------------------------------------------------------------------\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n\n// =========================================================================\n// define types for each level\nnamespace { // BEGIN empty namespace\n\n    typedef CppAD::AD<double>          a_double;\n    typedef CPPAD_TESTVECTOR(double)   d_vector;\n    typedef CPPAD_TESTVECTOR(a_double) a_vector;\n\n    a_vector ode(const a_vector y)\n    {   size_t n = y.size();\n        a_vector g(n);\n        g[0] = 1;\n        for(size_t k = 1; k < n; k++)\n            g[k] = y[k-1];\n        return g;\n    }\n\n}\n\n// -------------------------------------------------------------------------\n// use Taylor's method to solve this ordinary differential equaiton\nbool taylor_ode(void)\n{   // initialize the return value as true\n    bool ok = true;\n\n    // The ODE does not depend on the argument values\n    // so only tape once, also note that ode does not depend on t\n    size_t n = 5;    // number of independent and dependent variables\n    a_vector ay(n), ag(n);\n    CppAD::Independent( ay );\n    ag = ode(ay);\n    CppAD::ADFun<double> g(ay, ag);\n\n    // initialize the solution vector at time zero\n    d_vector y(n);\n    for(size_t j = 0; j < n; j++)\n        y[j] = 0.0;\n\n    size_t order   = n;   // order of the Taylor method\n    size_t n_step  = 4;   // number of time steps\n    double dt      = 0.5; // step size in time\n\n    // Taylor coefficients of order k\n    d_vector yk(n), zk(n);\n\n    // loop with respect to each step of Taylor's method\n    for(size_t i_step = 0; i_step < n_step; i_step++)\n    {   // Use Taylor's method to take a step\n        yk           = y;     // initialize y^{(k)}  for k = 0\n        double dt_kp = dt;    // initialize dt^(k+1) for k = 0\n        for(size_t k = 0; k < order; k++)\n        {   // evaluate k-th order Taylor coefficient of z(t) = g(y(t))\n            zk = g.Forward(k, yk);\n\n            for(size_t j = 0; j < n; j++)\n            {   // convert to (k+1)-Taylor coefficient for y\n                yk[j] = zk[j] / double(k + 1);\n\n                // add term for to this Taylor coefficient\n                // to solution for y(t, x)\n                y[j] += yk[j] * dt_kp;\n            }\n            // next power of t\n            dt_kp *= dt;\n        }\n    }\n\n    // check solution of the ODE,\n    // Taylor's method should have no truncation error for this case\n    double eps   = 100. * std::numeric_limits<double>::epsilon();\n    double check = 1.;\n    double t     = double(n_step) * dt;\n    for(size_t i = 0; i < n; i++)\n    {   check *= t / double(i + 1);\n        ok &= CppAD::NearEqual(y[i], check, eps, eps);\n    }\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/general/unary_minus.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin unary_minus.cpp}\n\nAD Unary Minus Operator: Example and Test\n#########################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end unary_minus.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n\nbool unary_minus(void)\n{   bool ok = true;\n    using CppAD::AD;\n\n\n    // domain space vector\n    size_t n = 1;\n    CPPAD_TESTVECTOR(AD<double>) x(n);\n    x[0]      = 3.;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(x);\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) y(m);\n    y[0] = - x[0];\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(x, y);\n\n    // check values\n    ok &= ( y[0] == -3. );\n\n    // forward computation of partials w.r.t. x[0]\n    CPPAD_TESTVECTOR(double) dx(n);\n    CPPAD_TESTVECTOR(double) dy(m);\n    size_t p = 1;\n    dx[0]    = 1.;\n    dy       = f.Forward(p, dx);\n    ok      &= ( dy[0] == -1. );   // dy[0] / dx[0]\n\n    // reverse computation of dertivative of y[0]\n    CPPAD_TESTVECTOR(double)  w(m);\n    CPPAD_TESTVECTOR(double) dw(n);\n    w[0] = 1.;\n    dw   = f.Reverse(p, w);\n    ok &= ( dw[0] == -1. );       // dy[0] / dx[0]\n\n    // use a VecAD<Base>::reference object with unary minus\n    CppAD::VecAD<double> v(1);\n    AD<double> zero(0);\n    v[zero] = x[0];\n    AD<double> result = - v[zero];\n    ok     &= (result == y[0]);\n\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/general/unary_plus.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin unary_plus.cpp}\n\nAD Unary Plus Operator: Example and Test\n########################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end unary_plus.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n\nbool unary_plus(void)\n{   bool ok = true;\n    using CppAD::AD;\n\n\n    // domain space vector\n    size_t n = 1;\n    CPPAD_TESTVECTOR(AD<double>) x(n);\n    x[0]      = 3.;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(x);\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) y(m);\n    y[0] = + x[0];\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(x, y);\n\n    // check values\n    ok &= ( y[0] == 3. );\n\n    // forward computation of partials w.r.t. x[0]\n    CPPAD_TESTVECTOR(double) dx(n);\n    CPPAD_TESTVECTOR(double) dy(m);\n    size_t p = 1;\n    dx[0]    = 1.;\n    dy       = f.Forward(p, dx);\n    ok      &= ( dy[0] == 1. );   // dy[0] / dx[0]\n\n    // reverse computation of dertivative of y[0]\n    CPPAD_TESTVECTOR(double)  w(m);\n    CPPAD_TESTVECTOR(double) dw(n);\n    w[0] = 1.;\n    dw   = f.Reverse(p, w);\n    ok &= ( dw[0] == 1. );       // dy[0] / dx[0]\n\n    // use a VecAD<Base>::reference object with unary plus\n    CppAD::VecAD<double> v(1);\n    AD<double> zero(0);\n    v[zero] = x[0];\n    AD<double> result = + v[zero];\n    ok     &= (result == y[0]);\n\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/general/value.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin value.cpp}\n\nConvert From AD to its Base Type: Example and Test\n##################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end value.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n\nbool Value(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::Value;\n\n    // domain space vector\n    size_t n = 2;\n    CPPAD_TESTVECTOR(AD<double>) x(n);\n    x[0] = 3.;\n    x[1] = 4.;\n\n    // check value before recording\n    ok &= (Value(x[0]) == 3.);\n    ok &= (Value(x[1]) == 4.);\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(x);\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) y(m);\n    y[0] = - x[1];\n\n    // cannot call Value(x[j]) or Value(y[0]) here (currently variables)\n    AD<double> p = 5.;        // p is a parameter (does not depend on x)\n    ok &= (Value(p) == 5.);\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(x, y);\n\n    // can call Value(x[j]) or Value(y[0]) here (currently parameters)\n    ok &= (Value(x[0]) ==  3.);\n    ok &= (Value(x[1]) ==  4.);\n    ok &= (Value(y[0]) == -4.);\n\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/general/var2par.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin var2par.cpp}\n\nConvert a Variable or Dynamic Parameter a Constant: Example and Test\n####################################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end var2par.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n\n\nbool Var2Par(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::Value;\n    using CppAD::Var2Par;\n\n    // independent variables\n    size_t nx = 2;\n    CPPAD_TESTVECTOR(AD<double>) ax(nx);\n    ax[0] = 3.;\n    ax[1] = 4.;\n\n    // independent dynamic parameters\n    size_t np = 1;\n    CPPAD_TESTVECTOR(AD<double>) ap(np);\n    ap[0] = 5.;\n\n    // declare independent variables and dynamic parameters\n    CppAD::Independent(ax, ap);\n\n    // range space vector\n    size_t ny = 2;\n    CPPAD_TESTVECTOR(AD<double>) ay(ny);\n    ay[0] = - ax[1] * Var2Par(ax[0]);    // same as ay[0] = -ax[1] * 3.;\n    ay[1] = - ax[1] * Var2Par(ap[0]);    // same as ay[1] = -ax[1] * 5.;\n\n    // Must convert these objects to constants before calling Value\n    ok &= ( Value( Var2Par(ax[0]) ) == 3. );\n    ok &= ( Value( Var2Par(ax[1]) ) == 4. );\n    ok &= ( Value( Var2Par(ap[0]) ) == 5. );\n    ok &= ( Value( Var2Par(ay[0]) ) == -12. );\n    ok &= ( Value( Var2Par(ay[1]) ) == -20. );\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(ax, ay);\n\n    // All AD object are currently constants\n    ok &= (Value(ax[0]) ==  3.);\n    ok &= (Value(ax[1]) ==  4.);\n    ok &= (Value(ap[0]) ==  5.);\n    ok &= (Value(ay[0]) == -12.);\n    ok &= (Value(ay[1]) == -20.);\n\n    // evaluate zero order forward mode\n    // (note that the only real variable in this recording is x[1])\n    CPPAD_TESTVECTOR(double) x(nx), p(np), y(ny);\n    x[0] = 6.;\n    x[1] = 7.;\n    p[0] = 8.;\n    f.new_dynamic(p);\n    y    = f.Forward(0, x);\n    ok  &= y[0] == - x[1] * 3.0;\n    ok  &= y[1] == - x[1] * 5.0;\n\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/general/vec_ad.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin vec_ad.cpp}\n\nAD Vectors that Record Index Operations: Example and Test\n#########################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end vec_ad.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n# include <cassert>\n\nnamespace {\n    // return the vector x that solves the following linear system\n    //    a[0] * x[0] + a[1] * x[1] = b[0]\n    //    a[2] * x[0] + a[3] * x[1] = b[1]\n    // in a way that will record pivot operations on the AD<double> tape\n    typedef CPPAD_TESTVECTOR(CppAD::AD<double>) Vector;\n    Vector Solve(const Vector &a , const Vector &b)\n    {   using namespace CppAD;\n        assert(a.size() == 4 && b.size() == 2);\n\n        // copy the vector b into the VecAD object B\n        VecAD<double> B(2);\n        AD<double>    u;\n        for(u = 0; u < 2; u += 1.)\n            B[u] = b[ size_t( Integer(u) ) ];\n\n        // copy the matrix a into the VecAD object A\n        VecAD<double> A(4);\n        for(u = 0; u < 4; u += 1.)\n            A[u] = a [ size_t( Integer(u) ) ];\n\n        // tape AD operation sequence that determines the row of A\n        // with maximum absolute element in column zero\n        AD<double> zero(0), one(1);\n        AD<double> rmax = CondExpGt(fabs(a[0]), fabs(a[2]), zero, one);\n\n        // divide row rmax by A(rmax, 0)\n        A[rmax * 2 + 1]  = A[rmax * 2 + 1] / A[rmax * 2 + 0];\n        B[rmax]          = B[rmax]         / A[rmax * 2 + 0];\n        A[rmax * 2 + 0]  = one;\n\n        // subtract A(other,0) times row A(rmax, *) from row A(other,*)\n        AD<double> other   = one - rmax;\n        A[other * 2 + 1]   = A[other * 2 + 1]\n                                    - A[other * 2 + 0] * A[rmax * 2 + 1];\n        B[other]           = B[other]\n                                    - A[other * 2 + 0] * B[rmax];\n        A[other * 2 + 0] = zero;\n\n        // back substitute to compute the solution vector x.\n        // Note that the columns of A correspond to rows of x.\n        // Also note that A[rmax * 2 + 0] is equal to one.\n        CPPAD_TESTVECTOR(AD<double>) x(2);\n        x[1] = B[other] / A[other * 2 + 1];\n        x[0] = B[rmax] - A[rmax * 2 + 1] * x[1];\n\n        return x;\n    }\n}\n\nbool vec_ad(void)\n{   bool ok = true;\n\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n = 4;\n    CPPAD_TESTVECTOR(double)       x(n);\n    CPPAD_TESTVECTOR(AD<double>) X(n);\n    // 2 * identity matrix (rmax in Solve will be 0)\n    X[0] = x[0] = 2.; X[1] = x[1] = 0.;\n    X[2] = x[2] = 0.; X[3] = x[3] = 2.;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(X);\n\n    // define the vector b\n    CPPAD_TESTVECTOR(double)       b(2);\n    CPPAD_TESTVECTOR(AD<double>) B(2);\n    B[0] = b[0] = 0.;\n    B[1] = b[1] = 1.;\n\n    // range space vector solves X * Y = b\n    size_t m = 2;\n    CPPAD_TESTVECTOR(AD<double>) Y(m);\n    Y = Solve(X, B);\n\n    // create f: X -> Y and stop tape recording\n    CppAD::ADFun<double> f(X, Y);\n\n    // By Cramer's rule:\n    // y[0] = [ b[0] * x[3] - x[1] * b[1] ] / [ x[0] * x[3] - x[1] * x[2] ]\n    // y[1] = [ x[0] * b[1] - b[0] * x[2] ] / [ x[0] * x[3] - x[1] * x[2] ]\n\n    double den   = x[0] * x[3] - x[1] * x[2];\n    double dsq   = den * den;\n    double num0  = b[0] * x[3] - x[1] * b[1];\n    double num1  = x[0] * b[1] - b[0] * x[2];\n\n    // check value\n    ok &= NearEqual(Y[0] , num0 / den, eps99, eps99);\n    ok &= NearEqual(Y[1] , num1 / den, eps99, eps99);\n\n    // forward computation of partials w.r.t. x[0]\n    CPPAD_TESTVECTOR(double) dx(n);\n    CPPAD_TESTVECTOR(double) dy(m);\n    dx[0] = 1.; dx[1] = 0.;\n    dx[2] = 0.; dx[3] = 0.;\n    dy    = f.Forward(1, dx);\n    ok &= NearEqual(dy[0], 0.         - num0 * x[3] / dsq, eps99, eps99);\n    ok &= NearEqual(dy[1], b[1] / den - num1 * x[3] / dsq, eps99, eps99);\n\n    // compute the solution for a new x matrix such that pivioting\n    // on the original rmax row would divide by zero\n    CPPAD_TESTVECTOR(double) y(m);\n    x[0] = 0.; x[1] = 2.;\n    x[2] = 2.; x[3] = 0.;\n\n    // new values for Cramer's rule\n    den   = x[0] * x[3] - x[1] * x[2];\n    dsq   = den * den;\n    num0  = b[0] * x[3] - x[1] * b[1];\n    num1  = x[0] * b[1] - b[0] * x[2];\n\n    // check values\n    y    = f.Forward(0, x);\n    ok &= NearEqual(y[0] , num0 / den, eps99, eps99);\n    ok &= NearEqual(y[1] , num1 / den, eps99, eps99);\n\n    // forward computation of partials w.r.t. x[1]\n    dx[0] = 0.; dx[1] = 1.;\n    dx[2] = 0.; dx[3] = 0.;\n    dy    = f.Forward(1, dx);\n    ok   &= NearEqual(dy[0],-b[1] / den + num0 * x[2] / dsq, eps99, eps99);\n    ok   &= NearEqual(dy[1], 0.         + num1 * x[2] / dsq, eps99, eps99);\n\n    // reverse computation of derivative of y[0] w.r.t x\n    CPPAD_TESTVECTOR(double) w(m);\n    CPPAD_TESTVECTOR(double) dw(n);\n    w[0] = 1.; w[1] = 0.;\n    dw   = f.Reverse(1, w);\n    ok  &= NearEqual(dw[0], 0.         - num0 * x[3] / dsq, eps99, eps99);\n    ok  &= NearEqual(dw[1],-b[1] / den + num0 * x[2] / dsq, eps99, eps99);\n    ok  &= NearEqual(dw[2], 0.         + num0 * x[1] / dsq, eps99, eps99);\n    ok  &= NearEqual(dw[3], b[0] / den - num0 * x[0] / dsq, eps99, eps99);\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/get_started/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# Build the example/get_started directory tests\n#\nSET(source_list get_started.cpp)\n#\nset_compile_flags( example_get_started \"${cppad_debug_which}\" \"${source_list}\" )\n#\nADD_EXECUTABLE(example_get_started EXCLUDE_FROM_ALL ${source_list})\n#\nTARGET_LINK_LIBRARIES(example_get_started ${cppad_lib} ${colpack_libs})\n#\n# check_example_get_started\nadd_check_executable(check_example get_started)\n"
  },
  {
    "path": "example/get_started/get_started.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin get_started.cpp}\n\nGetting Started Using CppAD to Compute Derivatives\n##################################################\n\nPurpose\n*******\nDemonstrate the use of CppAD by computing the derivative\nof a simple example function.\n\nFunction\n********\nThe example function :math:`f : \\B{R} \\rightarrow \\B{R}` is defined by\n\n.. math::\n\n    f(x) = a_0 + a_1 * x^1 + \\cdots + a_{k-1} * x^{k-1}\n\nwhere *a* is a fixed vector of length *k* .\n\nDerivative\n**********\nThe derivative of :math:`f(x)` is given by\n\n.. math::\n\n    f' (x) = a_1 + 2 * a_2 * x +  \\cdots + (k-1) * a_{k-1} * x^{k-2}\n\nValue\n*****\nFor the particular case in this example,\n:math:`k` is equal to 5,\n:math:`a = (1, 1, 1, 1, 1)`, and\n:math:`x = 3`.\nIf follows that\n\n.. math::\n\n    f' ( 3 ) = 1 + 2 * 3 + 3 * 3^2 + 4 * 3^3 = 142\n\nInclude File\n************\nThe following command, in the program below, includes the CppAD package:\n\n    # ``include <cppad/cppad.hpp>``\n\nPoly\n****\nThe routine ``Poly`` , defined below, evaluates a polynomial.\nA general purpose polynomial evaluation routine is documented and\ndistributed with CppAD; see :ref:`Poly-name` .\n\nCppAD Namespace\n***************\nAll of the functions and objects defined by CppAD are in the\n``CppAD`` namespace. In the example below,\n\n    ``using CppAD::AD`` ;\n\nenables one to abbreviate ``CppAD::AD`` using just ``AD`` .\n\nCppAD Preprocessor Symbols\n**************************\nAll the :ref:`preprocessor-name` symbols defined by CppAD begin with\n``CPPAD_`` (some deprecated symbols begin with ``CppAD_`` ).\nThe preprocessor symbol :ref:`CPPAD_TESTVECTOR<testvector-name>`\nis used in the example below.\n\nProgram\n*******\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <iostream>        // standard input/output\n# include <vector>          // standard vector\n# include <cppad/cppad.hpp> // the CppAD package\n\nnamespace { // begin the empty namespace\n    // define the function Poly(a, x) = a[0] + a[1]*x[1] + ... + a[k-1]*x[k-1]\n    template <class Type>\n    Type Poly(const CPPAD_TESTVECTOR(double) &a, const Type &x)\n    {  size_t k  = a.size();\n        Type y   = 0.;  // initialize summation\n        Type x_i = 1.;  // initialize x^i\n        for(size_t i = 0; i < k; i++)\n        {  y   += a[i] * x_i;  // y   = y + a_i * x^i\n            x_i *= x;           // x_i = x_i * x\n        }\n        return y;\n    }\n}\n// main program\nint main(void)\n{  using CppAD::AD;   // use AD as abbreviation for CppAD::AD\n    using std::vector; // use vector as abbreviation for std::vector\n\n    // vector of polynomial coefficients\n    size_t k = 5;                  // number of polynomial coefficients\n    CPPAD_TESTVECTOR(double) a(k); // vector of polynomial coefficients\n    for(size_t i = 0; i < k; i++)\n        a[i] = 1.;                 // value of polynomial coefficients\n\n    // domain space vector\n    size_t n = 1;               // number of domain space variables\n    vector< AD<double> > ax(n); // vector of domain space variables\n    ax[0] = 3.;                 // value at which function is recorded\n\n    // declare independent variables and start recording operation sequence\n    CppAD::Independent(ax);\n\n    // range space vector\n    size_t m = 1;               // number of ranges space variables\n    vector< AD<double> > ay(m); // vector of ranges space variables\n    ay[0] = Poly(a, ax[0]);     // record operations that compute ay[0]\n\n    // store operation sequence in f: X -> Y and stop recording\n    CppAD::ADFun<double> f(ax, ay);\n\n    // compute derivative using operation sequence stored in f\n    vector<double> jac(m * n); // Jacobian of f (m by n matrix)\n    vector<double> x(n);       // domain space vector\n    x[0] = 3.;                 // argument value for computing derivative\n    jac  = f.Jacobian(x);      // Jacobian for operation sequence\n\n    // print the results\n    std::cout << \"f'(3) computed by CppAD = \" << jac[0] << std::endl;\n\n    // check if the derivative is correct\n    int error_code;\n    if( jac[0] == 142. )\n        error_code = 0;      // return code for correct case\n    else  error_code = 1;    // return code for incorrect case\n\n    return error_code;\n}\n/* {xrst_code}\n{xrst_spell_on}\nOutput\n******\nExecuting the program above will generate the following output:\n::\n\n    f'(3) computed by CppAD = 142\n\nRunning\n*******\nAfter you configure your system using the :ref:`cmake-name` command,\nyou compile and run this example by executing the command\n\n    ``make check_example_get_started``\n\nin the build directory; i.e., the directory where the cmake command\nwas executed.\n\nExercises\n*********\nModify the program above to accomplish the following tasks\nusing CppAD:\n\n#. Compute and print the derivative of :math:`f(x) = 1 + x + x^2 + x^3 + x^4`\n   at the point :math:`x = 2`.\n#. Compute and print the derivative of :math:`f(x) = 1 + x + x^2 / 2`\n   at the point :math:`x = .5`.\n#. Compute and print the derivative of :math:`f(x) = \\exp (x) - 1 - x - x^2 / 2`\n   at the point :math:`x = .5`.\n\n{xrst_end get_started.cpp}\n*/\n"
  },
  {
    "path": "example/graph/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n#\n# BEGIN_SORT_THIS_LINE_PLUS_2\nSET(source_list\n    add_op.cpp\n    atom4_op.cpp\n    atom_op.cpp\n    azmul_op.cpp\n    cexp_op.cpp\n    comp_op.cpp\n    discrete_op.cpp\n    div_op.cpp\n    graph.cpp\n    mul_op.cpp\n    pow_op.cpp\n    print_graph.cpp\n    print_op.cpp\n    sub_op.cpp\n    sum_op.cpp\n    switch_var_dyn.cpp\n    unary_op.cpp\n)\n# END_SORT_THIS_LINE_MINUS_2\n\nset_compile_flags(example_graph \"${cppad_debug_which}\" \"${source_list}\" )\n#\nADD_EXECUTABLE(example_graph EXCLUDE_FROM_ALL ${source_list})\n\n# List of libraries to be linked into the specified target\nTARGET_LINK_LIBRARIES(example_graph\n    ${cppad_lib}\n    ${colpack_libs}\n)\n#\n# check_example_graph\nadd_check_executable(check_example graph)\n"
  },
  {
    "path": "example/graph/add_op.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin graph_add_op.cpp}\n\nC++ AD Graph add Operator: Example and Test\n###########################################\n\nSource Code\n***********\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end graph_add_op.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nbool add_op(void)\n{   bool ok = true;\n    using std::string;\n    //\n    // AD graph example\n    // node_1 : p[0]\n    // node_2 : p[1]\n    // node_3 : x[0]\n    // node_4 : p[0] + p[1]\n    // node_5 : x[0] + ( p[0] + p[1] )\n    // y[0]   = x[0] + ( p[0] + p[1] )\n    //\n    // C++ graph object\n    CppAD::cpp_graph graph_obj;\n    //\n    // operator being used\n    CppAD::graph::graph_op_enum op_enum;\n    //\n    // set scalars\n    graph_obj.function_name_set(\"add_op example\");\n    size_t n_dynamic_ind = 2;\n    graph_obj.n_dynamic_ind_set(n_dynamic_ind);\n    size_t n_variable_ind = 1;\n    graph_obj.n_variable_ind_set(n_variable_ind);\n    //\n    // node_4 : p[0] + p[1]\n    op_enum = CppAD::graph::add_graph_op;\n    graph_obj.operator_vec_push_back(op_enum);\n    graph_obj.operator_arg_push_back(1);\n    graph_obj.operator_arg_push_back(2);\n    //\n    // node_5 : x[0] + ( p[0] + p[1] )\n    graph_obj.operator_vec_push_back(op_enum);\n    graph_obj.operator_arg_push_back(3);\n    graph_obj.operator_arg_push_back(4);\n    //\n    // y[0]   = x[0] + ( p[0] + p[1] )\n    graph_obj.dependent_vec_push_back(5);\n    //\n    // f(x, p) = x_0 + ( p_0 + p_1 )\n    CppAD::ADFun<double> f;\n    f.from_graph(graph_obj);\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 2;\n    //\n    // set independent variables and parameters\n    CPPAD_TESTVECTOR(double) p(2), x(1);\n    p[0] = 2.0;\n    p[1] = 3.0;\n    x[0] = 4.0;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    CPPAD_TESTVECTOR(double) y = f.Forward(0, x);\n    //\n    // check result\n    ok &= y[0] == x[0] + ( p[0] + p[1] );\n    // -----------------------------------------------------------------------\n    // Convert function to graph and back again\n    f.to_graph(graph_obj);\n    f.from_graph(graph_obj);\n    // -----------------------------------------------------------------------\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 2;\n    //\n    // set independent variables and parameters\n    p[0] = 2.0;\n    p[1] = 3.0;\n    x[0] = 4.0;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    //\n    // check result\n    ok &= y[0] == x[0] + ( p[0] + p[1] );\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/graph/atom4_op.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin graph_atom4_op.cpp}\n\nC++ AD Graph Atomic Four Functions: Example and Test\n####################################################\n\nSource Code\n***********\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end graph_atom4_op.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nnamespace {\n    class atomic_int_pow : public CppAD::atomic_four<double> {\n    public:\n        atomic_int_pow(void) : CppAD::atomic_four<double>(\"int_pow\")\n        { }\n    private:\n        // for_type\n        bool for_type(\n            size_t                                     call_id     ,\n            const CppAD::vector<CppAD::ad_type_enum>&  type_x      ,\n            CppAD::vector<CppAD::ad_type_enum>&        type_y      ) override\n        {   type_y[0] = type_x[0];\n            return true;\n        }\n        // forward\n        bool forward(\n            size_t                              call_id      ,\n            const CppAD::vector<bool>&          select_y     ,\n            size_t                              order_low    ,\n            size_t                              order_up     ,\n            const CppAD::vector<double>&        taylor_x     ,\n            CppAD::vector<double>&              taylor_y     ) override\n        {\n            // order_up\n            if( order_up != 0 )\n                return false;\n            //\n            // taylor_y\n            taylor_y[0] = 1.0;\n            for(size_t i = 0; i < call_id; ++i)\n                taylor_y[0] *= taylor_x[0];\n            //\n            return true;\n        }\n    };\n}\n\nbool atom4_op(void)\n{   bool ok = true;\n    using std::string;\n    //\n    // reciprocal\n    atomic_int_pow int_pow;\n    // -----------------------------------------------------------------------\n    //\n    // This function has an atomic function operator with name int_pow\n    // node_1 : p[0]\n    // node_2 : x[0]\n    // node_3 : p[0] + x[0]\n    // node_4 : int_pow( p[0] + x[0] )\n    // y[0]   = ( p[0] + x[0] ) ** call_id\n    //\n    // call_id\n    size_t call_id = 2;\n    //\n    // C++ graph object\n    CppAD::cpp_graph graph_obj;\n    graph_obj.initialize();\n    //\n    // operator being used\n    CppAD::graph::graph_op_enum op_enum;\n    //\n    graph_obj.function_name_set(\"g(p; x)\");\n    graph_obj.n_dynamic_ind_set(1);\n    graph_obj.n_variable_ind_set(1);\n    //\n    // node_3 : p[0] + x[0]\n    op_enum = CppAD::graph::add_graph_op;\n    graph_obj.operator_vec_push_back(op_enum);\n    graph_obj.operator_arg_push_back(1);\n    graph_obj.operator_arg_push_back(2);\n    //\n    // node_4 : f( p[0] + x[0] )\n    //\n    // name_index, n_result, n_arg come before first_node\n    size_t name_index = graph_obj.atomic_name_vec_size();\n    graph_obj.atomic_name_vec_push_back(\"int_pow\");\n    //\n    op_enum = CppAD::graph::atom4_graph_op;\n    graph_obj.operator_vec_push_back(op_enum);\n    graph_obj.operator_arg_push_back(name_index);  // name_index\n    graph_obj.operator_arg_push_back(call_id);     // call_id\n    graph_obj.operator_arg_push_back(1);           // n_result\n    graph_obj.operator_arg_push_back(1);           // n_node_arg\n    graph_obj.operator_arg_push_back(3);           // first and last node arg\n    //\n    // y[0]  = int_pow( p[0] + x[0] ) = ( p[0] + x[0] ) ** call_id\n    graph_obj.dependent_vec_push_back(4);\n    // ------------------------------------------------------------------------\n    CppAD::ADFun<double> g;\n    g.from_graph(graph_obj);\n    // ------------------------------------------------------------------------\n    ok &= g.Domain() == 1;\n    ok &= g.Range() == 1;\n    ok &= g.size_dyn_ind() == 1;\n    //\n    // set p in g(p; x)\n    CPPAD_TESTVECTOR(double) p(1);\n    p[0] = 2.0;\n    g.new_dynamic(p);\n    //\n    // evaluate g(p; x)\n    CPPAD_TESTVECTOR(double) x(1), y(1);\n    x[0] = 3.0;\n    y    = g.Forward(0, x);\n    //\n    // check value\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    double check = std::pow( p[0] + x[0], double(call_id) );\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n    // ------------------------------------------------------------------------\n    g.to_graph(graph_obj);\n    g.from_graph(graph_obj);\n    // ------------------------------------------------------------------------\n    ok &= g.Domain() == 1;\n    ok &= g.Range() == 1;\n    ok &= g.size_dyn_ind() == 1;\n    //\n    // set p in g(p; x)\n    p[0] = 4.0;\n    g.new_dynamic(p);\n    //\n    // evaluate g(p; x)\n    x[0] = 5.0;\n    y    = g.Forward(0, x);\n    //\n    // check value\n    check = std::pow( p[0] + x[0], double(call_id) );\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n    // ------------------------------------------------------------------------\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/graph/atom_op.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin graph_atom_op.cpp}\n\nC++ AD Graph Atomic Three Functions: Example and Test\n#####################################################\n\nSource Code\n***********\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end graph_atom_op.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nbool atom_op(void)\n{   bool ok = true;\n    using std::string;\n    // -----------------------------------------------------------------------\n    // Define f_0 (x_0, x_1; p) = x_1 + p_0 * x_0\n    //\n    // This function does not have an atomic function operator\n    // node_1 : p[0]\n    // node_2 : x[0]\n    // node_3 : x[1]\n    // node_4 : p[0] * x[0]\n    // node_5 : x[1] + p[0] * x[0]\n    // y[0]   = x[1] + p[0] * x[0]\n    //\n    // C++ graph object\n    CppAD::cpp_graph graph_obj;\n    //\n    // operator being used\n    CppAD::graph::graph_op_enum op_enum;\n    //\n    // set scalars\n    graph_obj.function_name_set(\"f(x; p)\");\n    size_t n_dynamic_ind = 1;\n    graph_obj.n_dynamic_ind_set(n_dynamic_ind);\n    size_t n_variable_ind = 2;\n    graph_obj.n_variable_ind_set(n_variable_ind);\n    //\n    // node_4 : p[0] * x[0]\n    op_enum = CppAD::graph::mul_graph_op;\n    graph_obj.operator_vec_push_back(op_enum);\n    graph_obj.operator_arg_push_back(1);\n    graph_obj.operator_arg_push_back(2);\n    //\n    // node_5 : x[1] + p[0] * x[0]\n    op_enum = CppAD::graph::add_graph_op;\n    graph_obj.operator_vec_push_back(op_enum);\n    graph_obj.operator_arg_push_back(3);\n    graph_obj.operator_arg_push_back(4);\n    //\n    // y[0]   = x[1] + p[0] * x[0]\n    graph_obj.dependent_vec_push_back(5);\n    //\n    // f(x, p) = x_1 + p_0 * x_0\n    CppAD::ADFun<float> f;\n    f.from_graph(graph_obj);\n    //\n    ok &= f.Domain() == 2;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 1;\n    //\n    // A ckhpoint_two function with name f(x; p) is derived from\n    // an atomic_three function with the same name.\n    bool internal_bool    = false;\n    bool use_hes_sparsity = false;\n    bool use_base2ad      = false;\n    bool use_in_parallel  = false;\n    CppAD::chkpoint_two<float> chk_f(f, \"f(x; p)\",\n        internal_bool, use_hes_sparsity, use_base2ad, use_in_parallel\n    );\n    // -----------------------------------------------------------------------\n    // g (u_0, u_1; p, q) = f(u_0 + q_0, u_1 + q_1, p)\n    //                    = u_1 + q_1 + p_0 * ( u_0 + q_0 )\n    //\n    // This function has an atomic function operator with name f(x; p)\n    // node_1 : q[0]\n    // node_2 : q[1]\n    // node_3 : u[0]\n    // node_4 : u[1]\n    // node_5 : u[0] + q[0]\n    // node_6 : u[1] + q[1]\n    // node_7 : f( u[0] + q[0], u[1] + q[1]; p)\n    // y[0]   = u[1] + q[1] + p[0] * (u[0]  + q[0])\n    //\n    graph_obj.initialize();\n    //\n    graph_obj.function_name_set(\"g(u; p, q)\");\n    n_dynamic_ind = 2;\n    graph_obj.n_dynamic_ind_set(n_dynamic_ind);\n    n_variable_ind = 2;\n    graph_obj.n_variable_ind_set(n_variable_ind);\n    //\n    // node_5 : u[0] + q[0]\n    op_enum = CppAD::graph::add_graph_op;\n    graph_obj.operator_vec_push_back(op_enum);\n    graph_obj.operator_arg_push_back(3);\n    graph_obj.operator_arg_push_back(1);\n    //\n    // node_6 : u[1] + q[1]\n    graph_obj.operator_vec_push_back(op_enum);\n    graph_obj.operator_arg_push_back(4);\n    graph_obj.operator_arg_push_back(2);\n    //\n    // node_7 : f( u[0] + q[0], u[1] + q[1]; p)\n    //\n    // name_index, n_result, n_arg come before first_node\n    size_t name_index = graph_obj.atomic_name_vec_size();\n    graph_obj.atomic_name_vec_push_back(\"f(x; p)\");\n    //\n    op_enum = CppAD::graph::atom_graph_op;\n    graph_obj.operator_vec_push_back(op_enum);\n    graph_obj.operator_arg_push_back(name_index);  // name_index\n    graph_obj.operator_arg_push_back(1);           // n_result\n    graph_obj.operator_arg_push_back(2);           // n_node_arg\n    graph_obj.operator_arg_push_back(5);           // first node arg\n    graph_obj.operator_arg_push_back(6);           // second node arg\n    //\n    // y[0]   = u[1] + q[1] + p[0] * (u[0]  + q[0])\n    graph_obj.dependent_vec_push_back(7);\n    // ------------------------------------------------------------------------\n    CppAD::ADFun<float> g;\n    g.from_graph(graph_obj);\n    // ------------------------------------------------------------------------\n    ok &= g.Domain() == 2;\n    ok &= g.Range() == 1;\n    ok &= g.size_dyn_ind() == 2;\n    //\n    // set p in g(u; p, q)\n    CPPAD_TESTVECTOR(float) p(1);\n    p[0] = 2.0;\n    chk_f.new_dynamic(p);\n    //\n    // set q in g(u; p, q)\n    CPPAD_TESTVECTOR(float) q(2);\n    q[0] = 3.0;\n    q[1] = 4.0;\n    g.new_dynamic(q);\n    //\n    // evaluate g(u; p, q)\n    CPPAD_TESTVECTOR(float) u(2), y(1);\n    u[0] = 5.0;\n    u[1] = 6.0;\n    y    = g.Forward(0, u);\n    //\n    // check value\n    ok &= y[0] == u[1] + q[1] + p[0] * (u[0]  + q[0]);\n    // ------------------------------------------------------------------------\n    g.to_graph(graph_obj);\n    g.from_graph(graph_obj);\n    // ------------------------------------------------------------------------\n    ok &= g.Domain() == 2;\n    ok &= g.Range() == 1;\n    ok &= g.size_dyn_ind() == 2;\n    //\n    // set p in g(u; p, q)\n    p[0] = 3.0;\n    chk_f.new_dynamic(p);\n    //\n    // set q in g(u; p, q)\n    q[0] = 4.0;\n    q[1] = 5.0;\n    g.new_dynamic(q);\n    //\n    // evaluate g(u; p, q)\n    u[0] = 6.0;\n    u[1] = 7.0;\n    y    = g.Forward(0, u);\n    //\n    // check value\n    ok &= y[0] == u[1] + q[1] + p[0] * (u[0]  + q[0]);\n    // ------------------------------------------------------------------------\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/graph/azmul_op.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin graph_azmul_op.cpp}\n\nC++ AD Graph add Operator: Example and Test\n###########################################\n\nSource Code\n***********\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end graph_azmul_op.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nbool azmul_op(void)\n{   bool ok = true;\n    using std::string;\n    //\n    // AD graph example\n    // node_1 : p[0]\n    // node_2 : p[1]\n    // node_3 : x[0]\n    // node_4 : azmul(p[0] , p[1])\n    // node_5 : azmul(x[0] , p[1])\n    // y[0]   = azmul(p[0] , p[1])\n    // y[1]   = azmul(x[0] , p[1])\n    //\n    // C++ graph object\n    CppAD::cpp_graph graph_obj;\n    //\n    // operator being used\n    CppAD::graph::graph_op_enum op_enum;\n    //\n    // set scalars\n    graph_obj.function_name_set(\"azmul_op example\");\n    size_t n_dynamic_ind = 2;\n    graph_obj.n_dynamic_ind_set(n_dynamic_ind);\n    size_t n_variable_ind = 1;\n    graph_obj.n_variable_ind_set(n_variable_ind);\n    //\n    // node_4 : azmul(p[0], p[1])\n    op_enum = CppAD::graph::azmul_graph_op;\n    graph_obj.operator_vec_push_back(op_enum);\n    graph_obj.operator_arg_push_back(1);\n    graph_obj.operator_arg_push_back(2);\n    //\n    // node_5 : azmul(x[0], p[1])\n    graph_obj.operator_vec_push_back(op_enum);\n    graph_obj.operator_arg_push_back(3);\n    graph_obj.operator_arg_push_back(2);\n    //\n    // y[0]   = azmul(p[0], p[1])\n    // y[1]   = azmul(x[0], x[1])\n    graph_obj.dependent_vec_push_back(4);\n    graph_obj.dependent_vec_push_back(5);\n    //\n    // f(x, p) = y\n    CppAD::ADFun<double> f;\n    f.from_graph(graph_obj);\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 2;\n    ok &= f.size_dyn_ind() == 2;\n    //\n    // set independent variables and parameters\n    CPPAD_TESTVECTOR(double) p(2), x(1);\n    p[0] = 2.0;\n    p[1] = 3.0;\n    x[0] = 4.0;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    CPPAD_TESTVECTOR(double) y = f.Forward(0, x);\n    //\n    // check result\n    ok &= y[0] == p[0] * p[1];\n    ok &= y[1] == x[0] * p[1];\n    // -----------------------------------------------------------------------\n    // Convert function to graph and back again\n    f.to_graph(graph_obj);\n    f.from_graph(graph_obj);\n    // -----------------------------------------------------------------------\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 2;\n    ok &= f.size_dyn_ind() == 2;\n    //\n    // set independent variables and parameters\n    p[0] = 3.0;\n    p[1] = std::numeric_limits<double>::quiet_NaN();\n    x[0] = 0.0;\n    //\n    // suppress checking for nan in y\n    f.check_for_nan(false);\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    //\n    // check result\n    ok &= std::isnan(y[0]);\n    ok &= y[1] == 0.0;\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/graph/cexp_op.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin graph_cexp_op.cpp}\n\nC++ AD Graph Conditional Expressions: Example and Test\n######################################################\n\nSource Code\n***********\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end graph_cexp_op.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nbool cexp_op(void)\n{   bool ok = true;\n    using std::string;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    //\n    // AD graph example\n    // node_1 : p[0]\n    // node_2 : x[0]\n    // node_3 : c[0]\n    // node_4 : cexp_le(p[0], x[0], p[0], x[0])\n    // y[0]   = cexp_le(p[0], x[0], p[0], x[0])\n    //\n    //\n    // C++ graph object\n    CppAD::cpp_graph graph_obj;\n    //\n    // operator being used\n    CppAD::graph::graph_op_enum op_enum;\n    //\n    // set scalars\n    graph_obj.function_name_set(\"cexp_op example\");\n    size_t n_dynamic_ind = 1;\n    graph_obj.n_dynamic_ind_set(n_dynamic_ind);\n    size_t n_variable_ind = 1;\n    graph_obj.n_variable_ind_set(n_variable_ind);\n    graph_obj.constant_vec_push_back(-0.1);\n    //\n    // node_4 : cexp_le(p[0], x[0], p[0], x[0])\n    op_enum = CppAD::graph::cexp_le_graph_op;\n    graph_obj.operator_vec_push_back(op_enum);\n    graph_obj.operator_arg_push_back(1);\n    graph_obj.operator_arg_push_back(2);\n    graph_obj.operator_arg_push_back(1);\n    graph_obj.operator_arg_push_back(2);\n    //\n    // y[0]   = cexp_le(p[0], x[0], p[0], x[0])\n    graph_obj.dependent_vec_push_back(4);\n    //\n    // f(x, p) = cexp_le(p[0], x[0], p[0], x[0])\n    CppAD::ADFun<double> f;\n    f.from_graph(graph_obj);\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 1;\n    //\n    // set independent variables and parameters\n    CPPAD_TESTVECTOR(double) p(1), x(1);\n    p[0] = 0.2;\n    x[0] = 0.3;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    CPPAD_TESTVECTOR(double) y = f.Forward(0, x);\n    //\n    // check result\n    double check;\n    if( p[0] <= x[0] )\n        check= p[0];\n    else\n        check = x[0];\n    //\n    // check result\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n    // ----------------------------------------------------------------------\n    // Convert to Graph graph and back again\n    f.to_graph(graph_obj);\n    f.from_graph(graph_obj);\n    // ----------------------------------------------------------------------\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    //\n    // check result\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/graph/comp_op.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin graph_comp_op.cpp}\n\nC++ AD Graph Comparison Operators: Example and Test\n###################################################\n\nSource Code\n***********\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end graph_comp_op.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nbool comp_op(void)\n{   bool ok = true;\n    using std::string;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    //\n    // AD graph example\n    // node_1 : p[0]\n    // node_2 : x[0]\n    //        : x[0] < p[0]\n    // node_3 : p[0] - x[0]\n    // node_4 : log( p[0] - x[0] )\n    // y[0]   = log( p[0] - x[0] )\n    //\n    // C++ graph object\n    CppAD::cpp_graph graph_obj;\n    //\n    // operator being used\n    CppAD::graph::graph_op_enum op_enum;\n    //\n    // set scalars\n    graph_obj.function_name_set(\"comp_op example\");\n    size_t n_dynamic_ind = 1;\n    graph_obj.n_dynamic_ind_set(n_dynamic_ind);\n    size_t n_variable_ind = 1;\n    graph_obj.n_variable_ind_set(n_variable_ind);\n    //\n    // x[0] < p[0]\n    op_enum = CppAD::graph::comp_lt_graph_op;\n    graph_obj.operator_vec_push_back(op_enum);\n    graph_obj.operator_arg_push_back(2);\n    graph_obj.operator_arg_push_back(1);\n    //\n    // node_3 : p[0] - x[0]\n    op_enum = CppAD::graph::sub_graph_op;\n    graph_obj.operator_vec_push_back(op_enum);\n    graph_obj.operator_arg_push_back(1);\n    graph_obj.operator_arg_push_back(2);\n    //\n    // node_4 : log( p[0] - x[0] )\n    op_enum = CppAD::graph::log_graph_op;\n    graph_obj.operator_vec_push_back(op_enum);\n    graph_obj.operator_arg_push_back(3);\n    //\n    // y[0]   = log( p[0] - x[0] )\n    graph_obj.dependent_vec_push_back(4);\n    //\n    // f(x, p) = log( p[0] - x[0] )\n    CppAD::ADFun<double> f;\n    f.from_graph(graph_obj);\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 1;\n    //\n    // set independent variables and parameters\n    CPPAD_TESTVECTOR(double) p(1), x(1);\n    p[0] = 0.3;\n    x[0] = 0.2;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    CPPAD_TESTVECTOR(double) y = f.Forward(0, x);\n    //\n    //  x[0] < p[0] so comparison should not have changed\n    ok &= f.compare_change_number() == 0;\n    //\n    // check result\n    double check = std::log( p[0] - x[0] );\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n    //\n    // case where comparison is false\n    f.check_for_nan(false); // suppress checking for nan for this test\n    x[0] = 0.4;\n    y = f.Forward(0, x);\n    ok &= f.compare_change_number() == 1;\n    //\n    // -----------------------------------------------------------------------\n    // Convert to Graph graph and back again\n    f.to_graph(graph_obj);\n    // std::cout << graph;\n    f.from_graph(graph_obj);\n    // -----------------------------------------------------------------------\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    x[0] = 0.2;\n    y = f.Forward(0, x);\n    //\n    // check result\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n    //\n    // case where comparison is false\n    x[0] = 0.4;\n    y = f.Forward(0, x);\n    ok &= f.compare_change_number() == 1;\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/graph/discrete_op.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin graph_discrete_op.cpp}\n\nC++ AD Graph add Operator: Example and Test\n###########################################\n\nSource Code\n***********\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end graph_discrete_op.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nnamespace {\n    double heaviside(const double &x)\n    {   if( x < 0.0 )\n            return 0.0;\n        if( x == 0.0 )\n            return 0.5;\n        return 1.0;\n    }\n    CPPAD_DISCRETE_FUNCTION(double, heaviside)\n}\n\nbool discrete_op(void)\n{   bool ok = true;\n    using std::string;\n    //\n    // The discrete function does not exist until its AD version is called\n    heaviside( CppAD::AD<double>( 0.0 ) );\n    //\n    // AD graph example\n    // node_1 : p[0]\n    // node_2 : x[0]\n    // node_3 : heaviside(p[0])\n    // node_4 : heaviside(p[1])\n    // node_5 = heaviside(p[0]) + heaviside(p[1])\n    // y[0]   = heaviside(p[0]) + heaviside(p[1])\n    //\n    // C++ graph object\n    CppAD::cpp_graph graph_obj;\n    //\n    // operator being used\n    CppAD::graph::graph_op_enum op_enum;\n    //\n    // set scalars\n    graph_obj.function_name_set(\"discrete_op example\");\n    size_t n_dynamic_ind = 1;\n    graph_obj.n_dynamic_ind_set(n_dynamic_ind);\n    size_t n_variable_ind = 1;\n    graph_obj.n_variable_ind_set(n_variable_ind);\n    //\n    // name_index corresponding to heaviside function\n    size_t name_index = graph_obj.discrete_name_vec_size();\n    graph_obj.discrete_name_vec_push_back(\"heaviside\");\n    //\n    // heaviside(p[0])\n    op_enum = CppAD::graph::discrete_graph_op;\n    graph_obj.operator_vec_push_back(op_enum);\n    graph_obj.operator_arg_push_back(name_index);  // name_index\n    graph_obj.operator_arg_push_back(1);           // node arg\n    //\n    // heaviside(x[0])\n    graph_obj.operator_vec_push_back(op_enum);\n    graph_obj.operator_arg_push_back(name_index);  // name_index\n    graph_obj.operator_arg_push_back(2);           // node arg\n    //\n    // heaviside(p[0]) + heaviside(x[0])\n    op_enum = CppAD::graph::add_graph_op;\n    graph_obj.operator_vec_push_back(op_enum);\n    graph_obj.operator_arg_push_back(3);           // first node arg\n    graph_obj.operator_arg_push_back(4);           // second node arg\n    //\n    // y[0] = heaviside(p[0]) + heaviside(x[0])\n    graph_obj.dependent_vec_push_back(5);\n    //\n    // f(x, p) = heaviside(p[0]) + heaviside(x[0])\n    CppAD::ADFun<double> f;\n    f.from_graph(graph_obj);\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 1;\n    //\n    // set independent variables and parameters\n    CPPAD_TESTVECTOR(double) p(1), x(1);\n    p[0] = 0.0;\n    x[0] = 2.0;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    CPPAD_TESTVECTOR(double) y = f.Forward(0, x);\n    //\n    // check result\n    ok &= y[0] == heaviside(p[0]) + heaviside(x[0]);\n    // -----------------------------------------------------------------------\n    // Convert function to graph and back again\n    f.to_graph(graph_obj);\n    f.from_graph(graph_obj);\n    // -----------------------------------------------------------------------\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 1;\n    //\n    // set independent variables and parameters\n    p[0] = -2.0;\n    x[0] = 2.0;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    //\n    // check result\n    ok &= y[0] == heaviside(p[0]) + heaviside(x[0]);\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/graph/div_op.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin graph_div_op.cpp}\n\nC++ AD Graph div Operator: Example and Test\n###########################################\n\nSource Code\n***********\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end graph_div_op.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nbool div_op(void)\n{   bool ok = true;\n    using std::string;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    //\n    // AD graph example\n    // node_1 : p[0]\n    // node_2 : p[1]\n    // node_3 : x[0]\n    // node_4 : p[0] / p[1]\n    // node_5 : x[0] / ( p[1] / p[0] )\n    // y[0]   = p[0] / p[1]\n    // y[1]   = x[0] / ( p[0] / p[1] )\n    //\n    //\n    // C++ graph object\n    CppAD::cpp_graph graph_obj;\n    //\n    // operator being used\n    CppAD::graph::graph_op_enum op_enum;\n    //\n    // set scalars\n    graph_obj.function_name_set(\"div example\");\n    size_t n_dynamic_ind = 2;\n    graph_obj.n_dynamic_ind_set(n_dynamic_ind);\n    size_t n_variable_ind = 1;\n    graph_obj.n_variable_ind_set(n_variable_ind);\n    //\n    // node_4 : p[0] / p[1]\n    op_enum = CppAD::graph::div_graph_op;\n    graph_obj.operator_vec_push_back(op_enum);\n    graph_obj.operator_arg_push_back(1);\n    graph_obj.operator_arg_push_back(2);\n    //\n    // node_5 : x[0] / ( p[1] / p[0] )\n    graph_obj.operator_vec_push_back(op_enum);\n    graph_obj.operator_arg_push_back(3);\n    graph_obj.operator_arg_push_back(4);\n    //\n    // y[0]   = p[0] / p[1]\n    // y[1]   = x[0] / ( p[0] / p[1] )\n    graph_obj.dependent_vec_push_back(4);\n    graph_obj.dependent_vec_push_back(5);\n    //\n    // f(x, p) = [ p_0 / p_1 , x_0 * p_1 / p_0 ]\n    CppAD::ADFun<double> f;\n    f.from_graph(graph_obj);\n    //\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 2;\n    ok &= f.size_dyn_ind() == 2;\n    //\n    // set independent variables and parameters\n    CPPAD_TESTVECTOR(double) p(2), x(1);\n    p[0] = 2.0;\n    p[1] = 3.0;\n    x[0] = 4.0;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    CPPAD_TESTVECTOR(double) y = f.Forward(0, x);\n    //\n    // check result\n    ok &= CppAD::NearEqual(y[0] , p[0] / p[1] , eps99, eps99 );\n    ok &= CppAD::NearEqual(y[1] , x[0] / ( p[0] / p[1] ), eps99, eps99 );\n    // -----------------------------------------------------------------------\n    // Convert to Graph graph and back again\n    f.to_graph(graph_obj);\n    // std::cout << \"json = \" << json;\n    f.from_graph(graph_obj);\n    // -----------------------------------------------------------------------\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 2;\n    ok &= f.size_dyn_ind() == 2;\n    //\n    // set independent variables and parameters\n    p[0] = 2.0;\n    p[1] = 3.0;\n    x[0] = 4.0;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    //\n    // check result\n    ok &= CppAD::NearEqual(y[0] , p[0] / p[1] , eps99, eps99 );\n    ok &= CppAD::NearEqual(y[1] , x[0] / ( p[0] / p[1] ), eps99, eps99 );\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/graph/graph.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin graph.cpp}\n\ngraph Examples and Tests Driver\n###############################\n\nRunning These Tests\n*******************\nAfter executing the :ref:`cmake-name` command\nform the :ref:`download@Distribution Directory`,\nyou can build and run these tests with the commands::\n\n    cd build\n    make check_example_graph\n\nNote that your choice of :ref:`cmake@generator` may require using\nan different version of make; e.g., ``ninja`` .\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end graph.cpp}\n-------------------------------------------------------------------------------\n*/\n// BEGIN C++\n\n// CPPAD_HAS_* defines\n# include <cppad/configure.hpp>\n\n// for thread_alloc\n# include <cppad/utility/thread_alloc.hpp>\n\n// test runner\n# include <cppad/utility/test_boolofvoid.hpp>\n\n// BEGIN_SORT_THIS_LINE_PLUS_2\n// external compiled tests\nextern bool add_op(void);\nextern bool atom4_op(void);\nextern bool atom_op(void);\nextern bool azmul_op(void);\nextern bool cexp_op(void);\nextern bool comp_op(void);\nextern bool discrete_op(void);\nextern bool div_op(void);\nextern bool mul_op(void);\nextern bool pow_op(void);\nextern bool print_graph(void);\nextern bool print_op(void);\nextern bool sub_op(void);\nextern bool sum_op(void);\nextern bool switch_var_dyn(void);\nextern bool unary_op(void);\n// END_SORT_THIS_LINE_MINUS_1\n\n// main program that runs all the tests\nint main(void)\n{   std::string group = \"example/graph\";\n    size_t      width = 20;\n    CppAD::test_boolofvoid Run(group, width);\n\n    // This line is used by test_one.sh\n\n    // BEGIN_SORT_THIS_LINE_PLUS_2\n    // external compiled tests\n    Run( add_op,               \"add_op\"          );\n    Run( atom4_op,             \"atom4_op\"        );\n    Run( atom_op,              \"atom_op\"         );\n    Run( azmul_op,             \"azmul_op\"        );\n    Run( cexp_op,              \"cexp_op\"         );\n    Run( comp_op,              \"comp_op\"         );\n    Run( discrete_op,          \"discrete_op\"     );\n    Run( div_op,               \"div_op\"          );\n    Run( mul_op,               \"mul_op\"          );\n    Run( pow_op,               \"pow_op\"          );\n    Run( print_graph,          \"print_graph\"     );\n    Run( print_op,             \"print_op\"        );\n    Run( sub_op,               \"sub_op\"          );\n    Run( sum_op,               \"sum_op\"          );\n    Run( switch_var_dyn,       \"switch_var_dyn\"  );\n    Run( unary_op,             \"unary_op\"        );\n    // END_SORT_THIS_LINE_MINUS_1\n\n    // check for memory leak\n    bool memory_ok = CppAD::thread_alloc::free_all();\n    // print summary at end\n    bool ok = Run.summary(memory_ok);\n    //\n    return static_cast<int>( ! ok );\n}\n// END C++\n"
  },
  {
    "path": "example/graph/mul_op.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin graph_mul_op.cpp}\n\nC++ AD Graph mul Operator: Example and Test\n###########################################\n\nSource Code\n***********\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end graph_mul_op.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nbool mul_op(void)\n{   bool ok = true;\n    using std::string;\n    //\n    // AD graph example\n    // node_1 : p[0]\n    // node_2 : p[1]\n    // node_3 : x[0]\n    // node_4 : p[0] * p[1]\n    // node_5 : x[0] * p[0] * p[1]\n    // y[0]   = x[0] * p[0] * p[1]\n    //\n    // C++ graph object\n    CppAD::cpp_graph graph_obj;\n    //\n    // operator being used\n    CppAD::graph::graph_op_enum op_enum;\n    //\n    // set scalars\n    graph_obj.function_name_set(\"mul_op example\");\n    size_t n_dynamic_ind = 2;\n    graph_obj.n_dynamic_ind_set(n_dynamic_ind);\n    size_t n_variable_ind = 1;\n    graph_obj.n_variable_ind_set(n_variable_ind);\n    //\n    // node_4 : p[0] * p[1]\n    op_enum = CppAD::graph::mul_graph_op;\n    graph_obj.operator_vec_push_back(op_enum);\n    graph_obj.operator_arg_push_back(1);\n    graph_obj.operator_arg_push_back(2);\n    //\n    // node_5 : x[0] * p[0] * p[1]\n    graph_obj.operator_vec_push_back(op_enum);\n    graph_obj.operator_arg_push_back(3);\n    graph_obj.operator_arg_push_back(4);\n    //\n    // y[0]   = x[0] * p[0] * p[1]\n    graph_obj.dependent_vec_push_back(5);\n    //\n    // f(x, p) = x_0 * p_0 * p_1\n    CppAD::ADFun<double> f;\n    f.from_graph(graph_obj);\n    //\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 2;\n    //\n    // set independent variables and parameters\n    CPPAD_TESTVECTOR(double) p(2), x(1);\n    p[0] = 2.0;\n    p[1] = 3.0;\n    x[0] = 4.0;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    CPPAD_TESTVECTOR(double) y = f.Forward(0, x);\n    //\n    // check result\n    ok &= y[0] == x[0] * p[0] * p[1];\n    // -----------------------------------------------------------------------\n    // Convert to Graph graph and back again\n    f.to_graph(graph_obj);\n    // std::cout << \"json = \" << json;\n    f.from_graph(graph_obj);\n    // -----------------------------------------------------------------------\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 2;\n    //\n    // set independent variables and parameters\n    p[0] = 2.0;\n    p[1] = 3.0;\n    x[0] = 4.0;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    //\n    // check result\n    ok &= y[0] == x[0] * p[0] * p[1];\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/graph/pow_op.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin graph_pow_op.cpp}\n\nC++ AD Graph pow Operator: Example and Test\n###########################################\n\nSource Code\n***********\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end graph_pow_op.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nbool pow_op(void)\n{   bool ok = true;\n    using std::string;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    //\n    // AD graph example\n    // node_1 : p[0]\n    // node_2 : p[1]\n    // node_3 : x[0]\n    // node_4 : pow(p[0] , p[1])\n    // node_5 : pow(x[0] , p[1])\n    // y[0]   = pow(p[0] , p[1])\n    // y[1]   = pow(x[0] , p[1])\n    //\n    // C++ graph object\n    CppAD::cpp_graph graph_obj;\n    //\n    // operator being used\n    CppAD::graph::graph_op_enum op_enum;\n    //\n    // set scalars\n    graph_obj.function_name_set(\"pow_op example\");\n    size_t n_dynamic_ind = 2;\n    graph_obj.n_dynamic_ind_set(n_dynamic_ind);\n    size_t n_variable_ind = 1;\n    graph_obj.n_variable_ind_set(n_variable_ind);\n    //\n    // node_4 : pow(p[0], p[1])\n    op_enum = CppAD::graph::pow_graph_op;\n    graph_obj.operator_vec_push_back(op_enum);\n    graph_obj.operator_arg_push_back(1);\n    graph_obj.operator_arg_push_back(2);\n    //\n    // node_5 : pow(x[0], p[1])\n    graph_obj.operator_vec_push_back(op_enum);\n    graph_obj.operator_arg_push_back(3);\n    graph_obj.operator_arg_push_back(2);\n    //\n    // y[0]   = pow(p[0], p[1])\n    // y[1]   = pow(x[0], x[1])\n    graph_obj.dependent_vec_push_back(4);\n    graph_obj.dependent_vec_push_back(5);\n    //\n    // f(x, p) = y\n    CppAD::ADFun<double> f;\n    f.from_graph(graph_obj);\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 2;\n    ok &= f.size_dyn_ind() == 2;\n    //\n    // set independent variables and parameters\n    CPPAD_TESTVECTOR(double) p(2), x(1);\n    p[0] = 2.0;\n    p[1] = 3.0;\n    x[0] = 4.0;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    CPPAD_TESTVECTOR(double) y = f.Forward(0, x);\n    //\n    // check result\n    ok &= CppAD::NearEqual(y[0], pow(p[0], p[1]), eps99, eps99);\n    ok &= CppAD::NearEqual(y[1], pow(x[0], p[1]), eps99, eps99);\n    // -----------------------------------------------------------------------\n    // Convert function to graph and back again\n    f.to_graph(graph_obj);\n    f.from_graph(graph_obj);\n    // -----------------------------------------------------------------------\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 2;\n    ok &= f.size_dyn_ind() == 2;\n    //\n    // set independent variables and parameters\n    p[0] = 3.0;\n    p[1] = 4.0;\n    x[0] = 5.0;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    //\n    // check result\n    ok &= CppAD::NearEqual(y[0], pow(p[0], p[1]), eps99, eps99);\n    ok &= CppAD::NearEqual(y[1], pow(x[0], p[1]), eps99, eps99);\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/graph/print_graph.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin print_graph.cpp}\n\nPrint a C++ AD Graph: Example and Test\n######################################\n\nSource Code\n***********\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end print_graph.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nbool print_graph(void)\n{   bool ok = true;\n    using std::string;\n    //\n    // AD graph example\n    // node_1 : p[0]\n    // node_2 : p[1]\n    // node_3 : x[0]\n    // node_4 : p[0] + p[1]\n    // node_5 : x[0] + ( p[0] + p[1] )\n    // y[0]   = x[0] + ( p[0] + p[1] )\n    //\n    // C++ graph object\n    CppAD::cpp_graph graph_obj;\n    //\n    // operator being used\n    CppAD::graph::graph_op_enum op_enum;\n    //\n    // set scalars\n    graph_obj.function_name_set(\"print_graph example\");\n    size_t n_dynamic_ind = 2;\n    graph_obj.n_dynamic_ind_set(n_dynamic_ind);\n    size_t n_variable_ind = 1;\n    graph_obj.n_variable_ind_set(n_variable_ind);\n    //\n    // node_4 : p[0] + p[1]\n    op_enum = CppAD::graph::add_graph_op;\n    graph_obj.operator_vec_push_back(op_enum);\n    graph_obj.operator_arg_push_back(1);\n    graph_obj.operator_arg_push_back(2);\n    //\n    // node_5 : x[0] + ( p[0] + p[1] )\n    graph_obj.operator_vec_push_back(op_enum);\n    graph_obj.operator_arg_push_back(3);\n    graph_obj.operator_arg_push_back(4);\n    //\n    // y[0]   = x[0] + ( p[0] + p[1] )\n    graph_obj.dependent_vec_push_back(5);\n    //\n    // get output of print command\n    std::stringstream os;\n    graph_obj.print(os);\n    //\n    std::string check =\n        \"print_graph example\\n\"\n        \"          1      p[0]\\n\"\n        \"          2      p[1]\\n\"\n        \"          3      x[0]\\n\"\n        \"          4       add    1    2\\n\"\n        \"          5       add    3    4\\n\"\n        \"y nodes = 5\\n\"\n    ;\n    std::string str = os.str();\n    ok &= str == check;\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/graph/print_op.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin graph_print_op.cpp}\n\nC++ AD Graph print Operator: Example and Test\n#############################################\n\nSource Code\n***********\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end graph_print_op.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nbool print_op(void)\n{   bool ok = true;\n    using std::string;\n    std::stringstream stream_out;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    //\n    // AD graph example\n    // node_1 : p[0]\n    // node_2 : x[0]\n    //        : print(p[0], \"p[0] = \", p[0], \"\\n\")\n    //        : print(x[0], \"x[0] = \", x[0], \"\\n\")\n    // node_3 : log(p[0])\n    // node_4 : log(x[0])\n    // node_5 = log(p[0]) + log(x[0])\n    // y[0]   = log(p[0]) + log(x[0])\n    //\n    // C++ graph object\n    CppAD::cpp_graph graph_obj;\n    //\n    // operator being used\n    CppAD::graph::graph_op_enum op_enum;\n    //\n    // set scalars\n    graph_obj.function_name_set(\"print_op example\");\n    size_t n_dynamic_ind = 1;\n    graph_obj.n_dynamic_ind_set(n_dynamic_ind);\n    size_t n_variable_ind = 1;\n    graph_obj.n_variable_ind_set(n_variable_ind);\n    //\n    // if p[0] <= 0: print \"p[0] = \", p[0], \"\\n\"\n    op_enum  = CppAD::graph::print_graph_op;\n    graph_obj.operator_vec_push_back(op_enum);\n    size_t before = graph_obj.print_text_vec_size();\n    graph_obj.print_text_vec_push_back(\"p[0] = \");\n    graph_obj.operator_arg_push_back(before);\n    size_t after = graph_obj.print_text_vec_size();\n    graph_obj.print_text_vec_push_back(\"\\n\");\n    graph_obj.operator_arg_push_back(after);\n    graph_obj.operator_arg_push_back(1);\n    graph_obj.operator_arg_push_back(1);\n    //\n    // if x[0] <= 0: print \"x[0] = \", x[0], \"\\n\"\n    graph_obj.operator_vec_push_back(op_enum);\n    before = graph_obj.print_text_vec_size();\n    graph_obj.print_text_vec_push_back(\"x[0] = \");\n    graph_obj.operator_arg_push_back(before);\n    graph_obj.operator_arg_push_back(after);\n    graph_obj.operator_arg_push_back(2);\n    graph_obj.operator_arg_push_back(2);\n    //\n    // node_3 : log(p[0])\n    op_enum = CppAD::graph::log_graph_op;\n    graph_obj.operator_vec_push_back(op_enum);\n    graph_obj.operator_arg_push_back(1);\n    //\n    // node_4 : log(x[0])\n    graph_obj.operator_vec_push_back(op_enum);\n    graph_obj.operator_arg_push_back(2);\n    //\n    // node_5: log(p[0]) + log(x[0])\n    op_enum = CppAD::graph::add_graph_op;\n    graph_obj.operator_vec_push_back(op_enum);\n    graph_obj.operator_arg_push_back(3);\n    graph_obj.operator_arg_push_back(4);\n    //\n    // y[0] = log(p[0]) + log(x[0])\n    graph_obj.dependent_vec_push_back(5);\n    //\n    // f(x, p) = log(x) + log(p)\n    CppAD::ADFun<double> f;\n    f.from_graph(graph_obj);\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 1;\n    //\n    // set independent variables and parameters\n    CPPAD_TESTVECTOR(double) p(1), x(1);\n    p[0] = 1.0;\n    x[0] = 2.0;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    CPPAD_TESTVECTOR(double) y = f.Forward(0, x, stream_out);\n    //\n    // check result\n    ok &= stream_out.str() == \"\";\n    double check = std::log(p[0]) + std::log(x[0]);\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n    //\n    // -----------------------------------------------------------------------\n    // Convert function to graph and back again\n    f.to_graph(graph_obj);\n    f.from_graph(graph_obj);\n    // -----------------------------------------------------------------------\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 1;\n    //\n    // set independent variables and parameters\n    p[0] = 1.0;\n    x[0] = -2.0;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    f.check_for_nan(false);\n    y = f.Forward(0, x, stream_out);\n    //\n    // check result\n    ok &= stream_out.str() == \"x[0] = -2\\n\";\n    ok &= std::isnan(y[0]);\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/graph/sub_op.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin graph_sub_op.cpp}\n\nC++ AD Graph sub Operator: Example and Test\n###########################################\n\nSource Code\n***********\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end graph_sub_op.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nbool sub_op(void)\n{   bool ok = true;\n    using std::string;\n    //\n    // AD graph example\n    // node_1 : p[0]\n    // node_2 : p[1]\n    // node_3 : x[0]\n    // node_4 : p[0] - p[1]\n    // node_5 : x[0] - ( p[0] - p[1] )\n    // y[0]   = x[0] - ( p[0] - p[1] )\n    //\n    // C++ graph object\n    CppAD::cpp_graph graph_obj;\n    //\n    // operator being used\n    CppAD::graph::graph_op_enum op_enum;\n    //\n    // set scalars\n    graph_obj.function_name_set(\"sub_op example\");\n    size_t n_dynamic_ind = 2;\n    graph_obj.n_dynamic_ind_set(n_dynamic_ind);\n    size_t n_variable_ind = 1;\n    graph_obj.n_variable_ind_set(n_variable_ind);\n    //\n    // node_4 : p[0] - p[1]\n    op_enum = CppAD::graph::sub_graph_op;\n    graph_obj.operator_vec_push_back(op_enum);\n    graph_obj.operator_arg_push_back(1);\n    graph_obj.operator_arg_push_back(2);\n    //\n    // node_5 : x[0] - ( p[0] - p[1] )\n    graph_obj.operator_vec_push_back(op_enum);\n    graph_obj.operator_arg_push_back(3);\n    graph_obj.operator_arg_push_back(4);\n    //\n    // y[0]   = x[0] - ( p[0] - p[1] )\n    graph_obj.dependent_vec_push_back(5);\n    //\n    // f(x, p) = x_0 - ( p_0 - p_1 )\n    CppAD::ADFun<double> f;\n    f.from_graph(graph_obj);\n    //\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 2;\n    //\n    // set independent variables and parameters\n    CPPAD_TESTVECTOR(double) p(2), x(1);\n    p[0] = 2.0;\n    p[1] = 3.0;\n    x[0] = 4.0;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    CPPAD_TESTVECTOR(double) y = f.Forward(0, x);\n    //\n    // check result\n    ok &= y[0] == x[0] - ( p[0] - p[1] );\n    // -----------------------------------------------------------------------\n    // Convert to Graph graph and back again\n    f.to_graph(graph_obj);\n    // std::cout << \"json = \" << json;\n    f.from_graph(graph_obj);\n    // -----------------------------------------------------------------------\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 2;\n    //\n    // set independent variables and parameters\n    p[0] = 2.0;\n    p[1] = 3.0;\n    x[0] = 4.0;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    //\n    // check result\n    ok &= y[0] == x[0] - ( p[0] - p[1] );\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/graph/sum_op.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin graph_sum_op.cpp}\n\nC++ AD Graph sum Operator: Example and Test\n###########################################\n\nSource Code\n***********\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end graph_sum_op.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nbool sum_op(void)\n{   bool ok = true;\n    using std::string;\n    //\n    // AD graph example\n    // node_1 : p[0]\n    // node_2 : p[1]\n    // node_3 : p[2]\n    // node_4 : x[0]\n    // node_5 : p[0] + p[1] + p[2]\n    // node_6 : x[0] + p[0] + p[1] + p[2]\n    // y[0]   = x[0] + p[0] + p[1] + p[2]\n    //\n    //\n    // C++ graph object\n    CppAD::cpp_graph graph_obj;\n    //\n    // operator being used\n    CppAD::graph::graph_op_enum op_enum;\n    //\n    // set scalars\n    graph_obj.function_name_set(\"sum_op example\");\n    size_t n_dynamic_ind = 3;\n    graph_obj.n_dynamic_ind_set(n_dynamic_ind);\n    size_t n_variable_ind = 1;\n    graph_obj.n_variable_ind_set(n_variable_ind);\n    //\n    // node_5 : p[0] + p[1] + p[2]\n    //\n    op_enum = CppAD::graph::sum_graph_op;\n    graph_obj.operator_vec_push_back(op_enum);\n    graph_obj.operator_arg_push_back(3);  // n_node_arg\n    graph_obj.operator_arg_push_back(1);  // first node arg\n    graph_obj.operator_arg_push_back(2);  // second node arg\n    graph_obj.operator_arg_push_back(3);  // third node are\n    //\n    // node_6 : x[0] + p[0] + p[1] + p[2]\n    //\n    // n_arg comes before first_node\n    graph_obj.operator_arg_push_back(2);\n    graph_obj.operator_vec_push_back(op_enum);\n    graph_obj.operator_arg_push_back(4);\n    graph_obj.operator_arg_push_back(5);\n    //\n    // y[0]   = x[0] + p[0] + p[1] + p[2]\n    graph_obj.dependent_vec_push_back(6);\n    //\n    // f(x, p) = x_0 + p_0 + p_1 + p_2\n    CppAD::ADFun<double> f;\n    f.from_graph(graph_obj);\n    //\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 3;\n    //\n    // set independent variables and parameters\n    CPPAD_TESTVECTOR(double) p(3), x(1);\n    for(size_t j = 0; j < 3; ++j)\n        p[j] = double(j + 1);\n    x[0] = 5.0;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    CPPAD_TESTVECTOR(double) y = f.Forward(0, x);\n    //\n    // check result\n    ok &= y[0] == x[0] + p[0] + p[1] + p[2];\n    // -----------------------------------------------------------------------\n    // Convert to Graph graph and back again\n    f.to_graph(graph_obj);\n    // std::cout << \"json = \" << json;\n    f.from_graph(graph_obj);\n    // -----------------------------------------------------------------------\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 3;\n    //\n    // set independent variables and parameters\n    for(size_t j = 0; j < 3; ++j)\n        p[j] = double(j + 1);\n    x[0] = 5.0;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    //\n    // check result\n    ok &= y[0] == x[0] + p[0] + p[1] + p[2];\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/graph/switch_var_dyn.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin switch_var_dyn.cpp}\n\nSwitching Between Variables and Dynamic Parameters: Example and Test\n####################################################################\n\nFunction\n********\nFor each :ref:`ADFun-name` object there is a corresponding function\n:math:`f(x, p)` where\n:ref:`independent@x` is the vector of independent variables\nand *p* is the vector of\nindependent :ref:`Independent@dynamic` parameters.\n\nConvert a Function to a Graph\n*****************************\nThe :ref:`to_graph-name` routine can be used to convert a ``ADFun``\nto a graph representation; see :ref:`cpp_ad_graph-name` .\n\nConvert a Graph to a Function\n*****************************\nThe :ref:`from_graph-name` routine can be used to convert a graph back\nto a function. During this conversion, it is possible to change\ndynamic parameters to variables and variables to dynamic parameters;\nsee :ref:`from_graph@dyn2var` and *var2dyn* in the\n``from_graph`` documentation.\nNote that many such conversions can be done\nusing the same ``cpp_ad_graph`` object.\n\nSource Code\n***********\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end switch_var_dyn.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nbool switch_var_dyn(void)\n{   bool ok = true;\n    using std::string;\n    //\n    // f(x_0, x_1, x_2) = y_0 = x_2 * ( x_0 + x_1 );\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) ax(3), ay(1);\n    for(size_t j = 0; j < 3; ++j)\n        ax[j] = CppAD::AD<double>(j);\n    Independent(ax);\n    ay[0] = ax[2] * ( ax[0] + ax[1] );\n    CppAD::ADFun<double> f(ax, ay);\n    ok &= f.Domain() == 3;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 0;\n    //\n    // set independent variables and parameters\n    CPPAD_TESTVECTOR(double) p(0), x(3);\n    x[0] = 2.0;\n    x[1] = 3.0;\n    x[2] = 4.0;\n    //\n    // compute y = f(x)\n    f.new_dynamic(p);\n    CPPAD_TESTVECTOR(double) y = f.Forward(0, x);\n    //\n    // check result\n    ok &= y[0] == x[2] * ( x[0] + x[1] );\n    // -----------------------------------------------------------------------\n    //\n    // C++ graph object\n    CppAD::cpp_graph graph_obj;\n    f.to_graph(graph_obj);\n    //\n    // change x[0]->p[0], x[1]->p[1], x[2]->x[0]\n    CppAD::vector<bool> dyn2var(0), var2dyn(3);\n    var2dyn[0] = true;\n    var2dyn[1] = true;\n    var2dyn[2] = false;\n    f.from_graph(graph_obj, dyn2var, var2dyn);\n    p.resize(2);\n    x.resize(1);\n    //\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 2;\n    //\n    // set independent variables and parameters\n    p[0] = 1.0;\n    p[1] = 2.0;\n    x[0] = 3.0;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    //\n    // check result\n    ok &= y[0] == x[0] * ( p[0] + p[1] );\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/graph/unary_op.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin graph_unary_op.cpp}\n\nGraph Unary Operator: Example and Test\n######################################\n\nSource Code\n***********\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end graph_unary_op.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nbool unary_op(void)\n{   bool ok = true;\n    using std::string;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    //\n    // AD graph example\n    // node_1 : p[0]\n    // node_2 : x[0]\n    // node_3 : c[0]\n    // node_4 : sin(p[0])\n    // node_5 : sin(x[0])\n    // node_6 : sin(c[0])\n    // node_7 : sin(p[0]) + sin(x[0]) + sin(c[0])\n    // y[0]   = sin(p[0]) + sin(x[0]) + sin(c[0])\n    //\n    // C++ graph object\n    CppAD::cpp_graph graph_obj;\n    //\n    // operator being used\n    CppAD::graph::graph_op_enum op_enum;\n    //\n    // set scalars\n    graph_obj.function_name_set(\"unary_op example\");\n    size_t n_dynamic_ind = 1;\n    graph_obj.n_dynamic_ind_set(n_dynamic_ind);\n    size_t n_variable_ind = 1;\n    graph_obj.n_variable_ind_set(n_variable_ind);\n    graph_obj.constant_vec_push_back( -0.1 );\n    //\n    // node_4 : sin(p[0])\n    op_enum = CppAD::graph::sin_graph_op;\n    graph_obj.operator_vec_push_back(op_enum);\n    graph_obj.operator_arg_push_back(1);\n    //\n    // node_5 : sin(x[0])\n    graph_obj.operator_vec_push_back(op_enum);\n    graph_obj.operator_arg_push_back(2);\n    //\n    // node_6 : sin(c[0])\n    graph_obj.operator_vec_push_back(op_enum);\n    graph_obj.operator_arg_push_back(3);\n    //\n    // node_7 : sin(p[0]) + sin(x[0]) + sin(c[0])\n    //\n    // n_arg comes before first_node\n    graph_obj.operator_arg_push_back(3);\n    // op_enum\n    op_enum = CppAD::graph::sum_graph_op;\n    graph_obj.operator_vec_push_back(op_enum);\n    graph_obj.operator_arg_push_back(4);\n    graph_obj.operator_arg_push_back(5);\n    graph_obj.operator_arg_push_back(6);\n    //\n    // y[0]   = sin(p[0]) + sin(x[0]) + sin(c[0])\n    graph_obj.dependent_vec_push_back(7);\n    //\n    // f(x, p) = sin(p_0) + sin(x_0) + sin(c_0)\n    CppAD::ADFun<double> f;\n    f.from_graph(graph_obj);\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 1;\n    //\n    // value of constant in function\n    CPPAD_TESTVECTOR(double) c(1);\n    c[0] = -0.1;\n    //\n    // set independent variables and parameters\n    CPPAD_TESTVECTOR(double) p(1), x(1);\n    p[0] = 0.2;\n    x[0] = 0.3;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    CPPAD_TESTVECTOR(double) y = f.Forward(0, x);\n    //\n    // check result\n    double check = std::sin(p[0]) + std::sin(x[0]) + std::sin(c[0]);\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n    // -----------------------------------------------------------------------\n    // Convert to Graph graph and back again\n    f.to_graph(graph_obj);\n    f.from_graph(graph_obj);\n    // -----------------------------------------------------------------------\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    //\n    // check result\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/ipopt_solve/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-23 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# Build the example/ipopt_solve directory tests\n\n# Local link directories to search, as determined by pkg-config for ipopt\nLINK_DIRECTORIES( ${ipopt_LIBRARY_DIRS} )\n#\n# BEGIN_SORT_THIS_LINE_PLUS_2\nSET(source_list\n    get_started.cpp\n    ipopt_solve.cpp\n    ode_inverse.cpp\n    retape.cpp\n)\n# END_SORT_THIS_LINE_MINUS_2\n\nset_compile_flags( example_ipopt_solve \"${cppad_debug_which}\" \"${source_list}\" )\n#\nADD_EXECUTABLE(example_ipopt_solve EXCLUDE_FROM_ALL ${source_list})\n#\n# libraries to be linked into the specified target,\n# as determined by pkg-config for ipopt\nTARGET_LINK_LIBRARIES(example_ipopt_solve\n    ${cppad_lib}\n    ${ipopt_LINK_LIBRARIES}\n    ${colpack_libs}\n)\n\n# check_example_ipopt_solve\nadd_check_executable(check_example ipopt_solve)\n"
  },
  {
    "path": "example/ipopt_solve/get_started.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n\n{xrst_begin ipopt_solve_get_started.cpp}\n{xrst_spell\n    lc\n}\n\nNonlinear Programming Using CppAD and Ipopt: Example and Test\n#############################################################\n\nPurpose\n*******\nThis example program demonstrates how to use :ref:`ipopt_solve-name` to\nsolve the example problem in the Ipopt documentation; i.e., the problem\n\n.. math::\n\n    \\begin{array}{lc}\n    {\\rm minimize \\; }      &  x_1 * x_4 * (x_1 + x_2 + x_3) + x_3\n    \\\\\n    {\\rm subject \\; to \\; } &  x_1 * x_2 * x_3 * x_4  \\geq 25\n    \\\\\n                            &  x_1^2 + x_2^2 + x_3^2 + x_4^2 = 40\n    \\\\\n                            &  1 \\leq x_1, x_2, x_3, x_4 \\leq 5\n    \\end{array}\n\nConfiguration Requirement\n*************************\nThis example will be compiled and tested provided\n:ref:`cmake@include_ipopt` is on the cmake command line.\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end ipopt_solve_get_started.cpp}\n*/\n// BEGIN C++\n# include <cppad/ipopt/solve.hpp>\n\nnamespace {\n    using CppAD::AD;\n\n    class FG_eval {\n    public:\n        typedef CPPAD_TESTVECTOR( AD<double> ) ADvector;\n        void operator()(ADvector& fg, const ADvector& x)\n        {   assert( fg.size() == 3 );\n            assert( x.size()  == 4 );\n\n            // Fortran style indexing\n            AD<double> x1 = x[0];\n            AD<double> x2 = x[1];\n            AD<double> x3 = x[2];\n            AD<double> x4 = x[3];\n            // f(x)\n            fg[0] = x1 * x4 * (x1 + x2 + x3) + x3;\n            // g_1 (x)\n            fg[1] = x1 * x2 * x3 * x4;\n            // g_2 (x)\n            fg[2] = x1 * x1 + x2 * x2 + x3 * x3 + x4 * x4;\n            //\n            return;\n        }\n    };\n}\n\nbool get_started(void)\n{   bool ok = true;\n    size_t i;\n    typedef CPPAD_TESTVECTOR( double ) Dvector;\n\n    // number of independent variables (domain dimension for f and g)\n    size_t nx = 4;\n    // number of constraints (range dimension for g)\n    size_t ng = 2;\n    // initial value of the independent variables\n    Dvector xi(nx);\n    xi[0] = 1.0;\n    xi[1] = 5.0;\n    xi[2] = 5.0;\n    xi[3] = 1.0;\n    // lower and upper limits for x\n    Dvector xl(nx), xu(nx);\n    for(i = 0; i < nx; i++)\n    {   xl[i] = 1.0;\n        xu[i] = 5.0;\n    }\n    // lower and upper limits for g\n    Dvector gl(ng), gu(ng);\n    gl[0] = 25.0;     gu[0] = 1.0e19;\n    gl[1] = 40.0;     gu[1] = 40.0;\n\n    // object that computes objective and constraints\n    FG_eval fg_eval;\n\n    // options\n    std::string options;\n    // turn off any printing\n    options += \"Integer print_level  0\\n\";\n    options += \"String  sb           yes\\n\";\n    // maximum number of iterations\n    options += \"Integer max_iter     10\\n\";\n    // approximate accuracy in first order necessary conditions;\n    // see Mathematical Programming, Volume 106, Number 1,\n    // Pages 25-57, Equation (6)\n    options += \"Numeric tol          1e-6\\n\";\n    // derivative testing\n    options += \"String  derivative_test            second-order\\n\";\n    // maximum amount of random perturbation; e.g.,\n    // when evaluation finite diff\n    options += \"Numeric point_perturbation_radius  0.\\n\";\n\n    // place to return solution\n    CppAD::ipopt::solve_result<Dvector> solution;\n\n    // solve the problem\n    CppAD::ipopt::solve<Dvector, FG_eval>(\n        options, xi, xl, xu, gl, gu, fg_eval, solution\n    );\n    //\n    // Check some of the solution values\n    //\n    ok &= solution.status == CppAD::ipopt::solve_result<Dvector>::success;\n    //\n    double check_x[]  = { 1.000000, 4.743000, 3.82115, 1.379408 };\n    double check_zl[] = { 1.087871, 0.,       0.,      0.       };\n    double check_zu[] = { 0.,       0.,       0.,      0.       };\n    double rel_tol    = 1e-6;  // relative tolerance\n    double abs_tol    = 1e-6;  // absolute tolerance\n    for(i = 0; i < nx; i++)\n    {   ok &= CppAD::NearEqual(\n            check_x[i],  solution.x[i],   rel_tol, abs_tol\n        );\n        ok &= CppAD::NearEqual(\n            check_zl[i], solution.zl[i], rel_tol, abs_tol\n        );\n        ok &= CppAD::NearEqual(\n            check_zu[i], solution.zu[i], rel_tol, abs_tol\n        );\n    }\n\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/ipopt_solve/ipopt_solve.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin ipopt_solve.cpp}\n\nipopt_solve Examples and Tests Driver\n#####################################\n\nRunning These Tests\n*******************\nAfter executing the :ref:`cmake-name` command\nform the :ref:`download@Distribution Directory`,\nyou can build and run these tests with the commands::\n\n    cd build\n    make check_example_ipopt_solve\n\nNote that your choice of :ref:`cmake@generator` may require using\nan different version of make; e.g., ``ninja`` .\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end ipopt_solve.cpp}\n-------------------------------------------------------------------------------\n*/\n// BEGIN C++\n\n// ipopt solve include file\n# include <cppad/ipopt/solve.hpp>\n\n// external complied tests\nextern bool get_started(void);\nextern bool ode_inverse(void);\nextern bool retape(void);\n\n// test runner\n# include <cppad/utility/test_boolofvoid.hpp>\n\n// main program that runs all the tests\nint main(void)\n{   std::string group = \"example/ipopt_solve\";\n    size_t      width = 20;\n    CppAD::test_boolofvoid Run(group, width);\n\n    // This line is used by test_one.sh\n\n    // external compiled tests\n    Run( get_started,         \"get_started\"  );\n    Run( ode_inverse,         \"ode_inverse\"  );\n    Run( retape,              \"retape\"       );\n    //\n    // check for memory leak\n    bool memory_ok = CppAD::thread_alloc::free_all();\n    // print summary at end\n    bool ok = Run.summary(memory_ok);\n    //\n    return static_cast<int>( ! ok );\n}\n// END C++\n"
  },
  {
    "path": "example/ipopt_solve/ode_inverse.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin ipopt_solve_ode_inverse.cpp}\n{xrst_spell\n    nz\n}\n\nODE Inverse Problem Definitions: Source Code\n############################################\n\nPurpose\n*******\nThis example demonstrates how to invert for parameters\nin a ODE where the solution of the ODE is numerically approximated.\n\nForward Problem\n***************\nWe consider the following ordinary differential equation:\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        \\partial_t y_0 ( t , a ) & = & - a_1 * y_0 (t, a )\n        \\\\\n        \\partial_t y_1 (t , a )  & = & + a_1 * y_0 (t, a ) - a_2 * y_1 (t, a )\n    \\end{eqnarray}\n\nwith the initial conditions\n\n.. math::\n\n    y_0 (0 , a) = ( a_0 , 0 )^\\R{T}\n\nOur forward problem is stated as follows:\nGiven :math:`a \\in \\B{R}^3`\ndetermine the value of :math:`y ( t , a )`,\nfor :math:`t \\in R`, that solves the initial value problem above.\n\nMeasurements\n************\nSuppose we are also given measurement times :math:`s \\in \\B{R}^5`\nand  a measurement vector :math:`z \\in \\B{R}^4`\nand for :math:`i = 0, \\ldots, 3`, we model :math:`z_i` by\n\n.. math::\n\n    z_i = y_1 ( s_{i+1} , a) + e_i\n\nwhere :math:`e_{i-1} \\sim {\\bf N} (0 , \\sigma^2 )`\nis the measurement noise,\nand :math:`\\sigma > 0` is the standard deviation of the noise.\n\nSimulation Analytic Solution\n============================\nThe following analytic solution to the forward problem is used\nto simulate a data set:\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        y_0 (t , a) & = & a_0 * \\exp( - a_1 * t )\n        \\\\\n        y_1 (t , a) & = &\n        a_0 * a_1 * \\frac{\\exp( - a_2 * t ) - \\exp( -a_1 * t )}{ a_1 - a_2 }\n    \\end{eqnarray}\n\nSimulation Parameter Values\n===========================\n\n.. list-table::\n    :widths: auto\n\n    * - :math:`\\bar{a}_0 = 1`\n      - initial value of :math:`y_0 (t, a)`\n    * - :math:`\\bar{a}_1 = 2`\n      - transfer rate from compartment zero to compartment one\n    * - :math:`\\bar{a}_2 = 1`\n      - transfer rate from compartment one to outside world\n    * - :math:`\\sigma = 0`\n      - standard deviation of measurement noise\n    * - :math:`e_i = 0`\n      - simulated measurement noise, :math:`i = 1 , \\ldots , Nz`\n    * - :math:`s_i = i * .5`\n      - time corresponding to the *i*-th measurement,\n         :math:`i = 0 , \\ldots , 3`\n\nSimulated Measurement Values\n============================\nThe simulated measurement values are given by the equation\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    z_i\n    & = &  e_i + y_1 ( s_{i+1} , \\bar{a} )\n    \\\\\n    & = &\n    \\bar{a}_0 * \\bar{a}_1 *\n        \\frac{\\exp( - \\bar{a}_2 * s_i ) - \\exp( -\\bar{a}_1 * s_i )}\n            { \\bar{a}_1 - \\bar{a}_2 }\n    \\end{eqnarray}\n\nfor :math:`i = 0, \\ldots , 3`.\n\nInverse Problem\n***************\nThe maximum likelihood estimate for :math:`a` given :math:`z`\nsolves the following optimization problem\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    {\\rm minimize} \\;\n        & \\sum_{i=0}^3 ( z_i - y_1 ( s_{i+1} , a ) )^2\n        & \\;{\\rm w.r.t} \\; a \\in \\B{R}^3\n    \\end{eqnarray}\n\nTrapezoidal Approximation\n*************************\nWe are given a number of approximation points per measurement interval\n:math:`np` and define the time grid :math:`t \\in \\B{R}^{4 \\cdot np + 1}`\nas follows:\n:math:`t_0 = s_0` and\nfor :math:`i = 0 , 1 , 2, 3`, :math:`j = 1 , \\ldots , np`\n\n.. math::\n\n    t_{i \\cdot np + j} = s_i + (s_{i+1} - s{i}) \\frac{i}{np}\n\nWe note that for :math:`i = 1 , \\ldots , 4`,\n:math:`t_{i \\cdot np} = s_i`.\nThis example uses a trapezoidal approximation to solve the ODE.\nGiven :math:`a \\in \\B{R}^3` and :math:`y^{k-1} \\approx y( t_{k-1} , a )`,\nthe a trapezoidal method approximates :math:`y ( t_j , a )`\nby the value :math:`y^k \\in \\B{R}^2` ) that solves the equation\n\n.. math::\n\n    y^k  =  y^{k-1} + \\frac{G( y^k , a ) + G( y^{k-1} , a ) }{2} * (t_k - t_{k-1})\n\nwhere :math:`G : \\B{R}^2 \\times \\B{R}^3 \\rightarrow \\B{R}^2` is defined by\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        G_0 ( y , a ) & = & - a_1 * y_0\n        \\\\\n        G_1 ( y , a ) & = & + a_1 * y_0  - a_2 * y_1\n    \\end{eqnarray}\n\nSolution Method\n***************\nWe use constraints to embed the\nforward problem in the inverse problem.\nTo be specific, we solve the optimization problem\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    {\\rm minimize}\n    & \\sum_{i=0}^3 ( z_i - y_1^{(i+1) \\cdot np} )^2\n    & \\; {\\rm w.r.t} \\; a \\in \\B{R}^3\n        \\; y^0 \\in \\B{R}^2 , \\ldots , y^{3 \\cdot np -1} \\in \\B{R}^2\n    \\\\\n    {\\rm subject \\; to}\n        0 = y^0 - ( a_0 , 0 )^\\R{T}\n        \\\\\n        & 0 = y^k  -  y^{k-1} -\n        \\frac{G( y^k , a ) + G( y^{k-1} , a ) }{2}  (t_k - t_{k-1})\n        & \\; {\\rm for} \\; k = 1 , \\ldots , 4 \\cdot np\n    \\end{eqnarray}\n\nThe code below we using the notation\n:math:`x \\in \\B{3 + (4 \\cdot np + 1) \\cdot 2}` defined by\n\n.. math::\n\n    x = \\left(\n        a_0, a_1, a_2 ,\n        y_0^0, y_1^0,\n        \\ldots ,\n        y_0^{4 \\cdot np}, y_1^{4 \\cdots np}\n    \\right)\n\nSource\n******\nThe following source code\nimplements the ODE inversion method proposed above:\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end ipopt_solve_ode_inverse.cpp}\n------------------------------------------------------------------------------\n*/\n// BEGIN C++\n# include <cppad/ipopt/solve.hpp>\n\nnamespace {\n    using CppAD::AD;\n\n    // value of a during simulation a[0], a[1], a[2]\n    double a_[] =                   {2.0,  1.0, 0.5};\n    // number of components in a\n    size_t na_ = sizeof(a_) / sizeof(a_[0]);\n\n    // function used to simulate data\n    double yone(double t)\n    {   return\n            a_[0]*a_[1] * (exp(-a_[2]*t) - exp(-a_[1]*t)) / (a_[1] - a_[2]);\n    }\n\n    // time points were we have data (no data at first point)\n    double s_[] = {0.0,   0.5,        1.0,          1.5,         2.0 };\n\n    // Simulated data for case with no noise (first point is not used)\n    double z_[] = {yone(s_[1]), yone(s_[2]), yone(s_[3]), yone(s_[4])};\n    size_t nz_  = sizeof(z_) / sizeof(z_[0]);\n\n    // number of trapozoidal approximation points per measurement interval\n    size_t np_  = 40;\n\n\n    class FG_eval\n    {\n    private:\n    public:\n        // derived class part of constructor\n        typedef CPPAD_TESTVECTOR( AD<double> ) ADvector;\n\n        // Evaluation of the objective f(x), and constraints g(x)\n        void operator()(ADvector& fg, const ADvector& x)\n        {   CPPAD_TESTVECTOR( AD<double> ) a(na_);\n            size_t i, j, k;\n\n            // extract the vector a\n            for(i = 0; i < na_; i++)\n                a[i] = x[i];\n\n            // compute the object f(x)\n            fg[0] = 0.0;\n            for(i = 0; i < nz_; i++)\n            {   k = (i + 1) * np_;\n                AD<double> y_1 = x[na_ + 2 * k + 1];\n                AD<double> dif = z_[i] - y_1;\n                fg[0]         += dif * dif;\n            }\n\n            // constraint corresponding to initial value y(0, a)\n            // Note that this constraint is invariant with size of dt\n            fg[1] = x[na_+0] - a[0];\n            fg[2] = x[na_+1] - 0.0;\n\n            // constraints corresponding to trapozoidal approximation\n            for(i = 0; i < nz_; i++)\n            {   // spacing between grid point\n                double dt = (s_[i+1] - s_[i]) / static_cast<double>(np_);\n                for(j = 1; j <= np_; j++)\n                {   k = i * np_ + j;\n                    // compute derivative at y^k\n                    AD<double> y_0  = x[na_ + 2 * k + 0];\n                    AD<double> y_1  = x[na_ + 2 * k + 1];\n                    AD<double> G_0  = - a[1] * y_0;\n                    AD<double> G_1  = + a[1] * y_0 - a[2] * y_1;\n\n                    // compute derivative at y^{k-1}\n                    AD<double> ym_0  = x[na_ + 2 * (k-1) + 0];\n                    AD<double> ym_1  = x[na_ + 2 * (k-1) + 1];\n                    AD<double> Gm_0  = - a[1] * ym_0;\n                    AD<double> Gm_1  = + a[1] * ym_0 - a[2] * ym_1;\n\n                    // constraint should be zero\n                    fg[1 + 2*k ] = y_0  - ym_0 - dt*(G_0 + Gm_0)/2.;\n                    fg[2 + 2*k ] = y_1  - ym_1 - dt*(G_1 + Gm_1)/2.;\n\n                    // scale g(x) so it has similar size as f(x)\n                    fg[1 + 2*k ] /= dt;\n                    fg[2 + 2*k ] /= dt;\n                }\n            }\n        }\n    };\n}\nbool ode_inverse(void)\n{   bool ok = true;\n    size_t i;\n    typedef CPPAD_TESTVECTOR( double ) Dvector;\n\n    // number of components in the function g\n    size_t ng = (np_ * nz_ + 1) * 2;\n    // number of independent variables\n    size_t nx = na_ + ng;\n    // initial value for the variables we are optimizing w.r.t\n    Dvector xi(nx), xl(nx), xu(nx);\n    for(i = 0; i < nx; i++)\n    {   xi[i] =   0.0; // initial value\n        xl[i] = -1e19; // no lower limit\n        xu[i] = +1e19; // no upper limit\n    }\n    for(i = 0; i < na_; i++)\n        xi[0] = 1.5;   // initial value for a\n\n    // all the difference equations are constrained to be zero\n    Dvector gl(ng), gu(ng);\n    for(i = 0; i < ng; i++)\n    {   gl[i] = 0.0;\n        gu[i] = 0.0;\n    }\n    // object defining both f(x) and g(x)\n    FG_eval fg_eval;\n\n    // options\n    std::string options;\n    // Use sparse matrices for calculation of Jacobians and Hessians\n    // with forward mode for Jacobian (seems to be faster for this case).\n    options += \"Sparse  true        forward\\n\";\n    // turn off any printing\n    options += \"Integer print_level 0\\n\";\n    options += \"String  sb        yes\\n\";\n    // maximum number of iterations\n    options += \"Integer max_iter    30\\n\";\n    // approximate accuracy in first order necessary conditions;\n    // see Mathematical Programming, Volume 106, Number 1,\n    // Pages 25-57, Equation (6)\n    options += \"Numeric tol         1e-6\\n\";\n\n    // place to return solution\n    CppAD::ipopt::solve_result<Dvector> solution;\n\n    // solve the problem\n    CppAD::ipopt::solve<Dvector, FG_eval>(\n        options, xi, xl, xu, gl, gu, fg_eval, solution\n    );\n    //\n    // Check some of the solution values\n    //\n    ok &= solution.status == CppAD::ipopt::solve_result<Dvector>::success;\n    //\n    double rel_tol    = 1e-4;  // relative tolerance\n    double abs_tol    = 1e-4;  // absolute tolerance\n    for(i = 0; i < na_; i++)\n        ok &= CppAD::NearEqual( a_[i],  solution.x[i],   rel_tol, abs_tol);\n\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/ipopt_solve/retape.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n\n{xrst_begin ipopt_solve_retape.cpp}\n{xrst_spell\n    retaping\n}\n\nNonlinear Programming Retaping: Example and Test\n################################################\n\nPurpose\n*******\nThis example program demonstrates a case were the ``ipopt::solve``\nargument :ref:`ipopt_solve@options@Retape` should be true.\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end ipopt_solve_retape.cpp}\n*/\n// BEGIN C++\n# include <cppad/ipopt/solve.hpp>\n\nnamespace {\n    using CppAD::AD;\n\n    class FG_eval {\n    public:\n        typedef CPPAD_TESTVECTOR( AD<double> ) ADvector;\n        void operator()(ADvector& fg, const ADvector& x)\n        {   assert( fg.size() == 1 );\n            assert( x.size()  == 1 );\n\n            // compute the Huber function using a conditional\n            // statement that depends on the value of x.\n            double eps = 0.1;\n            if( fabs(x[0]) <= eps )\n                fg[0] = x[0] * x[0] / (2.0 * eps);\n            else\n                fg[0] = fabs(x[0]) - eps / 2.0;\n\n            return;\n        }\n    };\n}\n\nbool retape(void)\n{   bool ok = true;\n    typedef CPPAD_TESTVECTOR( double ) Dvector;\n\n    // number of independent variables (domain dimension for f and g)\n    size_t nx = 1;\n    // number of constraints (range dimension for g)\n    size_t ng = 0;\n    // initial value, lower and upper limits, for the independent variables\n    Dvector xi(nx), xl(nx), xu(nx);\n    xi[0] = 2.0;\n    xl[0] = -1e+19;\n    xu[0] = +1e+19;\n    // lower and upper limits for g\n    Dvector gl(ng), gu(ng);\n\n    // object that computes objective and constraints\n    FG_eval fg_eval;\n\n    // options\n    std::string options;\n    // retape operation sequence for each new x\n    options += \"Retape  true\\n\";\n    // turn off any printing\n    options += \"Integer print_level   0\\n\";\n    options += \"String  sb          yes\\n\";\n    // maximum number of iterations\n    options += \"Integer max_iter      10\\n\";\n    // approximate accuracy in first order necessary conditions;\n    // see Mathematical Programming, Volume 106, Number 1,\n    // Pages 25-57, Equation (6)\n    options += \"Numeric tol           1e-9\\n\";\n    // derivative testing\n    options += \"String  derivative_test            second-order\\n\";\n    // maximum amount of random perturbation; e.g.,\n    // when evaluation finite diff\n    options += \"Numeric point_perturbation_radius  0.\\n\";\n\n    // place to return solution\n    CppAD::ipopt::solve_result<Dvector> solution;\n\n    // solve the problem\n    CppAD::ipopt::solve<Dvector, FG_eval>(\n        options, xi, xl, xu, gl, gu, fg_eval, solution\n    );\n    //\n    // Check some of the solution values\n    //\n    ok &= solution.status == CppAD::ipopt::solve_result<Dvector>::success;\n    double rel_tol    = 1e-6;  // relative tolerance\n    double abs_tol    = 1e-6;  // absolute tolerance\n    ok &= CppAD::NearEqual( solution.x[0], 0.0,  rel_tol, abs_tol);\n\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/ipopt_solve/test.sh.in",
    "content": "#! /bin/bash -e\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\nexport LD_LIBRARY_PATH=@CPPAD_IPOPT_LD_PATH@\n./solve\n"
  },
  {
    "path": "example/jit/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-23 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# Build the example/git directory tests\n#\n# BEGIN_SORT_THIS_LINE_PLUS_2\nSET(source_list\n    atomic.cpp\n    compare_change.cpp\n    compile.cpp\n    dynamic.cpp\n    get_started.cpp\n    jit.cpp\n)\n# END_SORT_THIS_LINE_MINUS_2\n#\nset_compile_flags( example_jit \"${cppad_debug_which}\" \"${source_list}\" )\n#\nADD_EXECUTABLE(example_jit EXCLUDE_FROM_ALL ${source_list})\n#\n# List of libraries to be linked into the specified target\nTARGET_LINK_LIBRARIES(example_jit\n    ${cppad_lib}\n    ${colpack_libs}\n)\n#\n# check_example_jit\nadd_check_executable(check_example jit)\n"
  },
  {
    "path": "example/jit/atomic.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin jit_atomic.cpp}\n\nAtomic Callbacks in JIT Function: Example and Test\n##################################################\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end jit_atomic.cpp}\n-------------------------------------------------------------------------------\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n# include <cppad/utility/link_dll_lib.hpp>\n\n# if CPPAD_USE_CPLUSPLUS_2017\n# include <filesystem>\n# endif\n\n//  DLL_EXT\n# ifndef _WIN32\n# define DLL_EXT         \".so\"\n# else\n# define DLL_EXT         \".dll\"\n# endif\n\n// ----------------------------------------------------------------------------\nnamespace { // BEGIN_EMPTY_NAMESPACE\n//\n// write_c_file\nstd::string write_c_file(size_t index, const std::string& csrc)\n{   //\n    std::string file_name = \"atomic_\" + CppAD::to_string(index) + \".c\";\n    //\n    // write file_name\n    std::ofstream os;\n    os.open(file_name, std::ios::out);\n    os << csrc;\n    os.close();\n    //\n    return file_name;\n}\n//\n// atomic_fun\nclass atomic_fun : public CppAD::atomic_four<double> {\nprivate:\n    const std::string name_;\npublic:\n    atomic_fun(const std::string& name) :\n    CppAD::atomic_four<double>(name),\n    name_(name)\n    {}\nprivate:\n    bool for_type(\n        size_t                                     call_id     ,\n        const CppAD::vector<CppAD::ad_type_enum>&  type_x      ,\n        CppAD::vector<CppAD::ad_type_enum>&        type_y      ) override\n    {   type_y[0] = type_x[0];\n        return true;\n    }\n    // forward double\n    bool forward(\n        size_t                              call_id      ,\n        const CppAD::vector<bool>&          select_y     ,\n        size_t                              order_low    ,\n        size_t                              order_up     ,\n        const CppAD::vector<double>&        taylor_x     ,\n        CppAD::vector<double>&              taylor_y     ) override\n    {   if( order_up != 0 )\n            return false;;\n        taylor_y[0] = 1.0 / taylor_x[0];\n        return true;\n    }\npublic:\n    // forward_zero\n    std::string forward_zero(void)\n    {   std::string csrc =\n            \"# include <stddef.h>\\n\"\n            \"int cppad_atomic_\" + name_ + \"(\\n\";\n        csrc +=R\"_(\n    size_t        call_id,\n    size_t        nx,\n    const double* x,\n    size_t        ny,\n    double*       y,\n    size_t*       compare_change)\n{   if( nx != 1 ) return 1;\n    if( ny != 1 ) return 2;\n    y[0] = 1.0 / x[0];\n    return 0;\n}\n)_\";\n        return csrc;\n    }\n};\n} // END_EMPTY_NAMESPACE\n// ---------------------------------------------------------------------------\nbool atomic(void)\n{   // ok\n    bool ok = true;\n    //\n    // AD\n    using CppAD::AD;\n    //\n    // atomic_name\n    std::string atomic_name = \"reciprocal\";\n    //\n    // reciprocal\n    atomic_fun reciprocal(atomic_name);\n    //\n    // nx, ax\n    size_t nx = 2;\n    CPPAD_TESTVECTOR( AD<double> ) ax(nx);\n    double x0 = 0.5, x1 = 4.0;\n    ax[0] = x0;\n    ax[1] = x1;\n    CppAD::Independent(ax);\n    //\n    // ny, ay\n    size_t ny = nx;\n    CPPAD_TESTVECTOR( AD<double> ) ay(ny);\n    CPPAD_TESTVECTOR( AD<double> ) atom_x(1), atom_y(1);\n    for(size_t j = 0; j < nx; ++j)\n    {   atom_x[0] = ax[j];\n        reciprocal(atom_x, atom_y);\n        ay[j] = atom_y[0];\n    }\n    //\n    // function_name\n    std::string function_name = \"use_reciprocal\";\n    //\n    // f\n    CppAD::ADFun<double> f(ax, ay);\n    f.function_name_set(function_name);\n    //\n    // dll_file\n    std::string dll_file = \"atomic\" DLL_EXT;\n    //\n    // csrc_files\n    CppAD::vector<std::string> csrc_files(2);\n    csrc_files[0]      = write_c_file(0, reciprocal.forward_zero() );\n    std::string c_type = \"double\";\n    std::stringstream ss;\n    f.to_csrc(ss, c_type);\n    csrc_files[1] = write_c_file(1, ss.str() );\n    //\n    // create_dll_lib\n    std::map< std::string, std::string > options;\n    std::string err_msg = CppAD::create_dll_lib(dll_file, csrc_files, options);\n    if( err_msg != \"\" )\n    {   std::cout << \"jit_atomic: \" << err_msg << \"\\n\";\n        ok = false;\n        return ok;\n    }\n    //\n    // dll_linker\n    CppAD::link_dll_lib dll_linker(dll_file, err_msg);\n    //\n    // jit_double\n    using CppAD::jit_double;\n    //\n    // jit_function\n    jit_double jit_function = nullptr;\n    if( err_msg != \"\" )\n    {   std::cout << \"jit_atomic: \" << err_msg << \"\\n\";\n        ok = false;\n    }\n    else\n    {   // jit_function\n        std::string complete_name = \"cppad_jit_\" + function_name;\n        jit_function = reinterpret_cast<jit_double>(\n                dll_linker(complete_name, err_msg)\n        );\n        if( err_msg != \"\" )\n        {   std::cout << \"jit_atomic: \" << err_msg << \"\\n\";\n            ok = false;\n        }\n    }\n    if( ok )\n    {   //\n        // ok\n        // no change\n        CppAD::vector<double> x(nx), y(ny);\n        x[0] = x0;\n        x[1] = x1;\n        for(size_t i = 0; i < ny; ++i)\n            y[i] = std::numeric_limits<double>::quiet_NaN();\n        size_t compare_change = 0;\n        int flag = jit_function(\n            nx, x.data(), ny, y.data(), &compare_change\n        );\n        ok &= flag == 0;\n        ok &= compare_change == 0;\n        for(size_t i = 0; i < ny; ++i)\n            ok &= y[i] == 1.0 / x[i];\n    }\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/jit/compare_change.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-23 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin jit_compare_change.cpp}\n\nThe JIT compare_change Argument: Example and Test\n#################################################\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end jit_compare_change.cpp}\n-------------------------------------------------------------------------------\n*/\n// BEGIN C++\n\n# include <cstddef>\n# include <iostream>\n# include <fstream>\n# include <map>\n\n// DLL_EXT\n# ifdef _WIN32\n# define DLL_EXT \".dll\"\n# else\n# define DLL_EXT \".so\"\n# endif\n\n# include <cppad/cppad.hpp>\nbool compare_change(void)\n{   bool ok = true;\n    //\n    using CppAD::AD;\n    using CppAD::ADFun;\n    using CppAD::Independent;\n    using CppAD::NearEqual;\n    //\n    // nx, ny\n    size_t nx = 2, ny = 1;\n    //\n    // f(x) = x_0 + x_1\n    CPPAD_TESTVECTOR( AD<double> ) ax(nx), ay(ny);\n    ax[0] = 0.0;\n    ax[1] = 1.0;\n    Independent(ax);\n    if( ax[0] < ax[1] )\n        ay[0] = ax[1] - ax[0];\n    else\n        ay[0] = ax[0] - ax[1];\n    ADFun<double> f(ax, ay);\n    f.function_name_set(\"f\");\n    //\n    // csrc_file\n    // created in std::filesystem::current_path\n    std::string c_type    = \"double\";\n    std::string csrc_file = \"compare_change.c\";\n    std::ofstream ofs;\n    ofs.open(csrc_file , std::ofstream::out);\n    f.to_csrc(ofs, c_type);\n    ofs.close();\n    //\n    // dll_file\n    // created in std::filesystem::current_path\n    std::string dll_file = \"jit_to_csrc\" DLL_EXT;\n    CPPAD_TESTVECTOR( std::string) csrc_files(1);\n    csrc_files[0] = csrc_file;\n    std::map< std::string, std::string > options;\n    std::string err_msg = CppAD::create_dll_lib(dll_file, csrc_files, options);\n    if( err_msg != \"\" )\n    {   std::cerr << \"jit_to_csrc: err_msg = \" << err_msg << \"\\n\";\n        return false;\n    }\n    // dll_linker\n    CppAD::link_dll_lib dll_linker(dll_file, err_msg);\n    if( err_msg != \"\" )\n    {   std::cerr << \"jit_to_csrc: err_msg = \" << err_msg << \"\\n\";\n        return false;\n    }\n    //\n    // void_ptr\n    std::string function_name = \"cppad_jit_f\";\n    void* void_ptr = dll_linker(function_name, err_msg);\n    if( err_msg != \"\" )\n    {   std::cerr << \"jit_to_csrc: err_msg = \" << err_msg << \"\\n\";\n        return false;\n    }\n    //\n    // jit_double\n    using CppAD::jit_double;\n    //\n    // f_ptr\n    jit_double f_ptr =\n        reinterpret_cast<jit_double>(void_ptr);\n    //\n    // x, y, compare_change\n    // y = f(x)\n    size_t compare_change = 0;\n    std::vector<double> x(nx), y(ny);\n    x[0] = 0.1;\n    x[1] = 0.2;\n    f_ptr(nx, x.data(), ny, y.data(), &compare_change);\n    //\n    // ok\n    // comparison same as when recorded (compare_change the same)\n    ok &= compare_change == 0;\n    //\n    // ok\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    double check = x[1] - x[0];\n    ok &= NearEqual(y[0], check, eps99, eps99);\n    //\n    // x, y, compare_change\n    x[0] = 0.5;\n    x[1] = 0.1;\n    f_ptr(nx, x.data(), ny, y.data(), &compare_change);\n    //\n    // ok\n    // comparison different from when recorded (compare_change increased)\n    ok &= compare_change == 1;\n    //\n    // ok\n    check = x[1] - x[0];\n    ok &= NearEqual(y[0], check, eps99, eps99);\n    //\n    // x, y, compare_change\n    x[0] = 1.0;\n    x[1] = 5.0;\n    f_ptr(nx, x.data(), ny, y.data(), &compare_change);\n    //\n    // ok\n    // comparison as as when recorded (compare_change the same)\n    ok &= compare_change == 1;\n    //\n    // ok\n    check = x[1] - x[0];\n    ok &= NearEqual(y[0], check, eps99, eps99);\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/jit/compile.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin jit_compile.cpp}\n\nJIT Compiler Options: Example and Test\n######################################\n\ncompile\n*******\nThis example demonstrates setting the JIT\n:ref:`create_dll_lib@options@compile` option.\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end jit_compile.cpp}\n-------------------------------------------------------------------------------\n*/\n// BEGIN C++\n\n# include <cstddef>\n# include <iostream>\n# include <fstream>\n# include <map>\n\n// DLL_EXT\n# ifdef _WIN32\n# define DLL_EXT \".dll\"\n# else\n# define DLL_EXT \".so\"\n# endif\n\n# include <cppad/cppad.hpp>\nbool compile(void)\n{   bool ok = true;\n    //\n    using CppAD::AD;\n    using CppAD::ADFun;\n    using CppAD::Independent;\n    using CppAD::NearEqual;\n    //\n    // compile\n    std::string compile = \"\";\n# if CPPAD_C_COMPILER_MSVC_FLAGS\n    const char* cmd = CPPAD_C_COMPILER_CMD \"/HELP 1> temp.1 2> temp.2\";\n    if( std::system(cmd) == 0 )\n        compile = CPPAD_C_COMPILER_CMD \" /EHs /EHc /c /TC /O2\";\n# endif\n# if CPPAD_C_COMPILER_GNU_FLAGS\n    const char* cmd = CPPAD_C_COMPILER_CMD \" --version > temp\";\n    if( std::system(cmd) == 0 )\n        compile = CPPAD_C_COMPILER_CMD \" -c -fPIC -O2\";\n# endif\n    //\n    if( compile == \"\" )\n    {   std::cout << \": cannot determine C compiler to use so skipping test: \";\n        return ok;\n    }\n    // std::cout << \"compile = \" << compile << \"\\n\";\n    //\n    // nx, ny\n    size_t nx = 2, ny = 1;\n    //\n    // f(x) = x_0 + x_1\n    CPPAD_TESTVECTOR( AD<double> ) ax(nx), ay(ny);\n    ax[0] = 0.0;\n    ax[1] = 1.0;\n    Independent(ax);\n    ay[0] = ax[0] + ax[1];\n    ADFun<double> f(ax, ay);\n    f.function_name_set(\"f\");\n    //\n    // csrc_file\n    // created in std::filesystem::current_path\n    std::string c_type    = \"double\";\n    std::string csrc_file = \"compile.c\";\n    std::ofstream ofs;\n    ofs.open(csrc_file , std::ofstream::out);\n    f.to_csrc(ofs, c_type);\n    ofs.close();\n    //\n    // dll_file\n    // created in std::filesystem::current_path\n    std::string dll_file = \"jit_compile\" DLL_EXT;\n    CPPAD_TESTVECTOR( std::string) csrc_files(1);\n    csrc_files[0] = csrc_file;\n    std::map< std::string, std::string > options;\n    if( compile != \"\" )\n        options[\"compile\"] = compile;\n    std::string err_msg = CppAD::create_dll_lib(dll_file, csrc_files, options);\n    if( err_msg != \"\" )\n    {   std::cerr << \"jit_compile: err_msg = \" << err_msg << \"\\n\";\n        return false;\n    }\n    // dll_linker\n    CppAD::link_dll_lib dll_linker(dll_file, err_msg);\n    if( err_msg != \"\" )\n    {   std::cerr << \"jit_compile: err_msg = \" << err_msg << \"\\n\";\n        return false;\n    }\n    //\n    // void_ptr\n    std::string function_name = \"cppad_jit_f\";\n    void* void_ptr = dll_linker(function_name, err_msg);\n    if( err_msg != \"\" )\n    {   std::cerr << \"jit_compile: err_msg = \" << err_msg << \"\\n\";\n        return false;\n    }\n    //\n    // jit_double\n    using CppAD::jit_double;\n    //\n    // f_ptr\n    jit_double f_ptr =\n        reinterpret_cast<jit_double>(void_ptr);\n    //\n    // x, y, compare_change\n    // y = f(x)\n    size_t compare_change = 0;\n    std::vector<double> x(nx), y(ny);\n    x[0] = 0.3;\n    x[1] = 0.5;\n    f_ptr(nx, x.data(), ny, y.data(), &compare_change);\n    //\n    // ok\n    ok &= compare_change == 0;\n    //\n    // ok\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    double check = x[0] + x[1];\n    ok &= NearEqual(y[0], check, eps99, eps99);\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/jit/dynamic.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-23 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin jit_dynamic.cpp}\n\nJIT With Dynamic Parameters: Example and Test\n#############################################\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end jit_dynamic.cpp}\n-------------------------------------------------------------------------------\n*/\n// BEGIN C++\n\n# include <cstddef>\n# include <iostream>\n# include <fstream>\n# include <map>\n\n// DLL_EXT\n# ifdef _WIN32\n# define DLL_EXT \".dll\"\n# else\n# define DLL_EXT \".so\"\n# endif\n\n# include <cppad/cppad.hpp>\nbool dynamic(void)\n{   bool ok = true;\n    //\n    using CppAD::AD;\n    using CppAD::ADFun;\n    using CppAD::Independent;\n    using CppAD::NearEqual;\n    //\n    // nx, ny\n    size_t np = 2, nx = 2, ny = 1;\n    //\n    // f(x) = x_0 + x_1\n    CPPAD_TESTVECTOR( AD<double> ) ap(np), ax(nx), ay(ny);\n    ap[0] = 0.0;\n    ap[1] = 1.0;\n    ax[0] = 2.0;\n    ax[1] = 4.0;\n    Independent(ax, ap);\n    ay[0] = ap[0] * cos(ax[0])  + ap[1] * sin(ax[1]);\n    ADFun<double> f(ax, ay);\n    f.function_name_set(\"f\");\n    //\n    // csrc_file\n    // created in std::filesystem::current_path\n    std::string c_type    = \"double\";\n    std::string csrc_file = \"dynamic.c\";\n    std::ofstream ofs;\n    ofs.open(csrc_file , std::ofstream::out);\n    f.to_csrc(ofs, c_type);\n    ofs.close();\n    //\n    // dll_file\n    // created in std::filesystem::current_path\n    std::string dll_file = \"jit_dynamic\" DLL_EXT;\n    CPPAD_TESTVECTOR( std::string) csrc_files(1);\n    csrc_files[0] = csrc_file;\n    std::map< std::string, std::string > options;\n    std::string err_msg = CppAD::create_dll_lib(dll_file, csrc_files, options);\n    if( err_msg != \"\" )\n    {   std::cerr << \"jit_dynamic: err_msg = \" << err_msg << \"\\n\";\n        return false;\n    }\n    // dll_linker\n    CppAD::link_dll_lib dll_linker(dll_file, err_msg);\n    if( err_msg != \"\" )\n    {   std::cerr << \"jit_dynamic: err_msg = \" << err_msg << \"\\n\";\n        return false;\n    }\n    //\n    // void_ptr\n    std::string function_name = \"cppad_jit_f\";\n    void* void_ptr = dll_linker(function_name, err_msg);\n    if( err_msg != \"\" )\n    {   std::cerr << \"dynamic: err_msg = \" << err_msg << \"\\n\";\n        return false;\n    }\n    //\n    // jit_double\n    using CppAD::jit_double;\n    //\n    // f_ptr\n    jit_double f_ptr =\n        reinterpret_cast<jit_double>(void_ptr);\n    //\n    // u, y, compare_change\n    // y = f(u)\n    size_t nu             = np + nx;\n    size_t compare_change = 0;\n    std::vector<double> u(nu), y(ny);\n    u[0] = 0.3;  // p[0]\n    u[1] = 0.5;  // p[0]\n    u[2] = 0.7;  // x[0]\n    u[3] = 0.9;  // x[1]\n    f_ptr(nu, u.data(), ny, y.data(), &compare_change);\n    //\n    // ok\n    ok &= compare_change == 0;\n    //\n    // ok\n    // f(u) = p[0] * cos(x[0]) + p[1] * sin(x[1])\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    double check = u[0] * std::cos(u[2]) + u[1] * std::sin(u[3]);\n    ok &= NearEqual(y[0], check, eps99, eps99);\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/jit/get_started.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-23 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin jit_get_started.cpp}\n\nJIT Computation of Derivatives: Example and Test\n################################################\n\nPurpose\n*******\nThis is a simple example using CppAD for Just In Time (JIT)\ncompilation, linking, and running of C source code that computes derivatives.\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end jit_get_started.cpp}\n-------------------------------------------------------------------------------\n*/\n// BEGIN C++\n\n# include <cstddef>\n# include <iostream>\n# include <fstream>\n# include <map>\n\n# include <cppad/configure.hpp>\n# if CPPAD_USE_CPLUSPLUS_2017\n# include <filesystem>\n# endif\n\n// DLL_EXT\n# ifdef _WIN32\n# define DLL_EXT \".dll\"\n# else\n# define DLL_EXT \".so\"\n# endif\n\n# include <cppad/cppad.hpp>\nbool get_started(void)\n{   bool ok = true;\n    //\n    // p\n# if CPPAD_USE_CPLUSPLUS_2017\n    std::filesystem::path p;\n# endif\n    //\n    using CppAD::AD;\n    using CppAD::ADFun;\n    using CppAD::Independent;\n    using CppAD::NearEqual;\n    //\n    // f\n    // f_0 (x_0, x_1) =  x_0 * cos(x_1)\n    // f_1 (x_0, x_1) =  x_0 * sin(x_1)\n    size_t n = 2;\n    size_t m = 2;\n    CPPAD_TESTVECTOR( AD<double> ) ax(n), ay(m);\n    for(size_t j = 0; j < n; ++j)\n        ax[j] = AD<double>( j + 1);\n    Independent(ax);\n    ay[0] = ax[0] * cos( ax[1] );\n    ay[1] = ax[0] * sin( ax[1] );\n    ADFun<double> f(ax, ay);\n    ADFun< AD<double> , double > af = f.base2ad();\n    //\n    // g(x) = f'(x)\n    // g(x) = [ cos(x_1) , - x_0 * sin(x_1) ]\n    //        [ sin(x_1) ,   x_0 * cos(x_1) ]\n    Independent(ax);\n    CPPAD_TESTVECTOR( AD<double> ) az(m * n);\n    az = af.Jacobian(ax);\n    ADFun<double> g(ax, az);\n    g.function_name_set(\"g\");\n    //\n    // csrc_file\n    // created in std::filesystem::current_path()\n    std::string c_type    =  \"double\";\n    std::string csrc_file = \"get_started.c\";\n    std::ofstream ofs;\n    ofs.open(csrc_file , std::ofstream::out);\n    g.to_csrc(ofs, c_type);\n    ofs.close();\n    //\n    // p, ok\n# if CPPAD_USE_CPLUSPLUS_2017\n    p   = std::filesystem::current_path();\n    p  /= csrc_file;\n    ok &= std::filesystem::exists(p);\n# endif\n    //\n    // dll_file\n    // created in std::filesystem::current_path()\n    std::string dll_file = \"jit_get_started\" DLL_EXT;\n    CPPAD_TESTVECTOR( std::string) csrc_files(1);\n    csrc_files[0] = csrc_file;\n    std::map< std::string, std::string > options;\n    std::string err_msg = CppAD::create_dll_lib(dll_file, csrc_files, options);\n    if( err_msg != \"\" )\n    {   std::cerr << \"jit_get_started: err_msg = \" << err_msg << \"\\n\";\n        return false;\n    }\n    //\n    // p, ok\n# if CPPAD_USE_CPLUSPLUS_2017\n    p   = std::filesystem::current_path();\n    p  /= dll_file;\n    ok &= std::filesystem::exists(p);\n# endif\n    //\n    // dll_linker\n    CppAD::link_dll_lib dll_linker(dll_file, err_msg);\n    if( err_msg != \"\" )\n    {   std::cerr << \"jit_get_started: err_msg = \" << err_msg << \"\\n\";\n        return false;\n    }\n    //\n    // void_ptr\n    std::string function_name = \"cppad_jit_g\";\n    void* void_ptr = dll_linker(function_name, err_msg);\n    if( err_msg != \"\" )\n    {   std::cerr << \"jit_get_started: err_msg = \" << err_msg << \"\\n\";\n        return false;\n    }\n    //\n    // jit_double\n    using CppAD::jit_double;\n    //\n    // g_ptr\n    jit_double g_ptr =\n        reinterpret_cast<jit_double>(void_ptr);\n    //\n    // x, z, compare_change\n    // z = g(x)\n    size_t nx = n, nz = m * n, compare_change = 0;\n    std::vector<double> x(nx), z(nz);\n    x[0] = 0.3;\n    x[1] = 0.5;\n    g_ptr(nx, x.data(), nz, z.data(), &compare_change);\n    //\n    // ok\n    ok &= compare_change == 0;\n    //\n    // eps99\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    //\n    // ok\n    // df_0 / dx_0 is stored in z[0 * n + 0]\n    double value = z[ 0 * n + 0];\n    double check = std::cos(x[1]);\n    ok &= NearEqual(value, check, eps99, eps99);\n    //\n    // ok\n    // df_0 / dx_1 is stored in z[0 * n + 1]\n    value = z[ 0 * n + 1];\n    check = - x[0] * std::sin(x[1]);\n    ok &= NearEqual(value, check, eps99, eps99);\n    //\n    // ok\n    // df_1 / dx_0 is stored in z[1 * n + 0]\n    value = z[ 1 * n + 0];\n    check = std::sin(x[1]);\n    ok &= NearEqual(value, check, eps99, eps99);\n    //\n    // ok\n    // df_1 / dx_1 is stored in z[1 * n + 1]\n    value = z[ 1 * n + 1];\n    check = x[0] * std::cos(x[1]);\n    ok &= NearEqual(value, check, eps99, eps99);\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/jit/jit.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin jit.cpp}\n\njit Examples and Tests Driver\n#############################\n\nRunning These Tests\n*******************\nAfter executing the :ref:`cmake-name` command\nform the :ref:`download@Distribution Directory`,\nyou can build and run these tests with the commands::\n\n    cd build\n    make check_example_jit\n\nNote that your choice of :ref:`cmake@generator` may require using\nan different version of make; e.g., ``ninja`` .\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end jit.cpp}\n-------------------------------------------------------------------------------\n*/\n// BEGIN C++\n\n// CPPAD_HAS_* defines\n# include <cppad/configure.hpp>\n\n// system include files used for I/O\n# include <iostream>\n\n// for thread_alloc\n# include <cppad/utility/thread_alloc.hpp>\n\n// test runner\n# include <cppad/utility/test_boolofvoid.hpp>\n\n// BEGIN_SORT_THIS_LINE_PLUS_1\nextern bool atomic(void);\nextern bool compare_change(void);\nextern bool compile(void);\nextern bool dynamic(void);\nextern bool get_started(void);\n// END_SORT_THIS_LINE_MINUS_1\n\n// main program that runs all the tests\nint main(void)\n{   bool ok = true;\n    //\n# if ! (CPPAD_C_COMPILER_MSVC_FLAGS || CPPAD_C_COMPILER_GNU_FLAGS)\n    std::cout << \"Do not know how to use this C compiler to create a DLL\\n\";\n    std::cout << CPPAD_C_COMPILER_CMD << \"\\n\";\n    std::cout << \"Skipping example/jit\\n\";\n# else\n    std::string group = \"example/jit\";\n    size_t      width = 20;\n    CppAD::test_boolofvoid Run(group, width);\n\n    // This line is used by test_one.sh\n\n    // BEGIN_SORT_THIS_LINE_PLUS_1\n    Run( atomic,              \"atomic\"                );\n    Run( compare_change,      \"compare_change\"        );\n    Run( compile,             \"compile\"               );\n    Run( dynamic,             \"dynamic\"               );\n    Run( get_started,         \"get_started\"           );\n    // END_SORT_THIS_LINE_MINUS_1\n\n    // check for memory leak\n    bool memory_ok = CppAD::thread_alloc::free_all();\n    // print summary at end\n    ok = Run.summary(memory_ok);\n# endif\n    //\n    return static_cast<int>( ! ok );\n}\n// END C++\n"
  },
  {
    "path": "example/jit/jit.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-25 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin example_jit}\n\nJIT Creation, Compilation, and Linking of C Source Code\n#######################################################\n\nRestrictions\n************\nThese examples are not tested when the\n:ref:`cmake@cppad_link_flags` contain ``-m32`` .\n\nContents\n********\n{xrst_toc_table\n    example/jit/get_started.cpp\n    example/jit/compare_change.cpp\n    example/jit/compile.cpp\n    example/jit/atomic.cpp\n    example/jit/dynamic.cpp\n}\n\n{xrst_end example_jit}\n"
  },
  {
    "path": "example/json/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n#\n# BEGIN_SORT_THIS_LINE_PLUS_2\nSET(source_list\n    add_op.cpp\n    atom4_op.cpp\n    atom_op.cpp\n    azmul_op.cpp\n    cexp_op.cpp\n    comp_op.cpp\n    discrete_op.cpp\n    div_op.cpp\n    from_json.cpp\n    get_started.cpp\n    json.cpp\n    mul_op.cpp\n    pow_op.cpp\n    print_op.cpp\n    sparse.cpp\n    sub_op.cpp\n    sum_op.cpp\n    to_json.cpp\n    unary_op.cpp\n)\n# END_SORT_THIS_LINE_MINUS_2\n\nset_compile_flags(example_json \"${cppad_debug_which}\" \"${source_list}\" )\n#\nADD_EXECUTABLE(example_json EXCLUDE_FROM_ALL ${source_list})\n\n# List of libraries to be linked into the specified target\nTARGET_LINK_LIBRARIES(example_json\n    ${cppad_lib}\n    ${colpack_libs}\n)\n#\n# check_example_json\nadd_check_executable(check_example json)\n"
  },
  {
    "path": "example/json/add_op.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin json_add_op.cpp}\n\nJson add Operator: Example and Test\n###################################\n\nSource Code\n***********\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end json_add_op.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nbool add_op(void)\n{   bool ok = true;\n    using CppAD::vector;\n    using CppAD::AD;\n    //\n    // AD graph example\n    // node_1 : p[0]\n    // node_2 : p[1]\n    // node_3 : x[0]\n    // node_4 : p[0] + p[1]\n    // node_5 : x[0] + ( p[0] + p[1] )\n    // y[0]   = x[0] + ( p[0] + p[1] )\n    // use single quote to avoid having to escape double quote\n    std::string json =\n        \"{\\n\"\n        \"   'function_name'  : 'add_op example',\\n\"\n        \"   'op_define_vec'  : [ 2, [\\n\"\n        \"       { 'op_code':1, 'name':'add', 'n_arg':2 } ,\\n\"\n        \"       { 'op_code':2, 'name':'sub', 'n_arg':2 } ]\\n\"\n        \"   ],\\n\"\n        \"   'n_dynamic_ind'  : 2,\\n\"\n        \"   'n_variable_ind' : 1,\\n\"\n        \"   'constant_vec'   : [ 0, [ ] ],\\n\"\n        \"   'op_usage_vec'   : [ 2, [\\n\"\n        \"       [ 1, 1, 2 ] ,\\n\" // p[0] + p[1]\n        \"       [ 1, 3, 4 ] ]\\n\" // x[0] + ( p[0] + p[1] )\n        \"   ],\\n\"\n        \"   'dependent_vec' : [ 1, [5] ] \\n\"\n        \"}\\n\";\n    // Convert the single quote to double quote\n    for(size_t i = 0; i < json.size(); ++i)\n        if( json[i] == '\\'' ) json[i] = '\"';\n    //\n    // f(x, p) = x_0 + ( p_0 + p_1 )\n    CppAD::ADFun<double> f;\n    f.from_json(json);\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 2;\n    //\n    // set independent variables and parameters\n    vector<double> p(2), x(1);\n    p[0] = 2.0;\n    p[1] = 3.0;\n    x[0] = 4.0;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    vector<double> y = f.Forward(0, x);\n    //\n    // check result\n    ok &= y[0] == x[0] + ( p[0] + p[1] );\n    // -----------------------------------------------------------------------\n    // Convert to Json graph and back again\n    json = f.to_json();\n    // std::cout << \"json = \" << json;\n    f.from_json(json);\n    // -----------------------------------------------------------------------\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 2;\n    //\n    // set independent variables and parameters\n    p[0] = 2.0;\n    p[1] = 3.0;\n    x[0] = 4.0;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    //\n    // check result\n    ok &= y[0] == x[0] + ( p[0] + p[1] );\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/json/atom4_op.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin json_atom4_op.cpp}\n\nJson Atomic Function Operator: Example and Test\n###############################################\n\nSource Code\n***********\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end json_atom4_op.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nnamespace {\n    class atomic_avg : public CppAD::atomic_four<double> {\n    public:\n        atomic_avg(void) : CppAD::atomic_four<double>(\"avg\")\n        { }\n    private:\n        // for_type\n        bool for_type(\n            size_t                                     call_id     ,\n            const CppAD::vector<CppAD::ad_type_enum>&  type_x      ,\n            CppAD::vector<CppAD::ad_type_enum>&        type_y      ) override\n        {   type_y[0] = type_x[0];\n            return true;\n        }\n        // forward\n        bool forward(\n            size_t                              call_id      ,\n            const CppAD::vector<bool>&          select_y     ,\n            size_t                              order_low    ,\n            size_t                              order_up     ,\n            const CppAD::vector<double>&        taylor_x     ,\n            CppAD::vector<double>&              taylor_y     ) override\n        {\n            // order_up\n            if( order_up != 0 )\n                return false;\n            //\n            // n\n            size_t n = taylor_x.size();\n            if( n == 0 )\n                return false;\n            //\n            // taylor_y\n            double sum = 0.0;\n            for(size_t j = 0; j < n; ++j)\n                sum += taylor_x[j];\n            taylor_y[0] = sum / double(n);\n            //\n            return true;\n        }\n    };\n}\n\nbool atom4_op(void)\n{   bool ok = true;\n    using CppAD::vector;\n    using CppAD::AD;\n    //\n    // avg\n    atomic_avg avg;\n    //\n    // -----------------------------------------------------------------------\n    // g (p; x) = avg( [ p_0 * x_0, p_0 * x_1 ] )\n    //          = p_0 * (x_0 + x_1) / 2\n    //\n    // This function has an atomic function operator with name avg\n    // node_1 : p[0]\n    // node_2 : x[0]\n    // node_3 : x[1]\n    // node_4 : p[0] * x[0]\n    // node_5 : p[0] * x[1]\n    // node_6 : avg( p[0] * x[0], p[0] * x[1] )\n    // y[0]   = p[0] * ( x[0] + x[1] ) / 2\n    std::string json =\n        \"{\\n\"\n        \"   'function_name'  : 'g(p; x)',\\n\"\n        \"   'op_define_vec'  : [ 2, [\\n\"\n        \"       { 'op_code':1, 'name':'atom4'          } ,\\n\"\n        \"       { 'op_code':2, 'name':'mul', 'n_arg':2 } ]\\n\"\n        \"   ],\\n\"\n        \"   'n_dynamic_ind'  : 1,\\n\"              // p[0]\n        \"   'n_variable_ind' : 2,\\n\"              // x[0], x[1]\n        \"   'constant_vec'   : [ 0, [ ] ],\\n\"\n        \"   'op_usage_vec'   : [ 3, [\\n\"\n        \"       [ 2, 1, 2 ]                      ,\\n\" // p[0] * x[0]\n        \"       [ 2, 1, 3 ]                      ,\\n\" // p[0] * x[1]\n                // avg( p[0] * x[0], p[0] * x[1] )\n        \"       [ 1, 'avg', 0, 1, 2, [ 4, 5 ] ]  ]\\n\"\n        \"   ],\\n\"\n        \"   'dependent_vec' : [ 1, [6] ] \\n\"\n        \"}\\n\";\n    // Convert the single quote to double quote\n    for(size_t i = 0; i < json.size(); ++i)\n        if( json[i] == '\\'' ) json[i] = '\"';\n    // ------------------------------------------------------------------------\n    CppAD::ADFun<double> g;\n    g.from_json(json);\n    // ------------------------------------------------------------------------\n    ok &= g.Domain() == 2;\n    ok &= g.Range() == 1;\n    ok &= g.size_dyn_ind() == 1;\n    //\n    // set p in g(p; x)\n    vector<double> p(1);\n    p[0] = 2.0;\n    g.new_dynamic(p);\n    //\n    // evaluate g(p; x)\n    vector<double> x(2), y(1);\n    x[0] = 3.0;\n    x[1] = 4.0;\n    y    = g.Forward(0, x);\n    //\n    // check value\n    ok &= y[0] == p[0] * (x[0] + x[1]) / 2.0;\n    // ------------------------------------------------------------------------\n    json = g.to_json();\n    g.from_json(json);\n    // ------------------------------------------------------------------------\n    ok &= g.Domain() == 2;\n    ok &= g.Range() == 1;\n    ok &= g.size_dyn_ind() == 1;\n    //\n    // set p in g(p; x)\n    p[0] = 5.0;\n    g.new_dynamic(p);\n    //\n    // evaluate g(p; x)\n    x[0] = 6.0;\n    x[1] = 7.0;\n    y    = g.Forward(0, x);\n    //\n    // check value\n    ok &= y[0] == p[0] * (x[0] + x[1]) / 2.0;\n    // ------------------------------------------------------------------------\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/json/atom_op.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin json_atom_op.cpp}\n\nJson Atomic Function Three Operator: Example and Test\n#####################################################\n\nSource Code\n***********\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end json_atom_op.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nbool atom_op(void)\n{   bool ok = true;\n    using CppAD::vector;\n    using CppAD::AD;\n    // use single quote in graphs to avoid having to escape double quote\n    //\n    // -----------------------------------------------------------------------\n    // Define f_0 (x_0, x_1; p) = x_1 + p_0 * x_0\n    //\n    // This function does not have an atomic function operator\n    // node_1 : p[0]\n    // node_2 : x[0]\n    // node_3 : x[1]\n    // node_4 : p[0] * x[0]\n    // node_5 : x[1] + p[0] * x[0]\n    // y[0]   = x[1] + p[0] * x[0]\n    std::string json =\n        \"{\\n\"\n        \"   'function_name'  : 'f(x; p)',\\n\"\n        \"   'op_define_vec'  : [ 2, [\\n\"\n        \"       { 'op_code':1, 'name':'mul', 'n_arg':2 } ,\\n\"\n        \"       { 'op_code':2, 'name':'add', 'n_arg':2 } ]\\n\"\n        \"   ],\\n\"\n        \"   'n_dynamic_ind'  : 1,\\n\"         // p[0]\n        \"   'n_variable_ind' : 2,\\n\"         // x[0], x[1]\n        \"   'constant_vec'   : [ 0, [ ] ],\\n\"\n        \"   'op_usage_vec'   : [ 2, [\\n\"\n        \"       [ 1, 1, 2 ] ,\\n\" // p[0] * x[0]\n        \"       [ 2, 3, 4 ] ]\\n\" // x[1] + p[0] * x[0]\n        \"   ],\\n\"\n        \"   'dependent_vec' : [ 1, [5] ] \\n\"\n        \"}\\n\";\n    // Convert the single quote to double quote\n    for(size_t i = 0; i < json.size(); ++i)\n        if( json[i] == '\\'' ) json[i] = '\"';\n    //\n    CppAD::ADFun<double> f;\n    f.from_json(json);\n    ok &= f.Domain() == 2;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 1;\n    //\n    // A ckhpoint_two function with name f(x; p) is derived from\n    // an atomic_three function with the same name.\n    bool internal_bool    = false;\n    bool use_hes_sparsity = false;\n    bool use_base2ad      = false;\n    bool use_in_parallel  = false;\n    CppAD::chkpoint_two<double> chk_f(f, \"f(x; p)\",\n        internal_bool, use_hes_sparsity, use_base2ad, use_in_parallel\n    );\n    // -----------------------------------------------------------------------\n    // g (u_0, u_1; p, q) = f(u_0 + q_0, u_1 + q_1, p)\n    //                    = u_1 + q_1 + p_0 * ( u_0 + q_0 )\n    //\n    // This function has an atomic function operator with name f(x; p)\n    // node_1 : q[0]\n    // node_2 : q[1]\n    // node_3 : u[0]\n    // node_4 : u[1]\n    // node_5 : u[0] + q[0]\n    // node_6 : u[1] + q[1]\n    // node_7 : f( u[0] + q[0], u[1] + q[1]; p)\n    // y[0]   = u[1] + q[1] + p[0] * (u[0]  + q[0])\n    json =\n        \"{\\n\"\n        \"   'function_name'  : 'g(u; p, q)',\\n\"\n        \"   'op_define_vec'  : [ 2, [\\n\"\n        \"       { 'op_code':1, 'name':'atom'           } ,\\n\"\n        \"       { 'op_code':2, 'name':'add', 'n_arg':2 } ]\\n\"\n        \"   ],\\n\"\n        \"   'n_dynamic_ind'  : 2,\\n\"              // q[0], q[1]\n        \"   'n_variable_ind' : 2,\\n\"              // u[0], u[1]\n        \"   'constant_vec'   : [ 0, [ ] ],\\n\"\n        \"   'op_usage_vec'   : [ 3, [\\n\"\n        \"       [ 2, 3, 1 ]                      ,\\n\" // u[0] + q[0]\n        \"       [ 2, 4, 2 ]                      ,\\n\" // u[1] + q[1]\n        // f(u_0 + q_0, u_1 + q_1; p) =  u[1] + q[1] + p[0] * (u[0]  + q[0])\n        \"       [ 1, 'f(x; p)', 1, 2, [ 5, 6 ] ] ]\\n\"\n        \"   ],\\n\"\n        \"   'dependent_vec' : [ 1, [7] ] \\n\"\n        \"}\\n\";\n    // Convert the single quote to double quote\n    for(size_t i = 0; i < json.size(); ++i)\n        if( json[i] == '\\'' ) json[i] = '\"';\n    // ------------------------------------------------------------------------\n    CppAD::ADFun<double> g;\n    g.from_json(json);\n    // ------------------------------------------------------------------------\n    ok &= g.Domain() == 2;\n    ok &= g.Range() == 1;\n    ok &= g.size_dyn_ind() == 2;\n    //\n    // set p in g(u; p, q)\n    vector<double> p(1);\n    p[0] = 2.0;\n    chk_f.new_dynamic(p);\n    //\n    // set q in g(u; p, q)\n    vector<double> q(2);\n    q[0] = 3.0;\n    q[1] = 4.0;\n    g.new_dynamic(q);\n    //\n    // evaluate g(u; p, q)\n    vector<double> u(2), y(1);\n    u[0] = 5.0;\n    u[1] = 6.0;\n    y    = g.Forward(0, u);\n    //\n    // check value\n    ok &= y[0] == u[1] + q[1] + p[0] * (u[0]  + q[0]);\n    // ------------------------------------------------------------------------\n    json = g.to_json();\n    // std::cout << json;\n    g.from_json(json);\n    // ------------------------------------------------------------------------\n    ok &= g.Domain() == 2;\n    ok &= g.Range() == 1;\n    ok &= g.size_dyn_ind() == 2;\n    //\n    // set p in g(u; p, q)\n    p[0] = 3.0;\n    chk_f.new_dynamic(p);\n    //\n    // set q in g(u; p, q)\n    q[0] = 4.0;\n    q[1] = 5.0;\n    g.new_dynamic(q);\n    //\n    // evaluate g(u; p, q)\n    u[0] = 6.0;\n    u[1] = 7.0;\n    y    = g.Forward(0, u);\n    //\n    // check value\n    ok &= y[0] == u[1] + q[1] + p[0] * (u[0]  + q[0]);\n    // ------------------------------------------------------------------------\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/json/azmul_op.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin json_azmul_op.cpp}\n\nJson azmul Operator: Example and Test\n#####################################\n\nSource Code\n***********\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end json_azmul_op.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nbool azmul_op(void)\n{   bool ok = true;\n    using CppAD::vector;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    //\n    // AD graph example\n    // node_1 : p[0]\n    // node_2 : p[1]\n    // node_3 : x[0]\n    // node_4 : x[1]\n    // node_5 : azmul(p[0], p[1])\n    // node_6 : azmul(x[0], x[1])\n    // node_7 = azmul(p[0], p[1]) + azmul(x[0], x[1])\n    // y[0]   = azmul(p[0], p[1]) + azmul(x[0], x[1])\n    // use single quote to avoid having to escape double quote\n    std::string json =\n        \"{\\n\"\n        \"   'function_name'  : 'azmul_op example',\\n\"\n        \"   'op_define_vec'  : [ 2, [\\n\"\n        \"       { 'op_code':1, 'name':'add',   'n_arg':2 } ,\\n\"\n        \"       { 'op_code':2, 'name':'azmul', 'n_arg':2 } ]\\n\"\n        \"   ],\\n\"\n        \"   'n_dynamic_ind'  : 2,\\n\"\n        \"   'n_variable_ind' : 2,\\n\"\n        \"   'constant_vec'   : [ 0, [ ] ],\\n\"\n        \"   'op_usage_vec'   : [ 3, [\\n\"\n        \"       [ 2, 1, 2 ] ,\\n\" // azmul(p[0], p[1])\n        \"       [ 2, 3, 4 ] ,\\n\" // azmul(x[0], )\n        \"       [ 1, 5, 6 ] ]\\n\" // azmul(p[0], p[1]) + azmul(x[0], x[1])\n        \"   ],\\n\"\n        \"   'dependent_vec' : [ 1, [7] ] \\n\"\n        \"}\\n\";\n    // Convert the single quote to double quote\n    for(size_t i = 0; i < json.size(); ++i)\n        if( json[i] == '\\'' ) json[i] = '\"';\n    //\n    // f(x, p) = azmul(p_0, p_1) + azmul(x_0, x_1);\n    CppAD::ADFun<double> f;\n    f.from_json(json);\n    //\n    ok &= f.Domain() == 2;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 2;\n    //\n    // set independent variables and parameters\n    vector<double> p(2), x(2);\n    p[0] = 2.0;\n    p[1] = 3.0;\n    x[0] = 4.0;\n    x[1] = 5.0;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    vector<double> y = f.Forward(0, x);\n    //\n    // check result\n    double check_y0 = 0.0;\n    if( p[0] != 0.0 )\n        check_y0 += p[0] * p[1];\n    if( x[0] != 0.0 )\n        check_y0 += x[0] * x[1];\n    ok &= NearEqual(y[0], check_y0, eps99, eps99);\n    // -----------------------------------------------------------------------\n    // Convert to Json graph and back again\n    json = f.to_json();\n    // std::cout << \"json = \" << json;\n    f.from_json(json);\n    // -----------------------------------------------------------------------\n    ok &= f.Domain() == 2;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 2;\n    //\n    // set independent variables and parameters\n    p[0] = 0.0;\n    p[1] = std::numeric_limits<double>::quiet_NaN();\n    x[0] = 2.0;\n    x[1] = 3.0;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    //\n    // check result\n    check_y0 = 0.0;\n    if( p[0] != 0.0 )\n        check_y0 += p[0] * p[1];\n    if( x[0] != 0.0 )\n        check_y0 += x[0] * x[1];\n    ok &= NearEqual(y[0], check_y0, eps99, eps99);\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/json/cexp_op.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin json_cexp_op.cpp}\n\nJson Conditional Expressions: Example and Test\n##############################################\n\nSource Code\n***********\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end json_cexp_op.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nbool cexp_op(void)\n{   bool ok = true;\n    using CppAD::vector;\n    using CppAD::AD;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    //\n    // AD graph example\n    // node_1 : p[0]\n    // node_2 : x[0]\n    // node_3 : c[0]\n    // node_4 : cexp_le(p[0], x[0], p[0], x[0])\n    // y[0]   = cexp_le(p[0], x[0], p[0], x[0])\n    // use single quote to avoid having to escape double quote\n    std::string json =\n        \"{\\n\"\n        \"   'function_name'  : 'cexp_op example',\\n\"\n        \"   'op_define_vec'  : [ 1, [\\n\"\n        \"       { 'op_code':1, 'name':'cexp_le', 'n_arg':4 } ]\\n\"\n        \"   ],\\n\"\n        \"   'n_dynamic_ind'  : 1,\\n\"\n        \"   'n_variable_ind' : 1,\\n\"\n        \"   'constant_vec'   : [ 1, [ -0.1 ] ],\\n\" // c[0]\n        \"   'op_usage_vec'   : [ 1, [\\n\"\n        \"       [ 1, 1, 2, 1, 2 ]      ]\\n\" // cexp_le(p[0], x[0], p[0], x[0])\n        \"   ],\\n\"\n        \"   'dependent_vec' : [ 1, [4] ] \\n\"\n        \"}\\n\";\n    // Convert the single quote to double quote\n    for(size_t i = 0; i < json.size(); ++i)\n        if( json[i] == '\\'' ) json[i] = '\"';\n    //\n    // f(x, p) = cexp_le(p[0], x[0], p[0], x[0])\n    CppAD::ADFun<double> f;\n    f.from_json(json);\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 1;\n    //\n    // set independent variables and parameters\n    vector<double> p(1), x(1);\n    p[0] = 0.2;\n    x[0] = 0.3;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    vector<double> y = f.Forward(0, x);\n    //\n    // check result\n    double check;\n    if( p[0] <= x[0] )\n        check= p[0];\n    else\n        check = x[0];\n    //\n    // check result\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n    // ----------------------------------------------------------------------\n    // Convert to Json graph and back again\n    json = f.to_json();\n    f.from_json(json);\n    // ----------------------------------------------------------------------\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    //\n    // check result\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/json/comp_op.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin json_comp_op.cpp}\n\nJson Comparison Operators: Example and Test\n###########################################\n\nSource Code\n***********\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end json_comp_op.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nbool comp_op(void)\n{   bool ok = true;\n    using CppAD::vector;\n    using CppAD::AD;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    //\n    // AD graph example\n    // node_1 : p[0]\n    // node_2 : x[0]\n    //        : x[0] < p[0]\n    // node_3 : p[0] - x[0]\n    // node_4 : log( p[0] - x[0] )\n    // y[0]   = log( p[0] - x[0] )\n    // use single quote to avoid having to escape double quote\n    std::string json =\n        \"{\\n\"\n        \"   'function_name'  : 'comp_op example',\\n\"\n        \"   'op_define_vec'  : [ 3, [\\n\"\n        \"       { 'op_code':1, 'name':'comp_lt'            } ,\\n\"\n        \"       { 'op_code':2, 'name':'sub',     'n_arg':2 } ,\\n\"\n        \"       { 'op_code':3, 'name':'log',     'n_arg':1 } ]\\n\"\n        \"   ],\\n\"\n        \"   'n_dynamic_ind'  : 1,\\n\"\n        \"   'n_variable_ind' : 1,\\n\"\n        \"   'constant_vec'   : [ 0, [ ] ],\\n\"\n        \"   'op_usage_vec'   : [ 3, [\\n\"\n        \"       [ 1, 0, 2, [2, 1 ] ] ,\\n\" // x[0] < p[0]\n        \"       [ 2, 1, 2          ] ,\\n\" // p[0] - x[0]\n        \"       [ 3, 3             ] ]\\n\" // log( p[0] - x[0] )\n        \"   ],\\n\"\n        \"   'dependent_vec' : [ 1, [4] ] \\n\"\n        \"}\\n\";\n    // Convert the single quote to double quote\n    for(size_t i = 0; i < json.size(); ++i)\n        if( json[i] == '\\'' ) json[i] = '\"';\n    //\n    // f(x, p) = log( p[0] - x[0] )\n    CppAD::ADFun<double> f;\n    f.from_json(json);\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 1;\n    //\n    // set independent variables and parameters\n    vector<double> p(1), x(1);\n    p[0] = 0.3;\n    x[0] = 0.2;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    vector<double> y = f.Forward(0, x);\n    //\n    //  x[0] < p[0] so comparison should not have changed\n    ok &= f.compare_change_number() == 0;\n    //\n    // check result\n    double check = std::log( p[0] - x[0] );\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n    //\n    // case where comparison is false\n    f.check_for_nan(false); // suppress checking for nan for this test\n    x[0] = 0.4;\n    y = f.Forward(0, x);\n    ok &= f.compare_change_number() == 1;\n    //\n    // -----------------------------------------------------------------------\n    // Convert to Json graph and back again\n    json = f.to_json();\n    // std::cout << json;\n    f.from_json(json);\n    // -----------------------------------------------------------------------\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    x[0] = 0.2;\n    y = f.Forward(0, x);\n    //\n    // check result\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n    //\n    // case where comparison is false\n    x[0] = 0.4;\n    y = f.Forward(0, x);\n    ok &= f.compare_change_number() == 1;\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/json/discrete_op.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin json_discrete_op.cpp}\n\nJson add Operator: Example and Test\n###################################\n\nSource Code\n***********\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end json_discrete_op.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nnamespace {\n    double heaviside(const double &x)\n    {   if( x < 0.0 )\n            return 0.0;\n        if( x == 0.0 )\n            return 0.5;\n        return 1.0;\n    }\n    CPPAD_DISCRETE_FUNCTION(double, heaviside)\n}\n\nbool discrete_op(void)\n{   bool ok = true;\n    using CppAD::vector;\n    using CppAD::AD;\n    //\n    // The discrete function does not exist until its AD version is called\n    heaviside( CppAD::AD<double>( 0.0 ) );\n    //\n    //\n    // AD graph example\n    // node_1 : p[0]\n    // node_2 : x[0]\n    // node_3 : heaviside(p[0])\n    // node_4 : heaviside(p[1])\n    // node_5 = heaviside(p[0]) + heaviside(p[1])\n    // y[0]   = heaviside(p[0]) + heaviside(p[1])\n    // use single quote to avoid having to escape double quote\n    std::string json =\n        \"{\\n\"\n        \"   'function_name'  : 'discrete_op example',\\n\"\n        \"   'op_define_vec'  : [ 2, [\\n\"\n        \"       { 'op_code':1, 'name':'add',      'n_arg':2 } ,\\n\"\n        \"       { 'op_code':2, 'name':'discrete' }            ]\\n\"\n        \"   ],\\n\"\n        \"   'n_dynamic_ind'  : 1,\\n\"\n        \"   'n_variable_ind' : 1,\\n\"\n        \"   'constant_vec'   : [ 0, [ ] ],\\n\"\n        \"   'op_usage_vec'   : [ 3, [\\n\"\n        \"       [ 2, 'heaviside', 1, 1, [ 1 ] ] ,\\n\" // heaviside(p[0])\n        \"       [ 2, 'heaviside', 1, 1, [ 2 ] ] ,\\n\" // heaviside(x[0])\n        \"       [ 1, 3, 4 ] ]\\n\"  // heaviside(p[0]) + heaviside(x[0])\n        \"   ],\\n\"\n        \"   'dependent_vec' : [ 1, [5] ] \\n\"\n        \"}\\n\";\n    // Convert the single quote to double quote\n    for(size_t i = 0; i < json.size(); ++i)\n        if( json[i] == '\\'' ) json[i] = '\"';\n    //\n    // f(x, p) = x_0 + ( p_0 + p_1 )\n    CppAD::ADFun<double> f;\n    f.from_json(json);\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 1;\n    //\n    // set independent variables and parameters\n    CPPAD_TESTVECTOR(double) p(1), x(1);\n    p[0] = 0.0;\n    x[0] = 2.0;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    CPPAD_TESTVECTOR(double) y = f.Forward(0, x);\n    //\n    // check result\n    ok &= y[0] == heaviside(p[0]) + heaviside(x[0]);\n    // -----------------------------------------------------------------------\n    // Convert to Json graph and back again\n    json = f.to_json();\n    // std::cout << \"json = \" << json;\n    f.from_json(json);\n    // -----------------------------------------------------------------------\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 1;\n    //\n    // set independent variables and parameters\n    p[0] = -2.0;\n    x[0] = 2.0;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    //\n    // check result\n    ok &= y[0] == heaviside(p[0]) + heaviside(x[0]);\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/json/div_op.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin json_div_op.cpp}\n\nJson div Operator: Example and Test\n###################################\n\nSource Code\n***********\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end json_div_op.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nbool div_op(void)\n{   bool ok = true;\n    using CppAD::vector;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    //\n    // AD graph example\n    // node_1 : p[0]\n    // node_2 : p[1]\n    // node_3 : x[0]\n    // node_4 : p[0] / p[1]\n    // node_5 : x[0] / ( p[1] / p[0] )\n    // y[0]   = p[0] / p[1]\n    // y[1]   = x[0] / ( p[0] / p[1] )\n    // use single quote to avoid having to escape double quote\n    std::string json =\n        \"{\\n\"\n        \"   'function_name'  : 'div example',\\n\"\n        \"   'op_define_vec'  : [ 1, [\\n\"\n        \"       { 'op_code':1, 'name':'div', 'n_arg':2 } ]\\n\"\n        \"   ],\\n\"\n        \"   'n_dynamic_ind'  : 2,\\n\"\n        \"   'n_variable_ind' : 1,\\n\"\n        \"   'constant_vec'   : [ 0, [ ] ],\\n\"\n        \"   'op_usage_vec'   : [ 2, [\\n\"\n        \"       [ 1, 1, 2 ] ,\\n\" // p[0] / p[1]\n        \"       [ 1, 3, 4 ] ]\\n\" // x[0] / ( p[0] / p[1] )\n        \"   ],\\n\"\n        \"   'dependent_vec' : [ 2, [4, 5] ] \\n\"\n        \"}\\n\";\n    // Convert the single quote to double quote\n    for(size_t i = 0; i < json.size(); ++i)\n        if( json[i] == '\\'' ) json[i] = '\"';\n    //\n    // f(x, p) = [ p_0 / p_1 , x_0 * p_1 / p_0 ]\n    CppAD::ADFun<double> f;\n    f.from_json(json);\n    //\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 2;\n    ok &= f.size_dyn_ind() == 2;\n    //\n    // set independent variables and parameters\n    vector<double> p(2), x(1);\n    p[0] = 2.0;\n    p[1] = 3.0;\n    x[0] = 4.0;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    vector<double> y = f.Forward(0, x);\n    //\n    // check result\n    ok &= NearEqual(y[0] , p[0] / p[1] , eps99, eps99 );\n    ok &= NearEqual(y[1] , x[0] / ( p[0] / p[1] ), eps99, eps99 );\n    // -----------------------------------------------------------------------\n    // Convert to Json graph and back again\n    json = f.to_json();\n    // std::cout << \"json = \" << json;\n    f.from_json(json);\n    // -----------------------------------------------------------------------\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 2;\n    ok &= f.size_dyn_ind() == 2;\n    //\n    // set independent variables and parameters\n    p[0] = 2.0;\n    p[1] = 3.0;\n    x[0] = 4.0;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    //\n    // check result\n    ok &= NearEqual(y[0] , p[0] / p[1] , eps99, eps99 );\n    ok &= NearEqual(y[1] , x[0] / ( p[0] / p[1] ), eps99, eps99 );\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/json/from_json.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin from_json.cpp}\n\nConvert Jason Graph to an ADFun Object: Example and Test\n########################################################\n\nSource Code\n***********\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end from_json.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nbool from_json(void)\n{   bool ok = true;\n    using CppAD::vector;\n    //\n    // An AD graph example\n    // node_1 : p[0]\n    // node_2 : x[0]\n    // node_3 : x[1]\n    // node_4 : -2.0\n    // node_5 : p[0] + x[0] + x[1]\n    // node_6 : (p[0] + x[0] + x[1]) * (p[0] + x[0] + x[1])\n    // y[0]   = (p[0] + x[0] + x[1]) * (p[0] + x[0] + x[1])\n    // use single quote to avoid having to escape double quote\n    std::string json =\n        \"{\\n\"\n        \"   'function_name'  : 'from_json example',\\n\"\n        \"   'op_define_vec'  : [ 3, [\\n\"\n        \"       { 'op_code':1, 'name':'add', 'n_arg':2 } ,\\n\"\n        \"       { 'op_code':2, 'name':'mul', 'n_arg':2 } ,\\n\"\n        \"       { 'op_code':3, 'name':'sum'            } ]\\n\"\n        \"   ],\\n\"\n        \"   'n_dynamic_ind'  : 1,\\n\"\n        \"   'n_variable_ind' : 2,\\n\"\n        \"   'constant_vec'   : [ 1, [ -2.0 ] ],\\n\"\n        \"   'op_usage_vec'   : [ 2, [\\n\"\n        \"       [ 3, 1, 3, [1, 2, 3 ] ] ,\\n\"\n        \"       [ 2, 5, 5             ] ] \\n\"\n        \"   ],\\n\"\n        \"   'dependent_vec'   : [ 1, [6] ] \\n\"\n        \"}\\n\";\n    // Convert the single quote to double quote\n    for(size_t i = 0; i < json.size(); ++i)\n        if( json[i] == '\\'' ) json[i] = '\"';\n    //\n    CppAD::ADFun<double> fun;\n    fun.from_json(json);\n    //\n    // Compute function value\n    vector<double> p(1), x(2);\n    p[0] = 1.0;\n    x[0] = 2.0;\n    x[1] = 3.0;\n    fun.new_dynamic(p);\n    vector<double> y = fun.Forward(0, x);\n    ok  &= y[0] ==  (p[0] + x[0] + x[1]) * (p[0] + x[0] + x[1]);\n    //\n    // Conpute derivative value\n    vector<double> jac = fun.Jacobian(x);\n    ok &= jac[0] == 2.0 * (p[0] + x[0] + x[1]);\n    ok &= jac[1] == 2.0 * (p[0] + x[0] + x[1]);\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/json/get_started.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin json_get_started.cpp}\n{xrst_spell\n    dx\n}\n\nJson Get Started: Example and Test\n##################################\n\nNotation\n********\n\n.. csv-table::\n    :widths: auto\n\n    Notation,Description,size\n    :ref:`json_ad_graph@Node Indices@p`,vector of dynamic parameters,1\n    :ref:`json_ad_graph@Node Indices@x`,vector of independent variables,1\n    :ref:`json_ad_graph@Node Indices@c`,vector of constants,1\n    y,vector of dependent variables,1\n\nNode Table\n**********\n\n.. csv-table::\n    :widths: auto\n\n    index,value\n    1,p[0]\n    2,x[0]\n    3,c[0]\n    4,sin(p[0])\n    5,sin(x[0])\n    6,sin(c[0])\n    7,sin(p[0]) + sin(x[0]) + sin(c[0])\n    y[0],sin(p[0]) + sin(x[0]) + sin(c[0])\n\nInclude\n*******\nInclude the CppAD core functions:\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <cppad/cppad.hpp>\n/* {xrst_code}\n{xrst_spell_on}\n\nSyntax\n******\n| *ok* = ``get_started`` ()\n{xrst_spell_off}\n{xrst_code cpp} */\nbool get_started(void)\n{\n/* {xrst_code}\n{xrst_spell_on}\n\nSetup\n*****\n{xrst_spell_off}\n{xrst_code cpp} */\n    bool ok = true;\n    using CppAD::vector;\n    using CppAD::AD;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n/* {xrst_code}\n{xrst_spell_on}\nFunction\n********\n\nBegin Function\n==============\nSee :ref:`json_ad_graph@AD Graph@function` :\n{xrst_spell_off}\n{xrst_code cpp} */\n    std::string json =\n        \"{\\n\"\n        \"   'function_name'  : 'get_started example',\\n\"\n/* {xrst_code}\n{xrst_spell_on}\nBegin op_define_vec\n===================\nsee :ref:`json_ad_graph@op_define_vec` :\n{xrst_spell_off}\n{xrst_code cpp} */\n        \"   'op_define_vec'  : [ 2, [\\n\"\n/* {xrst_code}\n{xrst_spell_on}\nDefine Unary\n============\nsee :ref:`json_graph_op@Unary Operators` :\n{xrst_spell_off}\n{xrst_code cpp} */\n        \"       { 'op_code':1, 'name':'sin', 'n_arg':1 } ,\\n\"\n/* {xrst_code}\n{xrst_spell_on}\nDefine Sum\n==========\nsee :ref:`json_graph_op@sum` :\n{xrst_spell_off}\n{xrst_code cpp} */\n        \"       { 'op_code':2, 'name':'sum'            } ]\\n\"\n/* {xrst_code}\n{xrst_spell_on}\nEnd op_define_vec\n=================\n{xrst_spell_off}\n{xrst_code cpp} */\n        \"   ],\\n\"\n/* {xrst_code}\n{xrst_spell_on}\nn_dynamic_ind\n=============\nsee :ref:`json_ad_graph@dynamic_ind_vec@n_dynamic_ind` :\n{xrst_spell_off}\n{xrst_code cpp} */\n        \"   'n_dynamic_ind'  : 1,\\n\"\n/* {xrst_code}\n{xrst_spell_on}\nn_variable_ind\n==============\nsee :ref:`json_ad_graph@variable_ind_vec@n_variable_ind` :\n{xrst_spell_off}\n{xrst_code cpp} */\n        \"   'n_variable_ind' : 1,\\n\"\n/* {xrst_code}\n{xrst_spell_on}\nconstant_vec\n============\nsee :ref:`json_ad_graph@constant_vec` :\n{xrst_spell_off}\n{xrst_code cpp} */\n        \"   'constant_vec'   : [ 1, [ -0.1 ] ],\\n\" // c[0]\n/* {xrst_code}\n{xrst_spell_on}\nBegin op_usage_vec\n==================\nsee :ref:`json_ad_graph@op_usage_vec` :\n{xrst_spell_off}\n{xrst_code cpp} */\n        \"   'op_usage_vec'   : [ 4, [\\n\"\n/* {xrst_code}\n{xrst_spell_on}\nop_usage\n========\nsee op_usage with\n:ref:`json_ad_graph@op_usage@n_arg In Definition` :\n{xrst_spell_off}\n{xrst_code cpp} */\n        \"       [ 1, 1]                ,\\n\" // sin(p[0])\n        \"       [ 1, 2]                ,\\n\" // sin(x[0])\n        \"       [ 1, 3]                ,\\n\" // sin(c[0])\n/* {xrst_code}\n{xrst_spell_on}\nsee op_usage with\n:ref:`json_ad_graph@op_usage@n_arg Not In Definition` :\n\n{xrst_spell_off}\n{xrst_code cpp} */\n        \"       [ 2, 1, 3, [4, 5, 6] ] ]\\n\" // sin(p[0])+sin(x[0])+sin(c[0])\n/* {xrst_code}\n{xrst_spell_on}\nEnd op_usage_vec\n================\n{xrst_spell_off}\n{xrst_code cpp} */\n        \"   ],\\n\"\n/* {xrst_code}\n{xrst_spell_on}\ndependent_vec\n=============\nsee :ref:`dependent_var<json_ad_graph@dependent_vec>`\n{xrst_spell_off}\n{xrst_code cpp} */\n        \"   'dependent_vec' : [ 1, [7] ] \\n\"\n/* {xrst_code}\n{xrst_spell_on}\nEnd Function\n============\n{xrst_spell_off}\n{xrst_code cpp} */\n        \"}\\n\";\n/* {xrst_code}\n{xrst_spell_on}\nConvert Single to Double Quotes\n*******************************\n{xrst_spell_off}\n{xrst_code cpp} */\n    for(size_t i = 0; i < json.size(); ++i)\n        if( json[i] == '\\'' ) json[i] = '\"';\n/* {xrst_code}\n{xrst_spell_on}\ndouble f(x, p)\n**************\n{xrst_spell_off}\n{xrst_code cpp} */\n    CppAD::ADFun<double> f;\n    f.from_json(json);\n/* {xrst_code}\n{xrst_spell_on}\nCheck f(x, p)\n*************\n{xrst_spell_off}\n{xrst_code cpp} */\n    vector<double> c(1), p(1), x(1), y(1);\n    c[0] = -0.1; // must match value in graph\n    p[0] = 0.2;  // can be any value\n    x[0] = 0.3;  // can be any value\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    //\n    // f(x, p) = sin(p_0) + sin(x_0) + sin(c_0)\n    double check = std::sin(p[0]) + std::sin(x[0]) + std::sin(c[0]);\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n\n/* {xrst_code}\n{xrst_spell_on}\nAD<double> f(x, p)\n******************\n{xrst_spell_off}\n{xrst_code cpp} */\n    CppAD::ADFun< AD<double>, double > af( f.base2ad() );\n/* {xrst_code}\n{xrst_spell_on}\nEvaluate Derivative\n*******************\n{xrst_spell_off}\n{xrst_code cpp} */\n    // set independent variables and parameters\n    vector< AD<double> > ap(1), ax(1);\n    ap[0] = 0.2;\n    ax[0] = 0.3;\n    //\n    // record computation of z = d/dx f(x, p)\n    CppAD::Independent(ax, ap);\n    af.new_dynamic(ap);\n    vector< AD<double> > az = af.Jacobian(ax);\n/* {xrst_code}\n{xrst_spell_on}\ndouble g(x, p) = d/dx f(x, p)\n*****************************\n{xrst_spell_off}\n{xrst_code cpp} */\n    CppAD::ADFun<double> g(ax, az);\n/* {xrst_code}\n{xrst_spell_on}\nConvert to Json and Back\n************************\n{xrst_spell_off}\n{xrst_code cpp} */\n    json = g.to_json();\n    g.from_json(json);\n/* {xrst_code}\n{xrst_spell_on}\nCheck g(x, p)\n*************\n{xrst_spell_off}\n{xrst_code cpp} */\n    c[0] = -0.1; // must match value in graph\n    p[0] = 0.3;  // can be any value\n    x[0] = 0.4;  // can be any value\n    //\n    // compute z = g(x, p)\n    g.new_dynamic(p);\n    vector<double> z = g.Forward(0, x);\n    //\n    // g(x, p) = d/dx f(x, p) = d/dx sin(x) = cos(x)\n    check = std::cos(x[0]);\n    ok &= CppAD::NearEqual(z[0], check, eps99, eps99);\n    //\n    return ok;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end json_get_started.cpp}\n*/\n"
  },
  {
    "path": "example/json/json.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin json.cpp}\n\njson Examples and Tests Driver\n##############################\n\nRunning These Tests\n*******************\nAfter executing the :ref:`cmake-name` command\nform the :ref:`download@Distribution Directory`,\nyou can build and run these tests with the commands::\n\n    cd build\n    make check_example_json\n\nNote that your choice of :ref:`cmake@generator` may require using\nan different version of make; e.g., ``ninja`` .\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end json.cpp}\n-------------------------------------------------------------------------------\n*/\n// BEGIN C++\n\n// CPPAD_HAS_* defines\n# include <cppad/configure.hpp>\n\n// for thread_alloc\n# include <cppad/utility/thread_alloc.hpp>\n\n// test runner\n# include <cppad/utility/test_boolofvoid.hpp>\n\n// BEGIN_SORT_THIS_LINE_PLUS_2\n// external compiled tests\nextern bool add_op(void);\nextern bool atom4_op(void);\nextern bool atom_op(void);\nextern bool azmul_op(void);\nextern bool cexp_op(void);\nextern bool comp_op(void);\nextern bool discrete_op(void);\nextern bool div_op(void);\nextern bool from_json(void);\nextern bool get_started(void);\nextern bool mul_op(void);\nextern bool pow_op(void);\nextern bool print_op(void);\nextern bool sparse(void);\nextern bool sub_op(void);\nextern bool sum_op(void);\nextern bool to_json(void);\nextern bool unary_op(void);\n// END_SORT_THIS_LINE_MINUS_1\n\n// main program that runs all the tests\nint main(void)\n{   std::string group = \"example/json\";\n    size_t      width = 20;\n    CppAD::test_boolofvoid Run(group, width);\n\n    // This line is used by test_one.sh\n\n    // BEGIN_SORT_THIS_LINE_PLUS_2\n    // external compiled tests\n    Run( add_op,               \"add_op\"          );\n    Run( atom4_op,             \"atom4_op\"        );\n    Run( azmul_op,             \"azmul_op\"        );\n    Run( cexp_op,              \"cexp_op\"         );\n    Run( comp_op,              \"comp_op\"         );\n    Run( discrete_op,          \"discrete_op\"     );\n    Run( div_op,               \"div_op\"          );\n    Run( from_json,            \"from_json\"       );\n    Run( get_started,          \"get_started\"     );\n    Run( mul_op,               \"mul_op\"          );\n    Run( pow_op,               \"pow_op\"          );\n    Run( print_op,             \"print_op\"        );\n    Run( sparse,               \"sparse\"          );\n    Run( sub_op,               \"sub_op\"          );\n    Run( sum_op,               \"sum_op\"          );\n    Run( to_json,              \"to_json\"         );\n    Run( unary_op,             \"unary_op\"        );\n    // END_SORT_THIS_LINE_MINUS_1\n\n    // check for memory leak\n    bool memory_ok = CppAD::thread_alloc::free_all();\n    // print summary at end\n    bool ok = Run.summary(memory_ok);\n    //\n    return static_cast<int>( ! ok );\n}\n// END C++\n"
  },
  {
    "path": "example/json/mul_op.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin json_mul_op.cpp}\n\nJson mul Operator: Example and Test\n###################################\n\nSource Code\n***********\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end json_mul_op.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nbool mul_op(void)\n{   bool ok = true;\n    using CppAD::vector;\n    using CppAD::AD;\n    //\n    // AD graph example\n    // node_1 : p[0]\n    // node_2 : p[1]\n    // node_3 : x[0]\n    // node_4 : p[0] * p[1]\n    // node_5 : x[0] * p[0] * p[1]\n    // y[0]   = x[0] * p[0] * p[1]\n    // use single quote to avoid having to escape double quote\n    std::string json =\n        \"{\\n\"\n        \"   'function_name'  : 'mul_op example',\\n\"\n        \"   'op_define_vec'  : [ 2, [\\n\"\n        \"       { 'op_code':1, 'name':'add', 'n_arg':2 } ,\\n\"\n        \"       { 'op_code':2, 'name':'mul', 'n_arg':2 } ]\\n\"\n        \"   ],\\n\"\n        \"   'n_dynamic_ind'  : 2,\\n\"\n        \"   'n_variable_ind' : 1,\\n\"\n        \"   'constant_vec'   : [ 0, [ ] ],\\n\"\n        \"   'op_usage_vec'   : [ 2, [\\n\"\n        \"       [ 2, 1, 2 ] ,\\n\" // p[0] * p[1]\n        \"       [ 2, 3, 4 ] ]\\n\" // x[0] * p[0] * p[1]\n        \"   ],\\n\"\n        \"   'dependent_vec' : [ 1, [5] ] \\n\"\n        \"}\\n\";\n    // Convert the single quote to double quote\n    for(size_t i = 0; i < json.size(); ++i)\n        if( json[i] == '\\'' ) json[i] = '\"';\n    //\n    // f(x, p) = x_0 * p_0 * p_1\n    CppAD::ADFun<double> f;\n    f.from_json(json);\n    //\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 2;\n    //\n    // set independent variables and parameters\n    vector<double> p(2), x(1);\n    p[0] = 2.0;\n    p[1] = 3.0;\n    x[0] = 4.0;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    vector<double> y = f.Forward(0, x);\n    //\n    // check result\n    ok &= y[0] == x[0] * p[0] * p[1];\n    // -----------------------------------------------------------------------\n    // Convert to Json graph and back again\n    json = f.to_json();\n    // std::cout << \"json = \" << json;\n    f.from_json(json);\n    // -----------------------------------------------------------------------\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 2;\n    //\n    // set independent variables and parameters\n    p[0] = 2.0;\n    p[1] = 3.0;\n    x[0] = 4.0;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    //\n    // check result\n    ok &= y[0] == x[0] * p[0] * p[1];\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/json/pow_op.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin json_pow_op.cpp}\n\nJson pow Operator: Example and Test\n###################################\n\nSource Code\n***********\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end json_pow_op.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nbool pow_op(void)\n{   bool ok = true;\n    using CppAD::vector;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    //\n    // AD graph example\n    // node_1 : p[0]\n    // node_2 : p[1]\n    // node_3 : x[0]\n    // node_4 : pow(p[0], p[1])\n    // node_5 : pow(p[0], x[0])\n    // node_6 = pow(p[0], p[1]) + pow(p[0], x[0])\n    // y[0]   = pow(p[0], p[1]) + pow(p[0], x[0])\n    // use single quote to avoid having to escape double quote\n    std::string json =\n        \"{\\n\"\n        \"   'function_name'  : 'pow_op example',\\n\"\n        \"   'op_define_vec'  : [ 2, [\\n\"\n        \"       { 'op_code':1, 'name':'add', 'n_arg':2 } ,\\n\"\n        \"       { 'op_code':2, 'name':'pow', 'n_arg':2 } ]\\n\"\n        \"   ],\\n\"\n        \"   'n_dynamic_ind'  : 2,\\n\"\n        \"   'n_variable_ind' : 1,\\n\"\n        \"   'constant_vec'   : [ 0, [ ] ],\\n\"\n        \"   'op_usage_vec'   : [ 3, [\\n\"\n        \"       [ 2, 1, 2 ] ,\\n\" // pow(p[0], p[1])\n        \"       [ 2, 1, 3 ] ,\\n\" // pow(p[0], x[0])\n        \"       [ 1, 4, 5 ] ]\\n\" // pow(p[0], p[1]) + pow(p[0], x[0])\n        \"   ],\\n\"\n        \"   'dependent_vec' : [ 1, [6] ] \\n\"\n        \"}\\n\";\n    // Convert the single quote to double quote\n    for(size_t i = 0; i < json.size(); ++i)\n        if( json[i] == '\\'' ) json[i] = '\"';\n    //\n    // f(x, p) = pow(p_0, p_1) + pow(p_0, x_0)\n    CppAD::ADFun<double> f;\n    f.from_json(json);\n    //\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 2;\n    //\n    // set independent variables and parameters\n    vector<double> p(2), x(1);\n    p[0] = 2.0;\n    p[1] = 3.0;\n    x[0] = 4.0;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    vector<double> y = f.Forward(0, x);\n    //\n    // check result\n    double check_y0 = std::pow(p[0], p[1]) + std::pow(p[0], x[0]);\n    ok &= NearEqual(y[0], check_y0, eps99, eps99);\n    // -----------------------------------------------------------------------\n    // Convert to Json graph and back again\n    json = f.to_json();\n    // std::cout << \"json = \" << json;\n    f.from_json(json);\n    // -----------------------------------------------------------------------\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 2;\n    //\n    // set independent variables and parameters\n    p[0] = 2.0;\n    p[1] = 3.0;\n    x[0] = 4.0;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    //\n    // check result\n    ok &= NearEqual(y[0], check_y0, eps99, eps99);\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/json/print_op.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin json_print_op.cpp}\n\nJson AD Graph print Operator: Example and Test\n##############################################\n\nSource Code\n***********\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end json_print_op.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nbool print_op(void)\n{   bool ok = true;\n    using std::string;\n    std::stringstream stream_out;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    //\n    // AD graph example\n    // node_1 : p[0]\n    // node_2 : x[0]\n    //        : print(p[0], \"p[0] = \", p[0], \"\\n\")\n    //        : print(x[0], \"x[0] = \", x[0], \"\\n\")\n    // node_3 : log(p[0])\n    // node_4 : log(x[0])\n    // node_5 = log(p[0]) + log(x[0])\n    // y[0]   = log(p[0]) + log(x[0])\n    // use single quote to avoid having to escape double quote\n    std::string json =\n        \"{\\n\"\n        \"   'function_name'  : 'print_op example',\\n\"\n        \"   'op_define_vec'  : [ 3, [\\n\"\n        \"       { 'op_code':1, 'name':'print'              } ,\\n\"\n        \"       { 'op_code':2, 'name':'log',     'n_arg':1 } ,\\n\"\n        \"       { 'op_code':3, 'name':'add',     'n_arg':2 } ]\\n\"\n        \"   ],\\n\"\n        \"   'n_dynamic_ind'  : 1,\\n\"\n        \"   'n_variable_ind' : 1,\\n\"\n        \"   'constant_vec'   : [ 0, [ ] ],\\n\"\n        \"   'op_usage_vec'   : [ 5, [\\n\"\n        \"       [ 1, 'p[0] = ', '\\n', 0, 2, [1, 1 ] ] ,\\n\" // first print\n        \"       [ 1, 'x[0] = ', '\\n', 0, 2, [2, 2 ] ] ,\\n\" // second print\n        \"       [ 2, 1    ] ,\\n\" // log(p[0])\n        \"       [ 2, 2    ] ,\\n\" // log(x[0])\n        \"       [ 3, 3, 4 ] ]\\n\" // log(p[0]) + log(x[0])\n        \"   ],\\n\"\n        \"   'dependent_vec' : [ 1, [5] ] \\n\"\n        \"}\\n\";\n    // Convert the single quote to double quote\n    for(size_t i = 0; i < json.size(); ++i)\n        if( json[i] == '\\'' ) json[i] = '\"';\n    //\n    // f(x, p) = log(p[0]) + log(x[0])\n    CppAD::ADFun<double> f;\n    f.from_json(json);\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 1;\n    //\n    // set independent variables and parameters\n    CPPAD_TESTVECTOR(double) p(1), x(1);\n    p[0] = 1.0;\n    x[0] = 2.0;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    CPPAD_TESTVECTOR(double) y = f.Forward(0, x, stream_out);\n    //\n    // check result\n    ok &= stream_out.str() == \"\";\n    double check = std::log(p[0]) + std::log(x[0]);\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n    //\n    // -----------------------------------------------------------------------\n    // Convert function to json and back again\n    json = f.to_json();\n    // std::cout << json;\n    f.from_json(json);\n    // -----------------------------------------------------------------------\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 1;\n    //\n    // set independent variables and parameters\n    p[0] = 1.0;\n    x[0] = -2.0;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    f.check_for_nan(false);\n    y = f.Forward(0, x, stream_out);\n    //\n    // check result\n    ok &= stream_out.str() == \"x[0] = -2\\n\";\n    ok &= std::isnan(y[0]);\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/json/sparse.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin json_sparse.cpp}\n\nJson Representation of a Sparse Matrix: Example and Test\n########################################################\n\nDiscussion\n**********\nThe example using a CppAD Json to represent the sparse matrix\n\n.. math::\n\n    \\partial_x f(x, p) = \\left( \\begin{array}{ccc}\n        p_0 & 0    & 0 \\\\\n        0   & p_1  & 0 \\\\\n        0   & 0    & c_0\n    \\end{array} \\right)\n\nwhere :math:`c_0` is the constant 3.\n\nSource Code\n***********\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end json_sparse.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nbool sparse(void)\n{   bool ok = true;\n    using CppAD::vector;\n    typedef vector<size_t> s_vector;\n    typedef vector<double> d_vector;\n    //\n    // An AD graph example\n    // node_1 : p[0]\n    // node_2 : p[1]\n    // node_3 : x[0]\n    // node_4 : x[1]\n    // node_5 : x[2]\n    // node_6 : c[0]\n    // node_7 : p[0] * x[0]\n    // node_8 : p[1] * x[1]\n    // node_9 : c[0] * x[2]\n    // y[0]   = p[0] * x[0]\n    // y[1]   = p[1] * x[1]\n    // y[2]   = c[0] * x[0]\n    // use single quote to avoid having to escape double quote\n    std::string json =\n        \"{\\n\"\n        \"   'function_name'  : 'sparse example',\\n\"\n        \"   'op_define_vec'  : [ 1, [\\n\"\n        \"       { 'op_code':1, 'name':'mul', 'n_arg':2 } ]\\n\"\n        \"   ],\\n\"\n        \"   'n_dynamic_ind'  : 2,\\n\"\n        \"   'n_variable_ind' : 3,\\n\"\n        \"   'constant_vec'   : [ 1, [ 3.0 ] ],\\n\"\n        \"   'op_usage_vec'   : [ 3, [\\n\"\n        \"       [ 1, 1, 3 ] , \\n\"\n        \"       [ 1, 2, 4 ] , \\n\"\n        \"       [ 1, 6, 5 ] ] \\n\"\n        \"   ],\\n\"\n        \"   'dependent_vec'   : [ 3, [7, 8, 9] ] \\n\"\n        \"}\\n\";\n    // Convert the single quote to double quote\n    for(size_t i = 0; i < json.size(); ++i)\n        if( json[i] == '\\'' ) json[i] = '\"';\n    //\n    CppAD::ADFun<double> fun;\n    fun.from_json(json);\n    ok &= fun.Domain() == 3;\n    ok &= fun.Range()  == 3;\n    ok &= fun.size_dyn_ind() == 2;\n    //\n    // Point at which we are going to evaluate the Jacobian of f(x, p).\n    // The Jacobian is constant w.r.t. x, so the value of x does not matter.\n    vector<double> p(2), x(3);\n    p[0] = 1.0;\n    p[1] = 2.0;\n    for(size_t j = 0; j < x.size(); ++j)\n        x[j] = 0.0;\n    //\n    // set the dynamic parameters\n    fun.new_dynamic(p);\n    //\n    // compute the sparsity pattern for f_x(x, p)\n    vector<bool> select_domain(3);\n    vector<bool> select_range(3);\n    for(size_t i = 0; i < 3; ++i)\n    {   select_domain[i] = true;\n        select_range[i]  = true;\n    }\n    bool transpose = false;\n    CppAD::sparse_rc<s_vector> pattern;\n    fun.subgraph_sparsity(select_domain, select_range, transpose, pattern);\n    //\n    // compute the entire Jacobian\n    CppAD::sparse_rcv<s_vector, d_vector> subset(pattern);\n    fun.subgraph_jac_rev(x, subset);\n    //\n    // information in the sparse Jacobian\n    const s_vector& row( subset.row() );\n    const s_vector& col( subset.col() );\n    const d_vector& val( subset.val() );\n    size_t   nnz       = subset.nnz();\n    s_vector row_major = subset.row_major();\n    //\n    // check number of non-zero elements in sparse matrix\n    ok      &= nnz == 3;\n    //\n    // check first element of matrix (in row major order)\n    size_t k = row_major[0];\n    ok      &= row[k] == 0;\n    ok      &= col[k] == 0;\n    ok      &= val[k] == p[0];\n    //\n    // check second element of matrix\n    k        = row_major[1];\n    ok      &= row[k] == 1;\n    ok      &= col[k] == 1;\n    ok      &= val[k] == p[1];\n    //\n    // check third element of matrix\n    k        = row_major[2];\n    ok      &= row[k] == 2;\n    ok      &= col[k] == 2;\n    ok      &= val[k] == 3.0;\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/json/sub_op.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin json_sub_op.cpp}\n\nJson sub Operator: Example and Test\n###################################\n\nSource Code\n***********\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end json_sub_op.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nbool sub_op(void)\n{   bool ok = true;\n    using CppAD::vector;\n    using CppAD::AD;\n    //\n    // AD graph example\n    // node_1 : p[0]\n    // node_2 : p[1]\n    // node_3 : x[0]\n    // node_4 : p[0] - p[1]\n    // node_5 : x[0] - ( p[0] - p[1] )\n    // y[0]   = x[0] - ( p[0] - p[1] )\n    // use single quote to avoid having to escape double quote\n    std::string json =\n        \"{\\n\"\n        \"   'function_name'  : 'sub_op example',\\n\"\n        \"   'op_define_vec'  : [ 2, [\\n\"\n        \"       { 'op_code':1, 'name':'add', 'n_arg':2 } ,\\n\"\n        \"       { 'op_code':2, 'name':'sub', 'n_arg':2 } ]\\n\"\n        \"   ],\\n\"\n        \"   'n_dynamic_ind'  : 2,\\n\"\n        \"   'n_variable_ind' : 1,\\n\"\n        \"   'constant_vec'   : [ 0, [ ] ],\\n\"\n        \"   'op_usage_vec'   : [ 2, [\\n\"\n        \"       [ 2, 1, 2 ] ,\\n\" // p[0] - p[1]\n        \"       [ 2, 3, 4 ] ]\\n\" // x[0] - ( p[0] - p[1] )\n        \"   ],\\n\"\n        \"   'dependent_vec' : [ 1, [5] ] \\n\"\n        \"}\\n\";\n    // Convert the single quote to double quote\n    for(size_t i = 0; i < json.size(); ++i)\n        if( json[i] == '\\'' ) json[i] = '\"';\n    //\n    // f(x, p) = x_0 - ( p_0 - p_1 )\n    CppAD::ADFun<double> f;\n    f.from_json(json);\n    //\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 2;\n    //\n    // set independent variables and parameters\n    vector<double> p(2), x(1);\n    p[0] = 2.0;\n    p[1] = 3.0;\n    x[0] = 4.0;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    vector<double> y = f.Forward(0, x);\n    //\n    // check result\n    ok &= y[0] == x[0] - ( p[0] - p[1] );\n    // -----------------------------------------------------------------------\n    // Convert to Json graph and back again\n    json = f.to_json();\n    // std::cout << \"json = \" << json;\n    f.from_json(json);\n    // -----------------------------------------------------------------------\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 2;\n    //\n    // set independent variables and parameters\n    p[0] = 2.0;\n    p[1] = 3.0;\n    x[0] = 4.0;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    //\n    // check result\n    ok &= y[0] == x[0] - ( p[0] - p[1] );\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/json/sum_op.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin json_sum_op.cpp}\n\nJson sum Operator: Example and Test\n###################################\n\nSource Code\n***********\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end json_sum_op.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nbool sum_op(void)\n{   bool ok = true;\n    using CppAD::vector;\n    using CppAD::AD;\n    //\n    // AD graph example\n    // node_1 : p[0]\n    // node_2 : p[1]\n    // node_3 : p[2]\n    // node_4 : x[0]\n    // node_5 : p[0] + p[1] + p[2]\n    // node_6 : x[0] + p[0] + p[1] + p[2]\n    // y[0]   = x[0] + p[0] + p[1] + p[2]\n    // use single quote to avoid having to escape double quote\n    std::string json =\n        \"{\\n\"\n        \"   'function_name'  : 'sum_op example',\\n\"\n        \"   'op_define_vec'  : [ 2, [\\n\"\n        \"       { 'op_code':1, 'name':'add', 'n_arg':2 } ,\\n\"\n        \"       { 'op_code':2, 'name':'sum' } ]\\n\"\n        \"   ],\\n\"\n        \"   'n_dynamic_ind'  : 3,\\n\"\n        \"   'n_variable_ind' : 1,\\n\"\n        \"   'constant_vec'   : [ 0, [ ] ],\\n\"\n        \"   'op_usage_vec'   : [ 2, [\\n\"\n        \"       [ 2, 1, 3, [1, 2, 3] ] ,\\n\" // p[0] + p[1] + p[2]\n        \"       [ 2, 1, 2, [4, 5 ]   ] ]\\n\" // x[0] + p[0] + p[1] + p[2]\n        \"   ],\\n\"\n        \"   'dependent_vec' : [ 1, [6] ] \\n\"\n        \"}\\n\";\n    // Convert the single quote to double quote\n    for(size_t i = 0; i < json.size(); ++i)\n        if( json[i] == '\\'' ) json[i] = '\"';\n    //\n    // f(x, p) = x_0 + p_0 + p_1 + p_2\n    CppAD::ADFun<double> f;\n    f.from_json(json);\n    //\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 3;\n    //\n    // set independent variables and parameters\n    vector<double> p(3), x(1);\n    for(size_t j = 0; j < 3; ++j)\n        p[j] = double(j + 1);\n    x[0] = 5.0;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    vector<double> y = f.Forward(0, x);\n    //\n    // check result\n    ok &= y[0] == x[0] + p[0] + p[1] + p[2];\n    // -----------------------------------------------------------------------\n    // Convert to Json graph and back again\n    json = f.to_json();\n    // std::cout << \"json = \" << json;\n    f.from_json(json);\n    // -----------------------------------------------------------------------\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 3;\n    //\n    // set independent variables and parameters\n    for(size_t j = 0; j < 3; ++j)\n        p[j] = double(j + 1);\n    x[0] = 5.0;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    //\n    // check result\n    ok &= y[0] == x[0] + p[0] + p[1] + p[2];\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/json/to_json.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin to_json.cpp}\n\nConvert an ADFun Object to a Json AD Graph: Example and Test\n############################################################\n\nSource Code\n***********\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end to_json.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nbool to_json(void)\n{   bool ok = true;\n    using CppAD::vector;\n    using CppAD::AD;\n    //\n    // An AD graph example\n    // node_1 : x[0]\n    // node_2 : x[1]\n    // node_3 : x[0] + x[1]\n    // node_4 : (x[0] + x[1]) * x[1]\n    // y[0]   = (x[0] + x[1]) * x[1]\n    // use single quote to avoid having to escape double quote\n    std::string json =\n        \"{\\n\"\n        \"   'function_name'  : 'to_json example',\\n\"\n        \"   'op_define_vec'  : [ 2, [\\n\"\n        \"       { 'op_code':1, 'name':'add', 'n_arg':2 } ,\\n\"\n        \"       { 'op_code':2, 'name':'mul', 'n_arg':2 } ]\\n\"\n        \"   ],\\n\"\n        \"   'n_dynamic_ind'  : 0,\\n\"\n        \"   'n_variable_ind' : 2,\\n\"\n        \"   'constant_vec'   : [ 0, [ ] ],\\n\"\n        \"   'op_usage_vec'   : [ 2, [\\n\"\n        \"       [ 1, 1, 2 ] ,\\n\"\n        \"       [ 2, 3, 2 ] ]\\n\"\n        \"   ],\\n\"\n        \"   'dependent_vec' : [ 1, [4] ] \\n\"\n        \"}\\n\";\n    // Convert the single quote to double quote\n    for(size_t i = 0; i < json.size(); ++i)\n        if( json[i] == '\\'' ) json[i] = '\"';\n    //\n    // f(x) = (x_0 + x_1) * x_1\n    CppAD::ADFun< AD<double> > af;\n    af.from_json(json);\n    ok &= af.Domain() == 2;\n    ok &= af.Range() == 1;\n    //\n    // Declare independent variables for a new recording\n    vector< AD<double> > ax(2);\n    ax[0] = 1.0;\n    ax[1] = 2.0;\n    CppAD::Independent(ax);\n    //\n    // Compute f(x)\n    af.Forward(0, ax);\n    //\n    // Compute z = f'(x)\n    vector< AD<double> > aw(1), az(2);\n    aw[0] = 1.0;\n    az    = af.Reverse(1, aw);\n    //\n    // define g(x) = f'(x)\n    CppAD::ADFun<double> g(ax, az);\n    // ------------------------------------------------------------------------\n    // Convert to Json graph and back\n    json = g.to_json();\n    // std::cout << json;\n    g.from_json(json);\n    // ------------------------------------------------------------------------\n    //\n    // Evaluate function corresponding to g\n    vector<double> x(2), z(2);\n    x[0] = 3.0;\n    x[1] = 4.0;\n    z = g.Forward(0, x);\n    //\n    // should be derivative of f\n    ok &= z[0] == x[1];\n    ok &= z[1] == x[0] + 2.0 * x[1];\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/json/unary_op.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin json_unary_op.cpp}\n\nJson Unary Operators: Example and Test\n######################################\n\nSource Code\n***********\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end json_unary_op.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nbool unary_op(void)\n{   bool ok = true;\n    using CppAD::vector;\n    using CppAD::AD;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    //\n    // AD graph example\n    // node_1 : p[0]\n    // node_2 : x[0]\n    // node_3 : c[0]\n    // node_4 : sin(p[0])\n    // node_5 : sin(x[0])\n    // node_6 : sin(c[0])\n    // node_7 : sin(p[0]) + sin(x[0]) + sin(c[0])\n    // y[0]   = sin(p[0]) + sin(x[0]) + sin(c[0])\n    // use single quote to avoid having to escape double quote\n    std::string json =\n        \"{\\n\"\n        \"   'function_name'  : 'unary_op example',\\n\"\n        \"   'op_define_vec'  : [ 2, [\\n\"\n        \"       { 'op_code':1, 'name':'sin', 'n_arg':1 } ,\\n\"\n        \"       { 'op_code':2, 'name':'sum'            } ]\\n\"\n        \"   ],\\n\"\n        \"   'n_dynamic_ind'  : 1,\\n\"\n        \"   'n_variable_ind' : 1,\\n\"\n        \"   'constant_vec'   : [ 1, [ -0.1 ] ],\\n\" // c[0]\n        \"   'op_usage_vec'   : [ 4, [\\n\"\n        \"       [ 1, 1]                ,\\n\" // sin(p[0])\n        \"       [ 1, 2]                ,\\n\" // sin(x[0])\n        \"       [ 1, 3]                ,\\n\" // sin(c[0])\n        \"       [ 2, 1, 3, [4, 5, 6] ] ]\\n\" // sin(p[0])+sin(x[0])+sin(c[0])\n        \"   ],\\n\"\n        \"   'dependent_vec' : [ 1, [7] ] \\n\"\n        \"}\\n\";\n    // Convert the single quote to double quote\n    for(size_t i = 0; i < json.size(); ++i)\n        if( json[i] == '\\'' ) json[i] = '\"';\n    //\n    // f(x, p) = sin(p_0) + sin(x_0) + sin(c_0)\n    CppAD::ADFun<double> f;\n    f.from_json(json);\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 1;\n    //\n    // value of constant in function\n    vector<double> c(1);\n    c[0] = -0.1;\n    //\n    // set independent variables and parameters\n    vector<double> p(1), x(1);\n    p[0] = 0.2;\n    x[0] = 0.3;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    vector<double> y = f.Forward(0, x);\n    //\n    // check result\n    double check = std::sin(p[0]) + std::sin(x[0]) + std::sin(c[0]);\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n    // -----------------------------------------------------------------------\n    // Convert to Json graph and back again\n    json = f.to_json();\n    f.from_json(json);\n    // -----------------------------------------------------------------------\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    //\n    // check result\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/multi_thread/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-25 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n# initialize list as empty\nSET(check_example_multi_thread_depends \"\")\n\n# Define the operation\n# CHECK_LIBRARY_EXISTS (LIBRARY FUNCTION LOCATION VARIABLE)\n#  LIBRARY  - the name of the library you are looking for\n#  FUNCTION - the name of the function\n#  LOCATION - location where the library should be found\n#  VARIABLE - variable to store the result\nINCLUDE(CheckLibraryExists)\n\n#\n# openmp\nIF ( OpenMP_CXX_FOUND )\n    # OpenMP_CXX_FLAGS - flags to add to the CXX compiler for OpenMP support\n    ADD_SUBDIRECTORY(openmp)\nENDIF ( OpenMP_CXX_FOUND )\n#\n# pthread_lib_path\nSET( pthread_ok FALSE )\nFIND_LIBRARY(pthread_lib_path pthread)\nMESSAGE(STATUS \"pthread library path = ${pthread_lib_path}\")\nIF ( pthread_lib_path )\n    SET(CMAKE_REQUIRED_DEFINITIONS \"\")\n    SET(CMAKE_REQUIRED_FLAGS       \"\")\n    SET(CMAKE_REQUIRED_INCLUDES    \"\")\n    SET(CMAKE_REQUIRED_LIBRARIES   \"\")\n    CHECK_LIBRARY_EXISTS(\n        pthread pthread_barrier_wait ${pthread_lib_path} pthread_ok\n    )\n    IF ( pthread_ok )\n        ADD_SUBDIRECTORY(pthread)\n    ENDIF ( pthread_ok )\nENDIF ( pthread_lib_path )\nIF( NOT pthread_ok )\n    SET( pthread_lib_path \"\" )\nENDIF( NOT pthread_ok )\n#\n# sthread\n# Put sthread after pthread because it can sometimes require pthread_lib_path\n# https://stackoverflow.com/questions/46994982\nADD_SUBDIRECTORY(sthread)\n#\n# bthread\nIF ( Boost_FOUND )\n    SET(CMAKE_REQUIRED_DEFINITIONS \"\")\n    SET(CMAKE_REQUIRED_FLAGS       \"\")\n    SET(CMAKE_REQUIRED_INCLUDES    \"${Boost_INCLUDE_DIRS}\")\n    SET(CMAKE_REQUIRED_LIBRARIES   \"${Boost_LIBRARIES}\")\n    SET(source \"\n# include <boost/thread.hpp>\nint main(void)\n{   boost::barrier wait(1);\n    return 0;\n}\"\n    )\n    compile_source_test(${cmake_defined_ok} \"${source}\" boost_multi_thread_ok )\n    #\n    IF( boost_multi_thread_ok )\n        ADD_SUBDIRECTORY(bthread)\n    ENDIF( boost_multi_thread_ok )\n    #\nENDIF ( Boost_FOUND )\n\nIF( NOT( \"${check_example_multi_thread_depends}\" STREQUAL \"\" ) )\n    #\n    # check_example_multi_thread\n    ADD_CUSTOM_TARGET(\n        check_example_multi_thread\n        DEPENDS ${check_example_multi_thread_depends}\n    )\n    MESSAGE(STATUS \"make check_example_multi_thread: available\")\n    #\n    # Change check depends in parent environment\n    add_to_list(check_example_depends check_example_multi_thread)\n    SET(check_example_depends \"${check_example_depends}\" PARENT_SCOPE)\n    #\nENDIF( NOT( \"${check_example_multi_thread_depends}\" STREQUAL \"\" ) )\n"
  },
  {
    "path": "example/multi_thread/bthread/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# Build the example/multi_thread/bthread directory tests\n# Inherit build type from ../CMakeList.txt\n\n# Local include directories to search (not in package_prefix/include)\nINCLUDE_DIRECTORIES( ${CMAKE_CURRENT_SOURCE_DIR}/.. )\n\n# add_executable(<name> [WIN32] [MACOSX_BUNDLE] [EXCLUDE_FROM_ALL]\n#                 source1 source2 ... sourceN\n# )\nSET(source_list ../thread_test.cpp\n    ../team_example.cpp\n    ../harmonic.cpp\n    ../multi_atomic_two.cpp\n    ../multi_atomic_three.cpp\n    ../multi_chkpoint_one.cpp\n    ../multi_chkpoint_two.cpp\n    ../multi_newton.cpp\n    a11c_bthread.cpp\n    get_started.cpp\n    team_bthread.cpp\n)\nset_compile_flags(\n    example_multi_thread_bthread \"${cppad_debug_which}\" \"${source_list}\"\n)\n#\nADD_EXECUTABLE( example_multi_thread_bthread EXCLUDE_FROM_ALL ${source_list} )\n\n# List of libraries to be linked into the specified target\nTARGET_LINK_LIBRARIES(example_multi_thread_bthread\n    ${cppad_lib}\n    ${colpack_libs}\n    ${Boost_LIBRARIES}\n)\n\n# check_example_multi_thread_bthread\nadd_check_executable(check_example_multi_thread bthread get_started)\n"
  },
  {
    "path": "example/multi_thread/bthread/a11c_bthread.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin a11c_bthread.cpp}\n\nA Simple Boost Thread Example and Test\n######################################\n\nPurpose\n*******\nThis example just demonstrates Boost threads and does not use CppAD at all.\n\nSource Code\n***********\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end a11c_bthread.cpp}\n----------------------------------------------------------------------------\n*/\n// BEGIN C++\n# include <boost/thread.hpp>\n# include <limits>\n# include <cmath>\n# include <cassert>\n// for size_t\n# include <cstddef>\n//\n# define NUMBER_THREADS 4\n\nnamespace { // Begin empty namespace\n    class worker_t\n    {\n    private:\n        int    n_;\n        float* a_;\n        float* b_;\n    public:\n        void setup(size_t n, float* a, float* b)\n        {   n_ = static_cast<int>(n);\n            a_ = a;\n            b_ = b;\n        }\n        // Beginning of Example A.1.1.1c of OpenMP 2.5 standard document\n        void a1(int n, float *a, float *b)\n        {   int i;\n            for(i = 1; i < n; i++)\n                b[i] = (a[i] + a[i-1]) / 2.0f;\n            return;\n        }\n        // End of Example A.1.1.1c of OpenMP 2.5 standard document\n        void operator()()\n        {   a1(n_, a_, b_); }\n    };\n}\n\nbool a11c(void)\n{   bool ok = true;\n\n    // Test setup\n    size_t i, j, n_total = 10;\n    float *a = new float[n_total];\n    float *b = new float[n_total];\n    for(i = 0; i < n_total; i++)\n        a[i] = float(i);\n\n    // number of threads\n    size_t number_threads = NUMBER_THREADS;\n\n    // set of workers\n    worker_t worker[NUMBER_THREADS];\n    // threads for each worker\n    boost::thread* bthread[NUMBER_THREADS];\n\n    // Break the work up into sub work for each thread\n    size_t  n     = n_total / number_threads;\n    size_t  n_tmp = n;\n    float*  a_tmp = a;\n    float*  b_tmp = b;\n    worker[0].setup(n_tmp, a_tmp, b_tmp);\n    for(j = 1; j < number_threads; j++)\n    {   n_tmp = n + 1;\n        a_tmp = a_tmp + n - 1;\n        b_tmp = b_tmp + n - 1;\n        if( j == (number_threads - 1) )\n            n_tmp = n_total - j * n + 1;\n\n        worker[j].setup(n_tmp, a_tmp, b_tmp);\n\n        // create this thread\n        bthread[j] = new boost::thread(worker[j]);\n    }\n\n    // do this threads portion of the work\n    worker[0]();\n\n    // wait for other threads to finish\n    for(j = 1; j < number_threads; j++)\n    {   bthread[j]->join();\n        delete bthread[j];\n    }\n\n    // check the result\n    float eps = 100.f * std::numeric_limits<float>::epsilon();\n    for(i = 1; i < n ; i++)\n        ok &= std::fabs( (2. * b[i] - a[i] - a[i-1]) / b[i] ) <= eps;\n\n    delete [] a;\n    delete [] b;\n\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/multi_thread/bthread/get_started.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin bthread_get_started.cpp}\n\n{xrst_template ,\n    example/multi_thread/template/get_started.xrst\n\n    title: Getting Started Using @Name@ Threads With CppAD\n    start source code after: // <space> BEGIN_C++\n    end source code before:  // <space> END_C++\n\n    @Name@    , Boost\n    @####@    , #####\n    @DEFAULT@ , USE_DEFAULT_ADFUN_CONSTRUCTOR\n}\n\n{xrst_end bthread_get_started.cpp}\n------------------------------------------------------------------------------\n*/\n// BEGIN_C++\n# include <cppad/cppad.hpp>\n# include <boost/thread.hpp>\n\n# define USE_DEFAULT_ADFUN_CONSTRUCTOR 1\n\nnamespace {\n    //\n    // d_vector, ad_vector, fun_vector, bthread_vector\n    typedef CPPAD_TESTVECTOR(double)                  d_vector;\n    typedef CPPAD_TESTVECTOR( CppAD::AD<double> )    ad_vector;\n    typedef CPPAD_TESTVECTOR( CppAD::ADFun<double> ) fun_vector;\n    typedef CPPAD_TESTVECTOR( boost::thread* )       bthread_vector;\n    //\n    // std::vector<bool> does not support the data method; see\n    // https://en.cppreference.com/w/cpp/container/vector_bool\n    // 'Does not necessarily store its elements as a contiguous array.'\n    typedef CppAD::vector<bool>                      b_vector;\n    //\n    // thread_specific_data_\n    void cleanup(size_t* thread_num)\n    {   delete thread_num;\n        return;\n    }\n    boost::thread_specific_ptr<size_t> thread_specific_data_(cleanup);\n    //\n    // sequential_execution_\n    bool sequential_execution_ = true;\n    //\n    // in_parallel\n    bool in_parallel(void)\n    {   return ! sequential_execution_; }\n    //\n    // thread_number\n    size_t thread_number(void)\n    {   // return thread_all_[thread_num].thread_num\n        return *thread_specific_data_.get();\n    }\n    //\n    // partial\n    double partial(\n        CppAD::ADFun<double>& f, size_t j, const d_vector& x\n    )\n    {   size_t nx = x.size();\n        d_vector dx(nx), dy(1);\n        for(size_t k = 0; k < nx; ++k)\n            dx[k] = 0.0;\n        dx[j] = 1.0;\n        f.Forward(0, x);\n        dy = f.Forward(1, dx);\n        return dy[0];\n    }\n    //\n    // run_one_thread\n    void run_one_thread(\n        size_t                thread_num     ,\n        CppAD::ADFun<double>* f_ptr          ,\n        size_t                j_begin        ,\n        size_t                j_end          ,\n        const d_vector*       x_ptr          ,\n        d_vector*             Jac_ptr        ,\n        bool*                 ok_ptr         )\n    {   //\n        // x, Jac, ok\n        CppAD::ADFun<double>& f   = *f_ptr;\n        const d_vector&       x   = *x_ptr;\n        d_vector&             Jac = *Jac_ptr;\n        bool&                 ok  = *ok_ptr;\n        //\n        // thread_specific_data_\n        // This sets up the thread_number function for this thread.\n        if( thread_num != 0 )\n        {   thread_specific_data_.reset(new size_t(thread_num) );\n            ok &= thread_number() == thread_num;\n        }\n        //\n        // f\n        // This will cause an assert if Taylor coefficients were allocated\n        // by a different thread.\n        f.capacity_order(0);\n        //\n        // Jac\n        for(size_t j = j_begin; j < j_end; ++j)\n            Jac[j] = partial(f, j, x);\n    }\n}\nbool get_started(void)\n{   // ok\n    bool ok = true;\n    //\n    // eps99\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    //\n    // nx, ax\n    size_t nx = 10;\n    ad_vector ax(nx);\n    for(size_t j = 0; j < nx; ++j)\n        ax[j] = 1.0;\n    CppAD::Independent(ax);\n    //\n    // fun\n    ad_vector  ay(1);\n    ay[0] = ax[0];\n    for(size_t j = 1; j < nx; ++j)\n        ay[0] *= ax[j];\n# if USE_DEFAULT_ADFUN_CONSTRUCTOR\n    CppAD::ADFun<double> fun;\n    fun.Dependent(ax, ay);\n# else\n    // This allocates memory for first order Taylor coefficients using thread 0.\n    // An assert will occur at f.capacity_order(0) in run_one_thread when\n    // it is called by a different thread.\n    CppAD::ADFun<double> fun(ax, ay);\n# endif\n    //\n    // num_threads, f_thread, ok_thread\n    size_t num_threads = 4;\n    fun_vector f_thread(num_threads);\n    b_vector   ok_thread(num_threads);\n    for(size_t thread_num = 0; thread_num < num_threads; ++thread_num)\n    {   f_thread[thread_num] = fun;\n        ok_thread[thread_num] = true;\n    }\n    //\n    // x\n    d_vector x(nx);\n    for(size_t j = 0; j < nx; ++j)\n        x[j] = 1.0 + 1.0 / double(j+1);\n    //\n    // thread_specific_data_\n    // must be set for this thread before calling parall_setup or parallel_ad\n    {   size_t thread_num = 0;\n        thread_specific_data_.reset(new size_t(thread_num) );\n        ok &= thread_number() == thread_num;\n    }\n    //\n    // parallel_setup\n    CppAD::thread_alloc::parallel_setup(\n        num_threads, in_parallel, thread_number\n    );\n    //\n    // parallel_ad\n    CppAD::parallel_ad<double>();\n    //\n    // hold_memory\n    // optional and may improve speed if you do a lot of memory allocation\n    CppAD::thread_alloc::hold_memory(true);\n    //\n    // thread_ptr\n    bthread_vector thread_ptr(num_threads - 1);\n    //\n    // Jac\n    d_vector Jac(nx);\n    //\n    // n_per_thread, n_extra\n    size_t n_per_thread = nx / num_threads;\n    size_t n_extra      = nx % num_threads;\n    //\n    // sequential_execution_\n    sequential_execution_ = false;\n    ok &= in_parallel();\n    //\n    // Jac\n    // Launch num_threads - 1 boost threads\n    size_t j_begin = n_per_thread;\n    size_t j_end;\n    for(size_t thread_num = 1; thread_num < num_threads; ++thread_num)\n    {   j_end = j_begin + n_per_thread;\n        if( thread_num <= n_extra )\n            ++j_end;\n        CppAD::ADFun<double>* f_ptr  = &f_thread[thread_num];\n        bool*                 ok_ptr = &ok_thread[thread_num];\n        thread_ptr[thread_num-1] = new boost::thread(\n            run_one_thread, thread_num, f_ptr, j_begin, j_end, &x, &Jac, ok_ptr\n        );\n        j_begin = j_end;\n    }\n    ok &= j_end == nx;\n    {   // run master thread's indices\n        size_t thread_num = 0;\n        j_begin           = 0;\n        j_end             = j_begin + n_per_thread;\n        CppAD::ADFun<double, double>* f_ptr  = &f_thread[thread_num];\n        bool*                         ok_ptr = &ok_thread[thread_num];\n        run_one_thread(thread_num, f_ptr, j_begin, j_end, &x, &Jac, ok_ptr);\n    }\n    // wait for other threads to finish\n    for(size_t thread_num = 1; thread_num < num_threads; ++thread_num)\n        thread_ptr[thread_num-1]->join();\n    //\n    // sequential_execution_\n    sequential_execution_ = true;\n    CppAD::thread_alloc::parallel_setup(1, nullptr, nullptr);\n    ok &= ! in_parallel();\n    //\n    // hold_memory\n    // free memory for other threads before this (the master thread)\n    ok &= thread_number() == 0;\n    CppAD::thread_alloc::hold_memory(false);\n    for(size_t thread_num = 1; thread_num < num_threads; ++thread_num)\n    {   CppAD::thread_alloc::free_available(thread_num);\n        ok &= ok_thread[thread_num];\n    }\n    ok &= ok_thread[0];\n    CppAD::thread_alloc::free_available(0);\n    //\n    // j\n    for(size_t j = 0; j < nx; ++j)\n    {   //\n        // check\n        double check = 1.0;\n        for(size_t k = 0; k < nx; ++k)\n            if(k != j)\n                check *= x[k];\n        //\n        // ok\n        ok &= CppAD::NearEqual(Jac[j], check, eps99, eps99);\n    }\n    return ok;\n}\n// END_C++\n"
  },
  {
    "path": "example/multi_thread/bthread/team_bthread.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin team_bthread.cpp}\n\nBoost Thread Implementation of a Team of AD Threads\n###################################################\nSee :ref:`team_thread.hpp-name` for this routines specifications.\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end team_bthread.cpp}\n*/\n// BEGIN C++\n# include <boost/thread.hpp>\n# include <cppad/cppad.hpp>\n# include \"../team_thread.hpp\"\n# define MAX_NUMBER_THREADS 48\n\nnamespace {\n    using CppAD::thread_alloc;\n\n    // number of threads in the team\n    size_t num_threads_ = 1;\n\n    // no need to cleanup up thread specific data\n    void cleanup(size_t*)\n    {   return; }\n\n    // thread specific pointer the thread number (initialize as null)\n    boost::thread_specific_ptr<size_t> thread_num_ptr_(cleanup);\n\n    // type of the job currently being done by each thread\n    enum thread_job_t { init_enum, work_enum, join_enum } thread_job_;\n\n    // barrier used to wait for other threads to finish work\n    boost::barrier* wait_for_work_ = nullptr;\n\n    // barrier used to wait for master thread to set next job\n    boost::barrier* wait_for_job_ = nullptr;\n\n    // Are we in sequential mode; i.e., other threads are waiting for\n    // master thread to set up next job ?\n    bool sequential_execution_ = true;\n\n    // structure with information for one thread\n    typedef struct {\n        // The thread\n        boost::thread*       bthread;\n        // CppAD thread number as global (pointed to by thread_num_ptr_)\n        size_t               thread_num;\n        // true if no error for this thread, false otherwise.\n        bool                 ok;\n    } thread_one_t;\n\n    // vector with information for all threads\n    thread_one_t thread_all_[MAX_NUMBER_THREADS];\n\n    // pointer to function that does the work for one thread\n    void (* worker_)(void) = nullptr;\n\n    // ---------------------------------------------------------------------\n    // in_parallel()\n    bool in_parallel(void)\n    {   return ! sequential_execution_; }\n\n    // ---------------------------------------------------------------------\n    // thread_number()\n    size_t thread_number(void)\n    {   // return thread_all_[thread_num].thread_num\n        return *thread_num_ptr_.get();\n    }\n    // --------------------------------------------------------------------\n    // function that gets called by boost thread constructor\n    void thread_work(size_t thread_num)\n    {   bool ok = wait_for_work_ != nullptr;\n        ok     &= wait_for_job_  != nullptr;\n        ok     &= thread_num     != 0;\n\n        // thread specific storage of thread number for this thread\n        thread_num_ptr_.reset(& thread_all_[thread_num].thread_num );\n\n        while( true )\n        {\n            // Use wait_for_jog_ to give master time in sequential mode\n            // (so it can change global information like thread_job_)\n            wait_for_job_->wait();\n\n            // case where we are terminating this thread (no more work)\n            if( thread_job_ == join_enum)\n                break;\n\n            // only other case once wait_for_job_ has been completed (so far)\n            ok &= thread_job_ == work_enum;\n            worker_();\n\n            // Use wait_for_work_ to inform master that our work is done and\n            // that this thread will not use global information until\n            // passing its barrier wait_for_job_ above.\n            wait_for_work_->wait();\n\n        }\n        thread_all_[thread_num].ok &= ok;\n        return;\n    }\n}\n\nbool team_create(size_t num_threads)\n{   bool ok = true;;\n\n    if( num_threads > MAX_NUMBER_THREADS )\n    {   std::cerr << \"team_create: num_threads greater than \";\n        std::cerr << MAX_NUMBER_THREADS << std::endl;\n        exit(1);\n    }\n    // check that we currently do not have multiple threads running\n    ok  = num_threads_ == 1;\n    ok &= wait_for_work_ == nullptr;\n    ok &= wait_for_job_  == nullptr;\n    ok &= sequential_execution_;\n\n    size_t thread_num;\n    for(thread_num = 0; thread_num < num_threads; thread_num++)\n    {   // Each thread gets a pointer to its version of this thread_num\n        // so it knows which section of thread_all it is working with\n        thread_all_[thread_num].thread_num = thread_num;\n\n        // initialize\n        thread_all_[thread_num].ok = true;\n        thread_all_[0].bthread     = nullptr;\n    }\n    // Finish setup of thread_all_ for this thread\n    thread_num_ptr_.reset(& thread_all_[0].thread_num);\n\n    // Now that thread_number() has necessary information for the case\n    // num_threads_ == 1, and while still in sequential mode,\n    // call setup for using CppAD::AD<double> in parallel mode.\n    thread_alloc::parallel_setup(num_threads, in_parallel, thread_number);\n    thread_alloc::hold_memory(true);\n    CppAD::parallel_ad<double>();\n\n    // now change num_threads_ to its final value.\n    num_threads_ = num_threads;\n\n    // initialize two barriers, one for work done, one for new job ready\n    wait_for_work_ = new boost::barrier( (unsigned int) num_threads );\n    wait_for_job_  = new boost::barrier( (unsigned int) num_threads );\n\n    // initial job for the threads\n    thread_job_           = init_enum;\n    if( num_threads > 1 )\n        sequential_execution_ = false;\n\n    // This master thread is already running, we need to create\n    // num_threads - 1 more threads\n    for(thread_num = 1; thread_num < num_threads; thread_num++)\n    {   // Create the thread with thread number equal to thread_num\n        thread_all_[thread_num].bthread =\n            new boost::thread(thread_work, thread_num);\n    }\n\n    // Current state is other threads are at wait_for_job_.\n    // This master thread (thread zero) has not completed wait_for_job_\n    sequential_execution_ = true;\n    return ok;\n}\n\nbool team_work(void worker(void))\n{\n    // Current state is other threads are at wait_for_job_.\n    // This master thread (thread zero) has not completed wait_for_job_\n    bool ok = sequential_execution_;\n    ok     &= thread_number() == 0;\n    ok     &= wait_for_work_  != nullptr;\n    ok     &= wait_for_job_   != nullptr;\n\n    // set global version of this work routine\n    worker_ = worker;\n\n    // set the new job that other threads are waiting for\n    thread_job_ = work_enum;\n\n    // Enter parallel execution when master thread calls wait_for_job_\n    if( num_threads_ > 1 )\n        sequential_execution_ = false;\n    wait_for_job_->wait();\n\n    // Now do the work in this thread and then wait\n    // until all threads have completed wait_for_work_\n    worker();\n    wait_for_work_->wait();\n\n    // Current state is other threads are at wait_for_job_.\n    // This master thread (thread zero) has not completed wait_for_job_\n    sequential_execution_ = true;\n\n    size_t thread_num;\n    for(thread_num = 0; thread_num < num_threads_; thread_num++)\n        ok &= thread_all_[thread_num].ok;\n    return ok;\n}\n\nbool team_destroy(void)\n{   // Current state is other threads are at wait_for_job_.\n    // This master thread (thread zero) has not completed wait_for_job_\n    bool ok = sequential_execution_;\n    ok     &= thread_number() == 0;\n    ok     &= wait_for_work_ != nullptr;\n    ok     &= wait_for_job_  != nullptr;\n\n    // set the new job that other threads are waiting for\n    thread_job_ = join_enum;\n\n    // enter parallel execution soon as master thread completes wait_for_job_\n    if( num_threads_ > 1 )\n            sequential_execution_ = false;\n    wait_for_job_->wait();\n\n    // now wait for the other threads to be destroyed\n    size_t thread_num;\n    ok &= thread_all_[0].bthread == nullptr;\n    for(thread_num = 1; thread_num < num_threads_; thread_num++)\n    {   thread_all_[thread_num].bthread->join();\n        delete thread_all_[thread_num].bthread;\n        thread_all_[thread_num].bthread = nullptr;\n    }\n    // now we are down to just the master thread (thread zero)\n    sequential_execution_ = true;\n\n    // destroy wait_for_work_\n    delete wait_for_work_;\n    wait_for_work_ = nullptr;\n\n    // destroy wait_for_job_\n    delete wait_for_job_;\n    wait_for_job_ = nullptr;\n\n    // check ok before changing num_threads_\n    for(thread_num = 0; thread_num < num_threads_; thread_num++)\n        ok &= thread_all_[thread_num].ok;\n\n    // now inform CppAD that there is only one thread\n    num_threads_ = 1;\n    thread_alloc::parallel_setup(num_threads_, nullptr, nullptr);\n    thread_alloc::hold_memory(false);\n    CppAD::parallel_ad<double>();\n\n    return ok;\n}\n\nconst char* team_name(void)\n{   return \"bthread\"; }\n// END C++\n"
  },
  {
    "path": "example/multi_thread/harmonic.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin harmonic_common}\n\nCommon Variables Used by Multi-threading Sum of 1/i\n###################################################\n\nPurpose\n*******\nThis source code defines the common\ninclude files, defines, and variables that are used by\nthe summation that defines the harmonic series\n\n.. math::\n\n    1 + 1/2 + 1/3 + ... + 1/n\n\nSource\n******\n{xrst_literal\n    // BEGIN COMMON C++\n    // END COMMON C++\n}\n\n{xrst_end harmonic_common}\n*/\n// BEGIN COMMON C++\n\n\n# include <cppad/cppad.hpp>\n# include \"harmonic.hpp\"\n# include \"team_thread.hpp\"\n# define MAX_NUMBER_THREADS 48\n\nnamespace {\n    using CppAD::thread_alloc; // fast multi-threadeding memory allocator\n\n    // Number of threads, set by previous call to harmonic_time\n    // (zero means one thread with no multi-threading setup)\n    size_t num_threads_ = 0;\n\n    // value of mega_sum, set by previous call to harmonic_time.\n    size_t mega_sum_;\n\n    // structure with information for one thread\n    typedef struct {\n        // index to start summation at (worker input)\n        // set by previous call to harmonic_setup\n        size_t start;\n        // index to end summation at (worker input)\n        // set by previous call to harmonic_setup\n        size_t stop;\n        // summation for this thread\n        // set by worker\n        double sum;\n        // false if an error occurs, true otherwise\n        // set by worker\n        bool   ok;\n    } work_one_t;\n\n    // vector with information for all threads\n    // (use pointers instead of values to avoid false sharing)\n    work_one_t* work_all_[MAX_NUMBER_THREADS];\n}\n// END COMMON C++\n/*\n------------------------------------------------------------------------------\n{xrst_begin harmonic_setup}\n\nSet Up Multi-threading Sum of 1/i\n#################################\n\nSyntax\n******\n| *ok* = ``harmonic_setup`` ( *num_sum* )\n\nPurpose\n*******\nThis routine does the setup for splitting\nthe summation that defines the harmonic series\n\n.. math::\n\n    1 + 1/2 + 1/3 + ... + 1/n\n\ninto separate parts for each thread.\n\nThread\n******\nIt is assumed that this function is called by thread zero,\nand all the other threads are blocked (waiting).\n\nnum_sum\n*******\nThe argument *num_sum* has prototype\n\n    ``size_t`` *num_sum*\n\nIt specifies the value of :math:`n` in the summation.\n\nSource\n******\n{xrst_literal\n    // BEGIN SETUP C++\n    // END SETUP C++\n}\n\n{xrst_end harmonic_setup}\n*/\n// BEGIN SETUP C++\nnamespace {\nbool harmonic_setup(size_t num_sum)\n{  // sum = 1/num_sum + 1/(num_sum-1) + ... + 1\n    size_t num_threads  = std::max(num_threads_, size_t(1));\n    bool ok             = num_threads == thread_alloc::num_threads();\n    ok                 &= thread_alloc::thread_num() == 0;\n    ok                 &= num_sum >= num_threads;\n    //\n    for(size_t thread_num = 0; thread_num < num_threads; thread_num++)\n    {  // allocate separate memory for this thread to avoid false sharing\n        size_t min_bytes(sizeof(work_one_t)), cap_bytes;\n        void* v_ptr = thread_alloc::get_memory(min_bytes, cap_bytes);\n        work_all_[thread_num] = static_cast<work_one_t*>(v_ptr);\n        //\n        // in case this thread's worker does not get called\n        work_all_[thread_num]->ok = false;\n        // parameters that define the work for this and previous thread\n        if( thread_num == 0 )\n            work_all_[0]->start = 1;\n        else\n        {  size_t index  = (num_sum * thread_num) / num_threads;\n            work_all_[thread_num-1]->stop = index;\n            work_all_[thread_num]->start  = index;\n        }\n    }\n    work_all_[num_threads-1]->stop = num_sum + 1;\n    return ok;\n}\n}\n// END SETUP C++\n/*\n-------------------------------------------------------------------------------\n{xrst_begin harmonic_worker}\n\nDo One Thread's Work for Sum of 1/i\n###################################\n\nSyntax\n******\n\n    ``harmonic_worker`` ()\n\nPurpose\n*******\nThis routines computes the sum\nthe summation that defines the harmonic series\n\n    1/ *start* + 1/( *start* +1) + ... + 1/( *end* ``-1`` )\n\nstart\n*****\nThis is the value of the :ref:`harmonic_common-name` information\n\n    *start* = ``work_all_`` [ *thread_num* ] ``->start``\n\nend\n***\nThis is the value of the :ref:`harmonic_common-name` information\n\n    *end* = ``work_all_`` [ *thread_num* ] ``->end``\n\nthread_num\n**********\nThis is the number for the current thread; see\n:ref:`thread_num<ta_thread_num-name>` .\n\nSource\n******\n{xrst_literal\n    // BEGIN WORKER C++\n    // END WORKER C++\n}\n\n{xrst_end harmonic_worker}\n*/\n// BEGIN WORKER C++\nnamespace {\nvoid harmonic_worker(void)\n{  // sum =  1/(stop-1) + 1/(stop-2) + ... + 1/start\n    size_t thread_num  = thread_alloc::thread_num();\n    size_t num_threads = std::max(num_threads_, size_t(1));\n    bool   ok          = thread_num < num_threads;\n    size_t start       = work_all_[thread_num]->start;\n    size_t stop        = work_all_[thread_num]->stop;\n    double sum         = 0.;\n\n    ok &= stop > start;\n    size_t i = stop;\n    while( i > start )\n    {  i--;\n        sum += 1. / double(i);\n    }\n\n    work_all_[thread_num]->sum = sum;\n    work_all_[thread_num]->ok  = ok;\n}\n}\n// END WORKER C++\n/*\n-------------------------------------------------------------------------------\n{xrst_begin harmonic_takedown}\n\nTake Down Multi-threading Sum of 1/i\n####################################\n\nSyntax\n******\n\n    *ok* = ``harmonic_takedown`` ( *sum* )\n\nPurpose\n*******\nThis routine does the takedown for splitting\nthe summation that defines the harmonic series\n\n.. math::\n\n    s = 1 + 1/2 + 1/3 + ... + 1/n\n\ninto separate parts for each thread; see :ref:`harmonic_setup-name` .\n\nThread\n******\nIt is assumed that this function is called by thread zero,\nand all the other threads have completed their work and are blocked (waiting).\n\nsum\n***\nThis argument has prototype\n\n    ``double&`` *sum*\n\nThe input value of the argument does not matter.\nUpon return it is the value of the summation; i.e. :math:`s`.\n\nSource\n******\n{xrst_literal\n    // BEGIN TAKEDOWN C++\n    // END TAKEDOWN C++\n}\n\n{xrst_end harmonic_takedown}\n*/\n// BEGIN TAKEDOWN C++\nnamespace {\nbool harmonic_takedown(double& sum)\n{  // sum = 1/num_sum + 1/(num_sum-1) + ... + 1\n    bool ok            = true;\n    ok                &= thread_alloc::thread_num() == 0;\n    size_t num_threads = std::max(num_threads_, size_t(1));\n    sum                = 0.;\n    //\n    // go down so that free memory for other threads before memory for master\n    size_t thread_num = num_threads;\n    while(thread_num--)\n    {  // check that this tread was ok with the work it did\n        ok  &= work_all_[thread_num]->ok;\n        //\n        // add this threads contribution to the sum\n        sum += work_all_[thread_num]->sum;\n        //\n        // delete problem specific information\n        void* v_ptr = static_cast<void*>( work_all_[thread_num] );\n        thread_alloc::return_memory( v_ptr );\n        //\n        // check that there is no longer any memory inuse by this thread\n        // (for general applications, the master might still be using memory)\n        ok &= thread_alloc::inuse(thread_num) == 0;\n        //\n        // return all memory being held for future use by this thread\n        thread_alloc::free_available(thread_num);\n    }\n    return ok;\n}\n}\n// END TAKEDOWN C++\n/*\n------------------------------------------------------------------------------\n{xrst_begin harmonic_sum}\n\nMulti-Threaded Implementation of Summation of 1/i\n#################################################\n\nSyntax\n******\n*ok* = ``harmonic_sum`` ( *sum* , *num_sum* )\n\nPurpose\n*******\nMulti-threaded computation of the summation that defines the harmonic series\n\n.. math::\n\n    s = 1 + 1/2 + 1/3 + ... + 1/n\n\nThread\n******\nIt is assumed that this function is called by thread zero,\nand all the other threads are blocked (waiting).\n\nok\n**\nThis return value has prototype\n\n    ``bool`` *ok*\n\nIf this return value is false, an error occurred during ``harmonic`` .\n\nsum\n***\nThis argument has prototype\n\n    ``double&`` *sum*\n\nThe input value of the argument does not matter.\nUpon return it is the value of the summation; i.e. :math:`s`.\n\nnum_sum\n*******\nThis argument has prototype\n\n    ``size_t`` *num_sum*\n\nIt specifies the number of terms in the summation; i.e. :math:`n`.\n\nSource\n******\n{xrst_literal\n    // BEGIN SUM C++\n    // END SUM C++\n}\n\n{xrst_end harmonic_sum}\n*/\n// BEGIN SUM C++\nnamespace {\nbool harmonic_sum(double& sum, size_t num_sum)\n{  // sum = 1/num_sum + 1/(num_sum-1) + ... + 1\n    bool ok = true;\n    ok     &= thread_alloc::thread_num() == 0;\n\n    // setup the work for multi-threading\n    ok &= harmonic_setup(num_sum);\n\n    // now do the work for each thread\n    if( num_threads_ > 0 )\n        team_work( harmonic_worker );\n    else\n        harmonic_worker();\n\n    // combine the result for each thread and takedown the multi-threading.\n    ok &= harmonic_takedown(sum);\n\n    return ok;\n}\n}\n// END SUM C++\n/*\n-------------------------------------------------------------------------------\n{xrst_begin harmonic_time}\n\nTiming Test of Multi-Threaded Summation of 1/i\n##############################################\n\nSyntax\n******\n\n| *ok* = ``harmonic_time`` (\n| |tab| *time_out* , *test_time* , *num_threads* , *mega_sum*\n| )\n\nPurpose\n*******\nRuns a correctness and timing test for a multi-threaded\ncomputation of the summation that defines the harmonic series\n\n.. math::\n\n    1 + 1/2 + 1/3 + ... + 1/n\n\nThread\n******\nIt is assumed that this function is called by thread zero in sequential\nmode; i.e., not :ref:`in_parallel<ta_in_parallel-name>` .\n\nok\n**\nThis return value has prototype\n\n    ``bool`` *ok*\n\nIf it is true,\n``harmonic_time`` passed the correctness test.\nOtherwise it is false.\n\ntime_out\n********\nThis argument has prototype\n\n    ``double&`` *time_out*\n\nThe input value of the argument does not matter.\nUpon return it is the number of wall clock seconds required for\nto compute the summation.\n\ntest_time\n*********\nIs the minimum amount of wall clock time that the test should take.\nThe number of repeats for the test will be increased until this time\nis reached.\nThe reported *time_out* is the total wall clock time divided by the\nnumber of repeats.\n\nnum_threads\n***********\nThis argument has prototype\n\n    ``size_t`` *num_threads*\n\nIt specifies the number of threads that are available for this test.\nIf it is zero, the test is run without the multi-threading environment and\n\n    1 == ``thread_alloc::num_threads`` ()\n\nwhen ``harmonic_time`` is called.\nIf it is non-zero, the test is run with the multi-threading and\n\n    *num_threads* = ``thread_alloc::num_threads`` ()\n\nwhen ``harmonic_time`` is called.\n\nmega_sum\n********\nThis argument has prototype\n\n    ``size_t&`` *mega_sum*\n\nand is greater than zero.\nThe value :math:`n` in the summation\nis equal to :math:`10^6` times *mega_sum* .\n\nSource\n******\n{xrst_literal\n    // BEGIN TIME C++\n    // END TIME C++\n}\n\n{xrst_end harmonic_time}\n*/\n// BEGIN TIME C++\n# include <cstring>\n# include <limits>\n# include <iostream>\n# include <cstdlib>\n# include <algorithm>\n\n// Note there is no mention of parallel mode in the documentation for\n// speed_test (so it is safe to use without special consideration).\n# include <cppad/utility/time_test.hpp>\n\nnamespace {\n    // value of sum resulting from most recent call to test_once\n    double sum_ = 0.;\n    //\n    void test_once(void)\n    {   if( mega_sum_ < 1 )\n        {   std::cerr << \"harmonic_time: mega_sum < 1\" << std::endl;\n            exit(1);\n        }\n        size_t num_sum = mega_sum_ * 1000000;\n        bool ok = harmonic_sum(sum_, num_sum);\n        if( ! ok )\n        {   std::cerr << \"harmonic: error\" << std::endl;\n            exit(1);\n        }\n        return;\n    }\n    //\n    void test_repeat(size_t repeat)\n    {   size_t i;\n        for(i = 0; i < repeat; i++)\n            test_once();\n        return;\n    }\n}\n\n// This is the only routine that is accessible outside of this file\nbool harmonic_time(\n    double& time_out, double test_time, size_t num_threads, size_t mega_sum)\n{   bool ok  = true;\n    ok      &= thread_alloc::thread_num() == 0;\n\n    // arguments passed to harmonic_sum\n    num_threads_ = num_threads;\n    mega_sum_    = mega_sum;\n\n    // create team of threads\n    ok &= thread_alloc::in_parallel() == false;\n    if( num_threads > 0 )\n    {   team_create(num_threads);\n        ok &= num_threads == thread_alloc::num_threads();\n    }\n    else\n    {   ok &= 1 == thread_alloc::num_threads();\n    }\n\n    // run the test case and set the time return value\n    time_out = CppAD::time_test(test_repeat, test_time);\n\n    // destroy team of threads\n    if( num_threads > 0 )\n        team_destroy();\n    ok &= thread_alloc::in_parallel() == false;\n\n    // Correctness check\n    double eps1000 =\n        double(mega_sum_) * 1e3 * std::numeric_limits<double>::epsilon();\n    size_t i       = mega_sum_ * 1000000;\n    double check = 0.;\n    while(i)\n        check += 1. / double(i--);\n    ok &= std::fabs(sum_ - check) <= eps1000;\n\n    return ok;\n}\n\n// END TIME C++\n"
  },
  {
    "path": "example/multi_thread/harmonic.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_MULTI_THREAD_HARMONIC_HPP\n# define CPPAD_EXAMPLE_MULTI_THREAD_HARMONIC_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\nbool harmonic_time(\n    double& time_out, double test_time, size_t num_threads, size_t mega_sum\n);\n\n# endif\n"
  },
  {
    "path": "example/multi_thread/harmonic.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin harmonic.cpp}\n\nMulti-Threading Harmonic Summation Example / Test\n#################################################\n\nSource File\n***********\nAll of the routines below are located in the file\n::\n\n    example/multi_thread/harmonic.cpp\n\nContents\n********\n{xrst_toc_table\n    example/multi_thread/harmonic.cpp\n}\n\n{xrst_end harmonic.cpp}\n"
  },
  {
    "path": "example/multi_thread/multi_atomic_three.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin multi_atomic_three_user}\n\nDefines a atomic_three Operation that Computes Square Root\n##########################################################\n\nSyntax\n******\n| ``atomic_user`` *a_square_root*\n| *a_square_root* ( *au* , *ay* )\n\nPurpose\n*******\nThis atomic function operation computes a square root using Newton's method.\nIt is meant to be very inefficient in order to demonstrate timing results.\n\nau\n**\nThis argument has prototype\n\n    ``const`` *ADvector* & *au*\n\nwhere *ADvector* is a\n:ref:`simple vector class<SimpleVector-name>` with elements\nof type ``AD<double>`` .\nThe size of *au* is three.\n\nnum_itr\n=======\nWe use the notation\n\n    *num_itr* = ``size_t`` ( ``Integer`` ( *au* [0] ) )\n\nfor the number of Newton iterations in the computation of the square root\nfunction.  The component *au* [0] must be a\n:ref:`glossary@Parameter` .\n\ny_initial\n=========\nWe use the notation\n\n    *y_initial* = *au* [1]\n\nfor the initial value of the Newton iterate.\n\ny_squared\n=========\nWe use the notation\n\n    *y_squared* = *au* [2]\n\nfor the value we are taking the square root of.\n\nay\n**\nThis argument has prototype\n\n    *ADvector* & *ay*\n\nThe size of *ay* is one and\n*ay* [0] is the square root of *y_squared* .\n\nLimitations\n***********\nOnly zero order forward mode is implements for the\n``atomic_user`` class.\n\nSource\n******\n{xrst_literal\n    // BEGIN USER C++\n    // END USER C++\n}\n\n{xrst_end multi_atomic_three_user}\n*/\n// BEGIN USER C++\n// includes used by all source code in multi_atomic_three.cpp file\n# include <cppad/cppad.hpp>\n# include \"multi_atomic_three.hpp\"\n# include \"team_thread.hpp\"\n//\nnamespace {\nusing CppAD::thread_alloc;                // multi-threading memory allocator\nusing CppAD::vector;                      // uses thread_alloc\ntypedef CppAD::ad_type_enum ad_type_enum; // constant, dynamic or variable\n\nclass atomic_user : public CppAD::atomic_three<double> {\npublic:\n    // ctor\n    atomic_user(void)\n    : CppAD::atomic_three<double>(\"atomic_square_root\")\n    { }\nprivate:\n    // for_type\n    bool for_type(\n        const vector<double>&        parameter_u ,\n        const vector<ad_type_enum>&  type_u      ,\n        vector<ad_type_enum>&        type_y      ) override\n    {  bool ok = parameter_u.size() == 3;\n        ok     &= type_u.size() == 3;\n        ok     &= type_y.size() == 1;\n        if( ! ok )\n            return false;\n        ok     &= type_u[0] < CppAD::variable_enum;\n        if( ! ok )\n            return false;\n        type_y[0] = std::max( type_u[0], type_u[1] );\n        type_y[0] = std::max( type_y[0], type_u[2] );\n        //\n        return true;\n    }\n    // forward\n    bool forward(\n        const vector<double>&        parameter_u ,\n        const vector<ad_type_enum>&  type_u      ,\n        size_t                       need_y      ,\n        size_t                       order_low   ,\n        size_t                       order_up    ,\n        const vector<double>&        taylor_u    ,\n        vector<double>&              taylor_y    ) override\n    {\n# ifndef NDEBUG\n        size_t n = taylor_u.size() / (order_up + 1);\n        size_t m = taylor_y.size() / (order_up + 1);\n        assert( n == 3 );\n        assert( m == 1 );\n# endif\n        // only implementing zero order forward for this example\n        if( order_up != 0 )\n            return false;\n\n        // extract components of argument vector\n        size_t num_itr    = size_t( taylor_u[0] );\n        double y_initial  = taylor_u[1];\n        double y_squared  = taylor_u[2];\n\n        // Use Newton's method to solve f(y) = y^2 = y_squared\n        double y_itr = y_initial;\n        for(size_t itr = 0; itr < num_itr; itr++)\n        {  // solve (y - y_itr) * f'(y_itr) = y_squared - y_itr^2\n            double fp_itr = 2.0 * y_itr;\n            y_itr         = y_itr + (y_squared - y_itr * y_itr) / fp_itr;\n        }\n\n        // return the Newton approximation for f(y) = y_squared\n        taylor_y[0] = y_itr;\n        return true;\n    }\n};\n}\n// END USER C++\n/*\n{xrst_begin multi_atomic_three_common}\n\nMulti-Threaded atomic_three Common Information\n##############################################\n\nPurpose\n*******\nThis source code defines the common variables that are used by\nthe ``multi_atomic_three_`` *name* functions.\n\nSource\n******\n{xrst_literal\n    // BEGIN COMMON C++\n    // END COMMON C++\n}\n\n{xrst_end multi_atomic_three_common}\n*/\n// BEGIN COMMON C++\nnamespace {\n    // Number of threads, set by multi_atomic_three_time\n    // (zero means one thread with no multi-threading setup)\n    size_t num_threads_ = 0;\n\n    // Number of Newton iterations, set by multi_atomic_three_time\n    size_t num_itr_;\n\n    // We can use one atomic_atomic function for all threads because\n    // there is no member data that gets changed during worker call.\n    // This needs to stay in scope for as long as a recording will use it.\n    // We cannot be in parallel mode when this object is created or deleted.\n    // We use a pointer so that there is no left over memory in thread zero.\n    atomic_user* a_square_root_ = 0;\n\n    // structure with information for one thread\n    typedef struct {\n        // used by worker to compute the square root, set by multi_atomic_three_setup\n        CppAD::ADFun<double>* fun;\n        //\n        // value we are computing square root of, set by multi_atomic_three_setup\n        vector<double>* y_squared;\n        //\n        // square root, set by worker\n        vector<double>* square_root;\n        //\n        // false if an error occurs, true otherwise, set by worker\n        bool ok;\n    } work_one_t;\n    //\n    // Vector with information for all threads\n    // (uses pointers instead of values to avoid false sharing)\n    // allocated by multi_atomic_three_setup, freed by multi_atomic_three_takedown\n    work_one_t* work_all_[CPPAD_MAX_NUM_THREADS];\n}\n// END COMMON C++\n/*\n-------------------------------------------------------------------------------\n{xrst_begin multi_atomic_three_setup}\n\nMulti-Threaded atomic_three Set Up\n##################################\n\nSyntax\n******\n*ok* = ``multi_atomic_three_setup`` ( *y_squared* )\n\nPurpose\n*******\nThis routine splits up the computation into the individual threads.\n\nThread\n******\nIt is assumed that this function is called by thread zero\nand all the other threads are blocked (waiting).\n\ny_squared\n*********\nThis argument has prototype\n\n    ``const vector<double>&`` *y_squared*\n\nand its size is equal to the number of equations to solve.\nIt is the values that we are computing the square root of.\n\nok\n**\nThis return value has prototype\n\n    ``bool`` *ok*\n\nIf it is false,\n``multi_atomic_three_setup`` detected an error.\n\nSource\n******\n{xrst_literal\n    // BEGIN SETUP C++\n    // END SETUP C++\n}\n\n{xrst_end multi_atomic_three_setup}\n*/\n// BEGIN SETUP C++\nnamespace {\nbool multi_atomic_three_setup(const vector<double>& y_squared)\n{  using CppAD::AD;\n    size_t num_threads = std::max(num_threads_, size_t(1));\n    bool   ok          = num_threads == thread_alloc::num_threads();\n    ok                &= thread_alloc::thread_num() == 0;\n    //\n    // declare independent variable variable vector\n    vector< AD<double> > ax(1);\n    ax[0] = 2.0;\n    CppAD::Independent(ax);\n    //\n    // argument and result for atomic function\n    vector< AD<double> > au(3), ay(1);\n    au[0] = AD<double>( num_itr_ ); // num_itr\n    au[1] = ax[0];                  // y_initial\n    au[2] = ax[0];                  // y_squared\n    // put atomic function operation in recording\n    (*a_square_root_)(au, ay);\n    //\n    // f(u) = sqrt(u)\n    CppAD::ADFun<double> fun(ax, ay);\n    //\n    // number of square roots for each thread\n    size_t per_thread = (y_squared.size() + num_threads - 1) / num_threads;\n    size_t y_index    = 0;\n    //\n    for(size_t thread_num = 0; thread_num < num_threads; thread_num++)\n    {  // allocate separate memory for each thread to avoid false sharing\n        size_t min_bytes(sizeof(work_one_t)), cap_bytes;\n        void* v_ptr = thread_alloc::get_memory(min_bytes, cap_bytes);\n        work_all_[thread_num] = static_cast<work_one_t*>(v_ptr);\n        //\n        // Run constructor on work_all_[thread_num]->fun\n        work_all_[thread_num]->fun = new CppAD::ADFun<double>;\n        //\n        // Run constructor on work_all_[thread_num] vectors\n        work_all_[thread_num]->y_squared = new vector<double>;\n        work_all_[thread_num]->square_root = new vector<double>;\n        //\n        // Each worker gets a separate copy of fun. This is necessary because\n        // the Taylor coefficients will be set by each thread.\n        *(work_all_[thread_num]->fun) = fun;\n        //\n        // values we are computing square root of for this thread\n        ok &=  0 == work_all_[thread_num]->y_squared->size();\n        for(size_t i = 0; i < per_thread; i++)\n        if( y_index < y_squared.size() )\n            work_all_[thread_num]->y_squared->push_back(y_squared[y_index++]);\n        //\n        // set to false in case this thread's worker does not get called\n        work_all_[thread_num]->ok = false;\n    }\n    ok &= y_index == y_squared.size();\n    //\n    return ok;\n}\n}\n// END SETUP C++\n/*\n------------------------------------------------------------------------------\n{xrst_begin multi_atomic_three_worker}\n\nMulti-Threaded atomic_three Worker\n##################################\n\nPurpose\n*******\nThis routine does the computation for one thread.\n\nSource\n******\n{xrst_literal\n    // BEGIN WORKER C++\n    // END WORKER C++\n}\n\n{xrst_end multi_atomic_three_worker}\n*/\n// BEGIN WORKER C++\nnamespace {\nvoid multi_atomic_three_worker(void)\n{  size_t thread_num  = thread_alloc::thread_num();\n    size_t num_threads = std::max(num_threads_, size_t(1));\n    bool   ok          = thread_num < num_threads;\n    //\n    vector<double> x(1), y(1);\n    size_t n = work_all_[thread_num]->y_squared->size();\n    work_all_[thread_num]->square_root->resize(n);\n    for(size_t i = 0; i < n; i++)\n    {  x[0] = (* work_all_[thread_num]->y_squared )[i];\n        y    = work_all_[thread_num]->fun->Forward(0, x);\n        //\n        (* work_all_[thread_num]->square_root )[i] = y[0];\n    }\n    work_all_[thread_num]->ok             = ok;\n}\n}\n// END WORKER C++\n/*\n------------------------------------------------------------------------------\n{xrst_begin multi_atomic_three_takedown}\n\nMulti-Threaded atomic_three Take Down\n#####################################\n\nSyntax\n******\n*ok* = ``multi_atomic_three_takedown`` ( *square_root* )\n\nPurpose\n*******\nThis routine gathers up the results for each thread and\nfrees memory that was allocated by :ref:`multi_atomic_three_setup-name` .\n\nThread\n******\nIt is assumed that this function is called by thread zero\nand all the other threads are blocked (waiting).\n\nsquare_root\n***********\nThis argument has prototype\n\n    ``vector<double>&`` *square_root*\n\nThe input value of *square_root* does not matter.\nUpon return,\nit has the same size and is the element by element square root of\n:ref:`multi_atomic_three_setup@y_squared` .\n\nok\n**\nThis return value has prototype\n\n    ``bool`` *ok*\n\nIf it is false,\n``multi_atomic_three_takedown`` detected an error.\n\nSource\n******\n{xrst_literal\n    // BEGIN TAKEDOWN C++\n    // END TAKEDOWN C++\n}\n\n{xrst_end multi_atomic_three_takedown}\n*/\n// BEGIN TAKEDOWN C++\nnamespace {\nbool multi_atomic_three_takedown(vector<double>& square_root)\n{  bool ok            = true;\n    ok                &= thread_alloc::thread_num() == 0;\n    size_t num_threads = std::max(num_threads_, size_t(1));\n    //\n    // extract square roots in original order\n    square_root.resize(0);\n    for(size_t thread_num = 0; thread_num < num_threads; thread_num++)\n    {  // results for this thread\n        size_t n = work_all_[thread_num]->square_root->size();\n        for(size_t i = 0; i < n; i++)\n            square_root.push_back((* work_all_[thread_num]->square_root )[i]);\n    }\n    //\n    // go down so that free memory for other threads before memory for master\n    size_t thread_num = num_threads;\n    while(thread_num--)\n    {  // check that this tread was ok with the work it did\n        ok  &= work_all_[thread_num]->ok;\n        //\n        // run destructor on vector object for this thread\n        delete work_all_[thread_num]->y_squared;\n        delete work_all_[thread_num]->square_root;\n        //\n        // run destructor on function object for this thread\n        delete work_all_[thread_num]->fun;\n        //\n        // delete problem specific information\n        void* v_ptr = static_cast<void*>( work_all_[thread_num] );\n        thread_alloc::return_memory( v_ptr );\n        //\n        // check that there is no longer any memory inuse by this thread\n        if( thread_num > 0 )\n        {  ok &= 0 == thread_alloc::inuse(thread_num);\n            //\n            // return all memory being held for future use by this thread\n            thread_alloc::free_available(thread_num);\n        }\n    }\n    return ok;\n}\n}\n// END TAKEDOWN C++\n/*\n{xrst_begin multi_atomic_three_run}\n\nRun Multi-Threaded atomic_three Calculation\n###########################################\n\nSyntax\n******\n*ok* = ``multi_atomic_three_run`` ( *y_squared* , *square_root* )\n\nThread\n******\nIt is assumed that this function is called by thread zero\nand all the other threads are blocked (waiting).\n\ny_squared\n*********\nThis argument has prototype\n\n    ``const vector<double>&`` *y_squared*\n\nand its size is equal to the number of threads.\nIt is the values that we are computing the square root of.\n\nsquare_root\n***********\nThis argument has prototype\n\n    ``vector<double>&`` *square_root*\n\nThe input value of *square_root* does not matter.\nUpon return,\nit has the same size and\nis the element by element square root of *y_squared* .\n\nok\n**\nThis return value has prototype\n\n    ``bool`` *ok*\n\nIf it is false,\n``multi_atomic_three_run`` detected an error.\n\nSource\n******\n{xrst_literal\n    // BEGIN RUN C++\n    // END RUN C++\n}\n\n{xrst_end multi_atomic_three_run}\n------------------------------------------------------------------------------\n*/\n// BEGIN RUN C++\nnamespace {\nbool multi_atomic_three_run(\n    const vector<double>& y_squared  ,\n    vector<double>&      square_root )\n{\n    bool ok = true;\n    ok     &= thread_alloc::thread_num() == 0;\n\n    // setup the work for multi-threading\n    ok &= multi_atomic_three_setup(y_squared);\n\n    // now do the work for each thread\n    if( num_threads_ > 0 )\n        team_work( multi_atomic_three_worker );\n    else\n        multi_atomic_three_worker();\n\n    // combine the result for each thread and takedown the multi-threading.\n    ok &= multi_atomic_three_takedown(square_root);\n\n    return ok;\n}\n}\n// END RUN C++\n/*\n------------------------------------------------------------------------------\n{xrst_begin multi_atomic_three_time}\n\nTiming Test for Multi-Threaded atomic_three Calculation\n#######################################################\n\nSyntax\n******\n\n| *ok* = ``multi_atomic_three_time`` (\n| |tab| *time_out* , *test_time* , *num_threads* , *num_solve*\n| )\n\nThread\n******\nIt is assumed that this function is called by thread zero in sequential\nmode; i.e., not :ref:`in_parallel<ta_in_parallel-name>` .\n\ntime_out\n********\nThis argument has prototype\n\n    ``double&`` *time_out*\n\nIts input value of the argument does not matter.\nUpon return it is the number of wall clock seconds\nused by :ref:`multi_atomic_three_run-name` .\n\ntest_time\n*********\nThis argument has prototype\n\n    ``double`` *test_time*\n\nand is the minimum amount of wall clock time that the test should take.\nThe number of repeats for the test will be increased until this time\nis reached.\nThe reported *time_out* is the total wall clock time divided by the\nnumber of repeats.\n\nnum_threads\n***********\nThis argument has prototype\n\n    ``size_t`` *num_threads*\n\nIt specifies the number of threads that are available for this test.\nIf it is zero, the test is run without the multi-threading environment and\n\n    1 == ``thread_alloc::num_threads`` ()\n\nIf it is non-zero, the test is run with the multi-threading and\n\n    *num_threads* = ``thread_alloc::num_threads`` ()\n\nnum_solve\n*********\nThis specifies the number of square roots that will be solved for.\n\nok\n**\nThe return value has prototype\n\n    ``bool`` *ok*\n\nIf it is true,\n``harmonic_time`` passed the correctness test and\n``multi_atomic_three_time`` did not detect an error.\nOtherwise it is false.\n\n{xrst_end multi_atomic_three_time}\n*/\n\n// BEGIN TIME C++\nnamespace {\n    // values we are taking the square root of\n    vector<double> y_squared_;\n\n    // results of the square root calculations\n    vector<double> square_root_;\n    //\n    void test_once(void)\n    {   bool ok = multi_atomic_three_run(y_squared_, square_root_);\n        if( ! ok )\n        {   std::cerr << \"multi_atomic_three_run: error\" << std::endl;\n            exit(1);\n        }\n        return;\n    }\n    //\n    void test_repeat(size_t repeat)\n    {   size_t i;\n        for(i = 0; i < repeat; i++)\n            test_once();\n        return;\n    }\n}\n// This is the only routine that is accessible outside of this file\nbool multi_atomic_three_time(\n    double& time_out, double test_time, size_t num_threads, size_t num_solve\n)\n{   bool ok = true;\n    //\n    size_t initial_inuse = thread_alloc::inuse(0);\n\n    // number of threads, zero for no multi-threading\n    num_threads_ = num_threads;\n\n    // number of Newton iterations\n    num_itr_ = 20;\n\n    // values we are talking the square root of\n    y_squared_.resize(num_solve);\n    for(size_t i_solve = 0; i_solve < num_solve; i_solve++)\n        y_squared_[i_solve] = double(i_solve) + 2.0;\n\n    // must create a_square_root_ sequential mode\n    a_square_root_ = new atomic_user;\n\n    // create team of threads\n    ok &= thread_alloc::in_parallel() == false;\n    if( num_threads > 0 )\n    {   team_create(num_threads);\n        ok &= num_threads == thread_alloc::num_threads();\n    }\n    else\n    {   ok &= 1 == thread_alloc::num_threads();\n    }\n\n    // run the test case and set the time return value\n    time_out = CppAD::time_test(test_repeat, test_time);\n\n    // destroy team of threads\n    if( num_threads > 0 )\n        team_destroy();\n    ok &= thread_alloc::in_parallel() == false;\n\n    // must delete a_square_root_ in sequential mode\n    delete a_square_root_;\n\n    // correctness check\n    ok &= square_root_.size() == num_solve;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    for(size_t i = 0; i < num_solve; i++)\n    {   double check = std::sqrt( y_squared_[i] );\n        ok          &= std::fabs( square_root_[i] / check - 1.0 ) <= eps99;\n    }\n    y_squared_.clear();\n    square_root_.clear();\n    //\n    // check that no static variables in this file are holding onto memory\n    ok &= initial_inuse == thread_alloc::inuse(0);\n    //\n    return ok;\n}\n// END TIME C++\n"
  },
  {
    "path": "example/multi_thread/multi_atomic_three.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_MULTI_THREAD_MULTI_ATOMIC_THREE_HPP\n# define CPPAD_EXAMPLE_MULTI_THREAD_MULTI_ATOMIC_THREE_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\nbool multi_atomic_three_time(\n    double& time_out, double test_time, size_t num_threads, size_t num_solve\n);\n\n# endif\n"
  },
  {
    "path": "example/multi_thread/multi_atomic_three.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin multi_atomic_three.cpp}\n\nMulti-Threading atomic_three Example / Test\n###########################################\n\nSource File\n***********\nAll of the routines below are located in the file\n::\n\n    example/multi_thread/multi_atomic_three.cpp\n\nContents\n********\n{xrst_toc_table\n    example/multi_thread/multi_atomic_three.cpp\n}\n\n{xrst_end multi_atomic_three.cpp}\n"
  },
  {
    "path": "example/multi_thread/multi_atomic_two.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin multi_atomic_two_user app}\n\nDefines a atomic_two Operation that Computes Square Root\n########################################################\n\nSyntax\n******\n| ``atomic_user`` *a_square_root*\n| *a_square_root* ( *au* , *ay* )\n\nPurpose\n*******\nThis atomic function operation computes a square root using Newton's method.\nIt is meant to be very inefficient in order to demonstrate timing results.\n\nau\n**\nThis argument has prototype\n\n    ``const`` *ADvector* & *au*\n\nwhere *ADvector* is a\n:ref:`simple vector class<SimpleVector-name>` with elements\nof type ``AD<double>`` .\nThe size of *au* is three.\n\nnum_itr\n=======\nWe use the notation\n\n    *num_itr* = ``size_t`` ( ``Integer`` ( *au* [0] ) )\n\nfor the number of Newton iterations in the computation of the square root\nfunction.  The component *au* [0] must be a\n:ref:`glossary@Parameter` .\n\ny_initial\n=========\nWe use the notation\n\n    *y_initial* = *au* [1]\n\nfor the initial value of the Newton iterate.\n\ny_squared\n=========\nWe use the notation\n\n    *y_squared* = *au* [2]\n\nfor the value we are taking the square root of.\n\nay\n**\nThis argument has prototype\n\n    *ADvector* & *ay*\n\nThe size of *ay* is one and\n*ay* [0] is the square root of *y_squared* .\n\nLimitations\n***********\nOnly zero order forward mode is implements for the\n``atomic_user`` class.\n\nSource\n******\n{xrst_literal\n    // BEGIN USER C++\n    // END USER C++\n}\n\n{xrst_end multi_atomic_two_user}\n*/\n// BEGIN USER C++\n// includes used by all source code in multi_atomic_two.cpp file\n# include <cppad/cppad.hpp>\n# include \"multi_atomic_two.hpp\"\n# include \"team_thread.hpp\"\n//\nnamespace {\nusing CppAD::thread_alloc; // fast multi-threading memory allocator\nusing CppAD::vector;       // uses thread_alloc\n\nclass atomic_user : public CppAD::atomic_base<double> {\npublic:\n    // ctor\n    atomic_user(void)\n    : CppAD::atomic_base<double>(\"atomic_square_root\")\n    { }\nprivate:\n    // forward mode routine called by CppAD\n    bool forward(\n        size_t                   p   ,\n        size_t                   q   ,\n        const vector<bool>&      vu  ,\n        vector<bool>&            vy  ,\n        const vector<double>&    tu  ,\n        vector<double>&          ty  ) override\n    {\n# ifndef NDEBUG\n        size_t n = tu.size() / (q + 1);\n        size_t m = ty.size() / (q + 1);\n        assert( n == 3 );\n        assert( m == 1 );\n# endif\n        // only implementing zero order forward for this example\n        if( q != 0 )\n            return false;\n\n        // extract components of argument vector\n        size_t num_itr    = size_t( tu[0] );\n        double y_initial  = tu[1];\n        double y_squared  = tu[2];\n\n        // check for setting variable information\n        if( vu.size() > 0 )\n        {  if( vu[0] )\n                return false;\n            vy[0] = vu[1] || vu[2];\n        }\n\n        // Use Newton's method to solve f(y) = y^2 = y_squared\n        double y_itr = y_initial;\n        for(size_t itr = 0; itr < num_itr; itr++)\n        {  // solve (y - y_itr) * f'(y_itr) = y_squared - y_itr^2\n            double fp_itr = 2.0 * y_itr;\n            y_itr         = y_itr + (y_squared - y_itr * y_itr) / fp_itr;\n        }\n\n        // return the Newton approximation for f(y) = y_squared\n        ty[0] = y_itr;\n        return true;\n    }\n};\n}\n// END USER C++\n/*\n{xrst_begin multi_atomic_two_common app}\n\nMulti-Threaded atomic_two Common Information\n############################################\n\nPurpose\n*******\nThis source code defines the common variables that are used by\nthe ``multi_atomic_two_`` *name* functions.\n\nSource\n******\n{xrst_literal\n    // BEGIN COMMON C++\n    // END COMMON C++\n}\n\n{xrst_end multi_atomic_two_common}\n*/\n// BEGIN COMMON C++\nnamespace {\n    // Number of threads, set by multi_atomic_two_time\n    // (zero means one thread with no multi-threading setup)\n    size_t num_threads_ = 0;\n\n    // Number of Newton iterations, set by multi_atomic_two_time\n    size_t num_itr_;\n\n    // We can use one atomic_atomic function for all threads because\n    // there is no member data that gets changed during worker call.\n    // This needs to stay in scope for as long as a recording will use it.\n    // We cannot be in parallel mode when this object is created or deleted.\n    // We use a pointer so that there is no left over memory in thread zero.\n    atomic_user* a_square_root_ = 0;\n\n    // structure with information for one thread\n    typedef struct {\n        // used by worker to compute the square root, set by multi_atomic_two_setup\n        CppAD::ADFun<double>* fun;\n        //\n        // value we are computing square root of, set by multi_atomic_two_setup\n        vector<double>* y_squared;\n        //\n        // square root, set by worker\n        vector<double>* square_root;\n        //\n        // false if an error occurs, true otherwise, set by worker\n        bool ok;\n    } work_one_t;\n    //\n    // Vector with information for all threads\n    // (uses pointers instead of values to avoid false sharing)\n    // allocated by multi_atomic_two_setup, freed by multi_atomic_two_takedown\n    work_one_t* work_all_[CPPAD_MAX_NUM_THREADS];\n}\n// END COMMON C++\n/*\n-------------------------------------------------------------------------------\n{xrst_begin multi_atomic_two_setup app}\n\nMulti-Threaded atomic_two Set Up\n################################\n\nSyntax\n******\n*ok* = ``multi_atomic_two_setup`` ( *y_squared* )\n\nPurpose\n*******\nThis routine splits up the computation into the individual threads.\n\nThread\n******\nIt is assumed that this function is called by thread zero\nand all the other threads are blocked (waiting).\n\ny_squared\n*********\nThis argument has prototype\n\n    ``const vector<double>&`` *y_squared*\n\nand its size is equal to the number of equations to solve.\nIt is the values that we are computing the square root of.\n\nok\n**\nThis return value has prototype\n\n    ``bool`` *ok*\n\nIf it is false,\n``multi_atomic_two_setup`` detected an error.\n\nSource\n******\n{xrst_literal\n    // BEGIN SETUP C++\n    // END SETUP C++\n}\n\n{xrst_end multi_atomic_two_setup}\n*/\n// BEGIN SETUP C++\nnamespace {\nbool multi_atomic_two_setup(const vector<double>& y_squared)\n{  using CppAD::AD;\n    size_t num_threads = std::max(num_threads_, size_t(1));\n    bool   ok          = num_threads == thread_alloc::num_threads();\n    ok                &= thread_alloc::thread_num() == 0;\n    //\n    // declare independent variable variable vector\n    vector< AD<double> > ax(1);\n    ax[0] = 2.0;\n    CppAD::Independent(ax);\n    //\n    // argument and result for atomic function\n    vector< AD<double> > au(3), ay(1);\n    au[0] = AD<double>( num_itr_ ); // num_itr\n    au[1] = ax[0];                  // y_initial\n    au[2] = ax[0];                  // y_squared\n    // put atomic function operation in recording\n    (*a_square_root_)(au, ay);\n    //\n    // f(u) = sqrt(u)\n    CppAD::ADFun<double> fun(ax, ay);\n    //\n    // number of square roots for each thread\n    size_t per_thread = (y_squared.size() + num_threads - 1) / num_threads;\n    size_t y_index    = 0;\n    //\n    for(size_t thread_num = 0; thread_num < num_threads; thread_num++)\n    {  // allocate separate memory for each thread to avoid false sharing\n        size_t min_bytes(sizeof(work_one_t)), cap_bytes;\n        void* v_ptr = thread_alloc::get_memory(min_bytes, cap_bytes);\n        work_all_[thread_num] = static_cast<work_one_t*>(v_ptr);\n        //\n        // Run constructor on work_all_[thread_num]->fun\n        work_all_[thread_num]->fun = new CppAD::ADFun<double>;\n        //\n        // Run constructor on work_all_[thread_num] vectors\n        work_all_[thread_num]->y_squared = new vector<double>;\n        work_all_[thread_num]->square_root = new vector<double>;\n        //\n        // Each worker gets a separate copy of fun. This is necessary because\n        // the Taylor coefficients will be set by each thread.\n        *(work_all_[thread_num]->fun) = fun;\n        //\n        // values we are computing square root of for this thread\n        ok &=  0 == work_all_[thread_num]->y_squared->size();\n        for(size_t i = 0; i < per_thread; i++)\n        if( y_index < y_squared.size() )\n            work_all_[thread_num]->y_squared->push_back(y_squared[y_index++]);\n        //\n        // set to false in case this thread's worker does not get called\n        work_all_[thread_num]->ok = false;\n    }\n    ok &= y_index == y_squared.size();\n    //\n    return ok;\n}\n}\n// END SETUP C++\n/*\n------------------------------------------------------------------------------\n{xrst_begin multi_atomic_two_worker app}\n\nMulti-Threaded atomic_two Worker\n################################\n\nPurpose\n*******\nThis routine does the computation for one thread.\n\nSource\n******\n{xrst_literal\n    // BEGIN WORKER C++\n    // END WORKER C++\n}\n\n{xrst_end multi_atomic_two_worker}\n*/\n// BEGIN WORKER C++\nnamespace {\nvoid multi_atomic_two_worker(void)\n{  size_t thread_num  = thread_alloc::thread_num();\n    size_t num_threads = std::max(num_threads_, size_t(1));\n    bool   ok          = thread_num < num_threads;\n    //\n    vector<double> x(1), y(1);\n    size_t n = work_all_[thread_num]->y_squared->size();\n    work_all_[thread_num]->square_root->resize(n);\n    for(size_t i = 0; i < n; i++)\n    {  x[0] = (* work_all_[thread_num]->y_squared )[i];\n        y    = work_all_[thread_num]->fun->Forward(0, x);\n        //\n        (* work_all_[thread_num]->square_root )[i] = y[0];\n    }\n    work_all_[thread_num]->ok             = ok;\n}\n}\n// END WORKER C++\n/*\n------------------------------------------------------------------------------\n{xrst_begin multi_atomic_two_takedown app}\n\nMulti-Threaded atomic_two Take Down\n###################################\n\nSyntax\n******\n*ok* = ``multi_atomic_two_takedown`` ( *square_root* )\n\nPurpose\n*******\nThis routine gathers up the results for each thread and\nfrees memory that was allocated by :ref:`multi_atomic_two_setup-name` .\n\nThread\n******\nIt is assumed that this function is called by thread zero\nand all the other threads are blocked (waiting).\n\nsquare_root\n***********\nThis argument has prototype\n\n    ``vector<double>&`` *square_root*\n\nThe input value of *square_root* does not matter.\nUpon return,\nit has the same size and is the element by element square root of\n:ref:`multi_atomic_two_setup@y_squared` .\n\nok\n**\nThis return value has prototype\n\n    ``bool`` *ok*\n\nIf it is false,\n``multi_atomic_two_takedown`` detected an error.\n\nSource\n******\n{xrst_literal\n    // BEGIN TAKEDOWN C++\n    // END TAKEDOWN C++\n}\n\n{xrst_end multi_atomic_two_takedown}\n*/\n// BEGIN TAKEDOWN C++\nnamespace {\nbool multi_atomic_two_takedown(vector<double>& square_root)\n{  bool ok            = true;\n    ok                &= thread_alloc::thread_num() == 0;\n    size_t num_threads = std::max(num_threads_, size_t(1));\n    //\n    // extract square roots in original order\n    square_root.resize(0);\n    for(size_t thread_num = 0; thread_num < num_threads; thread_num++)\n    {  // results for this thread\n        size_t n = work_all_[thread_num]->square_root->size();\n        for(size_t i = 0; i < n; i++)\n            square_root.push_back((* work_all_[thread_num]->square_root )[i]);\n    }\n    //\n    // go down so that free memory for other threads before memory for master\n    size_t thread_num = num_threads;\n    while(thread_num--)\n    {  // check that this tread was ok with the work it did\n        ok  &= work_all_[thread_num]->ok;\n        //\n        // run destructor on vector object for this thread\n        delete work_all_[thread_num]->y_squared;\n        delete work_all_[thread_num]->square_root;\n        //\n        // run destructor on function object for this thread\n        delete work_all_[thread_num]->fun;\n        //\n        // delete problem specific information\n        void* v_ptr = static_cast<void*>( work_all_[thread_num] );\n        thread_alloc::return_memory( v_ptr );\n        //\n        // check that there is no longer any memory inuse by this thread\n        if( thread_num > 0 )\n        {  ok &= 0 == thread_alloc::inuse(thread_num);\n            //\n            // return all memory being held for future use by this thread\n            thread_alloc::free_available(thread_num);\n        }\n    }\n    return ok;\n}\n}\n// END TAKEDOWN C++\n/*\n{xrst_begin multi_atomic_two_run app}\n\nRun Multi-Threaded atomic_two Calculation\n#########################################\n\nSyntax\n******\n*ok* = ``multi_atomic_two_run`` ( *y_squared* , *square_root* )\n\nThread\n******\nIt is assumed that this function is called by thread zero\nand all the other threads are blocked (waiting).\n\ny_squared\n*********\nThis argument has prototype\n\n    ``const vector<double>&`` *y_squared*\n\nand its size is equal to the number of threads.\nIt is the values that we are computing the square root of.\n\nsquare_root\n***********\nThis argument has prototype\n\n    ``vector<double>&`` *square_root*\n\nThe input value of *square_root* does not matter.\nUpon return,\nit has the same size and\nis the element by element square root of *y_squared* .\n\nok\n**\nThis return value has prototype\n\n    ``bool`` *ok*\n\nIf it is false,\n``multi_atomic_two_run`` detected an error.\n\nSource\n******\n{xrst_literal\n    // BEGIN RUN C++\n    // END RUN C++\n}\n\n{xrst_end multi_atomic_two_run}\n------------------------------------------------------------------------------\n*/\n// BEGIN RUN C++\nnamespace {\nbool multi_atomic_two_run(\n    const vector<double>& y_squared  ,\n    vector<double>&      square_root )\n{\n    bool ok = true;\n    ok     &= thread_alloc::thread_num() == 0;\n\n    // setup the work for multi-threading\n    ok &= multi_atomic_two_setup(y_squared);\n\n    // now do the work for each thread\n    if( num_threads_ > 0 )\n        team_work( multi_atomic_two_worker );\n    else\n        multi_atomic_two_worker();\n\n    // combine the result for each thread and takedown the multi-threading.\n    ok &= multi_atomic_two_takedown(square_root);\n\n    return ok;\n}\n}\n// END RUN C++\n/*\n------------------------------------------------------------------------------\n{xrst_begin multi_atomic_two_time app}\n\nTiming Test for Multi-Threaded atomic_two Calculation\n#####################################################\n\nSyntax\n******\n\n| *ok* = ``multi_atomic_two_time`` (\n| |tab| *time_out* , *test_time* , *num_threads* , *num_solve*\n| )\n\nThread\n******\nIt is assumed that this function is called by thread zero in sequential\nmode; i.e., not :ref:`in_parallel<ta_in_parallel-name>` .\n\ntime_out\n********\nThis argument has prototype\n\n    ``double&`` *time_out*\n\nIts input value of the argument does not matter.\nUpon return it is the number of wall clock seconds\nused by :ref:`multi_atomic_two_run-name` .\n\ntest_time\n*********\nThis argument has prototype\n\n    ``double`` *test_time*\n\nand is the minimum amount of wall clock time that the test should take.\nThe number of repeats for the test will be increased until this time\nis reached.\nThe reported *time_out* is the total wall clock time divided by the\nnumber of repeats.\n\nnum_threads\n***********\nThis argument has prototype\n\n    ``size_t`` *num_threads*\n\nIt specifies the number of threads that are available for this test.\nIf it is zero, the test is run without the multi-threading environment and\n\n    1 == ``thread_alloc::num_threads`` ()\n\nIf it is non-zero, the test is run with the multi-threading and\n\n    *num_threads* = ``thread_alloc::num_threads`` ()\n\nnum_solve\n*********\nThis specifies the number of square roots that will be solved for.\n\nok\n**\nThe return value has prototype\n\n    ``bool`` *ok*\n\nIf it is true,\n``harmonic_time`` passed the correctness test and\n``multi_atomic_two_time`` did not detect an error.\nOtherwise it is false.\n\n{xrst_end multi_atomic_two_time}\n*/\n\n// BEGIN TIME C++\nnamespace {\n    // values we are taking the square root of\n    vector<double> y_squared_;\n\n    // results of the square root calculations\n    vector<double> square_root_;\n    //\n    void test_once(void)\n    {   bool ok = multi_atomic_two_run(y_squared_, square_root_);\n        if( ! ok )\n        {   std::cerr << \"multi_atomic_two_run: error\" << std::endl;\n            exit(1);\n        }\n        return;\n    }\n    //\n    void test_repeat(size_t repeat)\n    {   size_t i;\n        for(i = 0; i < repeat; i++)\n            test_once();\n        return;\n    }\n}\n// This is the only routine that is accessible outside of this file\nbool multi_atomic_two_time(\n    double& time_out, double test_time, size_t num_threads, size_t num_solve\n)\n{   bool ok = true;\n    //\n    size_t initial_inuse = thread_alloc::inuse(0);\n\n    // number of threads, zero for no multi-threading\n    num_threads_ = num_threads;\n\n    // number of Newton iterations\n    num_itr_ = 20;\n\n    // values we are talking the square root of\n    y_squared_.resize(num_solve);\n    for(size_t i_solve = 0; i_solve < num_solve; i_solve++)\n        y_squared_[i_solve] = double(i_solve) + 2.0;\n\n    // must create a_square_root_ sequential mode\n    a_square_root_ = new atomic_user;\n\n    // create team of threads\n    ok &= thread_alloc::in_parallel() == false;\n    if( num_threads > 0 )\n    {   team_create(num_threads);\n        ok &= num_threads == thread_alloc::num_threads();\n    }\n    else\n    {   ok &= 1 == thread_alloc::num_threads();\n    }\n\n    // run the test case and set the time return value\n    time_out = CppAD::time_test(test_repeat, test_time);\n\n    // destroy team of threads\n    if( num_threads > 0 )\n        team_destroy();\n    ok &= thread_alloc::in_parallel() == false;\n\n    // must delete a_square_root_ in sequential mode\n    delete a_square_root_;\n\n    // free static variables in atomic_base class\n    CppAD::atomic_base<double>::clear();\n\n    // correctness check\n    ok &= square_root_.size() == num_solve;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    for(size_t i = 0; i < num_solve; i++)\n    {   double check = std::sqrt( y_squared_[i] );\n        ok          &= std::fabs( square_root_[i] / check - 1.0 ) <= eps99;\n    }\n    y_squared_.clear();\n    square_root_.clear();\n    //\n    // check that no static variables in this file are holding onto memory\n    ok &= initial_inuse == thread_alloc::inuse(0);\n    //\n    return ok;\n}\n// END TIME C++\n"
  },
  {
    "path": "example/multi_thread/multi_atomic_two.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_MULTI_THREAD_MULTI_ATOMIC_TWO_HPP\n# define CPPAD_EXAMPLE_MULTI_THREAD_MULTI_ATOMIC_TWO_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\nbool multi_atomic_two_time(\n    double& time_out, double test_time, size_t num_threads, size_t num_solve\n);\n\n# endif\n"
  },
  {
    "path": "example/multi_thread/multi_atomic_two.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin multi_atomic_two.cpp app}\n\nMulti-Threading atomic_two Example / Test\n#########################################\n\nDeprecated 2019-08-05\n*********************\nThis example is deprecated, use :ref:`multi_atomic_three.cpp-name` instead.\n\nSource File\n***********\nAll of the routines below are located in the file\n::\n\n    example/multi_thread/multi_atomic_two.cpp\n\nContents\n********\n{xrst_toc_table\n    example/multi_thread/multi_atomic_two.cpp\n}\n\n{xrst_end multi_atomic_two.cpp}\n"
  },
  {
    "path": "example/multi_thread/multi_chkpoint_one.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin multi_chkpoint_one_algo app}\n\nchkpoint_one Algorithm that Computes Square Root\n################################################\n\nSyntax\n******\n| *checkpoint_algo* ( *au* , *ay* )\n\nPurpose\n*******\nThis algorithm computes a square root using Newton's method.\nIt is meant to be very inefficient in order to demonstrate timing results.\n\nau\n**\nThis argument has prototype\n\n    ``const`` *ADvector* & *au*\n\nwhere *ADvector* is a\n:ref:`simple vector class<SimpleVector-name>` with elements\nof type ``AD<double>`` .\nThe size of *au* is three.\n\ny_initial\n=========\nWe use the notation\n\n    *y_initial* = *au* [0]\n\nfor the initial value of the Newton iterate.\n\ny_squared\n=========\nWe use the notation\n\n    *y_squared* = *au* [1]\n\nfor the value we are taking the square root of.\n\nay\n**\nThis argument has prototype\n\n    *ADvector* & *ay*\n\nThe size of *ay* is one and\n*ay* [0] is the square root of *y_squared* .\n\nSource\n******\n{xrst_literal\n    // BEGIN ALGO C++\n    // END ALGO C++\n}\n\n{xrst_end multi_chkpoint_one_algo}\n*/\n// BEGIN ALGO C++\n// includes used by all source code in multi_chkpoint_one.cpp file\n# include <cppad/cppad.hpp>\n# include \"multi_chkpoint_one.hpp\"\n# include \"team_thread.hpp\"\n//\nnamespace {\n    using CppAD::thread_alloc; // fast multi-threading memory allocator\n    using CppAD::vector;       // uses thread_alloc\n    //\n    typedef CppAD::AD<double> a_double;\n\n    void checkpoint_algo(const vector<a_double>& au , vector<a_double>& ay)\n    {\n        // extract components of argument vector\n        a_double y_initial  = au[0];\n        a_double y_squared  = au[1];\n\n        // Use Newton's method to solve f(y) = y^2 = y_squared\n        a_double y_itr = y_initial;\n        for(size_t itr = 0; itr < 20; itr++)\n        {  // solve (y - y_itr) * f'(y_itr) = y_squared - y_itr^2\n            a_double fp_itr = 2.0 * y_itr;\n            y_itr           = y_itr + (y_squared - y_itr * y_itr) / fp_itr;\n        }\n\n        // return the Newton approximation for f(y) = y_squared\n        ay[0] = y_itr;\n    }\n}\n// END ALGO C++\n\n/*\n{xrst_begin multi_chkpoint_one_common app}\n\nMulti-Threaded chkpoint_one Common Information\n##############################################\n\nPurpose\n*******\nThis source code defines the common variables that are used by\nthe ``multi_chkpoint_one_`` *name* functions.\n\nSource\n******\n{xrst_literal\n    // BEGIN COMMON C++\n    // END COMMON C++\n}\n\n{xrst_end multi_chkpoint_one_common}\n*/\n// BEGIN COMMON C++\nnamespace {\n    // Number of threads, set by multi_chkpoint_one_time\n    // (zero means one thread with no multi-threading setup)\n    size_t num_threads_ = 0;\n\n    // We can use one checkpoint function for all threads because\n    // there is no member data that gets changed during worker call.\n    // This needs to stay in scope for as long as a recording will use it.\n    // We cannot be in parallel mode when this object is created or deleted.\n    // We use a pointer so that there is no left over memory in thread zero.\n    CppAD::checkpoint<double>* a_square_root_ = nullptr;\n\n    // structure with information for one thread\n    typedef struct {\n        // used by worker to compute the square root,\n        // set by multi_chkpoint_one_setup\n        CppAD::ADFun<double>* fun;\n        //\n        // value we are computing square root of, set by multi_chkpoint_one_setup\n        vector<double>* y_squared;\n        //\n        // square root, set by worker\n        vector<double>* square_root;\n        //\n        // false if an error occurs, true otherwise, set by worker\n        bool ok;\n    } work_one_t;\n    //\n    // Vector with information for all threads\n    // (uses pointers instead of values to avoid false sharing)\n    // allocated by multi_chkpoint_one_setup, freed by multi_chkpoint_one_takedown\n    work_one_t* work_all_[CPPAD_MAX_NUM_THREADS];\n}\n// END COMMON C++\n/*\n-------------------------------------------------------------------------------\n{xrst_begin multi_chkpoint_one_setup app}\n\nMulti-Threaded chkpoint_one Set Up\n##################################\n\nSyntax\n******\n*ok* = ``multi_chkpoint_one_setup`` ( *y_squared* )\n\nPurpose\n*******\nThis routine splits up the computation into the individual threads.\n\nThread\n******\nIt is assumed that this function is called by thread zero\nand all the other threads are blocked (waiting).\n\ny_squared\n*********\nThis argument has prototype\n\n    ``const vector<double>&`` *y_squared*\n\nand its size is equal to the number of equations to solve.\nIt is the values that we are computing the square root of.\n\nok\n**\nThis return value has prototype\n\n    ``bool`` *ok*\n\nIf it is false,\n``multi_chkpoint_one_setup`` detected an error.\n\nSource\n******\n{xrst_literal\n    // BEGIN SETUP C++\n    // END SETUP C++\n}\n\n{xrst_end multi_chkpoint_one_setup}\n*/\n// BEGIN SETUP C++\nnamespace {\nbool multi_chkpoint_one_setup(const vector<double>& y_squared)\n{  size_t num_threads = std::max(num_threads_, size_t(1));\n    bool   ok          = num_threads == thread_alloc::num_threads();\n    ok                &= thread_alloc::thread_num() == 0;\n    //\n    // declare independent variable variable vector\n    vector<a_double> ax(1);\n    ax[0] = 2.0;\n    CppAD::Independent(ax);\n    //\n    // argument and result for checkpoint algorithm\n    vector<a_double> au(2), ay(1);\n    au[0] = ax[0];                  // y_initial\n    au[1] = ax[0];                  // y_squared\n\n    // put user checkpoint function in recording\n    (*a_square_root_)(au, ay);\n\n    // f(u) = sqrt(u)\n    CppAD::ADFun<double> fun(ax, ay);\n    //\n    // number of square roots for each thread\n    size_t per_thread = (y_squared.size() + num_threads - 1) / num_threads;\n    size_t y_index    = 0;\n    //\n    for(size_t thread_num = 0; thread_num < num_threads; thread_num++)\n    {  // allocate separate memory for each thread to avoid false sharing\n        size_t min_bytes(sizeof(work_one_t)), cap_bytes;\n        void* v_ptr = thread_alloc::get_memory(min_bytes, cap_bytes);\n        work_all_[thread_num] = static_cast<work_one_t*>(v_ptr);\n        //\n        // Run constructor on work_all_[thread_num]->fun\n        work_all_[thread_num]->fun = new CppAD::ADFun<double>;\n        //\n        // Run constructor on work_all_[thread_num] vectors\n        work_all_[thread_num]->y_squared = new vector<double>;\n        work_all_[thread_num]->square_root = new vector<double>;\n        //\n        // Each worker gets a separate copy of fun. This is necessary because\n        // the Taylor coefficients will be set by each thread.\n        *(work_all_[thread_num]->fun) = fun;\n        //\n        // values we are computing square root of for this thread\n        ok &=  0 == work_all_[thread_num]->y_squared->size();\n        for(size_t i = 0; i < per_thread; i++)\n        if( y_index < y_squared.size() )\n            work_all_[thread_num]->y_squared->push_back(y_squared[y_index++]);\n        //\n        // set to false in case this thread's worker does not get called\n        work_all_[thread_num]->ok = false;\n    }\n    ok &= y_index == y_squared.size();\n    //\n    return ok;\n}\n}\n// END SETUP C++\n/*\n------------------------------------------------------------------------------\n{xrst_begin multi_chkpoint_one_worker app}\n\nMulti-Threaded chkpoint_one Worker\n##################################\n\nPurpose\n*******\nThis routine does the computation for one thread.\n\nSource\n******\n{xrst_literal\n    // BEGIN WORKER C++\n    // END WORKER C++\n}\n\n{xrst_end multi_chkpoint_one_worker}\n*/\n// BEGIN WORKER C++\nnamespace {\nvoid multi_chkpoint_one_worker(void)\n{  size_t thread_num  = thread_alloc::thread_num();\n    size_t num_threads = std::max(num_threads_, size_t(1));\n    bool   ok          = thread_num < num_threads;\n    //\n    vector<double> x(1), y(1);\n    size_t n = work_all_[thread_num]->y_squared->size();\n    work_all_[thread_num]->square_root->resize(n);\n    for(size_t i = 0; i < n; i++)\n    {  x[0] = (* work_all_[thread_num]->y_squared )[i];\n        y    = work_all_[thread_num]->fun->Forward(0, x);\n        //\n        (* work_all_[thread_num]->square_root )[i] = y[0];\n    }\n    work_all_[thread_num]->ok             = ok;\n}\n}\n// END WORKER C++\n/*\n------------------------------------------------------------------------------\n{xrst_begin multi_chkpoint_one_takedown app}\n\nMulti-Threaded chkpoint_one Take Down\n#####################################\n\nSyntax\n******\n*ok* = ``multi_chkpoint_one_takedown`` ( *square_root* )\n\nPurpose\n*******\nThis routine gathers up the results for each thread and\nfrees memory that was allocated by :ref:`multi_chkpoint_one_setup-name` .\n\nThread\n******\nIt is assumed that this function is called by thread zero\nand all the other threads are blocked (waiting).\n\nsquare_root\n***********\nThis argument has prototype\n\n    ``vector<double>&`` *square_root*\n\nThe input value of *square_root* does not matter.\nUpon return,\nit has the same size and is the element by element square root of\n:ref:`multi_chkpoint_one_setup@y_squared` .\n\nok\n**\nThis return value has prototype\n\n    ``bool`` *ok*\n\nIf it is false,\n``multi_chkpoint_one_takedown`` detected an error.\n\nSource\n******\n{xrst_literal\n    // BEGIN TAKEDOWN C++\n    // END TAKEDOWN C++\n}\n\n{xrst_end multi_chkpoint_one_takedown}\n*/\n// BEGIN TAKEDOWN C++\nnamespace {\nbool multi_chkpoint_one_takedown(vector<double>& square_root)\n{  bool ok            = true;\n    ok                &= thread_alloc::thread_num() == 0;\n    size_t num_threads = std::max(num_threads_, size_t(1));\n    //\n    // extract square roots in original order\n    square_root.resize(0);\n    for(size_t thread_num = 0; thread_num < num_threads; thread_num++)\n    {  // results for this thread\n        size_t n = work_all_[thread_num]->square_root->size();\n        for(size_t i = 0; i < n; i++)\n            square_root.push_back((* work_all_[thread_num]->square_root )[i]);\n    }\n    //\n    // go down so that free memory for other threads before memory for master\n    size_t thread_num = num_threads;\n    while(thread_num--)\n    {  // check that this tread was ok with the work it did\n        ok  &= work_all_[thread_num]->ok;\n        //\n        // run destructor on vector object for this thread\n        delete work_all_[thread_num]->y_squared;\n        delete work_all_[thread_num]->square_root;\n        //\n        // run destructor on function object for this thread\n        delete work_all_[thread_num]->fun;\n        //\n        // delete problem specific information\n        void* v_ptr = static_cast<void*>( work_all_[thread_num] );\n        thread_alloc::return_memory( v_ptr );\n        //\n        // Note that checkpoint object has memory connect to each thread\n        // thread_alloc::inuse(thread_num) cannot be zero until it is deleted\n        if( thread_num > 0 )\n        {  ok &= thread_alloc::inuse(thread_num) > 0;\n            //\n            // return all memory that is not in use and\n            // but being held for future use by this thread\n            thread_alloc::free_available(thread_num);\n        }\n    }\n    return ok;\n}\n}\n// END TAKEDOWN C++\n/*\n{xrst_begin multi_chkpoint_one_run app}\n\nRun Multi-Threaded chkpoint_one Calculation\n###########################################\n\nSyntax\n******\n*ok* = ``multi_chkpoint_one_run`` ( *y_squared* , *square_root* )\n\nThread\n******\nIt is assumed that this function is called by thread zero\nand all the other threads are blocked (waiting).\n\ny_squared\n*********\nThis argument has prototype\n\n    ``const vector<double>&`` *y_squared*\n\nand its size is equal to the number of threads.\nIt is the values that we are computing the square root of.\n\nsquare_root\n***********\nThis argument has prototype\n\n    ``vector<double>&`` *square_root*\n\nThe input value of *square_root* does not matter.\nUpon return,\nit has the same size and\nis the element by element square root of *y_squared* .\n\nok\n**\nThis return value has prototype\n\n    ``bool`` *ok*\n\nIf it is false,\n``multi_chkpoint_one_run`` detected an error.\n\nSource\n******\n{xrst_literal\n    // BEGIN RUN C++\n    // END RUN C++\n}\n\n{xrst_end multi_chkpoint_one_run}\n------------------------------------------------------------------------------\n*/\n// BEGIN RUN C++\nnamespace {\nbool multi_chkpoint_one_run(\n    const vector<double>& y_squared  ,\n    vector<double>&      square_root )\n{\n    bool ok = true;\n    ok     &= thread_alloc::thread_num() == 0;\n\n    // setup the work for multi-threading\n    ok &= multi_chkpoint_one_setup(y_squared);\n\n    // now do the work for each thread\n    if( num_threads_ > 0 )\n        team_work( multi_chkpoint_one_worker );\n    else\n        multi_chkpoint_one_worker();\n\n    // combine the result for each thread and takedown the multi-threading.\n    ok &= multi_chkpoint_one_takedown(square_root);\n\n    return ok;\n}\n}\n// END RUN C++\n/*\n------------------------------------------------------------------------------\n{xrst_begin multi_chkpoint_one_time app}\n\nTiming Test for Multi-Threaded chkpoint_one Calculation\n#######################################################\n\nSyntax\n******\n\n| *ok* = ``multi_chkpoint_one_time`` (\n| |tab| *time_out* , *test_time* , *num_threads* , *num_solve*\n| )\n\nThread\n******\nIt is assumed that this function is called by thread zero in sequential\nmode; i.e., not :ref:`in_parallel<ta_in_parallel-name>` .\n\ntime_out\n********\nThis argument has prototype\n\n    ``double&`` *time_out*\n\nIts input value of the argument does not matter.\nUpon return it is the number of wall clock seconds\nused by :ref:`multi_chkpoint_one_run-name` .\n\ntest_time\n*********\nThis argument has prototype\n\n    ``double`` *test_time*\n\nand is the minimum amount of wall clock time that the test should take.\nThe number of repeats for the test will be increased until this time\nis reached.\nThe reported *time_out* is the total wall clock time divided by the\nnumber of repeats.\n\nnum_threads\n***********\nThis argument has prototype\n\n    ``size_t`` *num_threads*\n\nIt specifies the number of threads that are available for this test.\nIf it is zero, the test is run without the multi-threading environment and\n\n    1 == ``thread_alloc::num_threads`` ()\n\nIf it is non-zero, the test is run with the multi-threading and\n\n    *num_threads* = ``thread_alloc::num_threads`` ()\n\nnum_solve\n*********\nThis specifies the number of square roots that will be solved for.\n\nok\n**\nThe return value has prototype\n\n    ``bool`` *ok*\n\nIf it is true,\n``harmonic_time`` passed the correctness test and\n``multi_chkpoint_one_time`` did not detect an error.\nOtherwise it is false.\n\n{xrst_end multi_chkpoint_one_time}\n*/\n\n// BEGIN TIME C++\nnamespace {\n    // values we are taking the square root of\n    vector<double> y_squared_;\n\n    // results of the square root calculations\n    vector<double> square_root_;\n    //\n    void test_once(void)\n    {   bool ok = multi_chkpoint_one_run(y_squared_, square_root_);\n        if( ! ok )\n        {   std::cerr << \"multi_chkpoint_one_run: error\" << std::endl;\n            exit(1);\n        }\n        return;\n    }\n    //\n    void test_repeat(size_t repeat)\n    {   size_t i;\n        for(i = 0; i < repeat; i++)\n            test_once();\n        return;\n    }\n}\n// This is the only routine that is accessible outside of this file\nbool multi_chkpoint_one_time(\n    double& time_out, double test_time, size_t num_threads, size_t num_solve\n)\n{   bool ok = true;\n    //\n    size_t initial_inuse = thread_alloc::inuse(0);\n\n    // number of threads, zero for no multi-threading\n    num_threads_ = num_threads;\n\n    // values we are talking the square root of\n    y_squared_.resize(num_solve);\n    for(size_t i_solve = 0; i_solve < num_solve; i_solve++)\n        y_squared_[i_solve] = double(i_solve) + 2.0;\n\n    // must create a_square_root_ in sequential mode\n    vector<a_double> au(2), ay(1);\n    au[0] = 2.0;\n    au[1] = 2.0;\n    a_square_root_ = new CppAD::checkpoint<double>(\n        \"square_root\", checkpoint_algo, au, ay\n    );\n\n    // create team of threads\n    ok &= thread_alloc::in_parallel() == false;\n    if( num_threads > 0 )\n    {   team_create(num_threads);\n        ok &= num_threads == thread_alloc::num_threads();\n    }\n    else\n    {   ok &= 1 == thread_alloc::num_threads();\n    }\n\n    // run the test case and set the time return value\n    time_out = CppAD::time_test(test_repeat, test_time);\n\n    // destroy team of threads\n    if( num_threads > 0 )\n        team_destroy();\n    ok &= thread_alloc::in_parallel() == false;\n\n    // must delete a_square_root_ in sequential mode\n    delete a_square_root_;\n\n    // free static variables in atomic_base class\n    CppAD::atomic_base<double>::clear();\n\n    // correctness check\n    ok &= square_root_.size() == num_solve;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    for(size_t i = 0; i < num_solve; i++)\n    {   double check = std::sqrt( y_squared_[i] );\n        ok          &= std::fabs( square_root_[i] / check - 1.0 ) <= eps99;\n    }\n    //\n    // free memory in CppAD vectors that are still in scope\n    y_squared_.clear();\n    square_root_.clear();\n    au.clear();\n    ay.clear();\n    //\n    // check that no static variables in this file are holding onto memory\n    ok &= initial_inuse == thread_alloc::inuse(0);\n    //\n    return ok;\n}\n// END TIME C++\n"
  },
  {
    "path": "example/multi_thread/multi_chkpoint_one.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_MULTI_THREAD_MULTI_CHKPOINT_ONE_HPP\n# define CPPAD_EXAMPLE_MULTI_THREAD_MULTI_CHKPOINT_ONE_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\nbool multi_chkpoint_one_time(\n    double& time_out, double test_time, size_t num_threads, size_t num_solve\n);\n\n# endif\n"
  },
  {
    "path": "example/multi_thread/multi_chkpoint_one.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin multi_chkpoint_one.cpp app}\n\nMulti-Threading chkpoint_one Example / Test\n###########################################\n\nDeprecated 2019-08-06\n*********************\nThe example has been deprecated, use :ref:`multi_chkpoint_two.cpp-name` instead.\n\nSource File\n***********\nAll of the routines below are located in the file\n::\n\n    example/multi_thread/multi_chkpoint_one.cpp\n\nContents\n********\n{xrst_toc_table\n    example/multi_thread/multi_chkpoint_one.cpp\n}\n\n{xrst_end multi_chkpoint_one.cpp}\n"
  },
  {
    "path": "example/multi_thread/multi_chkpoint_two.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin multi_chkpoint_two_algo}\n\nchkpoint_two Algorithm that Computes Square Root\n################################################\n\nSyntax\n******\n| *checkpoint_algo* ( *au* , *ay* )\n\nPurpose\n*******\nThis algorithm computes a square root using Newton's method.\nIt is meant to be very inefficient in order to demonstrate timing results.\n\nau\n**\nThis argument has prototype\n\n    ``const`` *ADvector* & *au*\n\nwhere *ADvector* is a\n:ref:`simple vector class<SimpleVector-name>` with elements\nof type ``AD<double>`` .\nThe size of *au* is three.\n\ny_initial\n=========\nWe use the notation\n\n    *y_initial* = *au* [0]\n\nfor the initial value of the Newton iterate.\n\ny_squared\n=========\nWe use the notation\n\n    *y_squared* = *au* [1]\n\nfor the value we are taking the square root of.\n\nay\n**\nThis argument has prototype\n\n    *ADvector* & *ay*\n\nThe size of *ay* is one and\n*ay* [0] is the square root of *y_squared* .\n\nSource\n******\n{xrst_literal\n    // BEGIN ALGO C++\n    // END ALGO C++\n}\n\n{xrst_end multi_chkpoint_two_algo}\n*/\n// BEGIN ALGO C++\n// includes used by all source code in multi_chkpoint_two.cpp file\n# include <cppad/cppad.hpp>\n# include \"multi_chkpoint_two.hpp\"\n# include \"team_thread.hpp\"\n//\nnamespace {\n    using CppAD::thread_alloc; // fast multi-threading memory allocator\n    using CppAD::vector;       // uses thread_alloc\n    //\n    typedef CppAD::AD<double> a_double;\n\n    void checkpoint_algo(const vector<a_double>& au , vector<a_double>& ay)\n    {\n        // extract components of argument vector\n        a_double y_initial  = au[0];\n        a_double y_squared  = au[1];\n\n        // Use Newton's method to solve f(y) = y^2 = y_squared\n        a_double y_itr = y_initial;\n        for(size_t itr = 0; itr < 20; itr++)\n        {  // solve (y - y_itr) * f'(y_itr) = y_squared - y_itr^2\n            a_double fp_itr = 2.0 * y_itr;\n            y_itr           = y_itr + (y_squared - y_itr * y_itr) / fp_itr;\n        }\n\n        // return the Newton approximation for f(y) = y_squared\n        ay[0] = y_itr;\n    }\n}\n// END ALGO C++\n\n/*\n{xrst_begin multi_chkpoint_two_common}\n\nMulti-Threaded chkpoint_two Common Information\n##############################################\n\nPurpose\n*******\nThis source code defines the common variables that are used by\nthe ``multi_chkpoint_two_`` *name* functions.\n\nSource\n******\n{xrst_literal\n    // BEGIN COMMON C++\n    // END COMMON C++\n}\n\n{xrst_end multi_chkpoint_two_common}\n*/\n// BEGIN COMMON C++\nnamespace {\n    // Number of threads, set by multi_chkpoint_two_time\n    // (zero means one thread with no multi-threading setup)\n    size_t num_threads_ = 0;\n\n    // We can use one checkpoint function for all threads because\n    // there is no member data that gets changed during worker call.\n    // This needs to stay in scope for as long as a recording will use it.\n    // We cannot be in parallel mode when this object is created or deleted.\n    // We use a pointer so that there is no left over memory in thread zero.\n    CppAD::chkpoint_two<double>* a_square_root_ = nullptr;\n\n    // structure with information for one thread\n    typedef struct {\n        // used by worker to compute the square root,\n        // set by multi_chkpoint_two_setup\n        CppAD::ADFun<double>* fun;\n        //\n        // value we are computing square root of, set by multi_chkpoint_two_setup\n        vector<double>* y_squared;\n        //\n        // square root, set by worker\n        vector<double>* square_root;\n        //\n        // false if an error occurs, true otherwise, set by worker\n        bool ok;\n    } work_one_t;\n    //\n    // Vector with information for all threads\n    // (uses pointers instead of values to avoid false sharing)\n    // allocated by multi_chkpoint_two_setup, freed by multi_chkpoint_two_takedown\n    work_one_t* work_all_[CPPAD_MAX_NUM_THREADS];\n}\n// END COMMON C++\n/*\n-------------------------------------------------------------------------------\n{xrst_begin multi_chkpoint_two_setup}\n\nMulti-Threaded chkpoint_two Set Up\n##################################\n\nSyntax\n******\n*ok* = ``multi_chkpoint_two_setup`` ( *y_squared* )\n\nPurpose\n*******\nThis routine splits up the computation into the individual threads.\n\nThread\n******\nIt is assumed that this function is called by thread zero\nand all the other threads are blocked (waiting).\n\ny_squared\n*********\nThis argument has prototype\n\n    ``const vector<double>&`` *y_squared*\n\nand its size is equal to the number of equations to solve.\nIt is the values that we are computing the square root of.\n\nok\n**\nThis return value has prototype\n\n    ``bool`` *ok*\n\nIf it is false,\n``multi_chkpoint_two_setup`` detected an error.\n\nSource\n******\n{xrst_literal\n    // BEGIN SETUP C++\n    // END SETUP C++\n}\n\n{xrst_end multi_chkpoint_two_setup}\n*/\n// BEGIN SETUP C++\nnamespace {\nbool multi_chkpoint_two_setup(const vector<double>& y_squared)\n{  size_t num_threads = std::max(num_threads_, size_t(1));\n    bool   ok          = num_threads == thread_alloc::num_threads();\n    ok                &= thread_alloc::thread_num() == 0;\n    //\n    // declare independent variable variable vector\n    vector<a_double> ax(1);\n    ax[0] = 2.0;\n    CppAD::Independent(ax);\n    //\n    // argument and result for checkpoint algorithm\n    vector<a_double> au(2), ay(1);\n    au[0] = ax[0];                  // y_initial\n    au[1] = ax[0];                  // y_squared\n\n    // put user checkpoint function in recording\n    (*a_square_root_)(au, ay);\n\n    // f(u) = sqrt(u)\n    CppAD::ADFun<double> fun(ax, ay);\n    //\n    // number of square roots for each thread\n    size_t per_thread = (y_squared.size() + num_threads - 1) / num_threads;\n    size_t y_index    = 0;\n    //\n    for(size_t thread_num = 0; thread_num < num_threads; thread_num++)\n    {  // allocate separate memory for each thread to avoid false sharing\n        size_t min_bytes(sizeof(work_one_t)), cap_bytes;\n        void* v_ptr = thread_alloc::get_memory(min_bytes, cap_bytes);\n        work_all_[thread_num] = static_cast<work_one_t*>(v_ptr);\n        //\n        // Run constructor on work_all_[thread_num]->fun\n        work_all_[thread_num]->fun = new CppAD::ADFun<double>;\n        //\n        // Run constructor on work_all_[thread_num] vectors\n        work_all_[thread_num]->y_squared = new vector<double>;\n        work_all_[thread_num]->square_root = new vector<double>;\n        //\n        // Each worker gets a separate copy of fun. This is necessary because\n        // the Taylor coefficients will be set by each thread.\n        *(work_all_[thread_num]->fun) = fun;\n        //\n        // values we are computing square root of for this thread\n        ok &=  0 == work_all_[thread_num]->y_squared->size();\n        for(size_t i = 0; i < per_thread; i++)\n        if( y_index < y_squared.size() )\n            work_all_[thread_num]->y_squared->push_back(y_squared[y_index++]);\n        //\n        // set to false in case this thread's worker does not get called\n        work_all_[thread_num]->ok = false;\n    }\n    ok &= y_index == y_squared.size();\n    //\n    return ok;\n}\n}\n// END SETUP C++\n/*\n------------------------------------------------------------------------------\n{xrst_begin multi_chkpoint_two_worker}\n\nMulti-Threaded chkpoint_two Worker\n##################################\n\nPurpose\n*******\nThis routine does the computation for one thread.\n\nSource\n******\n{xrst_literal\n    // BEGIN WORKER C++\n    // END WORKER C++\n}\n\n{xrst_end multi_chkpoint_two_worker}\n*/\n// BEGIN WORKER C++\nnamespace {\nvoid multi_chkpoint_two_worker(void)\n{  size_t thread_num  = thread_alloc::thread_num();\n    size_t num_threads = std::max(num_threads_, size_t(1));\n    bool   ok          = thread_num < num_threads;\n    //\n    vector<double> x(1), y(1);\n    size_t n = work_all_[thread_num]->y_squared->size();\n    work_all_[thread_num]->square_root->resize(n);\n    for(size_t i = 0; i < n; i++)\n    {  x[0] = (* work_all_[thread_num]->y_squared )[i];\n        y    = work_all_[thread_num]->fun->Forward(0, x);\n        //\n        (* work_all_[thread_num]->square_root )[i] = y[0];\n    }\n    work_all_[thread_num]->ok             = ok;\n}\n}\n// END WORKER C++\n/*\n------------------------------------------------------------------------------\n{xrst_begin multi_chkpoint_two_takedown}\n\nMulti-Threaded chkpoint_two Take Down\n#####################################\n\nSyntax\n******\n*ok* = ``multi_chkpoint_two_takedown`` ( *square_root* )\n\nPurpose\n*******\nThis routine gathers up the results for each thread and\nfrees memory that was allocated by :ref:`multi_chkpoint_two_setup-name` .\n\nThread\n******\nIt is assumed that this function is called by thread zero\nand all the other threads are blocked (waiting).\n\nsquare_root\n***********\nThis argument has prototype\n\n    ``vector<double>&`` *square_root*\n\nThe input value of *square_root* does not matter.\nUpon return,\nit has the same size and is the element by element square root of\n:ref:`multi_chkpoint_two_setup@y_squared` .\n\nok\n**\nThis return value has prototype\n\n    ``bool`` *ok*\n\nIf it is false,\n``multi_chkpoint_two_takedown`` detected an error.\n\nSource\n******\n{xrst_literal\n    // BEGIN TAKEDOWN C++\n    // END TAKEDOWN C++\n}\n\n{xrst_end multi_chkpoint_two_takedown}\n*/\n// BEGIN TAKEDOWN C++\nnamespace {\nbool multi_chkpoint_two_takedown(vector<double>& square_root)\n{  bool ok            = true;\n    ok                &= thread_alloc::thread_num() == 0;\n    size_t num_threads = std::max(num_threads_, size_t(1));\n    //\n    // extract square roots in original order\n    square_root.resize(0);\n    for(size_t thread_num = 0; thread_num < num_threads; thread_num++)\n    {  // results for this thread\n        size_t n = work_all_[thread_num]->square_root->size();\n        for(size_t i = 0; i < n; i++)\n            square_root.push_back((* work_all_[thread_num]->square_root )[i]);\n    }\n    //\n    // go down so that free memory for other threads before memory for master\n    size_t thread_num = num_threads;\n    while(thread_num--)\n    {  // check that this tread was ok with the work it did\n        ok  &= work_all_[thread_num]->ok;\n        //\n        // run destructor on vector object for this thread\n        delete work_all_[thread_num]->y_squared;\n        delete work_all_[thread_num]->square_root;\n        //\n        // run destructor on function object for this thread\n        delete work_all_[thread_num]->fun;\n        //\n        // delete problem specific information\n        void* v_ptr = static_cast<void*>( work_all_[thread_num] );\n        thread_alloc::return_memory( v_ptr );\n        //\n        // Note that checkpoint object has memory connect to each thread\n        // thread_alloc::inuse(thread_num) cannot be zero until it is deleted\n        if( thread_num > 0 )\n        {  ok &= thread_alloc::inuse(thread_num) > 0;\n            //\n            // return all memory that is not in use and\n            // but being held for future use by this thread\n            thread_alloc::free_available(thread_num);\n        }\n    }\n    return ok;\n}\n}\n// END TAKEDOWN C++\n/*\n{xrst_begin multi_chkpoint_two_run}\n\nRun Multi-Threaded chkpoint_two Calculation\n###########################################\n\nSyntax\n******\n*ok* = ``multi_chkpoint_two_run`` ( *y_squared* , *square_root* )\n\nThread\n******\nIt is assumed that this function is called by thread zero\nand all the other threads are blocked (waiting).\n\ny_squared\n*********\nThis argument has prototype\n\n    ``const vector<double>&`` *y_squared*\n\nand its size is equal to the number of threads.\nIt is the values that we are computing the square root of.\n\nsquare_root\n***********\nThis argument has prototype\n\n    ``vector<double>&`` *square_root*\n\nThe input value of *square_root* does not matter.\nUpon return,\nit has the same size and\nis the element by element square root of *y_squared* .\n\nok\n**\nThis return value has prototype\n\n    ``bool`` *ok*\n\nIf it is false,\n``multi_chkpoint_two_run`` detected an error.\n\nSource\n******\n{xrst_literal\n    // BEGIN RUN C++\n    // END RUN C++\n}\n\n{xrst_end multi_chkpoint_two_run}\n------------------------------------------------------------------------------\n*/\n// BEGIN RUN C++\nnamespace {\nbool multi_chkpoint_two_run(\n    const vector<double>& y_squared  ,\n    vector<double>&      square_root )\n{\n    bool ok = true;\n    ok     &= thread_alloc::thread_num() == 0;\n\n    // setup the work for multi-threading\n    ok &= multi_chkpoint_two_setup(y_squared);\n\n    // now do the work for each thread\n    if( num_threads_ > 0 )\n        team_work( multi_chkpoint_two_worker );\n    else\n        multi_chkpoint_two_worker();\n\n    // combine the result for each thread and takedown the multi-threading.\n    ok &= multi_chkpoint_two_takedown(square_root);\n\n    return ok;\n}\n}\n// END RUN C++\n/*\n------------------------------------------------------------------------------\n{xrst_begin multi_chkpoint_two_time}\n\nTiming Test for Multi-Threaded chkpoint_two Calculation\n#######################################################\n\nSyntax\n******\n\n| *ok* = ``multi_chkpoint_two_time`` (\n| |tab| *time_out* , *test_time* , *num_threads* , *num_solve*\n| )\n\nThread\n******\nIt is assumed that this function is called by thread zero in sequential\nmode; i.e., not :ref:`in_parallel<ta_in_parallel-name>` .\n\ntime_out\n********\nThis argument has prototype\n\n    ``double&`` *time_out*\n\nIts input value of the argument does not matter.\nUpon return it is the number of wall clock seconds\nused by :ref:`multi_chkpoint_two_run-name` .\n\ntest_time\n*********\nThis argument has prototype\n\n    ``double`` *test_time*\n\nand is the minimum amount of wall clock time that the test should take.\nThe number of repeats for the test will be increased until this time\nis reached.\nThe reported *time_out* is the total wall clock time divided by the\nnumber of repeats.\n\nnum_threads\n***********\nThis argument has prototype\n\n    ``size_t`` *num_threads*\n\nIt specifies the number of threads that are available for this test.\nIf it is zero, the test is run without the multi-threading environment and\n\n    1 == ``thread_alloc::num_threads`` ()\n\nIf it is non-zero, the test is run with the multi-threading and\n\n    *num_threads* = ``thread_alloc::num_threads`` ()\n\nnum_solve\n*********\nThis specifies the number of square roots that will be solved for.\n\nok\n**\nThe return value has prototype\n\n    ``bool`` *ok*\n\nIf it is true,\n``harmonic_time`` passed the correctness test and\n``multi_chkpoint_two_time`` did not detect an error.\nOtherwise it is false.\n\n{xrst_end multi_chkpoint_two_time}\n*/\n\n// BEGIN TIME C++\nnamespace {\n    // values we are taking the square root of\n    vector<double> y_squared_;\n\n    // results of the square root calculations\n    vector<double> square_root_;\n    //\n    void test_once(void)\n    {   bool ok = multi_chkpoint_two_run(y_squared_, square_root_);\n        if( ! ok )\n        {   std::cerr << \"multi_chkpoint_two_run: error\" << std::endl;\n            exit(1);\n        }\n        return;\n    }\n    //\n    void test_repeat(size_t repeat)\n    {   size_t i;\n        for(i = 0; i < repeat; i++)\n            test_once();\n        return;\n    }\n}\n// This is the only routine that is accessible outside of this file\nbool multi_chkpoint_two_time(\n    double& time_out, double test_time, size_t num_threads, size_t num_solve\n)\n{   bool ok = true;\n    //\n    size_t initial_inuse = thread_alloc::inuse(0);\n\n    // number of threads, zero for no multi-threading\n    num_threads_ = num_threads;\n\n    // values we are talking the square root of\n    y_squared_.resize(num_solve);\n    for(size_t i_solve = 0; i_solve < num_solve; i_solve++)\n        y_squared_[i_solve] = double(i_solve) + 2.0;\n\n    // create a_square_root_ in sequential mode\n    {   // create corresponding ADFun inside block so it gets destroyed\n        // and does not have thread_alloc memory inuse at the end\n        vector<a_double> au(2), ay(1);\n        au[0] = 2.0;\n        au[1] = 2.0;\n        CppAD::Independent(au);\n        checkpoint_algo(au, ay);\n        CppAD::ADFun<double> fun(au, ay);\n        //\n        // create chkpoint_two version of algorithm\n        const char* name      = \"square_root\";\n        bool internal_bool    = false;\n        bool use_hes_sparsity = false;\n        bool use_base2ad      = false;\n        bool use_in_parallel  = true;\n        a_square_root_ = new CppAD::chkpoint_two<double>( fun, name,\n            internal_bool, use_hes_sparsity, use_base2ad, use_in_parallel\n        );\n    }\n\n    // create team of threads\n    ok &= thread_alloc::in_parallel() == false;\n    if( num_threads > 0 )\n    {   team_create(num_threads);\n        ok &= num_threads == thread_alloc::num_threads();\n    }\n    else\n    {   ok &= 1 == thread_alloc::num_threads();\n    }\n\n    // run the test case and set the time return value\n    time_out = CppAD::time_test(test_repeat, test_time);\n\n    // destroy team of threads\n    if( num_threads > 0 )\n        team_destroy();\n    ok &= thread_alloc::in_parallel() == false;\n\n    // must delete a_square_root_ in sequential mode\n    delete a_square_root_;\n\n    // correctness check\n    ok &= square_root_.size() == num_solve;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    for(size_t i = 0; i < num_solve; i++)\n    {   double check = std::sqrt( y_squared_[i] );\n        ok          &= std::fabs( square_root_[i] / check - 1.0 ) <= eps99;\n    }\n    //\n    // free memory in CppAD vectors that are still in scope\n    y_squared_.clear();\n    square_root_.clear();\n    //\n    // check that no static variables in this file are holding onto memory\n    ok &= initial_inuse == thread_alloc::inuse(0);\n    //\n    return ok;\n}\n// END TIME C++\n"
  },
  {
    "path": "example/multi_thread/multi_chkpoint_two.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_MULTI_THREAD_MULTI_CHKPOINT_TWO_HPP\n# define CPPAD_EXAMPLE_MULTI_THREAD_MULTI_CHKPOINT_TWO_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\nbool multi_chkpoint_two_time(\n    double& time_out, double test_time, size_t num_threads, size_t num_solve\n);\n\n# endif\n"
  },
  {
    "path": "example/multi_thread/multi_chkpoint_two.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin multi_chkpoint_two.cpp}\n\nMulti-Threading chkpoint_two Example / Test\n###########################################\n\nSource File\n***********\nAll of the routines below are located in the file\n::\n\n    example/multi_thread/multi_chkpoint_two.cpp\n\nContents\n********\n{xrst_toc_table\n    example/multi_thread/multi_chkpoint_two.cpp\n}\n\n{xrst_end multi_chkpoint_two.cpp}\n"
  },
  {
    "path": "example/multi_thread/multi_newton.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin multi_newton_common}\n\nCommon Variables use by Multi-Threaded Newton Method\n####################################################\n\nPurpose\n*******\nThis source code defined the common\ninclude files, defines, and variables that are used by the\nmulti-newton method.\n\nSource\n******\n{xrst_literal\n    // BEGIN COMMON C++\n    // END COMMON C++\n}\n\n{xrst_end multi_newton_common}\n*/\n// BEGIN COMMON C++\n# include <cppad/cppad.hpp>\n# include <cppad/utility/time_test.hpp>\n# include <cmath>\n# include <cstring>\n# include \"multi_newton.hpp\"\n# include \"team_thread.hpp\"\n# define USE_THREAD_ALLOC_FOR_WORK_ALL 1\n\nnamespace {\n    using CppAD::thread_alloc; // fast multi-threadeding memory allocator\n    using CppAD::vector;       // uses thread_alloc\n\n    // number of threads, set by multi_newton_time.\n    size_t num_threads_ = 0;\n\n    // function we are finding zeros of, set by multi_newton_time\n    void (*fun_)(double x, double& f, double& df) = 0;\n\n    // convergence criteria, set by multi_newton_setup\n    double epsilon_ = 0.;\n\n    // maximum number of iterations, set by  multi_newton_setup\n    size_t max_itr_ = 0;\n\n    // length for all sub-intervals\n    double sub_length_ = 0.;\n\n    // structure with information for one thread\n    typedef struct {\n        // number of sub intervals (worker input)\n        size_t num_sub;\n        // beginning of interval (worker input)\n        double xlow;\n        // end of interval (worker input)\n        double xup;\n        // vector of zero candidates (worker output)\n        // after call to multi_newton_setup:    x.size() == 0\n        // after call to multi_newton_work:     x.size() is number of zeros\n        // after call to multi_newton_takedown: x.size() == 0\n        vector<double> x;\n        // false if an error occurs, true otherwise (worker output)\n        bool   ok;\n    } work_one_t;\n    // vector with information for all threads\n    // after call to multi_newton_setup:    work_all.size() == num_threads\n    // after call to multi_newton_takedown: work_all.size() == 0\n    // (use pointers instead of values to avoid false sharing)\n    vector<work_one_t*> work_all_;\n}\n// END COMMON C++\n/*\n-------------------------------------------------------------------------------\n{xrst_begin multi_newton_setup}\n{xrst_spell\n    xlow\n    xup\n}\n\nSet Up Multi-Threaded Newton Method\n###################################\n\nSyntax\n******\n| *ok* = ``multi_newton_setup`` (\n| |tab| *num_sub* , *xlow* , *xup* , *epsilon* , *max_itr* , *num_threads*\n| )\n\nPurpose\n*******\nThese routine does the setup for splitting finding all the zeros in an\ninterval into separate sub-intervals, one for each thread.\n\nThread\n******\nIt is assumed that this function is called by thread zero,\nand all the other threads are blocked (waiting).\n\nnum_sub\n*******\nSee *num_sub* in :ref:`multi_newton_run<multi_newton_run@num_sub>` .\n\nxlow\n****\nSee *xlow* in :ref:`multi_newton_run<multi_newton_run@xlow>` .\n\nxup\n***\nSee *xup* in :ref:`multi_newton_run<multi_newton_run@xup>` .\n\nepsilon\n*******\nSee *epsilon* in :ref:`multi_newton_run<multi_newton_run@epsilon>` .\n\nmax_itr\n*******\nSee *max_itr* in :ref:`multi_newton_run<multi_newton_run@max_itr>` .\n\nnum_threads\n***********\nSee *num_threads* in\n:ref:`multi_newton_run<multi_newton_run@num_threads>` .\n\nSource\n******\n{xrst_literal\n    // BEGIN SETUP C++\n    // END SETUP C++\n}\n\n{xrst_end multi_newton_setup}\n*/\n// BEGIN SETUP C++\nnamespace {\nbool multi_newton_setup(\n    size_t num_sub                              ,\n    double xlow                                 ,\n    double xup                                  ,\n    double epsilon                              ,\n    size_t max_itr                              ,\n    size_t num_threads                          )\n{\n    num_threads  = std::max(num_threads_, size_t(1));\n    bool ok      = num_threads == thread_alloc::num_threads();\n    ok          &= thread_alloc::thread_num() == 0;\n\n    // inputs that are same for all threads\n    epsilon_ = epsilon;\n    max_itr_ = max_itr;\n\n    // resize the work vector to accommodate the number of threads\n    ok &= work_all_.size() == 0;\n    work_all_.resize(num_threads);\n\n    // length of each sub interval\n    sub_length_ = (xup - xlow) / double(num_sub);\n\n    // determine values that are specific to each thread\n    size_t num_min   = num_sub / num_threads; // minimum num_sub\n    size_t num_more  = num_sub % num_threads; // number that have one more\n    size_t sum_num   = 0;  // sum with respect to thread of num_sub\n    size_t thread_num, num_sub_thread;\n    for(thread_num = 0; thread_num < num_threads; thread_num++)\n    {\n# if  USE_THREAD_ALLOC_FOR_WORK_ALL\n        // allocate separate memory for this thread to avoid false sharing\n        size_t min_bytes(sizeof(work_one_t)), cap_bytes;\n        void* v_ptr = thread_alloc::get_memory(min_bytes, cap_bytes);\n        work_all_[thread_num] = static_cast<work_one_t*>(v_ptr);\n\n        // thread_alloc is a raw memory allocator; i.e., it does not call\n        // the constructor for the objects it creates. The vector\n        // class requires it's constructor to be called so we do it here\n        new(& (work_all_[thread_num]->x) ) vector<double>();\n# else\n        work_all_[thread_num] = new work_one_t;\n# endif\n\n        // number of sub-intervalse for this thread\n        if( thread_num < num_more  )\n            num_sub_thread = num_min + 1;\n        else\n            num_sub_thread = num_min;\n\n        // when thread_num == 0, xlow_thread == xlow\n        double xlow_thread = xlow + double(sum_num) * sub_length_;\n\n        // when thread_num == num_threads - 1, xup_thread = xup\n        double xup_thread =\n            xlow + double(sum_num + num_sub_thread) * sub_length_;\n        if( thread_num == num_threads - 1 )\n            xup_thread = xup;\n\n        // update sum_num for next time through loop\n        sum_num += num_sub_thread;\n\n        // input information specific to this thread\n        work_all_[thread_num]->num_sub = num_sub_thread;\n        work_all_[thread_num]->xlow    = xlow_thread;\n        work_all_[thread_num]->xup     = xup_thread;\n        ok &= work_all_[thread_num]->x.size() == 0;\n\n        // in case this thread does not get called\n        work_all_[thread_num]->ok = false;\n    }\n    ok &= sum_num == num_sub;\n    return ok;\n}\n}\n// END SETUP C++\n/*\n------------------------------------------------------------------------------\n{xrst_begin multi_newton_worker}\n{xrst_spell\n    xlow\n    xup\n}\n\nDo One Thread's Work for Multi-Threaded Newton Method\n#####################################################\n\nSyntax\n******\n``multi_newton_worker`` ()\n\nPurpose\n*******\nThis function finds all the zeros in the interval [ *low* , *up*  ] .\n\nlow\n***\nThis is the value of the :ref:`multi_newton_common-name` information\n\n    *low* = ``work_all_`` [ *thread_num* ] ``->xlow``\n\nup\n**\nThis is the value of the :ref:`multi_newton_common-name` information\n\n    *up* = ``work_all_`` [ *thread_num* ] ``->xup``\n\nthread_num\n**********\nThis is the number for the current thread; see\n:ref:`thread_num<ta_thread_num-name>` .\n\nSource\n******\n{xrst_literal\n    // BEGIN WORKER C++\n    // END WORKER C++\n}\n\n{xrst_end multi_newton_worker}\n*/\n// BEGIN WORKER C++\nnamespace {\nvoid multi_newton_worker(void)\n{\n    // Split [xlow, xup] into num_sub intervales and\n    // look for one zero in each sub-interval.\n    size_t thread_num    = thread_alloc::thread_num();\n    size_t num_threads   = std::max(num_threads_, size_t(1));\n    bool   ok            = thread_num < num_threads;\n    size_t num_sub       = work_all_[thread_num]->num_sub;\n    double xlow          = work_all_[thread_num]->xlow;\n    double xup           = work_all_[thread_num]->xup;\n    vector<double>& x    = work_all_[thread_num]->x;\n\n    // check arguments\n    ok &= max_itr_ > 0;\n    ok &= num_sub > 0;\n    ok &= xlow < xup;\n    ok &= x.size() == 0;\n\n    // check for special case where there is nothing for this thread to do\n    if( num_sub == 0 )\n    {  work_all_[thread_num]->ok = ok;\n        return;\n    }\n\n    // check for a zero on each sub-interval\n    size_t i;\n    double xlast = xlow - 2.0 * sub_length_; // over sub_length_ away from x_low\n    double flast = 2.0 * epsilon_;           // any value > epsilon_ would do\n    for(i = 0; i < num_sub; i++)\n    {\n        // note that when i == 0, xlow_i == xlow (exactly)\n        double xlow_i = xlow + double(i) * sub_length_;\n\n        // note that when i == num_sub - 1, xup_i = xup (exactly)\n        double xup_i  = xup  - double(num_sub - i - 1) * sub_length_;\n\n        // initial point for Newton iterations\n        double xcur = (xup_i + xlow_i) / 2.;\n\n        // Newton iterations\n        bool more_itr = true;\n        size_t itr    = 0;\n        // initialize these values to avoid MSC C++ warning\n        double fcur=0.0, dfcur=0.0;\n        while( more_itr )\n        {  fun_(xcur, fcur, dfcur);\n\n            // check end of iterations\n            if( fabs(fcur) <= epsilon_ )\n                more_itr = false;\n            if( (xcur == xlow_i ) && (fcur * dfcur > 0.) )\n                more_itr = false;\n            if( (xcur == xup_i) && (fcur * dfcur < 0.) )\n                more_itr = false;\n\n            // next Newton iterate\n            if( more_itr )\n            {  xcur = xcur - fcur / dfcur;\n                // keep in bounds\n                xcur = std::max(xcur, xlow_i);\n                xcur = std::min(xcur, xup_i);\n\n                more_itr = ++itr < max_itr_;\n            }\n        }\n        if( fabs( fcur ) <= epsilon_ )\n        {  // check for case where xcur is lower bound for this\n            // sub-interval and upper bound for previous sub-interval\n            if( fabs(xcur - xlast) >= sub_length_ )\n            {  x.push_back( xcur );\n                xlast = xcur;\n                flast = fcur;\n            }\n            else if( fabs(fcur) < fabs(flast) )\n            {  x[ x.size() - 1] = xcur;\n                xlast            = xcur;\n                flast            = fcur;\n            }\n        }\n    }\n    work_all_[thread_num]->ok = ok;\n}\n}\n// END WORKER C++\n/*\n-------------------------------------------------------------------------------\n{xrst_begin multi_newton_takedown}\n{xrst_spell\n    xout\n}\n\nTake Down Multi-threaded Newton Method\n######################################\n\nSyntax\n******\n\n    *ok* = ``harmonic_takedown`` ( *xout* )\n\nPurpose\n*******\nThis routine does the takedown for splitting the Newton method into\nsub-intervals.\n\nThread\n******\nIt is assumed that this function is called by thread zero,\nand all the other threads have completed their work and are blocked (waiting).\n\nxout\n****\nSee :ref:`multi_newton_run<multi_newton_run@xout>` .\n\nSource\n******\n{xrst_literal\n    // BEGIN TAKEDOWN C++\n    // END TAKEDOWN C++\n}\n\n{xrst_end multi_newton_takedown}\n*/\n// BEGIN TAKEDOWN C++\nnamespace {\nbool multi_newton_takedown(vector<double>& xout)\n{   // number of threads in the calculation\n    size_t num_threads  = std::max(num_threads_, size_t(1));\n\n    // remove duplicates and points that are not solutions\n    xout.resize(0);\n    bool   ok = true;\n    ok       &= thread_alloc::thread_num() == 0;\n\n    // initialize as more that sub_length_ / 2 from any possible solution\n    double xlast = - sub_length_;\n    for(size_t thread_num = 0; thread_num < num_threads; thread_num++)\n    {   vector<double>& x = work_all_[thread_num]->x;\n\n        size_t i;\n        for(i = 0; i < x.size(); i++)\n        {   // check for case where this point is lower limit for this\n            // thread and upper limit for previous thread\n            if( fabs(x[i] - xlast) >= sub_length_ )\n            {   xout.push_back( x[i] );\n                xlast = x[i];\n            }\n            else\n            {   double fcur, flast, df;\n                fun_(x[i],   fcur, df);\n                fun_(xlast, flast, df);\n                if( fabs(fcur) < fabs(flast) )\n                {   xout[ xout.size() - 1] = x[i];\n                    xlast                  = x[i];\n                }\n            }\n        }\n        // check that this thread was ok with the work it did\n        ok &= work_all_[thread_num]->ok;\n    }\n\n    // go down so free memory for other threads before memory for master\n    size_t thread_num = num_threads;\n    while(thread_num--)\n    {\n# if USE_THREAD_ALLOC_FOR_WORK_ALL\n        // call the destructor for vector destructor\n        work_all_[thread_num]->x.~vector<double>();\n        // delete the raw memory allocation\n        void* v_ptr = static_cast<void*>( work_all_[thread_num] );\n        thread_alloc::return_memory( v_ptr );\n# else\n        delete work_all_[thread_num];\n# endif\n        // Note that xout corresponds to memory that is inuse by master\n        // (so we can only check have freed all their memory).\n        if( thread_num > 0 )\n        {   // check that there is no longer any memory inuse by this thread\n            ok &= thread_alloc::inuse(thread_num) == 0;\n            // return all memory being held for future use by this thread\n            thread_alloc::free_available(thread_num);\n        }\n    }\n    // now we are done with the work_all_ vector so free its memory\n    // (because it is a static variable)\n    work_all_.clear();\n\n    return ok;\n}\n}\n// END TAKEDOWN C++\n/*\n------------------------------------------------------------------------------\n{xrst_begin multi_newton_run}\n{xrst_spell\n    df\n    xlow\n    xout\n    xup\n}\n\nA Multi-Threaded Newton's Method\n################################\n\nSyntax\n******\n\n| ``ok`` = ``multi_newton_run`` ( *xout* ,\n| |tab| ``fun`` , ``num_sub`` , ``xlow`` , ``xup`` , ``epsilon`` , ``max_itr`` , ``num_threads``\n| )\n\nPurpose\n*******\nMulti-threaded determination of the argument values :math:`x`,\nin the interval :math:`[a, b]` (where :math:`a < b`),\nsuch that :math:`f(x) = 0`.\n\nThread\n******\nIt is assumed that this function is called by thread zero,\nand all the other threads are blocked (waiting).\n\nMethod\n******\nFor :math:`i = 0 , \\ldots , n`,\nwe define the *i*-th grid point :math:`g_i` by\n\n.. math::\n\n    g_i = a \\frac{n - i}{n} +  b \\frac{i}{n}\n\nFor :math:`i = 0 , \\ldots , n-1`,\nwe define the *i*-th sub-interval of :math:`[a, b]` by\n\n.. math::\n\n    I_i = [ g_i , g_{i+1} ]\n\nNewton's method is applied starting\nat the center of each of the sub-intervals :math:`I_i` for\n:math:`i = 0 , \\ldots , n-1`\nand at most one zero is found for each sub-interval.\n\nok\n**\nThe return value *ok* has prototype\n\n    ``bool`` *ok*\n\nIf an error occurs, it is false, otherwise it is true.\n\nxout\n****\nThe argument *xout* has the prototype\n\n    ``vector<double>&`` *xout*\n\nThe input size and value of the elements of *xout* do not matter.\nUpon return from ``multi_newton`` ,\nthe size of *xout* is less than or equal\nthe number of sub-intervals :math:`n` and\n\n.. math::\n\n    | f( xout[i] ) | \\leq epsilon\n\nfor each valid index 0 <= ``i`` < ``xout`` . *size* () .\nTwo :math:`x` solutions are considered equal (and joined as one) if\nthe absolute difference between the solutions is less than\n:math:`(b - a) / n`.\n\nfun\n***\nThe argument *fun* has prototype\n\n    ``void`` *fun* ( ``double`` *x* , ``double&`` *f* , ``double&`` *df* )\n\nThis function must evaluate :math:`f(x)`,\nand its derivative :math:`f^{(1)} (x)`,\nusing the syntax\n\n    *fun* ( *x* , *f* , *df* )\n\nwhere the arguments to *fun* have the prototypes\n\n| |tab| ``double`` *x*\n| |tab| ``double&`` *f*\n| |tab| ``double&`` *df*\n\n.\nThe input values of *f* and *df* do not matter.\nUpon return they are :math:`f(x)` and :math:`f^{(1)} (x)` respectively.\n\nnum_sub\n*******\nThe argument *num_sub* has prototype\n\n    ``size_t`` *num_sub*\n\nIt specifies the number of sub-intervals; i.e., :math:`n`.\n\nxlow\n****\nThe argument *xlow* has prototype\n\n    ``double`` *xlow*\n\nIt specifies the lower limit for the entire search interval; i.e., :math:`a`.\n\nxup\n***\nThe argument *xup* has prototype\n\n    ``double`` *xup*\n\nIt specifies the upper limit for the entire search interval; i.e., :math:`b`.\n\nepsilon\n*******\nThe argument *epsilon* has prototype\n\n    ``double`` *epsilon*\n\nIt specifies the convergence criteria for Newton's method in terms\nof how small the function value must be.\n\nmax_itr\n*******\nThe argument *max_itr* has prototype\n\n    ``size_t`` *max_itr*\n\nIt specifies the maximum number of iterations of Newton's method to try\nbefore giving up on convergence (on each sub-interval).\n\nnum_threads\n***********\nThis argument has prototype\n\n    ``size_t`` *num_threads*\n\nIt specifies the number of threads that are available for this test.\nIf it is zero, the test is run without the multi-threading environment.\n\nSource\n******\n{xrst_literal\n    // BEGIN SOLVE C++\n    // END SOLVE C++\n}\n\n{xrst_end multi_newton_run}\n---------------------------------------------------------------------------\n*/\n// BEGIN SOLVE C++\nnamespace {\nbool multi_newton_run(\n    vector<double>& xout                       ,\n    void fun(double x, double& f, double& df)  ,\n    size_t num_sub                             ,\n    double xlow                                ,\n    double xup                                 ,\n    double epsilon                             ,\n    size_t max_itr                             ,\n    size_t num_threads                         )\n{\n    bool ok = true;\n    ok     &= thread_alloc::thread_num() == 0;\n\n    // setup the work for num_threads threads\n    ok &= multi_newton_setup(\n        num_sub, xlow, xup, epsilon, max_itr, num_threads\n    );\n\n    // now do the work for each thread\n    if( num_threads > 0 )\n        team_work( multi_newton_worker );\n    else\n        multi_newton_worker();\n\n    // now combine the results for all the threads\n    ok &= multi_newton_takedown(xout);\n\n    return ok;\n}\n}\n// END SOLVE C++\n/*\n-----------------------------------------------------------------------------\n{xrst_begin multi_newton_time}\n.\n\nTiming Test of Multi-Threaded Newton Method\n###########################################\n\nSyntax\n******\n\n| *ok* = ``multi_newton_time`` ( *time_out* , *test_time* , *num_threads* ,\n| |tab| *num_zero* , *num_sub* , *num_sum* , *use_ad*\n| )\n\nPurpose\n*******\nRuns correctness and timing test for a multi-threaded Newton method.\nThis test uses Newton's method to determine all the zeros of the sine\nfunction on an interval.\nCppAD, or hand coded derivatives,\ncan be used to calculate the derivatives used by Newton's method.\nThe calculation can be done in parallel on the different sub-intervals.\nIn addition, the calculation can be done without multi-threading.\n\nThread\n******\nIt is assumed that this function is called by thread zero in sequential\nmode; i.e., not :ref:`in_parallel<ta_in_parallel-name>` .\n\nok\n**\nThis return value has prototype\n\n    ``bool`` *ok*\n\nIf it is true,\n``multi_newton_time`` passed the correctness test.\nOtherwise it is false.\n\ntime_out\n********\nThis argument has prototype\n\n    ``double&`` *time_out*\n\nThe input value of the argument does not matter.\nUpon return it is the number of wall clock seconds required for\nthe multi-threaded Newton method can compute all the zeros.\n\ntest_time\n*********\nIs the minimum amount of wall clock time that the test should take.\nThe number of repeats for the test will be increased until this time\nis reached.\nThe reported *time_out* is the total wall clock time divided by the\nnumber of repeats.\n\nnum_threads\n***********\nThis argument has prototype\n\n    ``size_t`` *num_threads*\n\nIt specifies the number of threads that\nare available for this test.\nIf it is zero, the test is run without multi-threading and\n\n    1 == ``thread_alloc::num_threads`` ()\n\nwhen ``multi_newton_time`` is called.\nIf it is non-zero, the test is run with multi-threading and\n\n    *num_threads* == ``thread_alloc::num_threads`` ()\n\nwhen ``multi_newton_time`` is called.\n\nnum_zero\n********\nThis argument has prototype\n\n    ``size_t`` *num_zero*\n\nand it must be greater than one.\nIt specifies the actual number of zeros in the test function\n:math:`\\sin(x)`.\nTo be specific, ``multi_newton_time`` will attempt to determine\nall of the values of :math:`x` for which :math:`\\sin(x) = 0` and\n:math:`x` is in the interval\n\n    [ 0 , ( *num_zero* ``- 1`` ) * *pi*  ]\n\n.\n\nnum_sub\n*******\nThis argument has prototype\n\n    ``size_t`` *num_sub*\n\nIt specifies the number of sub-intervals to divide the total interval into.\nIt must be greater than *num_zero*\n(so that the correctness test can check we have found all the zeros).\n\nnum_sum\n*******\nThis argument has prototype\n\n    ``size_t`` *num_sum*\n\nand must be greater than zero.\nThe actual function used by the Newton method is\n\n.. math::\n\n    f(x) = \\frac{1}{n} \\sum_{i=1}^{n} \\sin (x)\n\nwhere :math:`n` is equal to *num_sum* .\nLarger values of *num_sum* simulate a case where the\nevaluation of the function :math:`f(x)` takes more time.\n\nuse_ad\n******\nThis argument has prototype\n\n    ``bool`` *user_ad*\n\nIf *use_ad* is ``true`` ,\nthen derivatives will be computed using CppAD.\nNote that this derivative computation includes\nre-taping the function for each\nvalue of :math:`x` (even though re-taping is not necessary).\n\nIf *use_ad* is ``false`` ,\nderivatives will be computed using a hand coded routine.\n\nSource\n******\n{xrst_literal\n    // BEGIN TIME C++\n    // END TIME C++\n}\n\n{xrst_end multi_newton_time}\n*/\n// BEGIN TIME C++\n\nnamespace { // empty namespace\n\n    // values correspond to arguments in previous call to multi_newton_time\n    size_t num_zero_;   // number of zeros of f(x) in the total interval\n    size_t num_sub_;    // number of sub-intervals to split calculation into\n    size_t num_sum_;    // larger values make f(x) take longer to calculate\n\n    // value of xout corresponding to most recent call to test_once\n    vector<double> xout_;\n\n    // A version of the sine function that can be made as slow as we like\n    template <class Float>\n    Float f_eval(Float x)\n    {   Float sum = 0.;\n        size_t i;\n        for(i = 0; i < num_sum_; i++)\n            sum += sin(x);\n\n        return sum / Float(num_sum_);\n    }\n\n    // Direct calculation of derivative with same number of floating point\n    // operations as for f_eval.\n    double df_direct(double x)\n    {   double sum = 0.;\n        size_t i;\n        for(i = 0; i < num_sum_; i++)\n            sum += cos(x);\n\n        return sum / double(num_sum_);\n    }\n\n    // AD calculation of detivative\n    void fun_ad(double x, double& f, double& df)\n    {   using CppAD::AD;\n\n        // use vector because it uses fast multi-threaded memory alloc\n        vector< AD<double> > X(1), Y(1);\n        X[0] = x;\n        CppAD::Independent(X);\n        Y[0] = f_eval(X[0]);\n        CppAD::ADFun<double> F(X, Y);\n        vector<double> dx(1), dy(1);\n        dx[0] = 1.;\n        dy    = F.Forward(1, dx);\n        f     = Value( Y[0] );\n        df    = dy[0];\n        return;\n    }\n\n    // evaluate the function and its derivative\n    void fun_no(double x, double& f, double& df)\n    {   f  = f_eval(x);\n        df = df_direct(x);\n        return;\n    }\n\n\n    // Run computation of all the zeros once\n    void test_once(void)\n    {   if(  num_zero_ == 0 )\n        {   std::cerr << \"multi_newton_time: num_zero == 0\" << std::endl;\n            exit(1);\n        }\n        double pi      = 4. * std::atan(1.);\n        double xlow    = 0.;\n        double xup     = double(num_zero_ - 1) * pi;\n        double eps     =\n            xup * 100. * CppAD::numeric_limits<double>::epsilon();\n        size_t max_itr = 20;\n\n        // note that fun_ is set to fun_ad or fun_no by multi_newton_time\n        bool ok = multi_newton_run(\n            xout_       ,\n            fun_        ,\n            num_sub_    ,\n            xlow        ,\n            xup         ,\n            eps         ,\n            max_itr     ,\n            num_threads_\n        );\n        if( ! ok )\n        {   std::cerr << \"multi_newton: error\" << std::endl;\n            exit(1);\n        }\n        return;\n    }\n\n    // Repeat computation of all the zeros a specified number of times\n    void test_repeat(size_t repeat)\n    {   size_t i;\n        for(i = 0; i < repeat; i++)\n            test_once();\n        return;\n    }\n} // end empty namespace\n\n\n// This is the only routine that is accessible outside of this file\nbool multi_newton_time(\n    double& time_out      ,\n    double  test_time     ,\n    size_t  num_threads   ,\n    size_t  num_zero      ,\n    size_t  num_sub       ,\n    size_t  num_sum       ,\n    bool    use_ad\n)\n{\n    bool ok = true;\n    ok     &= thread_alloc::thread_num() == 0;\n    ok     &= num_sub > num_zero;\n\n    // Set local namespace environment variables\n    num_threads_  = num_threads;\n    if( use_ad )\n        fun_ = fun_ad;\n    else\n        fun_ = fun_no;\n    //\n    num_zero_     = num_zero;\n    num_sub_      = num_sub;\n    num_sum_      = num_sum;\n\n    // create team of threads\n    ok &= thread_alloc::in_parallel() == false;\n    if( num_threads > 0 )\n    {   team_create(num_threads);\n        ok &= num_threads == thread_alloc::num_threads();\n    }\n    else\n    {   ok &= 1 == thread_alloc::num_threads();\n    }\n\n    // run the test case and set time return value\n    time_out = CppAD::time_test(test_repeat, test_time);\n\n    // destroy team of threads\n    if( num_threads > 0 )\n        team_destroy();\n    ok &= thread_alloc::in_parallel() == false;\n    //\n    // correctness check\n    double pi      = 4. * std::atan(1.);\n    double xup     = double(num_zero_ - 1) * pi;\n    double eps     = xup * 100. * CppAD::numeric_limits<double>::epsilon();\n    ok        &= (xout_.size() == num_zero);\n    size_t i   = 0;\n    for(i = 0; i < xout_.size(); i++)\n        ok &= std::fabs( xout_[i] - pi * double(i)) <= 2 * eps;\n\n    // xout_ is a static variable, so clear it to free its memory\n    xout_.clear();\n\n    // return correctness check result\n    return  ok;\n}\n// END TIME C++\n"
  },
  {
    "path": "example/multi_thread/multi_newton.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_MULTI_THREAD_MULTI_NEWTON_HPP\n# define CPPAD_EXAMPLE_MULTI_THREAD_MULTI_NEWTON_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\nbool multi_newton_time(\n    double& time_out      ,\n    double  test_time     ,\n    size_t  num_threads   ,\n    size_t  num_zero      ,\n    size_t  num_sub       ,\n    size_t  num_sum       ,\n    bool    use_ad\n);\n\n# endif\n"
  },
  {
    "path": "example/multi_thread/multi_newton.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin multi_newton.cpp}\n\nMulti-Threaded Newton Method Example / Test\n###########################################\n\nSource File\n***********\nAll of the routines below are located in the file\n::\n\n    example/multi_thread/multi_newton.cpp\n\nContents\n********\n{xrst_toc_table\n    example/multi_thread/multi_newton.cpp\n}\n\n{xrst_end multi_newton.cpp}\n"
  },
  {
    "path": "example/multi_thread/openmp/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-25 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# Build the example/multi_thread/openmp directory tests\n# Inherit build type from ../CMakeList.txt\n\n# Local include directories to search (not in package_prefix/include)\nINCLUDE_DIRECTORIES( ${CMAKE_CURRENT_SOURCE_DIR}/.. )\n\n# Cannot find specifications for CMAKE_CXX_FLAGS in version 2.6 documentation\n# so using ADD_DEFINITIONS instead.\nADD_DEFINITIONS( ${OpenMP_CXX_FLAGS} )\n\n# add_executable(<name> [WIN32] [MACOSX_BUNDLE] [EXCLUDE_FROM_ALL]\n#                 source1 source2 ... sourceN\n# )\nSET(source_list ../thread_test.cpp\n    ../team_example.cpp\n    ../harmonic.cpp\n    ../multi_atomic_two.cpp\n    ../multi_atomic_three.cpp\n    ../multi_chkpoint_one.cpp\n    ../multi_chkpoint_two.cpp\n    ../multi_newton.cpp\n    a11c_openmp.cpp\n    get_started.cpp\n    team_openmp.cpp\n)\nset_compile_flags( example_multi_thread_openmp \"${cppad_debug_which}\" \"${source_list}\" )\n#\nADD_EXECUTABLE( example_multi_thread_openmp EXCLUDE_FROM_ALL ${source_list} )\nTARGET_LINK_LIBRARIES(\n    example_multi_thread_openmp PRIVATE\n    ${cppad_lib}\n    ${colpack_libs}\n    ${OpenMP_CXX_LIBRARIES}\n)\n\n# Extra flags used by linker for openmp support\nSET(CMAKE_EXE_LINKER_FLAGS \"${OpenMP_CXX_FLAGS} ${cppad_link_flags}\" )\n\n# check_example_multi_thread_openmp\nadd_check_executable(check_example_multi_thread openmp get_started)\n"
  },
  {
    "path": "example/multi_thread/openmp/a11c_openmp.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin a11c_openmp.cpp}\n\nA Simple OpenMP Example and Test\n################################\n\nPurpose\n*******\nThis example just demonstrates OpenMP and does not use CppAD at all.\n\nSource Code\n***********\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end a11c_openmp.cpp}\n----------------------------------------------------------------------------\n*/\n// BEGIN C++\n# include <omp.h>\n# include <limits>\n# include <cmath>\n# include <cassert>\n// for size_t\n# include <cstddef>\n//\n# define NUMBER_THREADS 4\n\nnamespace {\n    // Beginning of Example A.1.1.1c of OpenMP 2.5 standard document ---------\n    void a1(int n, float *a, float *b)\n    {   // Original had 'int i;' instead of 'int i = 0;'\n        // Silence warning by clang 9.0.0: variable 'i' is uninitialized.\n        int i = 0;\n    # pragma omp parallel for\n        for(i = 1; i < n; i++) /* i is private by default */\n        {   assert( omp_get_num_threads() == NUMBER_THREADS );\n            b[i] = (a[i] + a[i-1]) / float(2);\n        }\n    }\n    // End of Example A.1.1.1c of OpenMP 2.5 standard document ---------------\n}\nbool a11c(void)\n{   bool ok = true;\n\n    // Test setup\n    size_t i, n = 1000;\n    float *a = new float[n];\n    float *b = new float[n];\n    for(i = 0; i < n; i++)\n        a[i] = float(i);\n\n    int n_thread = NUMBER_THREADS;   // number of threads in parallel regions\n    omp_set_dynamic(0);              // off dynamic thread adjust\n    omp_set_num_threads(n_thread);   // set the number of threads\n\n    a1(int(n), a, b);\n\n    // check the result\n    float eps = float(100) * std::numeric_limits<float>::epsilon();\n    for(i = 1; i < n ; i++)\n        ok &= std::fabs( (float(2) * b[i] - a[i] - a[i-1]) / b[i] ) <= eps;\n\n    delete [] a;\n    delete [] b;\n\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/multi_thread/openmp/get_started.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin openmp_get_started.cpp}\n\n{xrst_template ,\n    example/multi_thread/template/get_started.xrst\n\n    title: Getting Started Using @Name@ Threads With CppAD\n    start source code after: // <space> BEGIN_C++\n    end source code before:  // <space> END_C++\n\n    @Name@    , OpenMP\n    @####@    , ######\n    @DEFAULT@ , USE_DEFAULT_ADFUN_CONSTRUCTOR\n}\n\n{xrst_end openmp_get_started.cpp}\n------------------------------------------------------------------------------\n*/\n// BEGIN_C++\n# include <cppad/cppad.hpp>\n# include <omp.h>\n\n# define USE_DEFAULT_ADFUN_CONSTRUCTOR 1\n\nnamespace {\n    //\n    // d_vector, ad_vector, fun_vector\n    typedef CPPAD_TESTVECTOR(double)                  d_vector;\n    typedef CPPAD_TESTVECTOR( CppAD::AD<double> )    ad_vector;\n    typedef CPPAD_TESTVECTOR( CppAD::ADFun<double> ) fun_vector;\n    //\n    // in_parallel\n    bool in_parallel(void)\n    {   return omp_in_parallel() != 0;\n    }\n    //\n    // thread_number\n    size_t thread_number(void)\n    {   return static_cast<size_t>( omp_get_thread_num() );\n    }\n    //\n    // partial\n    double partial(\n        CppAD::ADFun<double>& f, size_t j, const d_vector& x\n    )\n    {   // f\n        // This will cause an assert if Taylor coefficients were allocated\n        // by a different thread.\n        f.capacity_order(0);\n        //\n        size_t nx = x.size();\n        d_vector dx(nx), dy(1);\n        for(size_t k = 0; k < nx; ++k)\n            dx[k] = 0.0;\n        dx[j] = 1.0;\n        f.Forward(0, x);\n        dy = f.Forward(1, dx);\n        return dy[0];\n    }\n}\nbool get_started(void)\n{   // ok\n    bool ok = true;\n    //\n    // eps99\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    //\n    // nx, ax\n    size_t nx = 10;\n    ad_vector ax(nx);\n    for(size_t j = 0; j < nx; ++j)\n        ax[j] = 1.0;\n    CppAD::Independent(ax);\n    //\n    // fun\n    ad_vector  ay(1);\n    ay[0] = ax[0];\n    for(size_t j = 1; j < nx; ++j)\n        ay[0] *= ax[j];\n# if USE_DEFAULT_ADFUN_CONSTRUCTOR\n    CppAD::ADFun<double> fun;\n    fun.Dependent(ax, ay);\n# else\n    // This allocates memory for first order Taylor coefficients using thread 0.\n    // An assert will occur at f.capacity_order(0) in run_one_thread when\n    // it is called by a different thread.\n    CppAD::ADFun<double> fun(ax, ay);\n# endif\n    //\n    // num_threads, f_thread\n    size_t num_threads = 4;\n    fun_vector f_thread(num_threads);\n    for(size_t i = 0; i < num_threads; ++i)\n        f_thread[i] = fun;\n    //\n    // x\n    d_vector x(nx);\n    for(size_t j = 0; j < nx; ++j)\n        ax[j] = 1.0 + 1.0 / double(j+1);\n    //\n    // parallel_setup\n    omp_set_num_threads( int(num_threads) );\n    ok &= ! in_parallel();\n    CppAD::thread_alloc::parallel_setup(\n        num_threads, in_parallel, thread_number\n    );\n    //\n    // parallel_ad\n    CppAD::parallel_ad<double>();\n    //\n    // hold_memory\n    // optional and may improve speed if you do a lot of memory allocation\n    CppAD::thread_alloc::hold_memory(true);\n    //\n    // Jac\n    ad_vector Jac(nx);\n    //\n    // j\n    // OpenMP does not allow one to use a size_t here.\n    int int_j;\n# pragma omp parallel for\n    for(int_j = 0; int_j < int(nx); ++int_j)\n    {   size_t j                 = size_t(int_j);\n        size_t thread_num        = thread_number();\n        CppAD::ADFun<double>& f  = f_thread[thread_num];\n        Jac[j] = partial(f, j, x);\n    }\n    //\n    // hold_memory\n    // free memory for other threads before this (the master thread)\n    CppAD::thread_alloc::parallel_setup(1, nullptr, nullptr);\n    ok &= ! in_parallel();\n    CppAD::thread_alloc::hold_memory(false);\n    for(size_t i = 1; i < num_threads; ++i)\n        CppAD::thread_alloc::free_available(i);\n    CppAD::thread_alloc::free_available(0);\n    //\n    // j\n    for(int_j = 0; int_j < int(nx); ++int_j)\n    {   size_t j = size_t(int_j);\n        //\n        // check\n        double check = 1.0;\n        for(size_t k = 0; k < nx; ++k)\n            if(k != j)\n                check *= x[j];\n        //\n        // ok\n        ok &= CppAD::NearEqual(Jac[j], check, eps99, eps99);\n    }\n    return ok;\n}\n// END_C++\n"
  },
  {
    "path": "example/multi_thread/openmp/team_openmp.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin team_openmp.cpp}\n\nOpenMP Implementation of a Team of AD Threads\n#############################################\nSee :ref:`team_thread.hpp-name` for this routines specifications.\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end team_openmp.cpp}\n*/\n// BEGIN C++\n# include <omp.h>\n# include <cppad/cppad.hpp>\n# include \"../team_thread.hpp\"\n\nnamespace {\n    using CppAD::thread_alloc;\n\n    // number of threads in this team\n    size_t num_threads_;\n\n    // used to inform CppAD when we are in parallel execution mode\n    bool in_parallel(void)\n    {   return omp_in_parallel() != 0; }\n\n    // used to inform CppAD of the current thread number\n    size_t thread_num(void)\n    {   return static_cast<size_t>( omp_get_thread_num() ); }\n}\n\nbool team_create(size_t num_threads)\n{\n    bool ok = ! in_parallel();\n    ok     &= thread_num() == 0;;\n    ok     &= num_threads > 0;\n\n    // Turn off dynamic thread adjustment\n    omp_set_dynamic(0);\n\n    // Set the number of OpenMP threads\n    omp_set_num_threads( int(num_threads) );\n\n    // setup for using CppAD::AD<double> in parallel\n    thread_alloc::parallel_setup(num_threads, in_parallel, thread_num);\n    thread_alloc::hold_memory(true);\n    CppAD::parallel_ad<double>();\n\n    // inform team_work of number of threads\n    num_threads_ = num_threads;\n\n    return ok;\n}\n\nbool team_work(void worker(void))\n{   bool ok = ! in_parallel();\n    ok     &= thread_num() == 0;;\n    ok     &= num_threads_ > 0;\n\n    int number_threads = int(num_threads_);\n    int thread_num;\n# pragma omp parallel for\n    for(thread_num = 0; thread_num < number_threads; thread_num++)\n        worker();\n// end omp parallel for\n\n    return ok;\n}\n\nbool team_destroy(void)\n{   bool ok = ! in_parallel();\n    ok     &= thread_num() == 0;;\n    ok     &= num_threads_ > 0;\n\n    // inform team_work of number of threads\n    num_threads_ = 1;\n\n    // Set the number of OpenMP threads to one\n    omp_set_num_threads( int(num_threads_) );\n\n    // inform CppAD no longer in multi-threading mode\n    thread_alloc::parallel_setup(num_threads_, nullptr, nullptr);\n    thread_alloc::hold_memory(false);\n    CppAD::parallel_ad<double>();\n\n    return ok;\n}\n\nconst char* team_name(void)\n{   return \"openmp\"; }\n// END C++\n"
  },
  {
    "path": "example/multi_thread/pthread/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-25 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# Build the example/multi_thread/pthread directory tests\n# Inherit build type from ../CMakeList.txt\n\n# Local include directories to search (not in package_prefix/include)\nINCLUDE_DIRECTORIES( ${CMAKE_CURRENT_SOURCE_DIR}/.. )\n\n# add_executable(<name> [WIN32] [MACOSX_BUNDLE] [EXCLUDE_FROM_ALL]\n#                 source1 source2 ... sourceN\n# )\nSET(source_list ../thread_test.cpp\n    ../team_example.cpp\n    ../harmonic.cpp\n    ../multi_atomic_two.cpp\n    ../multi_atomic_three.cpp\n    ../multi_chkpoint_one.cpp\n    ../multi_chkpoint_two.cpp\n    ../multi_newton.cpp\n    a11c_pthread.cpp\n    get_started.cpp\n    team_pthread.cpp\n)\nset_compile_flags( example_multi_thread_pthread \"${cppad_debug_which}\" \"${source_list}\" )\n#\nADD_EXECUTABLE( example_multi_thread_pthread EXCLUDE_FROM_ALL ${source_list} )\n\n# List of libraries to be linked into the specified target\nTARGET_LINK_LIBRARIES(example_multi_thread_pthread\n    ${cppad_lib}\n    ${colpack_libs}\n    ${pthread_lib_path}\n)\n\n# check_example_multi_thread_pthread\nadd_check_executable(check_example_multi_thread pthread get_started)\n"
  },
  {
    "path": "example/multi_thread/pthread/a11c_pthread.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin a11c_pthread.cpp}\n{xrst_spell\n    pthreads\n}\n\nA Simple Parallel Pthread Example and Test\n##########################################\n\nPurpose\n*******\nThis example just demonstrates pthreads and does not use CppAD at all.\n\nSource Code\n***********\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end a11c_pthread.cpp}\n----------------------------------------------------------------------------\n*/\n// BEGIN C++\n# include <pthread.h>\n# include <limits>\n# include <cmath>\n# include <cassert>\n// for size_t\n# include <cstddef>\n\n# define NUMBER_THREADS 4\n\n# ifdef NDEBUG\n# define CHECK_ZERO(expression) expression\n# else\n# define CHECK_ZERO(expression) assert( expression == 0 );\n# endif\nnamespace {\n    // Beginning of Example A.1.1.1c of OpenMP 2.5 standard document ---------\n    void a1(int n, float *a, float *b)\n    {   int i;\n        for(i = 1; i < n; i++)\n            b[i] = (a[i] + a[i-1]) / 2.0f;\n        return;\n    }\n    // End of Example A.1.1.1c of OpenMP 2.5 standard document ---------------\n    struct start_arg { int  n; float* a; float* b; };\n    void* start_routine(void* arg_vptr)\n    {   start_arg* arg = static_cast<start_arg*>( arg_vptr );\n        a1(arg->n, arg->a, arg->b);\n\n        void* no_status = nullptr;\n        pthread_exit(no_status);\n\n        return no_status;\n    }\n}\n\nbool a11c(void)\n{   bool ok = true;\n\n    // Test setup\n    int i, j, n_total = 10;\n    float *a = new float[size_t(n_total)];\n    float *b = new float[size_t(n_total)];\n    for(i = 0; i < n_total; i++)\n        a[i] = float(i);\n\n    // number of threads\n    int n_thread = NUMBER_THREADS;\n    // the threads\n    pthread_t thread[NUMBER_THREADS];\n    // arguments to start_routine\n    struct start_arg arg[NUMBER_THREADS];\n    // attr\n    pthread_attr_t attr;\n    CHECK_ZERO( pthread_attr_init( &attr ) );\n    CHECK_ZERO( pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE) );\n    //\n    // Break the work up into sub work for each thread\n    int n = n_total / n_thread;\n    arg[0].n = n;\n    arg[0].a = a;\n    arg[0].b = b;\n    for(j = 1; j < n_thread; j++)\n    {   arg[j].n = n + 1;\n        arg[j].a = arg[j-1].a + n - 1;\n        arg[j].b = arg[j-1].b + n - 1;\n        if( j == (n_thread - 1) )\n            arg[j].n = n_total - j * n + 1;\n    }\n    for(j = 0; j < n_thread; j++)\n    {   // inform each thread of which block it is working on\n        void* arg_vptr = static_cast<void*>( &arg[j] );\n        CHECK_ZERO( pthread_create(\n            &thread[j], &attr, start_routine, arg_vptr\n        ) );\n    }\n    for(j = 0; j < n_thread; j++)\n    {   void* no_status = nullptr;\n        CHECK_ZERO( pthread_join(thread[j], &no_status) );\n    }\n\n    // check the result\n    float eps = 100.0f * std::numeric_limits<float>::epsilon();\n    for(i = 1; i < n ; i++)\n        ok &= std::fabs( (2. * b[i] - a[i] - a[i-1]) / b[i] ) <= eps;\n\n    delete [] a;\n    delete [] b;\n\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/multi_thread/pthread/get_started.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin pthread_get_started.cpp}\n{xrst_spell\n    posix\n}\n\n{xrst_template ,\n    example/multi_thread/template/get_started.xrst\n\n    title: Getting Started Using @Name@ Threads With CppAD\n    start source code after: // <space> BEGIN_C++\n    end source code before:  // <space> END_C++\n\n    @Name@    , Posix\n    @####@    , #####\n    @DEFAULT@ , USE_DEFAULT_ADFUN_CONSTRUCTOR\n}\n\n{xrst_end pthread_get_started.cpp}\n------------------------------------------------------------------------------\n*/\n// BEGIN_C++\n# include <cppad/cppad.hpp>\n# include <pthread.h>\n\n# define USE_DEFAULT_ADFUN_CONSTRUCTOR 1\n\nnamespace {\n    //\n    // d_vector, ad_vector, fun_vector\n    typedef CPPAD_TESTVECTOR(double)                 d_vector;\n    typedef CPPAD_TESTVECTOR( CppAD::AD<double> )    ad_vector;\n    typedef CPPAD_TESTVECTOR( CppAD::ADFun<double> ) fun_vector;\n    typedef CPPAD_TESTVECTOR( pthread_t )            pthread_vector;\n    //\n    // thread_info, thread_info_vector\n    typedef struct {\n        size_t                thread_num;\n        CppAD::ADFun<double>* f_ptr;\n        size_t                j_begin;\n        size_t                j_end;\n        const d_vector*       x_ptr;\n        d_vector*             Jac_ptr;\n        bool                  ok;\n    } thread_info;\n    typedef CPPAD_TESTVECTOR( thread_info ) thread_info_vector;\n    //\n    // thread_specific_key_\n    pthread_key_t thread_specific_key_;\n    //\n    // thread_specific_destructor\n    void thread_specific_destructor(void* thread_num_vptr)\n    {   return; }\n    //\n    // sequential_execution_\n    bool sequential_execution_ = true;\n    //\n    // in_parallel\n    bool in_parallel(void)\n    {   return ! sequential_execution_; }\n    //\n    // thread_number\n    size_t thread_number(void)\n    {   // get thread specific information\n        void*   thread_num_vptr = pthread_getspecific(thread_specific_key_);\n        size_t* thread_num_ptr  = static_cast<size_t*>(thread_num_vptr);\n        size_t  thread_num      = *thread_num_ptr;\n        return thread_num;\n    }\n    //\n    // partial\n    double partial(\n        CppAD::ADFun<double>& f, size_t j, const d_vector& x\n    )\n    {   size_t nx = x.size();\n        d_vector dx(nx), dy(1);\n        for(size_t k = 0; k < nx; ++k)\n            dx[k] = 0.0;\n        dx[j] = 1.0;\n        f.Forward(0, x);\n        dy = f.Forward(1, dx);\n        return dy[0];\n    }\n    //\n    // run_one_thread\n    void* run_one_thread(void* thread_info_vptr)\n    {   //\n        // thread_num, f_ptr, j_begin, j_end, x_ptr, Jac_ptr\n        thread_info* thread_info_ptr =\n            static_cast<thread_info*>(thread_info_vptr);\n        size_t                thread_num = thread_info_ptr->thread_num;\n        CppAD::ADFun<double>* f_ptr      = thread_info_ptr->f_ptr;\n        size_t                j_begin    = thread_info_ptr->j_begin;\n        size_t                j_end      = thread_info_ptr->j_end;\n        const d_vector*       x_ptr      = thread_info_ptr->x_ptr;\n        d_vector*             Jac_ptr    = thread_info_ptr->Jac_ptr;\n        //\n        // f, Jac, ok\n        CppAD::ADFun<double>& f   = *f_ptr;\n        d_vector&             Jac = *Jac_ptr;\n        bool&                 ok  = thread_info_ptr->ok;\n        //\n        // rc\n        int rc;\n        //\n        // pthread_setspecific, ok\n        // This sets up the thread_number function for this thread.\n        if( thread_num != 0 )\n        {   rc  = pthread_setspecific(thread_specific_key_, &thread_num);\n            ok &= rc == 0;\n            ok &= thread_number() == thread_num;\n        }\n        //\n        // f\n        // This will cause an assert if Taylor coefficients were allocated\n        // by a different thread.\n        f.capacity_order(0);\n        //\n        // Jac\n        for(size_t j = j_begin; j < j_end; ++j)\n            Jac[j] = partial(f, j, *x_ptr);\n        //\n        return nullptr;\n    }\n}\nbool get_started(void)\n{   // ok\n    bool ok = true;\n    //\n    // eps99\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    //\n    // nx, ax\n    size_t nx = 10;\n    ad_vector ax(nx);\n    for(size_t j = 0; j < nx; ++j)\n        ax[j] = 1.0;\n    CppAD::Independent(ax);\n    //\n    // fun\n    ad_vector  ay(1);\n    ay[0] = ax[0];\n    for(size_t j = 1; j < nx; ++j)\n        ay[0] *= ax[j];\n# if USE_DEFAULT_ADFUN_CONSTRUCTOR\n    CppAD::ADFun<double> fun;\n    fun.Dependent(ax, ay);\n# else\n    // This allocates memory for first order Taylor coefficients using thread 0.\n    // An assert will occur at f.capacity_order(0) in run_one_thread when\n    // it is called by a different thread.\n    CppAD::ADFun<double> fun(ax, ay);\n# endif\n    //\n    // num_threads, f_thread\n    size_t num_threads = 4;\n    fun_vector f_thread(num_threads);\n    for(size_t i = 0; i < num_threads; ++i)\n        f_thread[i] = fun;\n    //\n    // x\n    d_vector x(nx);\n    for(size_t j = 0; j < nx; ++j)\n        x[j] = 1.0 + 1.0 / double(j+1);\n    //\n    // Jac\n    d_vector Jac(nx);\n    //\n    // n_per_thread, n_extra\n    size_t n_per_thread = nx / num_threads;\n    size_t n_extra      = nx % num_threads;\n    //\n    // thread_info_vec\n    thread_info_vector thread_info_vec(num_threads);\n    size_t j_begin = 0;\n    size_t j_end;\n    for(size_t thread_num = 0; thread_num < num_threads; ++thread_num)\n    {   j_end = j_begin + n_per_thread;\n        if( thread_num < n_extra )\n            ++j_end;\n        //\n        thread_info_vec[thread_num].thread_num = thread_num;\n        thread_info_vec[thread_num].f_ptr      = &f_thread[thread_num];\n        thread_info_vec[thread_num].j_begin    = j_begin;\n        thread_info_vec[thread_num].j_end      = j_end;\n        thread_info_vec[thread_num].x_ptr      = &x;\n        thread_info_vec[thread_num].Jac_ptr    = &Jac;\n        thread_info_vec[thread_num].ok         = true;\n        //\n        j_begin = j_end;\n    }\n    ok &= j_end == nx;\n    //\n    // rc\n    int rc;\n    //\n    // thread_specific_key_, ok\n    rc  = pthread_key_create(&thread_specific_key_, thread_specific_destructor);\n    ok &= rc == 0;\n\n    //\n    // thread_setspecific, ok\n    // must be set for this thread before calling parall_setup or parallel_ad\n    rc = pthread_setspecific(\n            thread_specific_key_, &thread_info_vec[0].thread_num\n    );\n    ok &= rc == 0;\n    ok &= thread_number() == 0;\n    //\n    // parallel_setup\n    CppAD::thread_alloc::parallel_setup(\n        num_threads, in_parallel, thread_number\n    );\n    //\n    // parallel_ad\n    CppAD::parallel_ad<double>();\n    //\n    // hold_memory\n    // optional and may improve speed if you do a lot of memory allocation\n    CppAD::thread_alloc::hold_memory(true);\n    //\n    // ptread_vec\n    pthread_vector pthread_vec(num_threads - 1);\n    //\n    // sequential_execution_, ok\n    sequential_execution_ = false;\n    ok &= in_parallel();\n    //\n    // Jac, pthread_vec, ok\n    // Launch num_threads - 1 posix threads\n    for(size_t thread_num = 1; thread_num < num_threads; ++thread_num)\n    {   pthread_attr_t* no_attr = nullptr;\n        rc = pthread_create(\n            &pthread_vec[thread_num-1],\n            no_attr,\n            run_one_thread,\n            &thread_info_vec[thread_num]\n        );\n        ok &= rc == 0;\n    }\n    {   // run master thread's indices\n        size_t thread_num = 0;\n        run_one_thread(&thread_info_vec[thread_num]);\n    }\n    // wait for other threads to finish\n    for(size_t thread_num = 1; thread_num < num_threads; ++thread_num)\n    {   void* no_status = nullptr;\n        rc  = pthread_join(pthread_vec[thread_num-1], &no_status);\n        ok &= rc == 0;\n    }\n    //\n    // sequential_execution_, ok\n    sequential_execution_ = true;\n    CppAD::thread_alloc::parallel_setup(1, nullptr, nullptr);\n    ok &= ! in_parallel();\n    //\n    // hold_memory, ok\n    // free memory for other threads before this (the master thread)\n    ok &= thread_number() == 0;\n    CppAD::thread_alloc::hold_memory(false);\n    for(size_t thread_num = 1; thread_num < num_threads; ++thread_num)\n    {   ok &= thread_info_vec[thread_num].ok;\n        CppAD::thread_alloc::free_available(thread_num);\n    }\n    ok &= thread_info_vec[0].ok;\n    CppAD::thread_alloc::free_available(0);\n    //\n    // ok\n    for(size_t j = 0; j < nx; ++j)\n    {   //\n        // check\n        double check = 1.0;\n        for(size_t k = 0; k < nx; ++k)\n            if(k != j)\n                check *= x[k];\n        //\n        // ok\n        ok &= CppAD::NearEqual(Jac[j], check, eps99, eps99);\n    }\n    return ok;\n}\n// END_C++\n"
  },
  {
    "path": "example/multi_thread/pthread/team_pthread.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin team_pthread.cpp}\n{xrst_spell\n    destructors\n}\n\nPthread Implementation of a Team of AD Threads\n##############################################\nSee :ref:`team_thread.hpp-name` for this routines specifications.\n\nBug in Cygwin\n*************\n\nThere is a bug in ``pthread_exit`` ,\nusing cygwin 5.1 and g++ version 4.3.4,\nwhereby calling ``pthread_exit`` is not the same as returning from\nthe corresponding routine.\nTo be specific, destructors for the vectors are not called\nand a memory leaks result.\nSet the following preprocessor symbol to 1 to demonstrate this bug:\n{xrst_spell_off}\n{xrst_code cpp} */\n# define DEMONSTRATE_BUG_IN_CYGWIN 0\n/* {xrst_code}\n{xrst_spell_on}\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end team_pthread.cpp}\n*/\n// BEGIN C++\n# include <pthread.h>\n# include <cppad/cppad.hpp>\n# include \"../team_thread.hpp\"\n# define MAX_NUMBER_THREADS 48\n\n// It seems that when a barrier is passed, its counter is automatically reset\n// to its original value and it can be used again, but where is this\n// stated in the pthreads speicifcations ?\nnamespace {\n    using CppAD::thread_alloc;\n\n    // number of threads in the team\n    size_t num_threads_ = 1;\n\n    // key for accessing thread specific information\n    pthread_key_t thread_specific_key_;\n\n    // no need to destroy thread specific information\n    void thread_specific_destructor(void* thread_num_vptr)\n    {   return; }\n\n    // type of the job currently being done by each thread\n    enum thread_job_t { init_enum, work_enum, join_enum } thread_job_;\n\n    // barrier used to wait for other threads to finish work\n    pthread_barrier_t wait_for_work_;\n\n    // barrier used to wait for master thread to set next job\n    pthread_barrier_t wait_for_job_;\n\n    // Are we in sequential mode; i.e., other threads are waiting for\n    // master thread to set up next job ?\n    bool sequential_execution_ = true;\n\n    // structure with information for one thread\n    typedef struct {\n        // cppad unique identifier for thread that uses this struct\n        size_t          thread_num;\n        // pthread unique identifier for thread that uses this struct\n        pthread_t       pthread_id;\n        // true if no error for this thread, false otherwise.\n        bool            ok;\n    } thread_one_t;\n\n    // vector with information for all threads\n    thread_one_t thread_all_[MAX_NUMBER_THREADS];\n\n    // pointer to function that does the work for one thread\n    void (* worker_)(void) = nullptr;\n\n    // ---------------------------------------------------------------------\n    // in_parallel()\n    bool in_parallel(void)\n    {   return ! sequential_execution_; }\n\n    // ---------------------------------------------------------------------\n    // thread_number()\n    size_t thread_number(void)\n    {   // get thread specific information\n        void*   thread_num_vptr = pthread_getspecific(thread_specific_key_);\n        size_t* thread_num_ptr  = static_cast<size_t*>(thread_num_vptr);\n        size_t  thread_num      = *thread_num_ptr;\n        if( thread_num >= num_threads_ )\n        {   std::cerr << \"thread_number: program error\" << std::endl;\n            exit(1);\n        }\n        return thread_num;\n    }\n    // --------------------------------------------------------------------\n    // function that gets called by pthread_create\n    void* thread_work(void* thread_num_vptr)\n    {   int rc;\n        bool ok = true;\n\n        // Set thread specific data where other routines can access it\n        rc = pthread_setspecific(thread_specific_key_, thread_num_vptr);\n        ok &= rc == 0;\n\n        // thread_num to problem specific information for this thread\n        size_t thread_num = *static_cast<size_t*>(thread_num_vptr);\n\n        // master thread does not use this routine\n        ok &= thread_num > 0;\n\n        while( true )\n        {\n            // Use wait_for_job_ to give master time in sequential mode\n            // (so it can change global information like thread_job_)\n            rc = pthread_barrier_wait(&wait_for_job_);\n            ok &= (rc == 0 || rc == PTHREAD_BARRIER_SERIAL_THREAD);\n\n            // case where we are terminating this thread (no more work)\n            if( thread_job_ == join_enum )\n                break;\n\n            // only other case once wait_for_job_ barrier is passed (so far)\n            ok &= thread_job_ == work_enum;\n            worker_();\n\n            // Use wait_for_work_ to inform master that our work is done and\n            // that this thread will not use global information until\n            // passing its barrier wait_for_job_ above.\n            rc = pthread_barrier_wait(&wait_for_work_);\n            ok &= (rc == 0 || rc == PTHREAD_BARRIER_SERIAL_THREAD);\n        }\n        thread_all_[thread_num].ok = ok;\n# if DEMONSTRATE_BUG_IN_CYGWIN\n        // Terminate this thread\n        void* no_status = nullptr;\n        pthread_exit(no_status);\n# endif\n        return nullptr;\n    }\n}\n\nbool team_create(size_t num_threads)\n{   bool ok = true;;\n    int rc;\n\n    if( num_threads > MAX_NUMBER_THREADS )\n    {   std::cerr << \"team_create: num_threads greater than \";\n        std::cerr << MAX_NUMBER_THREADS << std::endl;\n        exit(1);\n    }\n    // check that we currently do not have multiple threads running\n    ok  = num_threads_ == 1;\n    ok &= sequential_execution_;\n\n    size_t thread_num;\n    for(thread_num = 0; thread_num < num_threads; thread_num++)\n    {   // Each thread gets a pointer to its version of this thread_num\n        // so it knows which section of thread_all_ it is working with\n        thread_all_[thread_num].thread_num = thread_num;\n\n        // initialize\n        thread_all_[thread_num].ok         = true;\n    }\n    // Finish setup of thread_all_ for this thread\n    thread_all_[0].pthread_id = pthread_self();\n\n    // create a key for thread specific information\n    rc = pthread_key_create(&thread_specific_key_,thread_specific_destructor);\n    ok &= (rc == 0);\n\n    // set thread specific information for this (master thread)\n    void* thread_num_vptr = static_cast<void*>(&(thread_all_[0].thread_num));\n    rc = pthread_setspecific(thread_specific_key_, thread_num_vptr);\n    ok &= (rc == 0);\n\n    // Now that thread_number() has necessary information for this thread\n    // (number zero), and while still in sequential mode,\n    // call setup for using CppAD::AD<double> in parallel mode.\n    thread_alloc::parallel_setup(num_threads, in_parallel, thread_number);\n    thread_alloc::hold_memory(true);\n    CppAD::parallel_ad<double>();\n\n    // Now change num_threads_ to its final value. Waiting till now allows\n    // calls to thread_number during parallel_setup to check thread_num == 0.\n    num_threads_ = num_threads;\n\n    // initialize two barriers, one for work done, one for new job ready\n    pthread_barrierattr_t* no_barrierattr = nullptr;\n    rc = pthread_barrier_init(\n        &wait_for_work_, no_barrierattr, (unsigned int) num_threads\n    );\n    ok &= (rc == 0);\n    rc  = pthread_barrier_init(\n        &wait_for_job_, no_barrierattr, (unsigned int) num_threads\n    );\n    ok &= (rc == 0);\n\n    // structure used to create the threads\n    pthread_t       pthread_id;\n    // default for pthread_attr_setdetachstate is PTHREAD_CREATE_JOINABLE\n    pthread_attr_t* no_attr= nullptr;\n\n    // initial job for the threads\n    thread_job_           = init_enum;\n    if( num_threads > 1 )\n        sequential_execution_ = false;\n\n    // This master thread is already running, we need to create\n    // num_threads - 1 more threads\n    for(thread_num = 1; thread_num < num_threads; thread_num++)\n    {\n        // Create the thread with thread number equal to thread_num\n        thread_num_vptr = static_cast<void*> (\n            &(thread_all_[thread_num].thread_num)\n        );\n        rc = pthread_create(\n                &pthread_id ,\n                no_attr     ,\n                thread_work ,\n                thread_num_vptr\n        );\n        thread_all_[thread_num].pthread_id = pthread_id;\n        ok &= (rc == 0);\n    }\n\n    // Current state is other threads are at wait_for_job_.\n    // This master thread (thread zero) has not completed wait_for_job_\n    sequential_execution_ = true;\n    return ok;\n}\n\nbool team_work(void worker(void))\n{   int rc;\n\n    // Current state is other threads are at wait_for_job_.\n    // This master thread (thread zero) has not completed wait_for_job_\n    bool ok = sequential_execution_;\n    ok     &= thread_number() == 0;\n\n    // set global version of this work routine\n    worker_ = worker;\n\n\n    // set the new job that other threads are waiting for\n    thread_job_ = work_enum;\n\n    // enter parallel execution soon as master thread completes wait_for_job_\n    if( num_threads_ > 1 )\n        sequential_execution_ = false;\n\n    // wait until all threads have completed wait_for_job_\n    rc  = pthread_barrier_wait(&wait_for_job_);\n    ok &= (rc == 0 || rc == PTHREAD_BARRIER_SERIAL_THREAD);\n\n    // Now do the work in this thread and then wait\n    // until all threads have completed wait_for_work_\n    worker();\n    rc = pthread_barrier_wait(&wait_for_work_);\n    ok &= (rc == 0 || rc == PTHREAD_BARRIER_SERIAL_THREAD);\n\n    // Current state is other threads are at wait_for_job_.\n    // This master thread (thread zero) has not completed wait_for_job_\n    sequential_execution_ = true;\n\n    size_t thread_num;\n    for(thread_num = 0; thread_num < num_threads_; thread_num++)\n        ok &= thread_all_[thread_num].ok;\n    return ok;\n}\n\nbool team_destroy(void)\n{   int rc;\n\n    // Current state is other threads are at wait_for_job_.\n    // This master thread (thread zero) has not completed wait_for_job_\n    bool ok = sequential_execution_;\n    ok     &= thread_number() == 0;\n\n    // set the new job that other threads are waiting for\n    thread_job_ = join_enum;\n\n    // Enter parallel execution soon as master thread completes wait_for_job_\n    if( num_threads_ > 1 )\n            sequential_execution_ = false;\n    rc  = pthread_barrier_wait(&wait_for_job_);\n    ok &= (rc == 0 || rc == PTHREAD_BARRIER_SERIAL_THREAD);\n\n    // now wait for the other threads to exit\n    size_t thread_num;\n    for(thread_num = 1; thread_num < num_threads_; thread_num++)\n    {   void* no_status = nullptr;\n        rc      = pthread_join(\n            thread_all_[thread_num].pthread_id, &no_status\n        );\n        ok &= (rc == 0);\n    }\n\n    // now we are down to just the master thread (thread zero)\n    sequential_execution_ = true;\n\n    // destroy the key for thread specific data\n    pthread_key_delete(thread_specific_key_);\n\n    // destroy wait_for_work_\n    rc  = pthread_barrier_destroy(&wait_for_work_);\n    ok &= (rc == 0);\n\n    // destroy wait_for_job_\n    rc  = pthread_barrier_destroy(&wait_for_job_);\n    ok &= (rc == 0);\n\n    // check ok before changing num_threads_\n    for(thread_num = 0; thread_num < num_threads_; thread_num++)\n        ok &= thread_all_[thread_num].ok;\n\n    // now inform CppAD that there is only one thread\n    num_threads_ = 1;\n    thread_alloc::parallel_setup(num_threads_, nullptr, nullptr);\n    thread_alloc::hold_memory(false);\n    CppAD::parallel_ad<double>();\n\n    return ok;\n}\n\nconst char* team_name(void)\n{   return \"pthread\"; }\n// END C++\n"
  },
  {
    "path": "example/multi_thread/sthread/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-25 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# Build the example/multi_thread/sthread directory tests\n# Inherit build type from ../CMakeList.txt\n\n# Local include directories to search (not in package_prefix/include)\nINCLUDE_DIRECTORIES( ${CMAKE_CURRENT_SOURCE_DIR}/.. )\n\n# add_executable(<name> [WIN32] [MACOSX_BUNDLE] [EXCLUDE_FROM_ALL]\n#                 source1 source2 ... sourceN\n# )\nSET(source_list ../thread_test.cpp\n    ../team_example.cpp\n    ../harmonic.cpp\n    ../multi_atomic_two.cpp\n    ../multi_atomic_three.cpp\n    ../multi_chkpoint_one.cpp\n    ../multi_chkpoint_two.cpp\n    ../multi_newton.cpp\n    a11c_sthread.cpp\n    get_started.cpp\n    team_sthread.cpp\n)\nset_compile_flags(\n    example_multi_thread_sthread \"${cppad_debug_which}\" \"${source_list}\"\n)\n#\nADD_EXECUTABLE( example_multi_thread_sthread EXCLUDE_FROM_ALL ${source_list} )\n\n# List of libraries to be linked into the specified target\nTARGET_LINK_LIBRARIES(example_multi_thread_sthread\n    ${cppad_lib}\n    ${colpack_libs}\n    ${pthread_lib_path}\n)\n\n# check_example_multi_thread_sthread\nadd_check_executable(check_example_multi_thread sthread get_started)\n"
  },
  {
    "path": "example/multi_thread/sthread/a11c_sthread.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin a11c_sthread.cpp}\n\nA Simple Boost Thread Example and Test\n######################################\n\nPurpose\n*******\nThis example just demonstrates Boost threads and does not use CppAD at all.\n\nSource Code\n***********\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end a11c_sthread.cpp}\n----------------------------------------------------------------------------\n*/\n// BEGIN C++\n# include <thread>\n# include <limits>\n# include <cmath>\n# include <cassert>\n// for size_t\n# include <cstddef>\n//\n# define NUMBER_THREADS 4\n\nnamespace { // Begin empty namespace\n    class worker_t\n    {\n    private:\n        int    n_;\n        float* a_;\n        float* b_;\n    public:\n        void setup(size_t n, float* a, float* b)\n        {   n_ = static_cast<int>(n);\n            a_ = a;\n            b_ = b;\n        }\n        // Beginning of Example A.1.1.1c of OpenMP 2.5 standard document\n        void a1(int n, float *a, float *b)\n        {   int i;\n            for(i = 1; i < n; i++)\n                b[i] = (a[i] + a[i-1]) / 2.0f;\n            return;\n        }\n        // End of Example A.1.1.1c of OpenMP 2.5 standard document\n        void operator()()\n        {   a1(n_, a_, b_); }\n    };\n}\n\nbool a11c(void)\n{   bool ok = true;\n\n    // Test setup\n    size_t i, j, n_total = 10;\n    float *a = new float[n_total];\n    float *b = new float[n_total];\n    for(i = 0; i < n_total; i++)\n        a[i] = float(i);\n\n    // number of threads\n    size_t number_threads = NUMBER_THREADS;\n\n    // set of workers\n    worker_t worker[NUMBER_THREADS];\n\n    // threads for each worker\n    std::thread* sthread[NUMBER_THREADS];\n\n    // Break the work up into sub work for each thread\n    size_t  n     = n_total / number_threads;\n    size_t  n_tmp = n;\n    float*  a_tmp = a;\n    float*  b_tmp = b;\n    worker[0].setup(n_tmp, a_tmp, b_tmp);\n    for(j = 1; j < number_threads; j++)\n    {   n_tmp = n + 1;\n        a_tmp = a_tmp + n - 1;\n        b_tmp = b_tmp + n - 1;\n        if( j == (number_threads - 1) )\n            n_tmp = n_total - j * n + 1;\n\n        worker[j].setup(n_tmp, a_tmp, b_tmp);\n\n        // create this thread\n        sthread[j] = new std::thread(worker[j]);\n    }\n\n    // do this threads portion of the work\n    worker[0]();\n\n    // wait for other threads to finish\n    for(j = 1; j < number_threads; j++)\n     { sthread[j]->join();\n        delete sthread[j];\n        sthread[j] = nullptr;\n    }\n\n    // check the result\n    float eps = 100.f * std::numeric_limits<float>::epsilon();\n    for(i = 1; i < n ; i++)\n        ok &= std::fabs( (2. * b[i] - a[i] - a[i-1]) / b[i] ) <= eps;\n\n    delete [] a;\n    delete [] b;\n\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/multi_thread/sthread/get_started.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin sthread_get_started.cpp}\n\n{xrst_template ,\n    example/multi_thread/template/get_started.xrst\n\n    title: Getting Started Using @Name@ Threads With CppAD\n    start source code after: // <space> BEGIN_C++\n    end source code before:  // <space> END_C++\n\n    @Name@    , Standard\n    @####@    , ########\n    @DEFAULT@ , USE_DEFAULT_ADFUN_CONSTRUCTOR\n}\n\n{xrst_end sthread_get_started.cpp}\n------------------------------------------------------------------------------\n*/\n// BEGIN_C++\n# include <thread>\n# include <mutex>\n# include <cppad/cppad.hpp>\n\n# define USE_DEFAULT_ADFUN_CONSTRUCTOR 1\n\nnamespace {\n    //\n    // d_vector, ad_vector, fun_vector, sthread_vector\n    typedef CPPAD_TESTVECTOR(double)                  d_vector;\n    typedef CPPAD_TESTVECTOR( CppAD::AD<double> )    ad_vector;\n    typedef CPPAD_TESTVECTOR( CppAD::ADFun<double> ) fun_vector;\n    typedef CPPAD_TESTVECTOR( std::thread* )         sthread_vector;\n    //\n    // std::vector<bool> does not support the data method; see\n    // https://en.cppreference.com/w/cpp/container/vector_bool\n    // 'Does not necessarily store its elements as a contiguous array.'\n    typedef CppAD::vector<bool>                      b_vector;\n    //\n    // thread_id2num_\n    std::map<std::thread::id, size_t> thread_id2num_;\n    //\n    // begin_thread_mutex_\n    std::mutex begin_thread_mutex_;\n    //\n    // sequential_execution_\n    bool sequential_execution_ = true;\n    //\n    // in_parallel\n    bool in_parallel(void)\n    {   return ! sequential_execution_; }\n    //\n    // thread_number\n    size_t thread_number(void)\n    {   std::thread::id thread_id = std::this_thread::get_id();\n        return thread_id2num_.at( thread_id );\n    }\n    //\n    // partial\n    double partial(\n        CppAD::ADFun<double>& f, size_t j, const d_vector& x\n    )\n    {   size_t nx = x.size();\n        d_vector dx(nx), dy(1);\n        for(size_t k = 0; k < nx; ++k)\n            dx[k] = 0.0;\n        dx[j] = 1.0;\n        f.Forward(0, x);\n        dy = f.Forward(1, dx);\n        return dy[0];\n    }\n    //\n    // run_one_thread\n    void run_one_thread(\n        size_t                thread_num     ,\n        CppAD::ADFun<double>* f_ptr          ,\n        size_t                j_begin        ,\n        size_t                j_end          ,\n        const d_vector*       x_ptr          ,\n        d_vector*             Jac_ptr        ,\n        bool*                 ok_ptr         )\n    {   //\n        // begin_thread_mutex_\n        begin_thread_mutex_.lock();\n        begin_thread_mutex_.unlock();\n        //\n        // f, x, Jac, ok\n        CppAD::ADFun<double>& f   = *f_ptr;\n        const d_vector&       x   = *x_ptr;\n        d_vector&             Jac = *Jac_ptr;\n        bool&                 ok  = *ok_ptr;\n        //\n        // ok\n        ok &= thread_number() == thread_num;\n        //\n        // f\n        // This will cause an assert if Taylor coefficients were allocated\n        // by a different thread.\n        f.capacity_order(0);\n        //\n        // Jac\n        for(size_t j = j_begin; j < j_end; ++j)\n            Jac[j] = partial(f, j, x);\n    }\n}\nbool get_started(void)\n{   // ok\n    bool ok = true;\n    //\n    // eps99\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    //\n    // nx, ax\n    size_t nx = 10;\n    ad_vector ax(nx);\n    for(size_t j = 0; j < nx; ++j)\n        ax[j] = 1.0;\n    CppAD::Independent(ax);\n    //\n    // fun\n    ad_vector  ay(1);\n    ay[0] = ax[0];\n    for(size_t j = 1; j < nx; ++j)\n        ay[0] *= ax[j];\n# if USE_DEFAULT_ADFUN_CONSTRUCTOR\n    CppAD::ADFun<double> fun;\n    fun.Dependent(ax, ay);\n# else\n    // This allocates memory for first order Taylor coefficients using thread 0.\n    // An assert will occur at f.capacity_order(0) in run_one_thread when\n    // it is called by a different thread.\n    CppAD::ADFun<double> fun(ax, ay);\n# endif\n    //\n    // num_threads, f_thread, ok_thread\n    size_t num_threads = 4;\n    fun_vector f_thread(num_threads);\n    b_vector   ok_thread(num_threads);\n    for(size_t thread_num = 0; thread_num < num_threads; ++thread_num)\n    {   f_thread[thread_num] = fun;\n        ok_thread[thread_num] = true;\n    }\n    //\n    // x\n    d_vector x(nx);\n    for(size_t j = 0; j < nx; ++j)\n        x[j] = 1.0 + 1.0 / double(j+1);\n    //\n    // thread_id2num_\n    // must setup for this thread before calling parallel_setup\n    thread_id2num_.clear();\n    std::thread::id thread_id  = std::this_thread::get_id();\n    size_t          thread_num = 0;\n    thread_id2num_[thread_id]  = thread_num;\n    //\n    // parallel_setup\n    CppAD::thread_alloc::parallel_setup(\n        num_threads, in_parallel, thread_number\n    );\n    //\n    // parallel_ad\n    CppAD::parallel_ad<double>();\n    //\n    // hold_memory\n    // optional and may improve speed if you do a lot of memory allocation\n    CppAD::thread_alloc::hold_memory(true);\n    //\n    // thread_ptr\n    sthread_vector thread_ptr(num_threads - 1);\n    //\n    // Jac\n    d_vector Jac(nx);\n    //\n    // n_per_thread, n_extra\n    size_t n_per_thread = nx / num_threads;\n    size_t n_extra      = nx % num_threads;\n    //\n    // sequential_execution_\n    sequential_execution_ = false;\n    ok &= in_parallel();\n    //\n    // begin_thread_mutex_\n    begin_thread_mutex_.lock();\n    //\n    // Jac\n    // Launch num_threads - 1 threads\n    size_t j_begin = n_per_thread;\n    size_t j_end;\n    for(thread_num = 1; thread_num < num_threads; ++thread_num)\n    {   j_end = j_begin + n_per_thread;\n        if( thread_num <= n_extra )\n            ++j_end;\n        CppAD::ADFun<double>* f_ptr  = &f_thread[thread_num];\n        bool*                 ok_ptr = &ok_thread[thread_num];\n        thread_ptr[thread_num-1] = new std::thread(\n            run_one_thread, thread_num, f_ptr, j_begin, j_end, &x, &Jac, ok_ptr\n        );\n        //\n        // thread_id2num_\n        thread_id2num_[ thread_ptr[thread_num-1]->get_id() ] = thread_num;\n        //\n        j_begin = j_end;\n    }\n    //\n    // begin_thread_mutex_\n    begin_thread_mutex_.unlock();\n    //\n    ok &= j_end == nx;\n    {   // run master thread's indices\n        thread_num        = 0;\n        j_begin           = 0;\n        j_end             = j_begin + n_per_thread;\n        CppAD::ADFun<double, double>* f_ptr  = &f_thread[thread_num];\n        bool*                         ok_ptr = &ok_thread[thread_num];\n        run_one_thread(thread_num, f_ptr, j_begin, j_end, &x, &Jac, ok_ptr);\n    }\n    // wait for other threads to finish\n    for(thread_num = 1; thread_num < num_threads; ++thread_num)\n    {   thread_ptr[thread_num-1]->join();\n        delete thread_ptr[thread_num-1];\n    }\n    //\n    // sequential_execution_\n    sequential_execution_ = true;\n    CppAD::thread_alloc::parallel_setup(1, nullptr, nullptr);\n    ok &= ! in_parallel();\n    //\n    // hold_memory\n    // free memory for other threads before this (the master thread)\n    ok &= thread_number() == 0;\n    CppAD::thread_alloc::hold_memory(false);\n    for(thread_num = 1; thread_num < num_threads; ++thread_num)\n    {   CppAD::thread_alloc::free_available(thread_num);\n        ok &= ok_thread[thread_num];\n    }\n    ok &= ok_thread[0];\n    CppAD::thread_alloc::free_available(0);\n    //\n    // j\n    for(size_t j = 0; j < nx; ++j)\n    {   //\n        // check\n        double check = 1.0;\n        for(size_t k = 0; k < nx; ++k)\n            if(k != j)\n                check *= x[k];\n        //\n        // ok\n        ok &= CppAD::NearEqual(Jac[j], check, eps99, eps99);\n    }\n    return ok;\n}\n// END_C++\n"
  },
  {
    "path": "example/multi_thread/sthread/team_sthread.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin team_sthread.cpp}\n\nStandard Thread Implementation of a Team of AD Threads\n######################################################\nSee :ref:`team_thread.hpp-name` for this routines specifications.\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end team_sthread.cpp}\n*/\n// BEGIN C++\n# include <thread>\n# include <mutex>\n# include <map>\n# include <cppad/cppad.hpp>\n# include \"../team_thread.hpp\"\n\nnamespace {\n    using CppAD::thread_alloc;\n    //\n    // begin_work_mutex_;\n    std::mutex begin_work_mutex_;\n    //\n    // thread_id2num_\n    std::map< std::thread::id, size_t > thread_id2num_;\n    //\n    // num_threads_\n    // number of threads in this team\n    size_t num_threads_;\n    //\n    // sequential_execution_\n    bool sequential_execution_ = true;\n    //\n    // in_parallel\n    // used to inform CppAD when we are in parallel execution mode\n    bool in_parallel(void)\n    {   return ! sequential_execution_; }\n    //\n    // thread_number\n    // used to inform CppAD of the current thread number\n    size_t thread_number(void)\n    {   return thread_id2num_.at( std::this_thread::get_id() ); }\n}\n// team_create\nbool team_create(size_t num_threads)\n{\n    bool ok = ! in_parallel();\n    ok     &= num_threads > 0;\n    //\n    // thread_id2num_\n    // must setup for this thread before calling parallel_setup\n    thread_id2num_.clear();\n    std::thread::id thread_id  = std::this_thread::get_id();\n    size_t                       thread_num = 0;\n    thread_id2num_[thread_id]  = thread_num;\n    //\n    // setup for using CppAD::AD<double> in parallel\n    thread_alloc::parallel_setup(num_threads, in_parallel, thread_number);\n    thread_alloc::hold_memory(true);\n    CppAD::parallel_ad<double>();\n    //\n    // num_thread_\n    num_threads_ = num_threads;\n    //\n    return ok;\n}\n// work_wrapper\nvoid work_wrapper(void worker(void))\n{   // begin_work_mutex_\n    // wait here while thread_id2num_ is changing\n    begin_work_mutex_.lock();\n    begin_work_mutex_.unlock();\n    //\n    // now go to work\n    worker();\n}\n// team_work\nbool team_work( void worker(void) )\n{   bool ok = sequential_execution_;\n    ok     &= num_threads_ > 0;\n    //\n    // begin_work_mutex_\n    // stop all threads at the beginning of the work routine\n    begin_work_mutex_.lock();\n    //\n    // sequential_execution\n    sequential_execution_ = false;\n    //\n    // thread_ptr\n    CppAD::vector<std::thread*> thread_ptr(num_threads_ - 1);\n    //\n    // thread_num\n    for(size_t thread_num = 1; thread_num < num_threads_; ++thread_num)\n    {   //\n        // thread_ptr\n        thread_ptr[thread_num - 1] = new std::thread(work_wrapper, worker);\n        //\n        // thread_id\n        std::thread::id thread_id = thread_ptr[thread_num-1]->get_id();\n        //\n        // thread_id2num_\n        thread_id2num_[thread_id] = thread_num;\n    }\n    //\n    // begin_work_mutex_\n    // Let the threads go\n    begin_work_mutex_.unlock();\n    //\n    // put this thread to work\n    worker();\n    //\n    // join\n    for(size_t thread_num = 1; thread_num < num_threads_; ++thread_num)\n    {   thread_ptr[thread_num-1]->join();\n        delete thread_ptr[thread_num-1];\n    }\n    //\n    // sequential execution\n    sequential_execution_ = true;\n    //\n    return ok;\n}\n\nbool team_destroy(void)\n{   bool ok = ! in_parallel();\n    ok     &= thread_number() == 0;;\n    ok     &= num_threads_ > 0;\n\n    // inform team_work of number of threads\n    num_threads_ = 1;\n    //\n    // inform CppAD no longer in multi-threading mode\n    thread_alloc::parallel_setup(num_threads_, nullptr, nullptr);\n    thread_alloc::hold_memory(false);\n    CppAD::parallel_ad<double>();\n    //\n    return ok;\n}\n\nconst char* team_name(void)\n{   return \"sthread\"; }\n// END C++\n"
  },
  {
    "path": "example/multi_thread/team_example.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin team_example.cpp}\n{xrst_spell\n    bthread\n    openmp\n    pthread\n}\n\nUsing a Team of AD Threads: Example and Test\n############################################\n\nPurpose\n*******\nThis example demonstrates how use a team of threads with CppAD.\n\nthread_team\n***********\nThe following three implementations of the\n:ref:`team_thread.hpp-name` specifications are included:\n\n.. csv-table::\n    :widths: auto\n\n    team_openmp.cpp,:ref:`team_openmp.cpp-title`\n    team_bthread.cpp,:ref:`team_bthread.cpp-title`\n    team_pthread.cpp,:ref:`team_pthread.cpp-title`\n\nSource Code\n***********\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end team_example.cpp}\n------------------------------------------------------------------------------\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n# include \"team_thread.hpp\"\n# define NUMBER_THREADS  4\n\nnamespace {\n    using CppAD::thread_alloc;\n\n    // structure with information for one thread\n    typedef struct {\n        // function argument (worker input)\n        double          x;\n        // false if an error occurs, true otherwise (worker output)\n        bool            ok;\n    } work_one_t;\n    // vector with information for all threads\n    // (use pointers instead of values to avoid false sharing)\n    work_one_t* work_all_[NUMBER_THREADS];\n    // --------------------------------------------------------------------\n    // function that does the work for one thread\n    void worker(void)\n    {   using CppAD::NearEqual;\n        using CppAD::AD;\n        bool ok = true;\n        size_t thread_num = thread_alloc::thread_num();\n\n        // CppAD::vector uses the CppAD fast multi-threading allocator\n        CppAD::vector< AD<double> > ax(1), ay(1);\n        ax[0] = work_all_[thread_num]->x;\n        Independent(ax);\n        ay[0] = sqrt( ax[0] * ax[0] );\n        CppAD::ADFun<double> f(ax, ay);\n\n        // Check function value corresponds to the identity\n        double eps = 10. * CppAD::numeric_limits<double>::epsilon();\n        ok        &= NearEqual(ay[0], ax[0], eps, eps);\n\n        // Check derivative value corresponds to the identity.\n        CppAD::vector<double> d_x(1), d_y(1);\n        d_x[0] = 1.;\n        d_y    = f.Forward(1, d_x);\n        ok    &= NearEqual(d_x[0], 1., eps, eps);\n\n        // pass back ok information for this thread\n        work_all_[thread_num]->ok = ok;\n    }\n}\n\n// This test routine is only called by the master thread (thread_num = 0).\nbool team_example(void)\n{   bool ok = true;\n\n    size_t num_threads = NUMBER_THREADS;\n\n    // Check that no memory is in use or available at start\n    // (using thread_alloc in sequential mode)\n    size_t thread_num;\n    for(thread_num = 0; thread_num < num_threads; thread_num++)\n    {   ok &= thread_alloc::inuse(thread_num) == 0;\n        ok &= thread_alloc::available(thread_num) == 0;\n    }\n\n    // initialize work_all_\n    for(thread_num = 0; thread_num < num_threads; thread_num++)\n    {   // allocate separate memory for this thread to avoid false sharing\n        size_t min_bytes(sizeof(work_one_t)), cap_bytes;\n        void*  v_ptr = thread_alloc::get_memory(min_bytes, cap_bytes);\n        work_all_[thread_num]     = static_cast<work_one_t*>(v_ptr);\n        // in case this thread's worker does not get called\n        work_all_[thread_num]->ok = false;\n        // parameter that defines the work for this thread\n        work_all_[thread_num]->x  = double(thread_num) + 1.;\n    }\n\n    ok &= team_create(num_threads);\n    ok &= team_work(worker);\n    ok &= team_destroy();\n\n    // go down so that free memrory for other threads before memory for master\n    thread_num = num_threads;\n    while(thread_num--)\n    {   // check that this thread was ok with the work it did\n        ok &= work_all_[thread_num]->ok;\n        // delete problem specific information\n        void* v_ptr = static_cast<void*>( work_all_[thread_num] );\n        thread_alloc::return_memory( v_ptr );\n        // check that there is no longer any memory inuse by this thread\n        // (for general applications, the master might still be using memory)\n        ok &= thread_alloc::inuse(thread_num) == 0;\n        // return all memory being held for future use by this thread\n        thread_alloc::free_available(thread_num);\n    }\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/multi_thread/team_example.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_MULTI_THREAD_TEAM_EXAMPLE_HPP\n# define CPPAD_EXAMPLE_MULTI_THREAD_TEAM_EXAMPLE_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\nextern bool team_example(void);\n\n# endif\n"
  },
  {
    "path": "example/multi_thread/team_thread.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_MULTI_THREAD_TEAM_THREAD_HPP\n# define CPPAD_EXAMPLE_MULTI_THREAD_TEAM_THREAD_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin team_thread.hpp}\n{xrst_spell\n    bthread\n    openmp\n    posix\n    pthread\n    sthread\n}\nSpecifications for A Team of AD Threads\n#######################################\n\nSyntax\n******\n| ``include`` ``\"team_thread.hpp\"``\n| *ok* = ``team_create`` ( *num_threads* )\n| *ok* = ``team_work`` ( *worker* )\n| *ok* = ``team_destroy`` ()\n| *name* = ``team_name`` ()\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN PROTOTYPE\n    // END PROTOTYPE\n}\n\nPurpose\n*******\nThese routines start, use, and stop a team of threads that can\nbe used with the CppAD type ``AD<double>`` .\nExamples are provided for\nOpenMP threads, Posix threads, Boost threads and Standard threads.\n\nRestrictions\n************\nCalls to the routines\n``team_create`` ,\n``team_work`` , and\n``team_destroy`` , must all be done by the master thread; i.e.,\n:ref:`thread_num<ta_thread_num-name>` must be zero.\nIn addition, they must all be done in sequential execution mode; i.e.,\nwhen the master thread is the only thread that is running\n(:ref:`in_parallel<ta_in_parallel-name>` must be false).\n\nteam_create\n***********\nThe argument *num_threads*  > 0\nspecifies the number of threads in this team.\nThis initializes both ``AD<double>`` and ``team_work``\nto be used with *num_threads* .\nIf *num_threads*  > 1 ,\n*num_threads* ``- 1`` new threads are created\nand put in a waiting state until ``team_work`` is called.\n\nteam_work\n*********\nThis routine may be called one or more times\nbetween the call to ``team_create`` and ``team_destroy`` .\nEach call to ``team_work`` runs *num_threads* versions\nof *worker* with the corresponding value of\n:ref:`thread_num<ta_thread_num-name>`\nbetween zero and *num_threads* ``- 1`` and\ndifferent for each thread,\n\nteam_destroy\n************\nThis routine terminates all the other threads except for\nthread number zero; i.e., it terminates the threads corresponding to\n\n    *thread_num* = 1 , ... , *num_threads* ``-1``\n\nteam_name\n*********\nThis routines returns a name that identifies this threading system.\nThe return value is a statically allocated ``'\\0'`` terminated C string.\n\nok\n**\nThe return value *ok*\nis ``false`` if an error is detected during the\ncorresponding call.\nOtherwise it is ``true`` .\n{xrst_toc_hidden\n    example/multi_thread/openmp/team_openmp.cpp\n    example/multi_thread/bthread/team_bthread.cpp\n    example/multi_thread/pthread/team_pthread.cpp\n    example/multi_thread/sthread/team_sthread.cpp\n}\n\nExample Use\n***********\nExample use of these specifications can be found in the file\n:ref:`team_example.cpp-name` .\n\nExample Implementation\n**********************\nExample implementations of these specifications can be found in the files:\n\n.. csv-table::\n    :widths: auto\n\n    team_openmp.cpp,:ref:`team_openmp.cpp-title`\n    team_bthread.cpp,:ref:`team_bthread.cpp-title`\n    team_pthread.cpp,:ref:`team_pthread.cpp-title`\n    team_sthread.cpp,:ref:`team_sthread.cpp-title`\n\nSpeed Test of Implementation\n****************************\nSpeed tests of using CppAD with the team implementations above\ncan be found in:\n\n.. csv-table::\n    :widths: auto\n\n    harmonic.cpp,:ref:`harmonic.cpp-title`\n    multi_newton.cpp,:ref:`multi_newton.cpp-title`\n\n{xrst_end team_thread.hpp}\n*/\n# include <cstddef> // for size_t\n\n// BEGIN PROTOTYPE\nextern bool team_create(size_t num_threads);\nextern bool team_work(void worker(void));\nextern bool team_destroy(void);\nextern const char* team_name(void);\n// END PROTOTYPE\n\n# endif\n"
  },
  {
    "path": "example/multi_thread/template/get_started.xrst",
    "content": "{xrst_comment\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2024 Bradley M. Bell\n\nThis file is intended to help document the multi threading get_started examples\n\nIt has the following xrst template comments:\n    title: Getting Started Using @Name@ Threads With CppAD\n    start source code after: // <space> BEGIN_C++\n    end source code before:  // <space> END_C++\n\nIt has the following xrst template replacements\n    @Name@    : is the name of this threading system\n    @####@    : is the underlining for the name of the threading system\n    @DEFAULT@ : is macro a macro name. If it is 1 (0),\n                    the ADFun default ctor is used (is not used)\n}\n\nGetting Started Using @Name@ Threads With CppAD\n######################@####@###################\n\nin_parallel\n***********\nsee :ref:`ta_parallel_setup@in_parallel` .\n\nthread_number\n*************\nsee :ref:`ta_parallel_setup@thread_num` .\n\nADFun Constructor\n*****************\nIf you use the :ref:`fun_construct@Sequence Constructor` for the original\nfunction, you will need to clear the Taylor coefficient memory associated\nwith the function using :ref:`capacity_order-name` ; e.g. ::\n\n    {xrst_spell_off}\n    CppAD::ADFun fun(ax, ay);\n    fun.capacity_order(0);\n    {xrst_spell_on}\n\nIf you do not free the Taylor coefficient memory in ``fun`` ,\nthe function assignments will allocate zero order Taylor coefficients for each\nfunction in ``fun_thread`` using thread zero. Depending on what you do in\nparallel mode, you may attempt to free that memory using another thread.\nFor example, if you change @DEFAULT@ from 1 to 0, you will\nget the message::\n\n    Attempt to return memory for a different thread while in parallel mode\n\nSource Code\n***********\n{xrst_literal\n    // BEGIN_C++\n    // END_C++\n}\n"
  },
  {
    "path": "example/multi_thread/thread_test.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin thread_test.cpp}\n{xrst_spell\n    posix\n}\n\nRun Multi-Threading Examples and Speed Tests\n############################################\n\nPurpose\n*******\nRuns the CppAD multi-threading examples and timing tests:\n\nbuild\n*****\nWe use *build* for the directory where you run the :ref:`cmake-name`\ncommand.\n\nthreading\n*********\nIf the :ref:`cmake-name` command output indicates that\n``openmp``, ``bthread`` , ``pthread`` , or ``sthread`` is available,\nyou can run the program below with *threading* equal to\n``openmp``, ``bthread`` , ``pthread`` , or ``sthread`` respectively.\n\nprogram\n*******\nWe use the notation *program* for\n\n    ``example_multi_thread_`` *threading*\n\nRunning Tests\n*************\nYou can build this program and run the default version of its test\nparameters by executing the following commands:\n\n| |tab| ``cd`` *build*\n| |tab| ``make check_`` *program*\n\nAfter this operation, in the directory\n\n    *build* / ``example/multi_thread/`` *threading*\n\nyou can execute the following commands:\n\n| .\n| ./ *program* ``a11c``\n| ./ *program* ``get_started``\n| ./ *program* ``team_example``\n| ./ *program* ``harmonic`` *test_time* *max_threads* *mega_sum*\n| ./ *program* ``atomic_two`` *test_time* *max_threads* *num_solve*\n| ./ *program* ``atomic_three`` *test_time* *max_threads* *num_solve*\n| ./ *program* ``chkpoint_one`` *test_time* *max_threads* *num_solve*\n| ./ *program* ``chkpoint_two`` *test_time* *max_threads* *num_solve*\n| ./ *program* ``multi_newton`` *test_time* *max_threads*  \\\\\n| |tab| *num_zero* *num_sub* *num_sum* *use_ad*\n\nWe refer to the values ``a11c`` , ... , ``multi_newton``\nas the *test_case* below.\n{xrst_toc_hidden\n    example/multi_thread/openmp/a11c_openmp.cpp\n    example/multi_thread/bthread/a11c_bthread.cpp\n    example/multi_thread/pthread/a11c_pthread.cpp\n    example/multi_thread/sthread/a11c_sthread.cpp\n    example/multi_thread/openmp/get_started.cpp\n    example/multi_thread/bthread/get_started.cpp\n    example/multi_thread/pthread/get_started.cpp\n    example/multi_thread/sthread/get_started.cpp\n    example/multi_thread/team_example.cpp\n    example/multi_thread/harmonic.xrst\n    example/multi_thread/multi_atomic_three.xrst\n    example/multi_thread/multi_chkpoint_two.xrst\n    example/multi_thread/multi_newton.xrst\n    example/multi_thread/team_thread.hpp\n}\n\na11c\n****\nThe *test_case* ``a11c`` runs the examples\n:ref:`a11c_openmp.cpp-name` ,\n:ref:`a11c_bthread.cpp-name` ,\n:ref:`a11c_pthread.cpp-name` , and\n:ref:`a11c_sthread.cpp-name` .\nThese cases demonstrate simple multi-threading,\nwithout algorithmic differentiation, using\nOpenMP, Boost Posix and Standard threads respectively.\n\nget_started\n***********\nThe *test_case* ``get_started`` runs the examples\n:ref:`openmp_get_started.cpp-name` ,\n:ref:`bthread_get_started.cpp-name` ,\n:ref:`pthread_get_started.cpp-name` , and\n:ref:`sthread_get_started.cpp-name` .\nThese cases demonstrate simple multi-threading,\nwith algorithmic differentiation, using\nOpenMP, Boost Posix and Standard threads respectively.\n\nteam_example\n************\nThe *test_case* ``team_example`` runs the\n:ref:`team_example.cpp-name` example.\nThis case demonstrates simple multi-threading with algorithmic differentiation\nand using a :ref:`team of threads<team_thread.hpp-name>` .\n\ntest_time\n*********\nAll of the other cases include the *test_time* argument.\nThis is the minimum amount of wall clock time that the test should take.\nThe number of repeats for the test will be increased until this time\nis reached.\nThe reported time is the total wall clock time divided by the\nnumber of repeats.\n\nmax_threads\n===========\nAll of the other cases include the *max_threads* argument.\nThis is a non-negative integer specifying\nthe maximum number of threads to use for the test.\nThe specified test is run with the following number of threads:\n\n    *num_threads* = 0 , ... , *max_threads*\n\nThe value of zero corresponds to not using the multi-threading system.\n\n{xrst_comment -------------------------------------------------------------- }\n\nharmonic\n********\nThe *test_case* ``harmonic`` runs the\n:ref:`harmonic_time-name` example.\nThis is a timing test for a multi-threading\nexample without algorithmic differentiation using a team of threads.\n\nmega_sum\n========\nThe command line argument *mega_sum*\nis an integer greater than or equal one and has the same meaning as in\n:ref:`harmonic_time<harmonic_time@mega_sum>` .\n\n{xrst_comment -------------------------------------------------------------- }\n\nAtomic and Checkpoint\n*********************\nThe *test_case* values\n``atomic_two`` ,\n``atomic_three`` ,\n``chkpoint_one`` ,\n``chkpoint_two`` ,\nall run the same problem.\nThese cases preforms a timing test for a multi-threading\nexample without algorithmic differentiation using a team of threads.\n\n.. csv-table::\n    :widths: auto\n\n    *test_case*,Documentation\n    ``atomic_two``,:ref:`multi_atomic_two.cpp-name`\n    ``atomic_three``,:ref:`multi_atomic_three.cpp-name`\n    ``chkpoint_one``,:ref:`multi_chkpoint_one.cpp-name`\n    ``chkpoint_two``,:ref:`multi_chkpoint_two.cpp-name`\n\nnum_solve\n=========\nThe command line argument *num_solve*\nis an integer specifying the number of solves; see\n:ref:`multi_atomic_two_time@num_solve` in ``multi_atomic_two_time`` .\n\n{xrst_comment -------------------------------------------------------------- }\n\nmulti_newton\n************\nThe *test_case* ``multi_newton``  runs the\n:ref:`multi_newton.cpp-name` example.\nThis preforms a timing test for a multi-threading\nexample with algorithmic differentiation using a team of threads.\n\nnum_zero\n========\nThe command line argument *num_zero*\nis an integer greater than or equal two and has the same meaning as in\n:ref:`multi_newton_time<multi_newton_time@num_zero>` .\n\nnum_sub\n=======\nThe command line argument *num_sub*\nis an integer greater than or equal one and has the same meaning as in\n:ref:`multi_newton_time<multi_newton_time@num_sub>` .\n\nnum_sum\n=======\nThe command line argument *num_sum*\nis an integer greater than or equal one and has the same meaning as in\n:ref:`multi_newton_time<multi_newton_time@num_sum>` .\n\nuse_ad\n======\nThe command line argument *use_ad* is either\n``true`` or ``false`` and has the same meaning as in\n:ref:`multi_newton_time<multi_newton_time@use_ad>` .\n\n{xrst_comment -------------------------------------------------------------- }\n\nTeam Implementations\n********************\nThe following routines are used to implement the specific threading\nsystems through the common interface :ref:`team_thread.hpp-name` :\n\n.. csv-table::\n    :widths: auto\n\n    team_openmp.cpp,:ref:`team_openmp.cpp-title`\n    team_bthread.cpp,:ref:`team_bthread.cpp-title`\n    team_pthread.cpp,:ref:`team_pthread.cpp-title`\n    team_sthread.cpp,:ref:`team_sthread.cpp-title`\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end thread_test.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n# include <cmath>\n# include <cstring>\n# include <ctime>\n# include \"team_thread.hpp\"\n# include \"team_example.hpp\"\n# include \"harmonic.hpp\"\n# include \"multi_atomic_two.hpp\"\n# include \"multi_atomic_three.hpp\"\n# include \"multi_chkpoint_one.hpp\"\n# include \"multi_chkpoint_two.hpp\"\n# include \"multi_newton.hpp\"\n\nextern bool a11c(void);\nextern bool get_started(void);\n\nnamespace {\n    size_t arg2size_t(\n        const char* arg       ,\n        int limit             ,\n        const char* error_msg )\n    {   int i = std::atoi(arg);\n        if( i >= limit )\n            return size_t(i);\n        std::cerr << \"value = \" << i << std::endl;\n        std::cerr << error_msg << std::endl;\n        exit(1);\n    }\n    double arg2double(\n        const char* arg       ,\n        double limit          ,\n        const char* error_msg )\n    {   double d = std::atof(arg);\n        if( d >= limit )\n            return d;\n        std::cerr << \"value = \" << d << std::endl;\n        std::cerr << error_msg << std::endl;\n        exit(1);\n    }\n}\n\nint main(int argc, char *argv[])\n{   using CppAD::thread_alloc;\n    bool ok         = true;\n    using std::cout;\n    using std::endl;\n\n    // command line usage message\n    const char* usage =\n    \"./<program> a11c\\n\"\n    \"./<program> get_started\\n\"\n    \"./<program> team_example\\n\"\n    \"./<program> harmonic     test_time max_threads mega_sum\\n\"\n    \"./<program> atomic_two   test_time max_threads num_solve\\n\"\n    \"./<program> atomic_three test_time max_threads num_solve\\n\"\n    \"./<program> chkpoint_one test_time max_threads num_solve\\n\"\n    \"./<program> chkpoint_two test_time max_threads num_solve\\n\"\n    \"./<program> multi_newton test_time max_threads \\\\\\n\"\n    \"   num_zero num_sub num_sum use_ad\\\\\\n\"\n    \"where <program> is example_multi_thread_<threading>\\n\"\n    \"and <threading> is openmp, bthread, pthread, or sthread\";\n\n    // command line argument values (assign values to avoid compiler warnings)\n    size_t num_zero=0, num_sub=0, num_sum=0;\n    bool use_ad=true;\n\n    // put the date and time in the output file\n    std::time_t rawtime;\n    std::time( &rawtime );\n    const char* gmt = std::asctime( std::gmtime( &rawtime ) );\n    size_t len = size_t( std::strlen(gmt) );\n    cout << \"gmtime        = '\";\n    for(size_t i = 0; i < len; i++)\n        if( gmt[i] != '\\n' ) cout << gmt[i];\n    cout << \"';\" << endl;\n\n    // CppAD version number\n    cout << \"cppad_version = '\" << CPPAD_PACKAGE_STRING << \"';\" << endl;\n\n    // put the team name in the output file\n    cout << \"thread_system = '\" << team_name() << \"';\" << endl;\n\n    // print command line as valid matlab/octave\n    cout << \"command       = '\" << argv[0];\n    for(int i = 1; i < argc; i++)\n        cout << \" \" << argv[i];\n    cout << \"';\" << endl;\n\n    ok = false;\n    const char* test_name = \"\";\n    if( argc > 1 )\n        test_name = *++argv;\n    bool run_a11c         = std::strcmp(test_name, \"a11c\")             == 0;\n    bool run_get_started  = std::strcmp(test_name, \"get_started\")      == 0;\n    bool run_team_example = std::strcmp(test_name, \"team_example\")     == 0;\n    bool run_harmonic     = std::strcmp(test_name, \"harmonic\")         == 0;\n    bool run_atomic_two   = std::strcmp(test_name, \"atomic_two\")       == 0;\n    bool run_atomic_three = std::strcmp(test_name, \"atomic_three\")     == 0;\n    bool run_chkpoint_one = std::strcmp(test_name, \"chkpoint_one\")     == 0;\n    bool run_chkpoint_two = std::strcmp(test_name, \"chkpoint_two\")     == 0;\n    bool run_multi_newton = std::strcmp(test_name, \"multi_newton\")     == 0;\n    if( run_a11c || run_get_started || run_team_example )\n        ok = (argc == 2);\n    else if( run_harmonic\n    || run_atomic_two\n    || run_atomic_three\n    || run_chkpoint_one\n    || run_chkpoint_two )\n        ok = (argc == 5);\n    else if( run_multi_newton )\n        ok = (argc == 8);\n    if( ! ok )\n    {   std::cerr << \"test_name     = \" << test_name << endl;\n        std::cerr << \"argc          = \" << argc      << endl;\n        std::cerr << usage << endl;\n        exit(1);\n    }\n    if( run_a11c || run_get_started || run_team_example )\n    {   if( run_a11c )\n            ok        = a11c();\n        else if( run_get_started )\n            ok        = get_started();\n        else\n            ok        = team_example();\n        if( thread_alloc::free_all() )\n            cout << \"free_all      = true;\"  << endl;\n        else\n        {   ok = false;\n            cout << \"free_all      = false;\" << endl;\n        }\n        if( ok )\n            cout << \"OK            = true;\"  << endl;\n        else cout << \"OK            = false;\" << endl;\n        return ! ok;\n    }\n\n    // test_time\n    double test_time = arg2double( *++argv, 0.,\n        \"run: test_time is less than zero\"\n    );\n\n    // max_threads\n    size_t max_threads = arg2size_t( *++argv, 0,\n        \"run: max_threads is less than zero\"\n    );\n\n    size_t mega_sum  = 0; // assignment to avoid compiler warning\n    size_t num_solve = 0;\n    if( run_harmonic )\n    {   // mega_sum\n        mega_sum = arg2size_t( *++argv, 1,\n            \"run: mega_sum is less than one\"\n        );\n    }\n    else if( run_atomic_two\n    || run_atomic_three\n    || run_chkpoint_one\n    || run_chkpoint_two )\n    {   // num_solve\n        num_solve = arg2size_t( *++argv, 1,\n            \"run: num_solve is less than one\"\n        );\n    }\n    else\n    {   ok &= run_multi_newton;\n        if( ! ok )\n        {   cout << \"thread_test: program error\\n\";\n            return ! ok;\n        }\n\n        // num_zero\n        num_zero = arg2size_t( *++argv, 2,\n            \"run: num_zero is less than two\"\n        );\n\n        // num_sub\n        num_sub = arg2size_t( *++argv, 1,\n            \"run: num_sub is less than one\"\n        );\n\n        // num_sum\n        num_sum = arg2size_t( *++argv, 1,\n            \"run: num_sum is less than one\"\n        );\n\n        // use_ad\n        ++argv;\n        if( std::strcmp(*argv, \"true\") == 0 )\n            use_ad = true;\n        else if( std::strcmp(*argv, \"false\") == 0 )\n            use_ad = false;\n        else\n        {   std::cerr << \"run: use_ad = '\" << *argv;\n            std::cerr << \"' is not true or false\" << endl;\n            exit(1);\n        }\n    }\n\n    // run the test for each number of threads\n    cout << \"time_all  = [\" << endl;\n    for(size_t num_threads = 0; num_threads <= max_threads; num_threads++)\n    {   double time_out;\n        bool this_ok;\n\n        // run the requested test\n        if( run_harmonic ) this_ok = harmonic_time(\n            time_out, test_time, num_threads, mega_sum\n        );\n        else if( run_atomic_two ) this_ok = multi_atomic_two_time(\n            time_out, test_time, num_threads, num_solve\n        );\n        else if( run_atomic_three ) this_ok = multi_atomic_three_time(\n            time_out, test_time, num_threads, num_solve\n        );\n        else if( run_chkpoint_one ) this_ok = multi_chkpoint_one_time(\n            time_out, test_time, num_threads, num_solve\n        );\n        else if( run_chkpoint_two ) this_ok = multi_chkpoint_two_time(\n            time_out, test_time, num_threads, num_solve\n        );\n        else\n        {   assert( run_multi_newton);\n            this_ok = multi_newton_time(\n                time_out                ,\n                test_time               ,\n                num_threads             ,\n                num_zero                ,\n                num_sub                 ,\n                num_sum                 ,\n                use_ad\n            );\n        }\n        // time_out\n        cout << std::setw(20) << time_out << \" % \";\n        // num_threads\n        if( num_threads == 0 )\n            cout << \"no threading\";\n        else\n            cout << num_threads << \" threads\";\n        if( this_ok )\n            cout << \" ok\" << endl;\n        else\n            cout << \" error\" << endl;\n        //\n        ok &= this_ok;\n    }\n    cout << \"];\" << endl;\n    //\n    if( thread_alloc::free_all() )\n        cout << \"free_all      = true;\"  << endl;\n    else\n    {   ok = false;\n        cout << \"free_all      = false;\" << endl;\n    }\n    if( ok )\n        cout << \"OK            = true;\"  << endl;\n    else cout << \"OK            = false;\" << endl;\n\n    return  ! ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/optimize/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# Build the example/optimize directory tests\n#\n#\n# BEGIN_SORT_THIS_LINE_PLUS_2\nSET(source_list\n    compare_op.cpp\n    conditional_skip.cpp\n    cumulative_sum.cpp\n    forward_active.cpp\n    nest_conditional.cpp\n    optimize.cpp\n    optimize_twice.cpp\n    print_for.cpp\n    reverse_active.cpp\n)\n# END_SORT_THIS_LINE_MINUS_2\n\nset_compile_flags( example_optimize \"${cppad_debug_which}\" \"${source_list}\" )\n#\nADD_EXECUTABLE(example_optimize EXCLUDE_FROM_ALL ${source_list})\n#\n# List of libraries to be linked into the specified target\nTARGET_LINK_LIBRARIES(example_optimize\n    ${cppad_lib}\n    ${colpack_libs}\n)\n#\n# check_example_optimize\nadd_check_executable(check_example optimize)\n"
  },
  {
    "path": "example/optimize/compare_op.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin optimize_compare_op.cpp}\n\nOptimize Comparison Operators: Example and Test\n###############################################\n\nSee Also\n********\n:ref:`cond_exp.cpp-name`\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end optimize_compare_op.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\nnamespace {\n    struct tape_size { size_t n_var; size_t n_op; };\n\n    template <class Vector> void fun(\n        const std::string& options ,\n        const Vector& x, Vector& y, tape_size& before, tape_size& after\n    )\n    {   typedef typename Vector::value_type scalar;\n\n        // phantom variable with index 0 and independent variables\n        // begin operator, independent variable operators and end operator\n        before.n_var = 1 + x.size(); before.n_op  = 2 + x.size();\n        after.n_var  = 1 + x.size(); after.n_op   = 2 + x.size();\n\n        // Create a variable that is is only used in the comparison operation\n        // It is not used when the comparison operator is not included\n        scalar one = 1. / x[0];\n        before.n_var += 1; before.n_op += 1;\n        after.n_var  += 0; after.n_op  += 0;\n        // If we keep comparison operators, we must compute their operands\n        if( options.find(\"no_compare_op\") == std::string::npos )\n        {   after.n_var += 1;  after.n_op += 1;\n        }\n\n        // Create a variable that is used by the result\n        scalar two = x[0] * 5.;\n        before.n_var += 1; before.n_op += 1;\n        after.n_var  += 1; after.n_op += 1;\n\n        // Only one variable created for this comparison operation\n        // but the value depends on which branch is taken.\n        scalar three;\n        if( one < x[0] )        // comparison operator\n            three = two / 2.0;  // division operator\n        else\n            three = 2.0 * two;  // multiplication operator\n        // comparison and either division of multiplication operator\n        before.n_var += 1; before.n_op += 2;\n        // comparison operator depends on optimization options\n        after.n_var += 1;  after.n_op += 1;\n        // check if we are keeping the comparison operator\n        if( options.find(\"no_compare_op\") == std::string::npos )\n            after.n_op += 1;\n\n        // results for this operation sequence\n        y[0] = three;\n        before.n_var += 0; before.n_op  += 0;\n        after.n_var  += 0; after.n_op   += 0;\n    }\n}\n\nbool compare_op(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps10 = 10.0 * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n  = 1;\n    CPPAD_TESTVECTOR(AD<double>) ax(n);\n    ax[0] = 0.5;\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) ay(m);\n\n    for(size_t k = 0; k < 2; k++)\n    {   // optimization options\n        std::string options = \"\";\n        if( k == 0 )\n            options = \"no_compare_op\";\n\n        // declare independent variables and start tape recording\n        CppAD::Independent(ax);\n\n        // compute function value\n        tape_size before, after;\n        fun(options, ax, ay, before, after);\n\n        // create f: x -> y and stop tape recording\n        CppAD::ADFun<double> f(ax, ay);\n        ok &= f.size_order() == 1; // this constructor does 0 order forward\n        ok &= f.size_var() == before.n_var;\n        ok &= f.size_op() == before.n_op;\n\n        // Optimize the operation sequence\n        f.optimize(options);\n        ok &= f.size_order() == 0; // 0 order forward not present\n        ok &= f.size_var() == after.n_var;\n        ok &= f.size_op() == after.n_op;\n\n        // Check result for a zero order calculation for a different x,\n        // where the result of the comparison is he same.\n        CPPAD_TESTVECTOR(double) x(n), y(m), check(m);\n        x[0] = 0.75;\n        y    = f.Forward(0, x);\n        if ( options == \"\" )\n            ok  &= f.compare_change_number() == 0;\n        fun(options, x, check, before, after);\n        ok &= NearEqual(y[0], check[0], eps10, eps10);\n\n        // Check case where result of the comparison is different\n        // (hence one needs to re-tape to get correct result)\n        x[0] = 2.0;\n        y    = f.Forward(0, x);\n        if ( options == \"\" )\n            ok  &= f.compare_change_number() == 1;\n        fun(options, x, check, before, after);\n        ok  &= std::fabs(y[0] - check[0]) > 0.5;\n    }\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/optimize/conditional_skip.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin optimize_conditional_skip.cpp}\n\nOptimize Conditional Expressions: Example and Test\n##################################################\n\nSee Also\n********\n:ref:`cond_exp.cpp-name`\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end optimize_conditional_skip.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\nnamespace {\n    struct tape_size { size_t n_var; size_t n_op; };\n\n    template <class Vector> void fun(\n        const std::string& options ,\n        const Vector& x, Vector& y, tape_size& before, tape_size& after\n    )\n    {   typedef typename Vector::value_type scalar;\n\n\n        // phantom variable with index 0 and independent variables\n        // begin operator, independent variable operators and end operator\n        before.n_var = 1 + x.size(); before.n_op  = 2 + x.size();\n        after.n_var  = 1 + x.size(); after.n_op   = 2 + x.size();\n\n        // Create a variable that is is only used as left operand\n        // in the comparison operation\n        scalar left = 1. / x[0];\n        before.n_var += 1; before.n_op += 1;\n        after.n_var  += 1; after.n_op  += 1;\n\n        // right operand in comparison operation\n        scalar right  = x[0];\n        before.n_var += 0; before.n_op  += 0;\n        after.n_var  += 0; after.n_op   += 0;\n\n        // Note that the left and right operand in the CondExpLt comparison\n        // are determined at this point. Hence the conditional skip operator\n        // will be inserted here so that the operations mentioned below can\n        // also be skipped during zero order forward mode.\n        if( options.find(\"no_conditional_skip\") == std::string::npos )\n            after.n_op += 1; // for conditional skip operation\n\n        // Create a variable that is only used when comparison result is true\n        // (can be skipped when the comparison result is false)\n        scalar if_true = x[0] * 5.0;\n        before.n_var += 1; before.n_op += 1;\n        after.n_var  += 1; after.n_op  += 1;\n\n        // Create two variables only used when the comparison result is false\n        // (can be skipped when the comparison result is true)\n        scalar temp      = 5.0 + x[0];\n        scalar if_false  = temp * 3.0;\n        before.n_var += 2; before.n_op += 2;\n        after.n_var  += 2; after.n_op  += 2;\n\n        // conditional comparison is 1 / x[0] < x[0]\n        scalar value = CppAD::CondExpLt(left, right, if_true, if_false);\n        before.n_var += 1; before.n_op += 1;\n        after.n_var  += 1; after.n_op  += 1;\n\n        // results for this operation sequence\n        y[0] = value;\n        before.n_var += 0; before.n_op  += 0;\n        after.n_var  += 0; after.n_op   += 0;\n    }\n}\n\nbool conditional_skip(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps10 = 10.0 * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n  = 1;\n    CPPAD_TESTVECTOR(AD<double>) ax(n);\n    ax[0] = 0.5;\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) ay(m);\n\n    for(size_t k = 0; k < 2; k++)\n    {   // optimization options\n        std::string options = \"\";\n        if( k == 0 )\n            options = \"no_conditional_skip\";\n\n        // declare independent variables and start tape recording\n        CppAD::Independent(ax);\n\n        // compute function computation\n        tape_size before, after;\n        fun(options, ax, ay, before, after);\n\n        // create f: x -> y and stop tape recording\n        CppAD::ADFun<double> f(ax, ay);\n        ok &= f.size_order() == 1; // this constructor does 0 order forward\n        ok &= f.size_var() == before.n_var;\n        ok &= f.size_op()  == before.n_op;\n\n        // Optimize the operation sequence\n        f.optimize(options);\n        ok &= f.size_order() == 0; // 0 order forward not present\n        ok &= f.size_var() == after.n_var;\n        ok &= f.size_op()  == after.n_op;\n\n        // Check case where result of the comparison is true (x[0] > 1.0).\n        CPPAD_TESTVECTOR(double) x(n), y(m), check(m);\n        x[0] = 1.75;\n        y    = f.Forward(0, x);\n        fun(options, x, check, before, after);\n        ok &= NearEqual(y[0], check[0], eps10, eps10);\n        if( options == \"\" )\n            ok  &= f.number_skip() == 2;\n        else\n            ok &= f.number_skip() == 0;\n\n        // Check case where result of the comparison is false (x[0] <= 1.0)\n        x[0] = 0.5;\n        y    = f.Forward(0, x);\n        fun(options, x, check, before, after);\n        ok &= NearEqual(y[0], check[0], eps10, eps10);\n        if( options == \"\" )\n            ok  &= f.number_skip() == 1;\n        else\n            ok &= f.number_skip() == 0;\n    }\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/optimize/cumulative_sum.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin optimize_cumulative_sum.cpp}\n\nOptimize Cumulative Sum Operations: Example and Test\n####################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end optimize_cumulative_sum.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nnamespace {\n    struct tape_size { size_t n_var; size_t n_op; };\n\n    template <class Vector> void fun(\n        const Vector& x, Vector& y, tape_size& before, tape_size& after\n    )\n    {   typedef typename Vector::value_type scalar;\n\n        // phantom variable with index 0 and independent variables\n        // begin operator, independent variable operators and end operator\n        before.n_var = 1 + x.size(); before.n_op  = 2 + x.size();\n        after.n_var  = 1 + x.size(); after.n_op   = 2 + x.size();\n\n        // operators that are identical, and that will be made part of the\n        // cumulative summation. Make sure do not replace second variable\n        // using the first and then remove the first as part of the\n        // cumulative summation.\n        scalar first  = x[0] + x[1];\n        scalar second = x[0] + x[1];\n        before.n_var += 2; before.n_op  += 2;\n        after.n_var  += 0; after.n_op   += 0;\n\n        // test that subtractions are also included in cumulative summations\n        scalar third = x[1] - 2.0;\n        before.n_var += 1; before.n_op  += 1;\n        after.n_var  += 0; after.n_op   += 0;\n\n        // the finial summation is converted to a cumulative summation\n        // the other is removed.\n        scalar csum = first + second + third;\n        before.n_var += 2; before.n_op  += 2;\n        after.n_var  += 1; after.n_op   += 1;\n\n        // results for this operation sequence\n        y[0] = csum;\n        before.n_var += 0; before.n_op  += 0;\n        after.n_var  += 0; after.n_op   += 0;\n    }\n}\nbool cumulative_sum(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps10 = 10.0 * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n  = 2;\n    CPPAD_TESTVECTOR(AD<double>) ax(n);\n    ax[0] = 0.5;\n    ax[1] = 1.5;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(ax);\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) ay(m);\n    tape_size before, after;\n    fun(ax, ay, before, after);\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(ax, ay);\n    ok &= f.size_order() == 1; // this constructor does 0 order forward\n    ok &= f.size_var() == before.n_var;\n    ok &= f.size_op()  == before.n_op;\n\n    // Optimize the operation sequence\n    f.optimize();\n    ok &= f.size_order() == 0; // 0 order forward not present\n    ok &= f.size_var() == after.n_var;\n    ok &= f.size_op()  == after.n_op;\n\n    // Check result for a zero order calculation for a different x,\n    CPPAD_TESTVECTOR(double) x(n), y(m), check(m);\n    x[0] = 0.75;\n    x[1] = 2.25;\n    y    = f.Forward(0, x);\n    fun(x, check, before, after);\n    ok  &= CppAD::NearEqual(y[0], check[0], eps10, eps10);\n\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/optimize/forward_active.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin optimize_forward_active.cpp}\n\nOptimize Forward Activity Analysis: Example and Test\n####################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end optimize_forward_active.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\nnamespace {\n    struct tape_size { size_t n_var; size_t n_op; };\n\n    template <class Vector> void fun(\n        const Vector& x, Vector& y, tape_size& before, tape_size& after\n    )\n    {   typedef typename Vector::value_type scalar;\n\n        // phantom variable with index 0 and independent variables\n        // begin operator, independent variable operators and end operator\n        before.n_var = 1 + x.size(); before.n_op  = 2 + x.size();\n        after.n_var  = 1 + x.size(); after.n_op   = 2 + x.size();\n\n        // adding the constant zero does not take any operations\n        scalar zero   = 0.0 + x[0];\n        before.n_var += 0; before.n_op  += 0;\n        after.n_var  += 0; after.n_op   += 0;\n\n        // multiplication by the constant one does not take any operations\n        scalar one    = 1.0 * x[1];\n        before.n_var += 0; before.n_op  += 0;\n        after.n_var  += 0; after.n_op   += 0;\n\n        // multiplication by the constant zero does not take any operations\n        // and results in the constant zero.\n        scalar two    = 0.0 * x[0];\n\n        // operations that only involve constants do not take any operations\n        scalar three  = (1.0 + two) * 3.0;\n        before.n_var += 0; before.n_op  += 0;\n        after.n_var  += 0; after.n_op   += 0;\n\n        // The optimizer will recognize that zero + one = one + zero\n        // for all values of x.\n        scalar four   = zero + one;\n        scalar five   = one  + zero;\n        before.n_var += 2; before.n_op  += 2;\n        after.n_var  += 1; after.n_op   += 1;\n\n        // The optimizer will recognize that sin(x[3]) = sin(x[3])\n        // for all values of x. Note that, for computation of derivatives,\n        // sin(x[3]) and cos(x[3]) are stored on the tape as a pair.\n        scalar six    = sin(x[2]);\n        scalar seven  = sin(x[2]);\n        before.n_var += 4; before.n_op  += 2;\n        after.n_var  += 2; after.n_op   += 1;\n\n        // If we used addition here, five + seven = zero + one + seven\n        // which would get converted to a cumulative summation operator.\n        scalar eight = five * seven;\n        before.n_var += 1; before.n_op  += 1;\n        after.n_var  += 1; after.n_op   += 1;\n\n        // Use two, three, four and six in order to avoid a compiler warning\n        // Note that addition of two and three does not take any operations.\n        // Also note that optimizer recognizes four * six == five * seven.\n        scalar nine  = eight + four * six * (two + three);\n        before.n_var += 3; before.n_op  += 3;\n        after.n_var  += 2; after.n_op   += 2;\n\n        // results for this operation sequence\n        y[0] = nine;\n        before.n_var += 0; before.n_op  += 0;\n        after.n_var  += 0; after.n_op   += 0;\n    }\n}\n\nbool forward_active(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps10 = 10.0 * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n  = 3;\n    CPPAD_TESTVECTOR(AD<double>) ax(n);\n    ax[0] = 0.5;\n    ax[1] = 1.5;\n    ax[2] = 2.0;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(ax);\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) ay(m);\n    tape_size before, after;\n    fun(ax, ay, before, after);\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(ax, ay);\n    ok &= f.size_order() == 1; // this constructor does 0 order forward\n    ok &= f.size_var() == before.n_var;\n    ok &= f.size_op()  == before.n_op;\n\n    // Optimize the operation sequence\n    // Note that, for this case, all the optimization was done during\n    // the recording and there is no benefit to the optimization.\n    f.optimize();\n    ok &= f.size_order() == 0; // 0 order forward not present\n    ok &= f.size_var() == after.n_var;\n    ok &= f.size_op()  == after.n_op;\n\n    // check zero order forward with different argument value\n    CPPAD_TESTVECTOR(double) x(n), y(m), check(m);\n    for(size_t i = 0; i < n; i++)\n        x[i] = double(i + 2);\n    y    = f.Forward(0, x);\n    fun(x, check, before, after);\n    ok &= NearEqual(y[0], check[0], eps10, eps10);\n\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/optimize/nest_conditional.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin optimize_nest_conditional.cpp}\n\nOptimize Nested Conditional Expressions: Example and Test\n#########################################################\n\nSee Also\n********\n:ref:`cond_exp.cpp-name`\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end optimize_nest_conditional.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\nnamespace {\n    struct tape_size { size_t n_var; size_t n_op; };\n\n    template <class Vector> void fun(\n        const std::string& options ,\n        const Vector& x, Vector& y, tape_size& before, tape_size& after\n    )\n    {   typedef typename Vector::value_type scalar;\n\n        // phantom variable with index 0 and independent variables\n        // begin operator, independent variable operators and end operator\n        before.n_var = 1 + x.size(); before.n_op  = 2 + x.size();\n        after.n_var  = 1 + x.size(); after.n_op   = 2 + x.size();\n\n        // Create a variable that is is only used in the second comparison\n        scalar two = 1. + x[0];\n        before.n_var += 1; before.n_op += 1;\n        after.n_var  += 1; after.n_op  += 1;\n\n        // Conditional skip for second comparison will be inserted here.\n        if( options.find(\"no_conditional_skip\") == std::string::npos )\n            after.n_op += 1; // for conditional skip operation\n\n        // Create a variable that is is only used in the first comparison\n        // (can be skipped when second comparison result is false)\n        scalar one = 1. / x[0];\n        before.n_var += 1; before.n_op += 1;\n        after.n_var  += 1; after.n_op  += 1;\n\n        // Conditional skip for first comparison will be inserted here.\n        if( options.find(\"no_conditional_skip\") == std::string::npos )\n            after.n_op += 1; // for conditional skip operation\n\n        // value when first comparison if false\n        scalar one_false = 5.0;\n\n        // Create a variable that is only used when second comparison is true\n        // (can be skipped when it is false)\n        scalar one_true = x[0] / 5.0;\n        before.n_var += 1; before.n_op += 1;\n        after.n_var  += 1; after.n_op  += 1;\n\n        // value when second comparison is false\n        scalar two_false = 3.0;\n\n        // First conditional compaison is 1 / x[0] < x[0]\n        // is only used when second conditional expression is true\n        // (can be skipped when it is false)\n        scalar two_true  = CppAD::CondExpLt(one, x[0], one_true, one_false);\n        before.n_var += 1; before.n_op += 1;\n        after.n_var  += 1; after.n_op  += 1;\n\n        // Second conditional compaison is 1 + x[0] < x[1]\n        scalar two_value = CppAD::CondExpLt(two, x[1], two_true, two_false);\n        before.n_var += 1; before.n_op += 1;\n        after.n_var  += 1; after.n_op  += 1;\n\n        // results for this operation sequence\n        y[0] = two_value;\n        before.n_var += 0; before.n_op  += 0;\n        after.n_var  += 0; after.n_op   += 0;\n    }\n}\n\nbool nest_conditional(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps10 = 10.0 * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n  = 2;\n    CPPAD_TESTVECTOR(AD<double>) ax(n);\n    ax[0] = 0.5;\n    ax[1] = 0.5;\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) ay(m);\n\n    for(size_t k = 0; k < 2; k++)\n    {   // optimization options\n        std::string options = \"\";\n        if( k == 0 )\n            options = \"no_conditional_skip\";\n\n        // declare independent variables and start tape recording\n        CppAD::Independent(ax);\n\n        // compute function computation\n        tape_size before, after;\n        fun(options, ax, ay, before, after);\n\n        // create f: x -> y and stop tape recording\n        CppAD::ADFun<double> f(ax, ay);\n        ok &= f.size_order() == 1; // this constructor does 0 order forward\n        ok &= f.size_var() == before.n_var;\n        ok &= f.size_op()  == before.n_op;\n\n        // Optimize the operation sequence\n        f.optimize(options);\n        ok &= f.size_order() == 0; // 0 order forward not present\n        ok &= f.size_var() == after.n_var;\n        ok &= f.size_op()  == after.n_op;\n\n        // Check case where result of the second comparison is true\n        // and first comparison is true\n        CPPAD_TESTVECTOR(double) x(n), y(m), check(m);\n        x[0] = 1.75;\n        x[1] = 4.0;\n        y    = f.Forward(0, x);\n        fun(options, x, check, before, after);\n        ok &= NearEqual(y[0], check[0], eps10, eps10);\n        ok  &= f.number_skip() == 0;\n\n        // Check case where result of the second comparison is true\n        // and first comparison is false\n        x[0] = 0.5;\n        x[1] = 4.0;\n        y    = f.Forward(0, x);\n        fun(options, x, check, before, after);\n        ok &= NearEqual(y[0], check[0], eps10, eps10);\n        if( options == \"\" )\n            ok  &= f.number_skip() == 1;\n        else\n            ok &= f.number_skip() == 0;\n\n        // Check case where result of the second comparison is false\n        // and first comparison is true\n        x[0] = 1.75;\n        x[1] = 0.0;\n        y    = f.Forward(0, x);\n        fun(options, x, check, before, after);\n        ok &= NearEqual(y[0], check[0], eps10, eps10);\n        if( options == \"\" )\n            ok  &= f.number_skip() == 3;\n        else\n            ok &= f.number_skip() == 0;\n\n        // Check case where result of the second comparison is false\n        // and first comparison is false\n        x[0] = 0.5;\n        x[1] = 0.0;\n        y    = f.Forward(0, x);\n        fun(options, x, check, before, after);\n        ok &= NearEqual(y[0], check[0], eps10, eps10);\n        if( options == \"\" )\n            ok  &= f.number_skip() == 3;\n        else\n            ok &= f.number_skip() == 0;\n    }\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/optimize/optimize.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin optimize.cpp}\n\noptimize Examples and Tests Driver\n##################################\n\nRunning These Tests\n*******************\nAfter executing the :ref:`cmake-name` command\nform the :ref:`download@Distribution Directory`,\nyou can build and run these tests with the commands::\n\n    cd build\n    make check_example_optimize\n\nNote that your choice of :ref:`cmake@generator` may require using\nan different version of make; e.g., ``ninja`` .\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end optimize.cpp}\n-------------------------------------------------------------------------------\n*/\n// BEGIN C++\n// for thread_alloc\n# include <cppad/utility/thread_alloc.hpp>\n\n// test runner\n# include <cppad/utility/test_boolofvoid.hpp>\n\n// external complied tests\nextern bool compare_op(void);\nextern bool conditional_skip(void);\nextern bool cumulative_sum(void);\nextern bool forward_active(void);\nextern bool nest_conditional(void);\nextern bool print_for(void);\nextern bool reverse_active(void);\nextern bool optimize_twice(void);\n\n// main program that runs all the tests\nint main(void)\n{   std::string group = \"example/optimize\";\n    size_t      width = 20;\n    CppAD::test_boolofvoid Run(group, width);\n\n    // This line is used by test_one.sh\n\n    // external compiled tests\n    Run( cumulative_sum,      \"compare_op\"         );\n    Run( cumulative_sum,      \"cumulative_sum\"     );\n    Run( conditional_skip,    \"conditional_skip\"   );\n    Run( forward_active,      \"forward_active\"     );\n    Run( nest_conditional,    \"nest_conditional\"   );\n    Run( print_for,           \"print_for\"          );\n    Run( reverse_active,      \"reverse_active\"     );\n    Run( optimize_twice,         \"re_optimize\"        );\n    //\n    // check for memory leak\n    bool memory_ok = CppAD::thread_alloc::free_all();\n    // print summary at end\n    bool ok = Run.summary(memory_ok);\n    //\n    return static_cast<int>( ! ok );\n}\n// END C++\n"
  },
  {
    "path": "example/optimize/optimize_twice.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin optimize_twice.cpp}\n\nOptimizing Twice: Example and Test\n##################################\n\nDiscussion\n**********\nBefore 2019-06-28, optimizing twice was not supported and would fail\nif cumulative sum operators were present after the first optimization.\nThis is now supported but it is not expected to have much benefit.\nIf you find a case where it does have a benefit, please inform the CppAD\ndevelopers of this.\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end optimize_twice.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\nbool optimize_twice(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::vector;\n\n    size_t n = 3;\n    vector< AD<double> > ax(n);\n    for(size_t j = 0; j < n; ++j)\n        ax[j] = 0.0;\n    Independent(ax);\n    //\n    AD<double> asum = 0.0;\n    for(size_t j = 0; j < n; ++j)\n        asum += ax[j];\n    //\n    vector< AD<double> > ay(1);\n    ay[0] = asum * asum;\n    //\n    // This method of recording the function does not do a 0 order forward\n    CppAD::ADFun<double> f;\n    f.Dependent(ax, ay);\n    ok &= f.size_order() == 0;\n    size_t size_var = f.size_var();\n    //\n    f.optimize(); // creates a cumulative sum operator\n    ok &= f.size_var() <= size_var - (n - 2);\n    size_var = f.size_var();\n    //\n    f.optimize(); // optimizes a function with a cumulative sum operator\n    ok &= f.size_var() == size_var; // no benefit expected by second optimize\n    //\n    // zero order forward\n    vector<double> x(n), y(1);\n    double sum = 0.0;\n    for(size_t j = 0; j < n; ++j)\n    {   x[j]  = double(j + 1);\n        sum  += x[j];\n    }\n    y     = f.Forward(0, x);\n    double check = sum * sum;\n    ok &= y[0] == check;\n    //\n    vector<double> w(1), dx(n);\n    w[0] = 1.0;\n    dx   = f.Reverse(1, w);\n    //\n    for(size_t j = 0; j < n; ++j)\n        ok &= dx[j] == 2.0 * sum;\n    //\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/optimize/print_for.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin optimize_print_for.cpp}\n\nOptimize Print Forward Operators: Example and Test\n##################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end optimize_print_for.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nnamespace {\n    struct tape_size { size_t n_var; size_t n_op; };\n\n    void PrintFor(\n        double pos, const char* before, double var, const char* after\n    )\n    {   if( pos <= 0.0 )\n            std::cout << before << var << after;\n        return;\n    }\n    template <class Vector> void fun(\n        const std::string& options ,\n        const Vector& x, Vector& y, tape_size& before, tape_size& after\n    )\n    {   typedef typename Vector::value_type scalar;\n\n        // phantom variable with index 0 and independent variables\n        // begin operator, independent variable operators and end operator\n        before.n_var = 1 + x.size(); before.n_op  = 2 + x.size();\n        after.n_var  = 1 + x.size(); after.n_op   = 2 + x.size();\n\n        // Argument to PrintFor is only needed\n        // if we are keeping print forward operators\n        scalar minus_one = x[0] - 1.0;\n        before.n_var += 1; before.n_op += 1;\n        if( options.find(\"no_print_for_op\") == std::string::npos )\n        {   after.n_var += 1;  after.n_op += 1;\n        }\n\n        // print argument to log function minus one, if it is <= 0\n        PrintFor(minus_one, \"minus_one == \", minus_one , \" is <=  0\\n\");\n        before.n_var += 0; before.n_op += 1;\n        if( options.find(\"no_print_for_op\") == std::string::npos )\n        {   after.n_var += 0;  after.n_op += 1;\n        }\n\n        // now compute log\n        y[0] = log( x[0] );\n        before.n_var += 1; before.n_op += 1;\n        after.n_var  += 1; after.n_op  += 1;\n    }\n}\n\nbool print_for(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps10 = 10.0 * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n  = 1;\n    CPPAD_TESTVECTOR(AD<double>) ax(n);\n    ax[0] = 1.5;\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) ay(m);\n\n    for(size_t k = 0; k < 2; k++)\n    {   // optimization options\n        std::string options = \"\";\n        if( k == 0 )\n            options = \"no_print_for_op\";\n\n        // declare independent variables and start tape recording\n        CppAD::Independent(ax);\n\n        // compute function value\n        tape_size before, after;\n        fun(options, ax, ay, before, after);\n\n        // create f: x -> y and stop tape recording\n        CppAD::ADFun<double> f(ax, ay);\n        ok &= f.size_order() == 1; // this constructor does 0 order forward\n        ok &= f.size_var() == before.n_var;\n        ok &= f.size_op() == before.n_op;\n\n        // Optimize the operation sequence\n        f.optimize(options);\n        ok &= f.size_order() == 0; // 0 order forward not present\n        ok &= f.size_var() == after.n_var;\n        ok &= f.size_op() == after.n_op;\n\n        // Check result for a zero order calculation for a different x\n        CPPAD_TESTVECTOR(double) x(n), y(m), check(m);\n        x[0] = 2.75;\n        y    = f.Forward(0, x);\n        fun(options, x, check, before, after);\n        ok &= NearEqual(y[0], check[0], eps10, eps10);\n    }\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/optimize/reverse_active.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin optimize_reverse_active.cpp}\n\nOptimize Reverse Activity Analysis: Example and Test\n####################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end optimize_reverse_active.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\nnamespace {\n    struct tape_size { size_t n_var; size_t n_op; };\n\n    template <class Vector> void fun(\n        const Vector& x, Vector& y, tape_size& before, tape_size& after\n    )\n    {   typedef typename Vector::value_type scalar;\n\n        // phantom variable with index 0 and independent variables\n        // begin operator, independent variable operators and end operator\n        before.n_var = 1 + x.size(); before.n_op  = 2 + x.size();\n        after.n_var  = 1 + x.size(); after.n_op   = 2 + x.size();\n\n        // initialized product of even and odd variables\n        scalar prod_even = x[0];\n        scalar prod_odd  = x[1];\n        before.n_var += 0; before.n_op  += 0;\n        after.n_var  += 0; after.n_op   += 0;\n        //\n        // compute product of even and odd variables\n        for(size_t i = 2; i < size_t( x.size() ); i++)\n        {   if( i % 2 == 0 )\n            {   // prod_even will affect dependent variable\n                prod_even = prod_even * x[i];\n                before.n_var += 1; before.n_op += 1;\n                after.n_var  += 1; after.n_op  += 1;\n            }\n            else\n            {   // prod_odd will not affect dependent variable\n                prod_odd  = prod_odd * x[i];\n                before.n_var += 1; before.n_op += 1;\n                after.n_var  += 0; after.n_op  += 0;\n            }\n        }\n\n        // dependent variable for this operation sequence\n        y[0] = prod_even;\n        before.n_var += 0; before.n_op  += 0;\n        after.n_var  += 0; after.n_op   += 0;\n    }\n}\n\nbool reverse_active(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps10 = 10.0 * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n  = 6;\n    CPPAD_TESTVECTOR(AD<double>) ax(n);\n    for(size_t i = 0; i < n; i++)\n        ax[i] = AD<double>(i + 1);\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(ax);\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) ay(m);\n    tape_size before, after;\n    fun(ax, ay, before, after);\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(ax, ay);\n    ok &= f.size_order() == 1; // this constructor does 0 order forward\n    ok &= f.size_var() == before.n_var;\n    ok &= f.size_op()  == before.n_op;\n\n    // Optimize the operation sequence\n    f.optimize();\n    ok &= f.size_order() == 0; // 0 order forward not present\n    ok &= f.size_var() == after.n_var;\n    ok &= f.size_op()  == after.n_op;\n\n    // check zero order forward with different argument value\n    CPPAD_TESTVECTOR(double) x(n), y(m), check(m);\n    for(size_t i = 0; i < n; i++)\n        x[i] = double(i + 2);\n    y    = f.Forward(0, x);\n    fun(x, check, before, after);\n    ok &= NearEqual(y[0], check[0], eps10, eps10);\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/print_for/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# Build the example/print_for directory tests\n#\nSET(source_list print_for.cpp)\n#\nset_compile_flags( example_print_for \"${cppad_debug_which}\" \"${source_list}\" )\n#\nADD_EXECUTABLE(example_print_for EXCLUDE_FROM_ALL ${source_list})\n#\n# List of libraries to be linked into the specified target\nTARGET_LINK_LIBRARIES(example_print_for\n    ${cppad_lib}\n    ${colpack_libs}\n)\n# check_example_print_for\nadd_check_executable(check_example print_for)\n"
  },
  {
    "path": "example/print_for/print_for.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin print_for_cout.cpp}\n\nPrinting During Forward Mode: Example and Test\n##############################################\n\nRunning\n*******\nTo build this program and run its correctness test see :ref:`cmake_check-name` .\n\nSource Code\n***********\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <cppad/cppad.hpp>\n\nnamespace {\n    using std::cout;\n    using std::endl;\n    using CppAD::AD;\n\n    // use of PrintFor to check for invalid function arguments\n    AD<double> check_log(const AD<double>& y)\n    {  // check during recording\n        if( y <= 0. )\n            cout << \"check_log: y = \" << y << \" is <= 0\" << endl;\n\n        // check during zero order forward calculation\n        PrintFor(y, \"check_log: y == \", y , \" which is <= 0\\n\");\n\n        return log(y);\n    }\n}\n\nvoid print_for(void)\n{  using CppAD::PrintFor;\n\n    // independent variable vector\n    size_t n = 1;\n    CPPAD_TESTVECTOR(AD<double>) ax(n);\n    ax[0] = 1.;\n    Independent(ax);\n\n    // print a VecAD<double>::reference object that is a parameter\n    CppAD::VecAD<double> av(1);\n    AD<double> Zero(0);\n    av[Zero] = 0.;\n    PrintFor(\"v[0] = \", av[Zero]);\n\n    // Print a newline to separate this from previous output,\n    // then print an AD<double> object that is a variable.\n    PrintFor(\"\\nv[0] + x[0] = \", av[0] + ax[0]);\n\n    // A conditional print that will not generate output when x[0] = 2.\n    PrintFor(ax[0], \"\\n  2. + x[0] = \",   2. + ax[0], \"\\n\");\n\n    // A conditional print that will generate output when x[0] = 2.\n    PrintFor(ax[0] - 2., \"\\n  3. + x[0] = \",   3. + ax[0], \"\\n\");\n\n    // A log evaluations that will result in an error message when x[0] = 2.\n    AD<double> var     = 2. - ax[0];\n    AD<double> log_var = check_log(var);\n\n    // dependent variable vector\n    size_t m = 2;\n    CPPAD_TESTVECTOR(AD<double>) ay(m);\n    ay[0] = av[Zero] + ax[0];\n\n    // define f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(ax, ay);\n\n    // zero order forward with x[0] = 2\n    CPPAD_TESTVECTOR(double) x(n);\n    x[0] = 2.;\n\n    cout << \"v[0] = 0\" << endl;\n    cout << \"v[0] + x[0] = 2\" << endl;\n    cout << \"  3. + x[0] = 5\" << endl;\n    cout << \"check_log: y == 0 which is <= 0\" << endl;\n    // ./makefile.am expects \"Test passes\" at beginning of next output line\n    cout << \"Test passes if four lines above repeat below:\" << endl;\n    f.Forward(0, x);\n\n    return;\n}\nint main(void)\n{  print_for();\n\n    return 0;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\nOutput\n******\nExecuting the program above generates the following output:\n::\n\n    v[0] = 0\n    v[0] + x[0] = 2\n    Test passes if two lines above repeat below:\n    v[0] = 0\n    v[0] + x[0] = 2\n\n{xrst_end print_for_cout.cpp}\n*/\n"
  },
  {
    "path": "example/print_for/test.sh",
    "content": "#! /bin/bash -e\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n./print_for | tee test.log\nsed -e '/^Test passes/,\\$$d' < test.log > test.1\nsed -e '1,/^Test passes/d'   < test.log > test.2\nif ! diff test.1 test.2 ; then exit 1 ; fi\n"
  },
  {
    "path": "example/sparse/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n#\n# BEGIN_SORT_THIS_LINE_PLUS_2\nSET(source_list sparse.cpp\n    colpack_hes.cpp\n    colpack_hessian.cpp\n    colpack_jac.cpp\n    colpack_jacobian.cpp\n    conj_grad.cpp\n    dependency.cpp\n    for_hes_sparsity.cpp\n    for_jac_sparsity.cpp\n    for_sparse_hes.cpp\n    for_sparse_jac.cpp\n    rc_sparsity.cpp\n    rev_hes_sparsity.cpp\n    rev_jac_sparsity.cpp\n    rev_sparse_hes.cpp\n    rev_sparse_jac.cpp\n    sparse_hes.cpp\n    sparse_hessian.cpp\n    sparse_jac_for.cpp\n    sparse_jac_rev.cpp\n    sparse_jacobian.cpp\n    sparse_sub_hes.cpp\n    sparsity_sub.cpp\n    sub_sparse_hes.cpp\n    subgraph_hes2jac.cpp\n    subgraph_jac_rev.cpp\n    subgraph_reverse.cpp\n    subgraph_sparsity.cpp\n)\n# END_SORT_THIS_LINE_MINUS_2\n\nIF( cppad_has_eigen )\n    SET(source_list sparse2eigen.cpp ${source_list} )\nENDIF( cppad_has_eigen )\n\nset_compile_flags( example_sparse \"${cppad_debug_which}\" \"${source_list}\" )\n#\nADD_EXECUTABLE(example_sparse EXCLUDE_FROM_ALL ${source_list})\n\n# List of libraries to be linked into the specified target\nTARGET_LINK_LIBRARIES(example_sparse\n    ${cppad_lib}\n    ${colpack_libs}\n)\n\n# check_example_sparse\nadd_check_executable(check_example sparse)\n"
  },
  {
    "path": "example/sparse/colpack_hes.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin colpack_hes.cpp}\n\nColPack: Sparse Hessian Example and Test\n########################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end colpack_hes.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\nbool colpack_hes(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    typedef CPPAD_TESTVECTOR(AD<double>)            a_vector;\n    typedef CPPAD_TESTVECTOR(double)                d_vector;\n    typedef CppAD::vector<size_t>                   i_vector;\n    typedef CppAD::sparse_rc<i_vector>              sparsity;\n    typedef CppAD::sparse_rcv<i_vector, d_vector>   sparse_matrix;\n    double eps = 10. * CppAD::numeric_limits<double>::epsilon();\n    //\n    // domain space vector\n    size_t n = 5;\n    a_vector  a_x(n);\n    for(size_t j = 0; j < n; j++)\n        a_x[j] = AD<double> (0);\n    //\n    // declare independent variables and starting recording\n    CppAD::Independent(a_x);\n\n    // colpack example case where hessian is a spear head\n    // i.e, H(i, j) non zero implies i = 0, j = 0, or i = j\n    AD<double> sum = 0.0;\n    // partial_0 partial_j = x[j]\n    // partial_j partial_j = x[0]\n    for(size_t j = 1; j < n; j++)\n        sum += a_x[0] * a_x[j] * a_x[j] / 2.0;\n    //\n    // partial_i partial_i = 2 * x[i]\n    for(size_t i = 0; i < n; i++)\n        sum += a_x[i] * a_x[i] * a_x[i] / 3.0;\n\n    // declare dependent variables\n    size_t m = 1;\n    a_vector  a_y(m);\n    a_y[0] = sum;\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(a_x, a_y);\n\n    // new value for the independent variable vector\n    d_vector x(n);\n    for(size_t j = 0; j < n; j++)\n        x[j] = double(j + 1);\n\n    /*\n             [ 2  2  3  4  5 ]\n    hes = [ 2  5  0  0  0 ]\n             [ 3  0  7  0  0 ]\n             [ 4  0  0  9  0 ]\n             [ 5  0  0  0 11 ]\n    */\n    // Normally one would use CppAD to compute sparsity pattern, but for this\n    // example we set it directly\n    size_t nr  = n;\n    size_t nc  = n;\n    size_t nnz = n + 2 * (n - 1);\n    sparsity pattern(nr, nc, nnz);\n    for(size_t k = 0; k < n; k++)\n    {   size_t r = k;\n        size_t c = k;\n        pattern.set(k, r, c);\n    }\n    for(size_t i = 1; i < n; i++)\n    {   size_t k = n + 2 * (i - 1);\n        size_t r = i;\n        size_t c = 0;\n        pattern.set(k,   r, c);\n        pattern.set(k+1, c, r);\n    }\n\n    // subset of elements to compute\n    // (only compute lower triangle)\n    nnz = n + (n - 1);\n    sparsity lower_triangle(nr, nc, nnz);\n    d_vector check(nnz);\n    for(size_t k = 0; k < n; k++)\n    {   size_t r = k;\n        size_t c = k;\n        lower_triangle.set(k, r, c);\n        check[k] = 2.0 * x[k];\n        if( k > 0 )\n            check[k] += x[0];\n    }\n    for(size_t j = 1; j < n; j++)\n    {   size_t k = n + (j - 1);\n        size_t r = 0;\n        size_t c = j;\n        lower_triangle.set(k, r, c);\n        check[k] = x[c];\n    }\n    sparse_matrix subset( lower_triangle );\n\n    // check results for both CppAD and Colpack\n    for(size_t i_method = 0; i_method < 4; i_method++)\n    {   // coloring method\n        std::string coloring;\n        switch(i_method)\n        {   case 0:\n            coloring = \"cppad.symmetric\";\n            break;\n\n            case 1:\n            coloring = \"cppad.general\";\n            break;\n\n            case 2:\n            coloring = \"colpack.symmetric\";\n            break;\n\n            case 3:\n            coloring = \"colpack.general\";\n            break;\n        }\n        //\n        // compute Hessian\n        CppAD::sparse_hes_work work;\n        d_vector w(m);\n        w[0] = 1.0;\n        size_t n_sweep = f.sparse_hes(\n            x, w, subset, pattern, coloring, work\n        );\n        //\n        // check result\n        const d_vector& hes( subset.val() );\n        for(size_t k = 0; k < nnz; k++)\n            ok &= NearEqual(check[k], hes[k], eps, eps);\n        if(\n            coloring == \"cppad.symmetric\"\n        ||  coloring == \"colpack.symmetric\"\n        )\n            ok &= n_sweep == 2;\n        else\n            ok &= n_sweep == 5;\n    }\n\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/sparse/colpack_hessian.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin colpack_hessian.cpp}\n\nColPack: Sparse Hessian Example and Test\n########################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end colpack_hessian.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\nbool colpack_hessian(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    typedef CPPAD_TESTVECTOR(AD<double>) a_vector;\n    typedef CPPAD_TESTVECTOR(double)     d_vector;\n    typedef CppAD::vector<size_t>        i_vector;\n    size_t i, j, k, ell;\n    double eps = 10. * CppAD::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n = 5;\n    a_vector  a_x(n);\n    for(j = 0; j < n; j++)\n        a_x[j] = AD<double> (0);\n\n    // declare independent variables and starting recording\n    CppAD::Independent(a_x);\n\n    // colpack example case where hessian is a spear head\n    // i.e, H(i, j) non zero implies i = 0, j = 0, or i = j\n    AD<double> sum = 0.0;\n    // partial_0 partial_j = x[j]\n    // partial_j partial_j = x[0]\n    for(j = 1; j < n; j++)\n        sum += a_x[0] * a_x[j] * a_x[j] / 2.0;\n    //\n    // partial_i partial_i = 2 * x[i]\n    for(i = 0; i < n; i++)\n        sum += a_x[i] * a_x[i] * a_x[i] / 3.0;\n\n    // declare dependent variables\n    size_t m = 1;\n    a_vector  a_y(m);\n    a_y[0] = sum;\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(a_x, a_y);\n\n    // new value for the independent variable vector\n    d_vector x(n);\n    for(j = 0; j < n; j++)\n        x[j] = double(j + 1);\n\n    /*\n             [ 2  2  3  4  5 ]\n    hes = [ 2  5  0  0  0 ]\n             [ 3  0  7  0  0 ]\n             [ 4  0  0  9  0 ]\n             [ 5  0  0  0 11 ]\n    */\n    d_vector check(n * n);\n    for(i = 0; i < n; i++)\n    {   for(j = 0; j < n; j++)\n        {   size_t index = i * n + j;\n            check[index] = 0.0;\n            if( i == 0 && 1 <= j )\n                check[index] += x[j];\n            if( 1 <= i && j == 0 )\n                check[index] += x[i];\n            if( i == j )\n            {   check[index] += 2.0 * x[i];\n                if( i != 0 )\n                    check[index] += x[0];\n            }\n        }\n    }\n    // Normally one would use f.RevSparseHes to compute\n    // sparsity pattern, but for this example we extract it from check.\n    std::vector< std::set<size_t> >  p(n);\n    i_vector row, col;\n    for(i = 0; i < n; i++)\n    {   for(j = 0; j < n; j++)\n        {   ell = i * n + j;\n            if( check[ell] != 0. )\n            {   // insert this non-zero entry in sparsity pattern\n                p[i].insert(j);\n\n                // the Hessian is symmetric, so only lower triangle\n                if( j <= i )\n                {   row.push_back(i);\n                    col.push_back(j);\n                }\n            }\n        }\n    }\n    size_t K = row.size();\n    d_vector hes(K);\n\n    // default coloring method is cppad.symmetric\n    CppAD::sparse_hessian_work work;\n    ok &= work.color_method == \"cppad.symmetric\";\n\n    // contrast and check results for both CppAD and Colpack\n    for(size_t i_method = 0; i_method < 4; i_method++)\n    {   // empty work structure\n        switch(i_method)\n        {   case 0:\n            work.color_method = \"cppad.symmetric\";\n            break;\n\n            case 1:\n            work.color_method = \"cppad.general\";\n            break;\n\n            case 2:\n            work.color_method = \"colpack.symmetric\";\n            break;\n\n            case 3:\n            work.color_method = \"colpack.general\";\n            break;\n        }\n\n        // compute Hessian\n        d_vector w(m);\n        w[0] = 1.0;\n        size_t n_sweep = f.SparseHessian(x, w, p, row, col, hes, work);\n        //\n        // check result\n        for(k = 0; k < K; k++)\n        {   ell = row[k] * n + col[k];\n            ok &= NearEqual(check[ell], hes[k], eps, eps);\n        }\n        if(\n            work.color_method == \"cppad.symmetric\"\n        ||  work.color_method == \"colpack.symmetric\"\n        )\n            ok &= n_sweep == 2;\n        else\n            ok &= n_sweep == 5;\n        //\n        // check that clear resets color_method to cppad.symmetric\n        work.clear();\n        ok &= work.color_method == \"cppad.symmetric\";\n    }\n\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/sparse/colpack_jac.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin colpack_jac.cpp}\n\nColPack: Sparse Jacobian Example and Test\n#########################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end colpack_jac.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\nbool colpack_jac(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    typedef CPPAD_TESTVECTOR(AD<double>)            a_vector;\n    typedef CPPAD_TESTVECTOR(double)                d_vector;\n    typedef CppAD::vector<size_t>                   i_vector;\n    typedef CppAD::sparse_rc<i_vector>              sparsity;\n    typedef CppAD::sparse_rcv<i_vector, d_vector>   sparse_matrix;\n\n    // domain space vector\n    size_t n = 4;\n    a_vector  a_x(n);\n    for(size_t j = 0; j < n; j++)\n        a_x[j] = AD<double> (0);\n\n    // declare independent variables and starting recording\n    CppAD::Independent(a_x);\n\n    size_t m = 3;\n    a_vector  a_y(m);\n    a_y[0] = a_x[0] + a_x[1];\n    a_y[1] = a_x[2] + a_x[3];\n    a_y[2] = a_x[0] + a_x[1] + a_x[2] + a_x[3] * a_x[3] / 2.;\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(a_x, a_y);\n\n    // new value for the independent variable vector\n    d_vector x(n);\n    for(size_t j = 0; j < n; j++)\n        x[j] = double(j);\n\n    /*\n             [ 1 1 0 0  ]\n    jac = [ 0 0 1 1  ]\n             [ 1 1 1 x_3]\n    */\n    // Normally one would use CppAD to compute sparsity pattern, but for this\n    // example we set it directly\n    size_t nr  = m;\n    size_t nc  = n;\n    size_t nnz = 8;\n    sparsity pattern(nr, nc, nnz);\n    d_vector check(nnz);\n    for(size_t k = 0; k < nnz; k++)\n    {   size_t r, c;\n        if( k < 2 )\n        {   r = 0;\n            c = k;\n        }\n        else if( k < 4 )\n        {   r = 1;\n            c = k;\n        }\n        else\n        {   r = 2;\n            c = k - 4;\n        }\n        pattern.set(k, r, c);\n        if( k == nnz - 1 )\n            check[k] = x[3];\n        else\n            check[k] = 1.0;\n    }\n\n    // using row and column indices to compute non-zero in rows 1 and 2\n    sparse_matrix subset( pattern );\n\n    // check results for both CppAD and Colpack\n    for(size_t i_method = 0; i_method < 4; i_method++)\n    {   // coloring method\n        std::string coloring;\n        if( i_method % 2 == 0 )\n            coloring = \"cppad\";\n        else\n            coloring = \"colpack\";\n        //\n        CppAD::sparse_jac_work work;\n        size_t group_max = 1;\n        if( i_method / 2 == 0 )\n        {   size_t n_sweep = f.sparse_jac_for(\n                group_max, x, subset, pattern, coloring, work\n            );\n            ok &= n_sweep == 4;\n        }\n        else\n        {   size_t n_sweep = f.sparse_jac_rev(\n                x, subset, pattern, coloring, work\n            );\n            ok &= n_sweep == 2;\n        }\n        const d_vector& hes( subset.val() );\n        for(size_t k = 0; k < nnz; k++)\n            ok &= check[k] == hes[k];\n    }\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/sparse/colpack_jacobian.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin colpack_jacobian.cpp}\n\nColPack: Sparse Jacobian Example and Test\n#########################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end colpack_jacobian.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\nbool colpack_jacobian(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    typedef CPPAD_TESTVECTOR(AD<double>) a_vector;\n    typedef CPPAD_TESTVECTOR(double)     d_vector;\n    typedef CppAD::vector<size_t>        i_vector;\n    size_t i, j, k, ell;\n    double eps = 10. * CppAD::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n = 4;\n    a_vector  a_x(n);\n    for(j = 0; j < n; j++)\n        a_x[j] = AD<double> (0);\n\n    // declare independent variables and starting recording\n    CppAD::Independent(a_x);\n\n    size_t m = 3;\n    a_vector  a_y(m);\n    a_y[0] = a_x[0] + a_x[1];\n    a_y[1] = a_x[2] + a_x[3];\n    a_y[2] = a_x[0] + a_x[1] + a_x[2] + a_x[3] * a_x[3] / 2.;\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(a_x, a_y);\n\n    // new value for the independent variable vector\n    d_vector x(n);\n    for(j = 0; j < n; j++)\n        x[j] = double(j);\n\n    /*\n             [ 1 1 0 0  ]\n    jac = [ 0 0 1 1  ]\n             [ 1 1 1 x_3]\n    */\n    d_vector check(m * n);\n    check[0] = 1.; check[1] = 1.; check[2]  = 0.; check[3]  = 0.;\n    check[4] = 0.; check[5] = 0.; check[6]  = 1.; check[7]  = 1.;\n    check[8] = 1.; check[9] = 1.; check[10] = 1.; check[11] = x[3];\n\n    // Normally one would use f.ForSparseJac or f.RevSparseJac to compute\n    // sparsity pattern, but for this example we extract it from check.\n    std::vector< std::set<size_t> >  p(m);\n\n    // using row and column indices to compute non-zero in rows 1 and 2\n    i_vector row, col;\n    for(i = 0; i < m; i++)\n    {   for(j = 0; j < n; j++)\n        {   ell = i * n + j;\n            if( check[ell] != 0. )\n            {   row.push_back(i);\n                col.push_back(j);\n                p[i].insert(j);\n            }\n        }\n    }\n    size_t K = row.size();\n    d_vector jac(K);\n\n    // empty work structure\n    CppAD::sparse_jacobian_work work;\n    ok &= work.color_method == \"cppad\";\n\n    // choose to use ColPack\n    work.color_method = \"colpack\";\n\n    // forward mode\n    size_t n_sweep = f.SparseJacobianForward(x, p, row, col, jac, work);\n    for(k = 0; k < K; k++)\n    {   ell = row[k] * n + col[k];\n        ok &= NearEqual(check[ell], jac[k], eps, eps);\n    }\n    ok &= n_sweep == 4;\n\n    // reverse mode\n    work.clear();\n    work.color_method = \"colpack\";\n    n_sweep = f.SparseJacobianReverse(x, p, row, col, jac, work);\n    for(k = 0; k < K; k++)\n    {   ell = row[k] * n + col[k];\n        ok &= NearEqual(check[ell], jac[k], eps, eps);\n    }\n    ok &= n_sweep == 2;\n\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/sparse/conj_grad.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin conj_grad.cpp}\n{xrst_spell\n    goto\n}\n\nDifferentiate Conjugate Gradient Algorithm: Example and Test\n############################################################\n\nPurpose\n*******\nThe conjugate gradient algorithm is sparse linear solver and\na good example where checkpointing can be applied (for each iteration).\nThis example is a preliminary version of a new library routine\nfor the conjugate gradient algorithm.\n\nAlgorithm\n*********\nGiven a positive definite matrix :math:`A \\in \\B{R}^{n \\times n}`,\na vector :math:`b \\in \\B{R}^n`,\nand tolerance :math:`\\varepsilon`,\nthe conjugate gradient algorithm finds an :math:`x \\in \\B{R}^n`\nsuch that :math:`\\| A x - b \\|^2 / n \\leq \\varepsilon^2`\n(or it terminates at a specified maximum number of iterations).\n\n#. Input:\n\n    The matrix :math:`A \\in \\B{R}^{n \\times n}`,\n    the vector :math:`b \\in \\B{R}^n`,\n    a tolerance :math:`\\varepsilon \\geq 0`,\n    a maximum number of iterations :math:`m`,\n    and the initial approximate solution :math:`x^0 \\in \\B{R}^n`\n    (can use zero for :math:`x^0`).\n\n#. Initialize:\n\n    :math:`g^0 = A * x^0 - b`,\n    :math:`d^0 = - g^0`,\n    :math:`s_0 = ( g^0 )^\\R{T} g^0`,\n    :math:`k = 0`.\n\n#. Convergence Check:\n\n    if :math:`k = m` or :math:`\\sqrt{ s_k / n } < \\varepsilon`,\n    return :math:`k` as the number of iterations and :math:`x^k`\n    as the approximate solution.\n\n#. Next :math:`x`:\n\n    :math:`\\mu_{k+1} = s_k / [ ( d^k )^\\R{T} A d^k ]`,\n    :math:`x^{k+1} = x^k + \\mu_{k+1} d^k`.\n\n#. Next :math:`g`:\n\n    :math:`g^{k+1} = g^k + \\mu_{k+1} A d^k`,\n    :math:`s_{k+1} = ( g^{k+1} )^\\R{T} g^{k+1}`.\n\n#. Next :math:`d`:\n\n    :math:`d^{k+1} = - g^k + ( s_{k+1} / s_k ) d^k`.\n\n#. Iterate:\n\n    :math:`k = k + 1`,\n    goto Convergence Check.\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end conj_grad.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n# include <cstdlib>\n# include <cmath>\n\nnamespace { // Begin empty namespace\n    using CppAD::AD;\n\n    // A simple matrix multiply c = a * b , where a has n columns\n    // and b has n rows. This should be changed to a function so that\n    // it can efficiently handle the case were A is large and sparse.\n    template <class Vector> // a simple vector class\n    void mat_mul(size_t n, const Vector& a, const Vector& b, Vector& c)\n    {   typedef typename Vector::value_type scalar;\n\n        size_t m, p;\n        m = a.size() / n;\n        p = b.size() / n;\n\n        assert( m * n == a.size() );\n        assert( n * p == b.size() );\n        assert( m * p == c.size() );\n\n        size_t i, j, k, ij;\n        for(i = 0; i < m; i++)\n        {   for(j = 0; j < p; j++)\n            {   ij    = i * p + j;\n                c[ij] = scalar(0);\n                for(k = 0; k < n; k++)\n                    c[ij] = c[ij] + a[i * m + k] * b[k * p + j];\n            }\n        }\n        return;\n    }\n\n    // Solve A * x == b to tolerance epsilon or terminate at m iterations.\n    template <class Vector> // a simple vector class\n    size_t conjugate_gradient(\n        size_t         m       , // input\n        double         epsilon , // input\n        const Vector&  A       , // input\n        const Vector&  b       , // input\n        Vector&        x       ) // input / output\n    {   typedef typename Vector::value_type scalar;\n        scalar mu, s_previous;\n        size_t i, k;\n\n        size_t n = x.size();\n        assert( A.size() == n * n );\n        assert( b.size() == n );\n\n        Vector g(n), d(n), s(1), Ad(n), dAd(1);\n\n        // g = A * x\n        mat_mul(n, A, x, g);\n        for(i = 0; i < n; i++)\n        {   // g = A * x - b\n            g[i] = g[i] - b[i];\n\n            // d = - g\n            d[i] = -g[i];\n        }\n        // s = g^T * g\n        mat_mul(n, g, g, s);\n\n        for(k = 0; k < m; k++)\n        {   s_previous = s[0];\n            if( s_previous < epsilon )\n                return k;\n\n            // Ad = A * d\n            mat_mul(n, A, d, Ad);\n\n            // dAd = d^T * A * d\n            mat_mul(n, d, Ad, dAd);\n\n            // mu = s / d^T * A * d\n            mu = s_previous / dAd[0];\n\n            // g = g + mu * A * d\n            for(i = 0; i < n; i++)\n            {   x[i] = x[i] + mu * d[i];\n                g[i] = g[i] + mu * Ad[i];\n            }\n\n            // s = g^T * g\n            mat_mul(n, g, g, s);\n\n            // d = - g + (s / s_previous) * d\n            for(i = 0; i < n; i++)\n                d[i] = - g[i] + ( s[0] / s_previous) * d[i];\n        }\n        return m;\n    }\n\n} // End empty namespace\n\nbool conj_grad(void)\n{   bool ok = true;\n\n    // ----------------------------------------------------------------------\n    // Setup\n    // ----------------------------------------------------------------------\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    using CppAD::vector;\n    using std::cout;\n    using std::endl;\n    size_t i, j;\n\n\n    // size of the vectors\n    size_t n  = 40;\n    vector<double> D(n * n), Dt(n * n), A(n * n), x(n), b(n), c(n);\n    vector< AD<double> > a_A(n * n), a_x(n), a_b(n);\n\n    // D = diagonally dominant matrix\n    // c = vector of ones\n    for(i = 0; i < n; i++)\n    {   c[i] = 1.;\n        double sum = 0;\n        for(j = 0; j < n; j++) if( i != j )\n        {   D[ i * n + j ] = std::rand() / double(RAND_MAX);\n            Dt[j * n + i ] = D[i * n + j ];\n            sum           += D[i * n + j ];\n        }\n        Dt[ i * n + i ] = D[ i * n + i ] = sum * 1.1;\n    }\n\n    // A = D^T * D\n    mat_mul(n, Dt, D, A);\n\n    // b = D^T * c\n    mat_mul(n, Dt, c, b);\n\n    // copy from double to AD<double>\n    for(i = 0; i < n; i++)\n    {   a_b[i] = b[i];\n        for(j = 0; j < n; j++)\n            a_A[ i * n + j ] = A[ i * n + j ];\n    }\n\n    // ---------------------------------------------------------------------\n    // Record the function f : b -> x\n    // ---------------------------------------------------------------------\n    // Make b the independent variable vector\n    Independent(a_b);\n\n    // Solve A * x = b using conjugate gradient method\n    double epsilon = 1e-7;\n    for(i = 0; i < n; i++)\n            a_x[i] = AD<double>(0);\n    size_t m = n + 1;\n    size_t k = conjugate_gradient(m, epsilon, a_A, a_b, a_x);\n\n    // create f_cg: b -> x and stop tape recording\n    CppAD::ADFun<double> f(a_b, a_x);\n\n    // ---------------------------------------------------------------------\n    // Check for correctness\n    // ---------------------------------------------------------------------\n\n    // conjugate gradient should converge with in n iterations\n    ok &= (k <= n);\n\n    // accuracy to which we expect values to agree\n    double delta = 10. * epsilon * std::sqrt( double(n) );\n\n    // copy x from AD<double> to double\n    for(i = 0; i < n; i++)\n        x[i] = Value( a_x[i] );\n\n    // check c = A * x\n    mat_mul(n, A, x, c);\n    for(i = 0; i < n; i++)\n        ok &= NearEqual(c[i] , b[i],  delta , delta);\n\n    // forward computation of partials w.r.t. b[0]\n    vector<double> db(n), dx(n);\n    for(j = 0; j < n; j++)\n        db[j] = 0.;\n    db[0] = 1.;\n\n    // check db = A * dx\n    delta = 5. * delta;\n    dx = f.Forward(1, db);\n    mat_mul(n, A, dx, c);\n    for(i = 0; i < n; i++)\n        ok   &= NearEqual(c[i], db[i], delta, delta);\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/sparse/dependency.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin dependency.cpp}\n{xrst_spell\n    rl\n}\n\nComputing Dependency: Example and Test\n######################################\n\nDiscussion\n**********\nThe partial of an dependent variable with respect to an independent variable\nmight always be zero even though the dependent variable depends on the\nvalue of the dependent variable. Consider the following case\n\n.. math::\n\n    f(x) = {\\rm sign} (x) =\n    \\left\\{ \\begin{array}{rl}\n        +1 & {\\rm if} \\; x > 0 \\\\\n        0  & {\\rm if} \\; x = 0 \\\\\n        -1 & {\\rm if} \\; x < 0\n    \\end{array} \\right.\n\nIn this case the value of :math:`f(x)` depends on the value of :math:`x`\nbut CppAD always returns zero for the derivative of the :ref:`sign-name` function.\n\nDependency Pattern\n******************\nIf the *i*-th dependent variables depends on the\nvalue of the *j*-th independent variable,\nthe corresponding entry in the dependency pattern is non-zero (true).\nOtherwise it is zero (false).\nCppAD uses :ref:`sparsity patterns<glossary@Sparsity Pattern>`\nto represent dependency patterns.\n\nComputation\n***********\nThe *dependency* argument to\n:ref:`for_jac_sparsity<for_jac_sparsity@dependency>` and\n:ref:`RevSparseJac<RevSparseJac@dependency>` is a flag that signals\nthat the dependency pattern (instead of the sparsity pattern) is computed.\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end dependency.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\nnamespace {\n    double heavyside(const double& x)\n    {   if( x <= 0.0 )\n            return 0.0;\n        return 1.0;\n    }\n    CPPAD_DISCRETE_FUNCTION(double, heavyside)\n}\n\nbool dependency(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    typedef CPPAD_TESTVECTOR(size_t)     SizeVector;\n    typedef CppAD::sparse_rc<SizeVector> sparsity;\n\n    // VecAD object for use later\n    CppAD::VecAD<double> vec_ad(2);\n    vec_ad[0] = 0.0;\n    vec_ad[1] = 1.0;\n\n    // domain space vector\n    size_t n  = 5;\n    CPPAD_TESTVECTOR(AD<double>) ax(n);\n    for(size_t j = 0; j < n; j++)\n        ax[j] = AD<double>(j + 1);\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(ax);\n\n    // some AD constants\n    AD<double> azero(0.0), aone(1.0);\n\n    // range space vector\n    size_t m  = n;\n    size_t m1 = n - 1;\n    CPPAD_TESTVECTOR(AD<double>) ay(m);\n    // Note that ay[m1 - j] depends on ax[j]\n    ay[m1 - 0] = sign( ax[0] );\n    ay[m1 - 1] = CondExpLe( ax[1], azero, azero, aone);\n    ay[m1 - 2] = CondExpLe( azero, ax[2], azero, aone);\n    ay[m1 - 3] = heavyside( ax[3] );\n    ay[m1 - 4] = vec_ad[ ax[4] - AD<double>(4.0) ];\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(ax, ay);\n\n    // sparsity pattern for n by n identity matrix\n    size_t nr  = n;\n    size_t nc  = n;\n    size_t nnz = n;\n    sparsity pattern_in(nr, nc, nnz);\n    for(size_t k = 0; k < nnz; k++)\n    {   size_t r = k;\n        size_t c = k;\n        pattern_in.set(k, r, c);\n    }\n\n    // compute dependency pattern\n    bool transpose     = false;\n    bool dependency    = true;  // would transpose dependency pattern\n    bool internal_bool = true;  // does not affect result\n    sparsity pattern_out;\n    f.for_jac_sparsity(\n        pattern_in, transpose, dependency, internal_bool, pattern_out\n    );\n    const SizeVector& row( pattern_out.row() );\n    const SizeVector& col( pattern_out.col() );\n    SizeVector col_major = pattern_out.col_major();\n\n    // check result\n    ok &= pattern_out.nr()  == n;\n    ok &= pattern_out.nc()  == n;\n    ok &= pattern_out.nnz() == n;\n    for(size_t k = 0; k < n; k++)\n    {   ok &= row[ col_major[k] ] == m1 - k;\n        ok &= col[ col_major[k] ] == k;\n    }\n    // -----------------------------------------------------------\n    // RevSparseJac and set dependency\n    CppAD::vector<    std::set<size_t> > eye_set(m), depend_set(m);\n    for(size_t i = 0; i < m; i++)\n    {   ok &= eye_set[i].empty();\n        eye_set[i].insert(i);\n    }\n    depend_set = f.RevSparseJac(n, eye_set, transpose, dependency);\n    for(size_t i = 0; i < m; i++)\n    {   std::set<size_t> check;\n        check.insert(m1 - i);\n        ok &= depend_set[i] == check;\n    }\n    dependency = false;\n    depend_set = f.RevSparseJac(n, eye_set, transpose, dependency);\n    for(size_t i = 0; i < m; i++)\n        ok &= depend_set[i].empty();\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/sparse/for_hes_sparsity.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin for_hes_sparsity.cpp}\n\nForward Mode Hessian Sparsity: Example and Test\n###############################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end for_hes_sparsity.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nbool for_hes_sparsity(void)\n{   bool ok = true;\n    using CppAD::AD;\n    typedef CPPAD_TESTVECTOR(size_t)     SizeVector;\n    typedef CppAD::sparse_rc<SizeVector> sparsity;\n    //\n    // domain space vector\n    size_t n = 3;\n    CPPAD_TESTVECTOR(AD<double>) ax(n);\n    ax[0] = 0.;\n    ax[1] = 1.;\n    ax[2] = 2.;\n\n    // declare independent variables and start recording\n    CppAD::Independent(ax);\n\n    // range space vector\n    size_t m = 2;\n    CPPAD_TESTVECTOR(AD<double>) ay(m);\n    ay[0] = sin( ax[2] );\n    ay[1] = ax[0] * ax[1];\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(ax, ay);\n\n    // include all x components in sparsity pattern\n    CPPAD_TESTVECTOR(bool) select_domain(n);\n    for(size_t j = 0; j < n; j++)\n        select_domain[j] = true;\n\n    // compute sparsity pattern for H(x) = F_1''(x)\n    CPPAD_TESTVECTOR(bool) select_range(m);\n    select_range[0]    = false;\n    select_range[1]    = true;\n    bool internal_bool = true;\n    sparsity pattern_out;\n    f.for_hes_sparsity(\n        select_domain, select_range, internal_bool, pattern_out\n    );\n    size_t nnz = pattern_out.nnz();\n    ok        &= nnz == 2;\n    ok        &= pattern_out.nr() == n;\n    ok        &= pattern_out.nc() == n;\n    {   // check results\n        const SizeVector& row( pattern_out.row() );\n        const SizeVector& col( pattern_out.col() );\n        SizeVector row_major = pattern_out.row_major();\n        //\n        ok &= row[ row_major[0] ] ==  0  && col[ row_major[0] ] ==  1;\n        ok &= row[ row_major[1] ] ==  1  && col[ row_major[1] ] ==  0;\n    }\n    //\n    // compute sparsity pattern for H(x) = F_0''(x)\n    select_range[0] = true;\n    select_range[1] = false;\n    f.for_hes_sparsity(\n        select_domain, select_range, internal_bool, pattern_out\n    );\n    nnz = pattern_out.nnz();\n    ok &= nnz == 1;\n    ok &= pattern_out.nr() == n;\n    ok &= pattern_out.nc() == n;\n    {   // check results\n        const SizeVector& row( pattern_out.row() );\n        const SizeVector& col( pattern_out.col() );\n        //\n        ok &= row[0] ==  2  && col[0] ==  2;\n    }\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/sparse/for_jac_sparsity.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin for_jac_sparsity.cpp}\n\nForward Mode Jacobian Sparsity: Example and Test\n################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end for_jac_sparsity.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nbool for_jac_sparsity(void)\n{   bool ok = true;\n    using CppAD::AD;\n    typedef CPPAD_TESTVECTOR(size_t)     SizeVector;\n    typedef CppAD::sparse_rc<SizeVector> sparsity;\n    //\n    // domain space vector\n    size_t n = 2;\n    CPPAD_TESTVECTOR(AD<double>) ax(n);\n    ax[0] = 0.;\n    ax[1] = 1.;\n\n    // declare independent variables and start recording\n    CppAD::Independent(ax);\n\n    // range space vector\n    size_t m = 3;\n    CPPAD_TESTVECTOR(AD<double>) ay(m);\n    ay[0] = ax[0];\n    ay[1] = ax[0] * ax[1];\n    ay[2] = ax[1];\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(ax, ay);\n\n    // sparsity pattern for the identity matrix\n    size_t nr     = n;\n    size_t nc     = n;\n    size_t nnz_in = n;\n    sparsity pattern_in(nr, nc, nnz_in);\n    for(size_t k = 0; k < nnz_in; k++)\n    {   size_t r = k;\n        size_t c = k;\n        pattern_in.set(k, r, c);\n    }\n    //\n    // Compute sparsity pattern for J(x) = F'(x)\n    bool transpose       = false;\n    bool dependency      = false;\n    bool internal_bool   = false;\n    sparsity pattern_out;\n    f.for_jac_sparsity(\n        pattern_in, transpose, dependency, internal_bool, pattern_out\n    );\n    size_t nnz = pattern_out.nnz();\n    ok        &= nnz == 4;\n    ok        &= pattern_out.nr() == m;\n    ok        &= pattern_out.nc() == n;\n    {   // check results\n        const SizeVector& row( pattern_out.row() );\n        const SizeVector& col( pattern_out.col() );\n        SizeVector col_major = pattern_out.col_major();\n        //\n        ok &= row[ col_major[0] ] ==  0  && col[ col_major[0] ] ==  0;\n        ok &= row[ col_major[1] ] ==  1  && col[ col_major[1] ] ==  0;\n        ok &= row[ col_major[2] ] ==  1  && col[ col_major[2] ] ==  1;\n        ok &= row[ col_major[3] ] ==  2  && col[ col_major[3] ] ==  1;\n        //\n        // check that set and not boolean values are stored\n        ok &= (f.size_forward_set() > 0);\n        ok &= (f.size_forward_bool() == 0);\n    }\n    //\n    // note that the transpose of the identity is the identity\n    transpose     = true;\n    internal_bool = true;\n    f.for_jac_sparsity(\n        pattern_in, transpose, dependency, internal_bool, pattern_out\n    );\n    nnz  = pattern_out.nnz();\n    ok  &= nnz == 4;\n    ok  &= pattern_out.nr() == n;\n    ok  &= pattern_out.nc() == m;\n    {   // check results\n        const SizeVector& row( pattern_out.row() );\n        const SizeVector& col( pattern_out.col() );\n        SizeVector row_major = pattern_out.row_major();\n        //\n        ok &= col[ row_major[0] ] ==  0  && row[ row_major[0] ] ==  0;\n        ok &= col[ row_major[1] ] ==  1  && row[ row_major[1] ] ==  0;\n        ok &= col[ row_major[2] ] ==  1  && row[ row_major[2] ] ==  1;\n        ok &= col[ row_major[3] ] ==  2  && row[ row_major[3] ] ==  1;\n        //\n        // check that set and not boolean values are stored\n        ok &= (f.size_forward_set() == 0);\n        ok &= (f.size_forward_bool() > 0);\n    }\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/sparse/for_sparse_hes.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin for_sparse_hes.cpp}\n\nForward Mode Hessian Sparsity: Example and Test\n###############################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end for_sparse_hes.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\nnamespace { // -------------------------------------------------------------\n\n// expected sparsity pattern\nbool check_f0[] = {\n    false, false, false,  // partials w.r.t x0 and (x0, x1, x2)\n    false, false, false,  // partials w.r.t x1 and (x0, x1, x2)\n    false, false, true    // partials w.r.t x2 and (x0, x1, x2)\n};\nbool check_f1[] = {\n    false,  true, false,  // partials w.r.t x0 and (x0, x1, x2)\n    true,  false, false,  // partials w.r.t x1 and (x0, x1, x2)\n    false, false, false   // partials w.r.t x2 and (x0, x1, x2)\n};\n\n// define the template function BoolCases<Vector> in empty namespace\ntemplate <class Vector> // vector class, elements of type bool\nbool BoolCases(bool optimize)\n{   bool ok = true;\n    using CppAD::AD;\n\n    // domain space vector\n    size_t n = 3;\n    CPPAD_TESTVECTOR(AD<double>) ax(n);\n    ax[0] = 0.;\n    ax[1] = 1.;\n    ax[2] = 2.;\n\n    // declare independent variables and start recording\n    CppAD::Independent(ax);\n\n    // range space vector\n    size_t m = 2;\n    CPPAD_TESTVECTOR(AD<double>) ay(m);\n    ay[0] = sin( ax[2] ) + ax[0] + ax[1] + ax[2];\n    ay[1] = ax[0] * ax[1];\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(ax, ay);\n    if( optimize )\n        f.optimize();\n\n    // sparsity pattern for diagonal of identity matrix\n    Vector r(n);\n    size_t i, j;\n    for(i = 0; i < n; i++)\n        r[ i ] = true;\n\n    // compute sparsity pattern for H(x) = F_0^{(2)} (x)\n    Vector s(m);\n    for(i = 0; i < m; i++)\n        s[i] = false;\n    s[0] = true;\n    Vector h(n * n);\n    h    = f.ForSparseHes(r, s);\n\n    // check values\n    for(i = 0; i < n; i++)\n        for(j = 0; j < n; j++)\n            ok &= (h[ i * n + j ] == check_f0[ i * n + j ] );\n\n    // compute sparsity pattern for H(x) = F_1^{(2)} (x)\n    for(i = 0; i < m; i++)\n        s[i] = false;\n    s[1] = true;\n    h    = f.ForSparseHes(r, s);\n\n    // check values\n    for(i = 0; i < n; i++)\n        for(j = 0; j < n; j++)\n            ok &= (h[ i * n + j ] == check_f1[ i * n + j ] );\n\n    return ok;\n}\n// define the template function SetCases<Vector> in empty namespace\ntemplate <class Vector> // vector class, elements of type std::set<size_t>\nbool SetCases(bool optimize)\n{   bool ok = true;\n    using CppAD::AD;\n\n    // domain space vector\n    size_t n = 3;\n    CPPAD_TESTVECTOR(AD<double>) ax(n);\n    ax[0] = 0.;\n    ax[1] = 1.;\n    ax[2] = 2.;\n\n    // declare independent variables and start recording\n    CppAD::Independent(ax);\n\n    // range space vector\n    size_t m = 2;\n    CPPAD_TESTVECTOR(AD<double>) ay(m);\n    ay[0] = sin( ax[2] );\n    ay[1] = ax[0] * ax[1];\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(ax, ay);\n    if( optimize )\n        f.optimize();\n\n    // sparsity pattern for the diagonal of the identity matrix\n    Vector r(1);\n    size_t i;\n    for(i = 0; i < n; i++)\n        r[0].insert(i);\n\n    // compute sparsity pattern for H(x) = F_0^{(2)} (x)\n    Vector s(1);\n    assert( s[0].empty() );\n    s[0].insert(0);\n    Vector h(n);\n    h    = f.ForSparseHes(r, s);\n\n    // check values\n    std::set<size_t>::iterator itr;\n    size_t j;\n    for(i = 0; i < n; i++)\n    {   for(j = 0; j < n; j++)\n        {   bool found = h[i].find(j) != h[i].end();\n            ok        &= (found == check_f0[i * n + j]);\n        }\n    }\n\n    // compute sparsity pattern for H(x) = F_1^{(2)} (x)\n    s[0].clear();\n    assert( s[0].empty() );\n    s[0].insert(1);\n    h    = f.ForSparseHes(r, s);\n\n    // check values\n    for(i = 0; i < n; i++)\n    {   for(j = 0; j < n; j++)\n        {   bool found = h[i].find(j) != h[i].end();\n            ok        &= (found == check_f1[i * n + j]);\n        }\n    }\n\n    return ok;\n}\n} // End empty namespace\n\n# include <vector>\n# include <valarray>\nbool for_sparse_hes(void)\n{   bool ok = true;\n    for(size_t k = 0; k < 2; k++)\n    {   bool optimize = bool(k);\n\n        // Run with Vector equal to four different cases\n        // all of which are Simple Vectors with elements of type bool.\n        ok &= BoolCases< CppAD::vector  <bool> >(optimize);\n        ok &= BoolCases< CppAD::vectorBool     >(optimize);\n        ok &= BoolCases< std::vector    <bool> >(optimize);\n        ok &= BoolCases< std::valarray  <bool> >(optimize);\n\n        // Run with Vector equal to two different cases both of which are\n        // Simple Vectors with elements of type std::set<size_t>\n        typedef std::set<size_t> set;\n        ok &= SetCases< CppAD::vector  <set> >(optimize);\n        ok &= SetCases< std::vector    <set> >(optimize);\n\n        // Do not use valarray because its element access in the const case\n        // returns a copy instead of a reference\n        // ok &= SetCases< std::valarray  <set> >(optimize);\n    }\n    return ok;\n}\n\n\n// END C++\n"
  },
  {
    "path": "example/sparse/for_sparse_jac.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin for_sparse_jac.cpp}\n\nForward Mode Jacobian Sparsity: Example and Test\n################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end for_sparse_jac.cpp}\n*/\n// BEGIN C++\n\n# include <set>\n# include <cppad/cppad.hpp>\n\nnamespace { // -------------------------------------------------------------\n// define the template function BoolCases<Vector>\ntemplate <class Vector>  // vector class, elements of type bool\nbool BoolCases(void)\n{   bool ok = true;\n    using CppAD::AD;\n\n    // domain space vector\n    size_t n = 2;\n    CPPAD_TESTVECTOR(AD<double>) X(n);\n    X[0] = 0.;\n    X[1] = 1.;\n\n    // declare independent variables and start recording\n    CppAD::Independent(X);\n\n    // range space vector\n    size_t m = 3;\n    CPPAD_TESTVECTOR(AD<double>) Y(m);\n    Y[0] = X[0];\n    Y[1] = X[0] * X[1];\n    Y[2] = X[1];\n\n    // create f: X -> Y and stop tape recording\n    CppAD::ADFun<double> f(X, Y);\n\n    // sparsity pattern for the identity matrix\n    Vector r(n * n);\n    size_t i, j;\n    for(i = 0; i < n; i++)\n    {   for(j = 0; j < n; j++)\n            r[ i * n + j ] = (i == j);\n    }\n\n    // sparsity pattern for F'(x)\n    Vector s(m * n);\n    s = f.ForSparseJac(n, r);\n\n    // check values\n    ok &= (s[ 0 * n + 0 ] == true);  // Y[0] does     depend on X[0]\n    ok &= (s[ 0 * n + 1 ] == false); // Y[0] does not depend on X[1]\n    ok &= (s[ 1 * n + 0 ] == true);  // Y[1] does     depend on X[0]\n    ok &= (s[ 1 * n + 1 ] == true);  // Y[1] does     depend on X[1]\n    ok &= (s[ 2 * n + 0 ] == false); // Y[2] does not depend on X[0]\n    ok &= (s[ 2 * n + 1 ] == true);  // Y[2] does     depend on X[1]\n\n    // check that values are stored\n    ok &= (f.size_forward_bool() > 0);\n    ok &= (f.size_forward_set() == 0);\n\n    // sparsity pattern for F'(x)^T, note R is the identity, so R^T = R\n    bool transpose = true;\n    Vector st(n * m);\n    st = f.ForSparseJac(n, r, transpose);\n\n    // check values\n    ok &= (st[ 0 * m + 0 ] == true);  // Y[0] does     depend on X[0]\n    ok &= (st[ 1 * m + 0 ] == false); // Y[0] does not depend on X[1]\n    ok &= (st[ 0 * m + 1 ] == true);  // Y[1] does     depend on X[0]\n    ok &= (st[ 1 * m + 1 ] == true);  // Y[1] does     depend on X[1]\n    ok &= (st[ 0 * m + 2 ] == false); // Y[2] does not depend on X[0]\n    ok &= (st[ 1 * m + 2 ] == true);  // Y[2] does     depend on X[1]\n\n    // check that values are stored\n    ok &= (f.size_forward_bool() > 0);\n    ok &= (f.size_forward_set() == 0);\n\n    // free values from forward calculation\n    f.size_forward_bool(0);\n    ok &= (f.size_forward_bool() == 0);\n\n    return ok;\n}\n// define the template function SetCases<Vector>\ntemplate <class Vector>  // vector class, elements of type std::set<size_t>\nbool SetCases(void)\n{   bool ok = true;\n    using CppAD::AD;\n\n    // domain space vector\n    size_t n = 2;\n    CPPAD_TESTVECTOR(AD<double>) X(n);\n    X[0] = 0.;\n    X[1] = 1.;\n\n    // declare independent variables and start recording\n    CppAD::Independent(X);\n\n    // range space vector\n    size_t m = 3;\n    CPPAD_TESTVECTOR(AD<double>) Y(m);\n    Y[0] = X[0];\n    Y[1] = X[0] * X[1];\n    Y[2] = X[1];\n\n    // create f: X -> Y and stop tape recording\n    CppAD::ADFun<double> f(X, Y);\n\n    // sparsity pattern for the identity matrix\n    Vector r(n);\n    size_t i;\n    for(i = 0; i < n; i++)\n    {   assert( r[i].empty() );\n        r[i].insert(i);\n    }\n\n    // sparsity pattern for F'(x)\n    Vector s(m);\n    s = f.ForSparseJac(n, r);\n\n    // an iterator to a standard set\n    std::set<size_t>::iterator itr;\n    bool found;\n\n    // Y[0] does     depend on X[0]\n    found = s[0].find(0) != s[0].end();  ok &= ( found == true );\n    // Y[0] does not depend on X[1]\n    found = s[0].find(1) != s[0].end();  ok &= ( found == false );\n    // Y[1] does     depend on X[0]\n    found = s[1].find(0) != s[1].end();  ok &= ( found == true );\n    // Y[1] does     depend on X[1]\n    found = s[1].find(1) != s[1].end();  ok &= ( found == true );\n    // Y[2] does not depend on X[0]\n    found = s[2].find(0) != s[2].end();  ok &= ( found == false );\n    // Y[2] does     depend on X[1]\n    found = s[2].find(1) != s[2].end();  ok &= ( found == true );\n\n    // check that values are stored\n    ok &= (f.size_forward_set() > 0);\n    ok &= (f.size_forward_bool() == 0);\n\n\n    // sparsity pattern for F'(x)^T\n    bool transpose = true;\n    Vector st(n);\n    st = f.ForSparseJac(n, r, transpose);\n\n    // Y[0] does     depend on X[0]\n    found = st[0].find(0) != st[0].end();  ok &= ( found == true );\n    // Y[0] does not depend on X[1]\n    found = st[1].find(0) != st[1].end();  ok &= ( found == false );\n    // Y[1] does     depend on X[0]\n    found = st[0].find(1) != st[0].end();  ok &= ( found == true );\n    // Y[1] does     depend on X[1]\n    found = st[1].find(1) != st[1].end();  ok &= ( found == true );\n    // Y[2] does not depend on X[0]\n    found = st[0].find(2) != st[0].end();  ok &= ( found == false );\n    // Y[2] does     depend on X[1]\n    found = st[1].find(2) != st[1].end();  ok &= ( found == true );\n\n    // check that values are stored\n    ok &= (f.size_forward_set() > 0);\n    ok &= (f.size_forward_bool() == 0);\n\n    return ok;\n}\n} // End empty namespace\n# include <vector>\n# include <valarray>\nbool ForSparseJac(void)\n{   bool ok = true;\n    // Run with Vector equal to four different cases\n    // all of which are Simple Vectors with elements of type bool.\n    ok &= BoolCases< CppAD::vectorBool     >();\n    ok &= BoolCases< CppAD::vector  <bool> >();\n    ok &= BoolCases< std::vector    <bool> >();\n    ok &= BoolCases< std::valarray  <bool> >();\n\n    // Run with Vector equal to two different cases both of which are\n    // Simple Vectors with elements of type std::set<size_t>\n    typedef std::set<size_t> set;\n    ok &= SetCases< CppAD::vector  <set> >();\n    // ok &= SetCases< std::vector    <set> >();\n\n    // Do not use valarray because its element access in the const case\n    // returns a copy instead of a reference\n    // ok &= SetCases< std::valarray  <set> >();\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/sparse/rc_sparsity.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin rc_sparsity.cpp}\n\nPreferred Sparsity Patterns: Row and Column Indices: Example and Test\n#####################################################################\n\nPurpose\n*******\nThis example show how to use row and column index sparsity patterns\n:ref:`sparse_rc-name` to compute sparse Jacobians and Hessians.\nThis became the preferred way to represent sparsity on\n:ref:`2017-02-09<2017@mm-dd@02-09>` .\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end rc_sparsity.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\nnamespace {\n    using CppAD::sparse_rc;\n    using CppAD::sparse_rcv;\n    using CppAD::NearEqual;\n    //\n    typedef CPPAD_TESTVECTOR(bool)                b_vector;\n    typedef CPPAD_TESTVECTOR(size_t)              s_vector;\n    typedef CPPAD_TESTVECTOR(double)              d_vector;\n    typedef CPPAD_TESTVECTOR( CppAD::AD<double> ) a_vector;\n    //\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    // -----------------------------------------------------------------------\n    // function f(x) that we are computing sparse results for\n    // -----------------------------------------------------------------------\n    a_vector fun(const a_vector& x)\n    {   size_t n  = x.size();\n        a_vector ret(n + 1);\n        for(size_t i = 0; i < n; i++)\n        {   size_t j = (i + 1) % n;\n            ret[i]     = x[i] * x[i] * x[j];\n        }\n        ret[n] = 0.0;\n        return ret;\n    }\n    // -----------------------------------------------------------------------\n    // Jacobian\n    // -----------------------------------------------------------------------\n    bool check_jac(\n        const d_vector&                       x      ,\n        const sparse_rcv<s_vector, d_vector>& subset )\n    {   bool ok  = true;\n        size_t n = x.size();\n        //\n        ok &= subset.nnz() == 2 * n;\n        const s_vector& row( subset.row() );\n        const s_vector& col( subset.col() );\n        const d_vector& val( subset.val() );\n        s_vector row_major = subset.row_major();\n        for(size_t i = 0; i < n; i++)\n        {   size_t j = (i + 1) % n;\n            size_t k = 2 * i;\n            //\n            ok &= row[ row_major[k] ]   == i;\n            ok &= row[ row_major[k+1] ] == i;\n            //\n            size_t ck  = col[ row_major[k] ];\n            size_t ckp = col[ row_major[k+1] ];\n            double vk  = val[ row_major[k] ];\n            double vkp = val[ row_major[k+1] ];\n            //\n            // put diagonal element first\n            if( j < i )\n            {   std::swap(ck, ckp);\n                std::swap(vk, vkp);\n            }\n            // diagonal element\n            ok &= ck == i;\n            ok &= NearEqual( vk, 2.0 * x[i] * x[j], eps99, eps99 );\n            // off diagonal element\n            ok &= ckp == j;\n            ok &= NearEqual( vkp, x[i] * x[i], eps99, eps99 );\n        }\n        return ok;\n    }\n    // Use forward mode for Jacobian and sparsity pattern\n    bool forward_jac(CppAD::ADFun<double>& f)\n    {   bool ok = true;\n        size_t n = f.Domain();\n        //\n        // sparsity pattern for identity matrix\n        sparse_rc<s_vector> pattern_in(n, n, n);\n        for(size_t k = 0; k < n; k++)\n            pattern_in.set(k, k, k);\n        //\n        // sparsity pattern for Jacobian\n        bool transpose     = false;\n        bool dependency    = false;\n        bool internal_bool = false;\n        sparse_rc<s_vector> pattern_out;\n        f.for_jac_sparsity(\n            pattern_in, transpose, dependency, internal_bool, pattern_out\n        );\n        //\n        // compute entire Jacobian\n        size_t                         group_max = 1;\n        std::string                    coloring  = \"cppad\";\n        sparse_rcv<s_vector, d_vector> subset( pattern_out );\n        CppAD::sparse_jac_work         work;\n        d_vector x(n);\n        for(size_t j = 0; j < n; j++)\n            x[j] = double(j + 2);\n        size_t n_sweep = f.sparse_jac_for(\n            group_max, x, subset, pattern_out, coloring, work\n        );\n        //\n        // check Jacobian\n        ok &= check_jac(x, subset);\n        ok &= n_sweep == 2;\n        //\n        return ok;\n    }\n    // Use reverse mode for Jacobian and sparsity pattern\n    bool reverse_jac(CppAD::ADFun<double>& f)\n    {   bool ok = true;\n        size_t n = f.Domain();\n        size_t m = f.Range();\n        //\n        // sparsity pattern for identity matrix\n        sparse_rc<s_vector> pattern_in(m, m, m);\n        for(size_t k = 0; k < m; k++)\n            pattern_in.set(k, k, k);\n        //\n        // sparsity pattern for Jacobian\n        bool transpose     = false;\n        bool dependency    = false;\n        bool internal_bool = false;\n        sparse_rc<s_vector> pattern_out;\n        f.rev_jac_sparsity(\n            pattern_in, transpose, dependency, internal_bool, pattern_out\n        );\n        //\n        // compute entire Jacobian\n        std::string                    coloring  = \"cppad\";\n        sparse_rcv<s_vector, d_vector> subset( pattern_out );\n        CppAD::sparse_jac_work         work;\n        d_vector x(n);\n        for(size_t j = 0; j < n; j++)\n            x[j] = double(j + 2);\n        size_t n_sweep = f.sparse_jac_rev(\n            x, subset, pattern_out, coloring, work\n        );\n        //\n        // check Jacobian\n        ok &= check_jac(x, subset);\n        ok &= n_sweep == 2;\n        //\n        return ok;\n    }\n    // ------------------------------------------------------------------------\n    // Hessian\n    // ------------------------------------------------------------------------\n    bool check_hes(\n        size_t                                i      ,\n        const d_vector&                       x      ,\n        const sparse_rcv<s_vector, d_vector>& subset )\n    {   bool ok  = true;\n        size_t n = x.size();\n        size_t j = (i + 1) % n;\n        //\n        ok &= subset.nnz() == 3;\n        const s_vector& row( subset.row() );\n        const s_vector& col( subset.col() );\n        const d_vector& val( subset.val() );\n        s_vector row_major = subset.row_major();\n        //\n        double v0 = val[ row_major[0] ];\n        double v1 = val[ row_major[1] ];\n        double v2 = val[ row_major[2] ];\n        if( j < i )\n        {   ok &= row[ row_major[0] ] == j;\n            ok &= col[ row_major[0] ] == i;\n            ok &= NearEqual( v0, 2.0 * x[i], eps99, eps99 );\n            //\n            ok &= row[ row_major[1] ] == i;\n            ok &= col[ row_major[1] ] == j;\n            ok &= NearEqual( v1, 2.0 * x[i], eps99, eps99 );\n            //\n            ok &= row[ row_major[2] ] == i;\n            ok &= col[ row_major[2] ] == i;\n            ok &= NearEqual( v2, 2.0 * x[j], eps99, eps99 );\n        }\n        else\n        {   ok &= row[ row_major[0] ] == i;\n            ok &= col[ row_major[0] ] == i;\n            ok &= NearEqual( v0, 2.0 * x[j], eps99, eps99 );\n            //\n            ok &= row[ row_major[1] ] == i;\n            ok &= col[ row_major[1] ] == j;\n            ok &= NearEqual( v1, 2.0 * x[i], eps99, eps99 );\n            //\n            ok &= row[ row_major[2] ] == j;\n            ok &= col[ row_major[2] ] == i;\n            ok &= NearEqual( v2, 2.0 * x[i], eps99, eps99 );\n        }\n        return ok;\n    }\n    // Use forward mode for Hessian and sparsity pattern\n    bool forward_hes(CppAD::ADFun<double>& f)\n    {   bool ok = true;\n        size_t n = f.Domain();\n        size_t m = f.Range();\n        //\n        b_vector select_domain(n);\n        for(size_t j = 0; j < n; j++)\n            select_domain[j] = true;\n        sparse_rc<s_vector> pattern_out;\n        //\n        for(size_t i = 0; i < m; i++)\n        {   // select i-th component of range\n            b_vector select_range(m);\n            d_vector w(m);\n            for(size_t k = 0; k < m; k++)\n            {   select_range[k] = k == i;\n                w[k] = 0.0;\n                if( k == i )\n                    w[k] = 1.0;\n            }\n            //\n            bool internal_bool = false;\n            f.for_hes_sparsity(\n                select_domain, select_range, internal_bool, pattern_out\n            );\n            //\n            // compute Hessian for i-th component function\n            std::string                    coloring  = \"cppad.symmetric\";\n            sparse_rcv<s_vector, d_vector> subset( pattern_out );\n            CppAD::sparse_hes_work         work;\n            d_vector x(n);\n            for(size_t j = 0; j < n; j++)\n                x[j] = double(j + 2);\n            size_t n_sweep = f.sparse_hes(\n                x, w, subset, pattern_out, coloring, work\n            );\n            //\n            // check Hessian\n            if( i == n )\n                ok &= subset.nnz() == 0;\n            else\n            {   ok &= check_hes(i, x, subset);\n                ok &= n_sweep == 1;\n            }\n        }\n        return ok;\n    }\n    // Use reverse mode for Hessian and sparsity pattern\n    bool reverse_hes(CppAD::ADFun<double>& f)\n    {   bool ok = true;\n        size_t n = f.Domain();\n        size_t m = f.Range();\n        //\n        // n by n identity matrix\n        sparse_rc<s_vector> pattern_in(n, n, n);\n        for(size_t j = 0; j < n; j++)\n            pattern_in.set(j, j, j);\n        //\n        bool transpose     = false;\n        bool dependency    = false;\n        bool internal_bool = true;\n        sparse_rc<s_vector> pattern_out;\n        //\n        f.for_jac_sparsity(\n            pattern_in, transpose, dependency, internal_bool, pattern_out\n        );\n        //\n        for(size_t i = 0; i < m; i++)\n        {   // select i-th component of range\n            b_vector select_range(m);\n            d_vector w(m);\n            for(size_t k = 0; k < m; k++)\n            {   select_range[k] = k == i;\n                w[k] = 0.0;\n                if( k == i )\n                    w[k] = 1.0;\n            }\n            //\n            f.rev_hes_sparsity(\n                select_range, transpose, internal_bool, pattern_out\n            );\n            //\n            // compute Hessian for i-th component function\n            std::string                    coloring  = \"cppad.symmetric\";\n            sparse_rcv<s_vector, d_vector> subset( pattern_out );\n            CppAD::sparse_hes_work         work;\n            d_vector x(n);\n            for(size_t j = 0; j < n; j++)\n                x[j] = double(j + 2);\n            size_t n_sweep = f.sparse_hes(\n                x, w, subset, pattern_out, coloring, work\n            );\n            //\n            // check Hessian\n            if( i == n )\n                ok &= subset.nnz() == 0;\n            else\n            {   ok &= check_hes(i, x, subset);\n                ok &= n_sweep == 1;\n            }\n        }\n        return ok;\n    }\n}\n// driver for all of the cases above\nbool rc_sparsity(void)\n{   bool ok = true;\n    //\n    // record the function\n    size_t n = 20;\n    size_t m = n + 1;\n    a_vector x(n), y(m);\n    for(size_t j = 0; j < n; j++)\n        x[j] = CppAD::AD<double>(j+1);\n    CppAD::Independent(x);\n    y = fun(x);\n    CppAD::ADFun<double> f(x, y);\n    //\n    // run the example / tests\n    ok &= forward_jac(f);\n    ok &= reverse_jac(f);\n    ok &= forward_hes(f);\n    ok &= reverse_hes(f);\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/sparse/rev_hes_sparsity.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin rev_hes_sparsity.cpp}\n\nReverse Mode Hessian Sparsity: Example and Test\n###############################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end rev_hes_sparsity.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nbool rev_hes_sparsity(void)\n{   bool ok = true;\n    using CppAD::AD;\n    typedef CPPAD_TESTVECTOR(size_t)     SizeVector;\n    typedef CppAD::sparse_rc<SizeVector> sparsity;\n    //\n    // domain space vector\n    size_t n = 3;\n    CPPAD_TESTVECTOR(AD<double>) ax(n);\n    ax[0] = 0.;\n    ax[1] = 1.;\n    ax[2] = 2.;\n\n    // declare independent variables and start recording\n    CppAD::Independent(ax);\n\n    // range space vector\n    size_t m = 2;\n    CPPAD_TESTVECTOR(AD<double>) ay(m);\n    ay[0] = sin( ax[2] );\n    ay[1] = ax[0] * ax[1];\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(ax, ay);\n\n    // sparsity pattern for the identity matrix\n    size_t nr     = n;\n    size_t nc     = n;\n    size_t nnz_in = n;\n    sparsity pattern_in(nr, nc, nnz_in);\n    for(size_t k = 0; k < nnz_in; k++)\n    {   size_t r = k;\n        size_t c = k;\n        pattern_in.set(k, r, c);\n    }\n    // compute sparsity pattern for J(x) = F'(x)\n    bool transpose       = false;\n    bool dependency      = false;\n    bool internal_bool   = false;\n    sparsity pattern_out;\n    f.for_jac_sparsity(\n        pattern_in, transpose, dependency, internal_bool, pattern_out\n    );\n    //\n    // compute sparsity pattern for H(x) = F_1''(x)\n    CPPAD_TESTVECTOR(bool) select_range(m);\n    select_range[0] = false;\n    select_range[1] = true;\n    f.rev_hes_sparsity(\n        select_range, transpose, internal_bool, pattern_out\n    );\n    size_t nnz = pattern_out.nnz();\n    ok        &= nnz == 2;\n    ok        &= pattern_out.nr() == n;\n    ok        &= pattern_out.nc() == n;\n    {   // check results\n        const SizeVector& row( pattern_out.row() );\n        const SizeVector& col( pattern_out.col() );\n        SizeVector row_major = pattern_out.row_major();\n        //\n        ok &= row[ row_major[0] ] ==  0  && col[ row_major[0] ] ==  1;\n        ok &= row[ row_major[1] ] ==  1  && col[ row_major[1] ] ==  0;\n    }\n    //\n    // compute sparsity pattern for H(x) = F_0''(x)\n    select_range[0] = true;\n    select_range[1] = false;\n    f.rev_hes_sparsity(\n        select_range, transpose, internal_bool, pattern_out\n    );\n    nnz = pattern_out.nnz();\n    ok &= nnz == 1;\n    ok &= pattern_out.nr() == n;\n    ok &= pattern_out.nc() == n;\n    {   // check results\n        const SizeVector& row( pattern_out.row() );\n        const SizeVector& col( pattern_out.col() );\n        //\n        ok &= row[0] ==  2  && col[0] ==  2;\n    }\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/sparse/rev_jac_sparsity.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin rev_jac_sparsity.cpp}\n\nReverse Mode Jacobian Sparsity: Example and Test\n################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end rev_jac_sparsity.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nbool rev_jac_sparsity(void)\n{   bool ok = true;\n    using CppAD::AD;\n    typedef CPPAD_TESTVECTOR(size_t)     SizeVector;\n    typedef CppAD::sparse_rc<SizeVector> sparsity;\n    //\n    // domain space vector\n    size_t n = 2;\n    CPPAD_TESTVECTOR(AD<double>) ax(n);\n    ax[0] = 0.;\n    ax[1] = 1.;\n\n    // declare independent variables and start recording\n    CppAD::Independent(ax);\n\n    // range space vector\n    size_t m = 3;\n    CPPAD_TESTVECTOR(AD<double>) ay(m);\n    ay[0] = ax[0];\n    ay[1] = ax[0] * ax[1];\n    ay[2] = ax[1];\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(ax, ay);\n\n    // sparsity pattern for the identity matrix\n    size_t nr     = m;\n    size_t nc     = m;\n    size_t nnz_in = m;\n    sparsity pattern_in(nr, nc, nnz_in);\n    for(size_t k = 0; k < nnz_in; k++)\n    {   size_t r = k;\n        size_t c = k;\n        pattern_in.set(k, r, c);\n    }\n    // compute sparsite pattern for J(x) = F'(x)\n    bool transpose       = false;\n    bool dependency      = false;\n    bool internal_bool   = false;\n    sparsity pattern_out;\n    f.rev_jac_sparsity(\n        pattern_in, transpose, dependency, internal_bool, pattern_out\n    );\n    size_t nnz = pattern_out.nnz();\n    ok        &= nnz == 4;\n    ok        &= pattern_out.nr() == m;\n    ok        &= pattern_out.nc() == n;\n    {   // check results\n        const SizeVector& row( pattern_out.row() );\n        const SizeVector& col( pattern_out.col() );\n        SizeVector col_major = pattern_out.col_major();\n        //\n        ok &= row[ col_major[0] ] ==  0  && col[ col_major[0] ] ==  0;\n        ok &= row[ col_major[1] ] ==  1  && col[ col_major[1] ] ==  0;\n        ok &= row[ col_major[2] ] ==  1  && col[ col_major[2] ] ==  1;\n        ok &= row[ col_major[3] ] ==  2  && col[ col_major[3] ] ==  1;\n    }\n    // note that the transpose of the identity is the identity\n    transpose     = true;\n    internal_bool = true;\n    f.rev_jac_sparsity(\n        pattern_in, transpose, dependency, internal_bool, pattern_out\n    );\n    nnz  = pattern_out.nnz();\n    ok  &= nnz == 4;\n    ok  &= pattern_out.nr() == n;\n    ok  &= pattern_out.nc() == m;\n    {   // check results\n        const SizeVector& row( pattern_out.row() );\n        const SizeVector& col( pattern_out.col() );\n        SizeVector row_major = pattern_out.row_major();\n        //\n        ok &= col[ row_major[0] ] ==  0  && row[ row_major[0] ] ==  0;\n        ok &= col[ row_major[1] ] ==  1  && row[ row_major[1] ] ==  0;\n        ok &= col[ row_major[2] ] ==  1  && row[ row_major[2] ] ==  1;\n        ok &= col[ row_major[3] ] ==  2  && row[ row_major[3] ] ==  1;\n    }\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/sparse/rev_sparse_hes.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin rev_sparse_hes.cpp}\n\nReverse Mode Hessian Sparsity: Example and Test\n###############################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end rev_sparse_hes.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\nnamespace { // -------------------------------------------------------------\n\n// expected sparsity pattern\nbool check_f0[] = {\n    false, false, false,  // partials w.r.t x0 and (x0, x1, x2)\n    false, false, false,  // partials w.r.t x1 and (x0, x1, x2)\n    false, false, true    // partials w.r.t x2 and (x0, x1, x2)\n};\nbool check_f1[] = {\n    false,  true, false,  // partials w.r.t x0 and (x0, x1, x2)\n    true,  false, false,  // partials w.r.t x1 and (x0, x1, x2)\n    false, false, false   // partials w.r.t x2 and (x0, x1, x2)\n};\n\n// define the template function BoolCases<Vector> in empty namespace\ntemplate <class Vector> // vector class, elements of type bool\nbool BoolCases(void)\n{   bool ok = true;\n    using CppAD::AD;\n\n    // domain space vector\n    size_t n = 3;\n    CPPAD_TESTVECTOR(AD<double>) ax(n);\n    ax[0] = 0.;\n    ax[1] = 1.;\n    ax[2] = 2.;\n\n    // declare independent variables and start recording\n    CppAD::Independent(ax);\n\n    // range space vector\n    size_t m = 2;\n    CPPAD_TESTVECTOR(AD<double>) ay(m);\n    ay[0] = sin( ax[2] );\n    ay[1] = ax[0] * ax[1];\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(ax, ay);\n\n    // sparsity pattern for the identity matrix\n    Vector r(n * n);\n    size_t i, j;\n    for(i = 0; i < n; i++)\n    {   for(j = 0; j < n; j++)\n            r[ i * n + j ] = (i == j);\n    }\n\n    // compute sparsity pattern for J(x) = F^{(1)} (x)\n    f.ForSparseJac(n, r);\n\n    // compute sparsity pattern for H(x) = F_0^{(2)} (x)\n    Vector s(m);\n    for(i = 0; i < m; i++)\n        s[i] = false;\n    s[0] = true;\n    Vector h(n * n);\n    h    = f.RevSparseHes(n, s);\n\n    // check values\n    for(i = 0; i < n; i++)\n        for(j = 0; j < n; j++)\n            ok &= (h[ i * n + j ] == check_f0[ i * n + j ] );\n\n    // compute sparsity pattern for H(x) = F_1^{(2)} (x)\n    for(i = 0; i < m; i++)\n        s[i] = false;\n    s[1] = true;\n    h    = f.RevSparseHes(n, s);\n\n    // check values\n    for(i = 0; i < n; i++)\n        for(j = 0; j < n; j++)\n            ok &= (h[ i * n + j ] == check_f1[ i * n + j ] );\n\n    // call that transposed the result\n    bool transpose = true;\n    h    = f.RevSparseHes(n, s, transpose);\n\n    // This h is symmetric, because R is symmetric, not really testing here\n    for(i = 0; i < n; i++)\n        for(j = 0; j < n; j++)\n            ok &= (h[ j * n + i ] == check_f1[ i * n + j ] );\n\n    return ok;\n}\n// define the template function SetCases<Vector> in empty namespace\ntemplate <class Vector> // vector class, elements of type std::set<size_t>\nbool SetCases(void)\n{   bool ok = true;\n    using CppAD::AD;\n\n    // domain space vector\n    size_t n = 3;\n    CPPAD_TESTVECTOR(AD<double>) ax(n);\n    ax[0] = 0.;\n    ax[1] = 1.;\n    ax[2] = 2.;\n\n    // declare independent variables and start recording\n    CppAD::Independent(ax);\n\n    // range space vector\n    size_t m = 2;\n    CPPAD_TESTVECTOR(AD<double>) ay(m);\n    ay[0] = sin( ax[2] );\n    ay[1] = ax[0] * ax[1];\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(ax, ay);\n\n    // sparsity pattern for the identity matrix\n    Vector r(n);\n    size_t i;\n    for(i = 0; i < n; i++)\n    {   assert( r[i].empty() );\n        r[i].insert(i);\n    }\n\n    // compute sparsity pattern for J(x) = F^{(1)} (x)\n    f.ForSparseJac(n, r);\n\n    // compute sparsity pattern for H(x) = F_0^{(2)} (x)\n    Vector s(1);\n    assert( s[0].empty() );\n    s[0].insert(0);\n    Vector h(n);\n    h    = f.RevSparseHes(n, s);\n\n    // check values\n    std::set<size_t>::iterator itr;\n    size_t j;\n    for(i = 0; i < n; i++)\n    {   for(j = 0; j < n; j++)\n        {   bool found = h[i].find(j) != h[i].end();\n            ok        &= (found == check_f0[i * n + j]);\n        }\n    }\n\n    // compute sparsity pattern for H(x) = F_1^{(2)} (x)\n    s[0].clear();\n    assert( s[0].empty() );\n    s[0].insert(1);\n    h    = f.RevSparseHes(n, s);\n\n    // check values\n    for(i = 0; i < n; i++)\n    {   for(j = 0; j < n; j++)\n        {   bool found = h[i].find(j) != h[i].end();\n            ok        &= (found == check_f1[i * n + j]);\n        }\n    }\n\n    // call that transposed the result\n    bool transpose = true;\n    h    = f.RevSparseHes(n, s, transpose);\n\n    // This h is symmetric, because R is symmetric, not really testing here\n    for(i = 0; i < n; i++)\n    {   for(j = 0; j < n; j++)\n        {   bool found = h[j].find(i) != h[j].end();\n            ok        &= (found == check_f1[i * n + j]);\n        }\n    }\n\n    return ok;\n}\n} // End empty namespace\n\n# include <vector>\n# include <valarray>\nbool rev_sparse_hes(void)\n{   bool ok = true;\n    // Run with Vector equal to four different cases\n    // all of which are Simple Vectors with elements of type bool.\n    ok &= BoolCases< CppAD::vector  <bool> >();\n    ok &= BoolCases< CppAD::vectorBool     >();\n    ok &= BoolCases< std::vector    <bool> >();\n    ok &= BoolCases< std::valarray  <bool> >();\n\n    // Run with Vector equal to two different cases both of which are\n    // Simple Vectors with elements of type std::set<size_t>\n    typedef std::set<size_t> set;\n    ok &= SetCases< CppAD::vector  <set> >();\n    ok &= SetCases< std::vector    <set> >();\n\n    // Do not use valarray because its element access in the const case\n    // returns a copy instead of a reference\n    // ok &= SetCases< std::valarray  <set> >();\n\n    return ok;\n}\n\n\n// END C++\n"
  },
  {
    "path": "example/sparse/rev_sparse_jac.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin rev_sparse_jac.cpp}\n\nReverse Mode Jacobian Sparsity: Example and Test\n################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end rev_sparse_jac.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\nnamespace { // -------------------------------------------------------------\n// define the template function BoolCases<Vector>\ntemplate <class Vector>  // vector class, elements of type bool\nbool BoolCases(void)\n{   bool ok = true;\n    using CppAD::AD;\n\n    // domain space vector\n    size_t n = 2;\n    CPPAD_TESTVECTOR(AD<double>) ax(n);\n    ax[0] = 0.;\n    ax[1] = 1.;\n\n    // declare independent variables and start recording\n    CppAD::Independent(ax);\n\n    // range space vector\n    size_t m = 3;\n    CPPAD_TESTVECTOR(AD<double>) ay(m);\n    ay[0] = ax[0];\n    ay[1] = ax[0] * ax[1];\n    ay[2] = ax[1];\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(ax, ay);\n\n    // sparsity pattern for the identity matrix\n    Vector r(m * m);\n    size_t i, j;\n    for(i = 0; i < m; i++)\n    {   for(j = 0; j < m; j++)\n            r[ i * m + j ] = (i == j);\n    }\n\n    // sparsity pattern for F'(x)\n    Vector s(m * n);\n    s = f.RevSparseJac(m, r);\n\n    // check values\n    ok &= (s[ 0 * n + 0 ] == true);  // y[0] does     depend on x[0]\n    ok &= (s[ 0 * n + 1 ] == false); // y[0] does not depend on x[1]\n    ok &= (s[ 1 * n + 0 ] == true);  // y[1] does     depend on x[0]\n    ok &= (s[ 1 * n + 1 ] == true);  // y[1] does     depend on x[1]\n    ok &= (s[ 2 * n + 0 ] == false); // y[2] does not depend on x[0]\n    ok &= (s[ 2 * n + 1 ] == true);  // y[2] does     depend on x[1]\n\n    // sparsity pattern for F'(x)^T, note R is the identity, so R^T = R\n    bool transpose = true;\n    Vector st(n * m);\n    st = f.RevSparseJac(m, r, transpose);\n\n    // check values\n    ok &= (st[ 0 * m + 0 ] == true);  // y[0] does     depend on x[0]\n    ok &= (st[ 1 * m + 0 ] == false); // y[0] does not depend on x[1]\n    ok &= (st[ 0 * m + 1 ] == true);  // y[1] does     depend on x[0]\n    ok &= (st[ 1 * m + 1 ] == true);  // y[1] does     depend on x[1]\n    ok &= (st[ 0 * m + 2 ] == false); // y[2] does not depend on x[0]\n    ok &= (st[ 1 * m + 2 ] == true);  // y[2] does     depend on x[1]\n\n    return ok;\n}\n// define the template function SetCases<Vector>\ntemplate <class Vector>  // vector class, elements of type std::set<size_t>\nbool SetCases(void)\n{   bool ok = true;\n    using CppAD::AD;\n\n    // domain space vector\n    size_t n = 2;\n    CPPAD_TESTVECTOR(AD<double>) ax(n);\n    ax[0] = 0.;\n    ax[1] = 1.;\n\n    // declare independent variables and start recording\n    CppAD::Independent(ax);\n\n    // range space vector\n    size_t m = 3;\n    CPPAD_TESTVECTOR(AD<double>) ay(m);\n    ay[0] = ax[0];\n    ay[1] = ax[0] * ax[1];\n    ay[2] = ax[1];\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(ax, ay);\n\n    // sparsity pattern for the identity matrix\n    Vector r(m);\n    size_t i;\n    for(i = 0; i < m; i++)\n    {   assert( r[i].empty() );\n        r[i].insert(i);\n    }\n\n    // sparsity pattern for F'(x)\n    Vector s(m);\n    s = f.RevSparseJac(m, r);\n\n    // check values\n    bool found;\n\n    // y[0] does     depend on x[0]\n    found = s[0].find(0) != s[0].end();  ok &= (found == true);\n    // y[0] does not depend on x[1]\n    found = s[0].find(1) != s[0].end();  ok &= (found == false);\n    // y[1] does     depend on x[0]\n    found = s[1].find(0) != s[1].end();  ok &= (found == true);\n    // y[1] does     depend on x[1]\n    found = s[1].find(1) != s[1].end();  ok &= (found == true);\n    // y[2] does not depend on x[0]\n    found = s[2].find(0) != s[2].end();  ok &= (found == false);\n    // y[2] does     depend on x[1]\n    found = s[2].find(1) != s[2].end();  ok &= (found == true);\n\n    // sparsity pattern for F'(x)^T\n    bool transpose = true;\n    Vector st(n);\n    st = f.RevSparseJac(m, r, transpose);\n\n    // y[0] does     depend on x[0]\n    found = st[0].find(0) != st[0].end();  ok &= (found == true);\n    // y[0] does not depend on x[1]\n    found = st[1].find(0) != st[1].end();  ok &= (found == false);\n    // y[1] does     depend on x[0]\n    found = st[0].find(1) != st[0].end();  ok &= (found == true);\n    // y[1] does     depend on x[1]\n    found = st[1].find(1) != st[1].end();  ok &= (found == true);\n    // y[2] does not depend on x[0]\n    found = st[0].find(2) != st[0].end();  ok &= (found == false);\n    // y[2] does     depend on x[1]\n    found = st[1].find(2) != st[1].end();  ok &= (found == true);\n\n    return ok;\n}\n} // End empty namespace\n# include <vector>\n# include <valarray>\nbool RevSparseJac(void)\n{   bool ok = true;\n    // Run with Vector equal to four different cases\n    // all of which are Simple Vectors with elements of type bool.\n    ok &= BoolCases< CppAD::vectorBool     >();\n    ok &= BoolCases< CppAD::vector  <bool> >();\n    ok &= BoolCases< std::vector    <bool> >();\n    ok &= BoolCases< std::valarray  <bool> >();\n\n\n    // Run with Vector equal to two different cases both of which are\n    // Simple Vectors with elements of type std::set<size_t>\n    typedef std::set<size_t> set;\n    ok &= SetCases< CppAD::vector  <set> >();\n    ok &= SetCases< std::vector    <set> >();\n\n    // Do not use valarray because its element access in the const case\n    // returns a copy instead of a reference\n    // ok &= SetCases< std::valarray  <set> >();\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/sparse/sparse.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin sparse.cpp}\n\nSparse AD Examples and Tests Driver\n###################################\n\nRunning These Tests\n*******************\nAfter executing the :ref:`cmake-name` command\nform the :ref:`download@Distribution Directory`,\nyou can build and run these tests with the commands::\n\n    cd build\n    make check_example_sparse\n\nNote that your choice of :ref:`cmake@generator` may require using\nan different version of make; e.g., ``ninja`` .\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end sparse.cpp}\n-------------------------------------------------------------------------------\n*/\n// BEGIN C++\n\n// CPPAD_HAS_* defines\n# include <cppad/configure.hpp>\n\n// for thread_alloc\n# include <cppad/utility/thread_alloc.hpp>\n\n// test runner\n# include <cppad/utility/test_boolofvoid.hpp>\n\n// BEGIN_SORT_THIS_LINE_PLUS_2\n// external compiled tests\nextern bool ForSparseJac(void);\nextern bool RevSparseJac(void);\nextern bool colpack_hes(void);\nextern bool colpack_hessian(void);\nextern bool colpack_jac(void);\nextern bool colpack_jacobian(void);\nextern bool conj_grad(void);\nextern bool dependency(void);\nextern bool for_hes_sparsity(void);\nextern bool for_jac_sparsity(void);\nextern bool for_sparse_hes(void);\nextern bool rc_sparsity(void);\nextern bool rev_hes_sparsity(void);\nextern bool rev_jac_sparsity(void);\nextern bool rev_sparse_hes(void);\nextern bool sparse2eigen(void);\nextern bool sparse_hes(void);\nextern bool sparse_hessian(void);\nextern bool sparse_jac_for(void);\nextern bool sparse_jac_rev(void);\nextern bool sparse_jacobian(void);\nextern bool sparse_sub_hes(void);\nextern bool sparsity_sub(void);\nextern bool sub_sparse_hes(void);\nextern bool subgraph_hes2jac(void);\nextern bool subgraph_jac_rev(void);\nextern bool subgraph_reverse(void);\nextern bool subgraph_sparsity(void);\n// END_SORT_THIS_LINE_MINUS_1\n\n// main program that runs all the tests\nint main(void)\n{   std::string group = \"example/sparse\";\n    size_t      width = 20;\n    CppAD::test_boolofvoid Run(group, width);\n\n    // This line is used by test_one.sh\n\n    // BEGIN_SORT_THIS_LINE_PLUS_2\n    // external compiled tests\n    Run( ForSparseJac,              \"ForSparseJac\" );\n    Run( RevSparseJac,              \"RevSparseJac\" );\n    Run( conj_grad,                 \"conj_grad\" );\n    Run( dependency,                \"dependency\" );\n    Run( for_hes_sparsity,          \"for_hes_sparsity\" );\n    Run( for_jac_sparsity,          \"for_jac_sparsity\" );\n    Run( for_sparse_hes,            \"for_sparse_hes\" );\n    Run( rc_sparsity,               \"rc_sparsity\" );\n    Run( rev_hes_sparsity,          \"rev_hes_sparsity\" );\n    Run( rev_jac_sparsity,          \"rev_jac_sparsity\" );\n    Run( rev_sparse_hes,            \"rev_sparse_hes\" );\n    Run( sparse_hes,                \"sparse_hes\" );\n    Run( sparse_hessian,            \"sparse_hessian\" );\n    Run( sparse_jac_for,            \"sparse_jac_for\" );\n    Run( sparse_jac_rev,            \"sparse_jac_rev\" );\n    Run( sparse_jacobian,           \"sparse_jacobian\" );\n    Run( sparse_sub_hes,            \"sparse_sub_hes\" );\n    Run( sparsity_sub,              \"sparsity_sub\" );\n    Run( sub_sparse_hes,            \"sub_sparse_hes\" );\n    Run( subgraph_hes2jac,          \"subgraph_hes2jac\" );\n    Run( subgraph_jac_rev,          \"subgraph_jac_rev\" );\n    Run( subgraph_reverse,          \"reverse_subgraph\");\n    Run( subgraph_sparsity,         \"subgraph_sparsity\" );\n    // END_SORT_THIS_LINE_MINUS_1\n    //\n# if CPPAD_HAS_COLPACK\n    Run( colpack_jac,               \"colpack_jac\" );\n    Run( colpack_jacobian,          \"colpack_jacobian\" );\n    Run( colpack_hes,               \"colpack_hes\" );\n    Run( colpack_hessian,           \"colpack_hessian\" );\n# endif\n# if CPPAD_HAS_EIGEN\n    Run( sparse2eigen,              \"sparse2eigen\" );\n# endif\n    //\n    // check for memory leak\n    bool memory_ok = CppAD::thread_alloc::free_all();\n    // print summary at end\n    bool ok = Run.summary(memory_ok);\n    //\n    return static_cast<int>( ! ok );\n}\n// END C++\n"
  },
  {
    "path": "example/sparse/sparse2eigen.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin sparse2eigen.cpp}\n\nConverting CppAD Sparse Matrix to Eigen Format: Example and Test\n################################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end sparse2eigen.cpp}\n*/\n// BEGIN C++\n# include <cppad/utility/sparse2eigen.hpp>\nbool sparse2eigen(void)\n{   bool ok = true;\n    //\n    typedef CppAD::vector<size_t>                 s_vector;\n    typedef CppAD::vector<double>                 d_vector;\n    typedef CppAD::sparse_rc<s_vector>            sparse_rc;\n    typedef CppAD::sparse_rcv<s_vector, d_vector> sparse_rcv;\n    //\n    // sparsity pattern\n    size_t nr  = 3;\n    size_t nc  = 4;\n    size_t nnz = 2 * nr;\n    sparse_rc pattern(nr, nc, nnz);\n    for(size_t i = 0; i < nr; i++)\n    {   for(size_t j = i; j <= i + 1; j++)\n        {   size_t k = i + j;\n            pattern.set(k, i, j);\n        }\n    }\n    //\n    // sparse matrix\n    sparse_rcv source(pattern);\n    for(size_t i = 0; i < nr; i++)\n    {   for(size_t j = i; j <= i + 1; j++)\n        {   size_t k = i + j;\n            double v = double(k) / 2.0;\n            source.set(k, v);\n        }\n    }\n    //\n    //  example using row major order\n    {   Eigen::SparseMatrix<double, Eigen::RowMajor> destination;\n        CppAD::sparse2eigen(source, destination);\n        //\n        typedef\n        Eigen::SparseMatrix<double, Eigen::RowMajor>::InnerIterator iterator;\n        //\n        // check result\n        const double* d_value = destination.valuePtr();\n        size_t k = 0;\n        for(int i = 0; i < destination.outerSize(); ++i)\n        {\n            for(iterator itr(destination, i); itr; ++itr)\n            {   // check row\n                ok &= itr.row() == i;\n                //\n                // check column\n                if( k % 2 == 0 )\n                    ok &= itr.col() == i;\n                else\n                    ok &= itr.col() == (i+1);\n                //\n                // check value\n                ok  &= itr.value() == double( itr.row() + itr.col() ) / 2.0;\n                ok  &= itr.value() == d_value[k];\n                //\n                ++k;\n            }\n        }\n        ok &= k == nnz;\n    }\n    //\n    //  example using column major order\n    {   Eigen::SparseMatrix<double, Eigen::ColMajor> destination;\n        CppAD::sparse2eigen(source, destination);\n        //\n        typedef\n        Eigen::SparseMatrix<double, Eigen::ColMajor>::InnerIterator iterator;\n        //\n        // check result\n        const double* d_value = destination.valuePtr();\n        size_t k = 0;\n        for(int j = 0; j < destination.outerSize(); ++j)\n        {   for(iterator itr(destination, j); itr; ++itr)\n            {   // check column\n                ok &= itr.col() == j;\n                //\n                // check row\n                if( j == 0 )\n                {   assert( k == 0 );\n                    ok &= itr.row() == 0;\n                }\n                else if( k % 2 == 1 )\n                    ok &= itr.row() == j - 1;\n                else\n                    ok &= itr.row() == j;\n                //\n                // check value\n                ok  &= itr.value() == double( itr.row() + itr.col() ) / 2.0;\n                ok  &= itr.value() == d_value[k];\n                //\n                ++k;\n            }\n        }\n        ok &= k == nnz;\n    }\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/sparse/sparse_hes.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin sparse_hes.cpp}\n\nComputing Sparse Hessian: Example and Test\n##########################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end sparse_hes.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\nbool sparse_hes(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    //\n    typedef CPPAD_TESTVECTOR(AD<double>)               a_vector;\n    typedef CPPAD_TESTVECTOR(double)                   d_vector;\n    typedef CPPAD_TESTVECTOR(size_t)                   s_vector;\n    typedef CPPAD_TESTVECTOR(bool)                     b_vector;\n    //\n    // domain space vector\n    size_t n = 12;  // must be greater than or equal 3; see n_sweep below\n    a_vector a_x(n);\n    for(size_t j = 0; j < n; j++)\n        a_x[j] = AD<double> (0);\n    //\n    // declare independent variables and starting recording\n    CppAD::Independent(a_x);\n    //\n    // range space vector\n    size_t m = 1;\n    a_vector a_y(m);\n    a_y[0] = a_x[0] * a_x[1];\n    for(size_t j = 0; j < n; j++)\n        a_y[0] += a_x[j] * a_x[j] * a_x[j];\n    //\n    // create f: x -> y and stop tape recording\n    // (without executing zero order forward calculation)\n    CppAD::ADFun<double> f;\n    f.Dependent(a_x, a_y);\n    //\n    // new value for the independent variable vector, and weighting vector\n    d_vector w(m), x(n);\n    for(size_t j = 0; j < n; j++)\n        x[j] = double(j);\n    w[0] = 1.0;\n    //\n    // vector used to check the value of the hessian\n    d_vector check(n * n);\n    size_t ij  = 0 * n + 1;\n    for(ij = 0; ij < n * n; ij++)\n        check[ij] = 0.0;\n    ij         = 0 * n + 1;\n    check[ij]  = 1.0;\n    ij         = 1 * n + 0;\n    check[ij]  = 1.0 ;\n    for(size_t j = 0; j < n; j++)\n    {   ij = j * n + j;\n        check[ij] = 6.0 * x[j];\n    }\n    //\n    // compute Hessian sparsity pattern\n    b_vector select_domain(n), select_range(m);\n    for(size_t j = 0; j < n; j++)\n        select_domain[j] = true;\n    select_range[0] = true;\n    //\n    CppAD::sparse_rc<s_vector> hes_pattern;\n    bool internal_bool = false;\n    f.for_hes_sparsity(\n        select_domain, select_range, internal_bool, hes_pattern\n    );\n    //\n    // compute entire sparse Hessian (really only need lower triangle)\n    CppAD::sparse_rcv<s_vector, d_vector> subset( hes_pattern );\n    CppAD::sparse_hes_work work;\n    std::string coloring = \"cppad.symmetric\";\n    size_t n_sweep = f.sparse_hes(x, w, subset, hes_pattern, coloring, work);\n    ok &= n_sweep == 2;\n    //\n    const s_vector row( subset.row() );\n    const s_vector col( subset.col() );\n    const d_vector val( subset.val() );\n    size_t nnz = subset.nnz();\n    ok &= nnz == n + 2;\n    for(size_t k = 0; k < nnz; k++)\n    {   ij = row[k] * n + col[k];\n        ok &= val[k] == check[ij];\n    }\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/sparse/sparse_hessian.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin sparse_hessian.cpp}\n\nSparse Hessian: Example and Test\n################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end sparse_hessian.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\nbool sparse_hessian(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    size_t i, j, k, ell;\n    typedef CPPAD_TESTVECTOR(AD<double>)               a_vector;\n    typedef CPPAD_TESTVECTOR(double)                     d_vector;\n    typedef CPPAD_TESTVECTOR(size_t)                     i_vector;\n    typedef CPPAD_TESTVECTOR(bool)                       b_vector;\n    typedef CPPAD_TESTVECTOR(std::set<size_t>)         s_vector;\n    double eps = 10. * CppAD::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n = 12;  // must be greater than or equal 3; see n_sweep below\n    a_vector a_x(n);\n    for(j = 0; j < n; j++)\n        a_x[j] = AD<double> (0);\n\n    // declare independent variables and starting recording\n    CppAD::Independent(a_x);\n\n    // range space vector\n    size_t m = 1;\n    a_vector a_y(m);\n    a_y[0] = a_x[0]*a_x[1];\n    for(j = 0; j < n; j++)\n        a_y[0] += a_x[j] * a_x[j] * a_x[j];\n\n    // create f: x -> y and stop tape recording\n    // (without executing zero order forward calculation)\n    CppAD::ADFun<double> f;\n    f.Dependent(a_x, a_y);\n\n    // new value for the independent variable vector, and weighting vector\n    d_vector w(m), x(n);\n    for(j = 0; j < n; j++)\n        x[j] = double(j);\n    w[0] = 1.0;\n\n    // vector used to check the value of the hessian\n    d_vector check(n * n);\n    for(ell = 0; ell < n * n; ell++)\n        check[ell] = 0.0;\n    ell        = 0 * n + 1;\n    check[ell] = 1.0;\n    ell        = 1 * n + 0;\n    check[ell] = 1.0 ;\n    for(j = 0; j < n; j++)\n    {   ell = j * n + j;\n        check[ell] = 6.0 * x[j];\n    }\n\n    // -------------------------------------------------------------------\n    // second derivative of y[0] w.r.t x\n    d_vector hes(n * n);\n    hes = f.SparseHessian(x, w);\n    for(ell = 0; ell < n * n; ell++)\n        ok &=  NearEqual(w[0] * check[ell], hes[ell], eps, eps );\n\n    // --------------------------------------------------------------------\n    // example using vectors of bools to compute sparsity pattern for Hessian\n    b_vector r_bool(n * n);\n    for(i = 0; i < n; i++)\n    {   for(j = 0; j < n; j++)\n            r_bool[i * n + j] = false;\n        r_bool[i * n + i] = true;\n    }\n    f.ForSparseJac(n, r_bool);\n    //\n    b_vector s_bool(m);\n    for(i = 0; i < m; i++)\n        s_bool[i] = w[i] != 0;\n    b_vector p_bool = f.RevSparseHes(n, s_bool);\n\n    hes = f.SparseHessian(x, w, p_bool);\n    for(ell = 0; ell < n * n; ell++)\n        ok &=  NearEqual(w[0] * check[ell], hes[ell], eps, eps );\n\n    // --------------------------------------------------------------------\n    // example using vectors of sets to compute sparsity pattern for Hessian\n    s_vector r_set(n);\n    for(i = 0; i < n; i++)\n        r_set[i].insert(i);\n    f.ForSparseJac(n, r_set);\n    //\n    s_vector s_set(m);\n    for(i = 0; i < m; i++)\n        if( w[i] != 0. )\n            s_set[0].insert(i);\n    s_vector p_set = f.RevSparseHes(n, s_set);\n\n    // example passing sparsity pattern to SparseHessian\n    hes = f.SparseHessian(x, w, p_set);\n    for(ell = 0; ell < n * n; ell++)\n        ok &=  NearEqual(w[0] * check[ell], hes[ell], eps, eps );\n\n    // --------------------------------------------------------------------\n    // use row and column indices to specify upper triangle of\n    // non-zero elements of Hessian\n    size_t K = n + 1;\n    i_vector row(K), col(K);\n    hes.resize(K);\n    k = 0;\n    for(j = 0; j < n; j++)\n    {   // diagonal of Hessian\n        row[k] = j;\n        col[k] = j;\n        k++;\n    }\n    // only off diagonal non-zero element in upper triangle\n    row[k] = 0;\n    col[k] = 1;\n    k++;\n    ok &= k == K;\n    CppAD::sparse_hessian_work work;\n\n    // can use p_set or p_bool.\n    size_t n_sweep = f.SparseHessian(x, w, p_set, row, col, hes, work);\n    for(k = 0; k < K; k++)\n    {   ell = row[k] * n + col[k];\n        ok &=  NearEqual(w[0] * check[ell], hes[k], eps, eps );\n    }\n    ok &= n_sweep == 2;\n\n    // now recompute at a different x and w (using work from previous call\n    w[0]       = 2.0;\n    x[1]       = 0.5;\n    ell        = 1 * n + 1;\n    check[ell] = 6.0 * x[1];\n    s_vector   not_used;\n    n_sweep    = f.SparseHessian(x, w, not_used, row, col, hes, work);\n    for(k = 0; k < K; k++)\n    {   ell = row[k] * n + col[k];\n        ok &=  NearEqual(w[0] * check[ell], hes[k], eps, eps );\n    }\n    ok &= n_sweep == 2;\n\n\n\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/sparse/sparse_jac_for.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin sparse_jac_for.cpp}\n\nComputing Sparse Jacobian Using Forward Mode: Example and Test\n##############################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end sparse_jac_for.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\nbool sparse_jac_for(void)\n{   bool ok = true;\n    //\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    using CppAD::sparse_rc;\n    using CppAD::sparse_rcv;\n    //\n    typedef CPPAD_TESTVECTOR(AD<double>) a_vector;\n    typedef CPPAD_TESTVECTOR(double)     d_vector;\n    typedef CPPAD_TESTVECTOR(size_t)     s_vector;\n    //\n    // domain space vector\n    size_t n = 3;\n    a_vector  a_x(n);\n    for(size_t j = 0; j < n; j++)\n        a_x[j] = AD<double> (0);\n    //\n    // declare independent variables and starting recording\n    CppAD::Independent(a_x);\n    //\n    size_t m = 4;\n    a_vector  a_y(m);\n    a_y[0] = a_x[0] + a_x[2];\n    a_y[1] = a_x[0] + a_x[2];\n    a_y[2] = a_x[1] + a_x[2];\n    a_y[3] = a_x[1] + a_x[2] * a_x[2] / 2.;\n    //\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(a_x, a_y);\n    //\n    // new value for the independent variable vector\n    d_vector x(n);\n    for(size_t j = 0; j < n; j++)\n        x[j] = double(j);\n    /*\n              [ 1 0 1   ]\n    J(x) = [ 1 0 1   ]\n              [ 0 1 1   ]\n              [ 0 1 x_2 ]\n    */\n    d_vector check(m * n);\n    //\n    // column-major order values of J(x)\n    size_t nnz = 8;\n    s_vector check_row(nnz), check_col(nnz);\n    d_vector check_val(nnz);\n    for(size_t k = 0; k < nnz; k++)\n    {   // check_val\n        if( k < 7 )\n            check_val[k] = 1.0;\n        else\n            check_val[k] = x[2];\n        //\n        // check_row and check_col\n        check_row[k] = k;\n        if( k < 2 )\n            check_col[k] = 0;\n        else if( k < 4 )\n            check_col[k] = 1;\n        else\n        {   check_col[k] = 2;\n            check_row[k] = k - 4;\n        }\n    }\n    //\n    // n by n identity matrix sparsity\n    sparse_rc<s_vector> pattern_in;\n    pattern_in.resize(n, n, n);\n    for(size_t k = 0; k < n; k++)\n        pattern_in.set(k, k, k);\n    //\n    // sparsity for J(x)\n    bool transpose     = false;\n    bool dependency    = false;\n    bool internal_bool = true;\n    sparse_rc<s_vector> pattern_jac;\n    f.for_jac_sparsity(\n        pattern_in, transpose, dependency, internal_bool, pattern_jac\n    );\n    //\n    // compute entire forward mode Jacobian\n    sparse_rcv<s_vector, d_vector> subset( pattern_jac );\n    CppAD::sparse_jac_work work;\n    std::string coloring = \"cppad\";\n    size_t group_max = 10;\n    size_t n_color = f.sparse_jac_for(\n        group_max, x, subset, pattern_jac, coloring, work\n    );\n    ok &= n_color == 2;\n    //\n    const s_vector row( subset.row() );\n    const s_vector col( subset.col() );\n    const d_vector val( subset.val() );\n    s_vector col_major = subset.col_major();\n    ok  &= subset.nnz() == nnz;\n    for(size_t k = 0; k < nnz; k++)\n    {   ok &= row[ col_major[k] ] == check_row[k];\n        ok &= col[ col_major[k] ] == check_col[k];\n        ok &= val[ col_major[k] ] == check_val[k];\n    }\n    // compute non-zero in row 3 only\n    sparse_rc<s_vector> pattern_row3;\n    pattern_row3.resize(m, n, 2); // nr = m, nc = n, nnz = 2\n    pattern_row3.set(0, 3, 1);    // row[0] = 3, col[0] = 1\n    pattern_row3.set(1, 3, 2);    // row[1] = 3, col[1] = 2\n    sparse_rcv<s_vector, d_vector> subset_row3( pattern_row3 );\n    work.clear();\n    n_color = f.sparse_jac_for(\n        group_max, x, subset_row3, pattern_jac, coloring, work\n    );\n    ok &= n_color == 2;\n    //\n    const s_vector row_row3( subset_row3.row() );\n    const s_vector col_row3( subset_row3.col() );\n    const d_vector val_row3( subset_row3.val() );\n    ok &= subset_row3.nnz() == 2;\n    //\n    ok &= row_row3[0] == 3;\n    ok &= col_row3[0] == 1;\n    ok &= val_row3[0] == 1.0;\n    //\n    ok &= row_row3[1] == 3;\n    ok &= col_row3[1] == 2;\n    ok &= val_row3[1] == x[2];\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/sparse/sparse_jac_rev.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin sparse_jac_rev.cpp}\n\nComputing Sparse Jacobian Using Reverse Mode: Example and Test\n##############################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end sparse_jac_rev.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\nbool sparse_jac_rev(void)\n{   bool ok = true;\n    //\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    using CppAD::sparse_rc;\n    using CppAD::sparse_rcv;\n    //\n    typedef CPPAD_TESTVECTOR(AD<double>) a_vector;\n    typedef CPPAD_TESTVECTOR(double)     d_vector;\n    typedef CPPAD_TESTVECTOR(size_t)     s_vector;\n    //\n    // domain space vector\n    size_t n = 4;\n    a_vector  a_x(n);\n    for(size_t j = 0; j < n; j++)\n        a_x[j] = AD<double> (0);\n    //\n    // declare independent variables and starting recording\n    CppAD::Independent(a_x);\n    //\n    size_t m = 3;\n    a_vector  a_y(m);\n    a_y[0] = a_x[0] + a_x[1];\n    a_y[1] = a_x[2] + a_x[3];\n    a_y[2] = a_x[0] + a_x[1] + a_x[2] + a_x[3] * a_x[3] / 2.;\n    //\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(a_x, a_y);\n    //\n    // new value for the independent variable vector\n    d_vector x(n);\n    for(size_t j = 0; j < n; j++)\n        x[j] = double(j);\n    /*\n              [ 1 1 0 0  ]\n    J(x) = [ 0 0 1 1  ]\n              [ 1 1 1 x_3]\n    */\n    //\n    // row-major order values of J(x)\n    size_t nnz = 8;\n    s_vector check_row(nnz), check_col(nnz);\n    d_vector check_val(nnz);\n    for(size_t k = 0; k < nnz; k++)\n    {   // check_val\n        if( k < 7 )\n            check_val[k] = 1.0;\n        else\n            check_val[k] = x[3];\n        //\n        // check_row and check_col\n        check_col[k] = k;\n        if( k < 2 )\n            check_row[k] = 0;\n        else if( k < 4 )\n            check_row[k] = 1;\n        else\n        {   check_row[k] = 2;\n            check_col[k] = k - 4;\n        }\n    }\n    //\n    // m by m identity matrix sparsity\n    sparse_rc<s_vector> pattern_in(m, m, m);\n    for(size_t k = 0; k < m; k++)\n        pattern_in.set(k, k, k);\n    //\n    // sparsity for J(x)\n    bool transpose     = false;\n    bool dependency    = false;\n    bool internal_bool = true;\n    sparse_rc<s_vector> pattern_jac;\n    f.rev_jac_sparsity(\n        pattern_in, transpose, dependency, internal_bool, pattern_jac\n    );\n    //\n    // compute entire reverse mode Jacobian\n    sparse_rcv<s_vector, d_vector> subset( pattern_jac );\n    CppAD::sparse_jac_work work;\n    std::string coloring = \"cppad\";\n    size_t n_sweep = f.sparse_jac_rev(x, subset, pattern_jac, coloring, work);\n    ok &= n_sweep == 2;\n    //\n    const s_vector row( subset.row() );\n    const s_vector col( subset.col() );\n    const d_vector val( subset.val() );\n    s_vector row_major = subset.row_major();\n    ok  &= subset.nnz() == nnz;\n    for(size_t k = 0; k < nnz; k++)\n    {   ok &= row[ row_major[k] ] == check_row[k];\n        ok &= col[ row_major[k] ] == check_col[k];\n        ok &= val[ row_major[k] ] == check_val[k];\n    }\n    //\n    // test using work stored by previous sparse_jac_rev\n    sparse_rc<s_vector> pattern_not_used;\n    std::string         coloring_not_used;\n    n_sweep = f.sparse_jac_rev(x, subset, pattern_jac, coloring, work);\n    ok &= n_sweep == 2;\n    for(size_t k = 0; k < nnz; k++)\n    {   ok &= row[ row_major[k] ] == check_row[k];\n        ok &= col[ row_major[k] ] == check_col[k];\n        ok &= val[ row_major[k] ] == check_val[k];\n    }\n    //\n    // compute non-zero in col 3 only, nr = m, nc = n, nnz = 2\n    sparse_rc<s_vector> pattern_col3(m, n, 2);\n    pattern_col3.set(0, 1, 3);    // row[0] = 1, col[0] = 3\n    pattern_col3.set(1, 2, 3);    // row[1] = 2, col[1] = 3\n    sparse_rcv<s_vector, d_vector> subset_col3( pattern_col3 );\n    work.clear();\n    n_sweep = f.sparse_jac_rev(x, subset_col3, pattern_jac, coloring, work);\n    ok &= n_sweep == 2;\n    //\n    const s_vector row_col3( subset_col3.row() );\n    const s_vector col_col3( subset_col3.col() );\n    const d_vector val_col3( subset_col3.val() );\n    ok &= subset_col3.nnz() == 2;\n    //\n    ok &= row_col3[0] == 1;\n    ok &= col_col3[0] == 3;\n    ok &= val_col3[0] == 1.0;\n    //\n    ok &= row_col3[1] == 2;\n    ok &= col_col3[1] == 3;\n    ok &= val_col3[1] == x[3];\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/sparse/sparse_jacobian.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin sparse_jacobian.cpp}\n\nSparse Jacobian: Example and Test\n#################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end sparse_jacobian.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\nnamespace { // ---------------------------------------------------------\nbool reverse()\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    typedef CPPAD_TESTVECTOR(AD<double>)   a_vector;\n    typedef CPPAD_TESTVECTOR(double)       d_vector;\n    typedef CPPAD_TESTVECTOR(size_t)       i_vector;\n    size_t i, j, k, ell;\n    double eps = 10. * CppAD::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n = 4;\n    a_vector  a_x(n);\n    for(j = 0; j < n; j++)\n        a_x[j] = AD<double> (0);\n\n    // declare independent variables and starting recording\n    CppAD::Independent(a_x);\n\n    size_t m = 3;\n    a_vector  a_y(m);\n    a_y[0] = a_x[0] + a_x[1];\n    a_y[1] = a_x[2] + a_x[3];\n    a_y[2] = a_x[0] + a_x[1] + a_x[2] + a_x[3] * a_x[3] / 2.;\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(a_x, a_y);\n\n    // new value for the independent variable vector\n    d_vector x(n);\n    for(j = 0; j < n; j++)\n        x[j] = double(j);\n\n    // Jacobian of y without sparsity pattern\n    d_vector jac(m * n);\n    jac = f.SparseJacobian(x);\n    /*\n             [ 1 1 0 0  ]\n    jac = [ 0 0 1 1  ]\n             [ 1 1 1 x_3]\n    */\n    d_vector check(m * n);\n    check[0] = 1.; check[1] = 1.; check[2]  = 0.; check[3]  = 0.;\n    check[4] = 0.; check[5] = 0.; check[6]  = 1.; check[7]  = 1.;\n    check[8] = 1.; check[9] = 1.; check[10] = 1.; check[11] = x[3];\n    for(ell = 0; ell < size_t(check.size()); ell++)\n        ok &=  NearEqual(check[ell], jac[ell], eps, eps );\n\n    // using packed boolean sparsity patterns\n    CppAD::vectorBool s_b(m * m), p_b(m * n);\n    for(i = 0; i < m; i++)\n    {   for(ell = 0; ell < m; ell++)\n            s_b[i * m + ell] = false;\n        s_b[i * m + i] = true;\n    }\n    p_b   = f.RevSparseJac(m, s_b);\n    jac   = f.SparseJacobian(x, p_b);\n    for(ell = 0; ell < size_t(check.size()); ell++)\n        ok &=  NearEqual(check[ell], jac[ell], eps, eps );\n\n    // using vector of sets sparsity patterns\n    std::vector< std::set<size_t> > s_s(m),  p_s(m);\n    for(i = 0; i < m; i++)\n        s_s[i].insert(i);\n    p_s   = f.RevSparseJac(m, s_s);\n    jac   = f.SparseJacobian(x, p_s);\n    for(ell = 0; ell < size_t(check.size()); ell++)\n        ok &=  NearEqual(check[ell], jac[ell], eps, eps );\n\n    // using row and column indices to compute non-zero in rows 1 and 2\n    // (skip row 0).\n    size_t K = 6;\n    i_vector row(K), col(K);\n    jac.resize(K);\n    k = 0;\n    for(j = 0; j < n; j++)\n    {   for(i = 1; i < m; i++)\n        {   ell = i * n + j;\n            if( p_b[ell] )\n            {   ok &= check[ell] != 0.;\n                row[k] = i;\n                col[k] = j;\n                k++;\n            }\n        }\n    }\n    ok &= k == K;\n\n    // empty work structure\n    CppAD::sparse_jacobian_work work;\n\n    // could use p_b\n    size_t n_sweep = f.SparseJacobianReverse(x, p_s, row, col, jac, work);\n    for(k = 0; k < K; k++)\n    {   ell = row[k] * n + col[k];\n        ok &= NearEqual(check[ell], jac[k], eps, eps);\n    }\n    ok &= n_sweep == 2;\n\n    // now recompute at a different x value (using work from previous call)\n    check[11] = x[3] = 10.;\n    std::vector< std::set<size_t> > not_used;\n    n_sweep = f.SparseJacobianReverse(x, not_used, row, col, jac, work);\n    for(k = 0; k < K; k++)\n    {   ell = row[k] * n + col[k];\n        ok &= NearEqual(check[ell], jac[k], eps, eps);\n    }\n    ok &= n_sweep == 2;\n\n    return ok;\n}\n\nbool forward()\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    typedef CPPAD_TESTVECTOR(AD<double>) a_vector;\n    typedef CPPAD_TESTVECTOR(double)       d_vector;\n    typedef CPPAD_TESTVECTOR(size_t)       i_vector;\n    size_t i, j, k, ell;\n    double eps = 10. * CppAD::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n = 3;\n    a_vector  a_x(n);\n    for(j = 0; j < n; j++)\n        a_x[j] = AD<double> (0);\n\n    // declare independent variables and starting recording\n    CppAD::Independent(a_x);\n\n    size_t m = 4;\n    a_vector  a_y(m);\n    a_y[0] = a_x[0] + a_x[2];\n    a_y[1] = a_x[0] + a_x[2];\n    a_y[2] = a_x[1] + a_x[2];\n    a_y[3] = a_x[1] + a_x[2] * a_x[2] / 2.;\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(a_x, a_y);\n\n    // new value for the independent variable vector\n    d_vector x(n);\n    for(j = 0; j < n; j++)\n        x[j] = double(j);\n\n    // Jacobian of y without sparsity pattern\n    d_vector jac(m * n);\n    jac = f.SparseJacobian(x);\n    /*\n             [ 1 0 1   ]\n    jac = [ 1 0 1   ]\n             [ 0 1 1   ]\n             [ 0 1 x_2 ]\n    */\n    d_vector check(m * n);\n    check[0] = 1.; check[1]  = 0.; check[2]  = 1.;\n    check[3] = 1.; check[4]  = 0.; check[5]  = 1.;\n    check[6] = 0.; check[7]  = 1.; check[8]  = 1.;\n    check[9] = 0.; check[10] = 1.; check[11] = x[2];\n    for(ell = 0; ell < size_t(check.size()); ell++)\n        ok &=  NearEqual(check[ell], jac[ell], eps, eps );\n\n    // test using packed boolean vectors for sparsity pattern\n    CppAD::vectorBool r_b(n * n), p_b(m * n);\n    for(j = 0; j < n; j++)\n    {   for(ell = 0; ell < n; ell++)\n            r_b[j * n + ell] = false;\n        r_b[j * n + j] = true;\n    }\n    p_b = f.ForSparseJac(n, r_b);\n    jac = f.SparseJacobian(x, p_b);\n    for(ell = 0; ell < size_t(check.size()); ell++)\n        ok &=  NearEqual(check[ell], jac[ell], eps, eps );\n\n    // test using vector of sets for sparsity pattern\n    std::vector< std::set<size_t> > r_s(n), p_s(m);\n    for(j = 0; j < n; j++)\n        r_s[j].insert(j);\n    p_s = f.ForSparseJac(n, r_s);\n    jac = f.SparseJacobian(x, p_s);\n    for(ell = 0; ell < size_t(check.size()); ell++)\n        ok &=  NearEqual(check[ell], jac[ell], eps, eps );\n\n    // using row and column indices to compute non-zero elements excluding\n    // row 0 and column 0.\n    size_t K = 5;\n    i_vector row(K), col(K);\n    jac.resize(K);\n    k = 0;\n    for(i = 1; i < m; i++)\n    {   for(j = 1; j < n; j++)\n        {   ell = i * n + j;\n            if( p_b[ell] )\n            {   ok &= check[ell] != 0.;\n                row[k] = i;\n                col[k] = j;\n                k++;\n            }\n        }\n    }\n    ok &= k == K;\n\n    // empty work structure\n    CppAD::sparse_jacobian_work work;\n\n    // could use p_s\n    size_t n_sweep = f.SparseJacobianForward(x, p_b, row, col, jac, work);\n    for(k = 0; k < K; k++)\n    {     ell = row[k] * n + col[k];\n        ok &= NearEqual(check[ell], jac[k], eps, eps);\n    }\n    ok &= n_sweep == 2;\n\n    // now recompute at a different x value (using work from previous call)\n    check[11] = x[2] = 10.;\n    n_sweep = f.SparseJacobianForward(x, p_s, row, col, jac, work);\n    for(k = 0; k < K; k++)\n    {     ell = row[k] * n + col[k];\n        ok &= NearEqual(check[ell], jac[k], eps, eps);\n    }\n    ok &= n_sweep == 2;\n\n    return ok;\n}\n} // End empty namespace\n\nbool sparse_jacobian(void)\n{   bool ok = true;\n    ok &= forward();\n    ok &= reverse();\n\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/sparse/sparse_sub_hes.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin sparse_sub_hes.cpp}\n\nSubset of a Sparse Hessian: Example and Test\n############################################\n\nPurpose\n*******\nThis example uses a\n:ref:`sparse_hessian@p@Column Subset` of the sparsity pattern\nto compute a subset of the Hessian.\n\nSee Also\n********\n:ref:`sub_sparse_hes.cpp-name`\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end sparse_sub_hes.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\nbool sparse_sub_hes(void)\n{   bool ok = true;\n    using CppAD::AD;\n    typedef CPPAD_TESTVECTOR(size_t)     SizeVector;\n    typedef CPPAD_TESTVECTOR(double)     DoubleVector;\n    typedef CppAD::sparse_rc<SizeVector> sparsity;\n    //\n    // domain space vector\n    size_t n = 4;\n    CPPAD_TESTVECTOR(AD<double>) ax(n);\n    for(size_t j = 0; j < n; j++)\n        ax[j] = double(j);\n\n    // declare independent variables and start recording\n    CppAD::Independent(ax);\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) ay(m);\n    ay[0] = 0.0;\n    for(size_t j = 0; j < n; j++)\n        ay[0] += double(j+1) * ax[0] * ax[j];\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(ax, ay);\n\n    // sparsity pattern for the identity matrix\n    size_t nr     = n;\n    size_t nc     = n;\n    size_t nnz_in = n;\n    sparsity pattern_in(nr, nc, nnz_in);\n    for(size_t k = 0; k < nnz_in; k++)\n    {   size_t r = k;\n        size_t c = k;\n        pattern_in.set(k, r, c);\n    }\n    // compute sparsity pattern for J(x) = f'(x)\n    bool transpose       = false;\n    bool dependency      = false;\n    bool internal_bool   = false;\n    sparsity pattern_out;\n    f.for_jac_sparsity(\n        pattern_in, transpose, dependency, internal_bool, pattern_out\n    );\n    //\n    // compute sparsity pattern for H(x) = f''(x)\n    CPPAD_TESTVECTOR(bool) select_range(m);\n    select_range[0]      = true;\n    CppAD::sparse_hes_work work;\n    f.rev_hes_sparsity(\n        select_range, transpose, internal_bool, pattern_out\n    );\n    size_t nnz = pattern_out.nnz();\n    ok        &= nnz == 7;\n    ok        &= pattern_out.nr() == n;\n    ok        &= pattern_out.nc() == n;\n    {   // check results\n        const SizeVector& row( pattern_out.row() );\n        const SizeVector& col( pattern_out.col() );\n        SizeVector row_major = pattern_out.row_major();\n        //\n        ok &= row[ row_major[0] ] ==  0  && col[ row_major[0] ] ==  0;\n        ok &= row[ row_major[1] ] ==  0  && col[ row_major[1] ] ==  1;\n        ok &= row[ row_major[2] ] ==  0  && col[ row_major[2] ] ==  2;\n        ok &= row[ row_major[3] ] ==  0  && col[ row_major[3] ] ==  3;\n        //\n        ok &= row[ row_major[4] ] ==  1  && col[ row_major[4] ] ==  0;\n        ok &= row[ row_major[5] ] ==  2  && col[ row_major[5] ] ==  0;\n        ok &= row[ row_major[6] ] ==  3  && col[ row_major[6] ] ==  0;\n    }\n    //\n    // Only interested in cross-terms. Since we are not computing rwo 0,\n    // we do not need sparsity entries in row 0.\n    CppAD::sparse_rc<SizeVector> subset_pattern(n, n, 3);\n    for(size_t k = 0; k < 3; k++)\n        subset_pattern.set(k, k+1, 0);\n    CppAD::sparse_rcv<SizeVector, DoubleVector> subset( subset_pattern );\n    //\n    // argument and weight values for computation\n    CPPAD_TESTVECTOR(double) x(n), w(m);\n    for(size_t j = 0; j < n; j++)\n        x[j] = double(n) / double(j+1);\n    w[0] = 1.0;\n    //\n    std::string coloring = \"cppad.general\";\n    size_t n_sweep = f.sparse_hes(\n        x, w, subset, subset_pattern, coloring, work\n    );\n    ok &= n_sweep == 1;\n    for(size_t k = 0; k < 3; k++)\n    {   size_t i = k + 1;\n        ok &= subset.val()[k] == double(i + 1);\n    }\n    //\n    // convert subset from lower triangular to upper triangular\n    for(size_t k = 0; k < 3; k++)\n        subset_pattern.set(k, 0, k+1);\n    subset = CppAD::sparse_rcv<SizeVector, DoubleVector>( subset_pattern );\n    //\n    // This will require more work because the Hessian is computed\n    // column by column (not row by row).\n    work.clear();\n    n_sweep = f.sparse_hes(\n        x, w, subset, subset_pattern, coloring, work\n    );\n    ok &= n_sweep == 3;\n    //\n    // but it will get the right answer\n    for(size_t k = 0; k < 3; k++)\n    {   size_t i = k + 1;\n        ok &= subset.val()[k] == double(i + 1);\n    }\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/sparse/sparsity_sub.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin sparsity_sub.cpp}\n\nSparsity Patterns For a Subset of Variables: Example and Test\n#############################################################\n\nSee Also\n********\n:ref:`sparse_sub_hes.cpp-name` , :ref:`sub_sparse_hes.cpp-name` .\n\nForSparseJac\n************\nThe routine :ref:`ForSparseJac-name` is used to compute the\nsparsity for both the full Jacobian (see *s* )\nand a subset of the Jacobian (see *s2* ).\n\nRevSparseHes\n************\nThe routine :ref:`RevSparseHes-name` is used to compute both\nsparsity for both the full Hessian (see *h* )\nand a subset of the Hessian (see *h2* ).\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end sparsity_sub.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nbool sparsity_sub(void)\n{   // C++ source code\n    bool ok = true;\n    //\n    using std::cout;\n    using CppAD::vector;\n    using CppAD::AD;\n    using CppAD::vectorBool;\n\n    size_t n = 4;\n    size_t m = n-1;\n    vector< AD<double> > ax(n), ay(m);\n    for(size_t j = 0; j < n; j++)\n        ax[j] = double(j+1);\n    CppAD::Independent(ax);\n    for(size_t i = 0; i < m; i++)\n        ay[i] = (ax[i+1] - ax[i]) * (ax[i+1] - ax[i]);\n    CppAD::ADFun<double> f(ax, ay);\n\n    // Evaluate the full Jacobian sparsity pattern for f\n    vectorBool r(n * n), s(m * n);\n    for(size_t j = 0 ; j < n; j++)\n    {   for(size_t i = 0; i < n; i++)\n            r[i * n + j] = (i == j);\n    }\n    s = f.ForSparseJac(n, r);\n\n    // evaluate the sparsity for the Hessian of f_0 + ... + f_{m-1}\n    vectorBool t(m), h(n * n);\n    for(size_t i = 0; i < m; i++)\n        t[i] = true;\n    h = f.RevSparseHes(n, t);\n\n    // evaluate the Jacobian sparsity pattern for first n/2 components of x\n    size_t n2 = n / 2;\n    vectorBool r2(n * n2), s2(m * n2);\n    for(size_t j = 0 ; j < n2; j++)\n    {   for(size_t i = 0; i < n; i++)\n            r2[i * n2 + j] = (i == j);\n    }\n    s2 = f.ForSparseJac(n2, r2);\n\n    // evaluate the sparsity for the subset of Hessian of\n    // f_0 + ... + f_{m-1} where first partial has only first n/2 components\n    vectorBool h2(n2 * n);\n    h2 = f.RevSparseHes(n2, t);\n\n    // check sparsity pattern for Jacobian\n    for(size_t i = 0; i < m; i++)\n    {   for(size_t j = 0; j < n2; j++)\n            ok &= s2[i * n2 + j] == s[i * n + j];\n    }\n\n    // check sparsity pattern for Hessian\n    for(size_t i = 0; i < n2; i++)\n    {   for(size_t j = 0; j < n; j++)\n            ok &= h2[i * n + j] == h[i * n + j];\n    }\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/sparse/sub_sparse_hes.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin sub_sparse_hes.cpp}\n{xrst_spell\n    nv\n}\n\nComputing Sparse Hessian for a Subset of Variables\n##################################################\n\nPurpose\n*******\nThis example uses\n:ref:`multiple levels of AD<mul_level-name>`\nto compute the Hessian for a subset of the variables\nwithout having to compute the sparsity pattern for the entire function.\n\nSee Also\n********\n:ref:`sparse_sub_hes.cpp-name` , :ref:`sparsity_sub.cpp-name` ,\n\nFunction\n********\nWe consider the function\n:math:`f : \\B{R}^{nu} \\times \\B{R}^{nv}  \\rightarrow \\B{R}` defined by\n\n.. math::\n\n    f (u, v) =\n    \\left( \\sum_{j=0}^{nu-1} u_j^3 \\right)\n    \\left( \\sum_{j=0}^{nv-1} v_j \\right)\n\nSubset\n******\nSuppose that we are only interested computing the function\n\n.. math::\n\n    H(u, v) = \\partial_u \\partial_u f (u, v)\n\nwhere this Hessian is sparse.\n\nExample\n*******\nThe following code shows one way to compute this subset of the\nHessian of :math:`f`.\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end sub_sparse_hes.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nnamespace {\n    using CppAD::vector;\n    template <class Scalar>\n    Scalar f(const vector<Scalar>& u,const vector<Scalar>& v)\n    {   size_t i;\n        Scalar sum_v = Scalar(0);\n        for(i = 0; i < v.size(); i++)\n            sum_v += v[i];\n        Scalar sum_cube_u = Scalar(0);\n        for(i = 0; i < u.size(); i++)\n            sum_cube_u += u[i] * u[i] * u[i] / 6.0;\n        return sum_v * sum_cube_u;\n    }\n}\n\nbool sub_sparse_hes(void)\n{   bool ok = true;\n    using CppAD::AD;\n    typedef AD<double>   adouble;\n    typedef AD<adouble> a2double;\n    typedef vector< std::set<size_t> > pattern;\n    double eps = 10. * std::numeric_limits<double>::epsilon();\n    size_t i, j;\n\n    // start recording with x = (u , v)\n    size_t nu = 10;\n    size_t nv = 5;\n    size_t n  = nu + nv;\n    vector<adouble> ax(n);\n    for(j = 0; j < n; j++)\n        ax[j] = adouble(j + 2);\n    CppAD::Independent(ax);\n\n    // extract u as independent variables\n    vector<a2double> a2u(nu);\n    for(j = 0; j < nu; j++)\n        a2u[j] = a2double(j + 2);\n    CppAD::Independent(a2u);\n\n    // extract v as parameters\n    vector<a2double> a2v(nv);\n    for(j = 0; j < nv; j++)\n        a2v[j] = ax[nu+j];\n\n    // record g(u)\n    vector<a2double> a2y(1);\n    a2y[0] = f(a2u, a2v);\n    CppAD::ADFun<adouble> g;\n    g.Dependent(a2u, a2y);\n\n    // compue sparsity pattern for Hessian of g(u)\n    pattern r(nu), s(1);\n    for(j = 0; j < nu; j++)\n        r[j].insert(j);\n    g.ForSparseJac(nu, r);\n    s[0].insert(0);\n    pattern p = g.RevSparseHes(nu, s);\n\n    // Row and column indices for non-zeros in lower triangle of Hessian\n    vector<size_t> row, col;\n    for(i = 0; i < nu; i++)\n    {   std::set<size_t>::const_iterator itr;\n        for(itr = p[i].begin(); itr != p[i].end(); itr++)\n        {   j = *itr;\n            if( j <= i )\n            {   row.push_back(i);\n                col.push_back(j);\n            }\n        }\n    }\n    size_t K = row.size();\n    CppAD::sparse_hessian_work work;\n    vector<adouble> au(nu), ahes(K), aw(1);\n    aw[0] = 1.0;\n    for(j = 0; j < nu; j++)\n        au[j] = ax[j];\n    size_t n_sweep = g.SparseHessian(au, aw, p, row, col, ahes, work);\n\n    // The Hessian w.r.t u is diagonal\n    ok &= n_sweep == 1;\n\n    // record H(u, v) = Hessian of f w.r.t u\n    CppAD::ADFun<double> H(ax, ahes);\n\n    // remove unnecessary operations\n    H.optimize();\n\n    // Now evaluate the Hessian at a particular value for u, v\n    vector<double> u(nu), v(nv), x(n);\n    for(j = 0; j < n; j++)\n        x[j] = double(j + 2);\n    vector<double> hes = H.Forward(0, x);\n\n    // Now check the Hessian\n    double sum_v = 0.0;\n    for(j = 0; j < nv; j++)\n        sum_v += x[nu + j];\n    for(size_t k = 0; k < K; k++)\n    {   i     = row[k];\n        j     = col[k];\n        ok   &= i == j;\n        double check = sum_v * x[i];\n        ok &= CppAD::NearEqual(hes[k], check, eps, eps);\n    }\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/sparse/subgraph_hes2jac.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin subgraph_hes2jac.cpp}\n{xrst_spell\n    subgraphs\n}\n\nSparse Hessian Using Subgraphs and Jacobian: Example and Test\n#############################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end subgraph_hes2jac.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\nbool subgraph_hes2jac(void)\n{   bool ok = true;\n    using CppAD::NearEqual;\n    typedef CppAD::AD<double>                      a_double;\n    typedef CPPAD_TESTVECTOR(double)               d_vector;\n    typedef CPPAD_TESTVECTOR(a_double)             a_vector;\n    typedef CPPAD_TESTVECTOR(size_t)               s_vector;\n    typedef CPPAD_TESTVECTOR(bool)                 b_vector;\n    typedef CppAD::sparse_rcv<s_vector, d_vector>  sparse_matrix;\n    //\n    double eps = 10. * CppAD::numeric_limits<double>::epsilon();\n    //\n    // double version of x\n    size_t n = 12;\n    d_vector x(n);\n    for(size_t j = 0; j < n; j++)\n        x[j] = double(j + 2);\n    //\n    // a_double version of x\n    a_vector ax(n);\n    for(size_t j = 0; j < n; j++)\n        ax[j] = x[j];\n    //\n    // declare independent variables and starting recording\n    CppAD::Independent(ax);\n    //\n    // a_double version of y = f(x) = 5 * x0 * x1 + sum_j xj^3\n    size_t m = 1;\n    a_vector ay(m);\n    ay[0] = 5.0 * ax[0] * ax[1];\n    for(size_t j = 0; j < n; j++)\n        ay[0] += ax[j] * ax[j] * ax[j];\n    //\n    // create double version of f: x -> y and stop tape recording\n    // (without executing zero order forward calculation)\n    CppAD::ADFun<double> f;\n    f.Dependent(ax, ay);\n    //\n    // Optimize this function to reduce future computations.\n    // Perhaps only one optimization at the end would be faster.\n    f.optimize();\n    //\n    // create a_double version of f\n    CppAD::ADFun<a_double, double> af = f.base2ad();\n    //\n    // declare independent variables and start recording g(x) = f'(x)\n    Independent(ax);\n    //\n    // Use one reverse mode pass to compute z = f'(x)\n    a_vector aw(m), az(n);\n    aw[0] = 1.0;\n    af.Forward(0, ax);\n    az = af.Reverse(1, aw);\n    //\n    // create double version of g : x -> f'(x)\n    CppAD::ADFun<double> g;\n    g.Dependent(ax, az);\n    ok &= g.size_random() == 0;\n    //\n    // Optimize this function to reduce future computations.\n    // Perhaps no optimization would be faster.\n    g.optimize();\n    //\n    // compute f''(x) = g'(x)\n    b_vector select_domain(n), select_range(n);\n    for(size_t j = 0; j < n; ++j)\n    {   select_domain[j] = true;\n        select_range[j]  = true;\n    }\n    sparse_matrix hessian;\n    g.subgraph_jac_rev(select_domain, select_range, x, hessian);\n    // -------------------------------------------------------------------\n    // check number of non-zeros in the Hessian\n    // (only x0 * x1 generates off diagonal terms)\n    ok &= hessian.nnz() == n + 2;\n    //\n    for(size_t k = 0; k < hessian.nnz(); ++k)\n    {   size_t r = hessian.row()[k];\n        size_t c = hessian.col()[k];\n        double v = hessian.val()[k];\n        //\n        if( r == c )\n        {   // a diagonal element\n            double check = 6.0 * x[r];\n            ok          &= NearEqual(v, check, eps, eps);\n        }\n        else\n        {   // off diagonal element\n            ok   &= (r == 0 && c == 1) || (r == 1 && c == 0);\n            double check = 5.0;\n            ok          &= NearEqual(v, check, eps, eps);\n        }\n    }\n    ok &= g.size_random() > 0;\n    g.clear_subgraph();\n    ok &= g.size_random() == 0;\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/sparse/subgraph_jac_rev.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin subgraph_jac_rev.cpp}\n\nComputing Sparse Jacobian Using Reverse Mode: Example and Test\n##############################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end subgraph_jac_rev.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\nbool subgraph_jac_rev(void)\n{   bool ok = true;\n    //\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    using CppAD::sparse_rc;\n    using CppAD::sparse_rcv;\n    //\n    typedef CPPAD_TESTVECTOR(AD<double>) a_vector;\n    typedef CPPAD_TESTVECTOR(double)     d_vector;\n    typedef CPPAD_TESTVECTOR(size_t)     s_vector;\n    typedef CPPAD_TESTVECTOR(bool)       b_vector;\n    //\n    // domain space vector\n    size_t n = 4;\n    a_vector  a_x(n);\n    for(size_t j = 0; j < n; j++)\n        a_x[j] = AD<double> (0);\n    //\n    // declare independent variables and starting recording\n    CppAD::Independent(a_x);\n    //\n    size_t m = 3;\n    a_vector  a_y(m);\n    a_y[0] = a_x[0] + a_x[1];\n    a_y[1] = a_x[2] + a_x[3];\n    a_y[2] = a_x[0] + a_x[1] + a_x[2] + a_x[3] * a_x[3] / 2.;\n    //\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(a_x, a_y);\n    ok &= f.size_random() == 0;\n    //\n    // new value for the independent variable vector\n    d_vector x(n);\n    for(size_t j = 0; j < n; j++)\n        x[j] = double(j);\n    /*\n              [ 1 1 0 0  ]\n    J(x) = [ 0 0 1 1  ]\n              [ 1 1 1 x_3]\n    */\n    //\n    // row-major order values of J(x)\n    size_t nnz = 8;\n    s_vector check_row(nnz), check_col(nnz);\n    d_vector check_val(nnz);\n    for(size_t k = 0; k < nnz; k++)\n    {   // check_val\n        if( k < 7 )\n            check_val[k] = 1.0;\n        else\n            check_val[k] = x[3];\n        //\n        // check_row and check_col\n        check_col[k] = k;\n        if( k < 2 )\n            check_row[k] = 0;\n        else if( k < 4 )\n            check_row[k] = 1;\n        else\n        {   check_row[k] = 2;\n            check_col[k] = k - 4;\n        }\n    }\n    //\n    // select all range components of domain and range\n    b_vector select_domain(n), select_range(m);\n    for(size_t j = 0; j < n; ++j)\n        select_domain[j] = true;\n    for(size_t i = 0; i < m; ++i)\n        select_range[i] = true;\n    // -----------------------------------------------------------------------\n    // Compute Jacobian using f.subgraph_jac_rev(x, subset)\n    // -----------------------------------------------------------------------\n    //\n    // get sparsity pattern\n    bool transpose     = false;\n    sparse_rc<s_vector> pattern_jac;\n    f.subgraph_sparsity(\n        select_domain, select_range, transpose, pattern_jac\n    );\n    // f.subgraph_jac_rev(x, subset)\n    sparse_rcv<s_vector, d_vector> subset( pattern_jac );\n    f.subgraph_jac_rev(x, subset);\n    //\n    // check result\n    ok  &= subset.nnz() == nnz;\n    s_vector row_major = subset.row_major();\n    for(size_t k = 0; k < nnz; k++)\n    {   ok &= subset.row()[ row_major[k] ] == check_row[k];\n        ok &= subset.col()[ row_major[k] ] == check_col[k];\n        ok &= subset.val()[ row_major[k] ] == check_val[k];\n    }\n    // -----------------------------------------------------------------------\n    // f.subgraph_jac_rev(select_domain, select_range, x, matrix_out)\n    // -----------------------------------------------------------------------\n    sparse_rcv<s_vector, d_vector>  matrix_out;\n    f.subgraph_jac_rev(select_domain, select_range, x, matrix_out);\n    //\n    // check result\n    ok  &= matrix_out.nnz() == nnz;\n    row_major = matrix_out.row_major();\n    for(size_t k = 0; k < nnz; k++)\n    {   ok &= matrix_out.row()[ row_major[k] ] == check_row[k];\n        ok &= matrix_out.col()[ row_major[k] ] == check_col[k];\n        ok &= matrix_out.val()[ row_major[k] ] == check_val[k];\n    }\n    //\n    ok &= f.size_random() > 0;\n    f.clear_subgraph();\n    ok &= f.size_random() == 0;\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/sparse/subgraph_reverse.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin subgraph_reverse.cpp}\n{xrst_spell\n    subgraphs\n}\n\nComputing Reverse Mode on Subgraphs: Example and Test\n#####################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end subgraph_reverse.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\nbool subgraph_reverse(void)\n{   bool ok = true;\n    //\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    using CppAD::sparse_rc;\n    using CppAD::sparse_rcv;\n    //\n    typedef CPPAD_TESTVECTOR(AD<double>) a_vector;\n    typedef CPPAD_TESTVECTOR(double)     d_vector;\n    typedef CPPAD_TESTVECTOR(bool)       b_vector;\n    typedef CPPAD_TESTVECTOR(size_t)     s_vector;\n    //\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    //\n    // domain space vector\n    size_t n = 4;\n    a_vector  a_x(n);\n    for(size_t j = 0; j < n; j++)\n        a_x[j] = AD<double> (0);\n    //\n    // declare independent variables and starting recording\n    CppAD::Independent(a_x);\n    //\n    size_t m = 3;\n    a_vector  a_y(m);\n    a_y[0] = a_x[0] + a_x[1];\n    a_y[1] = a_x[2] + a_x[3];\n    a_y[2] = a_x[0] + a_x[1] + a_x[2] + a_x[3] * a_x[3] / 2.;\n    //\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(a_x, a_y);\n    ok &= f.size_random() == 0;\n    //\n    // new value for the independent variable vector\n    d_vector x(n);\n    for(size_t j = 0; j < n; j++)\n        x[j] = double(j);\n    f.Forward(0, x);\n    /*\n              [ 1 1 0 0  ]\n    J(x) = [ 0 0 1 1  ]\n              [ 1 1 1 x_3]\n    */\n    double J[] = {\n        1.0, 1.0, 0.0, 0.0,\n        0.0, 0.0, 1.0, 1.0,\n        1.0, 1.0, 1.0, 0.0\n    };\n    J[11] = x[3];\n    //\n    // exclude x[0] from the calculations\n    b_vector select_domain(n);\n    select_domain[0] = false;\n    for(size_t j = 1; j < n; j++)\n        select_domain[j] = true;\n    //\n    // initialize for reverse mode derivatives computation on subgraphs\n    f.subgraph_reverse(select_domain);\n    //\n    // compute the derivative for each range component\n    for(size_t i = 0; i < m; i++)\n    {   d_vector dw;\n        s_vector col;\n        size_t   q = 1; // derivative of one Taylor coefficient (zero order)\n        f.subgraph_reverse(q, i, col, dw);\n        //\n        // check order in col\n        for(size_t c = 1; c < size_t( col.size() ); c++)\n            ok &= col[c] > col[c-1];\n        //\n        // check that x[0] has been excluded by select_domain\n        if( size_t( col.size() ) > 0 )\n            ok &= col[0] != 0;\n        //\n        // check derivatives for i-th row of J(x)\n        // note that dw is only specified for j in col\n        size_t c = 0;\n        for(size_t j = 1; j < n; j++)\n        {   while( c < size_t( col.size() ) && col[c] < j )\n                ++c;\n            if( c < size_t( col.size() ) && col[c] == j )\n                ok &= NearEqual(dw[j], J[i * n + j], eps99, eps99);\n            else\n                ok &= NearEqual(0.0, J[i * n + j], eps99, eps99);\n        }\n    }\n    ok &= f.size_random() > 0;\n    f.clear_subgraph();\n    ok &= f.size_random() == 0;\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/sparse/subgraph_sparsity.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin subgraph_sparsity.cpp}\n\nSubgraph Dependency Sparsity Patterns: Example and Test\n#######################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end subgraph_sparsity.cpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nbool subgraph_sparsity(void)\n{   bool ok = true;\n    using CppAD::AD;\n    typedef CPPAD_TESTVECTOR(size_t)     SizeVector;\n    typedef CppAD::sparse_rc<SizeVector> sparsity;\n    //\n    // domain space vector\n    size_t n = 2;\n    CPPAD_TESTVECTOR(AD<double>) ax(n);\n    ax[0] = 0.;\n    ax[1] = 1.;\n\n    // declare independent variables and start recording\n    CppAD::Independent(ax);\n\n    // range space vector\n    size_t m = 3;\n    CPPAD_TESTVECTOR(AD<double>) ay(m);\n    ay[0] = ax[0];\n    ay[1] = ax[0] * ax[1];\n    ay[2] = ax[1];\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(ax, ay);\n    ok &= f.size_random() == 0;\n\n    // compute sparsite pattern for F'(x)\n    CPPAD_TESTVECTOR(bool) select_domain(n), select_range(m);\n    for(size_t j = 0; j < n; j++)\n        select_domain[j] = true;\n    for(size_t i = 0; i < m; i++)\n        select_range[i] = true;\n    bool transpose       = false;\n    sparsity pattern_out;\n    f.subgraph_sparsity(select_domain, select_range, transpose, pattern_out);\n\n    // check sparsity pattern\n    size_t nnz = pattern_out.nnz();\n    ok        &= nnz == 4;\n    ok        &= pattern_out.nr() == m;\n    ok        &= pattern_out.nc() == n;\n    {   // check results\n        const SizeVector& row( pattern_out.row() );\n        const SizeVector& col( pattern_out.col() );\n        SizeVector col_major = pattern_out.col_major();\n        //\n        ok &= row[ col_major[0] ] ==  0  && col[ col_major[0] ] ==  0;\n        ok &= row[ col_major[1] ] ==  1  && col[ col_major[1] ] ==  0;\n        ok &= row[ col_major[2] ] ==  1  && col[ col_major[2] ] ==  1;\n        ok &= row[ col_major[3] ] ==  2  && col[ col_major[3] ] ==  1;\n    }\n    // note that the transpose of the identity is the identity\n    transpose     = true;\n    f.subgraph_sparsity(select_domain, select_range, transpose, pattern_out);\n    //\n    nnz  = pattern_out.nnz();\n    ok  &= nnz == 4;\n    ok  &= pattern_out.nr() == n;\n    ok  &= pattern_out.nc() == m;\n    {   // check results\n        const SizeVector& row( pattern_out.row() );\n        const SizeVector& col( pattern_out.col() );\n        SizeVector row_major = pattern_out.row_major();\n        //\n        ok &= col[ row_major[0] ] ==  0  && row[ row_major[0] ] ==  0;\n        ok &= col[ row_major[1] ] ==  1  && row[ row_major[1] ] ==  0;\n        ok &= col[ row_major[2] ] ==  1  && row[ row_major[2] ] ==  1;\n        ok &= col[ row_major[3] ] ==  2  && row[ row_major[3] ] ==  1;\n    }\n    ok &= f.size_random() > 0;\n    f.clear_subgraph();\n    ok &= f.size_random() == 0;\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/utility/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n#\nIF( use_cplusplus_2017_ok )\n    SET(dll_lib \"dll_lib.cpp\")\nELSE( use_cplusplus_2017_ok )\n    SET(dll_lib \"\")\nENDIF( use_cplusplus_2017_ok )\n#\n# BEGIN_SORT_THIS_LINE_PLUS_3\nSET(source_list\n    ${dll_lib}\n    check_numeric_type.cpp\n    check_simple_vector.cpp\n    cppad_vector.cpp\n    error_handler.cpp\n    index_sort.cpp\n    lu_factor.cpp\n    lu_invert.cpp\n    lu_solve.cpp\n    nan.cpp\n    near_equal.cpp\n    ode_err_control.cpp\n    ode_err_maxabs.cpp\n    ode_gear.cpp\n    ode_gear_control.cpp\n    poly.cpp\n    pow_int.cpp\n    romberg_mul.cpp\n    romberg_one.cpp\n    rosen_34.cpp\n    runge45_1.cpp\n    runge_45.cpp\n    set_union.cpp\n    simple_vector.cpp\n    sparse_rc.cpp\n    sparse_rcv.cpp\n    thread_alloc.cpp\n    to_string.cpp\n    utility.cpp\n    vector_bool.cpp\n)\n# END_SORT_THIS_LINE_MINUS_2\n\nset_compile_flags( example_utility \"${cppad_debug_which}\" \"${source_list}\" )\n#\nADD_EXECUTABLE(example_utility EXCLUDE_FROM_ALL ${source_list})\n#\n# List of libraries to be linked into the specified target\nTARGET_LINK_LIBRARIES(example_utility\n    ${cppad_lib}\n    ${colpack_libs}\n)\n#\n# check_example_utility\nadd_check_executable(check_example utility)\n"
  },
  {
    "path": "example/utility/check_numeric_type.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin check_numeric_type.cpp}\n\nThe CheckNumericType Function: Example and Test\n###############################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end check_numeric_type.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/utility/check_numeric_type.hpp>\n# include <cppad/utility/near_equal.hpp>\n\n\n// Choosing a value between 1 and 10 selects a numeric class property to be\n// omitted and result in an error message being generated\n# define CppADMyTypeOmit 0\n\nnamespace { // Empty namespace\n\n    // -------------------------------------------------------------------\n    class MyType {\n    private:\n        double d;\n    public:\n        // constructor from void\n        MyType(void) : d(0.)\n        { }\n        // constructor from an int\n        MyType(int d_) : d(d_)\n        { }\n        // copy constructor\n        MyType(const MyType &x)\n        {   d = x.d; }\n        // assignment operator\n        void operator = (const MyType &x)\n        {   d = x.d; }\n        // member function that converts to double\n        double Double(void) const\n        {   return d; }\n# if CppADMyTypeOmit != 1\n        // unary plus\n        MyType operator + (void) const\n        {   MyType x;\n            x.d =  d;\n            return x;\n        }\n# endif\n# if CppADMyTypeOmit != 2\n        // unary plus\n        MyType operator - (void) const\n        {   MyType x;\n            x.d = - d;\n            return x;\n        }\n# endif\n# if CppADMyTypeOmit != 3\n        // binary addition\n        MyType operator + (const MyType &x) const\n        {   MyType y;\n            y.d = d + x.d ;\n            return y;\n        }\n# endif\n# if CppADMyTypeOmit != 4\n        // binary subtraction\n        MyType operator - (const MyType &x) const\n        {   MyType y;\n            y.d = d - x.d ;\n            return y;\n        }\n# endif\n# if CppADMyTypeOmit != 5\n        // binary multiplication\n        MyType operator * (const MyType &x) const\n        {   MyType y;\n            y.d = d * x.d ;\n            return y;\n        }\n# endif\n# if CppADMyTypeOmit != 6\n        // binary division\n        MyType operator / (const MyType &x) const\n        {   MyType y;\n            y.d = d / x.d ;\n            return y;\n        }\n# endif\n# if CppADMyTypeOmit != 7\n        // compound assignment addition\n        void operator += (const MyType &x)\n        {   d += x.d; }\n# endif\n# if CppADMyTypeOmit != 8\n        // compound assignment subtraction\n        void operator -= (const MyType &x)\n        {   d -= x.d; }\n# endif\n# if CppADMyTypeOmit != 9\n        // compound assignment multiplication\n        void operator *= (const MyType &x)\n        {   d *= x.d; }\n# endif\n# if CppADMyTypeOmit != 10\n        // compound assignment division\n        void operator /= (const MyType &x)\n        {   d /= x.d; }\n# endif\n    };\n    // -------------------------------------------------------------------\n    /*\n    Solve: A[0] * x[0] + A[1] * x[1] = b[0]\n              A[2] * x[0] + A[3] * x[1] = b[1]\n    */\n    template <class NumericType>\n    void Solve(NumericType *A, NumericType *x, NumericType *b)\n    {\n        // make sure NumericType satisfies its conditions\n        CppAD::CheckNumericType<NumericType>();\n\n        // copy b to x\n        x[0] = b[0];\n        x[1] = b[1];\n\n        // copy A to work space\n        NumericType W[4];\n        W[0] = A[0];\n        W[1] = A[1];\n        W[2] = A[2];\n        W[3] = A[3];\n\n        // divide first row by W(1,1)\n        W[1] /= W[0];\n        x[0] /= W[0];\n        W[0] = NumericType(1);\n\n        // subtract W(2,1) times first row from second row\n        W[3] -= W[2] * W[1];\n        x[1] -= W[2] * x[0];\n        W[2] = NumericType(0);\n\n        // divide second row by W(2, 2)\n        x[1] /= W[3];\n        W[3]  = NumericType(1);\n\n        // use first row to solve for x[0]\n        x[0] -= W[1] * x[1];\n    }\n} // End Empty namespace\n\nbool CheckNumericType(void)\n{   bool ok  = true;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    MyType A[4];\n    A[0] = MyType(1); A[1] = MyType(2);\n    A[2] = MyType(3); A[3] = MyType(4);\n\n    MyType b[2];\n    b[0] = MyType(1);\n    b[1] = MyType(2);\n\n    MyType x[2];\n    Solve(A, x, b);\n\n    MyType sum;\n    sum = A[0] * x[0] + A[1] * x[1];\n    ok &= NearEqual(sum.Double(), b[0].Double(), eps99, eps99);\n\n    sum = A[2] * x[0] + A[3] * x[1];\n    ok &= NearEqual(sum.Double(), b[1].Double(), eps99, eps99);\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/utility/check_simple_vector.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin check_simple_vector.cpp}\n\nThe CheckSimpleVector Function: Example and Test\n################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end check_simple_vector.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/utility/vector.hpp>\n# include <cppad/utility/check_simple_vector.hpp>\n# include <iostream>\n\n\n// Choosing a value between 1 and 9 selects a simple vector property to be\n// omitted and result in an error message being generated\n# define CppADMyVectorOmit 0\n\n// -------------------------------------------------------------------------\n\n// example class used for non-constant elements (different from Scalar)\ntemplate <class Scalar>\nclass MyElement {\nprivate:\n    Scalar *element;\npublic:\n    // element constructor\n    MyElement(Scalar *e)\n    {   element = e; }\n    // an example element assignment that returns void\n    void operator = (const Scalar &s)\n    {   *element = s; }\n    // conversion to Scalar\n    operator Scalar() const\n    {   return *element; }\n};\n\n\n// example simple vector class\ntemplate <class Scalar>\nclass MyVector {\nprivate:\n    size_t length;\n    Scalar * data;\npublic:\n\n# if CppADMyVectorOmit != 1\n    // type of the elements in the vector\n    typedef Scalar value_type;\n# endif\n# if CppADMyVectorOmit != 2\n    // default constructor\n    MyVector(void) : length(0) , data(0)\n    { }\n# endif\n# if CppADMyVectorOmit != 3\n    // constructor with a specified size\n    MyVector(size_t n) : length(n)\n    {   if( length == 0 )\n            data = 0;\n        else\n            data = new Scalar[length];\n    }\n# endif\n# if CppADMyVectorOmit != 4\n    // copy constructor\n    MyVector(const MyVector &x) : length(x.length)\n    {   size_t i;\n        if( length == 0 )\n            data = 0;\n        else\n            data = new Scalar[length];\n\n        for(i = 0; i < length; i++)\n            data[i] = x.data[i];\n    }\n# endif\n# if CppADMyVectorOmit != 4\n# if CppADMyVectorOmit != 7\n    // destructor (it is not safe to delete the pointer in cases 4 and 7)\n    ~MyVector(void)\n    {   delete [] data; }\n# endif\n# endif\n# if CppADMyVectorOmit != 5\n    // size function\n    size_t size(void) const\n    {   return length; }\n# endif\n# if CppADMyVectorOmit != 6\n    // resize function\n    void resize(size_t n)\n    {   if( length > 0 )\n            delete [] data;\n        length = n;\n        if( length > 0 )\n            data = new Scalar[length];\n        else\n            data = 0;\n    }\n# endif\n# if CppADMyVectorOmit != 7\n    // assignment operator\n    MyVector & operator=(const MyVector &x)\n    {   size_t i;\n        for(i = 0; i < length; i++)\n            data[i] = x.data[i];\n        return *this;\n    }\n# endif\n# if CppADMyVectorOmit != 8\n    // non-constant element access\n    MyElement<Scalar> operator[](size_t i)\n    {   return data + i; }\n# endif\n# if CppADMyVectorOmit != 9\n    // constant element access\n    const Scalar & operator[](size_t i) const\n    {   return data[i]; }\n# endif\n};\n// -------------------------------------------------------------------------\n\n/*\nCompute r = a * v, where a is a scalar with same type as the elements of\nthe Simple Vector v. This routine uses the CheckSimpleVector function to ensure that\nthe types agree.\n*/\nnamespace { // Empty namespace\n    template <class Scalar, class Vector>\n    Vector Sscal(const Scalar &a, const Vector &v)\n    {\n        // invoke CheckSimpleVector function\n        CppAD::CheckSimpleVector<Scalar, Vector>();\n\n        size_t n = v.size();\n        Vector r(n);\n\n        size_t i;\n        for(i = 0; i < n; i++)\n            r[i] = a * v[i];\n\n        return r;\n    }\n}\n\nbool CheckSimpleVector(void)\n{   bool ok  = true;\n    using CppAD::vector;\n\n    // --------------------------------------------------------\n    // If you change double to float in the next statement,\n    // CheckSimpleVector will generate an error message at compile time.\n    double a = 3.;\n    // --------------------------------------------------------\n\n    size_t n = 2;\n    MyVector<double> v(n);\n    v[0]     = 1.;\n    v[1]     = 2.;\n    MyVector<double> r = Sscal(a, v);\n    ok      &= (r[0] == 3.);\n    ok      &= (r[1] == 6.);\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/utility/cppad_vector.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin cppad_vector.cpp}\n\nCppAD::vector Template Class: Example and Test\n##############################################\n\nPurpose\n*******\nThis is an example and test of the features of the\n:ref:`CppAD_vector-name` class that are not included in the\n:ref:`SimpleVector-name` concept.\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end cppad_vector.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/utility/vector.hpp>\n# include <cppad/utility/error_handler.hpp>\n# include <cppad/utility/check_simple_vector.hpp>\n# include <sstream> // sstream and string are used to test output operation\n# include <string>\n# include <algorithm>\n\nnamespace {\n    void myhandler(\n        bool known       ,\n        int  line        ,\n        const char *file ,\n        const char *exp  ,\n        const char *msg  )\n    {   // error handler must not return, so throw an exception\n        throw std::string( file );\n    }\n}\n\nbool CppAD_vector(void)\n{   bool ok = true;\n    using CppAD::vector;     // so can use vector instead of CppAD::vector\n    typedef double Scalar;   // change double to test other types\n\n    // check Simple Vector specifications\n    CppAD::CheckSimpleVector< Scalar, vector<Scalar> >();\n\n    // check constructor with size_t, with int, and with value\n    size_t two_s = 2;\n    int    two_i = 2;\n    Scalar value = 5.0;\n    vector<Scalar> vec(2), other(two_s), another(two_i, value);\n    ok &= another[0] == 5.0;\n    ok &= another[1] == 5.0;\n\n    // check resize with size_t and with int\n    vec.resize(2);\n    other.resize(two_s);\n    another.resize(two_i);\n\n    // assignment returns reference for use in other assignments\n    another[0] = Scalar(1);\n    another[1] = Scalar(2);\n    vec = other = another;\n    for(size_t i = 0; i < 2; ++i)\n    {   ok &= vec[i] == other[i];\n        ok &= vec[i] == another[i];\n    }\n\n    // operator ==\n    ok &= vec == other;\n    ok &= other == another;\n\n    // initializer constructor\n    vector<Scalar> yet_another = { 1.0, 3.0};\n    ok &= yet_another.size() == 2;\n    ok &= yet_another[0] == 1.0;\n    ok &= yet_another[1] == 3.0;\n\n    // operator <=, >=\n    ok &= vec <= yet_another;\n    ok &= yet_another >= vec;\n\n    // test of output\n    std::string        correct= \"{ 1, 2 }\";\n    std::string        str;\n    std::ostringstream buf;\n    buf << vec;\n    str = buf.str();\n    ok &= (str == correct);\n\n    // swap\n    other[0] = vec[0] + 1;\n    vec.swap(other);\n    ok  &= vec[0] == other[0] + 1;\n\n    // clear\n    vec.clear();\n    ok &= vec.size() == 0;\n    ok &= vec.capacity() == 0;\n\n    // push_back scalar and changes in capacity\n    size_t n = 100;\n    size_t old_capacity = vec.capacity();\n    for(size_t i = 0; i < n; i++)\n    {   vec.push_back( Scalar(n - i) );\n        ok &= (i+1) == vec.size();\n        ok &= i < vec.capacity();\n        ok &= old_capacity == vec.capacity() || i == old_capacity;\n        old_capacity = vec.capacity();\n    }\n    for(size_t i = 0; i < n; i++)\n        ok &= ( vec[i] == Scalar(n - i) );\n\n    // test of push_vector\n    vec.push_vector(vec);\n    ok &= (vec.size() == 2 * n);\n    for(size_t i = 0; i < n; i++)\n    {   ok &= vec[i]      == Scalar(n - i);\n        ok &= vec[i + n]  == Scalar(n - i);\n    }\n\n    // resize preserves elements when new size less than capacity\n    ok &= n < vec.capacity();\n    vec.resize(n);\n    for(size_t i = 0; i < n; i++)\n        ok &= vec[i] == Scalar(n - i);\n\n    // vector assignment OK no matter what target size was before assignment\n    other[0] = vec[0] + 1;\n    ok &= other.size() < vec.size();\n    other    = vec;\n    ok &= other.size() == vec.size();\n    for(size_t i = 0; i < vec.size(); i++)\n        ok &= other[i] == vec[i];\n\n    // create a const vector equal to vec\n    const vector<Scalar> cvec = vec;\n\n    // sort of vec (will reverse order of elements for this case)\n    std::sort(vec.begin(), vec.end());\n    for(size_t i = 0; i < n ; ++i)\n        ok &= vec[i] == Scalar(i + 1);\n\n    // use data pointer to sort using pointers instead of iterators\n    std::sort(other.data(), other.data() + other.size());\n    for(size_t i = 0; i < n ; ++i)\n        ok &= other[i] == Scalar(i + 1);\n    //\n    // test direct use of iterator and const_iterator\n    typedef vector<Scalar>::iterator       iterator;\n    typedef vector<Scalar>::const_iterator const_iterator;\n    iterator        itr = vec.begin(); // increasing order\n    const_iterator citr = cvec.end();  // decreasing order\n    while( itr != vec.end() )\n    {   --citr;\n        ok &= *itr == *citr;\n        ++itr;\n    }\n    // conversion from iterator to const_iterator\n    citr = vec.begin();\n    ok  &= *citr == vec[0];\n\n    // test use of [] operator with const_itr\n    for(size_t i = 0; i < n; ++i)\n        ok &= citr[i] == vec[i];\n\n    // test use of [] operator with iterator\n    itr = vec.begin();\n    for(size_t i = 0; i < n; ++i)\n        itr[i] = Scalar(i + 1);\n\n    // Replace the default CppAD error handler with myhandler (defined above).\n    // This replacement is in effect until info drops out of scope.\n    CppAD::ErrorHandler info(myhandler);\n\n# ifndef NDEBUG\n    // -----------------------------------------------------------------------\n    // check that iterator access out of range generates an error\n    ok  &= *itr == Scalar(1);  // this access OK\n    bool detected_error = false;\n    try\n    {   vec.clear();\n        // The iterator knows that the vector has changed and that\n        // this access is no longer valid\n        *itr;\n    }\n    catch(const std::string& file)\n    {   // This location for the error is not part of user API and may change\n        size_t pos     = file.find(\"/cppad_vector_itr.hpp\");\n        ok            &=  pos != std::string::npos;\n        detected_error = true;\n    }\n    ok &= detected_error;\n    // -----------------------------------------------------------------------\n# endif\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/utility/dll_lib.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin dll_lib.cpp}\n{xrst_spell\n    msvc\n}\n\ndll_lib: Example and Test\n#########################\n\noptions\n*******\nThe following subsection of this example sets\n:ref:`create_dll_lib@options` that are different\nfrom the default options:\n{xrst_literal\n    // BEGIN_OPTIONS\n    // END_OPTIONS\n}\n\nRestrictions\n************\nThis example is only built and run under the following conditions:\n\n#. The :ref:`cmake-name` command determines that the C compiler is\n   gcc, clang, or msvc.\n\n#. The :ref:`cmake-name` command determines it is OK to use\n   C++17 features.\n\n#. The :ref:`cmake@cppad_link_flags` do not contain ``-m32`` .\n\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end dll_lib.cpp}\n*/\n// BEGIN C++\n# include <filesystem>\n# include <fstream>\n# include <vector>\n# include <map>\n# include <cppad/utility/create_dll_lib.hpp>\n# include <cppad/utility/link_dll_lib.hpp>\n\n# if _WIN32\n# define DIR_SEP '\\\\'\n# define DLL_EXT \".dll\"\n# else\n# define DIR_SEP '/'\n# define DLL_EXT \".so\"\n# endif\n\n// CALL_CONVENTION, CALL_IMPORT\n# ifdef _MSC_VER\n# define CALL_CONVENTION __cdecl\n# define CALL_IMPORT     __declspec(dllimport)\n# else\n# define CALL_CONVENTION\n# define CALL_IMPORT\n# endif\n\nnamespace {\n    extern \"C\"\n        typedef CALL_IMPORT int (CALL_CONVENTION *function_ptr)(int x, int y);\n}\n\n\n\nbool dll_lib(void)\n{   bool ok = true;\n    //\n    // add_source\n    std::string add_source =\n        \"int add(int x, int y)\\n\"\n        \"{   return x + y; }\\n\"\n    ;\n    //\n    // dll_entry_source\n    std::string dll_entry_source =\n        \"extern int add(int x, int y);\"\n# ifdef _MSC_VER\n        \"__declspec(dllexport) int _cdecl dll_entry(int x, int y)\\n\"\n# else\n        \"int dll_entry(int x, int y)\\n\"\n# endif\n        \"{   return add(x, y);}\"\n    ;\n    //\n    // temp_dir\n    std::string temp_dir = std::filesystem::temp_directory_path().string();\n    if( temp_dir.back() != DIR_SEP )\n        temp_dir += DIR_SEP;\n    //\n    // ofs\n    std::ofstream ofs;\n    //\n    // add_file\n    std::string add_file = temp_dir + \"add.c\";\n    ofs.open(add_file.c_str(), std::ofstream::out);\n    ofs << add_source;\n    ofs.close();\n    //\n    // dll_entry_file\n    std::string dll_entry_file = temp_dir + \"dll_entry.c\";\n    ofs.open(dll_entry_file.c_str(), std::ofstream::out);\n    ofs << dll_entry_source;\n    ofs.close();\n    //\n// BEGIN_OPTIONS\n    // Example using options that are different from the default options\n    std::map< std::string, std::string > options;\n# ifdef _MSC_VER\n    options[\"compile\"] = \"cl /EHs /EHc /c /TC /O2\";\n# elif CPPAD_LINK_FLAGS_HAS_M32\n    options[\"compile\"] = \"gcc -c -fPIC -O2 -m32\";\n# else\n    options[\"compile\"] = \"gcc -c -fPIC -O2\";\n# endif\n// END_OPTIONS\n    //\n    // dll_file\n    std::vector< std::string > csrc_files(2);\n    csrc_files[0] = add_file;\n    csrc_files[1] = dll_entry_file;\n    std::string dll_file = temp_dir + \"dll_entry\" + DLL_EXT;\n    CppAD::create_dll_lib(dll_file, csrc_files, options);\n    //\n    // dll_linker\n    std::string err_msg;\n    CppAD::link_dll_lib dll_linker(dll_file, err_msg);\n    if( err_msg != \"\" )\n    {   std::cerr << \"dll_lib error: \" << err_msg << \"\\n\";\n        return false;\n    }\n    //\n    // dll_entry\n    void* vptr = dll_linker(\"dll_entry\", err_msg);\n    if( err_msg != \"\" )\n    {   std::cerr << \"dll_lib error: \" << err_msg << \"\\n\";\n        return false;\n    }\n    function_ptr dll_entry = reinterpret_cast<function_ptr>(vptr);\n    //\n    // z = dll_entry(x, y)\n    int x = 1, y = 2;\n    int z = dll_entry(x, y);\n    //\n    // ok\n    ok &= z == (x + y);\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/utility/error_handler.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin error_handler.cpp}\n\nReplacing The CppAD Error Handler: Example and Test\n###################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end error_handler.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/utility/error_handler.hpp>\n# include <cstring>\n\nnamespace {\n    void myhandler(\n        bool known       ,\n        int  line        ,\n        const char *file ,\n        const char *exp  ,\n        const char *msg  )\n    {   // error handler must not return, so throw an exception\n        throw line;\n    }\n}\n\n\nbool ErrorHandler(void)\n{   using CppAD::ErrorHandler;\n\n    int lineMinusFive = 0;\n\n    // replace the default CppAD error handler\n    ErrorHandler info(myhandler);\n\n    // set ok to false unless catch block is executed\n    bool ok = false;\n\n    // use try / catch because handler throws an exception\n    try {\n        // set the static variable Line to next source code line\n        lineMinusFive = __LINE__;\n\n        // can call myhandler anywhere that ErrorHandler is defined\n        ErrorHandler::Call(\n            true     , // reason for the error is known\n            __LINE__ , // current source code line number\n            __FILE__ , // current source code file name\n            \"1 > 0\"  , // an intentional error condition\n            \"Testing ErrorHandler\"     // reason for error\n        );\n    }\n    catch ( int line )\n    {   // check value of the line number that was passed to handler\n        ok = (line == lineMinusFive + 5);\n    }\n\n    // info drops out of scope and the default CppAD error handler\n    // is restored when this routine returns.\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/utility/index_sort.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin index_sort.cpp}\n\nIndex Sort: Example and Test\n############################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end index_sort.cpp}\n*/\n// BEGIN C++\n# include <cppad/utility/index_sort.hpp>\n# include <cppad/utility/vector.hpp>\n# include <valarray>\n# include <vector>\n\n\nnamespace{\n    // class that uses < to compare a pair of size_t values\n    class Key {\n    public:\n        size_t first_;\n        size_t second_;\n        //\n        Key(void)\n        { }\n        //\n        Key(size_t first, size_t second)\n        : first_(first), second_(second)\n        { }\n        //\n        bool operator<(const Key& other) const\n        {   if( first_ == other.first_ )\n                return second_ < other.second_;\n            return first_ < other.first_;\n        }\n    };\n\n    template <class KeyVector, class SizeVector>\n    bool vector_case(void)\n    {   bool ok = true;\n        size_t i, j;\n        size_t first[]  =  { 4, 4, 3, 3, 2, 2, 1, 1};\n        size_t second[] = { 0, 1, 0, 1, 0, 1, 0, 1};\n        size_t size     = sizeof(first) / sizeof(first[0]);\n\n        KeyVector keys(size);\n        for(i = 0; i < size; i++)\n            keys[i] = Key(first[i], second[i]);\n\n        SizeVector ind(size);\n        CppAD::index_sort(keys, ind);\n\n        // check that all the indices are different\n        for(i = 0; i < size; i++)\n        {   for(j = 0; j < size; j++)\n                ok &= (i == j) || (ind[i] != ind[j]);\n        }\n\n        // check for increasing order\n        for(i = 0; i < size-1; i++)\n        {   if( first[ ind[i] ] == first[ ind[i+1] ] )\n                ok &= second[ ind[i] ] <= second[ ind[i+1] ];\n            else\n                ok &= first[ ind[i] ] < first[ ind[i+1] ];\n        }\n\n        return ok;\n    }\n}\n\nbool index_sort(void)\n{   bool ok = true;\n\n    // some example simple vector template classes\n    ok &= vector_case<  std::vector<Key>,  std::valarray<size_t> >();\n    ok &= vector_case< std::valarray<Key>, CppAD::vector<size_t> >();\n    ok &= vector_case< CppAD::vector<Key>,   std::vector<size_t> >();\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/utility/lu_factor.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin lu_factor.cpp}\n\nLuFactor: Example and Test\n##########################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end lu_factor.cpp}\n*/\n\n// BEGIN C++\n# include <cstdlib>               // for rand function\n# include <cppad/utility/lu_factor.hpp>      // for CppAD::LuFactor\n# include <cppad/utility/near_equal.hpp>     // for CppAD::NearEqual\n# include <cppad/utility/vector.hpp>  // for CppAD::vector\n\nbool LuFactor(void)\n{   bool  ok = true;\n\n# ifndef _MSC_VER\n    using std::rand;\n    using std::srand;\n# endif\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    size_t  n = 5;                        // number rows in A\n    double  rand_max = double(RAND_MAX);  // maximum rand value\n    double  sum;                          // element of L * U\n    double  pij;                          // element of permuted A\n    size_t  i, j, k;                      // temporary indices\n\n    // A is an n by n matrix\n    CppAD::vector<double> A(n*n), LU(n*n), L(n*n), U(n*n);\n\n    // set A equal to an n by n random matrix\n    for(i = 0; i < n; i++)\n        for(j = 0; j < n; j++)\n            A[i * n + j] = rand() / rand_max;\n\n    // pivot vectors\n    CppAD::vector<size_t> ip(n);\n    CppAD::vector<size_t> jp(n);\n\n    // factor the matrix A\n    LU       = A;\n    CppAD::LuFactor(ip, jp, LU);\n\n    // check that ip and jp are permutations of the indices 0, ... , n-1\n    for(i = 0; i < n; i++)\n    {   ok &= (ip[i] < n);\n        ok &= (jp[i] < n);\n        for(j = 0; j < n; j++)\n        {   if( i != j )\n            {   ok &= (ip[i] != ip[j]);\n                ok &= (jp[i] != jp[j]);\n            }\n        }\n    }\n\n    // Extract L from LU\n    for(i = 0; i < n; i++)\n    {   // elements along and below the diagonal\n        for(j = 0; j <= i; j++)\n            L[i * n + j] = LU[ ip[i] * n + jp[j] ];\n        // elements above the diagonal\n        for(j = i+1; j < n; j++)\n            L[i * n + j] = 0.;\n    }\n\n    // Extract U from LU\n    for(i = 0; i < n; i++)\n    {   // elements below the diagonal\n        for(j = 0; j < i; j++)\n            U[i * n + j] = 0.;\n        // elements along the diagonal\n        U[i * n + i] = 1.;\n        // elements above the diagonal\n        for(j = i+1; j < n; j++)\n            U[i * n + j] = LU[ ip[i] * n + jp[j] ];\n    }\n\n    // Compute L * U\n    for(i = 0; i < n; i++)\n    {   for(j = 0; j < n; j++)\n        {   // compute element (i,j) entry in L * U\n            sum = 0.;\n            for(k = 0; k < n; k++)\n                sum += L[i * n + k] * U[k * n + j];\n            // element (i,j) in permuted version of A\n            pij  = A[ ip[i] * n + jp[j] ];\n            // compare\n            ok  &= NearEqual(pij, sum, eps99, eps99);\n        }\n    }\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/utility/lu_invert.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin lu_invert.cpp}\n\nLuInvert: Example and Test\n##########################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end lu_invert.cpp}\n*/\n\n\n// BEGIN C++\n# include <cstdlib>               // for rand function\n# include <cppad/utility/lu_invert.hpp>      // for CppAD::LuInvert\n# include <cppad/utility/near_equal.hpp>     // for CppAD::NearEqual\n# include <cppad/utility/vector.hpp>  // for CppAD::vector\n\nbool LuInvert(void)\n{   bool  ok = true;\n\n# ifndef _MSC_VER\n    using std::rand;\n    using std::srand;\n# endif\n    double eps200 = 200.0 * std::numeric_limits<double>::epsilon();\n\n    size_t  n = 7;                        // number rows in A\n    size_t  m = 3;                        // number columns in B\n    double  rand_max = double(RAND_MAX);  // maximum rand value\n    double  sum;                          // element of L * U\n    size_t  i, j, k;                      // temporary indices\n\n    // dimension matrices\n    CppAD::vector<double>\n        A(n*n), X(n*m), B(n*m), LU(n*n), L(n*n), U(n*n);\n\n    // seed the random number generator\n    srand(123);\n\n    // pivot vectors\n    CppAD::vector<size_t> ip(n);\n    CppAD::vector<size_t> jp(n);\n\n    // set pivot vectors\n    for(i = 0; i < n; i++)\n    {   ip[i] = (i + 2) % n;      // ip = 2 , 3, ... , n-1, 0, 1\n        jp[i] = (n + 2 - i) % n;  // jp = 2 , 1, n-1, n-2, ... , 3\n    }\n\n    // chose L, a random lower triangular matrix\n    for(i = 0; i < n; i++)\n    {   for(j = 0; j <= i; j++)\n            L [i * n + j]  = rand() / rand_max;\n        for(j = i+1; j < n; j++)\n            L [i * n + j]  = 0.;\n    }\n    // chose U, a random upper triangular matrix with ones on diagonal\n    for(i = 0; i < n; i++)\n    {   for(j = 0; j < i; j++)\n            U [i * n + j]  = 0.;\n        U[ i * n + i ] = 1.;\n        for(j = i+1; j < n; j++)\n            U [i * n + j]  = rand() / rand_max;\n    }\n    // chose X, a random matrix\n    for(i = 0; i < n; i++)\n    {   for(k = 0; k < m; k++)\n            X[i * m + k] = rand() / rand_max;\n    }\n    // set LU to a permuted combination of both L and U\n    for(i = 0; i < n; i++)\n    {   for(j = 0; j <= i; j++)\n            LU [ ip[i] * n + jp[j] ]  = L[i * n + j];\n        for(j = i+1; j < n; j++)\n            LU [ ip[i] * n + jp[j] ]  = U[i * n + j];\n    }\n    // set A to a permuted version of L * U\n    for(i = 0; i < n; i++)\n    {   for(j = 0; j < n; j++)\n        {   // compute (i,j) entry in permuted matrix\n            sum = 0.;\n            for(k = 0; k < n; k++)\n                sum += L[i * n + k] * U[k * n + j];\n            A[ ip[i] * n + jp[j] ] = sum;\n        }\n    }\n    // set B to A * X\n    for(i = 0; i < n; i++)\n    {   for(k = 0; k < m; k++)\n        {   // compute (i,k) entry of B\n            sum = 0.;\n            for(j = 0; j < n; j++)\n                sum += A[i * n + j] * X[j * m + k];\n            B[i * m + k] = sum;\n        }\n    }\n    // solve for X\n    CppAD::LuInvert(ip, jp, LU, B);\n\n    // check result\n    for(i = 0; i < n; i++)\n    {   for(k = 0; k < m; k++)\n        {   ok &= CppAD::NearEqual(\n                X[i * m + k], B[i * m + k], eps200, eps200\n            );\n        }\n    }\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/utility/lu_solve.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin lu_solve.cpp}\n\nLuSolve With Complex Arguments: Example and Test\n################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end lu_solve.cpp}\n*/\n\n// BEGIN C++\n\n# include <cppad/utility/lu_solve.hpp>       // for CppAD::LuSolve\n# include <cppad/utility/near_equal.hpp>     // for CppAD::NearEqual\n# include <cppad/utility/vector.hpp>  // for CppAD::vector\n# include <complex>               // for std::complex\n\ntypedef std::complex<double> Complex;    // define the Complex type\nbool LuSolve(void)\n{   bool  ok = true;\n    using namespace CppAD;\n\n    size_t   n = 3;           // number rows in A and B\n    size_t   m = 2;           // number columns in B, X and S\n\n    // A is an n by n matrix, B, X, and S are n by m matrices\n    CppAD::vector<Complex> A(n * n), B(n * m), X(n * m) , S(n * m);\n\n    Complex  logdet;          // log of determinant of A\n    int      signdet;         // zero if A is singular\n    Complex  det;             // determinant of A\n    size_t   i, j, k;         // some temporary indices\n\n    // set A equal to the n by n Hilbert Matrix\n    for(i = 0; i < n; i++)\n        for(j = 0; j < n; j++)\n            A[i * n + j] = 1. / (double) (i + j + 1);\n\n    // set S to the solution of the equation we will solve\n    for(j = 0; j < n; j++)\n        for(k = 0; k < m; k++)\n            S[ j * m + k ] = Complex(double(j), double(j + k));\n\n    // set B = A * S\n    size_t ik;\n    Complex sum;\n    for(k = 0; k < m; k++)\n    {   for(i = 0; i < n; i++)\n        {   sum = 0.;\n            for(j = 0; j < n; j++)\n                sum += A[i * n + j] * S[j * m + k];\n            B[i * m + k] = sum;\n        }\n    }\n\n    // solve the equation A * X = B and compute determinant of A\n    signdet = CppAD::LuSolve(n, m, A, B, X, logdet);\n    det     = Complex( signdet ) * exp( logdet );\n\n    double cond  = 4.62963e-4;       // condition number of A when n = 3\n    double determinant = 1. / 2160.; // determinant of A when n = 3\n    double delta = 1e-14 / cond;     // accuracy expected in X\n\n    // check determinant\n    ok &= CppAD::NearEqual(det, determinant, delta, delta);\n\n    // check solution\n    for(ik = 0; ik < n * m; ik++)\n        ok &= CppAD::NearEqual(X[ik], S[ik], delta, delta);\n\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/utility/nan.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin nan.cpp}\n\nnan: Example and Test\n#####################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end nan.cpp}\n*/\n\n// BEGIN C++\n# include <cppad/utility/nan.hpp>\n# include <vector>\n# include <limits>\n\nbool nan(void)\n{   bool ok = true;\n\n    // get a nan\n    double double_zero = 0.;\n    double double_nan = std::numeric_limits<double>::quiet_NaN();\n\n    // create a simple vector with no nans\n    std::vector<double> v(2);\n    v[0] = double_zero;\n    v[1] = double_zero;\n\n    // check that zero is not nan\n    ok &= ! CppAD::isnan(double_zero);\n    ok &= ! CppAD::hasnan(v);\n\n    // check that nan is a nan\n    v[1] = double_nan;\n    ok &= CppAD::isnan(double_nan);\n    ok &= CppAD::hasnan(v);\n\n    // check that nan is not equal to itself\n    ok &= (double_nan != double_nan);\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/utility/near_equal.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin near_equal.cpp}\n\nNearEqual Function: Example and Test\n####################################\n\nFile Name\n*********\nThis file is called ``near_equal.cpp`` instead of\n``NearEqual.cpp``\nto avoid a name conflict with ``../lib/NearEqual.cpp``\nin the corresponding Microsoft project file.\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end near_equal.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/utility/near_equal.hpp>\n\n# include <complex>\n\nbool Near_Equal(void)\n{   bool ok = true;\n    typedef std::complex<double> Complex;\n    using CppAD::NearEqual;\n\n    // double\n    double x    = 1.00000;\n    double y    = 1.00001;\n    double a    =  .00003;\n    double r    =  .00003;\n    double zero = 0.;\n    double inf  = 1. / zero;\n    double nan  = 0. / zero;\n\n    ok &= NearEqual(x, y, zero, a);\n    ok &= NearEqual(x, y, r, zero);\n    ok &= NearEqual(x, y, r, a);\n\n    ok &= ! NearEqual(x, y, r / 10., a / 10.);\n    ok &= ! NearEqual(inf, inf, r, a);\n    ok &= ! NearEqual(-inf, -inf, r, a);\n    ok &= ! NearEqual(nan, nan, r, a);\n\n    // complex\n    Complex X(x, x / 2.);\n    Complex Y(y, y / 2.);\n    Complex Inf(inf, zero);\n    Complex Nan(zero, nan);\n\n    ok &= NearEqual(X, Y, zero, a);\n    ok &= NearEqual(X, Y, r, zero);\n    ok &= NearEqual(X, Y, r, a);\n\n    ok &= ! NearEqual(X, Y, r / 10., a / 10.);\n    ok &= ! NearEqual(Inf, Inf, r, a);\n    ok &= ! NearEqual(-Inf, -inf, r, a);\n    ok &= ! NearEqual(Nan, Nan, r, a);\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/utility/ode_err_control.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin ode_err_control.cpp}\n\nOdeErrControl: Example and Test\n###############################\n\nDefine\n:math:`X : \\B{R} \\rightarrow \\B{R}^2` by\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        X_0 (0)       & = & 1  \\\\\n        X_1 (0)       & = & 0  \\\\\n        X_0^{(1)} (t) & = & - \\alpha X_0 (t)  \\\\\n        X_1^{(1)} (t) & = &  1 / X_0 (t)\n    \\end{eqnarray}\n\nIt follows that\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    X_0 (t) & = &  \\exp ( - \\alpha t )  \\\\\n    X_1 (t) & = & [ \\exp( \\alpha t ) - 1 ] / \\alpha\n    \\end{eqnarray}\n\nThis example tests OdeErrControl using the relations above.\n\nNan\n***\nNote that :math:`X_0 (t) > 0` for all :math:`t` and that the\nODE goes through a singularity between :math:`X_0 (t) > 0`\nand :math:`X_0 (t) < 0`.\nIf :math:`X_0 (t) < 0`,\nwe return ``nan`` in order to inform\n``OdeErrControl`` that its is taking to large a step.\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end ode_err_control.cpp}\n*/\n// BEGIN C++\n\n# include <limits>                      // for quiet_NaN\n# include <cstddef>                     // for size_t\n# include <cmath>                       // for exp\n# include <cppad/utility/ode_err_control.hpp>   // CppAD::OdeErrControl\n# include <cppad/utility/near_equal.hpp>        // CppAD::NearEqual\n# include <cppad/utility/vector.hpp>            // CppAD::vector\n# include <cppad/utility/runge_45.hpp>          // CppAD::Runge45\n\nnamespace {\n    // --------------------------------------------------------------\n    class Fun {\n    private:\n        const double alpha_;\n    public:\n        // constructor\n        Fun(double alpha) : alpha_(alpha)\n        { }\n\n        // set f = x'(t)\n        void Ode(\n            const double                &t,\n            const CppAD::vector<double> &x,\n            CppAD::vector<double>       &f)\n        {   f[0] = - alpha_ * x[0];\n            f[1] = 1. / x[0];\n            // case where ODE does not make sense\n            if( x[0] < 0. )\n                f[1] = std::numeric_limits<double>::quiet_NaN();\n        }\n\n    };\n\n    // --------------------------------------------------------------\n    class Method {\n    private:\n        Fun F;\n    public:\n        // constructor\n        Method(double alpha) : F(alpha)\n        { }\n        void step(\n            double ta,\n            double tb,\n            CppAD::vector<double> &xa ,\n            CppAD::vector<double> &xb ,\n            CppAD::vector<double> &eb )\n        {   xb = CppAD::Runge45(F, 1, ta, tb, xa, eb);\n        }\n        size_t order(void)\n        {   return 4; }\n    };\n}\n\nbool OdeErrControl(void)\n{   bool ok = true;     // initial return value\n\n    double alpha = 10.;\n    Method method(alpha);\n\n    CppAD::vector<double> xi(2);\n    xi[0] = 1.;\n    xi[1] = 0.;\n\n    CppAD::vector<double> eabs(2);\n    eabs[0] = 1e-4;\n    eabs[1] = 1e-4;\n\n    // inputs\n    double ti   = 0.;\n    double tf   = 1.;\n    double smin = 1e-4;\n    double smax = 1.;\n    double scur = 1.;\n    double erel = 0.;\n\n    // outputs\n    CppAD::vector<double> ef(2);\n    CppAD::vector<double> xf(2);\n    CppAD::vector<double> maxabs(2);\n    size_t nstep;\n\n\n    xf = OdeErrControl(method,\n        ti, tf, xi, smin, smax, scur, eabs, erel, ef, maxabs, nstep);\n\n    double x0 = exp(-alpha*tf);\n    ok &= CppAD::NearEqual(x0, xf[0], 1e-4, 1e-4);\n    ok &= CppAD::NearEqual(0., ef[0], 1e-4, 1e-4);\n\n    double x1 = (exp(alpha*tf) - 1) / alpha;\n    ok &= CppAD::NearEqual(x1, xf[1], 1e-4, 1e-4);\n    ok &= CppAD::NearEqual(0., ef[1], 1e-4, 1e-4);\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/utility/ode_err_maxabs.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin ode_err_maxabs.cpp}\n\nOdeErrControl: Example and Test Using Maxabs Argument\n#####################################################\n\nDefine\n:math:`X : \\B{R} \\rightarrow \\B{R}^2` by\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    X_0 (t) & = &  - \\exp ( - w_0 t )  \\\\\n    X_1 (t) & = & \\frac{w_0}{w_1 - w_0} [ \\exp ( - w_0 t ) - \\exp( - w_1 t )]\n    \\end{eqnarray}\n\nIt follows that :math:`X_0 (0) = 1`, :math:`X_1 (0) = 0` and\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        X_0^{(1)} (t) & = & - w_0 X_0 (t)  \\\\\n        X_1^{(1)} (t) & = & + w_0 X_0 (t) - w_1 X_1 (t)\n    \\end{eqnarray}\n\nNote that :math:`X_1 (0)` is zero an if :math:`w_0 t` is large,\n:math:`X_0 (t)` is near zero.\nThis example tests OdeErrControl using the *maxabs* argument.\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end ode_err_maxabs.cpp}\n*/\n// BEGIN C++\n\n# include <cstddef>              // for size_t\n# include <cmath>                // for exp\n# include <cppad/utility/ode_err_control.hpp>   // CppAD::OdeErrControl\n# include <cppad/utility/near_equal.hpp>    // CppAD::NearEqual\n# include <cppad/utility/vector.hpp> // CppAD::vector\n# include <cppad/utility/runge_45.hpp>      // CppAD::Runge45\n\nnamespace {\n    // --------------------------------------------------------------\n    class Fun {\n    private:\n            CppAD::vector<double> w;\n    public:\n        // constructor\n        Fun(const CppAD::vector<double> &w_) : w(w_)\n        { }\n\n        // set f = x'(t)\n        void Ode(\n            const double                &t,\n            const CppAD::vector<double> &x,\n            CppAD::vector<double>       &f)\n        {   f[0] = - w[0] * x[0];\n            f[1] = + w[0] * x[0] - w[1] * x[1];\n        }\n    };\n\n    // --------------------------------------------------------------\n    class Method {\n    private:\n        Fun F;\n    public:\n        // constructor\n        Method(const CppAD::vector<double> &w_) : F(w_)\n        { }\n        void step(\n            double ta,\n            double tb,\n            CppAD::vector<double> &xa ,\n            CppAD::vector<double> &xb ,\n            CppAD::vector<double> &eb )\n        {   xb = CppAD::Runge45(F, 1, ta, tb, xa, eb);\n        }\n        size_t order(void)\n        {   return 4; }\n    };\n}\n\nbool OdeErrMaxabs(void)\n{   bool ok = true;     // initial return value\n\n    CppAD::vector<double> w(2);\n    w[0] = 10.;\n    w[1] = 1.;\n    Method method(w);\n\n    CppAD::vector<double> xi(2);\n    xi[0] = 1.;\n    xi[1] = 0.;\n\n    CppAD::vector<double> eabs(2);\n    eabs[0] = 0.;\n    eabs[1] = 0.;\n\n    CppAD::vector<double> ef(2);\n    CppAD::vector<double> xf(2);\n    CppAD::vector<double> maxabs(2);\n\n    double ti   = 0.;\n    double tf   = 1.;\n    double smin = .5;\n    double smax = 1.;\n    double scur = .5;\n    double erel = 1e-4;\n\n    bool accurate = false;\n    while( ! accurate )\n    {   xf = OdeErrControl(method,\n            ti, tf, xi, smin, smax, scur, eabs, erel, ef, maxabs);\n        accurate = true;\n        size_t i;\n        for(i = 0; i < 2; i++)\n            accurate &= ef[i] <= erel * maxabs[i];\n        if( ! accurate )\n            smin = smin / 2;\n    }\n\n    double x0 = exp(-w[0]*tf);\n    ok &= CppAD::NearEqual(x0, xf[0], erel, 0.);\n    ok &= CppAD::NearEqual(0., ef[0], erel, erel);\n\n    double x1 = w[0] * (exp(-w[0]*tf) - exp(-w[1]*tf))/(w[1] - w[0]);\n    ok &= CppAD::NearEqual(x1, xf[1], erel, 0.);\n    ok &= CppAD::NearEqual(0., ef[1], erel, erel);\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/utility/ode_gear.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin ode_gear.cpp}\n{xrst_spell\n    rclr\n}\n\nOdeGear: Example and Test\n#########################\n\nDefine\n:math:`x : \\B{R} \\rightarrow \\B{R}^n` by\n\n.. math::\n\n    x_i (t) =  t^{i+1}\n\nfor :math:`i = 1 , \\ldots , n-1`.\nIt follows that\n\n.. math::\n\n    \\begin{array}{rclr}\n    x_i(0)     & = & 0                             & {\\rm for \\; all \\;} i \\\\\n    x_i ' (t)  & = & 1                             & {\\rm if \\;} i = 0      \\\\\n    x_i '(t)   & = & (i+1) t^i = (i+1) x_{i-1} (t) & {\\rm if \\;} i > 0\n    \\end{array}\n\nThe example tests OdeGear using the relations above:\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end ode_gear.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/utility/ode_gear.hpp>\n# include <cppad/cppad.hpp>        // For automatic differentiation\n\nnamespace {\n    class Fun {\n    public:\n        // constructor\n        Fun(bool use_x_) : use_x(use_x_)\n        { }\n\n        // compute f(t, x) both for double and AD<double>\n        template <class Scalar>\n        void Ode(\n            const Scalar                    &t,\n            const CPPAD_TESTVECTOR(Scalar) &x,\n            CPPAD_TESTVECTOR(Scalar)       &f)\n        {   size_t n  = x.size();\n            Scalar ti(1);\n            f[0]   = Scalar(1);\n            size_t i;\n            for(i = 1; i < n; i++)\n            {   ti *= t;\n                // convert int(size_t) to avoid warning\n                // on _MSC_VER systems\n                if( use_x )\n                    f[i] = int(i+1) * x[i-1];\n                else\n                    f[i] = int(i+1) * ti;\n            }\n        }\n\n        void Ode_dep(\n            const double                    &t,\n            const CPPAD_TESTVECTOR(double) &x,\n            CPPAD_TESTVECTOR(double)       &f_x)\n        {   using namespace CppAD;\n\n            size_t n  = x.size();\n            CPPAD_TESTVECTOR(AD<double>) T(1);\n            CPPAD_TESTVECTOR(AD<double>) X(n);\n            CPPAD_TESTVECTOR(AD<double>) F(n);\n\n            // set argument values\n            T[0] = t;\n            size_t i, j;\n            for(i = 0; i < n; i++)\n                X[i] = x[i];\n\n            // declare independent variables\n            Independent(X);\n\n            // compute f(t, x)\n            this->Ode(T[0], X, F);\n\n            // define AD function object\n            ADFun<double> fun(X, F);\n\n            // compute partial of f w.r.t x\n            CPPAD_TESTVECTOR(double) dx(n);\n            CPPAD_TESTVECTOR(double) df(n);\n            for(j = 0; j < n; j++)\n                dx[j] = 0.;\n            for(j = 0; j < n; j++)\n            {   dx[j] = 1.;\n                df = fun.Forward(1, dx);\n                for(i = 0; i < n; i++)\n                    f_x [i * n + j] = df[i];\n                dx[j] = 0.;\n            }\n        }\n\n    private:\n        const bool use_x;\n\n    };\n}\n\nbool OdeGear(void)\n{   bool ok = true; // initial return value\n    size_t i, j;    // temporary indices\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    size_t  m = 4;  // index of next value in X\n    size_t  n = m;  // number of components in x(t)\n\n    // vector of times\n    CPPAD_TESTVECTOR(double) T(m+1);\n    double step = .1;\n    T[0]        = 0.;\n    for(j = 1; j <= m; j++)\n    {   T[j] = T[j-1] + step;\n        step = 2. * step;\n    }\n\n    // initial values for x( T[m-j] )\n    CPPAD_TESTVECTOR(double) X((m+1) * n);\n    for(j = 0; j < m; j++)\n    {   double ti = T[j];\n        for(i = 0; i < n; i++)\n        {   X[ j * n + i ] = ti;\n            ti *= T[j];\n        }\n    }\n\n    // error bound\n    CPPAD_TESTVECTOR(double) e(n);\n\n    size_t use_x;\n    for( use_x = 0; use_x < 2; use_x++)\n    {   // function object depends on value of use_x\n        Fun F(use_x > 0);\n\n        // compute OdeGear approximation for x( T[m] )\n        CppAD::OdeGear(F, m, n, T, X, e);\n\n        double check = T[m];\n        for(i = 0; i < n; i++)\n        {   // method is exact up to order m and x[i] = t^{i+1}\n            if( i + 1 <= m ) ok &= CppAD::NearEqual(\n                X[m * n + i], check, eps99, eps99\n            );\n            // error bound should be zero up to order m-1\n            if( i + 1 < m ) ok &= CppAD::NearEqual(\n                e[i], 0., eps99, eps99\n            );\n            // check value for next i\n            check *= T[m];\n        }\n    }\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/utility/ode_gear_control.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin ode_gear_control.cpp}\n\nOdeGearControl: Example and Test\n################################\n\nDefine\n:math:`X : \\B{R} \\rightarrow \\B{R}^2` by\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    X_0 (t) & = &  - \\exp ( - w_0 t )  \\\\\n    X_1 (t) & = & \\frac{w_0}{w_1 - w_0} [ \\exp ( - w_0 t ) - \\exp( - w_1 t )]\n    \\end{eqnarray}\n\nIt follows that :math:`X_0 (0) = 1`, :math:`X_1 (0) = 0` and\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        X_0^{(1)} (t) & = & - w_0 X_0 (t)  \\\\\n        X_1^{(1)} (t) & = & + w_0 X_0 (t) - w_1 X_1 (t)\n    \\end{eqnarray}\n\nThe example tests OdeGearControl using the relations above:\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end ode_gear_control.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n# include <cppad/utility/ode_gear_control.hpp>   // CppAD::OdeGearControl\n\nnamespace {\n    // --------------------------------------------------------------\n    class Fun {\n    private:\n            CPPAD_TESTVECTOR(double) w;\n    public:\n        // constructor\n        Fun(const CPPAD_TESTVECTOR(double) &w_) : w(w_)\n        { }\n\n        // set f = x'(t)\n        template <class Scalar>\n        void Ode(\n            const Scalar                    &t,\n            const CPPAD_TESTVECTOR(Scalar) &x,\n            CPPAD_TESTVECTOR(Scalar)       &f)\n        {   f[0] = - w[0] * x[0];\n            f[1] = + w[0] * x[0] - w[1] * x[1];\n        }\n\n        void Ode_dep(\n            const double                    &t,\n            const CPPAD_TESTVECTOR(double) &x,\n            CPPAD_TESTVECTOR(double)       &f_x)\n        {   using namespace CppAD;\n\n            size_t n  = x.size();\n            CPPAD_TESTVECTOR(AD<double>) T(1);\n            CPPAD_TESTVECTOR(AD<double>) X(n);\n            CPPAD_TESTVECTOR(AD<double>) F(n);\n\n            // set argument values\n            T[0] = t;\n            size_t i, j;\n            for(i = 0; i < n; i++)\n                X[i] = x[i];\n\n            // declare independent variables\n            Independent(X);\n\n            // compute f(t, x)\n            this->Ode(T[0], X, F);\n\n            // define AD function object\n            ADFun<double> fun(X, F);\n\n            // compute partial of f w.r.t x\n            CPPAD_TESTVECTOR(double) dx(n);\n            CPPAD_TESTVECTOR(double) df(n);\n            for(j = 0; j < n; j++)\n                dx[j] = 0.;\n            for(j = 0; j < n; j++)\n            {   dx[j] = 1.;\n                df = fun.Forward(1, dx);\n                for(i = 0; i < n; i++)\n                    f_x [i * n + j] = df[i];\n                dx[j] = 0.;\n            }\n        }\n    };\n}\n\nbool OdeGearControl(void)\n{   bool ok = true;     // initial return value\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    CPPAD_TESTVECTOR(double) w(2);\n    w[0] = 10.;\n    w[1] = 1.;\n    Fun F(w);\n\n    CPPAD_TESTVECTOR(double) xi(2);\n    xi[0] = 1.;\n    xi[1] = 0.;\n\n    CPPAD_TESTVECTOR(double) eabs(2);\n    eabs[0] = 1e-4;\n    eabs[1] = 1e-4;\n\n    // return values\n    CPPAD_TESTVECTOR(double) ef(2);\n    CPPAD_TESTVECTOR(double) maxabs(2);\n    CPPAD_TESTVECTOR(double) xf(2);\n    size_t                nstep;\n\n    // input values\n    size_t  M   = 5;\n    double ti   = 0.;\n    double tf   = 1.;\n    double smin = 1e-8;\n    double smax = 1.;\n    double sini = eps99;\n    double erel = 0.;\n\n    xf = CppAD::OdeGearControl(F, M,\n        ti, tf, xi, smin, smax, sini, eabs, erel, ef, maxabs, nstep);\n\n    double x0 = exp(-w[0]*tf);\n    ok &= NearEqual(x0, xf[0], 1e-4, 1e-4);\n    ok &= NearEqual(0., ef[0], 1e-4, 1e-4);\n\n    double x1 = w[0] * (exp(-w[0]*tf) - exp(-w[1]*tf))/(w[1] - w[0]);\n    ok &= NearEqual(x1, xf[1], 1e-4, 1e-4);\n    ok &= NearEqual(0., ef[1], 1e-4, 1e-4);\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/utility/poly.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin poly.cpp}\n\nPolynomial Evaluation: Example and Test\n#######################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end poly.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n# include <cmath>\n\nbool poly(void)\n{   bool ok = true;\n\n    // degree of the polynomial\n    size_t deg = 3;\n\n    // set the polynomial coefficients\n    CPPAD_TESTVECTOR(double)   a(deg + 1);\n    size_t i;\n    for(i = 0; i <= deg; i++)\n        a[i] = 1.;\n\n    // evaluate this polynomial\n    size_t k = 0;\n    double z = 2.;\n    double p = CppAD::Poly(k, a, z);\n    ok      &= (p == 1. + z + z*z + z*z*z);\n\n    // evaluate derivative\n    k = 1;\n    p = CppAD::Poly(k, a, z);\n    ok &= (p == 1 + 2.*z + 3.*z*z);\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/utility/pow_int.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin pow_int.cpp}\n\nThe Pow Integer Exponent: Example and Test\n##########################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end pow_int.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n# include <cmath>\n\nbool pow_int(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // declare independent variables and start tape recording\n    size_t n  = 1;\n    double x0 = -0.5;\n    CPPAD_TESTVECTOR(AD<double>) x(n);\n    x[0]      = x0;\n    CppAD::Independent(x);\n\n    // dependent variable vector\n    size_t m = 7;\n    CPPAD_TESTVECTOR(AD<double>) y(m);\n    for(size_t i = 0; i < m; i++)\n        y[i] = CppAD::pow(x[0], int(i) - 3);\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(x, y);\n\n    // check value\n    double check;\n    for(size_t i = 0; i < m; i++)\n    {   check = std::pow(x0, double(i) - 3.0);\n        ok &= NearEqual(y[i] , check,  eps99 , eps99);\n    }\n\n    // forward computation of first partial w.r.t. x[0]\n    CPPAD_TESTVECTOR(double) dx(n);\n    CPPAD_TESTVECTOR(double) dy(m);\n    dx[0] = 1.;\n    dy    = f.Forward(1, dx);\n    for(size_t i = 0; i < m; i++)\n    {   check = (double(i) - 3.0) * std::pow(x0, double(i) - 4.0);\n        ok &= NearEqual(dy[i] , check,  eps99 , eps99);\n    }\n\n    // reverse computation of derivative of y[i]\n    CPPAD_TESTVECTOR(double)  w(m);\n    CPPAD_TESTVECTOR(double) dw(n);\n    for(size_t i = 0; i < m; i++)\n        w[i] = 0.;\n    for(size_t i = 0; i < m; i++)\n    {   w[i] = 1.;\n        dw    = f.Reverse(1, w);\n        check = (double(i) - 3.0) * std::pow(x0, double(i) - 4.0);\n        ok &= NearEqual(dw[0] , check,  eps99 , eps99);\n        w[i] = 0.;\n    }\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/utility/romberg_mul.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin romberg_mul.cpp}\n\nMulti-Dimensional Romberg Integration: Example and Test\n#######################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end romberg_mul.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/utility/romberg_mul.hpp>\n# include <cppad/utility/vector.hpp>\n# include <cppad/utility/near_equal.hpp>\n\n\nnamespace {\n\n    class TestFun {\n    private:\n        const CppAD::vector<size_t> deg;\n    public:\n        // constructor\n        TestFun(const CppAD::vector<size_t> deg_)\n        : deg(deg_)\n        { }\n\n        // function F(x) = x[0]^deg[0] * x[1]^deg[1]\n        double operator () (const CppAD::vector<double> &x)\n        {   size_t i;\n            double   f = 1;\n            for(i = 0; i < deg[0]; i++)\n                f *= x[0];\n            for(i = 0; i < deg[1]; i++)\n                f *= x[1];\n            return f;\n        }\n    };\n\n}\n\nbool RombergMul(void)\n{   bool ok = true;\n    size_t i;\n    size_t k;\n\n    CppAD::vector<size_t> deg(2);\n    deg[0] = 5;\n    deg[1] = 3;\n    TestFun F(deg);\n\n    CppAD::RombergMul<\n        TestFun              ,\n        CppAD::vector<size_t>,\n        CppAD::vector<double>,\n        2                    > RombergMulTest;\n\n    // arguments to RombergMul\n    CppAD::vector<double> a(2);\n    CppAD::vector<double> b(2);\n    CppAD::vector<size_t> n(2);\n    CppAD::vector<size_t> p(2);\n    for(i = 0; i < 2; i++)\n    {   a[i] = 0.;\n        b[i] = 1.;\n    }\n    n[0] = 4;\n    n[1] = 3;\n    double r, e;\n\n    // int_a1^b1 dx1 int_a0^b0 F(x0,x1) dx0\n    //    = [ b0^(deg[0]+1) - a0^(deg[0]+1) ] / (deg[0]+1)\n    //    * [ b1^(deg[1]+1) - a1^(deg[1]+1) ] / (deg[1]+1)\n    double bpow = 1.;\n    double apow = 1.;\n    for(i = 0; i <= deg[0]; i++)\n    {   bpow *= b[0];\n        apow *= a[0];\n    }\n    double check = (bpow - apow) / double(deg[0]+1);\n    bpow = 1.;\n    apow = 1.;\n    for(i = 0; i <= deg[1]; i++)\n    {   bpow *= b[1];\n        apow *= a[1];\n    }\n    check *= (bpow - apow) / double(deg[1]+1);\n\n    double step = (b[1] - a[1]) / exp(log(2.)*double(n[1]-1));\n    double spow = 1;\n    for(k = 0; k <= n[1]; k++)\n    {   spow = spow * step * step;\n        double bnd = 3 * double(deg[1] + 1) * spow;\n\n        for(i = 0; i < 2; i++)\n            p[i] = k;\n        r    = RombergMulTest(F, a, b, n, p, e);\n\n        ok  &= e < bnd;\n        ok  &= CppAD::NearEqual(check, r, 0., e);\n\n    }\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/utility/romberg_one.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin romberg_one.cpp}\n\nOne Dimensional Romberg Integration: Example and Test\n#####################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end romberg_one.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/utility/romberg_one.hpp>\n# include <cppad/utility/vector.hpp>\n# include <cppad/utility/near_equal.hpp>\n\nnamespace {\n    class Fun {\n    private:\n        const size_t degree;\n    public:\n        // constructor\n        Fun(size_t degree_) : degree(degree_)\n        { }\n\n        // function F(x) = x^degree\n        template <class Type>\n        Type operator () (const Type &x)\n        {   size_t i;\n            Type   f = 1;\n            for(i = 0; i < degree; i++)\n                f *= x;\n            return f;\n        }\n    };\n}\n\nbool RombergOne(void)\n{   bool ok = true;\n    size_t i;\n\n    size_t degree = 4;\n    Fun F(degree);\n\n    // arguments to RombergOne\n    double a = 0.;\n    double b = 1.;\n    size_t n = 4;\n    size_t p;\n    double r, e;\n\n    // int_a^b F(x) dx = [ b^(degree+1) - a^(degree+1) ] / (degree+1)\n    double bpow = 1.;\n    double apow = 1.;\n    for(i = 0; i <= degree; i++)\n    {   bpow *= b;\n        apow *= a;\n    }\n    double check = (bpow - apow) / double(degree+1);\n\n    // step size corresponding to r\n    double step = (b - a) / exp(log(2.)*double(n-1));\n    // step size corresponding to error estimate\n    step *= 2.;\n    // step size raised to a power\n    double spow = 1;\n\n    for(p = 0; p < n; p++)\n    {   spow = spow * step * step;\n\n        r = CppAD::RombergOne(F, a, b, n, p, e);\n\n        ok  &= e < double(degree+1) * spow;\n        ok  &= CppAD::NearEqual(check, r, 0., e);\n    }\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/utility/rosen_34.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin rosen_34.cpp}\n{xrst_spell\n    rclr\n}\n\nrosen_34: Example and Test\n##########################\n\nDefine\n:math:`X : \\B{R} \\rightarrow \\B{R}^n` by\n\n.. math::\n\n    X_i (t) =  t^{i+1}\n\nfor :math:`i = 1 , \\ldots , n-1`.\nIt follows that\n\n.. math::\n\n    \\begin{array}{rclr}\n    X_i(0)     & = & 0                             & {\\rm for \\; all \\;} i \\\\\n    X_i ' (t)  & = & 1                             & {\\rm if \\;} i = 0      \\\\\n    X_i '(t)   & = & (i+1) t^i = (i+1) X_{i-1} (t) & {\\rm if \\;} i > 0\n    \\end{array}\n\nThe example tests Rosen34 using the relations above:\n\nOperation Sequence\n******************\nThe :ref:`rosen34-name` method for solving ODE's requires the inversion\nof a system of linear equations.\nThis indices used for pivoting may change with different values\nfor :math:`t` and :math:`x`.\nThis example checks the comparison operators.\nIf some of the comparisons change,\nit makes a new recording of the function with the pivots for the current\n:math:`t` and :math:`x`.\nNote that one could skip this step and always use the same pivot.\nThis would not be as numerically stable,\nbut it would still solve the equations\n(so long as none of the pivot elements are zero).\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end rosen_34.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>        // For automatic differentiation\n\nnamespace {\n    class Fun {\n    private:\n        const bool           use_x_;\n        CppAD::ADFun<double> ode_ind_;\n        CppAD::ADFun<double> ode_dep_;\n    public:\n        // constructor\n        Fun(bool use_x) : use_x_(use_x)\n        { }\n\n        // compute f(t, x) both for double and AD<double>\n        template <class Scalar>\n        void Ode(\n            const Scalar                   &t,\n            const CPPAD_TESTVECTOR(Scalar) &x,\n            CPPAD_TESTVECTOR(Scalar)       &f)\n        {   size_t n  = x.size();\n            Scalar ti(1);\n            f[0]   = Scalar(1);\n            for(size_t i = 1; i < n; i++)\n            {   ti *= t;\n                if( use_x_ )\n                    f[i] = Scalar(i+1) * x[i-1];\n                else\n                    f[i] = Scalar(i+1) * ti;\n            }\n        }\n\n        // compute partial of f(t, x) w.r.t. t using AD\n        void Ode_ind(\n            const double                   &t,\n            const CPPAD_TESTVECTOR(double) &x,\n            CPPAD_TESTVECTOR(double)       &f_t)\n        {   using namespace CppAD;\n\n            size_t n                = x.size();\n            bool   ode_ind_defined  = ode_ind_.size_var() != 0;\n            //\n            CPPAD_TESTVECTOR(double) t_vec(1);\n            t_vec[0] = t;\n            //\n            bool retape = true;\n            if( ode_ind_defined )\n            {   // check if any comparison operators have a different result\n                ode_ind_.new_dynamic(x);\n                ode_ind_.Forward(0, t_vec);\n                retape = ode_ind_.compare_change_number() > 0;\n            }\n            if( retape )\n            {   // record function that evaluates f(t, x)\n                // with t as independent variable and x as dynamcic parameter\n                CPPAD_TESTVECTOR(AD<double>) at(1);\n                CPPAD_TESTVECTOR(AD<double>) ax(n);\n                CPPAD_TESTVECTOR(AD<double>) af(n);\n\n                // set argument values\n                at[0] = t;\n                size_t i;\n                for(i = 0; i < n; i++)\n                    ax[i] = x[i];\n\n                // declare independent variables and dynamic parameters\n                size_t abort_op_index = 0;\n                bool   record_compare = false;\n                Independent(at, abort_op_index, record_compare, ax);\n\n                // compute f(t, x)\n                this->Ode(at[0], ax, af);\n\n                // define AD function object\n                ode_ind_.Dependent(at, af);\n\n                // store result in ode_ind_ so can be re-used\n                assert( ode_ind_.size_var() != 0 );\n            }\n            // special case where new_dynamic not yet set\n            if( ! ode_ind_defined )\n                ode_ind_.new_dynamic(x);\n            // compute partial of f w.r.t t\n            f_t = ode_ind_.Jacobian(t_vec); // partial f(t, x) w.r.t. t\n        }\n\n        // compute partial of f(t, x) w.r.t. x using AD\n        void Ode_dep(\n            const double                   &t,\n            const CPPAD_TESTVECTOR(double) &x,\n            CPPAD_TESTVECTOR(double)       &f_x)\n        {   using namespace CppAD;\n\n            size_t n                = x.size();\n            bool   ode_dep_defined  = ode_dep_.size_var() != 0;\n            //\n            CPPAD_TESTVECTOR(double) t_vec(1), dx(n), df(n);\n            t_vec[0] = t;\n            //\n            bool retape = true;\n            if( ode_dep_defined )\n            {   // check if any comparison operators have a different result\n                ode_dep_.new_dynamic(t_vec);\n                ode_dep_.Forward(0, x);\n                retape = ode_dep_.compare_change_number() > 0;\n            }\n            if( retape )\n            {   // record function that evaluates f(t, x)\n                // with x as independent variable and t as dynamcic parameter\n                CPPAD_TESTVECTOR(AD<double>) at(1);\n                CPPAD_TESTVECTOR(AD<double>) ax(n);\n                CPPAD_TESTVECTOR(AD<double>) af(n);\n\n                // set argument values\n                at[0] = t;\n                for(size_t i = 0; i < n; i++)\n                    ax[i] = x[i];\n\n                // declare independent variables\n                size_t abort_op_index = 0;\n                bool   record_compare = false;\n                Independent(ax, abort_op_index, record_compare, at);\n\n                // compute f(t, x)\n                this->Ode(at[0], ax, af);\n\n                // define AD function object\n                ode_dep_.Dependent(ax, af);\n\n                // store result in ode_dep_ so can be re-used\n                assert( ode_ind_.size_var() != 0 );\n            }\n            // special case where new_dynamic not yet set\n            if( ! ode_dep_defined )\n                ode_dep_.new_dynamic(t_vec);\n            // compute partial of f w.r.t x\n            f_x = ode_dep_.Jacobian(x); // partial f(t, x) w.r.t. x\n        }\n\n\n    };\n}\n\nbool rosen_34(void)\n{   bool ok = true;     // initial return value\n\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    size_t  n = 4;      // number components in X(t) and order of method\n    size_t  M = 2;      // number of Rosen34 steps in [ti, tf]\n    double ti = 0.;     // initial time\n    double tf = 2.;     // final time\n\n    // xi = X(0)\n    CPPAD_TESTVECTOR(double) xi(n);\n    for(size_t i = 0; i <n; i++)\n        xi[i] = 0.;\n\n    for(size_t use_x = 0; use_x < 2; use_x++)\n    {   // function object depends on value of use_x\n        Fun F(use_x > 0);\n\n        // compute Rosen34 approximation for X(tf)\n        CPPAD_TESTVECTOR(double) xf(n), e(n);\n        xf = CppAD::Rosen34(F, M, ti, tf, xi, e);\n\n        double check = tf;\n        for(size_t i = 0; i < n; i++)\n        {   // check that error is always positive\n            ok    &= (e[i] >= 0.);\n            // 4th order method is exact for i < 4\n            if( i < 4 ) ok &=\n                NearEqual(xf[i], check, eps99, eps99);\n            // 3rd order method is exact for i < 3\n            if( i < 3 )\n                ok &= (e[i] <= eps99);\n\n            // check value for next i\n            check *= tf;\n        }\n    }\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/utility/runge45_1.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin runge45_1.cpp}\n{xrst_spell\n    rclr\n}\n\nRunge45: Example and Test\n#########################\n\nDefine\n:math:`X : \\B{R} \\rightarrow \\B{R}^n` by\n\n.. math::\n\n    X_i (t) =  t^{i+1}\n\nfor :math:`i = 1 , \\ldots , n-1`.\nIt follows that\n\n.. math::\n\n    \\begin{array}{rclr}\n    X_i(0)       & = & 0                           & {\\rm for \\; all \\;} i \\\\\n    X_i ' (t)  & = & 1                             & {\\rm if \\;} i = 0      \\\\\n    X_i '(t)   & = & (i+1) t^i = (i+1) X_{i-1} (t) & {\\rm if \\;} i > 0\n    \\end{array}\n\nThe example tests Runge45 using the relations above:\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end runge45_1.cpp}\n*/\n// BEGIN C++\n\n# include <cstddef>                 // for size_t\n# include <cppad/utility/near_equal.hpp>    // for CppAD::NearEqual\n# include <cppad/utility/vector.hpp>        // for CppAD::vector\n# include <cppad/utility/runge_45.hpp>      // for CppAD::Runge45\n\n// Runge45 requires fabs to be defined (not std::fabs)\n// <cppad/cppad.hpp> defines this for doubles, but runge_45.hpp does not.\n# include <math.h>      // for fabs without std in front\n\nnamespace {\n    class Fun {\n    public:\n        // constructor\n        Fun(bool use_x_) : use_x(use_x_)\n        { }\n\n        // set f = x'(t)\n        void Ode(\n            const double                &t,\n            const CppAD::vector<double> &x,\n            CppAD::vector<double>       &f)\n        {   size_t n  = x.size();\n            double ti = 1.;\n            f[0]      = 1.;\n            size_t i;\n            for(i = 1; i < n; i++)\n            {   ti *= t;\n                if( use_x )\n                    f[i] = double(i+1) * x[i-1];\n                else\n                    f[i] = double(i+1) * ti;\n            }\n        }\n    private:\n        const bool use_x;\n\n    };\n}\n\nbool runge_45_1(void)\n{   bool ok = true;     // initial return value\n    size_t i;           // temporary indices\n\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    size_t  n = 5;      // number components in X(t) and order of method\n    size_t  M = 2;      // number of Runge45 steps in [ti, tf]\n    double ti = 0.;     // initial time\n    double tf = 2.;     // final time\n\n    // xi = X(0)\n    CppAD::vector<double> xi(n);\n    for(i = 0; i <n; i++)\n        xi[i] = 0.;\n\n    size_t use_x;\n    for( use_x = 0; use_x < 2; use_x++)\n    {   // function object depends on value of use_x\n        Fun F(use_x > 0);\n\n        // compute Runge45 approximation for X(tf)\n        CppAD::vector<double> xf(n), e(n);\n        xf = CppAD::Runge45(F, M, ti, tf, xi, e);\n\n        double check = tf;\n        for(i = 0; i < n; i++)\n        {   // check that error is always positive\n            ok    &= (e[i] >= 0.);\n            // 5th order method is exact for i < 5\n            if( i < 5 ) ok &=\n                NearEqual(xf[i], check, eps99, eps99);\n            // 4th order method is exact for i < 4\n            if( i < 4 )\n                ok &= (e[i] <= eps99);\n\n            // check value for next i\n            check *= tf;\n        }\n    }\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/utility/runge_45.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin runge_45.cpp}\n\nRunge45: Example and Test\n#########################\n\nDefine\n:math:`X : \\B{R} \\times \\B{R} \\rightarrow \\B{R}^n` by\n\n.. math::\n\n    X_j (b, t) =  b \\left( \\sum_{k=0}^j t^k / k ! \\right)\n\nfor :math:`j = 0 , \\ldots , n-1`.\nIt follows that\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    X_j  (b, 0)   & = & b                                                     \\\\\n    \\partial_t X_j (b, t)   & = & b \\left( \\sum_{k=0}^{j-1} t^k / k ! \\right) \\\\\n    \\partial_t X_j (b, t)   & = & \\left\\{ \\begin{array}{ll}\n        0               & {\\rm if} \\; j = 0  \\\\\n        X_{j-1} (b, t)  & {\\rm otherwise}\n    \\end{array} \\right.\n    \\end{eqnarray}\n\nFor a fixed :math:`t_f`,\nwe can use :ref:`Runge45-name` to define\n:math:`f : \\B{R} \\rightarrow \\B{R}^n` as an approximation for\n:math:`f(b) = X(b, t_f )`.\nWe can then compute :math:`f^{(1)} (b)` which is an approximation for\n\n.. math::\n\n    \\partial_b X(b, t_f ) =  \\sum_{k=0}^j t_f^k / k !\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end runge_45.cpp}\n*/\n// BEGIN C++\n\n# include <cstddef>              // for size_t\n# include <limits>               // for machine epsilon\n# include <cppad/cppad.hpp>      // for all of CppAD\n\nnamespace {\n\n    template <class Scalar>\n    class Fun {\n    public:\n        // constructor\n        Fun(void)\n        { }\n\n        // set return value to X'(t)\n        void Ode(\n            const Scalar                    &t,\n            const CPPAD_TESTVECTOR(Scalar) &x,\n            CPPAD_TESTVECTOR(Scalar)       &f)\n        {   size_t n  = x.size();\n            f[0]      = 0.;\n            for(size_t k = 1; k < n; k++)\n                f[k] = x[k-1];\n        }\n    };\n}\n\nbool runge_45(void)\n{   typedef CppAD::AD<double> Scalar;\n    using CppAD::NearEqual;\n\n    bool ok = true;     // initial return value\n    size_t j;           // temporary indices\n\n    size_t     n = 5;   // number components in X(t) and order of method\n    size_t     M = 2;   // number of Runge45 steps in [ti, tf]\n    Scalar ad_ti = 0.;  // initial time\n    Scalar ad_tf = 2.;  // final time\n\n    // value of independent variable at which to record operations\n    CPPAD_TESTVECTOR(Scalar) ad_b(1);\n    ad_b[0] = 1.;\n\n    // declare b to be the independent variable\n    Independent(ad_b);\n\n    // object to evaluate ODE\n    Fun<Scalar> ad_F;\n\n    // xi = X(0)\n    CPPAD_TESTVECTOR(Scalar) ad_xi(n);\n    for(j = 0; j < n; j++)\n        ad_xi[j] = ad_b[0];\n\n    // compute Runge45 approximation for X(tf)\n    CPPAD_TESTVECTOR(Scalar) ad_xf(n), ad_e(n);\n    ad_xf = CppAD::Runge45(ad_F, M, ad_ti, ad_tf, ad_xi, ad_e);\n\n    // stop recording and use it to create f : b -> xf\n    CppAD::ADFun<double> f(ad_b, ad_xf);\n\n    // evaluate f(b)\n    CPPAD_TESTVECTOR(double)  b(1);\n    CPPAD_TESTVECTOR(double) xf(n);\n    b[0] = 1.;\n    xf   = f.Forward(0, b);\n\n    // check that f(b) = X(b, tf)\n    double tf    = Value(ad_tf);\n    double term  = 1;\n    double sum   = 0;\n    double eps   = 10. * CppAD::numeric_limits<double>::epsilon();\n    for(j = 0; j < n; j++)\n    {   sum += term;\n        ok &= NearEqual(xf[j], b[0] * sum, eps, eps);\n        term *= tf;\n        term /= double(j+1);\n    }\n\n    // evaluate f'(b)\n    CPPAD_TESTVECTOR(double) d_xf(n);\n    d_xf = f.Jacobian(b);\n\n    // check that f'(b) = partial of X(b, tf) w.r.t b\n    term  = 1;\n    sum   = 0;\n    for(j = 0; j < n; j++)\n    {   sum += term;\n        ok &= NearEqual(d_xf[j], sum, eps, eps);\n        term *= tf;\n        term /= double(j+1);\n    }\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/utility/set_union.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin set_union.cpp}\n\nSet Union: Example and Test\n###########################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end set_union.cpp}\n*/\n// BEGIN C++\n# include <cppad/utility/set_union.hpp>\n\nbool set_union(void)\n{   bool ok = true;\n\n    // create empty sets\n    std::set<size_t> left, right, result;\n\n    // set left = {1, 2}\n    left.insert(1);\n    left.insert(2);\n\n    // set right = {2, 3}\n    right.insert(2);\n    right.insert(3);\n\n    // set result = {1, 2} U {2, 3}\n    result = CppAD::set_union(left, right);\n\n    // expected result\n    size_t check_vec[] = {1, 2, 3};\n    std::set<size_t> check_set(check_vec, check_vec + 3);\n\n    // check result\n    ok &= result == check_set;\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/utility/simple_vector.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin simple_vector.cpp}\n\nSimple Vector Template Class: Example and Test\n##############################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end simple_vector.cpp}\n--------------------------------------------------------------------------\n*/\n// BEGIN C++\n# include <iostream>                   // std::cout and std::endl\n\n# include <vector>                     // std::vector\n# include <valarray>                   // std::valarray\n# include <cppad/utility/vector.hpp>       // CppAD::vector\n# include <cppad/utility/check_simple_vector.hpp>  // CppAD::CheckSimpleVector\nnamespace {\n    template <class Vector>\n    bool Ok(void)\n    {   // type corresponding to elements of Vector\n        typedef typename Vector::value_type Scalar;\n\n        bool ok = true;             // initialize testing flag\n\n        Vector x;                   // use the default constructor\n        ok &= (x.size() == 0);      // test size for an empty vector\n        Vector y(2);                // use the sizing constructor\n        ok &= (y.size() == 2);      // size for an vector with elements\n\n        // non-const access to the elements of y\n        size_t i;\n        for(i = 0; i < 2; i++)\n            y[i] = Scalar(i);\n\n        const Vector z(y);          // copy constructor\n        x.resize(2);                // resize\n        x = z;                      // vector assignment\n\n        // use the const access to the elements of x\n        // and test the values of elements of x, y, z\n        for(i = 0; i < 2; i++)\n        {   ok &= (x[i] == Scalar(i));\n            ok &= (y[i] == Scalar(i));\n            ok &= (z[i] == Scalar(i));\n        }\n        return ok;\n    }\n}\nbool SimpleVector (void)\n{   bool ok = true;\n\n    // use routine above to check these cases\n    ok &= Ok< std::vector<double> >();\n    ok &= Ok< std::valarray<float> >();\n    ok &= Ok< CppAD::vector<int> >();\n# ifndef _MSC_VER\n    // Avoid Microsoft following compiler warning:  'size_t' :\n    // forcing value to bool 'true' or 'false' (performance warning)\n    ok &= Ok< std::vector<bool> >();\n    ok &= Ok< CppAD::vector<bool> >();\n# endif\n    // use CheckSimpleVector for more extensive testing\n    CppAD::CheckSimpleVector<double, std::vector<double>  >();\n    CppAD::CheckSimpleVector<float,  std::valarray<float> >();\n    CppAD::CheckSimpleVector<int,    CppAD::vector<int>   >();\n    CppAD::CheckSimpleVector<bool,   std::vector<bool>    >();\n    CppAD::CheckSimpleVector<bool,   CppAD::vector<bool>  >();\n\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/utility/sparse_rc.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin sparse_rc.cpp}\n\nsparse_rc: Example and Test\n###########################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end sparse_rc.cpp}\n*/\n\n// BEGIN C++\n# include <cppad/utility/sparse_rc.hpp>\n# include <vector>\n\nbool sparse_rc(void)\n{   bool ok = true;\n    typedef std::vector<size_t> SizeVector;\n\n    // 3 by 3 identity matrix\n    size_t nr  = 3;\n    size_t nc  = 3;\n    size_t nnz = 3;\n    CppAD::sparse_rc<SizeVector> pattern(nr, nc, nnz);\n    for(size_t k = 0; k < nnz; k++)\n        pattern.set(k, k, k);\n\n    // row and column vectors corresponding to pattern\n    const SizeVector& row = pattern.row();\n    const SizeVector& col = pattern.row();\n\n    // check pattern\n    ok &= pattern.nnz() == nnz;\n    ok &= pattern.nr()  == nr;\n    ok &= pattern.nc()  == nc;\n    for(size_t k = 0; k < nnz; k++)\n    {   ok &= row[k] == k;\n        ok &= col[k] == k;\n    }\n\n    // change to sparsity pattern for a 5 by 5 diagonal matrix\n    // using push_back instead of set\n    nr  = 5;\n    nc  = 5;\n    pattern.resize(nr, nc, 0);\n    for(size_t k = 0; k < nr; k++)\n    {   size_t r = nr - k - 1; // reverse or row-major order\n        size_t c = nr - k - 1;\n        pattern.push_back(r, c);\n    }\n    nnz = pattern.nnz();\n\n    // check nnz, row major by value row major by reference, row and column\n    ok &= nnz == nr;\n    SizeVector        row_major_value     = pattern.row_major();\n    const SizeVector& row_major_reference = pattern.get_row_major();\n    for(size_t k = 0; k < nnz; k++)\n    {   ok &= row[ row_major_value[k] ] == k;\n        ok &= col[ row_major_value[k] ] == k;\n    }\n    ok &= row_major_reference.size() == 0;\n\n    // set_row_major\n    pattern.set_row_major();\n    ok &= row_major_reference.size() == nnz;\n    for(size_t k = 0; k < nnz; ++k)\n        ok &= row_major_reference[k] == row_major_value[k];\n\n    // create an empty pattern\n    CppAD::sparse_rc<SizeVector> other;\n    ok &= other.nnz() == 0;\n    ok &= other.nr()  == 0;\n    ok &= other.nc()  == 0;\n\n    // now swap other with pattern\n    pattern.swap(other);\n    ok &= pattern.nnz() == 0;\n    ok &= pattern.nr()  == 0;\n    ok &= pattern.nc()  == 0;\n    for(size_t k = 0; k < nnz; k++)\n    {   ok &= other.row()[k] == nnz - k - 1;\n        ok &= other.col()[k] == nnz - k - 1;\n    }\n\n    // now use the assignment statement\n    pattern = other;\n\n    // set_col_major\n    const SizeVector& col_major_reference( pattern.get_col_major() );\n    ok &= col_major_reference.size() == 0;\n    pattern.set_col_major();\n    ok &= col_major_reference.size() == nnz;\n    //\n    // check equality\n    ok &= pattern == other;\n    //\n    // Change pattern so it no longer corresponds to a diagonal matrix\n    pattern.set(nnz-1, 0, 1);\n    //\n    // check equality\n    ok &= ! (pattern == other);\n    //\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/utility/sparse_rcv.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin sparse_rcv.cpp}\n\nsparse_rcv: Example and Test\n############################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end sparse_rcv.cpp}\n*/\n\n// BEGIN C++\n# include <cppad/utility/sparse_rcv.hpp>\n# include <vector>\n\nbool sparse_rcv(void)\n{   bool ok = true;\n    typedef std::vector<size_t> SizeVector;\n    typedef std::vector<double> ValueVector;\n\n    // sparsity pattern for a 5 by 5 diagonal matrix\n    size_t nr  = 5;\n    size_t nc  = 5;\n    size_t nnz = 5;\n    CppAD::sparse_rc<SizeVector> pattern(nr, nc, nnz);\n    for(size_t k = 0; k < nnz; k++)\n    {   size_t r = nnz - k - 1; // reverse or column-major order\n        size_t c = nnz - k - 1;\n        pattern.set(k, r, c);\n    }\n\n    // sparse matrix\n    CppAD::sparse_rcv<SizeVector, ValueVector> matrix(pattern);\n    for(size_t k = 0; k < nnz; k++)\n    {   double v = double(k);\n        matrix.set(nnz - k - 1, v);\n    }\n\n    // row, column, and value vectors\n    const SizeVector&  row( matrix.row() );\n    const SizeVector&  col( matrix.row() );\n    const ValueVector& val( matrix.val() );\n    SizeVector col_major = matrix.col_major();\n\n    // check row,  column, and value\n    for(size_t k = 0; k < nnz; k++)\n    {   ok &= row[ col_major[k] ] == k;\n        ok &= col[ col_major[k] ] == k;\n        ok &= val[ col_major[k] ] == double(k);\n    }\n\n    // pat\n    const CppAD::sparse_rc<SizeVector> pat( matrix.pat() );\n    ok &= nnz == pat.nnz();\n    ok &= nr  == pat.nr();\n    ok &= nc  == pat.nc();\n    for(size_t k = 0; k < nnz; k++)\n    {   ok &= row[k] == pat.row()[k];\n        ok &= col[k] == pat.col()[k];\n    }\n\n    // create an empty matrix\n    CppAD::sparse_rcv<SizeVector, ValueVector> other;\n    ok &= other.nnz() == 0;\n    ok &= other.nr()  == 0;\n    ok &= other.nc()  == 0;\n\n    // now swap other with matrix\n    matrix.swap(other);\n    ok &= matrix.nnz() == 0;\n    ok &= matrix.nr()  == 0;\n    ok &= matrix.nc()  == 0;\n    for(size_t k = 0; k < nnz; k++)\n    {   ok &= other.row()[ col_major[k] ] == k;\n        ok &= other.col()[ col_major[k] ] == k;\n        ok &= other.val()[ col_major[k] ] == double(k);\n    }\n\n    // now use the assignment statement\n    matrix = other;\n    ok    &= other.nr()  == matrix.nr();\n    ok    &= other.nc()  == matrix.nc();\n    ok    &= other.nnz() == matrix.nnz();\n    for(size_t k = 0; k < nnz; k++)\n    {   ok &= matrix.row()[k] == other.row()[k];\n        ok &= matrix.col()[k] == other.col()[k];\n        ok &= matrix.val()[k] == other.val()[k];\n    }\n\n    // now use the copy constructor\n    CppAD::sparse_rcv<SizeVector, ValueVector> copy(matrix);\n    ok    &= copy.nr()  == matrix.nr();\n    ok    &= copy.nc()  == matrix.nc();\n    ok    &= copy.nnz() == matrix.nnz();\n    for(size_t k = 0; k < nnz; k++)\n    {   ok &= matrix.row()[k] == copy.row()[k];\n        ok &= matrix.col()[k] == copy.col()[k];\n        ok &= matrix.val()[k] == copy.val()[k];\n    }\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/utility/thread_alloc.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin thread_alloc.cpp}\n\nFast Multi-Threading Memory Allocator: Example and Test\n#######################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end thread_alloc.cpp}\n*/\n// BEGIN C++\n# include <cppad/utility/thread_alloc.hpp>\n# include <vector>\n# include <limits>\n\n\nnamespace { // Begin empty namespace\n\n\n\nbool raw_allocate(void)\n{   bool ok = true;\n    using CppAD::thread_alloc;\n    size_t thread;\n\n    // check that no memory is initilaly inuse\n    ok &= thread_alloc::free_all();\n\n    // amount of static memory used by thread zero\n    size_t static_inuse = 0;\n\n    // repeatedly allocate enough memory for at least two size_t values.\n    size_t min_size_t = 2;\n    size_t min_bytes  = min_size_t * sizeof(size_t);\n    size_t n_outer   = 10;\n    size_t n_inner    = 5;\n    for(size_t i = 0; i < n_outer; i++)\n    {   // Do not use CppAD::vector here because its use of thread_alloc\n        // complicates the inuse and available results.\n        std::vector<void*> v_ptr(n_inner);\n        // cap_bytes will be set by get_memory\n        size_t cap_bytes = 0; // set here to avoid MSC warning\n        for(size_t j = 0; j < n_inner; j++)\n        {   // allocate enough memory for min_size_t size_t objects\n            v_ptr[j]    = thread_alloc::get_memory(min_bytes, cap_bytes);\n            size_t* ptr = reinterpret_cast<size_t*>(v_ptr[j]);\n            // determine the number of size_t values we have obtained\n            size_t  cap_size_t = cap_bytes / sizeof(size_t);\n            ok                &= min_size_t <= cap_size_t;\n            // use placement new to call the size_t copy constructor\n            for(size_t k = 0; k < cap_size_t; k++)\n                new(ptr + k) size_t(i + j + k);\n            // check that the constructor worked\n            for(size_t k = 0; k < cap_size_t; k++)\n                ok &= ptr[k] == (i + j + k);\n        }\n        // check that n_inner * cap_bytes are inuse and none are available\n        thread = thread_alloc::thread_num();\n        ok &= thread_alloc::inuse(thread) == n_inner*cap_bytes + static_inuse;\n        ok &= thread_alloc::available(thread) == 0;\n        // return the memrory to thread_alloc\n        for(size_t j = 0; j < n_inner; j++)\n            thread_alloc::return_memory(v_ptr[j]);\n        // check that now n_inner * cap_bytes are now available\n        // and none are in use\n        ok &= thread_alloc::inuse(thread) == static_inuse;\n        ok &= thread_alloc::available(thread) == n_inner * cap_bytes;\n    }\n    thread_alloc::free_available(thread);\n\n    // check that the tests have not held onto memory\n    ok &= thread_alloc::free_all();\n\n    return ok;\n}\n\nclass my_char {\npublic:\n    char ch_ ;\n    my_char(void) : ch_(' ')\n    { }\n    my_char(const my_char& my_ch) : ch_(my_ch.ch_)\n    { }\n};\n\nbool type_allocate(void)\n{   bool ok = true;\n    using CppAD::thread_alloc;\n    size_t i;\n\n    // check initial memory values\n    size_t thread = thread_alloc::thread_num();\n    ok &= thread == 0;\n    ok &= thread_alloc::free_all();\n    size_t static_inuse = 0;\n\n    // initial allocation of an array\n    size_t  size_min  = 3;\n    size_t  size_one;\n    my_char *array_one  =\n        thread_alloc::create_array<my_char>(size_min, size_one);\n\n    // check the values and change them to null 'x'\n    for(i = 0; i < size_one; i++)\n    {   ok &= array_one[i].ch_ == ' ';\n        array_one[i].ch_ = 'x';\n    }\n\n    // now create a longer array\n    size_t size_two;\n    my_char *array_two =\n        thread_alloc::create_array<my_char>(2 * size_min, size_two);\n\n    // check the values in array one\n    for(i = 0; i < size_one; i++)\n        ok &= array_one[i].ch_ == 'x';\n\n    // check the values in array two\n    for(i = 0; i < size_two; i++)\n        ok &= array_two[i].ch_ == ' ';\n\n    // check the amount of inuse and available memory\n    // (an extra size_t value is used for each memory block).\n    size_t check = static_inuse + sizeof(my_char)*(size_one + size_two);\n    ok   &= thread_alloc::inuse(thread) - check < sizeof(my_char);\n    ok   &= thread_alloc::available(thread) == 0;\n\n    // delete the arrays\n    thread_alloc::delete_array(array_one);\n    thread_alloc::delete_array(array_two);\n    ok   &= thread_alloc::inuse(thread) == static_inuse;\n    check = sizeof(my_char)*(size_one + size_two);\n    ok   &= thread_alloc::available(thread) - check < sizeof(my_char);\n\n    // free the memory for use by this thread\n    thread_alloc::free_available(thread);\n\n    // check that the tests have not held onto memory\n    ok &= thread_alloc::free_all();\n\n    return ok;\n}\n\n} // End empty namespace\n\nbool check_alignment(void)\n{   bool ok = true;\n    using CppAD::thread_alloc;\n\n    // number of binary digits in a size_t value\n    size_t n_digit = std::numeric_limits<size_t>::digits;\n\n    // must be a multiple of 8\n    ok &= (n_digit % 8) == 0;\n\n    // number of bytes in a size_t value\n    size_t n_byte  = n_digit / 8;\n\n    // check raw allocation -------------------------------------------------\n    size_t min_bytes = 1;\n    size_t cap_bytes;\n    void* v_ptr = thread_alloc::get_memory(min_bytes, cap_bytes);\n\n    // convert to a size_t value\n    size_t v_size_t = reinterpret_cast<size_t>(v_ptr);\n\n    // check that it is aligned\n    ok &= (v_size_t % n_byte) == 0;\n\n    // return memory to available pool\n    thread_alloc::return_memory(v_ptr);\n\n    // check array allocation ----------------------------------------------\n    size_t size_min = 1;\n    size_t size_out;\n    my_char *array_ptr =\n        thread_alloc::create_array<my_char>(size_min, size_out);\n\n    // convert to a size_t value\n    size_t array_size_t = reinterpret_cast<size_t>(array_ptr);\n\n    // check that it is aligned\n    ok &= (array_size_t % n_byte) == 0;\n\n    // return memory to available pool\n    thread_alloc::delete_array(array_ptr);\n\n    return ok;\n}\n\n\nbool thread_alloc(void)\n{   bool ok  = true;\n    using CppAD::thread_alloc;\n\n    // check that there is only on thread\n    ok  &= thread_alloc::num_threads() == 1;\n    // so thread number must be zero\n    ok  &= thread_alloc::thread_num() == 0;\n    // and we are in sequential execution mode\n    ok  &= thread_alloc::in_parallel() == false;\n\n    // Instruct thread_alloc to hold onto memory.  This makes memory\n    // allocation faster (especially when there are multiple threads).\n    thread_alloc::hold_memory(true);\n\n    // run raw allocation tests\n    ok &= raw_allocate();\n\n    // run typed allocation tests\n    ok &= type_allocate();\n\n    // check alignment\n    ok &= check_alignment();\n\n    // return allocator to its default mode\n    thread_alloc::hold_memory(false);\n    return ok;\n}\n\n\n// END C++\n"
  },
  {
    "path": "example/utility/to_string.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin to_string.cpp}\n\nto_string: Example and Test\n###########################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end to_string.cpp}\n*/\n// BEGIN C++\n\n// Examples with fundamental types\n# include <cppad/utility/to_string.hpp>\nnamespace {\n    template <class Integer>\n    Integer string2signed(const std::string& s)\n    {   Integer result = 0;\n        size_t index   = 0;\n        if( s[0] == '-' )\n        {   ++index;\n            while( index < s.size() )\n                result = Integer(10) * result - Integer(s[index++] - '0' );\n        }\n        else\n        {   while( index < s.size() )\n                result = Integer(10) * result + Integer(s[index++] - '0' );\n        }\n        return result;\n    }\n    template <class Integer>\n    Integer string2unsigned(const std::string& s)\n    {   Integer result = 0;\n        size_t index   = 0;\n        while( index < s.size() )\n            result = Integer(10 * result + Integer(s[index++]) - '0');\n        return result;\n    }\n    template <class Integer>\n    bool signed_integer(void)\n    {   bool ok = true;\n        //\n        Integer max    = std::numeric_limits<Integer>::max();\n        std::string s  = CppAD::to_string(max);\n        Integer check  = string2signed<Integer>(s);\n        ok            &= max == check;\n        //\n        Integer min    = std::numeric_limits<Integer>::min();\n        s              = CppAD::to_string(min);\n        check          = string2signed<Integer>(s);\n        ok            &= min == check;\n        //\n        return ok;\n    }\n    template <class Integer>\n    bool unsigned_integer(void)\n    {   bool ok = true;\n        //\n        Integer max    = std::numeric_limits<Integer>::max();\n        std::string s  = CppAD::to_string(max);\n        Integer check  = string2unsigned<Integer>(s);\n        ok            &= max == check;\n        ok            &= std::numeric_limits<Integer>::min() == 0;\n        //\n        return ok;\n    }\n    template <class Float>\n    bool floating(void)\n    {   bool  ok  = true;\n        Float eps = std::numeric_limits<Float>::epsilon();\n        Float pi  = Float( 4.0 * std::atan(1.0) );\n        //\n        std::string s = CppAD::to_string( pi );\n        Float check   = Float( std::atof( s.c_str() ) );\n        ok           &= std::fabs( check / pi - 1.0 ) <= 2.0 * eps;\n        //\n        return ok;\n    }\n}\n\n// Examples with AD types\n# include <cppad/cppad.hpp>\nnamespace {\n    template <class Base>\n    bool ad_floating(void)\n    {   bool  ok  = true;\n        Base eps  = std::numeric_limits<Base>::epsilon();\n        Base pi   = Base( 4.0 * std::atan(1.0) );\n        //\n        std::string s = CppAD::to_string( CppAD::AD<Base>( pi ) );\n        Base check    = Base( std::atof( s.c_str() ) );\n        ok           &= fabs( check / pi - Base(1.0) ) <= Base( 2.0 ) * eps;\n        //\n        return ok;\n    }\n}\n\n// Test driver\nbool to_string(void)\n{   bool ok = true;\n\n    ok &= unsigned_integer<unsigned short>();\n    ok &= signed_integer<signed int>();\n    //\n    ok &= unsigned_integer<unsigned long>();\n    ok &= signed_integer<signed long>();\n    ok &= unsigned_integer<unsigned long long>();\n    ok &= signed_integer<signed long long>();\n    //\n    ok &= floating<float>();\n    ok &= floating<double>();\n    ok &= floating<long double>();\n    //\n    ok &= ad_floating<float>();\n    ok &= ad_floating<double>();\n    //\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/utility/utility.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin utility.cpp}\n\nCppAD Utilities Examples and Tests Driver\n#########################################\n\nRunning These Tests\n*******************\nAfter executing the :ref:`cmake-name` command\nform the :ref:`download@Distribution Directory`,\nyou can build and run these tests with the commands::\n\n    cd build\n    make check_example_utility\n\nNote that your choice of :ref:`cmake@generator` may require using\nan different version of make; e.g., ``ninja`` .\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end utility.cpp}\n-------------------------------------------------------------------------------\n*/\n// BEGIN C++\n\n// for thread_alloc\n# include <cppad/utility/thread_alloc.hpp>\n\n// test runner\n# include <cppad/utility/test_boolofvoid.hpp>\n\n// BEGIN_SORT_THIS_LINE_PLUS_1\nextern bool CheckNumericType(void);\nextern bool CheckSimpleVector(void);\nextern bool CppAD_vector(void);\nextern bool ErrorHandler(void);\nextern bool LuFactor(void);\nextern bool LuInvert(void);\nextern bool LuSolve(void);\nextern bool Near_Equal(void);\nextern bool OdeErrControl(void);\nextern bool OdeErrMaxabs(void);\nextern bool OdeGear(void);\nextern bool OdeGearControl(void);\nextern bool RombergMul(void);\nextern bool RombergOne(void);\nextern bool SimpleVector(void);\nextern bool dll_lib(void);\nextern bool index_sort(void);\nextern bool nan(void);\nextern bool poly(void);\nextern bool pow_int(void);\nextern bool rosen_34(void);\nextern bool runge_45(void);\nextern bool runge_45_1(void);\nextern bool set_union(void);\nextern bool sparse_rc(void);\nextern bool sparse_rcv(void);\nextern bool thread_alloc(void);\nextern bool to_string(void);\nextern bool vectorBool(void);\n// END_SORT_THIS_LINE_MINUS_1\n\n// main program that runs all the tests\nint main(void)\n{   std::string group = \"example/utility\";\n    size_t      width = 20;\n    CppAD::test_boolofvoid Run(group, width);\n\n    // This line is used by test_one.sh\n\n// BEGIN_SORT_THIS_LINE_PLUS_1\n    Run( CheckNumericType,       \"CheckNumericType\" );\n    Run( CheckSimpleVector,      \"CheckSimpleVector\" );\n    Run( CppAD_vector,           \"CppAD_vector\" );\n    Run( ErrorHandler,           \"ErrorHandler\" );\n    Run( LuFactor,               \"LuFactor\" );\n    Run( LuInvert,               \"LuInvert\" );\n    Run( LuSolve,                \"LuSolve\" );\n    Run( Near_Equal,             \"Near_Equal\" );\n    Run( OdeErrControl,          \"OdeErrControl\" );\n    Run( OdeErrMaxabs,           \"OdeErrMaxabs\" );\n    Run( OdeGear,                \"OdeGear\" );\n    Run( OdeGearControl,         \"OdeGearControl\" );\n    Run( RombergMul,             \"RombergMul\" );\n    Run( RombergOne,             \"RombergOne\" );\n    Run( SimpleVector,           \"SimpleVector\" );\n    Run( index_sort,             \"index_sort\" );\n    Run( nan,                    \"nan\" );\n    Run( poly,                   \"poly\" );\n    Run( pow_int,                \"pow_int\" );\n    Run( rosen_34,               \"rosen_34\" );\n    Run( runge_45,               \"runge_45\" );\n    Run( runge_45_1,             \"runge_45_1\" );\n    Run( set_union,              \"set_union\" );\n    Run( sparse_rc,              \"sparse_rc\" );\n    Run( sparse_rcv,             \"sparse_rcv\" );\n    Run( thread_alloc,           \"thread_alloc\" );\n    Run( to_string,              \"to_string\" );\n    Run( vectorBool,             \"vectorBool\" );\n// END_SORT_THIS_LINE_MINUS_1\n//\n# if CPPAD_C_COMPILER_GNU_FLAGS || CPPAD_C_COMPILER_MSVC_FLAGS\n# if CPPAD_USE_CPLUSPLUS_2017 && ! CPPAD_LINK_FLAGS_HAS_M32\n    Run( dll_lib,                \"dll_lib\" );\n# endif\n# endif\n    //\n    // check for memory leak\n    bool memory_ok = CppAD::thread_alloc::free_all();\n    // print summary at end\n    bool ok = Run.summary(memory_ok);\n    //\n    return static_cast<int>( ! ok );\n}\n// END C++\n"
  },
  {
    "path": "example/utility/vector_bool.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-23 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin vector_bool.cpp}\n\nCppAD::vectorBool Class: Example and Test\n#########################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end vector_bool.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/utility/vector_bool.hpp>\n# include <cppad/utility/check_simple_vector.hpp>\n# include <sstream> // sstream and string are used to test output operation\n# include <string>\n\nbool vectorBool(void)\n{   bool ok = true;\n    using CppAD::vectorBool;\n\n    // is that boolvector is\n    // a simple vector class with elements of type bool\n    CppAD::CheckSimpleVector< bool, vectorBool >();\n\n    vectorBool x;          // default constructor\n    ok &= (x.size() == 0);\n\n    // resize using size_t or int\n    size_t two_s = 2;\n    int    two_i = 2;\n    x.resize( two_s );\n    x.resize( two_i );\n    ok &= (x.size() == 2);\n\n    // set element values using size_t and int\n    size_t zero_s = 0;\n    int    one_i  = 1;\n    x[zero_s]     = false;\n    x[one_i]      = true;\n\n    vectorBool y(2);       // sizing constructor\n    ok &= (y.size() == 2);\n\n    // swap, get element values using size_t and int\n    y.swap(x);\n    ok &= y[zero_s] == false;\n    ok &= y[one_i]  == true;\n\n    const vectorBool z(y); // copy constructor and const element access\n    ok &= (z.size() == 2);\n    ok &= ( (z[0] == false) && (z[1] == true) );\n\n    x[0] = true;           // modify, assignment changes x\n    ok &= (x[0] == true);\n\n    // resize x to zero and check that vector assignment works for both\n    // size zero and matching sizes\n    x.resize(0);\n    ok &= (x.size() == 0);\n    ok &= (y.size() == z.size());\n    //\n    x = y = z;\n    ok &= ( (x[0] == false) && (x[1] == true) );\n    ok &= ( (y[0] == false) && (y[1] == true) );\n    ok &= ( (z[0] == false) && (z[1] == true) );\n\n    // test of push_vector\n    y.push_vector(z);\n    ok &= y.size() == 4;\n    ok &= ( (y[0] == false) && (y[1] == true) );\n    ok &= ( (y[2] == false) && (y[3] == true) );\n\n    y[1] = false;           // element assignment to another element\n    x[0] = y[1];\n    ok &= (x[0] == false);\n\n    // test of output\n    std::string        correct= \"01\";\n    std::string        str;\n    std::ostringstream buf;\n    buf << z;\n    str = buf.str();\n    ok &= (str == correct);\n\n    // test resize(0), capacity, and clear\n    size_t i = x.capacity();\n    ok      &= i > 0;\n    x.resize(0);\n    ok      &= i == x.capacity();\n    x.clear();\n    ok      &= 0 == x.capacity();\n\n    // test of push_back element\n    for(i = 0; i < 100; i++)\n        x.push_back( (i % 3) != 0 );\n    ok &= (x.size() == 100);\n    for(i = 0; i < 100; i++)\n        ok &= ( x[i] == ((i % 3) != 0) );\n\n    // initializer list constructor\n    vectorBool w = { true, false, false, true };\n    ok &= w.size() == 4;\n    ok &= w[0] == true;\n    ok &= w[1] == false;\n    ok &= w[2] == false;\n    ok &= w[3] == true;\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "example/valvector/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# Build the example/valvector directory tests\n#\n# BEGIN_SORT_THIS_LINE_PLUS_2\nSET(source_list valvector.cpp\n    ad_join.cpp\n    ad_split.cpp\n    ad_sum.cpp\n    assign.cpp\n    azmul.cpp\n    base_require.cpp\n    binary_op.cpp\n    compare_op.cpp\n    compound_op.cpp\n    condexp.cpp\n    ctor.cpp\n    element.cpp\n    get_started.cpp\n    llsq_obj.cpp\n    output.cpp\n    pow.cpp\n    resize.cpp\n    size.cpp\n    sum.cpp\n    unary_math.cpp\n    unary_op.cpp\n)\n# END_SORT_THIS_LINE_MINUS_2\n#\nset_compile_flags( example_valvector \"${cppad_debug_which}\" \"${source_list}\" )\n#\nADD_EXECUTABLE(example_valvector EXCLUDE_FROM_ALL ${source_list})\n#\n# List of libraries to be linked into the specified target\nTARGET_LINK_LIBRARIES(example_valvector\n    ${cppad_lib}\n    ${colpack_libs}\n)\n# check_example_valvector\nadd_check_executable(check_example valvector)\n"
  },
  {
    "path": "example/valvector/ad_join.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2024 Bradley M. Bell\n// ---------------------------------------------------------------------------\n/*\n{xrst_begin valvector_ad_join.cpp}\n\nExample and Test of Joining a valvector\n#######################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end valvector_ad_join.cpp}\n-------------------------------------------------------------------------------\n*/\n// BEGIN C++\n# include <cppad/example/valvector/split_join.hpp>\n# include <cppad/cppad.hpp>\nbool ad_join(void)\n{   // ok\n    bool ok = true;\n    //\n    // sparsity_type\n    typedef CppAD::sparse_rc< CPPAD_TESTVECTOR(size_t) > sparsity_type;\n    //\n    // scalar_type\n    typedef valvector::scalar_type scalar_type;\n    //\n    // ad_valvector\n    typedef CppAD::AD<valvector> ad_valvector;\n    //\n    // ajoin\n    valvector_ad_join ajoin;\n    //\n    // n, m\n    size_t n = 10;\n    size_t m = 1;\n    //\n    // ax\n    CPPAD_TESTVECTOR( ad_valvector ) ax(n);\n    for(size_t j = 0; j < n; ++j)\n        ax[j] = valvector(j);\n    CppAD::Independent(ax);\n    //\n    // ay\n    ad_valvector ay;\n    ajoin(ax, ay);\n    //\n    ad_valvector ay_sq = ay * ay;\n    //\n    // f\n    CPPAD_TESTVECTOR( ad_valvector ) az(m);\n    az[0] = ay_sq;\n    CppAD::ADFun<valvector> f(ax, az);\n    //\n    // x\n    CPPAD_TESTVECTOR( valvector ) x(n);\n    for(size_t j = 0; j < n; ++j)\n        x[j][0] = scalar_type(j + 1);\n    //\n    // a\n    CPPAD_TESTVECTOR( valvector ) z(m);\n    z = f.Forward(0, x);\n    //\n    // ok\n    for(size_t j = 0; j < n; ++j)\n        ok &= z[0][j] == x[j][0] * x[j][0];\n    //\n    // dw\n    CPPAD_TESTVECTOR( valvector ) w(m), dw(n);\n    w[0][0] = 1.0;\n    dw = f.Reverse(1, w);\n    //\n    // ok\n    for(size_t j = 0; j < n; ++j)\n        ok &= dw[0][j] == scalar_type(2) * x[0][j];\n    //\n    // jac_pattern\n    sparsity_type identity_pattern(n, n, n);\n    for(size_t k = 0; k < n; ++k)\n        identity_pattern.set(k, k, k);\n    bool transpose     = false;\n    bool dependency    = false;\n    bool internal_bool = false;\n    sparsity_type jac_pattern;\n    f.for_jac_sparsity(\n        identity_pattern, transpose, dependency, internal_bool, jac_pattern\n    );\n    //\n    // ok\n    ok &= jac_pattern.nnz() == n;\n    ok &= jac_pattern.nr()  == m;\n    ok &= jac_pattern.nc()  == n;\n    {   CPPAD_TESTVECTOR(size_t) col_major = jac_pattern.col_major();\n        const CPPAD_TESTVECTOR(size_t)& row = jac_pattern.row();\n        const CPPAD_TESTVECTOR(size_t)& col = jac_pattern.col();\n        for(size_t k = 0; k < n; ++k)\n        {   ok &= row[ col_major[k] ] == 0;\n            ok &= col[ col_major[k] ] == k;\n        }\n    }\n    //\n    // hes_pattern\n    internal_bool = false;\n    CPPAD_TESTVECTOR(bool) select_domain(n);\n    CPPAD_TESTVECTOR(bool) select_range(m);\n    select_range[0] = true;\n    for(size_t j = 0; j < n; ++j)\n        select_domain[j] = true;\n    sparsity_type hes_pattern;\n    f.for_hes_sparsity (\n        select_domain , select_range , internal_bool , hes_pattern\n    );\n    //\n    // ok\n    // The sparsity calculation does not distinguish between different elements\n    // of a valvector so the sparsity pattern fills in (this is not efficient).\n    ok &= hes_pattern.nnz() == n * n;\n    ok &= hes_pattern.nr()  == n;\n    ok &= hes_pattern.nc()  == n;\n    {   CPPAD_TESTVECTOR(size_t) col_major = hes_pattern.col_major();\n        const CPPAD_TESTVECTOR(size_t)& row = hes_pattern.row();\n        const CPPAD_TESTVECTOR(size_t)& col = hes_pattern.col();\n        size_t k = 0;\n        for(size_t j = 0; j < n; ++j)\n        {   for(size_t i = 0; i < n; ++i)\n            {   ok &= row[ col_major[k] ] == i;\n                ok &= col[ col_major[k] ] == j;\n                ++k;\n            }\n        }\n    }\n    //\n    // af\n    typedef CppAD::ADFun<ad_valvector, valvector> ad_fun_type;\n    ad_fun_type af = ad_fun_type( f.base2ad() );\n    //\n    // g\n    CPPAD_TESTVECTOR( ad_valvector ) adx(n), adz(m);\n    for(size_t j = 0; j < n; ++j)\n        adx[j] = valvector( 1.0 );\n    CppAD::Independent(ax);\n    af.Forward(0, ax);\n    adz = af.Forward(1, adx);\n    CppAD::ADFun<valvector> g(ax, adz);\n    //\n    // ok\n    CPPAD_TESTVECTOR( valvector ) dz(m);\n    dz = g.Forward(0, x);\n    for(size_t j = 0; j < n; ++j)\n        ok &= dz[0][j] == 2.0 * x[j][0];\n    //\n    // h\n    CPPAD_TESTVECTOR( ad_valvector ) aw(m), adw(n);\n    aw[0] = valvector( 1.0 );\n    CppAD::Independent(ax);\n    af.Forward(0, ax);\n    adw = af.Reverse(1, aw);\n    CppAD::ADFun<valvector> h(ax, adw);\n    //\n    // ok\n    dw = h.Forward(0, x);\n    for(size_t j = 0; j < n; ++j)\n        ok &= dw[j][0] == 2.0 * x[j][0];\n    //\n    // ok\n    f.optimize();\n    z = f.Forward(0, x);\n    for(size_t j = 0; j < n; ++j)\n        ok &= z[0][j] == x[j][0] * x[j][0];\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/valvector/ad_split.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2024 Bradley M. Bell\n// ---------------------------------------------------------------------------\n/*\n{xrst_begin valvector_ad_split.cpp}\n\nExample and Test of Splitting a valvector\n#########################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end valvector_ad_split.cpp}\n-------------------------------------------------------------------------------\n*/\n// BEGIN C++\n# include <cppad/example/valvector/split_join.hpp>\n# include <cppad/cppad.hpp>\nbool ad_split(void)\n{   // ok\n    bool ok = true;\n    //\n    // sparsity_type\n    typedef CppAD::sparse_rc< CPPAD_TESTVECTOR(size_t) > sparsity_type;\n    //\n    // scalar_type\n    typedef valvector::scalar_type scalar_type;\n    //\n    // ad_valvector\n    typedef CppAD::AD<valvector> ad_valvector;\n    //\n    // asplit\n    valvector_ad_split asplit;\n    //\n    // n, m\n    size_t n = 1;\n    size_t m = 10;\n    //\n    // ax\n    CPPAD_TESTVECTOR( ad_valvector ) ax(n);\n    ax[0] = valvector(0);\n    CppAD::Independent(ax);\n    //\n    // ax_sq\n    ad_valvector ax_sq = ax[0] * ax[0];\n    //\n    // f\n    CPPAD_TESTVECTOR( ad_valvector ) ay(m);\n    asplit(ax_sq, ay);\n    CppAD::ADFun<valvector> f(ax, ay);\n    //\n    // x\n    CPPAD_TESTVECTOR( valvector ) x(n);\n    x[0].resize(m);\n    for(size_t i = 0; i < m; ++i)\n        x[0][i] = scalar_type(i + 1);\n    //\n    // y\n    CPPAD_TESTVECTOR( valvector ) y(m);\n    y = f.Forward(0, x);\n    //\n    // ok\n    for(size_t i = 0; i < m; ++i)\n        ok &= y[i][0] == x[0][i] * x[0][i];\n    //\n    // dw\n    CPPAD_TESTVECTOR( valvector ) w(m), dw(n);\n    for(size_t i = 0; i < m; ++i)\n        w[i][0] = 1.0;\n    dw = f.Reverse(1, w);\n    //\n    // ok\n    for(size_t i = 0; i < m; ++i)\n        ok &= dw[0][i] == scalar_type(2) * x[0][i];\n    //\n    // jac_pattern\n    sparsity_type identity_pattern(n, n, n);\n    identity_pattern.set(0, 0, 0);\n    bool transpose     = false;\n    bool dependency    = false;\n    bool internal_bool = false;\n    sparsity_type jac_pattern;\n    f.for_jac_sparsity(\n        identity_pattern, transpose, dependency, internal_bool, jac_pattern\n    );\n    //\n    // ok\n    ok &= jac_pattern.nnz() == m;\n    ok &= jac_pattern.nr()  == m;\n    ok &= jac_pattern.nc()  == n;\n    CPPAD_TESTVECTOR(size_t) col_major = jac_pattern.col_major();\n    for(size_t k = 0; k < m; ++k)\n    {   ok &= jac_pattern.row()[k] == k;\n        ok &= jac_pattern.col()[k] == 0;\n    }\n    //\n    // hes_pattern\n    internal_bool = false;\n    CPPAD_TESTVECTOR(bool) select_domain(n);\n    CPPAD_TESTVECTOR(bool) select_range(m);\n    select_domain[0] = true;\n    for(size_t i = 0; i < m; ++i)\n        select_range[i] = false;\n    select_range[0] = true;\n    sparsity_type hes_pattern;\n    f.for_hes_sparsity (\n        select_domain , select_range , internal_bool , hes_pattern\n    );\n    //\n    // ok\n    ok &= hes_pattern.nnz() == 1;\n    ok &= hes_pattern.nr()  == n;\n    ok &= hes_pattern.nc()  == n;\n    ok &= hes_pattern.row()[0] == 0;\n    ok &= hes_pattern.col()[0] == 0;\n    //\n    // af\n    typedef CppAD::ADFun<ad_valvector, valvector> ad_fun_type;\n    ad_fun_type af = ad_fun_type( f.base2ad() );\n    //\n    // g\n    CPPAD_TESTVECTOR( ad_valvector ) adx(n), ady(m);\n    adx[0] = valvector( 1.0 );\n    CppAD::Independent(ax);\n    af.Forward(0, ax);\n    ady = af.Forward(1, adx);\n    CppAD::ADFun<valvector> g(ax, ady);\n    //\n    // ok\n    CPPAD_TESTVECTOR( valvector ) dy(m);\n    dy = g.Forward(0, x);\n    for(size_t i = 0; i < m; ++i)\n        ok &= dy[i][0] == 2.0 * x[0][i];\n    //\n    // h\n    CPPAD_TESTVECTOR( ad_valvector ) aw(m), adw(n);\n    for(size_t i = 0; i < m; ++i)\n        aw[i] = valvector( 1.0 );\n    CppAD::Independent(ax);\n    af.Forward(0, ax);\n    adw = af.Reverse(1, aw);\n    CppAD::ADFun<valvector> h(ax, adw);\n    //\n    // ok\n    dw = h.Forward(0, x);\n    for(size_t i = 0; i < m; ++i)\n        ok &= dw[0][i] == 2.0 * x[0][i];\n    //\n    // ok\n    f.optimize();\n    y = f.Forward(0, x);\n    for(size_t i = 0; i < m; ++i)\n        ok &= y[i][0] == x[0][i] * x[0][i];\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/valvector/ad_sum.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2024 Bradley M. Bell\n// ---------------------------------------------------------------------------\n/*\n{xrst_begin valvector_ad_sum.cpp}\n\nExample and Test of Summing a valvector\n#######################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end valvector_ad_sum.cpp}\n-------------------------------------------------------------------------------\n*/\n// BEGIN C++\n# include <cppad/example/valvector/sum.hpp>\n# include <cppad/cppad.hpp>\nbool ad_sum(void)\n{   // ok\n    bool ok = true;\n    //\n    // sparsity_type\n    typedef CppAD::sparse_rc< CPPAD_TESTVECTOR(size_t) > sparsity_type;\n    //\n    // scalar_type\n    typedef valvector::scalar_type scalar_type;\n    //\n    // ad_valvector\n    typedef CppAD::AD<valvector> ad_valvector;\n    //\n    // asum\n    valvector_ad_sum asum;\n    //\n    // n, m, p\n    size_t n = 1;\n    size_t m = 1;\n    size_t p = 10;\n    //\n    // ax\n    CPPAD_TESTVECTOR( ad_valvector ) ax(n);\n    ax[0] = valvector(1);\n    CppAD::Independent(ax);\n    //\n    // ax_sq\n    ad_valvector ax_sq = ax[0] * ax[0];\n    //\n    // ay\n    CPPAD_TESTVECTOR( ad_valvector ) ay(m);\n    asum(ax_sq, ay[0]);\n    //\n    // f\n    CppAD::ADFun<valvector> f(ax, ay);\n    //\n    // x\n    CPPAD_TESTVECTOR( valvector ) x(n);\n    x[0].resize(p);\n    for(size_t k = 0; k < p; ++k)\n        x[0][k] = scalar_type(k + 1);\n    //\n    // y\n    CPPAD_TESTVECTOR( valvector ) y(m);\n    y = f.Forward(0, x);\n    //\n    // ok\n    scalar_type check(0);\n    for(size_t k = 0; k < p; ++k)\n        check += x[0][k] * x[0][k];\n    ok &= check == y[0][0];\n    //\n    // dw\n    CPPAD_TESTVECTOR( valvector ) w(m), dw(n);\n    w[0][0] = 1.0;\n    dw = f.Reverse(1, w);\n    //\n    // ok\n    for(size_t k = 0; k < p; ++k)\n        ok &= dw[0][k] == scalar_type(2) * x[0][k];\n    //\n    // jac_pattern\n    sparsity_type identity_pattern(n, n, n);\n    for(size_t k = 0; k < n; ++k)\n        identity_pattern.set(k, k, k);\n    bool transpose     = false;\n    bool dependency    = false;\n    bool internal_bool = false;\n    sparsity_type jac_pattern;\n    f.for_jac_sparsity(\n        identity_pattern, transpose, dependency, internal_bool, jac_pattern\n    );\n    //\n    // ok\n    ok &= jac_pattern.nnz()    == 1;\n    ok &= jac_pattern.nr()     == 1;\n    ok &= jac_pattern.nc()     == 1;\n    ok &= jac_pattern.row()[0] == 0;\n    ok &= jac_pattern.col()[0] == 0;\n    //\n    // hes_pattern\n    internal_bool = false;\n    CPPAD_TESTVECTOR(bool) select_domain(n);\n    CPPAD_TESTVECTOR(bool) select_range(m);\n    select_range[0]  = true;\n    select_domain[0] = true;\n    sparsity_type hes_pattern;\n    f.for_hes_sparsity (\n        select_domain , select_range , internal_bool , hes_pattern\n    );\n    //\n    // ok\n    ok &= hes_pattern.nnz()    == n * n;\n    ok &= hes_pattern.nr()     == n;\n    ok &= hes_pattern.nc()     == n;\n    ok &= hes_pattern.row()[0] == 0;\n    ok &= hes_pattern.col()[0] == 0;\n    //\n    // af\n    typedef CppAD::ADFun<ad_valvector, valvector> ad_fun_type;\n    ad_fun_type af = ad_fun_type( f.base2ad() );\n    //\n    // g\n    CPPAD_TESTVECTOR( ad_valvector ) adx(n), ady(m);\n    adx[0] = valvector( 1.0 );\n    CppAD::Independent(ax);\n    af.Forward(0, ax);\n    ady = af.Forward(1, adx);\n    CppAD::ADFun<valvector> g(ax, ady);\n    //\n    // ok\n    CPPAD_TESTVECTOR( valvector ) dy(m);\n    dy    = g.Forward(0, x);\n    check = scalar_type(0);\n    for(size_t k = 0; k < p; ++k)\n        check += 2.0 * x[0][k];\n    ok &= dy[0][0] == check;\n    //\n    // h\n    CPPAD_TESTVECTOR( ad_valvector ) aw(m), adw(n);\n    aw[0] = valvector( 1.0 );\n    CppAD::Independent(ax);\n    af.Forward(0, ax);\n    adw = af.Reverse(1, aw);\n    CppAD::ADFun<valvector> h(ax, adw);\n    //\n    // ok\n    dw = h.Forward(0, x);\n    for(size_t k = 0; k < p; ++k)\n        ok &= dw[0][k] == 2.0 * x[0][k];\n    //\n    // ok\n    f.optimize();\n    y     = f.Forward(0, x);\n    check = scalar_type(0);\n    for(size_t k = 0; k < p; ++k)\n        check += x[0][k] * x[0][k];\n    ok &= y[0][0] == check;\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/valvector/assign.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2024 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin valvector_assign.cpp}\n\nExample and Test of valvector Assignment Operator\n#################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end valvector_assign.cpp}\n-------------------------------------------------------------------------------\n*/\n// BEGIN C++\n# include <cppad/example/valvector/class.hpp>\n//\nbool assign(void)\n{   // scalar_type\n    typedef valvector::scalar_type scalar_type;\n    //\n    //\n    // ok\n    bool ok = true;\n    //\n    // v, ok\n    valvector v;\n    ok &= v.size() == 1;\n    //\n    // w\n    valvector w = valvector( {2, 3, 4} );\n    ok &= w.size() == 3;\n    //\n    // v\n    v    = w;\n    v[0] = scalar_type(1);\n    //\n    // ok\n    ok &= v.size() == w.size();\n    ok &= w[0] == scalar_type(2);\n    ok &= v[0] == scalar_type(1);\n    for(size_t i = 1; i < w.size(); ++i)\n        ok &= v[i] == w[i];\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/valvector/azmul.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2024 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin valvector_azmul.cpp}\n\nExample and Test of valvector azmul Function\n############################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end valvector_azmul.cpp}\n-------------------------------------------------------------------------------\n*/\n// BEGIN C++\n# include <sstream>\n# include <string>\n# include <cppad/example/valvector/class.hpp>\n# include <cppad/utility/near_equal.hpp>\n//\nbool azmul(void)\n{   typedef valvector::scalar_type scalar_type;\n    //\n    // ok\n    bool ok = true;\n    //\n    // nan\n    scalar_type nan   = CppAD::numeric_limits<scalar_type>::quiet_NaN();\n    //\n    // x, y, z\n    valvector x = valvector( {0, 1, 2} );\n    valvector y = valvector( {nan, nan, 5} );;\n    valvector z = CppAD::azmul(x, y);\n    //\n    // ok\n    ok &= z[0] == scalar_type(0);\n    ok &= CppAD::isnan( z[1] );\n    ok &= z[2] == x[2] * y[2];\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/valvector/base_require.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2024 Bradley M. Bell\n// ---------------------------------------------------------------------------\n/*\n{xrst_begin valvector_base_require.cpp}\n\nExample and Test of valvector Base Requirements\n###############################################\n\nScope\n*****\nThis only covers that valvector\n:ref:`valvector_base_require@Features Implemented Here` .\n\nSource Code\n***********\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end valvector_base_require.cpp}\n-------------------------------------------------------------------------------\n*/\n// BEGIN C++\n# include <cppad/example/valvector/class.hpp>\n//\n// base_require\nbool base_require(void)\n{   // ok\n    bool ok = true;\n    //\n    // x, y\n    valvector x, y;\n    //\n    // ok\n    x = valvector(2.5);\n    int integer_x = CppAD::Integer(x);\n    ok &= integer_x == 2;\n    //\n    // ok\n    valvector nan = CppAD::numeric_limits<valvector>::quiet_NaN();\n    ok &= CppAD::isnan( nan );\n    //\n    // ok\n    x = valvector( {1, 2} );\n    std::string string_x = CppAD::to_string( x );\n    std::string s;\n    for(auto itr = string_x.begin(); itr != string_x.end(); ++itr)\n        if( *itr != ' ')\n            s.push_back( *itr );\n    ok &= s == \"{1,2}\";\n    //\n    // ok\n    x   = valvector( {1, 2} );\n    y   = valvector( {1.0, 2.0} );\n    ok &= CppAD::EqualOpSeq(x, y);\n    //\n    // ok\n    ok &= CppAD::IdenticalCon(x);\n    ok &= ! CppAD::IdenticalZero(x);\n    ok &= ! CppAD::IdenticalOne(x);\n    ok &= CppAD::IdenticalEqualCon(x, y);\n    //\n    x   = valvector( {0.0, 0.0} );\n    ok &= CppAD::IdenticalZero(x);\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/valvector/binary_op.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2024 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin valvector_binary_op.cpp}\n\nExample and Test of valvector Binary Operators\n##############################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end valvector_binary_op.cpp}\n-------------------------------------------------------------------------------\n*/\n// BEGIN C++\n# include <cppad/example/valvector/class.hpp>\n//\nbool binary_op(void)\n{   //\n    // ok\n    bool ok = true;\n    //\n    // u, v, w\n    valvector u( {4, 6, 8} );\n    valvector v(2);\n    valvector w;\n    //\n    // w_size\n    size_t w_size = std::max( u.size(), v.size() );\n    //\n    // ok\n    w = u + v;\n    ok &= w.size() == w_size;\n    for(size_t i = 0; i < w_size; ++i)\n        ok &= w[i] == u[i] + v[i];\n    //\n    // ok\n    w = u - v;\n    ok &= w.size() == w_size;\n    for(size_t i = 0; i < w_size; ++i)\n        ok &= w[i] == u[i] - v[i];\n    //\n    // ok\n    w = u * v;\n    ok &= w.size() == w_size;\n    for(size_t i = 0; i < w_size; ++i)\n        ok &= w[i] == u[i] * v[i];\n    //\n    // ok\n    w = u / v;\n    ok &= w.size() == w_size;\n    for(size_t i = 0; i < w_size; ++i)\n        ok &= w[i] == u[i] / v[i];\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/valvector/compare_op.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2024 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin valvector_compare_op.cpp}\n\nExample and Test of valvector Compare Operators\n###############################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end valvector_compare_op.cpp}\n-------------------------------------------------------------------------------\n*/\n// BEGIN C++\n# include <cppad/example/valvector/class.hpp>\n//\nbool compare_op(void)\n{   typedef valvector::scalar_type scalar_type;\n    //\n    // ok\n    bool ok = true;\n    //\n    // u, v\n    valvector u( {4, 6, 8} );\n    valvector v( {4.0, 6.0, 8.0} );\n    //\n    // ok\n    ok &= u == v;\n    u[0] = u[0] + scalar_type(1);\n    ok &= u != v;\n    //\n    // ok\n    ok &= valvector( 2.0 ) < valvector( 3.0 );\n    ok &= valvector( 4.0 ) > valvector( 3.0 );\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/valvector/compound_op.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2024 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin valvector_compound_op.cpp}\n\nExample and Test of valvector Compound Assignment Operators\n###########################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end valvector_compound_op.cpp}\n-------------------------------------------------------------------------------\n*/\n// BEGIN C++\n# include <cppad/example/valvector/class.hpp>\n//\nbool compound_op(void)\n{   //\n    // ok\n    bool ok = true;\n    //\n    // u, v, w\n    valvector u(2);\n    valvector v( {4, 6, 8} );\n    valvector w;\n    ok &= u.size() == 1;\n    ok &= v.size() == 3;\n    ok &= w.size() == 1;\n    //\n    // ok\n    w  = v;\n    w += u;\n    ok &= w.size() == 3;\n    for(size_t i = 0; i < w.size(); ++i)\n        ok &= w[i] == v[i] + u[i];\n    //\n    // ok\n    w  = v;\n    w -= u;\n    ok &= w.size() == 3;\n    for(size_t i = 0; i < w.size(); ++i)\n        ok &= w[i] == v[i] - u[i];\n    //\n    // ok\n    w  = v;\n    w *= u;\n    ok &= w.size() == 3;\n    for(size_t i = 0; i < w.size(); ++i)\n        ok &= w[i] == v[i] * u[i];\n    //\n    // ok\n    w  = v;\n    w /= u;\n    ok &= w.size() == 3;\n    for(size_t i = 0; i < w.size(); ++i)\n        ok &= w[i] == v[i] / u[i];\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/valvector/condexp.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2024 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin valvector_condexp.cpp}\n\nExample and Test of valvector Conditional Expressions\n#####################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end valvector_condexp.cpp}\n-------------------------------------------------------------------------------\n*/\n// BEGIN C++\n# include <sstream>\n# include <string>\n# include <cppad/example/valvector/class.hpp>\n# include <cppad/utility/near_equal.hpp>\n//\nbool condexp(void)\n{   //\n    // ok\n    bool ok = true;\n    //\n    // left, right, if_true, if_false\n    valvector left     = valvector( {0, 1, 2, 3, 4} );\n    valvector right    = valvector( 2 );\n    valvector if_true  = left;\n    valvector if_false = right;\n    //\n    // result\n    valvector result = CppAD::CondExpGe(left, right, if_true, if_false);\n    //\n    // ok\n    for(size_t i = 0; i < result.size(); ++i)\n        ok &= result[i] == std::max( left[i], right[i] );\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/valvector/ctor.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2024 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin valvector_ctor.cpp}\n\nExample and Test of valvector Constructors\n##########################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end valvector_ctor.cpp}\n-------------------------------------------------------------------------------\n*/\n// BEGIN C++\n# include <cppad/example/valvector/class.hpp>\n//\nbool ctor(void)\n{   // scalar_type\n    typedef valvector::scalar_type scalar_type;\n    //\n    // ok\n    bool ok = true;\n    //\n    // ok\n    valvector default_ctor;\n    ok &= default_ctor.size() == 1;\n    //\n    // ok\n    valvector scalar_ctor( scalar_type(1) );\n    ok &= scalar_ctor.size() == 1;\n    ok &= scalar_ctor[0] == scalar_type(1);\n    //\n    // ok\n    valvector int_ctor( int(1) );\n    ok &= int_ctor.size() == 1;\n    ok &= int_ctor[0] == scalar_type(1);\n    //\n    // ok\n    valvector long_int_ctor( (long int)(2) );\n    ok &= long_int_ctor.size() == 1;\n    ok &= long_int_ctor[0] == scalar_type(2);\n    //\n    // ok\n    valvector double_ctor( double(3) );\n    ok &= double_ctor.size() == 1;\n    ok &= double_ctor[0] == scalar_type(3);\n    //\n    // ok\n    valvector long_double_ctor( (long double)(4) );\n    ok &= long_double_ctor.size() == 1;\n    ok &= long_double_ctor[0] == scalar_type(4);\n    //\n    // ok\n    valvector size_t_ctor( size_t(5) );\n    ok &= size_t_ctor.size() == 1;\n    ok &= size_t_ctor[0] == scalar_type(5);\n    //\n    // ok\n    // Test implicit conversion of list elements to scalar_type\n    valvector list_ctor( { 6, 7.0 } );\n    ok &= list_ctor.size() == 2;\n    ok &= list_ctor[0] == scalar_type(6);\n    ok &= list_ctor[1] == scalar_type(7);\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/valvector/element.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2024 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin valvector_element.cpp}\n\nExample and Test of valvector Element Access\n############################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end valvector_element.cpp}\n-------------------------------------------------------------------------------\n*/\n// BEGIN C++\n# include <cppad/example/valvector/class.hpp>\n//\nbool element(void)\n{   // scalar_type\n    typedef valvector::scalar_type scalar_type;\n    //\n    //\n    // ok\n    bool ok = true;\n    //\n    // v, ok\n    valvector v(3);\n    ok &= v.size() == 1;\n    for(size_t i = 0; i <= 10; ++i)\n        v[i] = scalar_type(i);\n    ok &= v[0] == scalar_type(10);\n    ok &= v[1] == scalar_type(10);\n    //\n    // v\n    v.resize(3);\n    //\n    // ok\n    ok &= v.size() == 3;\n    for(size_t i = 0; i < v.size(); ++i)\n        v[i] = scalar_type(i);\n    for(size_t i = 0; i < v.size(); ++i)\n        ok &= v[i] == scalar_type(i);\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/valvector/get_started.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2024 Bradley M. Bell\n// ---------------------------------------------------------------------------\n/*\n{xrst_begin valvector_get_started.cpp}\n\nGetting Started Using valvector as a CppAD Base Class\n#####################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end valvector_get_started.cpp}\n-------------------------------------------------------------------------------\n*/\n// BEGIN C++\n# include <cppad/example/valvector/class.hpp>\n# include <cppad/cppad.hpp>\nbool get_started(void)\n{   // ok\n    bool ok = true;\n    //\n    // ad_valvector\n    typedef CppAD::AD<valvector> ad_valvector;\n    //\n    // ax\n    CPPAD_TESTVECTOR( ad_valvector ) ax(2);\n    ax[0] = valvector( {1.0} );\n    ax[1] = valvector( {2.0} );\n    CppAD::Independent(ax);\n    //\n    // f\n    CPPAD_TESTVECTOR( ad_valvector ) ay(1);\n    ay[0] = ax[0] * ax[1];\n    CppAD::ADFun<valvector> f(ax, ay);\n    //\n    // x\n    CPPAD_TESTVECTOR( valvector ) x(2);\n    x[0] = valvector( {1.0, 2.0, 3.0} );\n    x[1] = valvector( {4.0, 3.0, 2.0} );\n    //\n    // y\n    CPPAD_TESTVECTOR( valvector ) y(1);\n    y = f.Forward(0, x);\n    //\n    // ok\n    valvector check;\n    check = valvector( {4.0, 6.0, 6.0} );\n    ok   &= y[0] == check;\n    //\n    //  dw\n    CPPAD_TESTVECTOR( valvector ) w(1), dw(2);\n    w[0] = valvector( 1.0 );\n    dw   = f.Reverse(1, w);\n    //\n    // ok\n    ok &= dw[0] == x[1];\n    ok &= dw[1] == x[0];\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/valvector/llsq_obj.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2024 Bradley M. Bell\n// ---------------------------------------------------------------------------\n/*\n{xrst_begin valvector_llsq_obj.cpp}\n\nUsing valvector to Represent Linear Least Squares Objective\n###########################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end valvector_llsq_obj.cpp}\n-------------------------------------------------------------------------------\n*/\n// BEGIN C++\n# include <cppad/example/valvector/sum.hpp>\n# include <cppad/example/valvector/class.hpp>\n# include <cppad/cppad.hpp>\nbool llsq_obj(void)\n{   // ok\n    bool ok = true;\n    //\n    // scalar_type\n    typedef valvector::scalar_type scalar_type;\n    //\n    // eps99\n    scalar_type eps99 = CppAD::numeric_limits<scalar_type>::epsilon();\n    eps99            *= scalar_type(99);\n    //\n    // ad_valvector\n    typedef CppAD::AD<valvector> ad_valvector;\n    //\n    // asum\n    valvector_ad_sum asum;\n    //\n    // n_data\n    // number of data points in the fit\n    size_t n_data = 100;\n    //\n    // time, data\n    // argument and data values in the function being fit\n    valvector time, data;\n    if( n_data == 1 )\n    {   time[0] = 0.0;\n        data[0] = 0.0;\n    }\n    else\n    {   time.resize(n_data);\n        data.resize(n_data);\n        //\n        for(size_t i = 0; i < n_data; ++i)\n        {   time[i] = -1.0 + scalar_type(2 * i) / scalar_type(n_data - 1);\n            if( time[i] < 0.0 )\n                data[i] = -1.0;\n            else if( 0.0 < time[i] )\n                data[i] = +1.0;\n            else\n                data[i] = 0.0;\n        }\n    }\n    // data\n    if( n_data % 2 == 1 )\n    {   // in case time[n_data/2] was not exactly zero due to roundoff\n        data[n_data / 2] = 0.0;\n    }\n    //\n    // nx\n    // number of coefficients in the function being fit\n    size_t nx = 3;\n    //\n    // ax\n    // coefficients in the function being fit\n    CPPAD_TESTVECTOR( ad_valvector ) ax(nx);\n    for(size_t j = 0; j < nx; ++j)\n        ax[j] = valvector(0.0);\n    CppAD::Independent(ax);\n    //\n    // amodel\n    valvector time_j(1.0);\n    ad_valvector amodel(0.0);\n    for(size_t  j = 0; j < nx; ++j)\n    {   amodel += time_j * ax[j];\n        time_j *= time;\n    }\n    //\n    // aobj\n    ad_valvector ares = data - amodel;\n    ad_valvector asq  = ares * ares;\n    ad_valvector aobj;\n    asum(asq, aobj);\n    //\n    // ay\n    CPPAD_TESTVECTOR( ad_valvector ) ay(1);\n    ay[0] = aobj;\n    CppAD::ADFun<valvector> f(ax, ay);\n    //\n    // x\n    CPPAD_TESTVECTOR( valvector ) x(nx);\n    for(size_t j = 0; j < nx; ++j)\n        x[j][0] = 1.0;\n    //\n    // y\n    CPPAD_TESTVECTOR( valvector ) y(1);\n    y = f.Forward(0, x);\n    //\n    // res\n    CPPAD_TESTVECTOR( scalar_type ) res(n_data);\n    for(size_t i = 0; i < n_data; ++i)\n    {   scalar_type tj = 1.0;\n        scalar_type model = 0.0;\n        for(size_t j = 0; j < nx; ++j)\n        {   model += tj * x[j][0];\n            tj    *= time[i];\n        }\n        res[i] = data[i] - model;\n    }\n    //\n    // ok\n    scalar_type check = 0.0;\n    for(size_t i = 0; i < n_data; ++i)\n        check += res[i] * res[i];\n    ok   &= CppAD::NearEqual(y[0][0], check, eps99, eps99);\n    //\n    // dw\n    CPPAD_TESTVECTOR( valvector ) w(1), dw(nx);\n    w[0][0] = 1.0;\n    dw = f.Reverse(1, w);\n    //\n    //\n    // dres_sq\n    CPPAD_TESTVECTOR( scalar_type ) dres_sq(nx);\n    for(size_t j = 0; j < nx; ++j)\n        dres_sq[j] = 0.0;\n    for(size_t i = 0; i < n_data; ++i)\n    {   scalar_type tj = 1.0;\n        for(size_t j = 0; j < nx; ++j)\n        {   dres_sq[j] += - 2.0 * res[i] * tj;\n            tj         *= time[i];\n        }\n    }\n    //\n    // ok\n    // reverse mode does not know that x[j] had size one and represents\n    // a valvector of size n_data and with x[j][k] constant w.r.t k.\n    for(size_t j = 0; j < nx; ++j)\n    {   /*\n        std::cout << \"j = \" << j;\n        std::cout << \", dw[j] = \" << dw[j];\n        std::cout << \", dres_sq[j] = \" << dres_sq[j] << \"\\n\";\n        */\n        ok   &= dw[j].size() == n_data;\n        ok   &= CppAD::NearEqual(dw[j].sum(), dres_sq[j], eps99, eps99);\n    }\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/valvector/output.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2024 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin valvector_output.cpp}\n\nExample and Test of Outputting a valvector\n##########################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end valvector_output.cpp}\n-------------------------------------------------------------------------------\n*/\n// BEGIN C++\n# include <sstream>\n# include <string>\n# include <cppad/example/valvector/class.hpp>\n//\nbool output(void)\n{   //\n    // ok\n    bool ok = true;\n    //\n    // x\n    valvector x( {4, 6, 8} );\n    //\n    // s\n    std::stringstream ss;\n    ss << x;\n    std::string s = ss.str();\n    //\n    // q\n    std::string q;\n    for(auto itr = s.begin(); itr != s.end(); ++itr)\n        if( *itr != ' ')\n            q.push_back( *itr );\n    //\n    ok &= q == \"{4,6,8}\";\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/valvector/pow.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2024 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin valvector_pow.cpp}\n\nExample and Test of valvector pow Function\n##########################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end valvector_pow.cpp}\n-------------------------------------------------------------------------------\n*/\n// BEGIN C++\n# include <sstream>\n# include <string>\n# include <cppad/example/valvector/class.hpp>\n# include <cppad/utility/near_equal.hpp>\n//\nbool pow(void)\n{   typedef valvector::scalar_type scalar_type;\n    //\n    // ok\n    bool ok = true;\n    //\n    // eps99\n    scalar_type eps99 = CppAD::numeric_limits<scalar_type>::epsilon();\n    eps99            *= scalar_type(99);\n    //\n    // x, y, z\n    valvector x = valvector( {2, 3, 4} );\n    valvector y = valvector( {4, 3, 2} );;\n    valvector z = CppAD::pow(x, y);\n    //\n    // ok\n    ok &= x.size() == 3;\n    for(size_t i = 0; i < x.size(); ++i)\n    {   scalar_type check = pow( x[i], y[i] );\n        ok &= CppAD::NearEqual( z[i], check, eps99, eps99);\n    }\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/valvector/resize.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2024 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin valvector_resize.cpp}\n\nExample and Test of valvector Resize\n####################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end valvector_resize.cpp}\n-------------------------------------------------------------------------------\n*/\n// BEGIN C++\n# include <cppad/example/valvector/class.hpp>\n//\nbool resize(void)\n{   // scalar_type\n    typedef valvector::scalar_type scalar_type;\n    //\n    //\n    // ok\n    bool ok = true;\n    //\n    // v, ok\n    valvector v;\n    ok &= v.size() == 1;\n    //\n    // v\n    v.resize(3);\n    for(size_t i = 0; i < v.size(); ++i)\n        v[i] = scalar_type(i);\n    //\n    // ok\n    ok &= v.size() == 3;\n    for(size_t i = 0; i < v.size(); ++i)\n        ok &= v[i] == scalar_type(i);\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/valvector/size.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2024 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin valvector_size.cpp}\n\nExample and Test of valvector Size\n##################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end valvector_size.cpp}\n-------------------------------------------------------------------------------\n*/\n// BEGIN C++\n# include <cppad/example/valvector/class.hpp>\n//\nbool size(void)\n{   // scalar_type\n    typedef valvector::scalar_type scalar_type;\n    //\n    //\n    // ok\n    bool ok = true;\n    //\n    // v, ok\n    valvector v(3);\n    ok &= v.size() == 1;\n    for(size_t i = 0; i < 10; ++i)\n        ok &= v[i] == scalar_type(3);\n    //\n    // v\n    v.resize(3);\n    //\n    // ok\n    ok &= v.size() == 3;\n    for(size_t i = 0; i < v.size(); ++i)\n        v[i] = scalar_type(i);\n    for(size_t i = 0; i < v.size(); ++i)\n        ok &= v[i] == scalar_type(i);\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/valvector/sum.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2024 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin valvector_sum.cpp}\n\nExample and Test of valvector Size\n##################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end valvector_sum.cpp}\n-------------------------------------------------------------------------------\n*/\n// BEGIN C++\n# include <cppad/example/valvector/class.hpp>\n//\nbool sum(void)\n{   // scalar_type\n    typedef valvector::scalar_type scalar_type;\n    //\n    //\n    // ok\n    bool ok = true;\n    //\n    // v\n    valvector v( {1.0, 2.0, 3.0} );\n    //\n    // ok\n    scalar_type sum = v.sum();\n    ok &= sum == scalar_type(6.0);\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/valvector/unary_math.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2024 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin valvector_unary_math.cpp}\n\nExample and Test of valvector Unary Math Functions\n##################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end valvector_unary_math.cpp}\n-------------------------------------------------------------------------------\n*/\n// BEGIN C++\n# include <sstream>\n# include <string>\n# include <cppad/example/valvector/class.hpp>\n# include <cppad/utility/near_equal.hpp>\n//\nbool math_unary(void)\n{   typedef valvector::scalar_type scalar_type;\n    //\n    // ok\n    bool ok = true;\n    //\n    // eps99\n    scalar_type eps99 = CppAD::numeric_limits<scalar_type>::epsilon();\n    eps99            *= scalar_type(99);\n    //\n    // u, v, ok\n    valvector u = valvector( {2, 3, 4} );\n    valvector v;\n    ok &= u.size() == 3;\n    //\n    // ok\n    v   = CppAD::sqrt(u);\n    for(size_t i = 0; i < u.size(); ++i)\n        ok &= CppAD::NearEqual( v[i], sqrt(u[i]), eps99, eps99);\n\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/valvector/unary_op.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2024 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin valvector_unary_op.cpp}\n\nExample and Test of valvector Unary Operators\n#############################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end valvector_unary_op.cpp}\n-------------------------------------------------------------------------------\n*/\n// BEGIN C++\n# include <cppad/example/valvector/class.hpp>\n//\nbool unary_op(void)\n{   //\n    // ok\n    bool ok = true;\n    //\n    // v\n    valvector v( {-1, +1} );\n    //\n    // ok\n    valvector w = +v;\n    for(size_t i = 0; i < v.size(); ++i)\n        ok &= w[i] == v[i];\n    //\n    // ok\n    valvector u = -v;\n    for(size_t i = 0; i < v.size(); ++i)\n        ok &= u[i] == - v[i];\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "example/valvector/valvector.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2024 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin valvector.cpp}\n\nvalvector Examples and Tests Driver\n###################################\n\nRunning These Tests\n*******************\nAfter executing the :ref:`cmake-name` command\nform the :ref:`download@Distribution Directory`,\nyou can build and run these tests with the commands::\n\n    cd build\n    make check_example_valvector\n\nNote that your choice of :ref:`cmake@generator` may require using\nan different version of make; e.g., ``ninja`` .\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end valvector.cpp}\n-------------------------------------------------------------------------------\n*/\n// BEGIN C++\n\n// CPPAD_HAS_* defines\n# include <cppad/configure.hpp>\n\n// system include files used for I/O\n# include <iostream>\n\n// for thread_alloc\n# include <cppad/utility/thread_alloc.hpp>\n\n// test runner\n# include <cppad/utility/test_boolofvoid.hpp>\n\n// BEGIN_SORT_THIS_LINE_PLUS_1\nextern bool ad_join(void);\nextern bool ad_split(void);\nextern bool ad_sum(void);\nextern bool assign(void);\nextern bool azmul(void);\nextern bool base_require(void);\nextern bool binary_op(void);\nextern bool compare_op(void);\nextern bool compound_op(void);\nextern bool condexp(void);\nextern bool ctor(void);\nextern bool element(void);\nextern bool get_started(void);\nextern bool llsq_obj(void);\nextern bool math_unary(void);\nextern bool output(void);\nextern bool pow(void);\nextern bool resize(void);\nextern bool size(void);\nextern bool sum(void);\nextern bool unary_op(void);\n// END_SORT_THIS_LINE_MINUS_1\n\n// main program that runs all the tests\nint main(void)\n{   bool ok = true;\n    //\n    std::string group = \"example/valvector\";\n    size_t      width = 20;\n    CppAD::test_boolofvoid Run(group, width);\n\n    // This line is used by test_one.sh\n\n    // BEGIN_SORT_THIS_LINE_PLUS_1\n    Run( ad_join,             \"ad_join\"               );\n    Run( ad_split,            \"ad_split\"              );\n    Run( ad_sum,              \"ad_sum\"                );\n    Run( assign,              \"assign\"                );\n    Run( azmul,               \"azmul\"                 );\n    Run( base_require,        \"base_require\"          );\n    Run( binary_op,           \"binary_op\"             );\n    Run( compare_op,         \"compare_op\"             );\n    Run( compound_op,         \"compound_op\"           );\n    Run( condexp,             \"condexp\"               );\n    Run( ctor,                \"ctor\"                  );\n    Run( element,             \"element\"               );\n    Run( get_started,         \"get_started\"           );\n    Run( llsq_obj,            \"llsq_obj\"              );\n    Run( math_unary,          \"math_unary\"            );\n    Run( output,              \"output\"                );\n    Run( pow,                 \"pow\"                   );\n    Run( resize,              \"resize\"                );\n    Run( size,                \"size\"                  );\n    Run( sum,                 \"sum\"                   );\n    Run( unary_op,            \"unary_op\"              );\n    // END_SORT_THIS_LINE_MINUS_1\n\n    // check for memory leak\n    bool memory_ok = CppAD::thread_alloc::free_all();\n    // print summary at end\n    ok = Run.summary(memory_ok);\n    //\n    return static_cast<int>( ! ok );\n}\n// END C++\n"
  },
  {
    "path": "include/cppad/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# Configure the CppAD include file directory\n# -----------------------------------------------------------------------------\n# check_match\nMACRO(check_match match_variable match_constant output_variable)\n    STRING(COMPARE EQUAL ${${match_variable}} ${match_constant} match_flag )\n    IF( match_flag )\n        SET(${output_variable} 1)\n    ELSE( match_flag )\n        SET(${output_variable} 0)\n    ENDIF( match_flag )\n    print_variable(${output_variable})\nENDMACRO(check_match)\n# -----------------------------------------------------------------------------\n# CMAKE_REQUIRED_name\nSET(CMAKE_REQUIRED_DEFINITIONS \"\")\nSET(CMAKE_REQUIRED_FLAGS       \"\")\nSET(CMAKE_REQUIRED_INCLUDES    \"\")\nSET(CMAKE_REQUIRED_LIBRARIES   \"\")\n# -----------------------------------------------------------------------------\n#\n# cppad_c_compiler_cmd\n# is the command used to run the C compiler.\nSTRING(REGEX REPLACE \".*[/\\]\" \"\" cppad_c_compiler_cmd \"${CMAKE_C_COMPILER}\")\nprint_variable(cppad_c_compiler_cmd)\n#\n# c_compiler_msvc_clang\nSTRING(REGEX MATCH \".*[/\\]clang-cl.exe\" match \"${CMAKE_C_COMPILER}\" )\nIF( \"${match}\" STREQUAL \"${CMAKE_C_COMPILER}\"  )\n    SET(c_compiler_msvc_clang 1)\nELSE( )\n    SET(c_compiler_msvc_clang 0)\nENDIF( )\nprint_variable(c_compiler_msvc_clang)\n#\n# cmake_compiler_id_lower\nSTRING(TOLOWER \"${CMAKE_C_COMPILER_ID}\" cmake_compiler_id_lower)\n#\n# cppad_c_compiler_msvc_flags\nSTRING(FIND \"${cmake_compiler_id_lower}\" msvc index)\nIF( NOT \"${index}\" EQUAL \"-1\" )\n    SET(cppad_c_compiler_msvc_flags 1)\nELSEIF( ${c_compiler_msvc_clang} )\n    SET(cppad_c_compiler_msvc_flags 1)\n    #\n    STRING(FIND \"${cmake_compiler_id_lower}\" clang index)\n    IF( \"${index}\" EQUAL \"-1\" )\n        MESSAGE(FATAL_ERROR\n            \"Looks like MSVC compatible clang-cl.ext C compiler but\"\n            \"CMAKE_C_COMPILER_ID = ${CMAKE_C_COMPILER_ID}\"\n        )\n    ENDIF( )\nELSE( )\n    SET(cppad_c_compiler_msvc_flags 0)\nENDIF( )\nprint_variable( cppad_c_compiler_msvc_flags )\n#\n# cppad_c_compiler_gnu_flags\nIF( ${c_compiler_msvc_clang} )\n    SET(cppad_c_compiler_gnu_flags 0)\nELSE( )\n    STRING(FIND \"${cmake_compiler_id_lower}\" clang clang_index)\n    STRING(FIND \"${cmake_compiler_id_lower}\" gnu    gnu_index)\n    IF( \"${clang_index}\" EQUAL \"-1\"  AND \"${gnu_index}\" EQUAL \"-1\" )\n        SET(cppad_c_compiler_gnu_flags 0)\n    ELSE( )\n        SET(cppad_c_compiler_gnu_flags 1)\n    ENDIF( )\nENDIF( )\nprint_variable( cppad_c_compiler_gnu_flags )\n# -----------------------------------------------------------------------------\n# compiler_has_conversion_warn\nSET( clang_or_gnu 0 )\nIF( \"${CMAKE_CXX_COMPILER_ID}\" STREQUAL \"Clang\" )\n    SET(clang_or_gnu 1)\nENDIF( \"${CMAKE_CXX_COMPILER_ID}\" STREQUAL \"Clang\" )\nIF( \"${CMAKE_CXX_COMPILER_ID}\" STREQUAL \"GNU\" )\n    SET(clang_or_gnu 1)\nENDIF( \"${CMAKE_CXX_COMPILER_ID}\" STREQUAL \"GNU\" )\nIF( clang_or_gnu )\n    SET(CMAKE_REQUIRED_FLAGS\n        \"${cppad_cxx_flags} -Wfloat-conversion -Wconversion -Werror\"\n    )\n    #\n    SET(source \"int main(void) { return 0; }\")\n    compile_source_test(\n        ${cmake_defined_ok} \"${source}\" compiler_has_conversion_warn\n    )\n    #\n    SET(CMAKE_REQUIRED_FLAGS \"\")\nELSE( clang_or_gnu )\n    SET( compiler_has_conversion_warn 0 )\nENDIF( clang_or_gnu )\n# -----------------------------------------------------------------------------\n# cppad_boostvector, cppad_cppadvector, cppad_eigenvector, cppad_stdvector\n#\ncheck_match(cppad_testvector boost cppad_boostvector)\ncheck_match(cppad_testvector cppad cppad_cppadvector)\ncheck_match(cppad_testvector eigen cppad_eigenvector)\ncheck_match(cppad_testvector std   cppad_stdvector)\nIF( NOT cppad_boostvector )\nIF( NOT cppad_cppadvector )\nIF( NOT cppad_eigenvector )\nIF( NOT cppad_stdvector )\nMESSAGE(FATAL_ERROR\n\"cppad_testvector not one of following: boost, cppad, eigen, std.\"\n\"This should have been found earlier, please report this as a bug.\"\n)\nENDIF( NOT cppad_stdvector )\nENDIF( NOT cppad_eigenvector )\nENDIF( NOT cppad_cppadvector )\nENDIF( NOT cppad_boostvector )\n#\nIF( cppad_boostvector )\n    # FIND_PACKAGE(Boost) done by ../CMakeLists.txt\n    IF( NOT Boost_FOUND )\n        MESSAGE(FATAL_ERROR\n\"cppad_testvector == boost but cannot find boost include files\"\n        )\n    ENDIF( NOT Boost_FOUND )\nENDIF( cppad_boostvector )\n#\nIF( cppad_eigenvector )\n    IF( NOT cppad_has_eigen )\n        MESSAGE(FATAL_ERROR\n\"cppad_testvector == eigen but Eigen was not found or c++14 not supported\"\n        )\n    ENDIF( NOT cppad_has_eigen )\nENDIF( cppad_eigenvector )\n# -----------------------------------------------------------------------------\n# cppad_has_gettimeofday\n#\nSET(source \"\n# include<sys/time.h>\nint main(void)\n{   struct timeval time;\n    gettimeofday(&time, 0);\n    return 0;\n}\"\n)\ncompile_source_test(${cmake_defined_ok} \"${source}\" cppad_has_gettimeofday)\n# -----------------------------------------------------------------------------\n# Warn user if the following types are signed:\n#  cppad_tape_addr_type, cppad_tape_id_type\nFOREACH(cmake_var cppad_tape_id_type cppad_tape_addr_type )\n    SET(source \"\n# include <limits>\n# include <cstddef>\nint main(void)\n{   static_assert(\n        ! std::numeric_limits<${${cmake_var}}>::is_signed ,\n        \\\"${cmake_var} is a signed type\\\"\n    );\n    return 0;\n}\n\"\n    )\n    compile_source_test(\n        ${cmake_defined_ok} \"${source}\" ${cmake_var}_is_unsigned\n    )\n    IF( NOT ${${cmake_var}_is_unsigned} )\n        MESSAGE(STATUS\n\"Warning: using a signed type for ${cmake_var} is for CppAD developers only !\"\n        )\n    ENDIF( NOT ${${cmake_var}_is_unsigned} )\nENDFOREACH( cmake_var )\n# -----------------------------------------------------------------------------\n# cppad_has_mkstemp\n#\nSET(source \"\n# include <stdlib.h>\n# if _MSC_VER\n# include <io.h>\n# else\n# include <unistd.h>\n# endif\n\nint main(void)\n{\n    char pattern[] = \\\"/tmp/fileXXXXXX\\\";\n    int fd = mkstemp(pattern);\n    return 0;\n}\n\" )\ncompile_source_test(${cmake_defined_ok} \"${source}\" cppad_has_mkstemp )\n# -----------------------------------------------------------------------------\n# cppad_has_tmpname_s\n#\nSET(source \"\n# include <stdio.h>\nint main(void)\n{   char filename[L_tmpnam_s ];\n    if( tmpnam_s(filename, L_tmpnam_s ) != 0 )\n        return 1;\n    return 0;\n}\n\" )\ncompile_source_test(${cmake_defined_ok} \"${source}\" cppad_has_tmpnam_s )\n# -----------------------------------------------------------------------------\n# cppad_is_same_unsigned_int_size_t\n#\nSET(source \"\n# include <cstddef>\n# include <type_traits>\nint main(void)\n{   static_assert(\n        std::is_same<unsigned int, size_t>::value ,\n        \\\"message not needed with C++17 or later\\\"\n    );\n    return 0;\n}\n\" )\ncompile_source_test(\n    ${cmake_defined_ok} \"${source}\" cppad_is_same_unsigned_int_size_t\n)\n# -----------------------------------------------------------------------------\n# cppad_is_same_tape_addr_type_size_t\n#\nSET(source \"\n# include <cstddef>\n# include <type_traits>\nint main(void)\n{   static_assert(\n        std::is_same<${cppad_tape_addr_type}, size_t>::value ,\n        \\\"message not needed with C++17 or later\\\"\n    );\n    return 0;\n}\n\" )\ncompile_source_test(\n    ${cmake_defined_ok} \"${source}\" cppad_is_same_tape_addr_type_size_t\n)\n# -----------------------------------------------------------------------------\n# cppad_padding_block_t\n#\n# See block_t in include/cppad/utility/thread_alloc.hpp before changing this.\nSET(source \"\n# include <cstddef>\nint main(void)\n{   class block_t {\n        size_t extra_; size_t tc_index_; void* next_;\n    };\n    static_assert(\n        sizeof(block_t) % sizeof(double) == 0 ,\n        \\\"message not needed with C++17 or later\\\"\n    );\n    return 0;\n}\n\" )\ncompile_source_test(\n    ${cmake_defined_ok} \"${source}\" first_block_t_mod_double_zero\n)\nIF( ${first_block_t_mod_double_zero} )\n    SET(cppad_padding_block_t \"\")\nELSE()\n    SET(cppad_padding_block_t \"void* note_used_;\")\nENDIF()\nSET(source \"\n# include <cstddef>\nint main(void)\n{   class block_t {\n        size_t extra_; size_t tc_index_; void* next_; ${cppad_padding_block_t}\n    };\n    static_assert(\n        sizeof(block_t) % sizeof(double) == 0 ,\n        \\\"message not needed with C++17 or later\\\"\n    );\n    return 0;\n}\n\" )\ncompile_source_test(\n    ${cmake_defined_ok} \"${source}\" second_block_t_mod_double_zero\n)\nassert( second_block_t_mod_double_zero )\n# -----------------------------------------------------------------------------\n# configure.hpp\nCONFIGURE_FILE(\n    ${CMAKE_CURRENT_SOURCE_DIR}/configure.hpp.in\n    ${CMAKE_CURRENT_SOURCE_DIR}/configure.hpp\n)\n# -----------------------------------------------------------------------------\n"
  },
  {
    "path": "include/cppad/base_require.hpp",
    "content": "# ifndef CPPAD_BASE_REQUIRE_HPP\n# define CPPAD_BASE_REQUIRE_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin base_require}\n{xrst_spell\n    ostream\n}\n\nAD<Base> Requirements for a CppAD Base Type\n###########################################\n\nSyntax\n******\n| ``# include <cppad/base_require.hpp>``\n\nPurpose\n*******\nThis section lists the requirements for the type\n*Base* so that the type ``AD`` < *Base* > can be used.\n\nAPI Warning\n***********\nDefining a CppAD *Base* type is an advanced use of CppAD.\nThis part of the CppAD API changes with time. The most common change\nis adding more requirements.\nSearch for ``base_require`` in the\ncurrent :ref:`whats_new-name` section for these changes.\n\nStandard Base Types\n*******************\nIn the case where *Base* is\n``float`` ,\n``double`` ,\n``std::complex<float>`` ,\n``std::complex<double>`` ,\nor ``AD`` < *Other* > ,\nthese requirements are provided by including the file\n``cppad/cppad.hpp`` .\nIn the documentation, The notation :math:`\\B{R}` denotes\nthe field corresponding to the base type.\nMultiplication must be commutative for this field,\nbut it need not be the reals; e.g., the complex numbers.\n\nInclude Order\n*************\nIf you are linking a non-standard base type to CppAD,\nyou must first include the file ``cppad/base_require.hpp`` ,\nthen provide the specifications below,\nand then include the file ``cppad/cppad.hpp`` .\n\nNumeric Type\n************\nThe type *Base* must support all the operations for a\n:ref:`NumericType-name` .\n\nOutput Operator\n***************\nThe type *Base* must support the syntax\n\n    *os* << *x*\n\nwhere *os* is an ``std::ostream&``\nand *x* is a ``const base_alloc&`` .\nFor example, see\n:ref:`base_alloc<base_alloc.hpp@Output Operator>` .\n\nInteger\n*******\nThe type *Base* must support the syntax\n\n    *i* = ``CppAD::Integer`` ( *x* )\n\nwhich converts *x* to an ``int`` .\nThe argument *x* has prototype\n\n    ``const`` *Base* & *x*\n\nand the return value *i* has prototype\n\n    ``int`` *i*\n\nSuggestion\n==========\nIn many cases, the *Base* version of the ``Integer`` function\ncan be defined by\n\n| ``namespace CppAD`` {\n| |tab| ``inline int Integer`` ( ``const`` *Base* & ``x`` )\n| |tab| { ``return static_cast<int>`` ( ``x`` ); }\n| }\n\nFor example, see\n:ref:`base_float<base_float.hpp@Integer>` and\n:ref:`base_alloc<base_alloc.hpp@Integer>` .\n\nAbsolute Zero, azmul\n********************\nThe type *Base* must support the syntax\n\n    *z* = ``azmul`` ( *x* , *y* )\n\nsee; :ref:`azmul-name` .\nThe following preprocessor macro invocation suffices\n(for most *Base* types):\n\n| ``namespace CppAD`` {\n| |tab| ``CPPAD_AZMUL`` ( *Base* )\n| }\n\nwhere the macro is defined by\n{xrst_spell_off}\n{xrst_code cpp} */\n# define CPPAD_AZMUL(Base) \\\n    inline Base azmul(const Base& x, const Base& y) \\\n    {  Base zero(0.0);   \\\n        if( x == zero ) \\\n            return zero;  \\\n        return x * y;     \\\n    }\n/* {xrst_code}\n{xrst_spell_on}\n\nContents\n********\n{xrst_toc_table\n    xrst/base_require/base_member.xrst\n    include/cppad/core/base_cond_exp.hpp\n    xrst/base_require/base_identical.xrst\n    xrst/base_require/base_ordered.xrst\n    include/cppad/core/base_std_math.hpp\n    include/cppad/core/base_limits.hpp\n    include/cppad/core/base_to_string.hpp\n    include/cppad/core/base_hash.hpp\n    xrst/base_require/base_example.xrst\n}\n\n{xrst_end base_require}\n*/\n\n// definitions that must come before base implementations\n# include <cppad/utility/error_handler.hpp>\n# include <cppad/local/define.hpp>\n# include <cppad/core/cppad_assert.hpp>\n# include <cppad/local/declare_ad.hpp>\n\n// grouping documentation by feature\n# include <cppad/core/base_cond_exp.hpp>\n# include <cppad/core/base_std_math.hpp>\n# include <cppad/core/base_limits.hpp>\n# include <cppad/core/base_to_string.hpp>\n# include <cppad/core/base_hash.hpp>\n\n// must define template class numeric_limits before the base cases\n# include <cppad/core/numeric_limits.hpp>\n# include <cppad/core/epsilon.hpp> // deprecated\n\n// base cases that come with CppAD\n# include <cppad/core/base_float.hpp>\n# include <cppad/core/base_double.hpp>\n# include <cppad/core/base_complex.hpp>\n\n// deprecated base type\n# include <cppad/core/zdouble.hpp>\n\n# endif\n"
  },
  {
    "path": "include/cppad/configure.hpp.in",
    "content": "# ifndef CPPAD_CONFIGURE_HPP\n# define CPPAD_CONFIGURE_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*!\n{xrst_begin configure.hpp dev}\n{xrst_spell\n    adolc\n    cmd\n    colpack\n    gettimeofday\n    ipopt\n    mkstemp\n    noexcept\n    nullptr\n    pragmas\n    tmpnam\n    unreferenced\n    yyyy\n    yyyymmdd\n}\n\nPreprocessor Symbols Set By CMake Command\n#########################################\n\nCPPAD_LINK_FLAGS_HAS_M32\n************************\nis -m32 in the :ref:`cmake@cppad_link_flags` .\n{xrst_code hpp} */\n# define CPPAD_LINK_FLAGS_HAS_M32 @cppad_link_flags_has_m32@\n/* {xrst_code}\n\nCPPAD_COMPILER_HAS_CONVERSION_WARN\n**********************************\nis the compiler a variant of g++ and has conversion warnings\n{xrst_spell_off}\n{xrst_code hpp} */\n# define CPPAD_COMPILER_HAS_CONVERSION_WARN @compiler_has_conversion_warn@\n/* {xrst_code}\n{xrst_spell_on}\n\nCPPAD_DISABLE_SOME_MICROSOFT_COMPILER_WARNINGS\n**********************************************\nThis macro is only used to document the pragmas that disables the\nfollow warnings:\n\nC4100\n=====\nunreferenced formal parameter.\n\nC4127\n=====\nconditional expression is constant.\n\nC4723\n=====\nThe second operand in a divide operation evaluated to zero at compile time.\n\n{xrst_spell_off}\n{xrst_code hpp} */\n# define CPPAD_DISABLE_SOME_MICROSOFT_COMPILER_WARNINGS 1\n# if _MSC_VER\n# pragma warning( disable : 4100 )\n# pragma warning( disable : 4127 )\n# pragma warning( disable : 4723 )\n# endif\n# undef CPPAD_DISABLE_SOME_MICROSOFT_COMPILER_WARNINGS\n/* {xrst_code}\n{xrst_spell_on}\n\nCPPAD_DEBUG_AND_RELEASE\n***********************\nStarting with 2023-12-24,\nthis flag is set by the cmake command; see\n:ref:`cmake@cppad_debug_and_release` .\nBefore then, one would add -D CPPAD_DEBUG_AND_RELEASE\nwhen compiling CppAD code.\n{xrst_code hpp} */\n# define CPPAD_DEBUG_AND_RELEASE @cppad_debug_and_release_01@\n/* {xrst_code}\n\nCPPAD_USE_CPLUSPLUS_2011\n************************\nDeprecated 2020-12-03:\nIs it OK to use C++11 features. This is always 1 (for true).\n{xrst_spell_off}\n{xrst_code hpp} */\n# define CPPAD_USE_CPLUSPLUS_2011 1\n/* {xrst_code}\n{xrst_spell_on}\n\nCPPAD_USE_CPLUSPLUS_2017\n************************\nDeprecated 2020-12-03:\nIs it OK for CppAD use C++17 features.\n{xrst_spell_off}\n{xrst_code hpp} */\n# define CPPAD_USE_CPLUSPLUS_2017 @use_cplusplus_2017_ok@\n/* {xrst_code}\n{xrst_spell_on}\n\nCPPAD_PACKAGE_STRING\n********************\ncppad-yyyymmdd as a C string where yyyy is year, mm is month, and dd is day.\n{xrst_spell_off}\n{xrst_code hpp} */\n# define CPPAD_PACKAGE_STRING \"cppad-@cppad_version@\"\n/* {xrst_code}\n{xrst_spell_on}\n\nCPPAD_HAS_ADOLC\n***************\nWas include_adolc=true on the cmake command line.\n{xrst_spell_off}\n{xrst_code hpp} */\n# define CPPAD_HAS_ADOLC @cppad_has_adolc@\n/* {xrst_code}\n{xrst_spell_on}\n\nCPPAD_HAS_COLPACK\n*****************\nWas a colpack_prefix specified on the cmake command line.\n{xrst_spell_off}\n{xrst_code hpp} */\n# define CPPAD_HAS_COLPACK @cppad_has_colpack@\n/* {xrst_code}\n{xrst_spell_on}\n\nCPPAD_HAS_EIGEN\n***************\nWas Eigen found and c++14 is supported.\n{xrst_spell_off}\n{xrst_code hpp} */\n# define CPPAD_HAS_EIGEN @cppad_has_eigen@\n/* {xrst_code}\n{xrst_spell_on}\n\nCPPAD_HAS_IPOPT\n***************\nWas include_ipopt=true on the cmake command line.\n{xrst_spell_off}\n{xrst_code hpp} */\n# define CPPAD_HAS_IPOPT @cppad_has_ipopt@\n/* {xrst_code}\n{xrst_spell_on}\n\nCPPAD_DEPRECATED\n****************\nThis symbol is not currently being used.\n{xrst_spell_off}\n{xrst_code hpp} */\n# define CPPAD_DEPRECATED @cppad_deprecated_01@\n/* {xrst_code}\n{xrst_spell_on}\n\nCPPAD_BOOSTVECTOR\n*****************\nIf this symbol is one, and _MSC_VER is not defined,\nwe are using boost vector for CPPAD_TESTVECTOR.\nIt this symbol is zero,\nwe are not using boost vector for CPPAD_TESTVECTOR.\n{xrst_spell_off}\n{xrst_code hpp} */\n# define CPPAD_BOOSTVECTOR @cppad_boostvector@\n/* {xrst_code}\n{xrst_spell_on}\n\nCPPAD_CPPADVECTOR\n*****************\nIf this symbol is one,\nwe are using CppAD vector for CPPAD_TESTVECTOR.\nIt this symbol is zero,\nwe are not using CppAD vector for CPPAD_TESTVECTOR.\n{xrst_spell_off}\n{xrst_code hpp} */\n# define CPPAD_CPPADVECTOR @cppad_cppadvector@\n/* {xrst_code}\n{xrst_spell_on}\n\nCPPAD_STDVECTOR\n***************\nIf this symbol is one,\nwe are using standard vector for CPPAD_TESTVECTOR.\nIt this symbol is zero,\nwe are not using standard vector for CPPAD_TESTVECTOR.\n{xrst_spell_off}\n{xrst_code hpp} */\n# define CPPAD_STDVECTOR @cppad_stdvector@\n/* {xrst_code}\n{xrst_spell_on}\n\nCPPAD_EIGENVECTOR\n*****************\nIf this symbol is one,\nwe are using Eigen vector for CPPAD_TESTVECTOR.\nIf this symbol is zero,\nwe are not using Eigen vector for CPPAD_TESTVECTOR.\n{xrst_spell_off}\n{xrst_code hpp} */\n# define CPPAD_EIGENVECTOR @cppad_eigenvector@\n/* {xrst_code}\n{xrst_spell_on}\n\nCPPAD_HAS_GETTIMEOFDAY\n**********************\nIf this symbol is one, and _MSC_VER is not defined,\nthis system supports the gettimeofday function.\nOtherwise, this symbol should be zero.\n{xrst_spell_off}\n{xrst_code hpp} */\n# define CPPAD_HAS_GETTIMEOFDAY @cppad_has_gettimeofday@\n/* {xrst_code}\n{xrst_spell_on}\n\nCPPAD_TAPE_ADDR_TYPE\n********************\nIs the type used to store address on the tape.\nIf it is not size_t, then\n{xrst_code cpp}\n    sizeof(CPPAD_TAPE_ADDR_TYPE) < sizeof( size_t )\n{xrst_code}\ncan be used to conserve memory.\nThis type must support std::numeric_limits,\nthe <= operator,\nand conversion to size_t.\nMake sure that the type chosen returns true for is_pod<CPPAD_TAPE_ADDR_TYPE>\nin pod_vector.hpp.\nThis type is later defined as addr_t in the CppAD namespace.\n{xrst_spell_off}\n{xrst_code hpp} */\n# define CPPAD_TAPE_ADDR_TYPE @cppad_tape_addr_type@\n/* {xrst_code}\n{xrst_spell_on}\n\nCPPAD_IS_SAME_TAPE_ADDR_TYPE_SIZE_T\n***********************************\nIs size_t the type the same as CPPAD_TAPE_ADDR_TYPE.\n{xrst_spell_off}\n{xrst_code hpp} */\n# define CPPAD_IS_SAME_TAPE_ADDR_TYPE_SIZE_T \\\n    @cppad_is_same_tape_addr_type_size_t@\n/* {xrst_code}\n{xrst_spell_off}\n\n\nCPPAD_TAPE_ID_TYPE\n******************\nIs the type used to store tape identifiers.\nIf it is not size_t, then\n{xrst_code cpp}\n    sizeof(CPPAD_TAPE_ID_TYPE) < sizeof( size_t )\n{xrst_code}\ncan be used to conserve memory.\nThis type must support std::numeric_limits,\nthe <= operator,\nand conversion to size_t.\nMake sure that the type chosen returns true for is_pod<CPPAD_TAPE_ID_TYPE>\nin pod_vector.hpp.\nThis type is later defined as tape_id_t in the CppAD namespace.\n{xrst_spell_off}\n{xrst_code hpp} */\n# define CPPAD_TAPE_ID_TYPE @cppad_tape_id_type@\n/* {xrst_code}\n{xrst_spell_on}\n\nCPPAD_MAX_NUM_THREADS\n*********************\nSpecifies the maximum number of threads that CppAD can support\n(must be greater than or equal four).\n\nThe user may define CPPAD_MAX_NUM_THREADS before including any of the CppAD\nheader files.  If it is not yet defined,\n{xrst_spell_off}\n{xrst_code hpp} */\n# ifndef CPPAD_MAX_NUM_THREADS\n# define CPPAD_MAX_NUM_THREADS @cppad_max_num_threads@\n# endif\n/* {xrst_code}\n{xrst_spell_on}\n\nCPPAD_HAS_MKSTEMP\n*****************\nif true, mkstemp works in C++ on this system.\n{xrst_spell_off}\n{xrst_code hpp} */\n# define CPPAD_HAS_MKSTEMP @cppad_has_mkstemp@\n/* {xrst_code}\n{xrst_spell_on}\n\nCPPAD_HAS_TMPNAM_S\n******************\nIf true, tmpnam_s works in C++ on this system.\n{xrst_spell_off}\n{xrst_code hpp} */\n# define CPPAD_HAS_TMPNAM_S @cppad_has_tmpnam_s@\n/* {xrst_code}\n{xrst_spell_on}\n\nCPPAD_NULL\n**********\nDeprecated 2020-12-03:\nThis preprocessor symbol was used for a null pointer before c++11.\nReplace it by ``nullptr`` .\n\nCPPAD_NOEXCEPT\n**************\nDeprecated 2020-12-03:\nThis preprocessor symbol was used for no exception before c++11,\nreplace it by ``noexcept`` .\n\nCPPAD_NDEBUG_NOEXCEPT\n=====================\nThis preprocessor symbol is\n``noexcept`` when ``NDEBUG`` is defined.\nOtherwise it is empty.\n\nCPPAD_C_COMPILER_CMD\n********************\nThis is the command that runs the C compiler as a C string;\ni.e., surrounded by double quotes.\nIt can be used to run the C compiler; e.g. see for :ref:`create_dll_lib-name` .\n{xrst_code hpp} */\n# define CPPAD_C_COMPILER_CMD \"@cppad_c_compiler_cmd@\"\n/* {xrst_code}\n\nCPPAD_C_COMPILER_GNU_FLAGS\n**************************\nIf true, the C compiler uses the same flags as ``gcc``\n{xrst_spell_off}\n{xrst_code hpp} */\n# define CPPAD_C_COMPILER_GNU_FLAGS @cppad_c_compiler_gnu_flags@\n/* {xrst_code}\n{xrst_spell_on}\n\nCPPAD_C_COMPILER_MSVC_FLAGS\n***************************\nIf true, the C compiler uses the same flags as ``cl``\n{xrst_spell_off}\n{xrst_code hpp} */\n# define CPPAD_C_COMPILER_MSVC_FLAGS @cppad_c_compiler_msvc_flags@\n/* {xrst_code}\n{xrst_spell_on}\n\nCPPAD_IS_SAME_UNSIGNED_INT_SIZE_T\n*********************************\nIf true, ``unsigned int`` and ``size_t`` are the same type\n{xrst_code hpp} */\n# define CPPAD_IS_SAME_UNSIGNED_INT_SIZE_T @cppad_is_same_unsigned_int_size_t@\n/* {xrst_code}\n\nCPPAD_PADDING_BLOCK_T\n*********************\nIs a string used to define an object that pads the block_t structure\nso that its size is a multiple of the size of a double.\n{xrst_code hpp} */\n# define CPPAD_PADDING_BLOCK_T @cppad_padding_block_t@\n/* {xrst_code}\n\n{xrst_end configure.hpp}\n*/\n// -------------------------------------------------\n# define CPPAD_NULL                nullptr\n# define CPPAD_NOEXCEPT            noexcept\n//\n# ifdef NDEBUG\n# define CPPAD_NDEBUG_NOEXCEPT     noexcept\n# else\n# define CPPAD_NDEBUG_NOEXCEPT\n# endif\n// -------------------------------------------------\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/abort_recording.hpp",
    "content": "# ifndef CPPAD_CORE_ABORT_RECORDING_HPP\n# define CPPAD_CORE_ABORT_RECORDING_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin abort_recording}\n\nAbort Recording of an Operation Sequence\n########################################\n\nSyntax\n******\n| ``AD`` < *Base* >:: ``abort_recording`` ()\n\nPurpose\n*******\nSometimes it is necessary to abort the recording of an operation sequence\nthat started with a call of the form\n\n    ``Independent`` ( *x* )\n\nIf such a recording is currently in progress,\n``abort_recording`` will stop the recording and delete the\ncorresponding information.\nOtherwise, ``abort_recording`` has no effect.\n{xrst_toc_hidden\n    example/general/abort_recording.cpp\n}\nExample\n*******\nThe file\n:ref:`abort_recording.cpp-name`\ncontains an example and test of this operation.\n\n{xrst_end abort_recording}\n----------------------------------------------------------------------------\n*/\n\n\nnamespace CppAD {\n    template <class Base>\n    void AD<Base>::abort_recording(void)\n    {   local::ADTape<Base>* tape = AD<Base>::tape_ptr();\n        if( tape != nullptr )\n            AD<Base>::tape_manage(delete_tape_manage);\n    }\n}\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/abs.hpp",
    "content": "# ifndef CPPAD_CORE_ABS_HPP\n# define CPPAD_CORE_ABS_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n-------------------------------------------------------------------------------\n{xrst_begin abs}\n{xrst_spell\n    faq\n    rl\n}\n\nAD Absolute Value Functions: abs, fabs\n######################################\n\nSyntax\n******\n| *y* = ``abs`` ( *x* )\n| *y* = ``fabs`` ( *x* )\n\nx, y\n****\nSee the :ref:`unary_standard_math@Possible Types`\nfor a unary standard math function.\n\nAtomic\n******\nIn the case where *x* is an AD type,\nthis is an :ref:`atomic operation<glossary@Operation@Atomic>` .\n\nComplex Types\n*************\nThe functions ``abs`` and *fabs*\nare not defined for the base types\n``std::complex<float>`` or ``std::complex<double>``\nbecause the complex ``abs`` function is not complex differentiable\n(see :ref:`complex types faq<Faq@Complex Types>` ).\n\nDerivative\n**********\nCppAD defines the derivative of the ``abs`` function is\nthe :ref:`sign-name` function; i.e.,\n\n.. math::\n\n    {\\rm abs}^{(1)} ( x ) = {\\rm sign} (x ) =\n    \\left\\{ \\begin{array}{rl}\n        +1 & {\\rm if} \\; x > 0 \\\\\n        0  & {\\rm if} \\; x = 0 \\\\\n        -1 & {\\rm if} \\; x < 0\n    \\end{array} \\right.\n\nThe result for *x*  == 0 used to be a directional derivative.\n\nExample\n*******\n{xrst_toc_hidden\n    example/general/fabs.cpp\n}\nThe file\n:ref:`fabs.cpp-name`\ncontains an example and test of this function.\n\n{xrst_end abs}\n-------------------------------------------------------------------------------\n*/\n\n//  BEGIN CppAD namespace\nnamespace CppAD {\n\ntemplate <class Base>\nAD<Base> AD<Base>::abs_me (void) const\n{\n    AD<Base> result;\n    result.value_ = abs(value_);\n    CPPAD_ASSERT_UNKNOWN( Parameter(result) );\n\n    // check if there is a recording in progress\n    local::ADTape<Base>* tape = AD<Base>::tape_ptr();\n    if( tape == nullptr )\n        return result;\n\n    // check if operand is a constant parameter\n    if( tape_id_ != tape->id_ )\n        return result;\n\n    if(ad_type_ == dynamic_enum)\n    {   // dynamic parameter argument\n        result.taddr_   = tape->Rec_.put_dyn_par(\n            result.value_, local::abs_dyn, taddr_\n        );\n        result.tape_id_  = tape_id_;\n        result.ad_type_  = dynamic_enum;\n    }\n    else\n    {   // variable argument\n        CPPAD_ASSERT_UNKNOWN( local::NumRes(local::AbsOp) == 1 );\n        CPPAD_ASSERT_UNKNOWN( local::NumArg(local::AbsOp) == 1 );\n\n        // corresponding operand address\n        tape->Rec_.PutArg(taddr_);\n\n        // put operator in the tape\n        result.taddr_    = tape->Rec_.PutOp(local::AbsOp);\n\n        // make result a variable\n        result.tape_id_  = tape_id_;\n        result.ad_type_  = variable_enum;\n    }\n    return result;\n}\n\ntemplate <class Base>\nAD<Base> abs(const AD<Base> &x)\n{   return x.abs_me(); }\n\ntemplate <class Base>\nAD<Base> abs(const VecAD_reference<Base> &x)\n{   return x.ADBase().abs_me(); }\n\n} // END CppAD namespace\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/abs_normal_fun.hpp",
    "content": "# ifndef CPPAD_CORE_ABS_NORMAL_FUN_HPP\n# define CPPAD_CORE_ABS_NORMAL_FUN_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin abs_normal_fun}\n\nCreate An Abs-normal Representation of a Function\n#################################################\n\nSyntax\n******\n| *f* . ``abs_normal_fun`` ( *g* , *a* )\n\nf\n*\nThe object *f* has prototype\n\n    ``const ADFun`` < *Base* >& *f*\n\nIt represents a function :math:`f : \\B{R}^n \\rightarrow \\B{R}^m`.\nWe assume that the only non-smooth terms in the representation are\nabsolute value functions and use :math:`s \\in \\B{Z}_+`\nto represent the number of these terms.\n\nn\n=\nWe use *n* to denote the dimension of the domain space for *f* .\n\nm\n=\nWe use *m* to denote the dimension of the range space for *f* .\n\ns\n=\nWe use *s* to denote the number of absolute value terms in *f* .\n\na\n*\nThe object *a* has prototype\n\n    ``ADFun`` < *Base* > *a*\n\nThe initial function representation in *a* is lost.\nUpon return it represents the result of the absolute terms\n:math:`a : \\B{R}^n \\rightarrow \\B{R}^s`; see :math:`a(x)` defined below.\nNote that *a* is constructed by copying *f*\nand then changing the dependent variables. There may\nbe many calculations in this representation that are not necessary\nand can be removed using\n\n    *a* . ``optimize`` ()\n\nThis optimization is not done automatically by ``abs_normal_fun``\nbecause it may take a significant amount of time.\n\nzeta\n====\nLet :math:`\\zeta_0 ( x )`\ndenote the argument for the first absolute value term in :math:`f(x)`,\n:math:`\\zeta_1 ( x , |\\zeta_0 (x)| )` for the second term, and so on.\n\na(x)\n====\nFor :math:`i = 0 , \\ldots , {s-1}` define\n\n.. math::\n\n    a_i (x)\n    =\n    | \\zeta_i ( x , a_0 (x) , \\ldots , a_{i-1} (x ) ) |\n\nThis defines :math:`a : \\B{R}^n \\rightarrow \\B{R}^s`.\n\ng\n*\nThe object *g* has prototype\n\n    ``ADFun`` < *Base* > *g*\n\nThe initial function representation in *g* is lost.\nUpon return it represents the smooth function\n:math:`g : \\B{R}^{n + s} \\rightarrow  \\B{R}^{m + s}` is defined by\n\n.. math::\n\n    g( x , u )\n    =\n    \\left[ \\begin{array}{c} y(x, u) \\\\ z(x, u) \\end{array} \\right]\n\nwere :math:`y(x, u)` and :math:`z(x, u)` are defined below.\n\nz(x, u)\n=======\nDefine the smooth function\n:math:`z : \\B{R}^{n + s} \\rightarrow  \\B{R}^s` by\n\n.. math::\n\n    z_i ( x , u ) = \\zeta_i ( x , u_0 , \\ldots , u_{i-1} )\n\nNote that the partial of :math:`z_i` with respect to :math:`u_j` is zero\nfor :math:`j \\geq i`.\n\ny(x, u)\n=======\nThere is a smooth function\n:math:`y : \\B{R}^{n + s} \\rightarrow  \\B{R}^m`\nsuch that :math:`y( x , u ) = f(x)` whenever :math:`u = a(x)`.\n\nAffine Approximation\n********************\nWe define the affine approximations\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    y[ \\hat{x} ]( x , u )\n    & = &\n    y ( \\hat{x}, a( \\hat{x} ) )\n        + \\partial_x y ( \\hat{x}, a( \\hat{x} ) ) ( x - \\hat{x} )\n        + \\partial_u y ( \\hat{x}, a( \\hat{x} ) ) ( u - a( \\hat{x} ) )\n    \\\\\n    z[ \\hat{x} ]( x , u )\n    & = &\n    z ( \\hat{x}, a( \\hat{x} ) )\n        + \\partial_x z ( \\hat{x}, a( \\hat{x} ) ) ( x - \\hat{x} )\n        + \\partial_u z ( \\hat{x}, a( \\hat{x} ) ) ( u - a( \\hat{x} ) )\n    \\end{eqnarray}\n\nIt follows that\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    y( x , u )\n    & = &\n    y[ \\hat{x} ]( x , u ) + o ( x - \\hat{x}, u - a( \\hat{x} ) )\n    \\\\\n    z( x , u )\n    & = &\n    z[ \\hat{x} ]( x , u ) + o ( x - \\hat{x}, u - a( \\hat{x} ) )\n    \\end{eqnarray}\n\nAbs-normal Approximation\n************************\n\nApproximating a(x)\n==================\nThe function :math:`a(x)` is not smooth, but it is equal to\n:math:`| z(x, u) |` when :math:`u = a(x)`.\nFurthermore\n\n.. math::\n\n    z[ \\hat{x} ]( x , u )\n    =\n    z ( \\hat{x}, a( \\hat{x} ) )\n        + \\partial_x z ( \\hat{x}, a( \\hat{x} ) ) ( x - \\hat{x} )\n        + \\partial_u z ( \\hat{x}, a( \\hat{x} ) ) ( u - a( \\hat{x} ) )\n\nThe partial of :math:`z_i` with respect to :math:`u_j` is zero\nfor :math:`j \\geq i`. It follows that\n\n.. math::\n\n    z_i [ \\hat{x} ]( x , u )\n    =\n    z_i ( \\hat{x}, a( \\hat{x} ) )\n        + \\partial_x z_i ( \\hat{x}, a( \\hat{x} ) ) ( x - \\hat{x} )\n        + \\sum_{j < i} \\partial_{u(j)}\n            z_i ( \\hat{x}, a( \\hat{x} ) ) ( u_j - a_j ( \\hat{x} ) )\n\nConsidering the case :math:`i = 0` we define\n\n.. math::\n\n    a_0 [ \\hat{x} ]( x )\n    =\n    | z_0 [ \\hat{x} ]( x , u ) |\n    =\n    \\left|\n        z_0 ( \\hat{x}, a( \\hat{x} ) )\n        + \\partial_x z_0 ( \\hat{x}, a( \\hat{x} ) ) ( x - \\hat{x} )\n    \\right|\n\nIt follows that\n\n.. math::\n\n    a_0 (x) = a_0 [ \\hat{x} ]( x ) + o ( x - \\hat{x} )\n\nIn general, we define :math:`a_i [ \\hat{x} ]` using\n:math:`a_j [ \\hat{x} ]` for :math:`j < i` as follows:\n\n.. math::\n\n    a_i [ \\hat{x} ]( x )\n    =\n    \\left |\n        z_i ( \\hat{x}, a( \\hat{x} ) )\n        + \\partial_x z_i ( \\hat{x}, a( \\hat{x} ) ) ( x - \\hat{x} )\n        + \\sum_{j < i} \\partial_{u(j)}\n            z_i ( \\hat{x}, a( \\hat{x} ) )\n                ( a_j [ \\hat{x} ] ( x )  - a_j ( \\hat{x} ) )\n    \\right|\n\nIt follows that\n\n.. math::\n\n    a (x) = a[ \\hat{x} ]( x ) + o ( x - \\hat{x} )\n\nNote that in the case where :math:`z(x, u)` and :math:`y(x, u)` are\naffine,\n\n.. math::\n\n    a[ \\hat{x} ]( x ) = a( x )\n\nApproximating f(x)\n==================\n\n.. math::\n\n    f(x)\n    =\n    y ( x , a(x ) )\n    =\n    y [ \\hat{x} ] ( x , a[ \\hat{x} ] ( x ) )\n    + o( x - \\hat{x} )\n\nCorrespondence to Literature\n****************************\nUsing the notation\n:math:`Z = \\partial_x z(\\hat{x}, \\hat{u})`,\n:math:`L = \\partial_u z(\\hat{x}, \\hat{u})`,\n:math:`J = \\partial_x y(\\hat{x}, \\hat{u})`,\n:math:`Y = \\partial_u y(\\hat{x}, \\hat{u})`,\nthe approximation for :math:`z` and :math:`y` are\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    z[ \\hat{x} ]( x , u )\n    & = &\n    z ( \\hat{x}, a( \\hat{x} ) ) + Z ( x - \\hat{x} ) + L ( u - a( \\hat{x} ) )\n    \\\\\n    y[ \\hat{x} ]( x , u )\n    & = &\n    y ( \\hat{x}, a( \\hat{x} ) ) + J ( x - \\hat{x} ) + Y ( u - a( \\hat{x} ) )\n    \\end{eqnarray}\n\nMoving the terms with :math:`\\hat{x}` together, we have\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    z[ \\hat{x} ]( x , u )\n    & = &\n    z ( \\hat{x}, a( \\hat{x} ) ) - Z \\hat{x} - L a( \\hat{x} )  + Z x + L u\n    \\\\\n    y[ \\hat{x} ]( x , u )\n    & = &\n    y ( \\hat{x}, a( \\hat{x} ) ) - J \\hat{x} - Y a( \\hat{x} )  + J x + Y u\n    \\end{eqnarray}\n\nUsing the notation\n:math:`c = z ( \\hat{x}, \\hat{u} ) - Z \\hat{x} - L \\hat{u}`,\n:math:`b = y ( \\hat{x}, \\hat{u} ) - J \\hat{x} - Y \\hat{u}`,\nwe have\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    z[ \\hat{x} ]( x , u ) & = & c + Z x + L u\n    \\\\\n    y[ \\hat{x} ]( x , u ) & = & b + J x + Y u\n    \\end{eqnarray}\n\nConsidering the affine case, where the approximations are exact,\nand choosing :math:`u = a(x) = |z(x, u)|`, we obtain\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    z( x , a(x ) ) & = & c + Z x + L |z( x , a(x ) )|\n    \\\\\n    y( x , a(x ) ) & = & b + J x + Y |z( x , a(x ) )|\n    \\end{eqnarray}\n\nThis is Equation (2) of the\n:ref:`example_abs_normal@Reference` .\n{xrst_toc_hidden\n    example/abs_normal/abs_normal.xrst\n}\nExample\n*******\nThe file :ref:`abs_get_started.cpp-name` contains\nan example and test using this operation.\nThe section :ref:`example_abs_normal-name`\nhas a links to all the abs normal examples.\n\n{xrst_end abs_normal_fun}\n-------------------------------------------------------------------------------\n*/\n/*!\nfile abs_normal_fun.hpp\nCreate an abs-normal representation of a function\n*/\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\nCreate an abs-normal representation of an ADFun object.\n\n\\tparam Base\nbase type for this abs-normal form and for the function being represented;\ni.e., f.\n\n\\param f\nis the function that this object will represent in abs-normal form.\nThis is effectively const except that the play back state play_\nis used.\n*/\n\n# ifndef NDEBUG\n# define CPPAD_J_PAR_EQUAL_REC j_par = (size_t) rec\n# else\n# define CPPAD_J_PAR_EQUAL_REC rec\n# endif\n\ntemplate <class Base, class RecBase>\nvoid ADFun<Base,RecBase>::abs_normal_fun(ADFun& g, ADFun& a) const\n{   using namespace local;\n\n    // -----------------------------------------------------------------------\n    // Forward sweep to determine number of absolute value operations in f\n    // -----------------------------------------------------------------------\n    // The argument and result index in f for each absolute value operator\n    CppAD::vector<addr_t> f_abs_arg;\n    CppAD::vector<size_t> f_abs_res;\n    //\n    op_code_var   op;                 // this operator\n    const addr_t* arg = nullptr;   // arguments for this operator\n    size_t        i_var;              // variable index for this operator\n    local::play::const_sequential_iterator itr = play_.begin();\n    itr.op_info(op, arg, i_var);\n    CPPAD_ASSERT_UNKNOWN( op == BeginOp );\n    //\n    bool    more_operators = true;\n    while( op != EndOp )\n    {\n        // next op\n        (++itr).op_info(op, arg, i_var);\n        switch( op )\n        {   // absolute value operator\n            case AbsOp:\n            CPPAD_ASSERT_NARG_NRES(op, 1, 1);\n            f_abs_arg.push_back( arg[0] );\n            f_abs_res.push_back( i_var );\n            break;\n\n            default:\n            break;\n        }\n    }\n    // ------------------------------------------------------------------------\n    // Forward sweep to create new recording\n    // ------------------------------------------------------------------------\n    // dynamic parameter information in player\n    const pod_vector<bool>&     par_is_dyn( play_.par_is_dyn() );\n    const pod_vector<opcode_t>& dyn_par_op( play_.dyn_par_op() );\n    const pod_vector<addr_t>&   dyn_par_arg( play_.dyn_par_arg() );\n    //\n    // recorder for new operation sequence\n    recorder<Base> rec;\n    //\n    // number of parameters in both operation sequences\n    size_t num_par = play_.num_par_all();\n    //\n    // number of independent dynamic parameters\n    size_t n_dyn_independent = play_.num_dynamic_par();\n    rec.set_n_dyn_independent(n_dyn_independent);\n    //\n    // set all parameter to be exactly the same in rec as in play\n    size_t i_dyn = 0; // dynamic parameter index\n    size_t i_arg = 0; // dynamic parameter operator argument index\n    for(size_t i_par = 0; i_par < num_par; ++i_par)\n    {\n# ifndef NDEBUG\n        size_t j_par = 0;\n# endif\n        // value of this parameter\n        Base par = play_.par_one(i_par);\n        if( ! par_is_dyn[i_par] )\n            CPPAD_J_PAR_EQUAL_REC.put_con_par(par);\n        else\n        {   // operator for this dynamic parameter\n            op_code_dyn op_dyn = op_code_dyn( dyn_par_op[i_dyn] );\n            CPPAD_ASSERT_KNOWN(\n                op_dyn != local::atom_dyn,\n                \"abs_normal_fun: not yet implemented for \"\n                \"atomic dynamic parameter functions\"\n            );\n            //\n            // number of arguments for this dynamic parameter\n            size_t n_arg = num_arg_dyn(op_dyn);\n            //\n            switch(n_arg)\n            {   case 0:\n                CPPAD_J_PAR_EQUAL_REC.put_dyn_par(par, op_dyn);\n                break;\n\n                case 1:\n                CPPAD_J_PAR_EQUAL_REC.put_dyn_par(par, op_dyn,\n                    dyn_par_arg[i_arg + 0]\n                );\n                break;\n\n                case 2:\n                CPPAD_J_PAR_EQUAL_REC.put_dyn_par(par, op_dyn,\n                    dyn_par_arg[i_arg + 0] ,\n                    dyn_par_arg[i_arg + 1]\n                );\n                break;\n\n                case 5:\n                CPPAD_J_PAR_EQUAL_REC.put_dyn_cond_exp(par,\n                    CompareOp( dyn_par_arg[i_arg + 0] )  ,\n                    dyn_par_arg[i_arg + 1]               ,\n                    dyn_par_arg[i_arg + 2]               ,\n                    dyn_par_arg[i_arg + 3]               ,\n                    dyn_par_arg[i_arg + 4]\n                );\n                break;\n\n                default:\n                CPPAD_ASSERT_UNKNOWN(false);\n            }\n            ++i_dyn;\n            i_arg += n_arg;\n        }\n        CPPAD_ASSERT_UNKNOWN( j_par == i_par );\n    }\n    //\n    // number of variables in both operation sequences\n    // (the AbsOp operators are replace by InvOp operators)\n    const size_t num_var = play_.num_var();\n    //\n    // mapping from old variable index to new variable index\n    CPPAD_ASSERT_UNKNOWN(\n        size_t( (std::numeric_limits<addr_t>::max)() ) >= num_var\n    );\n    CppAD::vector<addr_t> f2g_var(num_var);\n    for(i_var = 0; i_var < num_var; i_var++)\n        f2g_var[i_var] = addr_t( num_var ); // invalid (should not be used)\n    //\n    // record the independent variables in f\n    itr = play_.begin();\n    itr.op_info(op, arg, i_var);\n    CPPAD_ASSERT_UNKNOWN( op == BeginOp );\n    more_operators   = true;\n    while( more_operators )\n    {   switch( op )\n        {\n            // phantom variable\n            case BeginOp:\n            CPPAD_ASSERT_NARG_NRES(op, 1, 1);\n            CPPAD_ASSERT_UNKNOWN( arg[0] == 0 );\n            rec.PutArg(0);\n            f2g_var[i_var] = rec.PutOp(op);\n            break;\n\n            // independent variables\n            case InvOp:\n            CPPAD_ASSERT_NARG_NRES(op, 0, 1);\n            f2g_var[i_var] = rec.PutOp(op);\n            break;\n\n            // end of independent variables\n            default:\n            more_operators = false;\n            break;\n        }\n        if( more_operators )\n            (++itr).op_info(op, arg, i_var);\n    }\n    // add one for the phantom variable\n    CPPAD_ASSERT_UNKNOWN( 1 + Domain() == i_var );\n    //\n    // record the independent variables corresponding AbsOp results\n    size_t index_abs;\n    for(index_abs = 0; index_abs < f_abs_res.size(); index_abs++)\n        f2g_var[ f_abs_res[index_abs] ] = rec.PutOp(InvOp);\n    //\n    // used to hold new argument vector\n    addr_t new_arg[6];\n    //\n    // now loop through the rest of the\n    more_operators = true;\n    index_abs      = 0;\n    while( more_operators )\n    {   addr_t mask; // temporary used in some switch cases\n        switch( op )\n        {\n            // check setting of f_abs_arg and f_abs_res;\n            case AbsOp:\n            CPPAD_ASSERT_NARG_NRES(op, 1, 1);\n            CPPAD_ASSERT_UNKNOWN( f_abs_arg[index_abs] ==  arg[0] );\n            CPPAD_ASSERT_UNKNOWN( f_abs_res[index_abs] ==  i_var );\n            CPPAD_ASSERT_UNKNOWN( f2g_var[i_var] > 0 );\n            ++index_abs;\n            break;\n\n            // These operators come at beginning of take and are handled above\n            case InvOp:\n            CPPAD_ASSERT_UNKNOWN(false);\n            break;\n\n            // ---------------------------------------------------------------\n            // Unary operators, argument a parameter, one result\n            case ParOp:\n            CPPAD_ASSERT_NARG_NRES(op, 1, 1);\n            new_arg[0] = arg[0]; // parameter\n            rec.PutArg( new_arg[0] );\n            f2g_var[i_var] = rec.PutOp(op);\n            break;\n\n            // --------------------------------------------------------------\n            // Unary operators, argument a variable, one result\n            // (excluding the absolute value operator AbsOp)\n            case AcosOp:\n            case AcoshOp:\n            case AsinOp:\n            case AsinhOp:\n            case AtanOp:\n            case AtanhOp:\n            case CosOp:\n            case CoshOp:\n            case ExpOp:\n            case Expm1Op:\n            case LogOp:\n            case Log1pOp:\n            case NegOp:\n            case SignOp:\n            case SinOp:\n            case SinhOp:\n            case SqrtOp:\n            case TanOp:\n            case TanhOp:\n            // some of these operators have an auxiliary result; e.g.,\n            // sine and cosine are computed togeather.\n            CPPAD_ASSERT_UNKNOWN( NumArg(op) ==  1 );\n            CPPAD_ASSERT_UNKNOWN( NumRes(op) == 1 || NumRes(op) == 2 );\n            CPPAD_ASSERT_UNKNOWN( size_t( f2g_var[ arg[0] ] ) < num_var );\n            new_arg[0] = f2g_var[ arg[0] ];\n            rec.PutArg( new_arg[0] );\n            f2g_var[i_var] = rec.PutOp( op );\n            break;\n\n            case ErfOp:\n            case ErfcOp:\n            CPPAD_ASSERT_NARG_NRES(op, 3, 5);\n            CPPAD_ASSERT_UNKNOWN( size_t( f2g_var[ arg[0] ] ) < num_var );\n            // Error function is a special case\n            // second argument is always the parameter 0\n            // third argument is always the parameter 2 / sqrt(pi)\n            rec.PutArg( arg[1] ); // parameter\n            rec.PutArg( arg[2] ); // parameter\n            f2g_var[i_var] = rec.PutOp(op);\n            break;\n            // --------------------------------------------------------------\n            // Binary operators, left variable, right parameter, one result\n            case SubvpOp:\n            case DivvpOp:\n            case PowvpOp:\n            case ZmulvpOp:\n            CPPAD_ASSERT_NARG_NRES(op, 2, 1);\n            CPPAD_ASSERT_UNKNOWN( size_t( f2g_var[ arg[0] ] ) < num_var );\n            new_arg[0] = f2g_var[ arg[0] ];\n            new_arg[1] = arg[1]; // parameter\n            rec.PutArg( new_arg[0], new_arg[1] );\n            f2g_var[i_var] = rec.PutOp(op);\n            break;\n            // ---------------------------------------------------\n            // Binary operators, left index, right variable, one result\n            case DisOp:\n            CPPAD_ASSERT_UNKNOWN( size_t( f2g_var[ arg[1] ] ) < num_var );\n            new_arg[0] = arg[0];\n            new_arg[1] = f2g_var[ arg[1] ];\n            rec.PutArg( new_arg[0], new_arg[1] );\n            f2g_var[i_var] = rec.PutOp(op);\n            break;\n\n            // --------------------------------------------------------------\n            // Binary operators, left parameter, right variable, one result\n            case AddpvOp:\n            case SubpvOp:\n            case MulpvOp:\n            case DivpvOp:\n            case PowpvOp:\n            case ZmulpvOp:\n# ifndef NDEBUG\n            if( op == PowpvOp )\n            {   CPPAD_ASSERT_NARG_NRES(op, 2, 3);\n            }\n            else\n            {   CPPAD_ASSERT_NARG_NRES(op, 2, 1);\n            }\n# endif\n            CPPAD_ASSERT_UNKNOWN( size_t( f2g_var[ arg[1] ] ) < num_var );\n            new_arg[0] = arg[0]; // parameter\n            new_arg[1] = f2g_var[ arg[1] ];\n            rec.PutArg( new_arg[0], new_arg[1] );\n            f2g_var[i_var] = rec.PutOp(op);\n            break;\n            // --------------------------------------------------------------\n            // Binary operators, left and right variables, one result\n            case AddvvOp:\n            case SubvvOp:\n            case MulvvOp:\n            case DivvvOp:\n            case PowvvOp:\n            case ZmulvvOp:\n# ifndef NDEBUG\n            if( op == PowvvOp )\n            {   CPPAD_ASSERT_NARG_NRES(op, 2, 3);\n            }\n            else\n            {   CPPAD_ASSERT_NARG_NRES(op, 2, 1);\n            }\n# endif\n            CPPAD_ASSERT_UNKNOWN( size_t( f2g_var[ arg[0] ] ) < num_var );\n            CPPAD_ASSERT_UNKNOWN( size_t( f2g_var[ arg[1] ] ) < num_var );\n            new_arg[0] = f2g_var[ arg[0] ];\n            new_arg[1] = f2g_var[ arg[1] ];\n            rec.PutArg( new_arg[0], new_arg[1] );\n            f2g_var[i_var] = rec.PutOp(op);\n            break;\n            // ---------------------------------------------------\n            // Conditional expression operators\n            case CExpOp:\n            CPPAD_ASSERT_NARG_NRES(op, 6, 1);\n            new_arg[0] = arg[0];\n            new_arg[1] = arg[1];\n            mask = 1;\n            for(size_t i = 2; i < 6; i++)\n            {   if( arg[1] & mask )\n                {   CPPAD_ASSERT_UNKNOWN( size_t(f2g_var[arg[i]]) < num_var );\n                    new_arg[i] = f2g_var[ arg[i] ];\n                }\n                else\n                    new_arg[i] = arg[i]; // parameter\n                mask = mask << 1;\n            }\n            rec.PutArg(\n                new_arg[0] ,\n                new_arg[1] ,\n                new_arg[2] ,\n                new_arg[3] ,\n                new_arg[4] ,\n                new_arg[5]\n            );\n            f2g_var[i_var] = rec.PutOp(op);\n            break;\n\n            // --------------------------------------------------\n            // Operators with no arguments and no results\n            case EndOp:\n            CPPAD_ASSERT_NARG_NRES(op, 0, 0);\n            rec.PutOp(op);\n            more_operators = false;\n            break;\n\n            // ---------------------------------------------------\n            // Operations with two arguments and no results\n            case LepvOp:\n            case LtpvOp:\n            case EqpvOp:\n            case NepvOp:\n            CPPAD_ASSERT_NARG_NRES(op, 2, 0);\n            new_arg[0] = arg[0]; // parameter\n            new_arg[1] = f2g_var[ arg[1] ];\n            rec.PutArg(new_arg[0], new_arg[1]);\n            rec.PutOp(op);\n            break;\n            //\n            case LevpOp:\n            case LtvpOp:\n            CPPAD_ASSERT_NARG_NRES(op, 2, 0);\n            new_arg[0] = f2g_var[ arg[0] ];\n            new_arg[1] = arg[1]; // parameter\n            rec.PutArg(new_arg[0], new_arg[1]);\n            rec.PutOp(op);\n            break;\n            //\n            case LevvOp:\n            case LtvvOp:\n            case EqvvOp:\n            case NevvOp:\n            CPPAD_ASSERT_NARG_NRES(op, 2, 0);\n            new_arg[0] = f2g_var[ arg[0] ];\n            new_arg[1] = f2g_var[ arg[1] ];\n            rec.PutArg(new_arg[0], new_arg[1]);\n            rec.PutOp(op);\n            break;\n\n            // ---------------------------------------------------\n            // print forward operator\n            case PriOp:\n            CPPAD_ASSERT_NARG_NRES(op, 5, 0);\n            //\n            // arg[0]\n            new_arg[0] = arg[0];\n            //\n            // arg[1]\n            if( arg[0] & 1 )\n            {\n                CPPAD_ASSERT_UNKNOWN( size_t( f2g_var[ arg[1] ] )  < num_var );\n                new_arg[1] = f2g_var[ arg[1] ];\n            }\n            else\n            {   new_arg[1] = arg[1]; // parameter\n            }\n            //\n            // arg[3]\n            if( arg[0] & 2 )\n            {\n                CPPAD_ASSERT_UNKNOWN( size_t( f2g_var[ arg[3] ] )  < num_var );\n                new_arg[3] = f2g_var[ arg[3] ];\n            }\n            else\n            {   new_arg[3] = arg[3]; // parameter\n            }\n            new_arg[2] = rec.PutTxt( play_.GetTxt(size_t(arg[2])) );\n            new_arg[4] = rec.PutTxt( play_.GetTxt(size_t(arg[4])) );\n            //\n            rec.PutArg(\n                new_arg[0] ,\n                new_arg[1] ,\n                new_arg[2] ,\n                new_arg[3] ,\n                new_arg[4]\n            );\n            // no result\n            rec.PutOp(op);\n            break;\n\n            // ---------------------------------------------------\n            // VecAD operators\n\n            // Load using a parameter index\n            case LdpOp:\n            CPPAD_ASSERT_NARG_NRES(op, 3, 1);\n            new_arg[0] = arg[0];\n            new_arg[1] = arg[1]; // parameter\n            new_arg[2] = arg[2];\n            rec.PutArg(\n                new_arg[0],\n                new_arg[1],\n                new_arg[2]\n            );\n            f2g_var[i_var] = rec.PutLoadOp(op);\n            break;\n\n            // Load using a variable index\n            case LdvOp:\n            CPPAD_ASSERT_NARG_NRES(op, 3, 1);\n            CPPAD_ASSERT_UNKNOWN( size_t( f2g_var[ arg[1] ] ) < num_var );\n            new_arg[0] = arg[0];\n            new_arg[1] = f2g_var[ arg[1] ];\n            new_arg[2] = arg[2];\n            rec.PutArg(\n                new_arg[0],\n                new_arg[1],\n                new_arg[2]\n            );\n            f2g_var[i_var] = rec.PutLoadOp(op);\n            break;\n\n            // Store a parameter using a parameter index\n            case StppOp:\n            CPPAD_ASSERT_NARG_NRES(op, 3, 0);\n            new_arg[0] = arg[0];\n            new_arg[1] = arg[1]; // parameter\n            new_arg[2] = arg[2]; // parameter\n            rec.PutArg(\n                new_arg[0],\n                new_arg[1],\n                new_arg[2]\n            );\n            rec.PutOp(op);\n            break;\n\n            // Store a parameter using a variable index\n            case StvpOp:\n            CPPAD_ASSERT_NARG_NRES(op, 3, 0);\n            CPPAD_ASSERT_UNKNOWN( size_t( f2g_var[ arg[1] ] ) < num_var );\n            new_arg[0] = arg[0];\n            new_arg[1] = f2g_var[ arg[1] ];\n            new_arg[2] = arg[2]; // parameter\n            rec.PutArg(\n                new_arg[0],\n                new_arg[1],\n                new_arg[2]\n            );\n            rec.PutOp(op);\n            break;\n\n            // Store a variable using a parameter index\n            case StpvOp:\n            CPPAD_ASSERT_NARG_NRES(op, 3, 0);\n            CPPAD_ASSERT_UNKNOWN( size_t( f2g_var[ arg[2] ] ) < num_var );\n            new_arg[0] = arg[0];\n            new_arg[1] = arg[1]; // parameter\n            new_arg[2] = f2g_var[ arg[2] ];\n            rec.PutArg(\n                new_arg[0],\n                new_arg[1],\n                new_arg[2]\n            );\n            rec.PutOp(op);\n            break;\n\n            // Store a variable using a variable index\n            case StvvOp:\n            CPPAD_ASSERT_NARG_NRES(op, 3, 0);\n            CPPAD_ASSERT_UNKNOWN( size_t( f2g_var[ arg[1] ] ) < num_var );\n            CPPAD_ASSERT_UNKNOWN( size_t( f2g_var[ arg[2] ] ) < num_var );\n            new_arg[0] = arg[0];\n            new_arg[1] = f2g_var[ arg[1] ];\n            new_arg[2] = f2g_var[ arg[2] ];\n            rec.PutArg(\n                new_arg[0],\n                new_arg[1],\n                new_arg[2]\n            );\n            break;\n\n            // -----------------------------------------------------------\n            // atomic function call operators\n\n            case AFunOp:\n            CPPAD_ASSERT_NARG_NRES(op, 4, 0);\n            // atom_index, atom_old, atom_n, atom_m\n            rec.PutArg(arg[0], arg[1], arg[2], arg[3]);\n            rec.PutOp(AFunOp);\n            break;\n\n            case FunapOp:\n            CPPAD_ASSERT_NARG_NRES(op, 1, 0);\n            new_arg[0] = arg[0]; // parameter\n            rec.PutArg(new_arg[0]);\n            rec.PutOp(FunapOp);\n            break;\n\n            case FunavOp:\n            CPPAD_ASSERT_NARG_NRES(op, 1, 0);\n            CPPAD_ASSERT_UNKNOWN( size_t( f2g_var[arg[0]] ) < num_var );\n            new_arg[0] = f2g_var[ arg[0] ];\n            rec.PutArg(new_arg[0]);\n            rec.PutOp(FunavOp);\n            break;\n\n            case FunrpOp:\n            CPPAD_ASSERT_NARG_NRES(op, 1, 0);\n            new_arg[0] = arg[0]; // parameter\n            rec.PutArg(new_arg[0]);\n            rec.PutOp(FunrpOp);\n            break;\n\n            case FunrvOp:\n            CPPAD_ASSERT_NARG_NRES(op, 0, 1);\n            f2g_var[i_var] = rec.PutOp(FunrvOp);\n            break;\n            // ---------------------------------------------------\n\n            // all cases should be handled above\n            default:\n            CPPAD_ASSERT_UNKNOWN(false);\n        }\n        if( more_operators )\n            (++itr).op_info(op, arg, i_var);\n    }\n    // Check a few expected results\n    CPPAD_ASSERT_UNKNOWN( rec.num_var_op() == play_.num_var_op() );\n    CPPAD_ASSERT_UNKNOWN( rec.num_var() == play_.num_var() );\n    CPPAD_ASSERT_UNKNOWN( rec.num_var_load() == play_.num_var_load() );\n\n    // -----------------------------------------------------------------------\n    // Use rec to create the function g\n    // -----------------------------------------------------------------------\n\n    // number of variables in the recording\n    g.num_var_tape_ = rec.num_var();\n\n    // dimension cskip_op vector to number of operators\n    g.cskip_op_.resize( rec.num_var_op() );\n\n    // independent variables in g: (x, u)\n    size_t s = f_abs_res.size();\n    size_t n = Domain();\n    g.ind_taddr_.resize(n + s);\n    // (x, u)\n    for(size_t j = 0; j < n; j++)\n    {   g.ind_taddr_[j] = size_t( f2g_var[ ind_taddr_[j] ] );\n        CPPAD_ASSERT_UNKNOWN( g.ind_taddr_[j] == j + 1 );\n    }\n    for(size_t j = 0; j < s; j++)\n    {   g.ind_taddr_[n + j] = size_t( f2g_var[ f_abs_res[j] ] );\n        CPPAD_ASSERT_UNKNOWN( g.ind_taddr_[n + j] == n + j + 1 );\n    }\n\n    // dependent variable in g: (y, z)\n    CPPAD_ASSERT_UNKNOWN( s == f_abs_arg.size() );\n    size_t m = Range();\n    g.dep_taddr_.resize(m + s);\n    for(size_t i = 0; i < m; i++)\n    {   g.dep_taddr_[i] = size_t( f2g_var[ dep_taddr_[i] ] );\n        CPPAD_ASSERT_UNKNOWN( g.dep_taddr_[i] < num_var );\n    }\n    for(size_t i = 0; i < s; i++)\n    {   g.dep_taddr_[m + i] = size_t( f2g_var[ f_abs_arg[i] ] );\n        CPPAD_ASSERT_UNKNOWN( g.dep_taddr_[m + i] < num_var );\n    }\n\n    // which  dependent variables are parameters\n    g.dep_parameter_.resize(m + s);\n    for(size_t i = 0; i < m; i++)\n        g.dep_parameter_[i] = dep_parameter_[i];\n    for(size_t i = 0; i < s; i++)\n        g.dep_parameter_[m + i] = false;\n\n    // free memory allocated for sparse Jacobian calculation\n    // (the results are no longer valid)\n    g.for_jac_sparse_pack_.resize(0, 0);\n    g.for_jac_sparse_set_.resize(0, 0);\n\n    // free taylor coefficient memory\n    g.taylor_.clear();\n    g.num_order_taylor_ = 0;\n    g.cap_order_taylor_ = 0;\n\n    // Transferring the recording swaps its vectors so do this last\n    // replace the recording in g (this ADFun object)\n    g.play_.get_recording(rec, n + s);\n\n    // resize subgraph_info_\n    g.subgraph_info_.resize(\n        g.ind_taddr_.size(),   // n_ind\n        g.dep_taddr_.size(),   // n_dep\n        g.play_.num_var_op(),  // n_op\n        g.play_.num_var()      // n_var\n    );\n\n    // ------------------------------------------------------------------------\n    // Create the function a\n    // ------------------------------------------------------------------------\n\n    // start with a copy of f\n    a = *this;\n\n    // dependent variables in a(x)\n    CPPAD_ASSERT_UNKNOWN( s == f_abs_arg.size() );\n    a.dep_taddr_.resize(s);\n    for(size_t i = 0; i < s; i++)\n    {   a.dep_taddr_[i] = f_abs_res[i];\n        CPPAD_ASSERT_UNKNOWN( a.dep_taddr_[i] < num_var );\n    }\n\n    // free memory allocated for sparse Jacobian calculation\n    // (the results are no longer valid)\n    a.for_jac_sparse_pack_.resize(0, 0);\n    a.for_jac_sparse_set_.resize(0, 0);\n\n    // free taylor coefficient memory\n    a.taylor_.clear();\n    a.num_order_taylor_ = 0;\n    a.cap_order_taylor_ = 0;\n}\n\n// preprocessor symbols that are local to this file\n# undef CPPAD_J_PAR_EQUAL_REC\n\n} // END_CPPAD_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/ad.hpp",
    "content": "# ifndef CPPAD_CORE_AD_HPP\n# define CPPAD_CORE_AD_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n// simple AD operations that must be defined for AD as well as base class\n# include <cppad/core/ordered.hpp>\n# include <cppad/core/identical.hpp>\n\n// define the template classes that are used by the AD template class\n# include <cppad/local/op_code_dyn.hpp>\n# include <cppad/local/op_code_var.hpp>\n# include <cppad/core/ad_type.hpp>\n# include <cppad/local/record/recorder.hpp>\n# include <cppad/local/play/player.hpp>\n# include <cppad/local/ad_tape.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n\n// tape_manage_enum\ntypedef enum {\n    new_tape_manage,\n    delete_tape_manage\n}\ntape_manage_enum;\n\ntemplate <class Base>\nclass AD {\nprivate :\n    // -----------------------------------------------------------------------\n    // Base type value for this object\n    Base value_;\n    //\n    // tape for this object\n    tape_id_t tape_id_;\n    //\n    // tape address for this object\n    // (when tape_id is current tape for AD<Base>)\n    addr_t taddr_;\n    //\n    // sub-type for this object\n    // (when tape_id is current tape for AD<Base>)\n    ad_type_enum ad_type_;\n    // -----------------------------------------------------------------------\n\n    // enable use of AD<Base> in parallel mode\n    template <class Type>\n    friend void parallel_ad(void);\n\n    // template friend functions where template parameter is not bound\n    template <class ADVector>\n    friend void Independent(\n        ADVector&  x              ,\n        size_t     abort_op_index ,\n        bool       record_compare ,\n        ADVector&  dynamic\n    );\n\n    // one argument functions\n    friend bool Constant  <Base> (const AD<Base>    &u);\n    friend bool Constant  <Base> (const VecAD<Base> &u);\n    //\n    friend bool Dynamic   <Base> (const AD<Base>    &u);\n    friend bool Dynamic   <Base> (const VecAD<Base> &u);\n    //\n    friend bool Parameter <Base> (const AD<Base>    &u);\n    friend bool Parameter <Base> (const VecAD<Base> &u);\n    //\n    friend bool Variable  <Base> (const AD<Base>    &u);\n    friend bool Variable  <Base> (const VecAD<Base> &u);\n    //\n    friend int  Integer   <Base> (const AD<Base>    &u);\n    friend AD   Var2Par   <Base> (const AD<Base>    &u);\n    //\n    friend unsigned short hash_code <Base> (const AD<Base> &u);\n    //\n    // power function\n    friend AD pow <Base>\n        (const AD<Base> &x, const AD<Base> &y);\n\n    // azmul function\n    friend AD azmul <Base>\n        (const AD<Base> &x, const AD<Base> &y);\n\n    // order determining functions, see ordered.hpp\n    friend bool GreaterThanZero   <Base> (const AD<Base> &x);\n    friend bool GreaterThanOrZero <Base> (const AD<Base> &x);\n    friend bool LessThanZero      <Base> (const AD<Base> &x);\n    friend bool LessThanOrZero    <Base> (const AD<Base> &x);\n    friend bool abs_geq           <Base>\n        (const AD<Base>& x, const AD<Base>& y);\n\n    // The identical property functions, see identical.hpp\n    friend bool IdenticalCon      <Base> (const AD<Base> &x);\n    friend bool IdenticalZero     <Base> (const AD<Base> &x);\n    friend bool IdenticalOne      <Base> (const AD<Base> &x);\n    friend bool IdenticalEqualCon <Base>\n        (const AD<Base> &x, const AD<Base> &y);\n\n    // EqualOpSeq function\n    friend bool EqualOpSeq <Base>\n        (const AD<Base> &u, const AD<Base> &v);\n\n    // NearEqual function\n    friend bool NearEqual <Base> (\n    const AD<Base> &x, const AD<Base> &y, const Base &r, const Base &a);\n\n    friend bool NearEqual <Base> (\n    const Base &x, const AD<Base> &y, const Base &r, const Base &a);\n\n    friend bool NearEqual <Base> (\n    const AD<Base> &x, const Base &y, const Base &r, const Base &a);\n\n    // CondExp function\n    friend AD<Base> CondExpOp  <Base> (\n        enum CompareOp  cop       ,\n        const AD<Base> &left      ,\n        const AD<Base> &right     ,\n        const AD<Base> &trueCase  ,\n        const AD<Base> &falseCase\n    );\n\n    // classes\n    friend class local::ADTape<Base>;\n    friend class local::dyn_recorder<Base>;\n    friend class local::recorder<Base>;\n    friend class ADFun<Base>;\n    friend class atomic_base<Base>;\n    friend class atomic_three<Base>;\n    friend class atomic_four<Base>;\n    friend class discrete<Base>;\n    friend class VecAD<Base>;\n    friend class VecAD_reference<Base>;\n\n    // arithematic binary operators\n    friend AD<Base> operator + <Base>\n        (const AD<Base> &left, const AD<Base> &right);\n    friend AD<Base> operator - <Base>\n        (const AD<Base> &left, const AD<Base> &right);\n    friend AD<Base> operator * <Base>\n        (const AD<Base> &left, const AD<Base> &right);\n    friend AD<Base> operator / <Base>\n        (const AD<Base> &left, const AD<Base> &right);\n\n    // comparison operators\n    friend bool operator < <Base>\n        (const AD<Base> &left, const AD<Base> &right);\n    friend bool operator <= <Base>\n        (const AD<Base> &left, const AD<Base> &right);\n    friend bool operator > <Base>\n        (const AD<Base> &left, const AD<Base> &right);\n    friend bool operator >= <Base>\n        (const AD<Base> &left, const AD<Base> &right);\n    friend bool operator == <Base>\n        (const AD<Base> &left, const AD<Base> &right);\n    friend bool operator != <Base>\n        (const AD<Base> &left, const AD<Base> &right);\n\n    // input operator\n    friend std::istream& operator >> <Base>\n        (std::istream &is, AD<Base> &x);\n\n    // output operations\n    friend std::ostream& operator << <Base>\n        (std::ostream &os, const AD<Base> &x);\n    friend void PrintFor <Base> (\n        const AD<Base>&    flag   ,\n        const char*        before ,\n        const AD<Base>&    var    ,\n        const char*        after\n    );\npublic:\n    // type of value\n    typedef Base value_type;\n\n    // implicit default constructor\n    AD(void);\n\n    // destructor\n    ~AD(void) { }\n\n    // use default implicit copy constructor\n    // AD(const AD &x);\n\n# ifdef CPPAD_FOR_TMB\n    // TMB would rather have implicit construction from double,\n    // CppAD uses default constructor and assignment to double instead.\n    AD(const double &d);\n# else\n    // implicit construction from base type\n    AD(const Base &b);\n# endif\n\n    // implicit constructor from VecAD<Base>::reference\n    AD(const VecAD_reference<Base> &x);\n\n    // explicit construction from some other type (deprecated)\n    template <class T> explicit AD(const T &t);\n\n    // conversion from AD to Base type\n    friend Base Value <Base> (const AD<Base> &x);\n\n    // use default assignment operator\n    // AD& operator=(const AD &x);\n\n    // assignment from base type\n    AD& operator=(const Base &b);\n\n    // assignment from VecAD<Base>::reference\n    AD& operator=(const VecAD_reference<Base> &x);\n\n    // assignment from some other type\n    template <class T> AD& operator=(const T &right);\n\n    // compound assignment operators\n    AD& operator += (const AD &right);\n    AD& operator -= (const AD &right);\n    AD& operator *= (const AD &right);\n    AD& operator /= (const AD &right);\n\n    // unary operators\n    AD operator +(void) const;\n    AD operator -(void) const;\n\n    // interface so these functions need not be friends\n    AD abs_me(void) const;\n    AD acos_me(void) const;\n    AD asin_me(void) const;\n    AD atan_me(void) const;\n    AD cos_me(void) const;\n    AD cosh_me(void) const;\n    AD exp_me(void) const;\n    AD fabs_me(void) const;\n    AD log_me(void) const;\n    AD sin_me(void) const;\n    AD sign_me(void) const;\n    AD sinh_me(void) const;\n    AD sqrt_me(void) const;\n    AD tan_me(void) const;\n    AD tanh_me(void) const;\n    AD asinh_me(void) const;\n    AD acosh_me(void) const;\n    AD atanh_me(void) const;\n    AD erf_me(bool complemnet) const;\n    AD expm1_me(void) const;\n    AD log1p_me(void) const;\n\n    // ----------------------------------------------------------\n    // static public member functions\n\n    // abort current AD<Base> recording\n    static void        abort_recording(void);\n\n    // set the maximum number of OpenMP threads (deprecated)\n    static void        omp_max_thread(size_t number);\n\n    // These functions declared public so can be accessed by user through\n    // a macro interface and are not intended for direct use.\n    // The macro interface is documented in bool_fun.hpp.\n    // Developer documentation for these functions is in  bool_fun.hpp\n    static bool UnaryBool(\n        bool FunName(const Base &x),\n        const AD<Base> &x\n    );\n    static bool BinaryBool(\n        bool FunName(const Base &x, const Base &y),\n        const AD<Base> &x , const AD<Base> &y\n    );\n\nprivate:\n    // -----------------------------------------------------------------\n    // Make this parameter a new variable\n    void make_variable(tape_id_t id,  addr_t taddr)\n    {   CPPAD_ASSERT_UNKNOWN( Parameter(*this) ); // currently a par\n        CPPAD_ASSERT_UNKNOWN( taddr > 0 );        // sure valid taddr\n\n        tape_id_ = id;\n        taddr_   = taddr;\n        ad_type_ = variable_enum;\n    }\n    // -----------------------------------------------------------------\n    // Make this parameter a new dynamic\n    void make_dynamic(tape_id_t id,  addr_t taddr)\n    {    CPPAD_ASSERT_UNKNOWN( Parameter(*this) ); // currently a par\n         CPPAD_ASSERT_UNKNOWN( taddr > 0 );        // sure valid taddr\n\n         tape_id_ = id;\n         taddr_   = taddr;\n         ad_type_ = dynamic_enum;\n    }\n    // ---------------------------------------------------------------\n    // tape linking functions\n    //\n    // not static\n    local::ADTape<Base>* tape_this(void) const;\n    //\n    // static\n    static tape_id_t*            tape_id_ptr(size_t thread);\n    static local::ADTape<Base>** tape_handle(size_t thread);\n    static local::ADTape<Base>*         tape_manage(tape_manage_enum job);\n    static local::ADTape<Base>*  tape_ptr(void);\n    static local::ADTape<Base>*  tape_ptr(tape_id_t tape_id);\n};\n// ---------------------------------------------------------------------------\n\n} // END_CPPAD_NAMESPACE\n\n// tape linking private functions\n# include <cppad/core/tape_link.hpp>\n\n// operations that expect the AD template class to be defined\n\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/ad_assign.hpp",
    "content": "# ifndef CPPAD_CORE_AD_ASSIGN_HPP\n# define CPPAD_CORE_AD_ASSIGN_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n------------------------------------------------------------------------------\n\n{xrst_begin ad_assign}\n\nAD Assignment Operator\n######################\n\nSyntax\n******\n| *y* = *x*\n\nPurpose\n*******\nAssigns the value in *x* to the object *y* .\nIn either case,\n\nx\n*\nThe argument *x* has prototype\n\n    ``const`` *Type* & *x*\n\nwhere *Type* is\n``VecAD`` < *Base* >:: ``reference`` ,\n``AD`` < *Base* > ,\n*Base* ,\nor any type that has an implicit constructor of the form\n*Base* ( *x* ) .\n\ny\n*\nThe target *y* has prototype\n\n    ``AD`` < *Base* > *y*\n\nExample\n*******\n{xrst_toc_hidden\n    example/general/ad_assign.cpp\n}\nThe file :ref:`ad_assign.cpp-name` contain examples and tests of these operations.\nIt test returns true if it succeeds and false otherwise.\n\n{xrst_end ad_assign}\n------------------------------------------------------------------------------\n*/\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n\n/*!\n\\file ad_assign.hpp\nAD<Base> constructors and and copy operations.\n*/\n\n/*!\n\\page AD_default_assign\nUse default assignment operator\nbecause they may be optimized better than the code below:\n\\code\ntemplate <class Base>\nAD<Base>& AD<Base>::operator=(const AD<Base> &right)\n{   value_    = right.value_;\n    tape_id_  = right.tape_id_;\n    taddr_    = right.taddr_;\n    ad_type_  = right.ad_type_;\n\n    return *this;\n}\n\\endcode\n*/\n\n/*!\nAssignment to Base type value.\n\n\\tparam Base\nBase type for this AD object.\n\n\\param b\nis the Base type value being assignment to this AD object.\nThe tape identifier will be an invalid tape identifier,\nso this object is initially a parameter.\n*/\ntemplate <class Base>\nAD<Base>& AD<Base>::operator=(const Base &b)\n{   value_   = b;\n    tape_id_ = 0;\n    //\n    CPPAD_ASSERT_UNKNOWN( ! ( Variable(*this) || Dynamic(*this) ) );\n    return *this;\n}\n\n/*!\nAssignment to an ADVec<Base> element drops the vector information.\n\n\\tparam Base\nBase type for this AD object.\n*/\ntemplate <class Base>\nAD<Base>& AD<Base>::operator=(const VecAD_reference<Base> &x)\n{   *this = x.ADBase();\n    CPPAD_ASSERT_UNKNOWN( ! Dynamic(*this) );\n    return *this;\n}\n\n/*!\nAssignment from any other type, converts to Base type, and then uses assignment\nfrom Base type.\n\n\\tparam Base\nBase type for this AD object.\n\n\\tparam T\nis the the type that is being assigned to AD<Base>.\nThere must be an assignment for Base from Type.\n\n\\param t\nis the object that is being assigned to an AD<Base> object.\n*/\ntemplate <class Base>\ntemplate <class T>\nAD<Base>& AD<Base>::operator=(const T &t)\n{   *this = Base(t);\n    CPPAD_ASSERT_UNKNOWN( ! ( Variable(*this) || Dynamic(*this) ) );\n    return *this;\n}\n\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/ad_binary.hpp",
    "content": "# ifndef CPPAD_CORE_AD_BINARY_HPP\n# define CPPAD_CORE_AD_BINARY_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n-------------------------------------------------------------------------------\n{xrst_begin ad_binary}\n{xrst_spell\n    div\n}\n\nAD Binary Arithmetic Operators\n##############################\n\nSyntax\n******\n| *z* = *x* *Op* *y*\n\nPurpose\n*******\nPerforms arithmetic operations where either *x* or *y*\nhas type\n``AD`` < *Base* > or\n:ref:`VecAD@VecAD\\<Base>::reference` .\n\nOp\n**\nThe operator *Op* is one of the following\n\n.. csv-table::\n    :widths: auto\n\n    **Op**,**Meaning**\n    ``+``,*z* is *x* plus *y*\n    ``-``,*z* is *x* minus *y*\n    ``*``,*z* is *x* times *y*\n    ``/``,*z* is *x* divided by *y*\n\nBase\n****\nThe type *Base* is determined by the operand that\nhas type ``AD`` < *Base* > or ``VecAD`` < *Base* >:: ``reference`` .\n\nx\n*\nThe operand *x* has the following prototype\n\n    ``const`` *Type* & *x*\n\nwhere *Type* is\n``VecAD`` < *Base* >:: ``reference`` ,\n``AD`` < *Base* > ,\n*Base* , or\n``double`` .\n\ny\n*\nThe operand *y* has the following prototype\n\n    ``const`` *Type* & *y*\n\nwhere *Type* is\n``VecAD`` < *Base* >:: ``reference`` ,\n``AD`` < *Base* > ,\n*Base* , or\n``double`` .\n\nz\n*\nThe result *z* has the following prototype\n\n    *Type* *z*\n\nwhere *Type* is\n``AD`` < *Base* > .\n\nOperation Sequence\n******************\nThis is an :ref:`atomic_base<glossary@Operation@Atomic>`\n:ref:`glossary@AD of Base` operation\nand hence it is part of the current\nAD of *Base*\n:ref:`operation sequence<glossary@Operation@Sequence>` .\n{xrst_toc_hidden\n    example/general/add.cpp\n    example/general/sub.cpp\n    example/general/mul.cpp\n    example/general/div.cpp\n}\n\nZero Special Cases\n******************\nSuppose that an AD *value* is\n:ref:`identically zero <base_identical@Identical@Identical Functions>` .\nThen the following results will be identically zero no matter\nwhat *other* is:\nvalue * other, other * value, value / other.\nThis may be unexpected when *other* is nan\n(or when it is zero in the division case).\nThis is closely related to the :ref:`azmul-name` function.\n\nExample\n*******\nThe following files contain examples and tests of these functions.\nEach test returns true if it succeeds and false otherwise.\n\n.. csv-table::\n    :widths: auto\n\n    add.cpp,:ref:`add.cpp-title`\n    sub.cpp,:ref:`sub.cpp-title`\n    mul.cpp,:ref:`mul.cpp-title`\n    div.cpp,:ref:`div.cpp-title`\n\nDerivative\n**********\nIf :math:`f` and :math:`g` are\n:ref:`Base functions<glossary@Base Function>`\n\nAddition\n========\n\n.. math::\n\n    \\D{[ f(x) + g(x) ]}{x} = \\D{f(x)}{x} + \\D{g(x)}{x}\n\nSubtraction\n===========\n\n.. math::\n\n    \\D{[ f(x) - g(x) ]}{x} = \\D{f(x)}{x} - \\D{g(x)}{x}\n\nMultiplication\n==============\n\n.. math::\n\n    \\D{[ f(x) * g(x) ]}{x} = g(x) * \\D{f(x)}{x} + f(x) * \\D{g(x)}{x}\n\nDivision\n========\n\n.. math::\n\n    \\D{[ f(x) / g(x) ]}{x} =\n        [1/g(x)] * \\D{f(x)}{x} - [f(x)/g(x)^2] * \\D{g(x)}{x}\n\n{xrst_end ad_binary}\n-----------------------------------------------------------------------------\n*/\n# include <cppad/core/add.hpp>\n# include <cppad/core/sub.hpp>\n# include <cppad/core/mul.hpp>\n# include <cppad/core/div.hpp>\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/ad_ctor.hpp",
    "content": "# ifndef CPPAD_CORE_AD_CTOR_HPP\n# define CPPAD_CORE_AD_CTOR_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n------------------------------------------------------------------------------\n\n{xrst_begin ad_ctor}\n\nAD Constructors\n###############\n\nSyntax\n******\n| ``AD`` < *Base* > *ay* ()\n| ``AD`` < *Base* > *ay* ( *x* )\n\nPurpose\n*******\ncreates a new ``AD`` < *Base* > object *ay*\nand initializes it as a\nequal to *x* .\n\nx\n*\n\nimplicit\n========\nThere is an implicit constructor where *x* has prototype\n\n    ``const VecAD`` < *Base* >& *x*\n\nThere also is an implicit constructor where *x* has prototype\n\n    ``const`` *Base* & *x*\n\nIn this case, *ay* is a\n:ref:`constant parameter<glossary@Parameter@Constant>`\n\nexplicit\n========\nThere is an explicit constructor where *x* has prototype\n\n    ``const`` *Type* & *x*\n\nfor any type that has an explicit constructor of the form\n*Base* ( *x* ) .\nIn this case, *ay* is a\n:ref:`constant parameter<glossary@Parameter@Constant>`\n\nay\n**\nThe target *ay* has prototype\n\n    ``AD`` < *Base* > *ay*\n\nExample\n*******\n{xrst_toc_hidden\n    example/general/ad_ctor.cpp\n}\nThe files :ref:`ad_ctor.cpp-name` contain examples and tests of these operations.\nIt test returns true if it succeeds and false otherwise.\n\n{xrst_end ad_ctor}\n------------------------------------------------------------------------------\n*/\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n\n/*!\n\\file ad_ctor.hpp\nAD<Base> constructors and and copy operations.\n*/\n\n/*!\n\\page AD_default_ctor\nUse default copy constructor\nbecause they may be optimized better than the code below:\n\\code\ntemplate <class Base>\nAD<Base>::AD(const AD &x)\n{\n    value_    = x.value_;\n    tape_id_  = x.tape_id_;\n    taddr_    = x.taddr_;\n    ad_type_  = x.ad_type_;\n\n    return;\n}\n\\endcode\n*/\n\n/*!\nDefault Constructor.\n\n\\tparam Base\nBase type for this AD object.\n*/\ntemplate <class Base>\nAD<Base>::AD(void)\n: value_()\n, tape_id_(0)\n, taddr_(0)\n, ad_type_(constant_enum)\n{ }\n\n// --------------------------------------------------------------------------\n# ifdef CPPAD_FOR_TMB\n/*!\nConstructor from double.\n\n\\param d\nis value corresponding to this AD object.\nThe tape identifier will be an invalid tape identifier,\nso this object is initially a parameter.\n\n\\par CPPAD_FOR_TMB\nThis constructor is defined when CPPAD_FOR_TMB is defined.\n*/\ntemplate <class Base>\nAD<Base>::AD(const double &d)\n: value_( Base(d) )\n, tape_id_(0)\n, taddr_(0)\n, ad_type_(constant_enum)\n{   // check that this is a parameter\n    CPPAD_ASSERT_UNKNOWN( Parameter(*this) );\n}\n// --------------------------------------------------------------------------\n# else\n// --------------------------------------------------------------------------\n/*!\nConstructor from Base type.\n\n\\tparam Base\nBase type for this AD object.\n\n\\param b\nis the Base type value corresponding to this AD object.\nThe tape identifier will be an invalid tape identifier,\nso this object is initially a parameter.\n\n\\par CPPAD_FOR_TMB\nThis constructor is defined when CPPAD_FOR_TMB is not defined.\n*/\ntemplate <class Base>\nAD<Base>::AD(const Base &b)\n: value_(b)\n, tape_id_(0)\n, taddr_(0)\n, ad_type_(constant_enum)\n{   // check that this is a parameter\n    CPPAD_ASSERT_UNKNOWN( Parameter(*this) );\n}\n# endif\n// --------------------------------------------------------------------------\n\n/*!\nConstructor from an ADVec<Base> element drops the vector information.\n\n\\tparam Base\nBase type for this AD object.\n*/\ntemplate <class Base>\nAD<Base>::AD(const VecAD_reference<Base> &x)\n{   *this = x.ADBase(); }\n\n/*!\nConstructor from any other type, converts to Base type, and uses constructor\nfrom Base type.\n\n\\tparam Base\nBase type for this AD object.\n\n\\tparam T\nis the the type that is being converted to AD<Base>.\nThere must be a constructor for Base from Type.\n\n\\param t\nis the object that is being converted from T to AD<Base>.\n*/\ntemplate <class Base>\ntemplate <class T>\nAD<Base>::AD(const T &t)\n: value_( Base(t) )\n, tape_id_(0)\n, taddr_(0)\n, ad_type_(constant_enum)\n{ }\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/ad_fun.hpp",
    "content": "# ifndef CPPAD_CORE_AD_FUN_HPP\n# define CPPAD_CORE_AD_FUN_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin ADFun}\n\nADFun Objects\n#############\n\nPurpose\n*******\nAn AD of *Base*\n:ref:`operation sequence<glossary@Operation@Sequence>`\nis stored in an ``ADFun`` object by its :ref:`fun_construct-name` .\nThe ``ADFun`` object can then be used to calculate function values,\nderivative values, and other values related to the corresponding function.\n\nContents\n********\n{xrst_toc_table\n    include/cppad/core/ad_fun.xrst\n    include/cppad/core/optimize.hpp\n    include/cppad/core/fun_check.hpp\n    include/cppad/core/check_for_nan.hpp\n    include/cppad/core/to_csrc.hpp\n}\n\n{xrst_end ADFun}\n*/\n# include <cppad/core/graph/cpp_graph.hpp>\n# include <cppad/local/subgraph/info.hpp>\n# include <cppad/local/graph/cpp_graph_op.hpp>\n# include <cppad/local/val_graph/val_type.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\n\\file ad_fun.hpp\nFile used to define the ADFun<Base> class.\n*/\n\n/*!\nClass used to hold function objects\n\n\\tparam Base\nA function object has a recording of <tt>AD<Base></tt> operations.\nIt does it calculations using Base operations.\n*/\n\n\ntemplate <class Base, class RecBase>\nclass ADFun {\n    // ADFun<Base> must be a friend of ADFun< AD<Base> > for base2ad to work.\n    template <class Base2, class RecBase2> friend class ADFun;\nprivate:\n    // ------------------------------------------------------------\n    // Private member variables\n    // ------------------------------------------------------------\n\n    /// name of this function (so far only json operations use this value)\n    std::string function_name_;\n\n    /// Did the previous optimization exceed the collision limit\n    bool exceed_collision_limit_;\n\n    /// Has this ADFun object been optimized\n    bool has_been_optimized_;\n\n    /// Check for nan's and report message to user (default value is true).\n    bool check_for_nan_;\n\n    /// If zero, ignoring comparison operators. Otherwise is the\n    /// compare change count at which to store the operator index.\n    size_t compare_change_count_;\n\n    /// If compare_change_count_ is zero, compare_change_number_ is also zero.\n    /// Otherwise, it is set to the number of comparison operations that had a\n    /// different result during the subsequent zero order forward.\n    size_t compare_change_number_;\n\n    /// If compare_change_count is zero, compare_change_op_index_ is also\n    /// zero. Otherwise it is the operator index for the comparison operator\n    //// that corresponded to the number changing from count-1 to count.\n    size_t compare_change_op_index_;\n\n    /// number of orders stored in taylor_\n    size_t num_order_taylor_;\n\n    /// maximum number of orders that will fit in taylor_\n    size_t cap_order_taylor_;\n\n    /// number of directions stored in taylor_\n    size_t num_direction_taylor_;\n\n    /// number of variables in the recording (play_)\n    size_t num_var_tape_;\n\n    /// tape address for the independent variables\n    local::pod_vector<size_t> ind_taddr_;\n\n    /// tape address and parameter flag for the dependent variables\n    local::pod_vector<size_t> dep_taddr_;\n\n    /// which dependent variables are actually parameters\n    local::pod_vector<bool> dep_parameter_;\n\n    /// which operations can be conditionally skipped\n    /// Set during forward pass of order zero\n    local::pod_vector<bool> cskip_op_;\n\n    /// Variable on the tape corresponding to each vecad load operation\n    /// (if zero, the operation corresponds to a parameter).\n    local::pod_vector<addr_t> load_op2var_;\n\n    /// results of the forward mode calculations\n    local::pod_vector_maybe<Base> taylor_;\n\n    /// used for subgraph reverse mode calculations.\n    /// Declared here to avoid reallocation for each call to subgraph_reverse.\n    /// Not in subgraph_info_ because it depends on Base.\n    local::pod_vector_maybe<Base> subgraph_partial_;\n\n    /// the operation sequence corresponding to this object\n    local::player<Base> play_;\n\n    /// subgraph information for this object\n    local::subgraph::subgraph_info subgraph_info_;\n\n    /// Packed results of the forward mode Jacobian sparsity calculations.\n    /// for_jac_sparse_pack_.n_set() != 0  implies other sparsity results\n    /// are empty\n    local::sparse::pack_setvec for_jac_sparse_pack_;\n\n    /// Set results of the forward mode Jacobian sparsity calculations\n    /// for_jac_sparse_set_.n_set() != 0  implies for_sparse_pack_ is empty.\n    local::sparse::list_setvec for_jac_sparse_set_;\n\n\n    // ------------------------------------------------------------\n    // Private member functions\n    // ------------------------------------------------------------\n\n    /// change the operation sequence corresponding to this object\n    template <class ADvector>\n    void Dependent(local::ADTape<Base> *tape, const ADvector &y);\n\n    // vector of bool version of ForSparseJac\n    // (doxygen in cppad/core/for_sparse_jac.hpp)\n    template <class SetVector>\n    void ForSparseJacCase(\n        bool               set_type  ,\n        bool               transpose ,\n        bool               dependency,\n        size_t             q         ,\n        const SetVector&   r         ,\n        SetVector&         s\n    );\n\n    // vector of std::set<size_t> version of ForSparseJac\n    // (doxygen in cppad/core/for_sparse_jac.hpp)\n    template <class SetVector>\n    void ForSparseJacCase(\n        const std::set<size_t>&  set_type  ,\n        bool                     transpose ,\n        bool                     dependency,\n        size_t                   q         ,\n        const SetVector&         r         ,\n        SetVector&               s\n    );\n\n    // vector of bool version of RevSparseJac\n    // (doxygen in cppad/core/rev_sparse_jac.hpp)\n    template <class SetVector>\n    void RevSparseJacCase(\n        bool               set_type  ,\n        bool               transpose ,\n        bool               dependency,\n        size_t             p         ,\n        const SetVector&   s         ,\n        SetVector&         r\n    );\n\n    // vector of std::set<size_t> version of RevSparseJac\n    // (doxygen in cppad/core/rev_sparse_jac.hpp)\n    template <class SetVector>\n    void RevSparseJacCase(\n        const std::set<size_t>&  set_type  ,\n        bool                     transpose ,\n        bool                     dependency,\n        size_t                   p         ,\n        const SetVector&         s         ,\n        SetVector&               r\n    );\n\n    // vector of bool version of ForSparseHes\n    // (doxygen in cppad/core/for_sparse_hes.hpp)\n    template <class SetVector>\n    void ForSparseHesCase(\n        bool               set_type  ,\n        const SetVector&   r         ,\n        const SetVector&   s         ,\n        SetVector&         h\n    );\n\n    // vector of std::set<size_t> version of ForSparseHes\n    // (doxygen in cppad/core/for_sparse_hes.hpp)\n    template <class SetVector>\n    void ForSparseHesCase(\n        const std::set<size_t>&  set_type  ,\n        const SetVector&         r         ,\n        const SetVector&         s         ,\n        SetVector&               h\n    );\n\n    // vector of bool version of RevSparseHes\n    // (doxygen in cppad/core/rev_sparse_hes.hpp)\n    template <class SetVector>\n    void RevSparseHesCase(\n        bool               set_type  ,\n        bool               transpose ,\n        size_t             q         ,\n        const SetVector&   s         ,\n        SetVector&         h\n    );\n\n    // vector of std::set<size_t> version of RevSparseHes\n    // (doxygen in cppad/core/rev_sparse_hes.hpp)\n    template <class SetVector>\n    void RevSparseHesCase(\n        const std::set<size_t>&  set_type  ,\n        bool                     transpose ,\n        size_t                   q         ,\n        const SetVector&         s         ,\n        SetVector&               h\n    );\n\n    // Forward mode version of SparseJacobian\n    // (doxygen in cppad/core/sparse_jacobian.hpp)\n    template <class BaseVector, class SetVector, class SizeVector>\n    size_t SparseJacobianFor(\n        const BaseVector&           x               ,\n                  SetVector&            p_transpose     ,\n        const SizeVector&           row             ,\n        const SizeVector&           col             ,\n                  BaseVector&           jac             ,\n                  sparse_jacobian_work& work\n    );\n\n    // Reverse mode version of SparseJacobian\n    // (doxygen in cppad/core/sparse_jacobian.hpp)\n    template <class BaseVector, class SetVector, class SizeVector>\n    size_t SparseJacobianRev(\n        const BaseVector&           x               ,\n                  SetVector&            p               ,\n        const SizeVector&           row             ,\n        const SizeVector&           col             ,\n                  BaseVector&           jac             ,\n                  sparse_jacobian_work& work\n    );\n\n    // combined sparse_list and sparse_pack version of SparseHessian\n    // (doxygen in cppad/core/sparse_hessian.hpp)\n    template <class BaseVector, class SetVector, class SizeVector>\n    size_t SparseHessianCompute(\n        const BaseVector&              x           ,\n        const BaseVector&              w           ,\n                  SetVector&               sparsity    ,\n        const SizeVector&              row         ,\n        const SizeVector&              col         ,\n                  BaseVector&              hes         ,\n                  sparse_hessian_work&     work\n    );\n\npublic:\n    /// default constructor\n    ADFun(void);\n\n    /// copy constructor\n    ADFun(const ADFun& g) = delete;\n\n    // assignment operator\n    // (doxygen in cppad/core/fun_construct.hpp)\n    void operator=(const ADFun& f);\n\n    // swap\n    void swap(ADFun& f);\n\n    // move semenatics copy\n    ADFun(ADFun&& f);\n\n    // move semantics assignment\n    void operator=(ADFun&& f);\n\n    // create from Json or C++ AD graph\n    void from_json(const std::string& json);\n    void from_graph(const cpp_graph& graph_obj);\n    void from_graph(\n        const cpp_graph&    graph_obj  ,\n        const vector<bool>& dyn2var    ,\n        const vector<bool>& var2dyn\n    );\n\n    // convert function to  a\n    // C++ graph, Json graph, C source code\n    void to_graph(cpp_graph& graph_obj);\n    std::string to_json(void);\n    void to_csrc(std::ostream& os, const std::string& type);\n    //\n    // value graph routines\n    void fun2val( local::val_graph::tape_t<Base>& val_tape );\n    void val2fun(\n        const local::val_graph::tape_t<Base>&                   val_tape  ,\n        const CppAD::local::val_graph::Vector<size_t>&          dyn_ind   ,\n        const CppAD::local::val_graph::Vector<size_t>&          var_ind   ,\n        const CppAD::vectorBool&                                use_val\n    );\n    void val2fun(\n        const local::val_graph::tape_t<Base>&                   val_tape  ,\n        const CppAD::local::val_graph::Vector<size_t>&          dyn_ind   ,\n        const CppAD::local::val_graph::Vector<size_t>&          var_ind\n    );\n    void val_optimize(const std::string& options);\n\n    // create ADFun< AD<Base> > from this ADFun<Base>\n    // (doxygen in cppad/core/base2ad.hpp)\n    ADFun< AD<Base>, RecBase > base2ad(void) const;\n\n    /// sequence constructor\n    template <class ADvector>\n    ADFun(const ADvector &x, const ADvector &y);\n\n    /// destructor\n    ~ADFun(void);\n\n    /// set check_for_nan\n    void check_for_nan(bool value);\n\n    /// get check_for_nan\n    bool check_for_nan(void) const;\n\n    /// assign a new operation sequence\n    template <class ADvector>\n    void Dependent(const ADvector &x, const ADvector &y);\n\n    /// new_dynamic user API\n    template <class BaseVector>\n    void new_dynamic(const BaseVector& dynamic);\n\n    /// forward mode user API, one order multiple directions.\n    template <class BaseVector>\n    BaseVector Forward(size_t q, size_t r, const BaseVector& x);\n\n    /// forward mode user API, multiple orders one direction.\n    template <class BaseVector>\n    BaseVector Forward(\n        size_t q, const BaseVector& xq, std::ostream& s = std::cout\n    );\n\n    /// reverse mode sweep\n    template <class BaseVector>\n    BaseVector Reverse(size_t p, const BaseVector &v);\n\n    // forward Jacobian sparsity pattern\n    // (doxygen in cppad/core/for_sparse_jac.hpp)\n    template <class SetVector>\n    SetVector ForSparseJac(\n        size_t q, const SetVector &r, bool transpose = false,\n        bool dependency = false\n    );\n\n    // reverse Jacobian sparsity pattern\n    // (doxygen in cppad/core/rev_sparse_jac.hpp)\n    template <class SetVector>\n    SetVector RevSparseJac(\n        size_t q, const SetVector &s, bool transpose = false,\n        bool dependency = false\n    );\n\n    // subgraph_reverse: select domain\n    // (doxygen in cppad/core/subgraph_reverse.hpp)\n    template <class BoolVector>\n    void subgraph_reverse(\n        const BoolVector&                   select_domain\n    );\n\n    // subgraph_reverse: compute derivative\n    // (doxygen in cppad/core/subgraph_reverse.hpp)\n    template <class Addr, class BaseVector, class SizeVector>\n    void subgraph_reverse_helper(\n        size_t                               q         ,\n        size_t                               ell       ,\n        SizeVector&                          col       ,\n        BaseVector&                          dw\n    );\n\n    // subgraph_reverse: compute derivative\n    // (doxygen in cppad/core/subgraph_reverse.hpp)\n    template <class BaseVector, class SizeVector>\n    void subgraph_reverse(\n        size_t                               q         ,\n        size_t                               ell       ,\n        SizeVector&                          col       ,\n        BaseVector&                          dw\n    );\n\n    // subgraph_jac_rev: compute Jacobian\n    // (doxygen in cppad/core/subgraph_jac_rev.hpp)\n    template <class SizeVector, class BaseVector>\n    void subgraph_jac_rev(\n        const BaseVector&                    x         ,\n        sparse_rcv<SizeVector, BaseVector>&  subset\n    );\n\n    // subgraph_jac_rev: compute Jacobian\n    // (doxygen missing in cppad/core/subgraph_jac_rev.hpp)\n    template <class BoolVector, class SizeVector, class BaseVector>\n    void subgraph_jac_rev(\n        const BoolVector&                    select_domain ,\n        const BoolVector&                    select_range  ,\n        const BaseVector&                    x             ,\n        sparse_rcv<SizeVector, BaseVector>&  matrix_out\n    );\n\n\n    // compute sparse Jacobian using forward mode\n    // (doxygen in cppad/core/sparse_jac.hpp)\n    template <class SizeVector, class BaseVector>\n    size_t sparse_jac_for(\n        size_t                               group_max ,\n        const BaseVector&                    x         ,\n        sparse_rcv<SizeVector, BaseVector>&  subset    ,\n        const sparse_rc<SizeVector>&         pattern   ,\n        const std::string&                   coloring  ,\n        sparse_jac_work&                     work\n    );\n\n    // compute sparse Jacobian using reverse mode\n    // (doxygen in cppad/core/sparse_jac.hpp)\n    template <class SizeVector, class BaseVector>\n    size_t sparse_jac_rev(\n        const BaseVector&                    x        ,\n        sparse_rcv<SizeVector, BaseVector>&  subset   ,\n        const sparse_rc<SizeVector>&         pattern  ,\n        const std::string&                   coloring ,\n        sparse_jac_work&                     work\n    );\n\n    // compute sparse Hessian\n    // (doxygen in cppad/core/sparse_hes.hpp)\n    template <class SizeVector, class BaseVector>\n    size_t sparse_hes(\n        const BaseVector&                    x        ,\n        const BaseVector&                    w        ,\n        sparse_rcv<SizeVector, BaseVector>&  subset   ,\n        const sparse_rc<SizeVector>&         pattern  ,\n        const std::string&                   coloring ,\n        sparse_hes_work&                     work\n    );\n\n    // compute sparsity pattern using subgraphs\n    // (doxygen in cppad/core/subgraph_sparsity.hpp)\n    template <class BoolVector, class SizeVector>\n    void subgraph_sparsity(\n        const BoolVector&            select_domain    ,\n        const BoolVector&            select_range     ,\n        bool                         transpose        ,\n        sparse_rc<SizeVector>&       pattern_out\n    );\n\n\n    // forward mode Jacobian sparsity pattern\n    // (doxygen in cppad/core/for_jac_sparsity.hpp)\n    template <class SizeVector>\n    void for_jac_sparsity(\n        const sparse_rc<SizeVector>& pattern_in       ,\n        bool                         transpose        ,\n        bool                         dependency       ,\n        bool                         internal_bool    ,\n        sparse_rc<SizeVector>&       pattern_out\n    );\n\n    // reverse mode Jacobian sparsity pattern\n    // (doxygen in cppad/core/for_jac_sparsity.hpp)\n    template <class SizeVector>\n    void rev_jac_sparsity(\n        const sparse_rc<SizeVector>& pattern_in       ,\n        bool                         transpose        ,\n        bool                         dependency       ,\n        bool                         internal_bool    ,\n        sparse_rc<SizeVector>&       pattern_out\n    );\n\n    // reverse mode Hessian sparsity pattern\n    // (doxygen in cppad/core/rev_hes_sparsity.hpp)\n    template <class BoolVector, class SizeVector>\n    void rev_hes_sparsity(\n        const BoolVector&            select_range     ,\n        bool                         transpose        ,\n        bool                         internal_bool    ,\n        sparse_rc<SizeVector>&       pattern_out\n    );\n\n    // forward mode Hessian sparsity pattern\n    // (doxygen in cppad/core/for_hes_sparsity.hpp)\n    template <class BoolVector, class SizeVector>\n    void for_hes_sparsity(\n        const BoolVector&            select_domain    ,\n        const BoolVector&            select_range     ,\n        bool                         internal_bool    ,\n        sparse_rc<SizeVector>&       pattern_out\n    );\n\n    // forward mode Hessian sparsity pattern\n    // (see doxygen in cppad/core/for_sparse_hes.hpp)\n    template <class SetVector>\n    SetVector ForSparseHes(\n        const SetVector &r, const SetVector &s\n    );\n\n    // internal set sparsity version of ForSparseHes\n    // (used by checkpoint functions only)\n    void ForSparseHesCheckpoint(\n        vector<bool>&                 r         ,\n        vector<bool>&                 s         ,\n        local::sparse::list_setvec&   h\n    );\n\n    // reverse mode Hessian sparsity pattern\n    // (see doxygen in cppad/core/rev_sparse_hes.hpp)\n    template <class SetVector>\n    SetVector RevSparseHes(\n        size_t q, const SetVector &s, bool transpose = false\n    );\n\n    // internal set sparsity version of RevSparseHes\n    // (doxygen in cppad/core/rev_sparse_hes.hpp)\n    // (used by checkpoint functions only)\n    void RevSparseHesCheckpoint(\n        size_t                        q         ,\n        vector<bool>&                 s         ,\n        bool                          transpose ,\n        local::sparse::list_setvec&   h\n    );\n\n    // internal set sparsity version of RevSparseJac\n    // (doxygen in cppad/core/rev_sparse_jac.hpp)\n    // (used by checkpoint functions only)\n    void RevSparseJacCheckpoint(\n        size_t                        q          ,\n        const local::sparse::list_setvec&     r          ,\n        bool                          transpose  ,\n        bool                          dependency ,\n        local::sparse::list_setvec&   s\n    );\n\n    // internal set sparsity version of RevSparseJac\n    // (doxygen in cppad/core/for_sparse_jac.hpp)\n    // (used by checkpoint functions only)\n    void ForSparseJacCheckpoint(\n    size_t                             q          ,\n    const local::sparse::list_setvec&  r          ,\n    bool                               transpose  ,\n    bool                               dependency ,\n    local::sparse::list_setvec&        s\n    );\n\n    /// did previous optimization exceed the collision limit\n    bool exceed_collision_limit(void) const\n    {   return exceed_collision_limit_; }\n\n    /// amount of memory used for boolean Jacobain sparsity pattern\n    size_t size_forward_bool(void) const\n    {   return for_jac_sparse_pack_.memory(); }\n\n    /// free memory used for Jacobain sparsity pattern\n    void size_forward_bool(size_t zero)\n    {   CPPAD_ASSERT_KNOWN(\n            zero == 0,\n            \"size_forward_bool: argument not equal to zero\"\n        );\n        for_jac_sparse_pack_.resize(0, 0);\n    }\n\n    /// amount of memory used for vector of set Jacobain sparsity pattern\n    size_t size_forward_set(void) const\n    {   return for_jac_sparse_set_.memory(); }\n\n    /// free memory used for Jacobain sparsity pattern\n    void size_forward_set(size_t zero)\n    {   CPPAD_ASSERT_KNOWN(\n            zero == 0,\n            \"size_forward_bool: argument not equal to zero\"\n        );\n        for_jac_sparse_set_.resize(0, 0);\n    }\n\n    /// number of operators in the operation sequence\n    size_t size_op(void) const\n    {   return play_.num_var_op(); }\n\n    /// number of operator arguments in the operation sequence\n    size_t size_op_arg(void) const\n    {   return play_.num_var_arg(); }\n\n    /// amount of memory required for the operation sequence\n    size_t size_op_seq(void) const\n    {   return play_.size_op_seq(); }\n\n    /// amount of memory currently allocated for random access\n    /// of the operation sequence\n    size_t size_random(void) const\n    {   return play_.size_random(); }\n\n    /// number of parameters in the operation sequence\n    size_t size_par(void) const\n    {   return play_.num_par_all(); }\n\n    /// number of independent dynamic parameters\n    size_t size_dyn_ind(void) const\n    {   return play_.n_dyn_independent(); }\n\n    /// number of dynamic parameters\n    size_t size_dyn_par(void) const\n    {   return play_.num_dynamic_par(); }\n\n    /// number of dynamic parameters arguments\n    size_t size_dyn_arg(void) const\n    {   return play_.num_dynamic_arg(); }\n\n    /// number taylor coefficient orders calculated\n    size_t size_order(void) const\n    {   return num_order_taylor_; }\n\n    /// number taylor coefficient directions calculated\n    size_t size_direction(void) const\n    {   return num_direction_taylor_; }\n\n    /// number of characters in the operation sequence\n    size_t size_text(void) const\n    {   return play_.num_var_text(); }\n\n    /// number of variables in operation sequence\n    size_t size_var(void) const\n    {   return num_var_tape_; }\n\n    /// number of VecAD indices in the operation sequence\n    size_t size_VecAD(void) const\n    {   return play_.num_var_vec_ind(); }\n\n    /// set number of orders currently allocated (user API)\n    void capacity_order(size_t c);\n\n    /// set number of orders and directions currently allocated\n    void capacity_order(size_t c, size_t r);\n\n    /// number of variables in conditional expressions that can be skipped\n    size_t number_skip(void);\n\n    /// number of independent variables\n    size_t Domain(void) const\n    {   return ind_taddr_.size(); }\n\n    /// number of dependent variables\n    size_t Range(void) const\n    {   return dep_taddr_.size(); }\n\n    /// set and get function name\n    void function_name_set(const std::string& function_name)\n    {   function_name_ = function_name; }\n    std::string function_name_get(void)\n    {   return function_name_; }\n\n    /// is variable a parameter\n    bool Parameter(size_t i)\n    {   CPPAD_ASSERT_KNOWN(\n            i < dep_taddr_.size(),\n            \"Argument to Parameter is >= dimension of range space\"\n        );\n        return dep_parameter_[i];\n    }\n\n    /// Deprecated: number of comparison operations that changed\n    /// for the previous zero order forward (than when function was recorded)\n    size_t CompareChange(void) const\n    {   return compare_change_number_; }\n\n    /// count as which to store operator index\n    void compare_change_count(size_t count)\n    {   compare_change_count_    = count;\n        compare_change_number_   = 0;\n        compare_change_op_index_ = 0;\n    }\n\n    /// number of comparison operations that changed\n    size_t compare_change_number(void) const\n    {   return compare_change_number_; }\n\n    /// operator index for the count-th  comparison change\n    size_t compare_change_op_index(void) const\n    {   if( has_been_optimized_ )\n            return 0;\n        return compare_change_op_index_;\n    }\n\n    /// calculate entire Jacobian\n    template <class BaseVector>\n    BaseVector Jacobian(const BaseVector &x);\n\n    /// calculate Hessian for one component of f\n    template <class BaseVector>\n    BaseVector Hessian(const BaseVector &x, const BaseVector &w);\n    template <class BaseVector>\n    BaseVector Hessian(const BaseVector &x, size_t i);\n\n    /// forward mode calculation of partial w.r.t one domain component\n    template <class BaseVector>\n    BaseVector ForOne(\n        const BaseVector   &x ,\n        size_t              j );\n\n    /// reverse mode calculation of derivative of one range component\n    template <class BaseVector>\n    BaseVector RevOne(\n        const BaseVector   &x ,\n        size_t              i );\n\n    /// forward mode calculation of a subset of second order partials\n    template <class BaseVector, class SizeVector_t>\n    BaseVector ForTwo(\n        const BaseVector   &x ,\n        const SizeVector_t &J ,\n        const SizeVector_t &K );\n\n    /// reverse mode calculation of a subset of second order partials\n    template <class BaseVector, class SizeVector_t>\n    BaseVector RevTwo(\n        const BaseVector   &x ,\n        const SizeVector_t &I ,\n        const SizeVector_t &J );\n\n    /// calculate sparse Jacobians\n    template <class BaseVector>\n    BaseVector SparseJacobian(\n        const BaseVector &x\n    );\n    template <class BaseVector, class SetVector>\n    BaseVector SparseJacobian(\n        const BaseVector &x ,\n        const SetVector  &p\n    );\n    template <class BaseVector, class SetVector, class SizeVector>\n    size_t SparseJacobianForward(\n        const BaseVector&     x     ,\n        const SetVector&      p     ,\n        const SizeVector&     r     ,\n        const SizeVector&     c     ,\n        BaseVector&           jac   ,\n        sparse_jacobian_work& work\n    );\n    template <class BaseVector, class SetVector, class SizeVector>\n    size_t SparseJacobianReverse(\n        const BaseVector&     x    ,\n        const SetVector&      p    ,\n        const SizeVector&     r    ,\n        const SizeVector&     c    ,\n        BaseVector&           jac  ,\n        sparse_jacobian_work& work\n    );\n\n    /// calculate sparse Hessians\n    template <class BaseVector>\n    BaseVector SparseHessian(\n        const BaseVector&    x  ,\n        const BaseVector&    w\n    );\n    template <class BaseVector, class BoolVector>\n    BaseVector SparseHessian(\n        const BaseVector&    x  ,\n        const BaseVector&    w  ,\n        const BoolVector&    p\n    );\n    template <class BaseVector, class SetVector, class SizeVector>\n    size_t SparseHessian(\n        const BaseVector&    x   ,\n        const BaseVector&    w   ,\n        const SetVector&     p   ,\n        const SizeVector&    r   ,\n        const SizeVector&    c   ,\n        BaseVector&          hes ,\n        sparse_hessian_work& work\n    );\n\n    // Optimize the tape\n    // (see doxygen documentation in optimize.hpp)\n    void optimize( const std::string& options = \"\" );\n\n    // create abs-normal representation of the function f(x)\n    void abs_normal_fun( ADFun& g, ADFun& a ) const;\n\n    // clear all subgraph information\n    void clear_subgraph(void);\n    // ------------------- Deprecated -----------------------------\n\n    /// deprecated: assign a new operation sequence\n    template <class ADvector>\n    void Dependent(const ADvector &y);\n\n    /// Deprecated: number of variables in operation sequence\n    size_t Size(void) const\n    {   return num_var_tape_; }\n\n    /// Deprecated: # taylor_ coefficients currently stored\n    /// (per variable,direction)\n    size_t Order(void) const\n    {   return num_order_taylor_ - 1; }\n\n    /// Deprecated: amount of memory for this object\n    /// Note that an approximation is used for the std::set<size_t> memory\n    size_t Memory(void) const\n    {   size_t pervar  = cap_order_taylor_ * sizeof(Base)\n        + for_jac_sparse_pack_.memory()\n        + for_jac_sparse_set_.memory();\n        size_t total   = num_var_tape_  * pervar;\n        total         += play_.size_op_seq();\n        total         += play_.size_random();\n        total         += subgraph_info_.memory();\n        return total;\n    }\n\n    /// Deprecated: # taylor_ coefficient orderss stored\n    /// (per variable,direction)\n    size_t taylor_size(void) const\n    {   return num_order_taylor_; }\n\n    /// Deprecated: Does this AD operation sequence use\n    /// VecAD<Base>::reference operands\n    bool use_VecAD(void) const\n    {   return play_.num_var_vec_ind() > 0; }\n\n    /// Deprecated: # taylor_ coefficient orders calculated\n    /// (per variable,direction)\n    size_t size_taylor(void) const\n    {   return num_order_taylor_; }\n\n    /// Deprecated: set number of orders currently allocated\n    /// (per variable,direction)\n    void capacity_taylor(size_t per_var);\n};\n// ---------------------------------------------------------------------------\n\n} // END_CPPAD_NAMESPACE\n\n// non-user interfaces\n# include <cppad/local/sweep/forward_0.hpp>\n# include <cppad/local/sweep/forward_any.hpp>\n# include <cppad/local/sweep/forward_dir.hpp>\n# include <cppad/local/sweep/reverse.hpp>\n# include <cppad/local/sweep/for_jac.hpp>\n# include <cppad/local/sweep/rev_jac.hpp>\n# include <cppad/local/sweep/rev_hes.hpp>\n# include <cppad/local/sweep/for_hes.hpp>\n# include <cppad/core/graph/from_graph.hpp>\n# include <cppad/core/graph/to_graph.hpp>\n\n// user interfaces\n# include <cppad/core/parallel_ad.hpp>\n# include <cppad/core/independent/independent.hpp>\n# include <cppad/core/dependent.hpp>\n# include <cppad/core/fun_construct.hpp>\n# include <cppad/core/base2ad.hpp>\n# include <cppad/core/abort_recording.hpp>\n# include <cppad/core/fun_eval.hpp>\n# include <cppad/core/drivers.hpp>\n# include <cppad/core/fun_check.hpp>\n# include <cppad/core/omp_max_thread.hpp>\n# include <cppad/core/optimize.hpp>\n# include <cppad/core/abs_normal_fun.hpp>\n# include <cppad/core/graph/from_json.hpp>\n# include <cppad/core/graph/to_json.hpp>\n# include <cppad/core/to_csrc.hpp>\n\n// 2DO: move to core directory\n# include <cppad/local/val_graph/val_optimize.hpp>\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/ad_fun.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin record_adfun}\n\nCreate an ADFun Object by Recording an Operation Sequence\n#########################################################\n\nContents\n********\n{xrst_toc_table\n    include/cppad/core/independent/user.xrst\n    include/cppad/core/fun_construct.hpp\n    include/cppad/core/dependent.hpp\n    include/cppad/core/abort_recording.hpp\n    include/cppad/core/fun_property.xrst\n    include/cppad/core/function_name.xrst\n}\n\n{xrst_end record_adfun}\n-------------------------------------------------------------------------------\n{xrst_begin other_adfun}\n{xrst_spell\n    dyn\n}\n\nOther Ways to Create an ADFun Object\n####################################\n\nContents\n********\n{xrst_toc_table\n    include/cppad/core/base2ad.hpp\n    include/cppad/core/graph/json_ad_graph.xrst\n    include/cppad/core/graph/cpp_ad_graph.xrst\n    include/cppad/core/abs_normal_fun.hpp\n}\n\nSee Also\n********\n\n.. csv-table::\n    :widths: auto\n\n    switch_var_dyn.cpp,:ref:`switch_var_dyn.cpp-title`\n\n{xrst_end other_adfun}\n-------------------------------------------------------------------------------\n{xrst_begin drivers}\n\nFirst and Second Order Derivatives: Easy Drivers\n################################################\n\nContents\n********\n{xrst_toc_table\n    include/cppad/core/jacobian.hpp\n    include/cppad/core/hessian.hpp\n    include/cppad/core/for_one.hpp\n    include/cppad/core/rev_one.hpp\n    include/cppad/core/for_two.hpp\n    include/cppad/core/rev_two.hpp\n}\n\n{xrst_end drivers}\n-------------------------------------------------------------------------------\n{xrst_begin Forward}\n\nForward Mode\n############\n\nContents\n********\n{xrst_toc_table\n    include/cppad/core/new_dynamic.hpp\n    include/cppad/core/forward/forward_zero.xrst\n    include/cppad/core/forward/forward_one.xrst\n    include/cppad/core/forward/forward_two.xrst\n    include/cppad/core/forward/forward_order.xrst\n    include/cppad/core/forward/forward_dir.xrst\n    include/cppad/core/forward/size_order.xrst\n    include/cppad/core/forward/compare_change.xrst\n    include/cppad/core/capacity_order.hpp\n    include/cppad/core/num_skip.hpp\n}\n\n{xrst_end Forward}\n-------------------------------------------------------------------------------\n{xrst_begin Reverse}\n{xrst_spell\n    xq\n}\n\nReverse Mode\n############\n\nMultiple Directions\n*******************\nReverse mode after :ref:`Forward(q, r, xq)<forward_dir-name>`\nwith number of directions *r*  != 1 is not yet supported.\nThere is one exception, :ref:`reverse_one-name` is allowed\nbecause there is only one zero order forward direction.\nAfter such an operation, only the zero order forward\nresults are retained (the higher order forward results are lost).\n\nContents\n********\n{xrst_toc_table\n    xrst/reverse/reverse_one.xrst\n    xrst/reverse/reverse_two.xrst\n    xrst/reverse/reverse_any.xrst\n    include/cppad/core/subgraph_reverse.hpp\n}\n\n{xrst_end Reverse}\n-------------------------------------------------------------------------------\n{xrst_begin sparsity_pattern}\n{xrst_spell\n    subgraph\n}\n\nCalculating Sparsity Patterns\n#############################\n{xrst_toc_hidden\n    include/cppad/core/for_jac_sparsity.hpp\n    include/cppad/core/rev_jac_sparsity.hpp\n    include/cppad/core/for_hes_sparsity.hpp\n    include/cppad/core/rev_hes_sparsity.hpp\n    include/cppad/core/subgraph_sparsity.hpp\n    example/sparse/dependency.cpp\n    example/sparse/rc_sparsity.cpp\n    include/cppad/core/for_sparse_jac.hpp\n    include/cppad/core/rev_sparse_jac.hpp\n    include/cppad/core/rev_sparse_hes.hpp\n    include/cppad/core/for_sparse_hes.hpp\n}\n\nPreferred Sparsity Pattern Calculations\n***************************************\n\n.. csv-table::\n    :widths: auto\n\n    for_jac_sparsity,:ref:`for_jac_sparsity-title`\n    rev_jac_sparsity,:ref:`rev_jac_sparsity-title`\n    for_hes_sparsity,:ref:`for_hes_sparsity-title`\n    rev_hes_sparsity,:ref:`rev_hes_sparsity-title`\n    subgraph_sparsity,:ref:`subgraph_sparsity-title`\n\nOld Sparsity Pattern Calculations\n*********************************\n\n.. csv-table::\n    :widths: auto\n\n    ForSparseJac,:ref:`ForSparseJac-title`\n    RevSparseJac,:ref:`RevSparseJac-title`\n    ForSparseHes,:ref:`ForSparseHes-title`\n    RevSparseHes,:ref:`RevSparseHes-title`\n\n{xrst_end sparsity_pattern}\n-------------------------------------------------------------------------------\n{xrst_begin sparse_derivative}\n{xrst_spell\n    subgraph\n}\n\nCalculating Sparse Derivatives\n##############################\n{xrst_toc_hidden\n    include/cppad/core/sparse_jac.hpp\n    include/cppad/core/sparse_jacobian.hpp\n    include/cppad/core/sparse_hes.hpp\n    include/cppad/core/sparse_hessian.hpp\n    include/cppad/core/subgraph_jac_rev.hpp\n}\n\nPreferred Sparsity Patterns\n***************************\n\n.. csv-table::\n    :widths: auto\n\n    sparse_jac,:ref:`sparse_jac-title`\n    sparse_hes,:ref:`sparse_hes-title`\n    subgraph_jac_rev,:ref:`subgraph_jac_rev-title`\n\nOld Sparsity Patterns\n*********************\n\n.. csv-table::\n    :widths: auto\n\n    sparse_jacobian,:ref:`sparse_jacobian-title`\n    sparse_hessian,:ref:`sparse_hessian-title`\n\n{xrst_end sparse_derivative}\n-------------------------------------------------------------------------------\n"
  },
  {
    "path": "include/cppad/core/ad_io.hpp",
    "content": "# ifndef CPPAD_CORE_AD_IO_HPP\n# define CPPAD_CORE_AD_IO_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin ad_input}\n{xrst_spell\n    istream\n}\n\nAD Input Stream Operator\n########################\n\nSyntax\n******\n| *is* >> *x*\n\nPurpose\n*******\nSets *x* to a :ref:`glossary@Parameter`\nwith value *b* corresponding to\n\n    *is* >> *b*\n\nwhere *b* is a *Base* object.\nIt is assumed that this *Base* input operation returns\na reference to *is* .\n\nis\n**\nThe operand *is* has prototype\n\n    ``std::istream&`` *is*\n\nx\n*\nThe operand *x* has one of the following prototypes\n\n    ``AD`` < *Base* >& *x*\n\nResult\n******\nThe result of this operation can be used as a reference to *is* .\nFor example, if the operand *y* has prototype\n\n    ``AD`` < *Base* > *y*\n\nthen the syntax\n\n    *is* >> *x* >> *y*\n\nwill first read the *Base* value of *x* from *is* ,\nand then read the *Base* value to *y* .\n\nOperation Sequence\n******************\nThe result of this operation is not an\n:ref:`glossary@AD of Base` object.\nThus it will not be recorded as part of an\nAD of *Base*\n:ref:`operation sequence<glossary@Operation@Sequence>` .\n\nExample\n*******\n{xrst_toc_hidden\n    example/general/ad_input.cpp\n}\nThe file\n:ref:`ad_input.cpp-name`\ncontains an example and test of this operation.\n\n{xrst_end ad_input}\n------------------------------------------------------------------------------\n{xrst_begin ad_output}\n{xrst_spell\n    ostream\n}\n\nAD Output Stream Operator\n#########################\n\nSyntax\n******\n*os* << *x*\n\nSee Also\n********\n:ref:`PrintFor-name`\n\nPurpose\n*******\nWrites the *Base* value, corresponding to *x* ,\nto the output stream *os* .\n\nAssumption\n**********\nIf *b* is a *Base* object,\n\n    *os* << *b*\n\nreturns a reference to *os* .\n\nos\n**\nThe operand *os* has prototype\n\n    ``std::ostream&`` *os*\n\nx\n*\nThe operand *x* has one of the following prototypes\n\n| |tab| ``const AD`` < *Base* >& *x*\n| |tab| ``const VecAD`` < *Base* >:: ``reference&`` *x*\n\nResult\n******\nThe result of this operation can be used as a reference to *os* .\nFor example, if the operand *y* has prototype\n\n    ``AD`` < *Base* > *y*\n\nthen the syntax\n\n    *os* << *x* << *y*\n\nwill output the value corresponding to *x*\nfollowed by the value corresponding to *y* .\n\nOperation Sequence\n******************\nThe result of this operation is not an\n:ref:`glossary@AD of Base` object.\nThus it will not be recorded as part of an\nAD of *Base*\n:ref:`operation sequence<glossary@Operation@Sequence>` .\n\nExample\n*******\n{xrst_toc_hidden\n    example/general/ad_output.cpp\n}\nThe file\n:ref:`ad_output.cpp-name`\ncontains an example and test of this operation.\n\n{xrst_end ad_output}\n------------------------------------------------------------------------------\n*/\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\n\\file ad_io.hpp\nAD<Base> input and output stream operators.\n*/\n// ---------------------------------------------------------------------------\n/*!\nRead an AD<Base> object from an input stream.\n\n\\tparam Base\nBase type for the AD object.\n\n\\param is [in,out]\nIs the input stream from which that value is read.\n\n\\param x [out]\nis the object that is being set to a value.\nUpone return, x.value_ is read from the input stream\nand x.tape_is_ is zero; i.e., x is a parameter.\n*/\ntemplate <class Base>\nCPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION\nstd::istream& operator >> (std::istream& is, AD<Base>& x)\n{   // like assignment to a base type value\n    x.tape_id_ = 0;\n    CPPAD_ASSERT_UNKNOWN( Parameter(x) );\n    return (is >> x.value_);\n}\n// ---------------------------------------------------------------------------\n/*!\nWrite an AD<Base> object to an output stream.\n\n\\tparam Base\nBase type for the AD object.\n\n\\param os [in,out]\nIs the output stream to which that value is written.\n\n\\param x\nis the object that is being written to the output stream.\nThis is equivalent to writing x.value_ to the output stream.\n*/\ntemplate <class Base>\nCPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION\nstd::ostream& operator << (std::ostream &os, const AD<Base> &x)\n{   return (os << x.value_); }\n// ---------------------------------------------------------------------------\n/*!\nWrite a VecAD_reference<Base> object to an output stream.\n\n\\tparam Base\nBase type for the VecAD_reference object.\n\n\\param os [in,out]\nIs the output stream to which that value is written.\n\n\\param x\nis the element of the VecAD object that is being written to the output stream.\nThis is equivalent to writing the corresponding Base value to the stream.\n*/\ntemplate <class Base>\nCPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION\nstd::ostream& operator << (std::ostream &os, const VecAD_reference<Base> &x)\n{   return (os << x.ADBase()); }\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/ad_to_string.hpp",
    "content": "# ifndef CPPAD_CORE_AD_TO_STRING_HPP\n# define CPPAD_CORE_AD_TO_STRING_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin ad_to_string}\n\nConvert An AD or Base Type to String\n####################################\n\nSyntax\n******\n| *s* = ``to_string`` ( *value* ) .\n\nSee Also\n********\n:ref:`to_string-name` , :ref:`base_to_string-name`\n\nvalue\n*****\nThe argument *value* has prototype\n\n| |tab| ``const AD`` < *Base* >& *value*\n| |tab| ``const`` *Base* & *value*\n\nwhere *Base* is a type that supports the\n:ref:`base_to_string-name` type requirement.\n\ns\n*\nThe return value has prototype\n\n    ``std::string`` *s*\n\nand contains a representation of the specified *value* .\nIf *value* is an AD type,\nthe result has the same precision as for the *Base* type.\n\nExample\n*******\nThe file :ref:`to_string.cpp-name`\nincludes an example and test of ``to_string`` with AD types.\n\n{xrst_end ad_to_string}\n*/\n# include <cppad/utility/to_string.hpp>\n# include <cppad/core/ad.hpp>\n\nnamespace CppAD {\n\n    // Template definition is in cppad/utility/to_string.hpp.\n    // Partial specialzation for AD<Base> types\n    template<class Base>\n    struct to_string_struct< CppAD::AD<Base> >\n    {   std::string operator()(const CppAD::AD<Base>& value)\n        {   to_string_struct<Base> ts;\n            return ts( Value( Var2Par( value ) ) ); }\n    };\n\n}\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/ad_type.hpp",
    "content": "# ifndef CPPAD_CORE_AD_TYPE_HPP\n# define CPPAD_CORE_AD_TYPE_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/local/is_pod.hpp>\n\n# ifdef NDEBUG\n# define CPPAD_ASSERT_AD_TYPE(ad_obj)\n# else\n# define CPPAD_ASSERT_AD_TYPE(ad_obj)               \\\n    switch(ad_obj.ad_type_)                          \\\n    {   case constant_enum:                           \\\n        CPPAD_ASSERT_UNKNOWN( ad_obj.tape_id_ == 0 ); \\\n        break;                                        \\\n                                                                     \\\n        case dynamic_enum:                            \\\n        case variable_enum:                           \\\n        break;                                        \\\n                                                                     \\\n        default:                                      \\\n        CPPAD_ASSERT_UNKNOWN(false);                  \\\n    }                                                \\\n    CPPAD_ASSERT_UNKNOWN(                            \\\n        ad_obj.tape_id_ == 0 ||                       \\\n        ad_obj.ad_type_ == dynamic_enum ||            \\\n        ad_obj.ad_type_ == variable_enum              \\\n    );\n# endif\n\n\nnamespace CppAD {\n    // BEGIN TYPEDEF\n    typedef enum {\n        identical_zero_enum,      // identically zero\n        constant_enum,            // constant parameter\n        dynamic_enum,             // dynamic parameter\n        variable_enum,            // variable\n        number_ad_type_enum       // number of valid values for type_ad_enum\n    } ad_type_enum;\n    // END TYPEDEF\n\n    // BEGIN IS_POD\n    namespace local {\n        template <> inline bool\n        is_pod<ad_type_enum>(void) { return true; }\n    }\n    // END IS_POD\n}\n\n\n/*\n{xrst_begin ad_type_enum dev}\n{xrst_spell\n    typedef\n}\n\nType of AD an Object\n####################\n\ntypedef\n*******\nThis typedef is in the ``CppAD`` namespace:\n{xrst_literal\n    // BEGIN TYPEDEF\n    // END TYPEDEF\n}\n\nis_pod\n******\nThe following informs :ref:`is_pod-name` that this is plain old data.\n{xrst_literal\n    // BEGIN IS_POD\n    // END IS_POD\n}\n\nAtomic Function\n***************\nOnly some of the values are valid for the user atomic function API; see\n:ref:`atomic_three<atomic_three_define@ad_type>` and\n:ref:`atomic_four<atomic_four_for_type@ad_type>` .\n\nASSERT_AD_TYPE\n**************\nIf *ad_obj* is an ``AD`` < *Base* > object, the syntax\n\n    ``CPPAD_ASSERT_AD_TYPE`` ( *ad_obj* )\n\ncheck that *ad_obj* satisfies the following conditions:\n\n#. *ad_obj* . ``ad_type_`` is one of the following:\n   ``constant_enum`` , ``dynamic_enum`` , ``variable_enum`` .\n#. *ad_obj* . ``ad_type_`` is ``constant_enum`` , then\n   *ad_obj* . ``tape_id_`` == 0 .\n\n{xrst_end ad_type_enum}\n*/\n\n\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/ad_valued.hpp",
    "content": "# ifndef CPPAD_CORE_AD_VALUED_HPP\n# define CPPAD_CORE_AD_VALUED_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin ADValued}\n\nAD Valued Operations and Functions\n##################################\n\n{xrst_comment atomic.omh includes atomic_two.hpp}\n\nContents\n********\n{xrst_toc_table\n    include/cppad/core/arithmetic.hpp\n    include/cppad/core/standard_math.hpp\n    include/cppad/core/cond_exp.hpp\n    include/cppad/core/discrete/user.xrst\n    include/cppad/core/numeric_limits.hpp\n    include/cppad/core/atomic/atomic.xrst\n}\n\n{xrst_end ADValued}\n*/\n\n// include MathOther.h after CondExp.h because some MathOther.h routines use\n// CondExp.h and CondExp.h is not sufficiently declared in Declare.h\n\n# include <cppad/core/arithmetic.hpp>\n# include <cppad/core/standard_math.hpp>\n# include <cppad/core/azmul.hpp>\n# include <cppad/core/cond_exp.hpp>\n# include <cppad/core/discrete/discrete.hpp>\n# include <cppad/core/atomic/four/atomic.hpp>\n# include <cppad/core/atomic/three/atomic.hpp>\n# include <cppad/core/atomic/four/atomic.hpp>\n# include <cppad/core/chkpoint_two/chkpoint_two.hpp>\n# include <cppad/core/atomic/two/atomic.hpp>\n# include <cppad/core/atomic/one/atomic.hpp>\n# include <cppad/core/chkpoint_one/chkpoint_one.hpp>\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/add.hpp",
    "content": "# ifndef CPPAD_CORE_ADD_HPP\n# define CPPAD_CORE_ADD_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n//  BEGIN CppAD namespace\nnamespace CppAD {\n\ntemplate <class Base>\nAD<Base> operator + (const AD<Base> &left , const AD<Base> &right)\n{\n    // compute the Base part of this AD object\n    AD<Base> result;\n    result.value_  = left.value_ + right.value_;\n    CPPAD_ASSERT_UNKNOWN( Parameter(result) );\n\n    // check if there is a recording in progress\n    local::ADTape<Base>* tape = AD<Base>::tape_ptr();\n    if( tape == nullptr )\n        return result;\n    tape_id_t tape_id = tape->id_;\n    // tape_id cannot match the default value for tape_id_; i.e., 0\n    CPPAD_ASSERT_UNKNOWN( tape_id > 0 );\n\n    // check if left and right tapes match\n    bool match_left  = left.tape_id_  == tape_id;\n    bool match_right = right.tape_id_ == tape_id;\n\n    // check if left and right are dynamic parameters\n    bool dyn_left  = match_left  & (left.ad_type_ == dynamic_enum);\n    bool dyn_right = match_right & (right.ad_type_ == dynamic_enum);\n\n    // check if left and right are variables\n    bool var_left  = match_left  & (left.ad_type_ != dynamic_enum);\n    bool var_right = match_right & (right.ad_type_ != dynamic_enum);\n\n    CPPAD_ASSERT_KNOWN(\n        left.tape_id_ == right.tape_id_ || ! match_left || ! match_right ,\n        \"Add: AD variables or dynamic parameters on different threads.\"\n    );\n    if( var_left )\n    {   if( var_right )\n        {   // result = variable + variable\n            CPPAD_ASSERT_UNKNOWN( local::NumRes(local::AddvvOp) == 1 );\n            CPPAD_ASSERT_UNKNOWN( local::NumArg(local::AddvvOp) == 2 );\n\n            // put operand addresses in tape\n            tape->Rec_.PutArg(left.taddr_, right.taddr_);\n            // put operator in the tape\n            result.taddr_ = tape->Rec_.PutOp(local::AddvvOp);\n            // make result a variable\n            result.tape_id_ = tape_id;\n            result.ad_type_ = variable_enum;\n        }\n        else if( (! dyn_right) && IdenticalZero(right.value_) )\n        {   // result = variable + 0\n            result.make_variable(left.tape_id_, left.taddr_);\n        }\n        else\n        {   // result = variable  + parameter\n            //        = parameter + variable\n            CPPAD_ASSERT_UNKNOWN( local::NumRes(local::AddpvOp) == 1 );\n            CPPAD_ASSERT_UNKNOWN( local::NumArg(local::AddpvOp) == 2 );\n\n            // put operand addresses in tape\n            addr_t p = right.taddr_;\n            if( ! dyn_right )\n                p = tape->Rec_.put_con_par(right.value_);\n            tape->Rec_.PutArg(p, left.taddr_);\n            // put operator in the tape\n            result.taddr_ = tape->Rec_.PutOp(local::AddpvOp);\n            // make result a variable\n            result.tape_id_ = tape_id;\n            result.ad_type_ = variable_enum;\n        }\n    }\n    else if( var_right )\n    {   if( (! dyn_left) && IdenticalZero(left.value_) )\n        {   // result = 0 + variable\n            result.make_variable(right.tape_id_, right.taddr_);\n        }\n        else\n        {   // result = parameter + variable\n            CPPAD_ASSERT_UNKNOWN( local::NumRes(local::AddpvOp) == 1 );\n            CPPAD_ASSERT_UNKNOWN( local::NumArg(local::AddpvOp) == 2 );\n\n            // put operand addresses in tape\n            addr_t p = left.taddr_;\n            if( ! dyn_left )\n                p = tape->Rec_.put_con_par(left.value_);\n            tape->Rec_.PutArg(p, right.taddr_);\n            // put operator in the tape\n            result.taddr_ = tape->Rec_.PutOp(local::AddpvOp);\n            // make result a variable\n            result.tape_id_ = tape_id;\n            result.ad_type_ = variable_enum;\n        }\n    }\n    else if( dyn_left | dyn_right )\n    {   if( (! dyn_left) && IdenticalZero(left.value_) )\n        {\n            result.make_dynamic(right.tape_id_, right.taddr_);\n        }\n        else if( (! dyn_right) && IdenticalZero(right.value_) )\n        {\n            result.make_dynamic(left.tape_id_, left.taddr_);\n        }\n        else\n        {\n            addr_t arg0 = left.taddr_;\n            addr_t arg1 = right.taddr_;\n            if( ! dyn_left )\n            arg0 = tape->Rec_.put_con_par(left.value_);\n            if( ! dyn_right )\n            arg1 = tape->Rec_.put_con_par(right.value_);\n            //\n            // parameters with a dynamic parameter result\n            result.taddr_   = tape->Rec_.put_dyn_par(\n                result.value_, local::add_dyn,   arg0, arg1\n            );\n            result.tape_id_ = tape_id;\n            result.ad_type_ = dynamic_enum;\n        }\n    }\n    return result;\n}\n\n// convert other cases into the case above\nCPPAD_FOLD_AD_VALUED_BINARY_OPERATOR(+)\n\n} // END CppAD namespace\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/add_eq.hpp",
    "content": "# ifndef CPPAD_CORE_ADD_EQ_HPP\n# define CPPAD_CORE_ADD_EQ_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n//  BEGIN CppAD namespace\nnamespace CppAD {\n\ntemplate <class Base>\nAD<Base>& AD<Base>::operator += (const AD<Base> &right)\n{\n    // compute the Base part\n    Base left;\n    left    = value_;\n    value_ += right.value_;\n\n    // check if there is a recording in progress\n    local::ADTape<Base>* tape = AD<Base>::tape_ptr();\n    if( tape == nullptr )\n        return *this;\n    tape_id_t tape_id = tape->id_;\n    // tape_id cannot match the default value for tape_id_; i.e., 0\n    CPPAD_ASSERT_UNKNOWN( tape_id > 0 );\n\n    // check if left and right tapes match\n    bool match_left  = tape_id_       == tape_id;\n    bool match_right = right.tape_id_ == tape_id;\n\n    // check if left and right are dynamic parameters\n    bool dyn_left  = match_left  & (ad_type_ == dynamic_enum);\n    bool dyn_right = match_right & (right.ad_type_ == dynamic_enum);\n\n    // check if left and right are variables\n    bool var_left  = match_left  & (ad_type_ != dynamic_enum);\n    bool var_right = match_right & (right.ad_type_ != dynamic_enum);\n\n    CPPAD_ASSERT_KNOWN(\n        tape_id_ == right.tape_id_ || ! match_left || ! match_right ,\n        \"+= : AD variables or dynamic parameters on different threads.\"\n    );\n    if( var_left )\n    {   if( var_right )\n        {   // this = variable + variable\n            CPPAD_ASSERT_UNKNOWN( local::NumRes(local::AddvvOp) == 1 );\n            CPPAD_ASSERT_UNKNOWN( local::NumArg(local::AddvvOp) == 2 );\n\n            // put operand addresses in tape\n            tape->Rec_.PutArg(taddr_, right.taddr_);\n            // put operator in the tape\n            taddr_ = tape->Rec_.PutOp(local::AddvvOp);\n            // check that this is a variable\n            CPPAD_ASSERT_UNKNOWN( tape_id_ == tape_id );\n            CPPAD_ASSERT_UNKNOWN( ad_type_ == variable_enum);\n        }\n        else if( dyn_right | (! IdenticalZero(right.value_) ) )\n        {   // this = variable  + parameter\n            //      = parameter + variable\n            CPPAD_ASSERT_UNKNOWN( local::NumRes(local::AddpvOp) == 1 );\n            CPPAD_ASSERT_UNKNOWN( local::NumArg(local::AddpvOp) == 2 );\n\n            // put operand addresses in tape\n            addr_t p = right.taddr_;\n            if( ! dyn_right )\n                p = tape->Rec_.put_con_par(right.value_);\n            tape->Rec_.PutArg(p, taddr_);\n            // put operator in the tape\n            taddr_ = tape->Rec_.PutOp(local::AddpvOp);\n            // check that this is a variable\n            CPPAD_ASSERT_UNKNOWN( tape_id_ == tape_id );\n            CPPAD_ASSERT_UNKNOWN( ad_type_ == variable_enum);\n        }\n    }\n    else if( var_right  )\n    {   if( (! dyn_left) && IdenticalZero(left) )\n        {   // this = 0 + right\n            make_variable(right.tape_id_, right.taddr_);\n        }\n        else\n        {   // this = parameter + variable\n            CPPAD_ASSERT_UNKNOWN( local::NumRes(local::AddpvOp) == 1 );\n            CPPAD_ASSERT_UNKNOWN( local::NumArg(local::AddpvOp) == 2 );\n\n            // put operand addresses in tape\n            addr_t p = taddr_;\n            if( ! dyn_left )\n                p = tape->Rec_.put_con_par(left);\n            tape->Rec_.PutArg(p, right.taddr_);\n\n            // put operator in the tape\n            taddr_ = tape->Rec_.PutOp(local::AddpvOp);\n\n            // make this a variable\n            tape_id_ = tape_id;\n            ad_type_ = variable_enum;\n        }\n    }\n    else if( dyn_left | dyn_right )\n    {   if( (! dyn_right) && IdenticalZero(right.value_) )\n        {    // this is left += 0, so do nothing\n        }\n        else if( (! dyn_left) && IdenticalZero(left))\n        {    // this is 0 += right\n            make_dynamic(right.tape_id_, right.taddr_);\n        }\n        else\n        {\n            addr_t arg0 = taddr_;\n            addr_t arg1 = right.taddr_;\n            if( ! dyn_left )\n            arg0 = tape->Rec_.put_con_par(left);\n            if( ! dyn_right )\n            arg1 = tape->Rec_.put_con_par(right.value_);\n            //\n            // parameters with a dynamic parameter results\n            taddr_ = tape->Rec_.put_dyn_par(\n                value_, local::add_dyn, arg0, arg1\n            );\n            tape_id_ = tape_id;\n            ad_type_ = dynamic_enum;\n        }\n    }\n    return *this;\n}\n\nCPPAD_FOLD_ASSIGNMENT_OPERATOR(+=)\n\n} // END CppAD namespace\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/arithmetic.hpp",
    "content": "# ifndef CPPAD_CORE_ARITHMETIC_HPP\n# define CPPAD_CORE_ARITHMETIC_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n-------------------------------------------------------------------------------\n{xrst_begin Arithmetic}\n\nAD Arithmetic Operators and Compound Assignments\n################################################\n\nContents\n********\n{xrst_toc_table\n    include/cppad/core/unary_plus.hpp\n    include/cppad/core/unary_minus.hpp\n    include/cppad/core/ad_binary.hpp\n    include/cppad/core/compound_assign.hpp\n}\n\n{xrst_end Arithmetic}\n-------------------------------------------------------------------------------\n*/\n# include <cppad/core/unary_plus.hpp>\n# include <cppad/core/unary_minus.hpp>\n# include <cppad/core/ad_binary.hpp>\n# include <cppad/core/compound_assign.hpp>\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/atan2.hpp",
    "content": "# ifndef CPPAD_CORE_ATAN2_HPP\n# define CPPAD_CORE_ATAN2_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n-------------------------------------------------------------------------------\n{xrst_begin atan2}\n\nAD Two Argument Inverse Tangent Function\n########################################\n\nSyntax\n******\n| *theta* = ``atan2`` ( *y* , *x* )\n\nPurpose\n*******\nDetermines an angle :math:`\\theta \\in [ - \\pi , + \\pi ]`\nsuch that\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        \\sin ( \\theta )  & = & y / \\sqrt{ x^2 + y^2 }  \\\\\n        \\cos ( \\theta )  & = & x / \\sqrt{ x^2 + y^2 }\n    \\end{eqnarray}\n\ny\n*\nThe argument *y* has one of the following prototypes\n\n| |tab| ``const AD`` < *Base* >               & *y*\n| |tab| ``const VecAD`` < *Base* >:: ``reference &`` *y*\n\nx\n*\nThe argument *x* has one of the following prototypes\n\n| |tab| ``const AD`` < *Base* >               & *x*\n| |tab| ``const VecAD`` < *Base* >:: ``reference &`` *x*\n\ntheta\n*****\nThe result *theta* has prototype\n\n    ``AD`` < *Base* > *theta*\n\nOperation Sequence\n******************\nThe AD of *Base*\noperation sequence used to calculate *theta* is\n:ref:`glossary@Operation@Independent`\nof *x* and *y* .\n\nExample\n*******\n{xrst_toc_hidden\n    example/general/atan2.cpp\n}\nThe file\n:ref:`atan2.cpp-name`\ncontains an example and test of this function.\n\n{xrst_end atan2}\n-------------------------------------------------------------------------------\n*/\n\nnamespace CppAD { // BEGIN CppAD namespace\n\ninline float atan2(float x, float y)\n{   return std::atan2(x, y); }\n\ninline double atan2(double x, double y)\n{   return std::atan2(x, y); }\n\n// The code below is used as an example by the CondExp documentation.\n// BEGIN CondExp\ntemplate <class Base>\nAD<Base> atan2 (const AD<Base> &y, const AD<Base> &x)\n{   //\n    // zero, pi2, pi\n    AD<Base> zero(0.);\n    AD<Base> pi2(2. * atan(1.));\n    AD<Base> pi(2. * pi2);\n    //\n    // abs_x, abs_y\n    // Not using fabs because its derivative is zero at zero\n    AD<Base> abs_x = CondExpGe(x, zero, x, -x);\n    AD<Base> abs_y = CondExpGe(y, zero, y, -y);\n    //\n    // first\n    // This is the result for first quadrant: x >= 0 , y >= 0\n    AD<Base> alpha = atan(abs_y / abs_x);\n    AD<Base> beta  = pi2 - atan(abs_x / abs_y);\n    AD<Base> first = CondExpGt(abs_x, abs_y, alpha, beta);\n    //\n    // second\n    // This is the result for second quadrant: x <= 0 , y >= 0\n    AD<Base> second = pi - first;\n    //\n    // third\n    // This is the result for third quadrant: x <= 0 , y <= 0\n    AD<Base> third = - pi + first;\n    //\n    // fourth\n    // This is the result for fourth quadrant: x >= 0 , y <= 0\n    AD<Base> fourth = - first;\n    //\n    // alpha\n    // This is the result for x >= 0\n    alpha = CondExpGe(y, zero, first, fourth);\n    //\n    // beta\n    // This is the result for x <= 0\n    beta = CondExpGe(y, zero, second, third);\n    //\n    //\n    AD<Base> result = CondExpGe(x, zero, alpha, beta);\n    return result;\n}\n// END CondExp\n\ntemplate <class Base>\nAD<Base> atan2 (const VecAD_reference<Base> &y, const AD<Base> &x)\n{   return atan2( y.ADBase() , x ); }\n\ntemplate <class Base>\nAD<Base> atan2 (const AD<Base> &y, const VecAD_reference<Base> &x)\n{   return atan2( y , x.ADBase() ); }\n\ntemplate <class Base>\nAD<Base> atan2\n(const VecAD_reference<Base> &y, const VecAD_reference<Base> &x)\n{   return atan2( y.ADBase() , x.ADBase() ); }\n\n} // END CppAD namespace\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/atomic/atomic.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin atomic}\n\nAtomic AD Functions\n###################\n\nContents\n********\n{xrst_toc_table\n    include/cppad/core/atomic/four/atomic.xrst\n    include/cppad/core/atomic/three/atomic.xrst\n    include/cppad/core/chkpoint_two/chkpoint_two.hpp\n}\n\nDeprecated Atomic Function\n**************************\n:ref:`atomic_one-name` ,\n:ref:`atomic_two-name` ,\n:ref:`chkpoint_one-name` .\n\n{xrst_end atomic}\n"
  },
  {
    "path": "include/cppad/core/atomic/four/atomic.hpp",
    "content": "# ifndef CPPAD_CORE_ATOMIC_FOUR_ATOMIC_HPP\n# define CPPAD_CORE_ATOMIC_FOUR_ATOMIC_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_four_define}\n{xrst_spell\n    ctor\n}\n\nDefining Atomic Functions: Fourth Generation\n############################################\n\nSyntax\n******\n\nDefine Class\n============\n\n| ``class`` *atomic_user* : ``public CppAD::atomic_four<`` *Base* > {\n| |tab| ...\n| };\n\nConstructor\n===========\n*atomic_user* *afun* ( *ctor_arg_list* )\n\nCall\n====\n\n| *afun* ( *ax* , *ay* )\n| *afun* ( *call_id* , *ax* , *ay* )\n\nCallbacks\n=========\n\n| *ok* = *afun* . ``for_type`` ( *call_id* ,\n| |tab| *type_x* , *type_y*\n| )\n| *ok* = *afun* . ``forward`` ( *call_id* ,\n| |tab| *select_y* , *order_low* , *order_up* , *taylor_x* , *taylor_y*\n| )\n| *ok* = *afun* . ``reverse`` ( *call_id* ,\n| |tab| *select_x* , *order_up* , *taylor_x* , *taylor_y* , *partial_x* , *partial_y*\n| )\n| *ok* = *afun* . ``jac_sparsity`` ( *call_id* ,\n| |tab| *dependency* , *ident_zero_x* , *select_x* *select_y* , *pattern_out*\n| )\n| *ok* = *afun* . ``hes_sparsity`` ( *call_id* ,\n| |tab| *ident_zero_x* , *select_x* , *select_y* , *pattern_out*\n| )\n| *ok* = *afun* . ``rev_depend`` ( *call_id* ,\n| |tab| *ident_zero_x* , *depend_x* , *depend_y*\n| )\n\nSee Also\n********\n:ref:`chkpoint_two-name` , :ref:`atomic_three-name`\n\nPurpose\n*******\n\nSpeed\n=====\nIn some cases, it is possible to compute derivatives of a function\n\n.. math::\n\n    y = g(x) \\; {\\rm where} \\; g : \\B{R}^n \\rightarrow \\B{R}^m\n\nmore efficiently than by coding it using ``AD`` < *Base* >\n:ref:`glossary@Operation@Atomic` operations\nand letting CppAD do the rest.\nThe class ``atomic_four`` < ``Base`` > is used to\ncreate a new atomic operation corresponding to a function :math:`g(x)`\nwhere the user specifies how to compute the derivatives\nand sparsity patterns for :math:`g(x)`.\n\nReduce Memory\n=============\nIf the function :math:`g(x)` is used many times during the recording\nof an :ref:`ADFun-name` object,\nan atomic version of :math:`g(x)` removes the need for repeated\ncopies of the corresponding ``AD`` < *Base* > operations and variables\nin the recording.\n\nVirtual Functions\n*****************\nThe :ref:`callback functions<atomic_four_define@Syntax@Callbacks>`\nare implemented by defining the virtual functions in the\n*atomic_user* class.\nThese functions compute derivatives,\nsparsity patterns, and dependency relations.\nEach virtual function has a default implementation\nthat returns *ok* == ``false`` .\nThe :ref:`for_type<atomic_four_for_type-name>`\nand :ref:`forward<atomic_four_forward-name>` function\n(for the case *order_up*  == 0 ) are used by an atomic function\n:ref:`atomic_four_define@Syntax@Call` .\nHence, they are required for one to use an atomic function.\nOther functions and orders are only required if they are used\nfor your calculations.\nFor example,\n*forward* for the case *order_up*  == 2 can just return\n*ok* == ``false`` unless you require\nforward mode calculation of second derivatives.\n\nContents\n********\n{xrst_toc_table\n    include/cppad/core/atomic/four/ctor.hpp\n    include/cppad/core/atomic/four/call.hpp\n    include/cppad/core/atomic/four/for_type.hpp\n    include/cppad/core/atomic/four/forward.hpp\n    include/cppad/core/atomic/four/reverse.hpp\n    include/cppad/core/atomic/four/jac_sparsity.hpp\n    include/cppad/core/atomic/four/hes_sparsity.hpp\n    include/cppad/core/atomic/four/rev_depend.hpp\n}\n\n{xrst_end atomic_four_define}\n-------------------------------------------------------------------------------\n*/\n\n# include <set>\n# include <map>\n# include <cppad/core/cppad_assert.hpp>\n# include <cppad/local/atomic_index.hpp>\n# include <cppad/core/ad_type.hpp>\n# include <cppad/utility/sparse_rc.hpp>\n# include <cppad/local/pod_vector.hpp>\n# include <cppad/local/op_code_var.hpp>\n\n// needed before one can use in_parallel\n# include <cppad/utility/thread_alloc.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\n\\file atomic_four.hpp\nBase class for atomic function operations.\n*/\n\ntemplate <class Base>\nclass atomic_four {\n// ===================================================================\nprivate:\n    // ------------------------------------------------------\n    // constants\n    //\n    /// index of this object in local::atomic_index\n    /// (set by constructor and not changed; i.e., effectively const)\n    size_t index_;\n    //\n    // -----------------------------------------------------\n    //\n    /// temporary work space used by call member functions, declared here\n    // to avoid memory allocation/deallocation for each call\n    struct work_struct {\n        vector<ad_type_enum>        type_x;\n        vector<ad_type_enum>        type_y;\n        //\n        vector<Base>                taylor_x;\n        vector<Base>                taylor_y;\n        //\n        vector< AD<Base> >          ataylor_x;\n        vector< AD<Base> >          ataylor_y;\n        //\n        vector<bool>                select_y;\n    };\n    // Use pointers, to avoid false sharing between threads.\n    // Not using: vector<work_struct*> work_;\n    // so that deprecated atomic examples do not result in a memory leak.\n    work_struct* work_[CPPAD_MAX_NUM_THREADS];\n    // -----------------------------------------------------\npublic:\n    //\n    // atomic_index\n    // Needed by val_graph and not documented. Perhaps should be in\n    // include/cppad/core/atomic/four/devel/devel.xrst\n    size_t atomic_index(void) const\n    { return index_; }\n    // =====================================================================\n    // In User API\n    // =====================================================================\n    //\n    // ---------------------------------------------------------------------\n    // constructors\n    atomic_four(void);\n    atomic_four(const std::string& name);\n\n    // ------------------------------------------------------------------------\n    template <class ADVector> void operator()(\n        size_t           call_id ,\n        const ADVector&  ax      ,\n                  ADVector&  ay\n    );\n    template <class ADVector> void operator()(\n        const ADVector&  ax      ,\n                  ADVector&  ay\n    );\n    // ------------------------------------------------------------------------\n    // for_type\n    virtual bool for_type(\n        size_t                       call_id     ,\n        const vector<ad_type_enum>&  type_x      ,\n        vector<ad_type_enum>&        type_y\n    );\n    // ------------------------------------------------------------------------\n    // forward\n    virtual bool forward(\n        size_t                       call_id     ,\n        const vector<bool>&          select_y    ,\n        size_t                       order_low   ,\n        size_t                       order_up    ,\n        const vector<Base>&          taylor_x    ,\n        vector<Base>&                taylor_y\n    );\n    virtual bool forward(\n        size_t                       call_id      ,\n        const vector<bool>&          select_y    ,\n        size_t                       order_low    ,\n        size_t                       order_up     ,\n        const vector< AD<Base> >&    ataylor_x    ,\n        vector< AD<Base> >&          ataylor_y\n    );\n    // ------------------------------------------------------------------------\n    // reverse\n    virtual bool reverse(\n        size_t                       call_id     ,\n        const vector<bool>&          select_x    ,\n        size_t                       order_up    ,\n        const vector<Base>&          taylor_x    ,\n        const vector<Base>&          taylor_y    ,\n        vector<Base>&                partial_x   ,\n        const vector<Base>&          partial_y\n    );\n    virtual bool reverse(\n        size_t                       call_id     ,\n        const vector<bool>&          select_x    ,\n        size_t                       order_up    ,\n        const vector< AD<Base> >&    ataylor_x   ,\n        const vector< AD<Base> >&    ataylor_y   ,\n        vector< AD<Base> >&          apartial_x  ,\n        const vector< AD<Base> >&    apartial_y\n    );\n    // ------------------------------------------------------------\n    // jac_sparsity\n    virtual bool jac_sparsity(\n        size_t                       call_id      ,\n        bool                         dependency   ,\n        const vector<bool>&          ident_zero_x ,\n        const vector<bool>&          select_x     ,\n        const vector<bool>&          select_y     ,\n        sparse_rc< vector<size_t> >& pattern_out\n    );\n    template <class InternalSparsity>\n    bool for_jac_sparsity(\n        size_t                           call_id      ,\n        bool                             dependency   ,\n        const vector<bool>&              ident_zero_x ,\n        const vector<size_t>&            x_index      ,\n        const vector<size_t>&            y_index      ,\n        InternalSparsity&                var_sparsity\n    );\n    template <class InternalSparsity>\n    bool rev_jac_sparsity(\n        size_t                           call_id      ,\n        bool                             dependency   ,\n        const vector<bool>&              ident_zero_x ,\n        const vector<size_t>&            x_index      ,\n        const vector<size_t>&            y_index      ,\n        InternalSparsity&                var_sparsity\n    );\n    // deprecated version of this callback\n    virtual bool jac_sparsity(\n        size_t                       call_id      ,\n        bool                         dependency   ,\n        const vector<bool>&          select_x     ,\n        const vector<bool>&          select_y     ,\n        sparse_rc< vector<size_t> >& pattern_out\n    );\n    // ------------------------------------------------------------\n    // hes_sparsity\n    virtual bool hes_sparsity(\n        size_t                                  call_id      ,\n        const vector<bool>&                     ident_zero_x ,\n        const vector<bool>&                     select_x     ,\n        const vector<bool>&                     select_y     ,\n        sparse_rc< vector<size_t> >&            pattern_out\n    );\n    template <class InternalSparsity>\n    bool for_hes_sparsity(\n        size_t                           call_id          ,\n        const vector<bool>&              ident_zero_x     ,\n        const vector<size_t>&            x_index          ,\n        const vector<size_t>&            y_index          ,\n        size_t                           np1              ,\n        size_t                           numvar           ,\n        const InternalSparsity&          rev_jac_sparsity ,\n        InternalSparsity&                for_sparsity\n    );\n    template <class InternalSparsity>\n    bool rev_hes_sparsity(\n        size_t                           call_id          ,\n        const vector<bool>&              ident_zero_x     ,\n        const vector<size_t>&            x_index          ,\n        const vector<size_t>&            y_index          ,\n        const InternalSparsity&          for_jac_pattern  ,\n        bool*                            rev_jac_flag     ,\n        InternalSparsity&                hes_sparsity\n    );\n    // deprecated version of this callback\n    virtual bool hes_sparsity(\n        size_t                                  call_id      ,\n        const vector<bool>&                     select_x     ,\n        const vector<bool>&                     select_y     ,\n        sparse_rc< vector<size_t> >&            pattern_out\n    );\n    // ------------------------------------------------------------------------\n    // rev_depend\n    virtual bool rev_depend(\n        size_t                       call_id      ,\n        const vector<bool>&          ident_zero_x ,\n        vector<bool>&                depend_x     ,\n        const vector<bool>&          depend_y\n    );\n    // deprecated version of this callback\n    virtual bool rev_depend(\n        size_t                       call_id     ,\n        vector<bool>&                depend_x    ,\n        const vector<bool>&          depend_y\n    );\n    // =====================================================================\n    // Not in User API\n    // =====================================================================\n\n    /// Name corresponding to a atomic_four object\n    const std::string atomic_name(void) const\n    {   bool        set_null = false;\n        size_t      type  = 0;          // set to avoid warning\n        std::string name;\n        void*       v_ptr = nullptr; // set to avoid warning\n        local::atomic_index<Base>(set_null, index_, type, &name, v_ptr);\n        CPPAD_ASSERT_UNKNOWN( type == 4 );\n        return name;\n    }\n    /// destructor informs CppAD that this atomic function with this index\n    /// has dropped out of scope by setting its pointer to null\n    virtual ~atomic_four(void)\n    {   // change object pointer to null, but leave name for error reporting\n        bool         set_null = true;\n        size_t       type  = 0;          // set to avoid warning\n        std::string* name  = nullptr;\n        void*        v_ptr = nullptr; // set to avoid warning\n        local::atomic_index<Base>(set_null, index_, type, name, v_ptr);\n        CPPAD_ASSERT_UNKNOWN( type == 4 );\n        //\n        // free temporary work memory\n        for(size_t thread = 0; thread < CPPAD_MAX_NUM_THREADS; thread++)\n            free_work(thread);\n    }\n    /// allocates work_ for a specified thread\n    void allocate_work(size_t thread)\n    {   if( work_[thread] == nullptr )\n        {   // allocate the raw memory\n            size_t min_bytes = sizeof(work_struct);\n            size_t num_bytes;\n            void*  v_ptr     = thread_alloc::get_memory(min_bytes, num_bytes);\n            // save in work_\n            work_[thread]    = reinterpret_cast<work_struct*>( v_ptr );\n            // call constructor\n            new( work_[thread] ) work_struct;\n        }\n        return;\n    }\n    /// frees work_ for a specified thread\n    void free_work(size_t thread)\n    {   if( work_[thread] != nullptr )\n        {   // call destructor\n            work_[thread]->~work_struct();\n            // return memory to available pool for this thread\n            thread_alloc::return_memory(\n                reinterpret_cast<void*>(work_[thread])\n            );\n            // mark this thread as not allocated\n            work_[thread] = nullptr;\n        }\n        return;\n    }\n    /// atomic_four function object corresponding to a certain index\n    static atomic_four* class_object(size_t index)\n    {   bool         set_null = false;\n        size_t       type  = 0;          // set to avoid warning\n        std::string* name  = nullptr;\n        void*        v_ptr = nullptr; // set to avoid warning\n        local::atomic_index<Base>(set_null, index, type, name, v_ptr);\n        CPPAD_ASSERT_UNKNOWN( type == 4 );\n        return reinterpret_cast<atomic_four*>( v_ptr );\n    }\n    /// atomic_four function name corresponding to a certain index\n    static const std::string class_name(size_t index)\n    {   bool        set_null = false;\n        size_t      type  = 0;          // set to avoid warning\n        std::string name;\n        void*       v_ptr = nullptr; // set to avoid warning\n        local::atomic_index<Base>(set_null, index, type, &name, v_ptr);\n        CPPAD_ASSERT_UNKNOWN( type == 4 );\n        return name;\n    }\n\n    /*!\n    Set value of id (used by deprecated atomic_one class)\n\n    This function is called just before calling any of the virtual function\n    and has the corresponding id of the corresponding virtual call.\n    */\n    virtual void set_old(size_t id)\n    { }\n// ---------------------------------------------------------------------------\n};\n} // END_CPPAD_NAMESPACE\n\n// member functions\n# include <cppad/core/atomic/four/ctor.hpp>\n# include <cppad/core/atomic/four/call.hpp>\n# include <cppad/core/atomic/four/for_type.hpp>\n# include <cppad/core/atomic/four/rev_depend.hpp>\n# include <cppad/core/atomic/four/forward.hpp>\n# include <cppad/core/atomic/four/reverse.hpp>\n# include <cppad/core/atomic/four/jac_sparsity.hpp>\n# include <cppad/core/atomic/four/hes_sparsity.hpp>\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/atomic/four/atomic.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin atomic_four}\n\nAtomic AD Functions: Fourth Generation\n######################################\n\nContents\n********\n{xrst_toc_table\n    include/cppad/core/atomic/four/atomic.hpp\n    example/atomic_four/atomic_four.xrst\n}\n\n{xrst_end atomic_four}\n"
  },
  {
    "path": "include/cppad/core/atomic/four/call.hpp",
    "content": "# ifndef CPPAD_CORE_ATOMIC_FOUR_CALL_HPP\n# define CPPAD_CORE_ATOMIC_FOUR_CALL_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_four_call}\n\nCalling an Atomic Function\n##########################\n\nSyntax\n******\n| *afun* ( *ax* , *ay* )\n| *ay* = *afun* ( *call_id* , *ax* , *ay* )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_PROTOTYPE\n    // END_PROTOTYPE\n}\n\nPurpose\n*******\nGiven *ax* , this call computes the corresponding value of *ay* .\nIf ``AD`` < *Base* > operations are being recorded,\nit enters the computation as an atomic operation in the recording;\nsee :ref:`Independent@Start Recording` .\n\nBase\n****\nThis is the :ref:`atomic_four_ctor@atomic_four@Base`\nin the *afun* constructor.\nIt is also the *Base* type of the elements of\n*ax* and *ay* in the atomic function call.\nTo be specific, the elements of *ax* and *ay* have type\n``AD`` < ``Base`` > .\n\nADVector\n********\nThe type *ADVector* must be a\n:ref:`simple vector class<SimpleVector-name>` with elements of type\n``AD`` < *Base* > .\n\nafun\n****\nis a :ref:`atomic_four_ctor@atomic_user` object\nand this *afun* function call is implemented by the\n:ref:`atomic_four_ctor@atomic_four` class.\n\nax\n**\nThis vector is ``const`` and passed by reference and\nits size determines *n* .\nIt specifies vector :math:`x \\in \\B{R}^n`\nat which an ``AD`` < *Base* > version of\n:math:`y = g(x)` is to be evaluated.\n\nay\n**\nThis vector is passed by reference and its size determines *m* .\nThe input values of its elements\nare not specified (must not matter).\nUpon return, it is an ``AD`` < *Base* > version of\n:math:`y = g(x)`.\n\ncall_id\n*******\nThis optional argument has default value zero.\nIt can be used to specify additional information about this call to\n*afun* . For example, it could specify the index in vector of structures\nin the *afun* object where the actual information is placed.\n\nfor_type\n********\nThe :ref:`for_type<atomic_four_for_type-name>` routine will be called once,\nfor each call to an atomic function,\nbefore any other callbacks corresponding to the atomic function call.\nThis enables you to store, during the ``for_type`` routine,\nthe values in\n:ref:`atomic_four_for_type@type_x` and or\n:ref:`atomic_four_for_type@type_y` corresponding\nto this atomic function call.\n\nRestriction\n===========\nThe value of *call_id* must be less than or equal\n\n    ``std::numeric_limits<`` *cppad_tape_id_type* >:: ``max`` ()\n\nsee :ref:`cmake@cppad_tape_id_type` .\n\n{xrst_end atomic_four_call}\n-----------------------------------------------------------------------------\n*/\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n\n// BEGIN_PROTOTYPE\ntemplate <class Base> template <class ADVector>\nvoid atomic_four<Base>::operator()(\n    size_t           call_id ,\n    const ADVector&  ax      ,\n    ADVector&        ay      )\n// END_PROTOTYPE\n{\n    size_t n = ax.size();\n    size_t m = ay.size();\n# ifndef NDEBUG\n    bool ok = true;\n    std::string msg = \"atomic_four: call \" + atomic_name() + \" \";\n    if( (n == 0) || (m == 0) )\n    {   msg += \"ax.size() or ay.size() is zero\";\n        CPPAD_ASSERT_KNOWN(false, msg.c_str() );\n    }\n# endif\n    //\n    // type_x, type_y, taylor_x, taylor_y, select_y\n    size_t thread = thread_alloc::thread_num();\n    allocate_work(thread);\n    vector<ad_type_enum>& type_x   = work_[thread]->type_x;\n    vector<ad_type_enum>& type_y   = work_[thread]->type_y;\n    vector<Base>&         taylor_x = work_[thread]->taylor_x;\n    vector<Base>&         taylor_y = work_[thread]->taylor_y;\n    vector<bool>&         select_y = work_[thread]->select_y;\n    type_x.resize(n);\n    taylor_x.resize(n);\n    type_y.resize(m);\n    taylor_y.resize(m);\n    select_y.resize(m);\n    //\n    // tape_id, tape, taylor_x, type_x\n    tape_id_t            tape_id  = 0;\n    local::ADTape<Base>* tape     = nullptr;\n    for(size_t j = 0; j < n; j++)\n    {   taylor_x[j]  = ax[j].value_;\n        if( IdenticalZero( ax[j] ) )\n            type_x[j] = identical_zero_enum;\n        else if( Constant( ax[j] ) )\n            type_x[j] = constant_enum;\n        else\n        {   type_x[j] = ax[j].ad_type_;\n            if( tape_id == 0 )\n            {   tape    = ax[j].tape_this();\n                tape_id = ax[j].tape_id_;\n                CPPAD_ASSERT_UNKNOWN( tape != nullptr );\n            }\n# ifndef NDEBUG\n            if( Dynamic( ax[j] ) )\n            {     CPPAD_ASSERT_UNKNOWN( type_x[j] == dynamic_enum );\n            }\n            else\n            {   CPPAD_ASSERT_UNKNOWN( Variable( ax[j] ) );\n                CPPAD_ASSERT_UNKNOWN( type_x[j] == variable_enum );\n            }\n            if( tape_id != ax[j].tape_id_ )\n            {   msg += atomic_name() +\n                \": ax contains non-constant values from different threads.\";\n                CPPAD_ASSERT_KNOWN(false, msg.c_str());\n            }\n# endif\n        }\n    }\n    // Use zero order forward mode to compute all the components of y\n    for(size_t i = 0; i < m; ++i)\n        select_y[i] = true;\n    size_t order_low   = 0;\n    size_t order_up    = 0;\n# ifdef NDEBUG\n    for_type(\n        call_id, type_x, type_y\n    );\n    forward(\n        call_id, select_y, order_low, order_up, taylor_x, taylor_y\n    );\n# else\n    ok &= for_type(\n        call_id, type_x, type_y\n    );\n    ok &= forward(\n        call_id, select_y, order_low, order_up, taylor_x, taylor_y\n    );\n    if( ! ok )\n    {   msg += atomic_name() + \": ok is false for \"\n            \"type or zero order forward mode calculation.\";\n        CPPAD_ASSERT_KNOWN(false, msg.c_str());\n    }\n# endif\n    bool record_dynamic = false;\n    bool record_variable = false;\n    //\n    // set ay to be vector of constant parameters with correct value\n    for(size_t i = 0; i < m; i++)\n    {   // pass back values\n        ay[i].value_ = taylor_y[i];\n\n        // initialize entire vector as constants\n        ay[i].tape_id_ = 0;\n        ay[i].taddr_   = 0;\n\n        // we need to record this operation if\n        // any of the elements of ay are dynamics or variables,\n        record_dynamic  |= type_y[i] == dynamic_enum;\n        record_variable |= type_y[i] == variable_enum;\n    }\n# ifndef NDEBUG\n    if( (record_dynamic || record_variable) && tape == nullptr )\n    {   msg +=\n        \"all elements of x are constants but y contains a non-constant\";\n        CPPAD_ASSERT_KNOWN(false, msg.c_str() );\n    }\n# endif\n    if( record_dynamic)\n    {   tape->Rec_.put_dyn_atomic(\n            tape_id, index_, call_id, type_x, type_y, ax, ay\n        );\n    }\n    // case where result contains a variable\n    if( record_variable )\n    {   tape->Rec_.put_var_atomic(\n            tape_id, index_, call_id, type_x, type_y, ax, ay\n        );\n    }\n# ifndef NDEBUG\n    for(size_t i = 0; i < m; ++i) switch( type_y[i] )\n    {   //\n        case identical_zero_enum:\n        case constant_enum:\n        CPPAD_ASSERT_UNKNOWN( Constant( ay[i] ) );\n        break;\n        //\n        case dynamic_enum:\n        CPPAD_ASSERT_UNKNOWN( Dynamic( ay[i] ) );\n        break;\n        //\n        case variable_enum:\n        CPPAD_ASSERT_UNKNOWN( Variable( ay[i] ) );\n        break;\n        //\n        default:\n        CPPAD_ASSERT_KNOWN( false,\n            \"atomic_four: for_type: type_y[i]: is not a valid type\"\n        );\n        break;\n    }\n# endif\n    return;\n}\ntemplate <class Base> template <class ADVector>\nvoid atomic_four<Base>::operator()(\n    const ADVector&  ax      ,\n    ADVector&        ay      )\n{   size_t call_id = 0;\n    (*this)(call_id, ax, ay);\n}\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/atomic/four/ctor.hpp",
    "content": "# ifndef CPPAD_CORE_ATOMIC_FOUR_CTOR_HPP\n# define CPPAD_CORE_ATOMIC_FOUR_CTOR_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_four_ctor}\n\nAtomic Function Constructor\n###########################\n\nSyntax\n******\n| ``class`` *atomic_user* : ``public CppAD::atomic_four<`` *Base* > {\n| ``public:``\n| |tab| *atomic_user* ( *ctor_arg_list* ) : ``CppAD::atomic_four<`` *Base* >( *name* )\n| |tab| ...\n| };\n| *atomic_user afun* ( *ctor_arg_list* )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_PROTOTYPE\n    // END_PROTOTYPE\n}\n\natomic_user\n***********\n\nctor_arg_list\n=============\nIs a list of arguments for the *atomic_user* constructor.\n\nafun\n====\nThe object *afun* must stay in scope for as long\nas the corresponding atomic function is used.\nThis includes use by any :ref:`ADFun\\<Base><ADFun-name>` object that\nhas this *atomic_user* operation in its\n:ref:`operation sequence<glossary@Operation@Sequence>` .\n\nImplementation\n==============\nThe user defined *atomic_user* class is a publicly derived class of\n``atomic_four`` < *Base* > .\nIt should be declared as follows:\n\n| |tab| ``class`` *atomic_user* : ``public CppAD::atomic_four<`` *Base* > {\n| |tab| ``public:``\n| |tab| |tab| *atomic_user* ( *ctor_arg_list* ) : ``atomic_four`` < *Base* >( *name* )\n| |tab| ...\n| |tab| };\n\nwhere ...\ndenotes the rest of the implementation of the derived class.\nThis includes completing the constructor and\nall the virtual functions that have their\n``atomic_four`` implementations replaced by\n*atomic_user* implementations.\n\natomic_four\n***********\n\nRestrictions\n============\nThe ``atomic_four`` constructor and destructor cannot be called in\n:ref:`parallel<ta_in_parallel-name>` mode.\n\nBase\n====\nThe template parameter determines the\n:ref:`atomic_four_call@Base`\ntype for this ``AD`` < *Base* > atomic operation.\n\nname\n====\nThis ``atomic_four`` constructor argument has the following prototype\n\n    ``const std::string&`` *name*\n\nIt is the name for this atomic function and is used for error reporting.\nThe suggested value for *name* is *afun* or *atomic_user* ,\ni.e., the name of the corresponding atomic object or class.\n\nExample\n*******\nThe following is an example constructor definition taken from\n:ref:`atomic_four_norm_sq.cpp-name` :\n{xrst_literal\n    example/atomic_four/norm_sq.cpp\n    // BEGIN CONSTRUCTOR\n    // END CONSTRUCTOR\n}\n\n{xrst_end atomic_four_ctor}\n-------------------------------------------------------------------------------\n*/\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n\n// atomic_four()\ntemplate <class Base>\natomic_four<Base>::atomic_four(void)\n{   CPPAD_ASSERT_KNOWN(false,\n        \"Attempt to use the atomic_four default constructor\"\n    );\n}\n\n// atomic_four(name)\n// BEGIN_PROTOTYPE\ntemplate <class Base>\natomic_four<Base>::atomic_four(const std::string& name )\n// END_PROTOTYPE\n{   CPPAD_ASSERT_KNOWN(\n        ! thread_alloc::in_parallel() ,\n        \"atomic_four: constructor cannot be called in parallel mode.\"\n    );\n    //\n    // index_\n    bool        set_null  = false;\n    size_t      index     = 0;\n    size_t      type      = 4;\n    std::string copy_name = name;\n    void*       copy_this = reinterpret_cast<void*>( this );\n    index_  = local::atomic_index<Base>(\n        set_null, index, type, &copy_name, copy_this\n    );\n    //\n    // work_\n    for(size_t thread = 0; thread < CPPAD_MAX_NUM_THREADS; thread++)\n        work_[thread] = nullptr;\n}\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/atomic/four/devel/devel.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin atomic_four_devel dev}\n\natomic_four Developer Documentation\n###################################\n\nContents\n********\n{xrst_toc_table\n    include/cppad/core/atomic/four/devel/jac_sparsity.hpp\n    include/cppad/core/atomic/four/devel/hes_sparsity.hpp\n}\n\n{xrst_end atomic_four_devel}\n"
  },
  {
    "path": "include/cppad/core/atomic/four/devel/hes_sparsity.hpp",
    "content": "# ifndef CPPAD_CORE_ATOMIC_FOUR_DEVEL_HES_SPARSITY_HPP\n# define CPPAD_CORE_ATOMIC_FOUR_DEVEL_HES_SPARSITY_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*\n-----------------------------------------------------------------------------\n{xrst_begin atomic_four_for_hes_sparsity dev}\n{xrst_spell\n    numvar\n}\n\nLink from Forward Hessian Sparsity Sweep to atomic_four Callback\n################################################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_FOR_HES_SPARSITY\n    // END_FOR_HES_SPARSITY\n}\n\nInternalSparsity\n****************\nIs the used internally for sparsity calculations; i.e.,\nsparse_pack or sparse_list.\n\ncall_id [in]\n************\nsee :ref:`atomic_four_call@call_id` .\n\nident_zero_x\n************\nThis argument has size equal to the number of arguments to this\natomic function; i.e. the size of *ax* .\nIf *ident_zero_x* [ *j* ] is true, the argument *ax* [ *j* ]\nis a constant parameter that is identically zero.\n\nx_index\n*******\nis the variable index, on the tape, for the arguments to this function.\nThis size of x_index is n, the number of arguments to this function.\nThe index zero is used for parameters.\n\ny_index\n*******\nis the variable index, on the tape, for the results for this function.\nThis size of y_index is m, the number of results for this function.\nThe index zero is used for parameters.\n\nnp1\n***\nis the number of components of x plus one; i.e. *n*  + 1 .\n\nnumvar\n******\nis the total number of variables in the tape; i.e.,\n*play* ``->num_var`` () .\n\nfor_sparsity\n************\nThe sparsity patterns with index zero and index *np1* are empty\n(because they correspond to parameters).\n\nOn Input\n========\nOn input, for j = 0, ... , n-1,\nthe forward Jacobian sparsity for the *j*-th argument to the atomic function\nis the sparsity pattern with index *np1* + *x_index* [ *j* ] .\nIn addition, the sparsity pattern with index *j+1*-th contains\nthe non-zero cross partial indices where *j+1*-th is the other index.\nThis Hessian does not include the atomic operation.\n\nOn Output\n=========\nOn output, for i = 0, ... , m-1,\nthe forward Jacobian sparsity for the *i*-th result of the atomic function\nis the sparsity pattern with index *np1* + *y_index* [ *i* ] .\nIn addition, the sparsity pattern with index *j+1*-th contains\nthe non-zero cross partial indices where *j+1*-th is the other index.\nThis Hessian includes the atomic operation.\n\nrev_jac_pattern\n***************\nOn input, for i = 0, ... , m-1, the sparsity pattern with index y_index[i],\nis the reverse Jacobian sparsity for the i-th result to this atomic function.\nThis shows which components of the result affect the function we are\ncomputing the Hessian of.\n\nhes_sparsity_for\n****************\nThis is the sparsity pattern for the Hessian. On input, the non-linear\nterms in the atomic function have not been included. Upon return, they\nhave been included.\n\n{xrst_end atomic_four_for_hes_sparsity}\n*/\n// BEGIN_FOR_HES_SPARSITY\ntemplate <class Base>\ntemplate <class InternalSparsity>\nbool atomic_four<Base>::for_hes_sparsity(\n    size_t                           call_id          ,\n    const vector<bool>&              ident_zero_x     ,\n    const vector<size_t>&            x_index          ,\n    const vector<size_t>&            y_index          ,\n    size_t                           np1              ,\n    size_t                           numvar           ,\n    const InternalSparsity&          rev_jac_pattern  ,\n    InternalSparsity&                for_sparsity     )\n// END_FOR_HES_SPARSITY\n{  typedef typename InternalSparsity::const_iterator const_iterator;\n    //\n    CPPAD_ASSERT_UNKNOWN( rev_jac_pattern.end() == 1 );\n    CPPAD_ASSERT_UNKNOWN( for_sparsity.end() == np1 );\n    CPPAD_ASSERT_UNKNOWN( for_sparsity.n_set() == np1 + numvar );\n    CPPAD_ASSERT_UNKNOWN( for_sparsity.number_elements(0) == 0 );\n    CPPAD_ASSERT_UNKNOWN( for_sparsity.number_elements(np1) == 0 );\n    //\n    size_t n      = x_index.size();\n    size_t m      = y_index.size();\n    //\n    // select_x\n    vector<bool> select_x(n);\n    for(size_t j = 0; j < n; j++)\n    {  // check if should compute pattern w.r.t x[j]\n        select_x[j] = for_sparsity.number_elements(np1 + x_index[j]) > 0;\n    }\n    //\n    // bool select_y\n    vector<bool> select_y(m);\n    for(size_t i = 0; i < m; i++)\n    {  // check if we should include y[i]\n        select_y[i] = rev_jac_pattern.number_elements(y_index[i]) > 0;\n    }\n    // ------------------------------------------------------------------------\n    // call user's version of atomic function for Jacobian\n    sparse_rc< vector<size_t> > pattern_out;\n    bool dependency = false;\n    bool ok = jac_sparsity( call_id,\n        dependency, ident_zero_x, select_x, select_y, pattern_out\n    );\n    if(! ok) ok = jac_sparsity(\n        call_id, dependency, select_x, select_y, pattern_out\n    );\n    if( ! ok )\n        return false;\n    //\n    // transfer sparsity patterns from pattern_out to var_sparsity\n    size_t                nnz = pattern_out.nnz();\n    const vector<size_t>& row( pattern_out.row() );\n    const vector<size_t>& col( pattern_out.col() );\n    for(size_t k = 0; k < nnz; ++k)\n    {  size_t i = row[k];\n        size_t j = col[k];\n        CPPAD_ASSERT_KNOWN(\n            select_y[i] && select_x[j],\n            \"atomic: jac_sparsity: pattern_out not in \"\n            \"select_x or select_y range\"\n        );\n        const_iterator itr(for_sparsity, np1 + x_index[j]);\n        size_t ell = *itr;\n        while( ell < np1 )\n        {  for_sparsity.post_element(np1 + y_index[i], ell );\n            ell = *(++itr);\n        }\n    }\n    for(size_t i = 0; i < m; ++i)\n        for_sparsity.process_post( np1 + y_index[i] );\n    // ------------------------------------------------------------------------\n    // call user's version of atomic function for Hessian\n    ok = hes_sparsity(\n        call_id, ident_zero_x, select_x, select_y, pattern_out\n    );\n    if(! ok ) ok = hes_sparsity(\n        call_id, select_x, select_y, pattern_out\n    );\n    if( ! ok )\n        return ok;\n    //\n    // add new elements to Hessian sparisty in calling routine\n    nnz = pattern_out.nnz();\n    for(size_t k = 0; k < nnz; ++k)\n    {  size_t r = row[k];\n        size_t c = col[k];\n        CPPAD_ASSERT_KNOWN(\n            select_x[r] && select_x[c],\n            \"atomic: hes_sparsity: pattern_out not in select_x range\"\n        );\n        const_iterator itr_1(for_sparsity, np1 + x_index[r]);\n        size_t v1 = *itr_1;\n        while( v1 < np1 )\n        {  for_sparsity.binary_union(\n                v1, v1, np1 + x_index[c], for_sparsity\n                 );\n                 v1 = *(++itr_1);\n        }\n        // no need to add same elements twice\n        if( c != r )\n        {  const_iterator itr_2(for_sparsity, np1 + x_index[c]);\n            size_t v2 = *itr_2;\n            while( v2 < np1 )\n            {  for_sparsity.binary_union(\n                    v2, v2, np1 + x_index[r], for_sparsity\n                );\n                v2 = *(++itr_2);\n            }\n        }\n    }\n    return ok;\n}\n/*\n{xrst_begin atomic_four_rev_hes_sparsity dev}\n\nLink from Reverse Hessian Sparsity Sweep to atomic_four Callback\n################################################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_REV_HES_SPARSITY\n    // END_REV_HES_SPARSITY\n}\n\nInternalSparsity\n****************\nIs the used internally for sparsity calculations; i.e.,\nsparse_pack or sparse_list.\n\ncall_id [in]\n************\nsee :ref:`atomic_four_call@call_id` .\n\nident_zero_x\n************\nThis argument has size equal to the number of arguments to this\natomic function; i.e. the size of *ax* .\nIf *ident_zero_x* [ *j* ] is true, the argument *ax* [ *j* ]\nis a constant parameter that is identically zero.\n\nx_index\n*******\nis the variable index, on the tape, for the arguments to this function.\nThis size of x_index is n, the number of arguments to this function.\nThe index zero is used for parameters.\n\ny_index\n*******\nis the variable index, on the tape, for the results for this function.\nThis size of y_index is m, the number of results for this function.\nThe index zero is used for parameters.\n\nfor_jac_pattern\n***************\nOn input, for j = 0, ... , n-1, the sparsity pattern with index x_index[j],\nis the forward Jacobian pattern for the j-th argument to this atomic function.\n\nrev_jac_flag\n************\nOn input, for i = 0, ... , m-1, rev_jac_flag[ y_index[i] ] is true\nif the function we are computing the Hessian of has possibly non-zero Jacobian\nw.r.t variable y_index[i].\nOn output, for j = 0, ... , n, rev_jac_flag[ x_index[j] ] is set to true\nif the variable with index x_index[j] has possible non-zero Jacobian\nwith respect to one of the true y_index[i] cases.\nOtherwise, rev_jac_flag [ x_index[j] ] is not changed.\n\nhes_sparsity_rev\n****************\nIs the reverse mode sparsity pattern for the Hessian. On input, the non-linear\nterms in the atomic function have not been included. Upon return, they\nhave been included.\n\n{xrst_end atomic_four_rev_hes_sparsity}\n*/\n// BEGIN_REV_HES_SPARSITY\ntemplate <class Base>\ntemplate <class InternalSparsity>\nbool atomic_four<Base>::rev_hes_sparsity(\n    size_t                           call_id          ,\n    const vector<bool>&              ident_zero_x     ,\n    const vector<size_t>&            x_index          ,\n    const vector<size_t>&            y_index          ,\n    const InternalSparsity&          for_jac_pattern  ,\n    bool*                            rev_jac_flag     ,\n    InternalSparsity&                hes_sparsity_rev )\n// END_REV_HES_SPARSITY\n{   CPPAD_ASSERT_UNKNOWN( for_jac_pattern.number_elements(0) == 0 );\n    CPPAD_ASSERT_UNKNOWN( ! rev_jac_flag[0] );\n    //\n    size_t n      = x_index.size();\n    size_t m      = y_index.size();\n    //\n    // select_x\n    vector<bool> select_x(n);\n    for(size_t j = 0; j < n; j++)\n        select_x[j] = for_jac_pattern.number_elements( x_index[j] ) > 0;\n    //\n    // select_y\n    vector<bool> select_y(m);\n    for(size_t i = 0; i < m; i++)\n        select_y[i] = rev_jac_flag[ y_index[i] ];\n    //\n    // call atomic function for Jacobain sparsity\n    bool dependency = false;\n    sparse_rc< vector<size_t> > pattern_jac;\n    bool ok = jac_sparsity( call_id,\n        dependency, ident_zero_x, select_x, select_y, pattern_jac\n    );\n    if(! ok) ok = jac_sparsity(\n        call_id, dependency, select_x, select_y, pattern_jac\n    );\n    const vector<size_t>& row_jac( pattern_jac.row() );\n    const vector<size_t>& col_jac( pattern_jac.col() );\n    size_t nnz_jac = pattern_jac.nnz();\n    if( ! ok )\n        return ok;\n    //\n    // call atomic function for Hessian sparsity\n    sparse_rc< vector<size_t> > pattern_hes;\n    ok = hes_sparsity(\n        call_id, ident_zero_x, select_x, select_y, pattern_hes\n    );\n    if( ! ok ) ok = hes_sparsity(\n        call_id, select_x, select_y, pattern_hes\n    );\n    if( ! ok )\n        return ok;\n    //\n    // row_hes, col_hes, nnz_hes\n    const vector<size_t>& row_hes( pattern_hes.row() );\n    const vector<size_t>& col_hes( pattern_hes.col() );\n    size_t nnz_hes = pattern_hes.nnz();\n    //\n    // propagate Hessian sparsity through the Jacobian\n    for(size_t k = 0; k < nnz_jac; ++k)\n    {   size_t i = row_jac[k];\n        size_t j = col_jac[k];\n        CPPAD_ASSERT_KNOWN(\n            select_y[i] && select_x[j] ,\n            \"atomic: jac_sparsity: pattern_out not in \"\n            \"select_x or select_y range\"\n        );\n        // from y_index[i] to x_index[j]\n        hes_sparsity_rev.binary_union(\n            x_index[j], x_index[j], y_index[i], hes_sparsity_rev\n        );\n    }\n    //\n    // propagate rev_jac_flag through the Jacobian\n    // (seems OK to exclude variables with zero forward jacobian)\n    for(size_t k = 0; k < nnz_jac; ++k)\n    {   size_t j = col_jac[k];\n        rev_jac_flag[ x_index[j] ] = true;\n    }\n    //\n    // new hessian sparsity terms between y and x\n    for(size_t k = 0; k < nnz_hes; ++k)\n    {   size_t r = row_hes[k];\n        size_t c = col_hes[k];\n        CPPAD_ASSERT_KNOWN(\n            select_x[r] && select_x[c] ,\n            \"atomic: hes_sparsity: pattern_out not in select_x range\"\n        );\n        hes_sparsity_rev.binary_union(\n            x_index[r], x_index[r], x_index[c], for_jac_pattern\n        );\n        hes_sparsity_rev.binary_union(\n            x_index[c], x_index[c], x_index[r], for_jac_pattern\n        );\n    }\n    return ok;\n}\n\n} // END_CPPAD_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/atomic/four/devel/jac_sparsity.hpp",
    "content": "# ifndef CPPAD_CORE_ATOMIC_FOUR_DEVEL_JAC_SPARSITY_HPP\n# define CPPAD_CORE_ATOMIC_FOUR_DEVEL_JAC_SPARSITY_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n\n/*\n------------------------------------------------------------------------------\n{xrst_begin atomic_four_for_jac_sparsity dev}\n\nLink from Forward Jacobian Sparsity Sweep to atomic_four Callback\n#################################################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_FOR_JAC_SPARSITY\n    // END_FOR_JAC_SPARSITY\n}\n\nInternalSparsity\n****************\nis the type used for internal sparsity calculations; i.e.,\nsparse_pack or sparse_list.\n\ncall_id\n*******\nsee :ref:`atomic_four_call@call_id` .\n\ndependency\n**********\nif true, calculate dependency pattern,\notherwise calculate sparsity pattern.\n\nident_zero_x\n************\nThis argument has size equal to the number of arguments to this\natomic function; i.e. the size of *ax* .\nIf *ident_zero_x* [ *j* ] is true, the argument *ax* [ *j* ]\nis a constant parameter that is identically zero.\n\nx_index\n*******\nis the variable index, on the tape, for the arguments to this atomic function.\nThis size of x_index is, the number of arguments to this atomic function.\nThe index zero is used for parameters.\n\ny_index\n*******\nis the variable index, on the tape, for the results for this atomic function.\nThis size of y_index is m, the number of results for this atomic function.\nThe index zero is used for parameters.\n\nvar_sparsity\n************\nOn input, for j = 0, ... , n-1, the sparsity pattern with index x_index[j],\nis the sparsity for the j-th argument to this atomic function.\nOn output, for i = 0, ... , m-1, the sparsity pattern with index y_index[i],\nis the sparsity for the i-th result for this atomic function.\n\nReturn Value\n************\nis true if the computation succeeds.\n\n{xrst_end atomic_four_for_jac_sparsity}\n*/\n// BEGIN_FOR_JAC_SPARSITY\ntemplate <class Base>\ntemplate <class InternalSparsity>\nbool atomic_four<Base>::for_jac_sparsity(\n    size_t                           call_id      ,\n    bool                             dependency   ,\n    const vector<bool>&              ident_zero_x ,\n    const vector<size_t>&            x_index      ,\n    const vector<size_t>&            y_index      ,\n    InternalSparsity&                var_sparsity )\n// END_FOR_JAC_SPARSITY\n{  typedef typename InternalSparsity::const_iterator iterator;\n\n    // number of arguments and results for this atomic function\n    size_t n = x_index.size();\n    size_t m = y_index.size();\n\n    // select_y\n    vector<bool> select_y(m);\n    for(size_t i = 0; i < m; ++i)\n        select_y[i] = y_index[i] != 0;\n\n    // determine select_x\n    vector<bool> select_x(n);\n    for(size_t j = 0; j < n; ++j)\n    {  if( x_index[j] == 0 )\n            select_x[j] = false;\n        else\n        {  // check if x_j depends on any previous variable\n            iterator itr(var_sparsity, x_index[j]);\n            size_t ell = *itr;\n            select_x[j] = ell < var_sparsity.end();\n        }\n    }\n    sparse_rc< vector<size_t> > pattern_out;\n    bool ok = jac_sparsity( call_id,\n        dependency, ident_zero_x, select_x, select_y, pattern_out\n    );\n    if( ! ok ) ok = jac_sparsity(\n        call_id, dependency, select_x, select_y, pattern_out\n    );\n    if( ! ok )\n        return false;\n    //\n    // transfer sparsity patterns from pattern_out to var_sparsity\n    size_t                nnz = pattern_out.nnz();\n    const vector<size_t>& row( pattern_out.row() );\n    const vector<size_t>& col( pattern_out.col() );\n    for(size_t k = 0; k < nnz; ++k)\n    {  size_t i = row[k];\n        size_t j = col[k];\n        CPPAD_ASSERT_KNOWN(\n            select_y[i] && select_x[j],\n            \"atomic: jac_sparsity: pattern_out not in \"\n            \"select_x or select_y range\"\n        );\n        iterator itr(var_sparsity, x_index[j]);\n        size_t ell = *itr;\n        while( ell < var_sparsity.end() )\n        {  var_sparsity.post_element( y_index[i], ell );\n            ell = *(++itr);\n        }\n    }\n    for(size_t i = 0; i < m; ++i)\n        var_sparsity.process_post( y_index[i] );\n    //\n    return true;\n}\n\n/*\n------------------------------------------------------------------------------\n{xrst_begin atomic_four_rev_jac_sparsity dev}\n\nLink from Reverse Jacobian Sparsity Sweep to atomic_four Callback\n#################################################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_REV_JAC_SPARSITY\n    // END_REV_JAC_SPARSITY\n}\n\nInternalSparsity\n****************\nIs the type used for internal sparsity calculations; i.e.,\nsparse_pack or sparse_list.\n\ncall_id\n*******\nsee :ref:`atomic_four_call@call_id`\n\ndependency\n**********\nif true, calculate dependency pattern,\notherwise calculate sparsity pattern.\n\nident_zero_x\n************\nThis argument has size equal to the number of arguments to this\natomic function; i.e. the size of *ax* .\nIf *ident_zero_x* [ *j* ] is true, the argument *ax* [ *j* ]\nis a constant parameter that is identically zero.\n\nx_index\n*******\nis the variable index, on the tape, for the arguments to this atomic function.\nThis size of x_index is n, the number of arguments to this atomic function.\nThe index zero is used for parameters.\n\ny_index\n*******\nis the variable index, on the tape, for the results for this atomic function.\nThis size of y_index is m, the number of results for this atomic function.\nThe index zero is used for parameters.\n\nvar_sparsity\n************\nWe are given a sparsity pattern an outer function G(y, x) and compute\nthe pattern for an inner function H(x), which is the outer functions\nwith the components of y treated as functions of x; i.e.\nH(x) = G( Y(x), x).\n\ny_index\n=======\nOn input, for i = 0, ... , m-1, the sparsity pattern with index y_index[i],\nis the sparsity of the outer function with respect to the i-th\nresult for this atomic function.\n\nx_index\n=======\nOn input, for j = 0, ... , n-1, the sparsity pattern with index x_index[j],\nis the sparsity for the outer function with respect to the j-th\nargument to this atomic function.\nOn output, for j = 0, ... , n-1, the sparsity pattern with index x_index[j],\nis the sparsity for the inner function with respect to the j-th\nargument to this atomic function.\n\nReturn Value\n************\nis true if the computation succeeds.\n\n{xrst_end atomic_four_rev_jac_sparsity}\n*/\n// BEGIN_REV_JAC_SPARSITY\ntemplate <class Base>\ntemplate <class InternalSparsity>\nbool atomic_four<Base>::rev_jac_sparsity(\n    size_t                           call_id      ,\n    bool                             dependency   ,\n    const vector<bool>&              ident_zero_x ,\n    const vector<size_t>&            x_index      ,\n    const vector<size_t>&            y_index      ,\n    InternalSparsity&                var_sparsity )\n// END_REV_JAC_SPARSITY\n{   typedef typename InternalSparsity::const_iterator iterator;\n\n    // number of arguments and results for this atomic function\n    size_t n = x_index.size();\n    size_t m = y_index.size();\n\n    // selection vectors\n    vector<bool> select_x(n), select_y(m);\n\n    // select_x\n    for(size_t j = 0; j < n; ++j)\n        select_x[j] = x_index[j] != 0;\n\n    // determine select_y\n    for(size_t i = 0; i < m; ++i)\n    {   if( y_index[i] == 0 )\n            select_y[i] = false;\n        else\n        {   // check if y_i has sparsity is non-empty\n            iterator itr(var_sparsity, y_index[i]);\n            size_t ell = *itr;\n            select_y[i] = ell < var_sparsity.end();\n        }\n    }\n    sparse_rc< vector<size_t> > pattern_out;\n    bool ok = jac_sparsity( call_id,\n        dependency, ident_zero_x, select_x, select_y, pattern_out\n    );\n    if( ! ok ) ok = jac_sparsity(\n        call_id, dependency, select_x, select_y, pattern_out\n    );\n    if( ! ok )\n        return false;\n    //\n    // transfer sparsity patterns from pattern_out to var_sparsity\n    size_t                nnz = pattern_out.nnz();\n    const vector<size_t>& row( pattern_out.row() );\n    const vector<size_t>& col( pattern_out.col() );\n    for(size_t k = 0; k < nnz; ++k)\n    {   size_t i = row[k];\n        size_t j = col[k];\n        CPPAD_ASSERT_KNOWN(\n            select_y[i] && select_x[j],\n            \"atomic: jac_sparsity: pattern_out not in \"\n            \"select_x or select_y range\"\n        );\n        iterator itr(var_sparsity, y_index[i]);\n        size_t ell = *itr;\n        while( ell < var_sparsity.end() )\n        {   var_sparsity.post_element( x_index[j], ell );\n            ell = *(++itr);\n        }\n    }\n    for(size_t j = 0; j < n; ++j)\n        var_sparsity.process_post( x_index[j] );\n    //\n    return true;\n}\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/atomic/four/for_type.hpp",
    "content": "# ifndef CPPAD_CORE_ATOMIC_FOUR_FOR_TYPE_HPP\n# define CPPAD_CORE_ATOMIC_FOUR_FOR_TYPE_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_four_for_type}\n\nAtomic Function Forward Type Calculation\n########################################\n\nSyntax\n******\n| *ok* = *afun* . ``for_type`` ( *call_id* , *type_x* , *type_y* )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_PROTOTYPE\n    // END_PROTOTYPE\n}\n\nDependency Analysis\n*******************\nThis calculation is sometimes referred to as a forward dependency analysis.\n\nUsage\n*****\nThis syntax and prototype are used a\n:ref:`call<atomic_four_call-name>` to an atomic function.\n\nImplementation\n**************\nThis virtual function must be defined by the\n:ref:`atomic_four_ctor@atomic_user` derived class.\n\nvector\n******\nis the :ref:`CppAD_vector-name` template class.\n\nBase\n****\nSee :ref:`atomic_four_call@Base` .\n\ncall_id\n*******\nSee :ref:`atomic_four_call@call_id` .\n\nad_type\n*******\nThe type ``CppAD::ad_type_enum``\nis used to specify if an AD object is a\n:ref:`constant parameter<glossary@Parameter@Constant>`\n:ref:`dynamic parameter<glossary@Parameter@Dynamic>`\nor :ref:`glossary@Variable` .\nIt has the following possible values:\n\n.. csv-table::\n    :widths: auto\n\n    *ad_type_enum*,Meaning\n    ``identical_zero_enum``,identically zero\n    ``constant_enum``,constant parameter\n    ``dynamic_enum``,dynamic parameter\n    ``variable_enum``,variable\n\nIn addition,\n\n    ``identical_zero_enum < constant_enum < dynamic_enum < variable_enum``\n\nA value that is identically zero is also a constant parameter.\nIn CppAD, multiplication of a variable by a value that is identically zero\nis sometimes treated like :ref:`azmul-title`.\nThis avoids having to record the operation.\n\ntype_x\n******\nThis vector has size equal to the number of arguments in the\natomic function call; i.e., the size of\n:ref:`atomic_four_call@ax` which we denote by *n* .\nFor *j* =0,..., *n* ``-1`` , *type_x* [ *j* ]\nis the type of *ax* [ *j* ] .\n\ntype_y\n******\nThis vector has size equal to the number of results in the\natomic function call; i.e., the size of\n:ref:`atomic_four_call@ay` which we denote by *m* .\nThe input values of the elements of *type_y*\nare not specified (must not matter).\nUpon return, for :math:`i = 0 , \\ldots , m-1`,\n*type_y* [ *i* ] is set to one of the following values:\n\n#. It is ``identical_zero_enum`` if *ay* [ *i* ] is\n   :ref:`identically zero<base_identical@Identical>` .\n#. It is ``constant_enum`` if *ay* [ *i* ] only depends on\n   the arguments that are constants.\n#. It is ``dynamic_enum`` if *ay* [ *i* ] depends on\n   a dynamic parameter and does not depend on any variables.\n#. It is ``variable_enum`` if *ay* [ *i* ] depends on\n   a variable.\n\nok\n**\nIf this calculation succeeded, *ok* is true.\nOtherwise, it is false.\n\nExample\n*******\nThe following is an example ``for_type`` definition taken from\n:ref:`atomic_four_norm_sq.cpp-name` :\n{xrst_literal\n    example/atomic_four/norm_sq.cpp\n    // BEGIN FOR_TYPE\n    // END FOR_TYPE\n}\n\n{xrst_end atomic_four_for_type}\n-----------------------------------------------------------------------------\n*/\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n\n// BEGIN_PROTOTYPE\ntemplate <class Base>\nbool atomic_four<Base>::for_type(\n    size_t                       call_id     ,\n    const vector<ad_type_enum>&  type_x      ,\n    vector<ad_type_enum>&        type_y      )\n// END_PROTOTYPE\n{   return false; }\n\n} // END_CPPAD_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/atomic/four/forward.hpp",
    "content": "# ifndef CPPAD_CORE_ATOMIC_FOUR_FORWARD_HPP\n# define CPPAD_CORE_ATOMIC_FOUR_FORWARD_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_four_forward}\n{xrst_spell\n    ataylor\n}\n\nAtomic Function Forward Mode\n############################\n\nSyntax\n******\n\nBase\n====\n\n| *ok* = *afun* . ``forward`` (\n| |tab| *call_id* , *select_y* ,\n| |tab| *order_low* , *order_up* , *type_x* , *taylor_x* , *taylor_y*\n| )\n\nAD<Base>\n========\n\n| *ok* = *afun* . ``forward`` (\n| |tab| *call_id* , *select_y* ,\n| |tab| *order_low* , *order_up* , *type_x* , *ataylor_x* , *ataylor_y*\n| )\n\nPrototype\n*********\n\nBase\n====\n{xrst_literal\n    // BEGIN_PROTOTYPE_BASE\n    // END_PROTOTYPE_BASE\n}\n\nAD<Base>\n========\n{xrst_literal\n    // BEGIN_PROTOTYPE_AD_BASE\n    // END_PROTOTYPE_AD_BASE\n}\n\nBase\n****\nsee :ref:`atomic_four_call@Base` .\n\nvector\n******\nis the :ref:`CppAD_vector-name` template class.\n\nUsage\n*****\n\nBase\n====\nThe *Base* syntax and prototype are used by a\n:ref:`call<atomic_four_call-name>` to the atomic function *afun* .\nThey are also used by\n*f* . ``Forward`` and *f* . ``new_dynamic``\nwhere *f* has prototype\n\n    ``ADFun`` < *Base* > *f*\n\nand *afun* is used during the recording of *f* .\n\nAD<Base>\n========\nThe ``AD`` < *Base* > syntax and prototype are used by\n*af* . ``Forward`` and *af* . ``new_dynamic``\nwhere *af* has prototype\n\n    ``ADFun< AD<`` *Base* > , *Base* > *af*\n\nand *afun* is used in a function *af* ,\ncreated from *f* using :ref:`base2ad-name` .\n\nImplementation\n**************\nThe *taylor_x* , *taylor_y* version of this function\nmust be defined by the\n:ref:`atomic_four_ctor@atomic_user` class.\nIt can return *ok* == ``false``\n(and not compute anything) for values\nof *order_up* that are greater than those used by your\n:ref:`Forward-name` mode calculations.\nOrder zero must be implemented.\n\ncall_id\n*******\nSee :ref:`atomic_four_call@call_id` .\n\nselect_y\n********\nThis argument has size equal to the number of results to this\natomic function; i.e. the size of :ref:`atomic_four_call@ay` .\nIt specifies which components of *y* the corresponding\nTaylor coefficients must be computed.\n\norder_low\n*********\nThis argument\nspecifies the lowest order Taylor coefficient that we are computing.\n\np\n=\nWe sometimes use the notation *p* = *order_low* below.\n\norder_up\n********\nThis argument is the highest order Taylor coefficient that we\nare computing ( *order_low* <= *order_up* ).\n\nq\n=\nWe use the notation *q* = *order_up*  + 1 below.\nThis is the number of Taylor coefficients for each\ncomponent of *x* and *y* .\n\ntaylor_x\n********\nThe size of *taylor_x* is *q* * *n* .\nFor :math:`j = 0 , \\ldots , n-1` and :math:`k = 0 , \\ldots , q-1`,\nwe use the Taylor coefficient notation\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        x_j^k    & = & \\R{taylor\\_x} [ j * q + k ]\n        \\\\\n        X_j (t)  & = & x_j^0 + x_j^1 t^1 + \\cdots + x_j^{q-1} t^{q-1}\n    \\end{eqnarray}\n\nNote that superscripts represent an index for :math:`x_j^k`\nand an exponent for :math:`t^k`.\nAlso note that the Taylor coefficients for :math:`X(t)` correspond\nto the derivatives of :math:`X(t)` at :math:`t = 0` in the following way:\n\n.. math::\n\n    x_j^k = \\frac{1}{ k ! } X_j^{(k)} (0)\n\nparameters\n==========\nIf the *j*-th component of *x* is a parameter,\n\n    *type_x* [ *j* ] < ``CppAD::variable_enum``\n\nIn this case, for *k*  > 0 ,\n\n    *taylor_x* [ *j* * *q* + *k*  ] == 0\n\nataylor_x\n*********\nThe specifications for *ataylor_x* is the same as for *taylor_x*\n(only the type of *ataylor_x* is different).\n\ntaylor_y\n********\nThe size of *taylor_y* is *q* * *m* .\nUpon return,\nFor :math:`i = 0 , \\ldots , m-1` and :math:`k = 0 , \\ldots , q-1`,\nif *select_y* [ *i* ] is true,\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        Y_i (t)  & = & g_i [ X(t) ]\n        \\\\\n        Y_i (t)  & = & y_i^0 + y_i^1 t^1 + \\cdots + y_i^{q-1} t^{q-1} + o( t^{q-1} )\n        \\\\\n        \\R{taylor\\_y}  [ i * q + k ] & = & y_i^k\n    \\end{eqnarray}\n\nwhere :math:`o( t^{q-1} ) / t^{q-1} \\rightarrow 0`\nas :math:`t \\rightarrow 0`.\nNote that superscripts represent an index for :math:`y_j^k`\nand an exponent for :math:`t^k`.\nAlso note that the Taylor coefficients for :math:`Y(t)` correspond\nto the derivatives of :math:`Y(t)` at :math:`t = 0` in the following way:\n\n.. math::\n\n    y_j^k = \\frac{1}{ k ! } Y_j^{(k)} (0)\n\nIf :math:`p > 0`,\nfor :math:`i = 0 , \\ldots , m-1` and :math:`k = 0 , \\ldots , p-1`,\nthe input of *taylor_y* satisfies\n\n.. math::\n\n    \\R{taylor\\_y}  [ i * q + k ] = y_i^k\n\nThese values do not need to be recalculated\nand can be used during the computation of the higher order coefficients.\n\nataylor_y\n*********\nThe specifications for *ataylor_y* is the same as for *taylor_y*\n(only the type of *ataylor_y* is different).\n\nok\n**\nIf this calculation succeeded, *ok* is true.\nOtherwise, it is false.\n\nDiscussion\n**********\nFor example, suppose that *order_up*  == 2 ,\nand you know how to compute the function :math:`g(x)`,\nits first derivative :math:`g^{(1)} (x)`,\nand it component wise Hessian :math:`g_i^{(2)} (x)`.\nThen you can compute *taylor_x* using the following formulas:\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    y_i^0 & = & Y(0)\n            = g_i ( x^0 )\n    \\\\\n    y_i^1 & = & Y^{(1)} ( 0 )\n            = g_i^{(1)} ( x^0 ) X^{(1)} ( 0 )\n            = g_i^{(1)} ( x^0 ) x^1\n    \\\\\n    y_i^2\n    & = & \\frac{1}{2 !} Y^{(2)} (0)\n    \\\\\n    & = & \\frac{1}{2} X^{(1)} (0)^\\R{T} g_i^{(2)} ( x^0 ) X^{(1)} ( 0 )\n      +   \\frac{1}{2} g_i^{(1)} ( x^0 ) X^{(2)} ( 0 )\n    \\\\\n    & = & \\frac{1}{2} (x^1)^\\R{T} g_i^{(2)} ( x^0 ) x^1\n      +    g_i^{(1)} ( x^0 ) x^2\n    \\end{eqnarray}\n\nFor :math:`i = 0 , \\ldots , m-1`, and :math:`k = 0 , 1 , 2`,\n\n.. math::\n\n    \\R{taylor\\_y} [ i * q + k ] = y_i^k\n\nExample\n*******\nThe following is an example ``forward`` definition taken from\n:ref:`atomic_four_norm_sq.cpp-name` :\n{xrst_literal\n    example/atomic_four/norm_sq.cpp\n    // BEGIN FORWARD\n    // END FORWARD\n}\n\n{xrst_end atomic_four_forward}\n-----------------------------------------------------------------------------\n*/\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n\n// BEGIN_PROTOTYPE_BASE\ntemplate <class Base>\nbool atomic_four<Base>::forward(\n    size_t                       call_id     ,\n    const vector<bool>&          select_y    ,\n    size_t                       order_low   ,\n    size_t                       order_up    ,\n    const vector<Base>&          taylor_x    ,\n    vector<Base>&                taylor_y    )\n// END_PROTOTYPE_BASE\n{   return false; }\n\n// BEGIN_PROTOTYPE_AD_BASE\ntemplate <class Base>\nbool atomic_four<Base>::forward(\n    size_t                       call_id      ,\n    const vector<bool>&          select_y    ,\n    size_t                       order_low    ,\n    size_t                       order_up     ,\n    const vector< AD<Base> >&    ataylor_x    ,\n    vector< AD<Base> >&          ataylor_y    )\n// END_PROTOTYPE_AD_BASE\n{   return false; }\n\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/atomic/four/hes_sparsity.hpp",
    "content": "# ifndef CPPAD_CORE_ATOMIC_FOUR_HES_SPARSITY_HPP\n# define CPPAD_CORE_ATOMIC_FOUR_HES_SPARSITY_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/core/atomic/four/devel/hes_sparsity.hpp>\n/*\n{xrst_begin atomic_four_hes_sparsity}\n\nAtomic Function Hessian Sparsity Patterns\n#########################################\n\nSyntax\n******\n\nPreferred\n=========\n\n| *ok* = *afun* . ``hes_sparsity`` ( *call_id* ,\n| |tab| *ident_zero_x* , *select_x* , *select_y* , *pattern_out*\n| )\n\nDeprecated 2022-05-16\n=====================\n\n| *ok* = *afun* . ``hes_sparsity`` ( *call_id* ,\n| |tab| *select_x* , *select_y* , *pattern_out*\n| )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_PROTOTYPE\n    // END_PROTOTYPE\n}\n\nImplementation\n**************\nThis function must be defined if\n:ref:`atomic_four_ctor@atomic_user@afun` is\nused to define an :ref:`ADFun-name` object *f* ,\nand Hessian sparsity patterns are computed for *f* .\n\nBase\n****\nSee :ref:`atomic_four_call@Base` .\n\nvector\n******\nis the :ref:`CppAD_vector-name` template class.\n\ncall_id\n*******\nSee :ref:`atomic_four_call@call_id` .\n\nident_zero_x\n************\nThis can sometimes be used to create more efficient sparsity patterns.\nIf you do not see a way to do this, you can just ignore it.\nThis argument has size equal to the number of arguments to this\natomic function; i.e. the size of *ax* .\nIf *ident_zero_x* [ *j* ] is true, the argument *ax* [ *j* ]\nis a constant parameter that is identically zero.\nAn identically zero value times any other value can be treated\nas being identically zero.\n\nselect_x\n********\nThis argument has size equal to the number of arguments to this\natomic function; i.e. the size of *ax* .\nIt specifies which domain components are included in\nthe calculation of *pattern_out* .\nIf *select_x* [ *j* ] is false, then there will be no indices\n*k* such that either of the following hold:\n\n| |tab| *pattern_out* . ``row`` ()[ *k* ] == *j*\n| |tab| *pattern_out* . ``col`` ()[ *k* ] == *j*\n\n.\n\nselect_y\n********\nThis argument has size equal to the number of results to this\natomic function; i.e. the size of *ay* .\nIt specifies which range component functions :math:`g_i (x)` are included in\nof *pattern_out* .\n\npattern_out\n***********\nThis input value of *pattern_out* does not matter.\nUpon return it is the union,\nwith respect to *i* such that *select_y* [ *i* ] is true,\nof the sparsity pattern for Hessian of :math:`g_i (x)`.\nTo be specific, there are non-negative indices\n*r* , *c* , and *k* such that\n\n| |tab| *pattern_out* . ``row`` ()[ *k* ] == *r*\n| |tab| *pattern_out* . ``col`` ()[ *k* ] == *c*\n\nif and only if\nthere exists an index *i* such that,\n*select_y* [ *i* ] is true,\n*select_x* [ *r* ] is true,\n*select_x* [ *c* ] is true,\nand\n\n.. math::\n\n    \\partial_{x(r)} \\partial_{x(c)} g_i(x)\n\nis possibly non-zero.\nNote that the sparsity pattern should be symmetric.\n\nok\n**\nIf this calculation succeeded, *ok* is true.\nOtherwise it is false.\n\nExample\n*******\nThe following is an example ``hes_sparsity`` definition taken from\n:ref:`atomic_four_norm_sq.cpp-name` :\n{xrst_literal\n    example/atomic_four/norm_sq.cpp\n    // BEGIN HES_SPARSITY\n    // END HES_SPARSITY\n}\n\n{xrst_end atomic_four_hes_sparsity}\n-----------------------------------------------------------------------------\n*/\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n// BEGIN_PROTOTYPE\ntemplate <class Base>\nbool atomic_four<Base>::hes_sparsity(\n    size_t                                  call_id      ,\n    const vector<bool>&                     ident_zero_x ,\n    const vector<bool>&                     select_x     ,\n    const vector<bool>&                     select_y     ,\n    sparse_rc< vector<size_t> >&            pattern_out  )\n// END_PROTOTYPE\n{   return false; }\n//\n// deprecated version\ntemplate <class Base>\nbool atomic_four<Base>::hes_sparsity(\n    size_t                                  call_id      ,\n    const vector<bool>&                     select_x     ,\n    const vector<bool>&                     select_y     ,\n    sparse_rc< vector<size_t> >&            pattern_out  )\n{   return false; }\n\n} // END_CPPAD_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/atomic/four/jac_sparsity.hpp",
    "content": "# ifndef CPPAD_CORE_ATOMIC_FOUR_JAC_SPARSITY_HPP\n# define CPPAD_CORE_ATOMIC_FOUR_JAC_SPARSITY_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/core/atomic/four/devel/jac_sparsity.hpp>\n\n/*\n{xrst_begin atomic_four_jac_sparsity}\n\nAtomic Function Jacobian Sparsity Patterns\n##########################################\n\nSyntax\n******\n| You can define one or the other of the following callbacks,\n| but you should not define both.\n\nPreferred\n=========\n\n| *ok* = *afun* . ``jac_sparsity`` ( *call_id* ,\n| |tab| *dependency* , *ident_zero_x* , *select_x* , *select_y* , *pattern_out*\n| )\n\nDeprecated 2022-05-10\n=====================\n\n| *ok* = *afun* . ``jac_sparsity`` (\n| |tab| *dependency* , *call_id* , *select_x* , *select_y* , *pattern_out*\n| )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_PROTOTYPE\n    // END_PROTOTYPE\n}\n\nImplementation\n**************\nThis function must be defined if\n:ref:`atomic_four_ctor@atomic_user@afun` is\nused to define an :ref:`ADFun-name` object *f* ,\nand Jacobian sparsity patterns are computed for *f* .\n(Computing Hessian sparsity patterns\nrequires Jacobian sparsity patterns.)\n\nBase\n****\nSee :ref:`atomic_four_call@Base` .\n\nvector\n******\nis the :ref:`CppAD_vector-name` template class.\n\ncall_id\n*******\nSee :ref:`atomic_four_call@call_id` .\n\ndependency\n**********\nIf *dependency* is true,\nthen *pattern_out* is a\n:ref:`dependency.cpp@Dependency Pattern`\nfor this atomic function.\nOtherwise it is a\n:ref:`glossary@Sparsity Pattern` for the\nderivative of the atomic function.\n\nident_zero_x\n************\nThis can sometimes be used to create more efficient sparsity patterns.\nIf you do not see a way to do this, you can just ignore it.\nThis argument has size equal to the number of arguments to this\natomic function; i.e. the size of *ax* .\nIf *ident_zero_x* [ *j* ] is true, the argument *ax* [ *j* ]\nis a constant parameter that is identically zero.\nAn identically zero value times any other value can be treated\nas being identically zero.\n\nselect_x\n********\nThis argument has size equal to the number of arguments to this\natomic function; i.e. the size of *ax* .\nIt specifies which domain components are included in\nthe calculation of *pattern_out* .\nIf *select_x* [ *j* ] is false, then there will be no indices\n*k* such that\n\n    *pattern_out* . ``col`` ()[ *k* ] == *j*\n\n.\nIf *select_x* [ *j* ] is true, the argument *ax* [ *j* ]\nis a variable and *ident_zero_x* [ *j* ] will be false.\n\nselect_y\n********\nThis argument has size equal to the number of results to this\natomic function; i.e. the size of *ay* .\nIt specifies which range components are included in\nthe calculation of *pattern_out* .\nIf *select_y* [ *i* ] is false, then there will be no indices\n*k* such that\n\n    *pattern_out* . ``row`` ()[ *k* ] == *i*\n\n.\n\npattern_out\n***********\nThis input value of *pattern_out* does not matter.\nUpon return it is a\ndependency or sparsity pattern for the Jacobian of :math:`g(x)`,\nthe function corresponding to\n:ref:`atomic_four_ctor@atomic_user@afun` .\nTo be specific, there are non-negative indices\n*i* , *j* , *k* such that\n\n| |tab| *pattern_out* . ``row`` ()[ *k* ] == *i*\n| |tab| *pattern_out* . ``col`` ()[ *k* ] == *j*\n\nif and only if\n*select_x* [ *j* ] is true,\n*select_y* [ *j* ] is true,\nand :math:`g_i(x)` depends on the value of :math:`x_j`\n(and the partial of :math:`g_i(x)` with respect to\n:math:`x_j` is possibly non-zero).\n\nok\n**\nIf this calculation succeeded, *ok* is true.\nOtherwise it is false.\n\nExample\n*******\nThe following is an example ``jac_sparsity`` definition taken from\n:ref:`atomic_four_norm_sq.cpp-name` :\n{xrst_literal\n    example/atomic_four/norm_sq.cpp\n    // BEGIN JAC_SPARSITY\n    // END JAC_SPARSITY\n}\n\n{xrst_end atomic_four_jac_sparsity}\n-----------------------------------------------------------------------------\n*/\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n//\n// BEGIN_PROTOTYPE\ntemplate <class Base>\nbool atomic_four<Base>::jac_sparsity(\n    size_t                                  call_id      ,\n    bool                                    dependency   ,\n    const vector<bool>&                     ident_zero_x ,\n    const vector<bool>&                     select_x     ,\n    const vector<bool>&                     select_y     ,\n    sparse_rc< vector<size_t> >&            pattern_out  )\n// END_PROTOTYPE\n{   return false; }\n//\n// deprecated version of jac_sparsity callback\ntemplate <class Base>\nbool atomic_four<Base>::jac_sparsity(\n    size_t                                  call_id      ,\n    bool                                    dependency   ,\n    const vector<bool>&                     select_x     ,\n    const vector<bool>&                     select_y     ,\n    sparse_rc< vector<size_t> >&            pattern_out  )\n{   return false; }\n} // END_CPPAD_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/atomic/four/rev_depend.hpp",
    "content": "# ifndef CPPAD_CORE_ATOMIC_FOUR_REV_DEPEND_HPP\n# define CPPAD_CORE_ATOMIC_FOUR_REV_DEPEND_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-23 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_four_rev_depend}\n\nAtomic Function Reverse Dependency\n##################################\n\nSyntax\n******\nYou can define one or the other of the following callbacks,\nbut you should not define both.\n\nPreferred\n=========\n\n| *ok* = *afun* . ``rev_depend`` ( *call_id* ,\n| |tab| *ident_zero_x* , *depend_x* , *depend_y*\n| )\n\nDeprecated 2022-05-10\n=====================\n\n| *ok* = *afun* . ``rev_depend`` ( *call_id* ,\n| |tab| *depend_x* , *depend_y*\n| )\n\nPrototype\n=========\n{xrst_literal\n    // BEGIN_PROTOTYPE\n    // END_PROTOTYPE\n}\n\nDependency Analysis\n*******************\nThis calculation is sometimes referred to as a reverse dependency analysis.\n\nImplementation\n**************\nThis function must be defined if\n:ref:`atomic_four_ctor@atomic_user@afun` is\nused to define an :ref:`ADFun-name` object *f* ,\nand :ref:`f.optimize()<optimize-name>` is used.\n\nBase\n****\nSee :ref:`atomic_four_call@Base` .\n\nvector\n******\nis the :ref:`CppAD_vector-name` template class.\n\ncall_id\n*******\nSee :ref:`atomic_four_call@call_id` .\n\nident_zero_x\n************\nThis can sometimes be used to create more efficient dependency\n(fewer true values in *depend_x* ).\nIf you do not see a way to do this, you can just ignore it.\nThis argument has size equal to the number of arguments to this\natomic function; i.e. the size of *ax* .\nIf *ident_zero_x* [ *j* ] is true, the argument *ax* [ *j* ]\nis a constant parameter that is identically zero.\nAn identically zero value times any other value can be treated\nas being identically zero.\n\ndepend_x\n********\nThis vector has size equal to the number of arguments for this atomic function;\ni.e. *n* = *ax* . ``size`` () (see :ref:`atomic_four_call@ax` ).\nThe input values of the elements of *depend_x*\nare not specified (must not matter).\nUpon return, for :math:`j = 0 , \\ldots , n-1`,\n*depend_x* [ *j* ] is true if the values of interest depend\non the value of *ax* [ *j* ] in the corresponding atomic function call.\n\nOptimize\n========\nParameters and variables,\nthat the values of interest do not depend on,\nmay get removed by :ref:`optimization<optimize-name>` .\nThe corresponding values in\n:ref:`atomic_four_forward@taylor_x`\n(after optimization has removed them) are currently zero,\nbut perhaps these should be changed back to nan.\n\ndepend_y\n********\nThis vector has size equal to the number of results for this atomic function;\ni.e. *m* = *ay* . ``size`` () (see :ref:`atomic_four_call@ay` ).\nFor :math:`i = 0 , \\ldots , m-1`,\n*depend_y* [ *i* ] is true if the values of interest depend\non the value of *ay* [ *i* ] in the corresponding atomic function call.\n\nok\n**\nIf this calculation succeeded, *ok* is true.\nOtherwise, it is false.\n\nExample\n*******\nThe following is an example ``rev_depend`` definition taken from\n:ref:`atomic_four_norm_sq.cpp-name` :\n{xrst_literal\n    example/atomic_four/norm_sq.cpp\n    // BEGIN REV_DEPEND\n    // END REV_DEPEND\n}\n\n{xrst_end atomic_four_rev_depend}\n-----------------------------------------------------------------------------\n*/\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n\n// BEGIN_PROTOTYPE\ntemplate <class Base>\nbool atomic_four<Base>::rev_depend(\n    size_t                      call_id      ,\n    const vector<bool>&         ident_zero_x ,\n    vector<bool>&               depend_x     ,\n    const vector<bool>&         depend_y     )\n// END_PROTOTYPE\n{   return false; }\n\n// deprecated version\ntemplate <class Base>\nbool atomic_four<Base>::rev_depend(\n    size_t                      call_id     ,\n    vector<bool>&               depend_x    ,\n    const vector<bool>&         depend_y    )\n// end deprecated version\n{   return false; }\n\n} // END_CPPAD_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/atomic/four/reverse.hpp",
    "content": "# ifndef CPPAD_CORE_ATOMIC_FOUR_REVERSE_HPP\n# define CPPAD_CORE_ATOMIC_FOUR_REVERSE_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_four_reverse}\n{xrst_spell\n    apartial\n    ataylor\n}\n\nAtomic Function Reverse Mode\n############################\n\nSyntax\n******\n\nBase\n====\n\n| *ok* = *afun* . ``reverse`` (\n| |tab| *call_id* , *select_x* ,\n| |tab| *order_up* , *taylor_x* , *taylor_y* , *partial_x* , *partial_y*\n| )\n\nAD<Base>\n========\n\n| *ok* = *afun* . ``reverse`` (\n| |tab| *call_id* , *select_x* ,\n| |tab| *order_up* , *ataylor_x* , *ataylor_y* , *apartial_x* , *apartial_y*\n| )\n\nPrototype\n*********\n\nBase\n====\n{xrst_literal\n    // BEGIN_PROTOTYPE_BASE\n    // END_PROTOTYPE_BASE\n}\n\nAD<Base>\n========\n{xrst_literal\n    // BEGIN_PROTOTYPE_AD_BASE\n    // END_PROTOTYPE_AD_BASE\n}\n\nBase\n****\nsee :ref:`atomic_four_call@Base` .\n\nvector\n******\nis the :ref:`CppAD_vector-name` template class.\n\nUsage\n*****\n\nBase\n====\nThis syntax is used by *f* . ``Reverse`` where *f* has prototype\n\n    ``ADFun`` < *Base* > *f*\n\nand atomic function *afun* is used in *f* ;\nsee :ref:`atomic_four_call@Base` .\n\nAD<Base>\n========\nThis syntax is used by *af* . ``Reverse`` where *af* has prototype\n\n    ``ADFun< AD<`` *Base* > , *Base* > *af*\n\nand the atomic function *afun* is used in\n*af* ; see :ref:`base2ad-name` .\n\nImplementation\n**************\nThis function must be defined if\n:ref:`atomic_four_ctor@atomic_user@afun` is\nused during the recording of an :ref:`ADFun-name` object *f* ,\nand reverse mode derivatives are computed for *f* .\nIt can return *ok* == ``false``\n(and not compute anything) for values\nof *order_up* that are greater than those used by your\n:ref:`Reverse-name` mode calculations.\n\ncall_id\n*******\nSee :ref:`atomic_four_call@call_id` .\n\nselect_x\n********\nThis argument has size equal to the number of arguments to this\natomic function; i.e. the size of :ref:`atomic_four_call@ax` .\nIt specifies which components of *x* the corresponding\npartial derivatives *partial_x* must be computed.\n\norder_up\n********\nThis argument is one greater than highest order Taylor coefficient that\ncomputing the derivative of.\n\nq\n*\nWe use the notation *q* = *order_up*  + 1 below.\nThis is one less than the number of Taylor coefficients for each component\nof *x* and *y* .\n\ntaylor_x\n********\nThe size of *taylor_x* is *q* * *n* .\nFor :math:`j = 0 , \\ldots , n-1` and :math:`k = 0 , \\ldots , q-1`,\nwe use the Taylor coefficient notation\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        x_j^k    & = & \\R{taylor\\_x} [ j * q + k ]\n        \\\\\n        X_j (t)  & = & x_j^0 + x_j^1 t^1 + \\cdots + x_j^{q-1} t^{q-1}\n    \\end{eqnarray}\n\nNote that superscripts represent an index for :math:`x_j^k`\nand an exponent for :math:`t^k`.\nAlso note that the Taylor coefficients for :math:`X(t)` correspond\nto the derivatives of :math:`X(t)` at :math:`t = 0` in the following way:\n\n.. math::\n\n    x_j^k = \\frac{1}{ k ! } X_j^{(k)} (0)\n\nparameters\n==========\nIf the *j*-th component of *x* is a parameter,\n\n    *type_x* [ *j* ] < ``CppAD::variable_enum``\n\nIn this case, for *k*  > 0 ,\n\n    *taylor_x* [ *j* * *q* + *k*  ] == 0\n\nataylor_x\n*********\nThe specifications for *ataylor_x* is the same as for *taylor_x*\n(only the type of *ataylor_x* is different).\n\ntaylor_y\n********\nThe size of *taylor_y* is *q* * *m* .\nFor :math:`i = 0 , \\ldots , m-1` and :math:`k = 0 , \\ldots , q-1`,\nwe use the Taylor coefficient notation\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        Y_i (t)  & = & g_i [ X(t) ]\n        \\\\\n        Y_i (t)  & = &\n            y_i^0 + y_i^1 t^1 + \\cdots + y_i^{q-1} t^{q-1} + o ( t^{q-1} )\n        \\\\\n        y_i^k    & = & \\R{taylor\\_y} [ i * q + k ]\n    \\end{eqnarray}\n\nwhere :math:`o( t^{q-1} ) / t^{q-1} \\rightarrow 0` as :math:`t \\rightarrow 0`.\nNote that superscripts represent an index for :math:`y_j^k`\nand an exponent for :math:`t^k`.\nAlso note that the Taylor coefficients for :math:`Y(t)` correspond\nto the derivatives of :math:`Y(t)` at :math:`t = 0` in the following way:\n\n.. math::\n\n    y_j^k = \\frac{1}{ k ! } Y_j^{(k)} (0)\n\nataylor_y\n*********\nThe specifications for *ataylor_y* is the same as for *taylor_y*\n(only the type of *ataylor_y* is different).\n\nF\n*\nWe use the notation :math:`\\{ x_j^k \\} \\in \\B{R}^{n \\times q}` for\n\n.. math::\n\n    \\{ x_j^k \\W{:} j = 0 , \\ldots , n-1, k = 0 , \\ldots , q-1 \\}\n\nWe use the notation :math:`\\{ y_i^k \\} \\in \\B{R}^{m \\times q}` for\n\n.. math::\n\n    \\{ y_i^k \\W{:} i = 0 , \\ldots , m-1, k = 0 , \\ldots , q-1 \\}\n\nWe use\n:math:`F : \\B{R}^{n \\times q} \\rightarrow \\B{R}^{m \\times q}` by\nto denote the function corresponding to the forward mode calculations\n\n.. math::\n\n    y_i^k = F_i^k [ \\{ x_j^k \\} ]\n\nNote that\n\n.. math::\n\n    F_i^0 ( \\{ x_j^k \\} ) = g_i ( X(0) )  = g_i ( x^0 )\n\nWe also note that\n:math:`F_i^\\ell ( \\{ x_j^k \\} )` is a function of\n:math:`x^0 , \\ldots , x^\\ell`; i.e.,\nit is determined by the derivatives of :math:`g_i (x)`\nup to order :math:`\\ell`.\n\nG, H\n****\nWe use :math:`G : \\B{R}^{m \\times q} \\rightarrow \\B{R}`\nto denote an arbitrary scalar valued function of :math:`\\{ y_i^k \\}`.\nWe use :math:`H : \\B{R}^{n \\times q} \\rightarrow \\B{R}`\ndefined by\n\n.. math::\n\n    H ( \\{ x_j^k \\} ) = G[ F( \\{ x_j^k \\} ) ]\n\npartial_y\n*********\nThe size of *partial_y* is *q* * *m* .\nFor :math:`i = 0 , \\ldots , m-1`, :math:`k = 0 , \\ldots , q-1`,\n\n.. math::\n\n    \\R{partial\\_y} [ i * q + k ] = \\partial G / \\partial y_i^k\n\napartial_y\n**********\nThe specifications for *apartial_y* is the same as for\n*partial_y* (only the type of *apartial_y* is different).\n\npartial_x\n*********\nThe size of *partial_x* is *q* * *n* .\nThe input values of the elements of *partial_x*\nare not specified (must not matter).\nUpon return,\nfor :math:`j = 0 , \\ldots , n-1` and :math:`\\ell = 0 , \\ldots , q-1`,\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    \\R{partial\\_x} [ j * q + \\ell ] & = & \\partial H / \\partial x_j^\\ell\n    \\\\\n    & = &\n    ( \\partial G / \\partial \\{ y_i^k \\} ) \\cdot\n        ( \\partial \\{ y_i^k \\} / \\partial x_j^\\ell )\n    \\\\\n    & = &\n    \\sum_{k=0}^{q-1}\n    \\sum_{i=0}^{m-1}\n    ( \\partial G / \\partial y_i^k ) ( \\partial y_i^k / \\partial x_j^\\ell )\n    \\\\\n    & = &\n    \\sum_{k=\\ell}^{q-1}\n    \\sum_{i=0}^{m-1}\n    \\R{partial\\_y}[ i * q + k ] ( \\partial F_i^k / \\partial x_j^\\ell )\n    \\end{eqnarray}\n\nNote that we have used the fact that for :math:`k < \\ell`,\n:math:`\\partial F_i^k / \\partial x_j^\\ell = 0`.\n\nazmul\n=====\nAn :ref:`optimized<optimize-name>` function will use zero\nfor values in *taylor_x* and *taylor_y* that are\nnot necessary in the current context.\nIf you divide by these values when computing\n:math:`( \\partial F_i^k / \\partial x_j^\\ell )` you could get an nan\nif the corresponding value in *partial_y* is zero.\nTo be careful, if you do divide by\n*taylor_x* or *taylor_y* , use :ref:`azmul-name`\nfor to avoid zero over zero calculations.\n\napartial_x\n**********\nThe specifications for *apartial_x* is the same as for\n*partial_x* (only the type of *apartial_x* is different).\n\nok\n**\nIf this calculation succeeded, *ok* is true.\nOtherwise it is false.\n\nExample\n*******\nThe following is an example ``reverse`` definition taken from\n:ref:`atomic_four_norm_sq.cpp-name` :\n{xrst_literal\n    example/atomic_four/norm_sq.cpp\n    // BEGIN REVERSE\n    // END REVERSE\n}\n\nExamples\n********\nThe file :ref:`atomic_four_norm_sq.cpp-name`\ncontains an example that defines this routine.\n\n{xrst_end atomic_four_reverse}\n-----------------------------------------------------------------------------\n*/\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n\n// BEGIN_PROTOTYPE_BASE\ntemplate <class Base>\nbool atomic_four<Base>::reverse(\n    size_t                      call_id     ,\n    const vector<bool>&         select_x    ,\n    size_t                      order_up    ,\n    const vector<Base>&         taylor_x    ,\n    const vector<Base>&         taylor_y    ,\n    vector<Base>&               partial_x   ,\n    const vector<Base>&         partial_y   )\n// END_PROTOTYPE_BASE\n{   return false; }\n\n// BEGIN_PROTOTYPE_AD_BASE\ntemplate <class Base>\nbool atomic_four<Base>::reverse(\n    size_t                          call_id      ,\n    const vector<bool>&             select_x     ,\n    size_t                          order_up     ,\n    const vector< AD<Base> >&       ataylor_x    ,\n    const vector< AD<Base> >&       ataylor_y    ,\n    vector< AD<Base> >&             apartial_x   ,\n    const vector< AD<Base> >&       apartial_y   )\n// END_PROTOTYPE_AD_BASE\n{   return false; }\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/atomic/one/atomic.hpp",
    "content": "# ifndef CPPAD_CORE_ATOMIC_ONE_ATOMIC_HPP\n# define CPPAD_CORE_ATOMIC_ONE_ATOMIC_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_one app}\n{xrst_spell\n    px\n    py\n    tvector\n    tx\n    vx\n    vy\n}\n\nDefining Atomic Functions: First Generation\n###########################################\n\nDeprecated 2013-05-27\n*********************\nUsing ``CPPAD_USER_ATOMIC`` has been deprecated.\nUse :ref:`atomic_three-name` instead.\n\nSyntax Function\n***************\n\n| ``CPPAD_USER_ATOMIC`` ( *afun* , *Tvector* , *Base* ,\n| |tab| *forward* , *reverse* , *for_jac_sparse* , *rev_jac_sparse* , *rev_hes_sparse*\n| )\n\nUse Function\n============\n\n    *afun* ( *id* , *ax* , *ay* )\n\nCallback Routines\n=================\n\n| *ok* = *forward* ( *id* , *k* , *n* , *m* , *vx* , *vy* , *tx* , *ty* )\n| *ok* = *reverse* ( *id* , *k* , *n* , *m* , *tx* , *ty* , *px* , *py* )\n| *ok* = *for_jac_sparse* ( *id* , *n* , *m* , *q* , *r* , *s* )\n| *ok* = *rev_jac_sparse* ( *id* , *n* , *m* , *q* , *r* , *s* )\n| *ok* = *rev_hes_sparse* ( *id* , *n* , *m* , *q* , *r* , *s* , *t* , *u* , *v* )\n\nFree Static Memory\n==================\n``user_atomic`` < *Base* >:: ``clear`` ()\n\nPurpose\n*******\nIn some cases, the user knows how to compute the derivative\nof a function\n\n.. math::\n\n    y = f(x) \\; {\\rm where} \\; f : \\B{R}^n \\rightarrow \\B{R}^m\n\nmore efficiently than by coding it using ``AD`` < *Base* >\n:ref:`atomic_base<glossary@Operation@Atomic>` operations\nand letting CppAD do the rest.\nIn this case, ``CPPAD_USER_ATOMIC`` can be used\nadd the user code for :math:`f(x)`, and its derivatives,\nto the set of ``AD`` < *Base* > atomic operations.\n\nAnother possible purpose is to reduce the size of the tape.\n\nPartial Implementation\n**********************\nThe routines\n:ref:`atomic_one@forward` ,\n:ref:`atomic_one@reverse` ,\n:ref:`atomic_one@for_jac_sparse` ,\n:ref:`atomic_one@rev_jac_sparse` , and\n:ref:`atomic_one@rev_hes_sparse` ,\nmust be defined by the user.\nThe *forward* the routine,\nfor the case *k*  = 0 , must be implemented.\nFunctions with the correct prototype,\nthat just return ``false`` ,\ncan be used for the other cases\n(unless they are required by your calculations).\nFor example, you need not implement\n*forward* for the case *k*  == 2 until you require\nforward mode calculation of second derivatives.\n\nCPPAD_USER_ATOMIC\n*****************\nThe macro\n\n| ``CPPAD_USER_ATOMIC`` ( *afun* , *Tvector* , *Base* ,\n| |tab| *forward* , *reverse* , *for_jac_sparse* , *rev_jac_sparse* , *rev_hes_sparse*\n| )\n\ndefines the ``AD`` < *Base* > routine *afun* .\nThis macro can be placed within a namespace\n(not the ``CppAD`` namespace)\nbut must be outside of any routine.\n\nTvector\n=======\nThe macro argument *Tvector* must be a\n:ref:`simple vector template class<SimpleVector-name>` .\nIt determines the type of vectors used as arguments to the routine\n*afun* .\n\nBase\n====\nThe macro argument *Base* specifies the\n:ref:`base type<base_require-name>`\ncorresponding to ``AD`` < *Base>* operation sequences.\nCalling the routine *afun* will add the operator defined\nby this macro to an ``AD`` < *Base>* operation sequence.\n\nok\n**\nFor all routines documented below,\nthe return value *ok* has prototype\n\n    ``bool`` *ok*\n\nIf it is ``true`` , the corresponding evaluation succeeded,\notherwise it failed.\n\nid\n**\nFor all routines documented below,\nthe argument *id* has prototype\n\n    ``size_t`` *id*\n\nIts value in all other calls is the same as in the corresponding\ncall to *afun* .\nIt can be used to store and retrieve extra information about\na specific call to *afun* .\n\nk\n*\nFor all routines documented below, the argument *k* has prototype\n\n    ``size_t`` *k*\n\nThe value *k* is the order of the Taylor coefficient that\nwe are evaluating (:ref:`atomic_one@forward` )\nor taking the derivative of (:ref:`atomic_one@reverse` ).\n\nn\n*\nFor all routines documented below,\nthe argument *n* has prototype\n\n    ``size_t`` *n*\n\nIt is the size of the vector *ax* in the corresponding call to\n*afun* ( *id* , *ax* , *ay* ) ; i.e.,\nthe dimension of the domain space for :math:`y = f(x)`.\n\nm\n*\nFor all routines documented below, the argument *m* has prototype\n\n    ``size_t`` *m*\n\nIt is the size of the vector *ay* in the corresponding call to\n*afun* ( *id* , *ax* , *ay* ) ; i.e.,\nthe dimension of the range space for :math:`y = f(x)`.\n\ntx\n**\nFor all routines documented below,\nthe argument *tx* has prototype\n\n    ``const CppAD::vector<`` *Base* >& *tx*\n\nand *tx* . ``size`` () >= ( *k* + 1) * *n* .\nFor :math:`j = 0 , \\ldots , n-1` and :math:`\\ell = 0 , \\ldots , k`,\nwe use the Taylor coefficient notation\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        x_j^\\ell & = & tx [ j * ( k + 1 ) + \\ell ]\n        \\\\\n        X_j (t) & = & x_j^0 + x_j^1 t^1 + \\cdots + x_j^k t^k\n    \\end{eqnarray}\n\nIf *tx* . ``size`` () > ( *k* + 1) * *n* ,\nthe other components of *tx* are not specified and should not be used.\nNote that superscripts represent an index for :math:`x_j^\\ell`\nand an exponent for :math:`t^\\ell`.\nAlso note that the Taylor coefficients for :math:`X(t)` correspond\nto the derivatives of :math:`X(t)` at :math:`t = 0` in the following way:\n\n.. math::\n\n    x_j^\\ell = \\frac{1}{ \\ell ! } X_j^{(\\ell)} (0)\n\nty\n**\nIn calls to :ref:`atomic_one@forward` ,\nthe argument *ty* has prototype\n\n    ``CppAD::vector<`` *Base* >& *ty*\n\nwhile in calls to :ref:`atomic_one@reverse` it has prototype\n\n    ``const CppAD::vector<`` *Base* >& *ty*\n\nFor all calls, *tx* . ``size`` () >= ( *k* + 1) * *m* .\nFor :math:`i = 0 , \\ldots , m-1` and :math:`\\ell = 0 , \\ldots , k`,\nwe use the Taylor coefficient notation\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        y_i^\\ell & = & ty [ i * ( k + 1 ) + \\ell ]\n        \\\\\n        Y_i (t)  & = & y_i^0 + y_i^1 t^1 + \\cdots + y_i^k t^k + o ( t^k )\n    \\end{eqnarray}\n\nwhere :math:`o( t^k ) / t^k \\rightarrow 0` as :math:`t \\rightarrow 0`.\nIf *ty* . ``size`` () > ( *k* + 1) * *m* ,\nthe other components of *ty* are not specified and should not be used.\nNote that superscripts represent an index for :math:`y_j^\\ell`\nand an exponent for :math:`t^\\ell`.\nAlso note that the Taylor coefficients for :math:`Y(t)` correspond\nto the derivatives of :math:`Y(t)` at :math:`t = 0` in the following way:\n\n.. math::\n\n    y_j^\\ell = \\frac{1}{ \\ell ! } Y_j^{(\\ell)} (0)\n\nforward\n=======\nIn the case of *forward* ,\nfor :math:`i = 0 , \\ldots , m-1`, :math:`ty[ i *( k  + 1) + k ]` is an output\nand all the other components of *ty* are inputs.\n\nreverse\n=======\nIn the case of *reverse* ,\nall the components of *ty* are inputs.\n\nafun\n****\nThe macro argument *afun* ,\nis the name of the AD function corresponding to this atomic\noperation (as it is used in the source code).\nCppAD uses the other functions,\nwhere the arguments are vectors with elements of type *Base* ,\nto implement the function\n\n    *afun* ( *id* , *ax* , *ay* )\n\nwhere the argument are vectors with elements of type ``AD`` < *Base* > .\n\nax\n==\nThe *afun* argument *ax* has prototype\n\n    ``const`` *Tvector* < ``AD`` < *Base* > >& *ax*\n\nIt is the argument vector :math:`x \\in \\B{R}^n`\nat which the ``AD`` < *Base* > version of\n:math:`y = f(x)` is to be evaluated.\nThe dimension of the domain space for :math:`y = f (x)`\nis specified by :ref:`atomic_one@n` = *ax* . ``size`` () ,\nwhich must be greater than zero.\n\nay\n==\nThe *afun* result *ay* has prototype\n\n    *Tvector* < ``AD`` < *Base* > >& *ay*\n\nThe input values of its elements\nare not specified (must not matter).\nUpon return, it is the ``AD`` < *Base* > version of the\nresult vector :math:`y = f(x)`.\nThe dimension of the range space for :math:`y = f (x)`\nis specified by :ref:`atomic_one@m` = *ay* . ``size`` () ,\nwhich must be greater than zero.\n\nParallel Mode\n=============\nThe first call to\n\n    *afun* ( *id* , *ax* , *ay* )\n\nmust not be in :ref:`parallel<ta_in_parallel-name>` mode.\nIn addition, the\n:ref:`atomic_one clear<atomic_one@clear>`\nroutine cannot be called while in parallel mode.\n\nforward\n*******\nThe macro argument *forward* is a\nuser defined function\n\n    *ok* = *forward* ( *id* , *k* , *n* , *m* , *vx* , *vy* , *tx* , *ty* )\n\nthat computes results during a :ref:`Forward-name` mode sweep.\nFor this call, we are given the Taylor coefficients in *tx*\nform order zero through *k* ,\nand the Taylor coefficients in  *ty* with order less than *k* .\nThe *forward* routine computes the\n*k* order Taylor coefficients for :math:`y` using the definition\n:math:`Y(t) = f[ X(t) ]`.\nFor example, for :math:`i = 0 , \\ldots , m-1`,\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    y_i^0 & = & Y(0)\n            = f_i ( x^0 )\n    \\\\\n    y_i^1 & = & Y^{(1)} ( 0 )\n            = f_i^{(1)} ( x^0 ) X^{(1)} ( 0 )\n            = f_i^{(1)} ( x^0 ) x^1\n    \\\\\n    y_i^2\n    & = & \\frac{1}{2 !} Y^{(2)} (0)\n    \\\\\n    & = & \\frac{1}{2} X^{(1)} (0)^\\R{T} f_i^{(2)} ( x^0 ) X^{(1)} ( 0 )\n      +   \\frac{1}{2} f_i^{(1)} ( x^0 ) X^{(2)} ( 0 )\n    \\\\\n    & = & \\frac{1}{2} (x^1)^\\R{T} f_i^{(2)} ( x^0 ) x^1\n      +    f_i^{(1)} ( x^0 ) x^2\n    \\end{eqnarray}\n\nThen, for :math:`i = 0 , \\ldots , m-1`, it sets\n\n.. math::\n\n    ty [ i * (k + 1) + k ] = y_i^k\n\nThe other components of *ty* must be left unchanged.\n\nUsage\n=====\nThis routine is used,\nwith *vx* . ``size`` () > 0 and *k*  == 0 ,\nby calls to *afun* .\nIt is used,\nwith *vx* . ``size`` () = 0 and\n*k* equal to the order of the derivative begin computed,\nby calls to :ref:`forward<forward_order-name>` .\n\nvx\n==\nThe *forward* argument *vx* has prototype\n\n    ``const CppAD::vector<bool>&`` *vx*\n\nThe case *vx* . ``size`` () > 0 occurs\nonce for each call to *afun* ,\nduring the call,\nand before any of the other callbacks corresponding to that call.\nHence such a call can be used to cache information attached to\nthe corresponding *id*\n(such as the elements of *vx* ).\nIf *vx* . ``size`` () > 0 then\n*k*  == 0 ,\n*vx* . ``size`` () >= *n* , and\nfor :math:`j = 0 , \\ldots , n-1`,\n*vx* [ *j* ] is true if and only if\n*ax* [ *j* ] is a :ref:`glossary@Variable` .\n\nIf *vx* . ``size`` () == 0 ,\nthen *vy* . ``size`` () == 0 and neither of these vectors\nshould be used.\n\nvy\n==\nThe *forward* argument *vy* has prototype\n\n    ``CppAD::vector<bool>&`` *vy*\n\nIf *vy* . ``size`` () == 0 , it should not be used.\nOtherwise,\n*k*  == 0 and *vy* . ``size`` () >= *m* .\nThe input values of the elements of *vy*\nare not specified (must not matter).\nUpon return, for :math:`j = 0 , \\ldots , m-1`,\n*vy* [ *i* ] is true if and only if\n*ay* [ *j* ] is a variable.\n(CppAD uses *vy* to reduce the necessary computations.)\n\nreverse\n*******\nThe macro argument *reverse*\nis a user defined function\n\n    *ok* = *reverse* ( *id* , *k* , *n* , *m* , *tx* , *ty* , *px* , *py* )\n\nthat computes results during a :ref:`Reverse-name` mode sweep.\nThe input value of the vectors *tx* and *ty*\ncontain Taylor coefficient, up to order *k* ,\nfor :math:`X(t)` and :math:`Y(t)` respectively.\nWe use the :math:`\\{ x_j^\\ell \\}` and :math:`\\{ y_i^\\ell \\}`\nto denote these Taylor coefficients where the implicit range indices are\n:math:`i = 0 , \\ldots , m-1`,\n:math:`j = 0 , \\ldots , n-1`,\n:math:`\\ell = 0 , \\ldots , k`.\nUsing the calculations done by :ref:`atomic_one@forward` ,\nthe Taylor coefficients :math:`\\{ y_i^\\ell \\}` are a function of the Taylor\ncoefficients for :math:`\\{ x_j^\\ell \\}`; i.e., given :math:`y = f(x)`\nwe define the function\n:math:`F : \\B{R}^{n \\times (k+1)} \\rightarrow \\B{R}^{m \\times (k+1)}` by\n\n.. math::\n\n    y_i^\\ell =  F_i^\\ell ( \\{ x_j^\\ell \\} )\n\nWe use :math:`G : \\B{R}^{m \\times (k+1)} \\rightarrow \\B{R}`\nto denote an arbitrary scalar valued function of the Taylor coefficients for\n:math:`Y(t)` and write  :math:`z = G( \\{ y_i^\\ell \\} )`.\nThe ``reverse`` routine\nis given the derivative of :math:`z` with respect to\n:math:`\\{ y_i^\\ell \\}` and computes its derivative with respect\nto :math:`\\{ x_j^\\ell \\}`.\n\nUsage\n=====\nThis routine is used,\nwith *k*  + 1 equal to the order of the derivative being calculated,\nby calls to :ref:`reverse<reverse_any-name>` .\n\npy\n==\nThe *reverse* argument *py* has prototype\n\n    ``const CppAD::vector<`` *Base* >& *py*\n\nand *py* . ``size`` () >= ( *k* + 1) * *m* .\nFor :math:`i = 0 , \\ldots , m-1` and :math:`\\ell = 0 , \\ldots , k`,\n\n.. math::\n\n    py[ i * (k + 1 ) + \\ell ] = \\partial G / \\partial y_i^\\ell\n\nIf *py* . ``size`` () > ( *k* + 1) * *m* ,\nthe other components of *py* are not specified and should not be used.\n\npx\n==\nWe define the function\n\n.. math::\n\n    H ( \\{ x_j^\\ell \\} ) = G[ F( \\{ x_j^\\ell \\} ) ]\n\nThe *reverse* argument *px* has prototype\n\n    ``CppAD::vector<`` *Base* >& *px*\n\nand *px* . ``size`` () >= ( *k* + 1) * *n* .\nThe input values of the elements of *px*\nare not specified (must not matter).\nUpon return,\nfor :math:`j = 0 , \\ldots , n-1` and :math:`p = 0 , \\ldots , k`,\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    px [ j * (k + 1) + p ] & = & \\partial H / \\partial x_j^p\n    \\\\\n    & = &\n    ( \\partial G / \\partial \\{ y_i^\\ell \\} )\n        ( \\partial \\{ y_i^\\ell \\} / \\partial x_j^p )\n    \\\\\n    & = &\n    \\sum_{i=0}^{m-1} \\sum_{\\ell=0}^k\n    ( \\partial G / \\partial y_i^\\ell ) ( \\partial y_i^\\ell / \\partial x_j^p )\n    \\\\\n    & = &\n    \\sum_{i=0}^{m-1} \\sum_{\\ell=p}^k\n    py[ i * (k + 1 ) + \\ell ] ( \\partial F_i^\\ell / \\partial x_j^p )\n    \\end{eqnarray}\n\nNote that we have used the fact that for :math:`\\ell < p`,\n:math:`\\partial F_i^\\ell / \\partial x_j^p = 0`.\nIf *px* . ``size`` () > ( *k* + 1) * *n* ,\nthe other components of *px* are not specified and should not be used.\n\nfor_jac_sparse\n**************\nThe macro argument *for_jac_sparse*\nis a user defined function\n\n    *ok* = *for_jac_sparse* ( *id* , *n* , *m* , *q* , *r* , *s* )\n\nthat is used to compute results during a forward Jacobian sparsity sweep.\nFor a fixed :math:`n \\times q` matrix :math:`R`,\nthe Jacobian of :math:`f( x + R * u)` with respect to :math:`u \\in \\B{R}^q` is\n\n.. math::\n\n    S(x) = f^{(1)} (x) * R\n\nGiven a :ref:`glossary@Sparsity Pattern` for :math:`R`,\n*for_jac_sparse* computes a sparsity pattern for :math:`S(x)`.\n\nUsage\n=====\nThis routine is used by calls to :ref:`ForSparseJac-name` .\n\nq\n=\nThe *for_jac_sparse* argument *q* has prototype\n\n    ``size_t`` *q*\n\nIt specifies the number of columns in\n:math:`R \\in \\B{R}^{n \\times q}` and the Jacobian\n:math:`S(x) \\in \\B{R}^{m \\times q}`.\n\nr\n=\nThe *for_jac_sparse* argument *r* has prototype\n\n    ``const CppAD::vector< std::set<size_t> >&`` *r*\n\nand *r* . ``size`` () >= *n* .\nFor :math:`j = 0 , \\ldots , n-1`,\nall the elements of *r* [ *j* ] are between\nzero and *q* ``-1`` inclusive.\nThis specifies a sparsity pattern for the matrix :math:`R`.\n\ns\n=\nThe *for_jac_sparse* return value *s* has prototype\n\n    ``CppAD::vector< std::set<size_t> >&`` *s*\n\nand *s* . ``size`` () >= *m* .\nThe input values of its sets\nare not specified (must not matter). Upon return\nfor :math:`i = 0 , \\ldots , m-1`,\nall the elements of *s* [ *i* ] are between\nzero and *q* ``-1`` inclusive.\nThis represents a sparsity pattern for the matrix :math:`S(x)`.\n\nrev_jac_sparse\n**************\nThe macro argument *rev_jac_sparse*\nis a user defined function\n\n    *ok* = *rev_jac_sparse* ( *id* , *n* , *m* , *q* , *r* , *s* )\n\nthat is used to compute results during a reverse Jacobian sparsity sweep.\nFor a fixed :math:`q \\times m` matrix :math:`S`,\nthe Jacobian of :math:`S * f( x )` with respect to :math:`x \\in \\B{R}^n` is\n\n.. math::\n\n    R(x) = S * f^{(1)} (x)\n\nGiven a :ref:`glossary@Sparsity Pattern` for :math:`S`,\n*rev_jac_sparse* computes a sparsity pattern for :math:`R(x)`.\n\nUsage\n=====\nThis routine is used by calls to :ref:`RevSparseJac-name`\nand to :ref:`optimize-name` .\n\nq\n=\nThe *rev_jac_sparse* argument *q* has prototype\n\n    ``size_t`` *q*\n\nIt specifies the number of rows in\n:math:`S \\in \\B{R}^{q \\times m}` and the Jacobian\n:math:`R(x) \\in \\B{R}^{q \\times n}`.\n\ns\n=\nThe *rev_jac_sparse* argument *s* has prototype\n\n    ``const CppAD::vector< std::set<size_t> >&`` *s*\n\nand *s* . ``size`` () >= *m* .\nFor :math:`i = 0 , \\ldots , m-1`,\nall the elements of *s* [ *i* ]\nare between zero and *q* ``-1`` inclusive.\nThis specifies a sparsity pattern for the matrix :math:`S^\\R{T}`.\n\nr\n=\nThe *rev_jac_sparse* return value *r* has prototype\n\n    ``CppAD::vector< std::set<size_t> >&`` *r*\n\nand *r* . ``size`` () >= *n* .\nThe input values of its sets\nare not specified (must not matter).\nUpon return for :math:`j = 0 , \\ldots , n-1`,\nall the elements of *r* [ *j* ]\nare between zero and *q* ``-1`` inclusive.\nThis represents a sparsity pattern for the matrix :math:`R(x)^\\R{T}`.\n\nrev_hes_sparse\n**************\nThe macro argument *rev_hes_sparse*\nis a user defined function\n\n    *ok* = *rev_hes_sparse* ( *id* , *n* , *m* , *q* , *r* , *s* , *t* , *u* , *v* )\n\nThere is an unspecified scalar valued function\n:math:`g : \\B{R}^m \\rightarrow \\B{R}`.\nGiven a sparsity pattern for :math:`R`\nand information about the function :math:`z = g(y)`,\nthis routine computes the sparsity pattern for\n\n.. math::\n\n    V(x) = (g \\circ f)^{(2)}( x ) R\n\nUsage\n=====\nThis routine is used by calls to :ref:`RevSparseHes-name` .\n\nq\n=\nThe *rev_hes_sparse* argument *q* has prototype\n\n    ``size_t`` *q*\n\nIt specifies the number of columns in the sparsity patterns.\n\nr\n=\nThe *rev_hes_sparse* argument *r* has prototype\n\n    ``const CppAD::vector< std::set<size_t> >&`` *r*\n\nand *r* . ``size`` () >= *n* .\nFor :math:`j = 0 , \\ldots , n-1`,\nall the elements of *r* [ *j* ] are between\nzero and *q* ``-1`` inclusive.\nThis specifies a sparsity pattern for the matrix :math:`R \\in \\B{R}^{n \\times q}`.\n\ns\n=\nThe *rev_hes_sparse* argument *s* has prototype\n\n    ``const CppAD::vector<bool>&`` *s*\n\nand *s* . ``size`` () >= *m* .\nThis specifies a sparsity pattern for the matrix\n:math:`S(x) = g^{(1)} (y) \\in \\B{R}^{1 \\times m}`.\n\nt\n=\nThe *rev_hes_sparse* argument *t* has prototype\n\n    ``CppAD::vector<bool>&`` *t*\n\nand *t* . ``size`` () >= *n* .\nThe input values of its elements\nare not specified (must not matter).\nUpon return it represents a sparsity pattern for the matrix\n:math:`T(x) \\in \\B{R}^{1 \\times n}` defined by\n\n.. math::\n\n    T(x)  =  (g \\circ f)^{(1)} (x) =  S(x) * f^{(1)} (x)\n\nu\n=\nThe *rev_hes_sparse* argument *u* has prototype\n\n    ``const CppAD::vector< std::set<size_t> >&`` *u*\n\nand *u* . ``size`` () >= *m* .\nFor :math:`i = 0 , \\ldots , m-1`,\nall the elements of *u* [ *i* ]\nare between zero and *q* ``-1`` inclusive.\nThis specifies a sparsity pattern\nfor the matrix :math:`U(x) \\in \\B{R}^{m \\times q}` defined by\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    U(x)\n    & = &\n    \\partial_u \\{ \\partial_y g[ y + f^{(1)} (x) R u ] \\}_{u=0}\n    \\\\\n    & = &\n    \\partial_u \\{ g^{(1)} [ y + f^{(1)} (x) R u ] \\}_{u=0}\n    \\\\\n    & = &\n    g^{(2)} (y) f^{(1)} (x) R\n    \\end{eqnarray}\n\nv\n=\nThe *rev_hes_sparse* argument *v* has prototype\n\n    ``CppAD::vector< std::set<size_t> >&`` *v*\n\nand *v* . ``size`` () >= *n* .\nThe input values of its elements\nare not specified (must not matter).\nUpon return, for :math:`j = 0, \\ldots , n-1`,\nall the elements of *v* [ *j* ]\nare between zero and *q* ``-1`` inclusive.\nThis represents a sparsity pattern for the matrix\n:math:`V(x) \\in \\B{R}^{n \\times q}` defined by\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    V(x)\n    & = &\n    \\partial_u [ \\partial_x (g \\circ f) ( x + R u )  ]_{u=0}\n    \\\\\n    & = &\n    \\partial_u [ (g \\circ f)^{(1)}( x + R u )  ]_{u=0}\n    \\\\\n    & = &\n    (g \\circ f)^{(2)}( x ) R\n    \\\\\n    & = &\n    f^{(1)} (x)^\\R{T} g^{(2)} ( y ) f^{(1)} (x)  R\n    +\n    \\sum_{i=1}^m [ g^{(1)} (y) ]_i \\; f_i^{(2)} (x) R\n    \\\\\n    & = &\n    f^{(1)} (x)^\\R{T} U(x)\n    +\n    \\sum_{i=1}^m S(x)_i \\; f_i^{(2)} (x) R\n    \\end{eqnarray}\n\nclear\n*****\nUser atomic functions hold onto static work space in order to\nincrease speed by avoiding system memory allocation calls.\nThe function call\n\n    ``user_atomic`` < *Base* >:: ``clear`` ()\n\nmakes to work space :ref:`available<ta_available-name>` to\nfor other uses by the same thread.\nThis should be called when you are done using the\natomic functions for a specific value of *Base* .\n\nRestriction\n===========\nThe atomic function ``clear`` routine cannot be called\nwhile in :ref:`parallel<ta_in_parallel-name>` execution mode.\n\n{xrst_end atomic_one}\n------------------------------------------------------------------------------\n*/\n# include <set>\n# include <cppad/core/cppad_assert.hpp>\n\n// needed before one can use CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL\n# include <cppad/utility/thread_alloc.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\n\\file atomic_one.hpp\nuser defined atomic operations.\n*/\n\n/*!\n\\def CPPAD_USER_ATOMIC(afun, Tvector,\n    forward, reverse, for_jac_sparse, rev_jac_sparse, rev_hes_sparse\n)\nDefines the function <tt>afun(id, ax, ay)</tt>\nwhere id is ax and ay are vectors with <tt>AD<Base></tt> elements.\n\n\\par Tvector\nthe Simple Vector template class for this function.\n\n\\par Base\nthe base type for the atomic operation.\n\n\\par afun\nname of the CppAD defined function that corresponding to this operation.\nNote that afun, preceded` by a pound sign,\nis a version of afun with quotes around it.\n\n\\par forward\nname of the user defined function that computes corresponding\nresults during forward mode.\n\n\\par reverse\nname of the user defined function that computes corresponding\nresults during reverse mode.\n\n\\par for_jac_sparse\nname of the user defined routine that computes corresponding\nresults during forward mode jacobian sparsity sweeps.\n\n\\par rev_jac_sparse\nname of the user defined routine that computes corresponding\nresults during reverse mode jacobian sparsity sweeps.\n\n\\par rev_hes_sparse\nname of the user defined routine that computes corresponding\nresults during reverse mode Hessian sparsity sweeps.\n\n\\par memory allocation\nNote that atomic_one is used as a static object, so its objects\ndo note get deallocated until the program terminates.\n*/\n# define CPPAD_USER_ATOMIC(                                           \\\n      afun            ,                                                \\\n      Tvector         ,                                                \\\n      Base            ,                                                \\\n    forward         ,                                                \\\n      reverse         ,                                                \\\n      for_jac_sparse  ,                                                \\\n      rev_jac_sparse  ,                                                \\\n      rev_hes_sparse                                                   \\\n)                                                                     \\\ninline void afun (                                                    \\\n      size_t                               id ,                        \\\n      const Tvector< CppAD::AD<Base> >&    ax ,                        \\\n      Tvector< CppAD::AD<Base> >&          ay                          \\\n)                                                                     \\\n{   CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL;                            \\\n    static CppAD::atomic_one<Base> fun(                              \\\n             #afun          ,                                            \\\n             forward        ,                                            \\\n             reverse        ,                                            \\\n             for_jac_sparse ,                                            \\\n             rev_jac_sparse ,                                            \\\n             rev_hes_sparse                                              \\\n      );                                                               \\\n      fun(id, ax, ay);                                                 \\\n}\n\n/// link so that user_atomic<Base>::clear() still works\ntemplate <class Base> class user_atomic : public atomic_base<Base> {\n};\n\n/*!\nClass that actually implements the <tt>afun(id, ax, ay)</tt> calls.\n\nA new atomic_one object is generated each time the user invokes\nthe CPPAD_USER_ATOMIC macro; see static object in that macro.\n*/\ntemplate <class Base>\nclass atomic_one : public atomic_base<Base> {\npublic:\n    /// disable atomic_one<Base>::clear(void)\n    static void clear(void)\n    {   CPPAD_ASSERT_KNOWN(\n            false,\n            \"Deprecated API uses user_atomic<Base>::clear()\"\n        );\n    }\n    /// type for user routine that computes forward mode results\n    typedef bool (*F) (\n        size_t                  id ,\n        size_t                   k ,\n        size_t                   n ,\n        size_t                   m ,\n        const vector<bool>&     vx ,\n        vector<bool>&           vy ,\n        const vector<Base>&     tx ,\n        vector<Base>&           ty\n    );\n    /// type for user routine that computes reverse mode results\n    typedef bool (*R) (\n        size_t                  id ,\n        size_t                   k ,\n        size_t                   n ,\n        size_t                   m ,\n        const vector<Base>&     tx ,\n        const vector<Base>&     ty ,\n        vector<Base>&           px ,\n        const vector<Base>&     py\n    );\n    /// type for user routine that computes forward mode Jacobian sparsity\n    typedef bool (*FJS) (\n        size_t                           id ,\n        size_t                            n ,\n        size_t                            m ,\n        size_t                            q ,\n        const vector< std::set<size_t> >& r ,\n        vector< std::set<size_t>  >&      s\n    );\n    /// type for user routine that computes reverse mode Jacobian sparsity\n    typedef bool (*RJS) (\n        size_t                           id ,\n        size_t                            n ,\n        size_t                            m ,\n        size_t                            q ,\n        vector< std::set<size_t> >&       r ,\n        const vector< std::set<size_t> >& s\n    );\n    /// type for user routine that computes reverse mode Hessian sparsity\n    typedef bool (*RHS) (\n        size_t                           id ,\n        size_t                            n ,\n        size_t                            m ,\n        size_t                            q ,\n        const vector< std::set<size_t> >& r ,\n        const vector<bool>&               s ,\n        vector<bool>&                     t ,\n        const vector< std::set<size_t> >& u ,\n        vector< std::set<size_t> >&       v\n    );\nprivate:\n    /// id value corresponding to next virtual callback\n    size_t                  id_;\n    /// user's implementation of forward mode\n    const F                  f_;\n    /// user's implementation of reverse mode\n    const R                  r_;\n    /// user's implementation of forward jacobian sparsity calculations\n    const FJS              fjs_;\n    /// user's implementation of reverse jacobian sparsity calculations\n    const RJS              rjs_;\n    /// user's implementation of reverse Hessian sparsity calculations\n    const RHS              rhs_;\n\npublic:\n    /*!\n    Constructor called for each invocation of CPPAD_USER_ATOMIC.\n\n    Put this object in the list of all objects for this class and set\n    the constant private data f_, r_, fjs_, rjs_, rhs_.\n\n    \\param afun\n    is the user's name for the AD version of this atomic operation.\n\n    \\param f\n    user routine that does forward mode calculations for this operation.\n\n    \\param r\n    user routine that does reverse mode calculations for this operation.\n\n    \\param fjs\n    user routine that does forward Jacobian sparsity calculations.\n\n    \\param rjs\n    user routine that does reverse Jacobian sparsity calculations.\n\n    \\param rhs\n    user routine that does reverse Hessian sparsity calculations.\n\n    \\par\n    This constructor can not be used in parallel mode because\n    atomic_base has this restriction.\n    */\n    atomic_one(const char* afun, F f, R r, FJS fjs, RJS rjs, RHS rhs) :\n    atomic_base<Base>(afun) // name = afun\n    , f_(f)\n    , r_(r)\n    , fjs_(fjs)\n    , rjs_(rjs)\n    , rhs_(rhs)\n    {   this->option( atomic_base<Base>::set_sparsity_enum );\n    }\n    /*!\n    Implement the user call to <tt>afun(id, ax, ay)</tt>.\n\n    \\tparam ADVector\n    A simple vector class with elements of type <code>AD<Base></code>.\n\n    \\param id\n    extra information vector that is just passed through by CppAD,\n    and possibly used by user's routines.\n\n    \\param ax\n    is the argument vector for this call,\n    <tt>ax.size()</tt> determines the number of arguments.\n\n    \\param ay\n    is the result vector for this call,\n    <tt>ay.size()</tt> determines the number of results.\n    */\n    template <class ADVector>\n    void operator()(size_t id, const ADVector& ax, ADVector& ay)\n    {   // call atomic_base function object\n        this->atomic_base<Base>::operator()(ax, ay, id);\n        return;\n    }\n    /*!\n    Store id for next virtual function callback\n\n    \\param id\n    id value corresponding to next virtual callback\n    */\n    virtual void set_old(size_t id)\n    {   id_ = id; }\n    /*!\n    Link from atomic_one to forward mode\n\n    \\copydetails atomic_base::forward\n    */\n    virtual bool forward(\n        size_t                    p ,\n        size_t                    q ,\n        const vector<bool>&      vx ,\n                  vector<bool>&      vy ,\n        const vector<Base>&      tx ,\n                  vector<Base>&      ty )\n    {   CPPAD_ASSERT_UNKNOWN( tx.size() % (q+1) == 0 );\n        CPPAD_ASSERT_UNKNOWN( ty.size() % (q+1) == 0 );\n        size_t n = tx.size() / (q+1);\n        size_t m = ty.size() / (q+1);\n        size_t i, j, k, ell;\n\n        vector<Base> x(n * (q+1));\n        vector<Base> y(m * (q+1));\n        vector<bool> empty;\n\n        // atomic_one interface can only handle one order at a time\n        // so must just through hoops to get multiple orders at one time.\n        bool ok = true;\n        for(k = p; k <= q; k++)\n        {   for(j = 0; j < n; j++)\n                for(ell = 0; ell <= k; ell++)\n                    x[ j * (k+1) + ell ] = tx[ j * (q+1) + ell ];\n            for(i = 0; i < m; i++)\n                for(ell = 0; ell < k; ell++)\n                    y[ i * (k+1) + ell ] = ty[ i * (q+1) + ell ];\n            if( k == 0 )\n                ok &= f_(id_, k, n, m, vx, vy, x, y);\n            else\n                ok &= f_(id_, k, n, m, empty, empty, x, y);\n            for(i = 0; i < m; i++)\n                ty[ i * (q+1) + k ] = y[ i * (k+1) + k];\n        }\n        return ok;\n    }\n    /*!\n    Link from atomic_one to reverse mode\n\n    \\copydetails atomic_base::reverse\n    */\n    virtual bool reverse(\n        size_t                   q ,\n        const vector<Base>&     tx ,\n        const vector<Base>&     ty ,\n                  vector<Base>&     px ,\n        const vector<Base>&     py )\n    {   CPPAD_ASSERT_UNKNOWN( tx.size() % (q+1) == 0 );\n        CPPAD_ASSERT_UNKNOWN( ty.size() % (q+1) == 0 );\n        size_t n = tx.size() / (q+1);\n        size_t m = ty.size() / (q+1);\n        bool   ok = r_(id_, q, n, m, tx, ty, px, py);\n        return ok;\n    }\n    /*!\n    Link from forward Jacobian sparsity sweep to atomic_one\n\n    \\copydetails atomic_base::for_sparse_jac\n    */\n    virtual bool for_sparse_jac(\n        size_t                                q ,\n        const vector< std::set<size_t> >&     r ,\n                  vector< std::set<size_t> >&     s ,\n        const vector<Base>&                   x )\n    {   size_t n = r.size();\n        size_t m = s.size();\n        bool ok  = fjs_(id_, n, m, q, r, s);\n        return ok;\n    }\n\n    /*!\n    Link from reverse Jacobian sparsity sweep to atomic_one.\n\n    \\copydetails atomic_base::rev_sparse_jac\n    */\n    virtual bool rev_sparse_jac(\n        size_t                               q  ,\n        const vector< std::set<size_t> >&    rt ,\n                  vector< std::set<size_t> >&    st ,\n        const vector<Base>&                   x )\n    {   size_t n = st.size();\n        size_t m = rt.size();\n        bool ok  = rjs_(id_, n, m, q, st, rt);\n        return ok;\n    }\n    /*!\n    Link from reverse Hessian sparsity sweep to atomic_one\n\n    \\copydetails atomic_base::rev_sparse_hes\n    */\n    virtual bool rev_sparse_hes(\n        const vector<bool>&                   vx,\n        const vector<bool>&                   s ,\n                  vector<bool>&                   t ,\n        size_t                                q ,\n        const vector< std::set<size_t> >&     r ,\n        const vector< std::set<size_t> >&     u ,\n                  vector< std::set<size_t> >&     v ,\n        const vector<Base>&                   x )\n    {   size_t m = u.size();\n        size_t n = v.size();\n        CPPAD_ASSERT_UNKNOWN( r.size() == n );\n        CPPAD_ASSERT_UNKNOWN( s.size() == m );\n        CPPAD_ASSERT_UNKNOWN( t.size() == n );\n        //\n        // old interface used id instead of vx\n        bool ok = rhs_(id_, n, m, q, r, s, t, u, v);\n        return ok;\n    }\n};\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/atomic/three/afun.hpp",
    "content": "# ifndef CPPAD_CORE_ATOMIC_THREE_AFUN_HPP\n# define CPPAD_CORE_ATOMIC_THREE_AFUN_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_three_afun}\n\nUsing AD Version of an Atomic Function\n######################################\n\nSyntax\n******\n| *afun* ( *ax* , *ay* )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_PROTOTYPE\n    // END_PROTOTYPE\n}\n\nPurpose\n*******\nGiven *ax* , this call computes the corresponding value of *ay* .\nIf ``AD`` < *Base* > operations are being recorded,\nit enters the computation as an atomic operation in the recording;\nsee :ref:`Independent@Start Recording` .\n\nBase\n****\nThis is the *Base* type of the elements of *ax* and *ay*\nin the call to the *afun* atomic operation.\nTo be specific, the elements of *ax* and *ay* have type\n``AD`` < ``Base`` > .\n\nADVector\n********\nThe type *ADVector* must be a\n:ref:`simple vector class<SimpleVector-name>` with elements of type\n``AD`` < *Base* > .\n\nafun\n****\nis a :ref:`atomic_three_ctor@atomic_user` object\nand this *afun* function call is implemented by the\n:ref:`atomic_three_ctor@atomic_three` class.\n\nax\n**\nThis argument has prototype\n\n    ``const`` *ADVector* & *ax*\n\nand size must be equal to *n* .\nIt specifies vector :math:`x \\in \\B{R}^n`\nat which an ``AD`` < *Base* > version of\n:math:`y = g(x)` is to be evaluated; see\n:ref:`atomic_three_ctor@atomic_three@Base` .\n\nay\n**\nThis argument has prototype\n\n    *ADVector* & *ay*\n\nand size must be equal to *m* .\nThe input values of its elements\nare not specified (must not matter).\nUpon return, it is an ``AD`` < *Base* > version of\n:math:`y = g(x)`.\n\n{xrst_end atomic_three_afun}\n-----------------------------------------------------------------------------\n*/\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\n\\file atomic/three_afun.hpp\nImplement user call to an atomic_three function.\n*/\n\n/*!\nImplement the user call to afun(ax, ay)\n\n\\tparam ADVector\nA simple vector class with elements of type AD<Base>.\n\n\\param ax\nis the argument vector for this call,\nax.size() determines the number of arguments.\n\n\\param ay\nis the result vector for this call,\nay.size() determines the number of results.\n*/\n// BEGIN_PROTOTYPE\ntemplate <class Base>\ntemplate <class ADVector>\nvoid atomic_three<Base>::operator()(\n    const ADVector&  ax     ,\n    ADVector&        ay     )\n// END_PROTOTYPE\n{\n\n    size_t n = ax.size();\n    size_t m = ay.size();\n# ifndef NDEBUG\n    bool ok = true;\n    std::string msg = \"atomic_three: \" + atomic_name() + \".eval: \";\n    if( (n == 0) || (m == 0) )\n    {   msg += \"ax.size() or ay.size() is zero\";\n        CPPAD_ASSERT_KNOWN(false, msg.c_str() );\n    }\n# endif\n    size_t thread = thread_alloc::thread_num();\n    allocate_work(thread);\n    vector<Base>& taylor_x        = work_[thread]->taylor_x;\n    vector<Base>& taylor_y        = work_[thread]->taylor_y;\n    vector<ad_type_enum>& type_x  = work_[thread]->type_x;\n    vector<ad_type_enum>& type_y  = work_[thread]->type_y;\n    //\n    type_x.resize(n);\n    taylor_x.resize(n);\n    //\n    type_y.resize(m);\n    taylor_y.resize(m);\n    //\n    // Determine tape corresponding to variables in ax\n    tape_id_t            tape_id  = 0;\n    local::ADTape<Base>* tape     = nullptr;\n    for(size_t j = 0; j < n; j++)\n    {   taylor_x[j]  = ax[j].value_;\n        if( Constant( ax[j] ) )\n            type_x[j] = constant_enum;\n        else\n        {   type_x[j] = ax[j].ad_type_;\n            if( tape_id == 0 )\n            {   tape    = ax[j].tape_this();\n                tape_id = ax[j].tape_id_;\n                CPPAD_ASSERT_UNKNOWN( tape != nullptr );\n            }\n# ifndef NDEBUG\n            if( Dynamic( ax[j] ) )\n            {     CPPAD_ASSERT_UNKNOWN( type_x[j] == dynamic_enum );\n            }\n            else\n            {   CPPAD_ASSERT_UNKNOWN( Variable( ax[j] ) );\n                CPPAD_ASSERT_UNKNOWN( type_x[j] == variable_enum );\n            }\n            if( tape_id != ax[j].tape_id_ )\n            {   msg += atomic_name() +\n                \": ax contains non-constant values from different threads.\";\n                CPPAD_ASSERT_KNOWN(false, msg.c_str());\n            }\n# endif\n        }\n    }\n    // Use zero order forward mode to compute all the components of y\n    size_t need_y    = size_t(variable_enum) + 1;\n    size_t order_low = 0;\n    size_t order_up  = 0;\n    CPPAD_ASSERT_UNKNOWN( need_y > size_t(variable_enum) );\n# ifdef NDEBUG\n    forward(taylor_x, type_x, need_y, order_low, order_up, taylor_x, taylor_y);\n    for(size_t j = 0; j < n; ++j)\n        if( type_x[j] == variable_enum )\n            taylor_x[j] = CppAD::numeric_limits<Base>::quiet_NaN();\n    for_type(taylor_x, type_x, type_y);\n# else\n    ok &= forward(\n        taylor_x, type_x, need_y, order_low, order_up, taylor_x, taylor_y\n    );\n    for(size_t j = 0; j < n; ++j)\n        if( type_x[j] == variable_enum )\n            taylor_x[j] = CppAD::numeric_limits<Base>::quiet_NaN();\n    ok &= for_type(taylor_x, type_x, type_y);\n    if( ! ok )\n    {   msg += atomic_name() + \": ok is false for \"\n            \"type or zero order forward mode calculation.\";\n        CPPAD_ASSERT_KNOWN(false, msg.c_str());\n    }\n# endif\n    bool record_dynamic = false;\n    bool record_variable = false;\n    //\n    // set ay to be vector of constant parameters with correct value\n    for(size_t i = 0; i < m; i++)\n    {   // pass back values\n        ay[i].value_ = taylor_y[i];\n\n        // initialize entire vector as constants\n        ay[i].tape_id_ = 0;\n        ay[i].taddr_   = 0;\n\n        // we need to record this operation if\n        // any of the elements of ay are dynamics or variables,\n        record_dynamic  |= type_y[i] == dynamic_enum;\n        record_variable |= type_y[i] == variable_enum;\n    }\n# ifndef NDEBUG\n    if( (record_dynamic || record_variable) && tape == nullptr )\n    {   msg +=\n        \"all elements of x are constants but y contains a non-constant\";\n        CPPAD_ASSERT_KNOWN(false, msg.c_str() );\n    }\n# endif\n    if( record_dynamic)\n    {   size_t call_id = 0;\n        tape->Rec_.put_dyn_atomic(\n            tape_id, index_, call_id, type_x, type_y, ax, ay\n        );\n    }\n    // case where result contains a variable\n    if( record_variable )\n    {   size_t call_id = 0; // atomic_three does not user call_id\n        tape->Rec_.put_var_atomic(\n            tape_id, index_, call_id, type_x, type_y, ax, ay);\n    }\n# ifndef NDEBUG\n    for(size_t i = 0; i < m; ++i) switch( type_y[i] )\n    {   //\n        case constant_enum:\n        CPPAD_ASSERT_UNKNOWN( Constant( ay[i] ) );\n        break;\n        //\n        case dynamic_enum:\n        CPPAD_ASSERT_UNKNOWN( Dynamic( ay[i] ) );\n        break;\n        //\n        case variable_enum:\n        CPPAD_ASSERT_UNKNOWN( Variable( ay[i] ) );\n        break;\n        //\n        default:\n        CPPAD_ASSERT_KNOWN( false,\n            \"atomic_three: for_type: type_y[i]: is not a valid type\"\n        );\n        break;\n    }\n# endif\n    return;\n}\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/atomic/three/atomic.hpp",
    "content": "# ifndef CPPAD_CORE_ATOMIC_THREE_ATOMIC_HPP\n# define CPPAD_CORE_ATOMIC_THREE_ATOMIC_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_three_define}\n{xrst_spell\n    ctor\n}\n\nDefining Atomic Functions: Third Generation\n###########################################\n\nSyntax\n******\n\nDefine Class\n============\n\n| ``class`` *atomic_user* : ``public CppAD::atomic_three<`` *Base* > {\n| |tab| ...\n| };\n\nConstruct Atomic Function\n=========================\n*atomic_user* *afun* ( *ctor_arg_list* )\n\nUse Atomic Function\n===================\n*afun* ( *ax* , *ay* )\n\nClass Member Callbacks\n======================\n\n| *ok* = *afun* . ``for_type`` (\n| |tab| *parameter_x* , *type_x* , *type_y*\n| )\n| *ok* = *afun* . ``forward`` (\n| |tab| *parameter_x* , *type_x* ,\n| |tab| *need_y* , *order_low* , *order_up* , *taylor_x* , *taylor_y*\n| )\n| *ok* = *afun* . ``reverse`` (\n| |tab| *parameter_x* , *type_x* ,\n| |tab| *order_up* , *taylor_x* , *taylor_y* , *partial_x* , *partial_y*\n| )\n| *ok* = *afun* . ``jac_sparsity`` (\n| |tab| *parameter_x* , *type_x* , *dependency* , *select_x* *select_y* , *pattern_out*\n| )\n| *ok* = *afun* . ``hes_sparsity`` (\n| |tab| *parameter_x* , *type_x* , *select_x* *select_y* , *pattern_out*\n| )\n| *ok* = *afun* . ``rev_depend`` (\n| |tab| *parameter_x* , *type_x* , *depend_x* , *depend_y*\n| )\n\nSee Also\n********\n:ref:`chkpoint_two-name` , :ref:`atomic_two-name`\n\nPurpose\n*******\n\nSpeed\n=====\nIn some cases, it is possible to compute derivatives of a function\n\n.. math::\n\n    y = g(x) \\; {\\rm where} \\; g : \\B{R}^n \\rightarrow \\B{R}^m\n\nmore efficiently than by coding it using ``AD`` < *Base* >\n:ref:`glossary@Operation@Atomic` operations\nand letting CppAD do the rest.\nThe class ``atomic_three`` < ``Base`` > is used to\ncreate a new atomic operation corresponding to a function :math:`g(x)`\nwhere the user specifies how to compute the derivatives\nand sparsity patterns for :math:`g(x)`.\n\nReduce Memory\n=============\nIf the function :math:`g(x)` is used many times during the recording\nof an :ref:`ADFun-name` object,\nusing an atomic version of :math:`g(x)` removes the need for repeated\ncopies of the corresponding ``AD`` < *Base* > operations and variables\nin the recording.\n\nad_type\n*******\nThe type ``CppAD::ad_type_enum``\nis used to specify if an AD object is a\n:ref:`constant parameter<glossary@Parameter@Constant>`\n:ref:`dynamic parameter<glossary@Parameter@Dynamic>`\nor :ref:`glossary@Variable` .\nIt has the following possible values:\n\n.. csv-table::\n    :widths: auto\n\n    *ad_type_enum*,Meaning\n    ``constant_enum``,constant parameter\n    ``dynamic_enum``,dynamic parameter\n    ``variable_enum``,variable\n\nIn addition,\n``constant_enum < dynamic_enum < variable_enum`` .\n\nVirtual Functions\n*****************\nThe\n:ref:`callback functions<atomic_three_define@Syntax@Class Member Callbacks>`\nare implemented by defining the virtual functions in the\n*atomic_user* class.\nThese functions compute derivatives,\nsparsity patterns, and dependency relations.\nEach virtual function has a default implementation\nthat returns *ok* == ``false`` .\nThe :ref:`for_type<atomic_three_for_type-name>`\nand :ref:`forward<atomic_three_forward-name>` function\n(for the case *order_up*  == 0 ) must be implemented.\nOtherwise, only those functions and orders\nrequired by the your calculations need to be implemented.\nFor example,\n*forward* for the case *order_up*  == 2 can just return\n*ok* == ``false`` unless you require\nforward mode calculation of second derivatives.\n\nBase\n****\nThis is the base type of the elements of\n:ref:`atomic_three_afun@ax` and :ref:`atomic_three_afun@ay`\nin the corresponding *afun* ( *ax* , *ay* ) call; i.e.,\nthe elements of *ax* and *ay* have type\n``AD`` < *Base* > .\n\nparameter_x\n***********\nAll the virtual functions include this argument which has prototype\n\n    ``const CppAD::vector<`` *Base* > *parameter_x*\n\nIts size is equal to *n* = *ax* . ``size`` ()\nin corresponding *afun* ( *ax* , *ay* ) call.\n\nConstant\n========\nFor *j* =0,..., *n* ``-1`` ,\nif *ax* [ *j* ] is a :ref:`con_dyn_var@Constant` parameter,\n\n    *parameter_x* [ *j* ] == *ax* [ *j* ]\n\nDynamic\n=======\nIf *ax* [ *j* ] is a :ref:`con_dyn_var@Dynamic` parameter,\n*parameter_x* [ *j* ] value of *ax* [ *j* ] corresponding to the\nprevious call to :ref:`new_dynamic-name` for the corresponding function object.\n\nVariable\n========\nIf *ax* [ *j* ] is a variable,\nthe value of *parameter_x* [ *j* ] is not specified.\nSee the\n:ref:`atomic_three_mat_mul.hpp<atomic_three_mat_mul.hpp@Purpose@parameter_x>`\nfor an example using *parameter_x* .\n\ntype_x\n******\nAll the virtual functions include this argument.\nIts size is equal to *n* = *ax* . ``size`` ()\nin corresponding *afun* ( *ax* , *ay* ) call.\nFor *j* =0,..., *n* ``-1`` ,\nif *ax* [ *j* ] is a constant parameter,\n\n    *type_x* [ *j* ] == ``CppAD::constant_enum``\n\nif *ax* [ *j* ] is a dynamic parameter,\n\n    *type_x* [ *j* ] == ``CppAD::dynamic_enum``\n\nif *ax* [ *j* ] is a variable,\n\n    *type_x* [ *j* ] == ``CppAD::variable_enum``\n\nSee the\n:ref:`atomic_three_mat_mul.hpp<atomic_three_mat_mul.hpp@Purpose@type_x>`\nfor an example using *type_x* .\n\nContents\n********\n{xrst_toc_table\n    include/cppad/core/atomic/three/ctor.hpp\n    include/cppad/core/atomic/three/afun.hpp\n    include/cppad/core/atomic/three/for_type.hpp\n    include/cppad/core/atomic/three/forward.hpp\n    include/cppad/core/atomic/three/reverse.hpp\n    include/cppad/core/atomic/three/jac_sparsity.hpp\n    include/cppad/core/atomic/three/hes_sparsity.hpp\n    include/cppad/core/atomic/three/rev_depend.hpp\n}\n\n{xrst_end atomic_three_define}\n-------------------------------------------------------------------------------\n*/\n\n# include <set>\n# include <cppad/core/cppad_assert.hpp>\n# include <cppad/local/atomic_index.hpp>\n\n// needed before one can use in_parallel\n# include <cppad/utility/thread_alloc.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\n\\file atomic_three.hpp\nBase class for atomic function operations.\n*/\n\ntemplate <class Base>\nclass atomic_three {\n// ===================================================================\nprivate:\n    // ------------------------------------------------------\n    // constants\n    //\n    /// index of this object in local::atomic_index\n    /// (set by constructor and not changed; i.e., effectively const)\n    size_t index_;\n    //\n    // -----------------------------------------------------\n    //\n    /// temporary work space used by member functions, declared here to avoid\n    // memory allocation/deallocation for each usage\n    struct work_struct {\n        vector<ad_type_enum>        type_x;\n        vector<ad_type_enum>        type_y;\n        //\n        vector<Base>                taylor_x;\n        vector<Base>                taylor_y;\n        //\n        vector< AD<Base> >          ataylor_x;\n        vector< AD<Base> >          ataylor_y;\n        //\n        sparse_rc< vector<size_t> > pattern;\n    };\n    // Use pointers, to avoid false sharing between threads.\n    // Not using: vector<work_struct*> work_;\n    // so that deprecated atomic examples do not result in a memory leak.\n    work_struct* work_[CPPAD_MAX_NUM_THREADS];\n    // -----------------------------------------------------\npublic:\n    //\n    // atomic_index\n    size_t atomic_index(void) const\n    { return index_; }\n    // =====================================================================\n    // In User API\n    // =====================================================================\n    //\n    // ---------------------------------------------------------------------\n    // ctor: doxygen in atomic/three_ctor.hpp\n    atomic_three(void);\n    atomic_three(const std::string& name);\n\n    // ------------------------------------------------------------------------\n    // operator(): see doxygen in atomic_three/afun.hpp\n    template <class ADVector>\n    void operator()(\n        const ADVector&  ax     ,\n                  ADVector&  ay\n    );\n    // ------------------------------------------------------------------------\n    // type: doxygen in atomic/three_for_type.hpp\n    virtual bool for_type(\n        const vector<Base>&          parameter_x ,\n        const vector<ad_type_enum>&  type_x      ,\n        vector<ad_type_enum>&        type_y\n    );\n    // ------------------------------------------------------------------------\n    // type: doxygen in atomic/three_rev_depend.hpp\n    virtual bool rev_depend(\n        const vector<Base>&          parameter_x ,\n        const vector<ad_type_enum>&  type_x      ,\n        vector<bool>&                depend_x    ,\n        const vector<bool>&          depend_y\n    );\n    // ------------------------------------------------------------------------\n    // forward: see docygen in atomic/three_forward.hpp\n    virtual bool forward(\n        const vector<Base>&          parameter_x ,\n        const vector<ad_type_enum>&  type_x      ,\n        size_t                       need_y      ,\n        size_t                       order_low   ,\n        size_t                       order_up    ,\n        const vector<Base>&          taylor_x    ,\n        vector<Base>&                taylor_y\n    );\n    virtual bool forward(\n        const vector< AD<Base> >&    aparameter_x ,\n        const vector<ad_type_enum>&  type_x       ,\n        size_t                       need_y       ,\n        size_t                       order_low    ,\n        size_t                       order_up     ,\n        const vector< AD<Base> >&    ataylor_x    ,\n        vector< AD<Base> >&          ataylor_y\n    );\n    // ------------------------------------------------------------------------\n    // reverse: see docygen in atomic/three_reverse.hpp\n    virtual bool reverse(\n        const vector<Base>&          parameter_x ,\n        const vector<ad_type_enum>&  type_x      ,\n        size_t                       order_up    ,\n        const vector<Base>&          taylor_x    ,\n        const vector<Base>&          taylor_y    ,\n        vector<Base>&                partial_x   ,\n        const vector<Base>&          partial_y\n    );\n    virtual bool reverse(\n        const vector< AD<Base> >&    aparameter_x ,\n        const vector<ad_type_enum>&  type_x       ,\n        size_t                       order_up    ,\n        const vector< AD<Base> >&    ataylor_x   ,\n        const vector< AD<Base> >&    ataylor_y   ,\n        vector< AD<Base> >&          apartial_x  ,\n        const vector< AD<Base> >&    apartial_y\n    );\n    // ------------------------------------------------------------\n    // jac_sparsity: see doxygen in atomic/three_jac_sparsity.hpp\n    virtual bool jac_sparsity(\n        const vector<Base>&          parameter_x ,\n        const vector<ad_type_enum>&  type_x      ,\n        bool                         dependency  ,\n        const vector<bool>&          select_x    ,\n        const vector<bool>&          select_y    ,\n        sparse_rc< vector<size_t> >& pattern_out\n    );\n    template <class InternalSparsity>\n    bool for_jac_sparsity(\n        bool                             dependency   ,\n        const vector<Base>&              parameter_x  ,\n        const vector<ad_type_enum>&      type_x       ,\n        const vector<size_t>&            x_index      ,\n        const vector<size_t>&            y_index      ,\n        InternalSparsity&                var_sparsity\n    );\n    template <class InternalSparsity>\n    bool rev_jac_sparsity(\n        bool                             dependency   ,\n        const vector<Base>&              parameter_x  ,\n        const vector<ad_type_enum>&      type_x       ,\n        const vector<size_t>&            x_index      ,\n        const vector<size_t>&            y_index      ,\n        InternalSparsity&                var_sparsity\n    );\n    // ------------------------------------------------------------\n    // hes_sparsity: see doxygen in atomic/three_jac_sparsity.hpp\n    virtual bool hes_sparsity(\n        const vector<Base>&                     parameter_x  ,\n        const vector<ad_type_enum>&             type_x       ,\n        const vector<bool>&                     select_x     ,\n        const vector<bool>&                     select_y     ,\n        sparse_rc< vector<size_t> >&            pattern_out\n    );\n    template <class InternalSparsity>\n    bool for_hes_sparsity(\n        const vector<Base>&              parameter_x      ,\n        const vector<ad_type_enum>&      type_x           ,\n        const vector<size_t>&            x_index          ,\n        const vector<size_t>&            y_index          ,\n        size_t                           np1              ,\n        size_t                           numvar           ,\n        const InternalSparsity&          rev_jac_sparsity ,\n        InternalSparsity&                for_sparsity\n    );\n    template <class InternalSparsity>\n    bool rev_hes_sparsity(\n        const vector<Base>&              parameter_x      ,\n        const vector<ad_type_enum>&      type_x           ,\n        const vector<size_t>&            x_index          ,\n        const vector<size_t>&            y_index          ,\n        const InternalSparsity&          for_jac_pattern  ,\n        bool*                            rev_jac_flag     ,\n        InternalSparsity&                hes_sparsity\n    );\n\n    // =====================================================================\n    // Not in User API\n    // =====================================================================\n\n    /// Name corresponding to a atomic_three object\n    const std::string atomic_name(void) const\n    {   bool        set_null = false;\n        size_t      type  = 0;          // set to avoid warning\n        std::string name;\n        void*       v_ptr = nullptr; // set to avoid warning\n        local::atomic_index<Base>(set_null, index_, type, &name, v_ptr);\n        CPPAD_ASSERT_UNKNOWN( type == 3 );\n        return name;\n    }\n    /// destructor informs CppAD that this atomic function with this index\n    /// has dropped out of scope by setting its pointer to null\n    virtual ~atomic_three(void)\n    {   // change object pointer to null, but leave name for error reporting\n        bool         set_null = true;\n        size_t       type  = 0;          // set to avoid warning\n        std::string* name  = nullptr;\n        void*        v_ptr = nullptr; // set to avoid warning\n        local::atomic_index<Base>(set_null, index_, type, name, v_ptr);\n        CPPAD_ASSERT_UNKNOWN( type == 3 );\n        //\n        // free temporary work memory\n        for(size_t thread = 0; thread < CPPAD_MAX_NUM_THREADS; thread++)\n            free_work(thread);\n    }\n    /// allocates work_ for a specified thread\n    void allocate_work(size_t thread)\n    {   if( work_[thread] == nullptr )\n        {   // allocate the raw memory\n            size_t min_bytes = sizeof(work_struct);\n            size_t num_bytes;\n            void*  v_ptr     = thread_alloc::get_memory(min_bytes, num_bytes);\n            // save in work_\n            work_[thread]    = reinterpret_cast<work_struct*>( v_ptr );\n            // call constructor\n            new( work_[thread] ) work_struct;\n        }\n        return;\n    }\n    /// frees work_ for a specified thread\n    void free_work(size_t thread)\n    {   if( work_[thread] != nullptr )\n        {   // call destructor\n            work_[thread]->~work_struct();\n            // return memory to available pool for this thread\n            thread_alloc::return_memory(\n                reinterpret_cast<void*>(work_[thread])\n            );\n            // mark this thread as not allocated\n            work_[thread] = nullptr;\n        }\n        return;\n    }\n    /// atomic_three function object corresponding to a certain index\n    static atomic_three* class_object(size_t index)\n    {   bool         set_null = false;\n        size_t       type  = 0;          // set to avoid warning\n        std::string* name  = nullptr;\n        void*        v_ptr = nullptr; // set to avoid warning\n        local::atomic_index<Base>(set_null, index, type, name, v_ptr);\n        CPPAD_ASSERT_UNKNOWN( type == 3 );\n        return reinterpret_cast<atomic_three*>( v_ptr );\n    }\n    /// atomic_three function name corresponding to a certain index\n    static const std::string class_name(size_t index)\n    {   bool        set_null = false;\n        size_t      type  = 0;          // set to avoid warning\n        std::string name;\n        void*       v_ptr = nullptr; // set to avoid warning\n        local::atomic_index<Base>(set_null, index, type, &name, v_ptr);\n        CPPAD_ASSERT_UNKNOWN( type == 3 );\n        return name;\n    }\n\n    /*!\n    Set value of id (used by deprecated atomic_one class)\n\n    This function is called just before calling any of the virtual function\n    and has the corresponding id of the corresponding virtual call.\n    */\n    virtual void set_old(size_t id)\n    { }\n// ---------------------------------------------------------------------------\n};\n} // END_CPPAD_NAMESPACE\n\n// member functions\n# include <cppad/core/atomic/three/ctor.hpp>\n# include <cppad/core/atomic/three/afun.hpp>\n# include <cppad/core/atomic/three/for_type.hpp>\n# include <cppad/core/atomic/three/rev_depend.hpp>\n# include <cppad/core/atomic/three/forward.hpp>\n# include <cppad/core/atomic/three/reverse.hpp>\n# include <cppad/core/atomic/three/jac_sparsity.hpp>\n# include <cppad/core/atomic/three/hes_sparsity.hpp>\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/atomic/three/atomic.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin atomic_three}\n\nAtomic AD Functions: Third Generation\n#####################################\n\nContents\n********\n{xrst_toc_table\n    include/cppad/core/atomic/three/atomic.hpp\n    example/atomic_three/atomic_three.xrst\n}\n\n{xrst_end atomic_three}\n"
  },
  {
    "path": "include/cppad/core/atomic/three/ctor.hpp",
    "content": "# ifndef CPPAD_CORE_ATOMIC_THREE_CTOR_HPP\n# define CPPAD_CORE_ATOMIC_THREE_CTOR_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_three_ctor}\n\nAtomic Function Constructor\n###########################\n\nSyntax\n******\n| ``class`` *atomic_user* : ``public CppAD::atomic_three<`` *Base* > {\n| ``public:``\n| |tab| *atomic_user* ( *ctor_arg_list* ) : ``CppAD::atomic_three<`` *Base* >( *name* )\n| |tab| ...\n| };\n| *atomic_user afun* ( *ctor_arg_list* )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_PROTOTYPE\n    // END_PROTOTYPE\n}\n\natomic_user\n***********\n\nctor_arg_list\n=============\nIs a list of arguments for the *atomic_user* constructor.\n\nafun\n====\nThe object *afun* must stay in scope for as long\nas the corresponding atomic function is used.\nThis includes use by any :ref:`ADFun\\<Base><ADFun-name>` that\nhas this *atomic_user* operation in its\n:ref:`operation sequence<glossary@Operation@Sequence>` .\n\nImplementation\n==============\nThe user defined *atomic_user* class is a publicly derived class of\n``atomic_three`` < *Base* > .\nIt should be declared as follows:\n\n| |tab| ``class`` *atomic_user* : ``public CppAD::atomic_three<`` *Base* > {\n| |tab| ``public:``\n| |tab| |tab| *atomic_user* ( *ctor_arg_list* ) : ``atomic_three`` < *Base* >( *name* )\n| |tab| ...\n| |tab| };\n\nwhere ...\ndenotes the rest of the implementation of the derived class.\nThis includes completing the constructor and\nall the virtual functions that have their\n``atomic_three`` implementations replaced by\n*atomic_user* implementations.\n\natomic_three\n************\n\nRestrictions\n============\nThe ``atomic_three`` constructor and destructor cannot be called in\n:ref:`parallel<ta_in_parallel-name>` mode.\n\nBase\n====\nThe template parameter determines the\n:ref:`atomic_three_afun@Base`\ntype for this ``AD`` < *Base* > atomic operation.\n\nname\n====\nThis ``atomic_three`` constructor argument has the following prototype\n\n    ``const std::string&`` *name*\n\nIt is the name for this atomic function and is used for error reporting.\nThe suggested value for *name* is *afun* or *atomic_user* ,\ni.e., the name of the corresponding atomic object or class.\n\nExample\n*******\n\nDefine Constructor\n==================\nThe following is an example of a atomic function constructor definition:\n:ref:`get_started.cpp<atomic_three_get_started.cpp@Constructor>` .\n\nUse Constructor\n===============\nThe following is an example using a atomic function constructor:\n:ref:`get_started.cpp<atomic_three_get_started.cpp@Use Atomic Function@Constructor>` .\n\n{xrst_end atomic_three_ctor}\n-------------------------------------------------------------------------------\n*/\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\n\\file atomic/three_ctor.hpp\nConstructors for atomic_three class.\n*/\n\n/*!\nBase class for atomic_atomic functions.\n\n\\tparam Base\nThis class is used for defining an AD<Base> atomic operation y = g(x).\n\n\\par\nmake sure user does not invoke the default constructor\n*/\ntemplate <class Base>\natomic_three<Base>::atomic_three(void)\n{   CPPAD_ASSERT_KNOWN(false,\n        \"Attempt to use the atomic_three default constructor\"\n    );\n}\n/*!\nConstructor\n\n\\param name\nname used for error reporting\n*/\n// BEGIN_PROTOTYPE\ntemplate <class Base>\natomic_three<Base>::atomic_three(const std::string& name )\n// END_PROTOTYPE\n{   CPPAD_ASSERT_KNOWN(\n        ! thread_alloc::in_parallel() ,\n        \"atomic_three: constructor cannot be called in parallel mode.\"\n    );\n    //\n    // atomic_index\n    bool        set_null  = false;\n    size_t      index     = 0;\n    size_t      type      = 3;\n    std::string copy_name = name;\n    void*       copy_this = reinterpret_cast<void*>( this );\n    index_  = local::atomic_index<Base>(\n        set_null, index, type, &copy_name, copy_this\n    );\n    // initialize work pointers as null;\n    for(size_t thread = 0; thread < CPPAD_MAX_NUM_THREADS; thread++)\n        work_[thread] = nullptr;\n}\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/atomic/three/for_type.hpp",
    "content": "# ifndef CPPAD_CORE_ATOMIC_THREE_FOR_TYPE_HPP\n# define CPPAD_CORE_ATOMIC_THREE_FOR_TYPE_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_three_for_type}\n\nAtomic Function Forward Type Calculation\n########################################\n\nSyntax\n******\n| *ok* = *afun* . ``for_type`` ( *parameter_x* , *type_x* , *type_y* )\n\nPrototype\n=========\n{xrst_literal\n    // BEGIN_PROTOTYPE\n    // END_PROTOTYPE\n}\n\nDependency Analysis\n*******************\nThis calculation is sometimes referred to as a forward dependency analysis.\n\nUsage\n*****\nThis syntax and prototype are used by\n\n    *afun* ( *ax* , *ay* )\n\nwhere :ref:`atomic_three_ctor@atomic_user@afun`\nis a user defined atomic function.\n\nImplementation\n**************\nThis virtual function must be defined by the\n:ref:`atomic_three_ctor@atomic_user` class.\n\nBase\n****\nSee :ref:`atomic_three_define@Base` .\n\nparameter_x\n***********\nSee :ref:`atomic_three_define@parameter_x` .\n\ntype_x\n******\nSee :ref:`atomic_three_define@type_x` .\n\ntype_y\n******\nThis vector has size equal to the number of results for this atomic function;\ni.e. *m* = *ay* . ``size`` () .\nThe input values of the elements of *type_y*\nare not specified (must not matter).\nUpon return, for :math:`i = 0 , \\ldots , m-1`,\n*type_y* [ *i* ] is set to one of the following values:\n\n#. It is ``constant_enum`` if *ay* [ *i* ] only depends on\n   the arguments that are constants.\n#. It is ``dynamic_enum`` if *ay* [ *i* ] depends on\n   a dynamic parameter and does not depend on any variables.\n#. It is ``variable_enum`` if *ay* [ *i* ] depends on\n   a variable.\n\nok\n**\nIf this calculation succeeded, *ok* is true.\nOtherwise, it is false.\n\nExample\n*******\nThe following is an example of a atomic function ``for_type`` definition:\n:ref:`get_started.cpp<atomic_three_get_started.cpp@for_type>` .\n\n{xrst_end atomic_three_for_type}\n-----------------------------------------------------------------------------\n*/\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\n\\file atomic/three_for_type.hpp\nThird generation atomic type computation.\n*/\n/*!\nLink from atomic_three to type calculation\n\n\\param parameter_x [in]\nis the value of the parameters in the corresponding function call\nafun(ax, ay).\n\n\\param type_x [in]\nspecifies which components of x are\nconstants, dynamics, and variables\n\n\\param type_y [out]\nspecifies which components of y are\nconstants, dynamics, and variables\n*/\n// BEGIN_PROTOTYPE\ntemplate <class Base>\nbool atomic_three<Base>::for_type(\n    const vector<Base>&          parameter_x ,\n    const vector<ad_type_enum>&  type_x      ,\n    vector<ad_type_enum>&        type_y      )\n// END_PROTOTYPE\n{   return false; }\n\n} // END_CPPAD_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/atomic/three/forward.hpp",
    "content": "# ifndef CPPAD_CORE_ATOMIC_THREE_FORWARD_HPP\n# define CPPAD_CORE_ATOMIC_THREE_FORWARD_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_three_forward}\n{xrst_spell\n    aparameter\n    ataylor\n}\n\nAtomic Function Forward Mode\n############################\n\nBase\n****\nThis syntax and prototype are used by\n:ref:`afun(ax, ay)<atomic_three_afun-name>` ; see\n:ref:`atomic_three_afun@Base` .\nThey are also used by\n*f* . ``Forward`` and *f* . ``new_dynamic``\nwhere *f* has prototype\n\n    ``ADFun`` < *Base* > *f*\n\nand *afun* is used during the recording of *f* .\n\nSyntax\n======\n\n| *ok* = *afun* . ``forward`` (\n| |tab| *parameter_x* , *type_x* ,\n| |tab| *need_y* , *order_low* , *order_up* , *type_x* , *taylor_x* , *taylor_y*\n| )\n\nPrototype\n=========\n{xrst_literal\n    // BEGIN_PROTOTYPE_BASE\n    // END_PROTOTYPE_BASE\n}\n\nAD<Base>\n********\nThis syntax and prototype are used by\n*af* . ``Forward`` and *af* . ``new_dynamic``\nwhere *af* has prototype\n\n    ``ADFun< AD<`` *Base* > , *Base* > *af*\n\nand *afun* is used in *af* (see :ref:`base2ad-name` ).\n\nSyntax\n======\n\n| *ok* = *afun* . ``forward`` (\n| |tab| *parameter_x* , *type_x* ,\n| |tab| *need_y* , *order_low* , *order_up* , *type_x* , *ataylor_x* , *ataylor_y*\n| )\n\nPrototype\n=========\n{xrst_literal\n    // BEGIN_PROTOTYPE_AD_BASE\n    // END_PROTOTYPE_AD_BASE\n}\n\nImplementation\n**************\nThe *taylor_x* , *taylor_y* version of this function\nmust be defined by the\n:ref:`atomic_three_ctor@atomic_user` class.\nIt can just return *ok* == ``false``\n(and not compute anything) for values\nof *order_up* that are greater than those used by your\n:ref:`Forward-name` mode calculations\n(order zero must be implemented).\n\nparameter_x\n***********\nSee :ref:`atomic_three_define@parameter_x` .\n\naparameter_x\n************\nThe specifications for *aparameter_x*\nis the same as for :ref:`atomic_three_define@parameter_x`\n(only the type of *ataylor_x* is different).\n\ntype_x\n******\nSee :ref:`atomic_three_define@type_x` .\n\nneed_y\n******\nOne can ignore this argument and compute all the *taylor_y*\nTaylor coefficient.\nOften, this is not necessary and *need_y* is used to specify this.\nThe value :ref:`atomic_three_for_type@type_y` is used\nto determine which coefficients are necessary as follows:\n\nConstant Parameters\n===================\nIf *need_y* == ``size_t`` ( ``constant_enum`` ) ,\nthen only the taylor coefficients\nfor :math:`Y_i (t)` where *type_y* [ *i* ] == ``constant_enum``\nare necessary.\nThis is the case during a :ref:`from_json-name` operation.\n\nDynamic Parameters\n==================\nIf *need_y* == ``size_t`` ( ``dynamic_enum`` ) ,\nthen only the taylor coefficients\nfor :math:`Y_i (t)` where *type_y* [ *i* ] == ``dynamic_enum``\nare necessary.\nThis is the case during an :ref:`new_dynamic-name` operation.\n\nVariables\n=========\nIf *need_y* == ``size_t`` ( ``variable_enum`` ) ,\nIf ``ad_type_enum`` ( *need_y* ) == *variable_enum* ,\nthen only the taylor coefficients\nfor :math:`Y_i (t)` where *type_y* [ *i* ] == ``variable_enum``\nare necessary.\nThis is the case during a :ref:`f.Forward<Forward-name>` operation.\nT\n\nAll\n===\nIf *need_y > size_t* ( *variable_enum* ) ,\nthen the taylor coefficients for all :math:`Y_i (t)` are necessary.\nThis is the case during an *afun* ( *ax* , *ay* ) operation.\n\norder_low\n*********\nThis argument\nspecifies the lowest order Taylor coefficient that we are computing.\n\np\n=\nWe sometimes use the notation *p* = *order_low* below.\n\norder_up\n********\nThis argument\nspecifies the highest order Taylor coefficient that we are computing\n( *order_low* <= *order_up* ).\n\nq\n=\nWe sometimes use the notation *q* = *order_up* below.\n\ntaylor_x\n********\nThe size of *taylor_x* is ( *q* +1)* *n* .\nFor :math:`j = 0 , \\ldots , n-1` and :math:`k = 0 , \\ldots , q`,\nwe use the Taylor coefficient notation\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        x_j^k    & = & \\R{taylor\\_x} [ j * ( q + 1 ) + k ]\n        \\\\\n        X_j (t)  & = & x_j^0 + x_j^1 t^1 + \\cdots + x_j^q t^q\n    \\end{eqnarray}\n\nNote that superscripts represent an index for :math:`x_j^k`\nand an exponent for :math:`t^k`.\nAlso note that the Taylor coefficients for :math:`X(t)` correspond\nto the derivatives of :math:`X(t)` at :math:`t = 0` in the following way:\n\n.. math::\n\n    x_j^k = \\frac{1}{ k ! } X_j^{(k)} (0)\n\nparameters\n==========\nIf the *j*-th component of *x* corresponds to a parameter,\n\n    *type_x* [ *j* ] < ``CppAD::variable_enum``\n\nIn this case,\nthe *j*-th component of *parameter_x* is equal to :math:`x_j^0`;\ni.e.,\n\n    *parameter_x* [ *j* ] == *taylor_x* [ *j* * ( *q*  + 1 ) + 0 ]\n\nFurthermore, for *k*  > 0 ,\n\n    *taylor_x* [ *j* * ( *q* + 1 ) + *k*  ] == 0\n\nataylor_x\n*********\nThe specifications for *ataylor_x* is the same as for *taylor_x*\n(only the type of *ataylor_x* is different).\n\ntaylor_y\n********\nThe size of *taylor_y* is ( *q* +1)* *m* .\nUpon return,\nFor :math:`i = 0 , \\ldots , m-1` and :math:`k = 0 , \\ldots , q`,\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        Y_i (t)  & = & g_i [ X(t) ]\n        \\\\\n        Y_i (t)  & = & y_i^0 + y_i^1 t^1 + \\cdots + y_i^q t^q + o ( t^q )\n        \\\\\n        \\R{taylor\\_y}  [ i * ( q + 1 ) + k ] & = & y_i^k\n    \\end{eqnarray}\n\nwhere :math:`o( t^q ) / t^q \\rightarrow 0` as :math:`t \\rightarrow 0`.\nNote that superscripts represent an index for :math:`y_j^k`\nand an exponent for :math:`t^k`.\nAlso note that the Taylor coefficients for :math:`Y(t)` correspond\nto the derivatives of :math:`Y(t)` at :math:`t = 0` in the following way:\n\n.. math::\n\n    y_j^k = \\frac{1}{ k ! } Y_j^{(k)} (0)\n\nIf :math:`p > 0`,\nfor :math:`i = 0 , \\ldots , m-1` and :math:`k = 0 , \\ldots , p-1`,\nthe input of *taylor_y* satisfies\n\n.. math::\n\n    \\R{taylor\\_y}  [ i * ( q + 1 ) + k ] = y_i^k\n\nThese values do not need to be recalculated\nand can be used during the computation of the higher order coefficients.\n\nataylor_y\n*********\nThe specifications for *ataylor_y* is the same as for *taylor_y*\n(only the type of *ataylor_y* is different).\n\nok\n**\nIf this calculation succeeded, *ok* is true.\nOtherwise, it is false.\n\nDiscussion\n**********\nFor example, suppose that *order_up*  == 2 ,\nand you know how to compute the function :math:`g(x)`,\nits first derivative :math:`g^{(1)} (x)`,\nand it component wise Hessian :math:`g_i^{(2)} (x)`.\nThen you can compute *taylor_x* using the following formulas:\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    y_i^0 & = & Y(0)\n            = g_i ( x^0 )\n    \\\\\n    y_i^1 & = & Y^{(1)} ( 0 )\n            = g_i^{(1)} ( x^0 ) X^{(1)} ( 0 )\n            = g_i^{(1)} ( x^0 ) x^1\n    \\\\\n    y_i^2\n    & = & \\frac{1}{2 !} Y^{(2)} (0)\n    \\\\\n    & = & \\frac{1}{2} X^{(1)} (0)^\\R{T} g_i^{(2)} ( x^0 ) X^{(1)} ( 0 )\n      +   \\frac{1}{2} g_i^{(1)} ( x^0 ) X^{(2)} ( 0 )\n    \\\\\n    & = & \\frac{1}{2} (x^1)^\\R{T} g_i^{(2)} ( x^0 ) x^1\n      +    g_i^{(1)} ( x^0 ) x^2\n    \\end{eqnarray}\n\nFor :math:`i = 0 , \\ldots , m-1`, and :math:`k = 0 , 1 , 2`,\n\n.. math::\n\n    \\R{taylor\\_y} [ i * (q + 1) + k ] = y_i^k\n\n{xrst_toc_hidden\n    example/atomic_three/forward.cpp\n    example/atomic_three/dynamic.cpp\n}\nExamples\n********\nThe files\n:ref:`atomic_three_forward.cpp-name` and :ref:`atomic_three_dynamic.cpp-name`\ncontain examples and tests that uses this routine.\n\n{xrst_end atomic_three_forward}\n-----------------------------------------------------------------------------\n*/\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\n\\file atomic/three_forward.hpp\nThird generation atomic forward mode.\n*/\n/*!\nLink from atomic_three to forward mode\n\n\\param parameter_x [in]\ncontains the values, in afun(ax, ay), for arguments that are parameters.\n\n\\param type_x [in]\nwhat is the type, in afun(ax, ay), for each component of x.\n\n\\param need_y [in]\nspecifies which components of taylor_y are needed,\n\n\\param order_low [in]\nlowerest order for this forward mode calculation.\n\n\\param order_up [in]\nhighest order for this forward mode calculation.\n\n\\param taylor_x [in]\nTaylor coefficients corresponding to x for this calculation.\n\n\\param taylor_y [out]\nTaylor coefficient corresponding to y for this calculation\n\nSee the forward mode in user's documentation for atomic_three\n*/\n// BEGIN_PROTOTYPE_BASE\ntemplate <class Base>\nbool atomic_three<Base>::forward(\n    const vector<Base>&          parameter_x ,\n    const vector<ad_type_enum>&  type_x      ,\n    size_t                       need_y      ,\n    size_t                       order_low   ,\n    size_t                       order_up    ,\n    const vector<Base>&          taylor_x    ,\n    vector<Base>&                taylor_y    )\n// END_PROTOTYPE_BASE\n{   return false; }\n\n/*!\nLink from atomic_three to forward mode\n\n\\param aparameter_x [in]\ncontains the values, in afun(ax, ay), for arguments that are parameters.\n\n\\param type_x [in]\nwhat is the type, in afun(ax, ay), for each component of x.\n\n\\param need_y [in]\nspecifies which components of taylor_y are needed,\n\n\\param order_low [in]\nlowerest order for this forward mode calculation.\n\n\\param order_up [in]\nhighest order for this forward mode calculation.\n\n\\param ataylor_x [in]\nTaylor coefficients corresponding to x for this calculation.\n\n\\param ataylor_y [out]\nTaylor coefficient corresponding to y for this calculation\n\nSee the forward mode in user's documentation for base_three\n*/\n// BEGIN_PROTOTYPE_AD_BASE\ntemplate <class Base>\nbool atomic_three<Base>::forward(\n    const vector< AD<Base> >&    aparameter_x ,\n    const vector<ad_type_enum>&  type_x       ,\n    size_t                       need_y       ,\n    size_t                       order_low    ,\n    size_t                       order_up     ,\n    const vector< AD<Base> >&    ataylor_x    ,\n    vector< AD<Base> >&          ataylor_y    )\n// END_PROTOTYPE_AD_BASE\n{   return false; }\n\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/atomic/three/hes_sparsity.hpp",
    "content": "# ifndef CPPAD_CORE_ATOMIC_THREE_HES_SPARSITY_HPP\n# define CPPAD_CORE_ATOMIC_THREE_HES_SPARSITY_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_three_hes_sparsity}\n\nAtomic Function Hessian Sparsity Patterns\n#########################################\n\nSyntax\n******\n| *ok* = *afun* . ``hes_sparsity`` (\n| |tab| *parameter_x* , *type_x* , *select_x* , *select_y* , *pattern_out*\n| )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_PROTOTYPE\n    // END_PROTOTYPE\n}\n\nImplementation\n**************\nThis function must be defined if\n:ref:`atomic_three_ctor@atomic_user@afun` is\nused to define an :ref:`ADFun-name` object *f* ,\nand Hessian sparsity patterns are computed for *f* .\n\nBase\n****\nSee :ref:`atomic_three_afun@Base` .\n\nparameter_x\n***********\nSee :ref:`atomic_three_define@parameter_x` .\n\ntype_x\n******\nSee :ref:`atomic_three_define@type_x` .\n\nselect_x\n********\nThis argument has size equal to the number of arguments to this\natomic function; i.e. the size of *ax* .\nIt specifies which domain components are included in\nthe calculation of *pattern_out* .\nIf *select_x* [ *j* ] is false, then there will be no indices\n*k* such that either of the following hold:\n\n| |tab| *pattern_out* . ``row`` ()[ *k* ] == *j*\n| |tab| *pattern_out* . ``col`` ()[ *k* ] == *j*\n\n.\n\nselect_y\n********\nThis argument has size equal to the number of results to this\natomic function; i.e. the size of *ay* .\nIt specifies which range component functions :math:`g_i (x)` are included in\nof *pattern_out* .\n\npattern_out\n***********\nThis input value of *pattern_out* does not matter.\nUpon return it is the union,\nwith respect to *i* such that *select_y* [ *i* ] is true,\nof the sparsity pattern for Hessian of :math:`g_i (x)`.\nTo be specific, there are non-negative indices\n*i* , *r* , *c* , and *k* such that\n\n| |tab| *pattern_out* . ``row`` ()[ *k* ] == *r*\n| |tab| *pattern_out* . ``col`` ()[ *k* ] == *c*\n\nif and only if\n*select_y* [ *i* ] is true,\n*select_x* [ *r* ] is true,\n*select_x* [ *c* ] is true,\nand\n\n.. math::\n\n    \\partial_{x(r)} \\partial_{x(c)} g_i(x)\n\nis possibly non-zero.\nNote that the sparsity pattern should be symmetric.\n\nok\n**\nIf this calculation succeeded, *ok* is true.\nOtherwise it is false.\n{xrst_toc_hidden\n    example/atomic_three/hes_sparsity.cpp\n}\nExamples\n********\nThe file :ref:`atomic_three_hes_sparsity.cpp-name` contains an example and test\nthat uses this routine.\n\n{xrst_end atomic_three_hes_sparsity}\n-----------------------------------------------------------------------------\n*/\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\n\\file atomic/three_hes_sparsity.hpp\nThird generation atomic Hessian dependency and sparsity patterns.\n*/\n/*!\natomic_three to Hessian dependency and sparsity calculations.\n\n\\param parameter_x [in]\ncontains the values for arguments that are parameters.\n\n\\param type_x [in]\nwhat is the type, in afun(ax, ay), for each component of x.\n\n\\param select_x [in]\nwhich domain components to include in the dependency or sparsity pattern.\n\n\\param select_y [in]\nwhich range components to include in the dependency or sparsity pattern.\n\n\\param pattern_out [out]\nis the sparsity pattern for Hessian.\n*/\n// BEGIN_PROTOTYPE\ntemplate <class Base>\nbool atomic_three<Base>::hes_sparsity(\n    const vector<Base>&                     parameter_x  ,\n    const vector<ad_type_enum>&             type_x       ,\n    const vector<bool>&                     select_x     ,\n    const vector<bool>&                     select_y     ,\n    sparse_rc< vector<size_t> >&            pattern_out  )\n// END_PROTOTYPE\n{   return false; }\n/*!\nLink from forward Hessian sweep to atomic_three.\n2DO: move this function outside this file so can change\ndeveloper documentation to omhelp formatting.\n\n\\tparam InternalSparsity\nIs the used internally for sparsity calculations; i.e.,\nsparse_pack or sparse_list.\n\n\\param parameter_x\nis parameter arguments to the function, other components are nan.\n\n\\param type_x [in]\nwhat is the type, in afun(ax, ay), for each component of x.\n\n\\param x_index\nis the variable index, on the tape, for the arguments to this function.\nThis size of x_index is n, the number of arguments to this function.\nThe index zero is used for parameters.\n\n\\param y_index\nis the variable index, on the tape, for the results for this function.\nThis size of y_index is m, the number of results for this function.\nThe index zero is used for parameters.\n\n\\param for_jac_sparsity\nOn input, for j = 0, ... , n-1, the sparsity pattern with index x_index[j],\nis the forward Jacobian sparsity for the j-th argument to this atomic function.\n\n\\param rev_jac_pattern\nOn input, for i = 0, ... , m-1, the sparsity pattern with index y_index[i],\nis the reverse Jacobian sparsity for the i-th result to this atomic function.\nThis shows which components of the result affect the function we are\ncomputing the Hessian of.\n\n\\param hes_sparsity_for\nThis is the sparsity pattern for the Hessian. On input, the non-linear\nterms in the atomic function have not been included. Upon return, they\nhave been included.\n*/\ntemplate <class Base>\ntemplate <class InternalSparsity>\nbool atomic_three<Base>::for_hes_sparsity(\n    const vector<Base>&              parameter_x      ,\n    const vector<ad_type_enum>&      type_x           ,\n    const vector<size_t>&            x_index          ,\n    const vector<size_t>&            y_index          ,\n    size_t                           np1              ,\n    size_t                           numvar           ,\n    const InternalSparsity&          rev_jac_pattern  ,\n    InternalSparsity&                for_sparsity     )\n{   typedef typename InternalSparsity::const_iterator const_iterator;\n    //\n    CPPAD_ASSERT_UNKNOWN( rev_jac_pattern.end() == 1 );\n    CPPAD_ASSERT_UNKNOWN( for_sparsity.end() == np1 );\n    CPPAD_ASSERT_UNKNOWN( for_sparsity.n_set() == np1 + numvar );\n    size_t n      = x_index.size();\n    size_t m      = y_index.size();\n    //\n    // select_x\n    vector<bool> select_x(n);\n    for(size_t j = 0; j < n; j++)\n    {   // check if should compute pattern w.r.t x[j]\n        select_x[j] = for_sparsity.number_elements(np1 + x_index[j]) > 0;\n    }\n    //\n    // bool select_y\n    vector<bool> select_y(m);\n    for(size_t i = 0; i < m; i++)\n    {   // check if we should include y[i]\n        select_y[i] = rev_jac_pattern.number_elements(y_index[i]) > 0;\n    }\n    // ------------------------------------------------------------------------\n    // call user's version of atomic function for Jacobian\n    sparse_rc< vector<size_t> > pattern_out;\n    bool dependency = false;\n    bool ok = jac_sparsity(\n        parameter_x, type_x, dependency, select_x, select_y, pattern_out\n    );\n    if( ! ok )\n        return false;\n    //\n    // transfer sparsity patterns from pattern_out to var_sparsity\n    size_t                nnz = pattern_out.nnz();\n    const vector<size_t>& row( pattern_out.row() );\n    const vector<size_t>& col( pattern_out.col() );\n    for(size_t k = 0; k < nnz; ++k)\n    {   size_t i = row[k];\n        size_t j = col[k];\n        CPPAD_ASSERT_KNOWN(\n            select_y[i] && select_x[j],\n            \"atomic: jac_sparsity: pattern_out not in \"\n            \"select_x or select_y range\"\n        );\n        const_iterator itr(for_sparsity, np1 + x_index[j]);\n        size_t ell = *itr;\n        while( ell < np1 )\n        {   for_sparsity.post_element(np1 + y_index[i], ell );\n            ell = *(++itr);\n        }\n    }\n    for(size_t i = 0; i < m; ++i)\n        for_sparsity.process_post( np1 + y_index[i] );\n    // ------------------------------------------------------------------------\n    // call user's version of atomic function for Hessian\n    ok = hes_sparsity(\n        parameter_x, type_x, select_x, select_y, pattern_out\n    );\n    if( ! ok )\n        return ok;\n    //\n    // add new elements to Hessian sparisty in calling routine\n    nnz = pattern_out.nnz();\n    for(size_t k = 0; k < nnz; ++k)\n    {   size_t r = row[k];\n        size_t c = col[k];\n        CPPAD_ASSERT_KNOWN(\n            select_x[r] && select_x[c],\n            \"atomic: hes_sparsity: pattern_out not in select_x range\"\n        );\n        const_iterator itr_1(for_sparsity, np1 + x_index[r]);\n        size_t v1 = *itr_1;\n        while( v1 < np1 )\n        {   for_sparsity.binary_union(\n                v1, v1, np1 + x_index[c], for_sparsity\n                 );\n                 v1 = *(++itr_1);\n        }\n        // no need to add same elements twice\n        if( c != r )\n        {   const_iterator itr_2(for_sparsity, np1 + x_index[c]);\n            size_t v2 = *itr_2;\n            while( v2 < np1 )\n            {   for_sparsity.binary_union(\n                    v2, v2, np1 + x_index[r], for_sparsity\n                );\n                v2 = *(++itr_2);\n            }\n        }\n    }\n    return ok;\n}\n/*!\nLink from for_reverse Hessian sweep to atomic_three.\n\n\\tparam InternalSparsity\nIs the used internally for sparsity calculations; i.e.,\nsparse_pack or sparse_list.\n\n\\param parameter_x\nis parameter arguments to the function, other components are nan.\n\n\\param type_x [in]\nwhat is the type, in afun(ax, ay), for each component of x.\n\n\\param x_index\nis the variable index, on the tape, for the arguments to this function.\nThis size of x_index is n, the number of arguments to this function.\nThe index zero is used for parameters.\n\n\\param y_index\nis the variable index, on the tape, for the results for this function.\nThis size of y_index is m, the number of results for this function.\nThe index zero is used for parameters.\n\n\\param for_jac_pattern\nOn input, for j = 0, ... , n-1, the sparsity pattern with index x_index[j],\nis the forward Jacobian pattern for the j-th argument to this atomic function.\n\n\\param rev_jac_flag\nOn input, for i = 0, ... , m-1, rev_jac_flag[ y_index[i] ] is true\nif the function we are computing the Hessian of has possibly non-zero Jacobian\nw.r.t variable y_index[i].\nOn output, for j = 0, ... , n, rev_jac_flag[ x_index[j] ] is set to true\nif the variable with index x_index[j] has possible non-zero Jacobian\nwith respect to one of the true y_index[i] cases.\nOtherwise, rev_jac_flag [ x_inde[j] ] is not changed.\n\n\\param hes_sparsity_rev\nIs the reverse mode sparsity pattern for the Hessian. On input, the non-linear\nterms in the atomic function have not been included. Upon return, they\nhave been included.\n*/\ntemplate <class Base>\ntemplate <class InternalSparsity>\nbool atomic_three<Base>::rev_hes_sparsity(\n    const vector<Base>&              parameter_x      ,\n    const vector<ad_type_enum>&      type_x           ,\n    const vector<size_t>&            x_index          ,\n    const vector<size_t>&            y_index          ,\n    const InternalSparsity&          for_jac_pattern  ,\n    bool*                            rev_jac_flag     ,\n    InternalSparsity&                hes_sparsity_rev )\n{   typedef typename InternalSparsity::const_iterator const_iterator;\n    size_t n      = x_index.size();\n    size_t m      = y_index.size();\n    //\n    // select_x\n    vector<bool> select_x(n);\n    for(size_t j = 0; j < n; j++)\n    {   // check if should compute pattern w.r.t x[j]\n        const_iterator itr(for_jac_pattern, x_index[j]);\n        size_t i = *itr;\n        select_x[j] = i < for_jac_pattern.end();\n        CPPAD_ASSERT_UNKNOWN( x_index[j] > 0 || ! select_x[j] );\n    }\n    //\n    // bool select_y\n    vector<bool> select_y(m);\n    for(size_t i = 0; i < m; i++)\n    {   // check if we should include y[i]\n        select_y[i] = rev_jac_flag[ y_index[i] ];\n        CPPAD_ASSERT_UNKNOWN( y_index[i] > 0 || ! select_y[i] );\n    }\n    //\n    // call atomic function for Jacobain sparsity\n    bool dependency = false;\n    sparse_rc< vector<size_t> > pattern_jac;\n    bool ok = jac_sparsity(\n        parameter_x, type_x, dependency, select_x, select_y, pattern_jac\n    );\n    const vector<size_t>& row_jac( pattern_jac.row() );\n    const vector<size_t>& col_jac( pattern_jac.col() );\n    size_t nnz_jac = pattern_jac.nnz();\n    if( ! ok )\n        return ok;\n    //\n    // call atomic function for Hessian sparsity\n    sparse_rc< vector<size_t> > pattern_hes;\n    ok = hes_sparsity(parameter_x, type_x, select_x, select_y, pattern_hes);\n    const vector<size_t>& row_hes( pattern_hes.row() );\n    const vector<size_t>& col_hes( pattern_hes.col() );\n    size_t nnz_hes = pattern_hes.nnz();\n    if( ! ok )\n        return ok;\n    //\n    // propagate Hessian sparsity through the Jacobian\n    for(size_t k = 0; k < nnz_jac; ++k)\n    {   size_t i = row_jac[k];\n        size_t j = col_jac[k];\n        CPPAD_ASSERT_KNOWN(\n            select_y[i] && select_x[j] ,\n            \"atomic: jac_sparsity: pattern_out not in \"\n            \"select_x or select_y range\"\n        );\n        // from y_index[i] to x_index[j]\n        hes_sparsity_rev.binary_union(\n            x_index[j], x_index[j], y_index[i], hes_sparsity_rev\n        );\n    }\n    //\n    // propagate rev_jac_flag through the Jacobian\n    // (seems OK to exclude variables with zero forward jacobian)\n    for(size_t k = 0; k < nnz_jac; ++k)\n    {   size_t j = col_jac[k];\n        rev_jac_flag[ x_index[j] ] = true;\n    }\n    //\n    // new hessian sparsity terms between y and x\n    for(size_t k = 0; k < nnz_hes; ++k)\n    {   size_t r = row_hes[k];\n        size_t c = col_hes[k];\n        CPPAD_ASSERT_KNOWN(\n            select_x[r] && select_x[c] ,\n            \"atomic: hes_sparsity: pattern_out not in select_x range\"\n        );\n        hes_sparsity_rev.binary_union(\n            x_index[r], x_index[r], x_index[c], for_jac_pattern\n        );\n        hes_sparsity_rev.binary_union(\n            x_index[c], x_index[c], x_index[r], for_jac_pattern\n        );\n    }\n    return ok;\n}\n\n} // END_CPPAD_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/atomic/three/jac_sparsity.hpp",
    "content": "# ifndef CPPAD_CORE_ATOMIC_THREE_JAC_SPARSITY_HPP\n# define CPPAD_CORE_ATOMIC_THREE_JAC_SPARSITY_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_three_jac_sparsity}\n\nAtomic Function Jacobian Sparsity Patterns\n##########################################\n\nSyntax\n******\n| *ok* = *afun* . ``jac_sparsity`` (\n| |tab| *parameter_x* , *type_x* , *dependency* , *select_x* , *select_y* , *pattern_out*\n| )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_PROTOTYPE\n    // END_PROTOTYPE\n}\n\nImplementation\n**************\nThis function must be defined if\n:ref:`atomic_three_ctor@atomic_user@afun` is\nused to define an :ref:`ADFun-name` object *f* ,\nand Jacobian sparsity patterns are computed for *f* .\n(Computing Hessian sparsity patterns and optimizing\nrequires Jacobian sparsity patterns.)\n\nBase\n****\nSee :ref:`atomic_three_afun@Base` .\n\nparameter_x\n***********\nSee :ref:`atomic_three_define@parameter_x` .\n\ntype_x\n******\nSee :ref:`atomic_three_define@type_x` .\n\ndependency\n**********\nIf *dependency* is true,\nthen *pattern_out* is a\n:ref:`dependency.cpp@Dependency Pattern`\nfor this atomic function.\nOtherwise it is a\n:ref:`glossary@Sparsity Pattern` for the\nderivative of the atomic function.\n\nselect_x\n********\nThis argument has size equal to the number of arguments to this\natomic function; i.e. the size of *ax* .\nIt specifies which domain components are included in\nthe calculation of *pattern_out* .\nIf *select_x* [ *j* ] is false, then there will be no indices\n*k* such that\n\n    *pattern_out* . ``col`` ()[ *k* ] == *j*\n\n.\n\nselect_y\n********\nThis argument has size equal to the number of results to this\natomic function; i.e. the size of *ay* .\nIt specifies which range components are included in\nthe calculation of *pattern_out* .\nIf *select_y* [ *i* ] is false, then there will be no indices\n*k* such that\n\n    *pattern_out* . ``row`` ()[ *k* ] == *i*\n\n.\n\npattern_out\n***********\nThis input value of *pattern_out* does not matter.\nUpon return it is a\ndependency or sparsity pattern for the Jacobian of :math:`g(x)`,\nthe function corresponding to\n:ref:`atomic_three_ctor@atomic_user@afun` ;\n*dependency* above.\nTo be specific, there are non-negative indices\n*i* , *j* , *k* such that\n\n| |tab| *pattern_out* . ``row`` ()[ *k* ] == *i*\n| |tab| *pattern_out* . ``col`` ()[ *k* ] == *j*\n\nif and only if\n*select_x* [ *j* ] is true,\n*select_y* [ *j* ] is true,\nand :math:`g_i(x)` depends on the value of :math:`x_j`\n(and the partial of :math:`g_i(x)` with respect to\n:math:`x_j` is possibly non-zero).\n\nok\n**\nIf this calculation succeeded, *ok* is true.\nOtherwise it is false.\n{xrst_toc_hidden\n    example/atomic_three/jac_sparsity.cpp\n}\nExamples\n********\nThe file :ref:`atomic_three_jac_sparsity.cpp-name` contains an example and test\nthat uses this routine.\n\n{xrst_end atomic_three_jac_sparsity}\n-----------------------------------------------------------------------------\n*/\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\n\\file atomic/three_jac_sparsity.hpp\nThird generation atomic Jacobian dependency and sparsity patterns.\n*/\n/*!\natomic_three to Jacobian dependency and sparsity calculations.\n\n\\param parameter_x [in]\ncontains the values for arguments that are parameters.\n\n\\param type_x [in]\nwhat is the type, in afun(ax, ay), for each component of x.\n\n\\param dependency [in]\nif true, calculate dependency pattern,\notherwise calculate sparsity pattern.\n\n\\param select_x [in]\nwhich domain components to include in the dependency or sparsity pattern.\nThe index zero is used for parameters.\n\n\\param select_y [in]\nwhich range components to include in the dependency or sparsity pattern.\nThe index zero is used for parameters.\n\n\\param pattern_out [out]\nis the dependency or sparsity pattern.\n*/\n// BEGIN_PROTOTYPE\ntemplate <class Base>\nbool atomic_three<Base>::jac_sparsity(\n    const vector<Base>&                     parameter_x  ,\n    const vector<ad_type_enum>&             type_x       ,\n    bool                                    dependency   ,\n    const vector<bool>&                     select_x     ,\n    const vector<bool>&                     select_y     ,\n    sparse_rc< vector<size_t> >&            pattern_out  )\n// END_PROTOTYPE\n{   return false; }\n/*!\nLink from forward Jacobian sparsity calculations to atomic_three\n\n\\tparam InternalSparsity\nIs the type used for internal sparsity calculations; i.e.,\nsparse_pack or sparse_list.\n\n\\param dependency\nif true, calculate dependency pattern,\notherwise calculate sparsity pattern.\n\n\\param parameter_x\nis parameter arguments to the function, other components are nan.\n\n\\param type_x [in]\nwhat is the type, in afun(ax, ay), for each component of x.\n\n\\param x_index\nis the variable index, on the tape, for the arguments to this atomic function.\nThis size of x_index is n, the number of arguments to this atomic function.\nThe index zero is used for parameters.\n\n\\param y_index\nis the variable index, on the tape, for the results for this atomic function.\nThis size of y_index is m, the number of results for this atomic function.\nThe index zero is used for parameters.\n\n\\param var_sparsity\nOn input, for j = 0, ... , n-1, the sparsity pattern with index x_index[j],\nis the sparsity for the j-th argument to this atomic function.\nOn output, for i = 0, ... , m-1, the sparsity pattern with index y_index[i],\nis the sparsity for the i-th result for this atomic function.\n\n\\return\nis true if the computation succeeds.\n*/\ntemplate <class Base>\ntemplate <class InternalSparsity>\nbool atomic_three<Base>::for_jac_sparsity(\n    bool                             dependency   ,\n    const vector<Base>&              parameter_x  ,\n    const vector<ad_type_enum>&      type_x       ,\n    const vector<size_t>&            x_index      ,\n    const vector<size_t>&            y_index      ,\n    InternalSparsity&                var_sparsity )\n{   typedef typename InternalSparsity::const_iterator iterator;\n\n    // number of arguments and results for this atomic function\n    size_t n = x_index.size();\n    size_t m = y_index.size();\n\n    // select_y\n    vector<bool> select_y(m);\n    for(size_t i = 0; i < m; ++i)\n        select_y[i] = y_index[i] != 0;\n\n    // determine select_x\n    vector<bool> select_x(n);\n    for(size_t j = 0; j < n; ++j)\n    {   // check if x_j depends on any previous variable\n        iterator itr(var_sparsity, x_index[j]);\n        size_t ell = *itr;\n        select_x[j] = ell < var_sparsity.end();\n        CPPAD_ASSERT_UNKNOWN( x_index[j] > 0 || ! select_x[j] );\n    }\n    sparse_rc< vector<size_t> > pattern_out;\n    bool ok = jac_sparsity(\n        parameter_x, type_x, dependency, select_x, select_y, pattern_out\n    );\n    if( ! ok )\n        return false;\n    //\n    // transfer sparsity patterns from pattern_out to var_sparsity\n    size_t                nnz = pattern_out.nnz();\n    const vector<size_t>& row( pattern_out.row() );\n    const vector<size_t>& col( pattern_out.col() );\n    for(size_t k = 0; k < nnz; ++k)\n    {   size_t i = row[k];\n        size_t j = col[k];\n        CPPAD_ASSERT_KNOWN(\n            select_y[i] && select_x[j],\n            \"atomic: jac_sparsity: pattern_out not in \"\n            \"select_x or select_y range\"\n        );\n        iterator itr(var_sparsity, x_index[j]);\n        size_t ell = *itr;\n        while( ell < var_sparsity.end() )\n        {   var_sparsity.post_element( y_index[i], ell );\n            ell = *(++itr);\n        }\n    }\n    for(size_t i = 0; i < m; ++i)\n        var_sparsity.process_post( y_index[i] );\n    //\n    return true;\n}\n/*!\nLink from reverse Jacobian sparsity calculations to atomic_three\n\n\\tparam InternalSparsity\nIs the type used for internal sparsity calculations; i.e.,\nsparse_pack or sparse_list.\n\n\\param dependency\nif true, calculate dependency pattern,\notherwise calculate sparsity pattern.\n\n\\param parameter_x\nis parameter arguments to the function, other components are nan.\n\n\\param type_x [in]\nwhat is the type, in afun(ax, ay), for each component of x.\n\n\\param x_index\nis the variable index, on the tape, for the arguments to this atomic function.\nThis size of x_index is n, the number of arguments to this atomic function.\n\n\\param y_index\nis the variable index, on the tape, for the results for this atomic function.\nThis size of y_index is m, the number of results for this atomic function.\n\n\\param var_sparsity\nOn input, for i = 0, ... , m-1, the sparsity pattern with index y_index[i],\nis the sparsity of the outer function with respect to the i-th\nresult for this atomic function.\nOn input, for j = 0, ... , n-1, the sparsity pattern with index x_index[j],\nis the sparsity for the outer function with respect to the j-th\nargument to this atomic function.\nOn output, for j = 0, ... , n-1, the sparsity pattern with index x_index[j],\nis the sparsity for the outer function with respect to the j-th\nargument to this atomic function with the atomic function results\nremoved as arguments to the outer function.\n\n\\return\nis true if the computation succeeds.\n*/\ntemplate <class Base>\ntemplate <class InternalSparsity>\nbool atomic_three<Base>::rev_jac_sparsity(\n    bool                             dependency   ,\n    const vector<Base>&              parameter_x  ,\n    const vector<ad_type_enum>&      type_x       ,\n    const vector<size_t>&            x_index      ,\n    const vector<size_t>&            y_index      ,\n    InternalSparsity&                var_sparsity )\n{   typedef typename InternalSparsity::const_iterator iterator;\n\n    // number of arguments and results for this atomic function\n    size_t n = x_index.size();\n    size_t m = y_index.size();\n\n    // selection vectors\n    vector<bool> select_x(n), select_y(m);\n\n    // 2DO: perhaps we could use for_type(type_x, type_y)\n    // to reduce the true components in select_x\n    for(size_t j = 0; j < n; ++j)\n        select_x[j] = true;\n\n    // determine select_y\n    for(size_t i = 0; i < m; ++i)\n    {   // check if y_i has sparsity is non-empty\n        iterator itr(var_sparsity, y_index[i]);\n        size_t ell = *itr;\n        select_y[i] = ell < var_sparsity.end();\n    }\n    sparse_rc< vector<size_t> > pattern_out;\n    bool ok = jac_sparsity(\n        parameter_x, type_x, dependency, select_x, select_y, pattern_out\n    );\n    if( ! ok )\n        return false;\n    //\n    // transfer sparsity patterns from pattern_out to var_sparsity\n    size_t                nnz = pattern_out.nnz();\n    const vector<size_t>& row( pattern_out.row() );\n    const vector<size_t>& col( pattern_out.col() );\n    for(size_t k = 0; k < nnz; ++k)\n    {   size_t i = row[k];\n        size_t j = col[k];\n        CPPAD_ASSERT_KNOWN(\n            select_y[i] && select_x[j],\n            \"atomic: jac_sparsity: pattern_out not in \"\n            \"select_x or select_y range\"\n        );\n        iterator itr(var_sparsity, y_index[i]);\n        size_t ell = *itr;\n        while( ell < var_sparsity.end() )\n        {   var_sparsity.post_element( x_index[j], ell );\n            ell = *(++itr);\n        }\n    }\n    for(size_t j = 0; j < n; ++j)\n        var_sparsity.process_post( x_index[j] );\n    //\n    return true;\n}\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/atomic/three/rev_depend.hpp",
    "content": "# ifndef CPPAD_CORE_ATOMIC_THREE_REV_DEPEND_HPP\n# define CPPAD_CORE_ATOMIC_THREE_REV_DEPEND_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_three_rev_depend}\n\nAtomic Function Reverse Dependency Calculation\n##############################################\n\nSyntax\n******\n| *ok* = *afun* . ``rev_depend`` (\n| |tab| *parameter_x* , *type_x* , *depend_x* , *depend_y*\n| )\n\nPrototype\n=========\n{xrst_literal\n    // BEGIN_PROTOTYPE\n    // END_PROTOTYPE\n}\n\nDependency Analysis\n*******************\nThis calculation is sometimes referred to as a reverse dependency analysis.\n\nImplementation\n**************\nThis function must be defined if\n:ref:`atomic_three_ctor@atomic_user@afun` is\nused to define an :ref:`ADFun-name` object *f* ,\nand :ref:`f.optimize()<optimize-name>` is used.\n\nBase\n****\nSee :ref:`atomic_three_afun@Base` .\n\nparameter_x\n***********\nSee :ref:`atomic_three_define@parameter_x` .\n\ntype_x\n******\nSee :ref:`atomic_three_define@type_x` .\n\ndepend_x\n********\nThis vector has size equal to the number of arguments for this atomic function;\ni.e. *n* = *ax* . ``size`` () .\nThe input values of the elements of *depend_x*\nare not specified (must not matter).\nUpon return, for :math:`j = 0 , \\ldots , n-1`,\n*depend_x* [ *j* ] is true if the values of interest depend\non the value of :ref:`ax[j]<atomic_three_afun@ax>` in the corresponding\n*afun* ( *ax* , *ay* ) call.\n\nOptimize\n========\nParameters and variables,\nthat the values of interest do not depend on,\nmay get removed by :ref:`optimization<optimize-name>` .\nThe corresponding values in :ref:`atomic_three_define@parameter_x` ,\nand :ref:`atomic_three_forward@taylor_x`\n(after optimization has removed them) are not specified.\n\ndepend_y\n********\nThis vector has size equal to the number of results for this atomic function;\ni.e. *m* = *ay* . ``size`` () .\nFor :math:`i = 0 , \\ldots , m-1`,\n*depend_y* [ *i* ] is true if the values of interest depend\non the value of :ref:`ay[i]<atomic_three_afun@ay>` in the corresponding\n*afun* ( *ax* , *ay* ) call.\n\nok\n**\nIf this calculation succeeded, *ok* is true.\nOtherwise, it is false.\n\nContents\n********\n{xrst_toc_table\n    example/atomic_three/rev_depend.cpp\n}\nExample\n*******\nThe following is an example of a atomic function ``rev_depend`` definition:\n:ref:`atomic_three_rev_depend.cpp-name` .\n\n{xrst_end atomic_three_rev_depend}\n-----------------------------------------------------------------------------\n*/\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\n\\file atomic/three_rev_depend.hpp\nThird generation atomic type computation.\n*/\n/*!\nLink from atomic_three to reverse dependency calculation\n\n\\param parameter_x [in]\nis the value of the parameters in the corresponding function call\nafun(ax, ay).\n\n\\param type_x [in]\nis the value for each of the components of x.\n\n\\param depend_x [out]\nspecifies which components of x affect values of interest.\n\n\\param depend_y [in]\nspecifies which components of y affect values of interest.\n*/\n// BEGIN_PROTOTYPE\ntemplate <class Base>\nbool atomic_three<Base>::rev_depend(\n    const vector<Base>&         parameter_x ,\n    const vector<ad_type_enum>& type_x      ,\n    vector<bool>&               depend_x    ,\n    const vector<bool>&         depend_y    )\n// END_PROTOTYPE\n{   return false; }\n\n} // END_CPPAD_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/atomic/three/reverse.hpp",
    "content": "# ifndef CPPAD_CORE_ATOMIC_THREE_REVERSE_HPP\n# define CPPAD_CORE_ATOMIC_THREE_REVERSE_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_three_reverse}\n{xrst_spell\n    aparameter\n    apartial\n    ataylor\n}\n\nAtomic Function Reverse Mode\n############################\n\nBase\n****\nThis syntax is used by *f* . ``Reverse`` where *f* has prototype\n\n    ``ADFun`` < *Base* > *f*\n\nand *afun* is used in *f* ;\nsee :ref:`atomic_three_afun@Base` .\n\nSyntax\n======\n\n| *ok* = *afun* . ``reverse`` (\n| |tab| *parameter_x* , *type_x* ,\n| |tab| *order_up* , *taylor_x* , *taylor_y* , *partial_x* , *partial_y*\n| )\n\nPrototype\n=========\n{xrst_literal\n    // BEGIN_PROTOTYPE_BASE\n    // END_PROTOTYPE_BASE\n}\n\nAD<Base>\n********\nThis syntax is used by *af* . ``Reverse`` where *af* has prototype\n\n    ``ADFun< AD<`` *Base* > , *Base* > *af*\n\nand *afun* is used in *af* (see :ref:`base2ad-name` ).\n\nSyntax\n======\n\n| *ok* = *afun* . ``reverse`` (\n| |tab| *aparameter_x* , *type_x* ,\n| |tab| *order_up* , *ataylor_x* , *ataylor_y* , *apartial_x* , *apartial_y*\n| )\n\nPrototype\n=========\n{xrst_literal\n    // BEGIN_PROTOTYPE_AD_BASE\n    // END_PROTOTYPE_AD_BASE\n}\n\nImplementation\n**************\nThis function must be defined if\n:ref:`atomic_three_ctor@atomic_user@afun` is\nused to define an :ref:`ADFun-name` object *f* ,\nand reverse mode derivatives are computed for *f* .\nIt can return *ok* == ``false``\n(and not compute anything) for values\nof *order_up* that are greater than those used by your\n:ref:`Reverse-name` mode calculations.\n\nparameter_x\n***********\nSee :ref:`atomic_three_define@parameter_x` .\n\naparameter_x\n************\nThe specifications for *aparameter_x*\nis the same as for :ref:`atomic_three_define@parameter_x`\n(only the type of *ataylor_x* is different).\n\ntype_x\n******\nSee :ref:`atomic_three_define@type_x` .\n\norder_up\n********\nThis argument specifies the highest order Taylor coefficient that\ncomputing the derivative of.\n\ntaylor_x\n********\nThe size of *taylor_x* is ( *q* +1)* *n* .\nFor :math:`j = 0 , \\ldots , n-1` and :math:`k = 0 , \\ldots , q`,\nwe use the Taylor coefficient notation\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        x_j^k    & = & \\R{taylor\\_x} [ j * ( q + 1 ) + k ]\n        \\\\\n        X_j (t)  & = & x_j^0 + x_j^1 t^1 + \\cdots + x_j^q t^q\n    \\end{eqnarray}\n\nNote that superscripts represent an index for :math:`x_j^k`\nand an exponent for :math:`t^k`.\nAlso note that the Taylor coefficients for :math:`X(t)` correspond\nto the derivatives of :math:`X(t)` at :math:`t = 0` in the following way:\n\n.. math::\n\n    x_j^k = \\frac{1}{ k ! } X_j^{(k)} (0)\n\nparameters\n==========\nIf the *j*-th component of *x* corresponds to a parameter,\n\n    *type_x* [ *j* ] < ``CppAD::variable_enum``\n\nIn this case,\nthe *j*-th component of *parameter_x* is equal to :math:`x_j^0`;\ni.e.,\n\n    *parameter_x* [ *j* ] == *taylor_x* [ *j* * ( *q*  + 1 ) + 0 ]\n\nFurthermore, for *k*  > 0 ,\n\n    *taylor_x* [ *j* * ( *q* + 1 ) + *k*  ] == 0\n\nataylor_x\n*********\nThe specifications for *ataylor_x* is the same as for *taylor_x*\n(only the type of *ataylor_x* is different).\n\ntaylor_y\n********\nThe size of *taylor_y* is ( *q* +1)* *m* .\nFor :math:`i = 0 , \\ldots , m-1` and :math:`k = 0 , \\ldots , q`,\nwe use the Taylor coefficient notation\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        Y_i (t)  & = & g_i [ X(t) ]\n        \\\\\n        Y_i (t)  & = & y_i^0 + y_i^1 t^1 + \\cdots + y_i^q t^q + o ( t^q )\n        \\\\\n        y_i^k    & = & \\R{taylor\\_y} [ i * ( q + 1 ) + k ]\n    \\end{eqnarray}\n\nwhere :math:`o( t^q ) / t^q \\rightarrow 0` as :math:`t \\rightarrow 0`.\nNote that superscripts represent an index for :math:`y_j^k`\nand an exponent for :math:`t^k`.\nAlso note that the Taylor coefficients for :math:`Y(t)` correspond\nto the derivatives of :math:`Y(t)` at :math:`t = 0` in the following way:\n\n.. math::\n\n    y_j^k = \\frac{1}{ k ! } Y_j^{(k)} (0)\n\nataylor_y\n*********\nThe specifications for *ataylor_y* is the same as for *taylor_y*\n(only the type of *ataylor_y* is different).\n\nF\n*\nWe use the notation :math:`\\{ x_j^k \\} \\in \\B{R}^{n \\times (q+1)}` for\n\n.. math::\n\n    \\{ x_j^k \\W{:} j = 0 , \\ldots , n-1, k = 0 , \\ldots , q \\}\n\nWe use the notation :math:`\\{ y_i^k \\} \\in \\B{R}^{m \\times (q+1)}` for\n\n.. math::\n\n    \\{ y_i^k \\W{:} i = 0 , \\ldots , m-1, k = 0 , \\ldots , q \\}\n\nWe define the function\n:math:`F : \\B{R}^{n \\times (q+1)} \\rightarrow \\B{R}^{m \\times (q+1)}` by\n\n.. math::\n\n    y_i^k = F_i^k [ \\{ x_j^k \\} ]\n\nNote that\n\n.. math::\n\n    F_i^0 ( \\{ x_j^k \\} ) = g_i ( X(0) )  = g_i ( x^0 )\n\nWe also note that\n:math:`F_i^\\ell ( \\{ x_j^k \\} )` is a function of\n:math:`x^0 , \\ldots , x^\\ell`\nand is determined by the derivatives of :math:`g_i (x)`\nup to order :math:`\\ell`.\n\nG, H\n****\nWe use :math:`G : \\B{R}^{m \\times (q+1)} \\rightarrow \\B{R}`\nto denote an arbitrary scalar valued function of :math:`\\{ y_i^k \\}`.\nWe use :math:`H : \\B{R}^{n \\times (q+1)} \\rightarrow \\B{R}`\ndefined by\n\n.. math::\n\n    H ( \\{ x_j^k \\} ) = G[ F( \\{ x_j^k \\} ) ]\n\npartial_y\n*********\nThe size of *partial_y* is ( *q* +1)* *m* .\nFor :math:`i = 0 , \\ldots , m-1`, :math:`k = 0 , \\ldots , q`,\n\n.. math::\n\n    \\R{partial\\_y} [ i * (q + 1 ) + k ] = \\partial G / \\partial y_i^k\n\napartial_y\n**********\nThe specifications for *apartial_y* is the same as for\n*partial_y* (only the type of *apartial_y* is different).\n\npartial_x\n*********\nThe size of *partial_x* is ( *q* +1)* *n* .\nThe input values of the elements of *partial_x*\nare not specified (must not matter).\nUpon return,\nfor :math:`j = 0 , \\ldots , n-1` and :math:`\\ell = 0 , \\ldots , q`,\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    \\R{partial\\_x} [ j * (q + 1) + \\ell ] & = & \\partial H / \\partial x_j^\\ell\n    \\\\\n    & = &\n    ( \\partial G / \\partial \\{ y_i^k \\} ) \\cdot\n        ( \\partial \\{ y_i^k \\} / \\partial x_j^\\ell )\n    \\\\\n    & = &\n    \\sum_{k=0}^q\n    \\sum_{i=0}^{m-1}\n    ( \\partial G / \\partial y_i^k ) ( \\partial y_i^k / \\partial x_j^\\ell )\n    \\\\\n    & = &\n    \\sum_{k=\\ell}^q\n    \\sum_{i=0}^{m-1}\n    \\R{partial\\_y}[ i * (q + 1 ) + k ] ( \\partial F_i^k / \\partial x_j^\\ell )\n    \\end{eqnarray}\n\nNote that we have used the fact that for :math:`k < \\ell`,\n:math:`\\partial F_i^k / \\partial x_j^\\ell = 0`.\n\nShort Circuit Operations\n========================\nFor the :ref:`atomic_three_reverse@Base` prototype, if\n``IdenticalZero`` ( *partial_y* [ *i* * ( *q* +1)+ *k* ]) is true,\none does not need to compute :math:`( \\partial F_i^k / \\partial x_j^\\ell )`;\nsee :ref:`base_identical-name` .\nThis can be used,\nin a similar way to :ref:`atomic_three_forward@need_y` ,\nto avoid unnecessary operations.\n\nazmul\n=====\nAn :ref:`optimized<optimize-name>` function will use zero\nfor values in *taylor_x* and *taylor_y* that are\nnot necessary in the current context.\nIf you divide by these values when computing\n:math:`( \\partial F_i^k / \\partial x_j^\\ell )` you could get an nan\nif the corresponding value in *partial_y* is zero.\nTo be careful, if you do divide by\n*taylor_x* or *taylor_y* , use :ref:`azmul-name`\nfor to avoid zero over zero calculations.\n\napartial_x\n**********\nThe specifications for *apartial_x* is the same as for\n*partial_x* (only the type of *apartial_x* is different).\n\nok\n**\nIf this calculation succeeded, *ok* is true.\nOtherwise it is false.\n{xrst_toc_hidden\n    example/atomic_three/reverse.cpp\n}\nExamples\n********\nThe file :ref:`atomic_three_reverse.cpp-name` contains an example and test\nthat uses this routine.\n\n{xrst_end atomic_three_reverse}\n-----------------------------------------------------------------------------\n*/\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\n\\file atomic/three_reverse.hpp\nThird Generation Atomic reverse mode.\n*/\n/*!\nLink from reverse mode sweep to users routine.\n\n\\param parameter_x [in]\ncontains the values, in afun(ax, ay), for arguments that are parameters.\n\n\\param type_x [in]\nwhat is the type, in afun(ax, ay), for each component of x.\n\n\\param order_up [in]\nhighest order for this reverse mode calculation.\n\n\\param taylor_x [in]\nTaylor coefficients corresponding to x for this calculation.\n\n\\param taylor_y [in]\nTaylor coefficient corresponding to y for this calculation\n\n\\param partial_x [out]\nPartials w.r.t. the x Taylor coefficients.\n\n\\param partial_y [in]\nPartials w.r.t. the y Taylor coefficients.\n\nSee atomic_three_reverse mode use documentation\n*/\n// BEGIN_PROTOTYPE_BASE\ntemplate <class Base>\nbool atomic_three<Base>::reverse(\n    const vector<Base>&         parameter_x ,\n    const vector<ad_type_enum>& type_x      ,\n    size_t                      order_up    ,\n    const vector<Base>&         taylor_x    ,\n    const vector<Base>&         taylor_y    ,\n    vector<Base>&               partial_x   ,\n    const vector<Base>&         partial_y   )\n// END_PROTOTYPE_BASE\n{   return false; }\n\n/*!\nLink from reverse mode sweep to users routine.\n\n\\param aparameter_x [in]\ncontains the values, in afun(ax, ay), for arguments that are parameters.\n\n\\param type_x [in]\nwhat is the type, in afun(ax, ay), for each component of x.\n\n\n\\param order_up [in]\nhighest order for this reverse mode calculation.\n\n\\param ataylor_x [in]\nTaylor coefficients corresponding to x for this calculation.\n\n\\param ataylor_y [in]\nTaylor coefficient corresponding to y for this calculation\n\n\\param apartial_x [out]\nPartials w.r.t. the x Taylor coefficients.\n\n\\param apartial_y [in]\nPartials w.r.t. the y Taylor coefficients.\n\nSee atomic_three_reverse mode use documentation\n*/\n// BEGIN_PROTOTYPE_AD_BASE\ntemplate <class Base>\nbool atomic_three<Base>::reverse(\n    const vector< AD<Base> >&       aparameter_x ,\n    const vector<ad_type_enum>&     type_x       ,\n    size_t                          order_up     ,\n    const vector< AD<Base> >&       ataylor_x    ,\n    const vector< AD<Base> >&       ataylor_y    ,\n    vector< AD<Base> >&             apartial_x   ,\n    const vector< AD<Base> >&       apartial_y   )\n// END_PROTOTYPE_AD_BASE\n{   return false; }\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/atomic/two/afun.hpp",
    "content": "# ifndef CPPAD_CORE_ATOMIC_TWO_AFUN_HPP\n# define CPPAD_CORE_ATOMIC_TWO_AFUN_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_two_afun app}\n\nUsing AD Version of Atomic Function\n###################################\n\nSyntax\n******\n| *afun* ( *ax* , *ay* )\n\nPurpose\n*******\nGiven *ax* ,\nthis call computes the corresponding value of *ay* .\nIf ``AD`` < *Base* > operations are being recorded,\nit enters the computation as an atomic operation in the recording;\nsee :ref:`Independent@Start Recording` .\n\nADVector\n********\nThe type *ADVector* must be a\n:ref:`simple vector class<SimpleVector-name>` with elements of type\n``AD`` < *Base* > ; see :ref:`atomic_two_ctor@atomic_base@Base` .\n\nafun\n****\nis a :ref:`atomic_two_ctor@atomic_user` object\nand this *afun* function call is implemented by the\n:ref:`atomic<atomic_two_ctor@atomic_base>` class.\n\nax\n**\nThis argument has prototype\n\n    ``const`` *ADVector* & *ax*\n\nand size must be equal to *n* .\nIt specifies vector :math:`x \\in \\B{R}^n`\nat which an ``AD`` < *Base* > version of\n:math:`y = f(x)` is to be evaluated; see\n:ref:`atomic_two_ctor@atomic_base@Base` .\n\nay\n**\nThis argument has prototype\n\n    *ADVector* & *ay*\n\nand size must be equal to *m* .\nThe input values of its elements\nare not specified (must not matter).\nUpon return, it is an ``AD`` < *Base* > version of\n:math:`y = f(x)`.\n\n{xrst_end atomic_two_afun}\n-----------------------------------------------------------------------------\n*/\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\n\\file atomic/two_afun.hpp\nImplement user call to an atomic_two function.\n*/\n\n/*!\nImplement the user call to afun(ax, ay) and atomic_one call to\nafun(ax, ay, id).\n\n\\tparam ADVector\nA simple vector class with elements of type <code>AD<Base></code>.\n\n\\param id\noptional extra information vector that is just passed through by CppAD,\nand used by atomic_one derived class (not other derived classes).\nThis is an extra parameter to the virtual callbacks for atomic_one;\nsee the set_old member function.\n\n\\param ax\nis the argument vector for this call,\n<tt>ax.size()</tt> determines the number of arguments.\n\n\\param ay\nis the result vector for this call,\n<tt>ay.size()</tt> determines the number of results.\n*/\ntemplate <class Base>\ntemplate <class ADVector>\nvoid atomic_base<Base>::operator()(\n    const ADVector&  ax     ,\n             ADVector&  ay     ,\n    size_t           id     )\n{   size_t i, j;\n    size_t n = ax.size();\n    size_t m = ay.size();\n# ifndef NDEBUG\n    bool ok;\n    std::string msg = \"atomic_base: \" + atomic_name() + \".eval: \";\n    if( (n == 0) || (m == 0) )\n    {   msg += \"ax.size() or ay.size() is zero\";\n        CPPAD_ASSERT_KNOWN(false, msg.c_str() );\n    }\n# endif\n    size_t thread = thread_alloc::thread_num();\n    allocate_work(thread);\n    vector <Base>& tx  = work_[thread]->tx;\n    vector <Base>& ty  = work_[thread]->ty;\n    vector <bool>& vx  = work_[thread]->vx;\n    vector <bool>& vy  = work_[thread]->vy;\n    //\n    if( vx.size() != n )\n    {   vx.resize(n);\n        tx.resize(n);\n    }\n    if( vy.size() != m )\n    {   vy.resize(m);\n        ty.resize(m);\n    }\n    //\n    // Determine tape corresponding to variables in ax\n    tape_id_t            tape_id  = 0;\n    local::ADTape<Base>* tape     = nullptr;\n    for(j = 0; j < n; j++)\n    {   tx[j]  = ax[j].value_;\n        vx[j]  = ! Constant( ax[j] );\n        if( vx[j] )\n        {\n            if( tape_id == 0 )\n            {   tape    = ax[j].tape_this();\n                tape_id = ax[j].tape_id_;\n                CPPAD_ASSERT_UNKNOWN( tape != nullptr );\n            }\n# ifndef NDEBUG\n            if( tape_id != ax[j].tape_id_ )\n            {   msg += atomic_name() +\n                \": ax contains variables from different threads.\";\n                CPPAD_ASSERT_KNOWN(false, msg.c_str());\n            }\n# endif\n        }\n    }\n    // Use zero order forward mode to compute values\n    size_t p = 0, q = 0;\n    set_old(id);\n# ifdef NDEBUG\n    forward(p, q, vx, vy, tx, ty);\n# else\n    ok = forward(p, q, vx, vy, tx, ty);\n    if( ! ok )\n    {   msg += atomic_name() + \": ok is false for \"\n            \"zero order forward mode calculation.\";\n        CPPAD_ASSERT_KNOWN(false, msg.c_str());\n    }\n# endif\n    bool record_operation = false;\n    for(i = 0; i < m; i++)\n    {\n        // pass back values\n        ay[i].value_ = ty[i];\n\n        // initialize entire vector parameters (not in tape)\n        ay[i].tape_id_ = 0;\n        ay[i].taddr_   = 0;\n\n        // we need to record this operation if\n        // any of the elements of ay are variables,\n        record_operation |= vy[i];\n    }\n# ifndef NDEBUG\n    if( record_operation & (tape == nullptr) )\n    {   msg +=\n        \"all elements of vx are false but vy contains a true element\";\n        CPPAD_ASSERT_KNOWN(false, msg.c_str() );\n    }\n# endif\n    // if tape is not null, ay is on the tape\n    if( record_operation )\n    {\n        // Operator that marks beginning of this atomic operation\n        CPPAD_ASSERT_UNKNOWN( local::NumRes(local::AFunOp) == 0 );\n        CPPAD_ASSERT_UNKNOWN( local::NumArg(local::AFunOp) == 4 );\n        CPPAD_ASSERT_KNOWN(\n            size_t( std::numeric_limits<addr_t>::max() ) >=\n            std::max( std::max( std::max(index_, id), n), m ),\n            \"atomic_base: cppad_tape_addr_type maximum not large enough\"\n        );\n        tape->Rec_.PutArg(addr_t(index_), addr_t(id), addr_t(n), addr_t(m));\n        tape->Rec_.PutOp(local::AFunOp);\n\n        // Now put n operators, one for each element of argument vector\n        CPPAD_ASSERT_UNKNOWN( local::NumRes(local::FunavOp) == 0 );\n        CPPAD_ASSERT_UNKNOWN( local::NumRes(local::FunapOp) == 0 );\n        CPPAD_ASSERT_UNKNOWN( local::NumArg(local::FunavOp) == 1 );\n        CPPAD_ASSERT_UNKNOWN( local::NumArg(local::FunapOp) == 1 );\n        for(j = 0; j < n; j++)\n        {   if( Variable(ax[j]) )\n            {   // information for an argument that is a variable\n                tape->Rec_.PutArg(ax[j].taddr_);\n                tape->Rec_.PutOp(local::FunavOp);\n            }\n            else\n            {   // information for an argument that is parameter\n                addr_t par = ax[j].taddr_;\n                if( ! Dynamic( ax[j] ) )\n                    par = tape->Rec_.put_con_par(ax[j].value_);\n                tape->Rec_.PutArg(par);\n                tape->Rec_.PutOp(local::FunapOp);\n            }\n        }\n\n        // Now put m operators, one for each element of result vector\n        CPPAD_ASSERT_UNKNOWN( local::NumArg(local::FunrpOp) == 1 );\n        CPPAD_ASSERT_UNKNOWN( local::NumRes(local::FunrpOp) == 0 );\n        CPPAD_ASSERT_UNKNOWN( local::NumArg(local::FunrvOp) == 0 );\n        CPPAD_ASSERT_UNKNOWN( local::NumRes(local::FunrvOp) == 1 );\n        for(i = 0; i < m; i++)\n        {   if( vy[i] )\n            {   ay[i].taddr_    = tape->Rec_.PutOp(local::FunrvOp);\n                ay[i].tape_id_  = tape_id;\n                ay[i].ad_type_  = variable_enum;\n            }\n            else\n            {   CPPAD_ASSERT_UNKNOWN( ! Dynamic( ay[i] ) );\n                addr_t par = tape->Rec_.put_con_par(ay[i].value_);\n                tape->Rec_.PutArg(par);\n                tape->Rec_.PutOp(local::FunrpOp);\n            }\n        }\n\n        // Put a duplicate AFunOp at end of AFunOp sequence\n        CPPAD_ASSERT_KNOWN(\n            size_t( std::numeric_limits<addr_t>::max() ) >=\n            std::max( std::max( std::max(index_, id), n), m ),\n            \"atomic_base: cppad_tape_addr_type maximum not large enough\"\n        );\n        tape->Rec_.PutArg(addr_t(index_), addr_t(id), addr_t(n), addr_t(m));\n        tape->Rec_.PutOp(local::AFunOp);\n    }\n    return;\n}\n\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/atomic/two/atomic.hpp",
    "content": "# ifndef CPPAD_CORE_ATOMIC_TWO_ATOMIC_HPP\n# define CPPAD_CORE_ATOMIC_TWO_ATOMIC_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_two app}\n{xrst_spell\n    ctor\n    px\n    py\n    tx\n    vx\n    vy\n}\n\nDefining Atomic Functions: Second Generation\n############################################\n\nDeprecated 2019-01-01\n*********************\nUsing the ``atomic_base`` class has been deprecated.\nUse :ref:`atomic_three-name` instead.\n\nSyntax\n******\n| *atomic_user* *afun* ( *ctor_arg_list* )\n| *afun* ( *ax* , *ay* )\n| *ok* = *afun* . ``forward`` ( *p* , *q* , *vx* , *vy* , *tx* , *ty* )\n| *ok* = *afun* . ``reverse`` ( *q* , *tx* , *ty* , *px* , *py* )\n| *ok* = *afun* . ``for_sparse_jac`` ( *q* , *r* , *s* , *x* )\n| *ok* = *afun* . ``rev_sparse_jac`` ( *q* , *r* , *s* , *x* )\n| *ok* = *afun* . ``for_sparse_hes`` ( *vx* , *r* , *s* , *h* , *x* )\n| *ok* = *afun* . ``rev_sparse_hes`` ( *vx* , *s* , *t* , *q* , *r* , *u* , *v* , *x* )\n| *atomic_base* < ``Base`` >:: *clear* ()\n\nSee Also\n********\n:ref:`checkpoint<chkpoint_one-name>`\n\nPurpose\n*******\n\nSpeed\n=====\nIn some cases, the user knows how to compute derivatives of a function\n\n.. math::\n\n    y = f(x) \\; {\\rm where} \\; f : \\B{R}^n \\rightarrow \\B{R}^m\n\nmore efficiently than by coding it using ``AD`` < *Base* >\n:ref:`atomic_base<glossary@Operation@Atomic>` operations\nand letting CppAD do the rest.\nIn this case ``atomic_base`` < ``Base`` > can use\nthe user code for :math:`f(x)`, and its derivatives,\nas ``AD`` < *Base* > atomic operations.\n\nReduce Memory\n=============\nIf the function :math:`f(x)` is used often,\nusing an atomic version of :math:`f(x)` remove the need for repeated\ncopies of the corresponding ``AD`` < *Base* > operations.\n\nVirtual Functions\n*****************\nUser defined derivatives are implemented by defining the\nfollowing virtual functions in the *atomic_base* class:\n:ref:`forward<atomic_two_forward-name>` ,\n:ref:`reverse<atomic_two_reverse-name>` ,\n:ref:`for_sparse_jac<atomic_two_for_sparse_jac-name>` ,\n:ref:`rev_sparse_jac<atomic_two_rev_sparse_jac-name>` , and\n:ref:`rev_sparse_hes<atomic_two_rev_sparse_hes-name>` .\nThese virtual functions have a default implementation\nthat returns *ok* == ``false`` .\nThe ``forward`` function,\nfor the case *q*  == 0 , must be implemented.\nOtherwise, only those functions\nrequired by the your calculations need to be implemented.\nFor example,\n*forward* for the case *q*  == 2 can just return\n*ok* == ``false`` unless you require\nforward mode calculation of second derivatives.\n\nExamples\n********\nSee :ref:`atomic_two_example-name` .\n\nContents\n********\n{xrst_toc_table\n    include/cppad/core/atomic/two/ctor.hpp\n    include/cppad/core/atomic/two/option.hpp\n    include/cppad/core/atomic/two/afun.hpp\n    include/cppad/core/atomic/two/forward.hpp\n    include/cppad/core/atomic/two/reverse.hpp\n    include/cppad/core/atomic/two/for_sparse_jac.hpp\n    include/cppad/core/atomic/two/rev_sparse_jac.hpp\n    include/cppad/core/atomic/two/for_sparse_hes.hpp\n    include/cppad/core/atomic/two/rev_sparse_hes.hpp\n    include/cppad/core/atomic/two/clear.hpp\n}\n\n{xrst_end atomic_two}\n-------------------------------------------------------------------------------\n{xrst_begin atomic_two_example app}\n\nExample Defining Atomic Functions: Second Generation\n####################################################\n\nGetting Started\n***************\nthat shows the minimal amount of information required to create\na user defined atomic operation.\n\nScalar Function\n***************\nwhere the user provides the code for computing derivatives.\nThis example is simple because the domain and range are scalars.\n\nVector Range\n************\nwhere the user provides the code for computing derivatives.\nThis example is more complex because the range has two components.\n\nHessian Sparsity Patterns\n*************************\nwhere the user provides the code for computing Hessian sparsity patterns.\n\nContents\n********\n{xrst_toc_table\n    example/atomic_two/eigen_mat_mul.cpp\n    example/atomic_two/eigen_mat_inv.cpp\n    example/atomic_two/eigen_cholesky.cpp\n}\n\n{xrst_end atomic_two_example}\n-------------------------------------------------------------------------------\n*/\n\n# include <set>\n# include <cppad/core/cppad_assert.hpp>\n# include <cppad/local/sparse/internal.hpp>\n# include <cppad/local/atomic_index.hpp>\n# include <cppad/core/ad.hpp>\n\n// needed before one can use in_parallel\n# include <cppad/utility/thread_alloc.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\n\\file atomic_two.hpp\nBase class for atomic function operations.\n*/\n\ntemplate <class Base>\nclass atomic_base {\n// ===================================================================\npublic:\n    enum option_enum {\n        pack_sparsity_enum   ,\n        bool_sparsity_enum   ,\n        set_sparsity_enum\n    };\n    //\n    // atomic_index\n    size_t atomic_index(void) const\n    { return index_; }\nprivate:\n    // ------------------------------------------------------\n    // constants\n    //\n    /// index of this object in local::atomic_index\n    /// (set by constructor and not changed; i.e., effectively const)\n    size_t index_;\n    //\n    // -----------------------------------------------------\n    // variables\n    //\n    /// sparsity pattern this object is currently using\n    /// (set by constructor and option member functions)\n    option_enum sparsity_;\n    //\n    /// temporary work space used by member functions, declared here to avoid\n    // memory allocation/deallocation for each usage\n    struct work_struct {\n        vector<bool>               vx;\n        vector<bool>               vy;\n        //\n        vector<Base>               tx;\n        vector<Base>               ty;\n        //\n        vector< AD<Base> >         atx;\n        vector< AD<Base> >         aty;\n        //\n        vector<bool>               bool_t;\n        //\n        vectorBool                 pack_h;\n        vectorBool                 pack_r;\n        vectorBool                 pack_s;\n        vectorBool                 pack_u;\n        //\n        vector<bool>               bool_h;\n        vector<bool>               bool_r;\n        vector<bool>               bool_s;\n        vector<bool>               bool_u;\n        //\n        vector< std::set<size_t> > set_h;\n        vector< std::set<size_t> > set_r;\n        vector< std::set<size_t> > set_s;\n        vector< std::set<size_t> > set_u;\n    };\n    // Use pointers, to avoid false sharing between threads.\n    // Not using: vector<work_struct*> work_;\n    // so that deprecated atomic examples do not result in a memory leak.\n    work_struct* work_[CPPAD_MAX_NUM_THREADS];\npublic:\n    // =====================================================================\n    // In User API\n    // =====================================================================\n    //\n    // ---------------------------------------------------------------------\n    // ctor: doxygen in atomic_base/ctor.hpp\n    atomic_base(void);\n    atomic_base(\n        const std::string&     name,\n        option_enum            sparsity = bool_sparsity_enum\n    );\n\n    // option: see doxygen in atomic_base/option.hpp\n    void option(enum option_enum option_value);\n\n    // operator(): see doxygen in atomic_base/afun.hpp\n    template <class ADVector>\n    void operator()(\n        const ADVector&  ax     ,\n                  ADVector&  ay     ,\n        size_t           id = 0\n    );\n\n    // ------------------------------------------------------------------------\n    // base_two version of forward\n    virtual bool forward(\n        size_t                    p  ,\n        size_t                    q  ,\n        const vector<bool>&       vx ,\n        vector<bool>&             vy ,\n        const vector<Base>&       tx ,\n        vector<Base>&             ty\n    );\n    virtual bool forward(\n        size_t                    p  ,\n        size_t                    q  ,\n        const vector<bool>&       vx ,\n        vector<bool>&             vy ,\n        const vector< AD<Base> >& atx ,\n        vector< AD<Base> >&       aty\n    );\n    // base_three version of forward\n    bool forward(\n        size_t                       order_low  ,\n        size_t                       order_up   ,\n        const vector<ad_type_enum>&  type_x     ,\n        vector<ad_type_enum>&        type_y     ,\n        const vector<Base>&          taylor_x   ,\n        vector<Base>&                taylor_y\n    );\n    bool forward(\n        size_t                       order_low  ,\n        size_t                       order_up   ,\n        const vector<ad_type_enum>&  type_x     ,\n        vector<ad_type_enum>&        type_y     ,\n        const vector< AD<Base> >&    ataylor_x  ,\n        vector< AD<Base> >&          ataylor_y\n    );\n    // ------------------------------------------------------------------------\n    // reverse: see doxygen in atomic_base/reverse.hpp\n    virtual bool reverse(\n        size_t                    q  ,\n        const vector<Base>&       tx ,\n        const vector<Base>&       ty ,\n                  vector<Base>&       px ,\n        const vector<Base>&       py\n    );\n    virtual bool reverse(\n        size_t                    q   ,\n        const vector< AD<Base> >& atx ,\n        const vector< AD<Base> >& aty ,\n                  vector< AD<Base> >& apx ,\n        const vector< AD<Base> >& apy\n    );\n\n    // ------------------------------------------------------------\n    // for_sparse_jac: see doxygen in atomic_base/for_sparse_jac.hpp\n    virtual bool for_sparse_jac(\n        size_t                                  q  ,\n        const vector< std::set<size_t> >&       r  ,\n                  vector< std::set<size_t> >&       s  ,\n        const vector<Base>&                     x\n    );\n    virtual bool for_sparse_jac(\n        size_t                                  q  ,\n        const vector<bool>&                     r  ,\n                  vector<bool>&                     s  ,\n        const vector<Base>&                     x\n    );\n    virtual bool for_sparse_jac(\n        size_t                                  q  ,\n        const vectorBool&                       r  ,\n                  vectorBool&                       s  ,\n        const vector<Base>&                     x\n    );\n    template <class InternalSparsity>\n    bool for_sparse_jac(\n        const vector<Base>&              x            ,\n        const vector<size_t>&            x_index      ,\n        const vector<size_t>&            y_index      ,\n        InternalSparsity&                var_sparsity\n    );\n    // deprecated versions\n    virtual bool for_sparse_jac(\n        size_t                                  q  ,\n        const vector< std::set<size_t> >&       r  ,\n                  vector< std::set<size_t> >&       s\n    );\n    virtual bool for_sparse_jac(\n        size_t                                  q  ,\n        const vector<bool>&                     r  ,\n                  vector<bool>&                     s\n    );\n    virtual bool for_sparse_jac(\n        size_t                                  q  ,\n        const vectorBool&                       r  ,\n                  vectorBool&                       s\n    );\n    // ------------------------------------------------------------\n    // rev_sparse_jac: see doxygen in atomic_base/rev_sparse_jac.hpp\n    virtual bool rev_sparse_jac(\n        size_t                                  q  ,\n        const vector< std::set<size_t> >&       rt ,\n                  vector< std::set<size_t> >&       st ,\n        const vector<Base>&                     x\n    );\n    virtual bool rev_sparse_jac(\n        size_t                                  q  ,\n        const vector<bool>&                     rt ,\n                  vector<bool>&                     st ,\n        const vector<Base>&                     x\n    );\n    virtual bool rev_sparse_jac(\n        size_t                                  q  ,\n        const vectorBool&                       rt ,\n                  vectorBool&                       st ,\n        const vector<Base>&                     x\n    );\n    template <class InternalSparsity>\n    bool rev_sparse_jac(\n        const vector<Base>&        x            ,\n        const vector<size_t>&            x_index ,\n        const vector<size_t>&            y_index ,\n        InternalSparsity&          var_sparsity\n    );\n    // deprecated versions\n    virtual bool rev_sparse_jac(\n        size_t                                  q  ,\n        const vector< std::set<size_t> >&       rt ,\n                  vector< std::set<size_t> >&       st\n    );\n    virtual bool rev_sparse_jac(\n        size_t                                  q  ,\n        const vector<bool>&                     rt ,\n                  vector<bool>&                     st\n    );\n    virtual bool rev_sparse_jac(\n        size_t                                  q  ,\n        const vectorBool&                       rt ,\n                  vectorBool&                       st\n    );\n    // ------------------------------------------------------------\n    // for_sparse_hes: see doxygen in atomic_base/for_sparse_hes.hpp\n    virtual bool for_sparse_hes(\n        const vector<bool>&             vx ,\n        const vector<bool>&             r  ,\n        const vector<bool>&             s  ,\n        vector< std::set<size_t> >&     h  ,\n        const vector<Base>&             x\n    );\n    virtual bool for_sparse_hes(\n        const vector<bool>&             vx ,\n        const vector<bool>&             r  ,\n        const vector<bool>&             s  ,\n        vector<bool>&                   h  ,\n        const vector<Base>&             x\n    );\n    virtual bool for_sparse_hes(\n        const vector<bool>&             vx ,\n        const vector<bool>&             r  ,\n        const vector<bool>&             s  ,\n        vectorBool&                     h  ,\n        const vector<Base>&             x\n    );\n    template <class InternalSparsity>\n    bool for_sparse_hes(\n        const vector<Base>&              x                ,\n        const vector<size_t>&            x_index          ,\n        const vector<size_t>&            y_index          ,\n        size_t                           np1              ,\n        size_t                           numvar           ,\n        const InternalSparsity&          rev_jac_sparsity ,\n        InternalSparsity&                for_sparsity\n    );\n    // deprecated versions\n    virtual bool for_sparse_hes(\n        const vector<bool>&             vx ,\n        const vector<bool>&             r  ,\n        const vector<bool>&             s  ,\n        vector< std::set<size_t> >&     h\n    );\n    virtual bool for_sparse_hes(\n        const vector<bool>&             vx ,\n        const vector<bool>&             r  ,\n        const vector<bool>&             s  ,\n        vector<bool>&                   h\n    );\n    virtual bool for_sparse_hes(\n        const vector<bool>&             vx ,\n        const vector<bool>&             r  ,\n        const vector<bool>&             s  ,\n        vectorBool&                     h\n    );\n    // ------------------------------------------------------------\n    // rev_sparse_hes: see doxygen in atomic_base/rev_sparse_hes.hpp\n    virtual bool rev_sparse_hes(\n        const vector<bool>&                     vx ,\n        const vector<bool>&                     s  ,\n                  vector<bool>&                     t  ,\n        size_t                                  q  ,\n        const vector< std::set<size_t> >&       r  ,\n        const vector< std::set<size_t> >&       u  ,\n                  vector< std::set<size_t> >&       v  ,\n        const vector<Base>&                     x\n    );\n    virtual bool rev_sparse_hes(\n        const vector<bool>&                     vx ,\n        const vector<bool>&                     s  ,\n                  vector<bool>&                     t  ,\n        size_t                                  q  ,\n        const vector<bool>&                     r  ,\n        const vector<bool>&                     u  ,\n                  vector<bool>&                     v  ,\n        const vector<Base>&                     x\n    );\n    virtual bool rev_sparse_hes(\n        const vector<bool>&                     vx ,\n        const vector<bool>&                     s  ,\n                  vector<bool>&                     t  ,\n        size_t                                  q  ,\n        const vectorBool&                       r  ,\n        const vectorBool&                       u  ,\n                  vectorBool&                       v  ,\n        const vector<Base>&                     x\n    );\n    template <class InternalSparsity>\n    bool rev_sparse_hes(\n        const vector<Base>&              x                ,\n        const vector<size_t>&            x_index          ,\n        const vector<size_t>&            y_index          ,\n        const InternalSparsity&          for_jac_sparsity ,\n        bool*                            rev_jac_flag     ,\n        InternalSparsity&                rev_hes_sparsity\n    );\n    // deprecated\n    virtual bool rev_sparse_hes(\n        const vector<bool>&                     vx ,\n        const vector<bool>&                     s  ,\n                  vector<bool>&                     t  ,\n        size_t                                  q  ,\n        const vector< std::set<size_t> >&       r  ,\n        const vector< std::set<size_t> >&       u  ,\n                  vector< std::set<size_t> >&       v\n    );\n    virtual bool rev_sparse_hes(\n        const vector<bool>&                     vx ,\n        const vector<bool>&                     s  ,\n                  vector<bool>&                     t  ,\n        size_t                                  q  ,\n        const vector<bool>&                     r  ,\n        const vector<bool>&                     u  ,\n                  vector<bool>&                     v\n    );\n    virtual bool rev_sparse_hes(\n        const vector<bool>&                     vx ,\n        const vector<bool>&                     s  ,\n                  vector<bool>&                     t  ,\n        size_t                                  q  ,\n        const vectorBool&                       r  ,\n        const vectorBool&                       u  ,\n                  vectorBool&                       v\n    );\n    // ------------------------------------------------------------\n    // atomic_three like interface for reverse dependency analysis\n    bool rev_depend(\n        const vector<Base>&         parameter_x ,\n        const vector<ad_type_enum>& type_x      ,\n        vector<bool>&               depend_x    ,\n        const vector<bool>&         depend_y\n    );\n    // ------------------------------------------------------------\n    // clear: see doxygen in atomic_base/clear.hpp\n    static void clear(void);\n\n    // =====================================================================\n    // Not in User API\n    // =====================================================================\n\n    /// current sparsity setting\n    option_enum sparsity(void) const\n    {   return sparsity_; }\n\n    /// Name corresponding to a atomic_base object\n    const std::string atomic_name(void) const\n    {   bool        set_null = false;\n        size_t      type  = 0;          // set to avoid warning\n        std::string name;\n        void*       v_ptr = nullptr; // set to avoid warning\n        local::atomic_index<Base>(set_null, index_, type, &name, v_ptr);\n        CPPAD_ASSERT_UNKNOWN( type == 2 );\n        return name;\n    }\n    /// destructor informs CppAD that this atomic function with this index\n    /// has dropped out of scope by setting its pointer to null\n    virtual ~atomic_base(void)\n    {   // change object pointer to null, but leave name for error reporting\n        bool         set_null = true;\n        size_t       type  = 0;          // set to avoid warning\n        std::string* name  = nullptr;\n        void*        v_ptr = nullptr; // set to avoid warning\n        local::atomic_index<Base>(set_null, index_, type, name, v_ptr);\n        CPPAD_ASSERT_UNKNOWN( type == 2 );\n        //\n        // free temporary work memory\n        for(size_t thread = 0; thread < CPPAD_MAX_NUM_THREADS; thread++)\n            free_work(thread);\n    }\n    /// allocates work_ for a specified thread\n    void allocate_work(size_t thread)\n    {   if( work_[thread] == nullptr )\n        {   // allocate the raw memory\n            size_t min_bytes = sizeof(work_struct);\n            size_t num_bytes;\n            void*  v_ptr     = thread_alloc::get_memory(min_bytes, num_bytes);\n            // save in work_\n            work_[thread]    = reinterpret_cast<work_struct*>( v_ptr );\n            // call constructor\n            new( work_[thread] ) work_struct;\n        }\n        return;\n    }\n    /// frees work_ for a specified thread\n    void free_work(size_t thread)\n    {   if( work_[thread] != nullptr )\n        {   // call destructor\n            work_[thread]->~work_struct();\n            // return memory to available pool for this thread\n            thread_alloc::return_memory(\n                reinterpret_cast<void*>(work_[thread])\n            );\n            // mark this thread as not allocated\n            work_[thread] = nullptr;\n        }\n        return;\n    }\n    /// atomic_base function object corresponding to a certain index\n    static atomic_base* class_object(size_t index)\n    {   bool         set_null = false;\n        size_t       type  = 0;          // set to avoid warning\n        std::string* name  = nullptr;\n        void*        v_ptr = nullptr; // set to avoid warning\n        local::atomic_index<Base>(set_null, index, type, name, v_ptr);\n        CPPAD_ASSERT_UNKNOWN( type == 2 );\n        return reinterpret_cast<atomic_base*>( v_ptr );\n    }\n    /// atomic_base function name corresponding to a certain index\n    static const std::string class_name(size_t index)\n    {   bool        set_null = false;\n        size_t      type  = 0;          // set to avoid warning\n        std::string name;\n        void*       v_ptr = nullptr; // set to avoid warning\n        local::atomic_index<Base>(set_null, index, type, &name, v_ptr);\n        CPPAD_ASSERT_UNKNOWN( type == 2 );\n        return name;\n    }\n\n    /*!\n    Set value of id (used by deprecated atomic_one class)\n\n    This function is called just before calling any of the virtual function\n    and has the corresponding id of the corresponding virtual call.\n    */\n    virtual void set_old(size_t id)\n    { }\n// ---------------------------------------------------------------------------\n};\n} // END_CPPAD_NAMESPACE\n\n// functions implemented in cppad/core/atomic_base files\n# include <cppad/core/atomic/two/ctor.hpp>\n# include <cppad/core/atomic/two/option.hpp>\n# include <cppad/core/atomic/two/afun.hpp>\n# include <cppad/core/atomic/two/forward.hpp>\n# include <cppad/core/atomic/two/reverse.hpp>\n# include <cppad/core/atomic/two/for_sparse_jac.hpp>\n# include <cppad/core/atomic/two/rev_sparse_jac.hpp>\n# include <cppad/core/atomic/two/for_sparse_hes.hpp>\n# include <cppad/core/atomic/two/rev_sparse_hes.hpp>\n# include <cppad/core/atomic/two/rev_depend.hpp>\n# include <cppad/core/atomic/two/clear.hpp>\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/atomic/two/clear.hpp",
    "content": "# ifndef CPPAD_CORE_ATOMIC_TWO_CLEAR_HPP\n# define CPPAD_CORE_ATOMIC_TWO_CLEAR_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_two_clear app}\n\nFree Static Variables\n#####################\n\nSyntax\n******\n| ``atomic_base`` < *Base* >:: ``clear`` ()\n\nPurpose\n*******\nEach ``atomic_base`` objects holds onto work space in order to\navoid repeated memory allocation calls and thereby increase speed\n(until it is deleted).\nIf an the ``atomic_base`` object is global or static because,\nthe it does not get deleted.\nThis is a problem when using\n``thread_alloc`` :ref:`free_all<ta_free_all-name>`\nto check that all allocated memory has been freed.\nCalling this ``clear`` function will free all the\nmemory currently being held onto by the\n``atomic_base`` < *Base* > class.\n\nFuture Use\n**********\nIf there is future use of an ``atomic_base`` object,\nafter a call to ``clear`` ,\nthe work space will be reallocated and held onto.\n\nRestriction\n***********\nThis routine cannot be called\nwhile in :ref:`parallel<ta_in_parallel-name>` execution mode.\n\n{xrst_end atomic_two_clear}\n------------------------------------------------------------------------------\n*/\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\n\\file atomic/two_clear.hpp\nFree static variables in atomic_base class.\n*/\n/*!\nFree all thread_alloc static memory held by atomic_base (avoids reallocations).\n(This does not include class_object() which is an std::vector.)\n*/\ntemplate <class Base>\nvoid atomic_base<Base>::clear(void)\n{   CPPAD_ASSERT_KNOWN(\n        ! thread_alloc::in_parallel() ,\n        \"cannot use atomic_base clear during parallel execution\"\n    );\n    bool         set_null = true;\n    size_t       index  = 0;\n    size_t       type  = 0;          // set to avoid warning\n    std::string* name  = nullptr;\n    void*        v_ptr = nullptr; // set to avoid warning\n    size_t       n_atomic = local::atomic_index<Base>(\n        set_null, index, type, name, v_ptr\n    );\n    //\n    set_null = false;\n    for(index = 1; index <= n_atomic; ++index)\n    {   local::atomic_index<Base>(set_null, index, type, name, v_ptr);\n        if( type == 2 )\n        {   atomic_base* op = reinterpret_cast<atomic_base*>(v_ptr);\n            if( op != nullptr )\n            {   for(size_t thread = 0; thread < CPPAD_MAX_NUM_THREADS; thread++)\n                    op->free_work(thread);\n            }\n        }\n    }\n    return;\n}\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/atomic/two/ctor.hpp",
    "content": "# ifndef CPPAD_CORE_ATOMIC_TWO_CTOR_HPP\n# define CPPAD_CORE_ATOMIC_TWO_CTOR_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_two_ctor app}\n\nAtomic Function Constructor\n###########################\n\nSyntax\n******\n| *atomic_user afun* ( *ctor_arg_list* )\n| ``atomic_base`` < *Base* >( *name* , *sparsity* )\n\natomic_user\n***********\n\nctor_arg_list\n=============\nIs a list of arguments for the *atomic_user* constructor.\n\nafun\n====\nThe object *afun* must stay in scope for as long\nas the corresponding atomic function is used.\nThis includes use by any :ref:`ADFun\\<Base><ADFun-name>` that\nhas this *atomic_user* operation in its\n:ref:`operation sequence<glossary@Operation@Sequence>` .\n\nImplementation\n==============\nThe user defined *atomic_user* class is a publicly derived class of\n``atomic_base`` < *Base* > .\nIt should be declared as follows:\n\n| |tab| ``class`` *atomic_user* : ``public CppAD::atomic_base<`` *Base* > {\n| |tab| ``public:``\n| |tab| |tab| *atomic_user* ( *ctor_arg_list* ) : ``atomic_base`` < *Base* >( *name* , *sparsity* )\n| |tab| ...\n| |tab| };\n\nwhere ...\ndenotes the rest of the implementation of the derived class.\nThis includes completing the constructor and\nall the virtual functions that have their\n``atomic_base`` implementations replaced by\n*atomic_user* implementations.\n\natomic_base\n***********\n\nRestrictions\n============\nThe ``atomic_base`` constructor and destructor cannot be called in\n:ref:`parallel<ta_in_parallel-name>` mode.\n\nBase\n====\nThe template parameter determines the\n*Base* type for this ``AD`` < *Base* > atomic operation.\n\nname\n====\nThis ``atomic_base`` constructor argument has the following prototype\n\n    ``const std::string&`` *name*\n\nIt is the name for this atomic function and is used for error reporting.\nThe suggested value for *name* is *afun* or *atomic_user* ,\ni.e., the name of the corresponding atomic object or class.\n\nsparsity\n========\nThis ``atomic_base`` constructor argument has prototype\n\n    ``atomic_base`` < *Base* >:: ``option_enum`` *sparsity*\n\nThe current *sparsity* for an ``atomic_base`` object\ndetermines which type of sparsity patterns it uses\nand its value is one of the following:\n\n.. list-table::\n    :widths: auto\n\n    * - *sparsity*\n      - sparsity patterns\n    * - ``atomic_base`` < *Base* >:: ``pack_sparsity_enum``\n      - :ref:`CppAD_vector@vectorBool`\n    * - ``atomic_base`` < *Base* >:: ``bool_sparsity_enum``\n      - :ref:`vector<CppAD_vector-name>` ``<bool>``\n    * - ``atomic_base`` < *Base* >:: ``set_sparsity_enum``\n      - :ref:`vector<CppAD_vector-name>` ``<std::set<std::size_t> >``\n\nThere is a default value for *sparsity* if it is not\nincluded in the constructor (which may be either the bool or set option).\n\n{xrst_end atomic_two_ctor}\n-------------------------------------------------------------------------------\n*/\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\n\\file atomic/two_ctor.hpp\nConstructors for atomic_base class.\n*/\n\n/*!\nBase class for atomic_atomic functions.\n\n\\tparam Base\nThis class is used for defining an AD<Base> atomic operation y = f(x).\n\n\\par\nmake sure user does not invoke the default constructor\n*/\ntemplate <class Base>\natomic_base<Base>::atomic_base(void)\n{   CPPAD_ASSERT_KNOWN(false,\n        \"Attempt to use the atomic_base default constructor\"\n    );\n}\n/*!\nConstructor\n\n\\param name\nname used for error reporting\n\n\\param sparsity [in]\nwhat type of sparsity patterns are computed by this function,\nbool_sparsity_enum or set_sparsity_enum. Default value is\nbool sparsity patterns.\n*/\ntemplate <class Base>\natomic_base<Base>::atomic_base(\n        const std::string&     name,\n        option_enum            sparsity\n) :\nsparsity_( sparsity               )\n{   CPPAD_ASSERT_KNOWN(\n        ! thread_alloc::in_parallel() ,\n        \"atomic_base: constructor cannot be called in parallel mode.\"\n    );\n    CPPAD_ASSERT_UNKNOWN( constant_enum < dynamic_enum );\n    CPPAD_ASSERT_UNKNOWN( dynamic_enum < variable_enum );\n    //\n    // atomic_index\n    bool        set_null  = false;\n    size_t      index     = 0;\n    size_t      type      = 2;\n    std::string copy_name = name;\n    void*       copy_this = reinterpret_cast<void*>( this );\n    index_  = local::atomic_index<Base>(\n        set_null, index, type, &copy_name, copy_this\n    );\n    // initialize work pointers as null;\n    for(size_t thread = 0; thread < CPPAD_MAX_NUM_THREADS; thread++)\n        work_[thread] = nullptr;\n}\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/atomic/two/for_sparse_hes.hpp",
    "content": "# ifndef CPPAD_CORE_ATOMIC_TWO_FOR_SPARSE_HES_HPP\n# define CPPAD_CORE_ATOMIC_TWO_FOR_SPARSE_HES_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_two_for_sparse_hes app}\n{xrst_spell\n    vx\n}\n\nAtomic Forward Hessian Sparsity Patterns\n########################################\n\nSyntax\n******\n| *ok* = *afun* . ``for_sparse_hes`` ( *vx* , *r* , *s* , *h* , *x* )\n\nDeprecated 2016-06-27\n*********************\n*ok* = *afun* . ``for_sparse_hes`` ( *vx* , *r* , *s* , *h* )\n\nPurpose\n*******\nThis function is used by :ref:`ForSparseHes-name` to compute\nHessian sparsity patterns.\nIf you are using :ref:`ForSparseHes-name` ,\none of the versions of this\nvirtual function must be defined by the\n:ref:`atomic_two_ctor@atomic_user` class.\n\nGiven a :ref:`glossary@Sparsity Pattern` for\na diagonal matrix :math:`R \\in \\B{R}^{n \\times n}`, and\na row vector :math:`S \\in \\B{R}^{1 \\times m}`,\nthis routine computes the sparsity pattern for\n\n.. math::\n\n    H(x) = R^\\R{T} \\cdot (S \\cdot f)^{(2)}( x ) \\cdot R\n\nImplementation\n**************\nIf you are using and :ref:`ForSparseHes-name` ,\nthis virtual function must be defined by the\n:ref:`atomic_two_ctor@atomic_user` class.\n\nvx\n==\nThe argument *vx* has prototype\n\n    ``const CppAD:vector<bool>&`` *vx*\n\n*vx* . ``size`` () == *n* , and\nfor :math:`j = 0 , \\ldots , n-1`,\n*vx* [ *j* ] is true if and only if\n*ax* [ *j* ] is a :ref:`glossary@Variable`\nor :ref:`dynamic parameter<glossary@Parameter@Dynamic>`\nin the corresponding call to\n\n    *afun* ( *ax* , *ay* )\n\nr\n=\nThis argument has prototype\n\n    ``const CppAD:vector<bool>&`` *r*\n\nand is a :ref:`atomic_two_option@atomic_sparsity` pattern for\nthe diagonal of :math:`R \\in \\B{R}^{n \\times n}`.\n\ns\n=\nThe argument *s* has prototype\n\n    ``const CppAD:vector<bool>&`` *s*\n\nand its size is *m* .\nIt is a sparsity pattern for :math:`S \\in \\B{R}^{1 \\times m}`.\n\nh\n=\nThis argument has prototype\n\n    *atomic_sparsity* & *h*\n\nThe input value of its elements\nare not specified (must not matter).\nUpon return, *h* is a\n:ref:`atomic_two_option@atomic_sparsity` pattern for\n:math:`H(x) \\in \\B{R}^{n \\times n}` which is defined above.\n\nx\n=\nThe argument has prototype\n\n    ``const CppAD::vector<`` *Base* >& *x*\n\nand size is equal to the *n* .\nThis is the :ref:`Value-name`  corresponding to the parameters in the\nvector :ref:`atomic_two_afun@ax` (when the atomic function was called).\nTo be specific, if\n\n| |tab| ``if`` ( ``Parameter`` ( *ax* [ *i* ]) == ``true`` )\n| |tab| |tab| *x* [ *i* ] = ``Value`` ( *ax* [ *i* ] );\n| |tab| ``else``\n| |tab| |tab| *x* [ *i* ] = ``CppAD::numeric_limits<`` *Base* >:: ``quiet_NaN`` ();\n\nThe version of this function with out the *x* argument is deprecated;\ni.e., you should include the argument even if you do not use it.\n\n{xrst_end atomic_two_for_sparse_hes}\n-----------------------------------------------------------------------------\n*/\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\n\\file atomic/two_for_sparse_hes.hpp\nAtomic forward mode Hessian sparsity patterns.\n*/\n/*!\nLink, after case split, from for_hes_sweep to atomic_base.\n\n\\param vx [in]\nwhich components of x are variables.\n\n\\param r [in]\nis the forward Jacobian sparsity pattern w.r.t the argument vector x.\n\n\\param s [in]\nis the reverse Jacobian sparsity pattern w.r.t the result vector y.\n\n\\param h [out]\nis the Hessian sparsity pattern w.r.t the argument vector x.\n\n\\param x\nis the integer value of the x arguments that are parameters.\n*/\ntemplate <class Base>\nbool atomic_base<Base>::for_sparse_hes(\n    const vector<bool>&             vx ,\n    const vector<bool>&             r  ,\n    const vector<bool>&             s  ,\n    vector< std::set<size_t> >&     h  ,\n    const vector<Base>&             x  )\n{   return false; }\ntemplate <class Base>\nbool atomic_base<Base>::for_sparse_hes(\n    const vector<bool>&             vx ,\n    const vector<bool>&             r  ,\n    const vector<bool>&             s  ,\n    vector<bool>&                   h  ,\n    const vector<Base>&             x  )\n{   return false; }\ntemplate <class Base>\nbool atomic_base<Base>::for_sparse_hes(\n    const vector<bool>&             vx ,\n    const vector<bool>&             r  ,\n    const vector<bool>&             s  ,\n    vectorBool&                     h  ,\n    const vector<Base>&             x  )\n// deprecated versions\n{   return false; }\ntemplate <class Base>\nbool atomic_base<Base>::for_sparse_hes(\n    const vector<bool>&             vx ,\n    const vector<bool>&             r  ,\n    const vector<bool>&             s  ,\n    vector< std::set<size_t> >&     h  )\n{   return false; }\ntemplate <class Base>\nbool atomic_base<Base>::for_sparse_hes(\n    const vector<bool>&             vx ,\n    const vector<bool>&             r  ,\n    const vector<bool>&             s  ,\n    vector<bool>&                   h  )\n{   return false; }\ntemplate <class Base>\nbool atomic_base<Base>::for_sparse_hes(\n    const vector<bool>&             vx ,\n    const vector<bool>&             r  ,\n    const vector<bool>&             s  ,\n    vectorBool&                     h  )\n{   return false; }\n/*!\nLink, before case split, from for_hes_sweep to atomic_base.\n2DO: move this function outside this file so can change\ndeveloper documentation to omhelp formatting.\n\n\\tparam InternalSparsity\nIs the used internally for sparsity calculations; i.e.,\nsparse_pack or sparse_list.\n\n\\param x\nis parameter arguments to the function, other components are nan.\n\n\\param x_index\nis the variable index, on the tape, for the arguments to this function.\nThis size of x_index is n, the number of arguments to this function.\n\n\\param y_index\nis the variable index, on the tape, for the results for this function.\nThis size of y_index is m, the number of results for this function.\n\n\\param for_jac_sparsity\nOn input, for j = 0, ... , n-1, the sparsity pattern with index x_index[j],\nis the forward Jacobian sparsity for the j-th argument to this atomic function.\n\n\\param rev_jac_sparsity\nOn input, for i = 0, ... , m-1, the sparsity pattern with index y_index[i],\nis the reverse Jacobian sparsity for the i-th result to this atomic function.\nThis shows which components of the result affect the function we are\ncomputing the Hessian of.\n\n\\param for_hes_sparsity\nThis is the sparsity pattern for the Hessian. On input, the non-linear\nterms in the atomic function have not been included. Upon return, they\nhave been included.\n*/\ntemplate <class Base>\ntemplate <class InternalSparsity>\nbool atomic_base<Base>::for_sparse_hes(\n    const vector<Base>&              x                ,\n    const vector<size_t>&            x_index          ,\n    const vector<size_t>&            y_index          ,\n    size_t                           np1              ,\n    size_t                           numvar           ,\n    const InternalSparsity&          rev_jac_sparsity ,\n    InternalSparsity&                for_sparsity     )\n{   typedef typename InternalSparsity::const_iterator const_iterator;\n    CPPAD_ASSERT_UNKNOWN( rev_jac_sparsity.end() == 1 );\n    CPPAD_ASSERT_UNKNOWN( for_sparsity.end() == np1 );\n    CPPAD_ASSERT_UNKNOWN( for_sparsity.n_set() == np1 + numvar );\n    size_t n      = x_index.size();\n    size_t m      = y_index.size();\n    bool   ok     = false;\n    size_t thread = thread_alloc::thread_num();\n    allocate_work(thread);\n    //\n    // vx\n    vector<bool> vx(n);\n    for(size_t j = 0; j < n; j++)\n        vx[j] = x_index[j] != 0;\n    //\n    // bool_r\n    vector<bool>& bool_r( work_[thread]->bool_r );\n    bool_r.resize(n);\n    for(size_t j = 0; j < n; j++)\n    {   // check if we must compute row and column j of h\n        const_iterator itr(for_sparsity, np1 + x_index[j]);\n        size_t i = *itr;\n        bool_r[j] = i < np1;\n    }\n    //\n    // bool s\n    vector<bool>& bool_s( work_[thread]->bool_s );\n    bool_s.resize(m);\n    for(size_t i = 0; i < m; i++)\n    {   // check if row i of result is included in h\n        bool_s[i] = rev_jac_sparsity.is_element(y_index[i], 0);\n    }\n    //\n    // h\n    vectorBool&                 pack_h( work_[thread]->pack_h );\n    vector<bool>&               bool_h( work_[thread]->bool_h );\n    vector< std::set<size_t> >& set_h(  work_[thread]->set_h );\n    //\n    // call user's version of atomic function\n    std::string msg    = \": atomic_base.for_sparse_hes: returned false\";\n    if( sparsity_ == pack_sparsity_enum )\n    {   pack_h.resize(n * n);\n        ok = for_sparse_hes(vx, bool_r, bool_s, pack_h, x);\n        if( ! ok )\n            ok = for_sparse_hes(vx, bool_r, bool_s, pack_h);\n        if( ! ok )\n        {   msg = atomic_name() + msg + \" sparsity = pack_sparsity_enum\";\n            CPPAD_ASSERT_KNOWN(false, msg.c_str());\n        }\n    }\n    else if( sparsity_ == bool_sparsity_enum )\n    {   bool_h.resize(n * n);\n        ok = for_sparse_hes(vx, bool_r, bool_s, bool_h, x);\n        if( ! ok )\n            ok = for_sparse_hes(vx, bool_r, bool_s, bool_h);\n        if( ! ok )\n        {   msg = atomic_name() + msg + \" sparsity = bool_sparsity_enum\";\n            CPPAD_ASSERT_KNOWN(false, msg.c_str());\n        }\n    }\n    else\n    {   CPPAD_ASSERT_UNKNOWN( sparsity_ == set_sparsity_enum )\n        set_h.resize(n);\n        ok = for_sparse_hes(vx, bool_r, bool_s, set_h, x);\n        if( ! ok )\n            ok = for_sparse_hes(vx, bool_r, bool_s, set_h);\n        if( ! ok )\n        {   msg = atomic_name() + msg + \" sparsity = set_sparsity_enum\";\n            CPPAD_ASSERT_KNOWN(false, msg.c_str());\n        }\n    }\n    CPPAD_ASSERT_UNKNOWN( ok );\n    //\n    // modify hessian in calling routine\n    for(size_t i = 0; i < n; i++)\n    {   for(size_t j = 0; j < n; j++)\n        {   if( (x_index[i] > 0) && (x_index[j] > 0) )\n            {   bool flag = false;\n                switch( sparsity_ )\n                {   case pack_sparsity_enum:\n                    flag = pack_h[i * n + j];\n                    break;\n                    //\n                    case bool_sparsity_enum:\n                    flag = bool_h[i * n + j];\n                    break;\n                    //\n                    case set_sparsity_enum:\n                    flag = set_h[i].find(j) != set_h[i].end();\n                    break;\n                }\n                if( flag )\n                {   const_iterator itr_i(for_sparsity, np1 + x_index[i]);\n                    size_t i_x = *itr_i;\n                    while( i_x < np1 )\n                    {   for_sparsity.binary_union(\n                            i_x, i_x, np1 + x_index[j], for_sparsity\n                        );\n                        i_x = *(++itr_i);\n                    }\n                    const_iterator itr_j(for_sparsity, np1 + x_index[j]);\n                    size_t j_x = *itr_j;\n                    while( j_x < np1 )\n                    {   for_sparsity.binary_union(\n                            j_x, j_x, np1 + x_index[i], for_sparsity\n                        );\n                        j_x = *(++itr_j);\n                    }\n                }\n            }\n        }\n    }\n    return ok;\n}\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/atomic/two/for_sparse_jac.hpp",
    "content": "# ifndef CPPAD_CORE_ATOMIC_TWO_FOR_SPARSE_JAC_HPP\n# define CPPAD_CORE_ATOMIC_TWO_FOR_SPARSE_JAC_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_two_for_sparse_jac app}\n\nAtomic Forward Jacobian Sparsity Patterns\n#########################################\n\nSyntax\n******\n| *ok* = *afun* . ``for_sparse_jac`` ( *q* , *r* , *s* , *x* )\n\nDeprecated 2016-06-27\n*********************\n\n    *ok* = *afun* . ``for_sparse_jac`` ( *q* , *r* , *s* )\n\nPurpose\n*******\nThis function is used by :ref:`ForSparseJac-name` to compute\nJacobian sparsity patterns.\nFor a fixed matrix :math:`R \\in \\B{R}^{n \\times q}`,\nthe Jacobian of :math:`f( x + R * u)` with respect to :math:`u \\in \\B{R}^q` is\n\n.. math::\n\n    S(x) = f^{(1)} (x) * R\n\nGiven a :ref:`glossary@Sparsity Pattern` for :math:`R`,\n``for_sparse_jac`` computes a sparsity pattern for :math:`S(x)`.\n\nImplementation\n**************\nIf you are using\n:ref:`ForSparseJac-name` ,\n:ref:`ForSparseHes-name` , or\n:ref:`RevSparseHes-name` ,\none of the versions of this\nvirtual function must be defined by the\n:ref:`atomic_two_ctor@atomic_user` class.\n\nq\n=\nThe argument *q* has prototype\n\n    ``size_t`` *q*\n\nIt specifies the number of columns in\n:math:`R \\in \\B{R}^{n \\times q}` and the Jacobian\n:math:`S(x) \\in \\B{R}^{m \\times q}`.\n\nr\n=\nThis argument has prototype\n\n    ``const`` *atomic_sparsity* & *r*\n\nand is a :ref:`atomic_two_option@atomic_sparsity` pattern for\n:math:`R \\in \\B{R}^{n \\times q}`.\n\ns\n=\nThis argument has prototype\n\n    *atomic_sparsity* & *s*\n\nThe input values of its elements\nare not specified (must not matter).\nUpon return, *s* is a\n:ref:`atomic_two_option@atomic_sparsity` pattern for\n:math:`S(x) \\in \\B{R}^{m \\times q}`.\n\nx\n=\nThe argument has prototype\n\n    ``const CppAD::vector<`` *Base* >& *x*\n\nand size is equal to the *n* .\nThis is the :ref:`Value-name`  corresponding to the parameters in the\nvector :ref:`atomic_two_afun@ax` (when the atomic function was called).\nTo be specific, if\n\n| |tab| ``if`` ( ``Parameter`` ( *ax* [ *i* ]) == ``true`` )\n| |tab| |tab| *x* [ *i* ] = ``Value`` ( *ax* [ *i* ] );\n| |tab| ``else``\n| |tab| |tab| *x* [ *i* ] = ``CppAD::numeric_limits<`` *Base* >:: ``quiet_NaN`` ();\n\nThe version of this function with out the *x* argument is deprecated;\ni.e., you should include the argument even if you do not use it.\n\nok\n**\nThe return value *ok* has prototype\n\n    ``bool`` *ok*\n\nIf it is ``true`` , the corresponding evaluation succeeded,\notherwise it failed.\n\n{xrst_end atomic_two_for_sparse_jac}\n-----------------------------------------------------------------------------\n*/\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\n\\file atomic/two_for_sparse_jac.hpp\nAtomic forward Jacobian sparsity pattern.\n*/\n/*!\nLink, after case split, from for_jac_sweep to atomic_base.\n\n\\param q\nis the column dimension for the Jacobian sparsity patterns.\n\n\\param r\nis the Jacobian sparsity pattern for the argument vector x\n\n\\param s\nis the Jacobian sparsity pattern for the result vector y\n\n\\param x\nis the integer value for x arguments that are parameters.\n*/\ntemplate <class Base>\nbool atomic_base<Base>::for_sparse_jac(\n    size_t                                  q  ,\n    const vector< std::set<size_t> >&       r  ,\n             vector< std::set<size_t> >&       s  ,\n    const vector<Base>&                     x  )\n{   return false; }\ntemplate <class Base>\nbool atomic_base<Base>::for_sparse_jac(\n    size_t                                  q  ,\n    const vector<bool>&                     r  ,\n             vector<bool>&                     s  ,\n    const vector<Base>&                     x  )\n{   return false; }\ntemplate <class Base>\nbool atomic_base<Base>::for_sparse_jac(\n    size_t                                  q  ,\n    const vectorBool&                       r  ,\n             vectorBool&                       s  ,\n    const vector<Base>&                     x  )\n{   return false; }\n// deprecated versions\ntemplate <class Base>\nbool atomic_base<Base>::for_sparse_jac(\n    size_t                                  q  ,\n    const vector< std::set<size_t> >&       r  ,\n             vector< std::set<size_t> >&       s  )\n{   return false; }\ntemplate <class Base>\nbool atomic_base<Base>::for_sparse_jac(\n    size_t                                  q  ,\n    const vector<bool>&                     r  ,\n             vector<bool>&                     s  )\n{   return false; }\ntemplate <class Base>\nbool atomic_base<Base>::for_sparse_jac(\n    size_t                                  q  ,\n    const vectorBool&                       r  ,\n             vectorBool&                       s  )\n{   return false; }\n\n/*!\nLink, before case split, from for_jac_sweep to atomic_base.\n\n\\tparam InternalSparsity\nIs the type used for internal sparsity calculations; i.e.,\nsparse_pack or sparse_list.\n\n\\param x\nis parameter arguments to the function, other components are nan.\n\n\\param x_index\nis the variable index, on the tape, for the arguments to this function.\nThis size of x_index is n, the number of arguments to this function.\n\n\\param y_index\nis the variable index, on the tape, for the results for this function.\nThis size of y_index is m, the number of results for this function.\n\n\\param var_sparsity\nOn input, for j = 0, ... , n-1, the sparsity pattern with index x_index[j],\nis the sparsity for the j-th argument to this atomic function.\nOn output, for i = 0, ... , m-1, the sparsity pattern with index y_index[i],\nis the sparsity for the i-th result for this atomic function.\n*/\ntemplate <class Base>\ntemplate <class InternalSparsity>\nbool atomic_base<Base>::for_sparse_jac(\n    const vector<Base>&              x            ,\n    const vector<size_t>&            x_index      ,\n    const vector<size_t>&            y_index      ,\n    InternalSparsity&                var_sparsity )\n{   //\n    // pod_x_index, pod_y_index\n    local::pod_vector<size_t> pod_x_index( x_index.size() );\n    local::pod_vector<size_t> pod_y_index( y_index.size() );\n    for(size_t j = 0; j < x_index.size(); ++j)\n        pod_x_index[j] = x_index[j];\n    for(size_t i = 0; i < y_index.size(); ++i)\n        pod_y_index[i] = y_index[i];\n    //\n    // initial results are empty during forward mode\n    size_t q           = var_sparsity.end();\n    bool   input_empty = true;\n    bool   zero_empty  = true;\n    bool   transpose   = false;\n    size_t m           = pod_y_index.size();\n    bool   ok          = false;\n    size_t thread      = thread_alloc::thread_num();\n    allocate_work(thread);\n    //\n    std::string msg    = \": atomic_base.for_sparse_jac: returned false\";\n    if( sparsity_ == pack_sparsity_enum )\n    {   vectorBool& pack_r ( work_[thread]->pack_r );\n        vectorBool& pack_s ( work_[thread]->pack_s );\n        local::sparse::get_internal_pattern(\n            transpose, pod_x_index, var_sparsity, pack_r\n        );\n        //\n        pack_s.resize(m * q );\n        ok = for_sparse_jac(q, pack_r, pack_s, x);\n        if( ! ok )\n            ok = for_sparse_jac(q, pack_r, pack_s);\n        if( ! ok )\n        {   msg = atomic_name() + msg + \" sparsity = pack_sparsity_enum\";\n            CPPAD_ASSERT_KNOWN(false, msg.c_str());\n        }\n        local::sparse::set_internal_pattern(zero_empty, input_empty,\n            transpose, pod_y_index, var_sparsity, pack_s\n        );\n    }\n    else if( sparsity_ == bool_sparsity_enum )\n    {   vector<bool>& bool_r ( work_[thread]->bool_r );\n        vector<bool>& bool_s ( work_[thread]->bool_s );\n        local::sparse::get_internal_pattern(\n            transpose, pod_x_index, var_sparsity, bool_r\n        );\n        bool_s.resize(m * q );\n        ok = for_sparse_jac(q, bool_r, bool_s, x);\n        if( ! ok )\n            ok = for_sparse_jac(q, bool_r, bool_s);\n        if( ! ok )\n        {   msg = atomic_name() + msg + \" sparsity = bool_sparsity_enum\";\n            CPPAD_ASSERT_KNOWN(false, msg.c_str());\n        }\n        local::sparse::set_internal_pattern(zero_empty, input_empty,\n            transpose, pod_y_index, var_sparsity, bool_s\n        );\n    }\n    else\n    {   CPPAD_ASSERT_UNKNOWN( sparsity_ == set_sparsity_enum );\n        vector< std::set<size_t> >& set_r ( work_[thread]->set_r );\n        vector< std::set<size_t> >& set_s ( work_[thread]->set_s );\n        local::sparse::get_internal_pattern(\n            transpose, pod_x_index, var_sparsity, set_r\n        );\n        //\n        set_s.resize(m);\n        ok = for_sparse_jac(q, set_r, set_s, x);\n        if( ! ok )\n            ok = for_sparse_jac(q, set_r, set_s);\n        if( ! ok )\n        {   msg = atomic_name() + msg + \" sparsity = set_sparsity_enum\";\n            CPPAD_ASSERT_KNOWN(false, msg.c_str());\n        }\n        local::sparse::set_internal_pattern(zero_empty, input_empty,\n            transpose, pod_y_index, var_sparsity, set_s\n        );\n    }\n    return ok;\n}\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/atomic/two/forward.hpp",
    "content": "# ifndef CPPAD_CORE_ATOMIC_TWO_FORWARD_HPP\n# define CPPAD_CORE_ATOMIC_TWO_FORWARD_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_two_forward app}\n{xrst_spell\n    atx\n    aty\n    tx\n    vx\n    vy\n}\n\nAtomic Forward Mode\n###################\n\nSyntax\n******\n\nBase\n====\n\n    *ok* = *afun* . ``forward`` ( *p* , *q* , *vx* , *vy* , *tx* , *ty* )\n\nThis syntax is used by *f* . ``Forward`` where *f* has prototype\n\n    ``ADFun`` < *Base* > *f*\n\nand *afun* is used in *f* .\n\nAD<Base>\n========\n\n    *ok* = *afun* . ``forward`` ( *p* , *q* , *vx* , *vy* , *atx* , *aty* )\n\nThis syntax is used by *af* . ``Forward`` where *af* has prototype\n\n    ``ADFun< AD<`` *Base* > , *Base* > *af*\n\nand *afun* is used in *af* (see :ref:`base2ad-name` ).\n\nPurpose\n*******\nThis virtual function is used by :ref:`atomic_two_afun-name`\nto evaluate function values.\nIt is also used buy\n:ref:`f.Forward<Forward-name>` (and *af* . ``Forward`` )\nto compute function vales and derivatives.\n\nImplementation\n**************\nThis virtual function must be defined by the\n:ref:`atomic_two_ctor@atomic_user` class.\nIt can just return *ok* == ``false``\n(and not compute anything) for values\nof *q*  > 0 that are greater than those used by your\n:ref:`Forward-name` mode calculations.\n\np\n*\nThe argument *p* has prototype\n\n    ``size_t`` *p*\n\nIt specifies the lowest order Taylor coefficient that we are evaluating.\nDuring calls to :ref:`atomic_two_afun-name` , *p*  == 0 .\n\nq\n*\nThe argument *q* has prototype\n\n    ``size_t`` *q*\n\nIt specifies the highest order Taylor coefficient that we are evaluating.\nDuring calls to :ref:`atomic_two_afun-name` , *q*  == 0 .\n\nvx\n**\nThe ``forward`` argument *vx* has prototype\n\n    ``const CppAD::vector<bool>&`` *vx*\n\nThe case *vx* . ``size`` () > 0 only occurs while evaluating a call to\n:ref:`atomic_two_afun-name` .\nIn this case,\n*p* == *q*  == 0 ,\n*vx* . ``size`` () == *n* , and\nfor :math:`j = 0 , \\ldots , n-1`,\n*vx* [ *j* ] is true if and only if\n*ax* [ *j* ] is a :ref:`glossary@Variable`\nor :ref:`dynamic parameter<glossary@Parameter@Dynamic>`\nin the corresponding call to\n\n    *afun* ( *ax* , *ay* )\n\nIf *vx* . ``size`` () == 0 ,\nthen *vy* . ``size`` () == 0 and neither of these vectors\nshould be used.\n\nvy\n**\nThe ``forward`` argument *vy* has prototype\n\n    ``CppAD::vector<bool>&`` *vy*\n\nIf *vy* . ``size`` () == 0 , it should not be used.\nOtherwise,\n*q*  == 0 and *vy* . ``size`` () == *m* .\nThe input values of the elements of *vy*\nare not specified (must not matter).\nUpon return, for :math:`j = 0 , \\ldots , m-1`,\n*vy* [ *i* ] is true if and only if\n*ay* [ *i* ] is a variable\nor dynamic parameter\n(CppAD uses *vy* to reduce the necessary computations).\n\ntx\n**\nThe argument *tx* has prototype\n\n    ``const CppAD::vector<`` *Base* >& *tx*\n\nand *tx* . ``size`` () == ( *q* +1)* *n* .\nIt is used by *f* . ``Forward`` where *f* has type\n``ADFun`` < *Base* > *f* and *afun* is used in *f* .\nFor :math:`j = 0 , \\ldots , n-1` and :math:`k = 0 , \\ldots , q`,\nwe use the Taylor coefficient notation\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        x_j^k    & = & tx [ j * ( q + 1 ) + k ]\n        \\\\\n        X_j (t)  & = & x_j^0 + x_j^1 t^1 + \\cdots + x_j^q t^q\n    \\end{eqnarray}\n\nNote that superscripts represent an index for :math:`x_j^k`\nand an exponent for :math:`t^k`.\nAlso note that the Taylor coefficients for :math:`X(t)` correspond\nto the derivatives of :math:`X(t)` at :math:`t = 0` in the following way:\n\n.. math::\n\n    x_j^k = \\frac{1}{ k ! } X_j^{(k)} (0)\n\natx\n***\nThe argument *atx* has prototype\n\n    ``const CppAD::vector< AD<`` *Base* > >& *atx*\n\nOtherwise, *atx* specifications are the same as for *tx* .\n\nty\n**\nThe argument *ty* has prototype\n\n    ``CppAD::vector<`` *Base* >& *ty*\n\nand *tx* . ``size`` () == ( *q* +1)* *m* .\nIt is set by *f* . ``Forward`` where *f* has type\n``ADFun`` < *Base* > *f* and *afun* is used in *f* .\nUpon return,\nFor :math:`i = 0 , \\ldots , m-1` and :math:`k = 0 , \\ldots , q`,\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        Y_i (t)  & = & f_i [ X(t) ]\n        \\\\\n        Y_i (t)  & = & y_i^0 + y_i^1 t^1 + \\cdots + y_i^q t^q + o ( t^q )\n        \\\\\n        ty [ i * ( q + 1 ) + k ] & = & y_i^k\n    \\end{eqnarray}\n\nwhere :math:`o( t^q ) / t^q \\rightarrow 0` as :math:`t \\rightarrow 0`.\nNote that superscripts represent an index for :math:`y_j^k`\nand an exponent for :math:`t^k`.\nAlso note that the Taylor coefficients for :math:`Y(t)` correspond\nto the derivatives of :math:`Y(t)` at :math:`t = 0` in the following way:\n\n.. math::\n\n    y_j^k = \\frac{1}{ k ! } Y_j^{(k)} (0)\n\nIf :math:`p > 0`,\nfor :math:`i = 0 , \\ldots , m-1` and :math:`k = 0 , \\ldots , p-1`,\nthe input of *ty* satisfies\n\n.. math::\n\n    ty [ i * ( q + 1 ) + k ] = y_i^k\n\nand hence the corresponding elements need not be recalculated.\n\naty\n***\nThe argument *aty* has prototype\n\n    ``const CppAD::vector< AD<`` *Base* > >& *aty*\n\nOtherwise, *aty* specifications are the same as for *ty* .\n\nok\n**\nIf the required results are calculated, *ok* should be true.\nOtherwise, it should be false.\n\nDiscussion\n**********\nFor example, suppose that *q*  == 2 ,\nand you know how to compute the function :math:`f(x)`,\nits first derivative :math:`f^{(1)} (x)`,\nand it component wise Hessian :math:`f_i^{(2)} (x)`.\nThen you can compute *ty* using the following formulas:\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    y_i^0 & = & Y(0)\n            = f_i ( x^0 )\n    \\\\\n    y_i^1 & = & Y^{(1)} ( 0 )\n            = f_i^{(1)} ( x^0 ) X^{(1)} ( 0 )\n            = f_i^{(1)} ( x^0 ) x^1\n    \\\\\n    y_i^2\n    & = & \\frac{1}{2 !} Y^{(2)} (0)\n    \\\\\n    & = & \\frac{1}{2} X^{(1)} (0)^\\R{T} f_i^{(2)} ( x^0 ) X^{(1)} ( 0 )\n      +   \\frac{1}{2} f_i^{(1)} ( x^0 ) X^{(2)} ( 0 )\n    \\\\\n    & = & \\frac{1}{2} (x^1)^\\R{T} f_i^{(2)} ( x^0 ) x^1\n      +    f_i^{(1)} ( x^0 ) x^2\n    \\end{eqnarray}\n\nFor :math:`i = 0 , \\ldots , m-1`, and :math:`k = 0 , 1 , 2`,\n\n.. math::\n\n    ty [ i * (q + 1) + k ] = y_i^k\n\n{xrst_end atomic_two_forward}\n-----------------------------------------------------------------------------\n*/\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\n\\file atomic/two_forward.hpp\nAtomic forward mode\n*/\n/*!\nLink from atomic_base to forward mode (for replacement by derived class)\n\n\\param p [in]\nlowerest order for this forward mode calculation.\n\n\\param q [in]\nhighest order for this forward mode calculation.\n\n\\param vx [in]\nif size not zero, which components of x are variables\n\n\\param vy [out]\nif size not zero, which components of y are variables\n\n\\param tx [in]\nTaylor coefficients corresponding to x for this calculation.\n\n\\param ty [out]\nTaylor coefficient corresponding to y for this calculation\n\nSee the forward mode in user's documentation for atomic_two\n*/\ntemplate <class Base>\nbool atomic_base<Base>::forward(\n    size_t                    p  ,\n    size_t                    q  ,\n    const vector<bool>&       vx ,\n             vector<bool>&       vy ,\n    const vector<Base>&       tx ,\n             vector<Base>&       ty )\n{   return false; }\n/*!\nLink from atomic_base to forward mode (for replacement by derived class)\n\n\\param p [in]\nlowerest order for this forward mode calculation.\n\n\\param q [in]\nhighest order for this forward mode calculation.\n\n\\param vx [in]\nif size not zero, which components of x are variables\n\n\\param vy [out]\nif size not zero, which components of y are variables\n\n\\param atx [in]\nTaylor coefficients corresponding to x for this calculation.\n\n\\param aty [out]\nTaylor coefficient corresponding to y for this calculation\n\nSee the forward mode in user's documentation for atomic_two\n*/\ntemplate <class Base>\nbool atomic_base<Base>::forward(\n    size_t                    p   ,\n    size_t                    q   ,\n    const vector<bool>&       vx  ,\n             vector<bool>&       vy  ,\n    const vector< AD<Base> >& atx ,\n             vector< AD<Base> >& aty )\n{   return false; }\n/*!\nConvert atomic_three interface to atomic_two interface\n\n\\param order_low [in]\nlowerest order for this forward mode calculation.\n\n\\param order_up [in]\nhighest order for this forward mode calculation.\n\n\\param  type_x [in]\nif size not zero, which components of x are variables\n\n\\param type_y [out]\nif size not zero, which components of y are variables\n\n\\param taylor_x [in]\nTaylor coefficients corresponding to x for this calculation.\n\n\\param taylor_y [out]\nTaylor coefficient corresponding to y for this calculation\n\nSee the forward mode in user's documentation for atomic_three\n*/\n# define CPPAD_ATOMIC_BASE_MUSTDO 0\ntemplate <class Base>\nbool atomic_base<Base>::forward(\n    size_t                       order_low  ,\n    size_t                       order_up   ,\n    const vector<ad_type_enum>&  type_x     ,\n    vector<ad_type_enum>&        type_y     ,\n    const vector<Base>&          taylor_x   ,\n    vector<Base>&                taylor_y   )\n{   //\n    // atomic_base::afun(ax, ay) calls bool version directly\n    CPPAD_ASSERT_UNKNOWN( type_x.size() == 0 );\n    CPPAD_ASSERT_UNKNOWN( type_y.size() == 0 );\n    //\n# if CPPAD_ATOMIC_BASE_MUSTDO\n    size_t thread = thread_alloc::thread_num();\n    allocate_work(thread);\n    vector <bool>& vx  = work_[thread]->vx;\n    vector <bool>& vy  = work_[thread]->vy;\n    vx.resize(type_x.size());\n    vy.resize(type_y.size());\n# else\n    vector<bool> vx, vy;\n# endif\n    //\n    bool ok = forward(order_low, order_up, vx, vy, taylor_x, taylor_y);\n    //\n    return ok;\n}\n# undef CPPAD_ATOMIC_BASE_MUSTDO\n/*!\nConvert atomic_three interface to atomic_two interface\n\n\\param order_low [in]\nlowerest order for this forward mode calculation.\n\n\\param order_up [in]\nhighest order for this forward mode calculation.\n\n\\param  type_x [in]\nif size not zero, which components of x are variables\n\n\\param type_y [out]\nif size not zero, which components of y are variables\n\n\\param ataylor_x [in]\nTaylor coefficients corresponding to x for this calculation.\n\n\\param ataylor_y [out]\nTaylor coefficient corresponding to y for this calculation\n\nSee the forward mode in user's documentation for atomic_three\n*/\ntemplate <class Base>\nbool atomic_base<Base>::forward(\n    size_t                       order_low  ,\n    size_t                       order_up   ,\n    const vector<ad_type_enum>&  type_x     ,\n    vector<ad_type_enum>&        type_y     ,\n    const vector< AD<Base> >&    ataylor_x  ,\n    vector< AD<Base> >&          ataylor_y  )\n{   //\n    // atomic_base::afun(ax, ay) calls bool version directly\n    CPPAD_ASSERT_UNKNOWN( type_x.size() == 0 );\n    CPPAD_ASSERT_UNKNOWN( type_y.size() == 0 );\n    //\n    vector<bool> vx, vy;\n    bool ok = forward(order_low, order_up, vx, vy, ataylor_x, ataylor_y);\n    //\n    return ok;\n}\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/atomic/two/option.hpp",
    "content": "# ifndef CPPAD_CORE_ATOMIC_TWO_OPTION_HPP\n# define CPPAD_CORE_ATOMIC_TWO_OPTION_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_two_option app}\n{xrst_spell\n    typedef\n}\n\nSet Atomic Function Options\n###########################\n\nSyntax\n******\n| *afun* . ``option`` ( *option_value* )\n\nScope\n*****\nThese settings do not apply to individual *afun* calls,\nbut rather all subsequent uses of the corresponding atomic operation\nin an :ref:`ADFun-name` object.\n\natomic_sparsity\n***************\nNote that, if you use :ref:`optimize-name` , these sparsity patterns are used\nto determine the :ref:`dependency<dependency.cpp-name>` relationship between\nargument and result variables.\n\npack_sparsity_enum\n==================\nIf *option_value* is ``atomic_base`` < *Base* >:: ``pack_sparsity_enum`` ,\nthen the type used by *afun* for\n:ref:`sparsity patterns<glossary@Sparsity Pattern>` ,\n(after the option is set) will be\n\n    ``typedef CppAD::vectorBool`` *atomic_sparsity*\n\nIf *r* is a sparsity pattern\nfor a matrix :math:`R \\in \\B{R}^{p \\times q}`:\n*r* . ``size`` () == *p* * *q* .\n\nbool_sparsity_enum\n==================\nIf *option_value* is ``atomic_base`` < *Base* >:: ``bool_sparsity_enum`` ,\nthen the type used by *afun* for\n:ref:`sparsity patterns<glossary@Sparsity Pattern>` ,\n(after the option is set) will be\n\n    ``typedef CppAD::vector<bool>`` *atomic_sparsity*\n\nIf *r* is a sparsity pattern\nfor a matrix :math:`R \\in \\B{R}^{p \\times q}`:\n*r* . ``size`` () == *p* * *q* .\n\nset_sparsity_enum\n=================\nIf *option_value* is *atomic_base* < ``Base`` >:: *set_sparsity_enum* ,\nthen the type used by *afun* for\n:ref:`sparsity patterns<glossary@Sparsity Pattern>` ,\n(after the option is set) will be\n\n    ``typedef CppAD::vector< std::set<size_t> >`` *atomic_sparsity*\n\nIf *r* is a sparsity pattern\nfor a matrix :math:`R \\in \\B{R}^{p \\times q}`:\n*r* . ``size`` () == *p* , and for :math:`i = 0 , \\ldots , p-1`,\nthe elements of *r* [ *i* ] are between zero and :math:`q-1` inclusive.\n\n{xrst_end atomic_two_option}\n------------------------------------------------------------------------------\n*/\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\n\\file atomic/two_option.hpp\nSetting atomic_base options.\n*/\n\n/*!\nSetting atomic_base options.\n\n\\param option_value\nnew option value.\n*/\ntemplate <class Base>\nvoid atomic_base<Base>::option(enum option_enum option_value)\n{   switch( option_value )\n    {   case pack_sparsity_enum:\n        case bool_sparsity_enum:\n        case set_sparsity_enum:\n        sparsity_ = option_value;\n        break;\n\n        default:\n        CPPAD_ASSERT_KNOWN(\n            false,\n            \"atoic_base::option: option_value is not valid\"\n        );\n    }\n    return;\n}\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/atomic/two/rev_depend.hpp",
    "content": "# ifndef CPPAD_CORE_ATOMIC_TWO_REV_DEPEND_HPP\n# define CPPAD_CORE_ATOMIC_TWO_REV_DEPEND_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\n\\file atomic/two_rev_depend.hpp\nThird generation atomic type computation.\n*/\n/*!\nLink from atomic_two to reverse dependency calculation\n\n\\param parameter_x [in]\nis the value of the parameters in the corresponding function call\nafun(ax, ay).\n\n\\param type_x [in]\nis the type for each component of ax in the corresponding function call\nafun(ax, ay).\n\n\\param depend_x [out]\nspecifies which components of x affect values of interest.\n\n\\param depend_y [in]\nspecifies which components of y affect values of interest.\n*/\n// BEGIN_PROTOTYPE\ntemplate <class Base>\nbool atomic_base<Base>::rev_depend(\n    const vector<Base>&         parameter_x ,\n    const vector<ad_type_enum>& type_x      ,\n    vector<bool>&               depend_x    ,\n    const vector<bool>&         depend_y    )\n// END_PROTOTYPE\n{   bool ok = true;\n    CPPAD_ASSERT_UNKNOWN( depend_x.size() == parameter_x.size() );\n    size_t n = depend_x.size();\n    size_t m = depend_y.size();\n    //\n    size_t thread = thread_alloc::thread_num();\n    allocate_work(thread);\n    //\n    if( sparsity_ == pack_sparsity_enum )\n    {   vectorBool& rt ( work_[thread]->pack_r );\n        vectorBool& st ( work_[thread]->pack_s );\n        //\n        st.resize(n * 1 );\n        rt.resize(m * 1 );\n        for(size_t i = 0; i < m; ++i)\n            rt[i] = depend_y[i];\n        ok = rev_sparse_jac(1, rt, st, parameter_x);\n        if( ! ok )\n            ok = rev_sparse_jac(1, rt, st);\n        if( ! ok )\n            return false;\n        for(size_t j = 0; j < n; ++j)\n            depend_x[j] = st[j];\n    }\n    else if( sparsity_ == bool_sparsity_enum )\n    {\n        ok = rev_sparse_jac(1, depend_y, depend_x, parameter_x);\n        if( ! ok )\n            ok = rev_sparse_jac(m, depend_y, depend_x);\n        if( ! ok )\n            return false;\n    }\n    else\n    {   CPPAD_ASSERT_UNKNOWN( sparsity_ == set_sparsity_enum );\n        vector< std::set<size_t> >& rt ( work_[thread]->set_r );\n        vector< std::set<size_t> >& st ( work_[thread]->set_s );\n        rt.resize(m);\n        st.resize(n);\n        for(size_t i = 0; i < m; ++i)\n        {   if( depend_y[i] )\n                rt[i].insert(0);\n        }\n        ok = rev_sparse_jac(m, rt, st, parameter_x);\n        if( ! ok )\n            ok = rev_sparse_jac(m, rt, st);\n        if( ! ok )\n            return false;\n        for(size_t j = 0; j < n; ++j)\n            depend_x[j] = ! st[j].empty();\n    }\n    return ok;\n}\n\n} // END_CPPAD_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/atomic/two/rev_sparse_hes.hpp",
    "content": "# ifndef CPPAD_CORE_ATOMIC_TWO_REV_SPARSE_HES_HPP\n# define CPPAD_CORE_ATOMIC_TWO_REV_SPARSE_HES_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_two_rev_sparse_hes app}\n{xrst_spell\n    vx\n}\n\nAtomic Reverse Hessian Sparsity Patterns\n########################################\n\nSyntax\n******\n| *ok* = *afun* . ``rev_sparse_hes`` ( *vx* , *s* , *t* , *q* , *r* , *u* , *v* , *x* )\n\nDeprecated 2016-06-27\n*********************\n*ok* = *afun* . ``rev_sparse_hes`` ( *vx* , *s* , *t* , *q* , *r* , *u* , *v* )\n\nPurpose\n*******\nThis function is used by :ref:`RevSparseHes-name` to compute\nHessian sparsity patterns.\nIf you are using :ref:`RevSparseHes-name` to compute\none of the versions of this\nvirtual function muse be defined by the\n:ref:`atomic_two_ctor@atomic_user` class.\n\nThere is an unspecified scalar valued function\n:math:`g : \\B{R}^m \\rightarrow \\B{R}`.\nGiven a :ref:`glossary@Sparsity Pattern` for\n:math:`R \\in \\B{R}^{n \\times q}`,\nand information about the function :math:`z = g(y)`,\nthis routine computes the sparsity pattern for\n\n.. math::\n\n    V(x) = (g \\circ f)^{(2)}( x ) R\n\nImplementation\n**************\nIf you are using and :ref:`RevSparseHes-name` ,\nthis virtual function must be defined by the\n:ref:`atomic_two_ctor@atomic_user` class.\n\nvx\n==\nThe argument *vx* has prototype\n\n    ``const CppAD:vector<bool>&`` *vx*\n\n*vx* . ``size`` () == *n* , and\nfor :math:`j = 0 , \\ldots , n-1`,\n*vx* [ *j* ] is true if and only if\n*ax* [ *j* ] is a :ref:`glossary@Variable`\nor :ref:`dynamic parameter<glossary@Parameter@Dynamic>`\nin the corresponding call to\n\n    *afun* ( *ax* , *ay* )\n\ns\n=\nThe argument *s* has prototype\n\n    ``const CppAD:vector<bool>&`` *s*\n\nand its size is *m* .\nIt is a sparsity pattern for\n:math:`S(x) = g^{(1)} [ f(x) ] \\in \\B{R}^{1 \\times m}`.\n\nt\n=\nThis argument has prototype\n\n    ``CppAD:vector<bool>&`` *t*\n\nand its size is *m* .\nThe input values of its elements\nare not specified (must not matter).\nUpon return, *t* is a\nsparsity pattern for\n:math:`T(x) \\in \\B{R}^{1 \\times n}` where\n\n.. math::\n\n    T(x) = (g \\circ f)^{(1)} (x) = S(x) * f^{(1)} (x)\n\nq\n=\nThe argument *q* has prototype\n\n    ``size_t`` *q*\n\nIt specifies the number of columns in\n:math:`R \\in \\B{R}^{n \\times q}`,\n:math:`U(x) \\in \\B{R}^{m \\times q}`, and\n:math:`V(x) \\in \\B{R}^{n \\times q}`.\n\nr\n=\nThis argument has prototype\n\n    ``const`` *atomic_sparsity* & *r*\n\nand is a :ref:`atomic_two_option@atomic_sparsity` pattern for\n:math:`R \\in \\B{R}^{n \\times q}`.\n\nu\n*\nThis argument has prototype\n\n    ``const`` *atomic_sparsity* & *u*\n\nand is a :ref:`atomic_two_option@atomic_sparsity` pattern for\n:math:`U(x) \\in \\B{R}^{m \\times q}` which is defined by\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    U(x)\n    & = &\n    \\{ \\partial_u \\{ \\partial_y g[ y + f^{(1)} (x) R u ] \\}_{y=f(x)} \\}_{u=0}\n    \\\\\n    & = &\n    \\partial_u \\{ g^{(1)} [ f(x) + f^{(1)} (x) R u ] \\}_{u=0}\n    \\\\\n    & = &\n    g^{(2)} [ f(x) ] f^{(1)} (x) R\n    \\end{eqnarray}\n\nv\n=\nThis argument has prototype\n\n    *atomic_sparsity* & *v*\n\nThe input value of its elements\nare not specified (must not matter).\nUpon return, *v* is a\n:ref:`atomic_two_option@atomic_sparsity` pattern for\n:math:`V(x) \\in \\B{R}^{n \\times q}` which is defined by\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    V(x)\n    & = &\n    \\partial_u [ \\partial_x (g \\circ f) ( x + R u )  ]_{u=0}\n    \\\\\n    & = &\n    \\partial_u [ (g \\circ f)^{(1)}( x + R u )  ]_{u=0}\n    \\\\\n    & = &\n    (g \\circ f)^{(2)}( x ) R\n    \\\\\n    & = &\n    f^{(1)} (x)^\\R{T} g^{(2)} [ f(x) ] f^{(1)} (x)  R\n    +\n    \\sum_{i=1}^m g_i^{(1)} [ f(x) ] \\; f_i^{(2)} (x) R\n    \\\\\n    & = &\n    f^{(1)} (x)^\\R{T} U(x)\n    +\n    \\sum_{i=1}^m S_i (x) \\; f_i^{(2)} (x) R\n    \\end{eqnarray}\n\nx\n=\nThe argument has prototype\n\n    ``const CppAD::vector<`` *Base* >& *x*\n\nand size is equal to the *n* .\nThis is the :ref:`Value-name`  corresponding to the parameters in the\nvector :ref:`atomic_two_afun@ax` (when the atomic function was called).\nTo be specific, if\n\n| |tab| ``if`` ( ``Parameter`` ( *ax* [ *i* ]) == ``true`` )\n| |tab| |tab| *x* [ *i* ] = ``Value`` ( *ax* [ *i* ] );\n| |tab| ``else``\n| |tab| |tab| *x* [ *i* ] = ``CppAD::numeric_limits<`` *Base* >:: ``quiet_NaN`` ();\n\nThe version of this function with out the *x* argument is deprecated;\ni.e., you should include the argument even if you do not use it.\n\n{xrst_end atomic_two_rev_sparse_hes}\n-----------------------------------------------------------------------------\n*/\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\n\\file atomic/two_rev_sparse_hes.hpp\nAtomic reverse mode Hessian sparsity patterns.\n*/\n/*!\nLink from reverse Hessian sparsity sweep to atomic_base\n\n\\param vx [in]\nwhich components of x are variables.\n\n\\param s [in]\nis the reverse Jacobian sparsity pattern w.r.t the result vector y.\n\n\\param t [out]\nis the reverse Jacobian sparsity pattern w.r.t the argument vector x.\n\n\\param q [in]\nis the column dimension for the sparsity patterns.\n\n\\param r [in]\nis the forward Jacobian sparsity pattern w.r.t the argument vector x\n\n\\param u [in]\nis the Hessian sparsity pattern w.r.t the result vector y.\n\n\\param v [out]\nis the Hessian sparsity pattern w.r.t the argument vector x.\n\n\\param x [in]\nis the integer value of the x arguments that are parameters.\n*/\ntemplate <class Base>\nbool atomic_base<Base>::rev_sparse_hes(\n    const vector<bool>&                     vx ,\n    const vector<bool>&                     s  ,\n             vector<bool>&                     t  ,\n    size_t                                  q  ,\n    const vector< std::set<size_t> >&       r  ,\n    const vector< std::set<size_t> >&       u  ,\n             vector< std::set<size_t> >&       v  ,\n    const vector<Base>&                     x  )\n{   return false; }\ntemplate <class Base>\nbool atomic_base<Base>::rev_sparse_hes(\n    const vector<bool>&                     vx ,\n    const vector<bool>&                     s  ,\n             vector<bool>&                     t  ,\n    size_t                                  q  ,\n    const vector<bool>&                     r  ,\n    const vector<bool>&                     u  ,\n             vector<bool>&                     v  ,\n    const vector<Base>&                     x  )\n{   return false; }\ntemplate <class Base>\nbool atomic_base<Base>::rev_sparse_hes(\n    const vector<bool>&                     vx ,\n    const vector<bool>&                     s  ,\n             vector<bool>&                     t  ,\n    size_t                                  q  ,\n    const vectorBool&                       r  ,\n    const vectorBool&                       u  ,\n             vectorBool&                       v  ,\n    const vector<Base>&                     x  )\n{   return false; }\n// deprecated\ntemplate <class Base>\nbool atomic_base<Base>::rev_sparse_hes(\n    const vector<bool>&                     vx ,\n    const vector<bool>&                     s  ,\n             vector<bool>&                     t  ,\n    size_t                                  q  ,\n    const vector< std::set<size_t> >&       r  ,\n    const vector< std::set<size_t> >&       u  ,\n             vector< std::set<size_t> >&       v  )\n{   return false; }\ntemplate <class Base>\nbool atomic_base<Base>::rev_sparse_hes(\n    const vector<bool>&                     vx ,\n    const vector<bool>&                     s  ,\n             vector<bool>&                     t  ,\n    size_t                                  q  ,\n    const vector<bool>&                     r  ,\n    const vector<bool>&                     u  ,\n             vector<bool>&                     v  )\n{   return false; }\ntemplate <class Base>\nbool atomic_base<Base>::rev_sparse_hes(\n    const vector<bool>&                     vx ,\n    const vector<bool>&                     s  ,\n             vector<bool>&                     t  ,\n    size_t                                  q  ,\n    const vectorBool&                       r  ,\n    const vectorBool&                       u  ,\n             vectorBool&                       v  )\n{   return false; }\n/*!\nLink, before case split, from rev_hes_sweep to atomic_base.\n\n\\tparam InternalSparsity\nIs the used internally for sparsity calculations; i.e.,\nsparse_pack or sparse_list.\n\n\\param x\nis parameter arguments to the function, other components are nan.\n\n\\param x_index\nis the variable index, on the tape, for the arguments to this function.\nThis size of x_index is n, the number of arguments to this function.\n\n\\param y_index\nis the variable index, on the tape, for the results for this function.\nThis size of y_index is m, the number of results for this function.\n\n\\param for_jac_sparsity\nOn input, for j = 0, ... , n-1, the sparsity pattern with index x_index[j],\nis the forward Jacobian sparsity for the j-th argument to this atomic function.\n\n\\param rev_jac_flag\nThis shows which variables affect the function we are\ncomputing the Hessian of.\nOn input, for i = 0, ... , m-1, the rev_jac_flag[ y_index[i] ] is true\nif the Jacobian of function (we are computing sparsity for) is no-zero.\nUpon return, for j = 0, ... , n-1, rev_jac_flag [ x_index[j] ]\nas been adjusted to account removing this atomic function.\n\n\\param rev_hes_sparsity\nThis is the sparsity pattern for the Hessian.\nOn input, for i = 0, ... , m-1, row y_index[i] is the reverse Hessian sparsity\nwith one of the partials with respect to to y_index[i].\n*/\ntemplate <class Base>\ntemplate <class InternalSparsity>\nbool atomic_base<Base>::rev_sparse_hes(\n    const vector<Base>&              x                ,\n    const vector<size_t>&            x_index          ,\n    const vector<size_t>&            y_index          ,\n    const InternalSparsity&          for_jac_sparsity ,\n    bool*                            rev_jac_flag     ,\n    InternalSparsity&                rev_hes_sparsity )\n{   CPPAD_ASSERT_UNKNOWN( for_jac_sparsity.end() == rev_hes_sparsity.end() );\n    //\n    // pod_x_index, pod_y_index\n    local::pod_vector<size_t> pod_x_index( x_index.size() );\n    local::pod_vector<size_t> pod_y_index( y_index.size() );\n    for(size_t j = 0; j < x_index.size(); ++j)\n        pod_x_index[j] = x_index[j];\n    for(size_t i = 0; i < y_index.size(); ++i)\n        pod_y_index[i] = y_index[i];\n    //\n    size_t q           = rev_hes_sparsity.end();\n    size_t n           = pod_x_index.size();\n    size_t m           = pod_y_index.size();\n    bool   ok          = false;\n    size_t thread      = thread_alloc::thread_num();\n    allocate_work(thread);\n    bool   zero_empty  = true;\n    bool   input_empty = false;\n    bool   transpose   = false;\n    //\n    // vx\n    vector<bool> vx(n);\n    for(size_t j = 0; j < n; j++)\n        vx[j] = pod_x_index[j] != 0;\n    //\n    // note that s and t are vectors so transpose does not matter for bool case\n    vector<bool> bool_s( work_[thread]->bool_s );\n    vector<bool> bool_t( work_[thread]->bool_t );\n    //\n    bool_s.resize(m);\n    bool_t.resize(n);\n    //\n    for(size_t i = 0; i < m; i++)\n    {   if( pod_y_index[i] > 0  )\n            bool_s[i] = rev_jac_flag[ pod_y_index[i] ];\n    }\n    //\n    std::string msg = \": atomic_base.rev_sparse_hes: returned false\";\n    if( sparsity_ == pack_sparsity_enum )\n    {   vectorBool&  pack_r( work_[thread]->pack_r );\n        vectorBool&  pack_u( work_[thread]->pack_u );\n        vectorBool&  pack_v( work_[thread]->pack_h );\n        //\n        pack_v.resize(n * q);\n        //\n        local::sparse::get_internal_pattern(\n            transpose, pod_x_index, for_jac_sparsity, pack_r\n        );\n        local::sparse::get_internal_pattern(\n            transpose, pod_y_index, rev_hes_sparsity, pack_u\n        );\n        //\n        ok = rev_sparse_hes(vx, bool_s, bool_t, q, pack_r, pack_u, pack_v, x);\n        if( ! ok )\n            ok = rev_sparse_hes(vx, bool_s, bool_t, q, pack_r, pack_u, pack_v);\n        if( ! ok )\n        {   msg = atomic_name() + msg + \" sparsity = pack_sparsity_enum\";\n            CPPAD_ASSERT_KNOWN(false, msg.c_str());\n        }\n        local::sparse::set_internal_pattern(zero_empty, input_empty,\n            transpose, pod_x_index, rev_hes_sparsity, pack_v\n        );\n    }\n    else if( sparsity_ == bool_sparsity_enum )\n    {   vector<bool>&  bool_r( work_[thread]->bool_r );\n        vector<bool>&  bool_u( work_[thread]->bool_u );\n        vector<bool>&  bool_v( work_[thread]->bool_h );\n        //\n        bool_v.resize(n * q);\n        //\n        local::sparse::get_internal_pattern(\n            transpose, pod_x_index, for_jac_sparsity, bool_r\n        );\n        local::sparse::get_internal_pattern(\n            transpose, pod_y_index, rev_hes_sparsity, bool_u\n        );\n        //\n        ok = rev_sparse_hes(vx, bool_s, bool_t, q, bool_r, bool_u, bool_v, x);\n        if( ! ok )\n            ok = rev_sparse_hes(vx, bool_s, bool_t, q, bool_r, bool_u, bool_v);\n        if( ! ok )\n        {   msg = atomic_name() + msg + \" sparsity = bool_sparsity_enum\";\n            CPPAD_ASSERT_KNOWN(false, msg.c_str());\n        }\n        local::sparse::set_internal_pattern(zero_empty, input_empty,\n            transpose, pod_x_index, rev_hes_sparsity, bool_v\n        );\n    }\n    else\n    {   CPPAD_ASSERT_UNKNOWN( sparsity_ == set_sparsity_enum );\n        vector< std::set<size_t> >&  set_r( work_[thread]->set_r );\n        vector< std::set<size_t> >&  set_u( work_[thread]->set_u );\n        vector< std::set<size_t> >&  set_v( work_[thread]->set_h );\n        //\n        set_v.resize(n);\n        //\n        local::sparse::get_internal_pattern(\n            transpose, pod_x_index, for_jac_sparsity, set_r\n        );\n        local::sparse::get_internal_pattern(\n            transpose, pod_y_index, rev_hes_sparsity, set_u\n        );\n        //\n        ok = rev_sparse_hes(vx, bool_s, bool_t, q, set_r, set_u, set_v, x);\n        if( ! ok )\n            ok = rev_sparse_hes(vx, bool_s, bool_t, q, set_r, set_u, set_v);\n        if( ! ok )\n        {   msg = atomic_name() + msg + \" sparsity = set_sparsity_enum\";\n            CPPAD_ASSERT_KNOWN(false, msg.c_str());\n        }\n        local::sparse::set_internal_pattern(zero_empty, input_empty,\n            transpose, pod_x_index, rev_hes_sparsity, set_v\n        );\n    }\n    for(size_t j = 0; j < n; j++)\n    {   if( pod_x_index[j] > 0  )\n            rev_jac_flag[ pod_x_index[j] ] |= bool_t[j];\n    }\n    return ok;\n}\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/atomic/two/rev_sparse_jac.hpp",
    "content": "# ifndef CPPAD_CORE_ATOMIC_TWO_REV_SPARSE_JAC_HPP\n# define CPPAD_CORE_ATOMIC_TWO_REV_SPARSE_JAC_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_two_rev_sparse_jac app}\n{xrst_spell\n    rt\n}\n\nAtomic Reverse Jacobian Sparsity Patterns\n#########################################\n\nSyntax\n******\n| *ok* = *afun* . ``rev_sparse_jac`` ( *q* , *rt* , *st* , *x* )\n\nDeprecated 2016-06-27\n*********************\n\n    *ok* = *afun* . ``rev_sparse_jac`` ( *q* , *rt* , *st* )\n\nPurpose\n*******\nThis function is used by\n:ref:`RevSparseJac-name` to compute\nJacobian sparsity patterns.\nIf you are using :ref:`RevSparseJac-name` ,\none of the versions of this\nvirtual function must be defined by the\n:ref:`atomic_two_ctor@atomic_user` class.\n\nFor a fixed matrix :math:`R \\in \\B{R}^{q \\times m}`,\nthe Jacobian of :math:`R * f( x )` with respect to :math:`x \\in \\B{R}^n` is\n\n.. math::\n\n    S(x) = R * f^{(1)} (x)\n\nGiven a :ref:`glossary@Sparsity Pattern` for :math:`R`,\n``rev_sparse_jac`` computes a sparsity pattern for :math:`S(x)`.\n\nImplementation\n**************\nIf you are using\n:ref:`RevSparseJac-name` or :ref:`ForSparseHes-name` ,\nthis virtual function must be defined by the\n:ref:`atomic_two_ctor@atomic_user` class.\n\nq\n=\nThe argument *q* has prototype\n\n    ``size_t`` *q*\n\nIt specifies the number of rows in\n:math:`R \\in \\B{R}^{q \\times m}` and the Jacobian\n:math:`S(x) \\in \\B{R}^{q \\times n}`.\n\nrt\n==\nThis argument has prototype\n\n    ``const`` *atomic_sparsity* & *rt*\n\nand is a\n:ref:`atomic_two_option@atomic_sparsity` pattern for\n:math:`R^\\R{T} \\in \\B{R}^{m \\times q}`.\n\nst\n==\nThis argument has prototype\n\n    *atomic_sparsity* & *st*\n\nThe input value of its elements\nare not specified (must not matter).\nUpon return, *s* is a\n:ref:`atomic_two_option@atomic_sparsity` pattern for\n:math:`S(x)^\\R{T} \\in \\B{R}^{n \\times q}`.\n\nx\n=\nThe argument has prototype\n\n    ``const CppAD::vector<`` *Base* >& *x*\n\nand size is equal to the *n* .\nThis is the :ref:`Value-name` corresponding to the parameters in the\nvector :ref:`atomic_two_afun@ax` (when the atomic function was called).\nTo be specific, if\n\n| |tab| ``if`` ( ``Parameter`` ( *ax* [ *i* ]) == ``true`` )\n| |tab| |tab| *x* [ *i* ] = ``Value`` ( *ax* [ *i* ] );\n| |tab| ``else``\n| |tab| |tab| *x* [ *i* ] = ``CppAD::numeric_limits<`` *Base* >:: ``quiet_NaN`` ();\n\nThe version of this function with out the *x* argument is deprecated;\ni.e., you should include the argument even if you do not use it.\n\nok\n**\nThe return value *ok* has prototype\n\n    ``bool`` *ok*\n\nIf it is ``true`` , the corresponding evaluation succeeded,\notherwise it failed.\n\n{xrst_end atomic_two_rev_sparse_jac}\n-----------------------------------------------------------------------------\n*/\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\n\\file atomic/two_rev_sparse_jac.hpp\nAtomic reverse mode Jacobian sparsity patterns.\n*/\n/*!\nLink, after case split, from rev_jac_sweep to atomic_base\n\n\\param q [in]\nis the row dimension for the Jacobian sparsity patterns\n\n\\param rt [out]\nis the tansposed Jacobian sparsity pattern w.r.t to range variables y\n\n\\param st [in]\nis the tansposed Jacobian sparsity pattern for the argument variables x\n\n\\param x\nis the integer value for x arguments that are parameters.\n*/\ntemplate <class Base>\nbool atomic_base<Base>::rev_sparse_jac(\n    size_t                                  q  ,\n    const vector< std::set<size_t> >&       rt ,\n             vector< std::set<size_t> >&       st ,\n    const vector<Base>&                     x  )\n{   return false; }\ntemplate <class Base>\nbool atomic_base<Base>::rev_sparse_jac(\n    size_t                                  q  ,\n    const vector<bool>&                     rt ,\n             vector<bool>&                     st ,\n    const vector<Base>&                     x  )\n{   return false; }\ntemplate <class Base>\nbool atomic_base<Base>::rev_sparse_jac(\n    size_t                                  q  ,\n    const vectorBool&                       rt ,\n             vectorBool&                       st ,\n    const vector<Base>&                     x  )\n{   return false; }\n// deprecated versions\ntemplate <class Base>\nbool atomic_base<Base>::rev_sparse_jac(\n    size_t                                  q  ,\n    const vector< std::set<size_t> >&       rt ,\n             vector< std::set<size_t> >&       st )\n{   return false; }\ntemplate <class Base>\nbool atomic_base<Base>::rev_sparse_jac(\n    size_t                                  q  ,\n    const vector<bool>&                     rt ,\n             vector<bool>&                     st )\n{   return false; }\ntemplate <class Base>\nbool atomic_base<Base>::rev_sparse_jac(\n    size_t                                  q  ,\n    const vectorBool&                       rt ,\n             vectorBool&                       st )\n{   return false; }\n\n/*!\nLink, before case split, from rev_jac_sweep to atomic_base.\n\n\\tparam InternalSparsity\nIs the used internally for sparsity calculations; i.e.,\nsparse_pack or sparse_list.\n\n\\param x\nis parameter arguments to the function, other components are nan.\n\n\\param x_index\nis the variable index, on the tape, for the arguments to this function.\nThis size of x_index is n, the number of arguments to this function.\n\n\\param y_index\nis the variable index, on the tape, for the results for this function.\nThis size of y_index is m, the number of results for this function.\n\n\\param var_sparsity\nOn input, for i = 0, ... , m-1, the sparsity pattern with index y_index[i],\nis the sparsity for the i-th argument to this atomic function.\nOn output, for j = 0, ... , n-1, the sparsity pattern with index x_index[j],\nthe sparsity has been updated to remove y as a function of x.\n*/\ntemplate <class Base>\ntemplate <class InternalSparsity>\nbool atomic_base<Base>::rev_sparse_jac(\n    const vector<Base>&              x            ,\n    const vector<size_t>&            x_index      ,\n    const vector<size_t>&            y_index      ,\n    InternalSparsity&                var_sparsity )\n{   //\n    // pod_x_index, pod_y_index\n    local::pod_vector<size_t> pod_x_index( x_index.size() );\n    local::pod_vector<size_t> pod_y_index( y_index.size() );\n    for(size_t j = 0; j < x_index.size(); ++j)\n        pod_x_index[j] = x_index[j];\n    for(size_t i = 0; i < y_index.size(); ++i)\n        pod_y_index[i] = y_index[i];\n    //\n    // initial results may be non-empty during reverse mode\n    size_t q           = var_sparsity.end();\n    bool   input_empty = false;\n    bool   zero_empty  = true;\n    bool   transpose   = false;\n    size_t n           = pod_x_index.size();\n    bool   ok          = false;\n    size_t thread      = thread_alloc::thread_num();\n    allocate_work(thread);\n    //\n    std::string msg    = \": atomic_base.rev_sparse_jac: returned false\";\n    if( sparsity_ == pack_sparsity_enum )\n    {   vectorBool& pack_rt ( work_[thread]->pack_r );\n        vectorBool& pack_st ( work_[thread]->pack_s );\n        local::sparse::get_internal_pattern(\n            transpose, pod_y_index, var_sparsity, pack_rt\n        );\n        //\n        pack_st.resize(n * q );\n        ok = rev_sparse_jac(q, pack_rt, pack_st, x);\n        if( ! ok )\n            ok = rev_sparse_jac(q, pack_rt, pack_st);\n        if( ! ok )\n        {   msg = atomic_name() + msg + \" sparsity = pack_sparsity_enum\";\n            CPPAD_ASSERT_KNOWN(false, msg.c_str());\n        }\n        local::sparse::set_internal_pattern(zero_empty, input_empty,\n            transpose, pod_x_index, var_sparsity, pack_st\n        );\n    }\n    else if( sparsity_ == bool_sparsity_enum )\n    {   vector<bool>& bool_rt ( work_[thread]->bool_r );\n        vector<bool>& bool_st ( work_[thread]->bool_s );\n        local::sparse::get_internal_pattern(\n            transpose, pod_y_index, var_sparsity, bool_rt\n        );\n        bool_st.resize(n * q );\n        ok = rev_sparse_jac(q, bool_rt, bool_st, x);\n        if( ! ok )\n            ok = rev_sparse_jac(q, bool_rt, bool_st);\n        if( ! ok )\n        {   msg = atomic_name() + msg + \" sparsity = bool_sparsity_enum\";\n            CPPAD_ASSERT_KNOWN(false, msg.c_str());\n        }\n        local::sparse::set_internal_pattern(zero_empty, input_empty,\n            transpose, pod_x_index, var_sparsity, bool_st\n        );\n    }\n    else\n    {   CPPAD_ASSERT_UNKNOWN( sparsity_ == set_sparsity_enum );\n        vector< std::set<size_t> >& set_rt ( work_[thread]->set_r );\n        vector< std::set<size_t> >& set_st ( work_[thread]->set_s );\n        local::sparse::get_internal_pattern(\n            transpose, pod_y_index, var_sparsity, set_rt\n        );\n        set_st.resize(n);\n        ok = rev_sparse_jac(q, set_rt, set_st, x);\n        if( ! ok )\n            ok = rev_sparse_jac(q, set_rt, set_st);\n        if( ! ok )\n        {   msg = atomic_name() + msg + \" sparsity = set_sparsity_enum\";\n            CPPAD_ASSERT_KNOWN(false, msg.c_str());\n        }\n        local::sparse::set_internal_pattern(zero_empty, input_empty,\n            transpose, pod_x_index, var_sparsity, set_st\n        );\n    }\n    return ok;\n}\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/atomic/two/reverse.hpp",
    "content": "# ifndef CPPAD_CORE_ATOMIC_TWO_REVERSE_HPP\n# define CPPAD_CORE_ATOMIC_TWO_REVERSE_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_two_reverse app}\n{xrst_spell\n    apx\n    apy\n    atx\n    aty\n    px\n    py\n    tx\n}\n\nAtomic Reverse Mode\n###################\n\nSyntax\n******\n\nBase\n====\n\n    *ok* = *afun* . ``reverse`` ( *q* , *tx* , *ty* , *px* , *py* )\n\nThis syntax is used by *f* . ``Forward`` where *f* has prototype\n\n    ``ADFun`` < *Base* > *f*\n\nand *afun* is used in *f* .\n\nAD<Base>\n========\n\n    *ok* = *afun* . ``reverse`` ( *q* , *atx* , *aty* , *apx* , *apy* )\n\nThis syntax is used by *af* . ``Forward`` where *af* has prototype\n\n    ``ADFun< AD<`` *Base* > , *Base* > *af*\n\nand *afun* is used in *af* (see :ref:`base2ad-name` ).\n\nPurpose\n*******\nThis function is used by :ref:`Reverse-name`\nto compute derivatives.\n\nImplementation\n**************\nIf you are using\n:ref:`Reverse-name` mode,\nthis virtual function must be defined by the\n:ref:`atomic_two_ctor@atomic_user` class.\nIt can just return *ok* == ``false``\n(and not compute anything) for values\nof *q* that are greater than those used by your\n:ref:`Reverse-name` mode calculations.\n\nq\n*\nThe argument *q* has prototype\n\n    ``size_t`` *q*\n\nIt specifies the highest order Taylor coefficient that\ncomputing the derivative of.\n\ntx\n**\nThe argument *tx* has prototype\n\n    ``const CppAD::vector<`` *Base* >& *tx*\n\nand *tx* . ``size`` () == ( *q* +1)* *n* .\nFor :math:`j = 0 , \\ldots , n-1` and :math:`k = 0 , \\ldots , q`,\nwe use the Taylor coefficient notation\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        x_j^k    & = & tx [ j * ( q + 1 ) + k ]\n        \\\\\n        X_j (t)  & = & x_j^0 + x_j^1 t^1 + \\cdots + x_j^q t^q\n    \\end{eqnarray}\n\nNote that superscripts represent an index for :math:`x_j^k`\nand an exponent for :math:`t^k`.\nAlso note that the Taylor coefficients for :math:`X(t)` correspond\nto the derivatives of :math:`X(t)` at :math:`t = 0` in the following way:\n\n.. math::\n\n    x_j^k = \\frac{1}{ k ! } X_j^{(k)} (0)\n\natx\n***\nThe argument *atx* has prototype\n\n    ``const CppAD::vector< AD<`` *Base* > >& *atx*\n\nOtherwise, *atx* specifications are the same as for *tx* .\n\nty\n**\nThe argument *ty* has prototype\n\n    ``const CppAD::vector<`` *Base* >& *ty*\n\nand *tx* . ``size`` () == ( *q* +1)* *m* .\nFor :math:`i = 0 , \\ldots , m-1` and :math:`k = 0 , \\ldots , q`,\nwe use the Taylor coefficient notation\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        Y_i (t)  & = & f_i [ X(t) ]\n        \\\\\n        Y_i (t)  & = & y_i^0 + y_i^1 t^1 + \\cdots + y_i^q t^q + o ( t^q )\n        \\\\\n        y_i^k    & = & ty [ i * ( q + 1 ) + k ]\n    \\end{eqnarray}\n\nwhere :math:`o( t^q ) / t^q \\rightarrow 0` as :math:`t \\rightarrow 0`.\nNote that superscripts represent an index for :math:`y_j^k`\nand an exponent for :math:`t^k`.\nAlso note that the Taylor coefficients for :math:`Y(t)` correspond\nto the derivatives of :math:`Y(t)` at :math:`t = 0` in the following way:\n\n.. math::\n\n    y_j^k = \\frac{1}{ k ! } Y_j^{(k)} (0)\n\naty\n***\nThe argument *aty* has prototype\n\n    ``const CppAD::vector< AD<`` *Base* > >& *aty*\n\nOtherwise, *aty* specifications are the same as for *ty* .\n\nF\n*\nWe use the notation :math:`\\{ x_j^k \\} \\in \\B{R}^{n \\times (q+1)}` for\n\n.. math::\n\n    \\{ x_j^k \\W{:} j = 0 , \\ldots , n-1, k = 0 , \\ldots , q \\}\n\nWe use the notation :math:`\\{ y_i^k \\} \\in \\B{R}^{m \\times (q+1)}` for\n\n.. math::\n\n    \\{ y_i^k \\W{:} i = 0 , \\ldots , m-1, k = 0 , \\ldots , q \\}\n\nWe define the function\n:math:`F : \\B{R}^{n \\times (q+1)} \\rightarrow \\B{R}^{m \\times (q+1)}` by\n\n.. math::\n\n    y_i^k = F_i^k [ \\{ x_j^k \\} ]\n\nNote that\n\n.. math::\n\n    F_i^0 ( \\{ x_j^k \\} ) = f_i ( X(0) )  = f_i ( x^0 )\n\nWe also note that\n:math:`F_i^\\ell ( \\{ x_j^k \\} )` is a function of\n:math:`x^0 , \\ldots , x^\\ell`\nand is determined by the derivatives of :math:`f_i (x)`\nup to order :math:`\\ell`.\n\nG, H\n****\nWe use :math:`G : \\B{R}^{m \\times (q+1)} \\rightarrow \\B{R}`\nto denote an arbitrary scalar valued function of :math:`\\{ y_i^k \\}`.\nWe use :math:`H : \\B{R}^{n \\times (q+1)} \\rightarrow \\B{R}`\ndefined by\n\n.. math::\n\n    H ( \\{ x_j^k \\} ) = G[ F( \\{ x_j^k \\} ) ]\n\npy\n**\nThe argument *py* has prototype\n\n    ``const CppAD::vector<`` *Base* >& *py*\n\nand *py* . ``size`` () == ``m`` * ( *q* +1) .\nFor :math:`i = 0 , \\ldots , m-1`, :math:`k = 0 , \\ldots , q`,\n\n.. math::\n\n    py[ i * (q + 1 ) + k ] = \\partial G / \\partial y_i^k\n\napy\n***\nThe argument *apy* has prototype\n\n    ``const CppAD::vector< AD<`` *Base* > >& *apy*\n\nOtherwise, *apy* specifications are the same as for *py* .\n\npx\n==\nThe *px* has prototype\n\n    ``CppAD::vector<`` *Base* >& *px*\n\nand *px* . ``size`` () == ``n`` * ( *q* +1) .\nThe input values of the elements of *px*\nare not specified (must not matter).\nUpon return,\nfor :math:`j = 0 , \\ldots , n-1` and :math:`\\ell = 0 , \\ldots , q`,\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    px [ j * (q + 1) + \\ell ] & = & \\partial H / \\partial x_j^\\ell\n    \\\\\n    & = &\n    ( \\partial G / \\partial \\{ y_i^k \\} ) \\cdot\n        ( \\partial \\{ y_i^k \\} / \\partial x_j^\\ell )\n    \\\\\n    & = &\n    \\sum_{k=0}^q\n    \\sum_{i=0}^{m-1}\n    ( \\partial G / \\partial y_i^k ) ( \\partial y_i^k / \\partial x_j^\\ell )\n    \\\\\n    & = &\n    \\sum_{k=\\ell}^q\n    \\sum_{i=0}^{m-1}\n    py[ i * (q + 1 ) + k ] ( \\partial F_i^k / \\partial x_j^\\ell )\n    \\end{eqnarray}\n\nNote that we have used the fact that for :math:`k < \\ell`,\n:math:`\\partial F_i^k / \\partial x_j^\\ell = 0`.\n\napx\n***\nThe argument *apx* has prototype\n\n    ``CppAD::vector< AD<`` *Base* > >& *apx*\n\nOtherwise, *apx* specifications are the same as for *px* .\n\nok\n**\nThe return value *ok* has prototype\n\n    ``bool`` *ok*\n\nIf it is ``true`` , the corresponding evaluation succeeded,\notherwise it failed.\n\n{xrst_end atomic_two_reverse}\n-----------------------------------------------------------------------------\n*/\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\n\\file atomic/two_reverse.hpp\nAtomic reverse mode.\n*/\n/*!\nLink from reverse mode sweep to users routine.\n\n\\param q [in]\nhighest order for this reverse mode calculation.\n\n\\param tx [in]\nTaylor coefficients corresponding to x for this calculation.\n\n\\param ty [in]\nTaylor coefficient corresponding to y for this calculation\n\n\\param px [out]\nPartials w.r.t. the x Taylor coefficients.\n\n\\param py [in]\nPartials w.r.t. the y Taylor coefficients.\n\nSee atomic_reverse mode use documentation\n*/\ntemplate <class Base>\nbool atomic_base<Base>::reverse(\n    size_t                    q  ,\n    const vector<Base>&       tx ,\n    const vector<Base>&       ty ,\n             vector<Base>&       px ,\n    const vector<Base>&       py )\n{   return false; }\n\ntemplate <class Base>\nbool atomic_base<Base>::reverse(\n    size_t                    q  ,\n    const vector< AD<Base> >& atx ,\n    const vector< AD<Base> >& aty ,\n             vector< AD<Base> >& apx ,\n    const vector< AD<Base> >& apy )\n{   return false; }\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/azmul.hpp",
    "content": "# ifndef CPPAD_CORE_AZMUL_HPP\n# define CPPAD_CORE_AZMUL_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin azmul}\n{xrst_spell\n    ieee\n}\n\nAbsolute Zero Multiplication\n############################\n\nSyntax\n******\n| *z* = ``azmul`` ( *x* , *y* )\n\nPurpose\n*******\nEvaluates multiplication with an absolute zero\nfor any of the possible types listed below.\nThe result is given by\n\n.. math::\n\n    z = \\left\\{ \\begin{array}{ll}\n        0          & {\\rm if} \\; x = 0 \\\\\n        x \\cdot y  & {\\rm otherwise}\n    \\end{array} \\right.\n\nNote if *x* is zero and *y* is infinity,\nieee multiplication would result in not a number whereas\n*z* would be zero.\n\nBase\n****\nIf *Base* satisfies the\n:ref:`base type requirements<base_require-name>`\nand arguments *x* , *y* have prototypes\n\n| |tab| ``const`` *Base* & *x*\n| |tab| ``const`` *Base* & *y*\n\nthen the result *z* has prototype\n\n    *Base* *z*\n\nAD<Base>\n********\nIf the arguments *x* , *y* have prototype\n\n| |tab| ``const AD`` < *Base* >& *x*\n| |tab| ``const AD`` < *Base* >& *y*\n\nthen the result *z* has prototype\n\n    ``AD`` < *Base* > *z*\n\nVecAD<Base>\n***********\nIf the arguments *x* , *y* have prototype\n\n| |tab| ``const VecAD`` < *Base* >:: ``reference&`` *x*\n| |tab| ``const VecAD`` < *Base* >:: ``reference&`` *y*\n\nthen the result *z* has prototype\n\n    ``AD`` < *Base* > *z*\n\nExample\n*******\n{xrst_toc_hidden\n    example/general/azmul.cpp\n}\nThe file\n:ref:`azmul.cpp-name`\nis an examples and tests of this function.\n\n{xrst_end azmul}\n*/\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n// ==========================================================================\n\n// case where x and y are AD<Base> -------------------------------------------\ntemplate <class Base> AD<Base>\nazmul(const AD<Base>& x, const AD<Base>& y)\n{\n    // compute the Base part\n    AD<Base> result;\n    result.value_ = azmul(x.value_, y.value_);\n\n    // check if there is a recording in progress\n    local::ADTape<Base>* tape = AD<Base>::tape_ptr();\n    if( tape == nullptr )\n        return result;\n    tape_id_t tape_id = tape->id_;\n    // tape_id cannot match the default value for tape_id_; i.e., 0\n    CPPAD_ASSERT_UNKNOWN( tape_id > 0 );\n\n    // check if x and y tapes match\n    bool match_x  = x.tape_id_  == tape_id;\n    bool match_y  = y.tape_id_  == tape_id;\n\n    // check if x and y are dynamic parameters\n    bool dyn_x  = match_x  & (x.ad_type_ == dynamic_enum);\n    bool dyn_y  = match_y  & (y.ad_type_ == dynamic_enum);\n\n    // check if x and y are variables\n    bool var_x  = match_x  & (x.ad_type_ != dynamic_enum);\n    bool var_y  = match_y  & (y.ad_type_ != dynamic_enum);\n\n    CPPAD_ASSERT_KNOWN(\n        x.tape_id_ == y.tape_id_ || ! match_x || ! match_y ,\n        \"azmul: AD variables or dynamic parameters on different threads.\"\n    );\n    if( var_x )\n    {   if( var_y )\n        {   // result = azmul(variable, variable)\n            CPPAD_ASSERT_UNKNOWN( local::NumRes(local::ZmulvvOp) == 1 );\n            CPPAD_ASSERT_UNKNOWN( local::NumArg(local::ZmulvvOp) == 2 );\n\n            // put operand addresses in tape\n            tape->Rec_.PutArg(x.taddr_, y.taddr_);\n\n            // put operator in the tape\n            result.taddr_ = tape->Rec_.PutOp(local::ZmulvvOp);\n\n            // make result a variable\n            result.tape_id_ = tape_id;\n            result.ad_type_ = variable_enum;\n        }\n        else if( ( ! dyn_y ) && IdenticalZero( y.value_ ) )\n        {   // result = variable * 0\n        }\n        else if( ( ! dyn_y ) && IdenticalOne( y.value_ ) )\n        {   // result = variable * 1\n            result.make_variable(x.tape_id_, x.taddr_);\n        }\n        else\n        {   // result = zmul(variable, parameter)\n            CPPAD_ASSERT_UNKNOWN( local::NumRes(local::ZmulvpOp) == 1 );\n            CPPAD_ASSERT_UNKNOWN( local::NumArg(local::ZmulvpOp) == 2 );\n\n            // put operand addresses in tape\n            addr_t p = y.taddr_;\n            if( ! dyn_y )\n                p = tape->Rec_.put_con_par(y.value_);\n            tape->Rec_.PutArg(x.taddr_, p);\n\n            // put operator in the tape\n            result.taddr_ = tape->Rec_.PutOp(local::ZmulvpOp);\n\n            // make result a variable\n            result.tape_id_ = tape_id;\n            result.ad_type_ = variable_enum;\n        }\n    }\n    else if( var_y )\n    {   if( ( ! dyn_x ) && IdenticalZero(x.value_) )\n        {   // result = 0 * variable\n        }\n        else if( ( ! dyn_x ) && IdenticalOne( x.value_ ) )\n        {   // result = 1 * variable\n            result.make_variable(y.tape_id_, y.taddr_);\n        }\n        else\n        {   // result = zmul(parameter, variable)\n            CPPAD_ASSERT_UNKNOWN( local::NumRes(local::ZmulpvOp) == 1 );\n            CPPAD_ASSERT_UNKNOWN( local::NumArg(local::ZmulpvOp) == 2 );\n\n            // put operand addresses in tape\n            addr_t p = x.taddr_;\n            if( ! dyn_x )\n                p = tape->Rec_.put_con_par(x.value_);\n            tape->Rec_.PutArg(p, y.taddr_);\n\n            // put operator in the tape\n            result.taddr_ = tape->Rec_.PutOp(local::ZmulpvOp);\n\n            // make result a variable\n            result.tape_id_ = tape_id;\n            result.ad_type_ = variable_enum;\n        }\n    }\n    else if( dyn_x | dyn_y )\n    {   if( (! dyn_x) && IdenticalZero(x.value_) )\n        {    // result = 0 * dynamic\n        }\n        else if ( ( ! dyn_y ) && IdenticalZero(y.value_) )\n        {    // result = dynamic * 0\n        }\n        else if( ( ! dyn_x ) && IdenticalOne(x.value_) )\n        {    // result = 1 * dynamic\n            result.make_dynamic(y.tape_id_, y.taddr_);\n        }\n        else if( ( ! dyn_y ) && IdenticalOne(y.value_) )\n        {    // result = dynamic * 1\n            result.make_dynamic(x.tape_id_, x.taddr_ );\n        }\n        else\n        {\n            addr_t arg0 = x.taddr_;\n            addr_t arg1 = y.taddr_;\n            if( ! dyn_x )\n            arg0 = tape->Rec_.put_con_par(x.value_);\n            if( ! dyn_y )\n            arg1 = tape->Rec_.put_con_par(y.value_);\n            //\n            // parameters with a dynamic parameter result\n            result.taddr_   = tape->Rec_.put_dyn_par(\n                result.value_, local::zmul_dyn,   arg0, arg1\n            );\n            result.tape_id_ = tape_id;\n            result.ad_type_ = dynamic_enum;\n        }\n    }\n    return result;\n}\n// =========================================================================\n// Fold operations into case above\n// -------------------------------------------------------------------------\n// Operations with VecAD_reference<Base> and AD<Base> only\n\ntemplate <class Base> AD<Base>\nazmul(const AD<Base>& x, const VecAD_reference<Base>& y)\n{   return azmul(x, y.ADBase()); }\n\ntemplate <class Base> AD<Base>\nazmul(const VecAD_reference<Base>& x, const VecAD_reference<Base>& y)\n{   return azmul(x.ADBase(), y.ADBase()); }\n\ntemplate <class Base> AD<Base>\nazmul(const VecAD_reference<Base>& x, const AD<Base>& y)\n{   return azmul(x.ADBase(), y); }\n// -------------------------------------------------------------------------\n// Operations with Base\n\ntemplate <class Base> AD<Base>\nazmul(const Base& x, const AD<Base>& y)\n{   return azmul(AD<Base>(x), y); }\n\ntemplate <class Base> AD<Base>\nazmul(const Base& x, const VecAD_reference<Base>& y)\n{   return azmul(AD<Base>(x), y.ADBase()); }\n\ntemplate <class Base> AD<Base>\nazmul(const AD<Base>& x, const Base& y)\n{   return azmul(x, AD<Base>(y)); }\n\ntemplate <class Base> AD<Base>\nazmul(const VecAD_reference<Base>& x, const Base& y)\n{   return azmul(x.ADBase(), AD<Base>(y)); }\n\n// ==========================================================================\n} // END_CPPAD_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/base2ad.hpp",
    "content": "# ifndef CPPAD_CORE_BASE2AD_HPP\n# define CPPAD_CORE_BASE2AD_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin base2ad}\n\nCreate an AD<Base> Function From a Base Function\n################################################\n\nSyntax\n******\n| *af* = *f* . ``base2ad`` ()\n\nSee Also\n********\n:ref:`mul_level-name`\n\nBase\n****\nThis is the base type used to recorded the operation sequence in *f*\nand *af* ; i.e., the type ``AD`` < *Base* > was used to record\nthe operation sequence.\n\nf\n*\nThis object has prototype\n\n    ``ADFun`` < *Base* > *f*\n\nIt does it's derivative calculations using the type *Base* .\n\naf\n**\nThis object has prototype\n\n    ``ADFun< AD<`` *Base* > , *Base* > *af*\n\nIt has the same operation sequence as *f* ,\nbut it does it's derivative calculations using the type\n``AD`` < *Base>* .\nThis enables one to record new functions that are defined\nusing derivatives of the function *f* .\nInitially, there are no Taylor coefficients stored in *af* and\n:ref:`af.size_order()<size_order-name>` is zero.\n{xrst_toc_hidden\n    example/general/base2ad.cpp\n    example/general/base2vec_ad.cpp\n}\nExample\n*******\nThe file :ref:`base2ad.cpp-name`\ncontains an example and test of this operation.\n\nVecAD\n*****\nForward mode on a ``base2ad`` function does not preserve\n:ref:`VecAD-name` operations (which might be expected); see the\n:ref:`base2vec_ad.cpp-name` example.\n\n{xrst_end base2ad}\n----------------------------------------------------------------------------\n*/\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\n\\file base2ad.hpp\n*/\n/// Create an ADFun< AD<Base>, Base > from this ADFun<Base>\ntemplate <class Base, class RecBase>\nADFun< AD<Base>, RecBase > ADFun<Base,RecBase>::base2ad(void) const\n{   ADFun< AD<Base>, RecBase > fun;\n    //\n    // bool values\n    fun.has_been_optimized_        = has_been_optimized_;\n    fun.check_for_nan_             = check_for_nan_;\n    //\n    // size_t values\n    fun.compare_change_count_      = compare_change_count_;\n    fun.compare_change_number_     = compare_change_number_;\n    fun.compare_change_op_index_   = compare_change_op_index_;\n    CPPAD_ASSERT_UNKNOWN( fun.num_order_taylor_ == 0 ) ;\n    CPPAD_ASSERT_UNKNOWN( fun.cap_order_taylor_ == 0 );\n    CPPAD_ASSERT_UNKNOWN( fun.num_direction_taylor_ == 0 );\n    fun.num_var_tape_              = num_var_tape_;\n    //\n    // pod_vector objects\n    fun.ind_taddr_                 = ind_taddr_;\n    fun.dep_taddr_                 = dep_taddr_;\n    fun.dep_parameter_             = dep_parameter_;\n    fun.cskip_op_                  = cskip_op_;\n    fun.load_op2var_               = load_op2var_;\n    //\n    // pod_maybe_vector< AD<Base> > = pod_maybe_vector<Base>\n    CPPAD_ASSERT_UNKNOWN( fun.taylor_.size() == 0 );\n    //\n    // player\n    // (uses move semantics)\n    fun.play_ = play_.base2ad();\n    //\n    // subgraph\n    fun.subgraph_info_ = subgraph_info_;\n    //\n    // sparse_pack\n    fun.for_jac_sparse_pack_ = for_jac_sparse_pack_;\n    //\n    // sparse_list\n    fun.for_jac_sparse_set_  = for_jac_sparse_set_;\n    //\n    return fun;\n}\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/base_complex.hpp",
    "content": "# ifndef CPPAD_CORE_BASE_COMPLEX_HPP\n# define CPPAD_CORE_BASE_COMPLEX_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/configure.hpp>\n# include <limits>\n# include <complex>\n\n/*\n{xrst_begin base_complex.hpp}\n{xrst_spell\n    azmul\n    isnan\n}\n\nEnable use of AD<Base> where Base is std::complex<double>\n#########################################################\n{xrst_toc_hidden\n    example/general/complex_poly.cpp\n}\nExample\n*******\nThe file :ref:`complex_poly.cpp-name` contains an example use of\n``std::complex<double>`` type for a CppAD *Base* type.\n\nInclude Order\n*************\nThis file is included before ``<cppad/cppad.hpp>``\nso it is necessary to define the error handler\nin addition to including\n:ref:`base_require.hpp<base_require@Include Order>`\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <limits>\n# include <complex>\n# include <cppad/base_require.hpp>\n# include <cppad/core/cppad_assert.hpp>\n\n/* {xrst_code}\n{xrst_spell_on}\n\nCondExpOp\n*********\nThe type ``std::complex<double>`` does not support the\n``<`` , ``<=`` , ``>=`` , and ``>`` operators; see\n:ref:`base_cond_exp@CondExpTemplate@Not Ordered` .\nHence these operators and ``CondExpOp`` function are defined by\n{xrst_spell_off}\n{xrst_code cpp} */\n# define CPPAD_TEMP(op)                                          \\\n    inline bool operator op(                                      \\\n        const std::complex<double>& left   ,                       \\\n        const std::complex<double>& right  )                       \\\n    {  CppAD::ErrorHandler::Call(                                 \\\n            true     , __LINE__ , __FILE__ ,                        \\\n            \"std::complex<double> \" #op \" std::complex<double>\" ,   \\\n            \"Error: std::complex is not an ordered type\"            \\\n        );                                                         \\\n        return false;                                              \\\n    }\nnamespace CppAD {\n    CPPAD_TEMP(<)\n    CPPAD_TEMP(<=)\n    CPPAD_TEMP(>=)\n    CPPAD_TEMP(>)\n    inline std::complex<double> CondExpOp(\n        enum CppAD::CompareOp      cop        ,\n        const std::complex<double> &left      ,\n        const std::complex<double> &right     ,\n        const std::complex<double> &trueCase  ,\n        const std::complex<double> &falseCase )\n    {  CppAD::ErrorHandler::Call(\n            true     , __LINE__ , __FILE__ ,\n            \"std::complex<float> CondExpOp(...)\",\n            \"Error: cannot use CondExp with a complex type\"\n        );\n        return std::complex<double>(0);\n    }\n}\n# undef CPPAD_TEMP\n/* {xrst_code}\n{xrst_spell_on}\n\n\nCondExpRel\n**********\nThe :ref:`CPPAD_COND_EXP_REL<base_cond_exp@CondExpRel>` macro invocation\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    CPPAD_COND_EXP_REL( std::complex<double> )\n}\n/* {xrst_code}\n{xrst_spell_on}\nused ``CondExpOp`` above to\ndefine ``CondExp`` *Rel* for ``std::complex<double>`` arguments\nand *Rel* equal to\n``Lt`` , ``Le`` , ``Eq`` , ``Ge`` , and ``Gt`` .\n\nEqualOpSeq\n**********\nComplex numbers do not carry operation sequence information.\nThus they are equal in this sense if and only if there values are equal.\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    inline bool EqualOpSeq(\n        const std::complex<double> &x ,\n        const std::complex<double> &y )\n    {  return x == y;\n    }\n}\n/* {xrst_code}\n{xrst_spell_on}\n\nIdentical\n*********\nComplex numbers do not carry operation sequence information.\nThus they are all parameters so the identical functions just check values.\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    inline bool IdenticalCon(const std::complex<double> &x)\n    {  return true; }\n    inline bool IdenticalZero(const std::complex<double> &x)\n    {  return (x == std::complex<double>(0., 0.) ); }\n    inline bool IdenticalOne(const std::complex<double> &x)\n    {  return (x == std::complex<double>(1., 0.) ); }\n    inline bool IdenticalEqualCon(\n        const std::complex<double> &x, const std::complex<double> &y)\n    {  return (x == y); }\n}\n/* {xrst_code}\n{xrst_spell_on}\n\nOrdered\n*******\nComplex types do not support comparison operators,\n{xrst_spell_off}\n{xrst_code cpp} */\n# undef  CPPAD_USER_MACRO\n# define CPPAD_USER_MACRO(Fun)                                     \\\ninline bool Fun(const std::complex<double>& x)                     \\\n{      CppAD::ErrorHandler::Call(                                  \\\n                    true     , __LINE__ , __FILE__ ,                    \\\n                    #Fun\"(x)\",                                          \\\n                    \"Error: cannot use \" #Fun \" with x complex<double> \" \\\n         );                                                          \\\n         return false;                                               \\\n}\nnamespace CppAD {\n    CPPAD_USER_MACRO(LessThanZero)\n    CPPAD_USER_MACRO(LessThanOrZero)\n    CPPAD_USER_MACRO(GreaterThanOrZero)\n    CPPAD_USER_MACRO(GreaterThanZero)\n    inline bool abs_geq(\n        const std::complex<double>& x ,\n        const std::complex<double>& y )\n    {  return std::abs(x) >= std::abs(y); }\n}\n/* {xrst_code}\n{xrst_spell_on}\n\nInteger\n*******\nThe implementation of this function must agree\nwith the CppAD user specifications for complex arguments to the\n:ref:`Integer<Integer@x@Complex Types>` function:\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    inline int Integer(const std::complex<double> &x)\n    {  return static_cast<int>( x.real() ); }\n}\n/* {xrst_code}\n{xrst_spell_on}\n\nazmul\n*****\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    CPPAD_AZMUL( std::complex<double> )\n}\n/* {xrst_code}\n{xrst_spell_on}\n\nisnan\n*****\nThe gcc 4.1.1 compiler defines the function\n\n    ``int std::complex<double>::isnan`` ( ``std::complex<double>`` *z*  )\n\n(which is not specified in the C++ 1998 standard ISO/IEC 14882).\nThis causes an ambiguity between the function above and the CppAD\n:ref:`isnan<nan-name>` template function.\nWe avoid this ambiguity by defining a non-template version of\nthis function in the CppAD namespace.\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    inline bool isnan(const std::complex<double>& z)\n    {  return (z != z);\n    }\n}\n/* {xrst_code}\n{xrst_spell_on}\n\nValid Unary Math\n****************\nThe following macro invocations define the standard unary\nmath functions that are valid with complex arguments and are\nrequired to use ``AD< std::complex<double> >`` .\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    CPPAD_STANDARD_MATH_UNARY(std::complex<double>, cos)\n    CPPAD_STANDARD_MATH_UNARY(std::complex<double>, cosh)\n    CPPAD_STANDARD_MATH_UNARY(std::complex<double>, exp)\n    CPPAD_STANDARD_MATH_UNARY(std::complex<double>, log)\n    CPPAD_STANDARD_MATH_UNARY(std::complex<double>, sin)\n    CPPAD_STANDARD_MATH_UNARY(std::complex<double>, sinh)\n    CPPAD_STANDARD_MATH_UNARY(std::complex<double>, sqrt)\n}\n/* {xrst_code}\n{xrst_spell_on}\n\nInvalid Unary Math\n******************\nThe following macro definition and invocations define the standard unary\nmath functions that are invalid with complex arguments and are\nrequired to use ``AD< std::complex<double> >`` .\n{xrst_spell_off}\n{xrst_code cpp} */\n# undef  CPPAD_USER_MACRO\n# define CPPAD_USER_MACRO(Fun)                                     \\\ninline std::complex<double> Fun(const std::complex<double>& x)     \\\n{      CppAD::ErrorHandler::Call(                                  \\\n                    true     , __LINE__ , __FILE__ ,                    \\\n                    #Fun\"(x)\",                                          \\\n                    \"Error: cannot use \" #Fun \" with x complex<double> \" \\\n         );                                                          \\\n         return std::complex<double>(0);                             \\\n}\nnamespace CppAD {\n    CPPAD_USER_MACRO(abs)\n    CPPAD_USER_MACRO(fabs)\n    CPPAD_USER_MACRO(acos)\n    CPPAD_USER_MACRO(asin)\n    CPPAD_USER_MACRO(atan)\n    CPPAD_USER_MACRO(sign)\n    CPPAD_USER_MACRO(asinh)\n    CPPAD_USER_MACRO(acosh)\n    CPPAD_USER_MACRO(atanh)\n    CPPAD_USER_MACRO(erf)\n    CPPAD_USER_MACRO(erfc)\n    CPPAD_USER_MACRO(expm1)\n    CPPAD_USER_MACRO(log1p)\n}\n/* {xrst_code}\n{xrst_spell_on}\n\npow\n***\nThe following defines a ``CppAD::pow`` function that\nis required to use ``AD< std::complex<double> >`` :\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    inline std::complex<double> pow(\n        const std::complex<double> &x ,\n        const std::complex<double> &y )\n    {  return std::pow(x, y); }\n}\n/* {xrst_code}\n{xrst_spell_on}\n\nnumeric_limits\n**************\nThe following defines the CppAD :ref:`numeric_limits-name`\nfor the type ``std::complex<double>`` :\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    CPPAD_NUMERIC_LIMITS(double, std::complex<double>)\n}\n/* {xrst_code}\n{xrst_spell_on}\n\nto_string\n*********\nThe following defines the function CppAD :ref:`to_string-name`\nfor the type ``std::complex<double>`` :\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    CPPAD_TO_STRING(std::complex<double>)\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end base_complex.hpp}\n*/\n# undef  CPPAD_USER_MACRO_ONE\n# define CPPAD_USER_MACRO_ONE(Fun)                                 \\\ninline bool Fun(const std::complex<float>& x)                      \\\n{       CppAD::ErrorHandler::Call(                                  \\\n                    true     , __LINE__ , __FILE__ ,                    \\\n                    #Fun\"(x)\",                                          \\\n                    \"Error: cannot use \" #Fun \" with x complex<float> \" \\\n         );                                                          \\\n         return false;                                               \\\n}\n# undef  CPPAD_USER_MACRO_TWO\n# define CPPAD_USER_MACRO_TWO(Fun)                                 \\\ninline std::complex<float> Fun(const std::complex<float>& x)       \\\n{       CppAD::ErrorHandler::Call(                                  \\\n                    true     , __LINE__ , __FILE__ ,                    \\\n                    #Fun\"(x)\",                                          \\\n                    \"Error: cannot use \" #Fun \" with x complex<float> \" \\\n         );                                                          \\\n         return std::complex<float>(0);                              \\\n}\nnamespace CppAD {\n    // CondExpOp ------------------------------------------------------\n    inline std::complex<float> CondExpOp(\n        enum CppAD::CompareOp      cop       ,\n        const std::complex<float> &left      ,\n        const std::complex<float> &right     ,\n        const std::complex<float> &trueCase  ,\n        const std::complex<float> &falseCase )\n    {   CppAD::ErrorHandler::Call(\n            true     , __LINE__ , __FILE__ ,\n            \"std::complex<float> CondExpOp(...)\",\n            \"Error: cannot use CondExp with a complex type\"\n        );\n        return std::complex<float>(0);\n    }\n    // CondExpRel --------------------------------------------------------\n    CPPAD_COND_EXP_REL( std::complex<float> )\n    // EqualOpSeq -----------------------------------------------------\n    inline bool EqualOpSeq(\n        const std::complex<float> &x ,\n        const std::complex<float> &y )\n    {   return x == y;\n    }\n    // Identical ------------------------------------------------------\n    inline bool IdenticalCon(const std::complex<float> &x)\n    {   return true; }\n    inline bool IdenticalZero(const std::complex<float> &x)\n    {   return (x == std::complex<float>(0., 0.) ); }\n    inline bool IdenticalOne(const std::complex<float> &x)\n    {   return (x == std::complex<float>(1., 0.) ); }\n    inline bool IdenticalEqualCon(\n        const std::complex<float> &x, const std::complex<float> &y)\n    {   return (x == y); }\n    // Ordered --------------------------------------------------------\n    CPPAD_USER_MACRO_ONE(LessThanZero)\n    CPPAD_USER_MACRO_ONE(LessThanOrZero)\n    CPPAD_USER_MACRO_ONE(GreaterThanOrZero)\n    CPPAD_USER_MACRO_ONE(GreaterThanZero)\n    inline bool abs_geq(\n        const std::complex<float>& x ,\n        const std::complex<float>& y )\n    {   return std::abs(x) >= std::abs(y); }\n    // Integer ------------------------------------------------------\n    inline int Integer(const std::complex<float> &x)\n    {   return static_cast<int>( x.real() ); }\n    // isnan -------------------------------------------------------------\n    inline bool isnan(const std::complex<float>& z)\n    {   return (z != z);\n    }\n    // Valid standard math functions --------------------------------\n    CPPAD_STANDARD_MATH_UNARY(std::complex<float>, cos)\n    CPPAD_STANDARD_MATH_UNARY(std::complex<float>, cosh)\n    CPPAD_STANDARD_MATH_UNARY(std::complex<float>, exp)\n    CPPAD_STANDARD_MATH_UNARY(std::complex<float>, log)\n    CPPAD_STANDARD_MATH_UNARY(std::complex<float>, sin)\n    CPPAD_STANDARD_MATH_UNARY(std::complex<float>, sinh)\n    CPPAD_STANDARD_MATH_UNARY(std::complex<float>, sqrt)\n    // Invalid standard math functions -------------------------------\n    CPPAD_USER_MACRO_TWO(abs)\n    CPPAD_USER_MACRO_TWO(acos)\n    CPPAD_USER_MACRO_TWO(asin)\n    CPPAD_USER_MACRO_TWO(atan)\n    CPPAD_USER_MACRO_TWO(sign)\n    // The pow function\n    inline std::complex<float> pow(\n        const std::complex<float> &x ,\n        const std::complex<float> &y )\n    {   return std::pow(x, y); }\n    // numeric_limits -------------------------------------------------\n    CPPAD_NUMERIC_LIMITS(float, std::complex<float>)\n    // to_string -------------------------------------------------\n    CPPAD_TO_STRING(std::complex<float>)\n}\n\n// undefine macros only used by this file\n# undef CPPAD_USER_MACRO\n# undef CPPAD_USER_MACRO_ONE\n# undef CPPAD_USER_MACRO_TWO\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/base_cond_exp.hpp",
    "content": "# ifndef CPPAD_CORE_BASE_COND_EXP_HPP\n# define CPPAD_CORE_BASE_COND_EXP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin base_cond_exp}\n{xrst_spell\n    adolc\n}\n\nBase Type Requirements for Conditional Expressions\n##################################################\n\nPurpose\n*******\nThese definitions are required by the user's code to support the\n``AD`` < *Base* > type for :ref:`CondExp-name` operations:\n\nCompareOp\n*********\nThe following ``enum`` type is used in the specifications below:\n::\n\n    namespace CppAD {\n    // The conditional expression operator enum type\n    enum CompareOp\n    {  CompareLt, // less than\n    CompareLe, // less than or equal\n    CompareEq, // equal\n    CompareGe, // greater than or equal\n    CompareGt, // greater than\n    CompareNe  // not equal\n    };\n    }\n\nCondExpTemplate\n***************\nThe type *Base* must support the syntax\n\n| |tab| *result* = ``CppAD::CondExpOp`` (\n| |tab| |tab| *cop* , *left* , *right* , *exp_if_true* , *exp_if_false*\n| |tab| )\n\nwhich computes implements the corresponding :ref:`CondExp-name`\nfunction when the result has prototype\n\n    *Base* *result*\n\nThe argument *cop* has prototype\n\n    ``enum CppAD::CompareOp`` *cop*\n\nThe other arguments have the prototype\n\n| |tab| ``const`` *Base* & *left*\n| |tab| ``const`` *Base* & *right*\n| |tab| ``const`` *Base* & *exp_if_true*\n| |tab| ``const`` *Base* & *exp_if_false*\n\nOrdered Type\n============\nIf *Base* is a relatively simple type\nthat supports\n``<`` , ``<=`` , ``==`` , ``>=`` , and ``>`` operators\nits ``CondExpOp`` function can be defined by\n\n| ``namespace CppAD`` {\n| |tab| ``inline`` *Base* ``CondExpOp`` (\n| |tab| ``enum CppAD::CompareOp`` *cop*             ,\n| |tab| ``const`` *Base* & *left*           ,\n| |tab| ``const`` *Base* & *right*          ,\n| |tab| ``const`` *Base* & *exp_if_true*    ,\n| |tab| ``const`` *Base* & *exp_if_false*   )\n| |tab| { ``return CondExpTemplate`` (\n| |tab| |tab| |tab| ``cop`` , ``left`` , ``right`` , ``trueCase`` , ``falseCase`` );\n| |tab| }\n| }\n\nFor example, see\n:ref:`double CondExpOp<base_alloc.hpp@CondExpOp>` .\nFor an example of and implementation of ``CondExpOp`` with\na more involved *Base* type see\n:ref:`adolc CondExpOp<base_adolc.hpp@CondExpOp>` .\n\nNot Ordered\n===========\nIf the type *Base* does not support ordering; i.e., does not support\nthe ``<`` , ``<=`` , ``>=`` , or ``>`` operator they should be defined\nas resulting in error when used; e.g.\n\n| ``namespace CppAD`` {\n| |tab| ``inline bool operator<`` (\n| |tab| ``const`` *Base* & *left*          ,\n| |tab| ``const`` *Base* & *right*         )\n| |tab| {  // ``attempt to use < operator with`` *Base* ``arguments``\n| |tab| |tab| ``assert`` (0);\n| |tab| |tab| ``return`` false;\n| |tab| }\n| }\n\nUsing the ``CondExpOp`` function does should also be defined a an error; e.g.,\n\n| ``namespace CppAD`` {\n| |tab| ``inline`` *Base* ``CondExpOp`` (\n| |tab| ``enum CompareOp`` *cop*            ,\n| |tab| ``const`` *Base* & *left*          ,\n| |tab| ``const`` *Base* & *right*         ,\n| |tab| ``const`` *Base* & *exp_if_true*   ,\n| |tab| ``const`` *Base* & *exp_if_false*  )\n| |tab| {  // ``attempt to use CondExp with a`` *Base* ``argument``\n| |tab| |tab| ``assert`` (0);\n| |tab| |tab| ``return`` *Base* (0);\n| |tab| }\n| }\n\nFor example, see\n:ref:`complex CondExpOp<base_complex.hpp@CondExpOp>` .\n\nCondExpRel\n**********\nThe macro invocation\n\n    ``CPPAD_COND_EXP_REL`` ( *Base* )\n\nuses ``CondExpOp`` above to define the following functions\n\n| |tab| ``CondExpLt`` ( *left* , *right* , *exp_if_true* , *exp_if_false* )\n| |tab| ``CondExpLe`` ( *left* , *right* , *exp_if_true* , *exp_if_false* )\n| |tab| ``CondExpEq`` ( *left* , *right* , *exp_if_true* , *exp_if_false* )\n| |tab| ``CondExpGe`` ( *left* , *right* , *exp_if_true* , *exp_if_false* )\n| |tab| ``CondExpGt`` ( *left* , *right* , *exp_if_true* , *exp_if_false* )\n\nwhere the arguments have type *Base* .\nThis should be done inside of the CppAD namespace.\nFor example, see\n:ref:`base_alloc<base_alloc.hpp@CondExpRel>` .\n\n{xrst_end base_cond_exp}\n*/\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n\n/*!\n\\file base_cond_exp.hpp\nCondExp operations that aid in meeting Base type requirements.\n*/\n\n/*!\n\\def CPPAD_COND_EXP_BASE_REL(Type, Rel, Op)\nThis macro defines the operation\n\\verbatim\n    CondExpRel(left, right, exp_if_true, exp_if_false)\n\\endverbatim\nThe argument Type is the Base type for this base require operation.\nThe argument Rel is one of Lt, Le, Eq, Ge, Gt.\nThe argument Op is the corresponding CompareOp value.\n*/\n# define CPPAD_COND_EXP_BASE_REL(Type, Rel, Op)       \\\n    inline Type CondExp##Rel(                        \\\n        const Type& left      ,                     \\\n        const Type& right     ,                     \\\n        const Type& exp_if_true  ,                  \\\n        const Type& exp_if_false )                  \\\n    {   return CondExpOp(Op, left, right, exp_if_true, exp_if_false); \\\n    }\n\n/*!\n\\def CPPAD_COND_EXP_REL(Type)\nThe macro defines the operations\n\\verbatim\n    CondExpLt(left, right, exp_if_true, exp_if_false)\n    CondExpLe(left, right, exp_if_true, exp_if_false)\n    CondExpEq(left, right, exp_if_true, exp_if_false)\n    CondExpGe(left, right, exp_if_true, exp_if_false)\n    CondExpGt(left, right, exp_if_true, exp_if_false)\n\\endverbatim\nThe argument Type is the Base type for this base require operation.\n*/\n# define CPPAD_COND_EXP_REL(Type)                     \\\n    CPPAD_COND_EXP_BASE_REL(Type, Lt, CompareLt)     \\\n    CPPAD_COND_EXP_BASE_REL(Type, Le, CompareLe)     \\\n    CPPAD_COND_EXP_BASE_REL(Type, Eq, CompareEq)     \\\n    CPPAD_COND_EXP_BASE_REL(Type, Ge, CompareGe)     \\\n    CPPAD_COND_EXP_BASE_REL(Type, Gt, CompareGt)\n\n/*!\nTemplate function to implement Conditional Expressions for simple types\nthat have comparison operators.\n\n\\tparam CompareType\nis the type of the left and right operands to the comparison operator.\n\n\\tparam ResultType\nis the type of the result, which is the same as CompareType except\nduring forward and reverse mode sparese calculations.\n\n\\param cop\nspedifies which comparison to use; i.e.,\n$code <$$,\n$code <=$$,\n$code ==$$,\n$code >=$$,\n$code >$$, or\n$code !=$$.\n\n\\param left\nis the left operand to the comparison operator.\n\n\\param right\nis the right operand to the comparison operator.\n\n\\param exp_if_true\nis the return value is the comparison results in true.\n\n\\param exp_if_false\nis the return value is the comparison results in false.\n\n\\return\nsee exp_if_true and exp_if_false above.\n*/\ntemplate <class CompareType, class ResultType>\nResultType CondExpTemplate(\n    enum  CompareOp            cop          ,\n    const CompareType&         left         ,\n    const CompareType&         right        ,\n    const ResultType&          exp_if_true  ,\n    const ResultType&          exp_if_false )\n{   ResultType returnValue;\n    switch( cop )\n    {\n        case CompareLt:\n        if( left < right )\n            returnValue = exp_if_true;\n        else\n            returnValue = exp_if_false;\n        break;\n\n        case CompareLe:\n        if( left <= right )\n            returnValue = exp_if_true;\n        else\n            returnValue = exp_if_false;\n        break;\n\n        case CompareEq:\n        if( left == right )\n            returnValue = exp_if_true;\n        else\n            returnValue = exp_if_false;\n        break;\n\n        case CompareGe:\n        if( left >= right )\n            returnValue = exp_if_true;\n        else\n            returnValue = exp_if_false;\n        break;\n\n        case CompareGt:\n        if( left > right )\n            returnValue = exp_if_true;\n        else\n            returnValue = exp_if_false;\n        break;\n\n        default:\n        CPPAD_ASSERT_UNKNOWN(0);\n        returnValue = exp_if_true;\n    }\n    return returnValue;\n}\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/base_double.hpp",
    "content": "# ifndef CPPAD_CORE_BASE_DOUBLE_HPP\n# define CPPAD_CORE_BASE_DOUBLE_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/configure.hpp>\n# include <limits>\n\n/*\n{xrst_begin base_double.hpp}\n{xrst_spell\n    azmul\n    namespaces\n}\n\nEnable use of AD<Base> where Base is double\n###########################################\n\nCondExpOp\n*********\nThe type ``double`` is a relatively simple type that supports\n``<`` , ``<=`` , ``==`` , ``>=`` , and ``>`` operators; see\n:ref:`base_cond_exp@CondExpTemplate@Ordered Type` .\nHence its ``CondExpOp`` function is defined by\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    inline double CondExpOp(\n        enum CompareOp      cop          ,\n        const double&       left         ,\n        const double&       right        ,\n        const double&       exp_if_true  ,\n        const double&       exp_if_false )\n    {  return CondExpTemplate(cop, left, right, exp_if_true, exp_if_false);\n    }\n}\n/* {xrst_code}\n{xrst_spell_on}\n\nCondExpRel\n**********\nThe :ref:`CPPAD_COND_EXP_REL<base_cond_exp@CondExpRel>` macro invocation\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    CPPAD_COND_EXP_REL(double)\n}\n/* {xrst_code}\n{xrst_spell_on}\nuses ``CondExpOp`` above to\ndefine ``CondExp`` *Rel* for ``double`` arguments\nand *Rel* equal to\n``Lt`` , ``Le`` , ``Eq`` , ``Ge`` , and ``Gt`` .\n\nEqualOpSeq\n**********\nThe type ``double`` is simple (in this respect) and so we define\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    inline bool EqualOpSeq(const double& x, const double& y)\n    {  return x == y; }\n}\n/* {xrst_code}\n{xrst_spell_on}\n\nIdentical\n*********\nThe type ``double`` is simple (in this respect) and so we define\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    inline bool IdenticalCon(const double& x)\n    {  return true; }\n    inline bool IdenticalZero(const double& x)\n    {  return (x == 0.); }\n    inline bool IdenticalOne(const double& x)\n    {  return (x == 1.); }\n    inline bool IdenticalEqualCon(const double& x, const double& y)\n    {  return (x == y); }\n}\n/* {xrst_code}\n{xrst_spell_on}\n\nInteger\n*******\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    inline int Integer(const double& x)\n    {  return static_cast<int>(x); }\n}\n/* {xrst_code}\n{xrst_spell_on}\n\nazmul\n*****\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    CPPAD_AZMUL( double )\n}\n/* {xrst_code}\n{xrst_spell_on}\n\nOrdered\n*******\nThe ``double`` type supports ordered comparisons\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    inline bool GreaterThanZero(const double& x)\n    {  return x > 0.; }\n    inline bool GreaterThanOrZero(const double& x)\n    {  return x >= 0.; }\n    inline bool LessThanZero(const double& x)\n    {  return x < 0.; }\n    inline bool LessThanOrZero(const double& x)\n    {  return x <= 0.; }\n    inline bool abs_geq(const double& x, const double& y)\n    {  return std::fabs(x) >= std::fabs(y); }\n}\n/* {xrst_code}\n{xrst_spell_on}\n\nUnary Standard Math\n*******************\nThe following macro invocations import the ``double`` versions of\nthe unary standard math functions into the ``CppAD`` namespace.\nImporting avoids ambiguity errors when using both the\n``CppAD`` and ``std`` namespaces.\nNote this also defines the :ref:`float<base_float.hpp@Unary Standard Math>`\nversions of these functions.\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    using std::acos;\n    using std::asin;\n    using std::atan;\n    using std::cos;\n    using std::cosh;\n    using std::exp;\n    using std::fabs;\n    using std::log;\n    using std::log10;\n    using std::sin;\n    using std::sinh;\n    using std::sqrt;\n    using std::tan;\n    using std::tanh;\n    using std::asinh;\n    using std::acosh;\n    using std::atanh;\n    using std::erf;\n    using std::erfc;\n    using std::expm1;\n    using std::log1p;\n}\n/* {xrst_code}\n{xrst_spell_on}\nThe absolute value function is special because its ``std`` name is\n``fabs``\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    inline double abs(const double& x)\n    {  return std::fabs(x); }\n}\n/* {xrst_code}\n{xrst_spell_on}\n\nsign\n****\nThe following defines the ``CppAD::sign`` function that\nis required to use ``AD<double>`` :\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    inline double sign(const double& x)\n    {  if( x > 0. )\n            return 1.;\n        if( x == 0. )\n            return 0.;\n        return -1.;\n    }\n}\n/* {xrst_code}\n{xrst_spell_on}\n\npow\n***\nThe following defines a ``CppAD::pow`` function that\nis required to use ``AD<double>`` .\nAs with the unary standard math functions,\nthis has the exact same signature as ``std::pow`` ,\nso use it instead of defining another function.\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    using std::pow;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\nnumeric_limits\n**************\nThe following defines the CppAD :ref:`numeric_limits-name`\nfor the type ``double`` :\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    CPPAD_NUMERIC_LIMITS(double, double)\n}\n/* {xrst_code}\n{xrst_spell_on}\n\nto_string\n*********\nThere is no need to define ``to_string`` for ``double``\nbecause it is defined by including ``cppad/utility/to_string.hpp`` ;\nsee :ref:`to_string-name` .\nSee :ref:`base_complex.hpp<base_complex.hpp@to_string>` for an example where\nit is necessary to define ``to_string`` for a *Base* type.\n\n{xrst_end base_double.hpp}\n*/\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/base_float.hpp",
    "content": "# ifndef CPPAD_CORE_BASE_FLOAT_HPP\n# define CPPAD_CORE_BASE_FLOAT_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/configure.hpp>\n# include <limits>\n\n/*\n{xrst_begin base_float.hpp}\n{xrst_spell\n    azmul\n    namespaces\n}\n\nEnable use of AD<Base> where Base is float\n##########################################\n\nCondExpOp\n*********\nThe type ``float`` is a relatively simple type that supports\n``<`` , ``<=`` , ``==`` , ``>=`` , and ``>`` operators; see\n:ref:`base_cond_exp@CondExpTemplate@Ordered Type` .\nHence its ``CondExpOp`` function is defined by\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    inline float CondExpOp(\n        enum CompareOp     cop          ,\n        const float&       left         ,\n        const float&       right        ,\n        const float&       exp_if_true  ,\n        const float&       exp_if_false )\n    {  return CondExpTemplate(cop, left, right, exp_if_true, exp_if_false);\n    }\n}\n/* {xrst_code}\n{xrst_spell_on}\n\nCondExpRel\n**********\nThe :ref:`CPPAD_COND_EXP_REL<base_cond_exp@CondExpRel>` macro invocation\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    CPPAD_COND_EXP_REL(float)\n}\n/* {xrst_code}\n{xrst_spell_on}\nuses ``CondExpOp`` above to\ndefine ``CondExp`` *Rel* for ``float`` arguments\nand *Rel* equal to\n``Lt`` , ``Le`` , ``Eq`` , ``Ge`` , and ``Gt`` .\n\nEqualOpSeq\n**********\nThe type ``float`` is simple (in this respect) and so we define\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    inline bool EqualOpSeq(const float& x, const float& y)\n    {  return x == y; }\n}\n/* {xrst_code}\n{xrst_spell_on}\n\nIdentical\n*********\nThe type ``float`` is simple (in this respect) and so we define\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    inline bool IdenticalCon(const float& x)\n    {  return true; }\n    inline bool IdenticalZero(const float& x)\n    {  return (x == 0.f); }\n    inline bool IdenticalOne(const float& x)\n    {  return (x == 1.f); }\n    inline bool IdenticalEqualCon(const float& x, const float& y)\n    {  return (x == y); }\n}\n/* {xrst_code}\n{xrst_spell_on}\n\nInteger\n*******\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    inline int Integer(const float& x)\n    {  return static_cast<int>(x); }\n}\n/* {xrst_code}\n{xrst_spell_on}\n\nazmul\n*****\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    CPPAD_AZMUL( float )\n}\n/* {xrst_code}\n{xrst_spell_on}\n\nOrdered\n*******\nThe ``float`` type supports ordered comparisons\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    inline bool GreaterThanZero(const float& x)\n    {  return x > 0.f; }\n    inline bool GreaterThanOrZero(const float& x)\n    {  return x >= 0.f; }\n    inline bool LessThanZero(const float& x)\n    {  return x < 0.f; }\n    inline bool LessThanOrZero(const float& x)\n    {  return x <= 0.f; }\n    inline bool abs_geq(const float& x, const float& y)\n    {  return std::fabs(x) >= std::fabs(y); }\n}\n/* {xrst_code}\n{xrst_spell_on}\n\nUnary Standard Math\n*******************\nThe following macro invocations import the ``float`` versions of\nthe unary standard math functions into the ``CppAD`` namespace.\nImporting avoids ambiguity errors when using both the\n``CppAD`` and ``std`` namespaces.\nNote this also defines the :ref:`double<base_double.hpp@Unary Standard Math>`\nversions of these functions.\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    using std::acos;\n    using std::asin;\n    using std::atan;\n    using std::cos;\n    using std::cosh;\n    using std::exp;\n    using std::fabs;\n    using std::log;\n    using std::log10;\n    using std::sin;\n    using std::sinh;\n    using std::sqrt;\n    using std::tan;\n    using std::tanh;\n    using std::asinh;\n    using std::acosh;\n    using std::atanh;\n    using std::erf;\n    using std::erfc;\n    using std::expm1;\n    using std::log1p;\n}\n\n/* {xrst_code}\n{xrst_spell_on}\nThe absolute value function is special because its ``std`` name is\n``fabs``\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    inline float abs(const float& x)\n    {  return std::fabs(x); }\n}\n/* {xrst_code}\n{xrst_spell_on}\n\nsign\n****\nThe following defines the ``CppAD::sign`` function that\nis required to use ``AD<float>`` :\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    inline float sign(const float& x)\n    {  if( x > 0.f )\n            return 1.f;\n        if( x == 0.f )\n            return 0.f;\n        return -1.f;\n    }\n}\n/* {xrst_code}\n{xrst_spell_on}\npow\n***\nThe following defines a ``CppAD::pow`` function that\nis required to use ``AD<float>`` .\nAs with the unary standard math functions,\nthis has the exact same signature as ``std::pow`` ,\nso use it instead of defining another function.\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    using std::pow;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\nnumeric_limits\n**************\nThe following defines the CppAD :ref:`numeric_limits-name`\nfor the type ``float`` :\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    CPPAD_NUMERIC_LIMITS(float, float)\n}\n/* {xrst_code}\n{xrst_spell_on}\n\nto_string\n*********\nThere is no need to define ``to_string`` for ``float``\nbecause it is defined by including ``cppad/utility/to_string.hpp`` ;\nsee :ref:`to_string-name` .\nSee :ref:`base_complex.hpp<base_complex.hpp@to_string>` for an example where\nit is necessary to define ``to_string`` for a *Base* type.\n\n{xrst_end base_float.hpp}\n*/\n\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/base_hash.hpp",
    "content": "# ifndef CPPAD_CORE_BASE_HASH_HPP\n# define CPPAD_CORE_BASE_HASH_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin base_hash}\n{xrst_spell\n    adouble\n    valgrind\n}\n\nBase Type Requirements for Hash Coding Values\n#############################################\n\nSyntax\n******\n| *code* = ``hash_code`` ( *x* )\n\nPurpose\n*******\nCppAD uses a table of *Base* type values when recording\n``AD`` < *Base* > operations.\nA hashing function is used to reduce number of values stored in this table;\nfor example, it is not necessary to store the value 3.0 every\ntime it is used as a :ref:`con_dyn_var@Parameter` .\n\nDefault\n*******\nThe default hashing function works with the set of bits that correspond\nto a *Base* value.\nIn most cases this works well, but in some cases\nit does not. For example, in the\n:ref:`base_adolc.hpp-name` case, an ``adouble`` value can have\nfields that are not initialized and ``valgrind`` reported an error\nwhen these are used to form the hash code.\n\nx\n*\nThis argument has prototype\n\n    *const* ``Base`` & ``x``\n\nIt is the value we are forming a hash code for.\n\ncode\n****\nThe return value *code* has prototype\n\n    ``unsigned short`` *code*\n\nIt is the hash code corresponding to *x* . This intention is the\ncommonly used values will have different hash codes.\nThe hash code must satisfy\n\n    *code* < ``CPPAD_HASH_TABLE_SIZE``\n\nso that it is a valid index into the hash code table.\n\ninline\n******\nIf you define this function, it should declare it to be ``inline`` ,\nso that you do not get multiple definitions from different compilation units.\n\nExample\n*******\nSee the ``base_alloc`` :ref:`base_alloc.hpp@hash_code`\nand the ``adouble`` :ref:`base_adolc.hpp@hash_code` .\n\n{xrst_end base_hash}\n*/\n\n/*!\n\\def CPPAD_HASH_TABLE_SIZE\nthe codes returned by hash_code are between zero and CPPAD_HASH_TABLE_SIZE\nminus one.\n*/\n# define CPPAD_HASH_TABLE_SIZE 10000\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/base_limits.hpp",
    "content": "# ifndef CPPAD_CORE_BASE_LIMITS_HPP\n# define CPPAD_CORE_BASE_LIMITS_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-23 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin base_limits}\n\nBase Type Requirements for Numeric Limits\n#########################################\n\nnumeric_limits\n**************\nA specialization for\n:ref:`CppAD::numeric_limits<numeric_limits-name>`\nmust be defined in order to use the type ``AD`` < *Base* > .\nCppAD does not use a specialization of\n``std::numeric_limits<`` *Base* > .\nSince C++11, using a specialization of\n``std::numeric_limits<`` *Base* >\nwould require that *Base* be a literal type.\n\nCPPAD_NUMERIC_LIMITS\n********************\nIn most cases, this macro can be used to define the specialization where\nthe numeric limits for the type *Base*\nare the same as the standard numeric limits for the type *Other* .\nFor most *Base* types,\nthere is a choice of *Other* ,\nfor which the following preprocessor macro invocation suffices:\n\n| |tab| ``namespace CppAD`` {\n| |tab| |tab| ``CPPAD_NUMERIC_LIMITS`` ( *Other* , *Base* )\n| |tab| }\n\ne.g., see :ref:`base_double.hpp@numeric_limits` for the type ``double`` .\nThe macro ``CPPAD_NUMERIC_LIMITS`` is defined by\n{xrst_spell_off}\n{xrst_code cpp} */\n# define CPPAD_NUMERIC_LIMITS(Other, Base) \\\ntemplate <> class numeric_limits<Base>\\\n{\\\n    public:\\\n    static Base min(void) \\\n    {  return static_cast<Base>( std::numeric_limits<Other>::min() ); }\\\n    static Base max(void) \\\n    {  return static_cast<Base>( std::numeric_limits<Other>::max() ); }\\\n    static Base epsilon(void) \\\n    {  return static_cast<Base>( std::numeric_limits<Other>::epsilon() ); }\\\n    static Base quiet_NaN(void) \\\n    {  return static_cast<Base>( std::numeric_limits<Other>::quiet_NaN() ); }\\\n    static Base infinity(void) \\\n    {  return static_cast<Base>( std::numeric_limits<Other>::infinity() ); }\\\n    static const int digits10 = std::numeric_limits<Other>::digits10;\\\n    static const int max_digits10 = std::numeric_limits<Other>::max_digits10;\\\n};\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end base_limits}\n*/\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/base_std_math.hpp",
    "content": "# ifndef CPPAD_CORE_BASE_STD_MATH_HPP\n# define CPPAD_CORE_BASE_STD_MATH_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin base_std_math}\n{xrst_spell\n    acosh\n    asinh\n    erfc\n    expm\n    isnan\n}\n\nBase Type Requirements for Standard Math Functions\n##################################################\n\nPurpose\n*******\nThese definitions are required for the user's code to use the type\n``AD`` < *Base* > :\n\nUnary Standard Math\n*******************\nThe type *Base* must support the following functions\nunary standard math functions (in the CppAD namespace):\n\n.. csv-table::\n    :widths: auto\n\n    **Syntax**,**Result**\n    *y* = ``abs`` ( *x* ),absolute value\n    *y* = ``acos`` ( *x* ),inverse cosine\n    *y* = ``acosh`` ( *x* ),inverse hyperbolic cosine\n    *y* = ``asin`` ( *x* ),inverse sine\n    *y* = ``asinh`` ( *x* ),inverse hyperbolic sin\n    *y* = ``atan`` ( *x* ),inverse tangent\n    *y* = ``atanh`` ( *x* ),inverse hyperbolic tangent\n    *y* = ``cos`` ( *x* ),cosine\n    *y* = ``cosh`` ( *x* ),hyperbolic cosine\n    *y* = ``erf`` ( *x* ),error function\n    *y* = ``erfc`` ( *x* ),complementary error function\n    *y* = ``exp`` ( *x* ),exponential\n    *y* = ``expm1`` ( *x* ),exponential of x minus one\n    *y* = ``fabs`` ( *x* ),absolute value\n    *y* = ``log`` ( *x* ),natural logarithm\n    *y* = ``log1p`` ( *x* ),logarithm of one plus x\n    *y* = ``sin`` ( *x* ),sine\n    *y* = ``sinh`` ( *x* ),hyperbolic sine\n    *y* = ``sqrt`` ( *x* ),square root\n    *y* = ``tan`` ( *x* ),tangent\n\nwhere the arguments and return value have the prototypes\n\n| |tab| ``const`` *Base* & *x*\n| |tab| *Base* *y*\n\nFor example,\n:ref:`base_alloc<base_alloc.hpp@Unary Standard Math>` ,\n\nCPPAD_STANDARD_MATH_UNARY\n*************************\nThe macro invocation, within the CppAD namespace,\n\n    ``CPPAD_STANDARD_MATH_UNARY`` ( *Base* , *Fun* )\n\ndefines the syntax\n\n    *y* = ``CppAD::`` *Fun* ( *x* )\n\nThis macro uses the functions ``std::`` *Fun* which\nmust be defined and have the same prototype as ``CppAD::`` *Fun* .\nFor example,\n:ref:`float<base_float.hpp@Unary Standard Math>` .\n\nsign\n****\nThe type *Base* must support the syntax\n\n    *y* = ``CppAD::sign`` ( *x* )\n\nwhich computes\n\n.. math::\n\n    y = \\left\\{ \\begin{array}{ll}\n        +1 & {\\rm if} \\; x > 0 \\\\\n          0 & {\\rm if} \\; x = 0 \\\\\n        -1 & {\\rm if} \\; x < 0\n    \\end{array} \\right.\n\nwhere *x* and *y* have the same prototype as above.\nFor example, see\n:ref:`base_alloc<base_alloc.hpp@sign>` .\nNote that, if ordered comparisons are not defined for the type *Base* ,\nthe ``code sign`` function should generate an assert if it is used; see\n:ref:`complex invalid unary math<base_complex.hpp@Invalid Unary Math>` .\n\npow\n***\nThe type *Base* must support the syntax\n\n    *z* = ``CppAD::pow`` ( *x* , *y* )\n\nwhich computes :math:`z = x^y`.\nThe arguments *x* and *y* have prototypes\n\n| |tab| ``const`` *Base* & *x*\n| |tab| ``const`` *Base* & *y*\n\nand the return value *z* has prototype\n\n    *Base* *z*\n\nFor example, see\n:ref:`base_alloc<base_alloc.hpp@pow>` .\n\nisnan\n*****\nIf *Base* defines the ``isnan`` function,\nyou may also have to provide a definition in the CppAD namespace\n(to avoid a function ambiguity).\nFor example, see\n:ref:`base_complex<base_complex.hpp@isnan>` .\n\n{xrst_end base_std_math}\n-------------------------------------------------------------------------------\n*/\n\n# include <cmath>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n\n/*!\n\\file base_std_math.hpp\nDefinitions that aid meeting Base type requirements for standard math functions.\n*/\n\n/*!\n\\def CPPAD_STANDARD_MATH_UNARY(Type, Fun)\nThis macro defines the function\n\\verbatim\n    y = CppAD:Fun(x)\n\\endverbatim\nwhere the argument x and return value y have type Type\nusing the corresponding function <code>std::Fun</code>.\n*/\n# define CPPAD_STANDARD_MATH_UNARY(Type, Fun) \\\n    inline Type Fun(const Type& x)            \\\n    {   return std::Fun(x); }\n\n} // END_CPPAD_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/base_to_string.hpp",
    "content": "# ifndef CPPAD_CORE_BASE_TO_STRING_HPP\n# define CPPAD_CORE_BASE_TO_STRING_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin base_to_string}\n{xrst_spell\n    struct\n}\n\nExtending to_string To Another Floating Point Type\n##################################################\n\nBase Requirement\n****************\nIf the function :ref:`to_string-name` is used by an\n:ref:`glossary@AD Type Above Base` ,\nA specialization for the template structure\n``CppAD::to_string_struct`` must be defined.\n\nCPPAD_TO_STRING\n***************\nFor most *Base* types,\nthe following can be used to define the specialization:\n\n| |tab| ``namespace CppAD`` {\n| |tab| |tab| ``CPPAD_TO_STRING`` ( *Base* )\n| |tab| }\n\nNote that the ``CPPAD_TO_STRING`` macro assumes that the\n:ref:`base_limits-name` and :ref:`base_std_math-name` have already been defined\nfor this type.\nThis macro is defined as follows:\n{xrst_spell_off}\n{xrst_code cpp} */\n# define CPPAD_TO_STRING(Base) \\\ntemplate <> struct to_string_struct<Base>\\\n{  std::string operator()(const Base& value) \\\n    {  std::stringstream os;\\\n        int n_digits = 1 + CppAD::numeric_limits<Base>::digits10; \\\n        os << std::setprecision(n_digits);\\\n        os << value;\\\n        return os.str();\\\n    }\\\n};\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end base_to_string}\n------------------------------------------------------------------------------\n*/\n// make sure to_string has been included\n# include <cppad/utility/to_string.hpp>\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/bender_quad.hpp",
    "content": "# ifndef CPPAD_CORE_BENDER_QUAD_HPP\n# define CPPAD_CORE_BENDER_QUAD_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin BenderQuad app}\n{xrst_spell\n    avector\n    gx\n    gxx\n}\n\nComputing Jacobian and Hessian of Bender's Reduced Objective\n############################################################\n\nSyntax\n******\n| # ``include <cppad/cppad.hpp>``\n| *BenderQuad* ( ``x`` , ``y`` , ``fun`` , ``g`` , ``gx`` , ``gxx`` )\n\nSee Also\n********\n:ref:`opt_val_hes-name`\n\nProblem\n*******\nThe type :ref:`BenderQuad@ADvector` cannot be determined\nform the arguments above\n(currently the type *ADvector* must be\n``CPPAD_TESTVECTOR`` ( *Base* ) .)\nThis will be corrected in the future by requiring *Fun*\nto define *Fun* :: ``vector_type`` which will specify the\ntype *ADvector* .\n\nPurpose\n*******\nWe are given the optimization problem\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    {\\rm minimize} & F(x, y) & {\\rm w.r.t.} \\; (x, y) \\in \\B{R}^n \\times \\B{R}^m\n    \\end{eqnarray}\n\nthat is convex with respect to :math:`y`.\nIn addition, we are given a set of equations :math:`H(x, y)`\nsuch that\n\n.. math::\n\n    H[ x , Y(x) ] = 0 \\;\\; \\Rightarrow \\;\\; F_y [ x , Y(x) ] = 0\n\n(In fact, it is often the case that :math:`H(x, y) = F_y (x, y)`.)\nFurthermore, it is easy to calculate a Newton step for these equations; i.e.,\n\n.. math::\n\n    dy = - [ \\partial_y H(x, y)]^{-1} H(x, y)\n\nThe purpose of this routine is to compute the\nvalue, Jacobian, and Hessian of the reduced objective function\n\n.. math::\n\n    G(x) = F[ x , Y(x) ]\n\nNote that if only the value and Jacobian are needed, they can be\ncomputed more quickly using the relations\n\n.. math::\n\n    G^{(1)} (x) = \\partial_x F [x, Y(x) ]\n\nx\n*\nThe ``BenderQuad`` argument *x* has prototype\n\n    ``const`` *BAvector* & *x*\n\n(see :ref:`BenderQuad@BAvector` below)\nand its size must be equal to *n* .\nIt specifies the point at which we evaluating\nthe reduced objective function and its derivatives.\n\ny\n*\nThe ``BenderQuad`` argument *y* has prototype\n\n    ``const`` *BAvector* & *y*\n\nand its size must be equal to *m* .\nIt must be equal to :math:`Y(x)`; i.e.,\nit must solve the problem in :math:`y` for this given value of :math:`x`\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        {\\rm minimize} & F(x, y) & {\\rm w.r.t.} \\; y \\in \\B{R}^m\n    \\end{eqnarray}\n\nfun\n***\nThe ``BenderQuad`` object *fun*\nmust support the member functions listed below.\nThe ``AD`` < *Base* > arguments will be variables for\na tape created by a call to :ref:`Independent-name` from ``BenderQuad``\n(hence they can not be combined with variables corresponding to a\ndifferent tape).\n\nfun.f\n=====\nThe ``BenderQuad`` argument *fun* supports the syntax\n\n    *f* = *fun* . ``f`` ( *x* , *y* )\n\nThe *fun* . ``f`` argument *x* has prototype\n\n    ``const`` *ADvector* & *x*\n\n(see :ref:`BenderQuad@ADvector` below)\nand its size must be equal to *n* .\nThe *fun* . ``f`` argument *y* has prototype\n\n    ``const`` *ADvector* & *y*\n\nand its size must be equal to *m* .\nThe *fun* . ``f`` result *f* has prototype\n\n    *ADvector* *f*\n\nand its size must be equal to one.\nThe value of *f* is\n\n.. math::\n\n    f = F(x, y)\n\nfun.h\n=====\nThe ``BenderQuad`` argument *fun* supports the syntax\n\n    *h* = *fun* . ``h`` ( *x* , *y* )\n\nThe *fun* . ``h`` argument *x* has prototype\n\n    ``const`` *ADvector* & *x*\n\nand its size must be equal to *n* .\nThe *fun* . ``h`` argument *y* has prototype\n\n    ``const`` *BAvector* & *y*\n\nand its size must be equal to *m* .\nThe *fun* . ``h`` result *h* has prototype\n\n    *ADvector* *h*\n\nand its size must be equal to *m* .\nThe value of *h* is\n\n.. math::\n\n    h = H(x, y)\n\nfun.dy\n======\nThe ``BenderQuad`` argument *fun* supports the syntax\n\n| |tab| *dy* = *fun* . ``dy`` ( *x* , *y* , *h* )\n|\n| *x*\n\nThe *fun* . ``dy`` argument *x* has prototype\n\n    ``const`` *BAvector* & *x*\n\nand its size must be equal to *n* .\nIts value will be exactly equal to the ``BenderQuad`` argument\n*x* and values depending on it can be stored as private objects\nin *f* and need not be recalculated.\n\n    *y*\n\nThe *fun* . ``dy`` argument *y* has prototype\n\n    ``const`` *BAvector* & *y*\n\nand its size must be equal to *m* .\nIts value will be exactly equal to the ``BenderQuad`` argument\n*y* and values depending on it can be stored as private objects\nin *f* and need not be recalculated.\n\n    *h*\n\nThe *fun* . ``dy`` argument *h* has prototype\n\n    ``const`` *ADvector* & *h*\n\nand its size must be equal to *m* .\n\n    *dy*\n\nThe *fun* . ``dy`` result *dy* has prototype\n\n    *ADvector* *dy*\n\nand its size must be equal to *m* .\nThe return value *dy* is given by\n\n.. math::\n\n    dy = - [ \\partial_y H (x , y) ]^{-1} h\n\nNote that if *h* is equal to :math:`H(x, y)`,\n:math:`dy` is the Newton step for finding a zero\nof :math:`H(x, y)` with respect to :math:`y`;\ni.e.,\n:math:`y + dy` is an approximate solution for the equation\n:math:`H (x, y + dy) = 0`.\n\ng\n*\nThe argument *g* has prototype\n\n    *BAvector* & *g*\n\nand has size one.\nThe input value of its element does not matter.\nOn output,\nit contains the value of :math:`G (x)`; i.e.,\n\n.. math::\n\n    g[0] = G (x)\n\ngx\n**\nThe argument *gx* has prototype\n\n    *BAvector* & *gx*\n\nand has size :math:`n`.\nThe input values of its elements do not matter.\nOn output,\nit contains the Jacobian of :math:`G (x)`; i.e.,\nfor :math:`j = 0 , \\ldots , n-1`,\n\n.. math::\n\n    gx[ j ] = G^{(1)} (x)_j\n\ngxx\n***\nThe argument *gx* has prototype\n\n    *BAvector* & *gxx*\n\nand has size :math:`n \\times n`.\nThe input values of its elements do not matter.\nOn output,\nit contains the Hessian of :math:`G (x)`; i.e.,\nfor :math:`i = 0 , \\ldots , n-1`, and\n:math:`j = 0 , \\ldots , n-1`,\n\n.. math::\n\n    gxx[ i * n + j ] = G^{(2)} (x)_{i,j}\n\nBAvector\n********\nThe type *BAvector* must be a\n:ref:`SimpleVector-name` class.\nWe use *Base* to refer to the type of the elements of\n*BAvector* ; i.e.,\n\n    *BAvector* :: ``value_type``\n\nADvector\n********\nThe type *ADvector* must be a\n:ref:`SimpleVector-name` class with elements of type\n``AD`` < *Base* > ; i.e.,\n\n    *ADvector* :: ``value_type``\n\nmust be the same type as\n\n    ``AD`` < *BAvector* :: ``value_type >``\n\n.\n\nExample\n*******\n{xrst_toc_hidden\n    example/general/bender_quad.cpp\n}\nThe file\n:ref:`bender_quad.cpp-name`\ncontains an example and test of this operation.\n\n{xrst_end BenderQuad}\n-----------------------------------------------------------------------------\n*/\n\nnamespace CppAD { // BEGIN CppAD namespace\n\ntemplate <class BAvector, class Fun>\nvoid BenderQuad(\n    const BAvector   &x     ,\n    const BAvector   &y     ,\n    Fun               fun   ,\n    BAvector         &g     ,\n    BAvector         &gx    ,\n    BAvector         &gxx   )\n{   // determine the base type\n    typedef typename BAvector::value_type Base;\n\n    // check that BAvector is a SimpleVector class\n    CheckSimpleVector<Base, BAvector>();\n\n    // declare the ADvector type\n    typedef CPPAD_TESTVECTOR(AD<Base>) ADvector;\n\n    // size of the x and y spaces\n    size_t n = size_t(x.size());\n    size_t m = size_t(y.size());\n\n    // check the size of gx and gxx\n    CPPAD_ASSERT_KNOWN(\n        g.size() == 1,\n        \"BenderQuad: size of the vector g is not equal to 1\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t(gx.size()) == n,\n        \"BenderQuad: size of the vector gx is not equal to n\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t(gxx.size()) == n * n,\n        \"BenderQuad: size of the vector gxx is not equal to n * n\"\n    );\n\n    // some temporary indices\n    size_t i, j;\n\n    // variable versions x\n    ADvector vx(n);\n    for(j = 0; j < n; j++)\n        vx[j] = x[j];\n\n    // declare the independent variables\n    Independent(vx);\n\n    // evaluate h = H(x, y)\n    ADvector h(m);\n    h = fun.h(vx, y);\n\n    // evaluate dy (x) = Newton step as a function of x through h only\n    ADvector dy(m);\n    dy = fun.dy(x, y, h);\n\n    // variable version of y\n    ADvector vy(m);\n    for(j = 0; j < m; j++)\n        vy[j] = y[j] + dy[j];\n\n    // evaluate G~ (x) = F [ x , y + dy(x) ]\n    ADvector gtilde(1);\n    gtilde = fun.f(vx, vy);\n\n    // AD function object that corresponds to G~ (x)\n    // We will make heavy use of this tape, so optimize it\n    ADFun<Base> Gtilde;\n    Gtilde.Dependent(vx, gtilde);\n    Gtilde.optimize();\n\n    // value of G(x)\n    g = Gtilde.Forward(0, x);\n\n    // initial forward direction vector as zero\n    BAvector dx(n);\n    for(j = 0; j < n; j++)\n        dx[j] = Base(0.0);\n\n    // weight, first and second order derivative values\n    BAvector dg(1), w(1), ddw(2 * n);\n    w[0] = 1.;\n\n\n    // Jacobian and Hessian of G(x) is equal Jacobian and Hessian of Gtilde\n    for(j = 0; j < n; j++)\n    {   // compute partials in x[j] direction\n        dx[j] = Base(1.0);\n        dg    = Gtilde.Forward(1, dx);\n        gx[j] = dg[0];\n\n        // restore the dx vector to zero\n        dx[j] = Base(0.0);\n\n        // compute second partials w.r.t x[j] and x[l]  for l = 1, n\n        ddw = Gtilde.Reverse(2, w);\n        for(i = 0; i < n; i++)\n            gxx[ i * n + j ] = ddw[ i * 2 + 1 ];\n    }\n\n    return;\n}\n\n} // END CppAD namespace\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/bool_fun.hpp",
    "content": "# ifndef CPPAD_CORE_BOOL_FUN_HPP\n# define CPPAD_CORE_BOOL_FUN_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin bool_fun}\n\nAD Boolean Functions\n####################\n\nSyntax\n******\n| ``CPPAD_BOOL_UNARY`` ( *Base* , *unary_name* )\n| *b* = *unary_name* ( *u* )\n| *b* = *unary_name* ( *x* )\n| ``CPPAD_BOOL_BINARY`` ( *Base* , *binary_name* )\n| *b* = *binary_name* ( *u* , *v* )\n| *b* = *binary_name* ( *x* , *y* )\n\nPurpose\n*******\nCreate a ``bool`` valued function that has ``AD`` < *Base* > arguments.\n\nunary_name\n**********\nThis is the name of the ``bool`` valued function with one argument\n(as it is used in the source code).\nThe user must provide a version of *unary_name* where\nthe argument has type *Base* .\nCppAD uses this to create a version of *unary_name* where the\nargument has type ``AD`` < *Base* > .\n\nu\n*\nThe argument *u* has prototype\n\n    ``const`` *Base* & *u*\n\nIt is the value at which the user provided version of *unary_name*\nis to be evaluated.\nIt is also used for the first argument to the\nuser provided version of *binary_name* .\n\nx\n*\nThe argument *x* has prototype\n\n    ``const AD`` < *Base* > & *x*\n\nIt is the value at which the CppAD provided version of *unary_name*\nis to be evaluated.\nIt is also used for the first argument to the\nCppAD provided version of *binary_name* .\n\nb\n*\nThe result *b* has prototype\n\n    ``bool`` *b*\n\nCreate Unary\n************\nThe preprocessor macro invocation\n\n    ``CPPAD_BOOL_UNARY`` ( *Base* , *unary_name* )\n\ndefines the version of *unary_name* with a ``AD`` < *Base* >\nargument.\nThis can with in a namespace\n(not the ``CppAD`` namespace)\nbut must be outside of any routine.\n\nbinary_name\n***********\nThis is the name of the ``bool`` valued function with two arguments\n(as it is used in the source code).\nThe user must provide a version of *binary_name* where\nthe arguments have type *Base* .\nCppAD uses this to create a version of *binary_name* where the\narguments have type ``AD`` < *Base* > .\n\nv\n*\nThe argument *v* has prototype\n\n    ``const`` *Base* & *v*\n\nIt is the second argument to\nthe user provided version of *binary_name* .\n\ny\n*\nThe argument *x* has prototype\n\n    ``const AD`` < *Base* > & *y*\n\nIt is the second argument to\nthe CppAD provided version of *binary_name* .\n\nCreate Binary\n*************\nThe preprocessor macro invocation\n\n    ``CPPAD_BOOL_BINARY`` ( *Base* , *binary_name* )\n\ndefines the version of *binary_name* with ``AD`` < *Base* >\narguments.\nThis can with in a namespace\n(not the ``CppAD`` namespace)\nbut must be outside of any routine.\n\nOperation Sequence\n******************\nThe result of this operation is not an\n:ref:`glossary@AD of Base` object.\nThus it will not be recorded as part of an\nAD of *Base*\n:ref:`operation sequence<glossary@Operation@Sequence>` .\n\nExample\n*******\n{xrst_toc_hidden\n    example/general/bool_fun.cpp\n}\nThe file\n:ref:`bool_fun.cpp-name`\ncontains an example and test of these operations.\n\nDeprecated 2007-07-31\n*********************\nThe preprocessor symbols ``CppADCreateUnaryBool``\nand ``CppADCreateBinaryBool`` are defined to be the same as\n``CPPAD_BOOL_UNARY`` and ``CPPAD_BOOL_BINARY`` respectively\n(but their use is deprecated).\n\n{xrst_end bool_fun}\n*/\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\n\\file bool_fun.hpp\nRoutines and macros that implement functions from AD<Base> to bool.\n*/\n\n/*!\nMacro that defines a unary function <tt>bool F(AD<Base> x)</tt>\nusing <tt>bool F(Base x)</tt>.\n\n\\param Base\nbase for the AD type of arguments to this unary bool valued function.\n\n\\param unary_name\nname of this unary function; i.e., F.\n*/\n# define CPPAD_BOOL_UNARY(Base, unary_name)                        \\\n      inline bool unary_name (const CppAD::AD<Base> &x)             \\\n      {                                                              \\\n             return CppAD::AD<Base>::UnaryBool(unary_name, x);        \\\n      }\n\n/*!\nDeprecated name for CPPAD_BOOL_UNARY\n*/\n# define CppADCreateUnaryBool  CPPAD_BOOL_UNARY\n\n/*!\nLink a function name, and AD value pair to function call with base argument\nand bool return value.\n\n\\param FunName\nis the name of the function that we are linking.\n\n\\param x\nis the argument where we are evaluating the function.\n*/\ntemplate <class Base>\nbool AD<Base>::UnaryBool(\n    bool FunName(const Base &x),\n    const AD<Base> &x\n)\n{\n    return FunName(x.value_);\n}\n\n/*!\nMacro that defines a binary function <tt>bool F(AD<Base> x, AD<Base> y)</tt>\nusing <tt>bool F(Base x, Base y)</tt>.\n\n\\param Base\nbase for the AD type of arguments to this binary bool valued function.\n\n\\param binary_name\nname of this binary function; i.e., F.\n*/\n\n# define CPPAD_BOOL_BINARY(Base, binary_name)                      \\\n      inline bool binary_name (                                     \\\n             const CppAD::AD<Base> &x, const CppAD::AD<Base> &y)      \\\n      {                                                              \\\n             return CppAD::AD<Base>::BinaryBool(binary_name, x, y);   \\\n      }\n/*!\nDeprecated name for CPPAD_BOOL_BINARY\n*/\n# define CppADCreateBinaryBool CPPAD_BOOL_BINARY\n\n\n/*!\nLink a function name, and two AD values to function call with base arguments\nand bool return value.\n\n\\param FunName\nis the name of the function that we are linking.\n\n\\param x\nis the first argument where we are evaluating the function at.\n\n\\param y\nis the second argument where we are evaluating the function at.\n*/\ntemplate <class Base>\nbool AD<Base>::BinaryBool(\n    bool FunName(const Base &x, const Base &y),\n    const AD<Base> &x, const AD<Base> &y\n)\n{\n    return FunName(x.value_, y.value_);\n}\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/bool_valued.hpp",
    "content": "# ifndef CPPAD_CORE_BOOL_VALUED_HPP\n# define CPPAD_CORE_BOOL_VALUED_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin bool_valued}\n{xrst_spell\n    dyn\n    ext\n}\n\nBool Valued Operations and Functions with AD Arguments\n######################################################\n{xrst_toc_hidden\n    include/cppad/core/compare.hpp\n    include/cppad/core/near_equal_ext.hpp\n    include/cppad/core/bool_fun.hpp\n    include/cppad/core/con_dyn_var.hpp\n    include/cppad/core/equal_op_seq.hpp\n}\n\n.. csv-table::\n    :widths: auto\n\n    Compare,:ref:`Compare-title`\n    near_equal_ext,:ref:`near_equal_ext-title`\n    bool_fun,:ref:`bool_fun-title`\n    con_dyn_var,:ref:`con_dyn_var-title`\n    EqualOpSeq,:ref:`EqualOpSeq-title`\n\n{xrst_end bool_valued}\n*/\n\n# include <cppad/core/compare.hpp>\n# include <cppad/core/near_equal_ext.hpp>\n# include <cppad/core/bool_fun.hpp>\n# include <cppad/core/con_dyn_var.hpp>\n# include <cppad/core/equal_op_seq.hpp>\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/capacity_order.hpp",
    "content": "# ifndef CPPAD_CORE_CAPACITY_ORDER_HPP\n# define CPPAD_CORE_CAPACITY_ORDER_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin capacity_order}\n{xrst_spell\n    pre\n    xq\n    yq\n}\n\nControlling Taylor Coefficients Memory Allocation\n#################################################\n\nSyntax\n******\n| *f* . ``capacity_order`` ( *c* )\n\nSee Also\n========\n:ref:`fun_property-name`\n\nPurpose\n*******\nThe Taylor coefficients calculated by :ref:`Forward-name` mode calculations\nare retained in an :ref:`ADFun-name` object for subsequent use during\n:ref:`Reverse-name` mode and higher order Forward mode calculations.\nFor example, a call to :ref:`Forward<forward_order-name>` with the syntax\n\n    *yq* = *f* . ``Forward`` ( *q* , *xq* )\n\nwhere *q*  > 0 and  *xq* . ``size`` () == *f* . ``Domain`` () ,\nuses the lower order Taylor coefficients and\ncomputes the *q*-th order Taylor coefficients for all\nthe variables in the operation sequence corresponding to *f* .\nThe ``capacity_order`` operation allows you to control that\namount of memory that is retained by an AD function object\n(to hold ``Forward`` results for subsequent calculations).\n\nf\n*\nThe object *f* has prototype\n\n    ``ADFun`` < *Base* > *f*\n\nc\n*\nThe argument *c* has prototype\n\n    ``size_t`` *c*\n\nIt specifies the number of Taylor coefficient orders that are allocated\nin the AD operation sequence corresponding to *f* .\n\nPre-Allocating Memory\n=====================\nIf you plan to make calls to ``Forward`` with the maximum value of\n*q* equal to *Q* ,\nit should be faster to pre-allocate memory for these calls using\n\n    *f* . ``capacity_order`` ( *c* )\n\nwith *c* equal to :math:`Q + 1`.\nIf you do no do this, ``Forward`` will automatically allocate memory\nand will copy the results to a larger buffer, when necessary.\n\nNote that each call to :ref:`Dependent-name` frees the old memory\nconnected to the function object and sets the corresponding\ntaylor capacity to zero.\n\nFreeing Memory\n==============\nIf you no longer need the Taylor coefficients of order *q*\nand higher (that are stored in *f* ),\nyou can reduce the memory allocated to *f* using\n\n    *f* . ``capacity_order`` ( *c* )\n\nwith *c* equal to *q* .\nNote that, if :ref:`ta_hold_memory-name` is true, this memory is not actually\nreturned to the system, but rather held for future use by the same thread.\n\nOriginal State\n**************\nIf *f* is :ref:`constructed<fun_construct-name>` with the syntax\n\n    ``ADFun`` < *Base* > *f* ( *x* , *y* )\n\n,\nthere is an implicit call to :ref:`forward_zero-name` with *xq* equal to\nthe value of the\n:ref:`independent variables<glossary@Tape@Independent Variable>`\nwhen the AD operation sequence was recorded.\nThis corresponds to *c*  == 1 .\n{xrst_toc_hidden\n    example/general/capacity_order.cpp\n}\nExample\n*******\nThe file\n:ref:`capacity_order.cpp-name`\ncontains an example and test of these operations.\n\n{xrst_end capacity_order}\n-----------------------------------------------------------------------------\n*/\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\n\\file capacity_order.hpp\nControl of number of orders allocated.\n\\}\n*/\n\n/*!\nControl of number of orders and directions allocated.\n\n\\tparam Base\nThe type used during the forward mode computations; i.e., the corresponding\nrecording of operations used the type AD<Base>.\n\n\\param c\nis the number of orders to allocate memory for.\nIf <code>c == 0</code> then r must also be zero.\nIn this case num_order_taylor_, cap_order_taylor_, and num_direction_taylor_\nare all set to zero.\nIn addition, taylor_.clear() is called.\n\n\\param r\nis the number of directions to allocate memory for.\nIf <code>c == 1</code> then r must also be one.\nIn all cases, it must hold that\n<code>\n    r == num_direction_taylor_ || num_order_taylor <= 1\n</code>\nUpon return, num_direction_taylor_ is equal to r.\n\n\\par num_order_taylor_\nThe output value of num_order_taylor_ is the mininumum of its input\nvalue and c. This minimum is the number of orders that are copied to the\nnew taylor coefficient buffer.\n\n\\par num_direction_taylor_\nThe output value of num_direction_taylor_ is equal to r.\n*/\n\ntemplate <class Base, class RecBase>\nvoid ADFun<Base,RecBase>::capacity_order(size_t c, size_t r)\n{   // temporary indices\n    size_t i, k, ell;\n\n    if( (c == cap_order_taylor_) && (r == num_direction_taylor_) )\n        return;\n\n    if( c == 0 )\n    {   CPPAD_ASSERT_UNKNOWN( r == 0 );\n        taylor_.clear();\n        num_order_taylor_     = 0;\n        cap_order_taylor_     = 0;\n        num_direction_taylor_ = r;\n        return;\n    }\n    CPPAD_ASSERT_UNKNOWN(r==num_direction_taylor_ || num_order_taylor_<=1);\n\n    // Allocate new taylor with requested number of orders and directions\n    size_t new_len   = ( (c-1)*r + 1 ) * num_var_tape_;\n    local::pod_vector_maybe<Base> new_taylor(new_len);\n\n    // number of orders to copy\n    size_t p = std::min(num_order_taylor_, c);\n    if( p > 0 )\n    {\n        // old order capacity\n        size_t C = cap_order_taylor_;\n\n        // old number of directions\n        size_t R = num_direction_taylor_;\n\n        // copy the old data into the new matrix\n        CPPAD_ASSERT_UNKNOWN( p == 1 || r == R );\n        for(i = 0; i < num_var_tape_; i++)\n        {   // copy zero order\n            size_t old_index = ((C-1) * R + 1) * i + 0;\n            size_t new_index = ((c-1) * r + 1) * i + 0;\n            new_taylor[ new_index ] = taylor_[ old_index ];\n            // copy higher orders\n            for(k = 1; k < p; k++)\n            {   for(ell = 0; ell < R; ell++)\n                {   old_index = ((C-1) * R + 1) * i + (k-1) * R + ell + 1;\n                    new_index = ((c-1) * r + 1) * i + (k-1) * r + ell + 1;\n                    new_taylor[ new_index ] = taylor_[ old_index ];\n                }\n            }\n        }\n    }\n\n    // replace taylor_ by new_taylor\n    taylor_.swap(new_taylor);\n    cap_order_taylor_     = c;\n    num_order_taylor_     = p;\n    num_direction_taylor_ = r;\n\n    // note that the destructor for new_taylor will free the old taylor memory\n    return;\n}\n\n/*!\nUser API control of number of orders allocated.\n\n\\tparam Base\nThe type used during the forward mode computations; i.e., the corresponding\nrecording of operations used the type AD<Base>.\n\n\\param c\nis the number of orders to allocate memory for.\nIf <code>c == 0</code>,\nnum_order_taylor_, cap_order_taylor_, and num_direction_taylor_\nare all set to zero.\nIn addition, taylor_.clear() is called.\n\n\\par num_order_taylor_\nThe output value of num_order_taylor_ is the mininumum of its input\nvalue and c. This minimum is the number of orders that are copied to the\nnew taylor coefficient buffer.\n\n\\par num_direction_taylor_\nIf is zero (one), num_direction_taylor_ is set to zero (one).\nOtherwise, if num_direction_taylor_ is zero, it is set to one.\nOtherwise, num_direction_taylor_ is not modified.\n*/\n\ntemplate <class Base, class RecBase>\nvoid ADFun<Base,RecBase>::capacity_order(size_t c)\n{   size_t r;\n    if( (c == 0) || (c == 1) )\n    {   r = c;\n        capacity_order(c, r);\n        return;\n    }\n    r = num_direction_taylor_;\n    if( r == 0 )\n        r = 1;\n    capacity_order(c, r);\n    return;\n}\n\n} // END CppAD namespace\n\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/check_for_nan.hpp",
    "content": "# ifndef CPPAD_CORE_CHECK_FOR_NAN_HPP\n# define CPPAD_CORE_CHECK_FOR_NAN_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin check_for_nan}\n{xrst_spell\n    newline\n}\nCheck an ADFun Object For Nan Results\n#####################################\n\nSyntax\n******\n| *f* . ``check_for_nan`` ( *b* )\n| *b* = *f* . ``check_for_nan`` ()\n| ``get_check_for_nan`` ( *vec* , *file* )\n\nDebugging\n*********\nIf ``NDEBUG`` is not defined, and\nthe result of a :ref:`forward<forward_order-name>` or :ref:`reverse<reverse_any-name>`\ncalculation contains a  :ref:`nan-name` ,\nCppAD can halt with an error message.\n\nf\n*\nFor the syntax where *b* is an argument,\n*f* has prototype\n\n    ``ADFun`` < *Base* > *f*\n\n(see ``ADFun`` < *Base* > :ref:`constructor<fun_construct-name>` ).\nFor the syntax where *b* is the result,\n*f* has prototype\n\n    ``const ADFun`` < *Base* > *f*\n\nb\n*\nThis argument or result has prototype\n\n    ``bool`` *b*\n\nIf *b* is true (false),\nfuture calls to *f* . ``Forward`` will (will not) check for ``nan`` .\n\nDefault\n*******\nThe value for this setting after construction of *f* is true.\nThe value of this setting is not affected by calling\n:ref:`Dependent-name` for this function object.\n\nError Message\n*************\nIf this error is detected during zero order forward mode,\nthe values of the independent variables that resulted in the ``nan``\nare written to a temporary binary file.\nThis is so that you can run the original source code with those values\nto see what is causing the ``nan`` .\n\nvector_size\n===========\nThe error message with contain the text\n``vector_size`` = *vector_size* followed the newline character\n``'\\n'`` .\nThe value of *vector_size* is the number of elements\nin the independent vector.\n\nfile_name\n=========\nThe error message with contain the text\n``file_name`` = *file_name* followed the newline character\n``'\\n'`` .\nThe value of *file_name* is the name of the temporary file\nthat contains the dependent variable values.\n\nindex\n=====\nThe error message will contain the text\n``index`` = *index* followed by the newline character ``'\\n'`` .\nThe value of *index* is the lowest dependent variable index\nthat has the value ``nan`` .\n\nget_check_for_nan\n*****************\nThis routine can be used to get the independent variable\nvalues that result in a ``nan`` .\n\nvec\n===\nThis argument has prototype\n\n    ``CppAD::vector<`` *Base* >& *vec*\n\nIt size must be equal to the corresponding value of\n:ref:`check_for_nan@Error Message@vector_size`\nin the corresponding error message.\nThe input value of its elements does not matter.\nUpon return, it will contain the values for the independent variables,\nin the corresponding call to :ref:`Independent-name` ,\nthat resulted in the ``nan`` .\n(Note that the call to ``Independent`` uses an vector with elements\nof type ``AD`` < *Base* > and *vec* has elements of type\n*Base* .)\n\nfile\n====\nThis argument has prototype\n\n    ``const std::string&`` *file*\n\nIt must be the value of\n:ref:`check_for_nan@Error Message@file_name`\nin the corresponding error message.\n\nExample\n*******\n{xrst_toc_hidden\n    example/general/check_for_nan.cpp\n}\nThe file\n:ref:`check_for_nan.cpp-name`\ncontains an example and test of these operations.\n\n{xrst_end check_for_nan}\n*/\n\n# include <fstream>\n# include <cppad/utility/vector.hpp>\n# include <cppad/local/temp_file.hpp>\n\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n\n/*!\nSet check_for_nan\n\n\\param value\nnew value for this flag.\n*/\ntemplate <class Base, class RecBase>\nvoid ADFun<Base,RecBase>::check_for_nan(bool value)\n{   check_for_nan_ = value; }\n\n/*!\nGet check_for_nan\n\n\\return\ncurrent value of check_for_nan_.\n*/\ntemplate <class Base, class RecBase>\nbool ADFun<Base,RecBase>::check_for_nan(void) const\n{   return check_for_nan_; }\n\n/*!\nStores a vector in a file when nans occur.\n\n\\param vec [in]\nis the vector that is stored.\n\n\\param [out] file_name\nis the file where the vector is stored\n*/\ntemplate <class Base>\nvoid put_check_for_nan(const CppAD::vector<Base>& vec, std::string& file_name)\n{\n    // char_size\n    std::streamsize char_size = std::streamsize( sizeof(Base) * vec.size() );\n    //\n    // char_ptr\n    const char* char_ptr   = reinterpret_cast<const char*>( vec.data() );\n    //\n    // file_name\n    file_name = local::temp_file();\n    //\n    // write data to file_name\n    std::fstream file_out(file_name.c_str(), std::ios::out|std::ios::binary );\n    file_out.write(char_ptr, char_size);\n    file_out.close();\n    //\n    return;\n}\n/*!\nGets a vector that was stored by put_check_for_nan.\n\n\\param vec [out]\nis the vector that is stored.\n\n\\param file_name [in]\nis the file where the vector is stored\n*/\ntemplate <class Base>\nvoid get_check_for_nan(CppAD::vector<Base>& vec, const std::string& file_name)\n{   //\n    std::streamsize char_size = std::streamsize( sizeof(Base) * vec.size() );\n    char* char_ptr   = reinterpret_cast<char*>( vec.data() );\n    //\n    std::fstream file_in(file_name.c_str(), std::ios::in|std::ios::binary );\n    file_in.read(char_ptr, char_size);\n    //\n    return;\n}\n\n} // END_CPPAD_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/chkpoint_one/chkpoint_one.hpp",
    "content": "# ifndef CPPAD_CORE_CHKPOINT_ONE_CHKPOINT_ONE_HPP\n# define CPPAD_CORE_CHKPOINT_ONE_CHKPOINT_ONE_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/local/sparse/list_setvec.hpp>\n# include <cppad/local/sparse/pack_setvec.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\n\\file chkpoint_one.hpp\nFirst generation checkpoint functions.\n*/\n\n/*\n{xrst_begin chkpoint_one app}\n{xrst_spell\n    algo\n    sv\n}\n\nCheckpoint Functions: First Generation\n######################################\n\nDeprecated 2019-01-14\n*********************\nUsing the ``checkpoint`` class has been deprecated.\nUse :ref:`chkpoint_two-name` instead.\n\nSyntax\n******\n| ``checkpoint`` < *Base* > *atom_fun* (\n| |tab| *name* , *algo* , *ax* , *ay* , *sparsity* , *optimize*\n| )\n| *sv* = *atom_fun* . ``size_var`` ()\n| *atom_fun* . ``option`` ( *option_value* )\n| *algo* ( *ax* , *ay* )\n| *atom_fun* ( *ax* , *ay* )\n| *checkpoint* < ``Base`` >:: *clear* ()\n\nSee Also\n********\n:ref:`atomic_two-name` , :ref:`rev_checkpoint.cpp-name`\n\nPurpose\n*******\n\nReduce Memory\n=============\nYou can reduce the size of the tape and memory required for AD by\ncheckpointing functions of the form :math:`y = f(x)` where\n:math:`f : \\B{R}^n \\rightarrow \\B{R}^m`.\n\nFaster Recording\n================\nIt may also reduce the time to make a recording the same function\nfor different values of the independent variable.\nNote that the operation sequence for a recording that uses :math:`f(x)`\nmay depend on its independent variables.\n\nRepeating Forward\n=================\nNormally, CppAD store :ref:`forward-name` mode results until they freed\nusing :ref:`capacity_order-name` or the corresponding :ref:`ADFun-name` object is\ndeleted. This is not true for checkpoint functions because a checkpoint\nfunction may be used repeatedly with different arguments in the same tape.\nThus, forward mode results are recomputed each time a checkpoint function\nis used during a forward or reverse mode sweep.\n\nRestriction\n===========\nThe :ref:`operation sequence<glossary@Operation@Sequence>`\nrepresenting :math:`f(x)` cannot depend on the value of :math:`x`.\nThe approach in the :ref:`rev_checkpoint.cpp-name` example case be applied\nwhen the operation sequence depends on :math:`x`.\n\nMultiple Level AD\n=================\nIf *Base* is an AD type, it is possible to record *Base*\noperations.\nNote that *atom_fun* will treat *algo* as an atomic\noperation while recording ``AD`` < ``Base`` > operations, but not while\nrecording *Base* operations.\nSee the ``chkpoint_one_mul_level.cpp`` example.\n\nMethod\n******\nThe ``checkpoint`` class is derived from ``atomic_base``\nand makes this easy.\nIt implements all the ``atomic_base``\n:ref:`atomic_two@Virtual Functions`\nand hence its source code ``cppad/core/chkpoint_one/chkpoint_one.hpp``\nprovides an example implementation of :ref:`atomic_two-name` .\nThe difference is that ``chkpoint_one.hpp`` uses AD\ninstead of user provided derivatives.\n\nconstructor\n***********\nThe syntax for the checkpoint constructor is\n\n    ``checkpoint`` < *Base* > *atom_fun* ( *name* , *algo* , *ax* , *ay* )\n\n#. This constructor cannot be called in :ref:`parallel<ta_in_parallel-name>` mode.\n#. You cannot currently be recording\n   ``AD`` < *Base* > operations when the constructor is called.\n#. This object *atom_fun* must not be destructed for as long\n   as any ``ADFun`` < *Base* > object uses its atomic operation.\n#. This class is implemented as a derived class of\n   :ref:`atomic<atomic_two_ctor@atomic_base>` and hence\n   some of its error message will refer to ``atomic_base`` .\n\nBase\n****\nThe type *Base* specifies the base type for AD operations.\n\nADVector\n********\nThe type *ADVector* must be a\n:ref:`simple vector class<SimpleVector-name>` with elements of type\n``AD`` < *Base* > .\n\nname\n****\nThis *checkpoint* constructor argument has prototype\n\n    ``const char`` * *name*\n\nIt is the name used for error reporting.\nThe suggested value for *name* is *atom_fun* ; i.e.,\nthe same name as used for the object being constructed.\n\nax\n**\nThis argument has prototype\n\n    ``const`` *ADVector* & *ax*\n\nand size must be equal to *n* .\nIt specifies vector :math:`x \\in \\B{R}^n`\nat which an ``AD`` < *Base* > version of\n:math:`y = f(x)` is to be evaluated.\n\nay\n**\nThis argument has prototype\n\n    *ADVector* & *ay*\n\nIts input size must be equal to *m* and does not change.\nThe input values of its elements do not matter.\nUpon return, it is an ``AD`` < *Base* > version of\n:math:`y = f(x)`.\n\nsparsity\n********\nThis argument has prototype\n\n    ``atomic_base`` < *Base* >:: ``option_enum`` *sparsity*\n\nIt specifies :ref:`atomic_two_ctor@atomic_base@sparsity`\nin the ``atomic_base`` constructor and must be either\n``atomic_base`` < *Base* >:: ``pack_sparsity_enum`` ,\n``atomic_base`` < *Base* >:: ``bool_sparsity_enum`` , or\n``atomic_base`` < *Base* >:: ``set_sparsity_enum`` .\nThis argument is optional and its default value is unspecified.\n\noptimize\n********\nThis argument has prototype\n\n    ``bool`` *optimize*\n\nIt specifies if the recording corresponding to the atomic function\nshould be :ref:`optimized<optimize-name>` .\nOne expects to use a checkpoint function many times, so it should\nbe worth the time to optimize its operation sequence.\nFor debugging purposes, it may be useful to use the\noriginal operation sequence (before optimization)\nbecause it corresponds more closely to *algo* .\nThis argument is optional and its default value is true.\n\nsize_var\n********\nThis ``size_var`` member function return value has prototype\n\n    ``size_t`` *sv*\n\nIt is the :ref:`fun_property@size_var` for the\n``ADFun`` < *Base* > object is used to store the operation sequence\ncorresponding to *algo* .\n\noption\n******\nThe ``option`` syntax can be used to set the type of sparsity\npattern used by *atom_fun* .\nThis is an ``atomic_base`` < *Base* > function and its documentation\ncan be found at :ref:`atomic_two_option-name` .\n\nalgo\n****\nThe type of *algo* is arbitrary, except for the fact that\nthe syntax\n\n    *algo* ( *ax* , *ay* )\n\nmust evaluate the function :math:`y = f(x)` using\n``AD`` < *Base* > operations.\nIn addition, we assume that the\n:ref:`operation sequence<glossary@Operation@Sequence>`\ndoes not depend on the value of *ax* .\n\natom_fun\n********\nGiven *ax* it computes the corresponding value of *ay*\nusing the operation sequence corresponding to *algo* .\nIf ``AD`` < *Base* > operations are being recorded,\nit enters the computation as single operation in the recording\nsee :ref:`Independent@Start Recording` .\n(Currently each use of *atom_fun* actually corresponds to\n*m* + *n* +2 operations and creates *m* new variables,\nbut this is not part of the CppAD specifications and my change.)\n\nMemory\n******\n\nRestriction\n===========\nThe ``clear`` routine cannot be called\nwhile in :ref:`parallel<ta_in_parallel-name>` execution mode.\n\nParallel Mode\n*************\nThe CppAD checkpoint function delays the caching of certain calculations\nuntil they are needed.\nIn :ref:`parallel model<ta_parallel_setup-name>` ,\nthis may result in :ref:`thread_alloc::inuse(thread)<ta_inuse-name>`\nbeing non-zero even though the specified thread is no longer active.\nThis memory will be freed when the checkpoint object is deleted.\n\nclear\n=====\nThe ``atomic_base`` class holds onto static work space\nthat is not connected to a particular object\n(in order to increase speed by avoiding system memory allocation calls).\nThis call makes to work space :ref:`available<ta_available-name>` to\nfor other uses by the same thread.\nThis should be called when you are done using the\natomic functions for a specific value of *Base* .\n\n{xrst_end chkpoint_one}\n*/\n\ntemplate <class Base>\nclass checkpoint : public atomic_base<Base> {\n// ---------------------------------------------------------------------------\nprivate:\n    /// same as option_enum in base class\n    typedef typename atomic_base<Base>::option_enum option_enum;\n    //\n    // ------------------------------------------------------------------------\n    // member_\n    // ------------------------------------------------------------------------\n    // same checkpoint object can be used by multiple threads\n    struct member_struct {\n        //\n        /// AD function corresponding to this checkpoint object\n        ADFun<Base>             f_;\n        ADFun< AD<Base>, Base > af_;\n        //\n        /// sparsity for entire Jacobian f(x)^{(1)}\n        /// does not change so can cache it\n        local::sparse::list_setvec jac_sparse_set_;\n        vectorBool                 jac_sparse_bool_;\n        //\n        /// sparsity for sum_i f_i(x)^{(2)} does not change so can cache it\n        local::sparse::list_setvec hes_sparse_set_;\n        vectorBool                 hes_sparse_bool_;\n    };\n    /// This version of work is const except during constructor\n    member_struct const_member_;\n\n    /// use pointers and allocate memory to avoid false sharing\n    member_struct* member_[CPPAD_MAX_NUM_THREADS];\n    //\n    /// allocate member_ for this thread\n    void allocate_member(size_t thread)\n    {   if( member_[thread] == nullptr )\n        {   member_[thread] = new member_struct;\n            // The function is recorded in sequential mode and placed in\n            // const_member_.f_, other threads have copy.\n            member_[thread]->f_ = const_member_.f_;\n        }\n        return;\n    }\n    //\n    /// free member_ for this thread\n    void free_member(size_t thread)\n    {   if( member_[thread] != nullptr )\n        {   delete member_[thread];\n            member_[thread] = nullptr;\n        }\n        return;\n    }\n    // ------------------------------------------------------------------------\n    option_enum sparsity(void)\n    {   return static_cast< atomic_base<Base>* >(this)->sparsity(); }\n    // ------------------------------------------------------------------------\n    /// set jac_sparse_set_\n    void set_jac_sparse_set(void);\n    /// set jac_sparse_bool_\n    void set_jac_sparse_bool(void);\n    // ------------------------------------------------------------------------\n    /// set hes_sparse_set_\n    void set_hes_sparse_set(void);\n    /// set hes_sparse_bool_\n    void set_hes_sparse_bool(void);\n    // ------------------------------------------------------------------------\n    /*!\n    Link from user_atomic to forward sparse Jacobian pack and bool\n\n    \\copydetails atomic_base::for_sparse_jac\n    */\n    template <class sparsity_type>\n    bool for_sparse_jac_sparsity_type(\n        size_t                                  q  ,\n        const sparsity_type&                    r  ,\n                  sparsity_type&                    s  ,\n        const vector<Base>&                     x\n    );\n    // ------------------------------------------------------------------------\n    /*!\n    Link from user_atomic to reverse sparse Jacobian pack and bool\n\n    \\copydetails atomic_base::rev_sparse_jac\n    */\n    template <class sparsity_type>\n    bool rev_sparse_jac_sparsity_type(\n        size_t                                  q  ,\n        const sparsity_type&                    rt ,\n                  sparsity_type&                    st ,\n        const vector<Base>&                     x\n    );\n    /*!\n    Link from user_atomic to reverse sparse Hessian  bools\n\n    \\copydetails atomic_base::rev_sparse_hes\n    */\n    template <class sparsity_type>\n    bool rev_sparse_hes_sparsity_type(\n        const vector<bool>&                     vx ,\n        const vector<bool>&                     s  ,\n                  vector<bool>&                     t  ,\n        size_t                                  q  ,\n        const sparsity_type&                    r  ,\n        const sparsity_type&                    u  ,\n                  sparsity_type&                    v  ,\n        const vector<Base>&                     x\n    );\npublic:\n    // ------------------------------------------------------------------------\n    /*!\n    Constructor of a checkpoint object\n\n    \\param name [in]\n    is the user's name for the AD version of this atomic operation.\n\n    \\param algo [in/out]\n    user routine that compute AD function values\n    (not const because state may change during evaluation).\n\n    \\param ax [in]\n    argument value where algo operation sequence is taped.\n\n    \\param ay [out]\n    function value at specified argument value.\n\n    \\param sparsity [in]\n    what type of sparsity patterns are computed by this function,\n    pack_sparsity_enum bool_sparsity_enum, or set_sparsity_enum.\n    The default value is unspecified.\n\n    \\param optimize [in]\n    should the operation sequence corresponding to the algo be optimized.\n    The default value is true, but it is\n    sometimes useful to use false for debugging purposes.\n    */\n    template <class Algo, class ADVector>\n    checkpoint(\n        const char*                    name            ,\n        Algo&                          algo            ,\n        const ADVector&                ax              ,\n        ADVector&                      ay              ,\n        option_enum                    sparsity =\n                atomic_base<Base>::pack_sparsity_enum  ,\n        bool                           optimize = true\n    );\n    /// destructor\n    ~checkpoint(void)\n    {\n# ifndef NDEBUG\n        if( thread_alloc::in_parallel() )\n        {   std::string msg = atomic_base<Base>::atomic_name();\n            msg += \": checkpoint destructor called in parallel mode.\";\n            CPPAD_ASSERT_KNOWN(false, msg.c_str() );\n        }\n# endif\n        for(size_t thread = 0; thread < CPPAD_MAX_NUM_THREADS; ++thread)\n            free_member(thread);\n    }\n    // ------------------------------------------------------------------------\n    /*!\n    Implement the user call to atom_fun.size_var().\n    */\n    size_t size_var(void)\n    {   // make sure member_ is allocated for this thread\n        size_t thread = thread_alloc::thread_num();\n        allocate_member(thread);\n        //\n        return member_[thread]->f_.size_var();\n    }\n    // ------------------------------------------------------------------------\n    /*!\n    Implement the user call to atom_fun(ax, ay).\n\n    \\tparam ADVector\n    A simple vector class with elements of type AD<Base>.\n\n    \\param id\n    optional parameter which must be zero if present.\n\n    \\param ax\n    is the argument vector for this call,\n    ax.size() determines the number of arguments.\n\n    \\param ay\n    is the result vector for this call,\n    ay.size() determines the number of results.\n    */\n    template <class ADVector>\n    void operator()(const ADVector& ax, ADVector& ay, size_t id = 0)\n    {   CPPAD_ASSERT_KNOWN(\n            id == 0,\n            \"checkpoint: id is non-zero in atom_fun(ax, ay, id)\"\n        );\n        this->atomic_base<Base>::operator()(ax, ay, id);\n    }\n    // ------------------------------------------------------------------------\n    /*!\n    Link from user_atomic to forward mode\n\n    \\copydetails atomic_base::forward\n    */\n    virtual bool forward(\n        size_t                      p  ,\n        size_t                      q  ,\n        const vector<bool>&         vx ,\n                  vector<bool>&         vy ,\n        const vector<Base>&         tx ,\n                  vector<Base>&         ty\n    );\n    virtual bool forward(\n        size_t                      p   ,\n        size_t                      q   ,\n        const vector<bool>&         vx  ,\n                  vector<bool>&         vy  ,\n        const vector< AD<Base> >&   atx ,\n                  vector< AD<Base> >&   aty\n    );\n    // ------------------------------------------------------------------------\n    /*!\n    Link from user_atomic to reverse mode\n\n    \\copydetails atomic_base::reverse\n    */\n    virtual bool reverse(\n        size_t                          q  ,\n        const vector<Base>&             tx ,\n        const vector<Base>&             ty ,\n                  vector<Base>&             px ,\n        const vector<Base>&             py\n    );\n    virtual bool reverse(\n        size_t                          q  ,\n        const vector< AD<Base> >&       atx ,\n        const vector< AD<Base> >&       aty ,\n                  vector< AD<Base> >&       apx ,\n        const vector< AD<Base> >&       apy\n    );\n    // ------------------------------------------------------------------------\n    /*!\n    Link from user_atomic to forward sparse Jacobian pack\n\n    \\copydetails atomic_base::for_sparse_jac\n    */\n    virtual bool for_sparse_jac(\n        size_t                                  q  ,\n        const vectorBool&                       r  ,\n                  vectorBool&                       s  ,\n        const vector<Base>&                     x\n    );\n    /*!\n    Link from user_atomic to forward sparse Jacobian bool\n\n    \\copydetails atomic_base::for_sparse_jac\n    */\n    virtual bool for_sparse_jac(\n        size_t                                  q  ,\n        const vector<bool>&                     r  ,\n                  vector<bool>&                     s  ,\n        const vector<Base>&                     x\n    );\n    /*!\n    Link from user_atomic to forward sparse Jacobian sets\n\n    \\copydetails atomic_base::for_sparse_jac\n    */\n    virtual bool for_sparse_jac(\n        size_t                                  q  ,\n        const vector< std::set<size_t> >&       r  ,\n                  vector< std::set<size_t> >&       s  ,\n        const vector<Base>&                     x\n    );\n    // ------------------------------------------------------------------------\n    /*!\n    Link from user_atomic to reverse sparse Jacobian pack\n\n    \\copydetails atomic_base::rev_sparse_jac\n    */\n    virtual bool rev_sparse_jac(\n        size_t                                  q  ,\n        const vectorBool&                       rt ,\n                  vectorBool&                       st ,\n        const vector<Base>&                     x\n    );\n    /*!\n    Link from user_atomic to reverse sparse Jacobian bool\n\n    \\copydetails atomic_base::rev_sparse_jac\n    */\n    virtual bool rev_sparse_jac(\n        size_t                                  q  ,\n        const vector<bool>&                     rt ,\n                  vector<bool>&                     st ,\n        const vector<Base>&                     x\n    );\n    /*!\n    Link from user_atomic to reverse Jacobian sets\n\n    \\copydetails atomic_base::rev_sparse_jac\n    */\n    virtual bool rev_sparse_jac(\n        size_t                                  q  ,\n        const vector< std::set<size_t> >&       rt ,\n                  vector< std::set<size_t> >&       st ,\n        const vector<Base>&                     x\n    );\n    // ------------------------------------------------------------------------\n    /*!\n    Link from user_atomic to reverse sparse Hessian pack\n\n    \\copydetails atomic_base::rev_sparse_hes\n    */\n    virtual bool rev_sparse_hes(\n        const vector<bool>&                     vx ,\n        const vector<bool>&                     s  ,\n                  vector<bool>&                     t  ,\n        size_t                                  q  ,\n        const vectorBool&                       r  ,\n        const vectorBool&                       u  ,\n                  vectorBool&                       v  ,\n        const vector<Base>&                     x\n    );\n    /*!\n    Link from user_atomic to reverse sparse Hessian bool\n\n    \\copydetails atomic_base::rev_sparse_hes\n    */\n    virtual bool rev_sparse_hes(\n        const vector<bool>&                     vx ,\n        const vector<bool>&                     s  ,\n                  vector<bool>&                     t  ,\n        size_t                                  q  ,\n        const vector<bool>&                     r  ,\n        const vector<bool>&                     u  ,\n                  vector<bool>&                     v  ,\n        const vector<Base>&                     x\n    );\n    /*!\n    Link from user_atomic to reverse sparse Hessian sets\n\n    \\copydetails atomic_base::rev_sparse_hes\n    */\n    virtual bool rev_sparse_hes(\n        const vector<bool>&                     vx ,\n        const vector<bool>&                     s  ,\n                  vector<bool>&                     t  ,\n        size_t                                  q  ,\n        const vector< std::set<size_t> >&       r  ,\n        const vector< std::set<size_t> >&       u  ,\n                  vector< std::set<size_t> >&       v  ,\n        const vector<Base>&                     x\n    );\n};\n\n} // END_CPPAD_NAMESPACE\n\n// functions implemented in cppad/core/checkpoint files\n# include <cppad/core/chkpoint_one/ctor.hpp>\n# include <cppad/core/chkpoint_one/reverse.hpp>\n# include <cppad/core/chkpoint_one/forward.hpp>\n# include <cppad/core/chkpoint_one/rev_sparse_hes.hpp>\n# include <cppad/core/chkpoint_one/rev_sparse_jac.hpp>\n# include <cppad/core/chkpoint_one/for_sparse_jac.hpp>\n# include <cppad/core/chkpoint_one/set_hes_sparse_bool.hpp>\n# include <cppad/core/chkpoint_one/set_hes_sparse_set.hpp>\n# include <cppad/core/chkpoint_one/set_jac_sparse_bool.hpp>\n# include <cppad/core/chkpoint_one/set_jac_sparse_set.hpp>\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/chkpoint_one/ctor.hpp",
    "content": "# ifndef CPPAD_CORE_CHKPOINT_ONE_CTOR_HPP\n# define CPPAD_CORE_CHKPOINT_ONE_CTOR_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n\ntemplate <class Base>\ntemplate <class Algo, class ADVector>\ncheckpoint<Base>::checkpoint(\n    const char*                    name            ,\n    Algo&                          algo            ,\n    const ADVector&                ax              ,\n    ADVector&                      ay              ,\n    option_enum                    sparsity        ,\n    bool                           optimize\n) : atomic_base<Base>(name, sparsity)\n{\n# ifndef NDEBUG\n    if( thread_alloc::in_parallel() )\n    {   std::string msg = name;\n        msg += \": checkpoint constructor called in parallel mode.\";\n        CPPAD_ASSERT_KNOWN(false, msg.c_str() );\n    }\n# endif\n    for(size_t thread = 0; thread < CPPAD_MAX_NUM_THREADS; ++thread)\n        member_[thread] = nullptr;\n    //\n    CheckSimpleVector< CppAD::AD<Base> , ADVector>();\n    //\n    // make a copy of ax because Independent modifies AD information\n    ADVector x_tmp(ax);\n    // declare x_tmp as the independent variables\n    Independent(x_tmp);\n    // record mapping from x_tmp to ay\n    algo(x_tmp, ay);\n    // create function f_ : x -> y\n    const_member_.f_.Dependent(ay);\n    if( optimize )\n    {   // suppress checking for nan in f_ results\n        // (see optimize documentation for atomic functions)\n        const_member_.f_.check_for_nan(false);\n        //\n        // now optimize\n        const_member_.f_.optimize();\n    }\n    // now disable checking of comparison operations\n    // 2DO: add a debugging mode that checks for changes and aborts\n    const_member_.f_.compare_change_count(0);\n}\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/chkpoint_one/for_sparse_jac.hpp",
    "content": "# ifndef CPPAD_CORE_CHKPOINT_ONE_FOR_SPARSE_JAC_HPP\n# define CPPAD_CORE_CHKPOINT_ONE_FOR_SPARSE_JAC_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n\ntemplate <class Base>\ntemplate <class sparsity_type>\nbool checkpoint<Base>::for_sparse_jac_sparsity_type(\n    size_t                                  q  ,\n    const sparsity_type&                    r  ,\n             sparsity_type&                    s  ,\n    const vector<Base>&                     x  )\n{   // make sure member_ is allocated for this thread\n    size_t thread = thread_alloc::thread_num();\n    allocate_member(thread);\n    //\n    // during user sparsity calculations\n    size_t m = member_[thread]->f_.Range();\n    size_t n = member_[thread]->f_.Domain();\n    if( member_[thread]->jac_sparse_bool_.size() == 0 )\n        set_jac_sparse_bool();\n    if( member_[thread]->jac_sparse_set_.n_set() != 0 )\n        member_[thread]->jac_sparse_set_.resize(0, 0);\n    CPPAD_ASSERT_UNKNOWN( member_[thread]->jac_sparse_bool_.size() == m * n );\n    CPPAD_ASSERT_UNKNOWN( member_[thread]->jac_sparse_set_.n_set() == 0 );\n    CPPAD_ASSERT_UNKNOWN( r.size() == n * q );\n    CPPAD_ASSERT_UNKNOWN( s.size() == m * q );\n    //\n    bool ok = true;\n    for(size_t i = 0; i < m; i++)\n    {   for(size_t k = 0; k < q; k++)\n            s[i * q + k] = false;\n    }\n    // sparsity for  s = jac_sparse_bool_ * r\n    for(size_t i = 0; i < m; i++)\n    {   for(size_t k = 0; k < q; k++)\n        {   // initialize sparsity for S(i,k)\n            bool s_ik = false;\n            // S(i,k) = sum_j J(i,j) * R(j,k)\n            for(size_t j = 0; j < n; j++)\n            {   bool J_ij = member_[thread]->jac_sparse_bool_[ i * n + j];\n                bool R_jk = r[j * q + k ];\n                s_ik |= ( J_ij & R_jk );\n            }\n            s[i * q + k] = s_ik;\n        }\n    }\n    return ok;\n}\ntemplate <class Base>\nbool checkpoint<Base>::for_sparse_jac(\n    size_t                                  q  ,\n    const vectorBool&                       r  ,\n             vectorBool&                       s  ,\n    const vector<Base>&                     x  )\n{   // make sure member_ is allocated for this thread\n    size_t thread = thread_alloc::thread_num();\n    allocate_member(thread);\n    //\n    return for_sparse_jac_sparsity_type< vectorBool >(q, r, s, x);\n}\ntemplate <class Base>\nbool checkpoint<Base>::for_sparse_jac(\n    size_t                                  q  ,\n    const vector<bool>&                     r  ,\n             vector<bool>&                     s  ,\n    const vector<Base>&                     x  )\n{   // make sure member_ is allocated for this thread\n    size_t thread = thread_alloc::thread_num();\n    allocate_member(thread);\n    //\n    return for_sparse_jac_sparsity_type< vector<bool> >(q, r, s, x);\n}\ntemplate <class Base>\nbool checkpoint<Base>::for_sparse_jac(\n    size_t                                  q  ,\n    const vector< std::set<size_t> >&       r  ,\n             vector< std::set<size_t> >&       s  ,\n    const vector<Base>&                     x  )\n{   // make sure member_ is allocated for this thread\n    size_t thread = thread_alloc::thread_num();\n    allocate_member(thread);\n    //\n    // during user sparsity calculations\n    size_t m = member_[thread]->f_.Range();\n    size_t n = member_[thread]->f_.Domain();\n    if( member_[thread]->jac_sparse_bool_.size() != 0 )\n        member_[thread]->jac_sparse_bool_.clear();\n    if( member_[thread]->jac_sparse_set_.n_set() == 0 )\n        set_jac_sparse_set();\n    CPPAD_ASSERT_UNKNOWN( member_[thread]->jac_sparse_bool_.size() == 0 );\n    CPPAD_ASSERT_UNKNOWN( member_[thread]->jac_sparse_set_.n_set() == m );\n    CPPAD_ASSERT_UNKNOWN( member_[thread]->jac_sparse_set_.end()   == n );\n    CPPAD_ASSERT_UNKNOWN( r.size() == n );\n    CPPAD_ASSERT_UNKNOWN( s.size() == m );\n\n    bool ok = true;\n    for(size_t i = 0; i < m; i++)\n        s[i].clear();\n\n    // sparsity for  s = jac_sparse_set_ * r\n    for(size_t i = 0; i < m; i++)\n    {   // compute row i of the return pattern\n        local::sparse::list_setvec::const_iterator set_itr(\n            member_[thread]->jac_sparse_set_, i\n        );\n        size_t j = *set_itr;\n        while(j < n )\n        {   std::set<size_t>::const_iterator itr_j;\n            const std::set<size_t>& r_j( r[j] );\n            for(itr_j = r_j.begin(); itr_j != r_j.end(); itr_j++)\n            {   size_t k = *itr_j;\n                CPPAD_ASSERT_UNKNOWN( k < q );\n                s[i].insert(k);\n            }\n            j = *(++set_itr);\n        }\n    }\n\n    return ok;\n}\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/chkpoint_one/forward.hpp",
    "content": "# ifndef CPPAD_CORE_CHKPOINT_ONE_FORWARD_HPP\n# define CPPAD_CORE_CHKPOINT_ONE_FORWARD_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n\n// ---------------------------------------------------------------------------\ntemplate <class Base>\nbool checkpoint<Base>::forward(\n    size_t                   p  ,\n    size_t                   q  ,\n    const vector<bool>&      vx ,\n             vector<bool>&      vy ,\n    const vector<Base>&      tx ,\n             vector<Base>&      ty )\n{   // make sure member_ is allocated for this thread\n    size_t thread = thread_alloc::thread_num();\n    allocate_member(thread);\n    //\n    size_t n = member_[thread]->f_.Domain();\n    size_t m = member_[thread]->f_.Range();\n    //\n    CPPAD_ASSERT_UNKNOWN( member_[thread]->f_.size_var() > 0 );\n    CPPAD_ASSERT_UNKNOWN( tx.size() % (q+1) == 0 );\n    CPPAD_ASSERT_UNKNOWN( ty.size() % (q+1) == 0 );\n    CPPAD_ASSERT_UNKNOWN( n == tx.size() / (q+1) );\n    CPPAD_ASSERT_UNKNOWN( m == ty.size() / (q+1) );\n    bool ok  = true;\n    //\n    if( vx.size() == 0 )\n    {   // during user forward mode\n        if( member_[thread]->jac_sparse_set_.n_set() != 0 )\n            member_[thread]->jac_sparse_set_.resize(0,0);\n        if( member_[thread]->jac_sparse_bool_.size() != 0 )\n            member_[thread]->jac_sparse_bool_.clear();\n        //\n        if( member_[thread]->hes_sparse_set_.n_set() != 0 )\n            member_[thread]->hes_sparse_set_.resize(0,0);\n        if( member_[thread]->hes_sparse_bool_.size() != 0 )\n            member_[thread]->hes_sparse_bool_.clear();\n    }\n    if( vx.size() > 0 )\n    {   // need Jacobian sparsity pattern to determine variable relation\n        // during user recording using checkpoint functions\n        if( sparsity() == atomic_base<Base>::set_sparsity_enum )\n        {   if( member_[thread]->jac_sparse_set_.n_set() == 0 )\n                set_jac_sparse_set();\n            CPPAD_ASSERT_UNKNOWN(\n                member_[thread]->jac_sparse_set_.n_set() == m\n            );\n            CPPAD_ASSERT_UNKNOWN(\n                member_[thread]->jac_sparse_set_.end()   == n\n            );\n            //\n            for(size_t i = 0; i < m; i++)\n            {   vy[i] = false;\n                local::sparse::list_setvec::const_iterator set_itr(\n                    member_[thread]->jac_sparse_set_, i\n                );\n                size_t j = *set_itr;\n                while(j < n )\n                {   // y[i] depends on the value of x[j]\n                    // cast avoid Microsoft warning (should not be needed)\n                    vy[i] |= static_cast<bool>( vx[j] );\n                    j = *(++set_itr);\n                }\n            }\n        }\n        else\n        {   if( member_[thread]->jac_sparse_set_.n_set() != 0 )\n                member_[thread]->jac_sparse_set_.resize(0, 0);\n            if( member_[thread]->jac_sparse_bool_.size() == 0 )\n                set_jac_sparse_bool();\n            CPPAD_ASSERT_UNKNOWN(\n                member_[thread]->jac_sparse_set_.n_set() == 0\n            );\n            CPPAD_ASSERT_UNKNOWN(\n                member_[thread]->jac_sparse_bool_.size() == m * n\n            );\n            //\n            for(size_t i = 0; i < m; i++)\n            {   vy[i] = false;\n                for(size_t j = 0; j < n; j++)\n                {   if( member_[thread]->jac_sparse_bool_[ i * n + j ] )\n                    {   // y[i] depends on the value of x[j]\n                        // cast avoid Microsoft warning\n                        vy[i] |= static_cast<bool>( vx[j] );\n                    }\n                }\n            }\n        }\n    }\n    // compute forward results for orders zero through q\n    ty = member_[thread]->f_.Forward(q, tx);\n\n    // no longer need the Taylor coefficients in f_\n    // (have to reconstruct them every time)\n    // Hold onto sparsity pattern because it is always good.\n    size_t c = 0;\n    size_t r = 0;\n    member_[thread]->f_.capacity_order(c, r);\n    return ok;\n}\n\n// ---------------------------------------------------------------------------\ntemplate <class Base>\nbool checkpoint<Base>::forward(\n    size_t                     p   ,\n    size_t                     q   ,\n    const vector<bool>&        vx  ,\n             vector<bool>&        vy  ,\n    const vector< AD<Base> >&  atx ,\n             vector< AD<Base> >&  aty )\n{   // make sure member_ is allocated for this thread\n    size_t thread = thread_alloc::thread_num();\n    allocate_member(thread);\n    //\n    // make sure af_ is defined\n    if( member_[thread]->af_.size_var() == 0 )\n        member_[thread]->af_ = member_[thread]->f_.base2ad();\n    //\n# ifndef NDEBUG\n    size_t n = member_[thread]->f_.Domain();\n    size_t m = member_[thread]->f_.Range();\n# endif\n    //\n    CPPAD_ASSERT_UNKNOWN( member_[thread]->f_.size_var() > 0 );\n    CPPAD_ASSERT_UNKNOWN( atx.size() % (q+1) == 0 );\n    CPPAD_ASSERT_UNKNOWN( aty.size() % (q+1) == 0 );\n    CPPAD_ASSERT_UNKNOWN( n == atx.size() / (q+1) );\n    CPPAD_ASSERT_UNKNOWN( m == aty.size() / (q+1) );\n    CPPAD_ASSERT_UNKNOWN( vx.size() == 0 )\n    bool ok  = true;\n    //\n    // during user forward mode\n    if( member_[thread]->jac_sparse_set_.n_set() != 0 )\n        member_[thread]->jac_sparse_set_.resize(0,0);\n    if( member_[thread]->jac_sparse_bool_.size() != 0 )\n        member_[thread]->jac_sparse_bool_.clear();\n    //\n    if( member_[thread]->hes_sparse_set_.n_set() != 0 )\n        member_[thread]->hes_sparse_set_.resize(0,0);\n    if( member_[thread]->hes_sparse_bool_.size() != 0 )\n        member_[thread]->hes_sparse_bool_.clear();\n    //\n    // compute forward results for orders zero through q\n    aty = member_[thread]->af_.Forward(q, atx);\n\n    // no longer need the Taylor coefficients in af_\n    // (have to reconstruct them every time)\n    // Hold onto sparsity pattern because it is always good.\n    size_t c = 0;\n    size_t r = 0;\n    member_[thread]->af_.capacity_order(c, r);\n    //\n    return ok;\n}\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/chkpoint_one/rev_sparse_hes.hpp",
    "content": "# ifndef CPPAD_CORE_CHKPOINT_ONE_REV_SPARSE_HES_HPP\n# define CPPAD_CORE_CHKPOINT_ONE_REV_SPARSE_HES_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n\ntemplate <class Base>\ntemplate <class sparsity_type>\nbool checkpoint<Base>::rev_sparse_hes_sparsity_type(\n    const vector<bool>&                     vx ,\n    const vector<bool>&                     s  ,\n             vector<bool>&                     t  ,\n    size_t                                  q  ,\n    const sparsity_type&                    r  ,\n    const sparsity_type&                    u  ,\n             sparsity_type&                    v  ,\n    const vector<Base>&                     x  )\n{   // make sure member_ is allocated for this thread\n    size_t thread = thread_alloc::thread_num();\n    allocate_member(thread);\n    //\n    size_t n = member_[thread]->f_.Domain();\n# ifndef NDEBUG\n    size_t m = member_[thread]->f_.Range();\n# endif\n    CPPAD_ASSERT_UNKNOWN( vx.size() == n );\n    CPPAD_ASSERT_UNKNOWN(  s.size() == m );\n    CPPAD_ASSERT_UNKNOWN(  t.size() == n );\n    CPPAD_ASSERT_UNKNOWN(  r.size() == n * q );\n    CPPAD_ASSERT_UNKNOWN(  u.size() == m * q );\n    CPPAD_ASSERT_UNKNOWN(  v.size() == n * q );\n    //\n    bool ok        = true;\n\n    // make sure hes_sparse_bool_ has been set\n    if( member_[thread]->hes_sparse_bool_.size() == 0 )\n        set_hes_sparse_bool();\n    if( member_[thread]->hes_sparse_set_.n_set() != 0 )\n        member_[thread]->hes_sparse_set_.resize(0, 0);\n    CPPAD_ASSERT_UNKNOWN( member_[thread]->hes_sparse_bool_.size() == n * n );\n    CPPAD_ASSERT_UNKNOWN( member_[thread]->hes_sparse_set_.n_set() == 0 );\n\n\n    // compute sparsity pattern for T(x) = S(x) * f'(x)\n    t = member_[thread]->f_.RevSparseJac(1, s);\n# ifndef NDEBUG\n    for(size_t j = 0; j < n; j++)\n        CPPAD_ASSERT_UNKNOWN( vx[j] || ! t[j] )\n# endif\n\n    // V(x) = f'(x)^T * g''(y) * f'(x) * R  +  g'(y) * f''(x) * R\n    // U(x) = g''(y) * f'(x) * R\n    // S(x) = g'(y)\n\n    // compute sparsity pattern for A(x) = f'(x)^T * U(x)\n    bool transpose = true;\n    sparsity_type a(n * q);\n    a = member_[thread]->f_.RevSparseJac(q, u, transpose);\n\n    // Need sparsity pattern for H(x) = (S(x) * f(x))''(x) * R,\n    // but use less efficient sparsity for  f(x)''(x) * R so that\n    // hes_sparse_set_ can be used every time this is needed.\n    for(size_t i = 0; i < n; i++)\n    {   for(size_t k = 0; k < q; k++)\n        {   // initialize sparsity pattern for H(i,k)\n            bool h_ik = false;\n            // H(i,k) = sum_j f''(i,j) * R(j,k)\n            for(size_t j = 0; j < n; j++)\n            {   bool f_ij = member_[thread]->hes_sparse_bool_[i * n + j];\n                bool r_jk = r[j * q + k];\n                h_ik     |= ( f_ij & r_jk );\n            }\n            // sparsity for H(i,k)\n            v[i * q + k] = h_ik;\n        }\n    }\n\n    // compute sparsity pattern for V(x) = A(x) + H(x)\n    for(size_t i = 0; i < n; i++)\n    {   for(size_t k = 0; k < q; k++)\n            // v[ i * q + k ] |= a[ i * q + k];\n            v[ i * q + k ] = bool(v[ i * q + k]) || bool(a[ i * q + k]);\n    }\n    return ok;\n}\ntemplate <class Base>\nbool checkpoint<Base>::rev_sparse_hes(\n    const vector<bool>&                     vx ,\n    const vector<bool>&                     s  ,\n             vector<bool>&                     t  ,\n    size_t                                  q  ,\n    const vectorBool&                       r  ,\n    const vectorBool&                       u  ,\n             vectorBool&                       v  ,\n    const vector<Base>&                     x  )\n{   // make sure member_ is allocated for this thread\n    size_t thread = thread_alloc::thread_num();\n    allocate_member(thread);\n    //\n    return rev_sparse_hes_sparsity_type< vectorBool >(vx, s, t, q, r, u, v, x);\n}\ntemplate <class Base>\nbool checkpoint<Base>::rev_sparse_hes(\n    const vector<bool>&                     vx ,\n    const vector<bool>&                     s  ,\n             vector<bool>&                     t  ,\n    size_t                                  q  ,\n    const vector<bool>&                     r  ,\n    const vector<bool>&                     u  ,\n             vector<bool>&                     v  ,\n    const vector<Base>&                     x  )\n{   // make sure member_ is allocated for this thread\n    size_t thread = thread_alloc::thread_num();\n    allocate_member(thread);\n    //\n    return rev_sparse_hes_sparsity_type< vector<bool> >(vx, s, t, q, r, u, v, x);\n}\ntemplate <class Base>\nbool checkpoint<Base>::rev_sparse_hes(\n    const vector<bool>&                     vx ,\n    const vector<bool>&                     s  ,\n             vector<bool>&                     t  ,\n    size_t                                  q  ,\n    const vector< std::set<size_t> >&       r  ,\n    const vector< std::set<size_t> >&       u  ,\n             vector< std::set<size_t> >&       v  ,\n    const vector<Base>&                     x  )\n{   // make sure member_ is allocated for this thread\n    size_t thread = thread_alloc::thread_num();\n    allocate_member(thread);\n    //\n    size_t n = member_[thread]->f_.Domain();\n# ifndef NDEBUG\n    size_t m = member_[thread]->f_.Range();\n# endif\n    CPPAD_ASSERT_UNKNOWN( vx.size() == n );\n    CPPAD_ASSERT_UNKNOWN(  s.size() == m );\n    CPPAD_ASSERT_UNKNOWN(  t.size() == n );\n    CPPAD_ASSERT_UNKNOWN(  r.size() == n );\n    CPPAD_ASSERT_UNKNOWN(  u.size() == m );\n    CPPAD_ASSERT_UNKNOWN(  v.size() == n );\n    //\n    bool ok        = true;\n\n    // make sure hes_sparse_set_ has been set\n    if( member_[thread]->hes_sparse_bool_.size() != 0 )\n        member_[thread]->hes_sparse_bool_.clear();\n    if( member_[thread]->hes_sparse_set_.n_set() == 0 )\n        set_hes_sparse_set();\n    CPPAD_ASSERT_UNKNOWN( member_[thread]->hes_sparse_bool_.size() == 0 );\n    CPPAD_ASSERT_UNKNOWN( member_[thread]->hes_sparse_set_.n_set() == n );\n    CPPAD_ASSERT_UNKNOWN( member_[thread]->hes_sparse_set_.end()   == n );\n\n    // compute sparsity pattern for T(x) = S(x) * f'(x)\n    t = member_[thread]->f_.RevSparseJac(1, s);\n# ifndef NDEBUG\n    for(size_t j = 0; j < n; j++)\n        CPPAD_ASSERT_UNKNOWN( vx[j] || ! t[j] )\n# endif\n\n    // V(x) = f'(x)^T * g''(y) * f'(x) * R  +  g'(y) * f''(x) * R\n    // U(x) = g''(y) * f'(x) * R\n    // S(x) = g'(y)\n\n    // compute sparsity pattern for A(x) = f'(x)^T * U(x)\n    // 2DO: change a to use INTERNAL_SPARSE_SET\n    bool transpose = true;\n    vector< std::set<size_t> > a(n);\n    a = member_[thread]->f_.RevSparseJac(q, u, transpose);\n\n    // Need sparsity pattern for H(x) = (S(x) * f(x))''(x) * R,\n    // but use less efficient sparsity for  f(x)''(x) * R so that\n    // hes_sparse_set_ can be used every time this is needed.\n    for(size_t i = 0; i < n; i++)\n    {   v[i].clear();\n        local::sparse::list_setvec::const_iterator set_itr(\n            member_[thread]->hes_sparse_set_, i\n        );\n        size_t j = *set_itr;\n        while( j < n )\n        {   std::set<size_t>::const_iterator itr_j;\n            const std::set<size_t>& r_j( r[j] );\n            for(itr_j = r_j.begin(); itr_j != r_j.end(); itr_j++)\n            {   size_t k = *itr_j;\n                v[i].insert(k);\n            }\n            j = *(++set_itr);\n        }\n    }\n    // compute sparsity pattern for V(x) = A(x) + H(x)\n    std::set<size_t>::const_iterator itr;\n    for(size_t i = 0; i < n; i++)\n    {   for(itr = a[i].begin(); itr != a[i].end(); itr++)\n        {   size_t j = *itr;\n            CPPAD_ASSERT_UNKNOWN( j < q );\n            v[i].insert(j);\n        }\n    }\n\n    return ok;\n}\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/chkpoint_one/rev_sparse_jac.hpp",
    "content": "# ifndef CPPAD_CORE_CHKPOINT_ONE_REV_SPARSE_JAC_HPP\n# define CPPAD_CORE_CHKPOINT_ONE_REV_SPARSE_JAC_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n\ntemplate <class Base>\ntemplate <class sparsity_type>\nbool checkpoint<Base>::rev_sparse_jac_sparsity_type(\n    size_t                                  q  ,\n    const sparsity_type&                    rt ,\n             sparsity_type&                    st ,\n    const vector<Base>&                     x  )\n{   // make sure member_ is allocated for this thread\n    size_t thread = thread_alloc::thread_num();\n    allocate_member(thread);\n    //\n    // during user sparsity calculations\n    size_t m = member_[thread]->f_.Range();\n    size_t n = member_[thread]->f_.Domain();\n    if( member_[thread]->jac_sparse_bool_.size() == 0 )\n        set_jac_sparse_bool();\n    if( member_[thread]->jac_sparse_set_.n_set() != 0 )\n        member_[thread]->jac_sparse_set_.resize(0, 0);\n    CPPAD_ASSERT_UNKNOWN( member_[thread]->jac_sparse_bool_.size() == m * n );\n    CPPAD_ASSERT_UNKNOWN( member_[thread]->jac_sparse_set_.n_set() == 0 );\n    CPPAD_ASSERT_UNKNOWN( rt.size() == m * q );\n    CPPAD_ASSERT_UNKNOWN( st.size() == n * q );\n    bool ok  = true;\n    //\n    // S = R * J where J is jacobian\n    for(size_t i = 0; i < q; i++)\n    {   for(size_t j = 0; j < n; j++)\n        {   // initialize sparsity for S(i,j)\n            bool s_ij = false;\n            // S(i,j) = sum_k R(i,k) * J(k,j)\n            for(size_t k = 0; k < m; k++)\n            {   // sparsity for R(i, k)\n                bool R_ik = rt[ k * q + i ];\n                bool J_kj = member_[thread]->jac_sparse_bool_[ k * n + j ];\n                s_ij     |= (R_ik & J_kj);\n            }\n            // set sparsity for S^T\n            st[ j * q + i ] = s_ij;\n        }\n    }\n    return ok;\n}\ntemplate <class Base>\nbool checkpoint<Base>::rev_sparse_jac(\n    size_t                                  q  ,\n    const vectorBool&                       rt ,\n             vectorBool&                       st ,\n    const vector<Base>&                     x  )\n{   // make sure member_ is allocated for this thread\n    size_t thread = thread_alloc::thread_num();\n    allocate_member(thread);\n    //\n    return rev_sparse_jac_sparsity_type< vectorBool >(q, rt, st, x);\n}\ntemplate <class Base>\nbool checkpoint<Base>::rev_sparse_jac(\n    size_t                                  q  ,\n    const vector<bool>&                     rt ,\n             vector<bool>&                     st ,\n    const vector<Base>&                     x  )\n{   // make sure member_ is allocated for this thread\n    size_t thread = thread_alloc::thread_num();\n    allocate_member(thread);\n    //\n    return rev_sparse_jac_sparsity_type< vector<bool> >(q, rt, st, x);\n}\ntemplate <class Base>\nbool checkpoint<Base>::rev_sparse_jac(\n    size_t                                  q  ,\n    const vector< std::set<size_t> >&       rt ,\n             vector< std::set<size_t> >&       st ,\n    const vector<Base>&                     x  )\n{   // make sure member_ is allocated for this thread\n    size_t thread = thread_alloc::thread_num();\n    allocate_member(thread);\n    //\n    // during user sparsity calculations\n    size_t m = member_[thread]->f_.Range();\n    size_t n = member_[thread]->f_.Domain();\n    if( member_[thread]->jac_sparse_bool_.size() != 0 )\n        member_[thread]->jac_sparse_bool_.clear();\n    if( member_[thread]->jac_sparse_set_.n_set() == 0 )\n        set_jac_sparse_set();\n    CPPAD_ASSERT_UNKNOWN( member_[thread]->jac_sparse_bool_.size() == 0 );\n    CPPAD_ASSERT_UNKNOWN( member_[thread]->jac_sparse_set_.n_set() == m );\n    CPPAD_ASSERT_UNKNOWN( member_[thread]->jac_sparse_set_.end()   == n );\n    CPPAD_ASSERT_UNKNOWN( rt.size() == m );\n    CPPAD_ASSERT_UNKNOWN( st.size() == n );\n    //\n    bool ok  = true;\n    //\n    for(size_t j = 0; j < n; j++)\n        st[j].clear();\n    //\n    // sparsity for  s = r * jac_sparse_set_\n    // s^T = jac_sparse_set_^T * r^T\n    for(size_t i = 0; i < m; i++)\n    {   // i is the row index in r^T\n        std::set<size_t>::const_iterator itr_i;\n        const std::set<size_t>& r_i( rt[i] );\n        for(itr_i = r_i.begin(); itr_i != r_i.end(); itr_i++)\n        {   // k is the column index in r^T\n            size_t k = *itr_i;\n            CPPAD_ASSERT_UNKNOWN( k < q );\n            //\n            // i is column index in jac_sparse_set^T\n            local::sparse::list_setvec::const_iterator set_itr(\n                member_[thread]->jac_sparse_set_, i\n            );\n            size_t j = *set_itr;\n            while( j < n )\n            {   // j is row index in jac_sparse_set^T\n                st[j].insert(k);\n                j = *(++set_itr);\n            }\n        }\n    }\n\n    return ok;\n}\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/chkpoint_one/reverse.hpp",
    "content": "# ifndef CPPAD_CORE_CHKPOINT_ONE_REVERSE_HPP\n# define CPPAD_CORE_CHKPOINT_ONE_REVERSE_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n\n// ---------------------------------------------------------------------------\ntemplate <class Base>\nbool checkpoint<Base>::reverse(\n    size_t                    q  ,\n    const vector<Base>&       tx ,\n    const vector<Base>&       ty ,\n             vector<Base>&       px ,\n    const vector<Base>&       py )\n{   // make sure member_ is allocated for this thread\n    size_t thread = thread_alloc::thread_num();\n    allocate_member(thread);\n    //\n\n# ifndef NDEBUG\n    size_t n = member_[thread]->f_.Domain();\n    size_t m = member_[thread]->f_.Range();\n# endif\n    CPPAD_ASSERT_UNKNOWN( member_[thread]->f_.size_var() > 0 );\n    CPPAD_ASSERT_UNKNOWN( n == tx.size() / (q+1) );\n    CPPAD_ASSERT_UNKNOWN( m == ty.size() / (q+1) );\n    CPPAD_ASSERT_UNKNOWN( tx.size() % (q+1) == 0 );\n    CPPAD_ASSERT_UNKNOWN( ty.size() % (q+1) == 0 );\n    CPPAD_ASSERT_UNKNOWN( px.size() == n * (q+1) );\n    CPPAD_ASSERT_UNKNOWN( py.size() == m * (q+1) );\n    bool ok  = true;\n\n    // put proper forward mode coefficients in f_\n# ifdef NDEBUG\n    // compute forward results for orders zero through q\n    member_[thread]->f_.Forward(q, tx);\n# else\n    size_t i, j, k;\n    //\n    // compute forward results for orders zero through q\n    vector<Base> check_ty = member_[thread]->f_.Forward(q, tx);\n    for(i = 0; i < m; i++)\n    {   for(k = 0; k <= q; k++)\n        {   j = i * (q+1) + k;\n            CPPAD_ASSERT_UNKNOWN( check_ty[j] == ty[j] );\n        }\n    }\n# endif\n    // now can run reverse mode\n    px = member_[thread]->f_.Reverse(q+1, py);\n\n    // no longer need the Taylor coefficients in f_\n    // (have to reconstruct them every time)\n    size_t c = 0;\n    size_t r = 0;\n    member_[thread]->f_.capacity_order(c, r);\n    return ok;\n}\n// ---------------------------------------------------------------------------\ntemplate <class Base>\nbool checkpoint<Base>::reverse(\n    size_t                          q   ,\n    const vector< AD<Base> >&       atx ,\n    const vector< AD<Base> >&       aty ,\n             vector< AD<Base> >&       apx ,\n    const vector< AD<Base> >&       apy )\n{   // make sure member_ is allocated for this thread\n    size_t thread = thread_alloc::thread_num();\n    allocate_member(thread);\n    //\n    // make sure af_ is defined\n    if( member_[thread]->af_.size_var() == 0 )\n        member_[thread]->af_ = member_[thread]->f_.base2ad();\n# ifndef NDEBUG\n    size_t n = member_[thread]->f_.Domain();\n    size_t m = member_[thread]->f_.Range();\n# endif\n    CPPAD_ASSERT_UNKNOWN( member_[thread]->f_.size_var() > 0 );\n    CPPAD_ASSERT_UNKNOWN( n == atx.size() / (q+1) );\n    CPPAD_ASSERT_UNKNOWN( m == aty.size() / (q+1) );\n    CPPAD_ASSERT_UNKNOWN( atx.size() % (q+1) == 0 );\n    CPPAD_ASSERT_UNKNOWN( aty.size() % (q+1) == 0 );\n    CPPAD_ASSERT_UNKNOWN( apx.size() == n * (q+1) );\n    CPPAD_ASSERT_UNKNOWN( apy.size() == m * (q+1) );\n    bool ok  = true;\n\n    // put proper forward mode coefficients in f_\n# ifdef NDEBUG\n    // compute forward results for orders zero through q\n    member_[thread]->af_.Forward(q, atx);\n# else\n    size_t i, j, k;\n    //\n    // compute forward results for orders zero through q\n    vector< AD<Base> > check_aty = member_[thread]->af_.Forward(q, atx);\n    for(i = 0; i < m; i++)\n    {   for(k = 0; k <= q; k++)\n        {   j = i * (q+1) + k;\n            CPPAD_ASSERT_UNKNOWN( check_aty[j] == aty[j] );\n        }\n    }\n# endif\n    // now can run reverse mode\n    apx = member_[thread]->af_.Reverse(q+1, apy);\n\n    // no longer need the Taylor coefficients in f_\n    // (have to reconstruct them every time)\n    size_t c = 0;\n    size_t r = 0;\n    member_[thread]->af_.capacity_order(c, r);\n    return ok;\n}\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/chkpoint_one/set_hes_sparse_bool.hpp",
    "content": "# ifndef CPPAD_CORE_CHKPOINT_ONE_SET_HES_SPARSE_BOOL_HPP\n# define CPPAD_CORE_CHKPOINT_ONE_SET_HES_SPARSE_BOOL_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n\ntemplate <class Base>\nvoid checkpoint<Base>::set_hes_sparse_bool(void)\n{   // make sure member_ is allocated for this thread\n    size_t thread = thread_alloc::thread_num();\n    allocate_member(thread);\n    //\n    CPPAD_ASSERT_UNKNOWN( member_[thread]->hes_sparse_bool_.size() == 0 );\n    size_t n = member_[thread]->f_.Domain();\n    size_t m = member_[thread]->f_.Range();\n    //\n    // set version of sparsity for vector of all ones\n    vectorBool all_one(m);\n    for(size_t i = 0; i < m; i++)\n        all_one[i] = true;\n\n    // set version of sparsity for n by n identity matrix\n    vectorBool identity(n * n);\n    for(size_t j = 0; j < n; j++)\n    {   for(size_t i = 0; i < n; i++)\n            identity[ i * n + j ] = (i == j);\n    }\n\n    // compute sparsity pattern for H(x) = sum_i f_i(x)^{(2)}\n    bool transpose  = false;\n    bool dependency = false;\n    member_[thread]->f_.ForSparseJac(n, identity, transpose, dependency);\n    member_[thread]->hes_sparse_bool_ = member_[thread]->f_.RevSparseHes(n, all_one, transpose);\n    CPPAD_ASSERT_UNKNOWN( member_[thread]->hes_sparse_bool_.size() == n * n );\n    //\n    // drop the forward sparsity results from f_\n    member_[thread]->f_.size_forward_bool(0);\n    CPPAD_ASSERT_UNKNOWN( member_[thread]->f_.size_forward_bool() == 0 );\n    CPPAD_ASSERT_UNKNOWN( member_[thread]->f_.size_forward_set() == 0 );\n}\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/chkpoint_one/set_hes_sparse_set.hpp",
    "content": "# ifndef CPPAD_CORE_CHKPOINT_ONE_SET_HES_SPARSE_SET_HPP\n# define CPPAD_CORE_CHKPOINT_ONE_SET_HES_SPARSE_SET_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n\ntemplate <class Base>\nvoid checkpoint<Base>::set_hes_sparse_set(void)\n{   // make sure member_ is allocated for this thread\n    size_t thread = thread_alloc::thread_num();\n    allocate_member(thread);\n    //\n    CPPAD_ASSERT_UNKNOWN( member_[thread]->hes_sparse_set_.n_set() == 0 );\n    size_t n = member_[thread]->f_.Domain();\n    size_t m = member_[thread]->f_.Range();\n    //\n    // set version of sparsity for vector of all ones\n    vector<bool> all_one(m);\n    for(size_t i = 0; i < m; i++)\n        all_one[i] = true;\n\n    // set version of sparsity for n by n identity matrix\n    local::sparse::list_setvec identity;\n    identity.resize(n, n);\n    for(size_t j = 0; j < n; j++)\n    {   // Not using post_element because only adding one element per set\n        identity.add_element(j, j);\n    }\n\n    // compute sparsity pattern for H(x) = sum_i f_i(x)^{(2)}\n    bool transpose  = false;\n    bool dependency = false;\n    member_[thread]->f_.ForSparseJacCheckpoint(\n        n, identity, transpose, dependency, member_[thread]->jac_sparse_set_\n    );\n    member_[thread]->f_.RevSparseHesCheckpoint(\n        n, all_one, transpose, member_[thread]->hes_sparse_set_\n    );\n    CPPAD_ASSERT_UNKNOWN( member_[thread]->hes_sparse_set_.n_set() == n );\n    CPPAD_ASSERT_UNKNOWN( member_[thread]->hes_sparse_set_.end()   == n );\n    //\n    // drop the forward sparsity results from f_\n    member_[thread]->f_.size_forward_set(0);\n}\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/chkpoint_one/set_jac_sparse_bool.hpp",
    "content": "# ifndef CPPAD_CORE_CHKPOINT_ONE_SET_JAC_SPARSE_BOOL_HPP\n# define CPPAD_CORE_CHKPOINT_ONE_SET_JAC_SPARSE_BOOL_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n\ntemplate <class Base>\nvoid checkpoint<Base>::set_jac_sparse_bool(void)\n{   // make sure member_ is allocated for this thread\n    size_t thread = thread_alloc::thread_num();\n    allocate_member(thread);\n    //\n    CPPAD_ASSERT_UNKNOWN( member_[thread]->jac_sparse_bool_.size() == 0 );\n    bool transpose  = false;\n    bool dependency = true;\n    size_t n = member_[thread]->f_.Domain();\n    size_t m = member_[thread]->f_.Range();\n    // Use the choice for forward / reverse that results in smaller\n    // size for the sparsity pattern of all variables in the tape.\n    if( n <= m )\n    {   vectorBool identity(n * n);\n        for(size_t j = 0; j < n; j++)\n        {   for(size_t i = 0; i < n; i++)\n                identity[ i * n + j ] = (i == j);\n        }\n        member_[thread]->jac_sparse_bool_ = member_[thread]->f_.ForSparseJac(\n            n, identity, transpose, dependency\n        );\n        member_[thread]->f_.size_forward_bool(0);\n    }\n    else\n    {   vectorBool identity(m * m);\n        for(size_t j = 0; j < m; j++)\n        {   for(size_t i = 0; i < m; i++)\n                identity[ i * m + j ] = (i == j);\n        }\n        member_[thread]->jac_sparse_bool_ = member_[thread]->f_.RevSparseJac(\n            m, identity, transpose, dependency\n        );\n    }\n    CPPAD_ASSERT_UNKNOWN( member_[thread]->f_.size_forward_bool() == 0 );\n    CPPAD_ASSERT_UNKNOWN( member_[thread]->f_.size_forward_set() == 0 );\n}\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/chkpoint_one/set_jac_sparse_set.hpp",
    "content": "# ifndef CPPAD_CORE_CHKPOINT_ONE_SET_JAC_SPARSE_SET_HPP\n# define CPPAD_CORE_CHKPOINT_ONE_SET_JAC_SPARSE_SET_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n\ntemplate <class Base>\nvoid checkpoint<Base>::set_jac_sparse_set(void)\n{   // make sure member_ is allocated for this thread\n    size_t thread = thread_alloc::thread_num();\n    allocate_member(thread);\n    //\n    CPPAD_ASSERT_UNKNOWN( member_[thread]->jac_sparse_set_.n_set() == 0 );\n    bool transpose  = false;\n    bool dependency = true;\n    size_t n = member_[thread]->f_.Domain();\n    size_t m = member_[thread]->f_.Range();\n    // Use the choice for forward / reverse that results in smaller\n    // size for the sparsity pattern of all variables in the tape.\n    if( n <= m )\n    {   local::sparse::list_setvec identity;\n        identity.resize(n, n);\n        for(size_t j = 0; j < n; j++)\n        {   // Not using post_element because only adding one element per set\n            identity.add_element(j, j);\n        }\n        member_[thread]->f_.ForSparseJacCheckpoint(\n            n, identity, transpose, dependency, member_[thread]->jac_sparse_set_\n        );\n        member_[thread]->f_.size_forward_set(0);\n    }\n    else\n    {   local::sparse::list_setvec identity;\n        identity.resize(m, m);\n        for(size_t i = 0; i < m; i++)\n        {   // Not using post_element because only adding one element per set\n            identity.add_element(i, i);\n        }\n        member_[thread]->f_.RevSparseJacCheckpoint(\n            m, identity, transpose, dependency, member_[thread]->jac_sparse_set_\n        );\n    }\n    CPPAD_ASSERT_UNKNOWN( member_[thread]->f_.size_forward_set() == 0 );\n    CPPAD_ASSERT_UNKNOWN( member_[thread]->f_.size_forward_bool() == 0 );\n}\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/chkpoint_two/chk_fun.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin chkpoint_two_chk_fun}\n\nUsing Checkpoint Functions\n##########################\n\nSyntax\n******\n| *chk_fun* ( *ax* , *ay* )\n\nPurpose\n*******\nGiven *ax* ,\nthis call computes the corresponding value of *ay* .\nIf ``AD`` < *Base* > operations are being recorded,\nit enters the computation as an :ref:`atomic_three-name`\noperation in the recording;\nsee :ref:`Independent@Start Recording` .\n\nchk_fun\n*******\nThis object must have been created using the\n:ref:`chkpoint_two<chkpoint_two_ctor@chk_fun>` constructor.\n\nADVector\n********\nThe type *ADVector* must be a\n:ref:`simple vector class<SimpleVector-name>` with elements of type\n``AD`` < *Base* > .\n\nax\n**\nThis argument has prototype\n\n    ``const`` *ADVector* & ``ax``\n\nand its size equal to *n* = *fun* . ``Domain`` ()\nwhere :ref:`chkpoint_two_ctor@fun` is the ``ADFun`` < *Base* >\nfunction in used the constructor for *chk_fun* .\nIt specifies vector :math:`x \\in \\B{R}^n`\nat which we are computing an ``AD`` < *Base* > version of\n:math:`y = g(x)`.\n\nay\n**\nThis argument has prototype\n\n    *ADVector* & ``ay``\n\nand its size must be equal to *m* = *fun* . ``Range`` () .\nThe input values of its elements do not matter.\nUpon return, it is an ``AD`` < *Base* > version of\n:math:`y = g(x)`.\n\n{xrst_end chkpoint_two_chk_fun}\n"
  },
  {
    "path": "include/cppad/core/chkpoint_two/chkpoint_two.hpp",
    "content": "# ifndef CPPAD_CORE_CHKPOINT_TWO_CHKPOINT_TWO_HPP\n# define CPPAD_CORE_CHKPOINT_TWO_CHKPOINT_TWO_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\n\\file chkpoint_two.hpp\nSecond generation checkpoint functions.\n*/\n\n/*\n{xrst_begin chkpoint_two}\n{xrst_spell\n    chk\n}\n\nCheckpoint Functions: Second Generation\n#######################################\n\nSyntax\n******\n\nConstructor\n===========\n\n| ``chkpoint_two`` < *Base* > *chk_fun* ( *fun* , *name* ,\n| |tab| *internal_bool* , *use_hes_sparsity* , *use_base2ad* , *use_in_parallel*\n| )\n\nUse Checkpoint Function\n=======================\n*chk_fun* ( *ax* , *ay* )\n\nnew_dynamic\n===========\n*chk_fun* . ``new_dynamic`` ( *dynamic* )\n\nReduce Memory\n*************\nYou can reduce the size of the tape and memory required for AD\nusing a checkpoint representation of a function\n:math:`g : \\B{R}^n \\rightarrow \\B{R}^m`.\n\nFaster Recording\n****************\nIt may also reduce the time to make a recording if the same :math:`g(x)`\nis used many times (with different values) during the\nrecording of an ``ADFun`` < *Base* > object.\n\nRepeating Forward\n*****************\nNormally, CppAD stores :ref:`forward-name` mode results,\nuntil they freed using :ref:`capacity_order-name` ,\nor the corresponding :ref:`ADFun-name` object is deleted.\nThis is not true for ``chkpoint_two`` functions\nbecause the same checkpoint function may be used repeatedly\nwith different arguments during a single forward mode operation.\nThus, forward mode results are computed for each use of *chk_fun*\nin a forward mode sweep.\n\nOperation Sequence\n******************\nThe :ref:`operation sequence<glossary@Operation@Sequence>`\nrepresenting :math:`g(x)` is fixed; i.e.,\nit cannot depend on the value of :math:`x`.\n\natomic_three\n************\nThe ``chkpoint_two`` class is derived from ``atomic_three`` ,\nhence some of its error message will refer to atomic operations.\nThe ``chkpoint_two`` class implements all the\n:ref:`atomic_three_define@Virtual Functions`\nand hence its source code,\n\n    ``include/cppad/core/chkpoint_two/chkpoint_two.hpp``\n\nprovides an example for :ref:`atomic_three-name` operations.\nThe difference is that ``chkpoint_two.hpp`` uses AD\ninstead of user provided derivatives.\n\nBase\n****\nThe type *Base* specifies the base type for AD operations;\ni.e., *chk_fun* can be used during the recording of\n``AD`` < *Base* > operations.\n\nContents\n********\n{xrst_toc_table\n    include/cppad/core/chkpoint_two/ctor.hpp\n    include/cppad/core/chkpoint_two/chk_fun.xrst\n    include/cppad/core/chkpoint_two/dynamic.hpp\n    example/chkpoint_two/get_started.cpp\n    example/chkpoint_two/compare.cpp\n    example/chkpoint_two/base2ad.cpp\n    example/chkpoint_two/dynamic.cpp\n    example/chkpoint_two/ode.cpp\n}\n\n{xrst_end chkpoint_two}\n*/\n\ntemplate <class Base>\nclass chkpoint_two : public atomic_three<Base> {\n// ---------------------------------------------------------------------------\nprivate:\n    /// are sparsity calculations using bools or sets of integers\n    const bool internal_bool_;\n    //\n    /// can this checkpoint function calculate Hessian sparsity patterns\n    const bool use_hes_sparsity_;\n    //\n    /// can this checkpoint function be used in base2ad recordings\n    const bool use_base2ad_;\n    //\n    /// can this checkpoint function be used in parallel mode\n    const bool use_in_parallel_;\n    //\n    /// Jacobian sparsity for g(x) with dependency true.\n    /// This is set by the constructor and constant after that.\n    sparse_rc< vector<size_t> > jac_sparsity_;\n    //\n    /// Hessian sparsity for g(x). If use_hes_sparsity_ is true,\n    /// This is set by the constructor and constant after that.\n    sparse_rc< vector<size_t> > hes_sparsity_;\n    //\n    /// Function corresponding to this checkpoint object.\n    /// If use_in_parallel_, this is constant after the constructor.\n    ADFun<Base>    g_;\n    //\n    /// AD version of function corresponding to this checkpoint object\n    /// If use_in_parallel_, this is constant after the constructor.\n    ADFun< AD<Base>, Base>  ag_;\n    // ------------------------------------------------------------------------\n    // member_\n    // ------------------------------------------------------------------------\n    /// If use_in_parallel_ is true, must have a separate copy member data\n    /// that is not constant.\n    struct member_struct {\n        //\n        /// function corresponding to this checkpoint object\n        ADFun<Base>                 g_;\n        //\n        /// AD version of this function object\n        ADFun< AD<Base>, Base >     ag_;\n        //\n    };\n    /// use pointers and allocate memory to avoid false sharing\n    /// (initialized to null by constructor)\n    member_struct* member_[CPPAD_MAX_NUM_THREADS];\n    //\n    // ------------------------------------------------------------------------\n    /// allocate member_ for this thread\n    void allocate_member(size_t thread)\n    {   CPPAD_ASSERT_UNKNOWN( use_in_parallel_ );\n        if( member_[thread] == nullptr )\n        {   // allocaate raw memory\n            size_t min_bytes = sizeof(member_struct);\n            size_t num_bytes;\n            void* v_ptr = thread_alloc::get_memory(min_bytes, num_bytes);\n            // convert to member_struct*\n            member_[thread] = reinterpret_cast<member_struct*>(v_ptr);\n            // call member_struct constructor\n            new( member_[thread] ) member_struct;\n            //\n            // The thread has a copy of corresponding information.\n            member_[thread]->g_  = g_;\n            member_[thread]->ag_ = ag_;\n        }\n        return;\n    }\n    //\n    // ------------------------------------------------------------------------\n    /// free member_ for this thread\n    void free_member(size_t thread)\n    {   if( member_[thread] != nullptr )\n        {   // call destructor\n            member_[thread]->~member_struct();\n            // return raw m,emory to available pool for this thread\n            void* v_ptr = reinterpret_cast<void*>(member_[thread]);\n            thread_alloc::return_memory(v_ptr);\n            // mark member for this thread as not allocated\n            member_[thread] = nullptr;\n        }\n        return;\n    }\n    // -----------------------------------------------------------------------\n    // atomic_three virtual functions\n    // ------------------------------------------------------------------------\n    // type\n    virtual bool for_type(\n        const vector<Base>&          parameter_x ,\n        const vector<ad_type_enum>&  type_x      ,\n        vector<ad_type_enum>&        type_y\n    );\n    // forward\n    virtual bool forward(\n        const vector<Base>&          parameter_x ,\n        const vector<ad_type_enum>&  type_x      ,\n        size_t                       need_y      ,\n        size_t                       order_low   ,\n        size_t                       order_up    ,\n        const vector<Base>&          taylor_x    ,\n        vector<Base>&                taylor_y\n    );\n    // AD forward\n    virtual bool forward(\n        const vector< AD<Base> >&    aparameter_x ,\n        const vector<ad_type_enum>&  type_x       ,\n        size_t                       need_y       ,\n        size_t                       order_low    ,\n        size_t                       order_up     ,\n        const vector< AD<Base> >&    ataylor_x    ,\n        vector< AD<Base> >&          ataylor_y\n    );\n    // reverse\n    virtual bool reverse(\n        const vector<Base>&          parameter_x ,\n        const vector<ad_type_enum>&  type_x      ,\n        size_t                       order_up    ,\n        const vector<Base>&          taylor_x    ,\n        const vector<Base>&          taylor_y    ,\n        vector<Base>&                partial_x   ,\n        const vector<Base>&          partial_y\n    );\n    // AD reverse\n    virtual bool reverse(\n        const vector< AD<Base> >&    aparameter_x ,\n        const vector<ad_type_enum>&  type_x       ,\n        size_t                       order_up     ,\n        const vector< AD<Base> >&    ataylor_x    ,\n        const vector< AD<Base> >&    ataylor_y    ,\n        vector< AD<Base> >&          apartial_x   ,\n        const vector< AD<Base> >&    apartial_y\n    );\n    // jac_sparsity\n    virtual bool jac_sparsity(\n        const vector<Base>&            parameter_x  ,\n        const vector<ad_type_enum>&    type_x       ,\n        bool                           dependency   ,\n        const vector<bool>&            select_x     ,\n        const vector<bool>&            select_y     ,\n        sparse_rc< vector<size_t> >&   pattern_out\n    );\n    // hes_sparsity\n    virtual bool hes_sparsity(\n        const vector<Base>&            parameter_x  ,\n        const vector<ad_type_enum>&    type_x       ,\n        const vector<bool>&            select_x     ,\n        const vector<bool>&            select_y     ,\n        sparse_rc< vector<size_t> >&   pattern_out\n    );\n    // rev_depend\n    virtual bool rev_depend(\n        const vector<Base>&            parameter_x ,\n        const vector<ad_type_enum>&    type_x      ,\n        vector<bool>&                  depend_x    ,\n        const vector<bool>&            depend_y\n    );\npublic:\n    // ctor\n    chkpoint_two(\n        const ADFun<Base>& fun    ,\n        const std::string& name   ,\n        bool  internal_bool       ,\n        bool  use_hes_sparsity    ,\n        bool  use_base2ad         ,\n        bool  use_in_parallel\n    );\n    //\n    // destructor\n    ~chkpoint_two(void);\n    //\n    // assignment operator\n    void operator=(const chkpoint_two& other)\n    {   CPPAD_ASSERT_KNOWN(false,\n            \"cannot use chkpoint_two assignment operator\"\n        );\n    }\n    // copy constructor\n    chkpoint_two(const chkpoint_two& other)\n    :\n    internal_bool_    ( other.internal_bool_ ) ,\n    use_hes_sparsity_ ( other.use_hes_sparsity_ ) ,\n    use_base2ad_      ( other.use_base2ad_ ) ,\n    use_in_parallel_  ( other.use_in_parallel_ ) ,\n    jac_sparsity_     ( other.jac_sparsity_ ) ,\n    hes_sparsity_     ( other.hes_sparsity_ )\n    {   g_  = other.g_;\n        ag_ = other.ag_;\n    }\n    //\n    // new_dynamic\n    template <class BaseVector>\n    void new_dynamic(const BaseVector& dynamic);\n};\n\n} // END_CPPAD_NAMESPACE\n\n# include <cppad/core/chkpoint_two/ctor.hpp>\n# include <cppad/core/chkpoint_two/dynamic.hpp>\n# include <cppad/core/chkpoint_two/for_type.hpp>\n# include <cppad/core/chkpoint_two/forward.hpp>\n# include <cppad/core/chkpoint_two/reverse.hpp>\n# include <cppad/core/chkpoint_two/jac_sparsity.hpp>\n# include <cppad/core/chkpoint_two/hes_sparsity.hpp>\n# include <cppad/core/chkpoint_two/rev_depend.hpp>\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/chkpoint_two/ctor.hpp",
    "content": "# ifndef CPPAD_CORE_CHKPOINT_TWO_CTOR_HPP\n# define CPPAD_CORE_CHKPOINT_TWO_CTOR_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin chkpoint_two_ctor}\n{xrst_spell\n    chk\n}\n\nCheckpoint Function Constructor\n###############################\n\nSyntax\n******\n| ``chkpoint_two`` < *Base* > *chk_fun* ( *fun* , *name* ,\n| |tab| *internal_bool* , *use_hes_sparsity* , *use_base2ad* , *use_in_parallel*\n| )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_PROTOTYPE\n    // END_PROTOTYPE\n}\n\nParallel\n********\nThis constructor, and its corresponding destructor, must not be called in\n:ref:`parallel<ta_in_parallel-name>` mode.\nThe object *chk_fun* should not be destructed for as long as there is\nan ``ADFun`` < *Base* > object the has *chk_fun* in its recording.\n\nBase\n****\nThe type *Base* specifies the base type for AD operations.\n\nfun\n***\nThis specifies the function :math:`g(x)`.\nNote that *fun* may or may not have been\n:ref:`optimized<optimize-name>` before calling the constructor.\nThis will determine if the internal representation for *g* ( *x* )\nis optimized.\n\nname\n****\nis the name used for reporting errors using this checkpoint function.\n\ninternal_bool\n*************\nIf true, sparsity calculations are done with sets represented\nby vectors of boolean values.\nOtherwise, vectors of sets are used for sparsity patterns.\n\nuse_hes_sparsity\n****************\nIf true, Hessian sparsity patterns can be calculated for\n``ADFun`` < *Base* > objects that have uses of *chk_fun*\nin their recording.\nThis requires some extra memory and extra computation during the constructor.\n\nuse_base2ad\n***********\nIf this is true, *chk_fun* can be used during the recording\nof ``ADFun`` < *Base* > objects that get converted to\n``ADFun< AD<`` *Base* > > objects using :ref:`base2ad-name` .\nThis requires some extra memory and extra computation during the constructor.\n\nuse_in_parallel\n***************\nIf this is true, *chk_fun* can be used\n:ref:`ta_parallel_setup@in_parallel` .\nThis requires some extra memory for a constant copy of the *fun*\ninformation and a separate copy (that changes) for each thread.\n\nchk_fun\n*******\nThis is a checkpoint function representation of :math:`g(x)`\nthat can be used during the recording of ``AD`` < *Base* > operations.\n\n{xrst_end chkpoint_two_ctor}\n*/\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\n\\file chkpoint_two/ctor.hpp\nConstructor for chkpoint_two class.\n*/\n\n/*!\nConstructor\n\n\\tparam Base\nbase class for recording AD<Base> operations using this checkpoint object.\n\n\\param fun\nis the function g(x) corresponding to this checkpoint object.\n\n\\param name\nis the name used for error reporting.\n\n\\param internal_bool\nshould sparisity calculations be done using bools (or sets).\n\n\\param use_hes_sparsity\nwill this checkpoint function be used with Hessian sparsity calculations.\n\n\\param use_base2ad\nwill this checkpoint function be used with base2ad.\n\n\\param use_in_parallel\nwill this checkpoint function be used in parallel mode.\n*/\n\n// BEGIN_PROTOTYPE\ntemplate <class Base>\nchkpoint_two<Base>::chkpoint_two(\n        const ADFun<Base>& fun    ,\n        const std::string& name   ,\n        bool  internal_bool       ,\n        bool  use_hes_sparsity    ,\n        bool  use_base2ad         ,\n        bool  use_in_parallel     )\n// END_PROTOTYPE\n:\natomic_three<Base>(name)              ,\ninternal_bool_( internal_bool )       ,\nuse_hes_sparsity_( use_hes_sparsity ) ,\nuse_base2ad_ ( use_base2ad )          ,\nuse_in_parallel_ ( use_in_parallel )\n{   CPPAD_ASSERT_KNOWN(\n        ! thread_alloc::in_parallel() ,\n        \"chkpoint_two: constructor cannot be called in parallel mode.\"\n    );\n    // initialize member pointers as null;\n    for(size_t thread = 0; thread < CPPAD_MAX_NUM_THREADS; thread++)\n        member_[thread] = nullptr;\n    //\n    // g_\n    g_ = fun;\n    //\n    // suppress check for nan because chkpoint_two object can be used in a\n    // function that gets optimized and some checkpoint results may not matter.\n    g_.check_for_nan(false);\n    //\n    // ag_\n    if( use_base2ad )\n        ag_ = g_.base2ad();\n    //\n    // jac_sparsity__\n    size_t n = g_.Domain();\n    size_t m = g_.Range();\n    sparse_rc< vector<size_t> > pattern_in;\n    bool transpose     = false;\n    bool dependency    = true;\n    if( n <= m || use_hes_sparsity )\n    {   // use forward mode\n        pattern_in.resize(n, n, n);\n        for(size_t k = 0; k < n; ++k)\n            pattern_in.set(k, k, k);\n        g_.for_jac_sparsity(\n            pattern_in,\n            transpose,\n            dependency,\n            internal_bool,\n            jac_sparsity_\n        );\n    }\n    else\n    {   // use reverse mode\n        pattern_in.resize(m, m, m);\n        for(size_t k = 0; k < m; ++k)\n            pattern_in.set(k, k, k);\n        g_.rev_jac_sparsity(\n            pattern_in,\n            transpose,\n            dependency,\n            internal_bool,\n            jac_sparsity_\n        );\n    }\n    //\n    // hes_sparsity_\n    if( use_hes_sparsity )\n    {   vector<bool> select_y(m), select_x(n);\n        for(size_t i = 0; i < m; ++i)\n            select_y[i] = true;\n        if( n <= m )\n        {   for(size_t j = 0; j < n; ++j)\n                select_x[j] = true;\n            g_.for_hes_sparsity(\n                select_x, select_y, internal_bool, hes_sparsity_\n            );\n        }\n        else\n        {   // forward jacobian sparsity is stored in g_\n            g_.rev_hes_sparsity(\n                select_y, transpose, internal_bool, hes_sparsity_\n            );\n        }\n    }\n    // free memory holding forward Jacobian sparsity\n    if( internal_bool )\n        g_.size_forward_bool(0);\n    else\n        g_.size_forward_set(0);\n}\n/// destructor\ntemplate <class Base>\nchkpoint_two<Base>::~chkpoint_two(void)\n{\n# ifndef NDEBUG\n    if( thread_alloc::in_parallel() )\n    {   std::string msg = atomic_three<Base>::atomic_name();\n        msg += \": chkpoint_two destructor called in parallel mode.\";\n        CPPAD_ASSERT_KNOWN(false, msg.c_str() );\n    }\n# endif\n    for(size_t thread = 0; thread < CPPAD_MAX_NUM_THREADS; ++thread)\n        free_member(thread);\n    }\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/chkpoint_two/dynamic.hpp",
    "content": "# ifndef CPPAD_CORE_CHKPOINT_TWO_DYNAMIC_HPP\n# define CPPAD_CORE_CHKPOINT_TWO_DYNAMIC_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin chkpoint_two_dynamic}\n{xrst_spell\n    chk\n    dyn\n}\n\nDynamic Parameters in Checkpoint Functions\n##########################################\n\nSyntax\n******\n| *chk_fun* . ``new_dynamic`` ( *dynamic* )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_PROTOTYPE\n    // END_PROTOTYPE\n}\n\nchk_fun\n*******\nThis object must have been created using the\n:ref:`chkpoint_two<chkpoint_two_ctor@chk_fun>` constructor.\n\nBase\n====\nThis is the :ref:`chkpoint_two_ctor@Base` type\nin the *chk_fun* constructor.\n\nfun\n===\nThis is the function :ref:`chkpoint_two_ctor@fun`\nin the *chk_fun* constructor.\n\nBaseVector\n**********\nThis must be a :ref:`SimpleVector-name` with elements of type *Base* .\n\ndynamic\n*******\nThis is a vector with new values for the dynamic parameters\nin the function *fun* .\nIs size must be equal to\n:ref:`fun.size_dyn_ind()<fun_property@size_dyn_par>` .\nThis only affects the copy of *fun* used by *chk_fun* .\n\nMulti-Threading\n***************\nIf one is using :ref:`in_parallel<ta_in_parallel-name>` ,\nthere is a separate copy of *fun* for each thread.\nIn this case, only the dynamic parameters in the copy for the current\n:ref:`thread number<ta_thread_num-name>` are changed.\n\n{xrst_end chkpoint_two_dynamic}\n*/\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\n\\file chkpoint_two/dynamic.hpp\nChange the dynnamic parameter in a checkpoint function.\n*/\n\n/*!\nConstructor\n\n\\tparam Base\nbase class for recording AD<Base> operations using this checkpoint object.\n\n\\param dynamic\nis the new values for the dynamic parameters in the function\ndefining this checkpoint object.\n*/\n\n// BEGIN_PROTOTYPE\ntemplate <class Base>\ntemplate <class BaseVector>\nvoid chkpoint_two<Base>::new_dynamic(const BaseVector& dynamic)\n// END_PROTOTYPE\n{   ADFun<Base>* g_ptr = &g_;\n    if( use_in_parallel_ )\n    {   size_t thread = thread_alloc::thread_num();\n        allocate_member(thread);\n        g_ptr = &(member_[thread]->g_);\n    }\n# ifndef NDEBUG\n    else if( thread_alloc::in_parallel() )\n    {   std::string msg = atomic_three<Base>::atomic_name();\n        msg += \": use_in_parallel is false and in_parallel() is true\";\n        CPPAD_ASSERT_KNOWN(false, msg.c_str() );\n    }\n# endif\n    g_ptr->new_dynamic(dynamic);\n}\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/chkpoint_two/for_type.hpp",
    "content": "# ifndef CPPAD_CORE_CHKPOINT_TWO_FOR_TYPE_HPP\n# define CPPAD_CORE_CHKPOINT_TWO_FOR_TYPE_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\n\\file chkpoint_two/for_type.hpp\nSecond generation checkpoint type computation.\n*/\n/*!\nLink from atomic_three to type calculation\n\n\\param parameter_x [in]\nis the value of the parameters in the corresponding function call\nafun(ax, ay).\n\n\\param type_x [in]\nspecifies which components of x are\nconstants, dynamics, and variables\n\n\\param type_y [out]\nspecifies which components of y are\nconstants, dynamics, and variables\n*/\ntemplate <class Base>\nbool chkpoint_two<Base>::for_type(\n    const vector<Base>&          parameter_x ,\n    const vector<ad_type_enum>&  type_x      ,\n    vector<ad_type_enum>&        type_y      )\n{   size_t nr  = jac_sparsity_.nr();\n    size_t nnz = jac_sparsity_.nnz();\n    const vector<size_t>& row( jac_sparsity_.row() );\n    const vector<size_t>& col( jac_sparsity_.col() );\n    //\n    CPPAD_ASSERT_UNKNOWN( jac_sparsity_.nr() == type_y.size() );\n    CPPAD_ASSERT_UNKNOWN( jac_sparsity_.nc() == type_x.size() );\n    //\n    // initialize type_y as constant_enum\n    for(size_t i = 0; i < nr; ++i)\n        type_y[i] = constant_enum;\n    //\n    // loop over entries in Dependency pattern\n    for(size_t k = 0; k < nnz; ++k)\n    {   size_t i  = row[k];\n        size_t j  = col[k];\n        type_y[i] = std::max(type_y[i], type_x[j]);\n    }\n    return true;\n}\n\n} // END_CPPAD_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/chkpoint_two/forward.hpp",
    "content": "# ifndef CPPAD_CORE_CHKPOINT_TWO_FORWARD_HPP\n# define CPPAD_CORE_CHKPOINT_TWO_FORWARD_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\n\\file chkpoint_two/forward.hpp\nSecond generation checkpoint forward mode.\n*/\n/*!\nLink from chkpoint_two to forward mode\n\n\\param parameter_x [in]\ncontains the values, in afun(ax, ay), for arguments that are parameters.\n\n\\param type_x [in]\nwhat is the type, in afun(ax, ay), for each component of x.\n\n\\param need_y [in]\nspecifies which components of taylor_y are needed,\n\n\\param order_low [in]\nlowerest order for this forward mode calculation.\n\n\\param order_up [in]\nhighest order for this forward mode calculation.\n\n\\param taylor_x [in]\nTaylor coefficients corresponding to x for this calculation.\n\n\\param taylor_y [out]\nTaylor coefficient corresponding to y for this calculation\n\nSee the forward mode in user's documentation for atomic_three\n*/\ntemplate <class Base>\nbool chkpoint_two<Base>::forward(\n    const vector<Base>&          parameter_x ,\n    const vector<ad_type_enum>&  type_x      ,\n    size_t                       need_y      ,\n    size_t                       order_low   ,\n    size_t                       order_up    ,\n    const vector<Base>&          taylor_x    ,\n    vector<Base>&                taylor_y    )\n{   ADFun<Base>* g_ptr = &g_;\n    if( use_in_parallel_ )\n    {   size_t thread = thread_alloc::thread_num();\n        allocate_member(thread);\n        g_ptr = &(member_[thread]->g_);\n    }\n# ifndef NDEBUG\n    else if( thread_alloc::in_parallel() )\n    {   std::string msg = atomic_three<Base>::atomic_name();\n        msg += \": use_in_parallel is false and in_parallel() is true\";\n        CPPAD_ASSERT_KNOWN(false, msg.c_str() );\n    }\n# endif\n    // compute forward mode results for all values and orders\n    taylor_y = g_ptr->Forward(order_up, taylor_x);\n    //\n    return true;\n}\n/*!\nLink from chkpoint_two to AD forward mode\n\n\\param aparameter_x [in]\ncontains the values, in afun(ax, ay), for arguments that are parameters.\n\n\\param type_x [in]\nwhat is the type, in afun(ax, ay), for each component of x.\n\n\\param need_y [in]\nspecifies which components of taylor_y are needed,\n\n\\param order_low [in]\nlowerest order for this forward mode calculation.\n\n\\param order_up [in]\nhighest order for this forward mode calculation.\n\n\\param ataylor_x [in]\nTaylor coefficients corresponding to x for this calculation.\n\n\\param ataylor_y [out]\nTaylor coefficient corresponding to y for this calculation\n\nSee the forward mode in user's documentation for atomic_three\n*/\ntemplate <class Base>\nbool chkpoint_two<Base>::forward(\n    const vector< AD<Base> >&    aparameter_x ,\n    const vector<ad_type_enum>&  type_x       ,\n    size_t                       need_y       ,\n    size_t                       order_low    ,\n    size_t                       order_up     ,\n    const vector< AD<Base> >&    ataylor_x    ,\n    vector< AD<Base> >&          ataylor_y    )\n{   if( ! use_base2ad_ )\n        return false;\n    //\n    ADFun< AD<Base>, Base >* ag_ptr = &ag_;\n    if( use_in_parallel_ )\n    {   size_t thread = thread_alloc::thread_num();\n        allocate_member(thread);\n        ag_ptr = &(member_[thread]->ag_);\n    }\n# ifndef NDEBUG\n    else if( thread_alloc::in_parallel() )\n    {   std::string msg = atomic_three<Base>::atomic_name();\n        msg += \": use_in_parallel is false and in_parallel() is true\";\n        CPPAD_ASSERT_KNOWN(false, msg.c_str() );\n    }\n# endif\n    // compute forward mode results for all values and orders\n    ataylor_y = ag_ptr->Forward(order_up, ataylor_x);\n    //\n    return true;\n}\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/chkpoint_two/hes_sparsity.hpp",
    "content": "# ifndef CPPAD_CORE_CHKPOINT_TWO_HES_SPARSITY_HPP\n# define CPPAD_CORE_CHKPOINT_TWO_HES_SPARSITY_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\n\\file chkpoint_two/hes_sparsity.hpp\nSecond generation checkpoint Jacobian sparsity patterns.\n*/\n/*!\nchkpoint_two to Hessian sparsity calculations.\n\n\\param parameter_x [in]\ncontains the values for arguments that are parameters.\n\n\\param type_x [in]\nwhat is the type, in afun(ax, ay), for each component of x.\n\n\\param select_x [in]\nwhich domain components to include in the dependency or sparsity pattern.\nThe index zero is used for parameters.\n\n\\param select_y [in]\nwhich range components to include in the dependency or sparsity pattern.\nThe index zero is used for parameters.\nThis argument is ignored because the sparsity pattern corresponding to\nall components true is computed during the construction and used for all cases.\nThis errors on the side of caution for the sake of speed.\n\n\n\\param pattern_out [out]\nis the dependency or sparsity pattern.\n*/\n// BEGIN_PROTOTYPE\ntemplate <class Base>\nbool chkpoint_two<Base>::hes_sparsity(\n    const vector<Base>&                     parameter_x  ,\n    const vector<ad_type_enum>&             type_x       ,\n    const vector<bool>&                     select_x     ,\n    const vector<bool>&                     select_y     ,\n    sparse_rc< vector<size_t> >&            pattern_out  )\n// END_PROTOTYPE\n{   CPPAD_ASSERT_UNKNOWN( hes_sparsity_.nr() == select_x.size() );\n    CPPAD_ASSERT_UNKNOWN( hes_sparsity_.nc() == select_x.size() );\n    if( ! use_hes_sparsity_ )\n        return false;\n\n    // count number of non-zeros\n    size_t nnz = hes_sparsity_.nnz();\n    size_t nr  = hes_sparsity_.nr();\n    size_t nc  = hes_sparsity_.nc();\n    const vector<size_t>& row = hes_sparsity_.row();\n    const vector<size_t>& col = hes_sparsity_.col();\n    size_t nnz_out = 0;\n    for(size_t k = 0; k < nnz; ++k)\n    {   size_t i = row[k];\n        size_t j = col[k];\n        if( select_x[j] && select_x[i] )\n            ++nnz_out;\n    }\n\n    // set the output sparsity pattern\n    pattern_out.resize(nr, nc, nnz_out);\n    size_t ell = 0;\n    for(size_t k = 0; k < nnz; ++k)\n    {   size_t i = row[k];\n        size_t j = col[k];\n        if( select_x[j] && select_x[i] )\n            pattern_out.set(ell++, i, j);\n    }\n    CPPAD_ASSERT_UNKNOWN( ell == nnz_out );\n    //\n    return true;\n}\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/chkpoint_two/jac_sparsity.hpp",
    "content": "# ifndef CPPAD_CORE_CHKPOINT_TWO_JAC_SPARSITY_HPP\n# define CPPAD_CORE_CHKPOINT_TWO_JAC_SPARSITY_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\n\\file chkpoint_two/jac_sparsity.hpp\nSecond generation checkpoint Jacobian sparsity patterns.\n*/\n/*!\nchkpoint_two to Jacobian sparsity calculations.\n\n\\param dependency [in]\nThis argument is ignored.\nThe return pattern is always a dependency pattern which is a correct,\nbut possibly not efficient, sparsity pattern.\n\n\\param parameter_x [in]\ncontains the values for arguments that are parameters.\n\n\\param type_x [in]\nwhat is the type, in afun(ax, ay), for each component of x.\n\n\\param select_x [in]\nwhich domain components to include in the dependency or sparsity pattern.\nThe index zero is used for parameters.\n\n\\param select_y [in]\nwhich range components to include in the dependency or sparsity pattern.\nThe index zero is used for parameters.\n\n\\param pattern_out [out]\nis the dependency or sparsity pattern.\n*/\n// BEGIN_PROTOTYPE\ntemplate <class Base>\nbool chkpoint_two<Base>::jac_sparsity(\n    const vector<Base>&                     parameter_x  ,\n    const vector<ad_type_enum>&             type_x       ,\n    bool                                    dependency   ,\n    const vector<bool>&                     select_x     ,\n    const vector<bool>&                     select_y     ,\n    sparse_rc< vector<size_t> >&            pattern_out  )\n// END_PROTOTYPE\n{   CPPAD_ASSERT_UNKNOWN( jac_sparsity_.nr() == select_y.size() );\n    CPPAD_ASSERT_UNKNOWN( jac_sparsity_.nc() == select_x.size() );\n\n    // count number of non-zeros\n    size_t nnz = jac_sparsity_.nnz();\n    size_t nr  = jac_sparsity_.nr();\n    size_t nc  = jac_sparsity_.nc();\n    const vector<size_t>& row = jac_sparsity_.row();\n    const vector<size_t>& col = jac_sparsity_.col();\n    size_t nnz_out = 0;\n    for(size_t k = 0; k < nnz; ++k)\n    {   size_t i = row[k];\n        size_t j = col[k];\n        if( select_x[j] && select_y[i] )\n            ++nnz_out;\n    }\n\n    // set the output sparsity pattern\n    pattern_out.resize(nr, nc, nnz_out);\n    size_t ell = 0;\n    for(size_t k = 0; k < nnz; ++k)\n    {   size_t i = row[k];\n        size_t j = col[k];\n        if( select_x[j] && select_y[i] )\n            pattern_out.set(ell++, i, j);\n    }\n    CPPAD_ASSERT_UNKNOWN( ell == nnz_out );\n    //\n    return true;\n}\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/chkpoint_two/rev_depend.hpp",
    "content": "# ifndef CPPAD_CORE_CHKPOINT_TWO_REV_DEPEND_HPP\n# define CPPAD_CORE_CHKPOINT_TWO_REV_DEPEND_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\n\\file chkpoint_two/rev_depend.hpp\nSecond generation checkpoint type computation.\n*/\n/*!\nLink from atomic_three to dependency calculation\n\n\\param parameter_x [in]\nis the value of the parameters in the corresponding function call\nafun(ax, ay).\n\n\\param type_x [in]\nis the AD type for ax in the corresponding afun(ax, ay) call.\n\n\\param depend_x [out]\nspecifies which components of x affect the values of interest\n\n\\param depend_y [in]\nspecifies which components of y affect the values of interest\n*/\ntemplate <class Base>\nbool chkpoint_two<Base>::rev_depend(\n    const vector<Base>&         parameter_x ,\n    const vector<ad_type_enum>& type_x      ,\n    vector<bool>&               depend_x    ,\n    const vector<bool>&         depend_y    )\n{   size_t nc  = jac_sparsity_.nc();\n    size_t nnz = jac_sparsity_.nnz();\n    const vector<size_t>& row( jac_sparsity_.row() );\n    const vector<size_t>& col( jac_sparsity_.col() );\n    //\n    CPPAD_ASSERT_UNKNOWN( jac_sparsity_.nr() == depend_y.size() );\n    CPPAD_ASSERT_UNKNOWN( jac_sparsity_.nc() == depend_x.size() );\n    //\n    // initialize depend_x as false\n    for(size_t j = 0; j < nc; ++j)\n        depend_x[j] = false;\n    //\n    // loop over entries in Dependency pattern\n    for(size_t k = 0; k < nnz; ++k)\n    {   size_t i  = row[k];\n        size_t j  = col[k];\n        if( depend_y[i] )\n            depend_x[j] = true;\n    }\n    return true;\n}\n\n} // END_CPPAD_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/chkpoint_two/reverse.hpp",
    "content": "# ifndef CPPAD_CORE_CHKPOINT_TWO_REVERSE_HPP\n# define CPPAD_CORE_CHKPOINT_TWO_REVERSE_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\n\\file chkpoint_two/reverse.hpp\nSecond generation checkpoint reverse mode.\n*/\n/*!\nLink from chkpoint_two to reverse mode\n\n\\param parameter_x [in]\ncontains the values, in afun(ax, ay), for arguments that are parameters.\n\n\\param type_x [in]\nwhat is the type, in afun(ax, ay), for each component of x.\n\n\\param order_up [in]\nhighest order Taylor coefficient aht we are computing derivative of\n\n\\param taylor_x [in]\nTaylor coefficients corresponding to x for this calculation.\n\n\\param taylor_y [in]\nTaylor coefficient corresponding to y for this calculation\n\n\\param partial_x [out]\nPartials w.r.t. the x Taylor coefficients.\n\n\\param partial_y [in]\nPartials w.r.t. the y Taylor coefficients.\n\nSee the reverse mode in user's documentation for atomic_three\n*/\ntemplate <class Base>\nbool chkpoint_two<Base>::reverse(\n    const vector<Base>&         parameter_x   ,\n    const vector<ad_type_enum>& type_x        ,\n    size_t                      order_up      ,\n    const vector<Base>&         taylor_x      ,\n    const vector<Base>&         taylor_y      ,\n    vector<Base>&               partial_x     ,\n    const vector<Base>&         partial_y     )\n\n{   ADFun<Base>* g_ptr = &g_;\n    if( use_in_parallel_ )\n    {   size_t thread = thread_alloc::thread_num();\n        allocate_member(thread);\n        g_ptr = &(member_[thread]->g_);\n    }\n# ifndef NDEBUG\n    else if( thread_alloc::in_parallel() )\n    {   std::string msg = atomic_three<Base>::atomic_name();\n        msg += \": use_in_parallel is false and in_parallel() is true\";\n        CPPAD_ASSERT_KNOWN(false, msg.c_str() );\n    }\n# endif\n    // compute forward mode Taylor coefficient orders 0 through order_up\n# ifdef NDEBUG\n    g_ptr->Forward(order_up, taylor_x);\n# else\n    vector<Base> check = g_ptr->Forward(order_up, taylor_x);\n    CPPAD_ASSERT_UNKNOWN( taylor_y.size() == check.size() )\n    for(size_t i = 0; i < taylor_y.size(); ++i)\n        CPPAD_ASSERT_UNKNOWN( taylor_y[i] == check[i] );\n# endif\n    // now can run reverse mode\n    partial_x = g_ptr->Reverse(order_up+1, partial_y);\n    //\n    return true;\n}\n/*!\nLink from chkpoint_two to AD reverse mode\n\n\\param aparameter_x [in]\ncontains the values, in afun(ax, ay), for arguments that are parameters.\n\n\\param type_x [in]\nwhat is the type, in afun(ax, ay), for each component of x.\n\n\\param order_up [in]\nhighest order Taylor coefficient aht we are computing derivative of\n\n\\param ataylor_x [in]\nTaylor coefficients corresponding to x for this calculation.\n\n\\param ataylor_y [in]\nTaylor coefficient corresponding to y for this calculation\n\n\\param apartial_x [out]\nPartials w.r.t. the x Taylor coefficients.\n\n\\param apartial_y [in]\nPartials w.r.t. the y Taylor coefficients.\n\nSee the reverse mode in user's documentation for atomic_three\n*/\ntemplate <class Base>\nbool chkpoint_two<Base>::reverse(\n    const vector< AD<Base> >&   aparameter_x ,\n    const vector<ad_type_enum>& type_x       ,\n    size_t                      order_up     ,\n    const vector< AD<Base> >&   ataylor_x    ,\n    const vector< AD<Base> >&   ataylor_y    ,\n    vector< AD<Base> >&         apartial_x   ,\n    const vector< AD<Base> >&   apartial_y   )\n{   ADFun< AD<Base>, Base >* ag_ptr = &ag_;\n    if( use_in_parallel_ )\n    {   size_t thread = thread_alloc::thread_num();\n        allocate_member(thread);\n        ag_ptr = &(member_[thread]->ag_);\n    }\n    // compute forward mode Taylor coefficient orders 0 through order_up\n# ifdef NDEBUG\n    ag_ptr->Forward(order_up, ataylor_x);\n# else\n    vector< AD<Base> > acheck = ag_ptr->Forward(order_up, ataylor_x);\n    CPPAD_ASSERT_UNKNOWN( ataylor_y.size() == acheck.size() )\n    for(size_t i = 0; i < ataylor_y.size(); ++i)\n        CPPAD_ASSERT_UNKNOWN( ataylor_y[i] == acheck[i] );\n# endif\n    // now can run reverse mode\n    apartial_x = ag_ptr->Reverse(order_up+1, apartial_y);\n    //\n    return true;\n}\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/compare.hpp",
    "content": "# ifndef CPPAD_CORE_COMPARE_HPP\n# define CPPAD_CORE_COMPARE_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n-------------------------------------------------------------------------------\n{xrst_begin Compare}\n\nAD Binary Comparison Operators\n##############################\n\nSyntax\n******\n| *b* = *x* *Op* *y*\n\nPurpose\n*******\nCompares two operands where one of the operands is an\n``AD`` < *Base* > object.\nThe comparison has the same interpretation as for\nthe *Base* type.\n\nOp\n**\nThe operator *Op* is one of the following:\n\n.. csv-table::\n    :widths: auto\n\n    **Op**,**Meaning**\n    ``<``,is *x* less than *y*\n    ``<=``,is *x* less than or equal *y*\n    ``>``,is *x* greater than *y*\n    ``>=``,is *x* greater than or equal *y*\n    ``==``,is *x* equal to *y*\n    ``!=``,is *x* not equal to *y*\n\nx\n*\nThe operand *x* has prototype\n\n    ``const`` *Type* & *x*\n\nwhere *Type* is ``AD`` < *Base* > , *Base* , or ``int`` .\n\ny\n*\nThe operand *y* has prototype\n\n    ``const`` *Type* & *y*\n\nwhere *Type* is ``AD`` < *Base* > , *Base* , or ``int`` .\n\nb\n*\nThe result *b* has type\n\n    ``bool`` *b*\n\nOperation Sequence\n******************\nThe result of this operation is a ``bool`` value\n(not an :ref:`glossary@AD of Base` object).\nThus it will not be recorded as part of an\nAD of *Base*\n:ref:`operation sequence<glossary@Operation@Sequence>` .\n\nFor example, suppose\n*x* and *y* are ``AD`` < *Base* > objects,\nthe tape corresponding to ``AD`` < *Base* > is recording,\n*b* is true,\nand the subsequent code is\n\n| |tab| ``if`` ( *b*  )\n| |tab| |tab| *y* = ``cos`` ( *x* );\n| |tab| ``else``\n| |tab| |tab| *y* = ``sin`` ( *x* );\n\nonly the assignment *y* = ``cos`` ( *x* ) is recorded on the tape\n(if *x* is a :ref:`glossary@Parameter` ,\nnothing is recorded).\nThe :ref:`CompareChange-name` function can yield\nsome information about changes in comparison operation results.\nYou can use :ref:`CondExp-name` to obtain comparison operations\nthat depends on the\n:ref:`glossary@Tape@Independent Variable`\nvalues with out re-taping the AD sequence of operations.\n\nAssumptions\n***********\nIf one of the *Op* operators listed above\nis used with an ``AD`` < *Base* > object,\nit is assumed that the same operator is supported by the base type\n*Base* .\n\nExample\n*******\n{xrst_toc_hidden\n    example/general/compare.cpp\n}\nThe file\n:ref:`compare.cpp-name`\ncontains an example and test of these operations.\n\n{xrst_end Compare}\n-------------------------------------------------------------------------------\n*/\n//  BEGIN CppAD namespace\nnamespace CppAD {\n// -------------------------------- < --------------------------\ntemplate <class Base>\nCPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION\nbool operator < (const AD<Base> &left , const AD<Base> &right)\n{   bool result    =  (left.value_ < right.value_);\n    //\n    // check if we are recording compare operators\n    local::ADTape<Base> *tape = AD<Base>::tape_ptr();\n    if( tape == nullptr )\n        return result;\n    if( ! tape->Rec_.get_record_compare() )\n        return result;\n    tape_id_t tape_id = tape->id_;\n    // tape_id cannot match the default value for tape_id_; i.e., 0\n    CPPAD_ASSERT_UNKNOWN( tape_id > 0 );\n\n    // check if left and right tapes match\n    bool match_left  = left.tape_id_  == tape_id;\n    bool match_right = right.tape_id_ == tape_id;\n\n    // check if left and right are dynamic parameters\n    bool dyn_left  = match_left  & (left.ad_type_ == dynamic_enum);\n    bool dyn_right = match_right & (right.ad_type_ == dynamic_enum);\n\n    // check if left and right are variables\n    bool var_left  = match_left  & (left.ad_type_ != dynamic_enum);\n    bool var_right = match_right & (right.ad_type_ != dynamic_enum);\n\n    CPPAD_ASSERT_KNOWN(\n        left.tape_id_ == right.tape_id_ || ! match_left || ! match_right ,\n        \"< : AD variables or dynamic parameters on different threads.\"\n    );\n    if( var_left )\n    {   if( var_right )\n        {   // variable < variable\n            if( result )\n            {   tape->Rec_.PutOp(local::LtvvOp);\n                tape->Rec_.PutArg(left.taddr_, right.taddr_);\n            }\n            else\n            {   tape->Rec_.PutOp(local::LevvOp);\n                tape->Rec_.PutArg(right.taddr_, left.taddr_);\n            }\n        }\n        else\n        {   // variable < parameter\n            addr_t p = right.taddr_;\n            if( ! dyn_right )\n                p = tape->Rec_.put_con_par(right.value_);\n            if( result )\n            {   tape->Rec_.PutOp(local::LtvpOp);\n                tape->Rec_.PutArg(left.taddr_, p);\n            }\n            else\n            {   tape->Rec_.PutOp(local::LepvOp);\n                tape->Rec_.PutArg(p, left.taddr_);\n            }\n        }\n    }\n    else if ( var_right )\n    {   // parameter < variable\n        addr_t p = left.taddr_;\n        if( ! dyn_left )\n            p = tape->Rec_.put_con_par(left.value_);\n        if( result )\n        {   tape->Rec_.PutOp(local::LtpvOp);\n            tape->Rec_.PutArg(p, right.taddr_);\n        }\n        else\n        {   tape->Rec_.PutOp(local::LevpOp);\n            tape->Rec_.PutArg(right.taddr_, p);\n        }\n    }\n    else if( dyn_left | dyn_right )\n    {   // parameter < parameter\n        addr_t arg0 = left.taddr_;\n        addr_t arg1 = right.taddr_;\n        if( ! dyn_left )\n            arg0 = tape->Rec_.put_con_par(left.value_);\n        if( ! dyn_right )\n            arg1 = tape->Rec_.put_con_par(right.value_);\n        //\n        if( result )\n        {   tape->Rec_.PutOp(local::LtppOp);\n            tape->Rec_.PutArg(arg0, arg1);\n        }\n        else\n        {   tape->Rec_.PutOp(local::LeppOp);\n            tape->Rec_.PutArg(arg1, arg0);\n        }\n    }\n    return result;\n}\n// convert other cases into the case above\nCPPAD_FOLD_BOOL_VALUED_BINARY_OPERATOR(<)\n\n// -------------------------------- <= --------------------------\ntemplate <class Base>\nCPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION\nbool operator <= (const AD<Base> &left , const AD<Base> &right)\n{   bool result    =  (left.value_ <= right.value_);\n    //\n    // check if we are recording compare operators\n    local::ADTape<Base> *tape = AD<Base>::tape_ptr();\n    if( tape == nullptr )\n        return result;\n    if( ! tape->Rec_.get_record_compare() )\n        return result;\n    tape_id_t tape_id = tape->id_;\n    // tape_id cannot match the default value for tape_id_; i.e., 0\n    CPPAD_ASSERT_UNKNOWN( tape_id > 0 );\n\n    // check if left and right tapes match\n    bool match_left  = left.tape_id_  == tape_id;\n    bool match_right = right.tape_id_ == tape_id;\n\n    // check if left and right are dynamic parameters\n    bool dyn_left  = match_left  & (left.ad_type_ == dynamic_enum);\n    bool dyn_right = match_right & (right.ad_type_ == dynamic_enum);\n\n    // check if left and right are variables\n    bool var_left  = match_left  & (left.ad_type_ != dynamic_enum);\n    bool var_right = match_right & (right.ad_type_ != dynamic_enum);\n\n    CPPAD_ASSERT_KNOWN(\n        left.tape_id_ == right.tape_id_ || ! match_left || ! match_right ,\n        \"<= : AD variables or dynamic parameters on different threads.\"\n    );\n    if( var_left )\n    {   if( var_right )\n        {   // variable <= variable\n            if( result )\n            {   tape->Rec_.PutOp(local::LevvOp);\n                tape->Rec_.PutArg(left.taddr_, right.taddr_);\n            }\n            else\n            {   tape->Rec_.PutOp(local::LtvvOp);\n                tape->Rec_.PutArg(right.taddr_, left.taddr_);\n            }\n        }\n        else\n        {   // variable <= parameter\n            addr_t p = right.taddr_;\n            if( ! dyn_right )\n                p = tape->Rec_.put_con_par(right.value_);\n            if( result )\n            {   tape->Rec_.PutOp(local::LevpOp);\n                tape->Rec_.PutArg(left.taddr_, p);\n            }\n            else\n            {   tape->Rec_.PutOp(local::LtpvOp);\n                tape->Rec_.PutArg(p, left.taddr_);\n            }\n        }\n    }\n    else if ( var_right )\n    {   // parameter <= variable\n        addr_t p = left.taddr_;\n        if( ! dyn_left )\n            p = tape->Rec_.put_con_par(left.value_);\n        if( result )\n        {   tape->Rec_.PutOp(local::LepvOp);\n            tape->Rec_.PutArg(p, right.taddr_);\n        }\n        else\n        {   tape->Rec_.PutOp(local::LtvpOp);\n            tape->Rec_.PutArg(right.taddr_, p);\n        }\n    }\n    else if( dyn_left | dyn_right )\n    {   // parameter <= parameter\n        addr_t arg0 = left.taddr_;\n        addr_t arg1 = right.taddr_;\n        if( ! dyn_left )\n            arg0 = tape->Rec_.put_con_par(left.value_);\n        if( ! dyn_right )\n            arg1 = tape->Rec_.put_con_par(right.value_);\n        //\n        if( result )\n        {   tape->Rec_.PutOp(local::LeppOp);\n            tape->Rec_.PutArg(arg0, arg1);\n        }\n        else\n        {   tape->Rec_.PutOp(local::LtppOp);\n            tape->Rec_.PutArg(arg1, arg0);\n        }\n    }\n    return result;\n}\n// convert other cases into the case above\nCPPAD_FOLD_BOOL_VALUED_BINARY_OPERATOR(<=)\n\n// -------------------------------- > --------------------------\ntemplate <class Base>\nCPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION\nbool operator > (const AD<Base> &left , const AD<Base> &right)\n{   bool result    =  (left.value_ > right.value_);\n    //\n    // check if we are recording compare operators\n    local::ADTape<Base> *tape = AD<Base>::tape_ptr();\n    if( tape == nullptr )\n        return result;\n    if( ! tape->Rec_.get_record_compare() )\n        return result;\n    tape_id_t tape_id = tape->id_;\n    // tape_id cannot match the default value for tape_id_; i.e., 0\n    CPPAD_ASSERT_UNKNOWN( tape_id > 0 );\n\n    // check if left and right tapes match\n    bool match_left  = left.tape_id_  == tape_id;\n    bool match_right = right.tape_id_ == tape_id;\n\n    // check if left and right are dynamic parameters\n    bool dyn_left  = match_left  & (left.ad_type_ == dynamic_enum);\n    bool dyn_right = match_right & (right.ad_type_ == dynamic_enum);\n\n    // check if left and right are variables\n    bool var_left  = match_left  & (left.ad_type_ != dynamic_enum);\n    bool var_right = match_right & (right.ad_type_ != dynamic_enum);\n\n    CPPAD_ASSERT_KNOWN(\n        left.tape_id_ == right.tape_id_ || ! match_left || ! match_right ,\n        \"> : AD variables or dynamic parameters on different threads.\"\n    );\n    if( var_left )\n    {   if( var_right )\n        {   // variable > variable\n            if( result )\n            {   tape->Rec_.PutOp(local::LtvvOp);\n                tape->Rec_.PutArg(right.taddr_, left.taddr_);\n            }\n            else\n            {   tape->Rec_.PutOp(local::LevvOp);\n                tape->Rec_.PutArg(left.taddr_, right.taddr_);\n            }\n        }\n        else\n        {   // variable > parameter\n            addr_t p = right.taddr_;\n            if( ! dyn_right )\n                p = tape->Rec_.put_con_par(right.value_);\n            if( result )\n            {   tape->Rec_.PutOp(local::LtpvOp);\n                tape->Rec_.PutArg(p, left.taddr_);\n            }\n            else\n            {   tape->Rec_.PutOp(local::LevpOp);\n                tape->Rec_.PutArg(left.taddr_, p);\n            }\n        }\n    }\n    else if ( var_right )\n    {   // parameter > variable\n        addr_t p = left.taddr_;\n        if( ! dyn_left )\n            p = tape->Rec_.put_con_par(left.value_);\n        if( result )\n        {   tape->Rec_.PutOp(local::LtvpOp);\n            tape->Rec_.PutArg(right.taddr_, p);\n        }\n        else\n        {   tape->Rec_.PutOp(local::LepvOp);\n            tape->Rec_.PutArg(p, right.taddr_);\n        }\n    }\n    else if( dyn_left | dyn_right )\n    {   // parameter > parameter\n        addr_t arg0 = left.taddr_;\n        addr_t arg1 = right.taddr_;\n        if( ! dyn_left )\n            arg0 = tape->Rec_.put_con_par(left.value_);\n        if( ! dyn_right )\n            arg1 = tape->Rec_.put_con_par(right.value_);\n        //\n        if( result )\n        {   tape->Rec_.PutOp(local::LtppOp);\n            tape->Rec_.PutArg(arg1, arg0);\n        }\n        else\n        {   tape->Rec_.PutOp(local::LeppOp);\n            tape->Rec_.PutArg(arg0, arg1);\n        }\n    }\n    return result;\n}\n// convert other cases into the case above\nCPPAD_FOLD_BOOL_VALUED_BINARY_OPERATOR(>)\n\n// -------------------------------- >= --------------------------\ntemplate <class Base>\nCPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION\nbool operator >= (const AD<Base> &left , const AD<Base> &right)\n{   bool result    =  (left.value_ >= right.value_);\n    //\n    // check if we are recording compare operators\n    local::ADTape<Base> *tape = AD<Base>::tape_ptr();\n    if( tape == nullptr )\n        return result;\n    if( ! tape->Rec_.get_record_compare() )\n        return result;\n    tape_id_t tape_id = tape->id_;\n    // tape_id cannot match the default value for tape_id_; i.e., 0\n    CPPAD_ASSERT_UNKNOWN( tape_id > 0 );\n\n    // check if left and right tapes match\n    bool match_left  = left.tape_id_  == tape_id;\n    bool match_right = right.tape_id_ == tape_id;\n\n    // check if left and right are dynamic parameters\n    bool dyn_left  = match_left  & (left.ad_type_ == dynamic_enum);\n    bool dyn_right = match_right & (right.ad_type_ == dynamic_enum);\n\n    // check if left and right are variables\n    bool var_left  = match_left  & (left.ad_type_ != dynamic_enum);\n    bool var_right = match_right & (right.ad_type_ != dynamic_enum);\n\n    CPPAD_ASSERT_KNOWN(\n        left.tape_id_ == right.tape_id_ || ! match_left || ! match_right ,\n        \">= : AD variables or dynamic parameters on different threads.\"\n    );\n    if( var_left )\n    {   if( var_right )\n        {   // variable >= variable\n            if( result )\n            {   tape->Rec_.PutOp(local::LevvOp);\n                tape->Rec_.PutArg(right.taddr_, left.taddr_);\n            }\n            else\n            {   tape->Rec_.PutOp(local::LtvvOp);\n                tape->Rec_.PutArg(left.taddr_, right.taddr_);\n            }\n        }\n        else\n        {   // variable >= parameter\n            addr_t p = right.taddr_;\n            if( ! dyn_right )\n                p = tape->Rec_.put_con_par(right.value_);\n            if( result )\n            {   tape->Rec_.PutOp(local::LepvOp);\n                tape->Rec_.PutArg(p, left.taddr_);\n            }\n            else\n            {   tape->Rec_.PutOp(local::LtvpOp);\n                tape->Rec_.PutArg(left.taddr_, p);\n            }\n        }\n    }\n    else if ( var_right )\n    {   // parameter >= variable\n        addr_t p = left.taddr_;\n        if( ! dyn_left )\n            p = tape->Rec_.put_con_par(left.value_);\n        if( result )\n        {   tape->Rec_.PutOp(local::LevpOp);\n            tape->Rec_.PutArg(right.taddr_, p);\n        }\n        else\n        {   tape->Rec_.PutOp(local::LtpvOp);\n            tape->Rec_.PutArg(p, right.taddr_);\n        }\n    }\n    else if( dyn_left | dyn_right )\n    {   // parameter >= parameter\n        addr_t arg0 = left.taddr_;\n        addr_t arg1 = right.taddr_;\n        if( ! dyn_left )\n            arg0 = tape->Rec_.put_con_par(left.value_);\n        if( ! dyn_right )\n            arg1 = tape->Rec_.put_con_par(right.value_);\n        //\n        if( result )\n        {   tape->Rec_.PutOp(local::LeppOp);\n            tape->Rec_.PutArg(arg1, arg0);\n        }\n        else\n        {   tape->Rec_.PutOp(local::LtppOp);\n            tape->Rec_.PutArg(arg0, arg1);\n        }\n    }\n    return result;\n}\n// convert other cases into the case above\nCPPAD_FOLD_BOOL_VALUED_BINARY_OPERATOR(>=)\n\n// -------------------------------- == -------------------------\ntemplate <class Base>\nCPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION\nbool operator == (const AD<Base> &left , const AD<Base> &right)\n{   bool result    =  (left.value_ == right.value_);\n    //\n    // check if we are recording compare operators\n    local::ADTape<Base> *tape = AD<Base>::tape_ptr();\n    if( tape == nullptr )\n        return result;\n    if( ! tape->Rec_.get_record_compare() )\n        return result;\n    tape_id_t tape_id = tape->id_;\n    // tape_id cannot match the default value for tape_id_; i.e., 0\n    CPPAD_ASSERT_UNKNOWN( tape_id > 0 );\n\n    // check if left and right tapes match\n    bool match_left  = left.tape_id_  == tape_id;\n    bool match_right = right.tape_id_ == tape_id;\n\n    // check if left and right are dynamic parameters\n    bool dyn_left  = match_left  & (left.ad_type_ == dynamic_enum);\n    bool dyn_right = match_right & (right.ad_type_ == dynamic_enum);\n\n    // check if left and right are variables\n    bool var_left  = match_left  & (left.ad_type_ != dynamic_enum);\n    bool var_right = match_right & (right.ad_type_ != dynamic_enum);\n\n    CPPAD_ASSERT_KNOWN(\n        left.tape_id_ == right.tape_id_ || ! match_left || ! match_right ,\n        \"==: AD variables or dynamic parameters on different threads.\"\n    );\n    //\n    tape->Rec_.comp_eq(\n        var_left, var_right, dyn_left, dyn_right, left, right, result\n    );\n    //\n    return result;\n}\n// convert other cases into the case above\nCPPAD_FOLD_BOOL_VALUED_BINARY_OPERATOR(==)\n\n// -------------------------------- != -------------------------\ntemplate <class Base>\nCPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION\nbool operator != (const AD<Base> &left , const AD<Base> &right)\n{   bool result    =  (left.value_ != right.value_);\n    //\n    // check if we are recording compare operators\n    local::ADTape<Base> *tape = AD<Base>::tape_ptr();\n    if( tape == nullptr )\n        return result;\n    if( ! tape->Rec_.get_record_compare() )\n        return result;\n    tape_id_t tape_id = tape->id_;\n    // tape_id cannot match the default value for tape_id_; i.e., 0\n    CPPAD_ASSERT_UNKNOWN( tape_id > 0 );\n\n    // check if left and right tapes match\n    bool match_left  = left.tape_id_  == tape_id;\n    bool match_right = right.tape_id_ == tape_id;\n\n    // check if left and right are dynamic parameters\n    bool dyn_left  = match_left  & (left.ad_type_ == dynamic_enum);\n    bool dyn_right = match_right & (right.ad_type_ == dynamic_enum);\n\n    // check if left and right are variables\n    bool var_left  = match_left  & (left.ad_type_ != dynamic_enum);\n    bool var_right = match_right & (right.ad_type_ != dynamic_enum);\n\n    CPPAD_ASSERT_KNOWN(\n        left.tape_id_ == right.tape_id_ || ! match_left || ! match_right ,\n        \"!=: AD variables or dynamic parameters on different threads.\"\n    );\n    if( var_left )\n    {   if( var_right )\n        {   // variable == variable\n            tape->Rec_.PutArg(left.taddr_, right.taddr_);\n            if( result )\n                tape->Rec_.PutOp(local::NevvOp);\n            else\n                tape->Rec_.PutOp(local::EqvvOp);\n        }\n        else\n        {   // variable == parameter\n            addr_t p = right.taddr_;\n            if( ! dyn_right )\n                p = tape->Rec_.put_con_par(right.value_);\n            tape->Rec_.PutArg(p, left.taddr_);\n            if( result )\n                tape->Rec_.PutOp(local::NepvOp);\n            else\n                tape->Rec_.PutOp(local::EqpvOp);\n        }\n    }\n    else if ( var_right )\n    {   // parameter == variable\n        addr_t p = left.taddr_;\n        if( ! dyn_left )\n            p = tape->Rec_.put_con_par(left.value_);\n        tape->Rec_.PutArg(p, right.taddr_);\n        if( result )\n            tape->Rec_.PutOp(local::NepvOp);\n        else\n            tape->Rec_.PutOp(local::EqpvOp);\n    }\n    else if( dyn_left | dyn_right )\n    {   // parameter == parameter\n        addr_t arg0 = left.taddr_;\n        addr_t arg1 = right.taddr_;\n        if( ! dyn_left )\n            arg0 = tape->Rec_.put_con_par(left.value_);\n        if( ! dyn_right )\n            arg1 = tape->Rec_.put_con_par(right.value_);\n        //\n        tape->Rec_.PutArg(arg0, arg1);\n        if( result )\n            tape->Rec_.PutOp(local::NeppOp);\n        else\n            tape->Rec_.PutOp(local::EqppOp);\n    }\n    return result;\n}\n// convert other cases into the case above\nCPPAD_FOLD_BOOL_VALUED_BINARY_OPERATOR(!=)\n\n} // END CppAD namespace\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/compound_assign.hpp",
    "content": "# ifndef CPPAD_CORE_COMPOUND_ASSIGN_HPP\n# define CPPAD_CORE_COMPOUND_ASSIGN_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n-------------------------------------------------------------------------------\n{xrst_begin compound_assign}\n{xrst_spell\n    div\n}\n\nAD Compound Assignment Operators\n################################\n\nSyntax\n******\n| *x* *Op* *y*\n\nPurpose\n*******\nPerforms compound assignment operations\nwhere either *x* has type\n``AD`` < *Base* > .\n\nOp\n**\nThe operator *Op* is one of the following\n\n.. csv-table::\n    :widths: auto\n\n    **Op**,**Meaning**\n    ``+=``,*x* is assigned *x* plus *y*\n    ``-=``,*x* is assigned *x* minus *y*\n    ``*=``,*x* is assigned *x* times *y*\n    ``/=``,*x* is assigned *x* divided by *y*\n\nBase\n****\nThe type *Base* is determined by the operand *x* .\n\nx\n*\nThe operand *x* has the following prototype\n\n    ``AD`` < *Base* > & *x*\n\ny\n*\nThe operand *y* has the following prototype\n\n    ``const`` *Type* & *y*\n\nwhere *Type* is\n``VecAD`` < *Base* >:: ``reference`` ,\n``AD`` < *Base* > ,\n*Base* , or\n``double`` .\n\nResult\n******\nThe result of this assignment\ncan be used as a reference to *x* .\nFor example, if *z* has the following type\n\n    ``AD`` < *Base* > *z*\n\nthen the syntax\n\n    *z* = *x* += *y*\n\nwill compute *x* plus *y*\nand then assign this value to both *x* and *z* .\n\nOperation Sequence\n******************\nThis is an :ref:`atomic_base<glossary@Operation@Atomic>`\n:ref:`glossary@AD of Base` operation\nand hence it is part of the current\nAD of *Base*\n:ref:`operation sequence<glossary@Operation@Sequence>` .\n{xrst_toc_hidden\n    example/general/add_eq.cpp\n    example/general/sub_eq.cpp\n    example/general/mul_eq.cpp\n    example/general/div_eq.cpp\n}\n\nExample\n*******\nThe following files contain examples and tests of these functions.\nEach test returns true if it succeeds and false otherwise.\n\n.. csv-table::\n    :widths: auto\n\n    add_eq.cpp,:ref:`add_eq.cpp-title`\n    sub_eq.cpp,:ref:`sub_eq.cpp-title`\n    mul_eq.cpp,:ref:`mul_eq.cpp-title`\n    div_eq.cpp,:ref:`div_eq.cpp-title`\n\nDerivative\n**********\nIf :math:`f` and :math:`g` are\n:ref:`Base functions<glossary@Base Function>`\n\nAddition\n========\n\n.. math::\n\n    \\D{[ f(x) + g(x) ]}{x} = \\D{f(x)}{x} + \\D{g(x)}{x}\n\nSubtraction\n===========\n\n.. math::\n\n    \\D{[ f(x) - g(x) ]}{x} = \\D{f(x)}{x} - \\D{g(x)}{x}\n\nMultiplication\n==============\n\n.. math::\n\n    \\D{[ f(x) * g(x) ]}{x} = g(x) * \\D{f(x)}{x} + f(x) * \\D{g(x)}{x}\n\nDivision\n========\n\n.. math::\n\n    \\D{[ f(x) / g(x) ]}{x} =\n        [1/g(x)] * \\D{f(x)}{x} - [f(x)/g(x)^2] * \\D{g(x)}{x}\n\n{xrst_end compound_assign}\n-----------------------------------------------------------------------------\n*/\n# include <cppad/core/add_eq.hpp>\n# include <cppad/core/sub_eq.hpp>\n# include <cppad/core/mul_eq.hpp>\n# include <cppad/core/div_eq.hpp>\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/con_dyn_var.hpp",
    "content": "# ifndef CPPAD_CORE_CON_DYN_VAR_HPP\n# define CPPAD_CORE_CON_DYN_VAR_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n---------------------------------------------------------------------------\n\n{xrst_begin con_dyn_var}\n\nConstant, Dynamic, Parameter, and Variable\n##########################################\n\nSyntax\n******\n| *b* = ``Constant`` ( *x* )\n| *b* = ``Dynamic`` ( *x* )\n| *b* = ``Parameter`` ( *x* )\n| *b* = ``Variable`` ( *x* )\n\nx\n*\nThe argument *x* has prototype\n\n| |tab| ``const AD`` < *Base* >    & *x*\n| |tab| ``const VecAD`` < *Base* > & *x*\n\nb\n*\nThe return value *b* has prototype\n\n    ``bool`` *b*\n\nConstant\n********\nThe return value for ``Constant`` is true\nis true if and only if *x* is\na :ref:`glossary@Parameter@Constant` parameter.\nA :ref:`VecAD\\<Base><VecAD-name>` object is a constant parameter\nif no element of the vector depends on the independent variables.\n\nDynamic\n*******\nThe return value for ``Dynamic`` is true\nis true if and only if *x* is\na :ref:`glossary@Parameter@Dynamic` parameter.\nNo element of a :ref:`VecAD\\<Base><VecAD-name>` object\ncan depend on the dynamic parameters and this function returns false\nfor these objects.\n\nParameter\n*********\nThe return value for ``Parameter`` is true\nis true if and only if *x* is\na :ref:`glossary@Parameter` .\nA :ref:`VecAD\\<Base><VecAD-name>` object is a parameter\nif no element of the vector depends on the independent variables.\n\nVariable\n********\nThe return value for ``Variable`` is true\nis true if and only if *x* is\na :ref:`glossary@Variable` .\nA :ref:`VecAD\\<Base><VecAD-name>` object is a variable\nif any element of the vector depends on the independent variables.\n\nOperation Sequence\n******************\nThe result of this operation is not an\n:ref:`glossary@AD of Base` object.\nThus it will not be recorded as part of an\nAD of *Base*\n:ref:`operation sequence<glossary@Operation@Sequence>` .\n\nExample\n*******\n{xrst_toc_hidden\n    example/general/con_dyn_var.cpp\n}\nThe file\n:ref:`con_dyn_var.cpp-name`\ncontains an example and test of these functions.\n\n{xrst_end con_dyn_var}\n-----------------------------------------------------------------------------\n*/\n\nnamespace CppAD {\n    // -----------------------------------------------------------------------\n    // Constant\n    template <class Base>\n    bool Constant(const AD<Base> &x)\n    {   CPPAD_ASSERT_AD_TYPE( x );\n        if( x.tape_id_ == 0 )\n            return true;\n        //\n        size_t thread = size_t(x.tape_id_ % CPPAD_MAX_NUM_THREADS);\n        return x.tape_id_ != *AD<Base>::tape_id_ptr(thread);\n    }\n    //\n    template <class Base>\n    bool Constant(const VecAD<Base> &x)\n    {   CPPAD_ASSERT_AD_TYPE( x );\n        if( x.tape_id_ == 0 )\n            return true;\n        //\n        size_t thread = size_t(x.tape_id_ % CPPAD_MAX_NUM_THREADS);\n        return x.tape_id_ != *AD<Base>::tape_id_ptr(thread);\n    }\n    // -----------------------------------------------------------------------\n    // Dynamic\n    template <class Base>\n    bool Dynamic(const AD<Base> &x)\n    {   CPPAD_ASSERT_AD_TYPE( x );\n        if( (x.tape_id_ == 0) || (x.ad_type_ != dynamic_enum) )\n            return false;\n        //\n        size_t thread = size_t(x.tape_id_ % CPPAD_MAX_NUM_THREADS);\n        return x.tape_id_ == *AD<Base>::tape_id_ptr(thread);\n    }\n    //\n    template <class Base>\n    bool Dynamic(const VecAD<Base> &x)\n    {   CPPAD_ASSERT_AD_TYPE( x );\n        if( (x.tape_id_ == 0) || (x.ad_type_ != dynamic_enum) )\n            return false;\n        //\n        size_t thread = size_t(x.tape_id_ % CPPAD_MAX_NUM_THREADS);\n        return x.tape_id_ == *AD<Base>::tape_id_ptr(thread);\n    }\n    // -----------------------------------------------------------------------\n    // Parameter\n    template <class Base>\n    bool Parameter(const AD<Base> &x)\n    {   CPPAD_ASSERT_AD_TYPE( x );\n        if( (x.tape_id_ == 0) || (x.ad_type_ == dynamic_enum) )\n            return true;\n        //\n        size_t thread = size_t(x.tape_id_ % CPPAD_MAX_NUM_THREADS);\n        return x.tape_id_ != *AD<Base>::tape_id_ptr(thread);\n    }\n    //\n    template <class Base>\n    bool Parameter(const VecAD<Base> &x)\n    {   CPPAD_ASSERT_AD_TYPE( x );\n        if( (x.tape_id_ == 0) || (x.ad_type_ == dynamic_enum) )\n            return true;\n        //\n        size_t thread = size_t(x.tape_id_ % CPPAD_MAX_NUM_THREADS);\n        return x.tape_id_ != *AD<Base>::tape_id_ptr(thread);\n    }\n    // -----------------------------------------------------------------------\n    // Variable\n    template <class Base>\n    bool Variable(const AD<Base> &x)\n    {   CPPAD_ASSERT_AD_TYPE( x );\n        if( (x.tape_id_ == 0) || (x.ad_type_ != variable_enum) )\n            return false;\n        //\n        size_t thread = size_t(x.tape_id_ % CPPAD_MAX_NUM_THREADS);\n        return x.tape_id_ == *AD<Base>::tape_id_ptr(thread);\n    }\n    //\n    template <class Base>\n    bool Variable(const VecAD<Base> &x)\n    {   CPPAD_ASSERT_AD_TYPE( x );\n        if( (x.tape_id_ == 0) || (x.ad_type_ != variable_enum) )\n            return false;\n        //\n        size_t thread = size_t(x.tape_id_ % CPPAD_MAX_NUM_THREADS);\n        return x.tape_id_ == *AD<Base>::tape_id_ptr(thread);\n    }\n}\n// END CppAD namespace\n\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/cond_exp.hpp",
    "content": "# ifndef CPPAD_CORE_COND_EXP_HPP\n# define CPPAD_CORE_COND_EXP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n-------------------------------------------------------------------------------\n{xrst_begin CondExp}\n\nAD Conditional Expressions\n##########################\n\nSyntax\n******\n| *result* = ``CondExp`` *Rel* ( *left* , *right* , *if_true* , *if_false* )\n\nPurpose\n*******\nRecord,\nas part of an AD of *Base*\n:ref:`operation sequence<glossary@Operation@Sequence>` ,\nthe conditional result\n\n| |tab| ``if`` ( *left* *Cop* *right*  )\n| |tab| |tab| *result* = *if_true*\n| |tab| ``else``\n| |tab| |tab| *result* = *if_false*\n\nThe relational *Rel* and comparison operator *Cop*\nabove have the following correspondence:\n\n.. csv-table::\n\n    *Rel* , ``Lt`` , ``Le`` , ``Eq`` , ``Ge`` , ``Gt``\n    *Cop* ,  <     , <=     , ==     , >=     , >\n\nIf *f* is the :ref:`ADFun-name` object corresponding to the\nAD operation sequence,\nthe assignment choice for *result*\nin an AD conditional expression is made each time\n:ref:`f.Forward<Forward-name>` is used to evaluate the zero order Taylor\ncoefficients with new values for the\n:ref:`independent variables<glossary@Tape@Independent Variable>` .\nThis is in contrast to the :ref:`AD comparison operators<Compare-name>`\nwhich are boolean valued and not included in the AD operation sequence.\n\nRel\n***\nIn the syntax above, the relation *Rel* represents one of the following\ntwo characters: ``Lt`` , ``Le`` , ``Eq`` , ``Ge`` , ``Gt`` .\nAs in the table above,\n*Rel* determines which comparison operator *Cop* is used\nwhen comparing *left* and *right* .\n\nType\n****\nThese functions are defined in the CppAD namespace for arguments of\n*Type* is *Base* or ``AD`` < *Base* > .\nNote that all four arguments,\n*left* , *right*, *if_true* , *if_false* ,  must have the same type.\n\nleft\n****\nThe argument *left* has prototype\n\n    ``const`` *Type* & *left*\n\nIt specifies the value for the left side of the comparison operator.\n\nright\n*****\nThe argument *right* has prototype\n\n    ``const`` *Type* & *right*\n\nIt specifies the value for the right side of the comparison operator.\n\nif_true\n*******\nThe argument *if_true* has prototype\n\n    ``const`` *Type* & *if_true*\n\nIt specifies the return value if the result of the comparison is true.\n\nif_false\n********\nThe argument *if_false* has prototype\n\n    ``const`` *Type* & *if_false*\n\nIt specifies the return value if the result of the comparison is false.\n\nresult\n******\nThe *result* has prototype\n\n    *Type* & *if_false*\n\nOptimize\n********\nThe :ref:`optimize-name` method will optimize conditional expressions\nin the following way:\nDuring :ref:`zero order forward mode<forward_zero-name>` ,\nonce the value of the *left* and *right* have been determined,\nit is known if the true or false case is required.\nFrom this point on, values corresponding to the case that is not required\nare not computed.\nThis optimization is done for the rest of zero order forward mode\nas well as forward and reverse derivatives calculations.\n\nDeprecate 2005-08-07\n********************\nPrevious versions of CppAD used\n\n    ``CondExp`` ( *flag* , *if_true* , *if_false* )\n\nfor the same meaning as\n\n    ``CondExpGt`` ( *flag* , *Type* (0), *if_true* , *if_false* )\n\nUse of ``CondExp`` is deprecated, but continues to be supported.\n\nOperation Sequence\n******************\nThis is an AD of *Base*\n:ref:`atomic operation<glossary@Operation@Atomic>`\nand hence is part of the current\nAD of *Base*\n:ref:`operation sequence<glossary@Operation@Sequence>` .\n\nExample\n*******\n\nTest\n****\n{xrst_toc_hidden\n    example/general/cond_exp.cpp\n}\nThe file\n:ref:`cond_exp.cpp-name`\ncontains an example and test of this function.\n\nAtan2\n*****\nThe following implementation of the\nAD :ref:`atan2-name` function is a more complex\nexample of using conditional expressions:\n{xrst_literal\n    include/cppad/core/atan2.hpp\n    BEGIN CondExp\n    // END CondExp\n}\n\n{xrst_end CondExp}\n-------------------------------------------------------------------------------\n*/\n//  BEGIN CppAD namespace\nnamespace CppAD {\n\ntemplate <class Base>\nAD<Base> CondExpOp(\n    enum  CompareOp cop       ,\n    const AD<Base> &left      ,\n    const AD<Base> &right     ,\n    const AD<Base> &if_true   ,\n    const AD<Base> &if_false  )\n{\n    AD<Base> result;\n    CPPAD_ASSERT_UNKNOWN( Parameter(result) );\n\n    // check first case where do not need to tape\n    if( IdenticalCon(left) && IdenticalCon(right) )\n    {   result = CondExpOp(\n            cop, left.value_, right.value_, if_true.value_, if_false.value_\n        );\n        return result;\n    }\n\n    // must use CondExp in case Base is an AD type and recording\n    result.value_ = CondExpOp(cop,\n        left.value_, right.value_, if_true.value_, if_false.value_);\n\n    local::ADTape<Base> *tape = AD<Base>::tape_ptr();\n\n    // add this operation to the tape\n    if( tape != nullptr ) tape->Rec_.cond_exp(\n            tape->id_, cop, result, left, right, if_true, if_false\n    );\n\n    return result;\n}\n\n// ------------ CondExpOp(left, right, if_true, if_false) ----------------\n\n# define CPPAD_COND_EXP(Name)                                        \\\n    template <class Base>                                           \\\n    CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION                           \\\n    AD<Base> CondExp##Name(                                         \\\n        const AD<Base> &left      ,                                \\\n        const AD<Base> &right     ,                                \\\n        const AD<Base> &if_true   ,                                \\\n        const AD<Base> &if_false  )                                \\\n    {                                                                \\\n        return CondExpOp(Compare##Name,                            \\\n            left, right, if_true, if_false);                      \\\n    }\n\n// AD<Base>\nCPPAD_COND_EXP(Lt)\nCPPAD_COND_EXP(Le)\nCPPAD_COND_EXP(Eq)\nCPPAD_COND_EXP(Ge)\nCPPAD_COND_EXP(Gt)\ntemplate <class Base>\nCPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION\nAD<Base> CondExp(\n    const AD<Base> &flag      ,\n    const AD<Base> &if_true   ,\n    const AD<Base> &if_false  )\n{\n    return CondExpOp(CompareGt, flag, AD<Base>(0), if_true, if_false);\n}\n\n# undef CPPAD_COND_EXP\n} // END CppAD namespace\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/convert.hpp",
    "content": "# ifndef CPPAD_CORE_CONVERT_HPP\n# define CPPAD_CORE_CONVERT_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin Convert}\n\nConversion and I/O of AD Objects\n################################\n{xrst_toc_hidden\n    include/cppad/core/value.hpp\n    include/cppad/core/integer.hpp\n    include/cppad/core/ad_to_string.hpp\n    include/cppad/core/ad_io.hpp\n    include/cppad/core/print_for.hpp\n    include/cppad/core/var2par.hpp\n}\n\n.. csv-table::\n    :widths: auto\n\n    Value,:ref:`Value-title`\n    Integer,:ref:`Integer-title`\n    ad_output,:ref:`ad_output-title`\n    PrintFor,:ref:`PrintFor-title`\n    Var2Par,:ref:`Var2Par-title`\n\n{xrst_end Convert}\n*/\n\n# include <cppad/core/value.hpp>\n# include <cppad/core/integer.hpp>\n# include <cppad/core/ad_to_string.hpp>\n# include <cppad/core/ad_io.hpp>\n# include <cppad/core/print_for.hpp>\n# include <cppad/core/var2par.hpp>\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/cppad_assert.hpp",
    "content": "# ifndef CPPAD_CORE_CPPAD_ASSERT_HPP\n# define CPPAD_CORE_CPPAD_ASSERT_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*!\n\\file cppad_assert.hpp\nDefine the CppAD error checking macros (all of which begin with CPPAD_ASSERT_)\n*/\n\n/*\n-------------------------------------------------------------------------------\n{xrst_begin cppad_assert}\n{xrst_spell\n    msg\n}\n\nCppAD Assertions During Execution\n#################################\n\nSyntax\n******\n| ``CPPAD_ASSERT_KNOWN`` ( *exp* , *msg* )\n| ``CPPAD_ASSERT_UNKNOWN`` ( *exp* )\n\nPurpose\n*******\nThese CppAD macros are used to detect and report errors.\nThey are documented here because they correspond to the C++\nsource code that the error is reported at.\n\nNDEBUG\n******\nIf the preprocessor symbol\n:ref:`Faq@Speed@NDEBUG` is defined,\nthese macros do nothing; i.e., they are optimized out.\n\nRestriction\n***********\nThe CppAD user should not uses these macros.\nYou can however write your own macros that do not begin with ``CPPAD``\nand that call the :ref:`CppAD error handler<ErrorHandler-name>` .\n\nKnown\n*****\nThe ``CPPAD_ASSERT_KNOWN`` macro is used to check for an error\nwith a known cause.\nFor example, many CppAD routines uses these macros\nto make sure their arguments conform to their specifications.\n\nUnknown\n*******\nThe ``CPPAD_ASSERT_UNKNOWN`` macro is used to check that the\nCppAD internal data structures conform as expected.\nIf this is not the case, CppAD does not know why the error has\noccurred; for example, the user may have written past the end\nof an allocated array.\n\nExp\n***\nThe argument *exp* is a C++ source code expression\nthat results in a ``bool`` value that should be true.\nIf it is false, an error has occurred.\nThis expression may be execute any number of times\n(including zero times) so it must have not side effects.\n\nMsg\n***\nThe argument *msg* has prototype\n\n    ``const char`` * *msg*\n\nand contains a ``'\\0'`` terminated character string.\nThis string is a description of the error\ncorresponding to *exp* being false.\n\nError Handler\n*************\nThese macros use the\n:ref:`CppAD error handler<ErrorHandler-name>` to report errors.\nThis error handler can be replaced by the user.\n\n{xrst_end cppad_assert}\n------------------------------------------------------------------------------\n*/\n\n# include <cassert>\n# include <iostream>\n# include <cppad/utility/error_handler.hpp>\n\n/*!\n\\def CPPAD_ASSERT_KNOWN(exp, msg)\nCheck that exp is true, if not print msg and terminate execution.\n\nThe C++ expression exp is expected to be true.\nIf it is false,\nthe CppAD use has made an error that is described by msg.\nIf the preprocessor symbol NDEBUG is not defined,\nand exp is false,\nthis macro will report the source code line number at\nwhich this expected result occurred.\nIn addition, it will print the specified error message msg.\n*/\n# ifdef NDEBUG\n# define CPPAD_ASSERT_KNOWN(exp, msg)  // do nothing\n# else\n# define CPPAD_ASSERT_KNOWN(exp, msg)           \\\n{   if( ! ( exp ) )                         \\\n    CppAD::ErrorHandler::Call(              \\\n        true       ,                    \\\n        __LINE__   ,                    \\\n        __FILE__   ,                    \\\n        #exp       ,                    \\\n        msg        );                   \\\n}\n# endif\n\n/*!\n\\def CPPAD_ASSERT_UNKNOWN(exp)\nCheck that exp is true, if not terminate execution.\n\nThe C++ expression exp is expected to be true.\nIf it is false,\nCppAD has detected an error but does not know the cause of the error.\nIf the preprocessor symbol NDEBUG is not defined,\nand exp is false,\nthis macro will report the source code line number at\nwhich this expected result occurred.\n*/\n# ifdef NDEBUG\n# define CPPAD_ASSERT_UNKNOWN(exp)      // do nothing\n# else\n# define CPPAD_ASSERT_UNKNOWN(exp)              \\\n{   if( ! ( exp ) )                         \\\n    CppAD::ErrorHandler::Call(              \\\n        false      ,                    \\\n        __LINE__   ,                    \\\n        __FILE__   ,                    \\\n        #exp       ,                    \\\n        \"\"         );                   \\\n}\n# endif\n\n/*!\n\\def CPPAD_ASSERT_NARG_NRES(op, n_arg, n_res)\nCheck that operator op has the specified number of of arguments and results.\n\nIf NDEBUG is not defined and either the number of arguments\nor the number of results are not as expected,\nexecution is terminated and the source code line number is reported.\n*/\n# define CPPAD_ASSERT_NARG_NRES(op, n_arg, n_res)   \\\n    CPPAD_ASSERT_UNKNOWN( NumArg(op) == n_arg ) \\\n    CPPAD_ASSERT_UNKNOWN( NumRes(op) == n_res )\n\n/*!\n\\def CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL\nCheck that the first call to a routine is not during parallel execution mode.\n\nIf NDEBUG is defined, this macro has no effect\n(not even the definition of (assert_first_call).\nOtherwise, the variable\n\\code\n    static bool assert_first_call\n\\endcode\nis defined and if the first call is executed in parallel mode,\nexecution is terminated and the source code line number is reported.\n*/\n# ifdef NDEBUG\n# define CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL\n# else\n# define CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL                           \\\n    static bool assert_first_call = true;                              \\\n    if( assert_first_call )                                            \\\n    {   CPPAD_ASSERT_KNOWN(                                           \\\n        ! (CppAD::thread_alloc::in_parallel() ),                      \\\n        \"In parallel mode and parallel_setup has not been called.\"    \\\n        );                                                            \\\n        assert_first_call = false;                                    \\\n    }\n# endif\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/dependent.hpp",
    "content": "# ifndef CPPAD_CORE_DEPENDENT_HPP\n# define CPPAD_CORE_DEPENDENT_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin Dependent}\n\nStop Recording and Store Operation Sequence\n###########################################\n\nSyntax\n******\n| *f* . ``Dependent`` ( *x* , *y* )\n\nStop Recording\n**************\nThe call stops the recording and the AD of *Base*\n:ref:`operation sequence<glossary@Operation@Sequence>`\nthat started with the call\n\n    ``Independent`` ( *x* )\n\nStore Operation Sequence\n************************\nThis call also stores the operation sequence in *f* .\nThe operation sequence defines an\n:ref:`glossary@AD Function`\n\n.. math::\n\n    F : \\B{R}^n \\rightarrow \\B{R}^m\n\nwhere :math:`B` is the space corresponding to objects of type *Base* .\nThe value :math:`n` is the dimension of the\n:ref:`fun_property@Domain` space for the operation sequence.\nThe value :math:`m` is the dimension of the\n:ref:`fun_property@Range` space for the operation sequence\n(which is determined by the size of *y* ).\n\nf\n*\nThe object *f* has prototype\n\n    ``ADFun`` < *Base* > *f*\n\nThe AD of *Base* operation sequence is stored in *f* ; i.e.,\nit becomes the operation sequence corresponding to *f* .\nIf a previous operation sequence was stored in *f* ,\nit is deleted.\n\nx\n*\nThe argument *x*\nmust be the vector argument in a previous call to\n:ref:`Independent-name` .\nNeither its size, or any of its values, are allowed to change\nbetween calling\n\n    ``Independent`` ( *x* )\n\nand\n\n    *f* . ``Dependent`` ( *x* , *y* )\n\n.\n\ny\n*\nThe vector *y* has prototype\n\n    ``const`` *ADvector* & *y*\n\n(see :ref:`ADvector<fun_construct-name>` below).\nThe length of *y* must be greater than zero\nand is the dimension of the range space for *f* .\n\nADvector\n********\nThe type *ADvector* must be a :ref:`SimpleVector-name` class with\n:ref:`elements of type<SimpleVector@Elements of Specified Type>`\n``AD`` < *Base* > .\nThe routine :ref:`CheckSimpleVector-name` will generate an error message\nif this is not the case.\n\nTaping\n******\nThe tape,\nthat was created when ``Independent`` ( *x* ) was called,\nwill stop recording.\nThe AD operation sequence will be transferred from\nthe tape to the object *f* and the tape will then be deleted.\n\nForward\n*******\nNo :ref:`Forward-name` calculation is preformed during this operation.\nThus, directly after this operation,\n\n    *f* . ``size_order`` ()\n\nis zero (see :ref:`size_order-name` ).\n\nParallel Mode\n*************\nThe call to ``Independent`` ,\nand the corresponding call to\n\n    ``ADFun`` < *Base* > *f* ( *x* , *y* )\n\nor\n\n    *f* . ``Dependent`` ( *x* , *y* )\n\nor :ref:`abort_recording-name` ,\nmust be preformed by the same thread; i.e.,\n:ref:`thread_alloc::thread_num<ta_thread_num-name>` must be the same.\n\nExample\n*******\nThe file\n:ref:`fun_check.cpp-name`\ncontains an example and test of this operation.\n\n{xrst_end Dependent}\n----------------------------------------------------------------------------\n*/\n\n\n// BEGIN CppAD namespace\nnamespace CppAD {\n\n/*!\n\\file dependent.hpp\nDifferent versions of Dependent function.\n*/\n\n/*!\nDetermine the tape corresponding to this execution thread and then use\n<code>Dependent(tape, y)</code> to store this tapes recording in a function.\n\n\\param y [in]\nThe dependent variable vector for the corresponding function.\n*/\ntemplate <class Base, class RecBase>\ntemplate <class ADvector>\nvoid ADFun<Base,RecBase>::Dependent(const ADvector &y)\n{   local::ADTape<Base>* tape = AD<Base>::tape_ptr();\n    CPPAD_ASSERT_KNOWN(\n        tape != nullptr,\n        \"Can't store current operation sequence in this ADFun object\"\n        \"\\nbecause there is no active tape (for this thread).\"\n    );\n\n    // code above just determines the tape and checks for errors\n    Dependent(tape, y);\n}\n\n\n/*!\nDetermine the tape corresponding to this execution thread and then use\n<code>Dependent(tape, y)</code> to store this tapes recording in a function.\n\n\\param x [in]\nThe independent variable vector for this tape. This information is\nalso stored in the tape so a check is done to make sure it is correct\n(if NDEBUG is not defined).\n\n\\param y [in]\nThe dependent variable vector for the corresponding function.\n*/\ntemplate <class Base, class RecBase>\ntemplate <class ADvector>\nvoid ADFun<Base,RecBase>::Dependent(const ADvector &x, const ADvector &y)\n{\n    CPPAD_ASSERT_KNOWN(\n        x.size() > 0,\n        \"Dependent: independent variable vector has size zero.\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        Variable(x[0]),\n        \"Dependent: independent variable vector has been changed.\"\n    );\n    local::ADTape<Base> *tape = AD<Base>::tape_ptr(x[0].tape_id_);\n    CPPAD_ASSERT_KNOWN(\n        tape->size_independent_ == size_t( x.size() ),\n        \"Dependent: independent variable vector has been changed.\"\n    );\n# ifndef NDEBUG\n    size_t i, j;\n    for(j = 0; j < size_t(x.size()); j++)\n    {   CPPAD_ASSERT_KNOWN(\n        size_t(x[j].taddr_) == (j+1),\n        \"ADFun<Base>: independent variable vector has been changed.\"\n        );\n        CPPAD_ASSERT_KNOWN(\n        x[j].tape_id_ == x[0].tape_id_,\n        \"ADFun<Base>: independent variable vector has been changed.\"\n        );\n    }\n    for(i = 0; i < size_t(y.size()); i++)\n    {   CPPAD_ASSERT_KNOWN(\n        CppAD::Parameter( y[i] ) || (y[i].tape_id_ == x[0].tape_id_) ,\n        \"ADFun<Base>: dependent vector contains a variable for\"\n        \"\\na different tape (thread) than the independent variables.\"\n        );\n    }\n# endif\n\n    // code above just determines the tape and checks for errors\n    Dependent(tape, y);\n}\n\n/*!\nReplace the floationg point operations sequence for this function object.\n\n\\param tape\nis a tape that contains the new floating point operation sequence\nfor this function.\nAfter this operation, all memory allocated for this tape is deleted.\n\n\\param y\nThe dependent variable vector for the function being stored in this object.\n\n\\par\nAll of the private member data in ad_fun.hpp is set to correspond to the\nnew tape except for check_for_nan_.\n*/\n\ntemplate <class Base, class RecBase>\ntemplate <class ADvector>\nvoid ADFun<Base,RecBase>::Dependent(local::ADTape<Base> *tape, const ADvector &y)\n{\n    size_t   m = y.size();\n    size_t   n = tape->size_independent_;\n\n    // check ADvector is Simple Vector class with AD<Base> elements\n    CheckSimpleVector< AD<Base>, ADvector>();\n\n    CPPAD_ASSERT_KNOWN(\n        y.size() > 0,\n        \"ADFun operation sequence dependent variable size is zero size\"\n    );\n    // ---------------------------------------------------------------------\n    // Begin setting ad_fun.hpp private member data\n    // ---------------------------------------------------------------------\n    // dep_parameter_, dep_taddr_\n    CPPAD_ASSERT_UNKNOWN( local::NumRes(local::ParOp) == 1 );\n    dep_parameter_.resize(m);\n    dep_taddr_.resize(m);\n    for(size_t i = 0; i < m; i++)\n    {   dep_parameter_[i] = CppAD::Parameter(y[i]);\n        addr_t y_taddr;\n        if( dep_parameter_[i] )\n        {   // make a tape copy of dependent variables that are parameters,\n            y_taddr = tape->RecordParOp( y[i] );\n        }\n        else\n            y_taddr = y[i].taddr_;\n\n        CPPAD_ASSERT_UNKNOWN( y_taddr > 0 );\n        dep_taddr_[i] = size_t( y_taddr );\n    }\n\n    // put an EndOp at the end of the tape\n    tape->Rec_.PutOp(local::EndOp);\n\n    // bool values in this object except check_for_nan_\n    has_been_optimized_        = false;\n    //\n    // size_t values in this object\n    compare_change_count_      = 1;\n    compare_change_number_     = 0;\n    compare_change_op_index_   = 0;\n    num_order_taylor_          = 0;\n    cap_order_taylor_          = 0;\n    num_direction_taylor_      = 0;\n    num_var_tape_              = tape->Rec_.num_var();\n\n    // taylor_\n    taylor_.resize(0);\n\n    // cskip_op_\n    cskip_op_.resize( tape->Rec_.num_var_op() );\n\n    // load_op2var_\n    load_op2var_.resize( tape->Rec_.num_var_load() );\n\n    // play_\n    // Now that each dependent variable has a place in the tape,\n    // and there is a EndOp at the end of the tape, we can transfer the\n    // recording to the player and and erase the recording; i.e. ERASE Rec_.\n    play_.get_recording(tape->Rec_, n);\n\n    // ind_taddr_\n    // Note that play_ has been set, we can use it to check operators\n    ind_taddr_.resize(n);\n    CPPAD_ASSERT_UNKNOWN( n < num_var_tape_);\n    for(size_t j = 0; j < n; j++)\n    {   CPPAD_ASSERT_UNKNOWN( play_.GetOp(j+1) == local::InvOp );\n        ind_taddr_[j] = j+1;\n    }\n\n    // for_jac_sparse_pack_, for_jac_sparse_set_\n    for_jac_sparse_pack_.resize(0, 0);\n    for_jac_sparse_set_.resize(0,0);\n\n    // resize subgraph_info_\n    subgraph_info_.resize(\n        ind_taddr_.size(),   // n_dep\n        dep_taddr_.size(),   // n_ind\n        play_.num_var_op(),  // n_op\n        play_.num_var()      // n_var\n    );\n    // ---------------------------------------------------------------------\n    // End set ad_fun.hpp private member data\n    // ---------------------------------------------------------------------\n\n    // now we can delete the tape\n    AD<Base>::tape_manage(delete_tape_manage);\n\n    // total number of variables in this recording\n    CPPAD_ASSERT_UNKNOWN( num_var_tape_  == play_.num_var() );\n\n    // used to determine if there is an operation sequence in *this\n    CPPAD_ASSERT_UNKNOWN( num_var_tape_  > 0 );\n\n}\n\n} // END CppAD namespace\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/discrete/devel.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin devel_discrete dev}\n\nDeveloper Documentation for Discrete Function\n#############################################\n\nContents\n********\n{xrst_toc_table\n    include/cppad/core/discrete/discrete.hpp\n}\n\n{xrst_end devel_discrete}\n"
  },
  {
    "path": "include/cppad/core/discrete/discrete.hpp",
    "content": "# ifndef CPPAD_CORE_DISCRETE_DISCRETE_HPP\n# define CPPAD_CORE_DISCRETE_DISCRETE_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <vector>\n# include <cppad/core/cppad_assert.hpp>\n# include <cppad/local/op_code_dyn.hpp>\n\n// needed before one can use CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL\n# include <cppad/utility/thread_alloc.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*\n ------------------------------------------------------------------------------\n{xrst_begin discrete_create dev}\nCreate a Discrete AD Function\n#############################\n\nSyntax\n******\n| ``CPPAD_DISCRETE_FUNCTION`` ( *Base* , *name* )\n| ``name`` ( *ax* , *ay* )\n\nBase\n****\nis the base type for the discrete function.\n\nname\n****\nis the name of the user defined function that corresponding to this operation.\n\nax\n**\nIs a ``AD`` < *Base* > corresponding to the argument for the function.\n\nay\n**\nIs a ``AD`` < *Base* > corresponding to the result for the function.\n\nfun\n***\nThe local object ``fun`` is a member of the ``discrete`` class.\n\nSource Code\n***********\n{xrst_spell_off}\n{xrst_code hpp} */\n# define CPPAD_DISCRETE_FUNCTION(Base, name)            \\\ninline CppAD::AD<Base> name (const CppAD::AD<Base>& ax) \\\n{    static CppAD::discrete<Base> fun(#name, name);     \\\n      return fun.ad(ax);                                 \\\n}                                                       \\\nCppAD::AD<Base> this_variable_name_used_to_initialize_discrete_ ##name =  \\\nname( CppAD::AD<Base>(0.0) );\n//\n# define CppADCreateDiscrete CPPAD_DISCRETE_FUNCTION\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end discrete_create}\n-----------------------------------------------------------------------------\n{xrst_begin discrete_class dev}\n\nDeclare discrete Class and Member Data\n######################################\n\nparallel_ad\n***********\nis a friend of this class so it can call List to initialize\nits static data.\n\nFun\n***\nis the type for the user routine that computes *Base* function values.\n\nname\\_\n******\nname of this user defined discrete function.\n\nf\\_\n***\nuser routine that computes *Base* function values.\n\nindex\\_\n*******\nindex of this object in :ref:`discrete_list-name` for this *Base* .\n\nSource Code\n***********\n{xrst_spell_off}\n{xrst_code hpp} */\ntemplate <class Base>\nclass discrete {\nprivate:\n    template <class Type> friend void parallel_ad(void);\n    typedef Base (*Fun) (const Base& x);\n    const std::string    name_;\n    const Fun            f_;\n    const size_t         index_;\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end discrete_class}\n------------------------------------------------------------------------------\n{xrst_begin discrete_list dev}\nList of all objects in the discrete class\n#########################################\n\nSyntax\n******\n*list* = ``discrete`` < *Base* >:: ``List`` ()\n\nBase\n****\nIs the :ref:`discrete_create@Base`\ntype for this list of discrete functions.\n\nlist\n****\nis a reference to the list of all the\n``discrete`` object currently defined.\n\nstd::vector\n===========\nWe use ``std::vector`` instead of ``CppAD::vector``\nso it does not appear that there is a :ref:`memory_leak-name`\nthis list is not destroyed before\n:ref:`thread_alloc::free_all<ta_free_all-name>` is called by testing routines.\n\nSource Code\n***********\n{xrst_spell_off}\n{xrst_code hpp} */\nprivate:\n    static std::vector<discrete *>& List(void)\n    {  CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL;\n        static std::vector<discrete *> list;\n        return list;\n    }\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end discrete_list}\n ------------------------------------------------------------------------------\n{xrst_begin discrete_list_size dev}\nSize of the Discrete Function List\n##################################\n\nSyntax\n******\n*size* = ``discrete`` < *Base* >:: ``list_size`` ()\n\nBase\n****\nIs the :ref:`discrete_create@Base`\ntype for this list of discrete functions.\n\nsize\n****\nis the number of discrete functions for this *Base* type.\n\nSource Code\n***********\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    static size_t list_size(void)\n    {  return List().size(); }\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end discrete_list_size}\n ------------------------------------------------------------------------------\n{xrst_begin discrete_ctor dev}\nConstructor Called by each Use of CPPAD_DISCRETE_FUNCTION\n#########################################################\n\nSyntax\n******\n``discrete`` < *Base* > *fun* ( *name* , *f* )\n\nname\n****\nis the name of this function.\n\nf\n*\nuser routine that implements this function for Base class.\n\nfun\n***\nis the ``discrete`` object created by this call to the constructor.\n\nname\\_\n======\nis set equal to *name* .\n\nf\\_\n===\nis set equal to *f* .\n\nindex\\_\n=======\nThis object is put at the end of :ref:`discrete_list-name` and ``index_``\nis set to the index of this object in the discrete list.\n\nParallel\n********\nThis constructor cannot be used in parallel mode because it changes\nthe static object returned by :ref:`discrete_list-name` .\n\n{xrst_end discrete_ctor}\n*/\npublic:\n    discrete(const std::string& name, Fun f) :\n    name_(name), f_(f) , index_( List().size() )\n    {  std::string msg = \"discrete: first call to the discrete function \";\n        msg  += name;\n        msg  += \" is in parallel mode.\";\n        CPPAD_ASSERT_KNOWN(\n            ! thread_alloc::in_parallel() ,\n            msg.c_str()\n        );\n        List().push_back(this);\n    }\n/*\n ------------------------------------------------------------------------------\n{xrst_begin discrete_ad dev}\nImplement AD Version of a Discrete Function\n###########################################\n\nSyntax\n******\n*ay* = *fun* . ``ad`` ( *ax* )\n\nax\n**\nis the argument for the AD version of this function.\n\nay\n**\nis the return value for the AD version of this function.\n\nPrototype\n*********\n{xrst_spell_off}\n{xrst_code hpp} */\n    AD<Base> ad(const AD<Base> &ax) const\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end discrete_ad}\n*/\n    {\n        CPPAD_ASSERT_KNOWN(\n            size_t( std::numeric_limits<addr_t>::max() ) >= index_,\n            \"discrete: cppad_tape_addr_type maximum not large enough\"\n        );\n        //\n        AD<Base> ay;\n        ay.value_ = f_(ax.value_);\n        //\n        // check if there is a recording in progress\n        local::ADTape<Base>* tape = AD<Base>::tape_ptr();\n        if( tape == nullptr )\n            return ay;\n        //\n        // check if argument is a constant parameter\n        if( ax.tape_id_ != tape->id_ )\n            return ay;\n        //\n        if( ax.ad_type_ == dynamic_enum )\n        {\n            // tape dynamic parameter operation\n            ay.taddr_   = tape->Rec_.put_dyn_par(\n                ay.value_, local::dis_dyn, addr_t(index_), ax.taddr_\n            );\n            ay.tape_id_  = ax.tape_id_;\n            ay.ad_type_  = dynamic_enum;\n\n            // make result a dynamic parameter\n            ay.tape_id_    = tape->id_;\n            ay.ad_type_    = dynamic_enum;\n\n            CPPAD_ASSERT_UNKNOWN( Dynamic(ay) );\n        }\n        else if( ax.ad_type_ == variable_enum )\n        {\n            CPPAD_ASSERT_UNKNOWN( local::NumRes(local::DisOp) == 1 );\n            CPPAD_ASSERT_UNKNOWN( local::NumArg(local::DisOp) == 2 );\n\n            // put operand addresses in the tape\n            CPPAD_ASSERT_KNOWN(\n                size_t( std::numeric_limits<addr_t>::max() ) >= index_,\n                \"discrete: cppad_tape_addr_type maximum not large enough\"\n            );\n            tape->Rec_.PutArg(addr_t(index_), ax.taddr_);\n            // put operator in the tape\n            ay.taddr_ = tape->Rec_.PutOp(local::DisOp);\n            // make result a variable\n            ay.tape_id_    = tape->id_;\n            ay.ad_type_    = variable_enum;\n\n            CPPAD_ASSERT_UNKNOWN( Variable(ay) );\n        }\n        else\n        {  // other types not yet being used and should have this tape id\n            CPPAD_ASSERT_UNKNOWN(false);\n        }\n        return ay;\n    }\n/*\n ------------------------------------------------------------------------------\n{xrst_begin discrete_index dev}\n{xrst_spell\n    msg\n    str\n}\n\nIndex That Identifies a Discrete Function\n#########################################\n{xrst_code hpp} */\nstatic size_t index(const std::string& name)\n{  size_t i = List().size();\n    while(i--)\n    {  if( List()[i]->name_ == name )\n            return i;\n    }\n    std::string msg = \"There is no discrete function named \" + name;\n    CPPAD_ASSERT_KNOWN(false, msg.c_str());\n    return List().size();\n}\n/* {xrst_code}\n\n{xrst_end discrete_index}\n*/\n/*\n------------------------------------------------------------------------------\n{xrst_begin discrete_name dev}\n\nName Corresponding to a discrete Function\n#########################################\n\nSyntax\n******\n``discrete`` < *Base* >:: ``name`` ( *index* )\n\nBase\n****\nIs the :ref:`discrete_create@Base`\ntype for this list of discrete functions.\n\nindex\n*****\nIs the index, in the list, for this discrete function.\n\nSource Code\n***********\n{xrst_spell_off}\n{xrst_code hpp} */\n    static const std::string& name(size_t index)\n    {  return List()[index]->name_; }\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end discrete_name}\n------------------------------------------------------------------------------\n{xrst_begin discrete_eval dev}\nLink From Forward Mode Sweep to Users Routine\n#############################################\n\nSyntax\n******\n*y* = ``discrete`` < *Base* >:: ``eval`` ( *index* , *x* )\n\nBase\n****\nIs the :ref:`discrete_create@Base`\ntype for this list of discrete functions.\n\nindex\n*****\nindex for this function in :ref:`discrete_list-name` .\n\nx\n*\nargument at which to evaluate *Base* version of this function.\n\ny\n*\nresult for the *Base* version of this function.\n\nSource Code\n***********\n{xrst_spell_off}\n{xrst_code hpp} */\n    static Base eval(size_t index, const Base& x)\n    {  CPPAD_ASSERT_UNKNOWN(index < List().size() );\n        return List()[index]->f_(x);\n    }\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end discrete_eval}\n------------------------------------------------------------------------------\n{xrst_begin discrete_ad_eval dev}\nLink From Forward Mode Sweep to AD Version of Discrete Function\n###############################################################\n\nSyntax\n******\n*ay* = ``discrete`` < *Base* >:: ``eval`` ( *index* , *ax* )\n\nBase\n****\nIs the :ref:`discrete_create@Base`\ntype for this list of discrete functions.\n\nindex\n*****\nindex for this function in :ref:`discrete_list-name` .\n\nax\n**\nargument at which to evaluate ``AD`` < *Base* > version of this function.\n\nay\n**\nresult for the ``AD`` < *Base* > version of this function.\n\nSource Code\n***********\n{xrst_spell_off}\n{xrst_code hpp} */\n    static AD<Base> ad_eval(size_t index, const AD<Base>& ax)\n    {  CPPAD_ASSERT_UNKNOWN(index < List().size() );\n        return List()[index]->ad(ax);\n    }\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end discrete_ad_eval}\n*/\n};\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/discrete/user.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n/*\n{xrst_begin Discrete}\n{xrst_spell\n    retaping\n}\n\nDiscrete AD Functions\n#####################\n\nSyntax\n******\n| ``CPPAD_DISCRETE_FUNCTION`` ( *Base* , *name* )\n| *y* = *name* ( *x* )\n| *ay* = *name* ( *ax* )\n\nPurpose\n*******\nRecord the evaluation of a discrete function as part\nof an ``AD`` < *Base* >\n:ref:`operation sequence<glossary@Operation@Sequence>` .\nThe value of a discrete function can depend on the\n:ref:`independent variables<glossary@Tape@Independent Variable>` ,\nbut its derivative is identically zero.\nFor example, suppose that the integer part of\na :ref:`glossary@Variable` *x* is the\nindex into an array of values.\n\nBase\n****\nThis is the\n:ref:`base type<base_require-name>`\ncorresponding to the operations sequence;\ni.e., use of the *name* with arguments of type\n``AD`` < *Base* > can be recorded in an operation sequence.\n\nname\n****\nThis is the name of the function (as it is used in the source code).\nThe user must provide a version of *name*\nwhere the argument has type *Base* .\nCppAD uses this to create a version of *name*\nwhere the argument has type ``AD`` < *Base* > .\n\nx\n*\nThe argument *x* has prototype\n\n    ``const`` *Base* & *x*\n\nIt is the value at which the user provided version of *name*\nis to be evaluated.\n\ny\n*\nThe result *y* has prototype\n\n    *Base* *y*\n\nIt is the return value for the user provided version of *name* .\n\nax\n**\nThe argument *ax* has prototype\n\n    ``const AD`` < *Base* >& *ax*\n\nIt is the value at which the CppAD provided version of *name*\nis to be evaluated.\n\nay\n**\nThe result *ay* has prototype\n\n    ``AD`` < *Base* > *ay*\n\nIt is the return value for the CppAD provided version of *name* .\n\nCreate AD Version\n*****************\nThe preprocessor macro invocation\n\n    ``CPPAD_DISCRETE_FUNCTION`` ( *Base* , *name* )\n\ndefines the ``AD`` < *Base* > version of *name* .\nThis can be with in a namespace (not the ``CppAD`` namespace)\nbut must be outside of any routine.\n\nOperation Sequence\n******************\nThis is an AD of *Base*\n:ref:`atomic operation<glossary@Operation@Atomic>`\nand hence is part of the current\nAD of *Base*\n:ref:`operation sequence<glossary@Operation@Sequence>` .\n\nDerivatives\n***********\nDuring a zero order :ref:`Forward-name` operation,\nan :ref:`ADFun-name` object will compute the value of *name*\nusing the user provided *Base* version of this routine.\nAll the derivatives of *name* will be evaluated as zero.\n\nParallel Mode\n*************\nThe first call to\n\n    *name* ( *ax* )\n\nmust not be in :ref:`parallel<ta_in_parallel-name>` execution mode.\n\nExample\n*******\n{xrst_toc_hidden\n    example/general/tape_index.cpp\n    example/general/interp_onetape.cpp\n    example/general/interp_retape.cpp\n}\nThe file\n:ref:`tape_index.cpp-name`\ncontains an example and test that uses a discrete function\nto vary an array index during :ref:`Forward-name` mode calculations.\nThe file\n:ref:`interp_onetape.cpp-name`\ncontains an example and test that uses discrete\nfunctions to avoid retaping a calculation that requires interpolation.\n(The file\n:ref:`interp_retape.cpp-name`\nshows how interpolation can be done with retaping.)\n\nCppADCreateDiscrete Deprecated 2007-07-28\n*****************************************\nThe preprocessor symbol ``CppADCreateDiscrete``\nis defined to be the same as ``CPPAD_DISCRETE_FUNCTION``\nbut its use is deprecated.\n\n{xrst_end Discrete}\n"
  },
  {
    "path": "include/cppad/core/div.hpp",
    "content": "# ifndef CPPAD_CORE_DIV_HPP\n# define CPPAD_CORE_DIV_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n//  BEGIN CppAD namespace\nnamespace CppAD {\n\ntemplate <class Base>\nAD<Base> operator / (const AD<Base> &left , const AD<Base> &right)\n{\n    // compute the Base part\n    AD<Base> result;\n    result.value_  = left.value_ / right.value_;\n    CPPAD_ASSERT_UNKNOWN( Parameter(result) );\n\n    // check if there is a recording in progress\n    local::ADTape<Base>* tape = AD<Base>::tape_ptr();\n    if( tape == nullptr )\n        return result;\n    tape_id_t tape_id = tape->id_;\n    // tape_id cannot match the default value for tape_id_; i.e., 0\n    CPPAD_ASSERT_UNKNOWN( tape_id > 0 );\n\n    // check if left and right tapes match\n    bool match_left  = left.tape_id_  == tape_id;\n    bool match_right = right.tape_id_ == tape_id;\n\n    // check if left and right are dynamic parameters\n    bool dyn_left  = match_left  & (left.ad_type_ == dynamic_enum);\n    bool dyn_right = match_right & (right.ad_type_ == dynamic_enum);\n\n    // check if left and right are variables\n    bool var_left  = match_left  & (left.ad_type_ != dynamic_enum);\n    bool var_right = match_right & (right.ad_type_ != dynamic_enum);\n\n    CPPAD_ASSERT_KNOWN(\n        left.tape_id_ == right.tape_id_ || ! match_left || ! match_right ,\n        \"Divide: AD variables or dynamic parameters on different threads.\"\n    );\n    if( var_left )\n    {   if( var_right )\n        {   // result = variable / variable\n            CPPAD_ASSERT_UNKNOWN( local::NumRes(local::DivvvOp) == 1 );\n            CPPAD_ASSERT_UNKNOWN( local::NumArg(local::DivvvOp) == 2 );\n\n            // put operand addresses in tape\n            tape->Rec_.PutArg(left.taddr_, right.taddr_);\n            // put operator in the tape\n            result.taddr_ = tape->Rec_.PutOp(local::DivvvOp);\n            // make result a variable\n            result.tape_id_ = tape_id;\n            result.ad_type_ = variable_enum;\n        }\n        else if( (! dyn_right) && IdenticalOne(right.value_) )\n        {   // result = variable / 1\n            result.make_variable(left.tape_id_, left.taddr_);\n        }\n        else\n        {   // result = variable / parameter\n            CPPAD_ASSERT_UNKNOWN( local::NumRes(local::DivvpOp) == 1 );\n            CPPAD_ASSERT_UNKNOWN( local::NumArg(local::DivvpOp) == 2 );\n\n            // put operand addresses in tape\n            addr_t p = right.taddr_;\n            if( ! dyn_right )\n                p = tape->Rec_.put_con_par(right.value_);\n            tape->Rec_.PutArg(left.taddr_, p);\n            // put operator in the tape\n            result.taddr_ = tape->Rec_.PutOp(local::DivvpOp);\n            // make result a variable\n            result.tape_id_ = tape_id;\n            result.ad_type_ = variable_enum;\n        }\n    }\n    else if( var_right )\n    {   if( (! dyn_left) && IdenticalZero(left.value_) )\n        {   // result = 0 / variable\n            result.value_ = Base(0.0); // incase right.value_ is zero or nan\n        }\n        else\n        {   // result = parameter / variable\n            CPPAD_ASSERT_UNKNOWN( local::NumRes(local::DivpvOp) == 1 );\n            CPPAD_ASSERT_UNKNOWN( local::NumArg(local::DivpvOp) == 2 );\n\n            // put operand addresses in tape\n            addr_t p = left.taddr_;\n            if( ! dyn_left )\n                p = tape->Rec_.put_con_par(left.value_);\n            tape->Rec_.PutArg(p, right.taddr_);\n            // put operator in the tape\n            result.taddr_ = tape->Rec_.PutOp(local::DivpvOp);\n            // make result a variable\n            result.tape_id_ = tape_id;\n            result.ad_type_ = variable_enum;\n        }\n    }\n    else if( dyn_left | dyn_right )\n    {   if ( (!dyn_left) && IdenticalZero(left.value_))\n        {   // 0 / dynamic\n            result.value_ = Base(0.0);\n        } else if( (!dyn_right) && IdenticalOne(right.value_))\n        {   // dynamic / 1\n            result.make_dynamic(left.tape_id_, left.taddr_);\n        } else\n        {\n            addr_t arg0 = left.taddr_;\n            addr_t arg1 = right.taddr_;\n            if( ! dyn_left )\n            arg0 = tape->Rec_.put_con_par(left.value_);\n            if( ! dyn_right )\n            arg1 = tape->Rec_.put_con_par(right.value_);\n            //\n            // parameters with a dynamic parameter result\n            result.taddr_   = tape->Rec_.put_dyn_par(\n                result.value_, local::div_dyn,   arg0, arg1\n            );\n            result.tape_id_ = tape_id;\n            result.ad_type_ = dynamic_enum;\n        }\n    }\n    return result;\n}\n\n// convert other cases into the case above\nCPPAD_FOLD_AD_VALUED_BINARY_OPERATOR(/)\n\n\n} // END CppAD namespace\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/div_eq.hpp",
    "content": "# ifndef CPPAD_CORE_DIV_EQ_HPP\n# define CPPAD_CORE_DIV_EQ_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n//  BEGIN CppAD namespace\nnamespace CppAD {\n\ntemplate <class Base>\nAD<Base>& AD<Base>::operator /= (const AD<Base> &right)\n{\n    // compute the Base part\n    Base left;\n    left    = value_;\n    value_ /= right.value_;\n\n    // check if there is a recording in progress\n    local::ADTape<Base>* tape = AD<Base>::tape_ptr();\n    if( tape == nullptr )\n        return *this;\n    tape_id_t tape_id = tape->id_;\n    // tape_id cannot match the default value for tape_id_; i.e., 0\n    CPPAD_ASSERT_UNKNOWN( tape_id > 0 );\n\n    // check if left and right tapes match\n    bool match_left  = tape_id_       == tape_id;\n    bool match_right = right.tape_id_ == tape_id;\n\n    // check if left and right are dynamic parameters\n    bool dyn_left  = match_left  & (ad_type_ == dynamic_enum);\n    bool dyn_right = match_right & (right.ad_type_ == dynamic_enum);\n\n    // check if left and right are variables\n    bool var_left  = match_left  & (ad_type_ != dynamic_enum);\n    bool var_right = match_right & (right.ad_type_ != dynamic_enum);\n\n    CPPAD_ASSERT_KNOWN(\n        tape_id_ == right.tape_id_ || ! match_left || ! match_right ,\n        \"/= : AD variables or dynamic parameters on different threads.\"\n    );\n    if( var_left )\n    {   if( var_right )\n        {   // this = variable / variable\n            CPPAD_ASSERT_UNKNOWN( local::NumRes(local::DivvvOp) == 1 );\n            CPPAD_ASSERT_UNKNOWN( local::NumArg(local::DivvvOp) == 2 );\n\n            // put operand addresses in tape\n            tape->Rec_.PutArg(taddr_, right.taddr_);\n            // put operator in the tape\n            taddr_ = tape->Rec_.PutOp(local::DivvvOp);\n            // check that this is a variable\n            CPPAD_ASSERT_UNKNOWN( tape_id_ == tape_id );\n            CPPAD_ASSERT_UNKNOWN( ad_type_ == variable_enum);\n        }\n        else if( (! dyn_right) && IdenticalOne(right.value_) )\n        {   // this = variable * 1\n        }\n        else\n        {   // this = variable / parameter\n            CPPAD_ASSERT_UNKNOWN( local::NumRes(local::DivvpOp) == 1 );\n            CPPAD_ASSERT_UNKNOWN( local::NumArg(local::DivvpOp) == 2 );\n\n            // put operand addresses in tape\n            addr_t p = right.taddr_;\n            if( ! dyn_right )\n                p = tape->Rec_.put_con_par(right.value_);\n            tape->Rec_.PutArg(taddr_, p);\n            // put operator in the tape\n            taddr_ = tape->Rec_.PutOp(local::DivvpOp);\n            // check that this is a variable\n            CPPAD_ASSERT_UNKNOWN( tape_id_ == tape_id );\n            CPPAD_ASSERT_UNKNOWN( ad_type_ == variable_enum);\n        }\n    }\n    else if( var_right  )\n    {   if( (! dyn_left) && IdenticalZero(left) )\n        {   // this = 0 / variable\n        }\n        else\n        {   // this = parameter / variable\n            CPPAD_ASSERT_UNKNOWN( local::NumRes(local::DivpvOp) == 1 );\n            CPPAD_ASSERT_UNKNOWN( local::NumArg(local::DivpvOp) == 2 );\n\n            // put operand addresses in tape\n            addr_t p = taddr_;\n            if( ! dyn_left )\n                p = tape->Rec_.put_con_par(left);\n            tape->Rec_.PutArg(p, right.taddr_);\n\n            // put operator in the tape\n            taddr_ = tape->Rec_.PutOp(local::DivpvOp);\n\n            // make this a variable\n            tape_id_ = tape_id;\n            ad_type_ = variable_enum;\n        }\n    }\n    else if( dyn_left | dyn_right )\n    {   if( (!dyn_right) && IdenticalOne(right.value_))\n        {   // dynamic /= 1, so do nothing\n        } else if( (!dyn_left) && IdenticalZero(left))\n        {   // 0 /= dynamic, so do nothing\n        } else\n        {\n            addr_t arg0 = taddr_;\n            addr_t arg1 = right.taddr_;\n            if( ! dyn_left )\n            arg0 = tape->Rec_.put_con_par(left);\n            if( ! dyn_right )\n            arg1 = tape->Rec_.put_con_par(right.value_);\n            //\n            // parameters with a dynamic parameter results\n            taddr_ = tape->Rec_.put_dyn_par(\n                value_, local::div_dyn, arg0, arg1\n            );\n            tape_id_ = tape_id;\n            ad_type_ = dynamic_enum;\n        }\n    }\n    return *this;\n}\n\nCPPAD_FOLD_ASSIGNMENT_OPERATOR(/=)\n\n} // END CppAD namespace\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/drivers.hpp",
    "content": "# ifndef CPPAD_CORE_DRIVERS_HPP\n# define CPPAD_CORE_DRIVERS_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/core/jacobian.hpp>\n# include <cppad/core/hessian.hpp>\n# include <cppad/core/for_one.hpp>\n# include <cppad/core/rev_one.hpp>\n# include <cppad/core/for_two.hpp>\n# include <cppad/core/rev_two.hpp>\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/epsilon.hpp",
    "content": "# ifndef CPPAD_CORE_EPSILON_HPP\n# define CPPAD_CORE_EPSILON_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n------------------------------------------------------------------------------\n{xrst_begin epsilon app}\n{xrst_spell\n    eps\n}\n\nMachine Epsilon For AD Types\n############################\n\nDeprecated 2012-06-17\n*********************\nThis routine has been deprecated.\nYou should use the :ref:`numeric_limits-name` ``epsilon`` instead.\n\nSyntax\n******\n| *eps* = ``epsilon`` < *Float* >()\n\nPurpose\n*******\nObtain the value of machine epsilon corresponding\nto the type *Float* .\n\nFloat\n*****\nthis type can either be ``AD`` < *Base* > ,\nor it can be *Base* for any ``AD`` < *Base* > type.\n\neps\n***\nThe result *eps* has prototype\n\n    *Float* ``eps``\n\n{xrst_end epsilon}\n------------------------------------------------------------------------------\n*/\n\nnamespace CppAD {\n\n    template <class Type>\n    inline Type epsilon(void)\n    {   return Type ( numeric_limits<Type>::epsilon() ); }\n\n}\n# endif\n"
  },
  {
    "path": "include/cppad/core/equal_op_seq.hpp",
    "content": "# ifndef CPPAD_CORE_EQUAL_OP_SEQ_HPP\n# define CPPAD_CORE_EQUAL_OP_SEQ_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n------------------------------------------------------------------------------\n{xrst_begin EqualOpSeq}\n\nCheck if Two Value are Identically Equal\n########################################\n\nSyntax\n******\n| *b* = ``EqualOpSeq`` ( *x* , *y* )\n\nPurpose\n*******\nDetermine if two *x* and *y* are identically equal; i.e.,\nnot only is *x* == *y* true, but\nif they are :ref:`variables<glossary@Variable>` ,\nthey correspond have the same\n:ref:`operation sequence<glossary@Operation@Sequence>` .\n\nMotivation\n**********\nSometimes it is useful to cache information\nand only recalculate when a function's arguments change.\nIn the case of AD variables,\nit may be important not only when the argument values are equal,\nbut when they are related to the\n:ref:`independent variables<glossary@Tape@Independent Variable>`\nby the same operation sequence.\nAfter the assignment\n\n    *y* = *x*\n\nthese two AD objects would not only have equal values,\nbut would also correspond to the same operation sequence.\n\nx\n*\nThe argument *x* has prototype\n\n    ``const AD`` < *Base* > & *x*\n\ny\n*\nThe argument *y* has prototype\n\n    ``const AD`` < *Base* > & *y*\n\nb\n*\nThe result *b* has prototype\n\n    ``bool`` *b*\n\nThe result is true if and only if one of the following cases holds:\n\n#. Both *x* and *y* are variables\n   and correspond to the same operation sequence.\n#. Both *x* and *y* are parameters,\n   *Base* is an AD type,\n   and ``EqualOpSeq`` ( ``Value`` ( *x* ) , ``Value`` ( *y* ) ) is true.\n#. Both *x* and *y* are parameters,\n   *Base* is not an AD type,\n   and *x* == *y* is true.\n\nExample\n*******\n{xrst_toc_hidden\n    example/general/equal_op_seq.cpp\n}\nThe file\n:ref:`equal_op_seq.cpp-name`\ncontains an example and test of ``EqualOpSeq`` .\n\n{xrst_end EqualOpSeq}\n------------------------------------------------------------------------------\n*/\n\n\nnamespace CppAD {\n    template <class Base>\n    CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION\n    bool EqualOpSeq(const AD<Base> &x, const AD<Base> &y)\n    {\n        if( Parameter(x) )\n        {   if( Parameter(y) )\n                return EqualOpSeq(x.value_, y.value_);\n            else\n                return false;\n        }\n        else if( Parameter(y) )\n            return false;\n\n        return (x.taddr_ == y.taddr_);\n    }\n\n}\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/for_hes_sparsity.hpp",
    "content": "# ifndef CPPAD_CORE_FOR_HES_SPARSITY_HPP\n# define CPPAD_CORE_FOR_HES_SPARSITY_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin for_hes_sparsity}\n{xrst_spell\n    rc\n    walther\n}\n\nForward Mode Hessian Sparsity Patterns\n######################################\n\nSyntax\n******\n| *f* . ``for_hes_sparsity`` (\n| |tab| *select_domain* , *select_range* , *internal_bool* , *pattern_out*\n| )\n\nPurpose\n*******\nWe use :math:`F : \\B{R}^n \\rightarrow \\B{R}^m` to denote the\n:ref:`glossary@AD Function` corresponding to\nthe operation sequence stored in *f* .\nFix a diagonal matrix :math:`D \\in \\B{R}^{n \\times n}`,\na vector :math:`s \\in \\B{R}^m` and define the function\n\n.. math::\n\n    H(x) = D ( s^\\R{T} F )^{(2)} ( x ) D\n\nGiven  the sparsity for :math:`D` and :math:`s`,\n``for_hes_sparsity`` computes a sparsity pattern for :math:`H(x)`.\n\nx\n*\nNote that the sparsity pattern :math:`H(x)` corresponds to the\noperation sequence stored in *f* and does not depend on\nthe argument *x* .\n\nBoolVector\n**********\nThe type *BoolVector* is a :ref:`SimpleVector-name` class with\n:ref:`elements of type<SimpleVector@Elements of Specified Type>`\n``bool`` .\n\nSizeVector\n**********\nThe type *SizeVector* is a :ref:`SimpleVector-name` class with\n:ref:`elements of type<SimpleVector@Elements of Specified Type>`\n``size_t`` .\n\nf\n*\nThe object *f* has prototype\n\n    ``ADFun`` < *Base* > *f*\n\nselect_domain\n*************\nThe argument *select_domain* has prototype\n\n    ``const`` *BoolVector* & *select_domain*\n\nIt has size :math:`n` and specifies which components of the diagonal of\n:math:`D` are non-zero; i.e., *select_domain* [ *j* ] is true\nif and only if :math:`D_{j,j}` is possibly non-zero.\n\nselect_range\n************\nThe argument *select_range* has prototype\n\n    ``const`` *BoolVector* & *select_range*\n\nIt has size :math:`m` and specifies which components of the vector\n:math:`s` are non-zero; i.e., *select_range* [ *i* ] is true\nif and only if :math:`s_i` is possibly non-zero.\n\ninternal_bool\n*************\nIf this is true, calculations are done with sets represented by a vector\nof boolean values. Otherwise, a vector of sets of integers is used.\n\npattern_out\n***********\nThis argument has prototype\n\n    ``sparse_rc`` < *SizeVector* >& *pattern_out*\n\nThis input value of *pattern_out* does not matter.\nUpon return *pattern_out* is a sparsity pattern for :math:`H(x)`.\n\nSparsity for Entire Hessian\n***************************\nSuppose that :math:`D` is the :math:`n \\times n` identity matrix.\nIn this case, *pattern_out* is a sparsity pattern for\n:math:`(s^\\R{T} F) F^{(2)} ( x )`.\n\nAlgorithm\n*********\nSee Algorithm II in\n*Computing sparse Hessians with automatic differentiation*\nby Andrea Walther.\nNote that *s* provides the information so that\n'dead ends' are not included in the sparsity pattern.\n\nExample\n*******\n{xrst_toc_hidden\n    example/sparse/for_hes_sparsity.cpp\n}\nThe file :ref:`for_hes_sparsity.cpp-name`\ncontains an example and test of this operation.\n\n{xrst_end for_hes_sparsity}\n-----------------------------------------------------------------------------\n*/\n# include <cppad/core/ad_fun.hpp>\n# include <cppad/local/sparse/internal.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n\n/*!\nForward Hessian sparsity patterns.\n\n\\tparam Base\nis the base type for this recording.\n\n\\tparam BoolVector\nis the simple vector with elements of type bool that is used for\nsparsity for the vector s.\n\n\\tparam SizeVector\nis the simple vector with elements of type size_t that is used for\nrow, column index sparsity patterns.\n\n\\param select_domain\nis a sparsity pattern for for the diagonal of D.\n\n\\param select_range\nis a sparsity pattern for for s.\n\n\\param internal_bool\nIf this is true, calculations are done with sets represented by a vector\nof boolean values. Otherwise, a vector of standard sets is used.\n\n\\param pattern_out\nThe return value is a sparsity pattern for H(x) where\n\\f[\n    H(x) = D * F^{(1)} (x) * D\n\\f]\nHere F is the function corresponding to the operation sequence\nand x is any argument value.\n*/\ntemplate <class Base, class RecBase>\ntemplate <class BoolVector, class SizeVector>\nvoid ADFun<Base,RecBase>::for_hes_sparsity(\n    const BoolVector&            select_domain    ,\n    const BoolVector&            select_range     ,\n    bool                         internal_bool    ,\n    sparse_rc<SizeVector>&       pattern_out      )\n{\n    // used to identify the RecBase type in calls to sweeps\n    RecBase not_used_rec_base(0.0);\n    //\n    size_t n  = Domain();\n    size_t m  = Range();\n    //\n    CPPAD_ASSERT_KNOWN(\n        size_t( select_domain.size() ) == n,\n        \"for_hes_sparsity: size of select_domain is not equal to \"\n        \"number of independent variables\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t( select_range.size() ) == m,\n        \"for_hes_sparsity: size of select_range is not equal to \"\n        \"number of dependent variables\"\n    );\n    // do not need transpose or dependency\n    bool transpose  = false;\n    bool dependency = false;\n    //\n    local::pod_vector<bool> select_domain_pod_vector(n);\n    for(size_t j = 0; j < n; ++j)\n        select_domain_pod_vector[j] = select_domain[j];\n    //\n    sparse_rc<SizeVector> pattern_tmp;\n    if( internal_bool )\n    {\n        // reverse Jacobian sparsity pattern for select_range\n        local::sparse::pack_setvec internal_rev_jac;\n        internal_rev_jac.resize(num_var_tape_, 1);\n        for(size_t i = 0; i < m; i++) if( select_range[i] )\n        {   CPPAD_ASSERT_UNKNOWN( dep_taddr_[i] < num_var_tape_ );\n            // Not using post_element because only adding one element per set\n            internal_rev_jac.add_element( dep_taddr_[i] , 0 );\n        }\n        // reverse Jacobian sparsity for all variables on tape\n        local::sweep::rev_jac(\n            &play_,\n            dependency,\n            n,\n            num_var_tape_,\n            internal_rev_jac,\n            not_used_rec_base\n        );\n        // internal vector of sets that will hold Hessian\n        local::sparse::pack_setvec internal_for_hes;\n        internal_for_hes.resize(n + 1 + num_var_tape_, n + 1);\n        //\n        // compute forward Hessian sparsity pattern\n        local::sweep::for_hes(\n            &play_,\n            n,\n            num_var_tape_,\n            select_domain_pod_vector,\n            internal_rev_jac,\n            internal_for_hes,\n            not_used_rec_base\n        );\n        //\n        // put the result in pattern_tmp\n        local::sparse::get_internal_pattern(\n            transpose, ind_taddr_, internal_for_hes, pattern_tmp\n        );\n    }\n    else\n    {\n        // reverse Jacobian sparsity pattern for select_range\n        // (corresponds to s)\n        local::sparse::list_setvec internal_rev_jac;\n        internal_rev_jac.resize(num_var_tape_, 1);\n        for(size_t i = 0; i < m; i++) if( select_range[i] )\n        {   CPPAD_ASSERT_UNKNOWN( dep_taddr_[i] < num_var_tape_ );\n            // Not using post_element because only adding one element per set\n            internal_rev_jac.add_element( dep_taddr_[i] , 0 );\n        }\n        // reverse Jacobian sparsity for all variables on tape\n        local::sweep::rev_jac(\n            &play_,\n            dependency,\n            n,\n            num_var_tape_,\n            internal_rev_jac,\n            not_used_rec_base\n\n        );\n        // internal vector of sets that will hold Hessian\n        local::sparse::list_setvec internal_for_hes;\n        internal_for_hes.resize(n + 1 + num_var_tape_, n + 1);\n        //\n        // compute forward Hessian sparsity pattern\n        local::sweep::for_hes(\n            &play_,\n            n,\n            num_var_tape_,\n            select_domain_pod_vector,\n            internal_rev_jac,\n            internal_for_hes,\n            not_used_rec_base\n        );\n        //\n        // put the result in pattern_tmp\n        local::sparse::get_internal_pattern(\n            transpose, ind_taddr_, internal_for_hes, pattern_tmp\n        );\n    }\n    // subtract 1 from all column values\n    CPPAD_ASSERT_UNKNOWN( pattern_tmp.nr() == n );\n    CPPAD_ASSERT_UNKNOWN( pattern_tmp.nc() == n + 1 );\n    const SizeVector& row( pattern_tmp.row() );\n    const SizeVector& col( pattern_tmp.col() );\n    size_t nr   = n;\n    size_t nc   = n;\n    size_t nnz  = pattern_tmp.nnz();\n    pattern_out.resize(nr, nc, nnz);\n    for(size_t k = 0; k < nnz; k++)\n    {   CPPAD_ASSERT_UNKNOWN( 0 < col[k] );\n        pattern_out.set(k, row[k], col[k] - 1);\n    }\n    return;\n}\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/for_jac_sparsity.hpp",
    "content": "# ifndef CPPAD_CORE_FOR_JAC_SPARSITY_HPP\n# define CPPAD_CORE_FOR_JAC_SPARSITY_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin for_jac_sparsity}\n\nForward Mode Jacobian Sparsity Patterns\n#######################################\n\nSyntax\n******\n| *f* . ``for_jac_sparsity`` (\n| |tab| *pattern_in* , *transpose* , *dependency* , *internal_bool* , *pattern_out*\n| )\n\nPurpose\n*******\nWe use :math:`F : \\B{R}^n \\rightarrow \\B{R}^m` to denote the\n:ref:`glossary@AD Function` corresponding to\nthe operation sequence stored in *f* .\nFix :math:`R \\in \\B{R}^{n \\times \\ell}` and define the function\n\n.. math::\n\n    J(x) = F^{(1)} ( x ) * R\n\nGiven the :ref:`glossary@Sparsity Pattern` for :math:`R`,\n``for_jac_sparsity`` computes a sparsity pattern for :math:`J(x)`.\n\nx\n*\nNote that the sparsity pattern :math:`J(x)` corresponds to the\noperation sequence stored in *f* and does not depend on\nthe argument *x* .\n(The operation sequence may contain\n:ref:`CondExp-name` and  :ref:`VecAD-name` operations.)\n\nSizeVector\n**********\nThe type *SizeVector* is a :ref:`SimpleVector-name` class with\n:ref:`elements of type<SimpleVector@Elements of Specified Type>`\n``size_t`` .\n\nf\n*\nThe object *f* has prototype\n\n    ``ADFun`` < *Base* > *f*\n\nThe :ref:`ADFun-name` object *f* is not ``const`` .\nAfter a call to ``for_jac_sparsity`` , a sparsity pattern\nfor each of the variables in the operation sequence\nis held in *f* for possible later use during\nreverse Hessian sparsity calculations.\n\nsize_forward_bool\n=================\nAfter ``for_jac_sparsity`` , if *k* is a ``size_t`` object,\n\n    *k* = *f* . ``size_forward_bool`` ()\n\nsets *k* to the amount of memory (in unsigned character units)\nused to store the\n:ref:`glossary@Sparsity Pattern@Boolean Vector`\nsparsity patterns.\nIf *internal_bool* if false, *k* will be zero.\nOtherwise it will be non-zero.\nIf you do not need this information for :ref:`RevSparseHes-name`\ncalculations, it can be deleted\n(and the corresponding memory freed) using\n\n    *f* . ``size_forward_bool`` (0)\n\nafter which *f* . ``size_forward_bool`` () will return zero.\n\nsize_forward_set\n================\nAfter ``for_jac_sparsity`` , if *k* is a ``size_t`` object,\n\n    *k* = *f* . ``size_forward_set`` ()\n\nsets *k* to the amount of memory (in unsigned character units)\nused to store the\n:ref:`glossary@Sparsity Pattern@Vector of Sets`\nsparsity patterns.\nIf *internal_bool* if true, *k* will be zero.\nOtherwise it will be non-zero.\nIf you do not need this information for future :ref:`rev_hes_sparsity-name`\ncalculations, it can be deleted\n(and the corresponding memory freed) using\n\n    *f* . ``size_forward_set`` (0)\n\nafter which *f* . ``size_forward_set`` () will return zero.\n\npattern_in\n**********\nThe argument *pattern_in* has prototype\n\n    ``const sparse_rc`` < *SizeVector* >& *pattern_in*\n\nsee :ref:`sparse_rc-name` .\nIf *transpose* it is false (true),\n*pattern_in* is a sparsity pattern for :math:`R` (:math:`R^\\R{T}`).\n\ntranspose\n*********\nThis argument has prototype\n\n    ``bool`` *transpose*\n\nSee :ref:`for_jac_sparsity@pattern_in` above and\n:ref:`for_jac_sparsity@pattern_out` below.\n\ndependency\n**********\nThis argument has prototype\n\n    ``bool`` *dependency*\n\nsee :ref:`for_jac_sparsity@pattern_out` below.\n\ninternal_bool\n*************\nThis argument has prototype\n\n    ``bool`` *internal_bool*\n\nIf this is true, calculations are done with sets represented by a vector\nof boolean values. Otherwise, a vector of sets of integers is used.\n\npattern_out\n***********\nThis argument has prototype\n\n    ``sparse_rc`` < *SizeVector* >& *pattern_out*\n\nThis input value of *pattern_out* does not matter.\nIf *transpose* it is false (true),\nupon return *pattern_out* is a sparsity pattern for\n:math:`J(x)` (:math:`J(x)^\\R{T}`).\nIf *dependency* is true, *pattern_out* is a\n:ref:`dependency.cpp@Dependency Pattern`\ninstead of sparsity pattern.\n\nSparsity for Entire Jacobian\n****************************\nSuppose that\n:math:`R` is the :math:`n \\times n` identity matrix.\nIn this case, *pattern_out* is a sparsity pattern for\n:math:`F^{(1)} ( x )`  ( :math:`F^{(1)} (x)^\\R{T}` )\nif *transpose* is false (true).\n\nExample\n*******\n{xrst_toc_hidden\n    example/sparse/for_jac_sparsity.cpp\n}\nThe file\n:ref:`for_jac_sparsity.cpp-name`\ncontains an example and test of this operation.\n\n{xrst_end for_jac_sparsity}\n-----------------------------------------------------------------------------\n*/\n# include <cppad/core/ad_fun.hpp>\n# include <cppad/local/sparse/internal.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n\n/*!\nForward Jacobian sparsity patterns.\n\n\\tparam Base\nis the base type for this recording.\n\n\\tparam SizeVector\nis the simple vector with elements of type size_t that is used for\nrow, column index sparsity patterns.\n\n\\param pattern_in\nis the sparsity pattern for for R or R^T depending on transpose.\n\n\\param transpose\nIs the input and returned sparsity pattern transposed.\n\n\\param dependency\nAre the derivatives with respect to left and right of the expression below\nconsidered to be non-zero:\n\\code\n    CondExpRel(left, right, if_true, if_false)\n\\endcode\nThis is used by the optimizer to obtain the correct dependency relations.\n\n\\param internal_bool\nIf this is true, calculations are done with sets represented by a vector\nof boolean values. Otherwise, a vector of standard sets is used.\n\n\\param pattern_out\nThe value of transpose is false (true),\nthe return value is a sparsity pattern for J(x) ( J(x)^T ) where\n\\f[\n    J(x) = F^{(1)} (x) * R\n\\f]\nHere F is the function corresponding to the operation sequence\nand x is any argument value.\n*/\ntemplate <class Base, class RecBase>\ntemplate <class SizeVector>\nvoid ADFun<Base,RecBase>::for_jac_sparsity(\n    const sparse_rc<SizeVector>& pattern_in       ,\n    bool                         transpose        ,\n    bool                         dependency       ,\n    bool                         internal_bool    ,\n    sparse_rc<SizeVector>&       pattern_out      )\n{\n    // used to identify the RecBase type in calls to sweeps\n    RecBase not_used_rec_base(0.0);\n    //\n    // number or rows, columns, and non-zeros in pattern_in\n    size_t nr_in  = pattern_in.nr();\n    size_t nc_in  = pattern_in.nc();\n    //\n    size_t n   = nr_in;\n    size_t ell = nc_in;\n    if( transpose )\n        std::swap(n, ell);\n    //\n    CPPAD_ASSERT_KNOWN(\n        n == Domain() ,\n        \"for_jac_sparsity: number rows in R \"\n        \"is not equal number of independent variables.\"\n    );\n    bool zero_empty  = true;\n    bool input_empty = true;\n    if( internal_bool )\n    {   // allocate memory for bool sparsity calculation\n        // (sparsity pattern is empty after a resize)\n        for_jac_sparse_pack_.resize(num_var_tape_, ell);\n        for_jac_sparse_set_.resize(0, 0);\n        //\n        // set sparsity pattern for independent variables\n        local::sparse::set_internal_pattern(\n            zero_empty            ,\n            input_empty           ,\n            transpose             ,\n            ind_taddr_            ,\n            for_jac_sparse_pack_  ,\n            pattern_in\n        );\n\n        // compute sparsity for other variables\n        local::sweep::for_jac(\n            &play_,\n            dependency,\n            n,\n            num_var_tape_,\n            for_jac_sparse_pack_,\n            not_used_rec_base\n\n        );\n        // set the output pattern\n        local::sparse::get_internal_pattern(\n            transpose, dep_taddr_, for_jac_sparse_pack_, pattern_out\n        );\n    }\n    else\n    {\n        // allocate memory for set sparsity calculation\n        // (sparsity pattern is empty after a resize)\n        for_jac_sparse_set_.resize(num_var_tape_, ell);\n        for_jac_sparse_pack_.resize(0, 0);\n        //\n        // set sparsity pattern for independent variables\n        local::sparse::set_internal_pattern(\n            zero_empty            ,\n            input_empty           ,\n            transpose             ,\n            ind_taddr_            ,\n            for_jac_sparse_set_   ,\n            pattern_in\n        );\n\n        // compute sparsity for other variables\n        local::sweep::for_jac(\n            &play_,\n            dependency,\n            n,\n            num_var_tape_,\n            for_jac_sparse_set_,\n            not_used_rec_base\n\n        );\n        // get the output pattern\n        local::sparse::get_internal_pattern(\n            transpose, dep_taddr_, for_jac_sparse_set_, pattern_out\n        );\n    }\n    return;\n}\n\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/for_one.hpp",
    "content": "# ifndef CPPAD_CORE_FOR_ONE_HPP\n# define CPPAD_CORE_FOR_ONE_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin ForOne}\n\nFirst Order Partial Derivative: Driver Routine\n##############################################\n\nSyntax\n******\n| *dy* = *f* . ``ForOne`` ( *x* , *j* )\n\nPurpose\n*******\nWe use :math:`F : \\B{R}^n \\rightarrow \\B{R}^m` to denote the\n:ref:`glossary@AD Function` corresponding to *f* .\nThe syntax above sets *dy* to the\npartial of :math:`F` with respect to :math:`x_j`; i.e.,\n\n.. math::\n\n    dy\n    = \\D{F}{ x_j } (x)\n    = \\left[\n        \\D{ F_0 }{ x_j } (x) , \\cdots , \\D{ F_{m-1} }{ x_j } (x)\n    \\right]\n\nf\n*\nThe object *f* has prototype\n\n    ``ADFun`` < *Base* > *f*\n\nNote that the :ref:`ADFun-name` object *f* is not ``const``\n(see :ref:`ForOne@ForOne Uses Forward` below).\n\nx\n*\nThe argument *x* has prototype\n\n    ``const`` *Vector* & *x*\n\n(see :ref:`ForOne@Vector` below)\nand its size\nmust be equal to *n* , the dimension of the\n:ref:`fun_property@Domain` space for *f* .\nIt specifies\nthat point at which to evaluate the partial derivative.\n\nj\n*\nThe argument *j* has prototype\n\n    ``size_t`` *j*\n\nan is less than *n* ,\n:ref:`fun_property@Domain` space for *f* .\nIt specifies the component of *F*\nfor which we are computing the partial derivative.\n\ndy\n**\nThe result *dy* has prototype\n\n    *Vector* *dy*\n\n(see :ref:`ForOne@Vector` below)\nand its size is :math:`m`, the dimension of the\n:ref:`fun_property@Range` space for *f* .\nThe value of *dy* is the partial of :math:`F` with respect to\n:math:`x_j` evaluated at *x* ; i.e.,\nfor :math:`i = 0 , \\ldots , m - 1`\n\n.. math::\n\n    dy[i] = \\D{ F_i }{ x_j } ( x )\n\nVector\n******\nThe type *Vector* must be a :ref:`SimpleVector-name` class with\n:ref:`elements of type<SimpleVector@Elements of Specified Type>`\n*Base* .\nThe routine :ref:`CheckSimpleVector-name` will generate an error message\nif this is not the case.\n\nForOne Uses Forward\n*******************\nAfter each call to :ref:`Forward-name` ,\nthe object *f* contains the corresponding\n:ref:`Taylor coefficients<glossary@Taylor Coefficient>` .\nAfter a call to ``ForOne`` ,\nthe zero order Taylor coefficients correspond to\n*f* . ``Forward`` (0, *x* )\nand the other coefficients are unspecified.\n\nExample\n*******\n{xrst_toc_hidden\n    example/general/for_one.cpp\n}\nThe routine\n:ref:`ForOne<for_one.cpp-name>` is both an example and test.\nIt returns ``true`` , if it succeeds and ``false`` otherwise.\n\n{xrst_end ForOne}\n-----------------------------------------------------------------------------\n*/\n\n//  BEGIN CppAD namespace\nnamespace CppAD {\n\ntemplate <class Base, class RecBase>\ntemplate <class Vector>\nVector ADFun<Base,RecBase>::ForOne(const Vector &x, size_t j)\n{   size_t j1;\n\n    size_t n = Domain();\n    size_t m = Range();\n\n    // check Vector is Simple Vector class with Base type elements\n    CheckSimpleVector<Base, Vector>();\n\n    CPPAD_ASSERT_KNOWN(\n        x.size() == n,\n        \"ForOne: Length of x not equal domain dimension for f\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        j < n,\n        \"ForOne: the index j is not less than domain dimension for f\"\n    );\n\n    // point at which we are evaluating the second partials\n    Forward(0, x);\n\n    // direction in which are are taking the derivative\n    Vector dx(n);\n    for(j1 = 0; j1 < n; j1++)\n        dx[j1] = Base(0.0);\n    dx[j] = Base(1.0);\n\n    // dimension the return value\n    Vector dy(m);\n\n    // compute the return value\n    dy = Forward(1, dx);\n\n    return dy;\n}\n\n} // END CppAD namespace\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/for_sparse_hes.hpp",
    "content": "# ifndef CPPAD_CORE_FOR_SPARSE_HES_HPP\n# define CPPAD_CORE_FOR_SPARSE_HES_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin ForSparseHes}\n{xrst_spell\n    walther\n}\n\nHessian Sparsity Pattern: Forward Mode\n######################################\n\nSyntax\n******\n| *h* = *f* . ``ForSparseHes`` ( *r* , *s* )\n\nPurpose\n*******\nWe use :math:`F : \\B{R}^n \\rightarrow \\B{R}^m` to denote the\n:ref:`glossary@AD Function` corresponding to *f* .\nwe define\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    H(x)\n    & = & \\partial_x \\left[ \\partial_u S \\cdot F[ x + R \\cdot u ] \\right]_{u=0}\n    \\\\\n    & = & R^\\R{T} \\cdot (S \\cdot F)^{(2)} ( x ) \\cdot R\n    \\end{eqnarray}\n\nWhere :math:`R \\in \\B{R}^{n \\times n}` is a diagonal matrix\nand :math:`S \\in \\B{R}^{1 \\times m}` is a row vector.\nGiven a\n:ref:`glossary@Sparsity Pattern`\nfor the diagonal of :math:`R` and the vector :math:`S`,\n``ForSparseHes`` returns a sparsity pattern for the :math:`H(x)`.\n\nf\n*\nThe object *f* has prototype\n\n    ``const ADFun`` < *Base* > *f*\n\nx\n*\nIf the operation sequence in *f* is\n:ref:`glossary@Operation@Independent` of\nthe independent variables in :math:`x \\in \\B{R}^n`,\nthe sparsity pattern is valid for all values of\n(even if it has :ref:`CondExp-name` or :ref:`VecAD-name` operations).\n\nr\n*\nThe argument *r* has prototype\n\n    ``const`` *SetVector* & *r*\n\n(see :ref:`ForSparseHes@SetVector` below)\nIf it has elements of type ``bool`` ,\nits size is :math:`n`.\nIf it has elements of type ``std::set<size_t>`` ,\nits size is one and all the elements of *s* [0]\nare between zero and :math:`n - 1`.\nIt specifies a\n:ref:`glossary@Sparsity Pattern`\nfor the diagonal of :math:`R`.\nThe fewer non-zero elements in this sparsity pattern,\nthe faster the calculation should be and the more sparse\n:math:`H(x)` should be.\n\ns\n*\nThe argument *s* has prototype\n\n    ``const`` *SetVector* & *s*\n\n(see :ref:`ForSparseHes@SetVector` below)\nIf it has elements of type ``bool`` ,\nits size is :math:`m`.\nIf it has elements of type ``std::set<size_t>`` ,\nits size is one and all the elements of *s* [0]\nare between zero and :math:`m - 1`.\nIt specifies a\n:ref:`glossary@Sparsity Pattern`\nfor the vector *S* .\nThe fewer non-zero elements in this sparsity pattern,\nthe faster the calculation should be and the more sparse\n:math:`H(x)` should be.\n\nh\n*\nThe result *h* has prototype\n\n    *SetVector* & *h*\n\n(see :ref:`ForSparseHes@SetVector` below).\nIf *h* has elements of type ``bool`` ,\nits size is :math:`n * n`.\nIf it has elements of type ``std::set<size_t>`` ,\nits size is :math:`n` and all the set elements are between\nzero and *n* ``-1`` inclusive.\nIt specifies a\n:ref:`glossary@Sparsity Pattern`\nfor the matrix :math:`H(x)`.\n\nSetVector\n*********\nThe type *SetVector* must be a :ref:`SimpleVector-name` class with\n:ref:`elements of type<SimpleVector@Elements of Specified Type>`\n``bool`` or ``std::set<size_t>`` ;\nsee :ref:`glossary@Sparsity Pattern` for a discussion\nof the difference.\nThe type of the elements of\n:ref:`ForSparseHes@SetVector` must be the\nsame as the type of the elements of *r* .\n\nAlgorithm\n*********\nSee Algorithm II in\n*Computing sparse Hessians with automatic differentiation*\nby Andrea Walther.\nNote that *s* provides the information so that\n'dead ends' are not included in the sparsity pattern.\n\nExample\n*******\n{xrst_toc_hidden\n    example/sparse/for_sparse_hes.cpp\n}\nThe file\n:ref:`for_sparse_hes.cpp-name`\ncontains an example and test of this operation.\n\n{xrst_end ForSparseHes}\n-----------------------------------------------------------------------------\n*/\n# include <algorithm>\n# include <cppad/local/pod_vector.hpp>\n# include <cppad/local/std_set.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\n\\file core/for_sparse_hes.hpp\nForward mode Hessian sparsity patterns.\n*/\n// ===========================================================================\n// ForSparseHesCase\n/*!\nPrivate helper function for ForSparseHes(q, s) bool sparsity.\n\nAll of the description in the public member function ForSparseHes(q, s)\napplies.\n\n\\param set_type\nis a bool value. This argument is used to dispatch to the proper source\ncode depending on the value of SetVector::value_type.\n\n\\param r\nSee ForSparseHes(r, s).\n\n\\param s\nSee ForSparseHes(r, s).\n\n\\param h\nis the return value for the corresponding call to ForSparseJac(q, s).\n*/\ntemplate <class Base, class RecBase>\ntemplate <class SetVector>\nvoid ADFun<Base,RecBase>::ForSparseHesCase(\n    bool              set_type         ,\n    const SetVector&  r                ,\n    const SetVector&  s                ,\n    SetVector&        h                )\n{\n    // used to identify the RecBase type in calls to sweeps\n    RecBase not_used_rec_base(0.0);\n    //\n    size_t n = Domain();\n    size_t m = Range();\n    //\n    // check Vector is Simple SetVector class with bool elements\n    CheckSimpleVector<bool, SetVector>();\n    //\n    CPPAD_ASSERT_KNOWN(\n        size_t(r.size()) == n,\n        \"ForSparseHes: size of r is not equal to\\n\"\n        \"domain dimension for ADFun object.\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t(s.size()) == m,\n        \"ForSparseHes: size of s is not equal to\\n\"\n        \"range dimension for ADFun object.\"\n    );\n    //\n    // select_domain corresponding to r\n    local::pod_vector<bool> select_domain(n);\n    for(size_t j = 0; j < n; ++j)\n    {   select_domain[j] = r[j];\n        CPPAD_ASSERT_UNKNOWN( ind_taddr_[j]  == j + 1);\n        CPPAD_ASSERT_UNKNOWN( play_.GetOp(j + 1) == local::InvOp );\n    }\n    // sparsity pattern corresponding to s\n    local::sparse::pack_setvec rev_jac_pattern;\n    rev_jac_pattern.resize(num_var_tape_, 1);\n    for(size_t i = 0; i < m; i++)\n    {   CPPAD_ASSERT_UNKNOWN( dep_taddr_[i] < num_var_tape_ );\n        //\n        // Not using post_element because only adding one element per set\n        if( s[i] )\n            rev_jac_pattern.add_element( dep_taddr_[i], 0);\n    }\n    // compute reverse sparsity pattern for dependency analysis\n    // (note that we are only want non-zero derivatives not true dependency)\n    bool dependency = false;\n    local::sweep::rev_jac(\n        &play_,\n        dependency,\n        n,\n        num_var_tape_,\n        rev_jac_pattern,\n        not_used_rec_base\n    );\n    // vector of sets that will hold the forward Hessain values\n    local::sparse::pack_setvec for_hes_pattern;\n    for_hes_pattern.resize(n+1+num_var_tape_, n+1);\n    //\n    // compute the Hessian sparsity patterns\n    local::sweep::for_hes(\n        &play_,\n        n,\n        num_var_tape_,\n        select_domain,\n        rev_jac_pattern,\n        for_hes_pattern,\n        not_used_rec_base\n\n    );\n    // initialize return values corresponding to independent variables\n    h.resize(n * n);\n    for(size_t i = 0; i < n; i++)\n    {   for(size_t j = 0; j < n; j++)\n            h[ i * n + j ] = false;\n    }\n    // copy to result pattern\n    CPPAD_ASSERT_UNKNOWN( for_hes_pattern.end() == n+1 );\n    for(size_t i = 0; i < n; i++)\n    {   // ind_taddr_[i] is operator taddr for i-th independent variable\n        CPPAD_ASSERT_UNKNOWN( ind_taddr_[i] == i + 1 );\n        CPPAD_ASSERT_UNKNOWN( play_.GetOp( ind_taddr_[i] ) == local::InvOp );\n\n        // extract the result from for_hes_pattern\n        local::sparse::pack_setvec::const_iterator itr(for_hes_pattern, ind_taddr_[i] );\n        size_t j = *itr;\n        while( j < for_hes_pattern.end() )\n        {   CPPAD_ASSERT_UNKNOWN( 0 < j )\n            h[ i * n + (j-1) ] = true;\n            j = *(++itr);\n        }\n    }\n}\n/*!\nPrivate helper function for ForSparseHes(q, s) set sparsity.\n\nAll of the description in the public member function ForSparseHes(q, s)\napplies.\n\n\\param set_type\nis a std::set<size_t> value.\nThis argument is used to dispatch to the proper source\ncode depending on the value of SetVector::value_type.\n\n\\param r\nSee ForSparseHes(r, s).\n\n\\param s\nSee ForSparseHes(q, s).\n\n\\param h\nis the return value for the corresponding call to ForSparseJac(q, s).\n*/\ntemplate <class Base, class RecBase>\ntemplate <class SetVector>\nvoid ADFun<Base,RecBase>::ForSparseHesCase(\n    const std::set<size_t>&   set_type         ,\n    const SetVector&          r                ,\n    const SetVector&          s                ,\n    SetVector&                h                )\n{\n    // used to identify the RecBase type in calls to sweeps\n    RecBase not_used_rec_base(0.0);\n    //\n    size_t n = Domain();\n# ifndef NDEBUG\n    size_t m = Range();\n# endif\n    std::set<size_t>::const_iterator itr_1;\n    //\n    // check SetVector is Simple Vector class with sets for elements\n    CheckSimpleVector<std::set<size_t>, SetVector>(\n        local::one_element_std_set<size_t>(), local::two_element_std_set<size_t>()\n    );\n    CPPAD_ASSERT_KNOWN(\n        r.size() == 1,\n        \"ForSparseHes: size of s is not equal to one.\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        s.size() == 1,\n        \"ForSparseHes: size of s is not equal to one.\"\n    );\n    //\n    // select_domain corresponding to r\n    local::pod_vector<bool> select_domain(n);\n    for(size_t j = 0; j < n; ++j)\n    {   select_domain[j] = false;\n        CPPAD_ASSERT_UNKNOWN( ind_taddr_[j]  == j + 1);\n        CPPAD_ASSERT_UNKNOWN( play_.GetOp(j + 1) == local::InvOp );\n    }\n    itr_1 = r[0].begin();\n    while( itr_1 != r[0].end() )\n    {   size_t j = *itr_1++;\n        select_domain[j] = true;\n    }\n    // sparsity pattern corresponding to s\n    local::sparse::list_setvec rev_jac_pattern;\n    rev_jac_pattern.resize(num_var_tape_, 1);\n    itr_1 = s[0].begin();\n    while( itr_1 != s[0].end() )\n    {   size_t i = *itr_1++;\n        CPPAD_ASSERT_KNOWN(\n            i < m,\n            \"ForSparseHes: an element of the set s[0] has value \"\n            \"greater than or equal m\"\n        );\n        CPPAD_ASSERT_UNKNOWN( dep_taddr_[i] < num_var_tape_ );\n        //\n        // Not using post_element because only adding one element per set\n        rev_jac_pattern.add_element( dep_taddr_[i], 0);\n    }\n    //\n    // compute reverse sparsity pattern for dependency analysis\n    // (note that we are only want non-zero derivatives not true dependency)\n    bool dependency = false;\n    local::sweep::rev_jac(\n        &play_,\n        dependency,\n        n,\n        num_var_tape_,\n        rev_jac_pattern,\n        not_used_rec_base\n    );\n    //\n    // vector of sets that will hold reverse Hessain values\n    local::sparse::list_setvec for_hes_pattern;\n    for_hes_pattern.resize(n+1+num_var_tape_, n+1);\n    //\n    // compute the Hessian sparsity patterns\n    local::sweep::for_hes(\n        &play_,\n        n,\n        num_var_tape_,\n        select_domain,\n        rev_jac_pattern,\n        for_hes_pattern,\n        not_used_rec_base\n\n    );\n    // return values corresponding to independent variables\n    // j is index corresponding to reverse mode partial\n    h.resize(n);\n    CPPAD_ASSERT_UNKNOWN( for_hes_pattern.end() == n+1 );\n    for(size_t i = 0; i < n; i++)\n    {   CPPAD_ASSERT_UNKNOWN( ind_taddr_[i] == i + 1 );\n        CPPAD_ASSERT_UNKNOWN( play_.GetOp( ind_taddr_[i] ) == local::InvOp );\n\n        // extract the result from for_hes_pattern\n        local::sparse::list_setvec::const_iterator itr_2(for_hes_pattern, ind_taddr_[i] );\n        size_t j = *itr_2;\n        while( j < for_hes_pattern.end() )\n        {   CPPAD_ASSERT_UNKNOWN( 0 < j )\n                h[i].insert(j-1);\n            j = *(++itr_2);\n        }\n    }\n}\n\n// ===========================================================================\n// ForSparseHes\n\n/*!\nUser API for Hessian sparsity patterns using reverse mode.\n\nThe C++ source code corresponding to this operation is\n\\verbatim\n    h = f.ForSparseHes(q, r)\n\\endverbatim\n\n\\tparam Base\nis the base type for this recording.\n\n\\tparam SetVector\nis a simple vector with elements of type bool\nor std::set<size_t>.\n\n\\param r\nis a vector with size n that specifies the sparsity pattern\nfor the diagonal of the matrix \\f$ R \\f$,\nwhere n is the number of independent variables\ncorresponding to the operation sequence stored in play.\n\n\\param s\nis a vector with size m that specifies the sparsity pattern\nfor the vector \\f$ S \\f$,\nwhere m is the number of dependent variables\ncorresponding to the operation sequence stored in play.\n\n\\return\nThe return vector is a sparsity pattern for \\f$ H(x) \\f$\n\\f[\n    H(x) = R^T ( S * F)^{(2)} (x) R\n\\f]\nwhere \\f$ F \\f$ is the function corresponding to the operation sequence\nand x is any argument value.\n*/\n\ntemplate <class Base, class RecBase>\ntemplate <class SetVector>\nSetVector ADFun<Base,RecBase>::ForSparseHes(\n    const SetVector& r, const SetVector& s\n)\n{\n    SetVector h;\n    typedef typename SetVector::value_type Set_type;\n\n    // Should check to make sure q is same as in previous call to\n    // forward sparse Jacobian.\n    ForSparseHesCase(\n        Set_type()    ,\n        r             ,\n        s             ,\n        h\n    );\n\n    return h;\n}\n// ===========================================================================\n// ForSparseHesCheckpoint\n/*!\nHessian sparsity patterns calculation used by checkpoint functions.\n\n\\tparam Base\nis the base type for this recording.\n\n\\param r\nis a vector with size n that specifies the sparsity pattern\nfor the diagonal of \\f$ R \\f$,\nwhere n is the number of independent variables\ncorresponding to the operation sequence stored in play_.\n\n\\param s\nis a vector with size m that specifies the sparsity pattern\nfor the vector \\f$ S \\f$,\nwhere m is the number of dependent variables\ncorresponding to the operation sequence stored in play_.\n\n\\param h\nThe input size and elements of h do not matter.\nOn output, h is the sparsity pattern for the matrix \\f$ H(x) R \\f$.\n\n\\par Assumptions\nThe forward jacobian sparsity pattern must be currently stored\nin this ADFUN object.\n*/\n\n// The checkpoint class is not yet using forward sparse Hessians.\n# ifdef CPPAD_NOT_DEFINED\ntemplate <class Base, class RecBase>\nvoid ADFun<Base,RecBase>::ForSparseHesCheckpoint(\n    vector<bool>&                 r         ,\n    vector<bool>&                 s         ,\n    local::sparse::list_setvec&   h         )\n{\n    // used to identify the RecBase type in calls to sweeps\n    RecBase not_used_rec_base(0.0);\n    //\n\n    size_t n = Domain();\n    size_t m = Range();\n\n    // checkpoint functions should get this right\n    CPPAD_ASSERT_UNKNOWN( for_jac_sparse_pack_.n_set() == 0 );\n    CPPAD_ASSERT_UNKNOWN( for_jac_sparse_set_.n_set() == 0   );\n    CPPAD_ASSERT_UNKNOWN( s.size()                    == m );\n\n    // Array that holds the reverse Jacobiain dependency flags.\n    // Initialize as true for dependent variables, false for others.\n    local::pod_vector<bool> RevJac(num_var_tape_);\n    for(size_t i = 0; i < num_var_tape_; i++)\n        RevJac[i] = false;\n    for(size_t i = 0; i < m; i++)\n    {   CPPAD_ASSERT_UNKNOWN( dep_taddr_[i] < num_var_tape_ )\n        RevJac[ dep_taddr_[i] ] = s[i];\n    }\n\n    // holds forward Hessian sparsity pattern for all variables\n    local::sparse::list_setvec for_hes_pattern;\n    for_hes_pattern.resize(n+1+num_var_tape_, n+1);\n\n    // compute Hessian sparsity pattern for all variables\n    local::sweep::for_hes(\n        &play_,\n        n,\n        num_var_tape_,\n        for_jac_sparse_set_,\n        RevJac.data(),\n        for_hes_pattern,\n        not_used_rec_base\n\n    );\n\n    // dimension the return value\n    if( transpose )\n        h.resize(n, n);\n    else\n        h.resize(n, n);\n\n    // j is index corresponding to reverse mode partial\n    for(size_t j = 0; j < n; j++)\n    {   CPPAD_ASSERT_UNKNOWN( ind_taddr_[j] < num_var_tape_ );\n\n        // ind_taddr_[j] is operator taddr for j-th independent variable\n        CPPAD_ASSERT_UNKNOWN( ind_taddr_[j] == j + 1 );\n        CPPAD_ASSERT_UNKNOWN( play_.GetOp( ind_taddr_[j] ) == local::InvOp );\n\n        // extract the result from for_hes_pattern\n        CPPAD_ASSERT_UNKNOWN( for_hes_pattern.end() == q );\n        local::sparse::list_setvec::const_iterator itr(for_hes_pattern, .j + 1);\n        size_t i = *itr;\n        while( i < q )\n        {   if( transpose )\n                h.post_element(j,  i);\n            else\n                h.post_element(i, j);\n            i = *(++itr);\n        }\n    }\n    // process posts\n    for(size_t i = 0; i < n; ++i)\n        h.process_post(i);\n}\n# endif\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/for_sparse_jac.hpp",
    "content": "# ifndef CPPAD_CORE_FOR_SPARSE_JAC_HPP\n# define CPPAD_CORE_FOR_SPARSE_JAC_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin ForSparseJac}\n\nJacobian Sparsity Pattern: Forward Mode\n#######################################\n\nSyntax\n******\n| *s* = *f* . ``ForSparseJac`` ( *q* , *r* )\n| *s* = *f* . ``ForSparseJac`` ( *q* , *r* , *transpose* , *dependency* )\n\nPurpose\n*******\nWe use :math:`F : \\B{R}^n \\rightarrow \\B{R}^m` to denote the\n:ref:`glossary@AD Function` corresponding to *f* .\nFor a fixed :math:`n \\times q` matrix :math:`R`,\nthe Jacobian of :math:`F[ x + R * u ]`\nwith respect to :math:`u` at :math:`u = 0` is\n\n.. math::\n\n    S(x) = F^{(1)} ( x ) * R\n\nGiven a\n:ref:`glossary@Sparsity Pattern`\nfor :math:`R`,\n``ForSparseJac`` returns a sparsity pattern for the :math:`S(x)`.\n\nf\n*\nThe object *f* has prototype\n\n    ``ADFun`` < *Base* > *f*\n\nNote that the :ref:`ADFun-name` object *f* is not ``const`` .\nAfter a call to ``ForSparseJac`` , the sparsity pattern\nfor each of the variables in the operation sequence\nis held in *f* (for possible later use by :ref:`RevSparseHes-name` ).\nThese sparsity patterns are stored with elements of type ``bool``\nor elements of type ``std::set<size_t>``\n(see :ref:`ForSparseJac@SetVector` below).\n\nsize_forward_bool\n=================\nAfter ``ForSparseJac`` , if *k* is a ``size_t`` object,\n\n    *k* = *f* . ``size_forward_bool`` ()\n\nsets *k* to the amount of memory (in unsigned character units)\nused to store the sparsity pattern with elements of type ``bool``\nin the function object *f* .\nIf the sparsity patterns for the previous ``ForSparseJac`` used\nelements of type ``bool`` ,\nthe return value for ``size_forward_bool`` will be non-zero.\nOtherwise, its return value will be zero.\nThis sparsity pattern is stored for use by :ref:`RevSparseHes-name` and\nwhen it is not longer needed, it can be deleted\n(and the corresponding memory freed) using\n\n    *f* . ``size_forward_bool`` (0)\n\nAfter this call, *f* . ``size_forward_bool`` () will return zero.\n\nsize_forward_set\n================\nAfter ``ForSparseJac`` , if *k* is a ``size_t`` object,\n\n    *k* = *f* . ``size_forward_set`` ()\n\nsets *k* to the amount of memory (in unsigned character units)\nused to store the\n:ref:`glossary@Sparsity Pattern@Vector of Sets`\nsparsity patterns.\nIf the sparsity patterns for this operation use elements of type ``bool`` ,\nthe return value for ``size_forward_set`` will be zero.\nOtherwise, its return value will be non-zero.\nThis sparsity pattern is stored for use by :ref:`RevSparseHes-name` and\nwhen it is not longer needed, it can be deleted\n(and the corresponding memory freed) using\n\n    *f* . ``size_forward_set`` (0)\n\nAfter this call, *f* . ``size_forward_set`` () will return zero.\n\nx\n*\nIf the operation sequence in *f* is\n:ref:`glossary@Operation@Independent` of\nthe independent variables in :math:`x \\in \\B{R}^n`,\nthe sparsity pattern is valid for all values of\n(even if it has :ref:`CondExp-name` or :ref:`VecAD-name` operations).\n\nq\n*\nThe argument *q* has prototype\n\n    ``size_t`` *q*\n\nIt specifies the number of columns in\n:math:`R \\in \\B{R}^{n \\times q}` and the Jacobian\n:math:`S(x) \\in \\B{R}^{m \\times q}`.\n\ntranspose\n*********\nThe argument *transpose* has prototype\n\n    ``bool`` *transpose*\n\nThe default value ``false`` is used when *transpose* is not present.\n\ndependency\n**********\nThe argument *dependency* has prototype\n\n    ``bool`` *dependency*\n\nIf *dependency* is true,\nthe :ref:`dependency.cpp@Dependency Pattern`\n(instead of sparsity pattern) is computed.\n\nr\n*\nThe argument *r* has prototype\n\n    ``const`` *SetVector* & *r*\n\nsee :ref:`ForSparseJac@SetVector` below.\n\ntranspose false\n===============\nIf *r* has elements of type ``bool`` ,\nits size is :math:`n * q`.\nIf it has elements of type ``std::set<size_t>`` ,\nits size is :math:`n` and all the set elements must be between\nzero and *q* ``-1`` inclusive.\nIt specifies a\n:ref:`glossary@Sparsity Pattern`\nfor the matrix :math:`R \\in \\B{R}^{n \\times q}`.\n\ntranspose true\n==============\nIf *r* has elements of type ``bool`` ,\nits size is :math:`q * n`.\nIf it has elements of type ``std::set<size_t>`` ,\nits size is :math:`q` and all the set elements must be between\nzero and *n* ``-1`` inclusive.\nIt specifies a\n:ref:`glossary@Sparsity Pattern`\nfor the matrix :math:`R^\\R{T} \\in \\B{R}^{q \\times n}`.\n\ns\n*\nThe return value *s* has prototype\n\n    *SetVector* *s*\n\nsee :ref:`ForSparseJac@SetVector` below.\n\ntranspose false\n===============\nIf *s* has elements of type ``bool`` ,\nits size is :math:`m * q`.\nIf it has elements of type ``std::set<size_t>`` ,\nits size is :math:`m` and all its set elements are between\nzero and *q* ``-1`` inclusive.\nIt specifies a\n:ref:`glossary@Sparsity Pattern`\nfor the matrix :math:`S(x) \\in \\B{R}^{m \\times q}`.\n\ntranspose true\n==============\nIf *s* has elements of type ``bool`` ,\nits size is :math:`q * m`.\nIf it has elements of type ``std::set<size_t>`` ,\nits size is :math:`q` and all its set elements are between\nzero and *m* ``-1`` inclusive.\nIt specifies a\n:ref:`glossary@Sparsity Pattern`\nfor the matrix :math:`S(x)^\\R{T} \\in \\B{R}^{q \\times m}`.\n\nSetVector\n*********\nThe type *SetVector* must be a :ref:`SimpleVector-name` class with\n:ref:`elements of type<SimpleVector@Elements of Specified Type>`\n``bool`` or ``std::set<size_t>`` ;\nsee :ref:`glossary@Sparsity Pattern` for a discussion\nof the difference.\n\nEntire Sparsity Pattern\n***********************\nSuppose that :math:`q = n` and\n:math:`R` is the :math:`n \\times n` identity matrix.\nIn this case,\nthe corresponding value for *s* is a\nsparsity pattern for the Jacobian :math:`S(x) = F^{(1)} ( x )`.\n\nExample\n*******\n{xrst_toc_hidden\n    example/sparse/for_sparse_jac.cpp\n}\nThe file\n:ref:`for_sparse_jac.cpp-name`\ncontains an example and test of this operation.\nThe file\n:ref:`sparsity_sub.cpp<sparsity_sub.cpp@ForSparseJac>`\ncontains an example and test of using ``ForSparseJac``\nto compute the sparsity pattern for a subset of the Jacobian.\n\n{xrst_end ForSparseJac}\n-----------------------------------------------------------------------------\n*/\n\n# include <cppad/local/std_set.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\n\\file core/for_sparse_jac.hpp\nForward mode Jacobian sparsity patterns.\n*/\n// ---------------------------------------------------------------------------\n/*!\nPrivate helper function for ForSparseJac(q, r) boolean sparsity patterns.\n\nAll of the description in the public member function ForSparseJac(q, r)\napplies.\n\n\\param set_type\nis a bool value. This argument is used to dispatch to the proper source\ncode depending on the value of SetVector::value_type.\n\n\\param transpose\nSee ForSparseJac(q, r, transpose, dependency).\n\n\\param dependency\nSee ForSparseJac(q, r, transpose, dependency).\n\n\\param q\nSee ForSparseJac(q, r, transpose, dependency).\n\n\\param r\nSee ForSparseJac(q, r, transpose, dependency).\n\n\\param s\nis the return value for the corresponding call to ForSparseJac(q, r).\n*/\n\ntemplate <class Base, class RecBase>\ntemplate <class SetVector>\nvoid ADFun<Base,RecBase>::ForSparseJacCase(\n    bool                set_type      ,\n    bool                transpose     ,\n    bool                dependency    ,\n    size_t              q             ,\n    const SetVector&    r             ,\n    SetVector&          s             )\n{\n    // used to identify the RecBase type in calls to sweeps\n    RecBase not_used_rec_base(0.0);\n    //\n    size_t m = Range();\n    size_t n = Domain();\n\n    // check SetVector is Simple Vector class with bool elements\n    CheckSimpleVector<bool, SetVector>();\n\n    // dimension size of result vector\n    s.resize( m * q );\n\n    CPPAD_ASSERT_KNOWN(\n        q > 0,\n        \"ForSparseJac: q is not greater than zero\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t(r.size()) == n * q,\n        \"ForSparseJac: size of r is not equal to\\n\"\n        \"q times domain dimension for ADFun object.\"\n    );\n    //\n    // allocate memory for the requested sparsity calculation result\n    for_jac_sparse_pack_.resize(num_var_tape_, q);\n\n    // set values corresponding to independent variables\n    for(size_t i = 0; i < n; i++)\n    {   CPPAD_ASSERT_UNKNOWN( ind_taddr_[i] < num_var_tape_ );\n        // ind_taddr_[i] is operator taddr for i-th independent variable\n        CPPAD_ASSERT_UNKNOWN( play_.GetOp( ind_taddr_[i] ) == local::InvOp );\n\n        // set bits that are true\n        if( transpose )\n        {   for(size_t j = 0; j < q; j++) if( r[ j * n + i ] )\n                for_jac_sparse_pack_.post_element( ind_taddr_[i], j);\n        }\n        else\n        {   for(size_t j = 0; j < q; j++) if( r[ i * q + j ] )\n                for_jac_sparse_pack_.post_element( ind_taddr_[i], j);\n        }\n    }\n    // process posts\n    for(size_t j = 0; j < n; j++)\n        for_jac_sparse_pack_.process_post( ind_taddr_[j] );\n\n    // evaluate the sparsity patterns\n    local::sweep::for_jac(\n        &play_,\n        dependency,\n        n,\n        num_var_tape_,\n        for_jac_sparse_pack_,\n        not_used_rec_base\n\n    );\n\n    // return values corresponding to dependent variables\n    CPPAD_ASSERT_UNKNOWN( size_t(s.size()) == m * q );\n    for(size_t i = 0; i < m; i++)\n    {   CPPAD_ASSERT_UNKNOWN( dep_taddr_[i] < num_var_tape_ );\n\n        // extract the result from for_jac_sparse_pack_\n        if( transpose )\n        {   for(size_t j = 0; j < q; j++)\n                s[ j * m + i ] = false;\n        }\n        else\n        {   for(size_t j = 0; j < q; j++)\n                s[ i * q + j ] = false;\n        }\n        CPPAD_ASSERT_UNKNOWN( for_jac_sparse_pack_.end() == q );\n        local::sparse::pack_setvec::const_iterator\n            itr(for_jac_sparse_pack_, dep_taddr_[i] );\n        size_t j = *itr;\n        while( j < q )\n        {   if( transpose )\n                s[j * m + i] = true;\n            else\n                s[i * q + j] = true;\n            j = *(++itr);\n        }\n    }\n}\n// ---------------------------------------------------------------------------\n/*!\nPrivate helper function for ForSparseJac(q, r) set sparsity.\n\nAll of the description in the public member function ForSparseJac(q, r)\napplies.\n\n\\param set_type\nis a std::set<size_t> object.\nThis argument is used to dispatch to the proper source\ncode depending on the value of SetVector::value_type.\n\n\\param transpose\nSee ForSparseJac(q, r, transpose, dependency).\n\n\\param dependency\nSee ForSparseJac(q, r, transpose, dependency).\n\n\\param q\nSee ForSparseJac(q, r, transpose, dependency).\n\n\\param r\nSee ForSparseJac(q, r, transpose, dependency).\n\n\\param s\nis the return value for the corresponding call to ForSparseJac(q, r).\n*/\ntemplate <class Base, class RecBase>\ntemplate <class SetVector>\nvoid ADFun<Base,RecBase>::ForSparseJacCase(\n    const std::set<size_t>&    set_type      ,\n    bool                       transpose     ,\n    bool                       dependency    ,\n    size_t                     q             ,\n    const SetVector&           r             ,\n    SetVector&                 s             )\n{\n    // used to identify the RecBase type in calls to sweeps\n    RecBase not_used_rec_base(0.0);\n    //\n    size_t m = Range();\n    size_t n = Domain();\n\n    // check SetVector is Simple Vector class with sets for elements\n    CheckSimpleVector<std::set<size_t>, SetVector>(\n        local::one_element_std_set<size_t>(), local::two_element_std_set<size_t>()\n    );\n\n    // dimension size of result vector\n    if( transpose )\n        s.resize(q);\n    else\n        s.resize( m );\n\n    // temporary iterator\n    std::set<size_t>::const_iterator itr_1;\n\n    CPPAD_ASSERT_KNOWN(\n        q > 0,\n        \"ForSparseJac: q is not greater than zero\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t(r.size()) == n || transpose,\n        \"ForSparseJac: size of r is not equal to n and transpose is false.\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t(r.size()) == q || ! transpose,\n        \"ForSparseJac: size of r is not equal to q and transpose is true.\"\n    );\n    //\n    // allocate memory for the requested sparsity calculation\n    for_jac_sparse_set_.resize(num_var_tape_, q);\n\n    // set values corresponding to independent variables\n    if( transpose )\n    {   for(size_t i = 0; i < q; i++)\n        {   // add the elements that are present\n            itr_1 = r[i].begin();\n            while( itr_1 != r[i].end() )\n            {   size_t j = *itr_1++;\n                CPPAD_ASSERT_KNOWN(\n                j < n,\n                \"ForSparseJac: transpose is true and element of the set\\n\"\n                \"r[j] has value greater than or equal n.\"\n                );\n                CPPAD_ASSERT_UNKNOWN( ind_taddr_[j] < num_var_tape_ );\n                // operator for j-th independent variable\n                CPPAD_ASSERT_UNKNOWN(\n                    play_.GetOp( ind_taddr_[j] ) == local::InvOp\n                );\n                for_jac_sparse_set_.post_element( ind_taddr_[j], i);\n            }\n        }\n    }\n    else\n    {   for(size_t i = 0; i < n; i++)\n        {   CPPAD_ASSERT_UNKNOWN( ind_taddr_[i] < num_var_tape_ );\n            // ind_taddr_[i] is operator taddr for i-th independent variable\n            CPPAD_ASSERT_UNKNOWN( play_.GetOp( ind_taddr_[i] ) == local::InvOp );\n\n            // add the elements that are present\n            itr_1 = r[i].begin();\n            while( itr_1 != r[i].end() )\n            {   size_t j = *itr_1++;\n                CPPAD_ASSERT_KNOWN(\n                    j < q,\n                    \"ForSparseJac: an element of the set r[i] \"\n                    \"has value greater than or equal q.\"\n                );\n                for_jac_sparse_set_.post_element( ind_taddr_[i], j);\n            }\n        }\n    }\n    // process posts\n    for(size_t j = 0; j < n; j++)\n        for_jac_sparse_set_.process_post( ind_taddr_[j] );\n\n    // evaluate the sparsity patterns\n    local::sweep::for_jac(\n        &play_,\n        dependency,\n        n,\n        num_var_tape_,\n        for_jac_sparse_set_,\n        not_used_rec_base\n\n    );\n\n    // return values corresponding to dependent variables\n    CPPAD_ASSERT_UNKNOWN( size_t(s.size()) == m || transpose );\n    CPPAD_ASSERT_UNKNOWN( size_t(s.size()) == q || ! transpose );\n    for(size_t i = 0; i < m; i++)\n    {   CPPAD_ASSERT_UNKNOWN( dep_taddr_[i] < num_var_tape_ );\n\n        // extract results from for_jac_sparse_set_\n        // and add corresponding elements to sets in s\n        CPPAD_ASSERT_UNKNOWN( for_jac_sparse_set_.end() == q );\n        local::sparse::list_setvec::const_iterator\n            itr_2(for_jac_sparse_set_, dep_taddr_[i] );\n        size_t j = *itr_2;\n        while( j < q )\n        {   if( transpose )\n                s[j].insert(i);\n            else\n                s[i].insert(j);\n            j = *(++itr_2);\n        }\n    }\n}\n// ---------------------------------------------------------------------------\n\n/*!\nUser API for Jacobian sparsity patterns using forward mode.\n\nThe C++ source code corresponding to this operation is\n\\verbatim\n    s = f.ForSparseJac(q, r, transpose, dependency)\n\\endverbatim\n\n\\tparam Base\nis the base type for this recording.\n\n\\tparam SetVector\nis a simple vector with elements of type bool\nor std::set<size_t>.\n\n\\param q\nis the number of columns in the matrix \\f$ R \\f$.\n\n\\param r\nis a sparsity pattern for the matrix \\f$ R \\f$.\n\n\\param transpose\nare sparsity patterns for \\f$ R \\f$ and \\f$ S(x) \\f$ transposed.\n\n\\param dependency\nAre the derivatives with respect to left and right of the expression below\nconsidered to be non-zero:\n\\code\n    CondExpRel(left, right, if_true, if_false)\n\\endcode\nThis is used by the optimizer to obtain the correct dependency relations.\n\n\\return\nThe value of transpose is false (true),\nthe return value is a sparsity pattern for \\f$ S(x) \\f$ (\\f$ S(x)^T \\f$) where\n\\f[\n    S(x) = F^{(1)} (x) * R\n\\f]\nwhere \\f$ F \\f$ is the function corresponding to the operation sequence\nand x is any argument value.\nIf SetVector::value_type is bool,\nthe return value has size \\f$ m * q \\f$ (\\f$ q * m \\f$).\nwhere m is the number of dependent variables\ncorresponding to the operation sequence stored in f.\nIf SetVector::value_type is std::set<size_t>,\nthe return value has size \\f$ m \\f$ ( \\f$ q \\f$ )\nand with all its elements between zero and\n\\f$ q - 1 \\f$ ( \\f$ m - 1 \\f$).\n\n\\par Side Effects\nIf SetVector::value_type is bool,\nthe forward sparsity pattern for all of the variables on the\ntape is stored in for_jac_sparse_pack__.\nIn this case\n\\verbatim\n    for_jac_sparse_pack_.n_set() == num_var_tape_\n    for_jac_sparse_pack_.end() == q\n    for_jac_sparse_set_.n_set()  == 0\n    for_jac_sparse_set_.end()  == 0\n\\endverbatim\n\\n\n\\n\nIf SetVector::value_type is std::set<size_t>,\nthe forward sparsity pattern for all of the variables on the\ntape is stored in for_jac_sparse_set__.\nIn this case\n\\verbatim\n    for_jac_sparse_set_.n_set()   == num_var_tape_\n    for_jac_sparse_set_.end()   == q\n    for_jac_sparse_pack_.n_set()  == 0\n    for_jac_sparse_pack_.end()  == 0\n\\endverbatim\n*/\ntemplate <class Base, class RecBase>\ntemplate <class SetVector>\nSetVector ADFun<Base,RecBase>::ForSparseJac(\n    size_t             q             ,\n    const SetVector&   r             ,\n    bool               transpose     ,\n    bool               dependency    )\n{\n    SetVector s;\n    typedef typename SetVector::value_type Set_type;\n\n    // free all memory currently in sparsity patterns\n    for_jac_sparse_pack_.resize(0, 0);\n    for_jac_sparse_set_.resize(0, 0);\n\n    ForSparseJacCase(\n        Set_type()  ,\n        transpose   ,\n        dependency  ,\n        q           ,\n        r           ,\n        s\n    );\n\n    return s;\n}\n// ===========================================================================\n// ForSparseJacCheckpoint\n/*!\nForward mode Jacobian sparsity calculation used by checkpoint functions.\n\n\\tparam Base\nis the base type for this recording.\n\n\\param transpose\nis true (false) s is equal to \\f$ S(x) \\f$ (\\f$ S(x)^T \\f$)\nwhere\n\\f[\n    S(x) = F^{(1)} (x) * R\n\\f]\nwhere \\f$ F \\f$ is the function corresponding to the operation sequence\nand \\f$ x \\f$ is any argument value.\n\n\\param q\nis the number of columns in the matrix \\f$ R \\f$.\n\n\\param r\nis a sparsity pattern for the matrix \\f$ R \\f$.\n\n\\param transpose\nare the sparsity patterns for \\f$ R \\f$ and \\f$ S(x) \\f$ transposed.\n\n\\param dependency\nAre the derivatives with respect to left and right of the expression below\nconsidered to be non-zero:\n\\code\n    CondExpRel(left, right, if_true, if_false)\n\\endcode\nThis is used by the optimizer to obtain the correct dependency relations.\n\n\\param s\nThe input size and elements of s do not matter.\nOn output, s is the sparsity pattern for the matrix \\f$ S(x) \\f$\nor \\f$ S(x)^T \\f$ depending on transpose.\n\n\\par Side Effects\nIf SetVector::value_type is bool,\nthe forward sparsity pattern for all of the variables on the\ntape is stored in for_jac_sparse_pack__.\nIn this case\n\\verbatim\n    for_jac_sparse_pack_.n_set() == num_var_tape_\n    for_jac_sparse_pack_.end() == q\n    for_jac_sparse_set_.n_set()  == 0\n    for_jac_sparse_set_.end()  == 0\n\\endverbatim\n\\n\n\\n\nIf SetVector::value_type is std::set<size_t>,\nthe forward sparsity pattern for all of the variables on the\ntape is stored in for_jac_sparse_set__.\nIn this case\n\\verbatim\n    for_jac_sparse_set_.n_set()   == num_var_tape_\n    for_jac_sparse_set_.end()   == q\n    for_jac_sparse_pack_.n_set()  == 0\n    for_jac_sparse_pack_.end()  == 0\n\\endverbatim\n*/\ntemplate <class Base, class RecBase>\nvoid ADFun<Base,RecBase>::ForSparseJacCheckpoint(\n    size_t                             q          ,\n    const local::sparse::list_setvec&  r          ,\n    bool                               transpose  ,\n    bool                               dependency ,\n    local::sparse::list_setvec&        s          )\n{\n    // used to identify the RecBase type in calls to sweeps\n    RecBase not_used_rec_base(0.0);\n    //\n    size_t n = Domain();\n    size_t m = Range();\n\n# ifndef NDEBUG\n    if( transpose )\n    {   CPPAD_ASSERT_UNKNOWN( r.n_set() == q );\n        CPPAD_ASSERT_UNKNOWN( r.end()   == n );\n    }\n    else\n    {   CPPAD_ASSERT_UNKNOWN( r.n_set() == n );\n        CPPAD_ASSERT_UNKNOWN( r.end()   == q );\n    }\n    for(size_t j = 0; j < n; j++)\n    {   CPPAD_ASSERT_UNKNOWN( ind_taddr_[j] == (j+1) );\n        CPPAD_ASSERT_UNKNOWN( play_.GetOp( ind_taddr_[j] ) == local::InvOp );\n    }\n# endif\n\n    // free all memory currently in sparsity patterns\n    for_jac_sparse_pack_.resize(0, 0);\n    for_jac_sparse_set_.resize(0, 0);\n\n    // allocate new sparsity pattern\n    for_jac_sparse_set_.resize(num_var_tape_, q);\n\n    // set sparsity pattern for dependent variables\n    if( transpose )\n    {   for(size_t i = 0; i < q; i++)\n        {   local::sparse::list_setvec::const_iterator itr(r, i);\n            size_t j = *itr;\n            while( j < n )\n            {   for_jac_sparse_set_.post_element( ind_taddr_[j], i );\n                j = *(++itr);\n            }\n        }\n    }\n    else\n    {   for(size_t j = 0; j < n; j++)\n        {   local::sparse::list_setvec::const_iterator itr(r, j);\n            size_t i = *itr;\n            while( i < q )\n            {   for_jac_sparse_set_.post_element( ind_taddr_[j], i );\n                i = *(++itr);\n            }\n        }\n    }\n    // process posts\n    for(size_t j = 0; j < n; j++)\n        for_jac_sparse_set_.process_post( ind_taddr_[j] );\n\n    // evaluate the sparsity pattern for all variables\n    local::sweep::for_jac(\n        &play_,\n        dependency,\n        n,\n        num_var_tape_,\n        for_jac_sparse_set_,\n        not_used_rec_base\n\n    );\n\n    // dimension the return value\n    if( transpose )\n        s.resize(q, m);\n    else\n        s.resize(m, q);\n\n    // return values corresponding to dependent variables\n    for(size_t i = 0; i < m; i++)\n    {   CPPAD_ASSERT_UNKNOWN( dep_taddr_[i] < num_var_tape_ );\n\n        // extract the result from for_jac_sparse_set_\n        CPPAD_ASSERT_UNKNOWN( for_jac_sparse_set_.end() == q );\n        local::sparse::list_setvec::const_iterator\n            itr(for_jac_sparse_set_, dep_taddr_[i] );\n        size_t j = *itr;\n        while( j < q )\n        {   if( transpose )\n                s.post_element(j, i);\n            else\n                s.post_element(i, j);\n            j  = *(++itr);\n        }\n    }\n    // process posts\n    for(size_t i = 0; i < s.n_set(); ++i)\n        s.process_post(i);\n\n}\n\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/for_two.hpp",
    "content": "# ifndef CPPAD_CORE_FOR_TWO_HPP\n# define CPPAD_CORE_FOR_TWO_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin ForTwo}\n{xrst_spell\n    ddy\n}\n\nForward Mode Second Partial Derivative Driver\n#############################################\n\nSyntax\n******\n| *ddy* = *f* . ``ForTwo`` ( *x* , *j* , *k* )\n\nPurpose\n*******\nWe use :math:`F : \\B{R}^n \\rightarrow \\B{R}^m` to denote the\n:ref:`glossary@AD Function` corresponding to *f* .\nThe syntax above sets\n\n.. math::\n\n    ddy [ i * p + \\ell ]\n    =\n    \\DD{ F_i }{ x_{j[ \\ell ]} }{ x_{k[ \\ell ]} } (x)\n\nfor :math:`i = 0 , \\ldots , m-1`\nand :math:`\\ell = 0 , \\ldots , p`,\nwhere :math:`p` is the size of the vectors *j* and *k* .\n\nf\n*\nThe object *f* has prototype\n\n    ``ADFun`` < *Base* > *f*\n\nNote that the :ref:`ADFun-name` object *f* is not ``const``\n(see :ref:`ForTwo@ForTwo Uses Forward` below).\n\nx\n*\nThe argument *x* has prototype\n\n    ``const`` *BaseVector* & *x*\n\n(see :ref:`ForTwo@BaseVector` below)\nand its size\nmust be equal to *n* , the dimension of the\n:ref:`fun_property@Domain` space for *f* .\nIt specifies\nthat point at which to evaluate the partial derivatives listed above.\n\nj\n*\nThe argument *j* has prototype\n\n    ``const`` *SizeVector_t* & *j*\n\n(see :ref:`ForTwo@SizeVector_t` below)\nWe use *p* to denote the size of the vector *j* .\nAll of the indices in *j*\nmust be less than *n* ; i.e.,\nfor :math:`\\ell = 0 , \\ldots , p-1`, :math:`j[ \\ell ]  < n`.\n\nk\n*\nThe argument *k* has prototype\n\n    ``const`` *SizeVector_t* & *k*\n\n(see :ref:`ForTwo@SizeVector_t` below)\nand its size must be equal to *p* ,\nthe size of the vector *j* .\nAll of the indices in *k*\nmust be less than *n* ; i.e.,\nfor :math:`\\ell = 0 , \\ldots , p-1`, :math:`k[ \\ell ]  < n`.\n\nddy\n***\nThe result *ddy* has prototype\n\n    *BaseVector* *ddy*\n\n(see :ref:`ForTwo@BaseVector` below)\nand its size is :math:`m * p`.\nIt contains the requested partial derivatives; to be specific,\nfor :math:`i = 0 , \\ldots , m - 1`\nand :math:`\\ell = 0 , \\ldots , p - 1`\n\n.. math::\n\n    ddy [ i * p + \\ell ]\n    =\n    \\DD{ F_i }{ x_{j[ \\ell ]} }{ x_{k[ \\ell ]} } (x)\n\nBaseVector\n**********\nThe type *BaseVector* must be a :ref:`SimpleVector-name` class with\n:ref:`elements of type Base<SimpleVector@Elements of Specified Type>` .\nThe routine :ref:`CheckSimpleVector-name` will generate an error message\nif this is not the case.\n\nSizeVector_t\n************\nThe type *SizeVector_t* must be a :ref:`SimpleVector-name` class with\n:ref:`elements of type size_t<SimpleVector@Elements of Specified Type>` .\nThe routine :ref:`CheckSimpleVector-name` will generate an error message\nif this is not the case.\n\nForTwo Uses Forward\n*******************\nAfter each call to :ref:`Forward-name` ,\nthe object *f* contains the corresponding\n:ref:`Taylor coefficients<glossary@Taylor Coefficient>` .\nAfter a call to ``ForTwo`` ,\nthe zero order Taylor coefficients correspond to\n*f* . ``Forward`` (0, *x* )\nand the other coefficients are unspecified.\n\nExamples\n********\n{xrst_toc_hidden\n    example/general/for_two.cpp\n}\nThe routine\n:ref:`ForTwo<for_two.cpp-name>` is both an example and test.\nIt returns ``true`` , if it succeeds and ``false`` otherwise.\n\n{xrst_end ForTwo}\n-----------------------------------------------------------------------------\n*/\n\n//  BEGIN CppAD namespace\nnamespace CppAD {\n\ntemplate <class Base, class RecBase>\ntemplate <class BaseVector, class SizeVector_t>\nBaseVector ADFun<Base,RecBase>::ForTwo(\n    const BaseVector   &x,\n    const SizeVector_t &j,\n    const SizeVector_t &k)\n{   size_t i;\n    size_t j1;\n    size_t k1;\n    size_t l;\n\n    size_t n = Domain();\n    size_t m = Range();\n    size_t p = j.size();\n\n    // check BaseVector is Simple Vector class with Base type elements\n    CheckSimpleVector<Base, BaseVector>();\n\n    // check SizeVector_t is Simple Vector class with size_t elements\n    CheckSimpleVector<size_t, SizeVector_t>();\n\n    CPPAD_ASSERT_KNOWN(\n        x.size() == n,\n        \"ForTwo: Length of x not equal domain dimension for f.\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        j.size() == k.size(),\n        \"ForTwo: Length of the j and k vectors are not equal.\"\n    );\n    // point at which we are evaluating the second partials\n    Forward(0, x);\n\n\n    // dimension the return value\n    BaseVector ddy(m * p);\n\n    // allocate memory to hold all possible diagonal Taylor coefficients\n    // (for large sparse cases, this is not efficient)\n    BaseVector D(m * n);\n\n    // boolean flag for which diagonal coefficients are computed\n    CppAD::vector<bool> c(n);\n    for(j1 = 0; j1 < n; j1++)\n        c[j1] = false;\n\n    // direction vector in argument space\n    BaseVector dx(n);\n    for(j1 = 0; j1 < n; j1++)\n        dx[j1] = Base(0.0);\n\n    // result vector in range space\n    BaseVector dy(m);\n\n    // compute the diagonal coefficients that are needed\n    for(l = 0; l < p; l++)\n    {   j1 = j[l];\n        k1 = k[l];\n        CPPAD_ASSERT_KNOWN(\n        j1 < n,\n        \"ForTwo: an element of j not less than domain dimension for f.\"\n        );\n        CPPAD_ASSERT_KNOWN(\n        k1 < n,\n        \"ForTwo: an element of k not less than domain dimension for f.\"\n        );\n        size_t count = 2;\n        while(count)\n        {   count--;\n            if( ! c[j1] )\n            {   // diagonal term in j1 direction\n                c[j1]  = true;\n                dx[j1] = Base(1.0);\n                Forward(1, dx);\n\n                dx[j1] = Base(0.0);\n                dy     = Forward(2, dx);\n                for(i = 0; i < m; i++)\n                    D[i * n + j1 ] = dy[i];\n            }\n            j1 = k1;\n        }\n    }\n    // compute all the requested cross partials\n    for(l = 0; l < p; l++)\n    {   j1 = j[l];\n        k1 = k[l];\n        if( j1 == k1 )\n        {   for(i = 0; i < m; i++)\n                ddy[i * p + l] = Base(2.0) * D[i * n + j1];\n        }\n        else\n        {\n            // cross term in j1 and k1 directions\n            dx[j1] = Base(1.0);\n            dx[k1] = Base(1.0);\n            Forward(1, dx);\n\n            dx[j1] = Base(0.0);\n            dx[k1] = Base(0.0);\n            dy = Forward(2, dx);\n\n            // place result in return value\n            for(i = 0; i < m; i++)\n                ddy[i * p + l] = dy[i] - D[i*n+j1] - D[i*n+k1];\n\n        }\n    }\n    return ddy;\n}\n\n} // END CppAD namespace\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/forward/compare_change.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin compare_change}\n\nComparison Changes Between Taping and Zero Order Forward\n########################################################\n\nSyntax\n******\n| *f* . ``compare_change_count`` ( *count* )\n| *number* = *f* . ``compare_change_number`` ()\n| *op_index* = *f* . ``compare_change_op_index`` ()\n\nSee Also\n********\n:ref:`FunCheck-name`\n\nPurpose\n*******\nWe use :math:`F : \\B{R}^n \\rightarrow \\B{R}^m` to denote the\n:ref:`glossary@AD Function` corresponding to *f* ; i.e,\ngiven :math:`x \\in \\B{R}^n`, :math:`F(x)` is defined by\n\n    *F* ( *x* ) = *f* . ``Forward`` (0, *x* )\n\nsee :ref:`forward_zero-name` .\nIf :math:`x` is such that\nall the algorithm :ref:`comparison<Compare-name>` operations\nhave the same result as when the algorithm was taped,\nThe function :math:`F(x)` and the algorithm will have the same values.\n(This is a sufficient, but not necessary condition).\n\nf\n*\nIn the ``compare_change_number`` and ``compare_change_op_index``\nsyntax, the object *f* has prototype\n\n    ``const ADFun`` < *Base* > *f*\n\nIn the ``compare_change_count``\nsyntax, the object *f* has prototype\n\n    ``ADFun`` < *Base* > *f*\n\ncount\n*****\nThe argument *count* has prototype\n\n    *size_t* ``count``\n\nIt specifies which comparison change should correspond to the\ninformation stored in *f* during subsequent calls to\n:ref:`forward_zero-name` ; i.e.,\n\n    *f* . ``Forward`` (0, *x* )\n\nFor example, if *count*  == 1 ,\nthe operator index corresponding to the first comparison change\nwill be stored.\nThis is the default value used if *count* is not specified.\n\nSpeed\n=====\nThe special case where *count* == 0 , should be faster because\nthe comparisons are not checked during\n\n    *f* . ``Forward`` (0, *x* )\n\nnumber\n******\nThe return value *number* has prototype\n\n    ``size_t`` *number*\n\nIf *count* is non-zero,\n*number* is the number of\n``AD`` < *Base* > :ref:`comparison<Compare-name>` operations,\ncorresponding to the previous call to\n\n    *f* . ``Forward`` (0, *x* )\n\nthat have a different result for this value of *x*\nthan the value used when *f* was created by taping an algorithm.\nIf *count* is zero,\nor if no calls to *f* . ``Forward`` (0, *x* ) follow the previous\nsetting of *count* ,\n*number* is zero.\n\nDiscussion\n==========\nIf *count* and *number* are non-zero,\nyou may want to re-tape the algorithm with the\n:ref:`independent variables<glossary@Tape@Independent Variable>`\nequal to the values in *x* ,\nso the AD operation sequence properly represents the algorithm\nfor this value of independent variables.\nOn the other hand, re-taping the AD operation sequence usually takes\nsignificantly more time than evaluation using :ref:`forward_zero-name` .\nIf the functions values have not changed (see :ref:`FunCheck-name` )\nit may not be worth re-taping a new AD operation sequence.\n\nop_index\n********\nThe return value *op_index* has prototype\n\n    ``size_t`` *op_index*\n\nIf *count* is non-zero,\n*op_index* is the operator index corresponding the\n*count* -th comparison change during the previous call to\n\n    *f* . ``Forward`` (0, *x* )\n\nIf *count* is greater than the corresponding\n*number* , there is no such comparison change and *op_index*\nwill also be zero.\nIf *count* is zero,\nif the function *f* has been :ref:`optimized<optimize-name>` ,\nor if no calls to *f* . ``Forward`` (0, *x* ) follow the previous\nsetting of *count* ,\n*op_index* is zero.\n\nPurpose\n=======\nThe operator index can be used to generate an error during the taping\nprocess so that the corresponding algorithm can be inspected.\nIn some cases, it is possible to re-design this part of the\nalgorithm to avoid the particular comparison operation.\nFor example, using an :ref:`conditional expression<CondExp-name>`\nmay be appropriate in some cases.\nSee :ref:`Independent@abort_op_index` in the syntax\n\n    ``Independent`` ( *x* , *abort_op_index* )\n\n{xrst_toc_hidden\n    example/compare_change/compare_change.cpp\n}\nExample\n*******\n:ref:`compare_change.cpp-name`\ncontains an example and test of this operation.\n\n{xrst_end compare_change}\n"
  },
  {
    "path": "include/cppad/core/forward/devel.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin devel_forward dev}\n\nDevel: Forward Mode\n###################\n\nContents\n********\n{xrst_toc_table\n    include/cppad/core/forward/forward.hpp\n}\n\n{xrst_end devel_forward}\n"
  },
  {
    "path": "include/cppad/core/forward/forward.hpp",
    "content": "# ifndef CPPAD_CORE_FORWARD_FORWARD_HPP\n# define CPPAD_CORE_FORWARD_FORWARD_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n// documented after Forward but included here so easy to see\n# include <cppad/core/capacity_order.hpp>\n# include <cppad/core/num_skip.hpp>\n# include <cppad/core/check_for_nan.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n\n/*\n--------------------------------------- ---------------------------------------\n{xrst_begin devel_forward_order dev}\n{xrst_spell\n    pri\n    xq\n    yq\n}\n\nMultiple orders, one direction, forward mode Taylor coefficients\n################################################################\n\nSyntax\n******\n| *yq* = *f* . ``Forward`` ( *q* , *xq* , *s*  )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_FORWARD_ORDER\n    // END_FORWARD_ORDER\n}\n\nBase\n****\nThe type used during the forward mode computations; i.e., the corresponding\nrecording of operations used the type AD<Base>.\n\nBaseVector\n**********\nis a Simple Vector class with elements of type Base.\n\nq\n*\nis the highest order for this forward mode computation; i.e.,\nafter this calculation there will be *q* +1\nTaylor coefficients per variable.\n\nxq\n**\ncontains Taylor coefficients for the independent variables.\nThe size of *xq* must either be *n* or ( *q* +1)* *n* ,\nWe define *p* = *q* + 1 *- xq.size* ()/ *n* .\nFor *j* = 0 , ... , *n-1* ,\n*k* = 0, ... , *q* ,\n*xq* [ ( *q* +1)* *j* + *k - p* ]\nis the k-th order coefficient for the j-th independent variable.\n\ns\n*\nIs the stream where output corresponding to PriOp operations will written.\n\nyq\n**\ncontains Taylor coefficients for the dependent variables.\nThe size of the return value *yq*\nhas size *m* * ( *q* +1 *-p* ) .\nFor *i* = 0, ... , *m-1* ,\n*k* = *p* , ..., *q* ,\n*yq* [( *q* +1 *-p* )* *i* + ( *k-p* )]\nis the k-th order coefficient for the i-th dependent variable.\n\ntaylor\\_\n********\nThe Taylor coefficients up to order *p-1* are inputs\nand the coefficients from order *p* through *q* are outputs.\nLet *N* = *num_var_tape_* , and\n*C* = *cap_order_taylor_* .\nNote that for\n*i* = 1 , ..., *N-1* ,\n*k* = 0 , ..., *q* ,\n*taylor_* [ *C* * *i* + *k* ]\nis the k-th order coefficient,\nfor the i-th variable on the tape.\n(The first independent variable has index one on the tape\nand there is no variable with index zero.)\n\n{xrst_end devel_forward_order}\n*/\n// BEGIN_FORWARD_ORDER\ntemplate <class Base, class RecBase>\ntemplate <class BaseVector>\nBaseVector ADFun<Base,RecBase>::Forward(\n    size_t              q         ,\n    const BaseVector&   xq        ,\n             std::ostream& s         )\n// END_FORWARD_ORDER\n{\n    // used to identify the RecBase type in calls to sweeps\n    RecBase not_used_rec_base(0.0);\n\n    // temporary indices\n    size_t i, j, k;\n\n    // number of independent variables\n    size_t n = ind_taddr_.size();\n\n    // number of dependent variables\n    size_t m = dep_taddr_.size();\n\n    // check Vector is Simple Vector class with Base type elements\n    CheckSimpleVector<Base, BaseVector>();\n\n    // check size of xq\n    CPPAD_ASSERT_KNOWN(\n        size_t(xq.size()) == n || size_t(xq.size()) == n*(q+1),\n        \"Forward(q, xq): xq.size() is not equal n or n*(q+1)\"\n    );\n\n    // p = lowest order we are computing\n    size_t p = q + 1 - size_t(xq.size()) / n;\n    CPPAD_ASSERT_UNKNOWN( p == 0 || p == q );\n\n    // check one order case\n    CPPAD_ASSERT_KNOWN(\n        q <= num_order_taylor_ || p == 0,\n        \"Forward(q, xq): Number of Taylor coefficient orders stored in this\"\n        \" ADFun\\nis less than q and xq.size() != n*(q+1).\"\n    );\n\n    // if p > 1, the previous number of directions must be one\n    CPPAD_ASSERT_KNOWN(\n        p <= 1 || num_direction_taylor_ == 1,\n        \"Forward(q, xq): computing order q >= 2\"\n        \" and number of directions is not one.\"\n        \"\\nMust use Forward(q, r, xq) for this case\"\n    );\n\n    // does taylor_ need more orders or fewer directions\n    if( (cap_order_taylor_ <= q) || (num_direction_taylor_ != 1) )\n    {   if( p == 0 )\n        {   // no need to copy old values during capacity_order\n            num_order_taylor_ = 0;\n        }\n        else\n            num_order_taylor_ = q;\n        size_t c = std::max<size_t>(q + 1, cap_order_taylor_);\n        size_t r = 1;\n        capacity_order(c, r);\n    }\n    CPPAD_ASSERT_UNKNOWN( cap_order_taylor_ > q );\n    CPPAD_ASSERT_UNKNOWN( num_direction_taylor_ == 1 );\n\n    // short hand notation for order capacity\n    size_t C = cap_order_taylor_;\n\n    // The optimizer may skip a step that does not affect dependent variables.\n    // Initializing zero order coefficients avoids following valgrind warning:\n    // \"Conditional jump or move depends on uninitialised value(s)\".\n    for(j = 0; j < num_var_tape_; j++)\n    {   for(k = p; k <= q; k++)\n            taylor_[C * j + k] = CppAD::numeric_limits<Base>::quiet_NaN();\n    }\n\n    // set Taylor coefficients for independent variables\n# ifndef NDEBUG\n    for(j = 0; j < n; j++)\n    {   // ind_taddr_[j] is index of j-th independent variable\n        CPPAD_ASSERT_UNKNOWN( ind_taddr_[j] < num_var_tape_  );\n        // ind_taddr_[j] is operator taddr for j-th independent variable\n        CPPAD_ASSERT_UNKNOWN( play_.GetOp( ind_taddr_[j] ) == local::InvOp );\n    }\n# endif\n    if( p == q )\n    {   CPPAD_ASSERT_UNKNOWN( xq.size() == n );\n        for(j = 0; j < n; ++j)\n            taylor_[ C * ind_taddr_[j] + q] = xq[j];\n    }\n    else\n    {   CPPAD_ASSERT_UNKNOWN( xq.size() == (q + 1) * n );\n        for(j = 0; j < n; ++j)\n        {   for(k = 0; k <= q; k++)\n                taylor_[ C * ind_taddr_[j] + k] = xq[ (q+1)*j + k];\n        }\n    }\n    //\n    // evaluate the derivatives\n    CPPAD_ASSERT_UNKNOWN( cskip_op_.size() == play_.num_var_op() );\n    CPPAD_ASSERT_UNKNOWN( load_op2var_.size()  == play_.num_var_load() );\n    if( q == 0 )\n    {   bool print = true;\n        local::sweep::forward_0(\n            not_used_rec_base,\n            &play_,\n            num_var_tape_,\n            C,\n            cskip_op_.data(),\n            load_op2var_,\n            compare_change_count_,\n            compare_change_number_,\n            compare_change_op_index_,\n            s,\n            print,\n            taylor_.data()\n        );\n    }\n    else\n    {   bool print = true;\n        local::sweep::forward_any(\n            not_used_rec_base,\n            &play_,\n            num_var_tape_,\n            C,\n            cskip_op_.data(),\n            load_op2var_,\n            compare_change_count_,\n            compare_change_number_,\n            compare_change_op_index_,\n            s,\n            print,\n            p,\n            q,\n            taylor_.data()\n        );\n    }\n\n    // return Taylor coefficients for dependent variables\n    BaseVector yq;\n    if( p == q )\n    {   yq.resize(m);\n        for(i = 0; i < m; i++)\n        {   CPPAD_ASSERT_UNKNOWN( dep_taddr_[i] < num_var_tape_  );\n            yq[i] = taylor_[ C * dep_taddr_[i] + q];\n        }\n    }\n    else\n    {   yq.resize(m * (q+1) );\n        for(i = 0; i < m; i++)\n        {   for(k = 0; k <= q; k++)\n                yq[ (q+1) * i + k] =\n                    taylor_[ C * dep_taddr_[i] + k ];\n        }\n    }\n# ifndef NDEBUG\n    if( check_for_nan_ )\n    {   bool ok = true;\n        size_t index = m;\n        if( p == 0 )\n        {   for(i = 0; i < m; i++)\n            {   // Visual Studio 2012, CppAD required in front of isnan ?\n                if( CppAD::isnan( yq[ (q+1) * i + 0 ] ) )\n                {   ok    = false;\n                    if( index == m )\n                        index = i;\n                }\n            }\n        }\n        if( ! ok )\n        {   CPPAD_ASSERT_UNKNOWN( index < m );\n            //\n            CppAD::vector<Base> x0(n);\n            for(j = 0; j < n; j++)\n                x0[j] = taylor_[ C * ind_taddr_[j] + 0 ];\n            std::string  file_name;\n            put_check_for_nan(x0, file_name);\n            std::stringstream ss;\n            ss <<\n            \"yq = f.Forward(q, xq): a zero order Taylor coefficient is nan.\\n\"\n            \"Corresponding independent variables vector was written \"\n            \"to binary a file.\\n\"\n            \"vector_size = \" << n << \"\\n\" <<\n            \"file_name = \" << file_name << \"\\n\" <<\n            \"index = \" << index << \"\\n\";\n            // ss.str() returns a string object with a copy of the current\n            // contents in the stream buffer.\n            std::string msg_str       = ss.str();\n            // msg_str.c_str() returns a pointer to the c-string\n            // representation of the string object's value.\n            const char* msg_char_star = msg_str.c_str();\n            ErrorHandler::Call(\n                true,\n                __LINE__,\n                __FILE__,\n                \"if( CppAD::isnan( yq[ (q+1) * index + 0 ] )\",\n                msg_char_star\n            );\n        }\n        CPPAD_ASSERT_KNOWN(ok,\n            \"with the value nan.\"\n        );\n        if( 0 < q )\n        {   for(i = 0; i < m; i++)\n            {   for(k = p; k <= q; k++)\n                {   // Studio 2012, CppAD required in front of isnan ?\n                    ok &= ! CppAD::isnan( yq[ (q+1-p)*i + k-p ] );\n                }\n            }\n        }\n        CPPAD_ASSERT_KNOWN(ok,\n        \"yq = f.Forward(q, xq): has a non-zero order Taylor coefficient\\n\"\n        \"with the value nan (but zero order coefficients are not nan).\"\n        );\n    }\n# endif\n\n    // now we have q + 1  taylor_ coefficient orders per variable\n    num_order_taylor_ = q + 1;\n\n    return yq;\n}\n/*\n--------------------------------------- ---------------------------------------\n{xrst_begin devel_forward_dir dev}\n{xrst_spell\n    xq\n    yq\n}\n\nOne order, multiple directions, forward mode Taylor coefficients\n################################################################\n\nSyntax\n******\n\n    *yq* = *f* . ``Forward`` ( *q* , *r* , *xq* )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_FORWARD_DIR\n    // END_FORWARD_DIR\n}\n\nBase\n****\nThe type used during the forward mode computations; i.e., the corresponding\nrecording of operations used the type AD<Base>.\n\nBaseVector\n**********\nis a Simple Vector class with elements of type Base.\n\nq\n*\nis the order for this forward mode computation,\n*q > 0* .\nThere must be at least *q* Taylor coefficients\nper variable before this call.\nAfter this call there will be *q* +1\nTaylor coefficients per variable.\n\nr\n*\nis the number of directions for this calculation.\nIf *q* != 1 , r must be the same as in the previous\ncall to Forward where q was equal to one.\n\nxq\n**\ncontains Taylor coefficients for the independent variables.\nThe size of xq must either be *r* * *n* ,\nFor *j* = 0 , ... , *n-1* ,\n*ell* = 0, ... , *r-1* ,\n*xq* [ ( *r* * *j* + *ell* ]\nis the q-th order coefficient for the j-th independent variable\nand the ell-th direction.\n\nyq\n**\ncontains Taylor coefficients for the dependent variables.\nThe size of *y* is *r* * *m* .\nFor *i* = 0, ... , *m-1* ,\n*ell* = 0, ... , *r-1* ,\n*yq* [ *r* * *i* + *ell* ]\nis the q-th order coefficient for the i-th dependent variable\nand the ell-th direction.\n\ntaylor\\_\n********\nThe Taylor coefficients up to order *q-1* are inputs\nand the coefficients of order q are outputs.\nLet *N* = *num_var_tape_* , and\n*C* = *cap_order_taylor_* .\nNote that for\n*i* = 1 , ..., *N-1* ,\n*taylor_* [ ( *C-1* )* *r* * *i* + *i* + 0 ]\nis the zero order coefficient,\nfor the i-th variable, and all directions.\nFor *i* = 1 , ..., *N-1* ,\n*k* = 1 , ..., *q* ,\n*ell* = 0 , ..., *r-1* ,\n*taylor_* [ ( *C-1* )* *r* * *i* + *i* + ( *k-1* )* *r* + *ell* + 1 ]\nis the k-th order coefficient,\nfor the i-th variable, and ell-th direction.\n(The first independent variable has index one on the tape\nand there is no variable with index zero.)\n\n{xrst_end devel_forward_dir}\n*/\n// BEGIN_FORWARD_DIR\ntemplate <class Base, class RecBase>\ntemplate <class BaseVector>\nBaseVector ADFun<Base,RecBase>::Forward(\n    size_t              q         ,\n    size_t              r         ,\n    const BaseVector&   xq        )\n// END_FORWARD_DIR\n{\n    // used to identify the RecBase type in calls to sweeps\n    RecBase not_used_rec_base(0.0);\n\n    // temporary indices\n    size_t i, j, ell;\n\n    // number of independent variables\n    size_t n = ind_taddr_.size();\n\n    // number of dependent variables\n    size_t m = dep_taddr_.size();\n\n    // check Vector is Simple Vector class with Base type elements\n    CheckSimpleVector<Base, BaseVector>();\n\n    CPPAD_ASSERT_KNOWN( q > 0, \"Forward(q, r, xq): q == 0\" );\n    CPPAD_ASSERT_KNOWN(\n        size_t(xq.size()) == r * n,\n        \"Forward(q, r, xq): xq.size() is not equal r * n\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        q <= num_order_taylor_ ,\n        \"Forward(q, r, xq): Number of Taylor coefficient orders stored in\"\n        \" this ADFun is less than q\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        q == 1 || num_direction_taylor_ == r ,\n        \"Forward(q, r, xq): q > 1 and number of Taylor directions r\"\n        \" is not same as previous Forward(1, r, xq)\"\n    );\n\n    // does taylor_ need more orders or new number of directions\n    if( cap_order_taylor_ <= q || num_direction_taylor_ != r )\n    {   if( num_direction_taylor_ != r )\n            num_order_taylor_ = 1;\n\n        size_t c = std::max<size_t>(q + 1, cap_order_taylor_);\n        capacity_order(c, r);\n    }\n    CPPAD_ASSERT_UNKNOWN( cap_order_taylor_ > q );\n    CPPAD_ASSERT_UNKNOWN( num_direction_taylor_ == r )\n\n    // short hand notation for order capacity\n    size_t c = cap_order_taylor_;\n\n    // set Taylor coefficients for independent variables\n    for(j = 0; j < n; j++)\n    {   CPPAD_ASSERT_UNKNOWN( ind_taddr_[j] < num_var_tape_  );\n\n        // ind_taddr_[j] is operator taddr for j-th independent variable\n        CPPAD_ASSERT_UNKNOWN( play_.GetOp( ind_taddr_[j] ) == local::InvOp );\n\n        for(ell = 0; ell < r; ell++)\n        {   size_t index = ((c-1)*r + 1)*ind_taddr_[j] + (q-1)*r + ell + 1;\n            taylor_[ index ] = xq[ r * j + ell ];\n        }\n    }\n\n    // evaluate the derivatives\n    CPPAD_ASSERT_UNKNOWN( cskip_op_.size() == play_.num_var_op() );\n    CPPAD_ASSERT_UNKNOWN( load_op2var_.size()  == play_.num_var_load() );\n    local::sweep::forward_dir(\n        not_used_rec_base,\n        &play_,\n        num_var_tape_,\n        c,\n        cskip_op_.data(),\n        load_op2var_,\n        q,\n        r,\n        taylor_.data()\n    );\n\n    // return Taylor coefficients for dependent variables\n    BaseVector yq;\n    yq.resize(r * m);\n    for(i = 0; i < m; i++)\n    {   CPPAD_ASSERT_UNKNOWN( dep_taddr_[i] < num_var_tape_  );\n        for(ell = 0; ell < r; ell++)\n        {   size_t index = ((c-1)*r + 1)*dep_taddr_[i] + (q-1)*r + ell + 1;\n            yq[ r * i + ell ] = taylor_[ index ];\n        }\n    }\n# ifndef NDEBUG\n    if( check_for_nan_ )\n    {   bool ok = true;\n        for(i = 0; i < m; i++)\n        {   for(ell = 0; ell < r; ell++)\n            {   // Studio 2012, CppAD required in front of isnan ?\n                ok &= ! CppAD::isnan( yq[ r * i + ell ] );\n            }\n        }\n        CPPAD_ASSERT_KNOWN(ok,\n        \"yq = f.Forward(q, r, xq): has a non-zero order Taylor coefficient\\n\"\n        \"with the value nan (but zero order coefficients are not nan).\"\n        );\n    }\n# endif\n\n    // now we have q + 1  taylor_ coefficient orders per variable\n    num_order_taylor_ = q + 1;\n\n    return yq;\n}\n\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/forward/forward_dir.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin forward_dir}\n{xrst_spell\n    xk\n    xq\n    yq\n}\n\nMultiple Directions Forward Mode\n################################\n\nSyntax\n******\n| *yq* = *f* . ``Forward`` ( *q* , *r* , *xq* )\n\nPurpose\n*******\nWe use :math:`F : \\B{R}^n \\rightarrow \\B{R}^m` to denote the\n:ref:`glossary@AD Function` corresponding to *f* .\nGiven a function :math:`X : \\B{R} \\rightarrow \\B{R}^n`,\ndefined by its\n:ref:`Taylor coefficients<glossary@Taylor Coefficient>` ,\nforward mode computes the Taylor coefficients for the function\n\n.. math::\n\n    Y (t) = F [ X(t) ]\n\nThis version of forward mode computes multiple directions as the same\ntime (reducing the number of passes through the tape). This requires more\nmemory, but might be faster in some cases.\n\nReverse Mode\n************\nReverse mode for multiple directions has not yet been implemented.\nIf you have speed tests that indicate that multiple direction forward\nmode is faster, and you want to try multiple direction reverse mode,\ncontact the CppAD project manager.\n\nNotation\n********\n\nn\n=\nWe use *n* to denote the dimension of the\n:ref:`fun_property@Domain` space for *f* .\n\nm\n=\nWe use *m* to denote the dimension of the\n:ref:`fun_property@Range` space for *f* .\n\nf\n*\nThe :ref:`ADFun-name` object *f* has prototype\n\n    ``ADFun`` < *Base* > *f*\n\nNote that the :ref:`ADFun-name` object *f* is not ``const`` .\nAfter this call we will have\n\n| |tab| *f* . ``size_order`` ()     == *q*  + 1\n| |tab| *f* . ``size_direction`` () == *r*\n\nq\n*\nThis argument has prototype\n\n    ``size_t`` *q*\n\nIt specifies the order of Taylor Coefficient that we are calculating\nand must be greater than zero.\nThe zero order coefficients can only have one direction computed\nand stored in *f* so use :ref:`forward_zero-name`\nto compute the zero order coefficients.\n\nr\n*\nThis argument has prototype\n\n    ``size_t`` *r*\n\nIt specifies the number of directions that are computed together.\nIf ( *r*  == 1 ), you are only using one direction and\n:ref:`forward_order-name` is simpler, and should be faster,\nthan this more general case.\n\nxq\n**\nThe argument *xq* has prototype\n\n    ``const`` *Vector* & *xq*\n\nand its size must be *n* * *r*\n(see :ref:`forward_dir@Vector` below).\nFor :math:`\\ell = 0 , \\ldots , r-1`,\n:math:`j = 0 , \\ldots , n-1`,\nthe *j*-th component of the *q*-th order Taylor coefficient\nfor :math:`X_\\ell (t)` is defined by\n\n|tab| :math:`x_j^{(q),\\ell} =` *xq* [ *r* * *j* + *ell*  ]\n\nZero Order\n**********\nFor :math:`j = 0 , \\ldots , n-1`,\nthe *j*-th component of the zero order Taylor coefficient\nfor :math:`X_\\ell (t)` is defined by\n\n|tab| :math:`x_j^{(0)} =` *xk* [ *j*  ]\nwhere *xk* corresponds to the previous call\n\n    *f* . ``Forward`` ( *k* , *xk* )\n\nwith *k*  = 0 .\n\nNon-Zero Lower Orders\n*********************\nFor :math:`\\ell = 0 , \\ldots , r-1`,\n:math:`j = 0 , \\ldots , n-1`,\n:math:`k = 1, \\ldots , q-1`,\nthe *j*-th component of the *k*-th order Taylor coefficient\nfor :math:`X_\\ell (t)` is defined by\n\n|tab| :math:`x_j^{(k),\\ell} =` *xk* [ *r* * *j* + *ell*  ]\nwhere *xk* corresponds to the previous call\n\n    *f* . ``Forward`` ( *k* , *r* , *xk* )\n\nNote that *r* must have the same value in this previous call.\n\nX(t)\n****\nFor :math:`\\ell = 0 , \\ldots , r-1`, the function\n:math:`X_\\ell : \\B{R} \\rightarrow \\B{R}^n` is defined using\nthe Taylor coefficients :math:`x^{(k),\\ell} \\in \\B{R}^n`:\n\n.. math::\n\n    X_\\ell (t) = x^{(0)}  + x^{(1),\\ell} * t^1 + \\cdots +  x^{(q),\\ell} t^q\n\nNote that the *k*-th derivative of :math:`X_\\ell (t)` is related to\nits Taylor coefficients by\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        x^{(0)}       & = & X_\\ell (0)\n        \\\\\n        x^{(k), \\ell} & = & \\frac{1}{k !} X_\\ell^{(k)} (0)\n    \\end{eqnarray}\n\nfor :math:`k = 1 , \\ldots , q`.\n\nY(t)\n****\nFor :math:`\\ell = 0 , \\ldots , r-1`, the function\n:math:`Y_\\ell : \\B{R} \\rightarrow \\B{R}^m`  is defined by\n:math:`Y_\\ell (t) = F[ X_\\ell (t) ]`.\nWe use :math:`y^{(0)}` for the zero order coefficient\nand :math:`y^{(k),\\ell} \\in \\B{R}^m` to denote the\nhigher order coefficients; i.e.,\n\n.. math::\n\n    Y_\\ell (t) = y^{(0)} + y^{(1),\\ell} * t^1 + \\cdots + y^{(q),\\ell} * t^q\n    + o( t^q )\n\nwhere :math:`o( t^q ) * t^{-q} \\rightarrow 0` as :math:`t \\rightarrow 0`.\nNote that the *k*-th derivative of :math:`Y_\\ell (t)` is related to\nits Taylor coefficients by\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        y^{(0)}       & = & Y_\\ell (0)\n        \\\\\n        y^{(k), \\ell} & = & \\frac{1}{k !} Y_\\ell^{(k)} (0)\n    \\end{eqnarray}\n\nfor :math:`k = 1 , \\ldots , q`.\n\nyq\n**\nThe argument *yq* has prototype\n\n    *Vector* *yq*\n\nand its size is *m* * *r*\n(see :ref:`forward_dir@Vector` below).\nFor :math:`\\ell = 0 , \\ldots , r-1`,\n:math:`i = 0 , \\ldots , m-1`,\nthe *i*-th component of the *q*-th order Taylor coefficient\nfor :math:`Y_\\ell (t)` is given by\n\n|tab| :math:`y_i^{(q),\\ell} =` *yq* [ *r* * *i* + *ell*  ]\n\nVector\n******\nThe type *Vector* must be a :ref:`SimpleVector-name` class with\n:ref:`elements of type<SimpleVector@Elements of Specified Type>`\n*Base* .\nThe routine :ref:`CheckSimpleVector-name` will generate an error message\nif this is not the case.\n{xrst_toc_hidden\n    example/general/forward_dir.cpp\n}\nExample\n*******\nThe file\n:ref:`forward_dir.cpp-name`\ncontains an example and test using one order (multiple orders).\nThey return true if they succeed and false otherwise.\n\n{xrst_end forward_dir}\n"
  },
  {
    "path": "include/cppad/core/forward/forward_one.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin forward_one}\n\nFirst Order Forward Mode: Derivative Values\n###########################################\n\nSyntax\n******\n| *y1* = *f* . ``Forward`` (1, *x1* )\n\nPurpose\n*******\nWe use :math:`F : \\B{R}^n \\rightarrow \\B{R}^m` to denote the\n:ref:`glossary@AD Function` corresponding to *f* .\nThe result of the syntax above is\n\n.. math::\n\n    y1 = F^{(1)} (x0) * x1\n\nwhere :math:`F^{(1)} (x0)` is the Jacobian of :math:`F`\nevaluated at *x0* .\n\nf\n*\nThe object *f* has prototype\n\n    ``ADFun`` < *Base* > *f*\n\nNote that the :ref:`ADFun-name` object *f* is not ``const`` .\nBefore this call to ``Forward`` , the value returned by\n\n    *f* . ``size_order`` ()\n\nmust be greater than or equal one.\nAfter this call it will be will be two (see :ref:`size_order-name` ).\n\nx0\n**\nThe vector *x0* in the formula\n\n.. math::\n\n    y1 = F^{(1)} (x0) * x1\n\ncorresponds to the previous call to :ref:`forward_zero-name`\nusing this ADFun object *f* ; i.e.,\n\n    *f* . ``Forward`` (0, *x0* )\n\nIf there is no previous call with the first argument zero,\nthe value of the :ref:`Independent-name` variables\nduring the recording of the AD sequence of operations is used\nfor *x0* .\n\nx1\n**\nThe argument *x1* has prototype\n\n    ``const`` *Vector* & *x1*\n\n(see :ref:`forward_one@Vector` below)\nand its size must be equal to *n* , the dimension of the\n:ref:`fun_property@Domain` space for *f* .\n\nVector\n******\nThe type *Vector* must be a :ref:`SimpleVector-name` class with\n:ref:`elements of type<SimpleVector@Elements of Specified Type>`\n*Base* .\nThe routine :ref:`CheckSimpleVector-name` will generate an error message\nif this is not the case.\n\nExample\n*******\nThe file\n:ref:`forward.cpp-name`\ncontains an example and test of this operation.\n\nSpecial Case\n************\nThis is special case of :ref:`forward_order-name` where\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    Y(t) & = & F[ X(t) ]\n    \\\\\n    X(t) & = & x^{(0)} t^0 + x^{(1)} * t^1 + \\cdots, + x^{(q)} * t^q + o( t^q )\n    \\\\\n    Y(t) & = & y^{(0)} t^0 + y^{(1)} * t^1 + \\cdots, + y^{(q)} * t^q + o( t^q )\n    \\end{eqnarray}\n\nand :math:`o( t^q ) * t^{-q} \\rightarrow 0` as :math:`t \\rightarrow 0`.\nFor this special case, :math:`q = 1`,\n:math:`x^{(0)}` = *x0* ,\n:math:`x^{(1)}` = *x1* ,\n:math:`X(t) = x^{(0)} + x^{(1)} t`, and\n\n.. math::\n\n    y^{(0)} + y^{(1)} t  = F [ x^{(0)} + x^{(1)} t ] + o(t)\n\nTaking the derivative with respect to :math:`t`, at :math:`t = 0`,\nwe obtain\n\n.. math::\n\n    y^{(1)} = F^{(1)} [ x^{(0)} ] x^{(1)}\n\nwhich agrees with the specifications for\n*y1* in the :ref:`forward_one@Purpose` above.\n\n{xrst_end forward_one}\n"
  },
  {
    "path": "include/cppad/core/forward/forward_order.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin forward_order}\n{xrst_spell\n    cout\n    dx\n    ostream\n    xk\n    xq\n    yq\n}\n\nMultiple Order Forward Mode\n###########################\n\nSyntax\n******\n| *yq* = *f* . ``Forward`` ( *q* , *xq*  )\n| *yq* = *f* . ``Forward`` ( *q* , *xq* , *s* )\n\nPurpose\n*******\nWe use :math:`F : \\B{R}^n \\rightarrow \\B{R}^m` to denote the\n:ref:`glossary@AD Function` corresponding to *f* .\nGiven a function :math:`X : \\B{R} \\rightarrow \\B{R}^n`,\ndefined by its\n:ref:`Taylor coefficients<glossary@Taylor Coefficient>` ,\nforward mode computes the Taylor coefficients for the function\n\n.. math::\n\n    Y (t) = F [ X(t) ]\n\nFunction Values\n===============\nIf you are using forward mode to compute values for :math:`F(x)`,\n:ref:`forward_zero-name` is simpler to understand\nthan this explanation of the general case.\n\nDerivative Values\n=================\nIf you are using forward mode to compute values for :math:`F^{(1)} (x) * dx`,\n:ref:`forward_one-name` is simpler to understand\nthan this explanation of the general case.\n\nNotation\n********\n\nn\n=\nWe use *n* to denote the dimension of the\n:ref:`fun_property@Domain` space for *f* .\n\nm\n=\nWe use *m* to denote the dimension of the\n:ref:`fun_property@Range` space for *f* .\n\nf\n*\nThe :ref:`ADFun-name` object *f* has prototype\n\n    ``ADFun`` < *Base* > *f*\n\nNote that the :ref:`ADFun-name` object *f* is not ``const`` .\nAfter this call we will have\n\n| |tab| *f* . ``size_order`` ()     == *q*  + 1\n| |tab| *f* . ``size_direction`` () == 1\n\nOne Order\n*********\nIf *xq* . ``size`` () == *n* ,\nthen we are only computing one order.\nIn this case, before this call we must have\n\n| |tab| *f* . ``size_order`` ()     >= *q*\n| |tab| *f* . ``size_direction`` () == 1\n\nq\n*\nThe argument *q* has prototype\n\n    ``size_t`` *q*\n\nand specifies the highest order of the Taylor coefficients to be calculated.\n\nxq\n**\nThe argument *xq* has prototype\n\n    ``const`` *BaseVector* & *xq*\n\n(see :ref:`forward_order@BaseVector` below).\nAs above, we use *n* to denote the dimension of the\n:ref:`fun_property@Domain` space for *f* .\nThe size of *xq* must be either *n* or\n*n* * ( *q* +1) .\nAfter this call we will have\n\n    *f* . ``size_order`` ()     == *q*  + 1\n\nOne Order\n=========\nIf *xq* . ``size`` () == *n* ,\nthe *q*-th order Taylor coefficient for :math:`X(t)`\nis defined by\n\n|tab| :math:`x^{(q)} =` *xq* .\nFor :math:`k = 0 , \\ldots , q-1`,\nthe Taylor coefficient :math:`x^{(k)}`\nis defined by *xk* in the previous call to\n\n    *f* . ``Forward`` ( *k* , *xk* )\n\nMultiple Orders\n===============\nIf *xq* . ``size`` () == *n* * ( *q* +1) ,\nFor :math:`k = 0 , \\ldots , q`,\n:math:`j = 0 , \\ldots , n-1`,\nthe *j*-th component of the *k*-th order Taylor coefficient\nfor :math:`X(t)` is defined by\n\n|tab| :math:`x_j^{(k)} =` *xq* [ ( *q* +1) * *j* + *k*  ]\n\nRestrictions\n============\nNote if *f* uses :ref:`atomic_one-name` functions,\nthe size of *xq* must be *n* .\n\ns\n*\nIf the argument *s* is not present, ``std::cout``\nis used in its place.\nOtherwise, this argument has prototype\n\n    ``std::ostream&`` *s*\n\nIf order zero is begin calculated,\n*s* specifies where the output corresponding to :ref:`PrintFor-name`\nwill be written.\nIf order zero is not being calculated,\n*s* is not used\n\nX(t)\n****\nThe function\n:math:`X : \\B{R} \\rightarrow \\B{R}^n` is defined using\nthe Taylor coefficients :math:`x^{(k)} \\in \\B{R}^n`:\n\n.. math::\n\n    X(t) = x^{(0)} * t^0 + x^{(1)} * t^1 + \\cdots + x^{(q)} * t^q\n\nNote that for :math:`k = 0 , \\ldots , q`,\nthe *k*-th derivative of :math:`X(t)` is related to the\nTaylor coefficients by the equation\n\n.. math::\n\n    x^{(k)} = \\frac{1}{k !} X^{(k)} (0)\n\nY(t)\n****\nThe function\n:math:`Y : \\B{R} \\rightarrow \\B{R}^m` is defined by\n:math:`Y(t) = F[ X(t) ]`.\nWe use :math:`y^{(k)} \\in \\B{R}^m`\nto denote the *k*-th order Taylor coefficient of :math:`Y(t)`; i.e.,\n\n.. math::\n\n    Y(t) = y^{(0)} * t^0 + y^{(1)} * t^1 + \\cdots + y^{(q)} * t^q + o( t^q )\n\nwhere :math:`o( t^q ) * t^{-q} \\rightarrow 0` as :math:`t \\rightarrow 0`.\nNote that :math:`y^{(k)}` is related to\nthe *k*-th derivative of :math:`Y(t)` by the equation\n\n.. math::\n\n    y^{(k)} = \\frac{1}{k !} Y^{(k)} (0)\n\nyq\n**\nThe return value *yq* has prototype\n\n    *BaseVector* *yq*\n\n(see :ref:`forward_order@BaseVector` below).\n\nOne Order\n=========\nIf *xq* . ``size`` () == *n* ,\nthe vector *yq* has size *m* .\nThe *q*-th order Taylor coefficient for :math:`Y(t)`\nis returned as\n\n    *yq*\n\n:math:`= y^{(q)}`.\n\nMultiple Orders\n===============\nIf *xq* . ``size`` () == *n* * ( *q* +1) ,\nthe vector *yq* has size *m* * ( *q* +1) .\nFor :math:`k = 0 , \\ldots , q`,\nfor :math:`i = 0 , \\ldots , m-1`,\nthe *i*-th component of the *k*-th order Taylor coefficient\nfor :math:`Y(t)` is returned as\n\n    ``yq`` [ ( ``q`` +1) * ``i`` + ``k``  ]\n\n:math:`= y_i^{(k)}`\n\nBaseVector\n**********\nThe type *BaseVector* must be a :ref:`SimpleVector-name` class with\n:ref:`elements of type<SimpleVector@Elements of Specified Type>`\n*Base* .\nThe routine :ref:`CheckSimpleVector-name` will generate an error message\nif this is not the case.\n\nZero Order\n**********\nThe case where\n:math:`q = 0` and *xq* . ``size`` () == *n* ,\ncorresponds to the zero order\n:ref:`forward_zero@Special Case` .\n\nFirst Order\n***********\nThe case where\n:math:`q = 1` and *xq* . ``size`` () == *n* ,\ncorresponds to the first order\n:ref:`forward_one@Special Case` .\n\nSecond Order\n************\nThe case where\n:math:`q = 2` and *xq* . ``size`` () == *n* ,\ncorresponds to the second order\n:ref:`forward_two@Special Case` .\n{xrst_toc_hidden\n    example/general/forward.cpp\n    example/general/forward_order.cpp\n}\nExample\n*******\nThe files\n:ref:`forward.cpp-name` and :ref:`forward_order.cpp-name`\ncontain examples and tests of using forward mode with\none order and multiple orders respectively.\nThey return true if they succeed and false otherwise.\n\n{xrst_end forward_order}\n"
  },
  {
    "path": "include/cppad/core/forward/forward_two.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin forward_two}\n\nSecond Order Forward Mode: Derivative Values\n############################################\n\nSyntax\n******\n| *y2* = *f* . ``Forward`` (2, *x2* )\n\nPurpose\n*******\nWe use :math:`F : \\B{R}^n \\rightarrow \\B{R}^m` to denote the\n:ref:`glossary@AD Function` corresponding to *f* .\nThe result of the syntax above is that for\n*i* = 0 , ... , *m* ``-1`` ,\n\ny2 [i] =\n:math:`F_i^{(1)} (x0) * x2 + \\frac{1}{2} x1^T * F_i^{(2)} (x0) * x1`\n\nwhere\n:math:`F^{(1)} (x0)` is the Jacobian of :math:`F`, and\n:math:`F_i^{(2)} (x0)` is the Hessian of th *i*-th component of :math:`F`,\nevaluated at *x0* .\n\nf\n*\nThe object *f* has prototype\n\n    ``ADFun`` < *Base* > *f*\n\nNote that the :ref:`ADFun-name` object *f* is not ``const`` .\nBefore this call to ``Forward`` , the value returned by\n\n    *f* . ``size_order`` ()\n\nmust be greater than or equal two.\nAfter this call it will be will be three (see :ref:`size_order-name` ).\n\nx0\n**\nThe vector *x0* in the formula for *y2* [ *i* ]\ncorresponds to the previous call to :ref:`forward_zero-name`\nusing this ADFun object *f* ; i.e.,\n\n    *f* . ``Forward`` (0, *x0* )\n\nIf there is no previous call with the first argument zero,\nthe value of the :ref:`Independent-name` variables\nduring the recording of the AD sequence of operations is used\nfor *x0* .\n\nx1\n**\nThe vector *x1* in the formula for *y2* [ *i* ]\ncorresponds to the previous call to :ref:`forward_one-name`\nusing this ADFun object *f* ; i.e.,\n\n    *f* . ``Forward`` (1, *x1* )\n\nx2\n**\nThe argument *x2* has prototype\n\n    ``const`` *Vector* & *x2*\n\n(see :ref:`forward_two@Vector` below)\nand its size must be equal to *n* , the dimension of the\n:ref:`fun_property@Domain` space for *f* .\n\ny2\n**\nThe result *y2* has prototype\n\n    *Vector* *y2*\n\n(see :ref:`forward_two@Vector` below)\nThe size of *y1* is equal to *m* , the dimension of the\n:ref:`fun_property@Range` space for *f* .\nIts value is given element-wise by the formula in the\n:ref:`forward_two@Purpose` above.\n\nVector\n******\nThe type *Vector* must be a :ref:`SimpleVector-name` class with\n:ref:`elements of type<SimpleVector@Elements of Specified Type>`\n*Base* .\nThe routine :ref:`CheckSimpleVector-name` will generate an error message\nif this is not the case.\n\nExample\n*******\nThe file\n:ref:`forward.cpp-name`\ncontains an example and test of this operation.\n\nSpecial Case\n************\nThis is special case of :ref:`forward_order-name` where\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    Y(t) & = F[ X(t) ]\n    \\\\\n    X(t) & = & x^{(0)} t^0 + x^{(1)} * t^1 + \\cdots, + x^{(q)} * t^q + o( t^q )\n    \\\\\n    Y(t) & = & y^{(0)} t^0 + y^{(1)} * t^1 + \\cdots, + y^{(q)} * t^q + o( t^q )\n    \\end{eqnarray}\n\nand :math:`o( t^q ) * t^{-q} \\rightarrow 0` as :math:`t \\rightarrow 0`.\nFor this special case, :math:`q = 2`,\n:math:`x^{(0)}` = *x0* ,\n:math:`x^{(1)}` = *x1* ,\n:math:`x^{(2)}` = *x2* ,\n:math:`X(t) = x^{(0)} + x^{(1)} t + x^{(2)} t^2`, and\n\n.. math::\n\n    y^{(0)} + y^{(1)} t  + y^{(2)} t^2\n    =\n    F [ x^{(0)} + x^{(1)} t + x^{(2)} t^2 ] + o(t^2)\n\nRestricting our attention to the *i*-th component, and\ntaking the derivative with respect to :math:`t`, we obtain\n\n.. math::\n\n    y_i^{(1)} + 2 y_i^{(2)} t\n    =\n    F_i^{(1)} [ x^{(0)} + x^{(1)} t + x^{(2)} t^2 ] [ x^{(1)} + 2 x^{(2)} t ]\n    +\n    o(t)\n\nTaking a second derivative with respect to :math:`t`,\nand evaluating at :math:`t = 0`, we obtain\n\n.. math::\n\n    2 y_i^{(2)}\n    =\n    [ x^{(1)} ]^T F_i^{(2)} [ x^{(0)} ] x^{(1)}\n    +\n    F_i^{(1)} [ x^{(0)} ] 2 x^{(2)}\n\nwhich agrees with the specification for *y2* [ *i* ] in the\n:ref:`forward_two@Purpose` above.\n\n{xrst_end forward_two}\n"
  },
  {
    "path": "include/cppad/core/forward/forward_zero.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin forward_zero}\n{xrst_spell\n    cout\n    ostream\n}\n\nZero Order Forward Mode: Function Values\n########################################\n\nSyntax\n******\n| *y0* = *f* . ``Forward`` (0, *x0* )\n| *y0* = *f* . ``Forward`` (0, *x0* , *s* )\n\nPurpose\n*******\nWe use :math:`F : \\B{R}^n \\rightarrow \\B{R}^m` to denote the\n:ref:`glossary@AD Function` corresponding to *f* .\nThe result of the syntax above is\n\n.. math::\n\n    y0 = F(x0)\n\nSee the :ref:`FunCheck discussion<FunCheck@Discussion>` for\npossible differences between :math:`F(x)` and the algorithm that defined\nthe operation sequence.\n\nf\n*\nThe object *f* has prototype\n\n    ``ADFun`` < *Base* > *f*\n\nNote that the :ref:`ADFun-name` object *f* is not ``const`` .\nAfter this call to ``Forward`` , the value returned by\n\n    *f* . ``size_order`` ()\n\nwill be equal to one (see :ref:`size_order-name` ).\n\nx0\n**\nThe argument *x0* has prototype\n\n    ``const`` *Vector* & *x0*\n\n(see :ref:`forward_zero@Vector` below)\nand its size must be equal to *n* , the dimension of the\n:ref:`fun_property@Domain` space for *f* .\n\ns\n*\nIf the argument *s* is not present, ``std::cout``\nis used in its place.\nOtherwise, this argument has prototype\n\n    ``std::ostream&`` *s*\n\nIt specifies where the output corresponding to :ref:`PrintFor-name` ,\nand this zero order forward mode call, will be written.\n\ny0\n**\nThe result *y0* has prototype\n\n    *Vector* *y0*\n\n(see :ref:`forward_zero@Vector` below)\nand its value is :math:`F(x)` at *x* = *x0* .\nThe size of *y0* is equal to *m* , the dimension of the\n:ref:`fun_property@Range` space for *f* .\n\nVector\n******\nThe type *Vector* must be a :ref:`SimpleVector-name` class with\n:ref:`elements of type<SimpleVector@Elements of Specified Type>`\n*Base* .\nThe routine :ref:`CheckSimpleVector-name` will generate an error message\nif this is not the case.\n\nExample\n*******\nThe file\n:ref:`forward.cpp-name`\ncontains an example and test of this operation.\n\nSpecial Case\n************\nThis is special case of :ref:`forward_order-name` where\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    Y(t) & = & F[ X(t) ]\n    \\\\\n    X(t) & = & x^{(0)} t^0 + x^{(1)} * t^1 + \\cdots, + x^{(q)} * t^q + o( t^q )\n    \\\\\n    Y(t) & = & y^{(0)} t^0 + y^{(1)} * t^1 + \\cdots, + y^{(q)} * t^q + o( t^q )\n    \\end{eqnarray}\n\nand :math:`o( t^q ) * t^{-q} \\rightarrow 0` as :math:`t \\rightarrow 0`.\nFor this special case, :math:`q = 0`,\n:math:`x^{(0)}` = *x0* ,\n:math:`X(t) = x^{(0)}`, and\n\n.. math::\n\n    y^{(0)} = Y(t) = F[ X(t) ] = F( x^{(0)} )\n\nwhich agrees with the specifications for\n*y0* in the :ref:`forward_zero@Purpose` above.\n\n{xrst_end forward_zero}\n"
  },
  {
    "path": "include/cppad/core/forward/size_order.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin size_order}\n\nNumber Taylor Coefficient Orders Currently Stored\n#################################################\n\nSyntax\n******\n| *s* = *f* . ``size_order`` ()\n\nSee Also\n========\n:ref:`fun_property-name`\n\nPurpose\n*******\nDetermine the number of Taylor coefficient orders, per variable,direction,\ncurrently calculated and stored in the ADFun object *f* .\nSee the discussion under\n:ref:`size_order@Constructor` ,\n:ref:`size_order@Forward` , and\n:ref:`size_order@capacity_order`\nfor a description of when this value can change.\n\nf\n*\nThe object *f* has prototype\n\n    ``const ADFun`` < *Base* > *f*\n\ns\n*\nThe result *s* has prototype\n\n    ``size_t`` *s*\n\nand is the number of Taylor coefficient orders,\nper variable,direction in the AD operation sequence,\ncurrently calculated and stored in the ADFun object *f* .\n\nConstructor\n***********\nDirectly after the :ref:`fun_construct-name` syntax\n\n    ``ADFun`` < *Base* > *f* ( *x* , *y* )\n\nthe value of *s* returned by ``size_order`` is one.\nThis is because\nthere is an implicit call to ``Forward`` that computes\nthe zero order Taylor coefficients during this constructor.\n\nForward\n*******\nAfter a call to :ref:`Forward<forward_order-name>` with the syntax\n\n    *f* . ``Forward`` ( *q* , *x_q* )\n\nthe value of *s* returned by ``size_order``\nwould be :math:`q + 1`.\nThe call to ``Forward`` above\nuses the lower order Taylor coefficients to compute and store\nthe *q*-th order Taylor coefficients for all\nthe variables in the operation sequence corresponding to *f* .\nThus there are :math:`q + 1` (order zero through *q* )\nTaylor coefficients per variable,direction.\n(You can determine the number of variables in the operation sequence\nusing the :ref:`fun_property@size_var` function.)\n\ncapacity_order\n**************\nIf the number of Taylor coefficient orders\ncurrently stored in *f* is less than or equal *c* ,\na call to :ref:`capacity_order-name` with the syntax\n\n    *f* . ``capacity_order`` ( *c* )\n\ndoes not affect the value *s* returned by ``size_order`` .\nOtherwise,\nthe value *s* returned by ``size_order``\nis equal to *c*\n(only Taylor coefficients of order zero through :math:`c-1`\nhave been retained).\n\nExample\n*******\nThe file\n:ref:`forward.cpp-name`\ncontains an example and test of this operation.\n\n{xrst_end size_order}\n"
  },
  {
    "path": "include/cppad/core/fun_check.hpp",
    "content": "# ifndef CPPAD_CORE_FUN_CHECK_HPP\n# define CPPAD_CORE_FUN_CHECK_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin FunCheck}\n\nCheck an ADFun Sequence of Operations\n#####################################\n\nSyntax\n******\n| *ok* = ``FunCheck`` ( *f* , *g* , *x* , *r* , *a* )\n\nSee Also\n********\n:ref:`FunCheck-name`\n\nPurpose\n*******\nWe use :math:`F : \\B{R}^n \\rightarrow \\B{R}^m` to denote the\n:ref:`glossary@AD Function` corresponding to *f* .\nWe use :math:`G : \\B{R}^n \\rightarrow \\B{R}^m` to denote the\nfunction corresponding to the C++ function object *g* .\nThis routine check if\n\n.. math::\n\n    F(x) = G(x)\n\nIf :math:`F(x) \\neq G(x)`, the\n:ref:`operation sequence<glossary@Operation@Sequence>`\ncorresponding to *f* does not represents the algorithm used\nby *g* to calculate values for :math:`G`\n(see :ref:`FunCheck@Discussion` below).\n\nf\n*\nThe ``FunCheck`` argument *f* has prototype\n\n    ``ADFun`` < *Base* > *f*\n\nNote that the :ref:`ADFun-name` object *f* is not ``const``\n(see :ref:`Forward<FunCheck@FunCheck Uses Forward>` below).\n\ng\n*\nThe ``FunCheck`` argument *g* has prototype\n\n    *Fun* & *g*\n\n( *Fun* is defined the properties of *g* ).\nThe C++ function object *g* supports the syntax\n\n    *y* = *g* ( *x* )\n\nwhich computes :math:`y = G(x)`.\n\nx\n=\nThe *g* argument *x* has prototype\n\n    ``const`` *Vector* & *x*\n\n(see :ref:`FunCheck@Vector` below)\nand its size\nmust be equal to *n* , the dimension of the\n:ref:`fun_property@Domain` space for *f* .\n\ny\n*\nThe *g* result *y* has prototype\n\n    *Vector* *y*\n\nand its value is :math:`G(x)`.\nThe size of *y*\nis equal to *m* , the dimension of the\n:ref:`fun_property@Range` space for *f* .\n\nx\n*\nThe ``FunCheck`` argument *x* has prototype\n\n    ``const`` *Vector* & *x*\n\nand its size\nmust be equal to *n* , the dimension of the\n:ref:`fun_property@Domain` space for *f* .\nThis specifies that point at which to compare the values\ncalculated by *f* and *G* .\n\nr\n*\nThe ``FunCheck`` argument *r* has prototype\n\n    ``const`` *Base* & *r*\n\nIt specifies the relative error the element by element\ncomparison of the value of :math:`F(x)` and :math:`G(x)`.\n\na\n*\nThe ``FunCheck`` argument *a* has prototype\n\n    ``const`` *Base* & *a*\n\nIt specifies the absolute error the element by element\ncomparison of the value of :math:`F(x)` and :math:`G(x)`.\n\nok\n**\nThe ``FunCheck`` result *ok* has prototype\n\n    ``bool`` *ok*\n\nIt is true, if for :math:`i = 0 , \\ldots , m-1`\neither the relative error bound is satisfied\n\n.. math::\n\n    | F_i (x) - G_i (x) |\n    \\leq\n    r ( | F_i (x) | + | G_i (x) | )\n\nor the absolute error bound is satisfied\n\n.. math::\n\n    | F_i (x) - G_i (x) | \\leq a\n\nIt is false if for some :math:`(i, j)` neither\nof these bounds is satisfied.\n\nVector\n******\nThe type *Vector* must be a :ref:`SimpleVector-name` class with\n:ref:`elements of type<SimpleVector@Elements of Specified Type>`\n*Base* .\nThe routine :ref:`CheckSimpleVector-name` will generate an error message\nif this is not the case.\n\nFunCheck Uses Forward\n*********************\nAfter each call to :ref:`Forward-name` ,\nthe object *f* contains the corresponding\n:ref:`Taylor coefficients<glossary@Taylor Coefficient>` .\nAfter ``FunCheck`` ,\nthe previous calls to :ref:`Forward-name` are undefined.\n\nDiscussion\n**********\nSuppose that the algorithm corresponding to *g* contains\n\n| |tab| ``if`` ( *x*  >= 0 )\n| |tab| |tab| *y* = ``exp`` ( *x* )\n| |tab| ``else``\n| |tab| |tab| *y* = ``exp`` ( ``-`` *x* )\n\nwhere *x* and *y* are ``AD<double>`` objects.\nIt follows that the\nAD of ``double`` :ref:`operation sequence<glossary@Operation@Sequence>`\ndepends on the value of *x* .\nIf the sequence of operations stored in *f* corresponds to\n*g* with :math:`x \\geq 0`,\nthe function values computed using *f* when :math:`x < 0`\nwill not agree with the function values computed by :math:`g`.\nThis is because the operation sequence corresponding to *g* changed\n(and hence the object *f* does not represent the function\n:math:`G` for this value of *x* ).\nIn this case, you probably want to re-tape the calculations\nperformed by *g* with the\n:ref:`independent variables<glossary@Tape@Independent Variable>`\nequal to the values in *x*\n(so AD operation sequence properly represents the algorithm\nfor this value of independent variables).\n\nExample\n*******\n{xrst_toc_hidden\n    example/general/fun_check.cpp\n}\nThe file\n:ref:`fun_check.cpp-name`\ncontains an example and test of this function.\n\n{xrst_end FunCheck}\n---------------------------------------------------------------------------\n*/\n\nnamespace CppAD {\n    template <class Base, class RecBase, class Fun, class Vector>\n    bool FunCheck(\n        ADFun<Base, RecBase>  &f ,\n        Fun                   &g ,\n        const Vector          &x ,\n        const Base            &r ,\n        const Base            &a )\n    {   bool ok = true;\n\n        size_t m   = f.Range();\n        Vector yf  = f.Forward(0, x);\n        Vector yg  = g(x);\n\n        size_t i;\n        for(i = 0; i < m; i++)\n            ok  &= NearEqual(yf[i], yg[i], r, a);\n        return ok;\n    }\n}\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/fun_construct.hpp",
    "content": "# ifndef CPPAD_CORE_FUN_CONSTRUCT_HPP\n# define CPPAD_CORE_FUN_CONSTRUCT_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin fun_construct}\n{xrst_spell\n    versa\n}\n\nConstruct an ADFun Object and Stop Recording\n############################################\n\nSyntax\n******\n| ``ADFun`` < *Base* > *f* ( *ax* , *ay* );\n| ``ADFun`` < *Base* > *f*\n| *f* . ``swap`` ( *g* )\n| ``f`` = ``g``\n\nPurpose\n*******\nThe ``ADFun`` < *Base* > object *f*\nstores an AD of *Base*\n:ref:`operation sequence<glossary@Operation@Sequence>` .\nIt can then be used to calculate derivatives of the corresponding\n:ref:`glossary@AD Function`\n\n.. math::\n\n    F : \\B{R}^n \\rightarrow \\B{R}^m\n\nwhere :math:`B` is the space corresponding to objects of type *Base* .\n\nax\n**\nIf the argument *ax* is present, it has prototype\n\n    ``const`` *ADVector* & *ax*\n\nIt must be the vector argument in the previous call to\n:ref:`Independent-name` .\nNeither its size, or any of its values, are allowed to change\nbetween calling\n\n    ``Independent`` ( *ax* )\n\nand\n\n    ``ADFun`` < *Base* > *f* ( *ax* , *ay* )\n\nay\n**\nIf the argument *ay* is present, it has prototype\n\n    ``const`` *ADVector* & *ay*\n\nThe sequence of operations that map *ax*\nto *ay* are stored in the ADFun object *f* .\n\nADVector\n********\nThe type *ADVector* must be a :ref:`SimpleVector-name` class with\n:ref:`elements of type<SimpleVector@Elements of Specified Type>`\n``AD`` < *Base* > .\nThe routine :ref:`CheckSimpleVector-name` will generate an error message\nif this is not the case.\n\nDefault Constructor\n*******************\nThe default constructor\n\n    ``ADFun`` < *Base* > *g*\n\ncreates an\n``AD`` < *Base* > object with no corresponding operation sequence; i.e.,\n\n    *g* . ``size_var`` ()\n\nreturns the value zero (see :ref:`fun_property@size_var` ).\n\nSequence Constructor\n********************\nThe following constructor stores the current ``AD`` < *Base* > operation\nsequence in *f* :\n\n    ``ADFun`` < *Base* > *f* ( *ax* , *ay* )\n\nTo be specific, it is equivalent to the following\nsteps using the default constructor:\n\n#. Create *f* with the default constructor\n\n        ``ADFun`` < *Base* > *f* ;\n\n#. Stop the recording and store the operation sequence using\n\n        *f* . ``Dependent`` ( *ax* , *ay* );\n\n    see :ref:`Independent@Start Recording` ,\n    :ref:`Dependent@Stop Recording` , and\n    :ref:`Dependent@Store Operation Sequence` .\n\n#. Calculate the zero order Taylor coefficients for all\n   the variables in the operation sequence using\n\n        *y* = *f* . ``Forward`` ( 0 , *x* )\n\n    see :ref:`forward_zero-name`.\n    Here *x* and *y* are :ref:`simple vectors <SimpleVector-name>`\n    with elements of type *Base* and the elements of *x*\n    are equal to the corresponding elements in *ax*.\n\n#. If NDEBUG is not defined, *y* is checked to make sure it's elements are\n   nearly equal to the corresponding values in *ay* .\n\nCopy Constructor\n****************\nIt is an error to attempt to use the ``ADFun`` < *Base* > copy constructor;\ni.e., the following syntax is not allowed:\n\n    ``ADFun`` < *Base* > *g* ( *f* )\n\nwhere *f* is an ``ADFun`` < *Base* > object.\nUse its :ref:`fun_construct@Default Constructor` instead\nand its assignment operator.\n\nswap\n****\nThe swap operation *f* . ``swap`` ( *g* ) exchanges the contents of\nthe two ``ADFun`` < *Base* > functions; i.e.,\n*f* before the swap is identical to *g* after the swap and vise versa.\n\nAssignment Operator\n*******************\nThe ``ADFun`` < *Base* > assignment operation\n\n    *g* = *f*\n\nmakes a copy of the operation sequence currently stored in *f*\nin the object *g* .\nThe object *f* is not affected by this operation and\ncan be ``const`` .\nAll of information (state) stored in *f* is copied to *g*\nand any information originally in *g* is lost.\n\nMove Semantics\n==============\nIn the special case where *f* is a temporary object,\nthis assignment will use move semantics.\nThis avoids the overhead of the copying all the information from\n*f* to *g* .\n\nTaylor Coefficients\n===================\nThe Taylor coefficient information currently stored in *f*\n(computed by :ref:`f.Forward<Forward-name>` ) is\ncopied to *g* .\nHence, directly after this operation\n\n    *g* . ``size_order`` () == *f* . ``size_order`` ()\n\nSparsity Patterns\n=================\nThe forward Jacobian sparsity pattern currently stored in *f*\n(computed by :ref:`f.ForSparseJac<ForSparseJac-name>` ) is\ncopied to *g* .\nHence, directly after this operation\n\n| |tab| *g* . ``size_forward_bool`` () == *f* . ``size_forward_bool`` ()\n| |tab| *g* . ``size_forward_set`` ()  == *f* . ``size_forward_set`` ()\n\nParallel Mode\n*************\nThe call to ``Independent`` ,\nand the corresponding call to\n\n    ``ADFun`` < *Base* > *f* ( *ax* , *ay* )\n\nor\n\n    *f* . ``Dependent`` ( *ax* , *ay* )\n\nor :ref:`abort_recording-name` ,\nmust be preformed by the same thread; i.e.,\n:ref:`thread_alloc::thread_num<ta_thread_num-name>` must be the same.\n\nExample\n*******\n\nSequence Constructor\n====================\nThe file\n:ref:`independent.cpp-name`\ncontains an example and test of the sequence constructor.\n\nDefault Constructor\n===================\nThe files\n:ref:`fun_check.cpp-name`\nand\n:ref:`hes_lagrangian.cpp-name`\ncontain an examples and tests using the default constructor.\nThey return true if they succeed and false otherwise.\n{xrst_toc_hidden\n    example/general/fun_assign.cpp\n}\nAssignment Operator\n===================\nThe file\n:ref:`fun_assign.cpp-name`\ncontains an example and test of the ``ADFun`` < *Base* >\nassignment operator.\n\n{xrst_end fun_construct}\n----------------------------------------------------------------------------\n*/\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\n\\file fun_construct.hpp\nADFun function constructors and assignment operator.\n*/\n\n/*!\nADFun default constructor\n\nThe C++ syntax for this operation is\n\\verbatim\n    ADFun<Base> f\n\\endverbatim\nAn empty ADFun object is created.\nThe Dependent member function,\nor the ADFun<Base> assignment operator,\ncan then be used to put an operation sequence in this ADFun object.\n\n\\tparam Base\nis the base for the recording that can be stored in this ADFun object;\ni.e., operation sequences that were recorded using the type AD<Base>.\n*/\ntemplate <class Base, class RecBase>\nADFun<Base,RecBase>::ADFun(void) :\nfunction_name_(\"\"),\nexceed_collision_limit_(false),\nhas_been_optimized_(false),\ncheck_for_nan_(true) ,\ncompare_change_count_(0),\ncompare_change_number_(0),\ncompare_change_op_index_(0),\nnum_order_taylor_(0),\ncap_order_taylor_(0),\nnum_direction_taylor_(0),\nnum_var_tape_(0)\n{ }\n//\n// move semantics version of constructor\n// (none of the default constructor values matter to the destructor)\ntemplate <class Base, class RecBase>\nADFun<Base,RecBase>::ADFun(ADFun&& f)\n{   swap(f); }\n//\n// destructor\ntemplate <class Base, class RecBase>\nADFun<Base,RecBase>::~ADFun(void)\n{ }\n/*!\nADFun assignment operator\n\nThe C++ syntax for this operation is\n\\verbatim\n    g = f\n\\endverbatim\nwhere g and f are ADFun<Base> ADFun objects.\nA copy of the the operation sequence currently stored in f\nis placed in this ADFun object (called g above).\nAny information currently stored in this ADFun object is lost.\n\n\\tparam Base\nis the base for the recording that can be stored in this ADFun object;\ni.e., operation sequences that were recorded using the type AD<Base>.\n\n\\param f\nADFun object containing the operation sequence to be copied.\n*/\ntemplate <class Base, class RecBase>\nvoid ADFun<Base,RecBase>::operator=(const ADFun& f)\n{\n    // go through member variables in ad_fun.hpp order\n    //\n    // string objects\n    function_name_             = f.function_name_;\n    //\n    // bool objects\n    exceed_collision_limit_    = f.exceed_collision_limit_;\n    has_been_optimized_        = f.has_been_optimized_;\n    check_for_nan_             = f.check_for_nan_;\n    //\n    // size_t objects\n    compare_change_count_      = f.compare_change_count_;\n    compare_change_number_     = f.compare_change_number_;\n    compare_change_op_index_   = f.compare_change_op_index_;\n    num_order_taylor_          = f.num_order_taylor_;\n    cap_order_taylor_          = f.cap_order_taylor_;\n    num_direction_taylor_      = f.num_direction_taylor_;\n    num_var_tape_              = f.num_var_tape_;\n    //\n    // pod_vector objects\n    ind_taddr_                 = f.ind_taddr_;\n    dep_taddr_                 = f.dep_taddr_;\n    dep_parameter_             = f.dep_parameter_;\n    cskip_op_                  = f.cskip_op_;\n    load_op2var_               = f.load_op2var_;\n    //\n    // pod_vector_maybe_vectors\n    taylor_                    = f.taylor_;\n    subgraph_partial_          = f.subgraph_partial_;\n    //\n    // player\n    play_                      = f.play_;\n    //\n    // subgraph\n    subgraph_info_             = f.subgraph_info_;\n    //\n    // sparse_pack\n    for_jac_sparse_pack_       = f.for_jac_sparse_pack_;\n    //\n    // sparse_list\n    for_jac_sparse_set_        = f.for_jac_sparse_set_;\n}\n/// swap\ntemplate <class Base, class RecBase>\nvoid ADFun<Base,RecBase>::swap(ADFun& f)\n{\n    // string objects\n    function_name_.swap( f.function_name_ );\n    //\n    // bool objects\n    std::swap( exceed_collision_limit_    , f.exceed_collision_limit_);\n    std::swap( has_been_optimized_        , f.has_been_optimized_);\n    std::swap( check_for_nan_             , f.check_for_nan_);\n    //\n    // size_t objects\n    std::swap( compare_change_count_      , f.compare_change_count_);\n    std::swap( compare_change_number_     , f.compare_change_number_);\n    std::swap( compare_change_op_index_   , f.compare_change_op_index_);\n    std::swap( num_order_taylor_          , f.num_order_taylor_);\n    std::swap( cap_order_taylor_          , f.cap_order_taylor_);\n    std::swap( num_direction_taylor_      , f.num_direction_taylor_);\n    std::swap( num_var_tape_              , f.num_var_tape_);\n    //\n    // pod_vector objects\n    ind_taddr_.swap(      f.ind_taddr_);\n    dep_taddr_.swap(      f.dep_taddr_);\n    dep_parameter_.swap(  f.dep_parameter_);\n    taylor_.swap(         f.taylor_);\n    cskip_op_.swap(       f.cskip_op_);\n    load_op2var_.swap(    f.load_op2var_);\n    //\n    // player\n    play_.swap(f.play_);\n    //\n    // subgraph_info\n    subgraph_info_.swap(f.subgraph_info_);\n    //\n    // sparse_pack\n    for_jac_sparse_pack_.swap( f.for_jac_sparse_pack_);\n    //\n    // sparse_list\n    for_jac_sparse_set_.swap( f.for_jac_sparse_set_);\n}\n/// Move semantics version of constructor and assignment\ntemplate <class Base, class RecBase>\nvoid ADFun<Base,RecBase>::operator=(ADFun&& f)\n{   swap(f); }\n\n\n/*!\nADFun constructor from an operation sequence.\n\nThe C++ syntax for this operation is\n\\verbatim\n    ADFun<Base> f(x, y)\n\\endverbatim\nThe operation sequence that started with the previous call\n Independent(x), and that ends with this operation, is stored\nin this ADFun<Base> object f.\n\n\\tparam Base\nis the base for the recording that will be stored in the object f;\ni.e., the operations were recorded using the type AD<Base>.\n\n\\tparam ADVector\nis a simple vector class with elements of typea AD<Base>.\n\n\\param x\nis the independent variable vector for this ADFun object.\nThe domain dimension of this object will be the size of x.\n\n\\param y\nis the dependent variable vector for this ADFun object.\nThe range dimension of this object will be the size of y.\n\n\\par Taylor Coefficients\nA zero order forward mode sweep is done,\nand if NDEBUG is not defined the resulting values for the\ndependent variables are checked against the values in y.\nThus, the zero order Taylor coefficients\ncorresponding to the value of the x vector\nare stored in this ADFun object.\n*/\ntemplate <class Base, class RecBase>\ntemplate <class ADVector>\nADFun<Base,RecBase>::ADFun(const ADVector &x, const ADVector &y)\n{\n    // used to identify the RecBase type in calls to sweeps\n    RecBase not_used_rec_base(0.0);\n\n    CPPAD_ASSERT_KNOWN(\n        x.size() > 0,\n        \"ADFun<Base>: independent variable vector has size zero.\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        Variable(x[0]),\n        \"ADFun<Base>: independent variable vector has been changed.\"\n    );\n    local::ADTape<Base>* tape = AD<Base>::tape_ptr(x[0].tape_id_);\n    CPPAD_ASSERT_KNOWN(\n        tape->size_independent_ == size_t ( x.size() ),\n        \"ADFun<Base>: independent variable vector has been changed.\"\n    );\n    size_t j, n = x.size();\n# ifndef NDEBUG\n    size_t i, m = y.size();\n    for(j = 0; j < n; j++)\n    {   CPPAD_ASSERT_KNOWN(\n        size_t(x[j].taddr_) == (j+1),\n        \"ADFun<Base>: independent variable vector has been changed.\"\n        );\n        CPPAD_ASSERT_KNOWN(\n        x[j].tape_id_ == x[0].tape_id_,\n        \"ADFun<Base>: independent variable vector has been changed.\"\n        );\n    }\n    for(i = 0; i < m; i++)\n    {   CPPAD_ASSERT_KNOWN(\n        CppAD::Parameter( y[i] ) || (y[i].tape_id_ == x[0].tape_id_) ,\n        \"ADFun<Base>: dependent vector contains variables for\"\n        \"\\na different tape than the independent variables.\"\n        );\n    }\n# endif\n\n    // stop the tape and store the operation sequence\n    Dependent(tape, y);\n\n    // This function has not yet been optimized\n    exceed_collision_limit_    = false;\n\n    // ad_fun.hpp member values not set by dependent\n    check_for_nan_       = true;\n\n    // allocate memory for one zero order taylor_ coefficient\n    CPPAD_ASSERT_UNKNOWN( num_order_taylor_ == 0 );\n    CPPAD_ASSERT_UNKNOWN( num_direction_taylor_ == 0 );\n    size_t c = 1;\n    size_t r = 1;\n    capacity_order(c, r);\n    CPPAD_ASSERT_UNKNOWN( cap_order_taylor_     == c );\n    CPPAD_ASSERT_UNKNOWN( num_direction_taylor_ == r );\n\n    // set zero order coefficients corresponding to independent variables\n    CPPAD_ASSERT_UNKNOWN( n == ind_taddr_.size() );\n    for(j = 0; j < n; j++)\n    {   CPPAD_ASSERT_UNKNOWN( ind_taddr_[j] == (j+1) );\n        CPPAD_ASSERT_UNKNOWN( size_t(x[j].taddr_) == (j+1) );\n        taylor_[ ind_taddr_[j] ]  = x[j].value_;\n    }\n\n    // use independent variable values to fill in values for others\n    CPPAD_ASSERT_UNKNOWN( cskip_op_.size() == play_.num_var_op() );\n    CPPAD_ASSERT_UNKNOWN( load_op2var_.size()  == play_.num_var_load() );\n    bool print = false;\n    local::sweep::forward_0(\n        not_used_rec_base,\n        &play_,\n        num_var_tape_,\n        cap_order_taylor_,\n        cskip_op_.data(),\n        load_op2var_,\n        compare_change_count_,\n        compare_change_number_,\n        compare_change_op_index_,\n        std::cout,\n        print,\n        taylor_.data()\n    );\n    CPPAD_ASSERT_UNKNOWN( compare_change_count_    == 1 );\n    CPPAD_ASSERT_UNKNOWN( compare_change_number_   == 0 );\n    CPPAD_ASSERT_UNKNOWN( compare_change_op_index_ == 0 );\n\n    // now set the number of orders stored\n    num_order_taylor_ = 1;\n\n# ifndef NDEBUG\n    // on MS Visual Studio 2012, CppAD required in front of isnan ?\n    for(i = 0; i < m; i++)\n    if( taylor_[dep_taddr_[i]] != y[i].value_ || CppAD::isnan( y[i].value_ ) )\n    {   using std::endl;\n        std::ostringstream buf;\n        buf << \"A dependent variable value is not equal to \"\n            << \"its tape evaluation value,\" << endl\n            << \"perhaps it is nan.\" << endl\n            << \"Dependent variable value = \"\n            <<  y[i].value_ << endl\n            << \"Tape evaluation value    = \"\n            <<  taylor_[dep_taddr_[i]]  << endl\n            << \"Difference               = \"\n            <<  y[i].value_ -  taylor_[dep_taddr_[i]]  << endl\n        ;\n        // buf.str() returns a string object with a copy of the current\n        // contents in the stream buffer.\n        std::string msg_str       = buf.str();\n        // msg_str.c_str() returns a pointer to the c-string\n        // representation of the string object's value.\n        const char* msg_char_star = msg_str.c_str();\n        CPPAD_ASSERT_KNOWN(\n            0,\n            msg_char_star\n        );\n    }\n# endif\n}\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/fun_eval.hpp",
    "content": "# ifndef CPPAD_CORE_FUN_EVAL_HPP\n# define CPPAD_CORE_FUN_EVAL_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/core/new_dynamic.hpp>\n# include <cppad/core/forward/forward.hpp>\n# include <cppad/core/reverse.hpp>\n# include <cppad/core/sparse.hpp>\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/fun_property.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin fun_property}\n{xrst_spell\n    dyn\n}\n\nADFun Function Properties\n#########################\n\nSyntax\n******\n| *n* = *f* . ``Domain`` ()\n| *m* = *f* . ``Range`` ()\n| *p* = *f* . ``Parameter`` ( *i* )\n| *s* = *f* . ``size_var`` ()\n| *s* = *f* . ``size_par`` ()\n| *s* = *f* . ``size_op`` ()\n| *s* = *f* . ``size_op_arg`` ()\n| *s* = *f* . ``size_text`` ()\n| *s* = *f* . ``size_VecAD`` ()\n| *s* = *f* . ``size_random`` ()\n| *s* = *f* . ``size_dyn_ind`` ()\n| *s* = *f* . ``size_dyn_par`` ()\n| *s* = *f* . ``size_dyn_arg`` ()\n| *s* = *f* . ``size_op_seq`` ()\n\nSee Also\n========\n:ref:`function_name-name` ,\n:ref:`size_order-name` ,\n:ref:`capacity_order-name` ,\n:ref:`number_skip-name` .\n\nPurpose\n*******\nThe operations above return properties of the\nAD of *Base*\n:ref:`operation sequence<glossary@Operation@Sequence>`\nstored in the ADFun object *f* .\n(If there is no operation sequence stored in *f* ,\n``size_var`` returns zero.)\n\nf\n*\nThe object *f* has prototype\n\n    ``const ADFun`` < *Base* > *f*\n\n(see ``ADFun`` < *Base* > :ref:`constructor<fun_construct-name>` ).\n\nDomain\n******\nThe result *n* has prototype\n\n    ``size_t`` *n*\n\nand is the dimension of the domain space corresponding to *f* .\nThis is equal to the size of the vector *x* in the call\n\n    ``Independent`` ( *x* )\n\nthat starting recording the operation sequence\ncurrently stored in *f*\n(see :ref:`fun_construct-name` and :ref:`Dependent-name` ).\n\nRange\n*****\nThe result *m* has prototype\n\n    ``size_t`` *m*\n\nand is the dimension of the range space corresponding to *f* .\nThis is equal to the size of the vector *y* in syntax\n\n    *ADFun* < ``Base>`` *f* ( *x* , *y* )\n\nor\n\n    *f* . ``Dependent`` ( *y* )\n\ndepending on which stored the operation sequence currently in *f*\n(see :ref:`fun_construct-name` and :ref:`Dependent-name` ).\n\nParameter\n*********\nThe argument *i* has prototype\n\n    ``size_t`` *i*\n\nand :math:`0 \\leq i < m`.\nThe result *p* has prototype\n\n    ``bool`` *p*\n\nIt is true if the *i*-th component of range space for :math:`F`\ncorresponds to a\n:ref:`glossary@Parameter` in the operation sequence.\nIn this case,\nthe *i*-th component of :math:`F` is constant and\n\n.. math::\n\n    \\D{F_i}{x_j} (x) = 0\n\nfor :math:`j = 0 , \\ldots , n-1` and all :math:`x \\in \\B{R}^n`.\n\nsize_var\n********\nThe result *s* has prototype\n\n    ``size_t`` *s*\n\nand is the number of variables in the operation sequence plus the following:\none for a phantom variable with tape address zero,\none for each component of the range that is a parameter.\nThe amount of work and memory necessary for computing function values\nand derivatives using *f* is roughly proportional to *s* .\n(The function call :ref:`f.size_order()<size_order-name>`\nreturns the number of Taylor coefficient orders, per variable,direction,\ncurrently stored in *f* .)\n\nIf there is no operation sequence stored in *f* ,\n``size_var`` returns zero\n(see :ref:`fun_construct@Default Constructor` ).\n\nsize_par\n********\nThe result *s* has prototype\n\n    ``size_t`` *s*\n\nand is the number of parameters in the operation sequence\n(include a phantom parameter at index zero that is not used).\nParameters differ from variables in that only values\n(and not derivatives) need to be stored for each parameter.\nThese parameters are considered part of the operation\nsequence, as opposed to the Taylor coefficients which are\nconsidered extra data in the function object *f* .\nNote that one *Base* value is required for each parameter.\n\nsize_op\n*******\nThe result *s* has prototype\n\n    ``size_t`` *s*\n\nand is the number of operations in the operation sequence.\nSome operators, like comparison operators,\ndo not correspond to a variable.\nOther operators, like the sine operator,\ncorrespond to two variables.\nThus, this value will be different from\n:ref:`fun_property@size_var` .\nNote that one ``enum`` value is required for each operator.\n\nsize_op_arg\n***********\nThe result *s* has prototype\n\n    ``size_t`` *s*\n\nand is the total number of operator arguments in the operation sequence.\nFor example, Binary operators (e.g. addition) have two arguments.\nNote that one integer index is stored in the operation sequence\nfor each argument.\nAlso note that, as of 2013-10-20, there is an extra\nphantom argument with index 0 that is not used.\n\nsize_text\n*********\nThe result *s* has prototype\n\n    ``size_t`` *s*\n\nand is the total characters used in the :ref:`PrintFor-name` commands\nin this operation sequence.\n\nsize_VecAD\n**********\nThe result *s* has prototype\n\n    ``size_t`` *s*\n\nand is the number of :ref:`VecAD-name` vectors,\nplus the number of elements in the vectors.\nOnly ``VecAD`` vectors that depend on the\nindependent variables are stored in the operation sequence.\n\nsize_random\n***********\nThe result *s* has prototype\n\n    ``size_t`` *s*\n\nand is the amount of memory currently holding information\nfor randomly access the operator sequence.\nRandom access is only used by the following routines\n:ref:`subgraph_sparsity-name` ,\n:ref:`subgraph_reverse-name` , and\n:ref:`optimize-name` .\nThe optimize routine replaces the operation sequence, so the extra\nmemory is automatically dropped.\nThe subgraph routines hold onto this information\nso that it does not need to be recalculated between calls.\nThe routine\n:ref:`subgraph_reverse@clear_subgraph`\nwill free this extra memory.\n\nsize_dyn_ind\n************\nThe result *s* has prototype\n\n    ``size_t`` *s*\n\nand is the number of independent\n:ref:`glossary@Parameter@Dynamic` parameters\nin the operation sequence.\nThis is the size of the\n:ref:`Independent@dynamic` parameter in the\ncorresponding call to ``Independent`` .\n\nsize_dyn_par\n************\nThe result *s* has prototype\n\n    ``size_t`` *s*\n\nand is the number of\n:ref:`glossary@Parameter@Dynamic` parameters.\nThe dynamic parameters depend on the value of\nthe independent dynamic parameters but not on the value of the variables.\nThis includes the independent dynamic parameters.\n\nsize_dyn_arg\n************\nThe result *s* has prototype\n\n    ``size_t`` *s*\n\nand is the total number of dynamic parameter operator arguments\nin the operation sequence.\nFor example, Binary operators (e.g. addition) have two arguments.\nNote that one integer index is stored in the operation sequence\nfor each argument.\n\nsize_op_seq\n***********\nThe result *s* has prototype\n\n    ``size_t`` *s*\n\nand is the amount of memory required to store the operation sequence\n(not counting a small amount of memory required for every operation sequence).\nFor the current version of CppAD, this is given by\n{xrst_comment see size_t player::Memory(void)}\n\n| |tab| *s* = *f* . ``size_op`` ()      * ``sizeof`` ( ``CPPAD_VEC_ENUM_TYPE`` )\n| |tab| |tab| + *f* . ``size_op_arg`` ()  * ``sizeof`` ( *tape_addr_type* )\n| |tab| |tab| + *f* . ``size_par`` ()     * ``sizeof`` ( *Base* )\n| |tab| |tab| + *f* . ``size_par`` ()     * ``sizeof`` ( ``bool`` )\n| |tab| |tab| + *f* . ``size_dyn_par`` () * ``sizeof`` ( ``CPPAD_VEC_ENUM_TYPE`` )\n| |tab| |tab| + *f* . ``size_dyn_par`` () * ``sizeof`` ( *tape_addr_type* )\n| |tab| |tab| + *f* . ``size_dyn_arg`` () * ``sizeof`` ( *tape_addr_type* )\n| |tab| |tab| + *f* . ``size_text`` ()    * ``sizeof`` ( ``char`` )\n| |tab| |tab| + *f* . ``size_VecAD`` ()   * ``sizeof`` ( *tape_addr_type* )\n\nsee :ref:`tape_addr_type<cmake@cppad_tape_addr_type>` .\nNote that this is the minimal amount of memory that can hold\nthe information corresponding to an operation sequence.\nThe actual amount of memory allocated (:ref:`inuse<ta_inuse-name>` )\nfor the operations sequence may be larger.\nAlso note that ``CPPAD_VEC_ENUM_TYPE`` is not part\nof the CppAD API and may change.\n\nExample\n*******\n{xrst_toc_hidden\n    example/general/fun_property.cpp\n}\nThe file\n:ref:`fun_property.cpp-name`\ncontains an example and test of these operations.\n\n{xrst_end fun_property}\n"
  },
  {
    "path": "include/cppad/core/function_name.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin function_name}\n\nSetting and Getting a Function's Name\n#####################################\n\nSyntax\n******\n| *f* . ``function_name_set`` ( *function_name* )\n| *function_name* = *f* . ``function_name_get`` ()\n\nSee Also\n********\n:ref:`fun_property-name`\n\nf\n*\nIn the set operation, *f* has prototype\n\n    ``ADFun`` < *Base* > *f*\n\nIn the get operation, *f* has prototype\n\n    ``const ADFun`` < *Base* > *f*\n\n(see ``ADFun`` < *Base* > :ref:`constructor<fun_construct-name>` ).\n\nfunction_name\n*************\nis the name of the function.\nIn the set operation, *function_name* has prototype\n\n    ``const std::string&`` *function_name*\n\nIn the get operation, *function_name* has prototype\n\n    ``std::string`` *function_name*\n\n{xrst_toc_hidden\n    example/general/function_name.cpp\n}\nExample\n*******\nThe file :ref:`function_name.cpp-name` contains an example and test\nof these operations.\n\n{xrst_end function_name}\n"
  },
  {
    "path": "include/cppad/core/graph/cpp_ad_graph.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin cpp_ad_graph}\n{xrst_spell\n    notpos\n    nx\n}\n\nC++ Representation of an AD Graph\n#################################\n\nSee Also\n********\n:ref:`json_ad_graph-title`\n\nfunction\n********\nThis section defines a computational graph representation of a function\n:math:`y = f(x, p)`.\nThe vector *x* is called the independent variable vector,\n*p* is called the independent dynamic parameter vector,\nand *y* is called the dependent variable vector.\n\nNode Indices\n************\nThe nodes in an AD graph have the following order:\n::\n\n        p_0 , ... ,  p_{np-1} ,\n        x_0 , ... ,  x_{nx-1} ,\n        c_0 , ... ,  c_{nc-1} ,\n        r_0 , ... ,  r_{no-1}\n\np\n=\nThe sub-vector\n::\n\n        p_0, ... , p_{np-1}\n\nis the independent dynamic parameter vector;\nsee :ref:`cpp_ad_graph@n_dynamic_ind` .\nThe node index corresponding to *p_0* is ``1`` .\n\nx\n=\nThe sub-vector\n::\n\n        x_1, ... , x_nx\n\nis the independent variable vector;\nsee :ref:`cpp_ad_graph@n_variable_ind` .\nThe node index corresponding to *x_0* is\nthe index corresponding to *p_0* plus *np* .\n\nc\n=\nThe sub-vector\n::\n\n        c_1, ... , c_nc\n\nis the constant parameter vector;\nsee :ref:`cpp_ad_graph@constant_vec` .\nThe node index corresponding to *c_0* is\nthe index corresponding to *x_0* plus *nx* .\n\nr\n=\nThe sub-vector\n*r_i* for *i* =0,..., *no* ``-1`` is the result vector\nfor the *i*-th operator;\nsee :ref:`cpp_ad_graph@operator_vec` .\nAll of the node arguments for an the *i*-th operator are nodes\nthat come before the first element of *r_i* .\nThe node index corresponding to the first element of *r_0* is\nthe index corresponding to *c_0* plus *nc* .\nFor *i*  > 0 ,\nThe node index corresponding to the first element of *r_i* is\nthe index corresponding to the first element of *r_* { *i-1* } plus\nthe number of results for the *i-1*-th operator.\n\nfunction_name\n*************\nis a ``std::string`` containing the name for the function\ncorresponding to this graph.\n\ndiscrete_name_vec\n*****************\nis a vector with elements of type ``std::string`` .\nA discrete function has one argument, one result, and it derivative\nis always zero; e.g., the Heaviside function.\nCalls by this function to discrete functions use the index in this\nvector to identify the discrete functions; see\n:ref:`cpp_ad_graph@operator_arg@discrete_graph_op` below.\nIf there are no calls to discrete functions, this vector can be empty.\n\natomic_name_vec\n***************\nis a vector with elements of type ``std::string`` .\nAn atomic function can have any number of arguments and results\nand non-zero derivatives.\nCalls by this function to other functions use the index in this\nvector to identify the other functions; see\n:ref:`cpp_ad_graph@operator_arg@atom_graph_op` below.\nIf there are no calls to other functions, this vector can be empty.\nDiscrete functions are faster, and simpler to create and use\nthan atomic functions.\n\nprint_text_vec\n**************\nis a vector with elements of type ``std::string`` .\nThe :ref:`graph_op_enum@Print` operators uses indices\nin this vector for the corresponding\n:ref:`PrintFor@before` and :ref:`PrintFor@after` values.\nIf there are no print operators, this vector can be empty.\n\nn_dynamic_ind\n*************\nis the number of independent dynamic parameters in the function\n(called *np* above); see\n:ref:`Independent@dynamic` .\n\nn_variable_ind\n**************\nis the number of independent variables in the function\n(called *nx* above); see\n:ref:`Independent@x` .\n\nconstant_vec\n************\nis a vector of with elements of type\n``double`` and size *nc* that can be used to define this function.\n\noperator_vec\n************\nis a vector with elements of type ``graph_op_enum``\nand size *no* (the number of operators in the graph).\nFor *i* = 0, ..., *no* ``-1``\n*operator_vec* [ *i* ] contains the instructions\nfor computing the result vector *r_i* .\n\noperator_arg\n************\nis a vector with size equal to the sum of the size of each\nof its sub-vectors (which are described below).\nFor *i* = 0, ..., *no* ``-1`` , we use\n*first_node* [ *i* ] to denote the index in *operator_arg*\nof the first node argument to the *i*-th operator.\nWe use *n_node_arg* [ *i* ] to denote the number of node arguments\nfor the *i*-th operator.\nFor *j* = 0 , ..., *n_node_arg* [ *i* ] ``-1`` ,\nthe *j*-th node argument for the *i*-th operator has node index\n\n    *operator_arg* [ *first_node* [ *i* ] + *j*  ]\n\nThe *operator_arg* sub-vector for the *i*-th operator starts are\n*first_node* [ *i* ] and has *n_node_arg* [ *i* ] elements\nexcept for the following operators:\n``sum_graph_op`` ,\n``discrete_graph_op`` ,\n``atom_graph_op`` ,\n``print_graph_op`` .\n\nprint_graph_op\n==============\nIn the case where *operator_vec* [ *i* ]. ``op_enum`` is\n``print_graph_op`` :\n\n    *before* [ *i* ] = *operator_arg* [ *first_node* [ *i* ] ``- 2`` ]\n\nis the index in :ref:`cpp_ad_graph@print_text_vec`\nof the text that is printed before the value and\n\n    *after* [ *i* ] = *operator_arg* [ *first_node* [ *i* ] ``- 1`` ]\n\nis the index in :ref:`cpp_ad_graph@print_text_vec`\nof the text that is printed after the value.\nThe *operator_arg* sub-vector for the *i*-th operator\nstarts at index *first_node* [ *i* ] ``-2``\nand has 4 = *n_node_arg* [ *i* ]+2 elements.\nThe node with index\n\n    *notpos* [ *i* ] = *operator_arg* [ *first_node* [ *i* ] ]\n\nis checked and if it is positive, nothing is printed by this operator.\nOtherwise, the value corresponding to the following node is printed:\n\n    *value* [ *i* ] = *operator_arg* [ *first_node* [ *i* ] + 1 ]\n\ndiscrete_graph_op\n=================\nIn the case where *operator_vec* [ *i* ]. ``op_enum`` is\n``discrete_graph_op`` :\n\n    *name_index* [ *i* ] = *operator_arg* [ *first_node* [ *i* ] ``- 1`` ]\n\nis the index in :ref:`cpp_ad_graph@discrete_name_vec`\nof the function being called by this operator.\nFor this operator,\nthe *operator_arg* sub-vector for the *i*-th operator\nstarts at index *first_node* [ *i* ] ``-1``\nand has 2 = *n_node_arg* [ *i* ]+1 elements.\n\natom_graph_op\n=============\nIn the case where *operator_vec* [ *i* ]. ``op_enum`` is\n``atom_graph_op`` :\n\n    *name_index* [ *i* ] = *operator_arg* [ *first_node* [ *i* ] ``- 3`` ]\n\nis the index in :ref:`cpp_ad_graph@atomic_name_vec`\nof the function being called by this operator.\n\n    *n_result* [ *i* ] = *operator_arg* [ *first_node* [ *i* ] ``- 2`` ]\n\nis the number of result nodes for this operator.\n\n    *n_node_arg* [ *i* ] = *operator_arg* [ *first_node* [ *i* ] ``- 1`` ]\n\nis the number of node arguments for this operator.\nFor this operator,\nthe *operator_arg* sub-vector for the *i*-th operator\nstarts at index *first_node* [ *i* ] ``-3``\nand has *n_node_arg* [ *i* ]+3 elements.\n\nsum_graph_op\n============\nIn the case where *operator_vec* [ *i* ]. ``op_enum`` is\n``sum_graph_op`` :\n\n    *n_node_arg* [ *i* ] = *operator_arg* [ *first_node* [ *i* ] ``- 1`` ]\n\nis the number of node arguments for this operator.\nFor this operator,\nthe *operator_arg* sub-vector for the *i*-th operator\nstarts at index *first_node* [ *i* ] ``-1``\nand has *n_node_arg* [ *i* ]+1 elements.\n\ndependent_vec\n*************\nis a vector with size equal to the number element in *y* .\nThe *i*-th element of *y* corresponds to the node index\n*dependent_vec* [ *i* ] .\n\ncpp_graph\n*********\nThe ``cpp_graph`` class implements the data structure above.\nIt is defined by the documentation sections under Contents below:\n\nContents\n********\n{xrst_toc_table\n    include/cppad/core/graph/graph_op_enum.hpp\n    include/cppad/core/graph/cpp_graph.xrst\n    include/cppad/core/graph/from_graph.hpp\n    include/cppad/core/graph/to_graph.hpp\n}\n\n{xrst_end cpp_ad_graph}\n"
  },
  {
    "path": "include/cppad/core/graph/cpp_graph.hpp",
    "content": "# ifndef CPPAD_CORE_GRAPH_CPP_GRAPH_HPP\n# define CPPAD_CORE_GRAPH_CPP_GRAPH_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <iomanip>\n# include <string>\n# include <cppad/utility/vector.hpp>\n# include <cppad/local/graph/cpp_graph_op.hpp>\n# include <cppad/local/graph/cpp_graph_itr.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n\nclass cpp_graph { // BEGIN_CPP_GRAPH_CLASS\npublic:\n    typedef CppAD::graph::graph_op_enum graph_op_enum;\nprivate:\n    //\n    std::string                   function_name_;\n    vector<std::string>           discrete_name_vec_;\n    vector<std::string>           atomic_name_vec_;\n    vector<std::string>           print_text_vec_;\n    size_t                        n_dynamic_ind_;\n    size_t                        n_variable_ind_;\n    vector<double>                constant_vec_;\n    vector<graph_op_enum>         operator_vec_;\n    vector<size_t>                operator_arg_;\n    vector<size_t>                dependent_vec_;\npublic:\n    typedef local::graph::cpp_graph_itr const_iterator;\n    //\n    const_iterator begin(void) const\n    {   size_t op_index = 0;\n        return const_iterator(operator_vec_, operator_arg_, op_index);\n    }\n    const_iterator end(void)\n    {   size_t op_index = operator_vec_.size();\n        return const_iterator(operator_vec_, operator_arg_, op_index);\n    }\n/*\n-------------------------------------------------------------------------------\n{xrst_begin cpp_graph_ctor}\n\nC++ AD Graph Constructor\n########################\n\nSyntax\n******\n| ``cpp_graph`` *graph_obj*\n| *graph_obj* . ``initialize`` ()\n\nfunction_name\n*************\n:ref:`cpp_ad_graph@function_name`\nis initialized to the empty string.\n\nn_dynamic_ind\n*************\n:ref:`cpp_ad_graph@n_dynamic_ind` is initialized as zero.\n\nn_variable_ind\n**************\n:ref:`cpp_ad_graph@n_variable_ind` is initialized as zero.\n\nconstant_vec\n************\n:ref:`cpp_ad_graph@constant_vec` is initialized as empty.\n\noperator_vec\n************\n:ref:`cpp_ad_graph@operator_vec` is initialized as empty.\n\noperator_arg\n************\n:ref:`cpp_ad_graph@operator_arg` is initialized as empty.\n\ndependent_vec\n*************\n:ref:`cpp_ad_graph@dependent_vec` is initialized as empty.\n\nParallel Mode\n*************\nThe first use of the ``cpp_graph`` constructor\ncannot be in :ref:`parallel<ta_in_parallel-name>` execution mode.\n\n{xrst_end cpp_graph_ctor}\n--------------------------------------------------------------------------------\n*/\npublic:\n    void initialize(void)\n    {  function_name_  = \"\";\n        n_dynamic_ind_  = 0;\n        n_variable_ind_  = 0;\n        discrete_name_vec_.resize(0);\n        atomic_name_vec_.resize(0);\n        print_text_vec_.resize(0);\n        constant_vec_.resize(0);\n        operator_vec_.resize(0);\n        operator_arg_.resize(0);\n        dependent_vec_.resize(0);\n        return;\n    }\n    cpp_graph(void)\n    {  CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL\n        static bool first = true;\n        if( first )\n        {  first = false;\n            CPPAD_ASSERT_UNKNOWN( local::graph::op_name2enum.size() == 0 );\n            // initialize cpp_graph global variables in cpp_graph_op.cpp\n            local::graph::set_operator_info();\n        }\n        initialize();\n    }\n/*\n---------------------------------------------------------------------------------\n{xrst_begin cpp_graph_scalar}\n\nC++ AD Graph Scalar Values\n##########################\n\nSyntax\n******\n\nGet\n===\n\n| *function_name* = *graph_obj* . ``function_name_get`` ()\n| *n_dynamic_ind* = *graph_obj* . ``n_dynamic_ind_get`` ()\n| *n_variable_ind* = *graph_obj* . ``n_variable_ind_get`` ()\n\nSet\n===\n\n| *graph_obj* . ``function_name_set`` ( *function_name* )\n| *graph_obj* . ``n_dynamic_ind_set`` ( *n_dynamic_ind* )\n| *graph_obj* . ``n_variable_ind_set`` ( *n_variable_ind* )\n\nSet\n***\nThe argument for all the set operations is const.\n\ngraph_obj\n*********\nis an ``cpp_graph`` object.\nIt is const for all the get functions.\n\nfunction_name\n*************\nis a ``std::string&`` specifying the name of the function\nfor this graph.\n\nn_dynamic_ind\n*************\nis a ``size_t`` specifying the number of independent dynamic parameters.\n\nn_variable_ind\n**************\nis a ``size_t`` specifying the number of independent variables.\n\n{xrst_end cpp_graph_scalar}\n*/\n    // function_name\n    const std::string& function_name_get(void) const\n    {  return function_name_; }\n    void function_name_set(const std::string& function_name)\n    {  function_name_ = function_name; }\n    //\n    // n_dynamic_ind\n    const size_t& n_dynamic_ind_get(void) const\n    {  return n_dynamic_ind_; }\n    void n_dynamic_ind_set(const size_t n_dynamic_ind)\n    {  n_dynamic_ind_ = n_dynamic_ind; }\n    //\n    // n_variable_ind\n    const size_t& n_variable_ind_get(void) const\n    {  return n_variable_ind_; }\n    void n_variable_ind_set(const size_t n_variable_ind)\n    {  n_variable_ind_ = n_variable_ind; }\n/*\n---------------------------------------------------------------------------------\n{xrst_begin cpp_graph_vector}\n\nC++ AD Graph Vector Values\n##########################\n\nSyntax\n******\n\nSize\n====\n\n| *size* = *graph_obj* . ``discrete_name_vec_size`` ()\n| *size* = *graph_obj* . ``atomic_name_vec_size`` ()\n| *size* = *graph_obj* . ``print_text_vec_size`` ()\n| *size* = *graph_obj* . ``constant_vec_size`` ()\n| *size* = *graph_obj* . ``operator_vec_size`` ()\n| *size* = *graph_obj* . ``operator_arg_size`` ()\n| *size* = *graph_obj* . ``dependent_vec_size`` ()\n\nGet\n===\n\n| *discrete_name* = *graph_obj* . ``discrete_name_vec_get`` ( *index* )\n| *atomic_name* = *graph_obj* . ``atomic_name_vec_get`` ( *index* )\n| *print_text* = *graph_obj* . ``print_text_vec_get`` ( *index* )\n| *constant* = *graph_obj* . ``constant_vec_get`` ( *index* )\n| *op_enum* = *graph_obj* . ``operator_vec_get`` ( *index* )\n| *argument* = *graph_obj* . ``operator_arg_get`` ( *index* )\n| *node_index* = *graph_obj* . ``dependent_vec_get`` ( *index* )\n\nPush Back\n=========\n\n| *graph_obj* . ``discrete_name_vec_push_back`` ( *discrete_name* )\n| *graph_obj* . ``atomic_name_vec_push_back`` ( *atomic_name* )\n| *graph_obj* . ``print_text_vec_push_back`` ( *print_text* )\n| *graph_obj* . ``constant_vec_push_back`` ( *constant* )\n| *graph_obj* . ``operator_vec_push_back`` ( *op_enum* )\n| *graph_obj* . ``operator_arg_push_back`` ( *argument* )\n| *graph_obj* . ``dependent_vec_push_back`` ( *node_index* )\n\nFind\n====\n\n| *discrete_index* = *graph_obj* . ``discrete_name_vec_find`` ( *discrete_name* )\n| *atomic_index* = *graph_obj* . ``atomic_name_vec_find`` ( *atomic_name* )\n| *print_index* = *graph_obj* . ``print_text_vec_find`` ( *print_text* )\n\nArguments\n*********\nAll of the member function arguments are either call by value or const.\n\nsize\n****\nis a ``size_t`` value equal to the current size of the specified vector.\n\nindex\n*****\nis a ``size_t`` value that must be less than the current size\nof the specified vector.\n\npush_back\n*********\nThe arguments for all the push_back functions are const.\nThe size of the specified vector before a push_back,\nis the index in the vector corresponding to the argument value.\nThe size of the vector after the push_back is the size before plus one.\n\ngraph_obj\n*********\nis an ``cpp_graph`` object.\nIt is const for the size, get, and find functions and\nnot const for the push_back functions.\n\ndiscrete_name\n*************\nis a ``std::string`` equal to the name of a :ref:`discrete-name` function.\n\natomic_name\n***********\nis a ``std::string`` equal to the name of an :ref:`atomic_three-name` function.\n\nprint_text\n**********\nis a ``std::string`` equal to the text to be printed.\n\nconstant\n********\nis a ``double`` equal to the constant with the corresponding\nindex in ``constant_vec`` .\n\nop_enum\n*******\nis the :ref:`graph_op_enum-name` for corresponding operator.\n\nargument\n********\nis the ``size_t`` value for corresponding operator argument.\n\nnode_index\n**********\nis the node index for the corresponding dependent variable with\nthe corresponding index in\n:ref:`cpp_ad_graph@dependent_vec` .\n\ndiscrete_index\n**************\nis the index such that\n\n    *discrete_name* == *graph_obj* . ``discrete_name_vec_get`` ( *discrete_index* )\n\nIf there is no such index,\n\n    *discrete_index* == *graph_obj* . ``discrete_name_vec_size`` ()\n\natomic_index\n************\nis the index such that\n\n    *atomic_name* == *graph_obj* . ``atomic_name_vec_get`` ( *atomic_index* )\n\nIf there is no such index,\n\n    *atomic_index* == *graph_obj* . ``atomic_name_vec_size`` ()\n\nprint_index\n***********\nis the index such that\n\n    *print_text* == *graph_obj* . ``print_text_vec_get`` ( *print_index* )\n\nIf there is no such index,\n\n    *print_index* == *graph_obj* . ``print_text_vec_size`` ()\n\n{xrst_end cpp_graph_vector}\n*/\n    // discrete_name_vec\n    const std::string& discrete_name_vec_get(size_t index) const\n    {  return discrete_name_vec_[index]; }\n    size_t discrete_name_vec_size(void) const\n    {  return discrete_name_vec_.size(); }\n    void discrete_name_vec_push_back(const std::string& discrete_name)\n    {  discrete_name_vec_.push_back(discrete_name); }\n    size_t discrete_name_vec_find(const std::string& discrete_name) const\n    {  for(size_t i = 0; i < discrete_name_vec_.size(); ++i)\n            if( discrete_name == discrete_name_vec_[i] )\n                return i;\n        return discrete_name_vec_.size();\n    }\n    //\n    // atomic_name_vec\n    const std::string& atomic_name_vec_get(size_t index) const\n    {  return atomic_name_vec_[index]; }\n    size_t atomic_name_vec_size(void) const\n    {  return atomic_name_vec_.size(); }\n    void atomic_name_vec_push_back(const std::string& atomic_name)\n    {  atomic_name_vec_.push_back(atomic_name); }\n    size_t atomic_name_vec_find(const std::string& atomic_name) const\n    {  for(size_t i = 0; i < atomic_name_vec_.size(); ++i)\n            if( atomic_name == atomic_name_vec_[i] )\n                return i;\n        return atomic_name_vec_.size();\n    }\n    //\n    // print_text_vec\n    const std::string& print_text_vec_get(size_t index) const\n    {  return print_text_vec_[index]; }\n    size_t print_text_vec_size(void) const\n    {  return print_text_vec_.size(); }\n    void print_text_vec_push_back(const std::string& atomic_name)\n    {  print_text_vec_.push_back(atomic_name); }\n    size_t print_text_vec_find(const std::string& print_text) const\n    {  for(size_t i = 0; i < print_text_vec_.size(); ++i)\n            if( print_text == print_text_vec_[i] )\n                return i;\n        return print_text_vec_.size();\n    }\n    //\n    // constant_vec\n    const double& constant_vec_get(size_t index) const\n    {  return constant_vec_[index]; }\n    size_t constant_vec_size(void) const\n    {  return constant_vec_.size(); }\n    void constant_vec_push_back(const double& constant)\n    {  constant_vec_.push_back(constant); }\n    //\n    // oerator_vec\n    const graph_op_enum& operator_vec_get(size_t index) const\n    {  return operator_vec_[index]; }\n    size_t operator_vec_size(void) const\n    {  return operator_vec_.size(); }\n    void operator_vec_push_back(const graph_op_enum op_enum)\n    {  operator_vec_.push_back(op_enum); }\n    //\n    // operator_arg\n    const size_t& operator_arg_get(size_t index) const\n    {  return operator_arg_[index]; }\n    size_t operator_arg_size(void) const\n    {  return operator_arg_.size(); }\n    void operator_arg_push_back(const size_t argument)\n    {  operator_arg_.push_back(argument); }\n    //\n    // dependent_vec\n    const size_t& dependent_vec_get(size_t index) const\n    {  return dependent_vec_[index]; }\n    size_t dependent_vec_size(void) const\n    {  return dependent_vec_.size(); }\n    void dependent_vec_push_back(const size_t node_index)\n    {  dependent_vec_.push_back(node_index); }\n/*\n{xrst_begin cpp_graph_print}\n{xrst_spell\n    ostream\n}\n\nPrint A C++ AD Graph\n####################\n\nSyntax\n******\n\n    *graph_obj* . ``print`` ( *os* )\n\ngraph_obj\n*********\nis an const ``cpp_graph`` object.\n\nos\n**\nIs the ``std::ostream`` where the graph is printed.\n\nDiscussion\n**********\nThis function is included to help with using the ``cpp_graph`` class.\nThe formatting of it's output is not part of the API; i.e.,\nit may change in the future.\n{xrst_toc_hidden\n    example/graph/print_graph.cpp\n}\nExample\n*******\nThe file :ref:`print_graph.cpp-name` contains an example and test of this operation.\n\n{xrst_end cpp_graph_print}\n*/\n    void print(std::ostream& os) const\n    {   using std::setw;\n        using std::string;\n        //\n        // function name\n        if( function_name_ != \"\" )\n            os << function_name_ << \"\\n\";\n        //\n        // initialize node index\n        size_t node_index = 1;\n        //\n        // text vector\n        size_t n_text = print_text_vec_.size();\n        for(size_t i = 0; i < n_text; ++i)\n        {   string s_i = \"c[\" + std::to_string(i) + \"]\";\n            //\n            os << setw(11) << \"\";\n            os << setw(10) << s_i;\n            os << \"'\" << print_text_vec_[i] << \"'\";\n            os << \"\\n\";\n        }\n        //\n        //  parameter vector\n        for(size_t i = 0; i < n_dynamic_ind_; i++)\n        {   string p_i = \"p[\" + std::to_string(i) + \"]\";\n            //\n            os << setw(11)  << node_index;\n            os << setw(10) << p_i;\n            os << \"\\n\";\n            ++node_index;\n        }\n        //\n        //  variable vector\n        for(size_t i = 0; i < n_variable_ind_; i++)\n        {   string x_i = \"x[\" + std::to_string(i) + \"]\";\n            //\n            os << setw(11)  << node_index;\n            os << setw(10) << x_i;\n            os << \"\\n\";\n            ++node_index;\n        }\n        //\n        //  constant vector\n        size_t n_constant = constant_vec_.size();\n        for(size_t i = 0; i < n_constant; i++)\n        {   string c_i = \"c[\" + std::to_string(i) + \"]\";\n            //\n            os << setw(11) << node_index;\n            os << setw(10) << c_i;\n            os << setw(20) << constant_vec_[i];\n            os << \"\\n\";\n            ++node_index;\n        }\n\n        size_t                    n_op = operator_vec_.size();\n        cpp_graph::const_iterator itr;\n        for(size_t op_index = 0; op_index < n_op; ++op_index)\n        {   if( op_index == 0 )\n                itr = begin();\n            else\n                ++itr;\n            cpp_graph::const_iterator::value_type itr_value = *itr;\n            //\n            const vector<size_t>& str_index( *itr_value.str_index_ptr );\n            const vector<size_t>&       arg( *itr_value.arg_node_ptr );\n            graph_op_enum          op_enum  = itr_value.op_enum;\n            size_t                n_result  = itr_value.n_result;\n            size_t                   n_arg  = arg.size();\n            CPPAD_ASSERT_UNKNOWN( n_arg > 0 );\n            //\n            string op_name = local::graph::op_enum2name[ op_enum ];\n            //\n            if( n_result == 0 )\n                os << setw(11) << \"\";\n            else if( n_result == 1 )\n                os << setw(11)  << node_index;\n            else\n            {   string first = std::to_string(node_index);\n                string last  = std::to_string(node_index + n_result - 1);\n                os << setw(11) << first + \"-\" + last;\n            }\n            os << setw(10) << op_name;\n            for(size_t i = 0; i < n_arg; ++i)\n                os << setw(5) << arg[i];\n\n            switch( op_enum )\n            {\n                case graph::discrete_graph_op:\n                CPPAD_ASSERT_UNKNOWN( str_index.size() == 1 );\n                os << discrete_name_vec_get( str_index[0] );\n                break;\n\n                case graph::atom_graph_op:\n                CPPAD_ASSERT_UNKNOWN( str_index.size() == 1 );\n                os << atomic_name_vec_get( str_index[0] );\n                break;\n\n                case graph::print_graph_op:\n                CPPAD_ASSERT_UNKNOWN( str_index.size() == 2 );\n                os << print_text_vec_get( str_index[0] ) << \",\";\n                os << print_text_vec_get( str_index[1] );\n                break;\n\n                default:\n                CPPAD_ASSERT_UNKNOWN( str_index.size() == 0 );\n                break;\n            }\n            os << \"\\n\";\n            node_index += n_result;\n        }\n        //\n        //  dependent vector\n        size_t n_dependent = dependent_vec_.size();\n        os << \"y nodes = \";\n        for(size_t i = 0; i < n_dependent; i++)\n        {   os << dependent_vec_[i];\n            if( i + 1 < n_dependent )\n                os << \", \";\n        }\n        os << \"\\n\";\n    }\n\n}; // END CPP_GRAPH_CLASS\n\n} // END_CPPAD_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/graph/cpp_graph.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin cpp_graph}\n\nA C++ AD Graph Class\n####################\n\nContents\n********\n{xrst_toc_table\n    include/cppad/core/graph/cpp_graph.hpp\n}\n\n{xrst_end cpp_graph}\n"
  },
  {
    "path": "include/cppad/core/graph/from_graph.hpp",
    "content": "# ifndef CPPAD_CORE_GRAPH_FROM_GRAPH_HPP\n# define CPPAD_CORE_GRAPH_FROM_GRAPH_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/core/ad_fun.hpp>\n# include <cppad/core/ad_type.hpp>\n# include <cppad/core/discrete/discrete.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*\n{xrst_begin from_graph}\n\nADFun Object Corresponding to a CppAD Graph\n###########################################\n\nSyntax\n******\n| |tab| ``cpp_graph`` *graph_obj*\n| |tab| ``ADFun`` < *Base* > *fun*\n| |tab| *fun* . ``from_graph`` ( *graph_obj* )\n| |tab| *fun* . ``from_graph`` ( *graph_obj* , *dyn2var* , *var2dyn* )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_ONE_ARGUMENT\n    // END_ONE_ARGUMENT\n}\n{xrst_literal\n    // BEGIN_WITH_IS_DYNAMIC\n    // END_WITH_IS_DYNAMIC\n}\n\nBase\n****\nis the type corresponding to this :ref:`adfun-name` object;\ni.e., its calculations are done using the type *Base* .\n\nRecBase\n*******\nin the prototype above, *RecBase* is the same type as *Base* .\n\ngraph_obj\n*********\nis a :ref:`cpp_ad_graph-name` representation of this function.\n\ndyn2var\n*******\nis a vector with size equal to the number of independent dynamic parameters\nin the graph; i.e., the size of :ref:`cpp_ad_graph@Node Indices@p` .\nIt specifies which independent dynamic parameters in the graph are\nindependent variables in the function *fun* .\n\nvar2dyn\n*******\nis a vector with size equal to the number of independent variables\nin the graph; i.e., the size of :ref:`cpp_ad_graph@Node Indices@x` .\nIt specifies which independent variables in the graph are\nindependent dynamic parameters in the function *fun* .\n\nfun\n***\nIt *dyn2var* and *var2dyn* are not present,\nthe independent dynamic parameters and independent variables in *fun*\nare the same as for the graph.\nOtherwise, they are described below.\n\nm_true, m_false\n===============\nLet *m_true* ( *m_false* ) be the number of true (false)\nelements of *dyn2var* .\n\nn_true, n_false\n===============\nLet *n_true* ( *n_false* ) be the number of true (false)\nelements of *var2dyn* .\n\nIndependent Dynamic Parameters\n==============================\nThe first *m_false* independent dynamic parameters in *fun*\ncorrespond to the false components of *dyn2var*\nand have the same order as in the graph.\nThe next *n_true* independent dynamic parameters in *fun*\ncorrespond to the true components of *var2dyn*\nand have the same order as in the graph.\n\nIndependent Variables\n=====================\nThe first *m_true* independent variables in *fun*\ncorrespond to the true components of *dyn2var*\nand have the same order as in the graph.\nThe next *n_false* independent variables in *fun*\ncorrespond to the false components of *var2dyn*\nand have the same order as in the graph.\n{xrst_toc_hidden\n    example/graph/switch_var_dyn.cpp\n}\nExamples\n********\nThe file :ref:`switch_var_dyn.cpp-name` contains an example and test\nof this routine.\nFor simpler examples, that do not change the dynamic parameters and variables;\nsee :ref:`graph_op_enum examples<graph_op_enum@Examples>` .\n\n{xrst_end from_graph}\n*/\n// BEGIN_WITH_IS_DYNAMIC\ntemplate <class Base, class RecBase>\nvoid CppAD::ADFun<Base,RecBase>::from_graph(\n        const CppAD::cpp_graph& graph_obj     ,\n        const CppAD::vector<bool>& dyn2var    ,\n        const CppAD::vector<bool>& var2dyn    )\n// END_WITH_IS_DYNAMIC\n{   using CppAD::isnan;\n    using namespace CppAD::graph;\n    //\n    // some sizes\n    const std::string function_name  = graph_obj.function_name_get();\n    const size_t n_dynamic_ind       = graph_obj.n_dynamic_ind_get();\n    const size_t n_variable_ind      = graph_obj.n_variable_ind_get();\n    const size_t n_constant          = graph_obj.constant_vec_size();\n    const size_t n_usage             = graph_obj.operator_vec_size();\n    const size_t n_dependent         = graph_obj.dependent_vec_size();\n    //\n    // n_dynamic_ind_fun\n    // n_variable_ind_fun\n    CPPAD_ASSERT_KNOWN(\n        n_variable_ind == var2dyn.size(),\n        \"from_graph: size of var2dyn not equal \"\n        \"number of independent variables in graph\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        n_dynamic_ind == dyn2var.size(),\n        \"from_graph: size of dyn2val not equal \"\n        \"number of independent dynamic parameters in graph\"\n    );\n    size_t n_dynamic_ind_fun  = 0;\n    size_t n_variable_ind_fun = 0;\n    for(size_t i = 0; i < n_dynamic_ind; ++i)\n    {   if( dyn2var[i] )\n            ++n_variable_ind_fun;\n        else\n            ++n_dynamic_ind_fun;\n    }\n    for(size_t i = 0; i < n_variable_ind; ++i)\n    {   if( var2dyn[i] )\n            ++n_dynamic_ind_fun;\n        else\n            ++n_variable_ind_fun;\n    }\n    //\n    // Start of node indices\n# ifndef NDEBUG\n    size_t start_dynamic_ind = 1;\n    size_t start_independent = start_dynamic_ind + n_dynamic_ind;\n    size_t start_constant    = start_independent + n_variable_ind;\n    size_t start_operator    = start_constant    + n_constant;\n# endif\n    //\n    // initialize mappings from node index as empty\n    // (there is no node zero)\n    vector<ad_type_enum>        node_type( 1 );\n    local::pod_vector<addr_t>   node2fun( 1 );\n    node_type[0] = number_ad_type_enum; // invalid value\n    node2fun[0]  = 0;                   // invalid value\n    //\n    // discrete_index\n    // mapping from index in discrete_name_vec to discrete index\n    size_t n_list_discrete  = discrete<Base>::list_size();\n    size_t n_graph_discrete = graph_obj.discrete_name_vec_size();\n    vector<size_t> discrete_index( n_graph_discrete );\n    for(size_t i = 0; i < n_graph_discrete; ++i)\n        discrete_index[i] = n_list_discrete; // invalid discrete index\n    for(size_t index = 0; index < n_list_discrete; ++index)\n    {   const std::string& name( discrete<Base>::name(index) );\n        size_t graph_index = graph_obj.discrete_name_vec_find(name);\n        if( graph_index != n_graph_discrete )\n        {   if( discrete_index[graph_index] != n_list_discrete )\n            {   std::string msg = \"from_graph: error in call to \";\n                msg += name;\n                msg += \".\\nThere is more than one discrete \";\n                msg += \"function with this name\";\n                //\n                // use this source code as point of detection\n                bool known       = true;\n                int  line        = __LINE__;\n                const char* file = __FILE__;\n                const char* exp  = \"discrete_index[i] == n_list_discrete\";\n                //\n                // CppAD error handler\n                ErrorHandler::Call( known, line, file, exp, msg.c_str() );\n            }\n            discrete_index[graph_index] = index;\n        }\n    }\n    //\n    // atomic_name2index\n    // mapping from index in atomic_name_vec to atomic three index\n    size_t n_graph_atomic = graph_obj.atomic_name_vec_size();\n    vector<size_t> atomic_name2index( n_graph_atomic );\n    for(size_t index = 0; index < n_graph_atomic; ++index)\n        atomic_name2index[index] = 0; // invalid atomic index\n\n    {   bool        set_null = true;\n        size_t      index_in = 0;\n        size_t      type;\n        std::string name;\n        void*       ptr;\n        size_t n_atomic = CppAD::local::atomic_index<RecBase>(\n            set_null, index_in, type, &name, ptr\n        );\n        set_null = false;\n        for(index_in = 1; index_in <= n_atomic; ++index_in)\n        {   CppAD::local::atomic_index<RecBase>(\n                set_null, index_in, type, &name, ptr\n            );\n            size_t graph_index = graph_obj.atomic_name_vec_find(name);\n            if( graph_index != n_graph_atomic )\n            {   if( atomic_name2index[graph_index] != 0 )\n                {   std::string msg = \"from_graph: error in call to \";\n                    msg += name + \".\\n\";\n                    msg += \"There is more than one atomic \";\n                    msg += \"function with this name\";\n                    //\n                    // use this source code as point of detection\n                    bool known       = true;\n                    int  line        = __LINE__;\n                    const char* file = __FILE__;\n                    const char* exp  = \"atomic_index[index] == 0\";\n                    //\n                    // CppAD error handler\n                    ErrorHandler::Call(\n                        known, line, file, exp, msg.c_str()\n                    );\n                }\n                atomic_name2index[graph_index] = index_in;\n            }\n        }\n    }\n    // ----------------------------------------------------------------------\n    // Create a recording for this function\n    // ----------------------------------------------------------------------\n\n    // start a recording\n    local::recorder<Base> rec;\n    CPPAD_ASSERT_UNKNOWN( rec.num_var_op() == 0 );\n    rec.set_n_dyn_independent(n_dynamic_ind_fun);\n    rec.set_abort_op_index(0);\n    rec.set_record_compare(false);\n\n    // rec_text_index\n    // mapping from print_text_vec index to recording index\n    vector<addr_t> rec_text_index( graph_obj.print_text_vec_size() );\n    for(size_t i = 0; i < graph_obj.print_text_vec_size(); ++i)\n    {   const std::string& text = graph_obj.print_text_vec_get(i);\n        rec_text_index[i]       = rec.PutTxt( text.c_str() );\n    }\n\n    // nan\n    Base nan = CppAD::numeric_limits<Base>::quiet_NaN();\n\n    // Place the parameter with index 0 in the tape\n    const local::pod_vector_maybe<Base>& parameter( rec.par_all());\n    CPPAD_ASSERT_UNKNOWN( parameter.size() == 0 );\n    addr_t i_par = rec.put_con_par(nan);\n    CPPAD_ASSERT_UNKNOWN( i_par == 0 );\n    CPPAD_ASSERT_UNKNOWN( CppAD::isnan( parameter[i_par] ) );\n    //\n    // Place the variable with index 0 in the tape\n    CPPAD_ASSERT_NARG_NRES(local::BeginOp, 1, 1);\n    rec.PutOp(local::BeginOp);\n    rec.PutArg(0);\n    //\n    // Next come the independent dynamic parameters in the graph\n    addr_t i_var = 0;\n    for(size_t i = 0; i < n_dynamic_ind; ++i)\n    {\n        if( dyn2var[i] )\n        {   i_var = rec.PutOp( local::InvOp );\n            node_type.push_back(variable_enum);;\n            node2fun.push_back(i_var);\n        }\n         else\n        {   i_par = rec.put_dyn_par(nan, local::ind_dyn );\n            CPPAD_ASSERT_UNKNOWN( CppAD::isnan( parameter[i_par] ) );\n            node_type.push_back(dynamic_enum);\n            node2fun.push_back(i_par);\n        }\n    }\n\n    // Next come the independent variables in the graph\n    CPPAD_ASSERT_NARG_NRES(local::InvOp, 0, 1);\n    for(size_t i = 0; i < n_variable_ind; ++i)\n    {   if( var2dyn[i] )\n        {   i_par = rec.put_dyn_par(nan, local::ind_dyn );\n            CPPAD_ASSERT_UNKNOWN( CppAD::isnan( parameter[i_par] ) );\n            node_type.push_back(dynamic_enum);\n            node2fun.push_back(i_par);\n        }\n        else\n        {   i_var = rec.PutOp( local::InvOp );\n            node_type.push_back(variable_enum);;\n            node2fun.push_back(i_var);\n        }\n    }\n    CPPAD_ASSERT_UNKNOWN( size_t( i_par ) == n_dynamic_ind_fun );\n    CPPAD_ASSERT_UNKNOWN( size_t( i_var ) == n_variable_ind_fun );\n\n    // Next come the constant parameters\n    for(size_t i = 0; i < n_constant; ++i)\n    {   Base par = Base( graph_obj.constant_vec_get(i) );\n        i_par = rec.put_con_par(par);\n        CPPAD_ASSERT_UNKNOWN( parameter[i_par] == par );\n        //\n        node_type.push_back(constant_enum);;\n        node2fun.push_back(i_par);\n    }\n\n    //\n    // local arrays used to avoid reallocating memory\n    local::pod_vector<addr_t>       temporary;\n    vector<ad_type_enum>            type_x;\n    vector<addr_t>                  arg;\n    vector<size_t>                  arg_node;\n    //\n    // arrays only used by atom_graph_op, atom4_graph_op\n    vector<Base>                    parameter_x, taylor_y;\n    vector<ad_type_enum>            type_y;\n    vector< AD<Base> >              ax, ay;\n    vector<bool>                    select_y;\n    //\n    // define here because not using as loop index\n    cpp_graph::const_iterator       graph_itr;\n    //\n    // loop over operators in the recording\n# ifndef NDEBUG\n    size_t start_result = start_operator;\n# endif\n    for(size_t op_index = 0; op_index < n_usage; ++op_index)\n    {   // op_enum, str_index, n_result, arg_node\n        if( op_index == 0 )\n            graph_itr = graph_obj.begin();\n        else\n            ++graph_itr;\n        cpp_graph::const_iterator::value_type itr_value = *graph_itr;\n        const vector<size_t>& str_index(*itr_value.str_index_ptr );\n        graph_op_enum op_enum    = itr_value.op_enum;\n        size_t        n_result   = itr_value.n_result;\n        size_t        call_id    = itr_value.call_id;\n        size_t        n_arg      = itr_value.arg_node_ptr->size();\n        arg.resize(n_arg);\n        //\n        // make sure type_x is large enough\n        type_x.resize(n_arg);\n# ifndef NDEBUG\n        addr_t n_con_arg      = 0;\n# endif\n        addr_t n_dyn_arg      = 0;\n        addr_t n_var_arg      = 0;\n        for(size_t j = 0; j < n_arg; ++j)\n        {   size_t node_index = (*itr_value.arg_node_ptr)[j];\n            //\n            // argument to graph operator\n            CPPAD_ASSERT_KNOWN( node_index < start_result,\n                \"from_graph op argument index is greater or equal\\n\"\n                \"the starting index for the next result\"\n            );\n            //\n            // type of argument\n            type_x[j] = node_type[ node_index ];\n            //\n            // argument to function operator\n            arg[j]  = node2fun[ node_index ];\n            CPPAD_ASSERT_UNKNOWN( arg[j] != 0 );\n            //\n            // count number of arguments of different types\n# ifndef NDEBUG\n            n_con_arg += addr_t( type_x[j] == constant_enum );\n# endif\n            n_dyn_arg += addr_t( type_x[j] == dynamic_enum  );\n            n_var_arg += addr_t( type_x[j] == variable_enum );\n        }\n        CPPAD_ASSERT_UNKNOWN(\n            n_arg == size_t(n_con_arg + n_dyn_arg + n_var_arg)\n        );\n        //\n        addr_t i_result = 0; // invalid value\n        // -------------------------------------------------------------------\n        // conditional expressions\n        // -------------------------------------------------------------------\n        if( op_enum == cexp_eq_graph_op ||\n            op_enum == cexp_le_graph_op ||\n            op_enum == cexp_lt_graph_op )\n        {   CPPAD_ASSERT_UNKNOWN( n_result == 1 && n_arg == 4 );\n            // cop\n            CompareOp cop;\n            if( op_enum == cexp_eq_graph_op )\n                cop = CompareEq;\n            else if ( op_enum == cexp_le_graph_op )\n                cop = CompareLe;\n            else\n                cop = CompareLt;\n            //\n            if( n_var_arg == 0 )\n            {   if( n_dyn_arg == 0 )\n                {   // result is a constant parameter\n                    Base result = CondExpOp(cop,\n                        parameter[arg[0]],  // left\n                        parameter[arg[1]],  // right\n                        parameter[arg[2]],  // if_true\n                        parameter[arg[3]]   // if_false\n                    );\n                    i_result = rec.put_con_par(result);\n                }\n                else\n                {   i_result = rec.put_dyn_cond_exp(\n                        nan, cop, arg[0], arg[1], arg[2], arg[3]\n                    );\n                }\n            }\n            else\n            {   // flag marking which arguments are variables\n                addr_t flag = 0;\n                addr_t bit  = 1;\n                for(size_t j = 0; j < 4; ++j)\n                {   if( type_x[j] == variable_enum )\n                        flag |= bit;\n                    bit = 2 * bit;\n                }\n                CPPAD_ASSERT_UNKNOWN( flag != 0 );\n                rec.PutArg(addr_t(cop), flag, arg[0], arg[1], arg[2], arg[3]);\n                i_result = rec.PutOp(local::CExpOp);\n            }\n        }\n        // -------------------------------------------------------------------\n        // compare operators\n        // -------------------------------------------------------------------\n        else if(\n            op_enum == comp_eq_graph_op ||\n            op_enum == comp_le_graph_op ||\n            op_enum == comp_lt_graph_op ||\n            op_enum == comp_ne_graph_op )\n        {   CPPAD_ASSERT_UNKNOWN( n_result == 0 && n_arg == 2 );\n            //\n            bool var_left  = type_x[0] == variable_enum;\n            bool var_right = type_x[1] == variable_enum;\n            bool dyn_left  = type_x[0] == dynamic_enum;\n            bool dyn_right = type_x[1] == dynamic_enum;\n            //\n            ax.resize(n_arg);\n            // ax[0]\n            if( var_left | dyn_left )\n                ax[0].taddr_ = arg[0];\n            else\n                ax[0].value_ = parameter_x[0];\n            // ax[1]\n            if( var_right | dyn_right )\n                ax[1].taddr_ = arg[1];\n            else\n                ax[1].value_ = parameter_x[1];\n            //\n            bool result;\n            switch( op_enum )\n            {\n                case comp_eq_graph_op:\n                result = true;\n                rec.comp_eq(\n                var_left, var_right, dyn_left, dyn_right, ax[0], ax[1], result\n                );\n                break;\n\n                case comp_le_graph_op:\n                result = true;\n                rec.comp_le(\n                var_left, var_right, dyn_left, dyn_right, ax[0], ax[1], result\n                );\n                break;\n\n                case comp_lt_graph_op:\n                result = true;\n                rec.comp_lt(\n                var_left, var_right, dyn_left, dyn_right, ax[0], ax[1], result\n                );\n                break;\n\n                case comp_ne_graph_op:\n                result = false;\n                rec.comp_eq(\n                var_left, var_right, dyn_left, dyn_right, ax[0], ax[1], result\n                );\n                break;\n\n\n                default:\n                CPPAD_ASSERT_UNKNOWN(false);\n            }\n        }\n        // -------------------------------------------------------------------\n        // sum operator\n        // -------------------------------------------------------------------\n        else if( op_enum == sum_graph_op )\n        {\n            CPPAD_ASSERT_KNOWN( n_result == 1 ,\n                \"AD graph sum operator: n_result is not 1\"\n            );\n            if( n_var_arg == 0 )\n            {   // result of the sum is a parameter\n                Base sum_constant = 0.0;\n                temporary.resize(0);\n                for(size_t j = 0; j < n_arg; j++)\n                {   if( type_x[j] == constant_enum )\n                        sum_constant += parameter[ arg[j] ];\n                    else\n                    {   CPPAD_ASSERT_UNKNOWN( type_x[j] == dynamic_enum );\n                        temporary.push_back( arg[j] );\n                    }\n                }\n                CPPAD_ASSERT_UNKNOWN( temporary.size() == size_t(n_dyn_arg) );\n                //\n                // start with constant parameter\n                i_result = rec.put_con_par(sum_constant);\n                CPPAD_ASSERT_UNKNOWN( parameter[i_result] == sum_constant );\n                //\n                // sum the dynamic parameters\n                for(addr_t j = 0; j < n_dyn_arg; ++j)\n                {   i_result = rec.put_dyn_par(\n                        nan, local::add_dyn, i_result, temporary[j]\n                    );\n                    CPPAD_ASSERT_UNKNOWN( CppAD::isnan( parameter[i_result] ) );\n                }\n            }\n            else\n            {   // result of the sum is a variable\n                size_t n_temporary = 6 + size_t(n_var_arg + n_dyn_arg);\n                if( temporary.size() < n_temporary )\n                    temporary.resize( n_temporary );\n                Base sum_constant = 0.0;\n                addr_t j_variable = 5 ;\n                addr_t j_dynamic  = 5 + n_var_arg;\n                for(size_t j = 0; j < n_arg; j++)\n                {   if( type_x[j] == constant_enum )\n                        sum_constant += parameter[ arg[j] ];\n                    if( type_x[j] == variable_enum )\n                        temporary[ j_variable++ ] = arg[j];\n                    if( type_x[j] == dynamic_enum )\n                        temporary[ j_dynamic++ ]  = arg[j];\n                }\n                // number of arguments to this operator\n                temporary[j_dynamic] = j_dynamic + 1;\n                //\n                temporary[0] = rec.put_con_par(sum_constant);\n                CPPAD_ASSERT_UNKNOWN(parameter[temporary[0]] == sum_constant);\n                //\n                temporary[1] = 5 + n_var_arg;\n                temporary[2] = 5 + n_var_arg;\n                temporary[3] = temporary[2] + n_dyn_arg;\n                temporary[4] = temporary[2] + n_dyn_arg;\n                //\n                i_result = rec.PutOp(local::CSumOp);\n                for(size_t j = 0; j < n_temporary; ++j)\n                    rec.PutArg( temporary[j] );\n                CPPAD_ASSERT_UNKNOWN( local::NumRes(local::CSumOp) == 1 );\n            }\n        }\n        // -------------------------------------------------------------------\n        // print operator\n        // -------------------------------------------------------------------\n        else if( op_enum == print_graph_op )\n        {   CPPAD_ASSERT_UNKNOWN( n_arg == 2 && n_result == 0 );\n            //\n            // before\n            size_t before_graph = str_index[0];\n            addr_t before_rec   = rec_text_index[before_graph];\n            //\n            // after\n            size_t after_graph  = str_index[1];\n            addr_t after_rec    = rec_text_index[after_graph];\n            //\n            // base 2 representation of [ Var(notpos), Var(value) ]\n            addr_t is_var = 0;\n            if( type_x[0] == variable_enum )\n                is_var += 1;\n            if( type_x[1] == variable_enum )\n                is_var += 2;\n            //\n            // record this print operator\n            addr_t notpos = arg[0];\n            addr_t value  = arg[1];\n            rec.PutOp(local::PriOp);\n            rec.PutArg(is_var, notpos, before_rec, value, after_rec);\n        }\n        // -------------------------------------------------------------------\n        // discrete operator\n        // -------------------------------------------------------------------\n        else if( op_enum == discrete_graph_op )\n        {   CPPAD_ASSERT_UNKNOWN( n_arg == 1 && n_result == 1 );\n            size_t name_index = str_index[0];\n            size_t function_index = discrete_index[name_index];\n            if( function_index == n_list_discrete )\n            {   std::string msg = \"from_graph: error in call to \";\n                msg += graph_obj.discrete_name_vec_get(name_index);\n                msg += \".\\nNo previously defined discrete function \";\n                msg += \"has this name\";\n                //\n                // use this source code as point of detection\n                bool known       = true;\n                int  line        = __LINE__;\n                const char* file = __FILE__;\n                const char* exp  =\n                    \"discrete_index[name_index] != n_list_discrete\";\n                //\n                // CppAD error handler\n                ErrorHandler::Call(known, line, file, exp, msg.c_str());\n            }\n            if( type_x[0] == variable_enum )\n            {   CPPAD_ASSERT_NARG_NRES(local::DisOp, 2, 1);\n                i_result = rec.PutOp(local::DisOp);\n                rec.PutArg( addr_t(function_index) );\n                rec.PutArg( arg[0] );\n            }\n            else if( type_x[0] == dynamic_enum )\n            {   i_result = rec.put_dyn_par(\n                    nan, local::dis_dyn, addr_t(function_index), arg[0]\n                );\n            }\n            else\n            {   Base result = discrete<Base>::eval(\n                    function_index, parameter[ arg[0] ]\n                );\n                i_result = rec.put_con_par(result);\n                CPPAD_ASSERT_UNKNOWN( parameter[i_result] == result );\n            }\n        }\n        // -------------------------------------------------------------------\n        // atomic operator\n        // -------------------------------------------------------------------\n        else if( op_enum == atom_graph_op || op_enum == atom4_graph_op )\n        {   size_t name_index = str_index[0];\n            //\n            // atomic_index\n            CPPAD_ASSERT_UNKNOWN( name_index < atomic_name2index.size() );\n            size_t atomic_index = atomic_name2index[name_index];\n            if( atomic_index == 0 )\n            {   std::string msg = \"from_graph: error in call to \";\n                msg += graph_obj.atomic_name_vec_get(name_index);\n                msg += \".\\n\";\n                msg += \"No previously defined atomic function \";\n                msg += \"has this name\";\n                //\n                // use this source code as point of detection\n                bool known       = true;\n                int  line        = __LINE__;\n                const char* file = __FILE__;\n                const char* exp  = \"atomic_index != 0\";\n                //\n                // CppAD error handler\n                ErrorHandler::Call(known, line, file, exp, msg.c_str());\n            }\n            //\n            // parameter_x\n            parameter_x.resize(n_arg);\n            for(size_t j = 0; j < n_arg; ++j)\n            {   if( type_x[j] == constant_enum )\n                    parameter_x[j] = parameter[ arg[j] ];\n                else\n                    parameter_x[j] = nan;\n            }\n            //\n            // type, name, v_ptr\n            bool         set_null = false;\n            size_t       type;\n            std::string* name = nullptr;\n            void*        v_ptr;\n            CppAD::local::atomic_index<RecBase>(\n                set_null, atomic_index, type, name, v_ptr\n            );\n            CPPAD_ASSERT_KNOWN( 2 < type,\n                \"from_graph: attempt to use an atomic function with < 3\"\n            );\n            //\n            // type_y, taylor_y\n            type_y.resize(n_result);\n            size_t order_low = 0;\n            size_t order_up  = 0;\n            if( type == 3 )\n            {   // afun\n                atomic_three<RecBase>* afun =\n                    reinterpret_cast< atomic_three<RecBase>* >( v_ptr );\n                //\n                // type_y\n                afun->for_type(parameter_x, type_x, type_y);\n                //\n                // taylor_y\n                size_t need_y    = size_t(constant_enum);\n                taylor_y.resize(n_result);\n                afun->forward(\n                    parameter_x ,\n                    type_x      ,\n                    need_y      ,\n                    order_low   ,\n                    order_up    ,\n                    parameter_x ,\n                    taylor_y\n                );\n            }\n            else\n            {   CPPAD_ASSERT_UNKNOWN( type == 4 );\n                // afun\n                atomic_four<RecBase>* afun =\n                    reinterpret_cast< atomic_four<RecBase>* >( v_ptr );\n                //\n                // type_x\n                for(size_t j = 0; j < n_arg; ++j)\n                {   if( type_x[j] == constant_enum )\n                        if( parameter[ arg[j] ] == Base(0) )\n                            type_x[j] = identical_zero_enum;\n                }\n                //\n                // type_y\n                afun->for_type(call_id, type_x, type_y);\n                for(size_t i = 0; i < n_result; ++i)\n                {   if( type_y[i] == identical_zero_enum )\n                        type_y[i] = constant_enum;\n                }\n                //\n                // type_x\n                for(size_t j = 0; j < n_arg; ++j)\n                    if( type_x[j] == identical_zero_enum )\n                        type_x[j] = constant_enum;\n                //\n                // select_y\n                select_y.resize(n_result);\n                for(size_t i = 0; i < n_result; ++i)\n                    select_y[i] = type_y[i] == constant_enum;\n                //\n                // taylor_y\n                taylor_y.resize(n_result);\n                afun->forward(\n                    call_id     ,\n                    select_y    ,\n                    order_low   ,\n                    order_up    ,\n                    parameter_x ,\n                    taylor_y\n                );\n            }\n            //\n            // record_dynamic, record_variable\n            bool record_dynamic  = false;\n            bool record_variable = false;\n            for(size_t i = 0; i < n_result; ++i)\n            {   CPPAD_ASSERT_UNKNOWN( type_y[i] <= variable_enum );\n                record_dynamic  |= type_y[i] == dynamic_enum;\n                record_variable |= type_y[i] == variable_enum;\n            }\n            // tape_id is zero because not a true recording\n            tape_id_t tape_id = 0;\n            //\n            // ax, ay\n            if( record_dynamic || record_variable )\n            {   // tape_id (not a recording AD<Base> operations)\n                // ax\n                ax.resize(n_arg);\n                for(size_t j = 0; j < n_arg; ++j)\n                {   ax[j].value_ = parameter_x[j];\n                    ax[j].taddr_ = arg[j];\n                }\n                // ay\n                ay.resize(n_result);\n                for(size_t i = 0; i < n_result; ++i)\n                {   ay[i].value_ = nan; // not_used\n                    ay[i].taddr_ = 0;   // not used\n                }\n            }\n            if( record_dynamic ) rec.put_dyn_atomic(\n                    tape_id, atomic_index, call_id, type_x, type_y, ax, ay\n            );\n            if( record_variable ) rec.put_var_atomic(\n                    tape_id, atomic_index, call_id, type_x, type_y, ax, ay\n            );\n            //\n            // node_type, node2fun\n            for(size_t i = 0; i < n_result; ++i)\n            {   node_type.push_back(type_y[i]);\n                      switch( type_y[i] )\n                {   case constant_enum:\n                    node2fun.push_back(rec.put_con_par(taylor_y[i]));\n                    break;\n\n                    case dynamic_enum:\n                    case variable_enum:\n                    node2fun.push_back(ay[i].taddr_);\n                    break;\n\n                    default:\n                    CPPAD_ASSERT_UNKNOWN(false);\n                    break;\n                }\n            }\n        }\n        // -------------------------------------------------------------------\n        // unary operators\n        // -------------------------------------------------------------------\n        else if( n_arg == 1 )\n        {   CPPAD_ASSERT_UNKNOWN( n_arg == 1 && n_result == 1 );\n            Base result; // used in cases argument is a constant\n            if( type_x[0] == variable_enum ) switch( op_enum )\n            {\n                case abs_graph_op:\n                i_result = rec.PutOp(local::AbsOp);\n                rec.PutArg( arg[0] );\n                CPPAD_ASSERT_UNKNOWN( NumArg(local::AbsOp) == 1 );\n                break;\n\n                case acosh_graph_op:\n                i_result = rec.PutOp(local::AcoshOp);\n                rec.PutArg( arg[0] );\n                CPPAD_ASSERT_UNKNOWN( NumArg(local::AcoshOp) == 1 );\n                break;\n\n                case asinh_graph_op:\n                i_result = rec.PutOp(local::AsinhOp);\n                rec.PutArg( arg[0] );\n                CPPAD_ASSERT_UNKNOWN( NumArg(local::AsinhOp) == 1 );\n                break;\n\n                case atanh_graph_op:\n                i_result = rec.PutOp(local::AtanhOp);\n                rec.PutArg( arg[0] );\n                CPPAD_ASSERT_UNKNOWN( NumArg(local::AtanhOp) == 1 );\n                break;\n\n                case erf_graph_op:\n                i_result = rec.PutOp(local::ErfOp);\n                CPPAD_ASSERT_UNKNOWN( NumArg(local::ErfOp) == 3 );\n                //\n                // arg[0] = variable index for function argument\n                rec.PutArg( arg[0] );\n                //\n                // parameter[ arg[1] ] = 0.0\n                i_par = rec.put_con_par( Base(0.0) );\n                rec.PutArg( i_par );\n                //\n                // parameter[ arg[2] ] = 2 / sqrt(pi)\n                i_par = rec.put_con_par(Base(\n                    1.0 / std::sqrt( std::atan(1.0) )\n                ));\n                rec.PutArg( i_par );\n                //\n                break;\n\n                case erfc_graph_op:\n                i_result = rec.PutOp(local::ErfcOp);\n                CPPAD_ASSERT_UNKNOWN( NumArg(local::ErfcOp) == 3 );\n                //\n                // arg[0] = variable index for function argument\n                rec.PutArg( arg[0] );\n                //\n                // parameter[ arg[1] ] = 0.0\n                i_par = rec.put_con_par( Base(0.0) );\n                rec.PutArg( i_par );\n                //\n                // parameter[ arg[2] ] = 2 / sqrt(pi)\n                i_par = rec.put_con_par(Base(\n                    1.0 / std::sqrt( std::atan(1.0) )\n                ));\n                rec.PutArg( i_par );\n                //\n                break;\n\n                case expm1_graph_op:\n                i_result = rec.PutOp(local::Expm1Op);\n                rec.PutArg( arg[0] );\n                CPPAD_ASSERT_UNKNOWN( NumArg(local::Expm1Op) == 1 );\n                break;\n\n                case log1p_graph_op:\n                i_result = rec.PutOp(local::Log1pOp);\n                rec.PutArg( arg[0] );\n                CPPAD_ASSERT_UNKNOWN( NumArg(local::Log1pOp) == 1 );\n                break;\n\n                case acos_graph_op:\n                i_result = rec.PutOp(local::AcosOp);\n                rec.PutArg( arg[0] );\n                CPPAD_ASSERT_UNKNOWN( NumArg(local::AcosOp) == 1 );\n                break;\n\n                case asin_graph_op:\n                i_result = rec.PutOp(local::AsinOp);\n                rec.PutArg( arg[0] );\n                CPPAD_ASSERT_UNKNOWN( NumArg(local::AsinOp) == 1 );\n                break;\n\n                case atan_graph_op:\n                i_result = rec.PutOp(local::AtanOp);\n                rec.PutArg( arg[0] );\n                CPPAD_ASSERT_UNKNOWN( NumArg(local::AtanOp) == 1 );\n                break;\n\n                case cosh_graph_op:\n                i_result = rec.PutOp(local::CoshOp);\n                rec.PutArg( arg[0] );\n                CPPAD_ASSERT_UNKNOWN( NumArg(local::CoshOp) == 1 );\n                break;\n\n                case cos_graph_op:\n                i_result = rec.PutOp(local::CosOp);\n                rec.PutArg( arg[0] );\n                CPPAD_ASSERT_UNKNOWN( NumArg(local::CosOp) == 1 );\n                break;\n\n                case exp_graph_op:\n                i_result = rec.PutOp(local::ExpOp);\n                rec.PutArg( arg[0] );\n                CPPAD_ASSERT_UNKNOWN( NumArg(local::ExpOp) == 1 );\n                break;\n\n                case log_graph_op:\n                i_result = rec.PutOp(local::LogOp);\n                rec.PutArg( arg[0] );\n                CPPAD_ASSERT_UNKNOWN( NumArg(local::LogOp) == 1 );\n                break;\n\n                case neg_graph_op:\n                i_result = rec.PutOp(local::NegOp);\n                rec.PutArg( arg[0] );\n                CPPAD_ASSERT_UNKNOWN( NumArg(local::NegOp) == 1 );\n                break;\n\n                case sign_graph_op:\n                i_result = rec.PutOp(local::SignOp);\n                rec.PutArg( arg[0] );\n                CPPAD_ASSERT_UNKNOWN( NumArg(local::SignOp) == 1 );\n                break;\n\n                case sinh_graph_op:\n                i_result = rec.PutOp(local::SinhOp);\n                rec.PutArg( arg[0] );\n                CPPAD_ASSERT_UNKNOWN( NumArg(local::SinhOp) == 1 );\n                break;\n\n                case sin_graph_op:\n                i_result = rec.PutOp(local::SinOp);\n                rec.PutArg( arg[0] );\n                CPPAD_ASSERT_UNKNOWN( NumArg(local::SinOp) == 1 );\n                break;\n\n                case sqrt_graph_op:\n                i_result = rec.PutOp(local::SqrtOp);\n                rec.PutArg( arg[0] );\n                CPPAD_ASSERT_UNKNOWN( NumArg(local::SqrtOp) == 1 );\n                break;\n\n                case tanh_graph_op:\n                i_result = rec.PutOp(local::TanhOp);\n                rec.PutArg( arg[0] );\n                CPPAD_ASSERT_UNKNOWN( NumArg(local::TanhOp) == 1 );\n                break;\n\n                case tan_graph_op:\n                i_result = rec.PutOp(local::TanOp);\n                rec.PutArg( arg[0] );\n                CPPAD_ASSERT_UNKNOWN( NumArg(local::TanOp) == 1 );\n                break;\n\n                default:\n                CPPAD_ASSERT_UNKNOWN( false );\n                break;\n            }\n            else if( type_x[0] == dynamic_enum ) switch( op_enum )\n            {\n                case abs_graph_op:\n                i_result = rec.put_dyn_par(nan, local::abs_dyn, arg[0] );\n                CPPAD_ASSERT_UNKNOWN( CppAD::isnan( parameter[i_result] ) );\n                break;\n\n                case acosh_graph_op:\n                i_result = rec.put_dyn_par(nan, local::acosh_dyn, arg[0] );\n                CPPAD_ASSERT_UNKNOWN( CppAD::isnan( parameter[i_result] ) );\n                break;\n\n                case asinh_graph_op:\n                i_result = rec.put_dyn_par(nan, local::asinh_dyn, arg[0] );\n                CPPAD_ASSERT_UNKNOWN( CppAD::isnan( parameter[i_result] ) );\n                break;\n\n                case atanh_graph_op:\n                i_result = rec.put_dyn_par(nan, local::atanh_dyn, arg[0] );\n                CPPAD_ASSERT_UNKNOWN( CppAD::isnan( parameter[i_result] ) );\n                break;\n\n                case erf_graph_op:\n                i_result = rec.put_dyn_par(nan, local::erf_dyn, arg[0] );\n                CPPAD_ASSERT_UNKNOWN( CppAD::isnan( parameter[i_result] ) );\n                break;\n\n                case erfc_graph_op:\n                i_result = rec.put_dyn_par(nan, local::erfc_dyn, arg[0] );\n                CPPAD_ASSERT_UNKNOWN( CppAD::isnan( parameter[i_result] ) );\n                break;\n\n                case expm1_graph_op:\n                i_result = rec.put_dyn_par(nan, local::expm1_dyn, arg[0] );\n                CPPAD_ASSERT_UNKNOWN( CppAD::isnan( parameter[i_result] ) );\n                break;\n\n                case log1p_graph_op:\n                i_result = rec.put_dyn_par(nan, local::log1p_dyn, arg[0] );\n                CPPAD_ASSERT_UNKNOWN( CppAD::isnan( parameter[i_result] ) );\n                break;\n\n                case acos_graph_op:\n                i_result = rec.put_dyn_par(nan, local::acos_dyn, arg[0] );\n                CPPAD_ASSERT_UNKNOWN( CppAD::isnan( parameter[i_result] ) );\n                break;\n\n                case asin_graph_op:\n                i_result = rec.put_dyn_par(nan, local::asin_dyn, arg[0] );\n                CPPAD_ASSERT_UNKNOWN( CppAD::isnan( parameter[i_result] ) );\n                break;\n\n                case atan_graph_op:\n                i_result = rec.put_dyn_par(nan, local::atan_dyn, arg[0] );\n                CPPAD_ASSERT_UNKNOWN( CppAD::isnan( parameter[i_result] ) );\n                break;\n\n                case cosh_graph_op:\n                i_result = rec.put_dyn_par(nan, local::cosh_dyn, arg[0] );\n                CPPAD_ASSERT_UNKNOWN( CppAD::isnan( parameter[i_result] ) );\n                break;\n\n                case cos_graph_op:\n                i_result = rec.put_dyn_par(nan, local::cos_dyn, arg[0] );\n                CPPAD_ASSERT_UNKNOWN( CppAD::isnan( parameter[i_result] ) );\n                break;\n\n                case exp_graph_op:\n                i_result = rec.put_dyn_par(nan, local::exp_dyn, arg[0] );\n                CPPAD_ASSERT_UNKNOWN( CppAD::isnan( parameter[i_result] ) );\n                break;\n\n                case log_graph_op:\n                i_result = rec.put_dyn_par(nan, local::log_dyn, arg[0] );\n                CPPAD_ASSERT_UNKNOWN( CppAD::isnan( parameter[i_result] ) );\n                break;\n\n                case neg_graph_op:\n                i_result = rec.put_dyn_par(nan, local::neg_dyn, arg[0] );\n                CPPAD_ASSERT_UNKNOWN( CppAD::isnan( parameter[i_result] ) );\n                break;\n\n                case sign_graph_op:\n                i_result = rec.put_dyn_par(nan, local::sign_dyn, arg[0] );\n                CPPAD_ASSERT_UNKNOWN( CppAD::isnan( parameter[i_result] ) );\n                break;\n\n                case sinh_graph_op:\n                i_result = rec.put_dyn_par(nan, local::sinh_dyn, arg[0] );\n                CPPAD_ASSERT_UNKNOWN( CppAD::isnan( parameter[i_result] ) );\n                break;\n\n                case sin_graph_op:\n                i_result = rec.put_dyn_par(nan, local::sin_dyn, arg[0] );\n                CPPAD_ASSERT_UNKNOWN( CppAD::isnan( parameter[i_result] ) );\n                break;\n\n                case sqrt_graph_op:\n                i_result = rec.put_dyn_par(nan, local::sqrt_dyn, arg[0] );\n                CPPAD_ASSERT_UNKNOWN( CppAD::isnan( parameter[i_result] ) );\n                break;\n\n                case tanh_graph_op:\n                i_result = rec.put_dyn_par(nan, local::tanh_dyn, arg[0] );\n                CPPAD_ASSERT_UNKNOWN( CppAD::isnan( parameter[i_result] ) );\n                break;\n\n                case tan_graph_op:\n                i_result = rec.put_dyn_par(nan, local::tan_dyn, arg[0] );\n                CPPAD_ASSERT_UNKNOWN( CppAD::isnan( parameter[i_result] ) );\n                break;\n\n                default:\n                CPPAD_ASSERT_UNKNOWN( false );\n                break;\n            }\n            else switch( op_enum )\n            {\n                case abs_graph_op:\n                result    = CppAD::abs( parameter[ arg[0] ] );\n                i_result  = rec.put_con_par(result);\n                CPPAD_ASSERT_UNKNOWN( parameter[i_result] == result );\n                break;\n\n                case acosh_graph_op:\n                result    = CppAD::acosh( parameter[ arg[0] ] );\n                i_result  = rec.put_con_par(result);\n                CPPAD_ASSERT_UNKNOWN( parameter[i_result] == result );\n                break;\n\n                case asinh_graph_op:\n                result    = CppAD::asinh( parameter[ arg[0] ] );\n                i_result  = rec.put_con_par(result);\n                CPPAD_ASSERT_UNKNOWN( parameter[i_result] == result );\n                break;\n\n                case atanh_graph_op:\n                result    = CppAD::atanh( parameter[ arg[0] ] );\n                i_result  = rec.put_con_par(result);\n                CPPAD_ASSERT_UNKNOWN( parameter[i_result] == result );\n                break;\n\n                case erf_graph_op:\n                result    = CppAD::erf( parameter[ arg[0] ] );\n                i_result  = rec.put_con_par(result);\n                CPPAD_ASSERT_UNKNOWN( parameter[i_result] == result );\n                break;\n\n                case erfc_graph_op:\n                result    = CppAD::erfc( parameter[ arg[0] ] );\n                i_result  = rec.put_con_par(result);\n                CPPAD_ASSERT_UNKNOWN( parameter[i_result] == result );\n                break;\n\n                case expm1_graph_op:\n                result    = CppAD::expm1( parameter[ arg[0] ] );\n                i_result  = rec.put_con_par(result);\n                CPPAD_ASSERT_UNKNOWN( parameter[i_result] == result );\n                break;\n\n                case log1p_graph_op:\n                result    = CppAD::log1p( parameter[ arg[0] ] );\n                i_result  = rec.put_con_par(result);\n                CPPAD_ASSERT_UNKNOWN( parameter[i_result] == result );\n                break;\n\n                case acos_graph_op:\n                result    = CppAD::acos( parameter[ arg[0] ] );\n                i_result  = rec.put_con_par(result);\n                CPPAD_ASSERT_UNKNOWN( parameter[i_result] == result );\n                break;\n\n                case asin_graph_op:\n                result    = CppAD::asin( parameter[ arg[0] ] );\n                i_result  = rec.put_con_par(result);\n                CPPAD_ASSERT_UNKNOWN( parameter[i_result] == result );\n                break;\n\n                case atan_graph_op:\n                result    = CppAD::atan( parameter[ arg[0] ] );\n                i_result  = rec.put_con_par(result);\n                CPPAD_ASSERT_UNKNOWN( parameter[i_result] == result );\n                break;\n\n                case cosh_graph_op:\n                result    = CppAD::cosh( parameter[ arg[0] ] );\n                i_result  = rec.put_con_par(result);\n                CPPAD_ASSERT_UNKNOWN( parameter[i_result] == result );\n                break;\n\n                case cos_graph_op:\n                result    = CppAD::cos( parameter[ arg[0] ] );\n                i_result  = rec.put_con_par(result);\n                CPPAD_ASSERT_UNKNOWN( parameter[i_result] == result );\n                break;\n\n                case exp_graph_op:\n                result    = CppAD::exp( parameter[ arg[0] ] );\n                i_result  = rec.put_con_par(result);\n                CPPAD_ASSERT_UNKNOWN( parameter[i_result] == result );\n                break;\n\n                case log_graph_op:\n                result    = CppAD::log( parameter[ arg[0] ] );\n                i_result  = rec.put_con_par(result);\n                CPPAD_ASSERT_UNKNOWN( parameter[i_result] == result );\n                break;\n\n                case neg_graph_op:\n                result    = - parameter[ arg[0] ];\n                i_result  = rec.put_con_par(result);\n                CPPAD_ASSERT_UNKNOWN( parameter[i_result] == result );\n                break;\n\n                case sign_graph_op:\n                result    = CppAD::sign( parameter[ arg[0] ] );\n                i_result  = rec.put_con_par(result);\n                CPPAD_ASSERT_UNKNOWN( parameter[i_result] == result );\n                break;\n\n                case sinh_graph_op:\n                result    = CppAD::sinh( parameter[ arg[0] ] );\n                i_result  = rec.put_con_par(result);\n                CPPAD_ASSERT_UNKNOWN( parameter[i_result] == result );\n                break;\n\n                case sin_graph_op:\n                result    = CppAD::sin( parameter[ arg[0] ] );\n                i_result  = rec.put_con_par(result);\n                CPPAD_ASSERT_UNKNOWN( parameter[i_result] == result );\n                break;\n\n                case sqrt_graph_op:\n                result    = CppAD::sqrt( parameter[ arg[0] ] );\n                i_result  = rec.put_con_par(result);\n                CPPAD_ASSERT_UNKNOWN( parameter[i_result] == result );\n                break;\n\n                case tanh_graph_op:\n                result    = CppAD::tanh( parameter[ arg[0] ] );\n                i_result  = rec.put_con_par(result);\n                CPPAD_ASSERT_UNKNOWN( parameter[i_result] == result );\n                break;\n\n                case tan_graph_op:\n                result    = CppAD::tan( parameter[ arg[0] ] );\n                i_result  = rec.put_con_par(result);\n                CPPAD_ASSERT_UNKNOWN( parameter[i_result] == result );\n                break;\n\n                default:\n                CPPAD_ASSERT_UNKNOWN( false );\n                break;\n            }\n        }\n        // -------------------------------------------------------------------\n        // binary operators\n        // -------------------------------------------------------------------\n        else\n        {   CPPAD_ASSERT_UNKNOWN( n_arg == 2 && n_result == 1 );\n            Base result; // used in cases where both arguments are constants\n            if( type_x[0] == variable_enum && type_x[1] == variable_enum )\n            switch( op_enum )\n            {\n                case add_graph_op:\n                i_result = rec.PutOp(local::AddvvOp);\n                rec.PutArg( arg[0], arg[1] );\n                CPPAD_ASSERT_UNKNOWN( NumArg(local::AddvvOp) == 2 );\n                break;\n\n                case azmul_graph_op:\n                i_result = rec.PutOp(local::ZmulvvOp);\n                rec.PutArg( arg[0], arg[1] );\n                CPPAD_ASSERT_UNKNOWN( NumArg(local::ZmulvvOp) == 2 );\n                break;\n\n                case div_graph_op:\n                i_result = rec.PutOp(local::DivvvOp);\n                rec.PutArg( arg[0], arg[1] );\n                CPPAD_ASSERT_UNKNOWN( NumArg(local::DivvvOp) == 2 );\n                break;\n\n                case mul_graph_op:\n                i_result = rec.PutOp(local::MulvvOp);\n                rec.PutArg( arg[0], arg[1] );\n                CPPAD_ASSERT_UNKNOWN( NumArg(local::MulvvOp) == 2 );\n                break;\n\n                case pow_graph_op:\n                i_result = rec.PutOp(local::PowvvOp);\n                rec.PutArg( arg[0], arg[1] );\n                CPPAD_ASSERT_UNKNOWN( NumArg(local::PowvvOp) == 2 );\n                break;\n\n                case sub_graph_op:\n                i_result = rec.PutOp(local::SubvvOp);\n                rec.PutArg( arg[0], arg[1] );\n                CPPAD_ASSERT_UNKNOWN( NumArg(local::SubvvOp) == 2 );\n                break;\n\n                default:\n                CPPAD_ASSERT_UNKNOWN( false );\n                break;\n            }\n            else if( type_x[0] == variable_enum ) switch( op_enum )\n            {\n                // addition is communitative, so use Addpv\n                case add_graph_op:\n                i_result = rec.PutOp(local::AddpvOp);\n                rec.PutArg( arg[1], arg[0] );\n                CPPAD_ASSERT_UNKNOWN( NumArg(local::AddpvOp) == 2 );\n                break;\n\n                case azmul_graph_op:\n                i_result = rec.PutOp(local::ZmulvpOp);\n                rec.PutArg( arg[0], arg[1] );\n                CPPAD_ASSERT_UNKNOWN( NumArg(local::ZmulvpOp) == 2 );\n                break;\n\n                case div_graph_op:\n                i_result = rec.PutOp(local::DivvpOp);\n                rec.PutArg( arg[0], arg[1] );\n                CPPAD_ASSERT_UNKNOWN( NumArg(local::DivvpOp) == 2 );\n                break;\n\n                // multiplication is communitative, so use Mulpv\n                case mul_graph_op:\n                i_result = rec.PutOp(local::MulpvOp);\n                rec.PutArg( arg[1], arg[0] );\n                CPPAD_ASSERT_UNKNOWN( NumArg(local::MulpvOp) == 2 );\n                break;\n\n                case pow_graph_op:\n                i_result = rec.PutOp(local::PowvpOp);\n                rec.PutArg( arg[0], arg[1] );\n                CPPAD_ASSERT_UNKNOWN( NumArg(local::PowvpOp) == 2 );\n                break;\n\n                case sub_graph_op:\n                i_result = rec.PutOp(local::SubvpOp);\n                rec.PutArg( arg[0], arg[1] );\n                CPPAD_ASSERT_UNKNOWN( NumArg(local::SubvpOp) == 2 );\n                break;\n\n                default:\n                CPPAD_ASSERT_UNKNOWN( false );\n                break;\n            }\n            else if( type_x[1] == variable_enum ) switch( op_enum )\n            {\n                case add_graph_op:\n                i_result = rec.PutOp(local::AddpvOp);\n                rec.PutArg( arg[0], arg[1] );\n                CPPAD_ASSERT_UNKNOWN( NumArg(local::AddpvOp) == 2 );\n                break;\n\n                case azmul_graph_op:\n                i_result = rec.PutOp(local::ZmulpvOp);\n                rec.PutArg( arg[0], arg[1] );\n                CPPAD_ASSERT_UNKNOWN( NumArg(local::ZmulpvOp) == 2 );\n                break;\n\n                case div_graph_op:\n                i_result = rec.PutOp(local::DivpvOp);\n                rec.PutArg( arg[0], arg[1] );\n                CPPAD_ASSERT_UNKNOWN( NumArg(local::DivpvOp) == 2 );\n                break;\n\n                case mul_graph_op:\n                i_result = rec.PutOp(local::MulpvOp);\n                rec.PutArg( arg[0], arg[1] );\n                CPPAD_ASSERT_UNKNOWN( NumArg(local::MulpvOp) == 2 );\n                break;\n\n                case pow_graph_op:\n                i_result = rec.PutOp(local::PowpvOp);\n                rec.PutArg( arg[0], arg[1] );\n                CPPAD_ASSERT_UNKNOWN( NumArg(local::PowpvOp) == 2 );\n                break;\n\n                case sub_graph_op:\n                i_result = rec.PutOp(local::SubpvOp);\n                rec.PutArg( arg[0], arg[1] );\n                CPPAD_ASSERT_UNKNOWN( NumArg(local::SubpvOp) == 2 );\n                break;\n\n                default:\n                CPPAD_ASSERT_UNKNOWN( false );\n                break;\n            }\n            else if( type_x[0] == dynamic_enum || type_x[1] == dynamic_enum )\n            switch( op_enum )\n            {\n                case add_graph_op:\n                i_result =\n                    rec.put_dyn_par(nan, local::add_dyn, arg[0], arg[1]);\n                CPPAD_ASSERT_UNKNOWN( CppAD::isnan( parameter[i_result] ) );\n                break;\n\n                case azmul_graph_op:\n                i_result =\n                    rec.put_dyn_par(nan, local::zmul_dyn, arg[0], arg[1]);\n                CPPAD_ASSERT_UNKNOWN( CppAD::isnan( parameter[i_result] ) );\n                break;\n\n                case div_graph_op:\n                i_result =\n                    rec.put_dyn_par(nan, local::div_dyn, arg[0], arg[1]);\n                CPPAD_ASSERT_UNKNOWN( CppAD::isnan( parameter[i_result] ) );\n                break;\n\n                case mul_graph_op:\n                i_result =\n                    rec.put_dyn_par(nan, local::mul_dyn, arg[0], arg[1]);\n                break;\n\n                case pow_graph_op:\n                i_result =\n                    rec.put_dyn_par(nan, local::pow_dyn, arg[0], arg[1]);\n                CPPAD_ASSERT_UNKNOWN( CppAD::isnan( parameter[i_result] ) );\n                break;\n\n                case sub_graph_op:\n                i_result =\n                    rec.put_dyn_par(nan, local::sub_dyn, arg[0], arg[1]);\n                CPPAD_ASSERT_UNKNOWN( CppAD::isnan( parameter[i_result] ) );\n                break;\n\n                default:\n                CPPAD_ASSERT_UNKNOWN( false );\n                break;\n            }\n            else switch( op_enum )\n            {\n                case add_graph_op:\n                result = parameter[ arg[0] ] + parameter[ arg[1] ];\n                i_result = rec.put_con_par(result);\n                CPPAD_ASSERT_UNKNOWN( parameter[i_result] == result );\n                break;\n\n                case azmul_graph_op:\n                result = azmul( parameter[ arg[0] ] , parameter[ arg[1] ] );\n                i_result = rec.put_con_par(result);\n                CPPAD_ASSERT_UNKNOWN( parameter[i_result] == result );\n                break;\n\n                case div_graph_op:\n                result = parameter[ arg[0] ] / parameter[ arg[1] ];\n                i_result = rec.put_con_par(result);\n                CPPAD_ASSERT_UNKNOWN( parameter[i_result] == result );\n                break;\n\n                case mul_graph_op:\n                result = parameter[ arg[0] ] * parameter[ arg[1] ];\n                i_result = rec.put_con_par(result);\n                CPPAD_ASSERT_UNKNOWN( parameter[i_result] == result );\n                break;\n\n                case pow_graph_op:\n                result = pow( parameter[ arg[0] ],  parameter[ arg[1] ] );\n                i_result = rec.put_con_par(result);\n                CPPAD_ASSERT_UNKNOWN( parameter[i_result] == result );\n                break;\n\n                case sub_graph_op:\n                result = parameter[ arg[0] ] - parameter[ arg[1] ];\n                i_result = rec.put_con_par(result);\n                CPPAD_ASSERT_UNKNOWN( parameter[i_result] == result );\n                break;\n\n                default:\n                CPPAD_ASSERT_UNKNOWN( false );\n                break;\n\n            }\n        }\n        // Exclude cases where node_type and node2fun for the results\n        // have already been set\n        if( n_result != 0 )\n        if( op_enum != atom_graph_op && op_enum != atom4_graph_op )\n        {   // set node_type and node2fun for result\n            //\n            CPPAD_ASSERT_UNKNOWN( i_result != 0 );\n            CPPAD_ASSERT_UNKNOWN( n_result == 1 );\n            if( n_var_arg > 0 )\n                node_type.push_back(variable_enum);\n            else if( n_dyn_arg > 0 )\n                node_type.push_back(dynamic_enum);\n            else\n                node_type.push_back(constant_enum);\n            node2fun.push_back(i_result);\n        }\n        //\n# ifndef NDEBUG\n        start_result          += n_result;\n# endif\n        CPPAD_ASSERT_UNKNOWN( node2fun.size() == start_result );\n        CPPAD_ASSERT_UNKNOWN( node_type.size() == start_result );\n    }\n    // set this->dep_parameter_, set this->dep_taddr_\n    //\n    CPPAD_ASSERT_NARG_NRES(local::ParOp, 1, 1);\n    dep_parameter_.resize( n_dependent );\n    dep_taddr_.resize( n_dependent );\n    for(size_t i = 0; i < n_dependent; ++i)\n    {\n        CPPAD_ASSERT_UNKNOWN(\n            node_type[ graph_obj.dependent_vec_get(i) ] != number_ad_type_enum\n        );\n        if( node_type[ graph_obj.dependent_vec_get(i) ] == variable_enum )\n        {   dep_parameter_[i] = false;\n            dep_taddr_[i]     = size_t( node2fun[ graph_obj.dependent_vec_get(i) ] );\n        }\n        else\n        {   dep_parameter_[i] = true;\n            dep_taddr_[i]     = size_t( rec.PutOp(local::ParOp) );\n            rec.PutArg( node2fun[ graph_obj.dependent_vec_get(i) ] );\n        }\n    }\n    rec.PutOp(local::EndOp);\n    // ----------------------------------------------------------------------\n    // End recording, set private member data except for\n    // dep__parameter_ and dep_taddr_\n    // ----------------------------------------------------------------------\n    //\n    // bool values in this object except check_for_nan_\n    has_been_optimized_        = false;\n    //\n    // size_t values in this object\n    compare_change_count_      = 1;\n    compare_change_number_     = 0;\n    compare_change_op_index_   = 0;\n    num_order_taylor_          = 0;\n    cap_order_taylor_          = 0;\n    num_direction_taylor_      = 0;\n    num_var_tape_              = rec.num_var();\n    //\n    // taylor_\n    taylor_.resize(0);\n    //\n    // cskip_op_\n    cskip_op_.resize( rec.num_var_op() );\n    //\n    // load_op2var_\n    load_op2var_.resize( rec.num_var_load() );\n    //\n    // play_\n    // Now that each dependent variable has a place in the recording,\n    // and there is a EndOp at the end of the record, we can transfer the\n    // recording to the player and and erase the recording.\n    play_.get_recording(rec, n_variable_ind_fun);\n    //\n    // ind_taddr_\n    // Note that play_ has been set, we can use it to check operators\n    ind_taddr_.resize(n_variable_ind_fun);\n    CPPAD_ASSERT_UNKNOWN( n_variable_ind_fun < num_var_tape_);\n    for(size_t j = 0; j < n_variable_ind_fun; j++)\n    {   CPPAD_ASSERT_UNKNOWN( play_.GetOp(j+1) == local::InvOp );\n        ind_taddr_[j] = j+1;\n    }\n    //\n    // for_jac_sparse_pack_, for_jac_sparse_set_\n    for_jac_sparse_pack_.resize(0, 0);\n    for_jac_sparse_set_.resize(0,0);\n    //\n    // resize subgraph_info_\n    subgraph_info_.resize(\n        ind_taddr_.size(),   // n_dep\n        dep_taddr_.size(),   // n_ind\n        play_.num_var_op(),  // n_op\n        play_.num_var()      // n_var\n    );\n    //\n    // set the function name\n    function_name_ = function_name;\n    //\n    return;\n}\n// BEGIN_ONE_ARGUMENT\ntemplate <class Base, class RecBase>\nvoid CppAD::ADFun<Base,RecBase>::from_graph(\n    const CppAD::cpp_graph& graph_obj     )\n// END_ONE_ARGUMENT\n{   size_t n_variable_ind = graph_obj.n_variable_ind_get();\n    size_t n_dynamic_ind  = graph_obj.n_dynamic_ind_get();\n    CppAD::vector<bool> dyn2var(n_dynamic_ind), var2dyn(n_variable_ind);\n    for(size_t j = 0; j < n_dynamic_ind; ++j)\n        dyn2var[j] = false;\n    for(size_t j = 0; j < n_variable_ind; ++j)\n        var2dyn[j] = false;\n    //\n    from_graph(graph_obj, dyn2var, var2dyn);\n}\n\n} // END_CPPAD_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/graph/from_json.hpp",
    "content": "# ifndef CPPAD_CORE_GRAPH_FROM_JSON_HPP\n# define CPPAD_CORE_GRAPH_FROM_JSON_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/core/ad_fun.hpp>\n# include <cppad/core/ad_type.hpp>\n# include <cppad/local/graph/json_parser.hpp>\n\n/*\n{xrst_begin from_json}\n\nADFun Object Corresponding to a Json AD Graph\n#############################################\n\nSyntax\n******\n| |tab| ``ADFun`` < *Base* > *fun*\n| |tab| *fun* . ``from_json`` ( *json* )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_PROTOTYPE\n    // END_PROTOTYPE\n}\n\njson\n****\nis a :ref:`json_ad_graph-name` .\n\nBase\n****\nis the type corresponding to this :ref:`adfun-name` object;\ni.e., its calculations are done using the type *Base* .\n\nRecBase\n*******\nin the prototype above, *RecBase* is the same type as *Base* .\n{xrst_toc_hidden\n    example/json/from_json.cpp\n}\nExample\n*******\nThe file :ref:`from_json.cpp-name` is an example and test of this operation.\n\n{xrst_end from_json}\n*/\n// BEGIN_PROTOTYPE\ntemplate <class Base, class RecBase>\nvoid CppAD::ADFun<Base,RecBase>::from_json(const std::string& json)\n// END_PROTOTYPE\n{\n    using CppAD::isnan;\n    //\n    //\n    // C++ graph object\n    cpp_graph graph_obj;\n    //\n    // convert json to graph representation\n    local::graph::json_parser(json, graph_obj);\n    //\n    // convert the graph representation to a function\n    from_graph(graph_obj);\n    //\n    return;\n}\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/graph/graph_op_enum.hpp",
    "content": "# ifndef CPPAD_CORE_GRAPH_GRAPH_OP_ENUM_HPP\n# define CPPAD_CORE_GRAPH_GRAPH_OP_ENUM_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cstddef>\n# include <string>\n# include <map>\n\n# include <cppad/utility/vector.hpp>\n# include <cppad/configure.hpp>\n\n/*\n{xrst_begin graph_op_enum}\n\nC++ AD Graph Operator Enum Type\n###############################\n\n{xrst_comment\n    The following headings are referenced by comments in cpp_graph_op.cpp:\n    Atomic Function, Comparison, Discrete Function, Print, Summation\n}\n\nUnary\n*****\nThe unary operators have one argument and one result node.\nThe argument is a node index and the result is the next node.\n\nBinary\n******\nThe binary operators have two arguments and one result node.\nThe arguments are node indices and the result is the next node.\nThe first (second) argument is the left (right) operand node index.\n\nConditional Expression\n**********************\nThe conditional expression operators have four arguments and one result node.\nThe arguments are node indices and the result is the next node.\nThe first argument is :ref:`CondExp@left` ,\nthe second is :ref:`CondExp@right` ,\nthe third is :ref:`CondExp@if_true` ,\nthe fourth is :ref:`CondExp@if_false` ,\nthe result is given by\n\n| |tab| ``if`` ( *left* *cop* *right* )\n| |tab| |tab| *result* = *if_true* ;\n| |tab| ``else``\n| |tab| |tab| *result* = *if_false* ;\n\nwhere *cop* is given in the comment after the enum type values below.\n\nOther Comparisons\n=================\nNote that\n\n    ``CondExpGt`` ( *left* , *right* , *if_true* , *if_false* )\n\nis equivalent to\n\n    ``CondExpLe`` ( *left* , *right* , *if_false* , *if_true* )\n\nSimilar conversions can be used for all the possible\n:ref:`conditional expressions<CondExp-name>` .\n\nComparison\n**********\nThe comparison operators have two arguments and no result node.\nThe first (second) argument is the left (right) operand node index.\nThe comparison result was true for the value of the independent\ndynamic parameters and independent variables at which this graph was created.\n\nOther Comparisons\n=================\nThe comparison result true for *left* > *right*\nis equivalent to the comparison result true for *right* < *left* .\nThe comparison result false for *left* > *right*\nis equivalent to the comparison result true for *left* <= *right* .\nIn a similar fashion, all the possible comparisons results\ncan be converted to a true result for one of the comparisons above.\n\nSummation\n*********\nThe summation operator has one node result and a variable\nnumber of arguments.\nThe first argument is the number of nodes in the summation,\nand the other arguments are the indices of the nodes to be summed.\nThe total number of arguments for this operator\nis one plus the number of nodes in the summation.\n\nDiscrete Function\n*****************\nThe discrete function operator has two arguments and one node result.\nThe first argument is the index in\n:ref:`cpp_ad_graph@discrete_name_vec` for the\n:ref:`discrete@name` of the discrete function that is called.\nThe second argument is the index of the node that is the argument\nto the discrete function.\n\nAtomic Function\n***************\nThe atomic function operator has a variable number of arguments\nand a variable number of result nodes.\nThere are three extra arguments for :ref:`atomic_three-name` functions and\nfour extra arguments for :ref:`atomic_four-name` functions.\nThe total number of operator arguments is\nthe number of extra arguments\nplus the number of arguments for the function being called.\nThe extra arguments come before the function arguments.\n\n#. The first operator argument is function name represented by it's index in the\n   :ref:`cpp_ad_graph@atomic_name_vec` .\n#. If this is an atomic four function call,\n   the second operator argument is the :ref:`atomic_four_call@call_id` .\n#. In the atomic three (atomic four) case, second (third) operator argument\n   is the number of results for this function call.\n   The order of the function results is determined by the function being called.\n#. In the atomic three (atomic four) case, the third (fourth) operator argument\n   is the number of arguments for this function call.\n#. The rest of the operator arguments are the node indices for each of the\n   function arguments.\n   The order of the function arguments is determined by function being called.\n\nPrint\n*****\nThe print operator has four arguments.\n\n#. The first argument is the index in\n   :ref:`cpp_ad_graph@print_text_vec` for the\n   :ref:`PrintFor@before` text for this print operator.\n#. The second argument is the index in\n   :ref:`cpp_ad_graph@print_text_vec` for the\n   :ref:`PrintFor@after` text for this print operator.\n#. The third argument is the node corresponding to\n   :ref:`PrintFor@notpos` for this print operator.\n#. The fourth argument is the node corresponding to\n   :ref:`PrintFor@value` for this print operator.\n\nMissing Operators\n*****************\nAs of yet the following :ref:`ADFun-name` operators do not have a corresponding\ngraph operator:\n\n#. Operators to load and store :ref:`VecAD-name` elements.\n#. An operator for the :ref:`atomic_two-name` interface.\n\nEnum Values\n***********\n{xrst_literal\n    SORT_THIS_LINE_PLUS_3\n    SORT_THIS_LINE_MINUS_4\n}\n\nExamples\n********\n\nContents\n********\n{xrst_toc_table\n    example/graph/azmul_op.cpp\n    example/graph/add_op.cpp\n    example/graph/div_op.cpp\n    example/graph/mul_op.cpp\n    example/graph/pow_op.cpp\n    example/graph/sub_op.cpp\n    example/graph/unary_op.cpp\n    example/graph/sum_op.cpp\n    example/graph/comp_op.cpp\n    example/graph/cexp_op.cpp\n    example/graph/discrete_op.cpp\n    example/graph/atom_op.cpp\n    example/graph/atom4_op.cpp\n    example/graph/print_op.cpp\n}\n\n{xrst_end graph_op_enum}\n*/\n// BEGIN_SORT_THIS_LINE_PLUS_3\nnamespace CppAD { namespace graph {\n    enum graph_op_enum {\n        abs_graph_op,      // unary: absolute value\n        acos_graph_op,     // unary: inverse cosine\n        acosh_graph_op,    // unary: inverse hyperbolic cosine\n        add_graph_op,      // binary: addition\n        asin_graph_op,     // unary: inverse sine\n        asinh_graph_op,    // unary: inverse hyperbolic sine\n        atan_graph_op,     // unary: inverse tangent\n        atanh_graph_op,    // unary: inverse hyperbolic tangent\n        atom4_graph_op,    // atomic four function call\n        atom_graph_op,     // atomic three function call\n        azmul_graph_op,    // binary: absolute zero multiplication\n        cexp_eq_graph_op,  // conditional expression: ==\n        cexp_le_graph_op,  // conditional expression: <=\n        cexp_lt_graph_op,  // conditional expression: <\n        comp_eq_graph_op,  // comparison: ==\n        comp_le_graph_op,  // comparison: <=\n        comp_lt_graph_op,  // comparison: <\n        comp_ne_graph_op,  // comparison: !=\n        cos_graph_op,      // unary: cosine\n        cosh_graph_op,     // unary: hyperbolic cosine\n        discrete_graph_op, // discrete function\n        div_graph_op,      // binary: division\n        erf_graph_op,      // unary: error function\n        erfc_graph_op,     // unary: complementary error function\n        exp_graph_op,      // unary: exponential\n        expm1_graph_op,    // unary: exponential minus one\n        log1p_graph_op,    // unary: logarithm of one plus argument\n        log_graph_op,      // unary: logarithm\n        mul_graph_op,      // binary: multiplication\n        neg_graph_op,      // unary: minus\n        pow_graph_op,      // binary: first argument raised to second argument\n        print_graph_op,    // print during zero order forward\n        sign_graph_op,     // unary: sign of argument\n        sin_graph_op,      // unary: sine\n        sinh_graph_op,     // unary: hyperbolic sine\n        sqrt_graph_op,     // unary: square root\n        sub_graph_op,      // binary: subtraction\n        sum_graph_op,      // summation\n        tan_graph_op,      // unary: tangent\n        tanh_graph_op,     // unary: hyperbolic tangent\n        n_graph_op         // number of graph_op_enum operators\n    };\n} }\n// END_SORT_THIS_LINE_MINUS_4\n\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/graph/json_ad_graph.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin json_ad_graph}\n{xrst_spell\n    nx\n    str\n}\n\nJson Representation of an AD Graph\n##################################\n\nSee Also\n********\n:ref:`cpp_ad_graph-title`.\n\nNode Indices\n************\nThe nodes in an AD graph have the following order:\n::\n\n        p_0 , ... ,  p_{np-1} ,\n        x_0 , ... ,  x_{nx-1} ,\n        c_0 , ... ,  c_{nc-1} ,\n        r_0 , ... ,  r_{no-1}\n\np\n=\nThe sub-vector\n::\n\n        p_0, ... , p_{np-1}\n\nis the independent dynamic parameter vector;\nsee :ref:`json_ad_graph@dynamic_ind_vec@n_dynamic_ind` .\nThe node index corresponding to *p_0* is ``1`` .\n\nx\n=\nThe sub-vector\n::\n\n        x_0, ... , x_{nx-1}\n\nis the independent variable vector;\nsee :ref:`json_ad_graph@variable_ind_vec@n_variable_ind` .\nThe node index corresponding to *x_0* is\nthe index corresponding to *p_0* plus *np* .\n\nc\n=\nThe sub-vector\n::\n\n        c_0, ... , c_{nc-1}\n\nis the constant parameter vector;\nsee :ref:`json_ad_graph@constant_vec` .\nThe node index corresponding to *c_0* is\nthe index corresponding to *x_0* plus *nx* .\n\nr_i\n===\nFor *i* =0,..., *no* ``-1``\nthe sub-vector *r_i*\nis the result vector for the *i*-th operator usage;\nsee :ref:`json_ad_graph@op_usage_vec` .\nThe value *no* is the number of operator usages; see\n:ref:`json_ad_graph@op_usage_vec@n_usage` below.\nAll of the arguments for an the *i*-th operator are nodes\nthat come before the first element of *r_i* .\nThe node index corresponding to the first element of *r_0* is\nthe index corresponding to *c_0* plus *nc* .\nFor *i*  > 0 ,\nThe node index corresponding to the first element of *r_i* is\nthe index corresponding to the first element of *r_* { *i-1* } plus\nthe number of results for the *i-1*-th operator.\n\nFormat\n******\nA complete description of the format for an AD graph is given below.\nFor a general description of Json format see\n`Json Data types <https://en.wikipedia.org/wiki/JSON#Data_types>`_.\n\nToken\n*****\n\nWhite Space\n===========\nAny sequence of white space, except within a string,\nterminates the current token and is otherwise ignored.\n\nNon-Negative Integer\n====================\nA non-negative integer is a non-empty sequence of the following\ncharacters: ``0123456789`` .\n\nFloating Point Number\n=====================\nA floating point number is a non-empty sequence of the following\ncharacters: ``0123456789+-eE.`` .\nNote that there can't be any white space between a leading plus\nor minus sign and the rest of the number.\n\nString\n======\nA string starts with the double quote character ``\"``\nand includes all the characters until the next double quote.\nThe value of a string is the sequence of characters between the\ndouble quotes.\nCurrently there is no support using the double quote\nas part of the value of a string.\n\nSingle Character\n================\nThe following is a list of the single character tokens:\n\n.. list-table::\n    :widths: auto\n\n    * - Token\n      - Usage\n    * - ``,``\n      - separates entries in a list\n    * - ``:``\n      - separates name from corresponding value\n    * - ``{``\n      - starts a list of name ``:`` value pairs\n    * - ``}``\n      - ends a list of name ``:`` value pairs\n    * - ``[``\n      - starts a list of values\n    * - ``]``\n      - ends a list of values\n\nop_define_vec\n*************\nThis vector has the following Json format:\n\n    [ *n_define* , [ *first_op_define* , ..., *last_op_define*  ] ]\n\nwhere the non-negative integer *n_define*\nis the number of operator definitions in this vector.\n\nop_define\n=========\nThe possible operator definitions *op_define* are listed in\nsection :ref:`json_graph_op-name` .\nIf an operator has a fixed number of arguments, one result, and\nonly node indices for arguments, its definition has the form\n\n| {\n| |tab| ``\"op_code\"`` : *op_code* ,\n| |tab| ``\"name\"`` : *name* ,\n| |tab| ``\"n_arg\"`` : *n_arg*\n| }\n\nOtherwise the operator definition has the form\n\n| {\n| |tab| ``\"op_code\"`` : *op_code* ,\n| |tab| ``\"name\"`` : *name*\n| }\n\nFor example, the following is the *op_define* corresponding to the\n:ref:`json_graph_op@Binary Operators@add` operator:\n\n| {\n| |tab| ``\"op_code\"`` : *op_code* ,\n| |tab| ``\"name\"`` : ``\"add\"`` ,\n| |tab| ``\"n_arg\"`` :        2\n| }\n\nop_code\n=======\nNote that every operator definition has a *op_code* value.\nThese values must start at one and increment by one for each operator\ndefinition; i.e., the *op_code* for in *first_op_define* is\n``1`` , the value in the next definition is ``2`` , and so on.\nThe order of the definitions determines the *op_code* values\nused to specify operators for this computational graph.\n\nn_arg\n=====\nThis is the number of argument values for the operator; i.e.,\nthe dimension of its domain space.\nIf it is present in an operator definition,\nit is the same value for every usage of the operator.\nOtherwise it is specified by the operator usage.\n\nn_result\n========\nThis is the number of results for the operator; i.e.,\nthe dimension of its range space.\nIf *n_arg* is present in an operator definition,\n*n_result* is one for every usage of the operator.\nOtherwise it is specified by the operator usage.\n\nop_usage\n********\nEach operation usage\nhas the following information:\n\nn_arg In Definition\n===================\nIf *n_arg* is present in an operator definition,\nit is not in a corresponding *op_usage* which as the form\n\n    [ *op_code* , *first_arg* , ..., *last_arg*  ]\n\nn_arg Not In Definition\n=======================\nIf *n_arg* is not in an operator definition,\nit is in a corresponding *op_usage* .\nIf there are no strings in a corresponding usage, it has the form\n\n    [ *op_code* , *n_result* , *n_arg* , [ *first_arg* , ..., *last_arg*  ] ]\n\nStrings In Usage\n================\nIf *n_arg* is not in an operator definition,\nand there are strings in a corresponding usage,\na corresponding usage has the form\n\n| |tab| [ *op_code* , *first_str* , ..., *last_str* , *n_result* , *n_arg* ,\n| |tab| |tab| [ *first_arg* , ..., *last_arg*  ]\n| |tab| ]\n\nwhere *first_str* ..., *last_str* ,\nare a fixed number of strings that are part of the corresponding operator.\n\nfirst_arg, ..., last_arg\n========================\nThe values *first_arg* , ..., *last_arg* ,\nare the node indices corresponding to each of the arguments for this operator.\nThey must be less than the node index corresponding to the first\nresult for this operator; see\n:ref:`json_ad_graph@Node Indices@r_i` above.\nThey specify which previous results (results before this operator in the graph)\ncorrespond to each of the arguments to this operator.\nAs a consequence, there cannot be any cycles in the graph where\nthe operators are represented by arcs from the argument to the result nodes;\ni.e., the graph is acyclic.\n\ndynamic_ind_vec\n***************\nThis is the independent dynamic parameter vector\n(called *p* above); see\n:ref:`Independent@dynamic` .\nThe function can depend on these parameters,\nbut no derivatives are computed with respect to these parameters.\n\nn_dynamic_ind\n=============\nWe use the non-negative integer *n_dynamic_ind*\nfor the number of elements in this vector\n(called *np* above).\n\nvariable_ind_vec\n****************\nThis is the independent variable vector\n(called *x* above); see\n:ref:`Independent@x` .\nThe function can depend on these variable and\nderivatives can be computed  with respect to these variables.\n\nn_variable_ind\n==============\nWe use the non-negative integer *n_variable_ind*\nfor the number of element in this vector\n(called *nx* above).\n\nconstant_vec\n************\nThis is the constant parameter vector (called *c* above).\nThese parameters can be used to define the function and cannot change.\nThe Json format for *constant_vec* is\n\n    [ *n_constant* , [ *first_constant* , ..., *last_constant*  ] ]\n\nEach of the elements of this vector,\ne.g., *first_constant* ,\nis a :ref:`json_ad_graph@Token@Floating Point Number`\nspecifying the value for the corresponding node.\n\nn_constant\n==========\nThe non-negative integer *n_constant*\nis the number of elements in this vector\n(called *nc* above).\n\nop_usage_vec\n************\nThe Jason format for an *op_usage_vec* is\n\n    [ *n_usage* , [ *first_op_usage* , ..., *last_op_usage*  ] ]\n\nEach of the elements of this vector,\ne.g. *first_op_usage* ,\nis an :ref:`json_ad_graph@op_usage` .\n\nn_usage\n=======\nThe non-negative integer *n_usage*\nis the number of operator usages (called *no* above).\n\ndependent_vec\n*************\nThis is the vector of dependent variable node indices.\nThis identifies which nodes in the graph correspond to dependent variables.\nThe Json format for *dependent_vec* is\n\n    [ *n_dependent* , [ *first_dependent* , ..., *last_dependent*  ] ]\n\nEach of the elements of this vector,\ne.g. *first_dependent* ,\nis a :ref:`json_ad_graph@Token@Non-Negative Integer`\ncorresponding to a node index in the graph.\n\nn_dependent\n===========\nThe non-negative integer *n_dependent*\nis the number of elements in this vector.\n\nAD Graph\n********\nEach operator corresponds to a set of arcs from its argument nodes\nto its result nodes.\nThe graph is acyclic; see\n:ref:`json_ad_graph@op_usage@first_arg, ..., last_arg` .\n\nfunction_name\n=============\nA *function_name* is a\n:ref:`json_ad_graph@Token@String` that is used to identify\nthe function.\n\nfunction\n========\nThe Json AD graph representation of a function is\n\n| {\n| |tab| ``\"function_name\"`` : *function_name* ,\n| |tab| ``\"op_define_vec\"`` : *op_define_vec* ,\n| |tab| ``\"n_dynamic_ind\"`` : *n_dynamic_ind* ,\n| |tab| ``\"n_variable_ind\"`` : *n_variable_ind* ,\n| |tab| ``\"constant_vec\"`` : *constant_vec* ,\n| |tab| ``\"op_usage_vec\"`` : *op_usage_vec* ,\n| |tab| ``\"dependent_vec\"`` : *dependent_vec*\n| }\n\nThis represents a the :math:`y = f(x, p)` where\n:math:`p` is the dynamic parameter vector,\n:math:`x` is the independent variable vector, and\n:math:`y` is the dependent variable vector.\n\nContents\n********\n{xrst_toc_table\n    include/cppad/core/graph/json_graph_op.xrst\n    include/cppad/core/graph/from_json.hpp\n    include/cppad/core/graph/to_json.hpp\n    example/json/get_started.cpp\n    example/json/sparse.cpp\n}\n\n{xrst_end json_ad_graph}\n"
  },
  {
    "path": "include/cppad/core/graph/json_graph_op.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin json_graph_op}\n{xrst_spell\n    acosh\n    asinh\n    chkpoint\n    erfc\n    expm\n    neg\n    notpos\n}\n\nJson AD Graph Operator Definitions\n##################################\n\nNotation\n********\n\nop_code\n=======\nEach operator definition has a *op_code* value that\nis used to identify it for a particular *json_ad_graph* .\n\nArguments\n=========\nThe values *first_arg* , ... ,\n:ref:`last_arg<json_ad_graph@op_usage@first_arg, ..., last_arg>`\nare the node indices for arguments to an operator.\n\nUnary Operators\n***************\nAll these operations create one result node and\nhave the following Json definition:\n\n| {\n| |tab| ``\"op_code\"`` : *op_code* ,\n| |tab| ``\"name\"`` : *name* ,\n| |tab| ``\"n_arg\"`` :        1\n| }\n\nwhere *name* is a :ref:`json_ad_graph@Token@String` .\nA corresponding *op_usage* has the form\n\n    [ *op_code* , *arg*  ]\n\nThe possible values for the string *name* are listed\nin the table below.\nThe corresponding result is the node value as a function of the argument value.\n\n\n.. csv-table::\n    :widths: auto\n\n    {xrst_comment BEGIN_SORT_THIS_LINE_PLUS_2}\n    *name*,result\n    ``abs``,absolute value\n    ``acos``,inverse cosine\n    ``acosh``,inverse hyperbolic cosine\n    ``asin``,inverse sine\n    ``asinh``,inverse hyperbolic sine\n    ``atan``,inverse tangent\n    ``atanh``,inverse hyperbolic sine\n    ``cos``,cosine\n    ``cosh``,hyperbolic cosine\n    ``erf``,error functions\n    ``erfc``,complementary error function\n    ``exp``,exponential\n    ``expm1``,minus one plus the exponential\n    ``log1p``,log  plus one\n    ``log``,logarithm\n    ``neg``,negative\n    ``sign``,sign function\n    ``sin``,sine\n    ``sinh``,hyperbolic sine\n    ``sqrt``,square root\n    ``tan``,tangent\n    ``tanh``,hyperbolic tangent\n    {xrst_comment END_SORT_THIS_LINE_MINUS_1}\n\nExample\n=======\nThe file :ref:`json_unary_op.cpp-name` is an example and test\nfor one of these operators.\n\nBinary Operators\n****************\nAll these operations create one result node and\nhave the following Json definition:\n\n| {\n| |tab| ``\"op_code\"`` : *op_code* ,\n| |tab| ``\"name\"`` : *name* ,\n| |tab| ``\"n_arg\"`` :        2\n| }\n\nwhere *name* is a :ref:`json_ad_graph@Token@String` .\nA corresponding *op_usage* has the form\n\n    [ *op_code* , *first_arg* , *second_arg*  ]\n\nThe possible values for the string *name* are listed below:\n\nadd\n===\nThe result is\nthe first argument value plus the second argument value; see\nthe example and test :ref:`json_add_op.cpp-name` .\n\nazmul\n=====\nIf the first argument value is zero, the result is zero\n(even if the second argument value is nan).\nOtherwise the result is\nthe first argument value times the second argument value; see\nthe example and test :ref:`json_azmul_op.cpp-name` .\n\ndiv\n===\nThe result is\nthe first argument value divided by the second argument value; see\nthe example and test :ref:`json_div_op.cpp-name` .\n\nmul\n===\nThe result is\nthe first argument value times the second argument value; see\nthe example and test :ref:`json_mul_op.cpp-name` .\n\npow\n===\nThe result is\nthe first argument value raised to the second argument value; see\nthe example and test :ref:`json_pow_op.cpp-name` .\n\nsub\n===\nThe result is\nthe first argument value minus the second argument value; see\nthe example and test :ref:`json_sub_op.cpp-name` .\n\nsum\n***\nThis operator has the following Json definition:\n\n| {\n| |tab| ``\"op_code\"`` : *op_code* ,\n| |tab| ``\"name\"`` : ``\"sum\"``\n| }\n\nA corresponding *op_usage* has the form\n\n    [ *op_code* , *n_result* , *n_arg* , [ *first_arg* , ..., *last_arg*  ] ]\n\nwhere *n_result* is always ``1`` .\nThis operation creates one node with value equal to\nthe sum of values corresponding to all of its argument nodes.\n\nExample\n=======\nThe file :ref:`json_sum_op.cpp-name` is an example and test\nof this operation.\n\nConditional Expressions\n***********************\nThese operators are :ref:`conditional expressions<CondExp-name>`\nand have the following Json definition:\n\n| {\n| |tab| ``\"op_code\"`` : *op_code* ,\n| |tab| ``\"name\"`` :         \" ``cexp_`` *rel* ,\n| |tab| ``\"n_arg\"`` :        4\n| }\n\nwhere *rel* is ``eq`` (equal),\n``le`` (less than or equal), or\n``lt`` (less than).\nThe first argument is :ref:`CondExp@left` ,\nthe second is :ref:`CondExp@right` ,\nthe third is :ref:`CondExp@if_true` ,\nthe fourth is :ref:`CondExp@if_false` ,\nthe result is given by\n\n| |tab| ``if`` ( *left* *cop* *right* )\n| |tab| |tab| *result* = *if_true* ;\n| |tab| ``else``\n| |tab| |tab| *result* = *if_false* ;\n\nwhere the comparison *cop* is define by the cases below:\n\ncexp_eq\n=======\nFor this operator *cop* is ``==``\n\ncexp_le\n=======\nFor this operator *cop* is ``<=``\n\ncexp_lt\n=======\nFor this operator *cop* is ``<``\n\nOther Comparisons\n=================\nNote that\n\n    ``CondExpGt`` ( *left* , *right* , *if_true* , *if_false* )\n\nis equivalent to\n\n    ``CondExpLe`` ( *left* , *right* , *if_false* , *if_true* )\n\nSimilar conversions can be used for all the possible\n:ref:`conditional expressions<CondExp-name>` .\n\nExample\n=======\nThe file :ref:`json_cexp_op.cpp-name` is an example and test\nfor one of these operators.\n\nCompare Operators\n*****************\nThese are :ref:`comparison<Compare-name>` operators\nand have the following Json definition:\n\n| {\n| |tab| ``\"op_code\"`` : *op_code* ,\n| |tab| ``\"name\"`` :         \" ``comp_`` *rel* \"\n| }\n\nwhere *rel* is ``eq`` (equal),\n``ne`` (not equal),\n``le`` (less than or equal), or\n``lt`` (less than).\nA corresponding *op_usage* has the form\n\n    [ *op_code* , *n_result* , *n_arg* , [ *left* , *right*  ] ]\n\nn_result\n========\nThis is always zero because a comparison operator does not create\nany new nodes.\n\nn_arg\n=====\nThis is always two because a comparison operator has two argument nodes\ncorresponding to the left and right operands.\n\nleft, right\n===========\nThe logical comparison is defined as the logical expression\n\n    *left* *cop* *right*\n\nThe comparison *cop* is define by the cases below.\nThe Json graph corresponds to the comparison being true.\nIf, for a value of the independent parameters and variables,\nthe comparison is false,\nthe Json graph may no longer be valid.\nFor example, the Json graph may only contain the code for the true case below:\n\n| |tab| ``if`` ( *left* *cop* *right*  )\n| |tab| { *source code when result is true*  }\n| |tab| ``else``\n| |tab| { *source code when result is false*  }\n\nIncluding this operator enables CppAD to detect when the graph\nmay no longer be a valid representation of the intended function.\n\ncomp_eq\n=======\nFor this operator *cop* is ``==``\n\ncomp_le\n=======\nFor this operator *cop* is ``<=``\n\ncomp_lt\n=======\nFor this operator *cop* is ``<``\n\ncomp_ne\n=======\nFor this operator *cop* is ``!=``\n\nOther Comparisons\n=================\nThe comparison result true for *left* > *right*\nis equivalent to the comparison result true for *right* < *left* .\nThe comparison result false for *left* > *right*\nis equivalent to the comparison result true for *left* <= *right* .\nIn a similar fashion, all the possible comparisons results\ncan be converted to a true result for one of the comparisons above.\n\nExample\n=======\nThe file :ref:`json_comp_op.cpp-name` is an example and test\nfor one of these operators.\n\nDiscrete Functions\n******************\nThis operator has the following Json definition:\n\n| {\n| |tab| ``\"op_code\"`` : *op_code* ,\n| |tab| ``\"name\"`` : ``\"discrete\"``\n| }\n\nA corresponding op_usage has the form\n\n    [ *op_code* , *name* , *n_result* , *n_arg* , [ *arg*  ]  ]\n\nname\n====\nThe value *name* is a\n:ref:`json_ad_graph@Token@String` specifying the\n:ref:`discrete@name` of the discrete function that is called.\n\nn_result\n========\nThis is always ``1`` because a discrete function\ncreates one new node.\nThe result node value is the specified discrete function of the argument value.\n\nn_arg\n=====\nThis is always ``1`` because a discrete function has\none argument node.\n\narg\n===\nis the node index for the argument to the discrete function.\n\nExample\n=======\nthe example and test :ref:`json_discrete_op.cpp-name` .\n\nAtomic Functions\n****************\nThese operators create *n_result* nodes with values determined by\nan evaluation of the an :ref:`atomic_three-name` or :ref:`atomic_four-name` function.\n\nAtomic Three\n============\nThis operator has the following Json definition:\n\n| {\n| |tab| ``\"op_code\"`` : *op_code* ,\n| |tab| ``\"name\"`` : ``\"atom\"``\n| }\n\nA corresponding *op_usage* has the form\n\n| |tab| [ *op_code* , *name* , *n_result* , *n_arg* ,\n| |tab| |tab| [ *first_arg* , ..., *last_arg*  ]\n| |tab| ]\n\nAtomic Four\n===========\nThis operator has the following Json definition:\n\n| {\n| |tab| ``\"op_code\"`` : *op_code* ,\n| |tab| ``\"name\"`` : ``\"atom4\"``\n| }\n\nA corresponding *op_usage* has the form\n\n| |tab| [ *op_code* , *name* , *call_id* , *n_result* , *n_arg* ,\n| |tab| |tab| [ *first_arg* , ..., *last_arg*  ]\n| |tab| ]\n\nname\n====\nThe value *name* is a\n:ref:`json_ad_graph@Token@String` specifying the\n:ref:`atomic_three_ctor@atomic_three@name`\nof the ``atomic_three`` function that is called.\n\ncall_id\n=======\nis a :ref:`json_ad_graph@Token@Non-Negative Integer`\nspecifying the :ref:`atomic_four_call@call_id` for an\natomic four function.\n\nn_result\n========\nis the number of results for this function; i.e.,\nits range space dimension.\n\nn_arg\n=====\nis the number of arguments to this function; i.e.,\nits domain space dimension.\n\nfirst_arg, ..., last_arg\n========================\nThe values corresponding to the node indices\n*first_arg* , ..., *last_arg* are the\narguments (independent variables) for the atomic function evaluation.\nIn the case where the atomic function is a ``chkpoint_two`` function,\nthe independent dynamic parameters are specified by calling its\n:ref:`chkpoint_two@Syntax@new_dynamic` routine.\n\nExample\n=======\nthe example and test :ref:`json_atom_op.cpp-name` .\n\nPrint\n*****\nThis operator has the following Json definition:\n\n| {\n| |tab| ``\"op_code\"`` : *op_code* ,\n| |tab| ``\"name\"`` : ``\"print\"``\n| }\n\nA corresponding *op_usage* has the form\n\n    [ *op_code* , *before* , *after* , *n_result* , *n_arg* , [ *notpos* , *value*  ] ]\n\nbefore\n======\nis a :ref:`json_ad_graph@Token@String` that is printed\n:ref:`PrintFor@before` the value for this operator.\n\nafter\n=====\nis a :ref:`json_ad_graph@Token@String` that is printed\n:ref:`PrintFor@after` the value for this operator.\n\nn_result\n========\nThis is always zero because a print operator does not create\nany new nodes.\n\nn_arg\n=====\nThis is always two because a print operator has two argument nodes.\n\nnotpos\n======\nThis is :ref:`PrintFor@notpos`\nwhich determines if the value is printed.\n\nvalue\n=====\nThis is the :ref:`PrintFor@value` that is printed.\n\nExample\n=======\nThe file :ref:`json_print_op.cpp-name` is an example and test\nof this operator.\n\nContents\n********\n{xrst_toc_table\n    example/json/unary_op.cpp\n    example/json/add_op.cpp\n    example/json/azmul_op.cpp\n    example/json/div_op.cpp\n    example/json/mul_op.cpp\n    example/json/pow_op.cpp\n    example/json/sub_op.cpp\n    example/json/sum_op.cpp\n    example/json/cexp_op.cpp\n    example/json/comp_op.cpp\n    example/json/discrete_op.cpp\n    example/json/atom_op.cpp\n    example/json/atom4_op.cpp\n    example/json/print_op.cpp\n}\n\n{xrst_end json_graph_op}\n"
  },
  {
    "path": "include/cppad/core/graph/to_graph.hpp",
    "content": "# ifndef CPPAD_CORE_GRAPH_TO_GRAPH_HPP\n# define CPPAD_CORE_GRAPH_TO_GRAPH_HPP\n\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/core/ad_fun.hpp>\n# include <cppad/local/op_code_dyn.hpp>\n# include <cppad/local/graph/cpp_graph_op.hpp>\n\n/*\n------------------------------------------------------------------------------\n{xrst_begin to_graph}\n\nCreate a C++ AD Graph Corresponding to an ADFun Object\n######################################################\n\nSyntax\n******\n| |tab| ``cpp_graph`` *graph_obj*\n| |tab| ``ADFun`` < *Base* > *fun*\n| |tab| *fun* . ``to_graph`` ( *graph_obj* )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_PROTOTYPE\n    // END_PROTOTYPE\n}\n\nBase\n****\nis the type corresponding to this :ref:`adfun-name` object;\ni.e., its calculations are done using the type *Base* .\n\nRecBase\n*******\nin the prototype above, *RecBase* is the same type as *Base* .\n\ngraph_obj\n*********\nThis is a ``cpp_graph`` object.\nThe input value of the object does not matter.\nUpon return it is a :ref:`cpp_ad_graph-name` representation of this function.\n\nRestrictions\n************\nThe ``to_graph`` routine is not yet implement for some\npossible :ref:`ADFun-name` operators; see\n:ref:`graph_op_enum@Missing Operators` .\n\nExamples\n********\nSee :ref:`graph_op_enum examples<graph_op_enum@Examples>` .\n\n{xrst_end to_graph}\n*/\n// BEGIN_PROTOTYPE\ntemplate <class Base, class RecBase>\nvoid CppAD::ADFun<Base,RecBase>::to_graph(\n        CppAD::cpp_graph& graph_obj )\n// END_PROTOTYPE\n{   using local::pod_vector;\n    using local::opcode_t;\n    using namespace CppAD::graph;\n    //\n# ifndef NDEBUG\n# endif\n    graph_obj.initialize();\n    //\n    // --------------------------------------------------------------------\n    // some constants\n    // --------------------------------------------------------------------\n    //\n    // output: function_name\n    graph_obj.function_name_set(function_name_);\n    //\n    // dynamic parameter information\n    const pod_vector<opcode_t>& dyn_par_op ( play_.dyn_par_op()  );\n    const pod_vector<addr_t>&   dyn_par_arg( play_.dyn_par_arg() );\n    const pod_vector<addr_t>&   dyn2par_index ( play_.dyn2par_index() );\n    const pod_vector<bool>&     par_is_dyn( play_.par_is_dyn() );\n    //\n    // number of dynamic parameters\n    const size_t n_dynamic     = dyn2par_index.size();\n    //\n    // output: n_dynamic_ind\n    size_t n_dynamic_ind = play_.n_dyn_independent();\n    graph_obj.n_dynamic_ind_set(n_dynamic_ind);\n    //\n    // number of parameters\n    const size_t n_parameter = play_.num_par_all();\n    //\n    // number of constant parameters\n# ifndef NDEBUG\n    const size_t n_constant = n_parameter - n_dynamic - 1;\n# endif\n    //\n    // output: n_variable_ind\n    size_t n_variable_ind = ind_taddr_.size();\n    graph_obj.n_variable_ind_set(n_variable_ind);\n    //\n    // value of parameters\n    const Base* parameter = play_.par_ptr();\n    //\n    // number of variables\n    const size_t n_variable = play_.num_var();\n    //\n    // some checks\n    CPPAD_ASSERT_UNKNOWN( n_dynamic_ind <= n_dynamic );\n    CPPAD_ASSERT_UNKNOWN( par_is_dyn.size() == n_parameter );\n    CPPAD_ASSERT_UNKNOWN( n_parameter > 0 );\n    CPPAD_ASSERT_UNKNOWN( CppAD::isnan( parameter[0] ) );\n    CPPAD_ASSERT_UNKNOWN( ! par_is_dyn[0] );\n    // --------------------------------------------------------------------\n    // par2node\n    pod_vector<size_t> par2node(n_parameter);\n    par2node[0] = 0; // invalid value\n    for(size_t i = 1; i <= n_dynamic_ind; ++i)\n        par2node[i] = i; // independent dynamic parameters\n    for(size_t i = n_dynamic_ind + 1; i < n_parameter; ++i)\n        par2node[i] = 0; // will be set later\n    // ----------------------------------------------------------------------\n    //\n    // initialize index of previous node in the graph\n    size_t previous_node = 0;\n    //\n    // n_dynamic_ind\n    previous_node += n_dynamic_ind;\n    //\n    // n_variable_ind\n    previous_node += n_variable_ind;\n    // --------------------------------------------------------------------\n    //\n    // output: constant_vec\n    // constant_vec and par2node for constants\n    for(size_t i = 1; i < n_parameter; ++i)\n    {   if( ! par_is_dyn[i] )\n        {   // this is a constant node\n            graph_obj.constant_vec_push_back( parameter[i] );\n            par2node[i] = ++previous_node;\n        }\n    }\n    CPPAD_ASSERT_UNKNOWN( n_constant == graph_obj.constant_vec_size() );\n    // ----------------------------------------------------------------------\n    //  output: initialize atomic_name_vec, operator_vec, operator_arg\n    // temporary used for elements of operator_vec\n    //\n    // Json operators are dynamic operators plus variables operators.\n    // Skip BeginOp, EndOp, and independent variables.\n    //\n    // dynamic parameter operations and par2node\n    // for dynamic parameters that are not constants or independent\n    CPPAD_ASSERT_UNKNOWN( num_arg_dyn(local::ind_dyn) == 0 );\n    CPPAD_ASSERT_UNKNOWN( num_arg_dyn(local::atom_dyn) == 0 );\n    size_t i_arg = 0;\n    pod_vector<size_t> node_arg;\n\n    for(size_t i_dyn = n_dynamic_ind; i_dyn < n_dynamic; ++i_dyn)\n    {   // operator for this dynamic parameter\n        local::op_code_dyn dyn_op = local::op_code_dyn( dyn_par_op[i_dyn] );\n        //\n        // parameter index for this dynamic parameter\n        size_t i_par = size_t( dyn2par_index[i_dyn] );\n        CPPAD_ASSERT_UNKNOWN( par2node[i_par] == 0 );\n        par2node[i_par] = ++previous_node;\n        //\n        // number of arguments for operators with exception of atom_dyn\n        size_t n_arg = num_arg_dyn(dyn_op);\n        if( n_arg > node_arg.size() )\n            node_arg.resize(n_arg);\n        //\n        // parameter arguments in graph node space (except for atom_dyn)\n        if( dyn_op != local::atom_dyn )\n        {   size_t offset_par = num_non_par_arg_dyn(dyn_op);\n            for(size_t i = offset_par; i < n_arg; ++i)\n            {   node_arg[i] = par2node[ dyn_par_arg[i_arg + i] ];\n                CPPAD_ASSERT_UNKNOWN( node_arg[i] > 0 );\n            }\n        }\n        //\n        // invalid value\n        graph_op_enum graph_op = n_graph_op;\n        switch(dyn_op)\n        {\n            // ---------------------------------------------------------------\n            // unary operators\n\n            case local::abs_dyn:\n            case local::fabs_dyn:\n            graph_op = abs_graph_op;\n            break;\n\n            case local::acosh_dyn:\n            graph_op = acosh_graph_op;\n            break;\n\n            case local::asinh_dyn:\n            graph_op = asinh_graph_op;\n            break;\n\n            case local::atanh_dyn:\n            graph_op = atanh_graph_op;\n            break;\n\n            case local::erf_dyn:\n            graph_op = erf_graph_op;\n            break;\n\n            case local::erfc_dyn:\n            graph_op = erfc_graph_op;\n            break;\n\n            case local::expm1_dyn:\n            graph_op = expm1_graph_op;\n            break;\n\n            case local::log1p_dyn:\n            graph_op = log1p_graph_op;\n            break;\n\n            case local::acos_dyn:\n            graph_op = acos_graph_op;\n            break;\n\n            case local::asin_dyn:\n            graph_op = asin_graph_op;\n            break;\n\n            case local::atan_dyn:\n            graph_op = atan_graph_op;\n            break;\n\n            case local::cosh_dyn:\n            graph_op = cosh_graph_op;\n            break;\n\n            case local::cos_dyn:\n            graph_op = cos_graph_op;\n            break;\n\n            case local::exp_dyn:\n            graph_op = exp_graph_op;\n            break;\n\n            case local::log_dyn:\n            graph_op = log_graph_op;\n            break;\n\n            case local::neg_dyn:\n            graph_op = neg_graph_op;\n            break;\n\n            case local::sign_dyn:\n            graph_op = sign_graph_op;\n            break;\n\n            case local::sinh_dyn:\n            graph_op = sinh_graph_op;\n            break;\n\n            case local::sin_dyn:\n            graph_op = sin_graph_op;\n            break;\n\n            case local::sqrt_dyn:\n            graph_op = sqrt_graph_op;\n            break;\n\n            case local::tanh_dyn:\n            graph_op = tanh_graph_op;\n            break;\n\n            case local::tan_dyn:\n            graph_op = tan_graph_op;\n            break;\n\n            // ---------------------------------------------------------------\n            // binary operators\n\n            case local::add_dyn:\n            graph_op = add_graph_op;\n            break;\n\n            case local::div_dyn:\n            graph_op = div_graph_op;\n            break;\n\n            case local::mul_dyn:\n            graph_op = mul_graph_op;\n            break;\n\n            case local::pow_dyn:\n            graph_op = pow_graph_op;\n            break;\n\n            case local::sub_dyn:\n            graph_op = sub_graph_op;\n            break;\n\n            case local::zmul_dyn:\n            graph_op = azmul_graph_op;\n            break;\n\n            // ---------------------------------------------------------------\n            // graph_op determined later for these cases\n            case local::atom_dyn:\n            case local::cond_exp_dyn:\n            case local::dis_dyn:\n            case local::result_dyn:\n            break;\n\n            // ---------------------------------------------------------------\n            default:\n            // This error should have been reported above\n            CPPAD_ASSERT_UNKNOWN( false );\n            break;\n        }\n        switch( dyn_op )\n        {   // --------------------------------------------------------------\n            case local::result_dyn:\n            // setting par2node[i_dyn] above is all that is necessary\n            CPPAD_ASSERT_UNKNOWN( n_arg == 0 );\n            break;\n\n            // --------------------------------------------------------------\n            case local::dis_dyn:\n            {\n                // arg[0]: discrete function index\n                size_t discrete_index = size_t( dyn_par_arg[i_arg + 0] );\n                // get the name for this discrete function\n                std::string name = discrete<Base>::name( discrete_index );\n                //\n                // set graph index for this discrete function call\n                size_t name_index = graph_obj.discrete_name_vec_find(name);\n                if( name_index == graph_obj.discrete_name_vec_size() )\n                    graph_obj.discrete_name_vec_push_back(name);\n                //\n                graph_op = discrete_graph_op;\n                graph_obj.operator_vec_push_back( graph_op );\n                graph_obj.operator_arg_push_back( name_index );\n                graph_obj.operator_arg_push_back( node_arg[1] );\n            }\n            break;\n\n            // --------------------------------------------------------------\n            case local::atom_dyn:\n            {\n                // arg[0]: atomic function index\n                size_t atom_index  = size_t( dyn_par_arg[i_arg + 0] );\n                //\n                // arg[1]: call_id\n                size_t call_id = size_t( dyn_par_arg[i_arg + 1] );\n                //\n                // arg[2]: number of arguments to function\n                n_arg              = size_t( dyn_par_arg[i_arg + 2] );\n                // arg[3]: number of results from function\n                size_t n_result    = size_t( dyn_par_arg[i_arg + 3] );\n                //\n                // get the name and type for this atomic function\n                std::string     name;\n                size_t          type;\n                {   bool        set_null = false;\n                    void*       ptr;\n                    CppAD::local::atomic_index<RecBase>(\n                        set_null, atom_index, type, &name, ptr\n                    );\n                }\n                // set graph index for this atomic function call\n                size_t name_index = graph_obj.atomic_name_vec_find(name);\n                if( name_index == graph_obj.atomic_name_vec_size() )\n                    graph_obj.atomic_name_vec_push_back(name);\n                //\n                // atom_graph_op:\n                // name_index, n_result, n_arg (before first_node)\n                //\n                // atom4_graph_op:\n                // name_index, call_id, n_result, n_arg (before first_node)\n                graph_obj.operator_arg_push_back(name_index);\n                if( type == 4 )\n                    graph_obj.operator_arg_push_back(call_id);\n                graph_obj.operator_arg_push_back(n_result);\n                graph_obj.operator_arg_push_back(n_arg);\n                //\n                if( type == 3 )\n                    graph_op = atom_graph_op;\n                else\n                {   CPPAD_ASSERT_UNKNOWN( type == 4 );\n                    graph_op = atom4_graph_op;\n                }\n                //\n                graph_obj.operator_vec_push_back( graph_op );\n                //\n                for(size_t j  = 0; j < n_arg; ++j)\n                {   // arg[5 + j] is j-th argument to the function\n                    size_t node_j = par2node[ dyn_par_arg[i_arg + 5 + j] ];\n                    CPPAD_ASSERT_UNKNOWN( node_j < i_par );\n                    graph_obj.operator_arg_push_back( node_j );\n                }\n            }\n            break;\n\n            // --------------------------------------------------------------\n            case local::cond_exp_dyn:\n            {\n                CompareOp cop = CompareOp( dyn_par_arg[i_arg + 0] );\n                size_t left     = node_arg[1];\n                size_t right    = node_arg[2];\n                size_t if_true  = node_arg[3];\n                size_t if_false = node_arg[4];\n                switch( cop )\n                {   case CompareLt:\n                    graph_op = cexp_lt_graph_op;\n                    break;\n\n                    case CompareLe:\n                    graph_op = cexp_le_graph_op;\n                    break;\n\n                    case CompareEq:\n                    graph_op = cexp_eq_graph_op;\n                    break;\n\n                    case CompareGe:\n                    graph_op = cexp_lt_graph_op;\n                    std::swap(if_true, if_false);\n                    break;\n\n                    case CompareGt:\n                    graph_op = cexp_le_graph_op;\n                    std::swap(if_true, if_false);\n                    break;\n\n                    case CompareNe:\n                    graph_op = cexp_eq_graph_op;\n                    std::swap(if_true, if_false);\n                    break;\n\n                    default:\n                    CPPAD_ASSERT_UNKNOWN(false);\n                    break;\n                }\n                graph_obj.operator_vec_push_back( graph_op );\n                graph_obj.operator_arg_push_back( left );\n                graph_obj.operator_arg_push_back( right );\n                graph_obj.operator_arg_push_back( if_true );\n                graph_obj.operator_arg_push_back( if_false );\n            }\n            break;\n\n            // --------------------------------------------------------------\n            // unary or binary\n            default:\n            CPPAD_ASSERT_UNKNOWN((n_arg == 1) || (n_arg == 2));\n            //\n            graph_obj.operator_vec_push_back( graph_op );\n            for(size_t i = 0; i < n_arg; ++i)\n                graph_obj.operator_arg_push_back( node_arg[i] );\n            break;\n        }\n        i_arg  += n_arg;\n    }\n    // ----------------------------------------------------------------------\n    // variable operators\n    pod_vector<size_t> var2node(n_variable);\n    var2node[0] = 0; // invalid node value\n    for(size_t i = 1; i <= n_variable_ind; ++i)\n        var2node[i] = n_dynamic_ind + i;\n    for(size_t i = n_variable_ind + 1; i < n_variable; ++i)\n        var2node[i] = 0; // invalid node value\n    //\n    local::play::const_sequential_iterator itr  = play_.begin();\n    local::op_code_var var_op;\n    const              addr_t* arg;\n    size_t             i_var;\n    pod_vector<bool>   is_var(2);\n    vector<size_t>     atom_node_arg;\n    bool in_atomic_call = false;\n    bool more_operators = true;\n    while(more_operators)\n    {   // if non-zero, this is a fixed size operator with this many arguments\n        // and implemented after the switch. In additionk, is_var is set for\n        // each of the at most 2 arguments.\n        size_t fixed_n_arg = 0;\n\n        // invalid value\n        graph_op_enum graph_op = n_graph_op;\n\n        // next op\n        (++itr).op_info(var_op, arg, i_var);\n\n\n        // -------------------------------------------------------------------\n        // Cases with fixed number of arguments, one or two arguments, and\n        // operator is not ignored.\n        // -------------------------------------------------------------------\n        switch( var_op )\n        {   // 2DO: some of these cases can be joined\n\n            // -------------------------------------------------------------\n            // unary operators\n            case local::AbsOp:\n            fixed_n_arg = 1;\n            is_var[0] = true;\n            break;\n\n            case local::AcoshOp:\n            fixed_n_arg = 1;\n            is_var[0] = true;\n            break;\n\n            case local::AsinhOp:\n            fixed_n_arg = 1;\n            is_var[0] = true;\n            break;\n\n            case local::AtanhOp:\n            fixed_n_arg = 1;\n            is_var[0] = true;\n            break;\n\n            case local::ErfOp:\n            fixed_n_arg = 1;\n            is_var[0] = true;\n            break;\n\n            case local::ErfcOp:\n            fixed_n_arg = 1;\n            is_var[0] = true;\n            break;\n\n            case local::Expm1Op:\n            fixed_n_arg = 1;\n            is_var[0] = true;\n            break;\n\n            case local::Log1pOp:\n            fixed_n_arg = 1;\n            is_var[0] = true;\n            break;\n\n            case local::AcosOp:\n            fixed_n_arg = 1;\n            is_var[0] = true;\n            break;\n\n            case local::AsinOp:\n            fixed_n_arg = 1;\n            is_var[0] = true;\n            break;\n\n            case local::AtanOp:\n            fixed_n_arg = 1;\n            is_var[0] = true;\n            break;\n\n            case local::CoshOp:\n            fixed_n_arg = 1;\n            is_var[0] = true;\n            break;\n\n            case local::CosOp:\n            fixed_n_arg = 1;\n            is_var[0] = true;\n            break;\n\n            case local::ExpOp:\n            fixed_n_arg = 1;\n            is_var[0] = true;\n            break;\n\n            case local::LogOp:\n            fixed_n_arg = 1;\n            is_var[0] = true;\n            break;\n\n            case local::NegOp:\n            fixed_n_arg = 1;\n            is_var[0] = true;\n            break;\n\n            case local::SignOp:\n            fixed_n_arg = 1;\n            is_var[0] = true;\n            break;\n\n            case local::SinhOp:\n            fixed_n_arg = 1;\n            is_var[0] = true;\n            break;\n\n            case local::SinOp:\n            fixed_n_arg = 1;\n            is_var[0] = true;\n            break;\n\n            case local::SqrtOp:\n            fixed_n_arg = 1;\n            is_var[0] = true;\n            break;\n\n            case local::TanhOp:\n            fixed_n_arg = 1;\n            is_var[0] = true;\n            break;\n\n            case local::TanOp:\n            fixed_n_arg = 1;\n            is_var[0] = true;\n            break;\n\n            // ---------------------------------------------------------------\n            // binary operators\n            // ---------------------------------------------------------------\n\n            // first argument a parameter, second argument a variable\n            case local::AddpvOp:\n            case local::DivpvOp:\n            case local::MulpvOp:\n            case local::PowpvOp:\n            case local::SubpvOp:\n            case local::ZmulpvOp:\n            fixed_n_arg = 2;\n            is_var[0]   = false;\n            is_var[1]   = true;\n            break;\n\n            // first argument a variable, second argument a parameter\n            case local::DivvpOp:\n            case local::PowvpOp:\n            case local::SubvpOp:\n            case local::ZmulvpOp:\n            fixed_n_arg = 2;\n            is_var[0]   = true;\n            is_var[1]   = false;\n            break;\n\n            // first argument a variable, second argument a variable\n            case local::AddvvOp:\n            case local::DivvvOp:\n            case local::MulvvOp:\n            case local::PowvvOp:\n            case local::SubvvOp:\n            case local::ZmulvvOp:\n            fixed_n_arg = 2;\n            is_var[0]   = true;\n            is_var[1]   = true;\n            break;\n\n            // --------------------------------------------------------------\n            default:\n            break;\n        }\n        if( fixed_n_arg > 0 )\n        {   // Set graph_op\n            switch( var_op )\n            {\n                // ----------------------------------------------------------\n                // unary operators\n\n                case local::AbsOp:\n                graph_op = abs_graph_op;\n                break;\n\n                case local::AcoshOp:\n                graph_op = acosh_graph_op;\n                break;\n\n                case local::AsinhOp:\n                graph_op = asinh_graph_op;\n                break;\n\n                case local::AtanhOp:\n                graph_op = atanh_graph_op;\n                break;\n\n                case local::ErfOp:\n                graph_op = erf_graph_op;\n                break;\n\n                case local::ErfcOp:\n                graph_op = erfc_graph_op;\n                break;\n\n                case local::Expm1Op:\n                graph_op = expm1_graph_op;\n                break;\n\n                case local::Log1pOp:\n                graph_op = log1p_graph_op;\n                break;\n\n                case local::AcosOp:\n                graph_op = acos_graph_op;\n                break;\n\n                case local::AsinOp:\n                graph_op = asin_graph_op;\n                break;\n\n                case local::AtanOp:\n                graph_op = atan_graph_op;\n                break;\n\n                case local::CoshOp:\n                graph_op = cosh_graph_op;\n                break;\n\n                case local::CosOp:\n                graph_op = cos_graph_op;\n                break;\n\n                case local::ExpOp:\n                graph_op = exp_graph_op;\n                break;\n\n                case local::LogOp:\n                graph_op = log_graph_op;\n                break;\n\n                case local::NegOp:\n                graph_op = neg_graph_op;\n                break;\n\n                case local::SignOp:\n                graph_op = sign_graph_op;\n                break;\n\n                case local::SinhOp:\n                graph_op = sinh_graph_op;\n                break;\n\n                case local::SinOp:\n                graph_op = sin_graph_op;\n                break;\n\n                case local::SqrtOp:\n                graph_op = sqrt_graph_op;\n                break;\n\n                case local::TanhOp:\n                graph_op = tanh_graph_op;\n                break;\n\n                case local::TanOp:\n                graph_op = tan_graph_op;\n                break;\n\n                // -----------------------------------------------------------\n                // binary operators\n\n                case local::AddpvOp:\n                case local::AddvvOp:\n                graph_op = add_graph_op;\n                break;\n\n                case local::DivpvOp:\n                case local::DivvpOp:\n                case local::DivvvOp:\n                graph_op = div_graph_op;\n                break;\n\n                case local::MulpvOp:\n                case local::MulvvOp:\n                graph_op = mul_graph_op;\n                break;\n\n                case local::PowpvOp:\n                case local::PowvpOp:\n                case local::PowvvOp:\n                graph_op = pow_graph_op;\n                break;\n\n                case local::SubpvOp:\n                case local::SubvpOp:\n                case local::SubvvOp:\n                graph_op = sub_graph_op;\n                break;\n\n                case local::ZmulpvOp:\n                case local::ZmulvpOp:\n                case local::ZmulvvOp:\n                graph_op = azmul_graph_op;\n                break;\n\n                // -----------------------------------------------------------\n                default:\n                // This should be one of the cases above\n                CPPAD_ASSERT_UNKNOWN(false);\n                break;\n            }\n            //\n            // var2node and previous_node for this operator\n            var2node[i_var] = ++previous_node;\n            //\n            //\n            graph_obj.operator_vec_push_back( graph_op );\n            for(size_t i = 0; i < fixed_n_arg; ++i)\n            {   if( is_var[i] )\n                    graph_obj.operator_arg_push_back( var2node[ arg[i] ] );\n                else\n                    graph_obj.operator_arg_push_back( par2node[ arg[i] ] );\n            }\n        }\n        // -------------------------------------------------------------------\n        // Other cases\n        // -------------------------------------------------------------------\n        else switch( var_op )\n        {\n            // -------------------------------------------------------------\n            // comparison operators\n            case local::EqppOp:\n            case local::EqpvOp:\n            case local::EqvvOp:\n            case local::NeppOp:\n            case local::NepvOp:\n            case local::NevvOp:\n            case local::LtppOp:\n            case local::LtpvOp:\n            case local::LtvpOp:\n            case local::LtvvOp:\n            case local::LeppOp:\n            case local::LepvOp:\n            case local::LevpOp:\n            case local::LevvOp:\n            {   // node_0, node_1\n                size_t node_0, node_1;\n                switch( var_op )\n                {   // both nodes parameters\n                    case local::EqppOp:\n                    case local::NeppOp:\n                    case local::LtppOp:\n                    case local::LeppOp:\n                    node_0 = par2node[arg[0]];\n                    node_1 = par2node[arg[1]];\n                    break;\n\n                    // first node parameter, second variable\n                    case local::EqpvOp:\n                    case local::NepvOp:\n                    case local::LtpvOp:\n                    case local::LepvOp:\n                    node_0 = par2node[arg[0]];\n                    node_1 = var2node[arg[1]];\n                    break;\n\n                    // first node variable, second parameter\n                    case local::LtvpOp:\n                    case local::LevpOp:\n                    node_0 = var2node[arg[0]];\n                    node_1 = par2node[arg[1]];\n                    break;\n\n                    // both nodes variables\n                    case local::EqvvOp:\n                    case local::NevvOp:\n                    case local::LtvvOp:\n                    case local::LevvOp:\n                    node_0 = var2node[arg[0]];\n                    node_1 = var2node[arg[1]];\n                    break;\n\n                    // should never get here\n                    default:\n                    CPPAD_ASSERT_UNKNOWN(false);\n                    node_0 = 0; // to avoid compiler warning\n                    node_1 = 0;\n                    break;\n                }\n                // Set graph_op\n                switch( var_op )\n                {\n                    case local::EqppOp:\n                    case local::EqpvOp:\n                    case local::EqvvOp:\n                    graph_op = comp_eq_graph_op;\n                    break;\n\n                    case local::NeppOp:\n                    case local::NepvOp:\n                    case local::NevvOp:\n                    graph_op = comp_ne_graph_op;\n                    break;\n\n                    case local::LtppOp:\n                    case local::LtpvOp:\n                    case local::LtvpOp:\n                    case local::LtvvOp:\n                    graph_op = comp_lt_graph_op;\n                    break;\n\n                    case local::LeppOp:\n                    case local::LepvOp:\n                    case local::LevpOp:\n                    case local::LevvOp:\n                    graph_op = comp_le_graph_op;\n                    break;\n\n                    // should never get here\n                    default:\n                    CPPAD_ASSERT_UNKNOWN(false);\n                    graph_op = n_graph_op; // invalid values\n                    break;\n                }\n                graph_obj.operator_vec_push_back( graph_op );\n                graph_obj.operator_arg_push_back( node_0 );\n                graph_obj.operator_arg_push_back( node_1 );\n            }\n            break;\n\n            // --------------------------------------------------------------\n            // CSumOp\n            case local::CSumOp:\n            {   // does this case have subtraction terms\n                bool has_subtract = (arg[1] != arg[2]) || (arg[3] != arg[4]);\n                //\n                // var2node for this operator\n                if( has_subtract )\n                {   // two cumulative sum and one subtract operators\n                    var2node[i_var] = previous_node + 3;\n                }\n                else\n                {   // one cumulative sum operator\n                    var2node[i_var] = previous_node + 1;\n                }\n                //\n                // previous_node + 1 = sum corresponding to addition terms\n                //\n                graph_op = sum_graph_op;\n                CPPAD_ASSERT_UNKNOWN( 5 <= arg[1] );\n                CPPAD_ASSERT_UNKNOWN( arg[2] <= arg[3] );\n                size_t n_arg = size_t(1 + arg[1] - 5 + arg[3] - arg[2]);\n                //\n                // n_arg comes befrore first_node\n                graph_obj.operator_arg_push_back(n_arg);\n                //\n                // graph_op for addition terms\n                graph_obj.operator_vec_push_back( graph_op );\n                //\n                // argument nodes\n                size_t arg_node  = par2node[ arg[0] ];\n                graph_obj.operator_arg_push_back( arg_node );\n# ifndef NDEBUG\n                size_t j_arg = 1;\n# endif\n                for(addr_t i = 5; i < arg[1]; ++i)\n                {   arg_node    = var2node[ arg[i] ];\n                    CPPAD_ASSERT_UNKNOWN( arg_node > 0 );\n                    graph_obj.operator_arg_push_back( arg_node );\n# ifndef NDEBUG\n                    ++j_arg;\n# endif\n                }\n                for(addr_t i = arg[2]; i < arg[3]; ++i)\n                {   arg_node  = par2node[ arg[i] ];\n                    CPPAD_ASSERT_UNKNOWN( arg_node > 0 );\n                    graph_obj.operator_arg_push_back( arg_node );\n# ifndef NDEBUG\n                    ++j_arg;\n# endif\n                }\n                CPPAD_ASSERT_UNKNOWN( j_arg == n_arg );\n                if( has_subtract )\n                {   // previous_node + 2 = sum corresponding to subtract terms\n                    CPPAD_ASSERT_UNKNOWN( arg[1] <= arg[2] );\n                    CPPAD_ASSERT_UNKNOWN( arg[3] <= arg[4] );\n                    n_arg = size_t(arg[2] - arg[1] + arg[4] - arg[3]);\n                    //\n                    // n_arg comes before first_node\n                    graph_obj.operator_arg_push_back(n_arg);\n                    //\n                    // graph_op for subtraction terms\n                    graph_op = sum_graph_op;\n                    graph_obj.operator_vec_push_back( graph_op );\n                    //\n                    // argument nodes\n# ifndef NDEBUG\n                    j_arg = 0;\n# endif\n                    for(addr_t i = arg[1]; i < arg[2]; ++i)\n                    {   arg_node    = var2node[ arg[i] ];\n                        CPPAD_ASSERT_UNKNOWN( arg_node > 0 );\n                        graph_obj.operator_arg_push_back( arg_node );\n# ifndef NDEBUG\n                        ++j_arg;\n# endif\n                    }\n                    for(addr_t i = arg[3]; i < arg[4]; ++i)\n                    {   arg_node  = par2node[ arg[i] ];\n                        CPPAD_ASSERT_UNKNOWN( arg_node > 0 );\n                        graph_obj.operator_arg_push_back( arg_node );\n# ifndef NDEBUG\n                        ++j_arg;\n# endif\n                    }\n                    CPPAD_ASSERT_UNKNOWN( j_arg == n_arg );\n                    //\n                    // previous_node + 3 = first sum minus second sum\n                    graph_op = sub_graph_op;\n                    graph_obj.operator_vec_push_back( graph_op );\n                    graph_obj.operator_arg_push_back( previous_node + 1 );\n                    graph_obj.operator_arg_push_back( previous_node + 2 );\n                }\n                // previous node\n                if( has_subtract )\n                    previous_node += 3;\n                else\n                    previous_node += 1;\n            }\n            itr.correct_before_increment();\n            break;\n\n            // --------------------------------------------------------------\n            case local::DisOp:\n            {   // discrete function index\n                size_t discrete_index = size_t( arg[0] );\n                // name of this discrete function\n                std::string name  = discrete<Base>::name( discrete_index );\n                //\n                // set graph index for this discrete function call\n                size_t name_index = graph_obj.discrete_name_vec_find(name);\n                if( name_index == graph_obj.discrete_name_vec_size() )\n                    graph_obj.discrete_name_vec_push_back(name);\n                //\n                graph_op = discrete_graph_op;\n                graph_obj.operator_vec_push_back( graph_op );\n                graph_obj.operator_arg_push_back( name_index );\n                graph_obj.operator_arg_push_back( var2node[arg[1]] );\n                //\n                var2node[i_var] = ++previous_node;\n            }\n            break;\n            // --------------------------------------------------------------\n            case local::PriOp:\n            {\n                // before\n                std::string before( play_.GetTxt( size_t(arg[2]) ) );\n                size_t before_index = graph_obj.print_text_vec_find(before);\n                if( before_index == graph_obj.print_text_vec_size() )\n                    graph_obj.print_text_vec_push_back(before);\n                // after\n                std::string after( play_.GetTxt( size_t(arg[4]) ) );\n                size_t after_index = graph_obj.print_text_vec_find(after);\n                if( after_index == graph_obj.print_text_vec_size() )\n                    graph_obj.print_text_vec_push_back(after);\n                // notpos\n                size_t notpos_node;\n                if( arg[0] & 1 )\n                    notpos_node = var2node[ arg[1] ];\n                else\n                    notpos_node = par2node[ arg[1] ];\n                // value\n                size_t value_node;\n                if( arg[0] & 1 )\n                    value_node = var2node[ arg[3] ];\n                else\n                    value_node = par2node[ arg[3] ];\n                //\n                graph_op = print_graph_op;\n                graph_obj.operator_vec_push_back( graph_op );\n                graph_obj.operator_arg_push_back( before_index );\n                graph_obj.operator_arg_push_back( after_index );\n                graph_obj.operator_arg_push_back( notpos_node );\n                graph_obj.operator_arg_push_back( value_node );\n            }\n            break;\n\n            // --------------------------------------------------------------\n            case local::FunapOp:\n            atom_node_arg.push_back( par2node[arg[0]] );\n            break;\n\n            case local::FunavOp:\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) <= i_var );\n            atom_node_arg.push_back( var2node[arg[0]] );\n            break;\n\n            case local::FunrpOp:\n            par2node[arg[0]] = ++previous_node;\n            break;\n\n            case local::FunrvOp:\n            var2node[i_var] = ++previous_node;\n            break;\n\n            case local::AFunOp:\n            in_atomic_call = ! in_atomic_call;\n            if( in_atomic_call )\n            {   atom_node_arg.resize(0);\n            }\n            else\n            {   // This is the AFunOp at the end of the call\n                size_t atom_index   = size_t( arg[0] );\n                //\n                size_t call_id      = size_t( arg[1] );\n                size_t n_arg        = size_t( arg[2] );\n                size_t n_result     = size_t( arg[3] );\n                CPPAD_ASSERT_UNKNOWN( atom_node_arg.size() == n_arg );\n                //\n                // get the name and type for this atomic function\n                std::string     name;\n                size_t          type;\n                {   bool        set_null = false;\n                    void*       ptr;\n                    CppAD::local::atomic_index<RecBase>(\n                        set_null, atom_index, type, &name, ptr\n                    );\n                }\n                // set graph index for this atomic function\n                size_t name_index = graph_obj.atomic_name_vec_find(name);\n                if( name_index == graph_obj.atomic_name_vec_size() )\n                    graph_obj.atomic_name_vec_push_back(name);\n                //\n                // for atom_graph_op:\n                // name_index, n_result, n_arg (before first_node)\n                //\n                // for atom4_graph_op:\n                // name_index, call_id, n_result, n_arg (before first_node)\n                graph_obj.operator_arg_push_back(name_index);\n                if( type == 4 )\n                    graph_obj.operator_arg_push_back(call_id);\n                graph_obj.operator_arg_push_back(n_result);\n                graph_obj.operator_arg_push_back(n_arg);\n                if( type == 3 )\n                    graph_op = atom_graph_op;\n                else\n                {   CPPAD_ASSERT_UNKNOWN( type == 4 );\n                    graph_op = atom4_graph_op;\n                }\n                graph_obj.operator_vec_push_back( graph_op );\n                for(size_t i = 0; i < n_arg; ++i)\n                    graph_obj.operator_arg_push_back( atom_node_arg[i] );\n            }\n            break;\n            // --------------------------------------------------------------\n            // CExpOp:\n            case local::CExpOp:\n            {   CompareOp cop = CompareOp( arg[0] );\n                size_t left, right, if_true, if_false;\n                if( arg[1] & 1 )\n                    left = var2node[ arg[2] ];\n                else\n                    left = par2node[ arg[2] ];\n                if( arg[1] & 2 )\n                    right = var2node[ arg[3] ];\n                else\n                    right = par2node[ arg[3] ];\n                if( arg[1] & 4 )\n                    if_true = var2node[ arg[4] ];\n                else\n                    if_true = par2node[ arg[4] ];\n                if( arg[1] & 8 )\n                    if_false = var2node[ arg[5] ];\n                else\n                    if_false = par2node[ arg[5] ];\n                switch( cop )\n                {   case CompareLt:\n                    graph_op = cexp_lt_graph_op;\n                    break;\n\n                    case CompareLe:\n                    graph_op = cexp_le_graph_op;\n                    break;\n\n                    case CompareEq:\n                    graph_op = cexp_eq_graph_op;\n                    break;\n\n                    case CompareGe:\n                    graph_op = cexp_lt_graph_op;\n                    std::swap(if_true, if_false);\n                    break;\n\n                    case CompareGt:\n                    graph_op = cexp_le_graph_op;\n                    std::swap(if_true, if_false);\n                    break;\n\n                    case CompareNe:\n                    graph_op = cexp_eq_graph_op;\n                    std::swap(if_true, if_false);\n                    break;\n\n                    default:\n                    CPPAD_ASSERT_UNKNOWN(false);\n                    break;\n                }\n                // var2node and previous_node for this operator\n                var2node[i_var] = ++previous_node;\n                //\n                graph_obj.operator_vec_push_back( graph_op );\n                graph_obj.operator_arg_push_back( left );\n                graph_obj.operator_arg_push_back( right );\n                graph_obj.operator_arg_push_back( if_true );\n                graph_obj.operator_arg_push_back( if_false );\n            }\n            break;\n\n            // --------------------------------------------------------------\n            // EndOp:\n            case local::EndOp:\n            more_operators = false;\n            break;\n\n            // --------------------------------------------------------------\n            // InvOp: independent variables\n            case local::InvOp:\n            // no graph operators for independent variables\n            break;\n\n            // --------------------------------------------------------------\n            // ParOp:\n            case local::ParOp:\n            // no need for a graph operator, just map variable to parameter\n            var2node[i_var] = par2node[arg[0]];\n            break;\n\n            // --------------------------------------------------------------\n            default:\n            // This error should have been reported above\n            CPPAD_ASSERT_UNKNOWN(false);\n            break;\n        }\n    }\n    // ----------------------------------------------------------------------\n    // output: dependent_vec\n    size_t n_dependent = dep_taddr_.size();\n    for(size_t i = 0; i < n_dependent; ++i)\n        graph_obj.dependent_vec_push_back( var2node[ dep_taddr_[i] ] );\n    //\n    return;\n}\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/graph/to_json.hpp",
    "content": "# ifndef CPPAD_CORE_GRAPH_TO_JSON_HPP\n# define CPPAD_CORE_GRAPH_TO_JSON_HPP\n\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/core/ad_fun.hpp>\n# include <cppad/local/op_code_dyn.hpp>\n# include <cppad/local/graph/cpp_graph_op.hpp>\n# include <cppad/core/graph/cpp_graph.hpp>\n# include <cppad/local/graph/json_writer.hpp>\n\n/*\n------------------------------------------------------------------------------\n{xrst_begin to_json}\n\nJson AD Graph Corresponding to an ADFun Object\n##############################################\n\nSyntax\n******\n| *json* = *fun* . ``to_json`` ()\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_PROTOTYPE\n    // END_PROTOTYPE\n}\n\nfun\n***\nis the :ref:`adfun-name` object.\n\njson\n****\nThe return value of *json* is a\n:ref:`json_ad_graph-name` representation of the corresponding function.\n\nBase\n****\nis the type corresponding to this :ref:`adfun-name` object;\ni.e., its calculations are done using the type *Base* .\n\nRecBase\n*******\nin the prototype above, *RecBase* is the same type as *Base* .\n\nRestrictions\n************\nThe ``to_json`` routine is not yet implement for some\npossible :ref:`ADFun-name` operators; see\n:ref:`graph_op_enum@Missing Operators` .\n{xrst_toc_hidden\n    example/json/to_json.cpp\n}\nExample\n*******\nThe file :ref:`to_json.cpp-name` is an example and test of this operation.\n\n{xrst_end to_json}\n*/\n// BEGIN_PROTOTYPE\ntemplate <class Base, class RecBase>\nstd::string CppAD::ADFun<Base,RecBase>::to_json(void)\n// END_PROTOTYPE\n{   //\n    // to_graph return values\n    cpp_graph graph_obj;\n    //\n    // graph corresponding to this function\n    to_graph(graph_obj);\n    //\n    // convert to json\n    std::string json;\n    local::graph::json_writer(json, graph_obj);\n    //\n    return json;\n}\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/hash_code.hpp",
    "content": "# ifndef CPPAD_CORE_HASH_CODE_HPP\n# define CPPAD_CORE_HASH_CODE_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*!\n\\file core/hash_code.hpp\nCppAD hashing utility.\n*/\n# include <cppad/local/hash_code.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\nGeneral purpose hash code for an arbitrary value.\n\n\\tparam Value\nis the type of the argument being hash coded.\nIt should be a plain old data class; i.e.,\nthe values included in the equality operator in the object and\nnot pointed to by the object.\n\n\\param value\nthe value that we are generating a hash code for.\nAll of the fields in value should have been set before the hash code\nis computed (otherwise undefined values are used).\n\n\\return\nis a hash code that is between zero and CPPAD_HASH_TABLE_SIZE - 1.\n\n\\par Checked Assertions\n\\li std::numeric_limits<unsigned short>::max() >= CPPAD_HASH_TABLE_SIZE\n\\li sizeof(value) is even\n\\li sizeof(unsigned short)  == 2\n*/\ntemplate <class Value>\nunsigned short hash_code(const Value& value)\n{   return local::local_hash_code(value); }\n\n/*!\nhash code for an AD<Base> object.\n\n\\tparam Base\nis the base type for this AD value.\n\n\\param u\nthe AD value that we are generating a hash code for.\n\n\\return\nis a hash code that is between zero and CPPAD_HASH_TABLE_SIZE - 1.\n*/\ntemplate <class Base>\nunsigned short hash_code(const AD<Base>& u)\n{   size_t code = hash_code(u.value_);\n    code       += size_t(u.taddr_);\n    code       += size_t(u.ad_type_ == dynamic_enum);\n    return (unsigned short)(code % CPPAD_HASH_TABLE_SIZE);\n}\n\n} // END_CPPAD_NAMESPACE\n\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/hessian.hpp",
    "content": "# ifndef CPPAD_CORE_HESSIAN_HPP\n# define CPPAD_CORE_HESSIAN_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin Hessian}\n\nHessian: Easy Driver\n####################\n\nSyntax\n******\n| *hes* = *f* . ``Hessian`` ( *x* , *w* )\n| *hes* = *f* . ``Hessian`` ( *x* , *l* )\n\nPurpose\n*******\nWe use :math:`F : \\B{R}^n \\rightarrow \\B{R}^m` to denote the\n:ref:`glossary@AD Function` corresponding to *f* .\nThe syntax above sets *hes* to the Hessian\nThe syntax above sets *h* to the Hessian\n\n.. math::\n\n    hes = \\dpow{2}{x} \\sum_{i=1}^m w_i F_i (x)\n\nThe routine :ref:`sparse_hessian-name` may be faster in the case\nwhere the Hessian is sparse.\n\nf\n*\nThe object *f* has prototype\n\n    ``ADFun`` < *Base* > *f*\n\nNote that the :ref:`ADFun-name` object *f* is not ``const``\n(see :ref:`Hessian@Hessian Uses Forward` below).\n\nx\n*\nThe argument *x* has prototype\n\n    ``const`` *Vector* & *x*\n\n(see :ref:`Hessian@Vector` below)\nand its size\nmust be equal to *n* , the dimension of the\n:ref:`fun_property@Domain` space for *f* .\nIt specifies\nthat point at which to evaluate the Hessian.\n\nl\n*\nIf the argument *l* is present, it has prototype\n\n    ``size_t`` *l*\n\nand is less than *m* , the dimension of the\n:ref:`fun_property@Range` space for *f* .\nIt specifies the component of *F*\nfor which we are evaluating the Hessian.\nTo be specific, in the case where the argument *l* is present,\n\n.. math::\n\n    w_i = \\left\\{ \\begin{array}{ll}\n        1 & i = l \\\\\n        0 & {\\rm otherwise}\n    \\end{array} \\right.\n\nw\n*\nIf the argument *w* is present, it has prototype\n\n    ``const`` *Vector* & *w*\n\nand size :math:`m`.\nIt specifies the value of :math:`w_i` in the expression\nfor *h* .\n\nhes\n***\nThe result *hes* has prototype\n\n    *Vector* *hes*\n\n(see :ref:`Hessian@Vector` below)\nand its size is :math:`n * n`.\nFor :math:`j = 0 , \\ldots , n - 1`\nand :math:`\\ell = 0 , \\ldots , n - 1`\n\n.. math::\n\n    hes [ j * n + \\ell ] = \\DD{ w^{\\rm T} F }{ x_j }{ x_\\ell } ( x )\n\nVector\n******\nThe type *Vector* must be a :ref:`SimpleVector-name` class with\n:ref:`elements of type<SimpleVector@Elements of Specified Type>`\n*Base* .\nThe routine :ref:`CheckSimpleVector-name` will generate an error message\nif this is not the case.\n\nHessian Uses Forward\n********************\nAfter each call to :ref:`Forward-name` ,\nthe object *f* contains the corresponding\n:ref:`Taylor coefficients<glossary@Taylor Coefficient>` .\nAfter a call to ``Hessian`` ,\nthe zero order Taylor coefficients correspond to\n*f* . ``Forward`` (0, *x* )\nand the other coefficients are unspecified.\n\nExample\n*******\n{xrst_toc_hidden\n    example/general/hessian.cpp\n    example/general/hes_lagrangian.cpp\n}\nThe routines\n:ref:`hessian.cpp-name` and\n:ref:`hes_lagrangian.cpp-name`\nare examples and tests of ``Hessian`` .\nThey return ``true`` , if they succeed and ``false`` otherwise.\n\n{xrst_end Hessian}\n-----------------------------------------------------------------------------\n*/\n\n//  BEGIN CppAD namespace\nnamespace CppAD {\n\ntemplate <class Base, class RecBase>\ntemplate <class Vector>\nVector ADFun<Base,RecBase>::Hessian(const Vector &x, size_t l)\n{   size_t i, m = Range();\n    CPPAD_ASSERT_KNOWN(\n        l < m,\n        \"Hessian: index i is not less than range dimension for f\"\n    );\n\n    Vector w(m);\n    for(i = 0; i < m; i++)\n        w[i] = Base(0.0);\n    w[l] = Base(1.0);\n\n    return Hessian(x, w);\n}\n\n\ntemplate <class Base, class RecBase>\ntemplate <class Vector>\nVector ADFun<Base,RecBase>::Hessian(const Vector &x, const Vector &w)\n{   size_t j;\n    size_t k;\n\n    size_t n = Domain();\n\n    // check Vector is Simple Vector class with Base type elements\n    CheckSimpleVector<Base, Vector>();\n\n    CPPAD_ASSERT_KNOWN(\n        size_t(x.size()) == n,\n        \"Hessian: length of x not equal domain dimension for f\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t(w.size()) == Range(),\n        \"Hessian: length of w not equal range dimension for f\"\n    );\n\n    // point at which we are evaluating the Hessian\n    Forward(0, x);\n\n    // define the return value\n    Vector hes(n * n);\n\n    // direction vector for calls to forward\n    Vector u(n);\n    for(j = 0; j < n; j++)\n        u[j] = Base(0.0);\n\n\n    // location for return values from Reverse\n    Vector ddw(n * 2);\n\n    // loop over forward directions\n    for(j = 0; j < n; j++)\n    {   // evaluate partials of entire function w.r.t. j-th coordinate\n        u[j] = Base(1.0);\n        Forward(1, u);\n        u[j] = Base(0.0);\n\n        // evaluate derivative of partial corresponding to F_i\n        ddw = Reverse(2, w);\n\n        // return desired components\n        for(k = 0; k < n; k++)\n            hes[k * n + j] = ddw[k * 2 + 1];\n    }\n\n    return hes;\n}\n\n} // END CppAD namespace\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/identical.hpp",
    "content": "# ifndef CPPAD_CORE_IDENTICAL_HPP\n# define CPPAD_CORE_IDENTICAL_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/local/define.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\n\\file identical.hpp\nCheck if certain properties is true for any possible AD tape play back.\n*/\n\n// ---------------------------------------------------------------------------\n/*!\nDetermine if an AD<Base> object is a parameter, and could never have\na different value during any tape playback.\n\nAn AD<Base> object x is identically a parameter if and only if\nall of the objects in the following chain are parameters:\n\\code\n    x , x.value , x.value.value , ...\n\\endcode\nIn such a case, the value of the object will always be the same\nno matter what the independent variable values are at any level.\n\n\\param x\nvalues that we are checking for identically a pamameter.\n\n\\return\nreturns true iff x is identically a parameter.\n*/\ntemplate <class Base>\nbool IdenticalCon(const AD<Base> &x)\n{   return Constant(x) && IdenticalCon(x.value_); }\n// Zero ==============================================================\n/*!\nDetermine if an AD<Base> is equal to zero,\nand must be equal zero during any tape playback.\n\n\\param x\nobject that we are checking.\n\n\\return\nreturns true if and only if\n x is equals zero and is identically a parameter \\ref CppAD::IdenticalCon.\n*/\ntemplate <class Base>\nbool IdenticalZero(const AD<Base> &x)\n{   return Constant(x) && IdenticalZero(x.value_); }\n// One ==============================================================\n/*!\nDetermine if an AD<Base> is equal to one,\nand must be equal one during any tape playback.\n\n\\param x\nobject that we are checking.\n\n\\return\nreturns true if and only if\n x is equals one and is identically a parameter \\ref CppAD::IdenticalCon.\n*/\ntemplate <class Base>\nbool IdenticalOne(const AD<Base> &x)\n{   return Constant(x) && IdenticalOne(x.value_); }\n// Equal ===================================================================\n/*!\nDetermine if two AD<Base> objects are equal,\nand must be equal during any tape playback.\n\n\\param x\nfirst of two objects we are checking for equal.\n\n\\param y\nsecond of two objects we are checking for equal.\n\n\\return\nreturns true if and only if\nthe arguments are equal and both identically parameters \\ref CppAD::IdenticalCon.\n*/\ntemplate <class Base>\nbool IdenticalEqualCon\n(const AD<Base> &x, const AD<Base> &y)\n{   bool constant;\n    constant  = Constant(x) && Constant(y);\n    return constant  & IdenticalEqualCon(x.value_, y.value_);\n}\n// ==========================================================================\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/independent/devel.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin devel_independent dev}\n\nDeveloper Documentation for Independent\n#######################################\n\nContents\n********\n{xrst_toc_table\n    include/cppad/core/independent/independent.hpp\n}\n\n{xrst_end devel_independent}\n"
  },
  {
    "path": "include/cppad/core/independent/independent.hpp",
    "content": "# ifndef CPPAD_CORE_INDEPENDENT_INDEPENDENT_HPP\n# define CPPAD_CORE_INDEPENDENT_INDEPENDENT_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/local/independent.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n\n/*\n{xrst_begin independent_all dev}\n\nIndependent: All Arguments Present\n##################################\n\nPurpose\n*******\nThis implements :ref:`Independent-name` with all the possible arguments present.\n\nSyntax\n******\n| ``Independent`` ( *x* , *abort_op_index* , *record_compare* , *dynamic* )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_ALL_ARGUMENT\n    // END_ALL_ARGUMENT\n}\n\nBase\n****\nThe base type the recording started by this operation.\n\nADVector\n********\nis simple vector type with elements of type ``AD`` < *Base* > .\n\nx\n*\nis the vector of the independent variables.\n\nabort_op_index\n**************\noperator index at which execution will be aborted (during  the recording\nof operations). The value zero corresponds to not aborting (will not match).\n\nrecord_compare\n**************\nshould comparison operators be recorded.\n\ndynamic\n*******\nis the independent dynamic parameter vector.\n\n{xrst_end independent_all}\n*/\n// BEGIN_ALL_ARGUMENT\ntemplate <class ADVector>\nvoid Independent(\n    ADVector&  x              ,\n    size_t     abort_op_index ,\n    bool       record_compare ,\n    ADVector&  dynamic        )\n// END_ALL_ARGUMENT\n{   CPPAD_ASSERT_KNOWN(\n        abort_op_index == 0 || record_compare,\n        \"Independent: abort_op_index is non-zero and record_compare is false.\"\n    );\n    typedef typename ADVector::value_type ADBase;\n    typedef typename ADBase::value_type   Base;\n    CPPAD_ASSERT_KNOWN(\n        ADBase::tape_ptr() == nullptr,\n        \"Independent: cannot create a new tape because\\n\"\n        \"a previous tape is still active (for this thread).\\n\"\n        \"AD<Base>::abort_recording() would abort this previous recording.\"\n    );\n    local::ADTape<Base>* tape = ADBase::tape_manage(new_tape_manage);\n    tape->Independent(x, abort_op_index, record_compare, dynamic);\n}\n/*\n----------------------------------------------------------------------------\n{xrst_begin independent_x_abort_record dev}\n\nIndependent: Default For dynamic\n################################\n\nPurpose\n*******\nThis implements :ref:`Independent-name` using\nthe default for the dynamic argument.\n\nSyntax\n******\n``Independent`` ( *x* , *abort_op_index* , *record_compare* )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_THREE_ARGUMENT\n    // END_THREE_ARGUMENT\n}\n\nBase\n****\nThe base type the recording started by this operation.\n\nADVector\n********\nis simple vector type with elements of type ``AD`` < *Base* > .\n\nx\n*\nis the vector of the independent variables.\n\nabort_op_index\n**************\noperator index at which execution will be aborted (during  the recording\nof operations). The value zero corresponds to not aborting (will not match).\n\nrecord_compare\n**************\nshould comparison operators be recorded.\n\n{xrst_end independent_x_abort_record}\n*/\n// BEGIN_THREE_ARGUMENT\ntemplate <class ADVector>\nvoid Independent(ADVector &x, size_t abort_op_index, bool record_compare)\n// END_THREE_ARGUMENT\n{  ADVector dynamic(0); // empty vector\n    Independent(x, abort_op_index, record_compare, dynamic);\n}\n/*\n------------------------------------------------------------------------------\n{xrst_begin independent_x_abort_op_index dev}\n\nIndependent: Default For record_compare, dynamic\n################################################\n\nPurpose\n*******\nThis implements :ref:`Independent-name` using\nthe default for the record_compare and dynamic arguments.\n\nSyntax\n******\n``Independent`` ( *x* , *abort_op_index* )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_X_ABORT_OP_INDEX\n    // END_X_ABORT_OP_INDEX\n}\n\nBase\n****\nThe base type the recording started by this operation.\n\nADVector\n********\nis simple vector type with elements of type ``AD`` < *Base* > .\n\nx\n*\nis the vector of the independent variables.\n\nabort_op_index\n**************\noperator index at which execution will be aborted (during  the recording\nof operations). The value zero corresponds to not aborting (will not match).\n\n{xrst_end independent_x_abort_op_index}\n*/\n// BEGIN_X_ABORT_OP_INDEX\ntemplate <class ADVector>\nvoid Independent(ADVector &x, size_t abort_op_index)\n// END_X_ABORT_OP_INDEX\n{  bool     record_compare = true;\n    ADVector dynamic(0); // empty vector\n    Independent(x, abort_op_index, record_compare, dynamic);\n}\n/*\n------------------------------------------------------------------------------\n{xrst_begin independent_x_dynamic dev}\n\nIndependent: Default For abort_op_index, record_compare\n#######################################################\n\nPurpose\n*******\nThis implements :ref:`Independent-name` using\nthe default for the abort_op_index and record_compare.\n\nSyntax\n******\n``Independent`` ( *x* , *dynamic* )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_X_DYNAMIC\n    // END_X_DYNAMIC\n}\n\nBase\n****\nThe base type the recording started by this operation.\n\nADVector\n********\nis simple vector type with elements of type ``AD`` < *Base* > .\n\nx\n*\nis the vector of the independent variables.\n\ndynamic\n*******\nis the independent dynamic parameter vector.\n\n{xrst_end independent_x_dynamic}\n*/\n// BEGIN_X_DYNAMIC\ntemplate <class ADVector>\nvoid Independent(ADVector& x, ADVector& dynamic)\n// END_X_DYNAMIC\n{  size_t   abort_op_index = 0;\n    bool     record_compare = true;\n    Independent(x, abort_op_index, record_compare, dynamic);\n}\n/*\n------------------------------------------------------------------------------\n{xrst_begin independent_x dev}\n\nIndependent: Default For abort_op_index, record_compare, dynamic\n################################################################\n\nPurpose\n*******\nThis implements :ref:`Independent-name` using\nthe default for the abort_op_index, record_compare and dynamic arguments.\n\nSyntax\n******\n``Independent`` ( *x* )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_ONE_ARGUMENT\n    // END_ONE_ARGUMENT\n}\n\nBase\n****\nThe base type the recording started by this operation.\n\nADVector\n********\nis simple vector type with elements of type ``AD`` < *Base* > .\n\nx\n*\nis the vector of the independent variables.\n\n{xrst_end independent_x}\n*/\n// BEGIN_ONE_ARGUMENT\ntemplate <class ADVector>\nvoid Independent(ADVector &x)\n// END_ONE_ARGUMENT\n{   size_t   abort_op_index = 0;\n    bool     record_compare = true;\n    ADVector dynamic(0); // empty vector\n    Independent(x, abort_op_index, record_compare, dynamic);\n}\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/independent/user.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin Independent}\n\nDeclare Independent Variables and Start Recording\n#################################################\n\nSyntax\n******\n| ``Independent`` ( *x* )\n| ``Independent`` ( *x* , *dynamic* )\n| ``Independent`` ( *x* , *abort_op_index* )\n| ``Independent`` ( *x* , *abort_op_index* , *record_compare* )\n| ``Independent`` ( *x* , *abort_op_index* , *record_compare* , *dynamic* )\n\nStart Recording\n***************\nThe syntax above starts recording\n:ref:`glossary@AD of Base` operations\nwith *x* as the independent variable vector.\nOnce the\n:ref:`operation sequence<glossary@Operation@Sequence>` is completed,\nit must be transferred to a function object or aborted; see below.\n\nStop Recording\n**************\nThe recording is stopped,\nand the operation sequence is transferred to the AD function object *f* ,\nusing either the :ref:`function constructor<fun_construct-name>`\n\n    ``ADFun`` < *Base* > *f* ( *x* , *y* )\n\nor the :ref:`dependent variable specifier<Dependent-name>`\n\n    *f* . ``Dependent`` ( *x* , *y* )\n\nThe only other way to stop a recording is using\n:ref:`abort_recording-name` .\nBetween when the recording is started and when it stopped,\nwe refer to the elements of *x* ,\nand the values that depend on the elements of *x* ,\nas ``AD`` < *Base* > variables.\n\nx\n*\nThe vector *x* has prototype\n\n    *ADVector* & *x*\n\n(see *ADVector* below).\nThe size of the vector *x* , must be greater than zero,\nand is the number of independent variables for this\nAD operation sequence.\n\nabort_op_index\n**************\nIf this argument has prototype\n\n    ``size_t`` *abort_op_index*\n\nIf it is present,\nit specifies the operator index at which the execution will aborted\nby calling the CppAD :ref:`error handler<ErrorHandler-name>` .\nWhen this error handler leads to an assert, the user\ncan inspect the call stack to see the source code corresponding to\nthis operator index; see\n:ref:`compare_change@op_index@Purpose` for *op_index*\nand :ref:`Faq@Speed@NDEBUG` .\nNo abort will occur if *abort_op_index* is zero.\nIf this argument is not present, the default value zero is used\nfor *abort_index* .\n\nrecord_compare\n**************\nThis argument has prototype\n\n    ``bool`` *record_compare*\n\nIf it is present,\nit specifies if AD :ref:`compare-name`  operations are recorded.\nIt takes extra time and memory to record these operations.\nOn the other hand, they can be useful for detecting when and why\na functions recording would change; see *abort_op_index* above and\n:ref:`compare_change-name` .\nIf this argument is not present, the default value ``true`` is used\nfor *record_compare* .\nIf this argument is false, *abort_op_index* must be zero.\n\ndynamic\n*******\nIf this argument is present, it has prototype\n\n    ``const`` *ADVector* & *dynamic*\n\n(see *Vector* below).\nIt specifies the independent\n:ref:`glossary@Parameter@Dynamic` parameters.\nThe value of these parameters,\nin the :ref:`ADFun-name` object *f* ,\nthat can be changed using :ref:`new_dynamic-name` .\n\nEfficiency\n==========\nAny operations that use dynamic parameters will be recorded.\nWe use other dynamic parameters to denote parameters that depend on\nthe independent dynamic parameters *dynamic* ,\nand do not depend on *x* .\nIt is more efficient to compute other dynamic parameters before calling\n``Independent`` and include them in the\nindependent dynamic parameter vector *dynamic* .\n\nADVector\n********\nThe type *ADVector* must be a :ref:`SimpleVector-name` class with\n:ref:`elements of type<SimpleVector@Elements of Specified Type>`\n``AD`` < *Base* > .\nThe routine :ref:`CheckSimpleVector-name` will generate an error message\nif this is not the case.\n\nParallel Mode\n*************\nEach thread can have one, and only one, active recording.\nA call to ``Independent`` starts the recording for the current thread.\nThe recording must be stopped by a corresponding call to\n\n    ``ADFun`` < *Base* > *f* ( *x* , *y* )\n\nor\n\n    *f* . ``Dependent`` ( *x* , *y* )\n\nor :ref:`abort_recording-name`\npreformed by the same thread; i.e.,\n:ref:`thread_alloc::thread_num<ta_thread_num-name>` must be the same.\n\nExample\n*******\n{xrst_toc_hidden\n    example/general/independent.cpp\n}\nThe file\n:ref:`independent.cpp-name`\ncontains an example and test of this operation.\n\n{xrst_end Independent}\n"
  },
  {
    "path": "include/cppad/core/integer.hpp",
    "content": "# ifndef CPPAD_CORE_INTEGER_HPP\n# define CPPAD_CORE_INTEGER_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n------------------------------------------------------------------------------\n{xrst_begin Integer}\n\nConvert From AD to Integer\n##########################\n\nSyntax\n******\n| *i* = ``Integer`` ( *x* )\n\nPurpose\n*******\nConverts from an AD type to the corresponding integer value.\n\ni\n*\nThe result *i* has prototype\n\n    ``int`` *i*\n\nx\n*\n\nReal Types\n==========\nIf the argument *x* has either of the following prototypes:\n\n| |tab| ``const float`` & *x*\n| |tab| ``const double`` & *x*\n\nthe fractional part is dropped to form the integer value.\nFor example, if *x* is 1.5, *i* is 1.\nIn general, if :math:`x \\geq 0`, *i* is the\ngreatest integer less than or equal *x* .\nIf :math:`x \\leq 0`, *i* is the\nsmallest integer greater than or equal *x* .\n\nComplex Types\n=============\nIf the argument *x* has either of the following prototypes:\n\n| |tab| ``const std::complex<float>`` & *x*\n| |tab| ``const std::complex<double>`` & *x*\n\nThe result *i* is given by\n\n    *i* = ``Integer`` ( *x* . ``real`` ())\n\nAD Types\n========\nIf the argument *x* has either of the following prototypes:\n\n| |tab| ``const AD`` < *Base* >               & *x*\n| |tab| ``const VecAD`` < *Base* >:: ``reference &`` *x*\n\n*Base* must support the ``Integer`` function and\nthe conversion has the same meaning as for *Base* .\n\nOperation Sequence\n******************\nThe result of this operation is not an\n:ref:`glossary@AD of Base` object.\nThus it will not be recorded as part of an\nAD of *Base*\n:ref:`operation sequence<glossary@Operation@Sequence>` .\n\nExample\n*******\n{xrst_toc_hidden\n    example/general/integer.cpp\n}\nThe file\n:ref:`integer.cpp-name`\ncontains an example and test of this operation.\n\n{xrst_end Integer}\n------------------------------------------------------------------------------\n*/\n\n\nnamespace CppAD {\n\n    template <class Base>\n    CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION\n    int Integer(const AD<Base> &x)\n    {   return Integer(x.value_); }\n\n    template <class Base>\n    CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION\n    int Integer(const VecAD_reference<Base> &x)\n    {   return Integer( x.ADBase() ); }\n}\n# endif\n"
  },
  {
    "path": "include/cppad/core/jacobian.hpp",
    "content": "# ifndef CPPAD_CORE_JACOBIAN_HPP\n# define CPPAD_CORE_JACOBIAN_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin Jacobian}\n\nJacobian: Driver Routine\n########################\n\nSyntax\n******\n| *jac* = *f* . ``Jacobian`` ( *x* )\n\nPurpose\n*******\nWe use :math:`F : \\B{R}^n \\rightarrow \\B{R}^m` to denote the\n:ref:`glossary@AD Function` corresponding to *f* .\nThe syntax above sets *jac* to the\nJacobian of *F* evaluated at *x* ; i.e.,\n\n.. math::\n\n    jac = F^{(1)} (x)\n\nf\n*\nThe object *f* has prototype\n\n    ``ADFun`` < *Base* > *f*\n\nNote that the :ref:`ADFun-name` object *f* is not ``const``\n(see :ref:`Jacobian@Forward or Reverse` below).\n\nx\n*\nThe argument *x* has prototype\n\n    ``const`` *Vector* & *x*\n\n(see :ref:`Jacobian@Vector` below)\nand its size\nmust be equal to *n* , the dimension of the\n:ref:`fun_property@Domain` space for *f* .\nIt specifies\nthat point at which to evaluate the Jacobian.\n\njac\n***\nThe result *jac* has prototype\n\n    *Vector* *jac*\n\n(see :ref:`Jacobian@Vector` below)\nand its size is :math:`m * n`; i.e., the product of the\n:ref:`fun_property@Domain`\nand\n:ref:`fun_property@Range`\ndimensions for *f* .\nFor :math:`i = 0 , \\ldots , m - 1`\nand :math:`j = 0 , \\ldots , n - 1`\n\n.. math::\n\n    jac[ i * n + j ] = \\D{ F_i }{ x_j } ( x )\n\nVector\n******\nThe type *Vector* must be a :ref:`SimpleVector-name` class with\n:ref:`elements of type<SimpleVector@Elements of Specified Type>`\n*Base* .\nThe routine :ref:`CheckSimpleVector-name` will generate an error message\nif this is not the case.\n\nForward or Reverse\n******************\nThis will use order zero Forward mode and either\norder one Forward or order one Reverse to compute the Jacobian\n(depending on which it estimates will require less work).\nAfter each call to :ref:`Forward-name` ,\nthe object *f* contains the corresponding\n:ref:`Taylor coefficients<glossary@Taylor Coefficient>` .\nAfter a call to ``Jacobian`` ,\nthe zero order Taylor coefficients correspond to\n*f* . ``Forward`` (0, *x* )\nand the other coefficients are unspecified.\n\nExample\n*******\n{xrst_toc_hidden\n    example/general/jacobian.cpp\n}\nThe routine\n:ref:`Jacobian<jacobian.cpp-name>` is both an example and test.\nIt returns ``true`` , if it succeeds and ``false`` otherwise.\n\n{xrst_end Jacobian}\n-----------------------------------------------------------------------------\n*/\n\n//  BEGIN CppAD namespace\nnamespace CppAD {\n\ntemplate <class Base, class RecBase, class Vector>\nvoid JacobianFor(ADFun<Base, RecBase> &f, const Vector &x, Vector &jac)\n{   size_t i;\n    size_t j;\n\n    size_t n = f.Domain();\n    size_t m = f.Range();\n\n    // check Vector is Simple Vector class with Base type elements\n    CheckSimpleVector<Base, Vector>();\n\n    CPPAD_ASSERT_UNKNOWN( size_t(x.size())   == f.Domain() );\n    CPPAD_ASSERT_UNKNOWN( size_t(jac.size()) == f.Range() * f.Domain() );\n\n    // argument and result for forward mode calculations\n    Vector u(n);\n    Vector v(m);\n\n    // initialize all the components\n    for(j = 0; j < n; j++)\n        u[j] = Base(0.0);\n\n    // loop through the different coordinate directions\n    for(j = 0; j < n; j++)\n    {   // set u to the j-th coordinate direction\n        u[j] = Base(1.0);\n\n        // compute the partial of f w.r.t. this coordinate direction\n        v = f.Forward(1, u);\n\n        // reset u to vector of all zeros\n        u[j] = Base(0.0);\n\n        // return the result\n        for(i = 0; i < m; i++)\n            jac[ i * n + j ] = v[i];\n    }\n}\ntemplate <class Base, class RecBase, class Vector>\nvoid JacobianRev(ADFun<Base, RecBase> &f, const Vector &x, Vector &jac)\n{   size_t i;\n    size_t j;\n\n    size_t n = f.Domain();\n    size_t m = f.Range();\n\n    CPPAD_ASSERT_UNKNOWN( size_t(x.size())   == f.Domain() );\n    CPPAD_ASSERT_UNKNOWN( size_t(jac.size()) == f.Range() * f.Domain() );\n\n    // argument and result for reverse mode calculations\n    Vector u(n);\n    Vector v(m);\n\n    // initialize all the components\n    for(i = 0; i < m; i++)\n        v[i] = Base(0.0);\n\n    // loop through the different coordinate directions\n    for(i = 0; i < m; i++)\n    {   if( f.Parameter(i) )\n        {   // return zero for this component of f\n            for(j = 0; j < n; j++)\n                jac[ i * n + j ] = Base(0.0);\n        }\n        else\n        {\n            // set v to the i-th coordinate direction\n            v[i] = Base(1.0);\n\n            // compute the derivative of this component of f\n            u = f.Reverse(1, v);\n\n            // reset v to vector of all zeros\n            v[i] = Base(0.0);\n\n            // return the result\n            for(j = 0; j < n; j++)\n                jac[ i * n + j ] = u[j];\n        }\n    }\n}\n\ntemplate <class Base, class RecBase>\ntemplate <class Vector>\nVector ADFun<Base,RecBase>::Jacobian(const Vector &x)\n{   size_t i;\n    size_t n = Domain();\n    size_t m = Range();\n\n    CPPAD_ASSERT_KNOWN(\n        size_t(x.size()) == n,\n        \"Jacobian: length of x not equal domain dimension for F\"\n    );\n\n    // point at which we are evaluating the Jacobian\n    Forward(0, x);\n\n    // work factor for forward mode\n    size_t workForward = n;\n\n    // work factor for reverse mode\n    size_t workReverse = 0;\n    for(i = 0; i < m; i++)\n    {   if( ! Parameter(i) )\n            ++workReverse;\n    }\n\n    // choose the method with the least work\n    Vector jac( n * m );\n# ifdef CPPAD_FOR_TMB\n    if( workForward < workReverse )\n# else\n    if( workForward <= workReverse )\n# endif\n        JacobianFor(*this, x, jac);\n    else\n        JacobianRev(*this, x, jac);\n\n    return jac;\n}\n\n} // END CppAD namespace\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/lu_ratio.hpp",
    "content": "# ifndef CPPAD_CORE_LU_RATIO_HPP\n# define CPPAD_CORE_LU_RATIO_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin LuRatio app}\n{xrst_spell\n    ip\n    jp\n    xk\n}\n\nLU Factorization of A Square Matrix and Stability Calculation\n#############################################################\n\nSyntax\n******\n| ``# include <cppad/cppad.hpp>``\n| *sign* = ``LuRatio`` ( *ip* , *jp* , *LU* , *ratio* )\n\nDescription\n***********\nComputes an LU factorization of the matrix *A*\nwhere *A* is a square matrix.\nA measure of the numerical stability called *ratio* is calculated.\nThis ratio is useful when the results of ``LuRatio`` are\nused as part of an :ref:`ADFun-name` object.\n\nInclude\n*******\nThis routine is designed to be used with AD objects and\nrequires the ``cppad/cppad.hpp`` file to be included.\n\nMatrix Storage\n**************\nAll matrices are stored in row major order.\nTo be specific, if :math:`Y` is a vector\nthat contains a :math:`p` by :math:`q` matrix,\nthe size of :math:`Y` must be equal to :math:`p * q` and for\n:math:`i = 0 , \\ldots , p-1`,\n:math:`j = 0 , \\ldots , q-1`,\n\n.. math::\n\n    Y_{i,j} = Y[ i * q + j ]\n\nsign\n****\nThe return value *sign* has prototype\n\n    ``int`` *sign*\n\nIf *A* is invertible, *sign* is plus or minus one\nand is the sign of the permutation corresponding to the row ordering\n*ip* and column ordering *jp* .\nIf *A* is not invertible, *sign* is zero.\n\nip\n**\nThe argument *ip* has prototype\n\n    *SizeVector* & *ip*\n\n(see description of :ref:`LuFactor@SizeVector` below).\nThe size of *ip* is referred to as *n* in the\nspecifications below.\nThe input value of the elements of *ip* does not matter.\nThe output value of the elements of *ip* determine\nthe order of the rows in the permuted matrix.\n\njp\n**\nThe argument *jp* has prototype\n\n    *SizeVector* & *jp*\n\n(see description of :ref:`LuFactor@SizeVector` below).\nThe size of *jp* must be equal to *n* .\nThe input value of the elements of *jp* does not matter.\nThe output value of the elements of *jp* determine\nthe order of the columns in the permuted matrix.\n\nLU\n**\nThe argument *LU* has the prototype\n\n    *ADvector* & *LU*\n\nand the size of *LU* must equal :math:`n * n`\n(see description of :ref:`LuRatio@ADvector` below).\n\nA\n=\nWe define *A* as the matrix corresponding to the input\nvalue of *LU* .\n\nP\n=\nWe define the permuted matrix *P* in terms of *A* by\n\n    *P* ( *i* , *j* ) = *A* [ *ip* [ *i* ] * *n* + *jp* [ *j* ] ]\n\nL\n=\nWe define the lower triangular matrix *L* in terms of the\noutput value of *LU* .\nThe matrix *L* is zero above the diagonal\nand the rest of the elements are defined by\n\n    *L* ( *i* , *j* ) = *LU* [ *ip* [ *i* ] * *n* + *jp* [ *j* ] ]\n\nfor :math:`i = 0 , \\ldots , n-1` and :math:`j = 0 , \\ldots , i`.\n\nU\n=\nWe define the upper triangular matrix *U* in terms of the\noutput value of *LU* .\nThe matrix *U* is zero below the diagonal,\none on the diagonal,\nand the rest of the elements are defined by\n\n    *U* ( *i* , *j* ) = *LU* [ *ip* [ *i* ] * *n* + *jp* [ *j* ] ]\n\nfor :math:`i = 0 , \\ldots , n-2` and :math:`j = i+1 , \\ldots , n-1`.\n\nFactor\n======\nIf the return value *sign* is non-zero,\n\n    *L* * *U* = *P*\n\nIf the return value of *sign* is zero,\nthe contents of *L* and *U* are not defined.\n\nDeterminant\n===========\nIf the return value *sign* is zero,\nthe determinant of *A* is zero.\nIf *sign* is non-zero,\nusing the output value of *LU*\nthe determinant of the matrix *A* is equal to\n\n    *sign* * *LU* [ *ip* [0], *jp* [0]] * ... * *LU* [ *ip* [ *n* ``-1`` ], *jp* [ *n* ``-1`` ]]\n\nratio\n*****\nThe argument *ratio* has prototype\n\n    ``AD`` < *Base* > & *ratio*\n\nOn input, the value of *ratio* does not matter.\nOn output it is a measure of how good the choice of pivots is.\nFor :math:`p = 0 , \\ldots , n-1`,\nthe *p*-th pivot element is the element of maximum absolute value of a\n:math:`(n-p) \\times (n-p)` sub-matrix.\nThe ratio of each element of sub-matrix divided by the pivot element\nis computed.\nThe return value of *ratio* is the maximum absolute value of\nsuch ratios over with respect to all elements and all the pivots.\n\nPurpose\n=======\nSuppose that the execution of a call to ``LuRatio``\nis recorded in the ``ADFun`` < *Base* > object *F* .\nThen a call to :ref:`Forward-name` of the form\n\n    *F* . ``Forward`` ( *k* , *xk* )\n\nwith *k* equal to zero will revaluate this Lu factorization\nwith the same pivots and a new value for *A* .\nIn this case, the resulting *ratio* may not be one.\nIf *ratio* is too large (the meaning of too large is up to you),\nthe current pivots do not yield a stable LU factorization of *A* .\nA better choice for the pivots (for this value of *A* )\nwill be made if you recreate the ``ADFun`` object\nstarting with the :ref:`Independent-name` variable values\nthat correspond to the vector *xk* .\n\nSizeVector\n**********\nThe type *SizeVector* must be a :ref:`SimpleVector-name` class with\n:ref:`elements of type size_t<SimpleVector@Elements of Specified Type>` .\nThe routine :ref:`CheckSimpleVector-name` will generate an error message\nif this is not the case.\n\nADvector\n********\nThe type *ADvector* must be a\n:ref:`simple vector class<SimpleVector-name>` with elements of type\n``AD`` < *Base* > .\nThe routine :ref:`CheckSimpleVector-name` will generate an error message\nif this is not the case.\n\nExample\n*******\n{xrst_toc_hidden\n    example/general/lu_ratio.cpp\n}\nThe file :ref:`lu_ratio.cpp-name`\ncontains an example and test of using ``LuRatio`` .\n\n{xrst_end LuRatio}\n--------------------------------------------------------------------------\n*/\nnamespace CppAD { // BEGIN CppAD namespace\n\n// Lines different from the code in cppad/lu_factor.hpp end with           //\ntemplate <class SizeVector, class ADvector, class Base>                    //\nint LuRatio(SizeVector &ip, SizeVector &jp, ADvector &LU, AD<Base> &ratio) //\n{\n    typedef ADvector FloatVector;                                       //\n    typedef AD<Base>       Float;                                       //\n\n    // check numeric type specifications\n    CheckNumericType<Float>();\n\n    // check simple vector class specifications\n    CheckSimpleVector<Float, FloatVector>();\n    CheckSimpleVector<size_t, SizeVector>();\n\n    size_t  i, j;          // some temporary indices\n    const Float zero( 0 ); // the value zero as a Float object\n    size_t  imax;          // row index of maximum element\n    size_t  jmax;          // column index of maximum element\n    Float    emax;         // maximum absolute value\n    size_t  p;             // count pivots\n    int     sign;          // sign of the permutation\n    Float   etmp;          // temporary element\n    Float   pivot;         // pivot element\n\n    // -------------------------------------------------------\n    size_t n = size_t(ip.size());\n    CPPAD_ASSERT_KNOWN(\n        size_t(jp.size()) == n,\n        \"Error in LuFactor: jp must have size equal to n\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t(LU.size()) == n * n,\n        \"Error in LuFactor: LU must have size equal to n * m\"\n    );\n    // -------------------------------------------------------\n\n    // initialize row and column order in matrix not yet pivoted\n    for(i = 0; i < n; i++)\n    {   ip[i] = i;\n        jp[i] = i;\n    }\n    // initialize the sign of the permutation\n    sign = 1;\n    // initialize the ratio                                             //\n    ratio = Float(1);                                                   //\n    // ---------------------------------------------------------\n\n    // Reduce the matrix P to L * U using n pivots\n    for(p = 0; p < n; p++)\n    {   // determine row and column corresponding to element of\n        // maximum absolute value in remaining part of P\n        imax = jmax = n;\n        emax = zero;\n        for(i = p; i < n; i++)\n        {   for(j = p; j < n; j++)\n            {   CPPAD_ASSERT_UNKNOWN(\n                    (ip[i] < n) && (jp[j] < n)\n                );\n                etmp = LU[ ip[i] * n + jp[j] ];\n\n                // check if maximum absolute value so far\n                if( AbsGeq (etmp, emax) )\n                {   imax = i;\n                    jmax = j;\n                    emax = etmp;\n                }\n            }\n        }\n        for(i = p; i < n; i++)                                       //\n        {   for(j = p; j < n; j++)                               //\n            {   etmp  = fabs(LU[ ip[i] * n + jp[j] ] / emax); //\n                ratio =                                      //\n                CondExpGt(etmp, ratio, etmp, ratio);         //\n            }                                                    //\n        }                                                            //\n        CPPAD_ASSERT_KNOWN(\n            (imax < n) && (jmax < n) ,\n            \"AbsGeq must return true when second argument is zero\"\n        );\n        if( imax != p )\n        {   // switch rows so max absolute element is in row p\n            i        = ip[p];\n            ip[p]    = ip[imax];\n            ip[imax] = i;\n            sign     = -sign;\n        }\n        if( jmax != p )\n        {   // switch columns so max absolute element is in column p\n            j        = jp[p];\n            jp[p]    = jp[jmax];\n            jp[jmax] = j;\n            sign     = -sign;\n        }\n        // pivot using the max absolute element\n        pivot   = LU[ ip[p] * n + jp[p] ];\n\n        // check for determinant equal to zero\n        if( pivot == zero )\n        {   // abort the mission\n            return   0;\n        }\n\n        // Reduce U by the elementary transformations that maps\n        // LU( ip[p], jp[p] ) to one.  Only need transform elements\n        // above the diagonal in U and LU( ip[p] , jp[p] ) is\n        // corresponding value below diagonal in L.\n        for(j = p+1; j < n; j++)\n            LU[ ip[p] * n + jp[j] ] /= pivot;\n\n        // Reduce U by the elementary transformations that maps\n        // LU( ip[i], jp[p] ) to zero. Only need transform elements\n        // above the diagonal in U and LU( ip[i], jp[p] ) is\n        // corresponding value below diagonal in L.\n        for(i = p+1; i < n; i++ )\n        {   etmp = LU[ ip[i] * n + jp[p] ];\n            for(j = p+1; j < n; j++)\n            {   LU[ ip[i] * n + jp[j] ] -=\n                    etmp * LU[ ip[p] * n + jp[j] ];\n            }\n        }\n    }\n    return sign;\n}\n} // END CppAD namespace\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/mul.hpp",
    "content": "# ifndef CPPAD_CORE_MUL_HPP\n# define CPPAD_CORE_MUL_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n//  BEGIN CppAD namespace\nnamespace CppAD {\n\ntemplate <class Base>\nAD<Base> operator * (const AD<Base> &left , const AD<Base> &right)\n{\n    // compute the Base part\n    AD<Base> result;\n    result.value_  = left.value_ * right.value_;\n    CPPAD_ASSERT_UNKNOWN( Parameter(result) );\n\n    // check if there is a recording in progress\n    local::ADTape<Base>* tape = AD<Base>::tape_ptr();\n    if( tape == nullptr )\n        return result;\n    tape_id_t tape_id = tape->id_;\n    // tape_id cannot match the default value for tape_id_; i.e., 0\n    CPPAD_ASSERT_UNKNOWN( tape_id > 0 );\n\n    // check if left and right tapes match\n    bool match_left  = left.tape_id_  == tape_id;\n    bool match_right = right.tape_id_ == tape_id;\n\n    // check if left and right are dynamic parameters\n    bool dyn_left  = match_left  & (left.ad_type_ == dynamic_enum);\n    bool dyn_right = match_right & (right.ad_type_ == dynamic_enum);\n\n    // check if left and right are variables\n    bool var_left  = match_left  & (left.ad_type_ != dynamic_enum);\n    bool var_right = match_right & (right.ad_type_ != dynamic_enum);\n\n    CPPAD_ASSERT_KNOWN(\n        left.tape_id_ == right.tape_id_ || ! match_left || ! match_right ,\n        \"Multiply: AD variables or dynamic parameters on different threads.\"\n    );\n    if( var_left )\n    {   if( var_right )\n        {   // result = variable * variable\n            CPPAD_ASSERT_UNKNOWN( local::NumRes(local::MulvvOp) == 1 );\n            CPPAD_ASSERT_UNKNOWN( local::NumArg(local::MulvvOp) == 2 );\n\n            // put operand addresses in tape\n            tape->Rec_.PutArg(left.taddr_, right.taddr_);\n            // put operator in the tape\n            result.taddr_ = tape->Rec_.PutOp(local::MulvvOp);\n            // make result a variable\n            result.tape_id_ = tape_id;\n            result.ad_type_ = variable_enum;\n        }\n        else if( (! dyn_right) && IdenticalZero(right.value_) )\n        {   // result = variable * 0\n            result.value_ = Base(0.0); // incase left.value_ is nan\n        }\n        else if( (! dyn_right) && IdenticalOne(right.value_) )\n        {   // result = variable * 1\n            result.make_variable(left.tape_id_, left.taddr_);\n        }\n        else\n        {   // result = variable * parameter\n            CPPAD_ASSERT_UNKNOWN( local::NumRes(local::MulpvOp) == 1 );\n            CPPAD_ASSERT_UNKNOWN( local::NumArg(local::MulpvOp) == 2 );\n\n            // put operand addresses in tape\n            addr_t p = right.taddr_;\n            if( ! dyn_right )\n                p = tape->Rec_.put_con_par(right.value_);\n            tape->Rec_.PutArg(p, left.taddr_);\n            // put operator in the tape\n            result.taddr_ = tape->Rec_.PutOp(local::MulpvOp);\n            // make result a variable\n            result.tape_id_ = tape_id;\n            result.ad_type_ = variable_enum;\n        }\n    }\n    else if( var_right )\n    {   if( (! dyn_left) && IdenticalZero(left.value_) )\n        {   // result = 0 * variable\n            result.value_ = Base(0.0); // incase right.value_ is nan\n        }\n        else if( (! dyn_left) && IdenticalOne(left.value_) )\n        {   // result = 1 * variable\n            result.make_variable(right.tape_id_, right.taddr_);\n        }\n        else\n        {   // result = parameter * variable\n            CPPAD_ASSERT_UNKNOWN( local::NumRes(local::MulpvOp) == 1 );\n            CPPAD_ASSERT_UNKNOWN( local::NumArg(local::MulpvOp) == 2 );\n\n            // put operand addresses in tape\n            addr_t p = left.taddr_;\n            if( ! dyn_left )\n                p = tape->Rec_.put_con_par(left.value_);\n            tape->Rec_.PutArg(p, right.taddr_);\n            // put operator in the tape\n            result.taddr_ = tape->Rec_.PutOp(local::MulpvOp);\n            // make result a variable\n            result.tape_id_ = tape_id;\n            result.ad_type_ = variable_enum;\n        }\n    }\n    else if( dyn_left | dyn_right )\n    {   if ( (!dyn_left) && IdenticalZero(left.value_))\n        {   // 0 * dynamic\n            result.value_ = Base(0.0);\n        } else if( (!dyn_right) && IdenticalZero(right.value_))\n        {   // dynamic * 0\n            result.value_ = Base(0.0);\n        } else if( (!dyn_left) && IdenticalOne(left.value_))\n        {   // 1 * dynamic\n            result.make_dynamic(right.tape_id_, right.taddr_);\n        } else if( (!dyn_right) && IdenticalOne(right.value_))\n        {   // dynamic * 1\n            result.make_dynamic(left.tape_id_, left.taddr_);\n        } else\n        {\n            addr_t arg0 = left.taddr_;\n            addr_t arg1 = right.taddr_;\n            if( ! dyn_left )\n            arg0 = tape->Rec_.put_con_par(left.value_);\n            if( ! dyn_right )\n            arg1 = tape->Rec_.put_con_par(right.value_);\n            //\n            // parameters with a dynamic parameter result\n            result.taddr_   = tape->Rec_.put_dyn_par(\n                result.value_, local::mul_dyn,   arg0, arg1\n            );\n            result.tape_id_ = tape_id;\n            result.ad_type_ = dynamic_enum;\n        }\n    }\n    return result;\n}\n\n// convert other cases into the case above\nCPPAD_FOLD_AD_VALUED_BINARY_OPERATOR(*)\n\n} // END CppAD namespace\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/mul_eq.hpp",
    "content": "# ifndef CPPAD_CORE_MUL_EQ_HPP\n# define CPPAD_CORE_MUL_EQ_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n//  BEGIN CppAD namespace\nnamespace CppAD {\n\ntemplate <class Base>\nAD<Base>& AD<Base>::operator *= (const AD<Base> &right)\n{\n    // compute the Base part\n    Base left;\n    left    = value_;\n    value_ *= right.value_;\n\n    // check if there is a recording in progress\n    local::ADTape<Base>* tape = AD<Base>::tape_ptr();\n    if( tape == nullptr )\n        return *this;\n    tape_id_t tape_id = tape->id_;\n    // tape_id cannot match the default value for tape_id_; i.e., 0\n    CPPAD_ASSERT_UNKNOWN( tape_id > 0 );\n\n    // check if left and right tapes match\n    bool match_left  = tape_id_       == tape_id;\n    bool match_right = right.tape_id_ == tape_id;\n\n    // check if left and right are dynamic parameters\n    bool dyn_left  = match_left  & (ad_type_ == dynamic_enum);\n    bool dyn_right = match_right & (right.ad_type_ == dynamic_enum);\n\n    // check if left and right are variables\n    bool var_left  = match_left  & (ad_type_ != dynamic_enum);\n    bool var_right = match_right & (right.ad_type_ != dynamic_enum);\n\n    CPPAD_ASSERT_KNOWN(\n        tape_id_ == right.tape_id_ || ! match_left || ! match_right ,\n        \"*= : AD variables or dynamic parameters on different threads.\"\n    );\n    if( var_left )\n    {   if( var_right )\n        {   // this = variable * variable\n            CPPAD_ASSERT_UNKNOWN( local::NumRes(local::MulvvOp) == 1 );\n            CPPAD_ASSERT_UNKNOWN( local::NumArg(local::MulvvOp) == 2 );\n\n            // put operand addresses in tape\n            tape->Rec_.PutArg(taddr_, right.taddr_);\n            // put operator in the tape\n            taddr_ = tape->Rec_.PutOp(local::MulvvOp);\n            // check that this is a variable\n            CPPAD_ASSERT_UNKNOWN( tape_id_ == tape_id );\n            CPPAD_ASSERT_UNKNOWN( ad_type_ == variable_enum);\n        }\n        else if( (! dyn_right) && IdenticalOne(right.value_) )\n        {   // this = variable * 1\n        }\n        else if( (! dyn_right) && IdenticalZero(right.value_) )\n        {   // this = variable * 0\n            tape_id_ = 0; // not in current tape\n        }\n        else\n        {   // this = variable  * parameter\n            //      = parameter * variable\n            CPPAD_ASSERT_UNKNOWN( local::NumRes(local::MulpvOp) == 1 );\n            CPPAD_ASSERT_UNKNOWN( local::NumArg(local::MulpvOp) == 2 );\n\n            // put operand addresses in tape\n            addr_t p = right.taddr_;\n            if( ! dyn_right )\n                p = tape->Rec_.put_con_par(right.value_);\n            tape->Rec_.PutArg(p, taddr_);\n            // put operator in the tape\n            taddr_ = tape->Rec_.PutOp(local::MulpvOp);\n            // check that this is a variable\n            CPPAD_ASSERT_UNKNOWN( tape_id_ == tape_id );\n            CPPAD_ASSERT_UNKNOWN( ad_type_ == variable_enum);\n        }\n    }\n    else if( var_right  )\n    {   if( (! dyn_left) && IdenticalZero(left) )\n        {   // this = 0 * right\n        }\n        else if( (! dyn_left) && IdenticalOne(left) )\n        {   // this = 1 * right\n            make_variable(right.tape_id_, right.taddr_);\n        }\n        else\n        {   // this = parameter * variable\n            CPPAD_ASSERT_UNKNOWN( local::NumRes(local::MulpvOp) == 1 );\n            CPPAD_ASSERT_UNKNOWN( local::NumArg(local::MulpvOp) == 2 );\n\n            // put operand addresses in tape\n            addr_t p = taddr_;\n            if( ! dyn_left )\n                p = tape->Rec_.put_con_par(left);\n            tape->Rec_.PutArg(p, right.taddr_);\n\n            // put operator in the tape\n            taddr_ = tape->Rec_.PutOp(local::MulpvOp);\n\n            // make this a variable\n            tape_id_ = tape_id;\n            ad_type_ = variable_enum;\n        }\n    }\n    else if( dyn_left | dyn_right )\n    {   if( (!dyn_right) && IdenticalOne(right.value_))\n        {   // dynamic *= 1, so do nothing\n        } else if( (!dyn_right) && IdenticalZero(right.value_))\n        {   // dynamic *= 0, so remove from tape\n            tape_id_ = 0;\n        } else if( (!dyn_left) && IdenticalOne(left))\n        {   // 1 *= dynamic\n            make_dynamic(right.tape_id_, right.taddr_);\n        } else if( (!dyn_left) && IdenticalZero(left))\n        {   // 0 *= dynamic, so do nothing\n        } else\n        {\n            addr_t arg0 = taddr_;\n            addr_t arg1 = right.taddr_;\n            if( ! dyn_left )\n            arg0 = tape->Rec_.put_con_par(left);\n            if( ! dyn_right )\n            arg1 = tape->Rec_.put_con_par(right.value_);\n            //\n            // parameters with a dynamic parameter results\n            taddr_ = tape->Rec_.put_dyn_par(\n                value_, local::mul_dyn, arg0, arg1\n            );\n            tape_id_ = tape_id;\n            ad_type_ = dynamic_enum;\n        }\n    }\n    return *this;\n}\n\nCPPAD_FOLD_ASSIGNMENT_OPERATOR(*=)\n\n} // END CppAD namespace\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/near_equal_ext.hpp",
    "content": "# ifndef CPPAD_CORE_NEAR_EQUAL_EXT_HPP\n# define CPPAD_CORE_NEAR_EQUAL_EXT_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin near_equal_ext}\n\nCompare AD and Base Objects for Nearly Equal\n############################################\n\nSyntax\n******\n| *b* = ``NearEqual`` ( *x* , *y* , *r* , *a* )\n\nPurpose\n*******\nThe routine :ref:`NearEqual-name` determines if two objects of\nthe same type are nearly.\nThis routine is extended to the case where one object can have type\n*Type* while the other can have type\n``AD`` < *Type* > or\n``AD< std::complex<`` *Type* > > .\n\nx\n*\nThe arguments *x*\nhas one of the following possible prototypes:\n\n| |tab| ``const`` *Type* & *x*\n| |tab| ``const AD`` < *Type* >                 & *x*\n| |tab| ``const AD< std::complex<`` *Type* > > & *x*\n\ny\n*\nThe arguments *y*\nhas one of the following possible prototypes:\n\n| |tab| ``const`` *Type* & *y*\n| |tab| ``const AD`` < *Type* >                 & *y*\n| |tab| ``const AD< std::complex<`` *Type* > > & *x*\n\nr\n*\nThe relative error criteria *r* has prototype\n\n    ``const`` *Type* & *r*\n\nIt must be greater than or equal to zero.\nThe relative error condition is defined as:\n\n.. math::\n\n    \\frac{ | x - y | } { |x| + |y| } \\leq r\n\na\n*\nThe absolute error criteria *a* has prototype\n\n    ``const`` *Type* & *a*\n\nIt must be greater than or equal to zero.\nThe absolute error condition is defined as:\n\n.. math::\n\n    | x - y | \\leq a\n\nb\n*\nThe return value *b* has prototype\n\n    ``bool`` *b*\n\nIf either *x* or *y* is infinite or not a number,\nthe return value is false.\nOtherwise, if either the relative or absolute error\ncondition (defined above) is satisfied, the return value is true.\nOtherwise, the return value is false.\n\nType\n****\nThe type *Type* must be a\n:ref:`NumericType-name` .\nThe routine :ref:`CheckNumericType-name` will generate\nan error message if this is not the case.\nIf *a* and *b* have type *Type* ,\nthe following operation must be defined\n\n.. list-table::\n    :widths: auto\n\n    * - **Operation**\n      - **Description**\n    * - *a* <= *b*\n      - less that or equal operator (returns a ``bool`` object)\n\nOperation Sequence\n******************\nThe result of this operation is not an\n:ref:`glossary@AD of Base` object.\nThus it will not be recorded as part of an\nAD of *Base*\n:ref:`operation sequence<glossary@Operation@Sequence>` .\n\nExample\n*******\n{xrst_toc_hidden\n    example/general/near_equal_ext.cpp\n}\nThe file :ref:`near_equal_ext.cpp-name` contains an example\nand test of this extension of :ref:`NearEqual-name` .\nIt return true if it succeeds and false otherwise.\n\n{xrst_end near_equal_ext}\n\n*/\n// BEGIN CppAD namespace\nnamespace CppAD {\n// ------------------------------------------------------------------------\n\n// fold into base type and then use <cppad/near_equal.hpp>\ntemplate <class Base>\nCPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION\nbool NearEqual(\nconst AD<Base> &x, const AD<Base> &y, const Base &r, const Base &a)\n{   return NearEqual(x.value_, y.value_, r, a);\n}\n\ntemplate <class Base>\nCPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION\nbool NearEqual(\nconst Base &x, const AD<Base> &y, const Base &r, const Base &a)\n{   return NearEqual(x, y.value_, r, a);\n}\n\ntemplate <class Base>\nCPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION\nbool NearEqual(\nconst AD<Base> &x, const Base &y, const Base &r, const Base &a)\n{   return NearEqual(x.value_, y, r, a);\n}\n\n// fold into AD type and then use cases above\ntemplate <class Base>\nCPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION\nbool NearEqual(\n    const VecAD_reference<Base> &x, const VecAD_reference<Base> &y,\n    const Base &r, const Base &a)\n{   return NearEqual(x.ADBase(), y.ADBase(), r, a);\n}\ntemplate <class Base>\nCPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION\nbool NearEqual(const VecAD_reference<Base> &x, const AD<Base> &y,\n    const Base &r, const Base &a)\n{   return NearEqual(x.ADBase(), y, r, a);\n}\ntemplate <class Base>\nCPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION\nbool NearEqual(const VecAD_reference<Base> &x, const Base &y,\n    const Base &r, const Base &a)\n{   return NearEqual(x.ADBase(), y, r, a);\n}\ntemplate <class Base>\nCPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION\nbool NearEqual(const AD<Base> &x, const VecAD_reference<Base> &y,\n    const Base &r, const Base &a)\n{   return NearEqual(x, y.ADBase(), r, a);\n}\ntemplate <class Base>\nCPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION\nbool NearEqual(const Base &x, const VecAD_reference<Base> &y,\n    const Base &r, const Base &a)\n{   return NearEqual(x, y.ADBase(), r, a);\n}\n\n} // END CppAD namespace\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/new_dynamic.hpp",
    "content": "# ifndef CPPAD_CORE_NEW_DYNAMIC_HPP\n# define CPPAD_CORE_NEW_DYNAMIC_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin new_dynamic}\n\nChange the Dynamic Parameters\n#############################\n\nSyntax\n******\n| *f* . ``new_dynamic`` ( *dynamic* )\n\nPurpose\n*******\nOften one is only interested in computing derivatives with respect\nto a subset of arguments to a function.\nIn this case, it is easier to make all the arguments to the function\n:ref:`independent variables<glossary@Tape@Independent Variable>` .\nIt is more efficient,\nwill use less memory and be faster,\nif the only the argument were are computing derivatives with respect to\nare independent variables and the other arguments are\n:ref:`glossary@Parameter@Dynamic` parameters.\nThe ``new_dynamic`` method is used to change the value\nof the dynamic parameters in *f* .\n\nf\n*\nThe object *f* has prototype\n\n    ``ADFun`` < *Base* > *f*\n\nNote that the :ref:`ADFun-name` object *f* is not ``const`` .\n\ndynamic\n*******\nThis argument has prototype\n\n    ``const`` *BaseVector* & *dynamic*\n\n(see *BaseVector* below).\nIt specifies a new value for the independent\n:ref:`glossary@Parameter@Dynamic` parameters.\nIt size must be the same as the size of the independent\n:ref:`Independent@dynamic` parameter vector\nin the call to ``Independent`` that started\nthe recording for *f* ; see\n:ref:`fun_property@size_dyn_ind` .\n\nBaseVector\n**********\nThe type *BaseVector* must be a :ref:`SimpleVector-name` class with\n:ref:`elements of type<SimpleVector@Elements of Specified Type>`\n*Base* .\n\nTaylor Coefficients\n*******************\nThe Taylor coefficients computed by previous calls to\n:ref:`f.Forward<Forward-name>` are lost after this operation; including the\norder zero coefficients (because they may depend on the dynamic parameters).\nIn order words;\n:ref:`f.size_order<size_order-name>` returns zero directly after\n*f* . ``new_dynamic`` is called.\n{xrst_toc_hidden\n    example/general/new_dynamic.cpp\n}\nExample\n*******\nThe file :ref:`new_dynamic.cpp-name`\ncontains an example and test of this operation.\n\n{xrst_end new_dynamic}\n*/\n# include <cppad/local/sweep/dynamic.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\n\\file new_dynamic.hpp\nUser interface to ADFun dynamic_parameter member function.\n*/\n\n/*!\nChange the dynamic parameters in this ADFun object\n\n\\param dynamic\nis the vector of new values for the dynamic parameters.\n*/\ntemplate <class Base, class RecBase>\ntemplate <class BaseVector>\nvoid ADFun<Base,RecBase>::new_dynamic(const BaseVector& dynamic)\n{   using local::pod_vector;\n    CPPAD_ASSERT_KNOWN(\n        size_t( dynamic.size() ) == play_.n_dyn_independent() ,\n        \"f.new_dynamic: dynamic.size() different from corresponding \"\n        \"call to Independent\"\n    );\n    // check BaseVector is Simple Vector class with Base elements\n    CheckSimpleVector<Base, BaseVector>();\n\n    // retrieve player information about the dynamic parameters\n    local::pod_vector_maybe<Base>&     par_all( play_.par_all() );\n    const pod_vector<bool>&            par_is_dyn ( play_.par_is_dyn()  );\n    const pod_vector<local::opcode_t>& dyn_par_op ( play_.dyn_par_op()  );\n    const pod_vector<addr_t>&          dyn_par_arg( play_.dyn_par_arg() );\n    const pod_vector<addr_t>&     dyn2par_index ( play_.dyn2par_index() );\n\n    // set the dependent dynamic parameters\n    RecBase not_used_rec_base(0.0);\n    local::sweep::dynamic(\n        par_all             ,\n        dynamic             ,\n        par_is_dyn          ,\n        dyn2par_index       ,\n        dyn_par_op          ,\n        dyn_par_arg         ,\n        not_used_rec_base\n    );\n\n    // the existing Taylor coefficients are no longer valid\n    num_order_taylor_ = 0;\n\n    return;\n}\n\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/num_skip.hpp",
    "content": "# ifndef CPPAD_CORE_NUM_SKIP_HPP\n# define CPPAD_CORE_NUM_SKIP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin number_skip}\n\nNumber of Variables that Can be Skipped\n#######################################\n\nSyntax\n******\n| *n* = *f* . ``number_skip`` ()\n\nSee Also\n========\n:ref:`fun_property-name`\n\nPurpose\n*******\nThe :ref:`conditional expressions<CondExp-name>` use either the\n:ref:`if_true<CondExp-name>` or :ref:`if_false<CondExp-name>` .\nHence, some terms only need to be evaluated\ndepending on the value of the comparison in the conditional expression.\nThe :ref:`optimize-name` option is capable of detecting some of these\ncase and determining variables that can be skipped.\nThis routine returns the number such variables.\n\nn\n*\nThe return value *n* has type ``size_t``\nis the number of variables that the optimizer has determined can be skipped\n(given the independent variable values specified by the previous call to\n:ref:`f.Forward<Forward-name>` for order zero).\n\nf\n*\nThe object *f* has prototype\n\n    ``ADFun`` < *Base* > *f*\n\n{xrst_toc_hidden\n    example/general/number_skip.cpp\n}\nExample\n*******\nThe file :ref:`number_skip.cpp-name`\ncontains an example and test of this function.\n\n{xrst_end number_skip}\n-----------------------------------------------------------------------------\n*/\n\n# include <cppad/local/play/atom_op_info.hpp>\n\n// BEGIN CppAD namespace\nnamespace CppAD {\n\n// This routine is not const because it runs through the operations sequence\n// 2DO: compute this value during zero order forward operations.\ntemplate <class Base, class RecBase>\nsize_t ADFun<Base,RecBase>::number_skip(void)\n{   // must pass through operation sequence to map operations to variables\n\n    // information defined by atomic forward\n    size_t atom_index=0, atom_old=0, atom_m=0, atom_n=0;\n\n    // number of variables skipped\n    size_t num_var_skip = 0;\n\n    // start playback\n    local::play::const_sequential_iterator itr = play_.begin();\n    local::op_code_var op;\n    size_t        i_var;\n    const addr_t* arg;\n    itr.op_info(op, arg, i_var);\n    CPPAD_ASSERT_UNKNOWN(op == local::BeginOp)\n    while(op != local::EndOp)\n    {   // next op\n        (++itr).op_info(op, arg, i_var);\n        //\n        if( op == local::AFunOp )\n        {   // skip only appears at front or back AFunOp of atomic function call\n            bool skip_call = cskip_op_[ itr.op_index() ];\n            local::play::atom_op_info<Base>(\n                op, arg, atom_index, atom_old, atom_m, atom_n\n            );\n            CPPAD_ASSERT_UNKNOWN( NumRes(op) == 0 );\n            size_t num_op = atom_m + atom_n + 1;\n            for(size_t i = 0; i < num_op; i++)\n            {   CPPAD_ASSERT_UNKNOWN(\n                    op != local::CSkipOp && op != local::CSumOp\n                );\n                (++itr).op_info(op, arg, i_var);\n                if( skip_call )\n                    num_var_skip += NumRes(op);\n            }\n            CPPAD_ASSERT_UNKNOWN( op == local::AFunOp );\n        }\n        else\n        {   if( cskip_op_[ itr.op_index() ] )\n                num_var_skip += NumRes(op);\n            //\n            if( (op == local::CSkipOp) || (op == local::CSumOp) )\n                itr.correct_before_increment();\n        }\n    }\n    return num_var_skip;\n}\n\n} // END CppAD namespace\n\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/numeric_limits.hpp",
    "content": "# ifndef CPPAD_CORE_NUMERIC_LIMITS_HPP\n# define CPPAD_CORE_NUMERIC_LIMITS_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n------------------------------------------------------------------------------\n{xrst_begin numeric_limits}\n{xrst_spell\n    eps\n    isnan\n}\n\nNumeric Limits For an AD and Base Types\n#######################################\n\nSyntax\n******\n| *eps* = ``numeric_limits`` < *Float* >:: ``epsilon`` ()\n| *min* = ``numeric_limits`` < *Float* >:: ``min`` ()\n| *max* = ``numeric_limits`` < *Float* >:: ``max`` ()\n| *nan* = ``numeric_limits`` < *Float* >:: ``quiet_NaN`` ()\n| *inf* = ``numeric_limits`` < *Float* >:: ``infinity`` ()\n| ``numeric_limits`` < *Float* >:: ``digits10``\n| ``numeric_limits`` < *Float* >:: ``max_digits10``\n\nCppAD::numeric_limits\n*********************\nThe functions above and have the prototype\n\n    ``static`` *Float* ``CppAD::numeric_limits<`` *Float* >:: *fun* ( *void* )\n\nwhere *fun* is\n``epsilon`` , ``min`` , ``max`` , ``quiet_NaN`` , and ``infinity`` .\n\nThe values ``digits10`` and ``max_digits10`` are\nmember variable and not a functions.\n\nstd::numeric_limits\n*******************\nCppAD does not use a specialization of ``std::numeric_limits``\nbecause this would be to restrictive.\nThe C++ standard specifies that Non-fundamental standard\ntypes, such as\n:ref:`std::complex\\<double><base_complex.hpp-name>`\nshall not have specializations\nof ``std::numeric_limits`` ; see Section 18.2 of\nISO/IEC 14882:1998(E).\nIn addition, since C++11, a only literal types can have a specialization\nof ``std::numeric_limits`` .\n\nFloat\n*****\nThese functions are defined for all ``AD`` < *Base* > ,\nand for all corresponding *Base* types;\nsee *Base* type :ref:`base_limits-name` .\n\nepsilon\n*******\nThe result *eps* is equal to machine epsilon and has prototype\n\n    *Float* *eps*\n\nThe file :ref:`num_limits.cpp-name`\ntests the value *eps* by checking that the following are true\n\n| |tab| 1 != 1 + *eps*\n| |tab| 1 == 1 + *eps*  / 2\n\nwhere all the values, and calculations, are done with the precision\ncorresponding to *Float* .\n\nmin\n***\nThe result *min* is equal to\nthe minimum positive normalized value and has prototype\n\n    *Float* *min*\n\nThe file :ref:`num_limits.cpp-name`\ntests the value *min* by checking that the following are true\n\n| |tab| ``abs`` ( (( *min* / 100) * 100) / *min* ``- 1`` ) > 3 * *eps*\n| |tab| ``abs`` ( (( *min* * 100) / 100) / *min* ``- 1`` ) < 3 * *eps*\n\nwhere all the values, and calculations, are done with the precision\ncorresponding to *Float* .\n\nmax\n***\nThe result *max* is equal to\nthe maximum finite value and has prototype\n\n    *Float* *max*\n\nThe file :ref:`num_limits.cpp-name`\ntests the value *max* by checking that the following are true\n\n| |tab| ``abs`` ( (( *max* * 100) / 100) / *max* ``- 1`` ) > 3 * *eps*\n| |tab| ``abs`` ( (( *max* / 100) * 100) / *max* ``- 1`` ) < 3 * *eps*\n\nwhere all the values, and calculations, are done with the precision\ncorresponding to *Float* .\n\nquiet_NaN\n*********\nThe result *nan* is not a number and has prototype\n\n    *Float* *nan*\n\nThe file :ref:`num_limits.cpp-name`\ntests the value *nan* by checking that the following is true\n\n    *nan* != *nan*\n\ninfinity\n********\nThe result *inf* is equal to the\npositive infinite value and has prototype\n\n    *Float* *inf*\n\nThe file :ref:`num_limits.cpp-name`\ntests the value *inf* by checking that the following are true\n\n| |tab| *inf* + 100 == *inf*\n| |tab| ``isnan`` ( *inf* ``-`` *inf* )\n\ndigits10\n********\nThe member variable ``digits10`` has prototype\n\n    ``static const int numeric_limits`` < *Float* >:: ``digits10``\n\nIt is the number of decimal digits that can be represented by a\n*Float* value.  A number with this many decimal digits can be\nconverted to *Float* and back to a string,\nwithout change due to rounding or overflow.\n\nmax_digits10\n************\nThe member variable ``max_digits10`` has prototype\n\n    ``static const int numeric_limits`` < *Float* >:: ``max_digits10``\n\nis the number of decimal digits that are necessary to uniquely represent\nall distinct values of the type *Float* .\nFor example, the number of digits necessary to convert to text and back\nand get the exact same result.\n\nExample\n*******\n{xrst_toc_hidden\n    example/general/num_limits.cpp\n}\nThe file\n:ref:`num_limits.cpp-name`\ncontains an example and test of these functions.\n\n{xrst_end numeric_limits}\n------------------------------------------------------------------------------\n*/\n# include <iostream>\n\n# include <cppad/configure.hpp>\n# include <cppad/local/define.hpp>\n# include <cppad/core/cppad_assert.hpp>\n# include <cppad/local/declare_ad.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\n\\file numeric_limits.hpp\nFile that defines CppAD numeric_limits for AD types\n*/\n\n/// All these defaults correspond to errors\ntemplate <class Float>\nclass numeric_limits {\npublic:\n    /// machine epsilon\n    static Float epsilon(void)\n    {   CPPAD_ASSERT_KNOWN(\n        false,\n        \"numeric_limits<Float>::epsilon() is not specialized for this Float\"\n        );\n        return Float(0);\n    }\n    /// minimum positive normalized value\n    static Float min(void)\n    {   CPPAD_ASSERT_KNOWN(\n        false,\n        \"numeric_limits<Float>::min() is not specialized for this Float\"\n        );\n        return Float(0);\n    }\n    /// maximum finite value\n    static Float max(void)\n    {   CPPAD_ASSERT_KNOWN(\n        false,\n        \"numeric_limits<Float>::max() is not specialized for this Float\"\n        );\n        return Float(0);\n    }\n    /// not a number\n    static Float quiet_NaN(void)\n    {   CPPAD_ASSERT_KNOWN(\n        false,\n        \"numeric_limits<Float>::quiet_NaN() is not specialized for this Float\"\n        );\n        return Float(0);\n    }\n    /// positive infinite value\n    static Float infinity(void)\n    {   CPPAD_ASSERT_KNOWN(\n        false,\n        \"numeric_limits<Float>::infinity() is not specialized for this Float\"\n        );\n        return Float(0);\n    }\n    /// number of decimal digits\n    static const int digits10 = -1;\n};\n\n/// Partial specialization that defines limits for for all AD types\ntemplate <class Base>\nclass numeric_limits< AD<Base> > {\npublic:\n    /// machine epsilon\n    static AD<Base> epsilon(void)\n    {   return AD<Base>( numeric_limits<Base>::epsilon() ); }\n    /// minimum positive normalized value\n    static AD<Base> min(void)\n    {   return AD<Base>( numeric_limits<Base>::min() ); }\n    /// maximum finite value\n    static AD<Base> max(void)\n    {   return AD<Base>( numeric_limits<Base>::max() ); }\n    /// not a number\n    static AD<Base> quiet_NaN(void)\n    {   return AD<Base>( numeric_limits<Base>::quiet_NaN() ); }\n    /// positive infinite value\n    static AD<Base> infinity(void)\n    {   return AD<Base>( numeric_limits<Base>::infinity() ); }\n    /// number of decimal digits\n    static const int digits10     = numeric_limits<Base>::digits10;\n    static const int max_digits10 = numeric_limits<Base>::max_digits10;\n};\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/omp_max_thread.hpp",
    "content": "# ifndef CPPAD_CORE_OMP_MAX_THREAD_HPP\n# define CPPAD_CORE_OMP_MAX_THREAD_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin omp_max_thread app}\n{xrst_spell\n    mp\n}\n\nOpenMP Parallel Setup\n#####################\n\nDeprecated 2011-06-23\n*********************\nUse :ref:`thread_alloc::parallel_setup<ta_parallel_setup-name>`\nto set the number of threads.\n\nSyntax\n******\n| ``AD`` < *Base* >:: ``omp_max_thread`` ( *number* )\n\nPurpose\n*******\nBy default, for each ``AD`` < *Base* > class there is only one\ntape that records :ref:`glossary@AD of Base` operations.\nThis tape is a global variable and hence it cannot be used\nby multiple OpenMP threads at the same time.\nThe ``omp_max_thread`` function is used to set the\nmaximum number of OpenMP threads that can be active.\nIn this case, there is a different tape corresponding to each\n``AD`` < *Base* > class and thread pair.\n\nnumber\n******\nThe argument *number* has prototype\n\n    ``size_t`` *number*\n\nIt must be greater than zero and specifies the maximum number of\nOpenMp threads that will be active at one time.\n\nIndependent\n***********\nEach call to :ref:`Independent(x)<Independent-name>`\ncreates a new :ref:`glossary@Tape@Active` tape.\nAll of the operations with the corresponding variables\nmust be preformed by the same OpenMP thread.\nThis includes the corresponding call to\n:ref:`f.Dependent(x,y)<Dependent-name>` or the\n:ref:`ADFun f(x, y)<fun_construct@Sequence Constructor>`\nduring which the tape stops recording and the variables\nbecome parameters.\n\nRestriction\n***********\nNo tapes can be\n:ref:`glossary@Tape@Active` when this function is called.\n\n{xrst_end omp_max_thread}\n-----------------------------------------------------------------------------\n*/\n\n// BEGIN CppAD namespace\nnamespace CppAD {\n\ntemplate <class Base>\nvoid AD<Base>::omp_max_thread(size_t number)\n{\n# ifdef _OPENMP\n    thread_alloc::parallel_setup(\n        number, omp_alloc::in_parallel, omp_alloc::get_thread_num\n    );\n# else\n    CPPAD_ASSERT_KNOWN(\n        number == 1,\n        \"omp_max_thread: number > 1 and _OPENMP is not defined\"\n    );\n# endif\n    parallel_ad<Base>();\n}\n\n} // END CppAD namespace\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/opt_val_hes.hpp",
    "content": "# ifndef CPPAD_CORE_OPT_VAL_HES_HPP\n# define CPPAD_CORE_OPT_VAL_HES_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin opt_val_hes app}\n{xrst_spell\n    signdet\n    sy\n    yy\n}\n\nJacobian and Hessian of Optimal Values\n######################################\n\nSyntax\n******\n| *signdet* = ``opt_val_hes`` ( *x* , *y* , *fun* , *jac* , *hes* )\n\nSee Also\n********\n:ref:`BenderQuad-name`\n\nReference\n*********\nAlgorithmic differentiation of implicit functions and optimal values,\nBradley M. Bell and James V. Burke, Advances in Automatic Differentiation,\n2008, Springer.\n\nPurpose\n*******\nWe are given a function\n:math:`S : \\B{R}^n \\times \\B{R}^m \\rightarrow \\B{R}^\\ell`\nand we define :math:`F : \\B{R}^n \\times \\B{R}^m \\rightarrow \\B{R}`\nand :math:`V : \\B{R}^n \\rightarrow \\B{R}` by\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        F(x, y) & = & \\sum_{k=0}^{\\ell-1} S_k ( x , y)\n        \\\\\n        V(x)    & = & F [ x , Y(x) ]\n        \\\\\n        0       & = & \\partial_y F [x , Y(x) ]\n    \\end{eqnarray}\n\nWe wish to compute the Jacobian\nand possibly also the Hessian, of :math:`V (x)`.\n\nBaseVector\n**********\nThe type *BaseVector* must be a\n:ref:`SimpleVector-name` class.\nWe use *Base* to refer to the type of the elements of\n*BaseVector* ; i.e.,\n\n    *BaseVector* :: ``value_type``\n\nx\n*\nThe argument *x* has prototype\n\n    ``const`` *BaseVector* & *x*\n\nand its size must be equal to *n* .\nIt specifies the point at which we evaluating\nthe Jacobian :math:`V^{(1)} (x)`\n(and possibly the Hessian :math:`V^{(2)} (x)`).\n\ny\n*\nThe argument *y* has prototype\n\n    ``const`` *BaseVector* & *y*\n\nand its size must be equal to *m* .\nIt must be equal to :math:`Y(x)`; i.e.,\nit must solve the implicit equation\n\n.. math::\n\n    0 = \\partial_y F ( x , y)\n\nFun\n***\nThe argument *fun* is an object of type *Fun*\nwhich must support the member functions listed below.\nCppAD will may be recording operations of the type ``AD`` < *Base* >\nwhen these member functions are called.\nThese member functions must not stop such a recording; e.g.,\nthey must not call :ref:`AD\\<Base>::abort_recording<abort_recording-name>` .\n\nFun::ad_vector\n==============\nThe type *Fun* :: ``ad_vector`` must be a\n:ref:`SimpleVector-name` class with elements of type ``AD`` < *Base* > ; i.e.\n\n    *Fun* :: ``ad_vector::value_type``\n\nis equal to ``AD`` < *Base* > .\n\nfun.ell\n=======\nThe type *Fun* must support the syntax\n\n    *ell* = *fun* . ``ell`` ()\n\nwhere *ell* has prototype\n\n    ``size_t`` *ell*\n\nand is the value of :math:`\\ell`; i.e.,\nthe number of terms in the summation.\n\nOne can choose *ell* equal to one, and have\n:math:`S(x,y)` the same as :math:`F(x, y)`.\nEach of the functions :math:`S_k (x , y)`,\n(in the summation defining :math:`F(x, y)`)\nis differentiated separately using AD.\nFor very large problems, breaking :math:`F(x, y)` into the sum\nof separate simpler functions may reduce the amount of memory necessary for\nalgorithmic differentiation and there by speed up the process.\n\nfun.s\n=====\nThe type *Fun* must support the syntax\n\n    *s_k* = *fun* . ``s`` ( *k* , *x* , *y* )\n\nThe *fun* . ``s`` argument *k* has prototype\n\n    ``size_t`` *k*\n\nand is between zero and *ell* ``- 1`` .\nThe argument *x* to *fun* . ``s`` has prototype\n\n    ``const`` *Fun* :: ``ad_vector&`` *x*\n\nand its size must be equal to *n* .\nThe argument *y* to *fun* . ``s`` has prototype\n\n    ``const`` *Fun* :: ``ad_vector&`` *y*\n\nand its size must be equal to *m* .\nThe *fun* . ``s`` result *s_k* has prototype\n\n    ``AD`` < *Base* > *s_k*\n\nand its value must be given by :math:`s_k = S_k ( x , y )`.\n\nfun.sy\n======\nThe type *Fun* must support the syntax\n\n    *sy_k* = *fun* . ``sy`` ( *k* , *x* , *y* )\n\nThe  argument *k* to *fun* . ``sy`` has prototype\n\n    ``size_t`` *k*\n\nThe  argument *x* to *fun* . ``sy`` has prototype\n\n    ``const`` *Fun* :: ``ad_vector&`` *x*\n\nand its size must be equal to *n* .\nThe  argument *y* to *fun* . ``sy`` has prototype\n\n    ``const`` *Fun* :: ``ad_vector&`` *y*\n\nand its size must be equal to *m* .\nThe *fun* . ``sy`` result *sy_k* has prototype\n\n    *Fun* :: ``ad_vector`` *sy_k*\n\nits size must be equal to *m* ,\nand its value must be given by :math:`sy_k = \\partial_y S_k ( x , y )`.\n\njac\n***\nThe argument *jac* has prototype\n\n    *BaseVector* & *jac*\n\nand has size *n* or zero.\nThe input values of its elements do not matter.\nIf it has size zero, it is not affected. Otherwise, on output\nit contains the Jacobian of :math:`V (x)`; i.e.,\nfor :math:`j = 0 , \\ldots , n-1`,\n\n.. math::\n\n    jac[ j ] = V^{(1)} (x)_j\n\nwhere *x* is the first argument to ``opt_val_hes`` .\n\nhes\n***\nThe argument *hes* has prototype\n\n    *BaseVector* & *hes*\n\nand has size *n* * *n* or zero.\nThe input values of its elements do not matter.\nIf it has size zero, it is not affected. Otherwise, on output\nit contains the Hessian of :math:`V (x)`; i.e.,\nfor :math:`i = 0 , \\ldots , n-1`, and\n:math:`j = 0 , \\ldots , n-1`,\n\n.. math::\n\n    hes[ i * n + j ] = V^{(2)} (x)_{i,j}\n\nsigndet\n*******\nIf *hes* has size zero, *signdet* is not defined.\nOtherwise\nthe return value *signdet* is the sign of the determinant for\n:math:`\\partial_{yy}^2 F(x , y)`.\nIf it is zero, then the matrix is singular and\nthe Hessian is not computed ( *hes* is not changed).\n\nExample\n*******\n{xrst_toc_hidden\n    example/general/opt_val_hes.cpp\n}\nThe file\n:ref:`opt_val_hes.cpp-name`\ncontains an example and test of this operation.\n\n{xrst_end opt_val_hes}\n-----------------------------------------------------------------------------\n*/\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\n\\file opt_val_hes.hpp\n\\brief Computing Jabobians and Hessians of Optimal Values\n*/\n\n/*!\nComputing Jabobians and Hessians of Optimal Values\n\nWe are given a function\n\\f$ S : {\\rm R}^n \\times {\\rm R}^m \\rightarrow {\\rm R}^\\ell \\f$\nand we define \\f$ F : {\\rm R}^n \\times {\\rm R}^m \\rightarrow {\\rm R} \\f$\nand \\f$ V : {\\rm R}^n \\rightarrow {\\rm R}  \\f$ by\n\\f[\n\\begin{array}{rcl}\n    F(x, y) & = & \\sum_{k=0}^{\\ell-1} S_k ( x , y)\n    \\\\\n    V(x)    & = & F [ x , Y(x) ]\n    \\\\\n    0       & = & \\partial_y F [x , Y(x) ]\n\\end{array}\n\\f]\nWe wish to compute the Jacobian\nand possibly also the Hessian, of \\f$ V (x) \\f$.\n\n\\tparam BaseVector\nThe type BaseVector must be a SimpleVector class.\nWe use Base to refer to the type of the elements of\n BaseVector; i.e.,\n<tt>BaseVector::value_type</tt>.\n\n\\param x\nis a vector with size n.\nIt specifies the point at which we evaluating\nthe Jacobian \\f$ V^{(1)} (x) \\f$\n(and possibly the Hessian \\f$ V^{(2)} (x) \\f$).\n\n\n\\param y\nis a vector with size m.\nIt must be equal to \\f$ Y(x) \\f$; i.e.,\nit must solve the implicit equation\n\\f[\n    0 = \\partial_y F ( x , y)\n\\f]\n\n\\param fun\nThe argument fun is an object of type Fun\nwhich must support the member functions listed below.\nCppAD will may be recording operations of the type  AD<Base>\nwhen these member functions are called.\nThese member functions must not stop such a recording; e.g.,\nthey must not call AD<Base>::abort_recording.\n\n\\par Fun::ad_vector</tt>\nThe type <tt>Fun::ad_vector</tt> must be a\nSimpleVector class with elements of type  AD<Base>; i.e.\n<tt>Fun::ad_vector::value_type</tt>\nis equal to  AD<Base>.\n\n\\par fun.ell\nthe type Fun must support the syntax\n\\verbatim\n    ell = fun.ell()\n\\endverbatim\nwhere ell is a size_t value that is set to \\f$ \\ell \\f$; i.e.,\nthe number of terms in the summation.\n\n\\par fun.s\nThe type Fun must support the syntax\n\\verbatim\n    s_k = fun.s(k, x, y)\n\\endverbatim\nThe argument k has prototype <tt>size_t k</tt>.\nThe argument x has prototype <tt>const Fun::ad_vector& x</tt>\nand its size must be equal to n.\nThe argument y has prototype <tt>const Fun::ad_vector& y</tt>\nand its size must be equal to m.\nThe return value s_k has prototype AD<Base> s_k\nand its value must be given by \\f$ s_k = S_k ( x , y ) \\f$.\n\n\\par fun.sy\nThe type Fun must support the syntax\n\\verbatim\n    sy_k = fun.sy(k, x, y)\n\\endverbatim\nThe argument k has prototype <tt>size_t k</tt>.\nThe argument x has prototype <tt>const Fun::ad_vector& x</tt>\nand its size must be equal to n.\nThe argument y has prototype <tt>const Fun::ad_vector& y</tt>\nand its size must be equal to m.\nThe return value sy_k has prototype <tt>Fun::ad_vector& sy_k</tt>,\nits size is m\nand its value must be given by \\f$ sy_k = \\partial_y S_k ( x , y ) \\f$.\n\n\\param jac\nis a vector with size n or zero.\nThe input values of its elements do not matter.\nIf it has size zero, it is not affected. Otherwise, on output\nit contains the Jacobian of \\f$ V (x) \\f$; i.e.,\nfor \\f$ j = 0 , \\ldots , n-1 \\f$,\n\\f[\n    jac[ j ] = V^{(1)} (x)_j\n\\f] $$\nwhere x is the first argument to opt_val_hes.\n\n\\param hes\nis a vector with size <tt>n * n</tt> or zero.\nThe input values of its elements do not matter.\nIf it has size zero, it is not affected. Otherwise, on output\nit contains the Hessian of \\f$ V (x) \\f$; i.e.,\nfor \\f$ i = 0 , \\ldots , n-1 \\f$, and\n\\f$ j = 0 , \\ldots , n-1 \\f$,\n\\f[\n    hes[ i * n + j ] = V^{(2)} (x)_{i,j}\n\\f]\n\n\\return\nIf <tt>hes.size() == 0</tt>, the return value is not defined.\nOtherwise,\nthe return value is the sign of the determinant for\n\\f$ \\partial_{yy}^2 F(x , y) \\f$$.\nIf it is zero, then the matrix is singular and hes is not set\nto its specified value.\n*/\n\n\ntemplate <class BaseVector, class Fun>\nint opt_val_hes(\n    const BaseVector&   x     ,\n    const BaseVector&   y     ,\n    Fun                 fun   ,\n    BaseVector&         jac   ,\n    BaseVector&         hes   )\n{   // determine the base type\n    typedef typename BaseVector::value_type Base;\n\n    // check that BaseVector is a SimpleVector class with Base elements\n    CheckSimpleVector<Base, BaseVector>();\n\n    // determine the AD vector type\n    typedef typename Fun::ad_vector ad_vector;\n\n    // check that ad_vector is a SimpleVector class with AD<Base> elements\n    CheckSimpleVector< AD<Base> , ad_vector >();\n\n    // size of the x and y spaces\n    size_t n = size_t(x.size());\n    size_t m = size_t(y.size());\n\n    // number of terms in the summation\n    size_t ell = fun.ell();\n\n    // check size of return values\n    CPPAD_ASSERT_KNOWN(\n        size_t(jac.size()) == n || jac.size() == 0,\n        \"opt_val_hes: size of the vector jac is not equal to n or zero\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t(hes.size()) == n * n || hes.size() == 0,\n        \"opt_val_hes: size of the vector hes is not equal to n * n or zero\"\n    );\n\n    // some temporary indices\n    size_t i, j, k;\n\n    // AD version of S_k(x, y)\n    ad_vector s_k(1);\n\n    // ADFun version of S_k(x, y)\n    ADFun<Base> S_k;\n\n    // AD version of x\n    ad_vector a_x(n);\n\n    // AD version of y\n    ad_vector a_y(n);\n\n    if( jac.size() > 0  )\n    {   // this is the easy part, computing the V^{(1)} (x) which is equal\n        // to \\partial_x F (x, y) (see Theorem 2 of the reference).\n\n        // copy x and y to AD version\n        for(j = 0; j < n; j++)\n            a_x[j] = x[j];\n        for(j = 0; j < m; j++)\n            a_y[j] = y[j];\n\n        // initialize summation\n        for(j = 0; j < n; j++)\n            jac[j] = Base(0.);\n\n        // add in \\partial_x S_k (x, y)\n        for(k = 0; k < ell; k++)\n        {   // start recording\n            Independent(a_x);\n            // record\n            s_k[0] = fun.s(k, a_x, a_y);\n            // stop recording and store in S_k\n            S_k.Dependent(a_x, s_k);\n            // compute partial of S_k with respect to x\n            BaseVector jac_k = S_k.Jacobian(x);\n            // add \\partial_x S_k (x, y) to jac\n            for(j = 0; j < n; j++)\n                jac[j] += jac_k[j];\n        }\n    }\n    // check if we are done\n    if( hes.size() == 0 )\n        return 0;\n\n    /*\n    In this case, we need to compute the Hessian. Using Theorem 1 of the\n    reference:\n        Y^{(1)}(x) = - F_yy (x, y)^{-1} F_yx (x, y)\n    Using Theorem 2 of the reference:\n        V^{(2)}(x) = F_xx (x, y) + F_xy (x, y)  Y^{(1)}(x)\n    */\n    // Base and AD version of xy\n    BaseVector xy(n + m);\n    ad_vector a_xy(n + m);\n    for(j = 0; j < n; j++)\n        a_xy[j] = xy[j] = x[j];\n    for(j = 0; j < m; j++)\n        a_xy[n+j] = xy[n+j] = y[j];\n\n    // Initialization summation for Hessian of F\n    size_t nm_sq = (n + m) * (n + m);\n    BaseVector F_hes(nm_sq);\n    for(j = 0; j < nm_sq; j++)\n        F_hes[j] = Base(0.);\n    BaseVector hes_k(nm_sq);\n\n    // add in Hessian of S_k to hes\n    for(k = 0; k < ell; k++)\n    {   // start recording\n        Independent(a_xy);\n        // split out x\n        for(j = 0; j < n; j++)\n            a_x[j] = a_xy[j];\n        // split out y\n        for(j = 0; j < m; j++)\n            a_y[j] = a_xy[n+j];\n        // record\n        s_k[0] = fun.s(k, a_x, a_y);\n        // stop recording and store in S_k\n        S_k.Dependent(a_xy, s_k);\n        // when computing the Hessian it pays to optimize the tape\n        S_k.optimize();\n        // compute Hessian of S_k\n        hes_k = S_k.Hessian(xy, 0);\n        // add \\partial_x S_k (x, y) to jac\n        for(j = 0; j < nm_sq; j++)\n            F_hes[j] += hes_k[j];\n    }\n    // Extract F_yx\n    BaseVector F_yx(m * n);\n    for(i = 0; i < m; i++)\n    {   for(j = 0; j < n; j++)\n            F_yx[i * n + j] = F_hes[ (i+n)*(n+m) + j ];\n    }\n    // Extract F_yy\n    BaseVector F_yy(n * m);\n    for(i = 0; i < m; i++)\n    {   for(j = 0; j < m; j++)\n            F_yy[i * m + j] = F_hes[ (i+n)*(n+m) + j + n ];\n    }\n\n    // compute - Y^{(1)}(x) = F_yy (x, y)^{-1} F_yx (x, y)\n    BaseVector neg_Y_x(m * n);\n    Base logdet;\n    int signdet = CppAD::LuSolve(m, n, F_yy, F_yx, neg_Y_x, logdet);\n    if( signdet == 0 )\n        return signdet;\n\n    // compute hes = F_xx (x, y) + F_xy (x, y)  Y^{(1)}(x)\n    for(i = 0; i < n; i++)\n    {   for(j = 0; j < n; j++)\n        {   hes[i * n + j] = F_hes[ i*(n+m) + j ];\n            for(k = 0; k < m; k++)\n                hes[i*n+j] -= F_hes[i*(n+m) + k+n] * neg_Y_x[k*n+j];\n        }\n    }\n    return signdet;\n}\n\n} // END_CPPAD_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/optimize.hpp",
    "content": "# ifndef CPPAD_CORE_OPTIMIZE_HPP\n# define CPPAD_CORE_OPTIMIZE_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# define CPPAD_CORE_OPTIMIZE_PRINT_RESULT 0\n\n/*\n{xrst_begin optimize}\n{xrst_spell\n    onetape\n    substring\n}\n\nOptimize an ADFun Object Tape\n#############################\n\nSyntax\n******\n| *f* . ``optimize`` ()\n| *f* . ``optimize`` ( *options* )\n| *flag* = *f* . ``exceed_collision_limit`` ()\n\nPurpose\n*******\nThe operation sequence corresponding to an :ref:`ADFun-name` object can\nbe very large and involve many operations; see the\nsize functions in :ref:`fun_property-name` .\nThe *f* . ``optimize`` procedure reduces the number of operations,\nand thereby the time and the memory, required to\ncompute function and derivative values.\n\nf\n*\nThe object *f* has prototype\n\n    ``ADFun`` < *Base* > *f*\n\noptions\n*******\nThis argument has prototype\n\n    ``const std::string&`` *options*\n\nThe default for *options* is the empty string.\nIf it is present, it must consist of one or more of the options below\nseparated by a single space character.\n\nno_conditional_skip\n===================\nThe ``optimize`` function can create conditional skip operators\nto improve the speed of conditional expressions; see\n:ref:`CondExp@Optimize` .\nIf the sub-string ``no_conditional_skip`` appears in *options* ,\nconditional skip operations are not be generated.\nThis may make the optimize routine use significantly less memory\nand take less time to optimize *f* .\nIf conditional skip operations are generated,\nit may save a significant amount of time when\nusing *f* for :ref:`forward-name` or :ref:`reverse-name` mode calculations;\nsee :ref:`number_skip-name` .\n\nno_compare_op\n=============\nIf the sub-string ``no_compare_op`` appears in *options* ,\ncomparison operators will be removed from the optimized function.\nThese operators are necessary for the\n:ref:`compare_change-name` functions to be meaningful.\nOn the other hand, they are not necessary, and take extra time,\nwhen the compare_change functions are not used.\n\nno_print_for_op\n===============\nIf the sub-string ``no_compare_op`` appears in *options* ,\n:ref:`PrintFor-name` operations will be removed form the optimized function.\nThese operators are useful for reporting problems evaluating derivatives\nat independent variable values different from those used to record a function.\n\nno_cumulative_sum_op\n====================\nIf this sub-string appears,\nno cumulative sum operations will be generated during the optimization; see\n:ref:`optimize_cumulative_sum.cpp-name` .\n\ncollision_limit=value\n=====================\nIf this substring appears,\nwhere *value* is a sequence of decimal digits,\nthe optimizer's hash code collision limit will be set to *value* .\nWhen the collision limit is reached, the expressions with that hash code\nare removed and a new lists of expressions with that has code is started.\nThe larger *value* , the more identical expressions the optimizer\ncan recognize, but the slower the optimizer may run.\nThe default for *value* is ``10`` .\n\nval_graph\n=========\nIf the sub-string ``val_graph`` appears in *options* ,\nthe value graph optimizer is used.\nThis is a new (experimental) CppAD operation sequence optimizer.\n\n#. The val_graph optimizer has a much simpler implementation.\n#. It has better developer documentation\n#. It has examples and tests at the val_graph level.\n   This makes it easy to change the val_graph optimizer.\n#. The optimized tape has very similar speed to the old optimizer; i.e.,\n   when the :ref:`speed_main@Global Options@onetape` option is present.\n   For some of the :ref:`speed-name` test case\n   the val_graph optimized tape is significantly faster.\n#. The val_graph optimizer take much longer to run.\n   This is probably due to the conversion to and from a val_graph.\n\nno_conditional_skip\n-------------------\nIf the sub-string ``val_graph`` is present, the ``no_conditional_skip``\nsub-string must also appear.\n\ncollision_limit=value\n---------------------\nIf the sub-string ``val_graph`` is present, the ``collision_limit=value``\nsub-string must **not** appear.\nCurrently, there is no collision limit for the new optimizer.\n\nRe-Optimize\n***********\nBefore 2019-06-28, optimizing twice was not supported and would fail\nif cumulative sum operators were present after the first optimization.\nThis is now supported but it is not expected to have much benefit.\nIf you find a case where it does have a benefit, please inform the CppAD\ndevelopers of this.\n\nEfficiency\n**********\nIf a :ref:`zero order forward<forward_zero-name>` calculation is done during\nthe construction of *f* , it will require more memory\nand time than required after the optimization procedure.\nIn addition, it will need to be redone.\nFor this reason, it is more efficient to use\n\n| |tab| ``ADFun`` < *Base* > *f* ;\n| |tab| *f* . ``Dependent`` ( *x* , *y* );\n| |tab| *f* . ``optimize`` ();\n\ninstead of\n\n| |tab| ``ADFun`` < *Base* > *f* ( *x* , *y* )\n| |tab| *f* . ``optimize`` ();\n\nSee the discussion about\n:ref:`sequence constructors<fun_construct@Sequence Constructor>` .\n\nTaylor Coefficients\n*******************\nAny Taylor coefficients in the function object are lost; i.e.,\n:ref:`f.size_order()<size_order-name>` after the optimization is zero.\n(See the discussion about efficiency above.)\n\nSpeed Testing\n*************\nYou can run the CppAD :ref:`speed<speed_main-name>` tests and see\nthe corresponding changes in number of variables and execution time.\nNote that there is an interaction between using\n:ref:`speed_main@Global Options@optimize` and\n:ref:`speed_main@Global Options@onetape` .\nIf *onetape* is true and *optimize* is true,\nthe optimized tape will be reused many times.\nIf *onetape* is false and *optimize* is true,\nthe tape will be re-optimized for each test.\n\nAtomic Functions\n****************\nThere are some subtitle issue with optimized :ref:`atomic-name` functions\n:math:`v = g(u)`:\n\nrev_sparse_jac\n==============\nThe :ref:`atomic_two_rev_sparse_jac-name` function is be used to determine\nwhich components of *u* affect the dependent variables of *f* .\nFor each atomic operation, the current\n:ref:`atomic_two_option@atomic_sparsity` setting is used\nto determine if ``pack_sparsity_enum`` , ``bool_sparsity_enum`` ,\nor ``set_sparsity_enum`` is used to determine dependency relations\nbetween argument and result variables.\n\nnan\n===\nIf *u* [ *i* ] does not affect the value of\nthe dependent variables for *f* ,\nthe value of *u* [ *i* ] is set to :ref:`nan-name` .\n\nChecking Optimization\n*********************\nIf :ref:`Faq@Speed@NDEBUG` is not defined,\nand :ref:`f.size_order()<size_order-name>` is greater than zero,\na :ref:`forward_zero-name` calculation is done using the optimized version\nof *f* and the results are checked to see that they are\nthe same as before.\nIf they are not the same, the\n:ref:`ErrorHandler-name` is called with a known error message\nrelated to *f* . ``optimize`` () .\n\nexceed_collision_limit\n**********************\nIf the return value *flag* is true (false),\nthe previous call to *f* . ``optimize`` exceed the\n:ref:`collision_limit<optimize@options@collision_limit=value>` .\n\nExamples\n********\n{xrst_comment childtable without Example instead of Contents for header}\n{xrst_toc_hidden\n    example/optimize/optimize_twice.cpp\n    example/optimize/forward_active.cpp\n    example/optimize/reverse_active.cpp\n    example/optimize/compare_op.cpp\n    example/optimize/print_for.cpp\n    example/optimize/conditional_skip.cpp\n    example/optimize/nest_conditional.cpp\n    example/optimize/cumulative_sum.cpp\n}\n\n.. csv-table::\n    :widths: auto\n\n    optimize_twice.cpp,:ref:`optimize_twice.cpp-title`\n    optimize_forward_active.cpp,:ref:`optimize_forward_active.cpp-title`\n    optimize_reverse_active.cpp,:ref:`optimize_reverse_active.cpp-title`\n    optimize_compare_op.cpp,:ref:`optimize_compare_op.cpp-title`\n    optimize_print_for.cpp,:ref:`optimize_print_for.cpp-title`\n    optimize_conditional_skip.cpp,:ref:`optimize_conditional_skip.cpp-title`\n    optimize_nest_conditional.cpp,:ref:`optimize_nest_conditional.cpp-title`\n    optimize_cumulative_sum.cpp,:ref:`optimize_cumulative_sum.cpp-title`\n\n{xrst_end optimize}\n-----------------------------------------------------------------------------\n*/\n# include <cppad/local/optimize/optimize_run.hpp>\n/*!\n\\file optimize.hpp\nOptimize a player object operation sequence\n*/\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\nOptimize a player object operation sequence\n\nThe operation sequence for this object is replaced by one with fewer operations\nbut the same function and derivative values.\n\n\\tparam Base\nbase type for the operator; i.e., this operation was recorded\nusing AD<Base> and computations by this routine are done using type\n Base.\n\n\\param options\n\\li\nIf the sub-string \"no_conditional_skip\" appears,\nconditional skip operations will not be generated.\nThis may make the optimize routine use significantly less memory\nand take significantly less time.\n\\li\nIf the sub-string \"no_compare_op\" appears,\nthen comparison operators will be removed from the optimized tape.\nThese operators are necessary for the compare_change function to be\nbe meaningful in the resulting recording.\nOn the other hand, they are not necessary and take extra time\nwhen compare_change is not used.\n*/\ntemplate <class Base, class RecBase>\nvoid ADFun<Base,RecBase>::optimize(const std::string& options)\n{\n# if CPPAD_CORE_OPTIMIZE_PRINT_RESULT\n    // size of operation sequence before optimizatiton\n    size_t size_op_before = size_op();\n# endif\n\n    // number of independent variables\n    size_t n_ind_var = ind_taddr_.size();\n\n# ifndef NDEBUG\n    // n_ind_dyn, ind_dynamic\n    size_t n_ind_dyn = play_.n_dyn_independent();\n    CppAD::vector<Base> ind_dynamic(n_ind_dyn);\n    //\n    // n_dep_var, x, y, check, max_taylor, check_zero_order\n    size_t n_dep_var = dep_taddr_.size();\n    CppAD::vector<Base> x(n_ind_var), y(n_dep_var), check(n_dep_var);\n    Base max_taylor(0);\n    bool check_zero_order = num_order_taylor_ > 0;\n    if( check_zero_order )\n    {   //\n        // ind_dynamic\n        for(size_t j = 0; j < n_ind_dyn; ++j)\n        {   const addr_t par_ind = play_.dyn2par_index()[j];\n            ind_dynamic[j]       = play_.par_all()[par_ind];\n        }\n        //\n        // x\n        // zero order coefficients for independent vars\n        for(size_t j = 0; j < n_ind_var; j++)\n        {   CPPAD_ASSERT_UNKNOWN( play_.GetOp(j+1) == local::InvOp );\n            CPPAD_ASSERT_UNKNOWN( ind_taddr_[j]    == j+1   );\n            x[j] = taylor_[ ind_taddr_[j] * cap_order_taylor_ + 0];\n        }\n        // y\n        // zero order coefficients for dependent vars\n        for(size_t i = 0; i < n_dep_var; i++)\n        {   CPPAD_ASSERT_UNKNOWN( dep_taddr_[i] < num_var_tape_  );\n            y[i] = taylor_[ dep_taddr_[i] * cap_order_taylor_ + 0];\n        }\n        // max_taylor\n        // maximum zero order coefficient not counting BeginOp at beginning\n        // (which is corresponds to uninitialized memory).\n        for(size_t i = 1; i < num_var_tape_; i++)\n        {   if(  abs_geq(taylor_[i*cap_order_taylor_+0] , max_taylor) )\n                max_taylor = taylor_[i*cap_order_taylor_+0];\n        }\n    }\n# endif\n\n    //\n    // val_graph\n    bool val_graph = options.find(\"val_graph\") != std::string::npos;\n    //\n    if( val_graph )\n    {   val_optimize(options);\n        exceed_collision_limit_ = false;\n    }\n    else\n    {\n        // place to store the optimized version of the recording\n        local::recorder<Base> rec;\n\n        // create the optimized recording\n        size_t exceed = false;\n        switch( play_.address_type() )\n        {\n            case local::play::unsigned_short_enum:\n            exceed = local::optimize::optimize_run<unsigned short>(\n                options, n_ind_var, dep_taddr_, &play_, &rec\n            );\n            break;\n\n            case local::play::addr_t_enum:\n            exceed = local::optimize::optimize_run<addr_t>(\n                options, n_ind_var, dep_taddr_, &play_, &rec\n            );\n            break;\n\n            case local::play::size_t_enum:\n            exceed = local::optimize::optimize_run<size_t>(\n                options, n_ind_var, dep_taddr_, &play_, &rec\n            );\n            break;\n\n            default:\n            CPPAD_ASSERT_UNKNOWN(false);\n        }\n        exceed_collision_limit_ = exceed;\n\n        // now replace the recording\n        play_.get_recording(rec, n_ind_var);\n    }\n\n    // number of variables in the recording\n    num_var_tape_  = play_.num_var();\n\n    // set flag so this function knows it has been optimized\n    has_been_optimized_ = true;\n\n    // free memory allocated for sparse Jacobian calculation\n    // (the results are no longer valid)\n    for_jac_sparse_pack_.resize(0, 0);\n    for_jac_sparse_set_.resize(0,0);\n\n    // free old Taylor coefficient memory\n    taylor_.clear();\n    num_order_taylor_     = 0;\n    cap_order_taylor_     = 0;\n\n    // resize and initialize conditional skip vector\n    // (must use player size because it now has the recoreder information)\n    cskip_op_.resize( play_.num_var_op() );\n\n    // resize subgraph_info_\n    subgraph_info_.resize(\n        ind_taddr_.size(),    // n_ind\n        dep_taddr_.size(),    // n_dep\n        play_.num_var_op(),   // n_op\n        play_.num_var()       // n_var\n    );\n\n# ifndef NDEBUG\n    if( check_zero_order )\n    {   std::stringstream s;\n        //\n        // zero order forward calculation using new operation sequence\n        new_dynamic(ind_dynamic);\n        check = Forward(0, x, s);\n\n        // check results\n        Base eps99 = Base(99) * CppAD::numeric_limits<Base>::epsilon();\n        for(size_t i = 0; i < n_dep_var; i++)\n        if( ! abs_geq( eps99 * max_taylor , check[i] - y[i] ) )\n        {   std::string msg = \"Error during check of f.optimize().\";\n            msg += \"\\neps99 * max_taylor = \" + to_string(eps99 * max_taylor);\n            msg += \"\\ncheck[i] = \" + to_string(check[i]);\n            msg += \"\\ny[i]     = \" + to_string(y[i]);\n            CPPAD_ASSERT_KNOWN(\n                abs_geq( eps99 * max_taylor , check[i] - y[i] ) ,\n                msg.c_str()\n            );\n        }\n\n        // Erase memory that this calculation was done so NDEBUG gives\n        // same final state for this object (from users perspective)\n        num_order_taylor_     = 0;\n    }\n# endif\n# if CPPAD_CORE_OPTIMIZE_PRINT_RESULT\n    // size of operation sequence after optimizatiton\n    size_t size_op_after = size_op();\n    std::cout << \"optimize: size_op:  before = \" <<\n    size_op_before << \", after = \" << size_op_after << \"\\n\";\n# endif\n}\n\n} // END_CPPAD_NAMESPACE\n\n# undef CPPAD_CORE_OPTIMIZE_PRINT_RESULT\n# endif\n"
  },
  {
    "path": "include/cppad/core/ordered.hpp",
    "content": "# ifndef CPPAD_CORE_ORDERED_HPP\n# define CPPAD_CORE_ORDERED_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/local/define.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n\n/*!\n\\file ordered.hpp\nCheck and AD values ordering properties relative to zero.\n*/\n\n// GreaterThanZero ============================================================\n/*!\nCheck if an AD<Base> is greater than zero.\n\n\\param x\nvalue we are checking.\n\n\\return\nreturns true iff the x is greater than zero.\n*/\ntemplate <class Base>\nCPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION\nbool GreaterThanZero(const AD<Base> &x)\n{   return GreaterThanZero(x.value_); }\n// GreaterThanOrZero =========================================================\n/*!\nCheck if an AD<Base> is greater than or equal zero.\n\n\\param x\nvalue we are checking.\n\n\\return\nreturns true iff the x is greater than or equal zero.\n*/\ntemplate <class Base>\nCPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION\nbool GreaterThanOrZero(const AD<Base> &x)\n{   return GreaterThanOrZero(x.value_); }\n// LessThanZero ============================================================\n/*!\nCheck if an AD<Base> is less than zero.\n\n\\param x\nvalue we are checking.\n\n\\return\nreturns true iff the x is less than zero.\n*/\ntemplate <class Base>\nCPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION\nbool LessThanZero(const AD<Base> &x)\n{   return LessThanZero(x.value_); }\n// LessThanOrZero =========================================================\n/*!\nCheck if an AD<Base> is less than or equal zero.\n\n\\param x\nvalue we are checking.\n\n\\return\nreturns true iff the x is less than or equal zero.\n*/\ntemplate <class Base>\nCPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION\nbool LessThanOrZero(const AD<Base> &x)\n{   return LessThanOrZero(x.value_); }\n// abs_geq =========================================================\n/*!\nCheck if absolute value of one AD<Base> is greater or equal another.\n\n\\param x\nvalue we are checking if it is greater than or equal other.\n\n\\param y\nvalue we are checking if it is less than other.\n\n\\return\nreturns true iff the absolute value of x is greater than or equal\nabsolute value of y.\n*/\ntemplate <class Base>\nCPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION\nbool abs_geq(const AD<Base>& x, const AD<Base>& y)\n{   return abs_geq(x.value_, y.value_); }\n// ============================================================================\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/parallel_ad.hpp",
    "content": "# ifndef CPPAD_CORE_PARALLEL_AD_HPP\n# define CPPAD_CORE_PARALLEL_AD_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin parallel_ad}\n{xrst_spell\n    rosen\n    runge\n    teardown\n}\n\nEnable AD Calculations During Parallel Mode\n###########################################\n\nSyntax\n******\n| ``parallel_ad`` < *Base* >()\n\nPurpose\n*******\nThe function\n``parallel_ad`` < *Base* >()\nmust be called before any ``AD`` < *Base>* objects are used\nin :ref:`parallel<ta_in_parallel-name>` mode.\nIn addition, if this routine is called after one is done using\nparallel mode, it will free extra memory used to keep track of\nthe multiple ``AD`` < *Base* > tapes required for parallel execution.\n\nDiscussion\n**********\nBy default, for each ``AD`` < *Base* > class there is only one\ntape that records :ref:`glossary@AD of Base` operations.\nThis tape is a global variable and hence it cannot be used\nby multiple threads at the same time.\nThe :ref:`parallel_setup<ta_parallel_setup-name>` function informs CppAD of the\nmaximum number of threads that can be active in parallel mode.\nThis routine does extra setup\n(and teardown) for the particular *Base* type.\n\nCheckSimpleVector\n*****************\nThis routine has the side effect of calling ``CheckSimpleVector`` for\nsome of the possible\n:ref:`CheckSimpleVector@Scalar` and :ref:`CheckSimpleVector@Vector` cases.\nThe set of these cases may increase in the future and currently includes\nthe following:\n\n.. csv-table::\n    :header: Scalar, Vector\n\n    ``bool``          , ``CppAD::vectorBool``\n    ``size_t``        , ``CppAD::vector<size_t>``\n    *Base*            , *vector* < *Base* >\n    ``AD`` < *Base* > , *vector* ``AD`` < *Base* >\n\nWhere *vector* above is\n``CppAD::vector`` ,\n``std::vector`` , and\nthe :ref:`cppad_testvector-name` .\n\n\nExample\n*******\nThe files\n:ref:`openmp_get_started.cpp-name` ,\n:ref:`bthread_get_started.cpp-name` , and\n:ref:`pthread_get_started.cpp-name` ,\ncontain examples and tests that implement this function.\n\nRestriction\n***********\nThis routine cannot be called in parallel mode or while\nthere is a tape recording ``AD`` < *Base* > operations.\n\nOther Initialization\n********************\nIf the following routines have static memory and must be called once\nbefore being used in parallel mode:\n\n#. :ref:`CheckSimpleVector <CheckSimpleVector@Parallel Mode>`\n#. :ref:`thread_alloc, memory_leak <ta_parallel_setup-name>`\n#. :ref:`Rosen34 <Rosen34@Parallel Mode>`\n#. :ref:`Runge45 <Runge45@Parallel Mode>`\n#. :ref:`discrete <Discrete@Parallel Mode>`\n#. :ref:`atomic_one <atomic_one@afun@Parallel Mode>`\n\n\n{xrst_end parallel_ad}\n-----------------------------------------------------------------------------\n*/\n\n# include <vector>\n# include <cppad/utility/vector.hpp>\n# include <cppad/local/std_set.hpp>\n# include <cppad/local/val_graph/enable_parallel.hpp>\n\n// BEGIN CppAD namespace\nnamespace CppAD {\n\n/*!\nEnable parallel execution mode with <code>AD<Base></code> by initializing\nstatic variables that my be used.\n*/\n\ntemplate <class Base>\nvoid parallel_ad(void)\n{   CPPAD_ASSERT_KNOWN(\n        ! thread_alloc::in_parallel() ,\n        \"parallel_ad must be called before entering parallel execution mode.\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        AD<Base>::tape_ptr() == nullptr ,\n        \"parallel_ad cannot be called while a tape recording is in progress\"\n    );\n\n    // ensure statics in following functions are initialized\n    ErrorHandler::Current();                // error_handler.hpp\n    elapsed_seconds();                      // elapsed_seconds.hpp\n    local::num_arg_dyn(local::abs_dyn);     // op_code_dyn.hpp\n    local::op_name_dyn(local::abs_dyn);     // op_code_dyn.hpp\n    local::NumArg(local::BeginOp);          // op_code_var.hpp\n    local::NumRes(local::BeginOp);          // op_code_var.hpp\n    local::one_element_std_set<size_t>();   // std_set.hpp\n    local::two_element_std_set<size_t>();   // std_set.hpp\n\n    // the sparse_pack class has member functions with static data\n    local::sparse::pack_setvec sp;\n    sp.resize(1, 1);       // so can call add_element\n    sp.add_element(0, 0);  // has static data\n    sp.clear(0);           // has static data\n    sp.is_element(0, 0);   // has static data\n    local::sparse::pack_setvec::const_iterator itr(sp, 0); // has static data\n    ++itr;                                  // has static data\n\n    // statics that depend on the value of Base\n    AD<Base>::tape_id_ptr(0);                  // tape_link.hpp\n    AD<Base>::tape_handle(0);                  // tape_link.hpp\n    local::val_graph::enable_parallel<Base>(); // val_graph/*_op.hpp\n    discrete<Base>::List();                    // discrete.hpp\n\n    // Some check_simple_vector.hpp cases\n    //\n    CheckSimpleVector< bool, CppAD::vectorBool >();\n    CheckSimpleVector< size_t, CppAD::vector<size_t> >();\n    CheckSimpleVector< Base, CppAD::vector<Base> >();\n    CheckSimpleVector< AD<Base>, CppAD::vector< AD<Base> > >();\n    //\n    CheckSimpleVector< Base, std::vector<Base> >();\n    CheckSimpleVector< AD<Base>, std::vector< AD<Base> > >();\n    //\n# if CPPAD_BOOSTVECTOR\n    CheckSimpleVector< Base, boost::numeric::ublas::vector<Base> >();\n    CheckSimpleVector< AD<Base>, boost::numeric::ublas::vector< AD<Base> > >();\n# endif\n    //\n# if CPPAD_EIGENVECTOR\n    CheckSimpleVector< Base, CppAD::eigen_vector<Base> >();\n    CheckSimpleVector< AD<Base>, CppAD::eigen_vector< AD<Base> > > ();\n# endif\n\n}\n\n} // END CppAD namespace\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/pow.hpp",
    "content": "# ifndef CPPAD_CORE_POW_HPP\n# define CPPAD_CORE_POW_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin pow}\n\nThe AD Power Function\n#####################\n\nSyntax\n******\n| *z* = ``pow`` ( *x* , *y* )\n\nSee Also\n********\n:ref:`pow_int-name`\n\nPurpose\n*******\nDetermines the value of the power function which is defined by\n\n.. math::\n\n    {\\rm pow} (x, y) = x^y\n\nIf y is a Variable\n==================\nIf *y* is a variable,\nthe ``pow`` function may use\nlogarithms and exponentiation to compute derivatives.\nThis will not work if *x* is less than or equal zero.\n\nIf y is a Parameter\n===================\nIf *y* is a parameter, a different method is used to\ncompute the derivatives; see :ref:`pow_forward-name` .\nIn the special case where *x* is zero,\nzero is returned as the derivative.\nThis is correct when *y* minus the order of the derivative\nis greater than zero.\nIf *y* minus the order of the derivative is zero,\nthen *y* is an integer.\nIf *y* minus the order of the derivative is less than zero,\nthe actual derivative is infinite.\n\nIf y is an Integer\n==================\nIf the value of *y* is an integer,\nthe :ref:`pow_int-name` function can be used to compute this value\nusing only multiplication (and division if *y* is negative).\nThis will work even if *x* is less than or equal zero.\n\nx\n*\nThe argument *x* has one of the following prototypes\n\n| |tab| ``const`` *Base* & *x*\n| |tab| ``const AD`` < *Base* >& *x*\n| |tab| ``const VecAD`` < *Base* >:: ``reference&`` *x*\n\ny\n*\nThe argument *y* has one of the following prototypes\n\n| |tab| ``const`` *Base* & *y*\n| |tab| ``const AD`` < *Base* >& *y*\n| |tab| ``const VecAD`` < *Base* >:: ``reference&`` *y*\n\nz\n*\nIf both *x* and *y* are *Base* objects,\nthe result *z* is also a *Base* object.\nOtherwise, it has prototype\n\n    ``AD`` < *Base* > *z*\n\nOperation Sequence\n******************\nThis is an AD of *Base*\n:ref:`atomic operation<glossary@Operation@Atomic>`\nand hence is part of the current\nAD of *Base*\n:ref:`operation sequence<glossary@Operation@Sequence>` .\n\nExample\n*******\n{xrst_toc_hidden\n    example/general/pow.cpp\n    example/general/pow_nan.cpp\n}\nThe files\n:ref:`pow.cpp-name` and :ref:`pow_nan.cpp-name`\nare examples tests of this function.\n\n{xrst_end pow}\n-------------------------------------------------------------------------------\n*/\n\n//  BEGIN CppAD namespace\nnamespace CppAD {\n\n// case where x and y are AD<Base> -----------------------------------------\ntemplate <class Base> AD<Base>\npow(const AD<Base>& x, const AD<Base>& y)\n{\n    // compute the Base part\n    AD<Base> result;\n    result.value_  = pow(x.value_, y.value_);\n    CPPAD_ASSERT_UNKNOWN( Parameter(result) );\n\n    // check if there is a recording in progress\n    local::ADTape<Base>* tape = AD<Base>::tape_ptr();\n    if( tape == nullptr )\n        return result;\n    tape_id_t tape_id = tape->id_;\n    // tape_id cannot match the default value for tape_id_; i.e., 0\n    CPPAD_ASSERT_UNKNOWN( tape_id > 0 );\n\n    // check if x and y tapes match\n    bool match_x  = x.tape_id_  == tape_id;\n    bool match_y  = y.tape_id_  == tape_id;\n\n    // check if x and y are dynamic parameters\n    bool dyn_x  = match_x  & (x.ad_type_ == dynamic_enum);\n    bool dyn_y  = match_y  & (y.ad_type_ == dynamic_enum);\n\n    // check if x and y are variables\n    bool var_x  = match_x  & (x.ad_type_ != dynamic_enum);\n    bool var_y  = match_y  & (y.ad_type_ != dynamic_enum);\n\n    CPPAD_ASSERT_KNOWN(\n        x.tape_id_ == y.tape_id_ || ! match_x || ! match_y ,\n        \"pow: AD variables or dynamic parameters on different threads.\"\n    );\n    if( var_x )\n    {   if( var_y )\n        {   // result = variable^variable\n            CPPAD_ASSERT_UNKNOWN( local::NumRes(local::PowvvOp) == 3 );\n            CPPAD_ASSERT_UNKNOWN( local::NumArg(local::PowvvOp) == 2 );\n\n            // put operand addresses in tape\n            tape->Rec_.PutArg(x.taddr_, y.taddr_);\n\n            // put operator in the tape\n            result.taddr_ = tape->Rec_.PutOp(local::PowvvOp);\n\n            // make result a variable\n            result.tape_id_ = tape_id;\n            result.ad_type_ = variable_enum;\n        }\n        else if( (! dyn_y) && IdenticalZero( y.value_ ) )\n        {   // result = variable^0\n        }\n        else\n        {   // result = variable^parameter\n            CPPAD_ASSERT_UNKNOWN( local::NumRes(local::PowvpOp) == 1 );\n            CPPAD_ASSERT_UNKNOWN( local::NumArg(local::PowvpOp) == 2 );\n\n            // put operand addresses in tape\n            addr_t p = y.taddr_;\n            if( ! dyn_y )\n                p = tape->Rec_.put_con_par(y.value_);\n            tape->Rec_.PutArg(x.taddr_, p);\n\n            // put operator in the tape\n            result.taddr_ = tape->Rec_.PutOp(local::PowvpOp);\n\n            // make result a variable\n            result.tape_id_ = tape_id;\n            result.ad_type_ = variable_enum;\n        }\n    }\n    else if( var_y )\n    {   if( (! dyn_x) && IdenticalZero(x.value_) )\n        {   // result = 0^variable\n        }\n        else\n        {   // result = parameter^variable\n            CPPAD_ASSERT_UNKNOWN( local::NumRes(local::PowpvOp) == 3 );\n            CPPAD_ASSERT_UNKNOWN( local::NumArg(local::PowpvOp) == 2 );\n\n            // put operand addresses in tape\n            addr_t p = x.taddr_;\n            if( ! dyn_x )\n                p = tape->Rec_.put_con_par(x.value_);\n            tape->Rec_.PutArg(p, y.taddr_);\n\n            // put operator in the tape\n            result.taddr_ = tape->Rec_.PutOp(local::PowpvOp);\n\n            // make result a variable\n            result.tape_id_ = tape_id;\n            result.ad_type_ = variable_enum;\n        }\n    }\n    else if( dyn_x | dyn_y )\n    {   if( (!dyn_x) && IdenticalZero(x.value_) )\n        { // result = 0^dynamic\n        } else if( (! dyn_y) && IdenticalZero( y.value_ ) )\n        {   // result = dynamic^0\n        } else {\n            addr_t arg0 = x.taddr_;\n            addr_t arg1 = y.taddr_;\n            if( ! dyn_x )\n                arg0 = tape->Rec_.put_con_par(x.value_);\n            if( ! dyn_y )\n                arg1 = tape->Rec_.put_con_par(y.value_);\n            //\n            // parameters with a dynamic parameter result\n            result.taddr_   = tape->Rec_.put_dyn_par(\n                result.value_, local::pow_dyn,   arg0, arg1\n            );\n            result.tape_id_ = tape_id;\n            result.ad_type_ = dynamic_enum;\n        }\n    }\n    else\n    {   CPPAD_ASSERT_KNOWN( ! (dyn_x | dyn_y) ,\n        \"pow: one operand is a dynamic parameter and other not a variable\"\n        );\n    }\n    return result;\n}\n// =========================================================================\n// Fold operations in same way as CPPAD_FOLD_AD_VALUED_BINARY_OPERATOR(Op)\n// -------------------------------------------------------------------------\n// Operations with VecAD_reference<Base> and AD<Base> only\n\ntemplate <class Base> AD<Base>\npow(const AD<Base>& x, const VecAD_reference<Base>& y)\n{   return pow(x, y.ADBase()); }\n\ntemplate <class Base> AD<Base>\npow(const VecAD_reference<Base>& x, const VecAD_reference<Base>& y)\n{   return pow(x.ADBase(), y.ADBase()); }\n\ntemplate <class Base> AD<Base>\npow(const VecAD_reference<Base>& x, const AD<Base>& y)\n{   return pow(x.ADBase(), y); }\n// -------------------------------------------------------------------------\n// Operations with Base\n\ntemplate <class Base> AD<Base>\npow(const Base& x, const AD<Base>& y)\n{   return pow(AD<Base>(x), y); }\n\ntemplate <class Base> AD<Base>\npow(const Base& x, const VecAD_reference<Base>& y)\n{   return pow(AD<Base>(x), y.ADBase()); }\n\ntemplate <class Base> AD<Base>\npow(const AD<Base>& x, const Base& y)\n{   return pow(x, AD<Base>(y)); }\n\ntemplate <class Base> AD<Base>\npow(const VecAD_reference<Base>& x, const Base& y)\n{   return pow(x.ADBase(), AD<Base>(y)); }\n// -------------------------------------------------------------------------\n// Operations with double\n\ntemplate <class Base> AD<Base>\npow(const double& x, const AD<Base>& y)\n{   return pow(AD<Base>(x), y); }\n\ntemplate <class Base> AD<Base>\npow(const double& x, const VecAD_reference<Base>& y)\n{   return pow(AD<Base>(x), y.ADBase()); }\n\ntemplate <class Base> AD<Base>\npow(const AD<Base>& x, const double& y)\n{   return pow(x, AD<Base>(y)); }\n\ntemplate <class Base> AD<Base>\npow(const VecAD_reference<Base>& x, const double& y)\n{   return pow(x.ADBase(), AD<Base>(y)); }\n// -------------------------------------------------------------------------\n// Special case to avoid ambiguity when Base is double\n\ninline AD<double>\npow(const double& x, const AD<double>& y)\n{   return pow(AD<double>(x), y); }\n\ninline AD<double>\npow(const double& x, const VecAD_reference<double>& y)\n{   return pow(AD<double>(x), y.ADBase()); }\n\ninline AD<double>\npow(const AD<double>& x, const double& y)\n{   return pow(x, AD<double>(y)); }\n\ninline AD<double>\npow(const VecAD_reference<double>& x, const double& y)\n{   return pow(x.ADBase(), AD<double>(y)); }\n\n// =========================================================================\n// Fold operations for the cases where x is an int,\n// but let cppad/utility/pow_int.hpp handle the cases where y is an int.\n// -------------------------------------------------------------------------\ntemplate <class Base> AD<Base> pow\n(const int& x, const VecAD_reference<Base>& y)\n{   return pow(AD<Base>(x), y.ADBase()); }\n\ntemplate <class Base> AD<Base> pow\n(const int& x, const AD<Base>& y)\n{   return pow(AD<Base>(x), y); }\n\n} // END CppAD namespace\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/print_for.hpp",
    "content": "# ifndef CPPAD_CORE_PRINT_FOR_HPP\n# define CPPAD_CORE_PRINT_FOR_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin PrintFor}\n{xrst_spell\n    notpos\n}\n\nPrinting AD Values During Forward Mode\n######################################\n\nSyntax\n******\n| *f* . ``Forward`` (0, *x* )\n| *f* . ``Forward`` (0, *x* , *s* )\n| ``PrintFor`` ( *before* , *value* )\n| ``PrintFor`` ( *notpos* , *before* , *value* , *after* )\n\nSee Also\n********\n:ref:`ad_output-name`\n\nPurpose\n*******\nThe :ref:`zero order forward<forward_zero-name>` mode command\n\n    *f* . ``Forward`` (0, *x* )\n\nsets the\n:ref:`glossary@Tape@Independent Variable` vector\nequal to *x* .\nIt then computes a value for all of the dependent variables in the\n:ref:`operation sequence<glossary@Operation@Sequence>` corresponding\nto *f* .\nPutting a ``PrintFor`` in the operation sequence,\nprints *value* , corresponding to *x* ,\nto be printed during zero order forward operations.\n\nf.Forward(0, x)\n***************\nThe objects *f* , *x* , and the purpose\nfor this operation, are documented in :ref:`Forward-name` .\n\nnotpos\n******\nIf present, the argument *notpos* has one of the following prototypes\n\n| |tab| ``const AD`` < *Base* >& *notpos*\n| |tab| ``const VecAD`` < *Base* >:: ``reference&`` *notpos*\n\nIn this case\nthe text and *value* will be printed if and only if\n*notpos* is not positive (greater than zero) and a finite number.\n\nbefore\n******\nThe argument *before* has prototype\n\n    ``const char`` * *before*\n\nThis text is written to ``std::cout`` before *value* .\n\nvalue\n*****\nThe argument *value* has one of the following prototypes\n\n| |tab| ``const AD`` < *Base* >& *value*\n| |tab| ``const VecAD`` < *Base* >:: ``reference&`` *value*\n\nThe *value* , that corresponds to *x* ,\nis written to ``std::cout`` during the execution of\n\n    *f* . ``Forward`` (0, *x* )\n\nNote that *value* may be a\n:ref:`glossary@Variable` or\n:ref:`glossary@Parameter` .\nIf a parameter is\n:ref:`glossary@Parameter@Dynamic` its value\nwill depend on the previous call to :ref:`new_dynamic-name` .\n\nafter\n*****\nThe argument *after* has prototype\n\n    ``const char`` * *after*\n\nThis text is written to ``std::cout`` after *value* .\n\ns\n*\nYou can redirect this output to any standard output stream using the syntax\n\n    *f* . ``Forward`` (0, *x* , *s* )\n\nsee :ref:`forward_zero@s` in the zero order forward mode documentation.\n\nDiscussion\n**********\nThis is helpful for understanding why tape evaluations have trouble.\nFor example, if one of the operations in *f* is\n``log`` ( *value* ) and *value*  < 0 ,\nthe corresponding result will :ref:`nan-name` .\n\nExample\n*******\n{xrst_toc_hidden\n    example/print_for/print_for.cpp\n    example/general/print_for.cpp\n}\nThe program\n:ref:`print_for_cout.cpp-name`\nis an example and test that prints to standard output.\nThe output of this program\nstates the conditions for passing and failing the test.\nThe function\n:ref:`print_for_string.cpp-name`\nis an example and test that prints to an standard string stream.\nThis function automatically check for correct output.\n\n{xrst_end PrintFor}\n------------------------------------------------------------------------------\n*/\n\n# include <cstring>\n\nnamespace CppAD {\n    template <class Base>\n    void PrintFor(\n        const AD<Base>& notpos        ,\n        const char*     before        ,\n        const AD<Base>& value         ,\n        const char*     after         )\n    {   CPPAD_ASSERT_NARG_NRES(local::PriOp, 5, 0);\n\n        // check for case where we are not recording operations\n        local::ADTape<Base>* tape = AD<Base>::tape_ptr();\n        if( tape == nullptr )\n            return;\n\n        CPPAD_ASSERT_KNOWN(\n            std::strlen(before) <= 1000 ,\n            \"PrintFor: length of before is greater than 1000 characters\"\n        );\n        CPPAD_ASSERT_KNOWN(\n            std::strlen(after) <= 1000 ,\n            \"PrintFor: length of after is greater than 1000 characters\"\n        );\n        addr_t arg0, arg1, arg2, arg3, arg4;\n\n        // arg[0] = base 2 representation of [Var(notpos), Var(value)]\n        arg0 = 0;\n\n        // arg[1] = address for notpos\n        if( Constant(notpos) )\n            arg1  = tape->Rec_.put_con_par(notpos.value_);\n        else if( Dynamic(notpos) )\n            arg1  = notpos.taddr_;\n        else\n        {   arg0 += 1;\n            arg1  = notpos.taddr_;\n        }\n\n        // arg[2] = address of before\n        arg2 = tape->Rec_.PutTxt(before);\n\n        // arg[3] = address for value\n        if( Constant(value) )\n            arg3  = tape->Rec_.put_con_par(value.value_);\n        else if( Dynamic(value) )\n            arg3  = value.taddr_;\n        else\n        {   arg0 += 2;\n            arg3  = value.taddr_;\n        }\n\n        // arg[4] = address of after\n        arg4 = tape->Rec_.PutTxt(after);\n\n        // put the operator in the tape\n        tape->Rec_.PutArg(arg0, arg1, arg2, arg3, arg4);\n        tape->Rec_.PutOp(local::PriOp);\n    }\n    // Fold all other cases into the case above\n    template <class Base>\n    void PrintFor(const char* before, const AD<Base>& value)\n    {   PrintFor(AD<Base>(0), before, value, \"\" ); }\n    //\n    template <class Base>\n    void PrintFor(const char* before, const VecAD_reference<Base>& value)\n    {   PrintFor(AD<Base>(0), before, value.ADBase(), \"\" ); }\n    //\n    template <class Base>\n    void PrintFor(\n        const VecAD_reference<Base>& notpos ,\n        const char                  *before ,\n        const VecAD_reference<Base>& value  ,\n        const char                  *after  )\n    {   PrintFor(notpos.ADBase(), before, value.ADBase(), after); }\n    //\n    template <class Base>\n    void PrintFor(\n        const VecAD_reference<Base>& notpos ,\n        const char                  *before ,\n        const AD<Base>&              value  ,\n        const char                  *after  )\n    {   PrintFor(notpos.ADBase(), before, value, after); }\n    //\n    template <class Base>\n    void PrintFor(\n        const AD<Base>&              notpos ,\n        const char                  *before ,\n        const VecAD_reference<Base>& value  ,\n        const char                  *after  )\n    {   PrintFor(notpos, before, value.ADBase(), after); }\n}\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/rev_hes_sparsity.hpp",
    "content": "# ifndef CPPAD_CORE_REV_HES_SPARSITY_HPP\n# define CPPAD_CORE_REV_HES_SPARSITY_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin rev_hes_sparsity}\n{xrst_spell\n    rc\n}\n\nReverse Mode Hessian Sparsity Patterns\n######################################\n\nSyntax\n******\n| *f* . ``rev_hes_sparsity`` (\n| |tab| *select_range* , *transpose* , *internal_bool* , *pattern_out*\n| )\n\nPurpose\n*******\nWe use :math:`F : \\B{R}^n \\rightarrow \\B{R}^m` to denote the\n:ref:`glossary@AD Function` corresponding to\nthe operation sequence stored in *f* .\nFix :math:`R \\in \\B{R}^{n \\times \\ell}`, :math:`s \\in \\B{R}^m`\nand define the function\n\n.. math::\n\n    H(x) = ( s^\\R{T} F )^{(2)} ( x ) R\n\nGiven a :ref:`glossary@Sparsity Pattern` for :math:`R`\nand for the vector :math:`s`,\n``rev_hes_sparsity`` computes a sparsity pattern for :math:`H(x)`.\n\nx\n*\nNote that the sparsity pattern :math:`H(x)` corresponds to the\noperation sequence stored in *f* and does not depend on\nthe argument *x* .\n\nBoolVector\n**********\nThe type *BoolVector* is a :ref:`SimpleVector-name` class with\n:ref:`elements of type<SimpleVector@Elements of Specified Type>`\n``bool`` .\n\nSizeVector\n**********\nThe type *SizeVector* is a :ref:`SimpleVector-name` class with\n:ref:`elements of type<SimpleVector@Elements of Specified Type>`\n``size_t`` .\n\nf\n*\nThe object *f* has prototype\n\n    ``ADFun`` < *Base* > *f*\n\nR\n*\nThe sparsity pattern for the matrix :math:`R` is specified by\n:ref:`for_jac_sparsity@pattern_in` in the previous call\n\n| |tab| *f* . ``for_jac_sparsity`` (\n| |tab| |tab| *pattern_in* , *transpose* , *dependency* , *internal_bool* , *pattern_out*\n| )\n\nselect_range\n************\nThe argument *select_range* has prototype\n\n    ``const`` *BoolVector* & *select_range*\n\nIt has size :math:`m` and specifies which components of the vector\n:math:`s` are non-zero; i.e., *select_range* [ *i* ] is true\nif and only if :math:`s_i` is possibly non-zero.\n\ntranspose\n*********\nThis argument has prototype\n\n    ``bool`` *transpose*\n\nSee :ref:`rev_hes_sparsity@pattern_out` below.\n\ninternal_bool\n*************\nIf this is true, calculations are done with sets represented by a vector\nof boolean values. Otherwise, a vector of sets of integers is used.\nThis must be the same as in the previous call to\n*f* . ``for_jac_sparsity`` .\n\npattern_out\n***********\nThis argument has prototype\n\n    ``sparse_rc`` < *SizeVector* >& *pattern_out*\n\nThis input value of *pattern_out* does not matter.\nIf *transpose* it is false (true),\nupon return *pattern_out* is a sparsity pattern for\n:math:`H(x)` (:math:`H(x)^\\R{T}`).\n\nSparsity for Entire Hessian\n***************************\nSuppose that :math:`R` is the :math:`n \\times n` identity matrix.\nIn this case, *pattern_out* is a sparsity pattern for\n:math:`(s^\\R{T} F)^{(2)} ( x )`.\n\nExample\n*******\n{xrst_toc_hidden\n    example/sparse/rev_hes_sparsity.cpp\n}\nThe file\n:ref:`rev_hes_sparsity.cpp-name`\ncontains an example and test of this operation.\n\n{xrst_end rev_hes_sparsity}\n-----------------------------------------------------------------------------\n*/\n# include <cppad/core/ad_fun.hpp>\n# include <cppad/local/sparse/internal.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n\n/*!\nReverse Hessian sparsity patterns.\n\n\\tparam Base\nis the base type for this recording.\n\n\\tparam BoolVector\nis the simple vector with elements of type bool that is used for\nsparsity for the vector s.\n\n\\tparam SizeVector\nis the simple vector with elements of type size_t that is used for\nrow, column index sparsity patterns.\n\n\\param select_range\nis a sparsity pattern for for s.\n\n\\param transpose\nIs the returned sparsity pattern transposed.\n\n\\param internal_bool\nIf this is true, calculations are done with sets represented by a vector\nof boolean values. Otherwise, a vector of standard sets is used.\n\n\\param pattern_out\nThe value of transpose is false (true),\nthe return value is a sparsity pattern for H(x) ( H(x)^T ) where\n\\f[\n    H(x) = R * F^{(1)} (x)\n\\f]\nHere F is the function corresponding to the operation sequence\nand x is any argument value.\n*/\ntemplate <class Base, class RecBase>\ntemplate <class BoolVector, class SizeVector>\nvoid ADFun<Base,RecBase>::rev_hes_sparsity(\n    const BoolVector&            select_range     ,\n    bool                         transpose        ,\n    bool                         internal_bool    ,\n    sparse_rc<SizeVector>&       pattern_out      )\n{\n    // used to identify the RecBase type in calls to sweeps\n    RecBase not_used_rec_base(0.0);\n    //\n    size_t m  = Range();\n    //\n    CPPAD_ASSERT_KNOWN(\n        size_t( select_range.size() ) == m,\n        \"rev_hes_sparsity: size of select_range is not equal to \"\n        \"number of dependent variables\"\n    );\n    //\n    // vector that holds reverse Jacobian sparsity flag\n    local::pod_vector<bool> rev_jac_pattern(num_var_tape_);\n    for(size_t i = 0; i < num_var_tape_; i++)\n        rev_jac_pattern[i] = false;\n    //\n    // initialize rev_jac_pattern for dependent variables\n    for(size_t i = 0; i < m; i++)\n        rev_jac_pattern[ dep_taddr_[i] ] = select_range[i];\n    //\n    //\n    if( internal_bool )\n    {   CPPAD_ASSERT_KNOWN(\n            for_jac_sparse_pack_.n_set() > 0,\n            \"rev_hes_sparsity: previous call to for_jac_sparsity did not \"\n            \"use bool for internal sparsity patterns.\"\n        );\n        // column dimension of internal sparstiy pattern\n        size_t ell = for_jac_sparse_pack_.end();\n        //\n        // allocate memory for bool sparsity calculation\n        // (sparsity pattern is empty after a resize)\n        local::sparse::pack_setvec internal_hes;\n        internal_hes.resize(num_var_tape_, ell);\n        //\n        // compute the Hessian sparsity pattern\n        local::sweep::rev_hes(\n            &play_,\n            num_var_tape_,\n            for_jac_sparse_pack_,\n            rev_jac_pattern.data(),\n            internal_hes,\n            not_used_rec_base\n        );\n        // get sparstiy pattern for independent variables\n        local::sparse::get_internal_pattern(\n            transpose, ind_taddr_, internal_hes, pattern_out\n        );\n    }\n    else\n    {   CPPAD_ASSERT_KNOWN(\n            for_jac_sparse_set_.n_set() > 0,\n            \"rev_hes_sparsity: previous call to for_jac_sparsity did not \"\n            \"use bool for internal sparsity patterns.\"\n        );\n        // column dimension of internal sparstiy pattern\n        size_t ell = for_jac_sparse_set_.end();\n        //\n        // allocate memory for bool sparsity calculation\n        // (sparsity pattern is empty after a resize)\n        local::sparse::list_setvec internal_hes;\n        internal_hes.resize(num_var_tape_, ell);\n        //\n        // compute the Hessian sparsity pattern\n        local::sweep::rev_hes(\n            &play_,\n            num_var_tape_,\n            for_jac_sparse_set_,\n            rev_jac_pattern.data(),\n            internal_hes,\n            not_used_rec_base\n        );\n        // get sparstiy pattern for independent variables\n        local::sparse::get_internal_pattern(\n            transpose, ind_taddr_, internal_hes, pattern_out\n        );\n    }\n    return;\n}\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/rev_jac_sparsity.hpp",
    "content": "# ifndef CPPAD_CORE_REV_JAC_SPARSITY_HPP\n# define CPPAD_CORE_REV_JAC_SPARSITY_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin rev_jac_sparsity}\n\nReverse Mode Jacobian Sparsity Patterns\n#######################################\n\nSyntax\n******\n| *f* . ``rev_jac_sparsity`` (\n| |tab| *pattern_in* , *transpose* , *dependency* , *internal_bool* , *pattern_out*\n| )\n\nPurpose\n*******\nWe use :math:`F : \\B{R}^n \\rightarrow \\B{R}^m` to denote the\n:ref:`glossary@AD Function` corresponding to\nthe operation sequence stored in *f* .\nFix :math:`R \\in \\B{R}^{\\ell \\times m}` and define the function\n\n.. math::\n\n    J(x) = R * F^{(1)} ( x )\n\nGiven the :ref:`glossary@Sparsity Pattern` for :math:`R`,\n``rev_jac_sparsity`` computes a sparsity pattern for :math:`J(x)`.\n\nx\n*\nNote that the sparsity pattern :math:`J(x)` corresponds to the\noperation sequence stored in *f* and does not depend on\nthe argument *x* .\n(The operation sequence may contain\n:ref:`CondExp-name` and  :ref:`VecAD-name` operations.)\n\nSizeVector\n**********\nThe type *SizeVector* is a :ref:`SimpleVector-name` class with\n:ref:`elements of type<SimpleVector@Elements of Specified Type>`\n``size_t`` .\n\nf\n*\nThe object *f* has prototype\n\n    ``ADFun`` < *Base* > *f*\n\npattern_in\n**********\nThe argument *pattern_in* has prototype\n\n    ``const sparse_rc`` < *SizeVector* >& *pattern_in*\n\nsee :ref:`sparse_rc-name` .\nIf *transpose* it is false (true),\n*pattern_in* is a sparsity pattern for :math:`R` (:math:`R^\\R{T}`).\n\ntranspose\n*********\nThis argument has prototype\n\n    ``bool`` *transpose*\n\nSee :ref:`rev_jac_sparsity@pattern_in` above and\n:ref:`rev_jac_sparsity@pattern_out` below.\n\ndependency\n**********\nThis argument has prototype\n\n    ``bool`` *dependency*\n\nsee :ref:`rev_jac_sparsity@pattern_out` below.\n\ninternal_bool\n*************\nIf this is true, calculations are done with sets represented by a vector\nof boolean values. Otherwise, a vector of sets of integers is used.\n\npattern_out\n***********\nThis argument has prototype\n\n    ``sparse_rc`` < *SizeVector* >& *pattern_out*\n\nThis input value of *pattern_out* does not matter.\nIf *transpose* it is false (true),\nupon return *pattern_out* is a sparsity pattern for\n:math:`J(x)` (:math:`J(x)^\\R{T}`).\nIf *dependency* is true, *pattern_out* is a\n:ref:`dependency.cpp@Dependency Pattern`\ninstead of sparsity pattern.\n\nSparsity for Entire Jacobian\n****************************\nSuppose that\n:math:`R` is the :math:`m \\times m` identity matrix.\nIn this case, *pattern_out* is a sparsity pattern for\n:math:`F^{(1)} ( x )`  ( :math:`F^{(1)} (x)^\\R{T}` )\nif *transpose* is false (true).\n\nExample\n*******\n{xrst_toc_hidden\n    example/sparse/rev_jac_sparsity.cpp\n}\nThe file\n:ref:`rev_jac_sparsity.cpp-name`\ncontains an example and test of this operation.\n\n{xrst_end rev_jac_sparsity}\n-----------------------------------------------------------------------------\n*/\n# include <cppad/core/ad_fun.hpp>\n# include <cppad/local/sparse/internal.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n\n/*!\nReverse Jacobian sparsity patterns.\n\n\\tparam Base\nis the base type for this recording.\n\n\\tparam SizeVector\nis the simple vector with elements of type size_t that is used for\nrow, column index sparsity patterns.\n\n\\param pattern_in\nis the sparsity pattern for for R or R^T depending on transpose.\n\n\\param transpose\nIs the input and returned sparsity pattern transposed.\n\n\\param dependency\nAre the derivatives with respect to left and right of the expression below\nconsidered to be non-zero:\n\\code\n    CondExpRel(left, right, if_true, if_false)\n\\endcode\nThis is used by the optimizer to obtain the correct dependency relations.\n\n\\param internal_bool\nIf this is true, calculations are done with sets represented by a vector\nof boolean values. Otherwise, a vector of standard sets is used.\n\n\\param pattern_out\nThe value of transpose is false (true),\nthe return value is a sparsity pattern for J(x) ( J(x)^T ) where\n\\f[\n    J(x) = R * F^{(1)} (x)\n\\f]\nHere F is the function corresponding to the operation sequence\nand x is any argument value.\n*/\ntemplate <class Base, class RecBase>\ntemplate <class SizeVector>\nvoid ADFun<Base,RecBase>::rev_jac_sparsity(\n    const sparse_rc<SizeVector>& pattern_in       ,\n    bool                         transpose        ,\n    bool                         dependency       ,\n    bool                         internal_bool    ,\n    sparse_rc<SizeVector>&       pattern_out      )\n{\n    // used to identify the RecBase type in calls to sweeps\n    RecBase not_used_rec_base(0.0);\n    //\n    // number or rows, columns, and non-zeros in pattern_in\n    size_t nr_in  = pattern_in.nr();\n    size_t nc_in  = pattern_in.nc();\n    //\n    size_t ell = nr_in;\n    size_t m   = nc_in;\n    if( transpose )\n        std::swap(ell, m);\n    //\n    CPPAD_ASSERT_KNOWN(\n        m == Range() ,\n        \"rev_jac_sparsity: number columns in R \"\n        \"is not equal number of dependent variables.\"\n    );\n    // number of independent variables\n    size_t n = Domain();\n    //\n    bool zero_empty  = true;\n    bool input_empty = true;\n    if( internal_bool )\n    {   // allocate memory for bool sparsity calculation\n        // (sparsity pattern is empty after a resize)\n        local::sparse::pack_setvec internal_jac;\n        internal_jac.resize(num_var_tape_, ell);\n        //\n        // set sparsity pattern for dependent variables\n        local::sparse::set_internal_pattern(\n            zero_empty            ,\n            input_empty           ,\n            ! transpose           ,\n            dep_taddr_            ,\n            internal_jac          ,\n            pattern_in\n        );\n\n        // compute sparsity for other variables\n        local::sweep::rev_jac(\n            &play_,\n            dependency,\n            n,\n            num_var_tape_,\n            internal_jac,\n            not_used_rec_base\n\n        );\n        // get sparstiy pattern for independent variables\n        local::sparse::get_internal_pattern(\n            ! transpose, ind_taddr_, internal_jac, pattern_out\n        );\n    }\n    else\n    {   // allocate memory for bool sparsity calculation\n        // (sparsity pattern is empty after a resize)\n        local::sparse::list_setvec internal_jac;\n        internal_jac.resize(num_var_tape_, ell);\n        //\n        // set sparsity pattern for dependent variables\n        local::sparse::set_internal_pattern(\n            zero_empty            ,\n            input_empty           ,\n            ! transpose           ,\n            dep_taddr_            ,\n            internal_jac          ,\n            pattern_in\n        );\n\n        // compute sparsity for other variables\n        local::sweep::rev_jac(\n            &play_,\n            dependency,\n            n,\n            num_var_tape_,\n            internal_jac,\n            not_used_rec_base\n\n        );\n        // get sparstiy pattern for independent variables\n        local::sparse::get_internal_pattern(\n            ! transpose, ind_taddr_, internal_jac, pattern_out\n        );\n    }\n    return;\n}\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/rev_one.hpp",
    "content": "# ifndef CPPAD_CORE_REV_ONE_HPP\n# define CPPAD_CORE_REV_ONE_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin RevOne}\n{xrst_spell\n    dw\n}\n\nFirst Order Derivative: Driver Routine\n######################################\n\nSyntax\n******\n| *dw* = *f* . ``RevOne`` ( *x* , *i* )\n\nPurpose\n*******\nWe use :math:`F : \\B{R}^n \\rightarrow \\B{R}^m` to denote the\n:ref:`glossary@AD Function` corresponding to *f* .\nThe syntax above sets *dw* to the\nderivative of :math:`F_i` with respect to :math:`x`; i.e.,\n\n.. math::\n\n    dw =\n    F_i^{(1)} (x)\n    = \\left[\n        \\D{ F_i }{ x_0 } (x) , \\cdots , \\D{ F_i }{ x_{n-1} } (x)\n    \\right]\n\nf\n*\nThe object *f* has prototype\n\n    ``ADFun`` < *Base* > *f*\n\nNote that the :ref:`ADFun-name` object *f* is not ``const``\n(see :ref:`RevOne@RevOne Uses Forward` below).\n\nx\n*\nThe argument *x* has prototype\n\n    ``const`` *Vector* & *x*\n\n(see :ref:`RevOne@Vector` below)\nand its size\nmust be equal to *n* , the dimension of the\n:ref:`fun_property@Domain` space for *f* .\nIt specifies\nthat point at which to evaluate the derivative.\n\ni\n*\nThe index *i* has prototype\n\n    ``size_t`` *i*\n\nand is less than :math:`m`, the dimension of the\n:ref:`fun_property@Range` space for *f* .\nIt specifies the\ncomponent of :math:`F` that we are computing the derivative of.\n\ndw\n**\nThe result *dw* has prototype\n\n    *Vector* *dw*\n\n(see :ref:`RevOne@Vector` below)\nand its size is *n* , the dimension of the\n:ref:`fun_property@Domain` space for *f* .\nThe value of *dw* is the derivative of :math:`F_i`\nevaluated at *x* ; i.e.,\nfor :math:`j = 0 , \\ldots , n - 1`\n\n.. math::\n\n    dw[ j ] = \\D{ F_i }{ x_j } ( x )\n\nVector\n******\nThe type *Vector* must be a :ref:`SimpleVector-name` class with\n:ref:`elements of type<SimpleVector@Elements of Specified Type>`\n*Base* .\nThe routine :ref:`CheckSimpleVector-name` will generate an error message\nif this is not the case.\n\nRevOne Uses Forward\n*******************\nAfter each call to :ref:`Forward-name` ,\nthe object *f* contains the corresponding\n:ref:`Taylor coefficients<glossary@Taylor Coefficient>` .\nAfter a call to ``RevOne`` ,\nthe zero order Taylor coefficients correspond to\n*f* . ``Forward`` (0, *x* )\nand the other coefficients are unspecified.\n\nExample\n*******\n{xrst_toc_hidden\n    example/general/rev_one.cpp\n}\nThe routine\n:ref:`RevOne<rev_one.cpp-name>` is both an example and test.\nIt returns ``true`` , if it succeeds and ``false`` otherwise.\n\n{xrst_end RevOne}\n-----------------------------------------------------------------------------\n*/\n\n//  BEGIN CppAD namespace\nnamespace CppAD {\n\ntemplate <class Base, class RecBase>\ntemplate <class Vector>\nVector ADFun<Base,RecBase>::RevOne(const Vector  &x, size_t i)\n{   size_t i1;\n\n    size_t n = Domain();\n    size_t m = Range();\n\n    // check Vector is Simple Vector class with Base type elements\n    CheckSimpleVector<Base, Vector>();\n\n    CPPAD_ASSERT_KNOWN(\n        x.size() == n,\n        \"RevOne: Length of x not equal domain dimension for f\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        i < m,\n        \"RevOne: the index i is not less than range dimension for f\"\n    );\n\n    // point at which we are evaluating the derivative\n    Forward(0, x);\n\n    // component which are are taking the derivative of\n    Vector w(m);\n    for(i1 = 0; i1 < m; i1++)\n        w[i1] = 0.;\n    w[i] = Base(1.0);\n\n    // dimension the return value\n    Vector dw(n);\n\n    // compute the return value\n    dw = Reverse(1, w);\n\n    return dw;\n}\n\n} // END CppAD namespace\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/rev_sparse_hes.hpp",
    "content": "# ifndef CPPAD_CORE_REV_SPARSE_HES_HPP\n# define CPPAD_CORE_REV_SPARSE_HES_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin RevSparseHes}\n\nHessian Sparsity Pattern: Reverse Mode\n######################################\n\nSyntax\n******\n| *h* = *f* . ``RevSparseHes`` ( *q* , *s* )\n| *h* = *f* . ``RevSparseHes`` ( *q* , *s* , *transpose* )\n\nPurpose\n*******\nWe use :math:`F : \\B{R}^n \\rightarrow \\B{R}^m` to denote the\n:ref:`glossary@AD Function` corresponding to *f* .\nFor a fixed matrix :math:`R \\in \\B{R}^{n \\times q}`\nand a fixed vector :math:`S \\in \\B{R}^{1 \\times m}`,\nwe define\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    H(x)\n    & = & \\partial_x \\left[ \\partial_u S * F[ x + R * u ] \\right]_{u=0}\n    \\\\\n    & = & R^\\R{T} * (S * F)^{(2)} ( x )\n    \\\\\n    H(x)^\\R{T}\n    & = & (S * F)^{(2)} ( x ) * R\n    \\end{eqnarray}\n\nGiven a\n:ref:`glossary@Sparsity Pattern`\nfor the matrix :math:`R` and the vector :math:`S`,\n``RevSparseHes`` returns a sparsity pattern for the :math:`H(x)`.\n\nf\n*\nThe object *f* has prototype\n\n    ``const ADFun`` < *Base* > *f*\n\nx\n*\nIf the operation sequence in *f* is\n:ref:`glossary@Operation@Independent` of\nthe independent variables in :math:`x \\in \\B{R}^n`,\nthe sparsity pattern is valid for all values of\n(even if it has :ref:`CondExp-name` or :ref:`VecAD-name` operations).\n\nq\n*\nThe argument *q* has prototype\n\n    ``size_t`` *q*\n\nIt specifies the number of columns in :math:`R \\in \\B{R}^{n \\times q}`\nand the number of rows in :math:`H(x) \\in \\B{R}^{q \\times n}`.\nIt must be the same value as in the previous :ref:`ForSparseJac-name` call\n\n    *f* . ``ForSparseJac`` ( *q* , *r* , *r_transpose* )\n\nNote that if *r_transpose* is true, *r* in the call above\ncorresponding to :math:`R^\\R{T} \\in \\B{R}^{q \\times n}`\n\ntranspose\n*********\nThe argument *transpose* has prototype\n\n    ``bool`` *transpose*\n\nThe default value ``false`` is used when *transpose* is not present.\n\nr\n*\nThe matrix :math:`R` is specified by the previous call\n\n    *f* . ``ForSparseJac`` ( *q* , *r* , *transpose* )\n\nsee :ref:`ForSparseJac@r` .\nThe type of the elements of\n:ref:`RevSparseHes@SetVector` must be the\nsame as the type of the elements of *r* .\n\ns\n*\nThe argument *s* has prototype\n\n    ``const`` *SetVector* & *s*\n\n(see :ref:`RevSparseHes@SetVector` below)\nIf it has elements of type ``bool`` ,\nits size is :math:`m`.\nIf it has elements of type ``std::set<size_t>`` ,\nits size is one and all the elements of *s* [0]\nare between zero and :math:`m - 1`.\nIt specifies a\n:ref:`glossary@Sparsity Pattern`\nfor the vector *S* .\n\nh\n*\nThe result *h* has prototype\n\n    *SetVector* & *h*\n\n(see :ref:`RevSparseHes@SetVector` below).\n\ntranspose false\n===============\nIf *h* has elements of type ``bool`` ,\nits size is :math:`q * n`.\nIf it has elements of type ``std::set<size_t>`` ,\nits size is :math:`q` and all the set elements are between\nzero and *n* ``-1`` inclusive.\nIt specifies a\n:ref:`glossary@Sparsity Pattern`\nfor the matrix :math:`H(x)`.\n\ntranspose true\n==============\nIf *h* has elements of type ``bool`` ,\nits size is :math:`n * q`.\nIf it has elements of type ``std::set<size_t>`` ,\nits size is :math:`n` and all the set elements are between\nzero and *q* ``-1`` inclusive.\nIt specifies a\n:ref:`glossary@Sparsity Pattern`\nfor the matrix :math:`H(x)^\\R{T}`.\n\nSetVector\n*********\nThe type *SetVector* must be a :ref:`SimpleVector-name` class with\n:ref:`elements of type<SimpleVector@Elements of Specified Type>`\n``bool`` or ``std::set<size_t>`` ;\nsee :ref:`glossary@Sparsity Pattern` for a discussion\nof the difference.\nThe type of the elements of\n:ref:`RevSparseHes@SetVector` must be the\nsame as the type of the elements of *r* .\n\nEntire Sparsity Pattern\n***********************\nSuppose that :math:`q = n` and\n:math:`R \\in \\B{R}^{n \\times n}` is the :math:`n \\times n` identity matrix.\nFurther suppose that the :math:`S` is the *k*-th\n:ref:`glossary@Elementary Vector` ; i.e.\n\n.. math::\n\n    S_j = \\left\\{ \\begin{array}{ll}\n        1  & {\\rm if} \\; j = k\n        \\\\\n        0  & {\\rm otherwise}\n    \\end{array} \\right.\n\nIn this case,\nthe corresponding value *h* is a\nsparsity pattern for the Hessian matrix\n:math:`F_k^{(2)} (x) \\in \\B{R}^{n \\times n}`.\n\nExample\n*******\n{xrst_toc_hidden\n    example/sparse/rev_sparse_hes.cpp\n    example/sparse/sparsity_sub.cpp\n}\nThe file\n:ref:`rev_sparse_hes.cpp-name`\ncontains an example and test of this operation.\nThe file\n:ref:`sparsity_sub.cpp<sparsity_sub.cpp@RevSparseHes>`\ncontains an example and test of using ``RevSparseHes``\nto compute the sparsity pattern for a subset of the Hessian.\n\n{xrst_end RevSparseHes}\n-----------------------------------------------------------------------------\n*/\n# include <algorithm>\n# include <cppad/local/pod_vector.hpp>\n# include <cppad/local/std_set.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\n\\file core/rev_sparse_hes.hpp\nReverse mode Hessian sparsity patterns.\n*/\n// ===========================================================================\n// RevSparseHesCase\n/*!\nPrivate helper function for RevSparseHes(q, s) bool sparsity.\n\nAll of the description in the public member function RevSparseHes(q, s)\napplies.\n\n\\param set_type\nis a bool value. This argument is used to dispatch to the proper source\ncode depending on the value of SetVector::value_type.\n\n\\param transpose\nSee RevSparseHes(q, s).\n\n\\param q\nSee RevSparseHes(q, s).\n\n\\param s\nSee RevSparseHes(q, s).\n\n\\param h\nis the return value for the corresponding call to RevSparseJac(q, s).\n*/\ntemplate <class Base, class RecBase>\ntemplate <class SetVector>\nvoid ADFun<Base,RecBase>::RevSparseHesCase(\n    bool              set_type         ,\n    bool              transpose        ,\n    size_t            q                ,\n    const SetVector&  s                ,\n    SetVector&        h                )\n{\n    // used to identify the RecBase type in calls to sweeps\n    RecBase not_used_rec_base(0.0);\n    //\n    size_t n = Domain();\n    size_t m = Range();\n    //\n    h.resize(q * n );\n\n    CPPAD_ASSERT_KNOWN(\n        for_jac_sparse_pack_.n_set() > 0,\n        \"RevSparseHes: previous stored call to ForSparseJac did not \"\n        \"use bool for the elements of r.\"\n    );\n    CPPAD_ASSERT_UNKNOWN( for_jac_sparse_set_.n_set() == 0 );\n    CPPAD_ASSERT_UNKNOWN( for_jac_sparse_pack_.n_set() == num_var_tape_  );\n    //\n    // temporary indices\n    size_t i, j;\n\n    // check Vector is Simple SetVector class with bool elements\n    CheckSimpleVector<bool, SetVector>();\n\n    CPPAD_ASSERT_KNOWN(\n        q == for_jac_sparse_pack_.end(),\n        \"RevSparseHes: q is not equal to its value\\n\"\n        \"in the previous call to ForSparseJac with this ADFun object.\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t(s.size()) == m,\n        \"RevSparseHes: size of s is not equal to\\n\"\n        \"range dimension for ADFun object.\"\n    );\n\n    // Array that will hold reverse Jacobian dependency flag.\n    // Initialize as true for the dependent variables.\n    local::pod_vector<bool> RevJac(num_var_tape_);\n    for(i = 0; i < num_var_tape_; i++)\n        RevJac[i] = false;\n    for(i = 0; i < m; i++)\n    {   CPPAD_ASSERT_UNKNOWN( dep_taddr_[i] < num_var_tape_ );\n        RevJac[ dep_taddr_[i] ] = s[i];\n    }\n\n    // vector of sets that will hold reverse Hessain values\n    local::sparse::pack_setvec rev_hes_pattern;\n    rev_hes_pattern.resize(num_var_tape_, q);\n\n    // compute the Hessian sparsity patterns\n    local::sweep::rev_hes(\n        &play_,\n        num_var_tape_,\n        for_jac_sparse_pack_,\n        RevJac.data(),\n        rev_hes_pattern,\n        not_used_rec_base\n\n    );\n\n    // return values corresponding to independent variables\n    CPPAD_ASSERT_UNKNOWN( size_t(h.size()) == n * q );\n    for(j = 0; j < n; j++)\n    {   for(i = 0; i < q; i++)\n        {   if( transpose )\n                h[ j * q + i ] = false;\n            else\n                h[ i * n + j ] = false;\n        }\n    }\n\n    // j is index corresponding to reverse mode partial\n    for(j = 0; j < n; j++)\n    {   CPPAD_ASSERT_UNKNOWN( ind_taddr_[j] < num_var_tape_ );\n\n        // ind_taddr_[j] is operator taddr for j-th independent variable\n        CPPAD_ASSERT_UNKNOWN( ind_taddr_[j] == j + 1 );\n        CPPAD_ASSERT_UNKNOWN( play_.GetOp( ind_taddr_[j] ) == local::InvOp );\n\n        // extract the result from rev_hes_pattern\n        CPPAD_ASSERT_UNKNOWN( rev_hes_pattern.end() == q );\n        local::sparse::pack_setvec::const_iterator itr(rev_hes_pattern, j + 1);\n        i = *itr;\n        while( i < q )\n        {   if( transpose )\n                h[ j * q + i ] = true;\n            else\n                h[ i * n + j ] = true;\n            i = *(++itr);\n        }\n    }\n}\n/*!\nPrivate helper function for RevSparseHes(q, s) set sparsity.\n\nAll of the description in the public member function RevSparseHes(q, s)\napplies.\n\n\\param set_type\nis a std::set<size_t> value.\nThis argument is used to dispatch to the proper source\ncode depending on the value of SetVector::value_type.\n\n\\param transpose\nSee RevSparseHes(q, s).\n\n\\param q\nSee RevSparseHes(q, s).\n\n\\param s\nSee RevSparseHes(q, s).\n\n\\param h\nis the return value for the corresponding call to RevSparseJac(q, s).\n*/\ntemplate <class Base, class RecBase>\ntemplate <class SetVector>\nvoid ADFun<Base,RecBase>::RevSparseHesCase(\n    const std::set<size_t>&   set_type         ,\n    bool                      transpose        ,\n    size_t                    q                ,\n    const SetVector&          s                ,\n    SetVector&                h                )\n{\n    // used to identify the RecBase type in calls to sweeps\n    RecBase not_used_rec_base(0.0);\n    //\n    size_t n = Domain();\n# ifndef NDEBUG\n    size_t m = Range();\n# endif\n    //\n    if( transpose )\n        h.resize(n);\n    else\n        h.resize(q);\n\n    CPPAD_ASSERT_KNOWN(\n        for_jac_sparse_set_.n_set() > 0,\n        \"RevSparseHes: previous stored call to ForSparseJac did not \"\n        \"use std::set<size_t> for the elements of r.\"\n    );\n    CPPAD_ASSERT_UNKNOWN( for_jac_sparse_pack_.n_set() == 0 );\n    CPPAD_ASSERT_UNKNOWN( for_jac_sparse_set_.n_set() == num_var_tape_  );\n    //\n    // temporary indices\n    size_t i, j;\n    std::set<size_t>::const_iterator itr_1;\n\n    // check SetVector is Simple Vector class with sets for elements\n    CheckSimpleVector<std::set<size_t>, SetVector>(\n        local::one_element_std_set<size_t>(), local::two_element_std_set<size_t>()\n    );\n\n    CPPAD_ASSERT_KNOWN(\n        q == for_jac_sparse_set_.end(),\n        \"RevSparseHes: q is not equal to its value\\n\"\n        \"in the previous call to ForSparseJac with this ADFun object.\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        s.size() == 1,\n        \"RevSparseHes: size of s is not equal to one.\"\n    );\n\n    // Array that will hold reverse Jacobian dependency flag.\n    // Initialize as true for the dependent variables.\n    local::pod_vector<bool> RevJac(num_var_tape_);\n    for(i = 0; i < num_var_tape_; i++)\n        RevJac[i] = false;\n    itr_1 = s[0].begin();\n    while( itr_1 != s[0].end() )\n    {   i = *itr_1++;\n        CPPAD_ASSERT_KNOWN(\n            i < m,\n            \"RevSparseHes: an element of the set s[0] has value \"\n            \"greater than or equal m\"\n        );\n        CPPAD_ASSERT_UNKNOWN( dep_taddr_[i] < num_var_tape_ );\n        RevJac[ dep_taddr_[i] ] = true;\n    }\n\n\n    // vector of sets that will hold reverse Hessain values\n    local::sparse::list_setvec rev_hes_pattern;\n    rev_hes_pattern.resize(num_var_tape_, q);\n\n    // compute the Hessian sparsity patterns\n    local::sweep::rev_hes(\n        &play_,\n        num_var_tape_,\n        for_jac_sparse_set_,\n        RevJac.data(),\n        rev_hes_pattern,\n        not_used_rec_base\n\n    );\n\n    // return values corresponding to independent variables\n    // j is index corresponding to reverse mode partial\n    CPPAD_ASSERT_UNKNOWN( size_t(h.size()) == q || transpose );\n    CPPAD_ASSERT_UNKNOWN( size_t(h.size()) == n || ! transpose );\n    for(j = 0; j < n; j++)\n    {   CPPAD_ASSERT_UNKNOWN( ind_taddr_[j] < num_var_tape_ );\n        CPPAD_ASSERT_UNKNOWN( ind_taddr_[j] == j + 1 );\n        CPPAD_ASSERT_UNKNOWN( play_.GetOp( ind_taddr_[j] ) == local::InvOp );\n\n        // extract the result from rev_hes_pattern\n        // and add corresponding elements to result sets in h\n        CPPAD_ASSERT_UNKNOWN( rev_hes_pattern.end() == q );\n        local::sparse::list_setvec::const_iterator itr_2(rev_hes_pattern, j+1);\n        i = *itr_2;\n        while( i < q )\n        {   if( transpose )\n                h[j].insert(i);\n            else\n                h[i].insert(j);\n            i = *(++itr_2);\n        }\n    }\n}\n\n// ===========================================================================\n// RevSparseHes\n\n/*!\nUser API for Hessian sparsity patterns using reverse mode.\n\nThe C++ source code corresponding to this operation is\n\\verbatim\n    h = f.RevSparseHes(q, r)\n\\endverbatim\n\n\\tparam Base\nis the base type for this recording.\n\n\\tparam SetVector\nis a simple vector with elements of type bool\nor std::set<size_t>.\n\n\\param transpose\nis true (false) if is is equal to \\f$ H(x) \\f$ (\\f$ H(x)^T \\f$)\nwhere\n\\f[\n    H(x) = R^T (S * F)^{(2)} (x)\n\\f]\nwhere \\f$ F \\f$ is the function corresponding to the operation sequence\nand x is any argument value.\n\n\\param q\nis the value of q in the\nby the previous call of the form\n\\verbatim\n    f.ForSparseJac(q, r, packed)\n\\endverbatim\nThe value r in this call is a sparsity pattern for the matrix \\f$ R \\f$.\nThe type of the element of r for the previous call to ForSparseJac\nmust be the same as the type of the elements of s.\n\n\\param s\nis a vector with size m that specifies the sparsity pattern\nfor the vector \\f$ S \\f$,\nwhere m is the number of dependent variables\ncorresponding to the operation sequence stored in play.\n\n\\return\nIf transpose is false (true),\nthe return vector is a sparsity pattern for \\f$ H(x) \\f$ (\\f$ H(x)^T \\f$).\n\\f[\n    H(x) = R^T ( S * F)^{(2)} (x)\n\\f]\nwhere \\f$ F \\f$ is the function corresponding to the operation sequence\nand x is any argument value.\n*/\n\ntemplate <class Base, class RecBase>\ntemplate <class SetVector>\nSetVector ADFun<Base,RecBase>::RevSparseHes(\n    size_t q,  const SetVector& s, bool transpose\n)\n{\n    SetVector h;\n    typedef typename SetVector::value_type Set_type;\n\n    // Should check to make sure q is same as in previous call to\n    // forward sparse Jacobian.\n    RevSparseHesCase(\n        Set_type()    ,\n        transpose     ,\n        q             ,\n        s             ,\n        h\n    );\n\n    return h;\n}\n// ===========================================================================\n// RevSparseHesCheckpoint\n/*!\nHessian sparsity patterns calculation used by checkpoint functions.\n\n\\tparam Base\nis the base type for this recording.\n\n\\param transpose\nis true (false) h is equal to \\f$ H(x) \\f$ (\\f$ H(x)^T \\f$)\nwhere\n\\f[\n    H(x) = R^T (S * F)^{(2)} (x)\n\\f]\nwhere \\f$ F \\f$ is the function corresponding to the operation sequence\nand \\f$ x \\f$ is any argument value.\n\n\\param q\nis the value of q in the by the previous call of the form\n\\verbatim\n    f.ForSparseJac(q, r)\n\\endverbatim\nThe value r in this call is a sparsity pattern for the matrix \\f$ R \\f$.\n\n\\param s\nis a vector with size m that specifies the sparsity pattern\nfor the vector \\f$ S \\f$,\nwhere m is the number of dependent variables\ncorresponding to the operation sequence stored in play_.\n\n\\param h\nThe input size and elements of h do not matter.\nOn output, h is the sparsity pattern for the matrix \\f$ H(x) \\f$\nor \\f$ H(x)^T \\f$ depending on transpose.\n\n\\par Assumptions\nThe forward jacobian sparsity pattern must be currently stored\nin this ADFUN object.\n*/\ntemplate <class Base, class RecBase>\nvoid ADFun<Base,RecBase>::RevSparseHesCheckpoint(\n    size_t                        q         ,\n    vector<bool>&                 s         ,\n    bool                          transpose ,\n    local::sparse::list_setvec&   h         )\n{\n    // used to identify the RecBase type in calls to sweeps\n    RecBase not_used_rec_base(0.0);\n    //\n    size_t n = Domain();\n    size_t m = Range();\n\n    // checkpoint functions should get this right\n    CPPAD_ASSERT_UNKNOWN( for_jac_sparse_pack_.n_set() == 0 );\n    CPPAD_ASSERT_UNKNOWN( for_jac_sparse_set_.n_set() == num_var_tape_ );\n    CPPAD_ASSERT_UNKNOWN( for_jac_sparse_set_.end()   == q );\n    CPPAD_ASSERT_UNKNOWN( s.size()                    == m );\n\n    // Array that holds the reverse Jacobiain dependency flags.\n    // Initialize as true for dependent variables, false for others.\n    local::pod_vector<bool> RevJac(num_var_tape_);\n    for(size_t i = 0; i < num_var_tape_; i++)\n        RevJac[i] = false;\n    for(size_t i = 0; i < m; i++)\n    {   CPPAD_ASSERT_UNKNOWN( dep_taddr_[i] < num_var_tape_ )\n        RevJac[ dep_taddr_[i] ] = s[i];\n    }\n\n    // holds reverse Hessian sparsity pattern for all variables\n    local::sparse::list_setvec rev_hes_pattern;\n    rev_hes_pattern.resize(num_var_tape_, q);\n\n    // compute Hessian sparsity pattern for all variables\n    local::sweep::rev_hes(\n        &play_,\n        num_var_tape_,\n        for_jac_sparse_set_,\n        RevJac.data(),\n        rev_hes_pattern,\n        not_used_rec_base\n\n    );\n\n    // dimension the return value\n    if( transpose )\n        h.resize(n, q);\n    else\n        h.resize(q, n);\n\n    // j is index corresponding to reverse mode partial\n    for(size_t j = 0; j < n; j++)\n    {   CPPAD_ASSERT_UNKNOWN( ind_taddr_[j] < num_var_tape_ );\n\n        // ind_taddr_[j] is operator taddr for j-th independent variable\n        CPPAD_ASSERT_UNKNOWN( ind_taddr_[j] == j + 1 );\n        CPPAD_ASSERT_UNKNOWN( play_.GetOp( ind_taddr_[j] ) == local::InvOp );\n\n        // extract the result from rev_hes_pattern\n        CPPAD_ASSERT_UNKNOWN( rev_hes_pattern.end() == q );\n        local::sparse::list_setvec::const_iterator itr(rev_hes_pattern, j + 1);\n        size_t i = *itr;\n        while( i < q )\n        {   if( transpose )\n                h.post_element(j,  i);\n            else\n                h.post_element(i, j);\n            i = *(++itr);\n        }\n    }\n    for(size_t i = 0; i < h.n_set(); ++i)\n        h.process_post(i);\n}\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/rev_sparse_jac.hpp",
    "content": "# ifndef CPPAD_CORE_REV_SPARSE_JAC_HPP\n# define CPPAD_CORE_REV_SPARSE_JAC_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin RevSparseJac}\n\nJacobian Sparsity Pattern: Reverse Mode\n#######################################\n\nSyntax\n******\n| *s* = *f* . ``RevSparseJac`` ( *q* , *r* )\n| *s* = *f* . ``RevSparseJac`` ( *q* , *r* , *transpose* , *dependency* )\n\nPurpose\n*******\nWe use :math:`F : \\B{R}^n \\rightarrow \\B{R}^m` to denote the\n:ref:`glossary@AD Function` corresponding to *f* .\nFor a fixed matrix :math:`R \\in \\B{R}^{q \\times m}`,\nthe Jacobian of :math:`R * F( x )`\nwith respect to :math:`x` is\n\n.. math::\n\n    S(x) = R * F^{(1)} ( x )\n\nGiven a\n:ref:`glossary@Sparsity Pattern`\nfor :math:`R`,\n``RevSparseJac`` returns a sparsity pattern for the :math:`S(x)`.\n\nf\n*\nThe object *f* has prototype\n\n    ``ADFun`` < *Base* > *f*\n\nx\n*\nIf the operation sequence in *f* is\n:ref:`glossary@Operation@Independent` of\nthe independent variables in :math:`x \\in \\B{R}^n`,\nthe sparsity pattern is valid for all values of\n(even if it has :ref:`CondExp-name` or :ref:`VecAD-name` operations).\n\nq\n*\nThe argument *q* has prototype\n\n    ``size_t`` *q*\n\nIt specifies the number of rows in\n:math:`R \\in \\B{R}^{q \\times m}` and the\nJacobian :math:`S(x) \\in \\B{R}^{q \\times n}`.\n\ntranspose\n*********\nThe argument *transpose* has prototype\n\n    ``bool`` *transpose*\n\nThe default value ``false`` is used when *transpose* is not present.\n\ndependency\n**********\nThe argument *dependency* has prototype\n\n    ``bool`` *dependency*\n\nIf *dependency* is true,\nthe :ref:`dependency.cpp@Dependency Pattern`\n(instead of sparsity pattern) is computed.\n\nr\n*\nThe argument *s* has prototype\n\n    ``const`` *SetVector* & *r*\n\nsee :ref:`RevSparseJac@SetVector` below.\n\ntranspose false\n===============\nIf *r* has elements of type ``bool`` ,\nits size is :math:`q * m`.\nIf it has elements of type ``std::set<size_t>`` ,\nits size is *q* and all its set elements are between\nzero and :math:`m - 1`.\nIt specifies a\n:ref:`glossary@Sparsity Pattern`\nfor the matrix :math:`R \\in \\B{R}^{q \\times m}`.\n\ntranspose true\n==============\nIf *r* has elements of type ``bool`` ,\nits size is :math:`m * q`.\nIf it has elements of type ``std::set<size_t>`` ,\nits size is *m* and all its set elements are between\nzero and :math:`q - 1`.\nIt specifies a\n:ref:`glossary@Sparsity Pattern`\nfor the matrix :math:`R^\\R{T} \\in \\B{R}^{m \\times q}`.\n\ns\n*\nThe return value *s* has prototype\n\n    *SetVector* *s*\n\nsee :ref:`RevSparseJac@SetVector` below.\n\ntranspose false\n===============\nIf it has elements of type ``bool`` ,\nits size is :math:`q * n`.\nIf it has elements of type ``std::set<size_t>`` ,\nits size is *q* and all its set elements are between\nzero and :math:`n - 1`.\nIt specifies a\n:ref:`glossary@Sparsity Pattern`\nfor the matrix :math:`S(x) \\in {q \\times n}`.\n\ntranspose true\n==============\nIf it has elements of type ``bool`` ,\nits size is :math:`n * q`.\nIf it has elements of type ``std::set<size_t>`` ,\nits size is *n* and all its set elements are between\nzero and :math:`q - 1`.\nIt specifies a\n:ref:`glossary@Sparsity Pattern`\nfor the matrix :math:`S(x)^\\R{T} \\in {n \\times q}`.\n\nSetVector\n*********\nThe type *SetVector* must be a :ref:`SimpleVector-name` class with\n:ref:`elements of type<SimpleVector@Elements of Specified Type>`\n``bool`` or ``std::set<size_t>`` ;\nsee :ref:`glossary@Sparsity Pattern` for a discussion\nof the difference.\n\nEntire Sparsity Pattern\n***********************\nSuppose that :math:`q = m` and\n:math:`R` is the :math:`m \\times m` identity matrix.\nIn this case,\nthe corresponding value for *s* is a\nsparsity pattern for the Jacobian :math:`S(x) = F^{(1)} ( x )`.\n\nExample\n*******\n{xrst_toc_hidden\n    example/sparse/rev_sparse_jac.cpp\n}\nThe file\n:ref:`rev_sparse_jac.cpp-name`\ncontains an example and test of this operation.\n\n{xrst_end RevSparseJac}\n-----------------------------------------------------------------------------\n*/\n\n# include <cppad/local/std_set.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\n\\file core/rev_sparse_jac.hpp\nReverse mode Jacobian sparsity patterns.\n*/\n// =========================================================================\n// RevSparseJacCase\n\n/*!\nPrivate helper function for RevSparseJac(q, r, transpose) boolean sparsity.\n\nAll of the description in the public member function\n RevSparseJac(q, r, transpose) apply.\n\n\\param set_type\nis a bool value.\nThis argument is used to dispatch to the proper source code\ndepending on the value of SetVector::value_type.\n\n\\param transpose\nSee RevSparseJac(q, r, transpose, dependency)\n\n\\param dependency\nSee RevSparseJac(q, r, transpose, dependency)\n\n\\param q\nSee RevSparseJac(q, r, transpose, dependency)\n\n\\param r\nSee RevSparseJac(q, r, transpose, dependency)\n\n\\param s\nis the return value for the corresponding call to\nRevSparseJac(q, r, transpose).\n*/\n\ntemplate <class Base, class RecBase>\ntemplate <class SetVector>\nvoid ADFun<Base,RecBase>::RevSparseJacCase(\n    bool                set_type          ,\n    bool                transpose         ,\n    bool                dependency        ,\n    size_t              q                 ,\n    const SetVector&    r                 ,\n    SetVector&          s                 )\n{\n    // used to identify the RecBase type in calls to sweeps\n    RecBase not_used_rec_base(0.0);\n    //\n    size_t n = Domain();\n    size_t m = Range();\n\n    // dimension of the result vector\n    s.resize( q * n );\n\n    // check SetVector is Simple Vector class with bool elements\n    CheckSimpleVector<bool, SetVector>();\n    //\n    CPPAD_ASSERT_KNOWN(\n        q > 0,\n        \"RevSparseJac: q is not greater than zero\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t(r.size()) == q * m,\n        \"RevSparseJac: size of r is not equal to\\n\"\n        \"q times range dimension for ADFun object.\"\n    );\n    //\n    // vector of sets that will hold the results\n    local::sparse::pack_setvec    var_sparsity;\n    var_sparsity.resize(num_var_tape_, q);\n\n    // The sparsity pattern corresponding to the dependent variables\n    for(size_t i = 0; i < m; i++)\n    {   CPPAD_ASSERT_UNKNOWN( dep_taddr_[i] < num_var_tape_ );\n        if( transpose )\n        {   for(size_t j = 0; j < q; j++) if( r[ i * q + j ] )\n                var_sparsity.post_element( dep_taddr_[i], j );\n        }\n        else\n        {   for(size_t j = 0; j < q; j++) if( r[ j * m + i ] )\n                var_sparsity.post_element( dep_taddr_[i], j );\n        }\n    }\n    // process posts\n    for(size_t i = 0; i < m; i++)\n        var_sparsity.process_post( dep_taddr_[i] );\n\n    // evaluate the sparsity patterns\n    local::sweep::rev_jac(\n        &play_,\n        dependency,\n        n,\n        num_var_tape_,\n        var_sparsity,\n        not_used_rec_base\n\n    );\n\n    // return values corresponding to dependent variables\n    CPPAD_ASSERT_UNKNOWN( size_t(s.size()) == q * n );\n    for(size_t j = 0; j < n; j++)\n    {   CPPAD_ASSERT_UNKNOWN( ind_taddr_[j] == (j+1) );\n\n        // ind_taddr_[j] is operator taddr for j-th independent variable\n        CPPAD_ASSERT_UNKNOWN( play_.GetOp( ind_taddr_[j] ) == local::InvOp );\n\n        // extract the result from var_sparsity\n        if( transpose )\n        {   for(size_t i = 0; i < q; i++)\n                s[ j * q + i ] = false;\n        }\n        else\n        {   for(size_t i = 0; i < q; i++)\n                s[ i * n + j ] = false;\n        }\n        CPPAD_ASSERT_UNKNOWN( var_sparsity.end() == q );\n        local::sparse::pack_setvec::const_iterator itr(var_sparsity, j+1);\n        size_t i = *itr;\n        while( i < q )\n        {   if( transpose )\n                s[ j * q + i ] = true;\n            else\n                s[ i * n + j ] = true;\n            i  = *(++itr);\n        }\n    }\n}\n\n/*!\nPrivate helper function for RevSparseJac(q, r, transpose) set sparsity\n\nAll of the description in the public member function\n RevSparseJac(q, r, transpose) apply.\n\n\\param set_type\nis a std::set<size_t> object.\nThis argument is used to dispatch to the proper source code\ndepending on the value of SetVector::value_type.\n\n\\param transpose\nSee RevSparseJac(q, r, transpose, dependency)\n\n\\param dependency\nSee RevSparseJac(q, r, transpose, dependency)\n\n\\param q\nSee RevSparseJac(q, r, transpose, dependency)\n\n\\param r\nSee RevSparseJac(q, r, transpose, dependency)\n\n\\param s\nis the return value for the corresponding call to RevSparseJac(q, r, transpose)\n*/\n\ntemplate <class Base, class RecBase>\ntemplate <class SetVector>\nvoid ADFun<Base,RecBase>::RevSparseJacCase(\n    const std::set<size_t>&      set_type          ,\n    bool                         transpose         ,\n    bool                         dependency        ,\n    size_t                       q                 ,\n    const SetVector&             r                 ,\n    SetVector&                   s                 )\n{\n    // used to identify the RecBase type in calls to sweeps\n    RecBase not_used_rec_base(0.0);\n    //\n    // dimension of the result vector\n    if( transpose )\n        s.resize( Domain() );\n    else\n        s.resize( q );\n\n    // temporary indices\n    std::set<size_t>::const_iterator itr_1;\n\n    // check SetVector is Simple Vector class with sets for elements\n    CheckSimpleVector<std::set<size_t>, SetVector>(\n        local::one_element_std_set<size_t>(), local::two_element_std_set<size_t>()\n    );\n\n    // domain dimensions for F\n    size_t n = ind_taddr_.size();\n    size_t m = dep_taddr_.size();\n\n    CPPAD_ASSERT_KNOWN(\n        q > 0,\n        \"RevSparseJac: q is not greater than zero\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t(r.size()) == q || transpose,\n        \"RevSparseJac: size of r is not equal to q and transpose is false.\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t(r.size()) == m || ! transpose,\n        \"RevSparseJac: size of r is not equal to m and transpose is true.\"\n    );\n\n    // vector of lists that will hold the results\n    local::sparse::list_setvec   var_sparsity;\n    var_sparsity.resize(num_var_tape_, q);\n\n    // The sparsity pattern corresponding to the dependent variables\n    if( transpose )\n    {   for(size_t i = 0; i < m; i++)\n        {   itr_1 = r[i].begin();\n            while(itr_1 != r[i].end())\n            {   size_t j = *itr_1++;\n                CPPAD_ASSERT_KNOWN(\n                j < q,\n                \"RevSparseJac: transpose is true and element of the set\\n\"\n                \"r[i] has value greater than or equal q.\"\n                );\n                CPPAD_ASSERT_UNKNOWN( dep_taddr_[i] < num_var_tape_ );\n                var_sparsity.post_element( dep_taddr_[i], j );\n            }\n        }\n    }\n    else\n    {   for(size_t i = 0; i < q; i++)\n        {   itr_1 = r[i].begin();\n            while(itr_1 != r[i].end())\n            {   size_t j = *itr_1++;\n                CPPAD_ASSERT_KNOWN(\n                j < m,\n                \"RevSparseJac: transpose is false and element of the set\\n\"\n                \"r[i] has value greater than or equal range dimension.\"\n                );\n                CPPAD_ASSERT_UNKNOWN( dep_taddr_[j] < num_var_tape_ );\n                var_sparsity.post_element( dep_taddr_[j], i );\n            }\n        }\n    }\n    // process posts\n    for(size_t i = 0; i < m; i++)\n        var_sparsity.process_post( dep_taddr_[i] );\n\n    // evaluate the sparsity patterns\n    local::sweep::rev_jac(\n        &play_,\n        dependency,\n        n,\n        num_var_tape_,\n        var_sparsity,\n        not_used_rec_base\n\n    );\n\n    // return values corresponding to dependent variables\n    CPPAD_ASSERT_UNKNOWN( size_t(s.size()) == q || transpose );\n    CPPAD_ASSERT_UNKNOWN( size_t(s.size()) == n || ! transpose );\n    for(size_t j = 0; j < n; j++)\n    {   CPPAD_ASSERT_UNKNOWN( ind_taddr_[j] == (j+1) );\n\n        // ind_taddr_[j] is operator taddr for j-th independent variable\n        CPPAD_ASSERT_UNKNOWN( play_.GetOp( ind_taddr_[j] ) == local::InvOp );\n\n        CPPAD_ASSERT_UNKNOWN( var_sparsity.end() == q );\n        local::sparse::list_setvec::const_iterator itr_2(var_sparsity, j+1);\n        size_t i = *itr_2;\n        while( i < q )\n        {   if( transpose )\n                s[j].insert(i);\n            else\n                s[i].insert(j);\n            i = *(++itr_2);\n        }\n    }\n}\n\n// =========================================================================\n// RevSparseJac\n/*!\nUser API for Jacobian sparsity patterns using reverse mode.\n\nThe C++ source code corresponding to this operation is\n\\verbatim\n    s = f.RevSparseJac(q, r, transpose, dependency)\n\\endverbatim\n\n\\tparam Base\nis the base type for this recording.\n\n\\tparam SetVector\nis a simple vector with elements of type bool.\nor std::set<size_t>.\n\n\\param q\nis the number of rows in the matrix \\f$ R \\f$.\n\n\\param r\nis a sparsity pattern for the matrix \\f$ R \\f$.\n\n\\param transpose\nare the sparsity patterns for \\f$ R \\f$ and \\f$ S(x) \\f$ transposed.\n\n\\param dependency\nAre the derivatives with respect to left and right of the expression below\nconsidered to be non-zero:\n\\code\n    CondExpRel(left, right, if_true, if_false)\n\\endcode\nThis is used by the optimizer to obtain the correct dependency relations.\n\n\n\\return\nIf transpose is false (true), the return value is a sparsity pattern\nfor \\f$ S(x) \\f$ (\\f$ S(x)^T \\f$) where\n\\f[\n    S(x) = R * F^{(1)} (x)\n\\f]\nand \\f$ F \\f$ is the function corresponding to the operation sequence\nand x is any argument value.\nIf SetVector::value_type is bool,\nthe return value has size \\f$ q * n \\f$ ( \\f$ n * q \\f$).\nIf SetVector::value_type is std::set<size_t>,\nthe return value has size \\f$ q \\f$ ( \\f$ n \\f$)\nand with all its elements between zero and \\f$ n - 1 \\f$ (\\f$ q - 1 \\f$).\n*/\ntemplate <class Base, class RecBase>\ntemplate <class SetVector>\nSetVector ADFun<Base,RecBase>::RevSparseJac(\n    size_t              q          ,\n    const SetVector&    r          ,\n    bool                transpose  ,\n    bool                dependency )\n{\n    SetVector s;\n    typedef typename SetVector::value_type Set_type;\n\n    RevSparseJacCase(\n        Set_type()    ,\n        transpose     ,\n        dependency    ,\n        q             ,\n        r             ,\n        s\n    );\n    return s;\n}\n// ===========================================================================\n// RevSparseJacCheckpoint\n/*!\nReverse mode Jacobian sparsity calculation used by checkpoint functions.\n\n\\tparam Base\nis the base type for this recording.\n\n\\param transpose\nis true (false) s is equal to \\f$ S(x) \\f$ (\\f$ S(x)^T \\f$)\nwhere\n\\f[\n    S(x) = R * F^{(1)} (x)\n\\f]\nwhere \\f$ F \\f$ is the function corresponding to the operation sequence\nand \\f$ x \\f$ is any argument value.\n\n\\param q\nis the number of rows in the matrix \\f$ R \\f$.\n\n\\param r\nis a sparsity pattern for the matrix \\f$ R \\f$.\n\n\\param transpose\nare the sparsity patterns for \\f$ R \\f$ and \\f$ S(x) \\f$ transposed.\n\n\\param dependency\nAre the derivatives with respect to left and right of the expression below\nconsidered to be non-zero:\n\\code\n    CondExpRel(left, right, if_true, if_false)\n\\endcode\nThis is used by the optimizer to obtain the correct dependency relations.\n\n\\param s\nThe input size and elements of s do not matter.\nOn output, s is the sparsity pattern for the matrix \\f$ S(x) \\f$\nor \\f$ S(x)^T \\f$ depending on transpose.\n\n*/\ntemplate <class Base, class RecBase>\nvoid ADFun<Base,RecBase>::RevSparseJacCheckpoint(\n    size_t                               q          ,\n    const local::sparse::list_setvec&    r          ,\n    bool                                 transpose  ,\n    bool                                 dependency ,\n    local::sparse::list_setvec&          s          )\n{\n    // used to identify the RecBase type in calls to sweeps\n    RecBase not_used_rec_base(0.0);\n    //\n    size_t n = Domain();\n    size_t m = Range();\n\n# ifndef NDEBUG\n    if( transpose )\n    {   CPPAD_ASSERT_UNKNOWN( r.n_set() == m );\n        CPPAD_ASSERT_UNKNOWN( r.end()   == q );\n    }\n    else\n    {   CPPAD_ASSERT_UNKNOWN( r.n_set() == q );\n        CPPAD_ASSERT_UNKNOWN( r.end()   == m );\n    }\n    for(size_t i = 0; i < m; i++)\n        CPPAD_ASSERT_UNKNOWN( dep_taddr_[i] < num_var_tape_ );\n# endif\n\n    // holds reverse Jacobian sparsity pattern for all variables\n    local::sparse::list_setvec var_sparsity;\n    var_sparsity.resize(num_var_tape_, q);\n\n    // set sparsity pattern for dependent variables\n    if( transpose )\n    {   for(size_t i = 0; i < m; i++)\n        {   local::sparse::list_setvec::const_iterator itr(r, i);\n            size_t j = *itr;\n            while( j < q )\n            {   var_sparsity.post_element( dep_taddr_[i], j );\n                j = *(++itr);\n            }\n        }\n    }\n    else\n    {   for(size_t j = 0; j < q; j++)\n        {   local::sparse::list_setvec::const_iterator itr(r, j);\n            size_t i = *itr;\n            while( i < m )\n            {   var_sparsity.post_element( dep_taddr_[i], j );\n                i = *(++itr);\n            }\n        }\n    }\n    // process posts\n    for(size_t i = 0; i < m; i++)\n        var_sparsity.process_post( dep_taddr_[i] );\n\n    // evaluate the sparsity pattern for all variables\n    local::sweep::rev_jac(\n        &play_,\n        dependency,\n        n,\n        num_var_tape_,\n        var_sparsity,\n        not_used_rec_base\n\n    );\n\n    // dimension the return value\n    if( transpose )\n        s.resize(n, m);\n    else\n        s.resize(m, n);\n\n    // return values corresponding to independent variables\n    for(size_t j = 0; j < n; j++)\n    {   CPPAD_ASSERT_UNKNOWN( ind_taddr_[j] == (j+1) );\n\n        // ind_taddr_[j] is operator taddr for j-th independent variable\n        CPPAD_ASSERT_UNKNOWN( play_.GetOp( ind_taddr_[j] ) == local::InvOp );\n\n        // extract the result from var_sparsity\n        CPPAD_ASSERT_UNKNOWN( var_sparsity.end() == q );\n        local::sparse::list_setvec::const_iterator itr(var_sparsity, j+1);\n        size_t i = *itr;\n        while( i < q )\n        {   if( transpose )\n                s.post_element(j, i);\n            else\n                s.post_element(i, j);\n            i  = *(++itr);\n        }\n    }\n    // process posts\n    for(size_t i = 0; i < s.n_set(); i++)\n        s.process_post(i);\n\n}\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/rev_two.hpp",
    "content": "# ifndef CPPAD_CORE_REV_TWO_HPP\n# define CPPAD_CORE_REV_TWO_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin RevTwo}\n{xrst_spell\n    ddw\n}\n\nReverse Mode Second Partial Derivative Driver\n#############################################\n\nSyntax\n******\n| *ddw* = *f* . ``RevTwo`` ( *x* , *i* , *j* )\n\nPurpose\n*******\nWe use :math:`F : \\B{R}^n \\rightarrow \\B{R}^m` to denote the\n:ref:`glossary@AD Function` corresponding to *f* .\nThe syntax above sets\n\n.. math::\n\n    ddw [ k * p + \\ell ]\n    =\n    \\DD{ F_{i[ \\ell ]} }{ x_{j[ \\ell ]} }{ x_k } (x)\n\nfor :math:`k = 0 , \\ldots , n-1`\nand :math:`\\ell = 0 , \\ldots , p`,\nwhere :math:`p` is the size of the vectors *i* and *j* .\n\nf\n*\nThe object *f* has prototype\n\n    ``ADFun`` < *Base* > *f*\n\nNote that the :ref:`ADFun-name` object *f* is not ``const``\n(see :ref:`RevTwo@RevTwo Uses Forward` below).\n\nx\n*\nThe argument *x* has prototype\n\n    ``const`` *BaseVector* & *x*\n\n(see :ref:`RevTwo@BaseVector` below)\nand its size\nmust be equal to *n* , the dimension of the\n:ref:`fun_property@Domain` space for *f* .\nIt specifies\nthat point at which to evaluate the partial derivatives listed above.\n\ni\n*\nThe argument *i* has prototype\n\n    ``const`` *SizeVector_t* & *i*\n\n(see :ref:`RevTwo@SizeVector_t` below)\nWe use *p* to denote the size of the vector *i* .\nAll of the indices in *i*\nmust be less than *m* , the dimension of the\n:ref:`fun_property@Range` space for *f* ; i.e.,\nfor :math:`\\ell = 0 , \\ldots , p-1`, :math:`i[ \\ell ]  < m`.\n\nj\n*\nThe argument *j* has prototype\n\n    ``const`` *SizeVector_t* & *j*\n\n(see :ref:`RevTwo@SizeVector_t` below)\nand its size must be equal to *p* ,\nthe size of the vector *i* .\nAll of the indices in *j*\nmust be less than *n* ; i.e.,\nfor :math:`\\ell = 0 , \\ldots , p-1`, :math:`j[ \\ell ]  < n`.\n\nddw\n***\nThe result *ddw* has prototype\n\n    *BaseVector* *ddw*\n\n(see :ref:`RevTwo@BaseVector` below)\nand its size is :math:`n * p`.\nIt contains the requested partial derivatives; to be specific,\nfor :math:`k = 0 , \\ldots , n - 1`\nand :math:`\\ell = 0 , \\ldots , p - 1`\n\n.. math::\n\n    ddw [ k * p + \\ell ]\n    =\n    \\DD{ F_{i[ \\ell ]} }{ x_{j[ \\ell ]} }{ x_k } (x)\n\nBaseVector\n**********\nThe type *BaseVector* must be a :ref:`SimpleVector-name` class with\n:ref:`elements of type Base<SimpleVector@Elements of Specified Type>` .\nThe routine :ref:`CheckSimpleVector-name` will generate an error message\nif this is not the case.\n\nSizeVector_t\n************\nThe type *SizeVector_t* must be a :ref:`SimpleVector-name` class with\n:ref:`elements of type size_t<SimpleVector@Elements of Specified Type>` .\nThe routine :ref:`CheckSimpleVector-name` will generate an error message\nif this is not the case.\n\nRevTwo Uses Forward\n*******************\nAfter each call to :ref:`Forward-name` ,\nthe object *f* contains the corresponding\n:ref:`Taylor coefficients<glossary@Taylor Coefficient>` .\nAfter a call to ``RevTwo`` ,\nthe zero order Taylor coefficients correspond to\n*f* . ``Forward`` (0, *x* )\nand the other coefficients are unspecified.\n\nExamples\n********\n{xrst_toc_hidden\n    example/general/rev_two.cpp\n}\nThe routine\n:ref:`RevTwo<rev_two.cpp-name>` is both an example and test.\nIt returns ``true`` , if it succeeds and ``false`` otherwise.\n\n{xrst_end RevTwo}\n-----------------------------------------------------------------------------\n*/\n\n//  BEGIN CppAD namespace\nnamespace CppAD {\n\ntemplate <class Base, class RecBase>\ntemplate <class BaseVector, class SizeVector_t>\nBaseVector ADFun<Base,RecBase>::RevTwo(\n    const BaseVector   &x,\n    const SizeVector_t &i,\n    const SizeVector_t &j)\n{   size_t i1;\n    size_t j1;\n    size_t k;\n    size_t l;\n\n    size_t n = Domain();\n    size_t m = Range();\n    size_t p = i.size();\n\n    // check BaseVector is Simple Vector class with Base elements\n    CheckSimpleVector<Base, BaseVector>();\n\n    // check SizeVector_t is Simple Vector class with size_t elements\n    CheckSimpleVector<size_t, SizeVector_t>();\n\n    CPPAD_ASSERT_KNOWN(\n        x.size() == n,\n        \"RevTwo: Length of x not equal domain dimension for f.\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        i.size() == j.size(),\n        \"RevTwo: Length of the i and j vectors are not equal.\"\n    );\n    // point at which we are evaluating the second partials\n    Forward(0, x);\n\n    // dimension the return value\n    BaseVector ddw(n * p);\n\n    // direction vector in argument space\n    BaseVector dx(n);\n    for(j1 = 0; j1 < n; j1++)\n        dx[j1] = Base(0.0);\n\n    // direction vector in range space\n    BaseVector w(m);\n    for(i1 = 0; i1 < m; i1++)\n        w[i1] = Base(0.0);\n\n    // place to hold the results of a reverse calculation\n    BaseVector r(n * 2);\n\n    // check the indices in i and j\n    for(l = 0; l < p; l++)\n    {   i1 = i[l];\n        j1 = j[l];\n        CPPAD_ASSERT_KNOWN(\n        i1 < m,\n        \"RevTwo: an element of i not less than range dimension for f.\"\n        );\n        CPPAD_ASSERT_KNOWN(\n        j1 < n,\n        \"RevTwo: an element of j not less than domain dimension for f.\"\n        );\n    }\n\n    // loop over all forward directions\n    for(j1 = 0; j1 < n; j1++)\n    {   // first order forward mode calculation done\n        bool first_done = false;\n        for(l = 0; l < p; l++) if( j[l] == j1 )\n        {   if( ! first_done )\n            {   first_done = true;\n\n                // first order forward mode in j1 direction\n                dx[j1] = Base(1.0);\n                Forward(1, dx);\n                dx[j1] = Base(0.0);\n            }\n            // execute a reverse in this component direction\n            i1    = i[l];\n            w[i1] = Base(1.0);\n            r     = Reverse(2, w);\n            w[i1] = Base(0.0);\n\n            // place the reverse result in return value\n            for(k = 0; k < n; k++)\n                ddw[k * p + l] = r[k * 2 + 1];\n        }\n    }\n    return ddw;\n}\n\n} // END CppAD namespace\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/reverse.hpp",
    "content": "# ifndef CPPAD_CORE_REVERSE_HPP\n# define CPPAD_CORE_REVERSE_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <algorithm>\n# include <cppad/local/pod_vector.hpp>\n# include <cppad/local/play/sequential_iterator.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\n\\file core/reverse.hpp\nCompute derivatives using reverse mode.\n*/\n\n\n/*!\nUse reverse mode to compute derivative of forward mode Taylor coefficients.\n\nThe function\n\\f$ X : {\\bf R} \\times {\\bf R}^{n \\times q} \\rightarrow {\\bf R} \\f$\nis defined by\n\\f[\nX(t , u) = \\sum_{k=0}^{q-1} u^{(k)} t^k\n\\f]\nThe function\n\\f$ Y : {\\bf R} \\times {\\bf R}^{n \\times q} \\rightarrow {\\bf R} \\f$\nis defined by\n\\f[\nY(t , u) = F[ X(t, u) ]\n\\f]\nThe function\n\\f$ W : {\\bf R}^{n \\times q} \\rightarrow {\\bf R} \\f$ is defined by\n\\f[\nW(u) = \\sum_{k=0}^{q-1} ( w^{(k)} )^{\\rm T}\n\\frac{1}{k !} \\frac{ \\partial^k } { t^k } Y(0, u)\n\\f]\n\n\\tparam Base\nbase type for the operator; i.e., this operation sequence was recorded\nusing AD< Base > and computations by this routine are done using type\n Base.\n\n\\tparam BaseVector\nis a Simple Vector class with elements of type Base.\n\n\\param q\nis the number of the number of Taylor coefficients that are being\ndifferentiated (per variable).\n\n\\param w\nis the weighting for each of the Taylor coefficients corresponding\nto dependent variables.\nIf the argument w has size <tt>m * q </tt>,\nfor \\f$ k = 0 , \\ldots , q-1 \\f$ and \\f$ i = 0, \\ldots , m-1 \\f$,\n\\f[\n    w_i^{(k)} = w [ i * q + k ]\n\\f]\nIf the argument w has size m ,\nfor \\f$ k = 0 , \\ldots , q-1 \\f$ and \\f$ i = 0, \\ldots , m-1 \\f$,\n\\f[\nw_i^{(k)} = \\left\\{ \\begin{array}{ll}\n    w [ i ] & {\\rm if} \\; k = q-1\n    \\\\\n    0       & {\\rm otherwise}\n\\end{array} \\right.\n\\f]\n\n\\return\nIs a vector \\f$ dw \\f$ such that\nfor \\f$ j = 0 , \\ldots , n-1 \\f$ and\n\\f$ k = 0 , \\ldots , q-1 \\f$\n\\f[\n    dw[ j * q + k ] = W^{(1)} ( x )_{j,k}\n\\f]\nwhere the matrix \\f$ x \\f$ is the value for \\f$ u \\f$\nthat corresponding to the forward mode Taylor coefficients\nfor the independent variables as specified by previous calls to Forward.\n\n*/\ntemplate <class Base, class RecBase>\ntemplate <class BaseVector>\nBaseVector ADFun<Base,RecBase>::Reverse(size_t q, const BaseVector &w)\n{   // used to identify the RecBase type in calls to sweeps\n    RecBase not_used_rec_base(0.0);\n\n    // constants\n    const Base zero(0);\n\n    // temporary indices\n    size_t i, j, k;\n\n    // number of independent variables\n    size_t n = ind_taddr_.size();\n\n    // number of dependent variables\n    size_t m = dep_taddr_.size();\n\n    // check BaseVector is Simple Vector class with Base type elements\n    CheckSimpleVector<Base, BaseVector>();\n\n    CPPAD_ASSERT_KNOWN(\n        size_t(w.size()) == m || size_t(w.size()) == (m * q),\n        \"Argument w to Reverse does not have length equal to\\n\"\n        \"the dimension of the range or dimension of range times q.\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        q > 0,\n        \"The first argument to Reverse must be greater than zero.\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        num_order_taylor_ >= q,\n        \"Less than q Taylor coefficients are currently stored\"\n        \" in this ADFun object.\"\n    );\n    // special case where multiple forward directions have been computed,\n    // but we are only using the one direction zero order results\n    if( (q == 1) && (num_direction_taylor_ > 1) )\n    {   num_order_taylor_ = 1;        // number of orders to copy\n        size_t c = cap_order_taylor_; // keep the same capacity setting\n        size_t r = 1;                 // only keep one direction\n        capacity_order(c, r);\n    }\n    CPPAD_ASSERT_KNOWN(\n        num_direction_taylor_ == 1,\n        \"Reverse mode for Forward(q, r, xq) with more than one direction\"\n        \"\\n(r > 1) is not yet supported for q > 1.\"\n    );\n\n    // initialize entire Partial matrix to zero\n    local::pod_vector_maybe<Base> Partial(num_var_tape_ * q);\n    for(i = 0; i < num_var_tape_; i++)\n        for(j = 0; j < q; j++)\n            Partial[i * q + j] = zero;\n\n    // set the dependent variable direction\n    // (use += because two dependent variables can point to same location)\n    if( size_t(w.size()) == m )\n    {   for(i = 0; i < m; ++i)\n        {   CPPAD_ASSERT_UNKNOWN( dep_taddr_[i] < num_var_tape_  );\n            Partial[dep_taddr_[i] * q + q - 1] += w[i];\n        }\n    }\n    else\n    {   CPPAD_ASSERT_UNKNOWN( size_t(w.size()) == m * q );\n        for(i = 0; i < m; i++)\n        {   CPPAD_ASSERT_UNKNOWN( dep_taddr_[i] < num_var_tape_  );\n            for(k = 0; k < q; k++)\n                Partial[ dep_taddr_[i] * q + k ] += w[i * q + k ];\n        }\n    }\n    // evaluate the derivatives\n    CPPAD_ASSERT_UNKNOWN( cskip_op_.size() == play_.num_var_op() );\n    CPPAD_ASSERT_UNKNOWN( load_op2var_.size()  == play_.num_var_load() );\n    local::play::const_sequential_iterator play_itr = play_.end();\n    local::sweep::reverse(\n        num_var_tape_,\n        &play_,\n        cap_order_taylor_,\n        taylor_.data(),\n        q,\n        Partial.data(),\n        cskip_op_.data(),\n        load_op2var_,\n        play_itr,\n        not_used_rec_base\n    );\n\n    // return the derivative values\n    BaseVector value(n * q);\n    for(j = 0; j < n; j++)\n    {   CPPAD_ASSERT_UNKNOWN( ind_taddr_[j] < num_var_tape_  );\n\n        // independent variable taddr equals its operator taddr\n        CPPAD_ASSERT_UNKNOWN( play_.GetOp( ind_taddr_[j] ) == local::InvOp );\n\n        // by the Reverse Identity Theorem\n        // partial of y^{(k)} w.r.t. u^{(0)} is equal to\n        // partial of y^{(q-1)} w.r.t. u^{(q - 1 - k)}\n        if( size_t(w.size()) == m )\n        {   for(k = 0; k < q; k++)\n                value[j * q + k ] =\n                    Partial[ind_taddr_[j] * q + q - 1 - k];\n        }\n        else\n        {   for(k = 0; k < q; k++)\n                value[j * q + k ] =\n                    Partial[ind_taddr_[j] * q + k];\n        }\n    }\n    CPPAD_ASSERT_KNOWN( ! ( hasnan(value) && check_for_nan_ ) ,\n        \"dw = f.Reverse(q, w): has a nan,\\n\"\n        \"but none of its Taylor coefficients are nan.\"\n    );\n\n    return value;\n}\n\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/sign.hpp",
    "content": "# ifndef CPPAD_CORE_SIGN_HPP\n# define CPPAD_CORE_SIGN_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin sign}\n{xrst_spell\n    rl\n}\nThe Sign: sign\n##############\n\nSyntax\n******\n| *y* = ``sign`` ( *x* )\n\nDescription\n***********\nEvaluates the ``sign`` function which is defined by\n\n.. math::\n\n    {\\rm sign} (x) =\n    \\left\\{ \\begin{array}{rl}\n        +1 & {\\rm if} \\; x > 0 \\\\\n        0  & {\\rm if} \\; x = 0 \\\\\n        -1 & {\\rm if} \\; x < 0\n    \\end{array} \\right.\n\nx, y\n****\nSee the :ref:`unary_standard_math@Possible Types`\nfor a unary standard math function.\n\nAtomic\n******\nThis is an :ref:`atomic operation<glossary@Operation@Atomic>` .\n\nDerivative\n**********\nCppAD computes the derivative of the ``sign`` function as zero for all\nargument values *x* .\nThe correct mathematical derivative is different and\nis given by\n\n.. math::\n\n    {\\rm sign}^{(1)} (x) =  2 \\delta (x)\n\nwhere :math:`\\delta (x)` is the Dirac Delta function.\n\nExample\n*******\n{xrst_toc_hidden\n    example/general/sign.cpp\n}\nThe file\n:ref:`sign.cpp-name`\ncontains an example and test of this function.\n\n{xrst_end sign}\n-------------------------------------------------------------------------------\n*/\n\n//  BEGIN CppAD namespace\nnamespace CppAD {\n\ntemplate <class Base>\nAD<Base> AD<Base>::sign_me (void) const\n{\n    AD<Base> result;\n    result.value_ = sign(value_);\n    CPPAD_ASSERT_UNKNOWN( Parameter(result) );\n\n    // check if there is a recording in progress\n    local::ADTape<Base>* tape = AD<Base>::tape_ptr();\n    if( tape == nullptr )\n        return result;\n\n    // check if operand is a constant parameter\n    if( tape_id_ != tape->id_ )\n        return result;\n\n    if(ad_type_ == dynamic_enum)\n    {   // dynamic parameter argument\n        result.taddr_   = tape->Rec_.put_dyn_par(\n            result.value_, local::sign_dyn, taddr_\n        );\n        result.tape_id_  = tape_id_;\n        result.ad_type_  = dynamic_enum;\n    }\n    else\n    {   // variable argument\n        CPPAD_ASSERT_UNKNOWN( local::NumRes(local::SignOp) == 1 );\n        CPPAD_ASSERT_UNKNOWN( local::NumArg(local::SignOp) == 1 );\n\n        // corresponding operand address\n        tape->Rec_.PutArg(taddr_);\n\n        // put operator in the tape\n        result.taddr_ = tape->Rec_.PutOp(local::SignOp);\n\n        // make result a variable\n        result.tape_id_ = tape->id_;\n        result.ad_type_ = variable_enum;\n    }\n    return result;\n}\n\ntemplate <class Base>\nAD<Base> sign(const AD<Base> &x)\n{   return x.sign_me();\n}\ntemplate <class Base>\nAD<Base> sign(const VecAD_reference<Base> &x)\n{   return x.ADBase().sign_me(); }\n\n} // END CppAD namespace\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/sparse.hpp",
    "content": "# ifndef CPPAD_CORE_SPARSE_HPP\n# define CPPAD_CORE_SPARSE_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n//\n# include <cppad/core/for_jac_sparsity.hpp>\n# include <cppad/core/rev_jac_sparsity.hpp>\n//\n# include <cppad/core/for_hes_sparsity.hpp>\n# include <cppad/core/rev_hes_sparsity.hpp>\n//\n# include <cppad/core/for_sparse_jac.hpp>\n# include <cppad/core/rev_sparse_jac.hpp>\n//\n# include <cppad/core/for_sparse_hes.hpp>\n# include <cppad/core/rev_sparse_hes.hpp>\n//\n# include <cppad/core/sparse_jac.hpp>\n# include <cppad/core/sparse_hes.hpp>\n//\n# include <cppad/core/sparse_jacobian.hpp>\n# include <cppad/core/sparse_hessian.hpp>\n//\n# include <cppad/core/subgraph_sparsity.hpp>\n# include <cppad/core/subgraph_reverse.hpp>\n# include <cppad/core/subgraph_jac_rev.hpp>\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/sparse_hes.hpp",
    "content": "# ifndef CPPAD_CORE_SPARSE_HES_HPP\n# define CPPAD_CORE_SPARSE_HES_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin sparse_hes}\n{xrst_spell\n    nr\n    rc\n    rcv\n}\n\nComputing Sparse Hessians\n#########################\n\nSyntax\n******\n| *n_sweep* = *f* . ``sparse_hes`` (\n| |tab| *x* , *w* , *subset* , *pattern* , *coloring* , *work*\n| )\n\nPurpose\n*******\nWe use :math:`F : \\B{R}^n \\rightarrow \\B{R}^m` to denote the\nfunction corresponding to *f* .\nHere *n* is the :ref:`fun_property@Domain` size,\nand *m* is the :ref:`fun_property@Range` size, or *f* .\nThe syntax above takes advantage of sparsity when computing the Hessian\n\n.. math::\n\n    H(x) = \\dpow{2}{x} \\sum_{i=0}^{m-1} w_i F_i (x)\n\nIn the sparse case, this should be faster and take less memory than\n:ref:`Hessian-name` .\nThe matrix element :math:`H_{i,j} (x)` is the second partial of\n:math:`w^\\R{T} F (x)` with respect to :math:`x_i` and :math:`x_j`.\n\nSizeVector\n**********\nThe type *SizeVector* is a :ref:`SimpleVector-name` class with\n:ref:`elements of type<SimpleVector@Elements of Specified Type>`\n``size_t`` .\n\nBaseVector\n**********\nThe type *BaseVector* is a :ref:`SimpleVector-name` class with\n:ref:`elements of type<SimpleVector@Elements of Specified Type>`\n``size_t`` .\n\nf\n*\nThis object has prototype\n\n    ``ADFun`` < *Base* > *f*\n\nNote that the Taylor coefficients stored in *f* are affected\nby this operation; see\n:ref:`sparse_hes@Uses Forward` below.\n\nx\n*\nThis argument has prototype\n\n    ``const`` *BaseVector* & *x*\n\nand its size is *n* .\nIt specifies the point at which to evaluate the Hessian\n:math:`H(x)`.\n\nw\n*\nThis argument has prototype\n\n    ``const`` *BaseVector* & *w*\n\nand its size is *m* .\nIt specifies the weight for each of the components of :math:`F(x)`;\ni.e. :math:`w_i` is the weight for :math:`F_i (x)`.\n\nsubset\n******\nThis argument has prototype\n\n    ``sparse_rcv`` < *SizeVector* , *BaseVector* >& *subset*\n\nIts row size and column size is *n* ; i.e.,\n*subset* . ``nr`` () == *n* and *subset* . ``nc`` () == *n* .\nIt specifies which elements of the Hessian are computed.\n\n#. The input value of its value vector\n   *subset* . ``val`` () does not matter.\n   Upon return it contains the value of the corresponding elements\n   of the Hessian.\n#. All of the row, column pairs in *subset* must also appear in\n   *pattern* ; i.e., they must be possibly non-zero.\n#. The Hessian is symmetric, so one has a choice as to which off diagonal\n   elements to put in *subset* .\n   It will probably be more efficient if one makes this choice so that\n   the there are more entries in each non-zero column of *subset* ;\n   see :ref:`sparse_hes@n_sweep` below.\n\npattern\n*******\nThis argument has prototype\n\n    ``const sparse_rc`` < *SizeVector* >& *pattern*\n\nIts row size and column size is *n* ; i.e.,\n*pattern* . ``nr`` () == *n* and *pattern* . ``nc`` () == *n* .\nIt is a sparsity pattern for the Hessian :math:`H(x)`.\nIf the *i*-th row (*j*-th column) does not appear in *subset* ,\nthe *i*-th row (*j*-th column) of *pattern* does not matter\nand need not be computed.\nThis argument is not used (and need not satisfy any conditions),\nwhen :ref:`sparse_hes@work` is non-empty.\n\nsubset\n======\nIf the *i*-th row and *i*-th column do not appear in *subset* ,\nthe *i*-th row and column of *pattern* do not matter.\nIn this case the *i-th*-th row and column may have no entries in\n*pattern* even though they are possibly non-zero in :math:`H(x)`.\n(This can be used to reduce the amount of computation required to find\n*pattern* .)\n\ncoloring\n********\nThe coloring algorithm determines which rows and columns\ncan be computed during the same sweep.\nThis field has prototype\n\n    ``const std::string&`` *coloring*\n\nThis value only matters when work is empty; i.e.,\nafter the *work* constructor or *work* . ``clear`` () .\n\ncppad.symmetric\n===============\nThis coloring takes advantage of the fact that the Hessian matrix\nis symmetric when find a coloring that requires fewer\n:ref:`sweeps<sparse_hes@n_sweep>` .\n\ncppad.general\n=============\nThis is the same as the sparse Jacobian\n:ref:`sparse_jac@coloring@cppad` method\nwhich does not take advantage of symmetry.\n\ncolpack.symmetric\n=================\nIf :ref:`colpack_prefix-name` was specified on the\n:ref:`cmake@CMake Command` line,\nyou can set *coloring* to ``colpack.symmetric`` .\nThis also takes advantage of the fact that the Hessian matrix is symmetric.\n\ncolpack.general\n===============\nIf :ref:`colpack_prefix-name` was specified on the\n:ref:`cmake@CMake Command` line,\nyou can set *coloring* to ``colpack.general`` .\nThis is the same as the sparse Jacobian\n:ref:`sparse_jac@coloring@colpack` method\nwhich does not take advantage of symmetry.\n\ncolpack.star Deprecated 2017-06-01\n==================================\nThe ``colpack.star`` method is deprecated.\nIt is the same as the ``colpack.symmetric`` method\nwhich should be used instead.\n\nwork\n****\nThis argument has prototype\n\n    ``sparse_hes_work&`` *work*\n\nWe refer to its initial value,\nand its value after *work* . ``clear`` () , as empty.\nIf it is empty, information is stored in *work* .\nThis can be used to reduce computation when\na future call is for the same object *f* ,\nand the same subset of the Hessian.\nIn fact, it can be used with a different *f*\nand a different *subset* provided that Hessian sparsity pattern\nfor *f* and the sparsity pattern in *subset* are the same.\nIf either of these values change, use *work* . ``clear`` () to\nempty this structure.\n\nn_sweep\n*******\nThe return value *n_sweep* has prototype\n\n    ``size_t`` *n_sweep*\n\nIt is the number of first order forward sweeps\nused to compute the requested Hessian values.\nEach first forward sweep is followed by a second order reverse sweep\nso it is also the number of reverse sweeps.\nIt is also the number of colors determined by the coloring method\nmentioned above.\nThis is proportional to the total computational work,\nnot counting the zero order forward sweep,\nor combining multiple columns and rows into a single sweep.\n\nUses Forward\n************\nAfter each call to :ref:`Forward-name` ,\nthe object *f* contains the corresponding\n:ref:`Taylor coefficients<glossary@Taylor Coefficient>` .\nAfter a call to ``sparse_hes``\nthe zero order coefficients correspond to\n\n    *f* . ``Forward`` (0, *x* )\n\nAll the other forward mode coefficients are unspecified.\n\nExample\n*******\n{xrst_toc_hidden\n    example/sparse/sparse_hes.cpp\n}\nThe files :ref:`sparse_hes.cpp-name`\nis an example and test of ``sparse_hes`` .\nIt returns ``true`` , if it succeeds, and ``false`` otherwise.\n\nSubset Hessian\n**************\nThe routine\n:ref:`sparse_sub_hes.cpp-name`\nis an example and test that compute a subset of a sparse Hessian.\nIt returns ``true`` , for success, and ``false`` otherwise.\n\n{xrst_end sparse_hes}\n*/\n# include <cppad/core/cppad_assert.hpp>\n# include <cppad/local/sparse/internal.hpp>\n# include <cppad/local/color_general.hpp>\n# include <cppad/local/color_symmetric.hpp>\n\n/*!\n\\file sparse_hes.hpp\nSparse Hessian calculation routines.\n*/\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n\n/*!\nClass used to hold information used by Sparse Hessian routine in this file,\nso it does not need to be recomputed every time.\n*/\nclass sparse_hes_work {\n    public:\n        /// row and column indices for return values\n        /// (some may be reflected by symmetric coloring algorithms)\n        CppAD::vector<size_t> row;\n        CppAD::vector<size_t> col;\n        /// indices that sort the row and col arrays by color\n        CppAD::vector<size_t> order;\n        /// results of the coloring algorithm\n        CppAD::vector<size_t> color;\n\n        /// constructor\n        sparse_hes_work(void)\n        { }\n        /// inform CppAD that this information needs to be recomputed\n        void clear(void)\n        {\n            row.clear();\n            col.clear();\n            order.clear();\n            color.clear();\n        }\n};\n// ----------------------------------------------------------------------------\n/*!\nCalculate sparse Hessians using forward mode\n\n\\tparam Base\nthe base type for the recording that is stored in the ADFun object.\n\n\\tparam SizeVector\na simple vector class with elements of type size_t.\n\n\\tparam BaseVector\na simple vector class with elements of type Base.\n\n\\param x\na vector of length n, the number of independent variables in f\n(this ADFun object).\n\n\\param w\na vector of length m, the number of dependent variables in f\n(this ADFun object).\n\n\\param subset\nspedifies the subset of the sparsity pattern where the Hessian is evaluated.\nsubset.nr() == n,\nsubset.nc() == n.\n\n\\param pattern\nis a sparsity pattern for the Hessian of w^T * f;\npattern.nr() == n,\npattern.nc() == n,\nwhere m is number of dependent variables in f.\n\n\\param coloring\ndetermines which coloring algorithm is used.\nThis must be cppad.symmetric, cppad.general, colpack.symmetric,\nor colpack.star.\n\n\\param work\nthis structure must be empty, or contain the information stored\nby a previous call to sparse_hes.\nThe previous call must be for the same ADFun object f\nand the same subset.\n\n\\return\nThis is the number of first order forward\n(and second order reverse) sweeps used to compute the Hessian.\n*/\ntemplate <class Base, class RecBase>\ntemplate <class SizeVector, class BaseVector>\nsize_t ADFun<Base,RecBase>::sparse_hes(\n    const BaseVector&                    x        ,\n    const BaseVector&                    w        ,\n    sparse_rcv<SizeVector , BaseVector>& subset   ,\n    const sparse_rc<SizeVector>&         pattern  ,\n    const std::string&                   coloring ,\n    sparse_hes_work&                     work     )\n{   size_t n = Domain();\n    //\n    CPPAD_ASSERT_KNOWN(\n        subset.nr() == n,\n        \"sparse_hes: subset.nr() not equal domain dimension for f\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        subset.nc() == n,\n        \"sparse_hes: subset.nc() not equal domain dimension for f\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t( x.size() ) == n,\n        \"sparse_hes: x.size() not equal domain dimension for f\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t( w.size() ) == Range(),\n        \"sparse_hes: w.size() not equal range dimension for f\"\n    );\n    //\n    // work information\n    vector<size_t>& row(work.row);\n    vector<size_t>& col(work.col);\n    vector<size_t>& color(work.color);\n    vector<size_t>& order(work.order);\n    //\n    // subset information\n    const SizeVector& subset_row( subset.row() );\n    const SizeVector& subset_col( subset.col() );\n    //\n    // point at which we are evaluating the Hessian\n    Forward(0, x);\n    //\n    // number of elements in the subset\n    size_t K = subset.nnz();\n    //\n    // check for case were there is nothing to do\n    // (except for call to Forward(0, x)\n    if( K == 0 )\n        return 0;\n    //\n# ifndef NDEBUG\n    if( color.size() != 0 )\n    {   CPPAD_ASSERT_KNOWN(\n            color.size() == n,\n            \"sparse_hes: work is non-empty and conditions have changed\"\n        );\n        CPPAD_ASSERT_KNOWN(\n            row.size() == K,\n            \"sparse_hes: work is non-empty and conditions have changed\"\n        );\n        CPPAD_ASSERT_KNOWN(\n            col.size() == K,\n            \"sparse_hes: work is non-empty and conditions have changed\"\n        );\n        //\n        for(size_t k = 0; k < K; k++)\n        {   bool ok = row[k] == subset_row[k] && col[k] == subset_col[k];\n            ok     |= row[k] == subset_col[k] && col[k] == subset_row[k];\n            CPPAD_ASSERT_KNOWN(\n                ok,\n                \"sparse_hes: work is non-empty and conditions have changed\"\n            );\n        }\n    }\n# endif\n    //\n    // check for case where input work is empty\n    if( color.size() == 0 )\n    {   // compute work color and order vectors\n        CPPAD_ASSERT_KNOWN(\n            pattern.nr() == n,\n            \"sparse_hes: pattern.nr() not equal domain dimension for f\"\n        );\n        CPPAD_ASSERT_KNOWN(\n            pattern.nc() == n,\n            \"sparse_hes: pattern.nc() not equal domain dimension for f\"\n        );\n        //\n        // initialize work row, col to be same as subset row, col\n        row.resize(K);\n        col.resize(K);\n        // cannot assign vectors because may be of different types\n        // (SizeVector and CppAD::vector<size_t>)\n        for(size_t k = 0; k < K; k++)\n        {   row[k] = subset_row[k];\n            col[k] = subset_col[k];\n        }\n        //\n        // convert pattern to an internal version of its transpose\n        local::pod_vector<size_t> internal_index(n);\n        for(size_t j = 0; j < n; j++)\n            internal_index[j] = j;\n        bool transpose   = true;\n        bool zero_empty  = false;\n        bool input_empty = true;\n        local::sparse::list_setvec internal_pattern;\n        internal_pattern.resize(n, n);\n        local::sparse::set_internal_pattern(zero_empty, input_empty,\n            transpose, internal_index, internal_pattern, pattern\n        );\n        //\n        // execute coloring algorithm\n        // (we are using transpose because coloring groups rows, not columns)\n        color.resize(n);\n        if( coloring == \"cppad.general\" )\n            local::color_general_cppad(internal_pattern, col, row, color);\n        else if( coloring == \"cppad.symmetric\" )\n            local::color_symmetric_cppad(internal_pattern, col, row, color);\n        else if( coloring == \"colpack.general\" )\n        {\n# if CPPAD_HAS_COLPACK\n            local::color_general_colpack(internal_pattern, col, row, color);\n# else\n            CPPAD_ASSERT_KNOWN(\n                false,\n                \"sparse_hes: coloring = colpack.star \"\n                \"and colpack_prefix not in cmake command line.\"\n            );\n# endif\n        }\n        else if(\n            coloring == \"colpack.symmetric\" ||\n            coloring == \"colpack.star\"\n        )\n        {\n# if CPPAD_HAS_COLPACK\n            local::color_symmetric_colpack(internal_pattern, col, row, color);\n# else\n            CPPAD_ASSERT_KNOWN(\n                false,\n                \"sparse_hes: coloring = colpack.symmetric or colpack.star \"\n                \"and colpack_prefix not in cmake command line.\"\n            );\n# endif\n        }\n        else CPPAD_ASSERT_KNOWN(\n            false,\n            \"sparse_hes: coloring is not valid.\"\n        );\n        //\n        // put sorting indices in color order\n        SizeVector key(K);\n        order.resize(K);\n        for(size_t k = 0; k < K; k++)\n            key[k] = color[ col[k] ];\n        index_sort(key, order);\n    }\n    // Base versions of zero and one\n    Base one(1.0);\n    Base zero(0.0);\n    //\n    size_t n_color = 1;\n    for(size_t j = 0; j < n; j++) if( color[j] < n )\n        n_color = std::max<size_t>(n_color, color[j] + 1);\n    //\n    // initialize the return Hessian values as zero\n    for(size_t k = 0; k < K; k++)\n        subset.set(k, zero);\n    //\n    // direction vector for calls to first order forward\n    BaseVector dx(n);\n    //\n    // return values for calls to second order reverse\n    BaseVector ddw(2 * n);\n    //\n    // loop over colors\n    size_t k = 0;\n    for(size_t ell = 0; ell < n_color; ell++)\n    if( k  == K )\n    {   // kludge because colpack returns colors that are not used\n        // (it does not know about the subset corresponding to row, col)\n        CPPAD_ASSERT_UNKNOWN(\n            coloring == \"colpack.general\" ||\n            coloring == \"colpack.symmetric\" ||\n            coloring == \"colpack.star\"\n        );\n    }\n    else if( color[ col[ order[k] ] ] != ell )\n    {   // kludge because colpack returns colors that are not used\n        // (it does not know about the subset corresponding to row, col)\n        CPPAD_ASSERT_UNKNOWN(\n            coloring == \"colpack.general\" ||\n            coloring == \"colpack.symmetric\" ||\n            coloring == \"colpack.star\"\n        );\n    }\n    else\n    {   CPPAD_ASSERT_UNKNOWN( color[ col[ order[k] ] ] == ell );\n        //\n        // combine all columns with this color\n        for(size_t j = 0; j < n; j++)\n        {   dx[j] = zero;\n            if( color[j] == ell )\n                dx[j] = one;\n        }\n        // call forward mode for all these rows at once\n        Forward(1, dx);\n        //\n        // evaluate derivative of w^T * F'(x) * dx\n        ddw = Reverse(2, w);\n        //\n        // set the corresponding components of the result\n        while( k < K && color[ col[order[k]] ] == ell )\n        {   size_t index = row[ order[k] ] * 2 + 1;\n            subset.set(order[k], ddw[index] );\n            k++;\n        }\n    }\n    // check that all the required entries have been set\n    CPPAD_ASSERT_UNKNOWN( k == K );\n    return n_color;\n}\n\n} // END_CPPAD_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/sparse_hessian.hpp",
    "content": "# ifndef CPPAD_CORE_SPARSE_HESSIAN_HPP\n# define CPPAD_CORE_SPARSE_HESSIAN_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin sparse_hessian}\n{xrst_spell\n    valarray\n}\n\nSparse Hessian\n##############\n\nSyntax\n******\n| *hes* = *f* . ``SparseHessian`` ( *x* , *w* )\n| *hes* = *f* . ``SparseHessian`` ( *x* , *w* , *p* )\n| *n_sweep* = *f* . ``SparseHessian`` ( *x* , *w* , *p* , *row* , *col* , *hes* , *work* )\n\nPurpose\n*******\nWe use :math:`n` for the :ref:`fun_property@Domain` size,\nand :math:`m` for the :ref:`fun_property@Range` size of *f* .\nWe use :math:`F : \\B{R}^n \\rightarrow \\B{R}^m` do denote the\n:ref:`glossary@AD Function`\ncorresponding to *f* .\nThe syntax above sets *hes* to the Hessian\n\n.. math::\n\n    H(x) = \\dpow{2}{x} \\sum_{i=1}^m w_i F_i (x)\n\nThis routine takes advantage of the sparsity of the Hessian\nin order to reduce the amount of computation necessary.\nIf *row* and *col* are present, it also takes\nadvantage of the reduced set of elements of the Hessian that\nneed to be computed.\nOne can use speed tests (e.g. :ref:`speed_test-name` )\nto verify that results are computed faster\nthan when using the routine :ref:`Hessian-name` .\n\nf\n*\nThe object *f* has prototype\n\n    ``ADFun`` < *Base* > *f*\n\nNote that the :ref:`ADFun-name` object *f* is not ``const``\n(see :ref:`sparse_hessian@Uses Forward` below).\n\nx\n*\nThe argument *x* has prototype\n\n    ``const`` *BaseVector* & *x*\n\n(see :ref:`sparse_hessian@BaseVector` below)\nand its size\nmust be equal to *n* , the dimension of the\n:ref:`fun_property@Domain` space for *f* .\nIt specifies\nthat point at which to evaluate the Hessian.\n\nw\n*\nThe argument *w* has prototype\n\n    ``const`` *BaseVector* & *w*\n\nand size :math:`m`.\nIt specifies the value of :math:`w_i` in the expression\nfor *hes* .\nThe more components of :math:`w` that are identically zero,\nthe more sparse the resulting Hessian may be (and hence the more efficient\nthe calculation of *hes* may be).\n\np\n*\nThe argument *p* is optional and has prototype\n\n    ``const`` *SetVector* & *p*\n\n(see :ref:`sparse_hessian@SetVector` below)\nIf it has elements of type ``bool`` ,\nits size is :math:`n * n`.\nIf it has elements of type ``std::set<size_t>`` ,\nits size is :math:`n` and all its set elements are between\nzero and :math:`n - 1`.\nIt specifies a\n:ref:`glossary@Sparsity Pattern`\nfor the Hessian :math:`H(x)`.\n\nPurpose\n=======\nIf this sparsity pattern does not change between calls to\n``SparseHessian`` , it should be faster to calculate *p* once and\npass this argument to ``SparseHessian`` .\nIf you specify *p* , CppAD will use the same\ntype of sparsity representation\n(vectors of ``bool`` or vectors of ``std::set<size_t>`` )\nfor its internal calculations.\nOtherwise, the representation\nfor the internal calculations is unspecified.\n\nwork\n====\nIf you specify *work* in the calling sequence,\nit is not necessary to keep the sparsity pattern; see the heading\n:ref:`sparse_hessian@work@p` under the *work* description.\n\nColumn Subset\n=============\nIf the arguments *row* and *col* are present,\nand :ref:`sparse_hessian@work@color_method` is\n``cppad.general`` or ``cppad.symmetric`` ,\nit is not necessary to compute the entire sparsity pattern.\nOnly the following subset of column values will matter:\n\n    { *col* [ *k* ] : *k* = 0 , ... , *K* ``-1`` }\n\n.\n\nrow, col\n********\nThe arguments *row* and *col* are optional and have prototype\n\n| |tab| ``const`` *SizeVector* & *row*\n| |tab| ``const`` *SizeVector* & *col*\n\n(see :ref:`sparse_hessian@SizeVector` below).\nThey specify which rows and columns of :math:`H (x)` are\nreturned and in what order.\nWe use :math:`K` to denote the value *hes* . ``size`` ()\nwhich must also equal the size of *row* and *col* .\nFurthermore,\nfor :math:`k = 0 , \\ldots , K-1`, it must hold that\n:math:`row[k] < n` and :math:`col[k] < n`.\nIn addition,\nall of the :math:`(row[k], col[k])` pairs must correspond to a true value\nin the sparsity pattern *p* .\n\nhes\n***\nThe result *hes* has prototype\n\n    *BaseVector* *hes*\n\nIn the case where *row* and *col* are not present,\nthe size of *hes* is :math:`n * n` and\nits size is :math:`n * n`.\nIn this case, for :math:`i = 0 , \\ldots , n - 1`\nand :math:`ell = 0 , \\ldots , n - 1`\n\n.. math::\n\n    hes [ j * n + \\ell ] = \\DD{ w^{\\rm T} F }{ x_j }{ x_\\ell } ( x )\n\nIn the case where the arguments *row* and *col* are present,\nwe use :math:`K` to denote the size of *hes* .\nThe input value of its elements does not matter.\nUpon return, for :math:`k = 0 , \\ldots , K - 1`,\n\n.. math::\n\n    hes [ k ] = \\DD{ w^{\\rm T} F }{ x_j }{ x_\\ell } (x)\n    \\; , \\;\n    \\; {\\rm where} \\;\n    j = row[k]\n    \\; {\\rm and } \\;\n    \\ell = col[k]\n\nwork\n****\nIf this argument is present, it has prototype\n\n    ``sparse_hessian_work&`` *work*\n\nThis object can only be used with the routines ``SparseHessian`` .\nDuring its the first use, information is stored in *work* .\nThis is used to reduce the work done by future calls to ``SparseHessian``\nwith the same *f* , *p* , *row* , and *col* .\nIf a future call is made where any of these values have changed,\nyou must first call *work* . ``clear`` ()\nto inform CppAD that this information needs to be recomputed.\n\ncolor_method\n============\nThe coloring algorithm determines which rows and columns\ncan be computed during the same sweep.\nThis field has prototype\n\n    ``std::string`` *work* . ``color_method``\n\nThis value only matters on the first call to ``sparse_hessian`` that\nfollows the *work* constructor or a call to\n*work* . ``clear`` () .\n\n    ``\"cppad.symmetric\"``\n\nThis is the default coloring method (after a constructor or ``clear()`` ).\nIt takes advantage of the fact that the Hessian matrix\nis symmetric to find a coloring that requires fewer\n:ref:`sweeps<sparse_hessian@n_sweep>` .\n\n    ``\"cppad.general\"``\n\nThis is the same as the ``\"cppad\"`` method for the\n:ref:`sparse_jacobian<sparse_jacobian@work@color_method>` calculation.\n\n    ``\"colpack.symmetric\"``\n\nThis method requires that\n:ref:`colpack_prefix-name` was specified on the\n:ref:`cmake@CMake Command` line.\nIt also takes advantage of the fact that the Hessian matrix is symmetric.\n\n    ``\"colpack.general\"``\n\nThis is the same as the ``\"colpack\"`` method for the\n:ref:`sparse_jacobian<sparse_jacobian@work@color_method>` calculation.\n\ncolpack.star Deprecated 2017-06-01\n==================================\nThe ``colpack.star`` method is deprecated.\nIt is the same as the ``colpack.symmetric``\nwhich should be used instead.\n\np\n=\nIf *work* is present, and it is not the first call after\nits construction or a clear,\nthe sparsity pattern *p* is not used.\nThis enables one to free the sparsity pattern\nand still compute corresponding sparse Hessians.\n\nn_sweep\n*******\nThe return value *n_sweep* has prototype\n\n    ``size_t`` *n_sweep*\n\nIt is the number of first order forward sweeps\nused to compute the requested Hessian values.\nEach first forward sweep is followed by a second order reverse sweep\nso it is also the number of reverse sweeps.\nThis is proportional to the total work that ``SparseHessian`` does,\nnot counting the zero order forward sweep,\nor the work to combine multiple columns into a single\nforward-reverse sweep pair.\n\nBaseVector\n**********\nThe type *BaseVector* must be a :ref:`SimpleVector-name` class with\n:ref:`elements of type<SimpleVector@Elements of Specified Type>`\n*Base* .\nThe routine :ref:`CheckSimpleVector-name` will generate an error message\nif this is not the case.\n\nSetVector\n*********\nThe type *SetVector* must be a :ref:`SimpleVector-name` class with\n:ref:`elements of type<SimpleVector@Elements of Specified Type>`\n``bool`` or ``std::set<size_t>`` ;\nsee :ref:`glossary@Sparsity Pattern` for a discussion\nof the difference.\nThe routine :ref:`CheckSimpleVector-name` will generate an error message\nif this is not the case.\n\nRestrictions\n============\nIf *SetVector* has elements of ``std::set<size_t>`` ,\nthen *p* [ *i* ] must return a reference (not a copy) to the\ncorresponding set.\nAccording to section 26.3.2.3 of the 1998 C++ standard,\n``std::valarray< std::set<size_t> >`` does not satisfy\nthis condition.\n\nSizeVector\n**********\nThe type *SizeVector* must be a :ref:`SimpleVector-name` class with\n:ref:`elements of type<SimpleVector@Elements of Specified Type>`\n``size_t`` .\nThe routine :ref:`CheckSimpleVector-name` will generate an error message\nif this is not the case.\n\nUses Forward\n************\nAfter each call to :ref:`Forward-name` ,\nthe object *f* contains the corresponding\n:ref:`Taylor coefficients<glossary@Taylor Coefficient>` .\nAfter a call to any of the sparse Hessian routines,\nthe zero order Taylor coefficients correspond to\n*f* . ``Forward`` (0, *x* )\nand the other coefficients are unspecified.\n{xrst_toc_hidden\n    example/sparse/sparse_hessian.cpp\n    example/sparse/sub_sparse_hes.cpp\n    example/sparse/sparse_sub_hes.cpp\n}\n\nExample\n*******\nThe routine\n:ref:`sparse_hessian.cpp-name`\nis examples and tests of ``sparse_hessian`` .\nIt return ``true`` , if it succeeds and ``false`` otherwise.\n\nSubset Hessian\n**************\nThe routine\n:ref:`sub_sparse_hes.cpp-name`\nis an example and test that compute a sparse Hessian\nfor a subset of the variables.\nIt returns ``true`` , for success, and ``false`` otherwise.\n\n{xrst_end sparse_hessian}\n-----------------------------------------------------------------------------\n*/\n# include <cppad/local/std_set.hpp>\n# include <cppad/local/color_general.hpp>\n# include <cppad/local/color_symmetric.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\n\\file sparse_hessian.hpp\nSparse Hessian driver routine and helper functions.\n*/\n// ===========================================================================\n/*!\nclass used by SparseHessian to hold information\nso it does not need to be recomputed.\n*/\nclass sparse_hessian_work {\n    public:\n        /// Coloring method: \"cppad\", or \"colpack\"\n        /// (this field is set by user)\n        std::string color_method;\n        /// row and column indices for return values\n        /// (some may be reflected by star coloring algorithm)\n        CppAD::vector<size_t> row;\n        CppAD::vector<size_t> col;\n        /// indices that sort the user row and col arrays by color\n        CppAD::vector<size_t> order;\n        /// results of the coloring algorithm\n        CppAD::vector<size_t> color;\n\n        /// constructor\n        sparse_hessian_work(void) : color_method(\"cppad.symmetric\")\n        { }\n        /// inform CppAD that this information needs to be recomputed\n        void clear(void)\n        {   color_method = \"cppad.symmetric\";\n            row.clear();\n            col.clear();\n            order.clear();\n            color.clear();\n        }\n};\n// ===========================================================================\n/*!\nPrivate helper function that does computation for all Sparse Hessian cases.\n\n\\tparam Base\nis the base type for the recording that is stored in this ADFun<Base object.\n\n\\tparam BaseVector\nis a simple vector class with elements of type Base.\n\n\\tparam SetVector\nis a simple vector class with elements of type\n bool or std::set<size_t>.\n\n\\tparam SizeVector\nis sparse_pack or sparse_list.\n\n\\param x [in]\nis a vector specifying the point at which to compute the Hessian.\n\n\\param w [in]\nis the weighting vector that defines a scalar valued function by\na weighted sum of the components of the vector valued function\n$latex F(x)$$.\n\n\\param sparsity [in]\nis the sparsity pattern for the Hessian that we are calculating.\n\n\\param user_row [in]\nis the vector of row indices for the returned Hessian values.\n\n\\param user_col [in]\nis the vector of columns indices for the returned Hessian values.\nIt must have the same size as user_row.\n\n\\param hes [out]\nis the vector of Hessian values.\nIt must have the same size as user_row.\nThe return value <code>hes[k]</code> is the second partial of\n\\f$ w^{\\rm T} F(x)\\f$ with respect to the\n<code>row[k]</code> and <code>col[k]</code> component of \\f$ x\\f$.\n\n\\param work\nThis structure contains information that is computed by SparseHessianCompute.\nIf the sparsity pattern, row vector, or col vectors\nare not the same between calls to SparseHessianCompute,\n work.clear() must be called to reinitialize work.\n\n\\return\nIs the number of first order forward sweeps used to compute the\nrequested Hessian values.\n(This is also equal to the number of second order reverse sweeps.)\nThe total work, not counting the zero order\nforward sweep, or the time to combine computations, is proportional to this\nreturn value.\n*/\ntemplate <class Base, class RecBase>\ntemplate <class BaseVector, class SetVector, class SizeVector>\nsize_t ADFun<Base,RecBase>::SparseHessianCompute(\n    const BaseVector&           x           ,\n    const BaseVector&           w           ,\n             SetVector&            sparsity    ,\n    const SizeVector&           user_row    ,\n    const SizeVector&           user_col    ,\n             BaseVector&           hes         ,\n             sparse_hessian_work&  work        )\n{\n    using   CppAD::vectorBool;\n    size_t i, k, ell;\n\n    CppAD::vector<size_t>& row(work.row);\n    CppAD::vector<size_t>& col(work.col);\n    CppAD::vector<size_t>& color(work.color);\n    CppAD::vector<size_t>& order(work.order);\n\n    size_t n = Domain();\n\n    // some values\n    const Base zero(0);\n    const Base one(1);\n\n    // check BaseVector is Simple Vector class with Base type elements\n    CheckSimpleVector<Base, BaseVector>();\n\n    // number of components of Hessian that are required\n    size_t K = hes.size();\n    CPPAD_ASSERT_UNKNOWN( size_t( user_row.size() ) == K );\n    CPPAD_ASSERT_UNKNOWN( size_t( user_col.size() ) == K );\n\n    CPPAD_ASSERT_UNKNOWN( size_t(x.size()) == n );\n    CPPAD_ASSERT_UNKNOWN( color.size() == 0 || color.size() == n );\n    CPPAD_ASSERT_UNKNOWN( row.size() == 0   || row.size() == K );\n    CPPAD_ASSERT_UNKNOWN( col.size() == 0   || col.size() == K );\n\n\n    // Point at which we are evaluating the Hessian\n    Forward(0, x);\n\n    // check for case where nothing (except Forward above) to do\n    if( K == 0 )\n        return 0;\n\n    // Rows of the Hessian (i below) correspond to the forward mode index\n    // and columns (j below) correspond to the reverse mode index.\n    if( color.size() == 0 )\n    {\n        CPPAD_ASSERT_UNKNOWN( sparsity.n_set() ==  n );\n        CPPAD_ASSERT_UNKNOWN( sparsity.end() ==  n );\n\n        // copy user rwo and col to work space\n        row.resize(K);\n        col.resize(K);\n        for(k = 0; k < K; k++)\n        {   row[k] = user_row[k];\n            col[k] = user_col[k];\n        }\n\n        // execute coloring algorithm\n        color.resize(n);\n        if( work.color_method == \"cppad.general\" )\n            local::color_general_cppad(sparsity, row, col, color);\n        else if( work.color_method == \"cppad.symmetric\" )\n            local::color_symmetric_cppad(sparsity, row, col, color);\n        else if( work.color_method == \"colpack.general\" )\n        {\n# if CPPAD_HAS_COLPACK\n            local::color_general_colpack(sparsity, row, col, color);\n# else\n            CPPAD_ASSERT_KNOWN(\n                false,\n                \"SparseHessian: work.color_method = colpack.general \"\n                \"and colpack_prefix missing from cmake command line.\"\n            );\n# endif\n        }\n        else if(\n            work.color_method == \"colpack.symmetric\" ||\n            work.color_method == \"colpack.star\"\n        )\n        {\n# if CPPAD_HAS_COLPACK\n            local::color_symmetric_colpack(sparsity, row, col, color);\n# else\n            CPPAD_ASSERT_KNOWN(\n                false,\n                \"SparseHessian: work.color_method is \"\n                \"colpack.symmetric or colpack.star\\n\"\n                \"and colpack_prefix missing from cmake command line.\"\n            );\n# endif\n        }\n        else\n        {   CPPAD_ASSERT_KNOWN(\n                false,\n                \"SparseHessian: work.color_method is not valid.\"\n            );\n        }\n\n        // put sorting indices in color order\n        SizeVector key(K);\n        order.resize(K);\n        for(k = 0; k < K; k++)\n            key[k] = color[ row[k] ];\n        index_sort(key, order);\n\n    }\n    size_t n_color = 1;\n    for(ell = 0; ell < n; ell++) if( color[ell] < n )\n        n_color = std::max<size_t>(n_color, color[ell] + 1);\n\n    // direction vector for calls to forward (rows of the Hessian)\n    BaseVector u(n);\n\n    // location for return values from reverse (columns of the Hessian)\n    BaseVector ddw(2 * n);\n\n    // initialize the return value\n    for(k = 0; k < K; k++)\n        hes[k] = zero;\n\n    // loop over colors\n# ifndef NDEBUG\n    const std::string& coloring = work.color_method;\n# endif\n    k = 0;\n    for(ell = 0; ell < n_color; ell++)\n    if( k == K )\n    {   // kludge because colpack returns colors that are not used\n        // (it does not know about the subset corresponding to row, col)\n        CPPAD_ASSERT_UNKNOWN(\n            coloring == \"colpack.general\" ||\n            coloring == \"colpack.symmetric\" ||\n            coloring == \"colpack.star\"\n        );\n    }\n    else if( color[ row[ order[k] ] ] != ell )\n    {   // kludge because colpack returns colors that are not used\n        // (it does not know about the subset corresponding to row, col)\n        CPPAD_ASSERT_UNKNOWN(\n            coloring == \"colpack.general\" ||\n            coloring == \"colpack.symmetric\" ||\n            coloring == \"colpack.star\"\n        );\n    }\n    else\n    {   CPPAD_ASSERT_UNKNOWN( color[ row[ order[k] ] ] == ell );\n\n        // combine all rows with this color\n        for(i = 0; i < n; i++)\n        {   u[i] = zero;\n            if( color[i] == ell )\n                u[i] = one;\n        }\n        // call forward mode for all these rows at once\n        Forward(1, u);\n\n        // evaluate derivative of w^T * F'(x) * u\n        ddw = Reverse(2, w);\n\n        // set the corresponding components of the result\n        while( k < K && color[ row[ order[k] ] ] == ell )\n        {   hes[ order[k] ] = ddw[ col[ order[k] ] * 2 + 1 ];\n            k++;\n        }\n    }\n    return n_color;\n}\n// ===========================================================================\n// Public Member Functions\n// ===========================================================================\n/*!\nCompute user specified subset of a sparse Hessian.\n\nThe C++ source code corresponding to this operation is\n\\verbatim\n    SparseHessian(x, w, p, row, col, hes, work)\n\\endverbatim\n\n\\tparam Base\nis the base type for the recording that is stored in this ADFun<Base object.\n\n\\tparam BaseVector\nis a simple vector class with elements of type Base.\n\n\\tparam SetVector\nis a simple vector class with elements of type\n bool or std::set<size_t>.\n\n\\tparam SizeVector\nis a simple vector class with elements of type size_t.\n\n\\param x [in]\nis a vector specifying the point at which to compute the Hessian.\n\n\\param w [in]\nis the weighting vector that defines a scalar valued function by\na weighted sum of the components of the vector valued function\n$latex F(x)$$.\n\n\\param p [in]\nis the sparsity pattern for the Hessian that we are calculating.\n\n\\param row [in]\nis the vector of row indices for the returned Hessian values.\n\n\\param col [in]\nis the vector of columns indices for the returned Hessian values.\nIt must have the same size are r.\n\n\\param hes [out]\nis the vector of Hessian values.\nIt must have the same size are r.\nThe return value <code>hes[k]</code> is the second partial of\n\\f$ w^{\\rm T} F(x)\\f$ with respect to the\n<code>row[k]</code> and <code>col[k]</code> component of \\f$ x\\f$.\n\n\\param work\nThis structure contains information that is computed by SparseHessianCompute.\nIf the sparsity pattern, row vector, or col vectors\nare not the same between calls to SparseHessian,\n work.clear() must be called to reinitialize work.\n\n\\return\nIs the number of first order forward sweeps used to compute the\nrequested Hessian values.\n(This is also equal to the number of second order reverse sweeps.)\nThe total work, not counting the zero order\nforward sweep, or the time to combine computations, is proportional to this\nreturn value.\n*/\ntemplate <class Base, class RecBase>\ntemplate <class BaseVector, class SetVector, class SizeVector>\nsize_t ADFun<Base,RecBase>::SparseHessian(\n    const BaseVector&     x    ,\n    const BaseVector&     w    ,\n    const SetVector&      p    ,\n    const SizeVector&     row  ,\n    const SizeVector&     col  ,\n    BaseVector&           hes  ,\n    sparse_hessian_work&  work )\n{\n    size_t n    = Domain();\n    size_t K    = hes.size();\n# ifndef NDEBUG\n    size_t k;\n    CPPAD_ASSERT_KNOWN(\n        size_t(x.size()) == n ,\n        \"SparseHessian: size of x not equal domain dimension for f.\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t(row.size()) == K && size_t(col.size()) == K ,\n        \"SparseHessian: either r or c does not have the same size as ehs.\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        work.color.size() == 0 || work.color.size() == n,\n        \"SparseHessian: invalid value in work.\"\n    );\n    for(k = 0; k < K; k++)\n    {   CPPAD_ASSERT_KNOWN(\n            row[k] < n,\n            \"SparseHessian: invalid value in r.\"\n        );\n        CPPAD_ASSERT_KNOWN(\n            col[k] < n,\n            \"SparseHessian: invalid value in c.\"\n        );\n    }\n    if( work.color.size() != 0 )\n        for(size_t j = 0; j < n; j++) CPPAD_ASSERT_KNOWN(\n            work.color[j] <= n,\n            \"SparseHessian: invalid value in work.\"\n    );\n# endif\n    // check for case where there is nothing to compute\n    size_t n_sweep = 0;\n    if( K == 0 )\n        return n_sweep;\n\n    typedef typename SetVector::value_type Set_type;\n    typedef typename local::sparse::internal_pattern<Set_type>::pattern_type Pattern_type;\n    Pattern_type s;\n    if( work.color.size() == 0 )\n    {   bool transpose = false;\n        const char* error_msg = \"SparseHessian: sparsity pattern\"\n        \" does not have proper row or column dimension\";\n        sparsity_user2internal(s, p, n, n, transpose, error_msg);\n    }\n    n_sweep = SparseHessianCompute(x, w, s, row, col, hes, work);\n    return n_sweep;\n}\n/*!\nCompute a sparse Hessian.\n\nThe C++ source code corresponding to this operation is\n\\verbatim\n    hes = SparseHessian(x, w, p)\n\\endverbatim\n\n\n\\tparam Base\nis the base type for the recording that is stored in this\nADFun<Base object.\n\n\\tparam BaseVector\nis a simple vector class with elements of the Base.\n\n\\tparam SetVector\nis a simple vector class with elements of type\n bool or std::set<size_t>.\n\n\\param x [in]\nis a vector specifying the point at which to compute the Hessian.\n\n\\param w [in]\nThe Hessian is computed for a weighted sum of the components\nof the function corresponding to this ADFun<Base> object.\nThe argument w specifies the weights for each component.\nIt must have size equal to the range dimension for this ADFun<Base> object.\n\n\\param p [in]\nis a sparsity pattern for the Hessian.\n\n\\return\nWill be a vector of size n * n containing the Hessian of\nat the point specified by x\n(where n is the domain dimension for this ADFun<Base> object).\n*/\ntemplate <class Base, class RecBase>\ntemplate <class BaseVector, class SetVector>\nBaseVector ADFun<Base,RecBase>::SparseHessian(\n    const BaseVector& x, const BaseVector& w, const SetVector& p\n)\n{   size_t i, j, k;\n\n    size_t n = Domain();\n    BaseVector hes(n * n);\n\n    CPPAD_ASSERT_KNOWN(\n        size_t(x.size()) == n,\n        \"SparseHessian: size of x not equal domain size for f.\"\n    );\n\n    typedef typename SetVector::value_type Set_type;\n    typedef typename local::sparse::internal_pattern<Set_type>::pattern_type Pattern_type;\n\n    // initialize the return value as zero\n    Base zero(0);\n    for(i = 0; i < n; i++)\n        for(j = 0; j < n; j++)\n            hes[i * n + j] = zero;\n\n    // arguments to SparseHessianCompute\n    Pattern_type          s;\n    CppAD::vector<size_t> row;\n    CppAD::vector<size_t> col;\n    sparse_hessian_work   work;\n    bool transpose = false;\n    const char* error_msg = \"SparseHessian: sparsity pattern\"\n    \" does not have proper row or column dimension\";\n    sparsity_user2internal(s, p, n, n, transpose, error_msg);\n    k = 0;\n    for(i = 0; i < n; i++)\n    {   typename Pattern_type::const_iterator itr(s, i);\n        j = *itr;\n        while( j != s.end() )\n        {   row.push_back(i);\n            col.push_back(j);\n            k++;\n            j = *(++itr);\n        }\n    }\n    size_t K = k;\n    BaseVector H(K);\n\n    // now we have folded this into the following case\n    SparseHessianCompute(x, w, s, row, col, H, work);\n\n    // now set the non-zero return values\n    for(k = 0; k < K; k++)\n        hes[ row[k] * n + col[k] ] = H[k];\n\n    return hes;\n}\n/*!\nCompute a sparse Hessian\n\nThe C++ source code corresponding to this operation is\n\\verbatim\n    hes = SparseHessian(x, w)\n\\endverbatim\n\n\n\\tparam Base\nis the base type for the recording that is stored in this\nADFun<Base object.\n\n\\tparam BaseVector\nis a simple vector class with elements of the Base.\n\n\\param x [in]\nis a vector specifying the point at which to compute the Hessian.\n\n\\param w [in]\nThe Hessian is computed for a weighted sum of the components\nof the function corresponding to this ADFun<Base> object.\nThe argument w specifies the weights for each component.\nIt must have size equal to the range dimension for this ADFun<Base> object.\n\n\\return\nWill be a vector of size n * n containing the Hessian of\nat the point specified by x\n(where n is the domain dimension for this ADFun<Base> object).\n*/\ntemplate <class Base, class RecBase>\ntemplate <class BaseVector>\nBaseVector ADFun<Base,RecBase>::SparseHessian(const BaseVector &x, const BaseVector &w)\n{   size_t i, j, k;\n    typedef CppAD::vectorBool BoolVector;\n\n    size_t m = Range();\n    size_t n = Domain();\n\n    // determine the sparsity pattern p for Hessian of w^T F\n    BoolVector r(n * n);\n    for(j = 0; j < n; j++)\n    {   for(k = 0; k < n; k++)\n            r[j * n + k] = false;\n        r[j * n + j] = true;\n    }\n    ForSparseJac(n, r);\n    //\n    BoolVector s(m);\n    for(i = 0; i < m; i++)\n        s[i] = w[i] != 0;\n    BoolVector p = RevSparseHes(n, s);\n\n    // compute sparse Hessian\n    return SparseHessian(x, w, p);\n}\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/sparse_jac.hpp",
    "content": "# ifndef CPPAD_CORE_SPARSE_JAC_HPP\n# define CPPAD_CORE_SPARSE_JAC_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin sparse_jac}\n{xrst_spell\n    nr\n    rc\n    rcv\n}\n\nComputing Sparse Jacobians\n##########################\n\nSyntax\n******\n| *n_color* = *f* . ``sparse_jac_for`` (\n| |tab| *group_max* , *x* , *subset* , *pattern* , *coloring* , *work*\n| )\n| *n_color* = *f* . ``sparse_jac_rev`` (\n| |tab| *x* , *subset* , *pattern* , *coloring* , *work*\n| )\n\nPurpose\n*******\nWe use :math:`F : \\B{R}^n \\rightarrow \\B{R}^m` to denote the\nfunction corresponding to *f* .\nHere *n* is the :ref:`fun_property@Domain` size,\nand *m* is the :ref:`fun_property@Range` size, or *f* .\nThe syntax above takes advantage of sparsity when computing the Jacobian\n\n.. math::\n\n    J(x) = F^{(1)} (x)\n\nIn the sparse case, this should be faster and take less memory than\n:ref:`Jacobian-name` .\nWe use the notation :math:`J_{i,j} (x)` to denote the partial of\n:math:`F_i (x)` with respect to :math:`x_j`.\n\nSizeVector\n**********\nThe type *SizeVector* is a :ref:`SimpleVector-name` class with\n:ref:`elements of type<SimpleVector@Elements of Specified Type>`\n``size_t`` .\n\nBaseVector\n**********\nThe type *BaseVector* is a :ref:`SimpleVector-name` class with\n:ref:`elements of type<SimpleVector@Elements of Specified Type>`\n``size_t`` .\n\nsparse_jac_for\n**************\nThis function uses first order forward mode sweeps :ref:`forward_one-name`\nto compute multiple columns of the Jacobian at the same time.\n\nsparse_jac_rev\n**************\nThis uses function first order reverse mode sweeps :ref:`reverse_one-name`\nto compute multiple rows of the Jacobian at the same time.\n\nf\n*\nThis object has prototype\n\n    ``ADFun`` < *Base* > *f*\n\nNote that the Taylor coefficients stored in *f* are affected\nby this operation; see\n:ref:`sparse_jac@Uses Forward` below.\n\ngroup_max\n*********\nThis argument has prototype\n\n    ``size_t`` *group_max*\n\nand must be greater than zero.\nIt specifies the maximum number of colors to group during\na single forward sweep.\nIf a single color is in a group,\na single direction for of first order forward mode\n:ref:`forward_one-name` is used for each color.\nIf multiple colors are in a group,\nthe multiple direction for of first order forward mode\n:ref:`forward_dir-name` is used with one direction for each color.\nThis uses separate memory for each direction (more memory),\nbut my be significantly faster.\n\nx\n*\nThis argument has prototype\n\n    ``const`` *BaseVector* & *x*\n\nand its size is *n* .\nIt specifies the point at which to evaluate the Jacobian\n:math:`J(x)`.\n\nsubset\n******\nThis argument has prototype\n\n    ``sparse_rcv`` < *SizeVector* , *BaseVector* >& *subset*\n\nIts row size is *subset* . ``nr`` () == *m* ,\nand its column size is *subset* . ``nc`` () == *n* .\nIt specifies which elements of the Jacobian are computed.\nThe input value of its value vector\n*subset* . ``val`` () does not matter.\nUpon return it contains the value of the corresponding elements\nof the Jacobian.\nAll of the row, column pairs in *subset* must also appear in\n*pattern* ; i.e., they must be possibly non-zero.\n\npattern\n*******\nThis argument has prototype\n\n    ``const sparse_rc`` < *SizeVector* >& *pattern*\n\nIts row size is *pattern* . ``nr`` () == *m* ,\nand its column size is *pattern* . ``nc`` () == *n* .\nIt is a sparsity pattern for the Jacobian :math:`J(x)`.\nThis argument is not used (and need not satisfy any conditions),\nwhen :ref:`sparse_jac@work` is non-empty.\n\ncoloring\n********\nThe coloring algorithm determines which rows (reverse) or columns (forward)\ncan be computed during the same sweep.\nThis field has prototype\n\n    ``const std::string&`` *coloring*\n\nThis value only matters when work is empty; i.e.,\nafter the *work* constructor or *work* . ``clear`` () .\n\ncppad\n=====\nThis uses a general purpose coloring algorithm written for Cppad.\n\ncolpack\n=======\nIf :ref:`colpack_prefix-name` is specified on the\n:ref:`cmake@CMake Command` line,\nyou can set *coloring* to ``colpack`` .\nThis uses a general purpose coloring algorithm that is part of Colpack.\n\nwork\n****\nThis argument has prototype\n\n    ``sparse_jac_work&`` *work*\n\nWe refer to its initial value,\nand its value after *work* . ``clear`` () , as empty.\nIf it is empty, information is stored in *work* .\nThis can be used to reduce computation when\na future call is for the same object *f* ,\nthe same member function ``sparse_jac_for`` or ``sparse_jac_rev`` ,\nand the same subset of the Jacobian.\nIn fact, it can be used with a different *f*\nand a different *subset* provided that Jacobian sparsity pattern\nfor *f* and the sparsity pattern in *subset* are the same.\nIf any of these values change, use *work* . ``clear`` () to\nempty this structure.\n\nn_color\n*******\nThe return value *n_color* has prototype\n\n    ``size_t`` *n_color*\n\nIf ``sparse_jac_for`` (``sparse_jac_rev`` ) is used,\n*n_color* is the number of first order forward directions\nused to compute the requested Jacobian values.\nIt is also the number of colors determined by the coloring method\nmentioned above.\nThis is proportional to the total computational work,\nnot counting the zero order forward sweep,\nor combining multiple columns (rows) into a single sweep.\nNote that if *group_max*  == 1 ,\nor if we are using ``sparse_jac_rev`` ,\n*n_color* is equal to the number of sweeps.\n\nUses Forward\n************\nAfter each call to :ref:`Forward-name` ,\nthe object *f* contains the corresponding\n:ref:`Taylor coefficients<glossary@Taylor Coefficient>` .\nAfter a call to ``sparse_jac_forward`` or ``sparse_jac_rev`` ,\nthe zero order coefficients correspond to\n\n    *f* . ``Forward`` (0, *x* )\n\nAll the other forward mode coefficients are unspecified.\n\nExample\n*******\n{xrst_toc_hidden\n    example/sparse/sparse_jac_for.cpp\n    example/sparse/sparse_jac_rev.cpp\n}\nThe files :ref:`sparse_jac_for.cpp-name` and :ref:`sparse_jac_rev.cpp-name`\nare examples and tests of ``sparse_jac_for`` and ``sparse_jac_rev`` .\nThey return ``true`` , if they succeed, and ``false`` otherwise.\n\n{xrst_end sparse_jac}\n*/\n# include <cppad/core/cppad_assert.hpp>\n# include <cppad/local/sparse/internal.hpp>\n# include <cppad/local/color_general.hpp>\n# include <cppad/utility/vector.hpp>\n\n/*!\n\\file sparse_jac.hpp\nSparse Jacobian calculation routines.\n*/\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\nClass used to hold information used by Sparse Jacobian routines in this file,\nso they do not need to be recomputed every time.\n*/\nclass sparse_jac_work {\n    public:\n        /// indices that sort the user row and col arrays by color\n        CppAD::vector<size_t> order;\n        /// results of the coloring algorithm\n        CppAD::vector<size_t> color;\n        //\n        /// constructor\n        sparse_jac_work(void)\n        { }\n        /// reset work to empty.\n        /// This informs CppAD that color and order need to be recomputed\n        void clear(void)\n        {   order.clear();\n            color.clear();\n        }\n};\n// ----------------------------------------------------------------------------\n/*!\nCalculate sparse Jacobains using forward mode\n\n\\tparam Base\nthe base type for the recording that is stored in the ADFun object.\n\n\\tparam SizeVector\na simple vector class with elements of type size_t.\n\n\\tparam BaseVector\na simple vector class with elements of type Base.\n\n\\param group_max\nspecifies the maximum number of colors to group during a single forward sweep.\nThis must be greater than zero and group_max = 1 minimizes memory usage.\n\n\\param x\na vector of length n, the number of independent variables in f\n(this ADFun object).\n\n\\param subset\nspedifies the subset of the sparsity pattern where the Jacobian is evaluated.\nsubset.nr() == m,\nsubset.nc() == n.\n\n\\param pattern\nis a sparsity pattern for the Jacobian of f;\npattern.nr() == m,\npattern.nc() == n,\nwhere m is number of dependent variables in f.\n\n\\param coloring\ndetermines which coloring algorithm is used.\nThis must be cppad or colpack.\n\n\\param work\nthis structure must be empty, or contain the information stored\nby a previous call to sparse_jac_for.\nThe previous call must be for the same ADFun object f\nand the same subset.\n\n\\return\nThis is the number of first order forward sweeps used to compute\nthe Jacobian.\n*/\ntemplate <class Base, class RecBase>\ntemplate <class SizeVector, class BaseVector>\nsize_t ADFun<Base,RecBase>::sparse_jac_for(\n    size_t                               group_max  ,\n    const BaseVector&                    x          ,\n    sparse_rcv<SizeVector, BaseVector>&  subset     ,\n    const sparse_rc<SizeVector>&         pattern    ,\n    const std::string&                   coloring   ,\n    sparse_jac_work&                     work       )\n{   size_t m = Range();\n    size_t n = Domain();\n    //\n    CPPAD_ASSERT_KNOWN(\n        subset.nr() == m,\n        \"sparse_jac_for: subset.nr() not equal range dimension for f\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        subset.nc() == n,\n        \"sparse_jac_for: subset.nc() not equal domain dimension for f\"\n    );\n    //\n    // row and column vectors in subset\n    const SizeVector& row( subset.row() );\n    const SizeVector& col( subset.col() );\n    //\n    vector<size_t>& color(work.color);\n    vector<size_t>& order(work.order);\n    CPPAD_ASSERT_KNOWN(\n        color.size() == 0 || color.size() == n,\n        \"sparse_jac_for: work is non-empty and conditions have changed\"\n    );\n    //\n    // point at which we are evaluating the Jacobian\n    Forward(0, x);\n    //\n    // number of elements in the subset\n    size_t K = subset.nnz();\n    //\n    // check for case were there is nothing to do\n    // (except for call to Forward(0, x)\n    if( K == 0 )\n        return 0;\n    //\n    // check for case where input work is empty\n    if( color.size() == 0 )\n    {   // compute work color and order vectors\n        CPPAD_ASSERT_KNOWN(\n            pattern.nr() == m,\n            \"sparse_jac_for: pattern.nr() not equal range dimension for f\"\n        );\n        CPPAD_ASSERT_KNOWN(\n            pattern.nc() == n,\n            \"sparse_jac_for: pattern.nc() not equal domain dimension for f\"\n        );\n        //\n        // convert pattern to an internal version of its transpose\n        local::pod_vector<size_t> internal_index(n);\n        for(size_t j = 0; j < n; j++)\n            internal_index[j] = j;\n        bool transpose   = true;\n        bool zero_empty  = false;\n        bool input_empty = true;\n        local::sparse::list_setvec pattern_transpose;\n        pattern_transpose.resize(n, m);\n        local::sparse::set_internal_pattern(zero_empty, input_empty,\n            transpose, internal_index, pattern_transpose, pattern\n        );\n        //\n        // execute coloring algorithm\n        // (we are using transpose because coloring groups rows, not columns).\n        color.resize(n);\n        if( coloring == \"cppad\" )\n            local::color_general_cppad(pattern_transpose, col, row, color);\n        else if( coloring == \"colpack\" )\n        {\n# if CPPAD_HAS_COLPACK\n            local::color_general_colpack(pattern_transpose, col, row, color);\n# else\n            CPPAD_ASSERT_KNOWN(\n                false,\n                \"sparse_jac_for: coloring = colpack \"\n                \"and colpack_prefix missing from cmake command line.\"\n            );\n# endif\n        }\n        else CPPAD_ASSERT_KNOWN(\n            false,\n            \"sparse_jac_for: coloring is not valid.\"\n        );\n        //\n        // put sorting indices in color order\n        SizeVector key(K);\n        order.resize(K);\n        for(size_t k = 0; k < K; k++)\n            key[k] = color[ col[k] ];\n        index_sort(key, order);\n    }\n    // Base versions of zero and one\n    Base one(1.0);\n    Base zero(0.0);\n    //\n    size_t n_color = 1;\n    for(size_t j = 0; j < n; j++) if( color[j] < n )\n        n_color = std::max<size_t>(n_color, color[j] + 1);\n    //\n    // initialize the return Jacobian values as zero\n    for(size_t k = 0; k < K; k++)\n        subset.set(k, zero);\n    //\n    // index in subset\n    size_t k = 0;\n    // number of colors computed so far\n    size_t color_count = 0;\n    //\n    while( color_count < n_color )\n    {   // number of colors that will be in this group\n        size_t group_size = std::min<size_t>(group_max, n_color - color_count);\n        //\n        // forward mode values for independent and dependent variables\n        BaseVector dx(n * group_size), dy(m * group_size);\n        //\n        // set dx\n        for(size_t ell = 0; ell < group_size; ell++)\n        {   // combine all columns with this color\n            for(size_t j = 0; j < n; j++)\n            {   dx[j * group_size + ell] = zero;\n                if( color[j] == ell + color_count )\n                    dx[j * group_size + ell] = one;\n            }\n        }\n        if( group_size == 1 )\n            dy = Forward(1, dx);\n        else\n            dy = Forward(1, group_size, dx);\n        //\n        // store results in subset\n        for(size_t ell = 0; ell < group_size; ell++)\n        {   // color with index ell + color_count is in this group\n            while(k < K && color[ col[ order[k] ] ] == ell + color_count )\n            {   // subset element with index order[k] is included in this color\n                size_t r = row[ order[k] ];\n                subset.set( order[k], dy[ r * group_size + ell ] );\n                ++k;\n            }\n        }\n        // advance color count\n        color_count += group_size;\n    }\n    CPPAD_ASSERT_UNKNOWN( color_count == n_color );\n    //\n    return n_color;\n}\n// ----------------------------------------------------------------------------\n/*!\nCalculate sparse Jacobains using reverse mode\n\n\\tparam Base\nthe base type for the recording that is stored in the ADFun object.\n\n\\tparam SizeVector\na simple vector class with elements of type size_t.\n\n\\tparam BaseVector\na simple vector class with elements of type Base.\n\n\\param x\na vector of length n, the number of independent variables in f\n(this ADFun object).\n\n\\param subset\nspedifies the subset of the sparsity pattern where the Jacobian is evaluated.\nsubset.nr() == m,\nsubset.nc() == n.\n\n\\param pattern\nis a sparsity pattern for the Jacobian of f;\npattern.nr() == m,\npattern.nc() == n,\nwhere m is number of dependent variables in f.\n\n\\param coloring\ndetermines which coloring algorithm is used.\nThis must be cppad or colpack.\n\n\\param work\nthis structure must be empty, or contain the information stored\nby a previous call to sparse_jac_rev.\nThe previous call must be for the same ADFun object f\nand the same subset.\n\n\\return\nThis is the number of first order reverse sweeps used to compute\nthe Jacobian.\n*/\ntemplate <class Base, class RecBase>\ntemplate <class SizeVector, class BaseVector>\nsize_t ADFun<Base,RecBase>::sparse_jac_rev(\n    const BaseVector&                    x        ,\n    sparse_rcv<SizeVector, BaseVector>&  subset   ,\n    const sparse_rc<SizeVector>&         pattern  ,\n    const std::string&                   coloring ,\n    sparse_jac_work&                     work     )\n{   size_t m = Range();\n    size_t n = Domain();\n    //\n    CPPAD_ASSERT_KNOWN(\n        subset.nr() == m,\n        \"sparse_jac_rev: subset.nr() not equal range dimension for f\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        subset.nc() == n,\n        \"sparse_jac_rev: subset.nc() not equal domain dimension for f\"\n    );\n    //\n    // row and column vectors in subset\n    const SizeVector& row( subset.row() );\n    const SizeVector& col( subset.col() );\n    //\n    vector<size_t>& color(work.color);\n    vector<size_t>& order(work.order);\n    CPPAD_ASSERT_KNOWN(\n        color.size() == 0 || color.size() == m,\n        \"sparse_jac_rev: work is non-empty and conditions have changed\"\n    );\n    //\n    // point at which we are evaluating the Jacobian\n    Forward(0, x);\n    //\n    // number of elements in the subset\n    size_t K = subset.nnz();\n    //\n    // check for case were there is nothing to do\n    // (except for call to Forward(0, x)\n    if( K == 0 )\n        return 0;\n    //\n    // check for case where input work is empty\n    if( color.size() == 0 )\n    {   // compute work color and order vectors\n        CPPAD_ASSERT_KNOWN(\n            pattern.nr() == m,\n            \"sparse_jac_rev: pattern.nr() not equal range dimension for f\"\n        );\n        CPPAD_ASSERT_KNOWN(\n            pattern.nc() == n,\n            \"sparse_jac_rev: pattern.nc() not equal domain dimension for f\"\n        );\n        //\n        // convert pattern to an internal version\n        local::pod_vector<size_t> internal_index(m);\n        for(size_t i = 0; i < m; i++)\n            internal_index[i] = i;\n        bool transpose   = false;\n        bool zero_empty  = false;\n        bool input_empty = true;\n        local::sparse::list_setvec internal_pattern;\n        internal_pattern.resize(m, n);\n        local::sparse::set_internal_pattern(zero_empty, input_empty,\n            transpose, internal_index, internal_pattern, pattern\n        );\n        //\n        // execute coloring algorithm\n        color.resize(m);\n        if( coloring == \"cppad\" )\n            local::color_general_cppad(internal_pattern, row, col, color);\n        else if( coloring == \"colpack\" )\n        {\n# if CPPAD_HAS_COLPACK\n            local::color_general_colpack(internal_pattern, row, col, color);\n# else\n            CPPAD_ASSERT_KNOWN(\n                false,\n                \"sparse_jac_rev: coloring = colpack \"\n                \"and colpack_prefix missing from cmake command line.\"\n            );\n# endif\n        }\n        else CPPAD_ASSERT_KNOWN(\n            false,\n            \"sparse_jac_rev: coloring is not valid.\"\n        );\n        //\n        // put sorting indices in color order\n        SizeVector key(K);\n        order.resize(K);\n        for(size_t k = 0; k < K; k++)\n            key[k] = color[ row[k] ];\n        index_sort(key, order);\n    }\n    // Base versions of zero and one\n    Base one(1.0);\n    Base zero(0.0);\n    //\n    size_t n_color = 1;\n    for(size_t i = 0; i < m; i++) if( color[i] < m )\n        n_color = std::max<size_t>(n_color, color[i] + 1);\n    //\n    // initialize the return Jacobian values as zero\n    for(size_t k = 0; k < K; k++)\n        subset.set(k, zero);\n    //\n    // weighting vector and return values for calls to Reverse\n    BaseVector w(m), dw(n);\n    //\n    // loop over colors\n    size_t k = 0;\n    for(size_t ell = 0; ell < n_color; ell++)\n    if( k  == K )\n    {   // kludge because colpack returns colors that are not used\n        // (it does not know about the subset corresponding to row, col)\n        CPPAD_ASSERT_UNKNOWN( coloring == \"colpack\" );\n    }\n    else if( color[ row[ order[k] ] ] != ell )\n    {   // kludge because colpack returns colors that are not used\n        // (it does not know about the subset corresponding to row, col)\n        CPPAD_ASSERT_UNKNOWN( coloring == \"colpack\" );\n    }\n    else\n    {   CPPAD_ASSERT_UNKNOWN( color[ row[ order[k] ] ] == ell );\n        //\n        // combine all rows with this color\n        for(size_t i = 0; i < m; i++)\n        {   w[i] = zero;\n            if( color[i] == ell )\n                w[i] = one;\n        }\n        // call reverse mode for all these rows at once\n        dw = Reverse(1, w);\n        //\n        // set the corresponding components of the result\n        while( k < K && color[ row[order[k]] ] == ell )\n        {   subset.set(order[k], dw[col[order[k]]] );\n            k++;\n        }\n    }\n    return n_color;\n}\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/sparse_jacobian.hpp",
    "content": "# ifndef CPPAD_CORE_SPARSE_JACOBIAN_HPP\n# define CPPAD_CORE_SPARSE_JACOBIAN_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n// maximum number of sparse directions to compute at the same time\n\n// # define CPPAD_SPARSE_JACOBIAN_MAX_MULTIPLE_DIRECTION 1\n# define CPPAD_SPARSE_JACOBIAN_MAX_MULTIPLE_DIRECTION 64\n\n/*\n{xrst_begin sparse_jacobian}\n{xrst_spell\n    valarray\n}\n\nSparse Jacobian\n###############\n\nSyntax\n******\n| *jac* = *f* . ``SparseJacobian`` ( *x* )\n| *jac* = *f* . ``SparseJacobian`` ( *x* , *p* )\n| *n_sweep* = *f* . ``SparseJacobianForward`` ( *x* , *p* , *row* , *col* , *jac* , *work* )\n| *n_sweep* = *f* . ``SparseJacobianReverse`` ( *x* , *p* , *row* , *col* , *jac* , *work* )\n\nPurpose\n*******\nWe use :math:`n` for the :ref:`fun_property@Domain` size,\nand :math:`m` for the :ref:`fun_property@Range` size of *f* .\nWe use :math:`F : \\B{R}^n \\rightarrow \\B{R}^m` do denote the\n:ref:`glossary@AD Function`\ncorresponding to *f* .\nThe syntax above sets *jac* to the Jacobian\n\n.. math::\n\n    jac = F^{(1)} (x)\n\nThis routine takes advantage of the sparsity of the Jacobian\nin order to reduce the amount of computation necessary.\nIf *row* and *col* are present, it also takes\nadvantage of the reduced set of elements of the Jacobian that\nneed to be computed.\nOne can use speed tests (e.g. :ref:`speed_test-name` )\nto verify that results are computed faster\nthan when using the routine :ref:`Jacobian-name` .\n\nf\n*\nThe object *f* has prototype\n\n    ``ADFun`` < *Base* > *f*\n\nNote that the :ref:`ADFun-name` object *f* is not ``const``\n(see :ref:`sparse_jacobian@Uses Forward` below).\n\nx\n*\nThe argument *x* has prototype\n\n    ``const`` *BaseVector* & *x*\n\n(see :ref:`sparse_jacobian@BaseVector` below)\nand its size\nmust be equal to *n* , the dimension of the\n:ref:`fun_property@Domain` space for *f* .\nIt specifies\nthat point at which to evaluate the Jacobian.\n\np\n*\nThe argument *p* is optional and has prototype\n\n    ``const`` *SetVector* & *p*\n\n(see :ref:`sparse_jacobian@SetVector` below).\nIf it has elements of type ``bool`` ,\nits size is :math:`m * n`.\nIf it has elements of type ``std::set<size_t>`` ,\nits size is :math:`m` and all its set elements are between\nzero and :math:`n - 1`.\nIt specifies a\n:ref:`glossary@Sparsity Pattern`\nfor the Jacobian :math:`F^{(1)} (x)`.\n\nIf this sparsity pattern does not change between calls to\n``SparseJacobian`` , it should be faster to calculate *p* once\n(using :ref:`ForSparseJac-name` or :ref:`RevSparseJac-name` )\nand then pass *p* to ``SparseJacobian`` .\nFurthermore, if you specify *work* in the calling sequence,\nit is not necessary to keep the sparsity pattern; see the heading\n:ref:`sparse_jacobian@work@p` under the *work* description.\n\nIn addition,\nif you specify *p* , CppAD will use the same\ntype of sparsity representation\n(vectors of ``bool`` or vectors of ``std::set<size_t>`` )\nfor its internal calculations.\nOtherwise, the representation\nfor the internal calculations is unspecified.\n\nrow, col\n********\nThe arguments *row* and *col* are optional and have prototype\n\n| |tab| ``const`` *SizeVector* & *row*\n| |tab| ``const`` *SizeVector* & *col*\n\n(see :ref:`sparse_jacobian@SizeVector` below).\nThey specify which rows and columns of :math:`F^{(1)} (x)` are\ncomputes and in what order.\nNot all the non-zero entries in :math:`F^{(1)} (x)` need be computed,\nbut all the entries specified by *row* and *col*\nmust be possibly non-zero in the sparsity pattern.\nWe use :math:`K` to denote the value *jac* . ``size`` ()\nwhich must also equal the size of *row* and *col* .\nFurthermore,\nfor :math:`k = 0 , \\ldots , K-1`, it must hold that\n:math:`row[k] < m` and :math:`col[k] < n`.\n\njac\n***\nThe result *jac* has prototype\n\n    *BaseVector* & *jac*\n\nIn the case where the arguments *row* and *col* are not present,\nthe size of *jac* is :math:`m * n` and\nfor :math:`i = 0 , \\ldots , m-1`,\n:math:`j = 0 , \\ldots , n-1`,\n\n.. math::\n\n    jac [ i * n + j ] = \\D{ F_i }{ x_j } (x)\n\nIn the case where the arguments *row* and *col* are present,\nwe use :math:`K` to denote the size of *jac* .\nThe input value of its elements does not matter.\nUpon return, for :math:`k = 0 , \\ldots , K - 1`,\n\n.. math::\n\n    jac [ k ] = \\D{ F_i }{ x_j } (x)\n    \\; , \\;\n    \\; {\\rm where} \\;\n    i = row[k]\n    \\; {\\rm and } \\;\n    j = col[k]\n\nwork\n****\nIf this argument is present, it has prototype\n\n    ``sparse_jacobian_work&`` *work*\n\nThis object can only be used with the routines\n``SparseJacobianForward`` and ``SparseJacobianReverse`` .\nDuring its the first use, information is stored in *work* .\nThis is used to reduce the work done by future calls to the same mode\n(forward or reverse),\nthe same *f* , *p* , *row* , and *col* .\nIf a future call is for a different mode,\nor any of these values have changed,\nyou must first call *work* . ``clear`` ()\nto inform CppAD that this information needs to be recomputed.\n\ncolor_method\n============\nThe coloring algorithm determines which columns (forward mode)\nor rows (reverse mode) can be computed during the same sweep.\nThis field has prototype\n\n    ``std::string`` *work* . ``color_method``\n\nand its default value (after a constructor or ``clear()`` )\nis ``\"cppad\"`` .\nIf :ref:`colpack_prefix-name` is specified on the\n:ref:`cmake@CMake Command` line,\nyou can set this method to ``\"colpack\"`` .\nThis value only matters on the first call to ``sparse_jacobian``\nthat follows the *work* constructor or a call to\n*work* . ``clear`` () .\n\np\n=\nIf *work* is present, and it is not the first call after\nits construction or a clear,\nthe sparsity pattern *p* is not used.\nThis enables one to free the sparsity pattern\nand still compute corresponding sparse Jacobians.\n\nn_sweep\n*******\nThe return value *n_sweep* has prototype\n\n    ``size_t`` *n_sweep*\n\nIf ``SparseJacobianForward`` (``SparseJacobianReverse`` ) is used,\n*n_sweep* is the number of first order forward (reverse) sweeps\nused to compute the requested Jacobian values.\n(This is also the number of colors determined by the coloring method\nmentioned above).\nThis is proportional to the total work that ``SparseJacobian`` does,\nnot counting the zero order forward sweep,\nor the work to combine multiple columns (rows) into a single sweep.\n\nBaseVector\n**********\nThe type *BaseVector* must be a :ref:`SimpleVector-name` class with\n:ref:`elements of type<SimpleVector@Elements of Specified Type>`\n*Base* .\nThe routine :ref:`CheckSimpleVector-name` will generate an error message\nif this is not the case.\n\nSetVector\n*********\nThe type *SetVector* must be a :ref:`SimpleVector-name` class with\n:ref:`elements of type<SimpleVector@Elements of Specified Type>`\n``bool`` or ``std::set<size_t>`` ;\nsee :ref:`glossary@Sparsity Pattern` for a discussion\nof the difference.\nThe routine :ref:`CheckSimpleVector-name` will generate an error message\nif this is not the case.\n\nRestrictions\n============\nIf *SetVector* has elements of ``std::set<size_t>`` ,\nthen *p* [ *i* ] must return a reference (not a copy) to the\ncorresponding set.\nAccording to section 26.3.2.3 of the 1998 C++ standard,\n``std::valarray< std::set<size_t> >`` does not satisfy\nthis condition.\n\nSizeVector\n**********\nThe type *SizeVector* must be a :ref:`SimpleVector-name` class with\n:ref:`elements of type<SimpleVector@Elements of Specified Type>`\n``size_t`` .\nThe routine :ref:`CheckSimpleVector-name` will generate an error message\nif this is not the case.\n\nUses Forward\n************\nAfter each call to :ref:`Forward-name` ,\nthe object *f* contains the corresponding\n:ref:`Taylor coefficients<glossary@Taylor Coefficient>` .\nAfter a call to any of the sparse Jacobian routines,\nthe zero order Taylor coefficients correspond to\n*f* . ``Forward`` (0, *x* )\nand the other coefficients are unspecified.\n\nAfter ``SparseJacobian`` ,\nthe previous calls to :ref:`Forward-name` are undefined.\n\nExample\n*******\n{xrst_toc_hidden\n    example/sparse/sparse_jacobian.cpp\n}\nThe routine\n:ref:`sparse_jacobian.cpp-name`\nis examples and tests of ``sparse_jacobian`` .\nIt return ``true`` , if it succeeds and ``false`` otherwise.\n\n{xrst_end sparse_jacobian}\n==============================================================================\n*/\n# include <cppad/local/std_set.hpp>\n# include <cppad/local/color_general.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\n\\file sparse_jacobian.hpp\nSparse Jacobian driver routine and helper functions.\n*/\n// ===========================================================================\n/*!\nclass used by SparseJacobian to hold information so it does not need to be\nrecomputed.\n*/\nclass sparse_jacobian_work {\n    public:\n        /// Coloring method: \"cppad\", or \"colpack\"\n        /// (this field is set by user)\n        std::string color_method;\n        /// indices that sort the user row and col arrays by color\n        CppAD::vector<size_t> order;\n        /// results of the coloring algorithm\n        CppAD::vector<size_t> color;\n\n        /// constructor\n        sparse_jacobian_work(void) : color_method(\"cppad\")\n        { }\n        /// reset coloring method to its default and\n        /// inform CppAD that color and order need to be recomputed\n        void clear(void)\n        {   color_method = \"cppad\";\n            order.clear();\n            color.clear();\n        }\n};\n// ===========================================================================\n/*!\nPrivate helper function forward mode cases\n\n\\tparam Base\nis the base type for the recording that is stored in this\n<code>ADFun<Base></code> object.\n\n\\tparam BaseVector\nis a simple vector class with elements of type Base.\n\n\\tparam SetVector\nis either sparse_pack or sparse_list.\n\n\\tparam SizeVector\nis a simple vector class with elements of type size_t.\n\n\\param x [in]\nis a vector specifying the point at which to compute the Jacobian.\n\n\\param p_transpose [in]\nIf <code>work.color.size() != 0</code>,\nthen p_transpose is not used.\nOtherwise, it is a\nsparsity pattern for the transpose of the Jacobian of this ADFun<Base> object.\nNote that we do not change the values in p_transpose,\nbut is not const because we use its iterator facility.\n\n\\param row [in]\nis the vector of row indices for the returned Jacobian values.\n\n\\param col [in]\nis the vector of columns indices for the returned Jacobian values.\nIt must have the same size as row.\n\n\\param jac [out]\nis the vector of Jacobian values. We use K to denote the size of jac.\nThe return value <code>jac[k]</code> is the partial of the\n<code>row[k]</code> range component of the function with respect\nthe the <code>col[k]</code> domain component of its argument.\n\n\\param work\n<code>work.color_method</code> is an input. The rest of\nthis structure contains information that is computed by SparseJacobainFor.\nIf the sparsity pattern, row vector, or col vectors\nare not the same between calls to SparseJacobianFor,\n work.clear() must be called to reinitialize work.\n\n\\return\nIs the number of first order forward sweeps used to compute the\nrequested Jacobian values. The total work, not counting the zero order\nforward sweep, or the time to combine computations, is proportional to this\nreturn value.\n*/\ntemplate <class Base, class RecBase>\ntemplate <class BaseVector, class SetVector, class SizeVector>\nsize_t ADFun<Base,RecBase>::SparseJacobianFor(\n    const BaseVector&            x           ,\n             SetVector&             p_transpose ,\n    const SizeVector&            row         ,\n    const SizeVector&            col         ,\n             BaseVector&            jac         ,\n              sparse_jacobian_work& work        )\n{\n    size_t j, k, ell;\n\n    CppAD::vector<size_t>& order(work.order);\n    CppAD::vector<size_t>& color(work.color);\n\n    size_t m = Range();\n    size_t n = Domain();\n\n    // some values\n    const Base zero(0);\n    const Base one(1);\n\n    // check BaseVector is Simple Vector class with Base type elements\n    CheckSimpleVector<Base, BaseVector>();\n\n    CPPAD_ASSERT_UNKNOWN( size_t(x.size()) == n );\n    CPPAD_ASSERT_UNKNOWN( color.size() == 0 || color.size() == n );\n\n    // number of components of Jacobian that are required\n    size_t K = size_t(jac.size());\n    CPPAD_ASSERT_UNKNOWN( size_t( row.size() ) == K );\n    CPPAD_ASSERT_UNKNOWN( size_t( col.size() ) == K );\n\n    // Point at which we are evaluating the Jacobian\n    Forward(0, x);\n\n    // check for case where nothing (except Forward above) to do\n    if( K == 0 )\n        return 0;\n\n    if( color.size() == 0 )\n    {\n        CPPAD_ASSERT_UNKNOWN( p_transpose.n_set() ==  n );\n        CPPAD_ASSERT_UNKNOWN( p_transpose.end() ==  m );\n\n        // execute coloring algorithm\n        color.resize(n);\n        if( work.color_method == \"cppad\" )\n            local::color_general_cppad(p_transpose, col, row, color);\n        else if( work.color_method == \"colpack\" )\n        {\n# if CPPAD_HAS_COLPACK\n            local::color_general_colpack(p_transpose, col, row, color);\n# else\n            CPPAD_ASSERT_KNOWN(\n                false,\n                \"SparseJacobianForward: work.color_method = colpack \"\n                \"and colpack_prefix missing from cmake command line.\"\n            );\n# endif\n        }\n        else CPPAD_ASSERT_KNOWN(\n            false,\n            \"SparseJacobianForward: work.color_method is not valid.\"\n        );\n\n        // put sorting indices in color order\n        SizeVector key(K);\n        order.resize(K);\n        for(k = 0; k < K; k++)\n            key[k] = color[ col[k] ];\n        index_sort(key, order);\n    }\n    size_t n_color = 1;\n    for(j = 0; j < n; j++) if( color[j] < n )\n        n_color = std::max<size_t>(n_color, color[j] + 1);\n\n    // initialize the return value\n    for(k = 0; k < K; k++)\n        jac[k] = zero;\n\n# if CPPAD_SPARSE_JACOBIAN_MAX_MULTIPLE_DIRECTION == 1\n    // direction vector and return values for calls to forward\n    BaseVector dx(n), dy(m);\n\n    // loop over colors\n    k = 0;\n    for(ell = 0; ell < n_color; ell++)\n    {   CPPAD_ASSERT_UNKNOWN( color[ col[ order[k] ] ] == ell );\n\n        // combine all columns with this color\n        for(j = 0; j < n; j++)\n        {   dx[j] = zero;\n            if( color[j] == ell )\n                dx[j] = one;\n        }\n        // call forward mode for all these columns at once\n        dy = Forward(1, dx);\n\n        // set the corresponding components of the result\n        while( k < K && color[ col[order[k]] ] == ell )\n        {   jac[ order[k] ] = dy[row[order[k]]];\n            k++;\n        }\n    }\n# else\n    // abbreviation for this value\n    size_t max_r = CPPAD_SPARSE_JACOBIAN_MAX_MULTIPLE_DIRECTION;\n    CPPAD_ASSERT_UNKNOWN( max_r > 1 );\n\n    // count the number of colors done so far\n    size_t count_color = 0;\n    // count the sparse matrix entries done so far\n    k = 0;\n    while( count_color < n_color )\n    {   // number of colors we will do this time\n        size_t r = std::min<size_t>(max_r , n_color - count_color);\n        BaseVector dx(n * r), dy(m * r);\n\n        // loop over colors we will do this time\n        for(ell = 0; ell < r; ell++)\n        {   // combine all columns with this color\n            for(j = 0; j < n; j++)\n            {   dx[j * r + ell] = zero;\n                if( color[j] == ell + count_color )\n                    dx[j * r + ell] = one;\n            }\n        }\n        size_t q           = 1;\n        dy = Forward(q, r, dx);\n\n        // store results\n        for(ell = 0; ell < r; ell++)\n        {   // set the components of the result for this color\n            while( k < K && color[ col[order[k]] ] == ell + count_color )\n            {   jac[ order[k] ] = dy[ row[order[k]] * r + ell ];\n                k++;\n            }\n        }\n        count_color += r;\n    }\n# endif\n    return n_color;\n}\n/*!\nPrivate helper function for reverse mode cases.\n\n\\tparam Base\nis the base type for the recording that is stored in this\n<code>ADFun<Base></code> object.\n\n\\tparam BaseVector\nis a simple vector class with elements of type Base.\n\n\\tparam SetVector\nis either sparse_pack or sparse_list.\n\n\\tparam SizeVector\nis a simple vector class with elements of type size_t.\n\n\\param x [in]\nis a vector specifying the point at which to compute the Jacobian.\n\n\\param p [in]\nIf <code>work.color.size() != 0</code>, then p is not used.\nOtherwise, it is a\nsparsity pattern for the Jacobian of this ADFun<Base> object.\nNote that we do not change the values in p,\nbut is not const because we use its iterator facility.\n\n\\param row [in]\nis the vector of row indices for the returned Jacobian values.\n\n\\param col [in]\nis the vector of columns indices for the returned Jacobian values.\nIt must have the same size as row.\n\n\\param jac [out]\nis the vector of Jacobian values.\nIt must have the same size as row.\nThe return value <code>jac[k]</code> is the partial of the\n<code>row[k]</code> range component of the function with respect\nthe the <code>col[k]</code> domain component of its argument.\n\n\\param work\n<code>work.color_method</code> is an input. The rest of\nThis structure contains information that is computed by SparseJacobainRev.\nIf the sparsity pattern, row vector, or col vectors\nare not the same between calls to SparseJacobianRev,\n work.clear() must be called to reinitialize work.\n\n\\return\nIs the number of first order reverse sweeps used to compute the\nreverse Jacobian values. The total work, not counting the zero order\nforward sweep, or the time to combine computations, is proportional to this\nreturn value.\n*/\ntemplate <class Base, class RecBase>\ntemplate <class BaseVector, class SetVector, class SizeVector>\nsize_t ADFun<Base,RecBase>::SparseJacobianRev(\n    const BaseVector&           x           ,\n             SetVector&            p           ,\n    const SizeVector&           row         ,\n    const SizeVector&           col         ,\n             BaseVector&           jac         ,\n             sparse_jacobian_work& work        )\n{\n    size_t i, k, ell;\n\n    CppAD::vector<size_t>& order(work.order);\n    CppAD::vector<size_t>& color(work.color);\n\n    size_t m = Range();\n    size_t n = Domain();\n\n    // some values\n    const Base zero(0);\n    const Base one(1);\n\n    // check BaseVector is Simple Vector class with Base type elements\n    CheckSimpleVector<Base, BaseVector>();\n\n    CPPAD_ASSERT_UNKNOWN( size_t(x.size()) == n );\n    CPPAD_ASSERT_UNKNOWN (color.size() == m || color.size() == 0 );\n\n    // number of components of Jacobian that are required\n    size_t K = size_t(jac.size());\n    CPPAD_ASSERT_UNKNOWN( size_t( size_t( row.size() ) ) == K );\n    CPPAD_ASSERT_UNKNOWN( size_t( size_t( col.size() ) ) == K );\n\n    // Point at which we are evaluating the Jacobian\n    Forward(0, x);\n\n    // check for case where nothing (except Forward above) to do\n    if( K == 0 )\n        return 0;\n\n    if( color.size() == 0 )\n    {\n        CPPAD_ASSERT_UNKNOWN( p.n_set() == m );\n        CPPAD_ASSERT_UNKNOWN( p.end()   == n );\n\n        // execute the coloring algorithm\n        color.resize(m);\n        if( work.color_method == \"cppad\" )\n            local::color_general_cppad(p, row, col, color);\n        else if( work.color_method == \"colpack\" )\n        {\n# if CPPAD_HAS_COLPACK\n            local::color_general_colpack(p, row, col, color);\n# else\n            CPPAD_ASSERT_KNOWN(\n                false,\n                \"SparseJacobianReverse: work.color_method = colpack \"\n                \"and colpack_prefix missing from cmake command line.\"\n            );\n# endif\n        }\n        else CPPAD_ASSERT_KNOWN(\n            false,\n            \"SparseJacobianReverse: work.color_method is not valid.\"\n        );\n\n        // put sorting indices in color order\n        SizeVector key(K);\n        order.resize(K);\n        for(k = 0; k < K; k++)\n            key[k] = color[ row[k] ];\n        index_sort(key, order);\n    }\n    size_t n_color = 1;\n    for(i = 0; i < m; i++) if( color[i] < m )\n        n_color = std::max<size_t>(n_color, color[i] + 1);\n\n    // weighting vector for calls to reverse\n    BaseVector w(m);\n\n    // location for return values from Reverse\n    BaseVector dw(n);\n\n    // initialize the return value\n    for(k = 0; k < K; k++)\n        jac[k] = zero;\n\n    // loop over colors\n    k = 0;\n    for(ell = 0; ell < n_color; ell++)\n    {   CPPAD_ASSERT_UNKNOWN( color[ row[ order[k] ] ] == ell );\n\n        // combine all the rows with this color\n        for(i = 0; i < m; i++)\n        {   w[i] = zero;\n            if( color[i] == ell )\n                w[i] = one;\n        }\n        // call reverse mode for all these rows at once\n        dw = Reverse(1, w);\n\n        // set the corresponding components of the result\n        while( k < K && color[ row[order[k]] ]  == ell )\n        {   jac[ order[k] ] = dw[col[order[k]]];\n            k++;\n        }\n    }\n    return n_color;\n}\n// ==========================================================================\n// Public Member functions\n// ==========================================================================\n/*!\nCompute user specified subset of a sparse Jacobian using forward mode.\n\nThe C++ source code corresponding to this operation is\n\\verbatim\n    SparseJacobinanForward(x, p, row, col, jac, work)\n\\endverbatim\n\n\\tparam Base\nis the base type for the recording that is stored in this\n<code>ADFun<Base></code> object.\n\n\\tparam BaseVector\nis a simple vector class with elements of type Base.\n\n\\tparam SetVector\nis a simple vector class with elements of type\n bool or std::set<size_t>.\n\n\\tparam SizeVector\nis a simple vector class with elements of type size_t.\n\n\\param x [in]\nis a vector specifying the point at which to compute the Jacobian.\n\n\\param p [in]\nis the sparsity pattern for the Jacobian that we are calculating.\n\n\\param row [in]\nis the vector of row indices for the returned Jacobian values.\n\n\\param col [in]\nis the vector of columns indices for the returned Jacobian values.\nIt must have the same size as row.\n\n\\param jac [out]\nis the vector of Jacobian values.\nIt must have the same size as row.\nThe return value <code>jac[k]</code> is the partial of the\n<code>row[k]</code> range component of the function with respect\nthe the <code>col[k]</code> domain component of its argument.\n\n\\param work [in,out]\nthis structure contains information that depends on the function object,\nsparsity pattern, row vector, and col vector.\nIf they are not the same between calls to SparseJacobianForward,\n work.clear() must be called to reinitialize them.\n\n\\return\nIs the number of first order forward sweeps used to compute the\nrequested Jacobian values. The total work, not counting the zero order\nforward sweep, or the time to combine computations, is proportional to this\nreturn value.\n*/\ntemplate <class Base, class RecBase>\ntemplate <class BaseVector, class SetVector, class SizeVector>\nsize_t ADFun<Base,RecBase>::SparseJacobianForward(\n    const BaseVector&     x    ,\n    const SetVector&      p    ,\n    const SizeVector&     row  ,\n    const SizeVector&     col  ,\n    BaseVector&           jac  ,\n    sparse_jacobian_work& work )\n{\n    size_t n = Domain();\n    size_t m = Range();\n    size_t K = jac.size();\n# ifndef NDEBUG\n    size_t k;\n    CPPAD_ASSERT_KNOWN(\n        size_t(x.size()) == n ,\n        \"SparseJacobianForward: size of x not equal domain dimension for f.\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t(row.size()) == K && size_t(col.size()) == K ,\n        \"SparseJacobianForward: either r or c does not have \"\n        \"the same size as jac.\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        work.color.size() == 0 || work.color.size() == n,\n        \"SparseJacobianForward: invalid value in work.\"\n    );\n    for(k = 0; k < K; k++)\n    {   CPPAD_ASSERT_KNOWN(\n            row[k] < m,\n            \"SparseJacobianForward: invalid value in r.\"\n        );\n        CPPAD_ASSERT_KNOWN(\n            col[k] < n,\n            \"SparseJacobianForward: invalid value in c.\"\n        );\n    }\n    if( work.color.size() != 0 )\n        for(size_t j = 0; j < n; j++) CPPAD_ASSERT_KNOWN(\n            work.color[j] <= n,\n            \"SparseJacobianForward: invalid value in work.\"\n    );\n# endif\n    // check for case where there is nothing to compute\n    size_t n_sweep = 0;\n    if( K == 0 )\n        return n_sweep;\n\n    typedef typename SetVector::value_type Set_type;\n    typedef typename local::sparse::internal_pattern<Set_type>::pattern_type Pattern_type;\n    Pattern_type s_transpose;\n    if( work.color.size() == 0 )\n    {   bool transpose = true;\n        const char* error_msg = \"SparseJacobianForward: transposed sparsity\"\n        \" pattern does not have proper row or column dimension\";\n        sparsity_user2internal(s_transpose, p, n, m, transpose, error_msg);\n    }\n    n_sweep = SparseJacobianFor(x, s_transpose, row, col, jac, work);\n    return n_sweep;\n}\n/*!\nCompute user specified subset of a sparse Jacobian using forward mode.\n\nThe C++ source code corresponding to this operation is\n\\verbatim\n    SparseJacobinanReverse(x, p, row, col, jac, work)\n\\endverbatim\n\n\\tparam Base\nis the base type for the recording that is stored in this\n<code>ADFun<Base></code> object.\n\n\\tparam BaseVector\nis a simple vector class with elements of type Base.\n\n\\tparam SetVector\nis a simple vector class with elements of type\n bool or std::set<size_t>.\n\n\\tparam SizeVector\nis a simple vector class with elements of type size_t.\n\n\\param x [in]\nis a vector specifying the point at which to compute the Jacobian.\n\n\\param p [in]\nis the sparsity pattern for the Jacobian that we are calculating.\n\n\\param row [in]\nis the vector of row indices for the returned Jacobian values.\n\n\\param col [in]\nis the vector of columns indices for the returned Jacobian values.\nIt must have the same size as row.\n\n\\param jac [out]\nis the vector of Jacobian values.\nIt must have the same size as row.\nThe return value <code>jac[k]</code> is the partial of the\n<code>row[k]</code> range component of the function with respect\nthe the <code>col[k]</code> domain component of its argument.\n\n\\param work [in,out]\nthis structure contains information that depends on the function object,\nsparsity pattern, row vector, and col vector.\nIf they are not the same between calls to SparseJacobianReverse,\n work.clear() must be called to reinitialize them.\n\n\\return\nIs the number of first order reverse sweeps used to compute the\nreverse Jacobian values. The total work, not counting the zero order\nforward sweep, or the time to combine computations, is proportional to this\nreturn value.\n*/\ntemplate <class Base, class RecBase>\ntemplate <class BaseVector, class SetVector, class SizeVector>\nsize_t ADFun<Base,RecBase>::SparseJacobianReverse(\n    const BaseVector&     x    ,\n    const SetVector&      p    ,\n    const SizeVector&     row  ,\n    const SizeVector&     col  ,\n    BaseVector&           jac  ,\n    sparse_jacobian_work& work )\n{\n    size_t m = Range();\n    size_t n = Domain();\n    size_t K = jac.size();\n# ifndef NDEBUG\n    size_t k;\n    CPPAD_ASSERT_KNOWN(\n        size_t(x.size()) == n ,\n        \"SparseJacobianReverse: size of x not equal domain dimension for f.\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t(row.size()) == K && size_t(col.size()) == K ,\n        \"SparseJacobianReverse: either r or c does not have \"\n        \"the same size as jac.\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        work.color.size() == 0 || work.color.size() == m,\n        \"SparseJacobianReverse: invalid value in work.\"\n    );\n    for(k = 0; k < K; k++)\n    {   CPPAD_ASSERT_KNOWN(\n            row[k] < m,\n            \"SparseJacobianReverse: invalid value in r.\"\n        );\n        CPPAD_ASSERT_KNOWN(\n            col[k] < n,\n            \"SparseJacobianReverse: invalid value in c.\"\n        );\n    }\n    if( work.color.size() != 0 )\n        for(size_t i = 0; i < m; i++) CPPAD_ASSERT_KNOWN(\n            work.color[i] <= m,\n            \"SparseJacobianReverse: invalid value in work.\"\n    );\n# endif\n    // check for case where there is nothing to compute\n    size_t n_sweep = 0;\n    if( K == 0 )\n        return n_sweep;\n\n    typedef typename SetVector::value_type Set_type;\n    typedef typename local::sparse::internal_pattern<Set_type>::pattern_type Pattern_type;\n    Pattern_type s;\n    if( work.color.size() == 0 )\n    {   bool transpose = false;\n        const char* error_msg = \"SparseJacobianReverse: sparsity\"\n        \" pattern does not have proper row or column dimension\";\n        sparsity_user2internal(s, p, m, n, transpose, error_msg);\n    }\n    n_sweep = SparseJacobianRev(x, s, row, col, jac, work);\n    return n_sweep;\n}\n/*!\nCompute a sparse Jacobian.\n\nThe C++ source code corresponding to this operation is\n\\verbatim\n    jac = SparseJacobian(x, p)\n\\endverbatim\n\n\\tparam Base\nis the base type for the recording that is stored in this\n<code>ADFun<Base></code> object.\n\n\\tparam BaseVector\nis a simple vector class with elements of type Base.\n\n\\tparam SetVector\nis a simple vector class with elements of type\n bool or std::set<size_t>.\n\n\\param x [in]\nis a vector specifying the point at which to compute the Jacobian.\n\n\\param p [in]\nis the sparsity pattern for the Jacobian that we are calculating.\n\n\\return\nWill be a vector if size m * n containing the Jacobian at the\nspecified point (in row major order).\n*/\ntemplate <class Base, class RecBase>\ntemplate <class BaseVector, class SetVector>\nBaseVector ADFun<Base,RecBase>::SparseJacobian(\n    const BaseVector& x, const SetVector& p\n)\n{   size_t i, j, k;\n\n    size_t m = Range();\n    size_t n = Domain();\n    BaseVector jac(m * n);\n\n    CPPAD_ASSERT_KNOWN(\n        size_t(x.size()) == n,\n        \"SparseJacobian: size of x not equal domain size for f.\"\n    );\n    CheckSimpleVector<Base, BaseVector>();\n\n    typedef typename SetVector::value_type Set_type;\n    typedef typename local::sparse::internal_pattern<Set_type>::pattern_type Pattern_type;\n\n    // initialize the return value as zero\n    Base zero(0);\n    for(i = 0; i < m; i++)\n        for(j = 0; j < n; j++)\n            jac[i * n + j] = zero;\n\n    sparse_jacobian_work work;\n    CppAD::vector<size_t> row;\n    CppAD::vector<size_t> col;\n    if( n <= m )\n    {\n        // need an internal copy of sparsity pattern\n        Pattern_type s_transpose;\n        bool transpose = true;\n        const char* error_msg = \"SparseJacobian: transposed sparsity\"\n        \" pattern does not have proper row or column dimension\";\n        sparsity_user2internal(s_transpose, p, n, m, transpose, error_msg);\n\n        k = 0;\n        for(j = 0; j < n; j++)\n        {   typename Pattern_type::const_iterator itr(s_transpose, j);\n            i = *itr;\n            while( i != s_transpose.end() )\n            {   row.push_back(i);\n                col.push_back(j);\n                k++;\n                i = *(++itr);\n            }\n        }\n        size_t K = k;\n        BaseVector J(K);\n\n        // now we have folded this into the following case\n        SparseJacobianFor(x, s_transpose, row, col, J, work);\n\n        // now set the non-zero return values\n        for(k = 0; k < K; k++)\n            jac[ row[k] * n + col[k] ] = J[k];\n    }\n    else\n    {\n        // need an internal copy of sparsity pattern\n        Pattern_type s;\n        bool transpose = false;\n        const char* error_msg = \"SparseJacobian: sparsity\"\n        \" pattern does not have proper row or column dimension\";\n        sparsity_user2internal(s, p, m, n, transpose, error_msg);\n\n        k = 0;\n        for(i = 0; i < m; i++)\n        {   typename Pattern_type::const_iterator itr(s, i);\n            j = *itr;\n            while( j != s.end() )\n            {   row.push_back(i);\n                col.push_back(j);\n                k++;\n                j = *(++itr);\n            }\n        }\n        size_t K = k;\n        BaseVector J(K);\n\n        // now we have folded this into the following case\n        SparseJacobianRev(x, s, row, col, J, work);\n\n        // now set the non-zero return values\n        for(k = 0; k < K; k++)\n            jac[ row[k] * n + col[k] ] = J[k];\n    }\n\n    return jac;\n}\n\n/*!\nCompute a sparse Jacobian.\n\nThe C++ source code corresponding to this operation is\n\\verbatim\n    jac = SparseJacobian(x)\n\\endverbatim\n\n\\tparam Base\nis the base type for the recording that is stored in this\n<code>ADFun<Base></code> object.\n\n\\tparam BaseVector\nis a simple vector class with elements of the Base.\n\n\\param x [in]\nis a vector specifying the point at which to compute the Jacobian.\n\n\\return\nWill be a vector of size m * n containing the Jacobian at the\nspecified point (in row major order).\n*/\ntemplate <class Base, class RecBase>\ntemplate <class BaseVector>\nBaseVector ADFun<Base,RecBase>::SparseJacobian( const BaseVector& x )\n{   typedef CppAD::vectorBool   BoolVector;\n\n    size_t m = Range();\n    size_t n = Domain();\n\n    // sparsity pattern for Jacobian\n    BoolVector p(m * n);\n\n    if( n <= m )\n    {   size_t j, k;\n\n        // use forward mode\n        BoolVector r(n * n);\n        for(j = 0; j < n; j++)\n        {   for(k = 0; k < n; k++)\n                r[j * n + k] = false;\n            r[j * n + j] = true;\n        }\n        p = ForSparseJac(n, r);\n    }\n    else\n    {   size_t i, k;\n\n        // use reverse mode\n        BoolVector s(m * m);\n        for(i = 0; i < m; i++)\n        {   for(k = 0; k < m; k++)\n                s[i * m + k] = false;\n            s[i * m + i] = true;\n        }\n        p = RevSparseJac(m, s);\n    }\n    return SparseJacobian(x, p);\n}\n\n} // END_CPPAD_NAMESPACE\n# undef CPPAD_SPARSE_JACOBIAN_MAX_MULTIPLE_DIRECTION\n# endif\n"
  },
  {
    "path": "include/cppad/core/standard_math.hpp",
    "content": "# ifndef CPPAD_CORE_STANDARD_MATH_HPP\n# define CPPAD_CORE_STANDARD_MATH_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin unary_standard_math}\n{xrst_spell\n    acosh\n    asinh\n    expm\n}\n\nThe Unary Standard Math Functions\n#################################\n\nSyntax\n******\n| *y* = *fun* ( *x* )\n\nPurpose\n*******\nEvaluates the standard math function *fun* .\n\nPossible Types\n**************\n\nBase\n====\nIf *Base* satisfies the\n:ref:`base type requirements<base_require-name>`\nand argument *x* has prototype\n\n    ``const`` *Base* & *x*\n\nthen the result *y* has prototype\n\n    *Base* *y*\n\nAD<Base>\n========\nIf the argument *x* has prototype\n\n    ``const AD`` < *Base* >& *x*\n\nthen the result *y* has prototype\n\n    ``AD`` < *Base* > *y*\n\nVecAD<Base>\n===========\nIf the argument *x* has prototype\n\n    ``const VecAD`` < *Base* >:: ``reference&`` *x*\n\nthen the result *y* has prototype\n\n    ``AD`` < *Base* > *y*\n\n{xrst_toc_hidden\n    include/cppad/core/std_math_11.hpp\n    include/cppad/core/abs.hpp\n    include/cppad/core/sign.hpp\n}\n\nfun\n***\nThe possible values for *fun* are\n\n.. csv-table::\n    :widths: auto\n\n    *fun*,Description\n    abs,:ref:`abs-title`\n    acos,:ref:`acos-title`\n    acosh,:ref:`acosh-title`\n    asin,:ref:`asin-title`\n    asinh,:ref:`asinh-title`\n    atan,:ref:`atan-title`\n    atanh,:ref:`atanh-title`\n    cos,:ref:`cos-title`\n    cosh,:ref:`cosh-title`\n    erf,:ref:`erf-title`\n    exp,:ref:`exp-title`\n    expm1,:ref:`expm1-title`\n    :ref:`fabs<abs-name>` :ref:`abs-title`\n    log10,:ref:`log10-title`\n    log1p,:ref:`log1p-title`\n    log,:ref:`log-title`\n    sign,:ref:`sign-title`\n    sin,:ref:`sin-title`\n    sinh,:ref:`sinh-title`\n    sqrt,:ref:`sqrt-title`\n    tan,:ref:`tan-title`\n    tanh,:ref:`tanh-title`\n\n{xrst_end unary_standard_math}\n*/\n# include <cppad/core/abs.hpp>\n# include <cppad/core/sign.hpp>\n\n/*\n{xrst_begin binary_math}\n\nThe Binary Math Functions\n#########################\n\nContents\n********\n{xrst_toc_table\n    include/cppad/core/atan2.hpp\n    include/cppad/core/pow.hpp\n    include/cppad/core/azmul.hpp\n}\n\n{xrst_end binary_math}\n*/\n# include <cppad/core/atan2.hpp>\n# include <cppad/core/pow.hpp>\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/std_math_11.hpp",
    "content": "# ifndef CPPAD_CORE_STD_MATH_11_HPP\n# define CPPAD_CORE_STD_MATH_11_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n-------------------------------------------------------------------------------\n{xrst_begin acos}\n\nInverse Cosine Function: acos\n#############################\n\nSyntax\n******\n| *y* = ``acos`` ( *x* )\n\nx, y\n****\nSee the :ref:`unary_standard_math@Possible Types`\nfor a unary standard math function.\n\nAtomic\n******\nThis is an :ref:`atomic operation<glossary@Operation@Atomic>` .\n\nDerivative\n**********\n\n.. math::\n\n    \\R{acos}^{(1)} (x) = - (1 - x * x)^{-1/2}\n\nExample\n*******\n{xrst_toc_hidden\n    example/general/acos.cpp\n}\nThe file\n:ref:`acos.cpp-name`\ncontains an example and test of this function.\n\n{xrst_end acos}\n-------------------------------------------------------------------------------\n{xrst_begin acosh}\nThe Inverse Hyperbolic Cosine Function: acosh\n#############################################\n\nSyntax\n******\n*y* = ``acosh`` ( *x* )\n\nDescription\n***********\nThe inverse hyperbolic cosine function is defined by\n*x* == ``cosh`` ( *y* ) .\n\nx, y\n****\nSee the :ref:`unary_standard_math@Possible Types`\nfor a unary standard math function.\n\nAtomic\n******\nThis is an :ref:`atomic operation<glossary@Operation@Atomic>` .\n\nExample\n*******\n{xrst_toc_hidden\n    example/general/acosh.cpp\n}\nThe file\n:ref:`acosh.cpp-name`\ncontains an example and test of this function.\n\n{xrst_end acosh}\n-------------------------------------------------------------------------------\n{xrst_begin asin}\n\nInverse Sine Function: asin\n###########################\n\nSyntax\n******\n*y* = ``asin`` ( *x* )\n\nx, y\n****\nSee the :ref:`unary_standard_math@Possible Types`\nfor a unary standard math function.\n\nAtomic\n******\nThis is an :ref:`atomic operation<glossary@Operation@Atomic>` .\n\nDerivative\n**********\n\n.. math::\n\n    \\R{asin}^{(1)} (x) = (1 - x * x)^{-1/2}\n\nExample\n*******\n{xrst_toc_hidden\n    example/general/asin.cpp\n}\nThe file\n:ref:`asin.cpp-name`\ncontains an example and test of this function.\n\n{xrst_end asin}\n-------------------------------------------------------------------------------\n{xrst_begin asinh}\nThe Inverse Hyperbolic Sine Function: asinh\n###########################################\n\nSyntax\n******\n*y* = ``asinh`` ( *x* )\n\nDescription\n***********\nThe inverse hyperbolic sine function is defined by\n*x* == ``sinh`` ( *y* ) .\n\nx, y\n****\nSee the :ref:`unary_standard_math@Possible Types`\nfor a unary standard math function.\n\nAtomic\n******\nThis is an :ref:`atomic operation<glossary@Operation@Atomic>` .\n\nExample\n*******\n{xrst_toc_hidden\n    example/general/asinh.cpp\n}\nThe file\n:ref:`asinh.cpp-name`\ncontains an example and test of this function.\n\n{xrst_end asinh}\n-------------------------------------------------------------------------------\n{xrst_begin atan}\n\nInverse Tangent Function: atan\n##############################\n\nSyntax\n******\n*y* = ``atan`` ( *x* )\n\nx, y\n****\nSee the :ref:`unary_standard_math@Possible Types`\nfor a unary standard math function.\n\nAtomic\n******\nThis is an :ref:`atomic operation<glossary@Operation@Atomic>` .\n\nDerivative\n**********\n\n.. math::\n\n    \\R{atan}^{(1)} (x) = \\frac{1}{1 + x^2}\n\nExample\n*******\n{xrst_toc_hidden\n    example/general/atan.cpp\n}\nThe file\n:ref:`atan.cpp-name`\ncontains an example and test of this function.\n\n{xrst_end atan}\n-------------------------------------------------------------------------------\n{xrst_begin atanh}\nThe Inverse Hyperbolic Tangent Function: atanh\n##############################################\n\nSyntax\n******\n*y* = ``atanh`` ( *x* )\n\nDescription\n***********\nThe inverse hyperbolic tangent function is defined by\n*x* == ``tanh`` ( *y* ) .\n\nx, y\n****\nSee the :ref:`unary_standard_math@Possible Types`\nfor a unary standard math function.\n\nAtomic\n******\nThis is an :ref:`atomic operation<glossary@Operation@Atomic>` .\n\nExample\n*******\n{xrst_toc_hidden\n    example/general/atanh.cpp\n}\nThe file\n:ref:`atanh.cpp-name`\ncontains an example and test of this function.\n\n{xrst_end atanh}\n-------------------------------------------------------------------------------\n{xrst_begin cos}\n\nThe Cosine Function: cos\n########################\n\nSyntax\n******\n*y* = ``cos`` ( *x* )\n\nx, y\n****\nSee the :ref:`unary_standard_math@Possible Types`\nfor a unary standard math function.\n\nAtomic\n******\nThis is an :ref:`atomic operation<glossary@Operation@Atomic>` .\n\nDerivative\n**********\n\n.. math::\n\n    \\R{cos}^{(1)} (x) = - \\sin(x)\n\nExample\n*******\n{xrst_toc_hidden\n    example/general/cos.cpp\n}\nThe file\n:ref:`cos.cpp-name`\ncontains an example and test of this function.\n\n{xrst_end cos}\n-------------------------------------------------------------------------------\n{xrst_begin cosh}\n\nThe Hyperbolic Cosine Function: cosh\n####################################\n\nSyntax\n******\n*y* = ``cosh`` ( *x* )\n\nx, y\n****\nSee the :ref:`unary_standard_math@Possible Types`\nfor a unary standard math function.\n\nAtomic\n******\nThis is an :ref:`atomic operation<glossary@Operation@Atomic>` .\n\nDerivative\n**********\n\n.. math::\n\n    \\R{cosh}^{(1)} (x) = \\sinh(x)\n\nExample\n*******\n{xrst_toc_hidden\n    example/general/cosh.cpp\n}\nThe file\n:ref:`cosh.cpp-name`\ncontains an example and test of this function.\n\n{xrst_end cosh}\n-------------------------------------------------------------------------------\n{xrst_begin erf}\nThe Error Function\n##################\n\nSyntax\n******\n*y* = ``erf`` ( *x* )\n\nDescription\n***********\nReturns the value of the error function which is defined by\n\n.. math::\n\n    {\\rm erf} (x) = \\frac{2}{ \\sqrt{\\pi} } \\int_0^x \\exp( - t * t ) \\; {\\bf d} t\n\nx, y\n****\nSee the :ref:`unary_standard_math@Possible Types`\nfor a unary standard math function.\n\nAtomic\n******\nThis is an :ref:`atomic operation<glossary@Operation@Atomic>` .\n\nExample\n*******\n{xrst_toc_hidden\n    example/general/erf.cpp\n}\nThe file\n:ref:`erf.cpp-name`\ncontains an example and test of this function.\n\n{xrst_end erf}\n-------------------------------------------------------------------------------\n{xrst_begin erfc}\nThe Complementary Error Function: erfc\n######################################\n\nSyntax\n******\n*y* = ``erfc`` ( *x* )\n\nDescription\n***********\nReturns the value of the complementary error function which is defined by\n*y* == 1 ``- erf`` ( *x* ) .\n\nx, y\n****\nSee the :ref:`unary_standard_math@Possible Types`\nfor a unary standard math function.\n\nAtomic\n******\nThis is an :ref:`atomic operation<glossary@Operation@Atomic>` .\n\nExample\n*******\n{xrst_toc_hidden\n    example/general/erfc.cpp\n}\nThe file\n:ref:`erfc.cpp-name`\ncontains an example and test of this function.\n\n{xrst_end erfc}\n-------------------------------------------------------------------------------\n{xrst_begin exp}\n\nThe Exponential Function: exp\n#############################\n\nSyntax\n******\n*y* = ``exp`` ( *x* )\n\nx, y\n****\nSee the :ref:`unary_standard_math@Possible Types`\nfor a unary standard math function.\n\nAtomic\n******\nThis is an :ref:`atomic operation<glossary@Operation@Atomic>` .\n\nDerivative\n**********\n\n.. math::\n\n    \\R{exp}^{(1)} (x) = \\exp(x)\n\nExample\n*******\n{xrst_toc_hidden\n    example/general/exp.cpp\n}\nThe file\n:ref:`exp.cpp-name`\ncontains an example and test of this function.\n\n{xrst_end exp}\n-------------------------------------------------------------------------------\n{xrst_begin expm1}\nThe Exponential Function Minus One: expm1\n#########################################\n\nSyntax\n******\n*y* = ``expm1`` ( *x* )\n\nDescription\n***********\nReturns the value of the exponential function minus one which is defined\nby *y* == ``exp`` ( *x* ) ``- 1`` .\n\nx, y\n****\nSee the :ref:`unary_standard_math@Possible Types`\nfor a unary standard math function.\n\nAtomic\n******\nThis is an :ref:`atomic operation<glossary@Operation@Atomic>` .\n\nExample\n*******\n{xrst_toc_hidden\n    example/general/expm1.cpp\n}\nThe file\n:ref:`expm1.cpp-name`\ncontains an example and test of this function.\n\n{xrst_end expm1}\n-------------------------------------------------------------------------------\n{xrst_begin log}\n\nThe Exponential Function: log\n#############################\n\nSyntax\n******\n*y* = ``log`` ( *x* )\n\nx, y\n****\nSee the :ref:`unary_standard_math@Possible Types`\nfor a unary standard math function.\n\nAtomic\n******\nThis is an :ref:`atomic operation<glossary@Operation@Atomic>` .\n\nDerivative\n**********\n\n.. math::\n\n    \\R{log}^{(1)} (x) = \\frac{1}{x}\n\nExample\n*******\n{xrst_toc_hidden\n    example/general/log.cpp\n}\nThe file\n:ref:`log.cpp-name`\ncontains an example and test of this function.\n\n{xrst_end log}\n-------------------------------------------------------------------------------\n{xrst_begin log1p}\n\nThe Logarithm of One Plus Argument: log1p\n#########################################\n\nSyntax\n******\n*y* = ``log1p`` ( *x* )\n\nDescription\n***********\nReturns the value of the logarithm of one plus argument which is defined\nby *y* == ``log`` (1 + *x* ) .\n\nx, y\n****\nSee the :ref:`unary_standard_math@Possible Types`\nfor a unary standard math function.\n\nAtomic\n******\nThis is an :ref:`atomic operation<glossary@Operation@Atomic>` .\n\nExample\n*******\n{xrst_toc_hidden\n    example/general/log1p.cpp\n}\nThe file\n:ref:`log1p.cpp-name`\ncontains an example and test of this function.\n\n{xrst_end log1p}\n-------------------------------------------------------------------------------\n{xrst_begin log10}\n\nThe Base 10 Logarithm Function: log10\n#####################################\n\nSyntax\n******\n*y* = ``log10`` ( *x* )\n\nx, y\n****\nSee the :ref:`unary_standard_math@Possible Types`\nfor a unary standard math function.\n\nMethod\n******\nCppAD uses the representation\n\n.. math::\n\n    {\\rm log10} (x) = \\log(x) / \\log(10)\n\nExample\n*******\n{xrst_toc_hidden\n    example/general/log10.cpp\n}\nThe file\n:ref:`log10.cpp-name`\ncontains an example and test of this function.\n\n{xrst_end log10}\n-------------------------------------------------------------------------------\n{xrst_begin sin}\n\nThe Sine Function: sin\n######################\n\nSyntax\n******\n*y* = ``sin`` ( *x* )\n\nx, y\n****\nSee the :ref:`unary_standard_math@Possible Types`\nfor a unary standard math function.\n\nAtomic\n******\nThis is an :ref:`atomic operation<glossary@Operation@Atomic>` .\n\nDerivative\n**********\n\n.. math::\n\n    \\R{sin}^{(1)} (x) = \\cos(x)\n\nExample\n*******\n{xrst_toc_hidden\n    example/general/sin.cpp\n}\nThe file\n:ref:`sin.cpp-name`\ncontains an example and test of this function.\n\n{xrst_end sin}\n-------------------------------------------------------------------------------\n{xrst_begin sinh}\n\nThe Hyperbolic Sine Function: sinh\n##################################\n\nSyntax\n******\n*y* = ``sinh`` ( *x* )\n\nx, y\n****\nSee the :ref:`unary_standard_math@Possible Types`\nfor a unary standard math function.\n\nAtomic\n******\nThis is an :ref:`atomic operation<glossary@Operation@Atomic>` .\n\nDerivative\n**********\n\n.. math::\n\n    \\R{sinh}^{(1)} (x) = \\cosh(x)\n\nExample\n*******\n{xrst_toc_hidden\n    example/general/sinh.cpp\n}\nThe file\n:ref:`sinh.cpp-name`\ncontains an example and test of this function.\n\n{xrst_end sinh}\n-------------------------------------------------------------------------------\n{xrst_begin sqrt}\n\nThe Square Root Function: sqrt\n##############################\n\nSyntax\n******\n*y* = ``sqrt`` ( *x* )\n\nx, y\n****\nSee the :ref:`unary_standard_math@Possible Types`\nfor a unary standard math function.\n\nAtomic\n******\nThis is an :ref:`atomic operation<glossary@Operation@Atomic>` .\n\nDerivative\n**********\n\n.. math::\n\n    \\R{sqrt}^{(1)} (x) = \\frac{1}{2 \\R{sqrt} (x) }\n\nExample\n*******\n{xrst_toc_hidden\n    example/general/sqrt.cpp\n}\nThe file\n:ref:`sqrt.cpp-name`\ncontains an example and test of this function.\n\n{xrst_end sqrt}\n-------------------------------------------------------------------------------\n{xrst_begin tan}\n\nThe Tangent Function: tan\n#########################\n\nSyntax\n******\n*y* = ``tan`` ( *x* )\n\nx, y\n****\nSee the :ref:`unary_standard_math@Possible Types`\nfor a unary standard math function.\n\nAtomic\n******\nThis is an :ref:`atomic operation<glossary@Operation@Atomic>` .\n\nDerivative\n**********\n\n.. math::\n\n    \\R{tan}^{(1)} (x) = 1 + \\tan (x)^2\n\nExample\n*******\n{xrst_toc_hidden\n    example/general/tan.cpp\n}\nThe file\n:ref:`tan.cpp-name`\ncontains an example and test of this function.\n\n{xrst_end tan}\n-------------------------------------------------------------------------------\n{xrst_begin tanh}\n\nThe Hyperbolic Tangent Function: tanh\n#####################################\n\nSyntax\n******\n*y* = ``tanh`` ( *x* )\n\nx, y\n****\nSee the :ref:`unary_standard_math@Possible Types`\nfor a unary standard math function.\n\nAtomic\n******\nThis is an :ref:`atomic operation<glossary@Operation@Atomic>` .\n\nDerivative\n**********\n\n.. math::\n\n    \\R{tanh}^{(1)} (x) = 1 - \\tanh (x)^2\n\nExample\n*******\n{xrst_toc_hidden\n    example/general/tanh.cpp\n}\nThe file\n:ref:`tanh.cpp-name`\ncontains an example and test of this function.\n\n{xrst_end tanh}\n-------------------------------------------------------------------------------\n*/\n\n/*!\n\\file std_math_11.hpp\nDefine AD<Base> standard math functions (using their Base versions)\n*/\n\n/*!\n\\def CPPAD_STANDARD_MATH_UNARY_AD(Name, Op)\nDefines function Name with argument type AD<Base> and tape operation Op\n\nThe macro defines the function x.Name() where x has type AD<Base>.\nIt then uses this function to define Name(x) where x has type\nAD<Base> or VecAD_reference<Base>.\n\nIf x is a variable, the tape unary operator Op is used\nto record the operation and the result is identified as corresponding\nto this operation; i.e., Name(x).taddr_ identifies the operation and\nName(x).tape_id_ identifies the tape.\n\nThis macro is used to define AD<Base> versions of\nacos, asin, atan, cos, cosh, exp, fabs, log, sin, sinh, sqrt, tan, tanh.\n*/\n\n# define CPPAD_STANDARD_MATH_UNARY_AD(Name, Op)                   \\\n    template <class Base>                                         \\\n    inline AD<Base> Name(const AD<Base> &x)                       \\\n    {   return x.Name##_me();                                     \\\n    }                                                             \\\n    template <class Base>                                         \\\n    inline AD<Base> AD<Base>::Name##_me (void) const              \\\n    {                                                              \\\n        AD<Base> result;                                          \\\n        result.value_ = CppAD::Name(value_);                      \\\n        CPPAD_ASSERT_UNKNOWN( Parameter(result) );                \\\n                                                                                        \\\n        local::ADTape<Base>* tape = AD<Base>::tape_ptr();         \\\n        if( tape == nullptr )                                  \\\n            return result;                                        \\\n                                                                                        \\\n        if( tape_id_ != tape->id_ )                               \\\n            return result;                                        \\\n                                                                                        \\\n        if(ad_type_ == dynamic_enum)                        \\\n        {   result.taddr_ = tape->Rec_.put_dyn_par(               \\\n                result.value_, local::Name##_dyn, taddr_          \\\n            );                                                    \\\n            result.tape_id_ = tape_id_;                           \\\n            result.ad_type_ = dynamic_enum;                 \\\n        }                                                         \\\n        else                                                      \\\n        {   CPPAD_ASSERT_UNKNOWN( NumArg(Op) == 1 );              \\\n            tape->Rec_.PutArg(taddr_);                            \\\n            result.taddr_    = tape->Rec_.PutOp(Op);              \\\n            result.tape_id_  = tape->id_;                         \\\n            result.ad_type_  = variable_enum;                \\\n        }                                                         \\\n        return result;                                            \\\n    }                                                             \\\n    template <class Base>                                         \\\n    inline AD<Base> Name(const VecAD_reference<Base> &x)          \\\n    {   return x.ADBase().Name##_me(); }\n\n//  BEGIN CppAD namespace\nnamespace CppAD {\n\n      CPPAD_STANDARD_MATH_UNARY_AD(acos, local::AcosOp)\n      CPPAD_STANDARD_MATH_UNARY_AD(acosh, local::AcoshOp)\n      CPPAD_STANDARD_MATH_UNARY_AD(asin, local::AsinOp)\n      CPPAD_STANDARD_MATH_UNARY_AD(asinh, local::AsinhOp)\n      CPPAD_STANDARD_MATH_UNARY_AD(atan, local::AtanOp)\n      CPPAD_STANDARD_MATH_UNARY_AD(atanh, local::AtanhOp)\n      CPPAD_STANDARD_MATH_UNARY_AD(cos, local::CosOp)\n      CPPAD_STANDARD_MATH_UNARY_AD(cosh, local::CoshOp)\n      CPPAD_STANDARD_MATH_UNARY_AD(exp, local::ExpOp)\n      CPPAD_STANDARD_MATH_UNARY_AD(expm1, local::Expm1Op)\n      CPPAD_STANDARD_MATH_UNARY_AD(fabs, local::AbsOp)\n      CPPAD_STANDARD_MATH_UNARY_AD(log, local::LogOp)\n      CPPAD_STANDARD_MATH_UNARY_AD(log1p, local::Log1pOp)\n      CPPAD_STANDARD_MATH_UNARY_AD(sin, local::SinOp)\n      CPPAD_STANDARD_MATH_UNARY_AD(sinh, local::SinhOp)\n      CPPAD_STANDARD_MATH_UNARY_AD(sqrt, local::SqrtOp)\n      CPPAD_STANDARD_MATH_UNARY_AD(tan, local::TanOp)\n      CPPAD_STANDARD_MATH_UNARY_AD(tanh, local::TanhOp)\n\n\n    // Error function is a special case\n    template <class Base>\n    inline AD<Base> erf(const AD<Base> &x)\n    {   bool complement = false;\n        return x.erf_me(complement);\n    }\n    template <class Base>\n    inline AD<Base> erfc(const AD<Base> &x)\n    {   bool complement = true;\n        return x.erf_me(complement);\n    }\n    template <class Base>\n    inline AD<Base> AD<Base>::erf_me (bool complement) const\n    {\n        AD<Base> result;\n        if( complement )\n            result.value_ = CppAD::erfc(value_);\n        else\n            result.value_ = CppAD::erf(value_);\n        CPPAD_ASSERT_UNKNOWN( Parameter(result) );\n\n        // check if there is a recording in progress\n        local::ADTape<Base>* tape = AD<Base>::tape_ptr();\n        if( tape == nullptr )\n            return result;\n\n        // check if operand is a constant parameter\n        if( tape_id_ != tape->id_ )\n            return result;\n\n        if(ad_type_ == dynamic_enum)\n        {   local::op_code_dyn op = local::erf_dyn;\n            if( complement )\n                op = local::erfc_dyn;\n\n              // dynamic parameter argument\n            result.taddr_   = tape->Rec_.put_dyn_par(\n                result.value_, op, taddr_\n            );\n            result.tape_id_  = tape_id_;\n            result.ad_type_  = dynamic_enum;\n        }\n        else\n        {   local::op_code_var op = local::ErfOp;\n            if( complement )\n                op = local::ErfcOp;\n\n              // variable argument\n            CPPAD_ASSERT_UNKNOWN( local::NumArg(op) == 3 );\n\n            // arg[0] = argument to erf function\n            tape->Rec_.PutArg(taddr_);\n\n            // arg[1] = zero\n            addr_t p  = tape->Rec_.put_con_par( Base(0.0) );\n            tape->Rec_.PutArg(p);\n\n            // arg[2] = 2 / sqrt(pi)\n            p = tape->Rec_.put_con_par(Base(\n                1.0 / std::sqrt( std::atan(1.0) )\n            ));\n            tape->Rec_.PutArg(p);\n            //\n            result.taddr_   = tape->Rec_.PutOp(op);\n            result.tape_id_ = tape->id_;\n            result.ad_type_ = variable_enum;\n        }\n        return result;\n    }\n    template <class Base>\n    inline AD<Base> erf(const VecAD_reference<Base> &x)\n    {   bool complement = false;\n        return x.ADBase().erf_me(complement);\n    }\n    template <class Base>\n    inline AD<Base> erfc(const VecAD_reference<Base> &x)\n    {   bool complement = true;\n        return x.ADBase().erf_me(complement);\n    }\n\n      /*!\n    Compute the log of base 10 of x where  has type AD<Base>\n\n    \\tparam Base\n    is the base type (different from base for log)\n    for this AD type, see base_require.\n\n    \\param x\n    is the argument for the log10 function.\n\n    \\result\n    if the result is y, then \\f$ x = 10^y \\f$.\n    */\n      template <class Base>\n      inline AD<Base> log10(const AD<Base> &x)\n    {   return CppAD::log(x) / CppAD::log( Base(10) ); }\n      template <class Base>\n      inline AD<Base> log10(const VecAD_reference<Base> &x)\n    {   return CppAD::log(x.ADBase()) / CppAD::log( Base(10) ); }\n}\n\n# undef CPPAD_STANDARD_MATH_UNARY_AD\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/sub.hpp",
    "content": "# ifndef CPPAD_CORE_SUB_HPP\n# define CPPAD_CORE_SUB_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n//  BEGIN CppAD namespace\nnamespace CppAD {\n\ntemplate <class Base>\nAD<Base> operator - (const AD<Base> &left , const AD<Base> &right)\n{\n    // compute the Base part\n    AD<Base> result;\n    result.value_  = left.value_ - right.value_;\n    CPPAD_ASSERT_UNKNOWN( Parameter(result) );\n\n    // check if there is a recording in progress\n    local::ADTape<Base>* tape = AD<Base>::tape_ptr();\n    if( tape == nullptr )\n        return result;\n    tape_id_t tape_id = tape->id_;\n    // tape_id cannot match the default value for tape_id_; i.e., 0\n    CPPAD_ASSERT_UNKNOWN( tape_id > 0 );\n\n    // check if left and right tapes match\n    bool match_left  = left.tape_id_  == tape_id;\n    bool match_right = right.tape_id_ == tape_id;\n\n    // check if left and right are dynamic parameters\n    bool dyn_left  = match_left  & (left.ad_type_ == dynamic_enum);\n    bool dyn_right = match_right & (right.ad_type_ == dynamic_enum);\n\n    // check if left and right are variables\n    bool var_left  = match_left  & (left.ad_type_ != dynamic_enum);\n    bool var_right = match_right & (right.ad_type_ != dynamic_enum);\n\n\n    CPPAD_ASSERT_KNOWN(\n        left.tape_id_ == right.tape_id_ || ! match_left || ! match_right ,\n        \"Subtract: AD variables or dynamic parameters on different threads.\"\n    );\n    if( var_left )\n    {   if( var_right )\n        {   // result = variable - variable\n            CPPAD_ASSERT_UNKNOWN( local::NumRes(local::SubvvOp) == 1 );\n            CPPAD_ASSERT_UNKNOWN( local::NumArg(local::SubvvOp) == 2 );\n\n            // put operand addresses in tape\n            tape->Rec_.PutArg(left.taddr_, right.taddr_);\n            // put operator in the tape\n            result.taddr_ = tape->Rec_.PutOp(local::SubvvOp);\n            // make result a variable\n            result.tape_id_ = tape_id;\n            result.ad_type_ = variable_enum;\n        }\n        else if( (! dyn_right) && IdenticalZero(right.value_) )\n        {   // result = variable - 0\n            result.make_variable(left.tape_id_, left.taddr_);\n        }\n        else\n        {   // result = variable - parameter\n            CPPAD_ASSERT_UNKNOWN( local::NumRes(local::SubvpOp) == 1 );\n            CPPAD_ASSERT_UNKNOWN( local::NumArg(local::SubvpOp) == 2 );\n\n            // put operand addresses in tape\n            addr_t p = right.taddr_;\n            if( ! dyn_right )\n                p = tape->Rec_.put_con_par(right.value_);\n            tape->Rec_.PutArg(left.taddr_, p);\n            // put operator in the tape\n            result.taddr_ = tape->Rec_.PutOp(local::SubvpOp);\n            // make result a variable\n            result.tape_id_ = tape_id;\n            result.ad_type_ = variable_enum;\n        }\n    }\n    else if( var_right )\n    {   // result = parameter - variable\n        CPPAD_ASSERT_UNKNOWN( local::NumRes(local::SubpvOp) == 1 );\n        CPPAD_ASSERT_UNKNOWN( local::NumArg(local::SubpvOp) == 2 );\n\n        // put operand addresses in tape\n        addr_t p = left.taddr_;\n        if( ! dyn_left )\n            p = tape->Rec_.put_con_par(left.value_);\n        tape->Rec_.PutArg(p, right.taddr_);\n        // put operator in the tape\n        result.taddr_ = tape->Rec_.PutOp(local::SubpvOp);\n        // make result a variable\n        result.tape_id_ = tape_id;\n        result.ad_type_ = variable_enum;\n    }\n    else if( dyn_left | dyn_right )\n    {   if( (! dyn_right) && IdenticalZero(right.value_) )\n        {   // this is dynamic - 0\n            result.make_dynamic(left.tape_id_, left.taddr_);\n        }\n        else\n        {\n            addr_t arg0 = left.taddr_;\n            addr_t arg1 = right.taddr_;\n            if( ! dyn_left )\n            arg0 = tape->Rec_.put_con_par(left.value_);\n            if( ! dyn_right )\n            arg1 = tape->Rec_.put_con_par(right.value_);\n            //\n            // parameters with a dynamic parameter result\n            result.taddr_   = tape->Rec_.put_dyn_par(\n                result.value_, local::sub_dyn,   arg0, arg1\n            );\n            result.tape_id_ = tape_id;\n            result.ad_type_ = dynamic_enum;\n        }\n    }\n    return result;\n}\n\n// convert other cases into the case above\nCPPAD_FOLD_AD_VALUED_BINARY_OPERATOR(-)\n\n} // END CppAD namespace\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/sub_eq.hpp",
    "content": "# ifndef CPPAD_CORE_SUB_EQ_HPP\n# define CPPAD_CORE_SUB_EQ_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n//  BEGIN CppAD namespace\nnamespace CppAD {\n\ntemplate <class Base>\nAD<Base>& AD<Base>::operator -= (const AD<Base> &right)\n{\n    // compute the Base part\n    Base left;\n    left    = value_;\n    value_ -= right.value_;\n\n    // check if there is a recording in progress\n    local::ADTape<Base>* tape = AD<Base>::tape_ptr();\n    if( tape == nullptr )\n        return *this;\n    tape_id_t tape_id = tape->id_;\n    // tape_id cannot match the default value for tape_id_; i.e., 0\n    CPPAD_ASSERT_UNKNOWN( tape_id > 0 );\n\n    // check if left and right tapes match\n    bool match_left  = tape_id_       == tape_id;\n    bool match_right = right.tape_id_ == tape_id;\n\n    // check if left and right are dynamic parameters\n    bool dyn_left  = match_left  & (ad_type_ == dynamic_enum);\n    bool dyn_right = match_right & (right.ad_type_ == dynamic_enum);\n\n    // check if left and right are variables\n    bool var_left  = match_left  & (ad_type_ != dynamic_enum);\n    bool var_right = match_right & (right.ad_type_ != dynamic_enum);\n\n    CPPAD_ASSERT_KNOWN(\n        tape_id_ == right.tape_id_ || ! match_left || ! match_right ,\n        \"-= : AD variables or dynamic parameters on different threads.\"\n    );\n    if( var_left )\n    {   if( var_right )\n        {   // this = variable - variable\n            CPPAD_ASSERT_UNKNOWN( local::NumRes(local::SubvvOp) == 1 );\n            CPPAD_ASSERT_UNKNOWN( local::NumArg(local::SubvvOp) == 2 );\n\n            // put operand addresses in tape\n            tape->Rec_.PutArg(taddr_, right.taddr_);\n            // put operator in the tape\n            taddr_ = tape->Rec_.PutOp(local::SubvvOp);\n            // check that this is a variable\n            CPPAD_ASSERT_UNKNOWN( tape_id_ == tape_id );\n            CPPAD_ASSERT_UNKNOWN( ad_type_ == variable_enum);\n        }\n        else if( (! dyn_right) && IdenticalZero(right.value_) )\n        {   // this = variable - 0\n        }\n        else\n        {   // this = variable - parameter\n            CPPAD_ASSERT_UNKNOWN( local::NumRes(local::SubvpOp) == 1 );\n            CPPAD_ASSERT_UNKNOWN( local::NumArg(local::SubvpOp) == 2 );\n\n            // put operand addresses in tape\n            addr_t p = right.taddr_;\n            if( ! dyn_right )\n                p = tape->Rec_.put_con_par(right.value_);\n            tape->Rec_.PutArg(taddr_, p);\n            // put operator in the tape\n            taddr_ = tape->Rec_.PutOp(local::SubvpOp);\n            // check that this is a variable\n            CPPAD_ASSERT_UNKNOWN( tape_id_ == tape_id );\n            CPPAD_ASSERT_UNKNOWN( ad_type_ == variable_enum);\n        }\n    }\n    else if( var_right  )\n    {   // this = parameter - variable\n        CPPAD_ASSERT_UNKNOWN( local::NumRes(local::SubpvOp) == 1 );\n        CPPAD_ASSERT_UNKNOWN( local::NumArg(local::SubpvOp) == 2 );\n\n        // put operand addresses in tape\n        addr_t p = taddr_;\n        if( ! dyn_left )\n            p = tape->Rec_.put_con_par(left);\n        tape->Rec_.PutArg(p, right.taddr_);\n\n        // put operator in the tape\n        taddr_ = tape->Rec_.PutOp(local::SubpvOp);\n\n        // make this a variable\n        tape_id_ = tape_id;\n        ad_type_ = variable_enum;\n    }\n    else if( dyn_left | dyn_right )\n    {   if( (! dyn_right) && IdenticalZero(right.value_) )\n        {    // this is left -= 0, so do nothing\n        }\n        else\n        {\n            addr_t arg0 = taddr_;\n            addr_t arg1 = right.taddr_;\n            if( ! dyn_left )\n            arg0 = tape->Rec_.put_con_par(left);\n            if( ! dyn_right )\n            arg1 = tape->Rec_.put_con_par(right.value_);\n            //\n            // parameters with a dynamic parameter results\n            taddr_ = tape->Rec_.put_dyn_par(\n                value_, local::sub_dyn, arg0, arg1\n            );\n            tape_id_ = tape_id;\n            ad_type_ = dynamic_enum;\n        }\n    }\n    return *this;\n}\n\nCPPAD_FOLD_ASSIGNMENT_OPERATOR(-=)\n\n} // END CppAD namespace\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/subgraph_jac_rev.hpp",
    "content": "# ifndef CPPAD_CORE_SUBGRAPH_JAC_REV_HPP\n# define CPPAD_CORE_SUBGRAPH_JAC_REV_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin subgraph_jac_rev}\n{xrst_spell\n    nnz\n    nr\n    subgraphs\n}\n\nCompute Sparse Jacobians Using Subgraphs\n########################################\n\nSyntax\n******\n| *f* . ``subgraph_jac_rev`` ( *x* , *subset* )\n| *f* . ``subgraph_jac_rev`` (\n| |tab| *select_domain* , *select_range* , *x* , *matrix_out*\n| )\n\nSee Also\n********\n:ref:`subgraph_reverse@clear_subgraph` .\n\nPurpose\n*******\nWe use :math:`F : \\B{R}^n \\rightarrow \\B{R}^m` to denote the\nfunction corresponding to *f* .\nHere *n* is the :ref:`fun_property@Domain` size,\nand *m* is the :ref:`fun_property@Range` size, or *f* .\nThe syntax above takes advantage of sparsity when computing the Jacobian\n\n.. math::\n\n    J(x) = F^{(1)} (x)\n\nThe  first syntax requires one to know what which elements of the Jacobian\nthey want to compute.\nThe second syntax computes the sparsity pattern and the value\nof the Jacobian at the same time.\nIf one only wants the sparsity pattern,\nit should be faster to use :ref:`subgraph_sparsity-name` .\n\nMethod\n******\nThis routine uses a subgraph technique. To be specific,\nfor each dependent variable,\nit creates a subgraph of the operation sequence\ncontaining the variables that affect the dependent variable.\nThis avoids the overhead of performing set operations\nthat is inherent in other methods for computing sparsity patterns.\n\nBaseVector\n**********\nThe type *BaseVector* is a :ref:`SimpleVector-name` class with\n:ref:`elements of type<SimpleVector@Elements of Specified Type>`\n*Base* .\n\nSizeVector\n**********\nThe type *SizeVector* is a :ref:`SimpleVector-name` class with\n:ref:`elements of type<SimpleVector@Elements of Specified Type>`\n``size_t`` .\n\nBoolVector\n**********\nThe type *BoolVector* is a :ref:`SimpleVector-name` class with\n:ref:`elements of type<SimpleVector@Elements of Specified Type>`\n``bool`` .\n\nf\n*\nThis object has prototype\n\n    ``ADFun`` < *Base* > *f*\n\nNote that the Taylor coefficients stored in *f* are affected\nby this operation; see\n:ref:`sparse_jac@Uses Forward` below.\n\nx\n*\nThis argument has prototype\n\n    ``const`` *BaseVector* & *x*\n\nIt is the value of *x* at which we are computing the Jacobian.\n\nUses Forward\n************\nAfter each call to :ref:`Forward-name` ,\nthe object *f* contains the corresponding\n:ref:`Taylor coefficients<glossary@Taylor Coefficient>` .\nAfter a call to ``sparse_jac_forward`` or ``sparse_jac_rev`` ,\nthe zero order coefficients correspond to\n\n    *f* . ``Forward`` (0, *x* )\n\nAll the other forward mode coefficients are unspecified.\n\nsubset\n******\nThis argument has prototype\n\n    ``sparse_rcv`` < *SizeVector* , *BaseVector* >& *subset*\n\nIts row size is *subset* . ``nr`` () == *m* ,\nand its column size is *subset* . ``nc`` () == *n* .\nIt specifies which elements of the Jacobian are computed.\nThe input elements in its value vector\n*subset* . ``val`` () do not matter.\nUpon return it contains the value of the corresponding elements\nof the Jacobian.\n\nselect_domain\n*************\nThe argument *select_domain* has prototype\n\n    ``const`` *BoolVector* & *select_domain*\n\nIt has size :math:`n` and specifies which independent variables\nto include.\n\nselect_range\n************\nThe argument *select_range* has prototype\n\n    ``const`` *BoolVector* & *select_range*\n\nIt has size :math:`m` and specifies which components of the range\nto include in the calculation.\nA subgraph is built for each dependent variable and the selected set\nof independent variables.\n\nmatrix_out\n**********\nThis argument has prototype\n\n    ``sparse_rcv`` < *SizeVector* , *BaseVector* >& *matrix_out*\n\nThis input value of *matrix_out* does not matter.\nUpon return *matrix_out* is\n:ref:`sparse matrix<sparse_rcv-name>` representation of :math:`F^{(1)} (x)`.\nThe matrix has :math:`m` rows, :math:`n` columns.\nIf *select_domain* [ *j* ] is true,\n*select_range* [ *i* ] is true, and\n:math:`F_i (x)` depends on :math:`x_j`,\nthen the pair :math:`(i, j)` is in *matrix_out* .\nFor each *k* = 0 , ..., *matrix_out* . ``nnz`` () , let\n\n| |tab| *i* = *matrix_out* . ``row`` ()[ *k* ]\n| |tab| *j* = *matrix_out* . ``col`` ()[ *k* ]\n| |tab| *v* = *matrix_out* . ``val`` ()[ *k* ]\n\nIt follows that the partial of :math:`F_i (x)` with respect to\n:math:`x_j` is equal to :math:`v`.\n\nExample\n*******\n{xrst_toc_hidden\n    example/sparse/subgraph_jac_rev.cpp\n    example/sparse/subgraph_hes2jac.cpp\n}\nThe files :ref:`subgraph_jac_rev.cpp-name` and :ref:`subgraph_hes2jac.cpp-name`\nare examples and tests using ``subgraph_jac_rev`` .\nThey returns ``true`` for success and ``false`` for failure.\n\n{xrst_end subgraph_jac_rev}\n-----------------------------------------------------------------------------\n*/\n# include <cppad/core/ad_fun.hpp>\n# include <cppad/local/subgraph/info.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n\n/*!\nSubgraph sparsity patterns.\n\n\\tparam Base\nis the base type for this recording.\n\n\\tparam SizeVector\nis the simple vector with elements of type size_t that is used for\nrow, column index sparsity patterns.\n\n\\tparam BaseVector\na simple vector class with elements of type Base.\n\n\\param x\na vector of length n, the number of independent variables in f\n(this ADFun object).\n\n\\param subset\nspedifies the subset of the sparsity pattern where the Jacobian is evaluated.\nsubset.nr() == m,\nsubset.nc() == n.\n*/\ntemplate <class Base, class RecBase>\ntemplate <class SizeVector, class BaseVector>\nvoid ADFun<Base,RecBase>::subgraph_jac_rev(\n    const BaseVector&                   x      ,\n    sparse_rcv<SizeVector, BaseVector>& subset )\n{   size_t m = Range();\n    size_t n = Domain();\n    //\n    CPPAD_ASSERT_KNOWN(\n        subset.nr() == m,\n        \"subgraph_jac_rev: subset.nr() not equal range dimension for f\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        subset.nc() == n,\n        \"subgraph_jac_rev: subset.nc() not equal domain dimension for f\"\n    );\n    //\n    // point at which we are evaluating Jacobian\n    Forward(0, x);\n    //\n    // nnz and row, column, and row_major vectors for subset\n    size_t nnz = subset.nnz();\n    const SizeVector& row( subset.row() );\n    const SizeVector& col( subset.col() );\n    SizeVector row_major = subset.row_major();\n    //\n    // determine set of independent variables\n    local::pod_vector<bool> select_domain(n);\n    for(size_t j = 0; j < n; j++)\n        select_domain[j] = false;\n    for(size_t k = 0; k < nnz; k++)\n        select_domain[ col[k] ] = true;\n    //\n    // initialize reverse mode computation on subgraphs\n    subgraph_reverse(select_domain);\n    //\n    // memory used to hold subgraph_reverse results\n    BaseVector dw;\n    SizeVector dw_col;\n    //\n    // initialize index in row_major\n    size_t k = 0;\n    Base zero(0);\n    while(k < nnz )\n    {   size_t q   = 1;\n        size_t i_dep = row[ row_major[k] ];\n        size_t i_ind = col[ row_major[k] ];\n        size_t ell   = i_dep;\n        subgraph_reverse(q, ell, dw_col, dw);\n        //\n        size_t c = 0;\n        while( i_dep == ell )\n        {   // row numbers match\n            //\n            // advance c to possible match with column i_ind\n            while( c < size_t( dw_col.size() ) && dw_col[c] < i_ind )\n                ++c;\n            //\n            // check for match with i_ind\n            if( i_ind == dw_col[c] )\n                subset.set( row_major[k], dw[i_ind] );\n            else\n                subset.set( row_major[k], zero);\n            //\n            // advance to next (i_dep, i_ind)\n            ++k;\n            if( k == nnz )\n            {   i_dep = m;\n                i_ind = n;\n            }\n            else\n            {   i_dep = row[ row_major[k] ];\n                i_ind = col[ row_major[k] ];\n            }\n        }\n    }\n    return;\n}\ntemplate <class Base, class RecBase>\ntemplate <class BoolVector, class SizeVector, class BaseVector>\nvoid ADFun<Base,RecBase>::subgraph_jac_rev(\n    const BoolVector&                   select_domain  ,\n    const BoolVector&                   select_range   ,\n    const BaseVector&                   x              ,\n    sparse_rcv<SizeVector, BaseVector>& matrix_out     )\n{   size_t m = Range();\n    size_t n = Domain();\n    //\n    // point at which we are evaluating Jacobian\n    Forward(0, x);\n    //\n    // nnz and row, column, and row_major vectors for subset\n    local::pod_vector<size_t> row_out;\n    local::pod_vector<size_t> col_out;\n    local::pod_vector_maybe<Base>   val_out;\n    //\n    // initialize reverse mode computation on subgraphs\n    subgraph_reverse(select_domain);\n    //\n    // memory used to hold subgraph_reverse results\n    BaseVector dw;\n    SizeVector col;\n    //\n    // loop through selected independent variables\n    for(size_t i = 0; i < m; ++i) if( select_range[i] )\n    {   // compute Jacobian and sparsity for this dependent variable\n        size_t q   = 1;\n        subgraph_reverse(q, i, col, dw);\n        CPPAD_ASSERT_UNKNOWN( size_t( dw.size() ) == n );\n        //\n        // offset for this dependent variable\n        size_t index = row_out.size();\n        CPPAD_ASSERT_UNKNOWN( col_out.size() == index );\n        CPPAD_ASSERT_UNKNOWN( val_out.size() == index );\n        //\n        // extend vectors to hold results for this dependent variable\n        size_t col_size = size_t( col.size() );\n        row_out.extend( col_size );\n        col_out.extend( col_size );\n        val_out.extend( col_size );\n        //\n        // store results for this dependent variable\n        for(size_t c = 0; c < col_size; ++c)\n        {   row_out[index + c] = i;\n            col_out[index + c] = col[c];\n            val_out[index + c] = dw[ col[c] ];\n        }\n    }\n    //\n    // create sparsity pattern corresponding to row_out, col_out\n    size_t nr  = m;\n    size_t nc  = n;\n    size_t nnz = row_out.size();\n    sparse_rc<SizeVector> pattern(nr, nc, nnz);\n    for(size_t k = 0; k < nnz; ++k)\n        pattern.set(k, row_out[k], col_out[k]);\n    //\n    // create sparse matrix\n    sparse_rcv<SizeVector, BaseVector> matrix(pattern);\n    for(size_t k = 0; k < nnz; ++k)\n        matrix.set(k,  val_out[k]);\n    //\n    // return matrix\n    matrix_out = matrix;\n    //\n    return;\n}\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/subgraph_reverse.hpp",
    "content": "# ifndef CPPAD_CORE_SUBGRAPH_REVERSE_HPP\n# define CPPAD_CORE_SUBGRAPH_REVERSE_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin subgraph_reverse}\n{xrst_spell\n    dw\n    subgraphs\n}\n\nReverse Mode Using Subgraphs\n############################\n\nSyntax\n******\n| *f* . ``subgraph_reverse`` ( *select_domain* )\n| *f* . ``subgraph_reverse`` ( *q* , *ell* , *col* , *dw* )\n| *f* . ``clear_subgraph`` ()\n\nPurpose\n*******\nWe use :math:`F : \\B{R}^n \\rightarrow \\B{R}^m` to denote the\n:ref:`glossary@AD Function` corresponding to *f* .\nReverse mode computes the derivative of the :ref:`Forward-name` mode\n:ref:`Taylor coefficients<glossary@Taylor Coefficient>`\nwith respect to the domain variable :math:`x`.\n\nNotation\n********\nWe use the reverse mode\n:ref:`reverse_any@Notation` with the following change:\nthe vector\n:ref:`reverse_any@Notation@w^(k)` is defined\n\n.. math::\n\n    w_i^{(k)} = \\left\\{ \\begin{array}{ll}\n        1 & {\\rm if} \\; k = q-1 \\; \\R{and} \\; i = \\ell\n        \\\\\n        0       & {\\rm otherwise}\n    \\end{array} \\right.\n\nBaseVector\n**********\nThe type *BaseVector* must be a :ref:`SimpleVector-name` class with\n:ref:`elements of type<SimpleVector@Elements of Specified Type>`\n*Base* .\nThe routine :ref:`CheckSimpleVector-name` will generate an error message\nif this is not the case.\n\nBoolVector\n**********\nThe type *BoolVector* is a :ref:`SimpleVector-name` class with\n:ref:`elements of type<SimpleVector@Elements of Specified Type>`\n``bool`` .\n\nSizeVector\n**********\nThe type *SizeVector* is a :ref:`SimpleVector-name` class with\n:ref:`elements of type<SimpleVector@Elements of Specified Type>`\n``size_t`` .\n\nselect_domain\n*************\nThe argument *select_domain* has prototype\n\n    ``const`` *BoolVector* & *select_domain*\n\nIt has size :math:`n` and specifies which independent variables\nto include in future ``subgraph_reverse`` calculations.\nIf *select_domain* [ *j* ] is false,\nit is assumed that :math:`u^{(k)}_j = 0` for :math:`k > 0`; i.e.,\nthe *j*-th component of the Taylor coefficient for :math:`x`,\nwith order greater that zero, are zero; see\n:ref:`reverse_any@Notation@u^(k)` .\n\nq\n*\nThe argument *q* has prototype\n\n    ``size_t`` *q*\n\nand specifies the number of Taylor coefficient orders to be differentiated.\n\nell\n***\nThe argument *ell* has prototype\n\n    ``size_t`` *ell*\n\nand specifies the dependent variable index that we are computing\nthe derivatives for; i.e. :math:`\\ell`.\nThis index can only be used once per, and after, a call that selects\nthe independent variables using *select_domain* .\n\ncol\n***\nThis argument *col* has prototype\n\n    *SizeVector* *col*\n\nThe input size and value of its elements do not matter.\nThe *col* . ``resize`` member function is used to change its size\nto the number the number of possible non-zero derivative components.\nFor each *c* ,\n\n| |tab| *select_domain* [ *col* [ *c* ] ] == ``true``\n| |tab| *col* [ *c* +1] >= *col* [ *c* ]\n\nand the derivative with respect to the *j*-th independent\nvariable is possibly non-zero where\n*j* = *col* [ *c* ] .\n\ndw\n**\nThe argument *dw* has prototype\n\n    *Vector* *dw*\n\nIts input size and value does not matter.\nUpon return,\nit is a vector with size :math:`n \\times q`.\nFor :math:`c = 0 , \\ldots , %col%.size()-1`,\nand :math:`k = 0, \\ldots , q-1`,\n\n.. math::\n\n    dw[ j * q + k ] = W^{(1)} ( x )_{j,k}\n\nis the derivative of the specified Taylor coefficients w.r.t the *j*-th\nindependent variable where *j* = *col* [ *c* ] .\nNote that this corresponds to the :ref:`reverse_any-name` convention when\n:ref:`reverse_any@w` has size *m* * *q* .\n\nclear_subgraph\n**************\nCalling this routine will free memory that holds\ninformation between calls to subgraph calculations so that\nit does not need to be recalculated.\n(This memory is automatically freed when *f* is deleted.)\nYou cannot free this memory between calls that select the domain\nand corresponding calls that compute reverse mode derivatives.\nSome of this information is also used by :ref:`subgraph_sparsity-name` .\n\nExample\n*******\n{xrst_toc_hidden\n    example/sparse/subgraph_reverse.cpp\n}\nThe file\n:ref:`subgraph_reverse.cpp-name`\ncontains an example and test of this operation.\n\n{xrst_end subgraph_reverse}\n*/\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\n\\file subgraph_reverse.hpp\nCompute derivatives using reverse mode and subgraphs.\n*/\n\n/// clear all subgraph information\ntemplate <class Base, class RecBase>\nvoid ADFun<Base,RecBase>::clear_subgraph(void)\n{   play_.clear_random();\n    subgraph_info_.clear();\n    subgraph_partial_.clear();\n}\n\n/*!\nInitialize reverse mode derivative computation on subgraphs.\n\n\\param select_domain\nis a vector with size equal to the dimension of the domain for this function.\nOnly derivatives w.r.t. the components that are true will be computed.\n\n\\par subgraph_info_.map_user_op()\nIf the input size of this vector is zero,\nits value for this player (play_) is computed.\n\n\\par subgraph_info.in_subgraph_\nThis vector is initialized for a reverse mode computation on subgraphs.\n\n\\par subgraph_info.select_domain()\nThis vector is set equal to the select_domain argument.\n\n\\par subgraph_info.process_range()\nThis vector is initialized to have size Range() and its elements are false.\n*/\n\ntemplate <class Base, class RecBase>\ntemplate <class BoolVector>\nvoid ADFun<Base,RecBase>::subgraph_reverse( const BoolVector& select_domain )\n{   using local::pod_vector;\n    //\n    CPPAD_ASSERT_UNKNOWN(\n        dep_taddr_.size() == subgraph_info_.n_dep()\n    );\n    CPPAD_ASSERT_UNKNOWN(\n        size_t( select_domain.size() ) == subgraph_info_.n_ind()\n    );\n\n    // map_user_op\n    if( subgraph_info_.map_user_op().size() == 0 )\n        subgraph_info_.set_map_user_op(&play_);\n    else\n    {   CPPAD_ASSERT_UNKNOWN( subgraph_info_.check_map_user_op(&play_) );\n    }\n    CPPAD_ASSERT_UNKNOWN(\n        subgraph_info_.map_user_op().size() == play_.num_var_op()\n    );\n\n    // initialize for reverse mode subgraph computations\n    switch( play_.address_type() )\n    {\n        case local::play::unsigned_short_enum:\n        subgraph_info_.init_rev<unsigned short>(&play_, select_domain);\n        break;\n\n        case local::play::addr_t_enum:\n        subgraph_info_.init_rev<addr_t>(&play_, select_domain);\n        break;\n\n        case local::play::size_t_enum:\n        subgraph_info_.init_rev<size_t>(&play_, select_domain);\n        break;\n\n        default:\n        CPPAD_ASSERT_UNKNOWN(false);\n    }\n    CPPAD_ASSERT_UNKNOWN(\n        subgraph_info_.in_subgraph().size() == play_.num_var_op()\n    );\n\n    return;\n}\n\n\n/*!\nUse reverse mode to compute derivative of Taylor coefficients on a subgraph.\n\nThe function\n\\f$ X : {\\bf R} \\times {\\bf R}^{n \\times q} \\rightarrow {\\bf R} \\f$\nis defined by\n\\f[\nX(t , u) = \\sum_{k=0}^{q-1} u^{(k)} t^k\n\\f]\nThe function\n\\f$ Y : {\\bf R} \\times {\\bf R}^{n \\times q} \\rightarrow {\\bf R} \\f$\nis defined by\n\\f[\nY(t , u) = F[ X(t, u) ]\n\\f]\nThe function\n\\f$ W : {\\bf R}^{n \\times q} \\rightarrow {\\bf R} \\f$ is defined by\n\\f[\nW(u) = \\sum_{k=0}^{q-1} ( w^{(k)} )^{\\rm T}\n\\frac{1}{k !} \\frac{ \\partial^k } { t^k } Y(0, u)\n\\f]\n\n\\param q\nis the number of Taylor coefficient we are differentiating.\n\n\\param ell\nis the component of the range that is selected for differentiation.\n\n\\param col\nis the set of indices j = col[c] where the return value is defined.\nIf an index j is not in col, then either its derivative is zero,\nor it is not in select_domain.\n\n\\param dw\nIs a vector \\f$ dw \\f$ such that\nfor j = col[c],\n\\f$ k = 0 , \\ldots , q-1 \\f$\n\\f[\n    dw[ j * q + k ] = W^{(1)} ( x )_{j,k}\n\\f]\nwhere the matrix \\f$ x \\f$ is the value for \\f$ u \\f$\nthat corresponding to the forward mode Taylor coefficients\nfor the independent variables as specified by previous calls to Forward.\n\n\\par subgraph_info.process_range()\nThe element process_range[ell] is set to true by this operation.\n\n\\par subgraph_info.in_subgraph_\nsome of the elements of this vector are set to have value ell\n(so it can not longer be used to determine the subgraph corresponding to\nthe ell-th dependent variable).\n*/\ntemplate <class Base, class RecBase>\ntemplate <class Addr, class BaseVector, class SizeVector>\nvoid ADFun<Base,RecBase>::subgraph_reverse_helper(\n    size_t      q   ,\n    size_t      ell ,\n    SizeVector& col ,\n    BaseVector& dw  )\n{   using local::pod_vector;\n    // used to identify the RecBase type in calls to sweeps\n    RecBase not_used_rec_base(0.0);\n    //\n    // get a random iterator for this player\n    Addr not_used;\n    play_.setup_random(not_used);\n    typename local::play::const_random_iterator<Addr> random_itr =\n        play_.get_random( not_used );\n\n    // check BaseVector is Simple Vector class with Base type elements\n    CheckSimpleVector<Base, BaseVector>();\n    CPPAD_ASSERT_KNOWN(\n        q > 0,\n        \"The second argument to Reverse must be greater than zero.\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        num_order_taylor_ >= q,\n        \"Less than q Taylor coefficients are currently stored\"\n        \" in this ADFun object.\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        num_direction_taylor_ == 1,\n        \"reverse mode for Forward(q, r, xq) with more than one direction\"\n        \"\\n(r > 1) is not yet supported.\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        ell < dep_taddr_.size(),\n        \"dependent variable index in to large for this function\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        subgraph_info_.process_range()[ell] == false,\n        \"This dependent variable index has already been processed\\n\"\n        \"after the previous subgraph_reverse(select_domain).\"\n    );\n\n    // subgraph of operators connected to dependent variable ell\n    pod_vector<addr_t> subgraph;\n    subgraph_info_.get_rev(\n        random_itr, dep_taddr_, addr_t(ell), subgraph\n    );\n\n    // Add all the atomic function call operators\n    // for calls that have first operator in the subgraph\n    local::subgraph::entire_call(random_itr, subgraph);\n\n    // First add the BeginOp and EndOp to the subgraph and then sort it\n    // sort the subgraph\n    addr_t i_op_begin_op = 0;\n    addr_t i_op_end_op   = addr_t( play_.num_var_op() - 1);\n    subgraph.push_back(i_op_begin_op);\n    subgraph.push_back(i_op_end_op);\n    std::sort( subgraph.data(), subgraph.data() + subgraph.size() );\n    CPPAD_ASSERT_UNKNOWN( subgraph[0] == i_op_begin_op );\n    CPPAD_ASSERT_UNKNOWN( subgraph[subgraph.size()-1] == i_op_end_op );\n    /*\n    // Use this printout for debugging\n    std::cout << \"{ \";\n    for(size_t k = 0; k < subgraph.size(); k++)\n    {   if( k > 0 )\n            std::cout << \", \";\n        std::cout << subgraph[k];\n    }\n    std::cout << \"}\\n\";\n    */\n\n    // initialize subgraph_partial_ matrix to zero on subgraph\n    Base zero(0);\n    subgraph_partial_.resize(num_var_tape_ * q);\n    for(size_t k = 0; k < subgraph.size(); ++k)\n    {\n        size_t               i_op = size_t( subgraph[k] );\n        local::op_code_var   op;\n        const addr_t*        arg;\n        size_t               i_var;\n        random_itr.op_info(i_op, op, arg, i_var);\n        if( NumRes(op) == 0 )\n        {   CPPAD_ASSERT_UNKNOWN(\n                op == local::AFunOp  ||\n                op == local::FunapOp ||\n                op == local::FunavOp ||\n                op == local::FunrpOp ||\n                op == local::EndOp\n            );\n        }\n        else if( op != local::BeginOp )\n        {   CPPAD_ASSERT_UNKNOWN( i_var >= NumRes(op) );\n            size_t j_var = i_var + 1 - NumRes(op);\n            for(size_t i = j_var; i <= i_var; ++i)\n            {   for(size_t j = 0; j < q; ++j)\n                    subgraph_partial_[i * q + j] = zero;\n            }\n        }\n    }\n\n    // set partial to one for component we are differentiating\n    subgraph_partial_[ dep_taddr_[ell] * q + q - 1] = Base(1);\n\n    // evaluate the derivatives\n    CPPAD_ASSERT_UNKNOWN( cskip_op_.size() == play_.num_var_op() );\n    CPPAD_ASSERT_UNKNOWN( load_op2var_.size()  == play_.num_var_load() );\n    size_t n = Domain();\n    //\n    local::play::const_subgraph_iterator<Addr> subgraph_itr =\n        play_.end_subgraph(random_itr, &subgraph);\n    //\n    local::sweep::reverse(\n        num_var_tape_,\n        &play_,\n        cap_order_taylor_,\n        taylor_.data(),\n        q,\n        subgraph_partial_.data(),\n        cskip_op_.data(),\n        load_op2var_,\n        subgraph_itr,\n        not_used_rec_base\n    );\n\n    // number of non-zero in return value\n    size_t col_size       = 0;\n    size_t subgraph_index = 0;\n    CPPAD_ASSERT_UNKNOWN( subgraph[subgraph_index] == 0 );\n    // Skip BeginOp\n    ++subgraph_index;\n    while( subgraph_index < subgraph.size() )\n    {   // check for InvOp\n        if( subgraph[subgraph_index] > addr_t(n) )\n            subgraph_index = subgraph.size();\n        else\n        {   ++col_size;\n            ++subgraph_index;\n        }\n    }\n    col.resize(col_size);\n\n    // return the derivative values\n    dw.resize(n * q);\n    for(size_t c = 0; c < col_size; ++c)\n    {   size_t i_op = size_t( subgraph[c + 1] );\n        CPPAD_ASSERT_UNKNOWN( play_.GetOp(i_op) == local::InvOp );\n        //\n        size_t j = i_op - 1;\n        CPPAD_ASSERT_UNKNOWN( i_op == random_itr.var2op( ind_taddr_[j] ) );\n        //\n        // return partial for this independent variable\n        col[c] = j;\n        for(size_t k = 0; k < q; k++)\n            dw[j * q + k ] = subgraph_partial_[ind_taddr_[j] * q + k];\n    }\n    //\n    CPPAD_ASSERT_KNOWN( ! ( hasnan(dw) && check_for_nan_ ) ,\n        \"f.subgraph_reverse(dw, q, ell): dw has a nan,\\n\"\n        \"but none of f's Taylor coefficients are nan.\"\n    );\n    //\n    return;\n}\n/*!\n\\copydoc subgraph_reverse_helper\n\n*/\ntemplate <class Base, class RecBase>\ntemplate <class BaseVector, class SizeVector>\nvoid ADFun<Base,RecBase>::subgraph_reverse(\n    size_t      q   ,\n    size_t      ell ,\n    SizeVector& col ,\n    BaseVector& dw  )\n{   using local::pod_vector;\n    //\n    // call proper version of helper function\n    switch( play_.address_type() )\n    {\n        case local::play::unsigned_short_enum:\n        subgraph_reverse_helper<unsigned short>(q, ell, col, dw);\n        break;\n\n        case local::play::addr_t_enum:\n        subgraph_reverse_helper<addr_t>(q, ell, col, dw);\n        break;\n\n        case local::play::size_t_enum:\n        subgraph_reverse_helper<size_t>(q, ell, col, dw);\n        break;\n\n        default:\n        CPPAD_ASSERT_UNKNOWN(false);\n    }\n    //\n    return;\n}\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/subgraph_sparsity.hpp",
    "content": "# ifndef CPPAD_CORE_SUBGRAPH_SPARSITY_HPP\n# define CPPAD_CORE_SUBGRAPH_SPARSITY_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin subgraph_sparsity}\n{xrst_spell\n    rc\n    subgraphs\n}\n\nSubgraph Dependency Sparsity Patterns\n#####################################\n\nSyntax\n******\n| *f* . ``subgraph_sparsity`` (\n| |tab| *select_domain* , *select_range* , *transpose* , *pattern_out*\n| )\n\nSee Also\n********\n:ref:`subgraph_reverse@clear_subgraph` .\n\nNotation\n********\nWe use :math:`F : \\B{R}^n \\rightarrow \\B{R}^m` to denote the\n:ref:`glossary@AD Function` corresponding to\nthe operation sequence stored in *f* .\n\nMethod\n******\nThis routine uses a subgraph technique. To be specific,\nfor each dependent variable,\nit creates a subgraph of the operation sequence\ncontaining the variables that affect the dependent variable.\nThis avoids the overhead of performing set operations\nthat is inherent in other methods for computing sparsity patterns.\n\nAtomic Function\n***************\nThe sparsity calculation for\n:ref:`atomic functions<atomic_two_afun-name>` in the *f* operation sequence\nare not efficient. To be specific, each atomic function is treated as if\nall of its outputs depend on all of its inputs.\nThis may be improved upon in the future; see the\n:ref:`subgraph sparsity<wish_list@Subgraph@Sparsity>`\nwish list item.\n\nBoolVector\n**********\nThe type *BoolVector* is a :ref:`SimpleVector-name` class with\n:ref:`elements of type<SimpleVector@Elements of Specified Type>`\n``bool`` .\n\nSizeVector\n**********\nThe type *SizeVector* is a :ref:`SimpleVector-name` class with\n:ref:`elements of type<SimpleVector@Elements of Specified Type>`\n``size_t`` .\n\nf\n*\nThe object *f* has prototype\n\n    ``ADFun`` < *Base* > *f*\n\nselect_domain\n*************\nThe argument *select_domain* has prototype\n\n    ``const`` *BoolVector* & *select_domain*\n\nIt has size :math:`n` and specifies which independent variables\nto include in the calculation.\nIf not all the independent variables are included in the calculation,\na forward pass on the operation sequence is used to determine which\nnodes may be in the subgraphs.\n\nselect_range\n************\nThe argument *select_range* has prototype\n\n    ``const`` *BoolVector* & *select_range*\n\nIt has size :math:`m` and specifies which components of the range\nto include in the calculation.\nA subgraph is built for each dependent variable\nand the selected set of independent variables.\n\ntranspose\n*********\nThis argument has prototype\n\n    ``bool`` *transpose*\n\nIf *transpose* it is false (true),\nupon return *pattern_out* is a sparsity pattern for\n:math:`J(x)` (:math:`J(x)^\\R{T}`) defined below.\n\npattern_out\n***********\nThis argument has prototype\n\n    ``sparse_rc`` < *SizeVector* >& *pattern_out*\n\nThis input value of *pattern_out* does not matter.\nUpon return *pattern_out* is a\n:ref:`dependency.cpp@Dependency Pattern`\nfor :math:`F(x)`.\nThe pattern has :math:`m` rows, :math:`n` columns.\nIf *select_domain* [ *j* ] is true,\n*select_range* [ *i* ] is true, and\n:math:`F_i (x)` depends on :math:`x_j`,\nthen the pair :math:`(i, j)` is in *pattern_out* .\nNot that this is also a sparsity pattern for the Jacobian\n\n.. math::\n\n    J(x) = R F^{(1)} (x) D\n\nwhere :math:`D` (:math:`R`) is the diagonal matrix corresponding\nto *select_domain* ( *select_range* ).\n\nExample\n*******\n{xrst_toc_hidden\n    example/sparse/subgraph_sparsity.cpp\n}\nThe file\n:ref:`subgraph_sparsity.cpp-name`\ncontains an example and test of this operation.\n\n{xrst_end subgraph_sparsity}\n-----------------------------------------------------------------------------\n*/\n# include <cppad/core/ad_fun.hpp>\n# include <cppad/local/subgraph/sparsity.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n\n/*!\nSubgraph sparsity patterns.\n\n\\tparam Base\nis the base type for this recording.\n\n\\tparam SizeVector\nis the simple vector with elements of type size_t that is used for\nrow, column index sparsity patterns.\n\n\\param select_domain\nsparsity pattern for the diagonal of the square matrix D.\n\n\\param select_range\nsparsity pattern for the diagonal of the square matrix R\n\n\\param transpose\nIf true, the return is a dependency sparsity pattern for\n\\f$ D F^{(1)} (x)^T R \\f$\n\n\\param pattern_out\nThe input value does not matter.\nThe return value is a dependency sparsity pattern for  \\f$ R F^{(1)} (x) D \\f$\nwhere F is the function corresponding to the operation sequence\nand x is any argument value.\nis the sparsity pattern transposed.\n*/\ntemplate <class Base, class RecBase>\ntemplate <class BoolVector, class SizeVector>\nvoid ADFun<Base,RecBase>::subgraph_sparsity(\n    const BoolVector&            select_domain    ,\n    const BoolVector&            select_range     ,\n    bool                         transpose        ,\n    sparse_rc<SizeVector>&       pattern_out      )\n{\n    // compute the sparsity pattern in row, col\n    local::pod_vector<size_t> row;\n    local::pod_vector<size_t> col;\n\n    // create the optimized recording\n    switch( play_.address_type() )\n    {\n        case local::play::unsigned_short_enum:\n        local::subgraph::subgraph_sparsity<unsigned short>(\n            &play_,\n            subgraph_info_,\n            dep_taddr_,\n            select_domain,\n            select_range,\n            row,\n            col\n        );\n        break;\n\n        case local::play::addr_t_enum:\n        local::subgraph::subgraph_sparsity<addr_t>(\n            &play_,\n            subgraph_info_,\n            dep_taddr_,\n            select_domain,\n            select_range,\n            row,\n            col\n        );\n        break;\n\n        case local::play::size_t_enum:\n        local::subgraph::subgraph_sparsity<size_t>(\n            &play_,\n            subgraph_info_,\n            dep_taddr_,\n            select_domain,\n            select_range,\n            row,\n            col\n        );\n        break;\n\n        default:\n        CPPAD_ASSERT_UNKNOWN(false);\n    }\n\n    CPPAD_ASSERT_UNKNOWN( row.size() == col.size() );\n\n    // return the sparsity pattern\n    size_t nr  = dep_taddr_.size();\n    size_t nc  = ind_taddr_.size();\n    size_t nnz = row.size();\n    if( transpose )\n    {   pattern_out.resize(nc, nr, nnz);\n        for(size_t k = 0; k < nnz; k++)\n            pattern_out.set(k, col[k], row[k]);\n    }\n    else\n    {   pattern_out.resize(nr, nc, nnz);\n        for(size_t k = 0; k < nnz; k++)\n            pattern_out.set(k, row[k], col[k]);\n    }\n    return;\n}\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/tape_link.hpp",
    "content": "# ifndef CPPAD_CORE_TAPE_LINK_HPP\n# define CPPAD_CORE_TAPE_LINK_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/local/define.hpp>\n# include <cppad/utility/thread_alloc.hpp>\n# include <cppad/core/cppad_assert.hpp>\n\n// needed before one can use CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL\n# include <cppad/utility/thread_alloc.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\n\\file tape_link.hpp\nRoutines that Link AD<Base> and local::ADTape<Base> Objects.\n\nThe routines that connect the AD<Base> class to the corresponding tapes\n(one for each thread).\n*/\n\n/*!\nPointer to the tape identifier for this AD<Base> class and the specific thread.\n\n\\tparam Base\nis the base type for this AD<Base> class.\n\n\\param thread\nis the thread number. The following condition must hold\n\\code\n(! thread_alloc::in_parallel()) || thread == thread_alloc::thread_num()\n\\endcode\n\n\\return\nis a pointer to the tape identifier for this thread and AD<Base> class.\n*/\ntemplate <class Base>\ntape_id_t* AD<Base>::tape_id_ptr(size_t thread)\n{   CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL;\n    static tape_id_t tape_id_table[CPPAD_MAX_NUM_THREADS];\n    CPPAD_ASSERT_UNKNOWN(\n        (! thread_alloc::in_parallel()) || thread == thread_alloc::thread_num()\n    );\n    return tape_id_table + thread;\n}\n\n/*!\nHandle for the tape for this AD<Base> class and the specific thread.\n\n\\tparam Base\nis the base type for this AD<Base> class.\n\n\n\\param thread\nis the thread number; i.e.,\n\\code\n(! thread_alloc::in_parallel()) || thread == thread_alloc::thread_num()\n\\endcode\n\n\\return\nis a handle for the tape for this AD<Base> class and the specified thread.\n*/\ntemplate <class Base>\nlocal::ADTape<Base>** AD<Base>::tape_handle(size_t thread)\n{   CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL;\n    static local::ADTape<Base>* tape_table[CPPAD_MAX_NUM_THREADS];\n    CPPAD_ASSERT_UNKNOWN(\n        (! thread_alloc::in_parallel()) || thread == thread_alloc::thread_num()\n    );\n    return tape_table + thread;\n}\n\n/*!\nPointer for the tape for this AD<Base> class and the current thread.\n\n\\code\nthread == thread_alloc::thread_num()\n\\endcode\n\n\\tparam Base\nis the base type corresponding to AD<Base> operations.\n\n\\return\nis a pointer to the tape that is currently recording AD<Base> operations\nfor the current thread.\nIf this value is nullptr, there is no tape currently\nrecording AD<Base> operations for this thread.\n*/\ntemplate <class Base>\nlocal::ADTape<Base>* AD<Base>::tape_ptr(void)\n{   size_t thread = thread_alloc::thread_num();\n    return *tape_handle(thread);\n}\n\n/*!\nPointer for the tape for this AD<Base> class and the specified tape\nidentifier.\n\n\\tparam Base\nis the base type corresponding to AD<Base> operations.\n\n\\param tape_id\nis the identifier for the tape that is currently recording\nAD<Base> operations for the current thread.\nIt must hold that the current thread is\n\\code\n    thread = size_t( tape_id % CPPAD_MAX_NUM_THREADS )\n\\endcode\nand that there is a tape recording AD<Base> operations\nfor this thread.\nIf this is not the currently executing thread,\na variable from a different thread is being recorded on the\ntape for this thread which is a user error.\n\n\\return\nis a pointer to the tape that is currently recording AD<Base> operations\nfor the current thread (and it is not nullptr).\n\n\\par Restrictions\nThis routine should only be called if there is a tape recording operations\nfor the specified thread.\n*/\ntemplate <class Base>\nlocal::ADTape<Base>* AD<Base>::tape_ptr(tape_id_t tape_id)\n{   size_t thread = size_t( tape_id % CPPAD_MAX_NUM_THREADS );\n    CPPAD_ASSERT_KNOWN(\n        thread == thread_alloc::thread_num(),\n        \"Attempt to use an AD variable with two different threads.\"\n    );\n    CPPAD_ASSERT_UNKNOWN( tape_id == *tape_id_ptr(thread) );\n    CPPAD_ASSERT_UNKNOWN( *tape_handle(thread) != nullptr );\n    return *tape_handle(thread);\n}\n\n/*!\nCreate and delete tapes that record AD<Base> operations for current thread.\n\n\\par thread\nthe current thread is given by\n\\code\nthread = thread_alloc::thread_num()\n\\endcode\n\n\\tparam Base\nis the base type corresponding to AD<Base> operations.\n\n\\param job\nThis argument determines if we are creating a new tape, or deleting an\nold one.\n\n- new_tape_manage :\nCreates and a new tape.\nIt is assumed that there is no tape recording AD<Base> operations\nfor this thread when tape_manage is called.\n\n- delete_tape_manage :\nIt is assumed that there is a tape recording AD<Base> operations\nfor this thread when tape_manage is called.\nThe value of <tt>*tape_id_ptr(thread)</tt> will be advanced by\n CPPAD_MAX_NUM_THREADS.\n\n\n\\return\n- <tt>job == new_tape_manage</tt>: a pointer to the new tape is returned.\n- <tt>job == delete_tape_manage</tt>: the value nullptr is returned.\n*/\ntemplate <class Base>\nlocal::ADTape<Base>*  AD<Base>::tape_manage(tape_manage_enum job)\n{\n    CPPAD_ASSERT_UNKNOWN(\n        job == new_tape_manage || job == delete_tape_manage\n    );\n    // thread, tape_id, and tape for this call\n    size_t                thread     = thread_alloc::thread_num();\n    tape_id_t*            tape_id_p  = tape_id_ptr(thread);\n    local::ADTape<Base>** tape_h     = tape_handle(thread);\n\n\n    // -----------------------------------------------------------------------\n    // new_tape_manage\n    if( job == new_tape_manage )\n    {\n        // tape for this thread must be null at the start\n        CPPAD_ASSERT_UNKNOWN( *tape_h  == nullptr );\n\n        // allocate separate memory to avoid false sharing\n        *tape_h = new local::ADTape<Base>();\n\n        // if tape id is zero, initialize it so that\n        // thread == tape id % CPPAD_MAX_NUM_THREADS\n        if( *tape_id_p == 0 )\n        {   size_t new_tape_id = thread + CPPAD_MAX_NUM_THREADS;\n            CPPAD_ASSERT_KNOWN(\n                size_t( std::numeric_limits<tape_id_t>::max() ) >= new_tape_id,\n                \"cppad_tape_id_type maximum value has been exceeded\"\n            );\n            *tape_id_p = static_cast<tape_id_t>( new_tape_id );\n        }\n        // make sure tape_id value is valid for this thread\n        CPPAD_ASSERT_UNKNOWN(\n            size_t( *tape_id_p % CPPAD_MAX_NUM_THREADS ) == thread\n        );\n        // set the tape_id for this tape\n        (*tape_h)->id_ = *tape_id_p;\n    }\n    // -----------------------------------------------------------------------\n    // delete_tape_manage\n    if( job == delete_tape_manage )\n    {   // delete this tape\n        CPPAD_ASSERT_UNKNOWN( *tape_h  != nullptr );\n        delete *tape_h;\n        *tape_h = nullptr;\n        //\n        // advance tape_id so that all AD<Base> variables become parameters\n        CPPAD_ASSERT_KNOWN(\n            std::numeric_limits<CPPAD_TAPE_ID_TYPE>::max()\n            - CPPAD_MAX_NUM_THREADS > *tape_id_p,\n            \"To many different tapes given the type used for \"\n            \"CPPAD_TAPE_ID_TYPE\"\n        );\n        *tape_id_p  += CPPAD_MAX_NUM_THREADS;\n    }\n    // -----------------------------------------------------------------------\n    return *tape_h;\n}\n\n/*!\nGet a pointer to tape that records AD<Base> operations for the current thread.\n\n\\tparam Base\nis the base type corresponding to AD<Base> operations.\n\n\\par thread\nThe current thread must be given by\n\\code\n    thread = this->tape_id_ % CPPAD_MAX_NUM_THREADS\n\\endcode\n\n\\return\nis a pointer to the tape that is currently recording AD<Base> operations\nfor the current thread.\nThis value must not be nullptr; i.e., there must be a tape currently\nrecording AD<Base> operations for this thread.\n*/\n\ntemplate <class Base>\nlocal::ADTape<Base> *AD<Base>::tape_this(void) const\n{\n    size_t thread = size_t( tape_id_ % CPPAD_MAX_NUM_THREADS );\n    CPPAD_ASSERT_UNKNOWN( tape_id_ == *tape_id_ptr(thread) );\n    CPPAD_ASSERT_UNKNOWN( *tape_handle(thread) != nullptr );\n    return *tape_handle(thread);\n}\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/core/testvector.hpp",
    "content": "# ifndef CPPAD_CORE_TESTVECTOR_HPP\n# define CPPAD_CORE_TESTVECTOR_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin testvector}\n{xrst_spell\n    ublas\n}\n\nUsing The CppAD Test Vector Template Class\n##########################################\n\nSyntax\n******\n| ``CPPAD_TESTVECTOR`` ( *Scalar* )\n\nChoice\n******\nThe user can choose, during the install procedure,\nwhich template class to use in the examples and tests; see below.\nThis shows that any\n:ref:`simple vector<SimpleVector-name>` class can be used in place of\n\n    ``CPPAD_TESTVECTOR`` ( *Type* )\n\nWhen writing their own code,\nusers can choose a specific simple vector they prefer; for example,\n\n    ``CppAD::vector<`` *Type* >\n\nCppAD::vector\n*************\nIf in the :ref:`cmake@CMake Command`\nyou specify :ref:`cppad_testvector-name` to be ``cppad`` ,\n\n    # ``define CPPAD_TESTVECTOR`` ( *Scalar* ) ``CppAD::vector<`` *Scalar*  >\n\nCPPAD_CPPADVECTOR, Deprecated 2022-06-22\n========================================\nThis symbol is 1 (0) if the definition above\nis used (is not used) for ``CPPAD_TESTVECTOR`` .\n\nstd::vector\n***********\nIf in the cmake command\nyou specify *cppad_testvector* to be ``std`` ,\n\n    # ``define CPPAD_TESTVECTOR`` ( *Scalar* ) ``std::vector<`` *Scalar*  >\n\nCPPAD_STDVECTOR, Deprecated 2022-06-22\n======================================\nThis symbol is 1 (0) if the definition above\nis used (is not used) for ``CPPAD_TESTVECTOR`` .\n\nboost::numeric::ublas::vector\n*****************************\nIf in the cmake command\nyou specify *cppad_testvector* to be ``boost`` ,\n\n    # ``define CPPAD_TESTVECTOR`` ( *Scalar* ) ``boost::numeric::ublas::vector<`` *Scalar*  >\n\nCPPAD_BOOSTVECTOR, Deprecated 2022-06-22\n========================================\nThis symbol is 1 (0) if the definition above\nis used (is not used) for ``CPPAD_TESTVECTOR`` .\n\nCppAD::eigen_vector\n*******************\nIf in the cmake command\nyou specify *cppad_testvector* to be ``eigen`` ,\n\n    # ``define CPPAD_TESTVECTOR`` ( *Scalar* ) ``CppAD::eigen_vector<`` *Scalar*  >\n\nsee :ref:`cppad_eigen.hpp@eigen_vector` .\nIn this case CppAD will use the Eigen vector\nfor many of its examples and tests.\n\nCPPAD_EIGENVECTOR, Deprecated 2022-06-22\n========================================\nThis symbol is 1 (0) if the definition above\nis used (is not used) for ``CPPAD_TESTVECTOR`` .\n\n{xrst_end testvector}\n------------------------------------------------------------------------\n*/\n# include <cppad/configure.hpp>\n#\n# if CPPAD_CPPADVECTOR\n# define CPPAD_TESTVECTOR(Scalar) CppAD::vector< Scalar >\n# endif\n//\n# if CPPAD_STDVECTOR\n# include <vector>\n# define CPPAD_TESTVECTOR(Scalar) std::vector< Scalar >\n# endif\n//\n# if CPPAD_BOOSTVECTOR\n# include <boost/numeric/ublas/vector.hpp>\n# define CPPAD_TESTVECTOR(Scalar) boost::numeric::ublas::vector< Scalar >\n# endif\n//\n# if CPPAD_EIGENVECTOR\n# include <cppad/example/cppad_eigen.hpp>\n# define CPPAD_TESTVECTOR(Scalar) CppAD::eigen_vector< Scalar >\n# endif\n//\n# endif\n"
  },
  {
    "path": "include/cppad/core/to_csrc.hpp",
    "content": "# ifndef CPPAD_CORE_TO_CSRC_HPP\n# define CPPAD_CORE_TO_CSRC_HPP\n\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/core/ad_fun.hpp>\n# include <cppad/local/op_code_dyn.hpp>\n# include <cppad/local/graph/cpp_graph_op.hpp>\n# include <cppad/core/graph/cpp_graph.hpp>\n# include <cppad/local/graph/csrc_writer.hpp>\n/*\n------------------------------------------------------------------------------\n{xrst_begin to_csrc}\n{xrst_spell\n    cdecl\n    declspec\n    dllimport\n    ny\n    typedef\n    underbar\n}\n\nC Source Code Corresponding to an ADFun Object\n##############################################\n\nSyntax\n******\n| *fun* . ``to_csrc`` ( *os* , *c_type* )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_PROTOTYPE\n    // END_PROTOTYPE\n}\n\nfun\n***\nis the :ref:`adfun-name` object.\n\nBase\n****\nis the type corresponding to this :ref:`adfun-name` object;\ni.e., its calculations are done using the type *Base* .\n\nRecBase\n*******\nin the prototype above, *RecBase* is the same type as *Base* .\n\nos\n**\nThe C source code representation of the function *fun*\nis written to *os* .\n\nc_type\n******\nThe possible values for this argument are:\n``float`` , ``double`` , or ``long_double`` .\n\nJIT Functions\n*************\n\nFunction Type\n=============\nThe function type ``jit_``\\ *c_type* is defined in the CppAD namespace as:\n\n| ``typedef int`` (* ``jit_``\\ *c_type* )(\n| |tab| ``size_t`` , ``const`` *type* * , ``size_t`` , *type* * , ``size_t`` *\n| )\n\nHere *type* is the same as *c_type* except that the\nunderbar in ``long_double`` is replaced by a space.\nIn the case of the Visual C++ compiler (``_MSC_VER`` is defined),\n``__cdecl`` and ``__declspec(dllimport)`` are added to\nthe function type definition.\n\nSyntax\n======\n| *flag* = ``cppad_jit_``\\ *function_name* (\n| |tab| *nu* , *u* , *ny* , *y* , *compare_change*\n| )\n\nA corresponding function call evaluations zero order forward mode\nfor the function *fun* and\n\n| *function_name* = *fun*\\ ``.function_name_get`` ()\n\nsee :ref:`function_name-name` .\n\n\nAtomic Callbacks\n****************\n\nFunction Type\n=============\nThe function type ``atomic_``\\ *c_type* is defined in the CppAD namespace.\n\n| ``typedef int`` (* ``atomic_`` *c_type* )(\n| |tab| ``size_t`` , ``size_t`` , ``const`` *type* * , ``size_t`` , *type* * , ``size_t`` *\n| )\n\nSyntax\n======\n| *flag* = ``cppad_atomic_``\\ *atomic_name* (\n| |tab| *call_id* , *nu* , *u* , *ny* , *y* , *compare_change*\n| )\n\nA corresponding function call evaluates zero order forward mode for the\natomic function with the specified *atomic_name* ; see\natomic_four :ref:`atomic_four_ctor@atomic_four@name` .\n\ncall_id\n*******\nThis argument is only used during atomic four function callbacks,\nin which case it is the corresponding\n:ref:`atomic_four_call@call_id` .\n\nnu\n**\nis the number of independent dynamic parameters\nplus number of independent variables for the function *fun* .\n\nu\n*\nis a C vector of size *nu* containing the independent dynamic parameters\nand independent variables.\nThe independent dynamic parameter come first as in the same order as\n:ref:`Independent@dynamic` in the call to ``Independent``\nfor this function.\nThe independent variables are in the same order as\n:ref:`Independent@x` in the call to ``Independent`` for this function.\n\nny\n**\nis the number of dependent values for this function\n(a dependent value can be a variable, dynamic parameter, or constant parameter).\n\ny\n*\nis a C vector of size *ny* .\nThis input values of its elements do not matter.\nUpon return, it contains the function value correspond to *u* .\n\ncompare_change\n**************\nThis argument is both an input and an output.\nThe number of comparison operators that change their bool result value\nis added to *compare_change* . This way, *compare_change*\ncan be used to accumulate the number of changes between multiplier calls.\n\nflag\n****\nIf this is zero, no error was detected.\nIf it is one (two), *nu* ( *ny* ) does not have its expected value.\n\nRestrictions\n************\nThe ``to_csrc`` routine is not implemented for\n:ref:`vecad-name` operations.\n{xrst_toc_hidden\n    example/jit/jit.xrst\n}\nExample\n*******\nThe section :ref:`example_jit-name` contains examples and tests\nthat use ``to_csrc`` .\n\n{xrst_end to_csrc}\n*/\n# include <cppad/local/graph/csrc_writer.hpp>\n\n# if CPPAD_C_COMPILER_MSVC_FLAGS\n# define CPPAD_FUN_TYPE __cdecl\n# define CPPAD_IMPORT   __declspec(dllimport)\n# else\n# define CPPAD_FUN_TYPE\n# define CPPAD_IMPORT\n# endif\n\n\nnamespace CppAD {\n    extern \"C\" {\n        //\n        // jit_c_type\n        CPPAD_IMPORT typedef int (CPPAD_FUN_TYPE *jit_float)(\n            size_t, const float*, size_t, float*, size_t*\n        );\n        CPPAD_IMPORT typedef int (CPPAD_FUN_TYPE *jit_double)(\n            size_t, const double*, size_t, double*, size_t*\n        );\n        CPPAD_IMPORT typedef int (CPPAD_FUN_TYPE *jit_long_double)(\n            size_t, const long double*, size_t, long double*, size_t*\n        );\n        //\n        // atomic_c_type\n        CPPAD_IMPORT typedef int (CPPAD_FUN_TYPE *atomic_float)(\n            size_t, size_t, const float*, size_t, float*, size_t*\n        );\n        CPPAD_IMPORT typedef int (CPPAD_FUN_TYPE *atomic_double)(\n            size_t, size_t, const double*, size_t, double*, size_t*\n        );\n        CPPAD_IMPORT typedef int (CPPAD_FUN_TYPE *atomic_long_double)(\n            size_t, size_t, const long double*, size_t, long double*, size_t*\n        );\n    }\n}\n\n# undef CPPAD_FUN_TYPE\n# undef CPPAD_IMPORT\n\n// BEGIN_PROTOTYPE\ntemplate <class Base, class RecBase>\nvoid CppAD::ADFun<Base,RecBase>::to_csrc(\n    std::ostream&      os     ,\n    const std::string& c_type )\n// END_PROTOTYPE\n{   //\n    // type\n# ifndef NDEBUG\n    bool ok = false;\n    ok |= c_type == \"float\";\n    ok |= c_type == \"double\";\n    ok |= c_type == \"long_double\";\n    CPPAD_ASSERT_KNOWN(ok,\n        \"f.to_csrc: c_type is not one of the following: \"\n        \"float, double, long_double\"\n        );\n# endif\n    // to_graph return values\n    cpp_graph graph_obj;\n    //\n    // graph corresponding to this function\n    to_graph(graph_obj);\n    //\n    // os\n    local::graph::csrc_writer(os, graph_obj, c_type);\n    //\n    return;\n}\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/unary_minus.hpp",
    "content": "# ifndef CPPAD_CORE_UNARY_MINUS_HPP\n# define CPPAD_CORE_UNARY_MINUS_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin unary_minus}\n\nAD Unary Minus Operator\n#######################\n\nSyntax\n******\n| *y* = ``-`` *x*\n\nPurpose\n*******\nComputes the negative of *x* .\n\nBase\n****\nThe operation in the syntax above must be supported for the case where\nthe operand is a ``const`` *Base* object.\n\nx\n*\nThe operand *x* has one of the following prototypes\n\n| |tab| ``const AD`` < *Base* >               & *x*\n| |tab| ``const VecAD`` < *Base* >:: ``reference &`` *x*\n\ny\n*\nThe result *y* has type\n\n    ``AD`` < *Base* > *y*\n\nIt is equal to the negative of the operand *x* .\n\nOperation Sequence\n******************\nThis is an AD of *Base*\n:ref:`atomic operation<glossary@Operation@Atomic>`\nand hence is part of the current\nAD of *Base*\n:ref:`operation sequence<glossary@Operation@Sequence>` .\n\nDerivative\n**********\nIf :math:`f` is a\n:ref:`glossary@Base Function` ,\n\n.. math::\n\n    \\D{[ - f(x) ]}{x} = - \\D{f(x)}{x}\n\nExample\n*******\n{xrst_toc_hidden\n    example/general/unary_minus.cpp\n}\nThe file\n:ref:`unary_minus.cpp-name`\ncontains an example and test of this operation.\n\n{xrst_end unary_minus}\n-------------------------------------------------------------------------------\n*/\n\n//  BEGIN CppAD namespace\nnamespace CppAD {\n//\ntemplate <class Base>\nAD<Base> AD<Base>::operator - (void) const\n{\n    // compute the Base part of this AD object\n    AD<Base> result;\n    result.value_ = - value_;\n    CPPAD_ASSERT_UNKNOWN( Parameter(result) );\n\n    // check if there is a recording in progress\n    local::ADTape<Base>* tape = AD<Base>::tape_ptr();\n    if( tape == nullptr )\n        return result;\n    // tape_id cannot match the default value for tape_id; i.e., 0\n    CPPAD_ASSERT_UNKNOWN( tape->id_ > 0 );\n    //\n    if( tape->id_ != tape_id_ )\n        return result;\n    //\n    if( ad_type_ == variable_enum )\n    {   // result is a variable\n        CPPAD_ASSERT_UNKNOWN( local::NumRes(local::NegOp) == 1 );\n        CPPAD_ASSERT_UNKNOWN( local::NumRes(local::NegOp) == 1 );\n        //\n        // put operand address in the tape\n        tape->Rec_.PutArg(taddr_);\n        // put operator in the tape\n        result.taddr_ = tape->Rec_.PutOp(local::NegOp);\n        // make result a variable\n        result.tape_id_ = tape_id_;\n        result.ad_type_ = variable_enum;\n    }\n    else\n    {   CPPAD_ASSERT_UNKNOWN( ad_type_ == dynamic_enum );\n        addr_t arg0 = taddr_;\n        result.taddr_ = tape->Rec_.put_dyn_par(\n            result.value_, local::neg_dyn, arg0\n        );\n        result.tape_id_  = tape_id_;\n        result.ad_type_  = dynamic_enum;\n    }\n    return result;\n}\n//\ntemplate <class Base>\nAD<Base> operator - (const VecAD_reference<Base> &right)\n{   return - right.ADBase(); }\n\n}\n//  END CppAD namespace\n\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/unary_plus.hpp",
    "content": "# ifndef CPPAD_CORE_UNARY_PLUS_HPP\n# define CPPAD_CORE_UNARY_PLUS_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin unary_plus}\n\nAD Unary Plus Operator\n######################\n\nSyntax\n******\n| *y* = + *x*\n\nPurpose\n*******\nPerforms the unary plus operation\n(the result *y* is equal to the operand *x* ).\n\nx\n*\nThe operand *x* has one of the following prototypes\n\n| |tab| ``const AD`` < *Base* >               & *x*\n| |tab| ``const VecAD`` < *Base* >:: ``reference &`` *x*\n\ny\n*\nThe result *y* has type\n\n    ``AD`` < *Base* > *y*\n\nIt is equal to the operand *x* .\n\nOperation Sequence\n******************\nThis is an AD of *Base*\n:ref:`atomic operation<glossary@Operation@Atomic>`\nand hence is part of the current\nAD of *Base*\n:ref:`operation sequence<glossary@Operation@Sequence>` .\n\nDerivative\n**********\nIf :math:`f` is a\n:ref:`glossary@Base Function` ,\n\n.. math::\n\n    \\D{[ + f(x) ]}{x} = \\D{f(x)}{x}\n\nExample\n*******\n{xrst_toc_hidden\n    example/general/unary_plus.cpp\n}\nThe file\n:ref:`unary_plus.cpp-name`\ncontains an example and test of this operation.\n\n{xrst_end unary_plus}\n-------------------------------------------------------------------------------\n*/\n\n//  BEGIN CppAD namespace\nnamespace CppAD {\n\ntemplate <class Base>\nAD<Base> AD<Base>::operator + (void) const\n{   AD<Base> result(*this);\n\n    return result;\n}\n\n\ntemplate <class Base>\nAD<Base> operator + (const VecAD_reference<Base> &right)\n{   return right.ADBase(); }\n\n}\n//  END CppAD namespace\n\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/undef.hpp",
    "content": "# ifndef CPPAD_CORE_UNDEF_HPP\n# define CPPAD_CORE_UNDEF_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n----------------------------------------------------------------------------\nPreprecessor definitions that persist after cppad/cppad.hpp is included.\nThese are part of the user API (see omh/preprocessor.omh) with some exceptions\nthat are used by the CppAD examples and tests.\n\n// BEGIN_SORT_THIS_LINE_PLUS_1\n# undef CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL used by CPPAD_USER_ATOMIC\n# undef CPPAD_ASSERT_KNOWN                   used by cppad_ipopt\n# undef CPPAD_ASSERT_UNKNOWN                 used by cppad_ipopt\n# undef CPPAD_C_COMPILER_CMD                 used by dll examples.\n# undef CPPAD_C_COMPILER_GNU_FLAGS           used by dll examples.\n# undef CPPAD_C_COMPILER_MSVC_FLAGS          used by dll examples.\n# undef CPPAD_HASH_TABLE_SIZE                used by test_more/optimize.cpp\n# undef CPPAD_HAS_COLPACK                    used by speed/cppad/sparse_*.cpp\n# undef CPPAD_LINK_FLAGS_HAS_M32             used to exclude certain tests\n# undef EIGEN_MATRIXBASE_PLUGIN              example use of Eigen with CppAD\n// END_SORT_THIS_LINE_MINUS_1\n\n// for conditional testing when implicit conversion is not present\n# undef CPPAD_DEPRECATED\n-----------------------------------------------------------------------------\n*/\n// Preprecessor definitions that do not persist. None of these are in the\n// user API.\n// BEGIN_SORT_THIS_LINE_PLUS_1\n# undef CPPAD_ASSERT_AD_TYPE\n# undef CPPAD_ASSERT_NARG_NRES\n# undef CPPAD_AZMUL\n# undef CPPAD_BOOSTVECTOR\n# undef CPPAD_COMPILER_HAS_CONVERSION_WARN\n# undef CPPAD_COND_EXP\n# undef CPPAD_COND_EXP_BASE_REL\n# undef CPPAD_COND_EXP_REL\n# undef CPPAD_CPPADVECTOR\n# undef CPPAD_DEBUG_AND_RELEASE\n# undef CPPAD_EIGENVECTOR\n# undef CPPAD_FOLD_AD_VALUED_BINARY_OPERATOR\n# undef CPPAD_FOLD_ASSIGNMENT_OPERATOR\n# undef CPPAD_FOLD_BOOL_VALUED_BINARY_OPERATOR\n# undef CPPAD_HAS_ADOLC\n# undef CPPAD_HAS_EIGEN\n# undef CPPAD_HAS_GETTIMEOFDAY\n# undef CPPAD_HAS_IPOPT\n# undef CPPAD_HAS_MKSTEMP\n# undef CPPAD_HAS_TMPNAM_S\n# undef CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION\n# undef CPPAD_IS_SAME_TAPE_ADDR_TYPE_SIZE_T\n# undef CPPAD_IS_SAME_UNSIGNED_INT_SIZE_T\n# undef CPPAD_LIB_EXPORT\n# undef CPPAD_MAX_NUM_CAPACITY\n# undef CPPAD_MIN_DOUBLE_CAPACITY\n# undef CPPAD_NDEBUG_NOEXCEPT\n# undef CPPAD_NOEXCEPT\n# undef CPPAD_PADDING_BLOCK_T\n# undef CPPAD_STANDARD_MATH_UNARY_AD\n# undef CPPAD_STDVECTOR\n# undef CPPAD_TRACE_CAPACITY\n# undef CPPAD_TRACE_THREAD\n# undef CPPAD_TRACK_DEBUG\n# undef CPPAD_USER_MACRO\n# undef CPPAD_USER_MACRO_ONE\n# undef CPPAD_USER_MACRO_TWO\n# undef CPPAD_VEC_AD_COMP_ASSIGN\n# undef CPPAD_VEC_ENUM_TYPE\n// END_SORT_THIS_LINE_MINUS_1\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/user_ad.hpp",
    "content": "# ifndef CPPAD_CORE_USER_AD_HPP\n# define CPPAD_CORE_USER_AD_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n---------------------------------------------------------------------------\n\n{xrst_begin AD}\n\nAD Objects\n##########\n\nPurpose\n*******\nThe sections listed below describe the operations\nthat are available to :ref:`glossary@AD of Base` objects.\nThese objects are used to :ref:`glossary@Tape`\nan AD of *Base*\n:ref:`operation sequence<glossary@Operation@Sequence>` .\nThis operation sequence can\nbe transferred to an :ref:`ADFun-name` object where it\ncan be used to evaluate the corresponding\nfunction and derivative values.\n\nBase Type Requirements\n**********************\nThe *Base* requirements are provided by the CppAD package\nfor the following base types:\n``float`` ,\n``double`` ,\n``std::complex<float>`` ,\n``std::complex<double>`` .\nOtherwise, see :ref:`base_require-name` .\n\nContents\n********\n{xrst_toc_table\n    include/cppad/core/ad_ctor.hpp\n    include/cppad/core/ad_assign.hpp\n    include/cppad/core/convert.hpp\n    include/cppad/core/ad_valued.hpp\n    include/cppad/core/bool_valued.hpp\n    include/cppad/core/vec_ad/user.xrst\n    include/cppad/base_require.hpp\n}\n\n{xrst_end AD}\n---------------------------------------------------------------------------\n*/\n\n# include <cppad/core/ad_ctor.hpp>\n# include <cppad/core/ad_assign.hpp>\n# include <cppad/core/convert.hpp>\n# include <cppad/core/vec_ad/vec_ad.hpp>\n# include <cppad/core/ad_valued.hpp>\n# include <cppad/core/bool_valued.hpp>\n# include <cppad/core/zdouble.hpp>\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/value.hpp",
    "content": "# ifndef CPPAD_CORE_VALUE_HPP\n# define CPPAD_CORE_VALUE_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin Value}\n\nConvert From an AD Type to its Base Type\n########################################\n\nSyntax\n******\n| *b* = ``Value`` ( *x* )\n\nSee Also\n********\n:ref:`var2par-name`\n\nPurpose\n*******\nConverts from an AD type to the corresponding\n:ref:`glossary@Base Type` .\n\nx\n*\nThe argument *x* has prototype\n\n    ``const AD`` < *Base* > & *x*\n\nb\n*\nThe return value *b* has prototype\n\n    *Base* *b*\n\nOperation Sequence\n******************\nThe result of this operation is not an\n:ref:`glossary@AD of Base` object.\nThus it will not be recorded as part of an\nAD of *Base*\n:ref:`operation sequence<glossary@Operation@Sequence>` .\n\nRestriction\n***********\nThe argument *x* must not be a\n:ref:`glossary@Variable` or\n:ref:`glossary@Parameter@Dynamic` parameter\nbecause its dependency information\nwould not be included in the ``Value`` result *b* .\n\nExample\n*******\n{xrst_toc_hidden\n    example/general/value.cpp\n}\nThe file\n:ref:`value.cpp-name`\ncontains an example and test of this operation.\n\n{xrst_end Value}\n-------------------------------------------------------------------------------\n*/\n\n//  BEGIN CppAD namespace\nnamespace CppAD {\n\ntemplate <class Base>\nCPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION\nBase Value(const AD<Base> &x)\n{   Base result;\n    //\n    CPPAD_ASSERT_KNOWN(\n        ! ( Variable(x) || Dynamic(x) ) ,\n        \"Value: argument is a variable or dynamic parameter\"\n    );\n    //\n    result = x.value_;\n    return result;\n}\n\n}\n//  END CppAD namespace\n\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/var2par.hpp",
    "content": "# ifndef CPPAD_CORE_VAR2PAR_HPP\n# define CPPAD_CORE_VAR2PAR_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n------------------------------------------------------------------------------\n\n{xrst_begin Var2Par}\n\nConvert an AD Variable or Dynamic Parameter to a Constant\n#########################################################\n\nSyntax\n******\n| *y* = ``Var2Par`` ( *x* )\n\nSee Also\n********\n:ref:`value-name`\n\nPurpose\n*******\nReturns a\n:ref:`constant parameter<glossary@Parameter@Constant>` *y*\nwith the same value as *x* .\n\nx\n*\nThe argument *x* has prototype\n\n    ``const AD`` < *Base* > & ``x``\n\nThe argument *x* may be a\nvariable, dynamic parameter, or constant parameter.\n\ny\n*\nThe result *y* has prototype\n\n    ``AD`` < *Base* > & ``y``\n\nand is a constant parameter.\n\nExample\n*******\n{xrst_toc_hidden\n    example/general/var2par.cpp\n}\nThe file\n:ref:`var2par.cpp-name`\ncontains an example and test of this operation.\n\n{xrst_end Var2Par}\n------------------------------------------------------------------------------\n*/\n\n//  BEGIN CppAD namespace\nnamespace CppAD {\n\ntemplate <class Base>\nCPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION\nAD<Base> Var2Par(const AD<Base> &x)\n{   AD<Base> y(x.value_);\n    return y;\n}\n\n\ntemplate <class Base>\nCPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION\nAD<Base> Var2Par(const VecAD_reference<Base> &x)\n{   AD<Base> y(x.ADBase());\n    y.id_ = 0;\n}\n\n\n} // END CppAD namespace\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/vec_ad/user.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n/*\n{xrst_begin VecAD}\n{xrst_spell\n    grep\n    ldp\n    ldv\n    vp\n    wc\n}\n\nAD Vectors that Record Index Operations\n#######################################\n\nSyntax\n******\n| ``VecAD`` < *Base* > *vec* ( *n* )\n| *vec* . ``size`` ()\n| *base* = *vec* [ *i* ]\n| *abase* = *vec* [ *ind* ]\n| *vec* [ *ind* ]   = *right*\n| *left* = *vec* [ *ind* ]\n\nPurpose\n*******\nIf either *vec* or *ind* is a\n:ref:`glossary@Variable` or\n:ref:`dynamic parameter<glossary@Parameter@Dynamic>` ,\nthe indexing operation\n\n    *vec* [ *ind* ]\n\nis recorded in the corresponding ``AD`` < *Base* >\n:ref:`operation sequence<glossary@Operation@Sequence>` and\nincluded in the corresponding :ref:`ADFun-name` object *f* .\nSuch an index can change each time\nzero order :ref:`f.Forward<Forward-name>` is used; i.e.,\neach time *f* is evaluated with new value for the\n:ref:`independent variables<glossary@Tape@Independent Variable>` .\nNote that the value of *vec* [ *ind* ]\ndepends on the value of *ind*\nin a discrete fashion and CppAD computes its partial derivative with\nrespect to *ind* as zero.\n\nAlternatives\n************\nIf only the values in *vec* ,\nand not the indices *ind* ,\ndepend on the independent variables,\na :ref:`SimpleVector-name` with elements of type ``AD`` < *Base* >\nwould be more efficient than using ``VecAD`` < *Base* > .\nIf only the indices, and not the values in the vector,\ndepend on the independent variables,\na :ref:`Discrete-name` functions would be a much more efficient.\n\nEfficiency\n**********\nIf one uses ``VecAD`` vector where one could use a simple vector,\nthe :ref:`sparsity_pattern-name` will be less efficient\nbecause the dependence on different elements cannot be separated.\nIn addition, ``VecAD`` objects that only depend on dynamic parameters\nare treated as if they were variables making sparsity patterns\neven less efficient (have more possibly non-zero values than necessary);\nsee :ref:`wish_list@Dynamic Parameters@VecAD Vectors`\nunder dynamic parameters in the wish list.\n\nVecAD<Base>::reference\n**********************\nThe expression *vec* [ *ind* ] has prototype\n\n    ``VecAD`` < *Base* >:: ``reference`` *vec* [ *ind* ]\n\nwhich is like the ``AD`` < *Base* > type\nwith some notable exceptions:\n\nExceptions\n==========\n\n#. This object cannot be used with the\n   :ref:`Value-name` function to compute the corresponding *Base* value.\n   In some cases, the syntax\n\n        *vec* [ *i* ]\n\n    can be used to obtain the corresponding *Base* value; see below.\n\n#. This object cannot be used as the left hand side in a\n   with a :ref:`compound assignment<compound_assign-name>` ; i.e.,\n   ``+=`` ,\n   ``-=`` ,\n   ``*=`` , or\n   ``/=`` .\n   For example, the following syntax is not valid:\n\n        *vec* [ *ind* ] += *z* ;\n\n    no matter what the types of *z* .\n\n#. Assignment to ``vec`` [ ``ind`` ] returns a ``void`` .\n   For example, the following syntax is not valid:\n\n        *z* = *vec* [ *ind* ] = *u* ;\n\n    no matter what the types of *z* , and *u* .\n\n#. A *vec* [ *ind* ] object cannot appear in a :ref:`CondExp-name` ;\n   For example, the following syntax is not valid:\n\n        ``CondExpGt`` ( *vec* [ *ind* ], *u* , *v* , *w* )\n\n    no matter what the types of *u* , *v* , and *w* .\n\n#. A *vec* [ *ind* ] object should not be used with the\n   ``Constant`` , ``Dynamic`` , ``Parameter`` , and ``Variable``\n   functions (see :ref:`con_dyn_var-name` ).\n   The entire vector *vec* should be used instead.\n\n#. A ``VecAD`` vector\n   cannot be passed to ``Independent`` function.\n\nConstructor\n***********\n\nvec\n===\nThe syntax\n\n    ``VecAD`` < *Base* > *vec* ( *n* )\n\ncreates an ``VecAD`` object *vec* with\n*n* elements.\nThe initial value of the elements of *vec* is unspecified.\n\nn\n=\nThe argument *n* has prototype\n\n    ``size_t`` *n*\n\nsize\n****\nThe syntax\n\n    *vec* . ``size`` ()\n\nreturns the number of elements in the vector *vec* ;\ni.e., the value of *n* when it was constructed.\n\nBase Indexing\n*************\nWe refer to the syntax\n\n    *base* = *vec* [ *i* ]\n\nas base indexing of a ``VecAD`` object.\nThis indexing is only valid if the vector *vec* is a\n:ref:`con_dyn_var@Constant` ; i.e.,\nit does not depend on the independent variables.\n\ni\n=\nThe operand *i* has prototype\n\n    ``size_t`` *i*\n\nand must be less than *n* ; i.e., less than\nthe number of elements in *vec* .\n\nbase\n====\nThe result *base* has prototype\n\n    *Base* & *base*\n\ni.e., it is a reference to the *i*-th element in the vector *vec* .\nIt can be used to change the element value;\nfor example,\n\n    *vec* [ *i* ] = *b*\n\nis valid where *b* is a *Base* object.\nThe reference *base* is no longer valid once the\n*vec* changes in any way; i.e., has another assignment.\n\nAD Indexing\n***********\nWe refer to the syntax\n\n    *vec* [ *ind* ]\n\nas AD indexing of a ``VecAD`` object.\n\nind\n===\nThe argument *ind* has prototype\n\n    ``const AD`` < *Base* >& *ind*\n\nThe value of *ind* must be greater than or equal zero\nand less than *n* ; i.e., less than\nthe number of elements in *vec* .\n\nresult\n======\nThe resulting expression has prototype\n\n    ``VecAD`` < *Base* >:: ``reference`` *vec* [ *ind* ]\n\nThis objects operations are recorded as part of the ``AD`` < *Base* >\n:ref:`operation sequence<glossary@Operation@Sequence>` .\nIt acts like a reference to the\nelement with index ``floor`` ( *ind* ) in the vector *vec* ;\n( ``floor`` ( *ind* ) is\nthe greatest integer less than or equal *ind* ).\n\nright\n=====\nIs the right hand side of the assignment statement\nand specifies the new value for the corresponding element of *vec* .\nIt has one of the following prototypes:\n\n| |tab| ``int`` *right*\n| |tab| ``const`` *Base* & *right*\n| |tab| ``const AD`` < *Base* >& *right*\n| |tab| ``const VecAD_reverence`` < *Base* >& *right*\n\nleft\n====\nIs the left hand side of the assignment statement\nis the current value for the corresponding element of *vec* .\nIt has the following prototype:\n\n    ``const AD`` < *Base* >& *left*\n\nExample\n*******\n{xrst_toc_hidden\n    example/general/vec_ad.cpp\n}\nThe file\n:ref:`vec_ad.cpp-name`\ncontains an example and test using ``VecAD`` vectors.\n\nbase2ad\n*******\nForward mode on a ``base2ad`` function does not preserve\n:ref:`VecAD-name` operations (which might be expected); see the\n:ref:`base2vec_ad.cpp-name` example.\n\nSpeed and Memory\n****************\nThe :ref:`VecAD-name` vector type is inefficient because every\ntime an element of a vector is accessed, a new CppAD\n:ref:`glossary@Variable` is created on the tape\nusing either the ``Ldp`` or ``Ldv`` operation\n(unless all of the elements of the vector are\n:ref:`parameters<glossary@Parameter>` ).\nThe effect of this can be seen by executing the following steps:\n\n#. In the file ``cppad/local/forward1sweep.h`` ,\n   change the definition of ``CPPAD_FORWARD1SWEEP_TRACE`` to\n   ::\n\n        # define CPPAD_FORWARD1SWEEP_TRACE 1\n\n#. In the ``Example`` directory, execute the command\n   ::\n\n        ./test_one.sh lu_vec_ad_ok.cpp lu_vec_ad.cpp -DNDEBUG > lu_vec_ad_ok.log\n\n    This will write a trace of all the forward tape operations,\n    for the test case :ref:`lu_vec_ad_ok.cpp-name` ,\n    to the file ``lu_vec_ad_ok.log`` .\n#. In the ``Example`` directory execute the commands\n   ::\n\n        grep \"op=\"           lu_vec_ad_ok.log | wc -l\n        grep \"op=Ld[vp]\"     lu_vec_ad_ok.log | wc -l\n        grep \"op=St[vp][vp]\" lu_vec_ad_ok.log | wc -l\n\n    The first command counts the number of operators in the tracing,\n    the second counts the number of VecAD load operations,\n    and the third counts the number of VecAD store operations.\n    (For CppAD version 05-11-20 these counts were 956, 348, and 118\n    respectively.)\n\n{xrst_end VecAD}\n------------------------------------------------------------------------\n*/\n"
  },
  {
    "path": "include/cppad/core/vec_ad/vec_ad.hpp",
    "content": "# ifndef CPPAD_CORE_VEC_AD_VEC_AD_HPP\n# define CPPAD_CORE_VEC_AD_VEC_AD_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/local/pod_vector.hpp>\nnamespace CppAD { //  BEGIN_CPPAD_NAMESPACE\n/*\n{xrst_begin_parent dev_vec_ad dev}\n\nDeveloper Documentation for VecAD Operations\n############################################\n\nContents\n********\n{xrst_toc_table\n}\n\n{xrst_end dev_vec_ad}\n ------------------------------------------------------------------------------\n{xrst_begin vec_ad_comp_assign dev}\nVecAD: Prints Error Message If A Compound Assignment Is Used\n############################################################\n\nSyntax\n******\n| ``CPPAD_VEC_AD_COMP_ASSIGN`` ( *cop* )\n| ``ref cop right``\n\nCPPAD_VEC_AD_COMP_ASSIGN\n************************\nThis macro defines the compound assignment operator *cop*\nfor a VecAD reference element to be an error with an error message.\n\ncop\n***\nIs one of the following computed assignment operators:\n+= , -= , \\*= , /=.\n\nref\n***\nis the VecAD reference.\n\nright\n*****\nis the right hand side for the compound assignment.\n\nSource\n******\n{xrst_spell_off}\n{xrst_code hpp} */\n# define CPPAD_VEC_AD_COMP_ASSIGN(cop)                              \\\nVecAD_reference& operator cop (const VecAD_reference<Base> &right)  \\\n{  CPPAD_ASSERT_KNOWN(false,                                       \\\n        \"Can't use VecAD<Base>::reference on left side of \" #cop    \\\n    );                                                              \\\n    return *this;                                                   \\\n}                                                                   \\\nVecAD_reference& operator cop (const AD<Base> &right)               \\\n{  CPPAD_ASSERT_KNOWN(false,                                       \\\n        \"Can't use VecAD<Base>::reference on left side of \" #cop    \\\n    );                                                              \\\n    return *this;                                                   \\\n}                                                                   \\\nVecAD_reference& operator cop (const Base &right)                   \\\n{  CPPAD_ASSERT_KNOWN(false,                                       \\\n        \"Can't use VecAD<Base>::reference on left side of \" #cop    \\\n    );                                                              \\\n    return *this;                                                   \\\n}                                                                   \\\nVecAD_reference& operator cop (int right)                           \\\n{  CPPAD_ASSERT_KNOWN(false,                                       \\\n        \"Can't use VecAD<Base>::reference on left side of \" #cop    \\\n    );                                                              \\\n    return *this;                                                   \\\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end vec_ad_comp_assign}\n------------------------------------------------------------------------------\n{xrst_begin vec_ad_reference dev}\nVecAD Element Reference Class\n#############################\n\nSyntax\n******\n\n| ``VecAD_reverence`` *ref* ( *vec* , *ind* )\n| *ref* = *right*\n| ``ref cop right``\n| ``element`` = ``ref`` . *ADBase* ()\n\nMember Variables\n****************\n\nvec\\_\n=====\nThis private data is a reference to *vec* in the constructor.\n\nind\\_\n=====\nThis private data is a copy of *ind* in the constructor.\n\nBase\n****\nElements of this reference class act like an\n``AD`` < *Base* > object (in a restricted sense),\nin addition they track (on the tape) the index *ind* they correspond to.\n\nvec\n***\nis the vector containing the element being referenced and has prototype\n\n    ``VecAD`` < *Base* > *vec*\n\nind\n***\nis the index of the element being referenced and has prototype\n\n    ``const AD`` < *Base* >& ``ind``\n\nIf *ind* . ``tape_id_`` matches a current recording,\nso does *vec* . ``tape_id_`` and\nthe :ref:`AD type<atomic_three_define@ad_type>` corresponding to *vec*\nincludes this indexing operation; i.e., it is greater than or equal\nthe AD type corresponding to *ind* .\n\nright\n*****\nIs the right hand side of the assignment statement and has one\nof the following prototypes:\n\n| |tab| ``int`` *right*\n| |tab| ``const`` *Base* & *right*\n| |tab| ``const AD`` < *Base* >& *right*\n| |tab| ``const VecAD_reverence`` < *Base* >& *right*\n\ncop\n***\nIs one of the following computed assignment operators:\n+= , -= , \\*= , /=.\nAll of these operations report an error.\n\nelement\n*******\nIs a copy of the element corresponding to the reference *ref*\nand has prototype:\n\n    ``AD`` < *Base* > *element*\n\n{xrst_end vec_ad_reference}\n*/\ntemplate <class Base>\nclass VecAD_reference {\n    friend bool  Constant<Base>  (const VecAD<Base> &vec);\n    friend bool  Parameter<Base> (const VecAD<Base> &vec);\n    friend bool  Dynamic<Base>   (const VecAD<Base> &vec);\n    friend bool  Variable<Base>  (const VecAD<Base> &vec);\n    friend class VecAD<Base>;\n    friend class local::ADTape<Base>;\n\nprivate:\n    VecAD<Base>& vec_;  // reverence to vector\n    AD<Base>     ind_;  // index for this element\npublic:\n    VecAD_reference(VecAD<Base>& vec, const AD<Base>& ind)\n        : vec_( vec ) , ind_(ind)\n    { }\n\n    // assignment operators\n    void operator = (const VecAD_reference<Base> &right);\n    void operator = (const AD<Base> &right);\n    void operator = (const Base     &right);\n    void operator = (int             right);\n\n    // compound assignments\n    CPPAD_VEC_AD_COMP_ASSIGN( += )\n    CPPAD_VEC_AD_COMP_ASSIGN( -= )\n    CPPAD_VEC_AD_COMP_ASSIGN( *= )\n    CPPAD_VEC_AD_COMP_ASSIGN( /= )\n\n\n    /// Conversion from VecAD_reference to AD<Base>.\n    /// puts the correspond vecad load instruction in the tape.\n    AD<Base> ADBase(void) const\n    {   // start with default constructor (hence dynamic_ is false).\n        AD<Base> result;\n\n        size_t i = static_cast<size_t>( Integer(ind_) );\n        CPPAD_ASSERT_UNKNOWN( i < vec_.length_ );\n\n        // AD<Base> value corresponding to this element\n        result.value_ = vec_.data_[i];\n        CPPAD_ASSERT_UNKNOWN( Constant(result) );\n\n        // check if there is a recording in progress\n        local::ADTape<Base>* tape = AD<Base>::tape_ptr();\n        if( tape == nullptr )\n            return result;\n\n        // tape_id cannot match the default value zero\n        CPPAD_ASSERT_UNKNOWN( tape->id_ > 0 );\n\n        // check if vector, index match tape_id\n        bool match_vec   = vec_.tape_id_  == tape->id_;\n        bool match_ind   = ind_.tape_id_  == tape->id_;\n\n        // check if vector, index are dynamic parmaerters\n        CPPAD_ASSERT_UNKNOWN( vec_.ad_type_ != dynamic_enum);\n        bool dyn_ind   = match_ind   & (ind_.ad_type_  == dynamic_enum);\n\n        // check if vector, index are variables\n        bool var_vec   = match_vec   & (vec_.ad_type_   == variable_enum);\n        bool var_ind   = match_ind   & (ind_.ad_type_   == variable_enum);\n\n        // check if vector, index are constants\n        bool con_vec   = ! var_vec;\n        bool con_ind   = ! ( dyn_ind   | var_ind);\n        if( con_vec & con_ind )\n            return result;\n# ifndef NDEBUG\n    if( match_vec & match_ind ) CPPAD_ASSERT_KNOWN(\n        vec_.tape_id_ == ind_.tape_id_ ,\n        \"VecAD: vector and index are dynamic parameters or variables \"\n        \"on different treads.\"\n    );\n# endif\n        // parameter or variable index corresponding to ind_\n        addr_t ind_taddr = ind_.taddr_;\n        if( con_ind )\n            ind_taddr = tape->Rec_.put_con_par(ind_.value_);\n\n        // index corresponding to this element\n        CPPAD_ASSERT_UNKNOWN( var_vec );\n        {   CPPAD_ASSERT_UNKNOWN( vec_.offset_ > 0  );\n            size_t load_op_index = tape->Rec_.num_var_load();\n            //\n            if( var_ind )\n            {   CPPAD_ASSERT_UNKNOWN( local::NumRes(local::LdvOp) == 1 );\n                CPPAD_ASSERT_UNKNOWN( local::NumArg(local::LdvOp) == 3 );\n\n                // put operand addresses in tape, ind_ is a variable\n                result.taddr_ = tape->Rec_.PutLoadOp(local::LdvOp);\n                tape->Rec_.PutArg(\n                    (addr_t) vec_.offset_, ind_taddr, (addr_t) load_op_index\n                );\n\n                // change result to variable for this load\n                result.tape_id_ = tape->id_;\n                result.ad_type_ = variable_enum;\n            }\n            else\n            {   CPPAD_ASSERT_UNKNOWN( local::NumRes(local::LdpOp) == 1 );\n                CPPAD_ASSERT_UNKNOWN( local::NumArg(local::LdpOp) == 3 );\n                CPPAD_ASSERT_UNKNOWN( con_ind | dyn_ind );\n\n\n                // put operand addresses in tape\n                tape->Rec_.PutArg(\n                    (addr_t) vec_.offset_, ind_taddr, (addr_t) load_op_index\n                );\n                // put operator in the tape, ind_ is a parameter\n                result.taddr_ = tape->Rec_.PutLoadOp(local::LdpOp);\n\n                // change result to variable for this load\n                result.tape_id_ = tape->id_;\n                result.ad_type_ = variable_enum;\n            }\n        }\n        return result;\n    }\n};\n// ---------------------------------------------------------------------------\n/*!\n{xrst_begin vec_ad_class dev}\n{xrst_spell\n    taddr\n}\nVecAD Class Objects\n###################\n\nSyntax\n******\n\n| ``VecAD`` *empty* , *vec* ( *length* )\n| *length* = *vec* . ``size`` ()\n| *b* = *vec* [ *i* ]\n| *ref* = *vec* [ *ind* ]\n\nlength\n******\nis the size of the vector and has prototype\n\n    ``size_t`` *length*\n\nPrivate Members\n***************\n{xrst_literal\n    // BEGIN_VECAD_PRIVATE_DATA\n    // END_VECAD_PRIVATE_DATA\n}\n\nlength\\_\n========\nis a copy of *length* .\n\ndata\\_\n======\nThis vector has size *length* and\ncontains the value of the elements of the vector.\n\ntaddr\\_\n=======\nThis vector has size *length* .\nIf ``tape_id_`` matches the current recording\nand ``ad_type_`` is ``dynamic_enum`` ,\n``taddr`` [ *i* ] is the parameter index for the corresponding element.\n\noffset\\_\n========\nIf *tape_id_* is the current tape,\n*offset_* is the index of the first element of this vector\nin the combined vector that contains all the VecAD elements for this recording.\n*offset_* ``-1`` is the index of the size of this vector\nin the combined vector.\n\ntape_id\\_\n=========\nis the tape currently associated with this vector.\n\nad_type\\_\n=========\nis the :ref:`atomic_three_define@ad_type` corresponding to this\nvector.\n\ni\n*\nis a ``size_t`` value less than *length* .\nThis form of indexing can only be used when *vec* is a\nconstant parameter; i.e., its operations are not being recorded.\n\nb\n*\nis a reference to the *Base* value\nfor the *i*-th element of the vector.\n\nind\n***\nis a ``AD`` < *Base* > value less than *length* .\nThis form of indexing gets recorded and the value of the index\ncan change.\n\nref\n***\nis a reference to the ``AD`` < *Base* > value\nfor the *x*-th element of the vector.\nIf the vector is a parameter and the index is a variable,\nthe vector is changed to be a variable.\n\n{xrst_end vec_ad_class}\n*/\ntemplate <class Base>\nclass VecAD {\n    friend bool  Constant<Base>  (const VecAD<Base> &vec);\n    friend bool  Parameter<Base> (const VecAD<Base> &vec);\n    friend bool  Dynamic<Base>   (const VecAD<Base> &vec);\n    friend bool  Variable<Base>  (const VecAD<Base> &vec);\n    friend class local::ADTape<Base>;\n    friend class VecAD_reference<Base>;\n\n    friend std::ostream& operator << <Base>\n        (std::ostream &os, const VecAD<Base> &vec_);\nprivate:\n// BEGIN_VECAD_PRIVATE_DATA\n    const  size_t                 length_;\n    local::pod_vector_maybe<Base> data_;\n    local::pod_vector<addr_t>     taddr_;\n    tape_id_t                     tape_id_;\n    addr_t                        offset_;\n    ad_type_enum                  ad_type_;\n// END_VECAD_PRIVATE_DATA\npublic:\n    // declare the user's view of this type here\n    typedef VecAD_reference<Base> reference;\n\n    // default constructor\n    // initialize tape_id_ same as for default constructor; see default.hpp\n    VecAD(void)\n    : length_(0), tape_id_(0), offset_(0), ad_type_(constant_enum)\n    {   CPPAD_ASSERT_UNKNOWN( Constant(*this) ); }\n\n    // sizing constructor\n    // initialize tape_id_ same as for constants; see ad_copy.hpp\n    VecAD(size_t length)\n    : length_(length), tape_id_(0), offset_(0), ad_type_(constant_enum)\n    {   if( length_ > 0 )\n        {   size_t i;\n            Base zero(0);\n            data_.extend(length_);\n            taddr_.extend(length_);\n\n            // Initialize data to zero so all have same value.\n            // This uses less memory and avoids a valgrind error\n            // during TapeRec<Base>::PutPar\n            for(i = 0; i < length_; i++)\n            {   data_[i]  = zero;\n                taddr_[i] = 0;\n            }\n        }\n        CPPAD_ASSERT_UNKNOWN( Constant(*this) );\n    }\n\n    // destructor\n    ~VecAD(void)\n    { }\n\n    // number of elements in the vector\n    size_t size(void)\n    {   return length_; }\n\n    // element access (not taped)\n    Base& operator[](size_t i)\n    {\n        CPPAD_ASSERT_KNOWN(\n            Constant(*this),\n            \"VecAD: cannot use size_t indexing because this\"\n            \" VecAD vector is not a constant parameter.\"\n        );\n        CPPAD_ASSERT_KNOWN(\n            i < length_,\n            \"VecAD: element index is >= vector length\"\n        );\n\n        return data_[i];\n    }\n\n    // element access (taped)\n    VecAD_reference<Base> operator[](const AD<Base> &ind)\n    {\n        CPPAD_ASSERT_KNOWN(\n            0 <= Integer(ind),\n            \"VecAD: element index is less than zero\"\n        );\n        CPPAD_ASSERT_KNOWN(\n            static_cast<size_t>( Integer(ind) ) < length_,\n            \"VecAD: element index is >= vector length\"\n        );\n\n        // check if there is a recording in progress\n        local::ADTape<Base>* tape = AD<Base>::tape_ptr();\n        if( tape == nullptr )\n            return VecAD_reference<Base>(*this, ind);\n\n        // tape_id cannot match the default value zero\n        CPPAD_ASSERT_UNKNOWN( tape->id_ > 0 );\n\n        // check if vector, index match tape_id\n        bool match_vec   = tape_id_      == tape->id_;\n        bool match_ind   = ind.tape_id_  == tape->id_;\n\n        // check if vector, index are dynamic parmaerters\n        CPPAD_ASSERT_UNKNOWN( ad_type_ != dynamic_enum );\n        bool dyn_ind   = match_ind   & (ind.ad_type_  == dynamic_enum);\n\n        // check if vector, index are variables\n        bool var_vec   = match_vec   & (ad_type_       == variable_enum);\n        bool var_ind   = match_ind   & (ind.ad_type_   == variable_enum);\n\n        // check if vector, index are constants\n        bool con_vec   = ! var_vec;\n        bool con_ind   = ! ( dyn_ind   | var_ind);\n        if( con_vec & con_ind )\n            return VecAD_reference<Base>(*this, ind);\n# ifndef NDEBUG\n        if( match_vec & match_ind ) CPPAD_ASSERT_KNOWN(\n            tape_id_ == ind.tape_id_ ,\n            \"VecAD: vector and index are dynamic parameters or variables \"\n            \"on different treads.\"\n        );\n# endif\n        if( con_vec )\n        {   // place a copy of vector in tape\n            for(size_t i = 0; i < length_; ++i)\n                taddr_[i] = tape->Rec_.put_con_par( data_[i] );\n            offset_ = tape->Rec_.put_var_vecad(length_, taddr_);\n\n            // Advance pointer by one so starts at first component of this\n            // vector; i.e., skip length at beginning (so is always > 0)\n            offset_++;\n\n            // tape_id corresponding to this vector\n            tape_id_ = ind.tape_id_;\n\n            // VecAD objects go straight from constants to variables; i.e.,\n            // they never are dynamic parameters.\n            ad_type_ = variable_enum;\n        }\n        CPPAD_ASSERT_UNKNOWN( Variable(*this) );\n        return VecAD_reference<Base>(*this, ind);\n    }\n\n};\n// ---------------------------------------------------------------------------\n// ref = right\ntemplate <class Base>\nvoid VecAD_reference<Base>::operator=(const AD<Base> &right)\n{\n    // index in vector for this element\n    size_t index = static_cast<size_t>( Integer(ind_) );\n    CPPAD_ASSERT_UNKNOWN( index < vec_.length_ );\n\n    // Base part of assignment for this element\n    vec_.data_[index] = right.value_;\n\n    // check if there is a recording in progress\n    local::ADTape<Base>* tape = AD<Base>::tape_ptr();\n    if( tape == nullptr )\n        return;\n\n    // tape_id cannot match the default value zero\n    tape_id_t tape_id = tape->id_;\n    CPPAD_ASSERT_UNKNOWN( tape_id > 0 );\n\n    // check if vector, index, right match tape_id\n    bool match_vec   = vec_.tape_id_  == tape_id;\n    bool match_ind   = ind_.tape_id_  == tape_id;\n    bool match_right = right.tape_id_ == tape_id;\n    CPPAD_ASSERT_UNKNOWN( match_vec || ! match_ind );\n\n    // check if vector, index, right are dynamic parmaerters\n    CPPAD_ASSERT_UNKNOWN(vec_.ad_type_  != dynamic_enum);\n    bool dyn_ind   = match_ind   & (ind_.ad_type_  == dynamic_enum);\n    bool dyn_right = match_right & (right.ad_type_ == dynamic_enum);\n\n    // check if vector, index, right are variables\n    bool var_vec   = match_vec   & (vec_.ad_type_   == variable_enum);\n    bool var_ind   = match_ind   & (ind_.ad_type_   == variable_enum);\n    bool var_right = match_right & (right.ad_type_  == variable_enum);\n\n    // check if vector, index, right are constants\n    bool con_vec   = ! var_vec;\n    bool con_ind   = ! ( dyn_ind   | var_ind);\n    bool con_right = ! ( dyn_right | var_right);\n    if( con_vec & con_right )\n        return;\n\n# ifndef NDEBUG\n    if( match_ind )\n    {   CPPAD_ASSERT_UNKNOWN( ind_.tape_id_ == vec_.tape_id_ );\n        CPPAD_ASSERT_UNKNOWN( ind_.ad_type_ <= vec_.ad_type_ );\n    }\n    if( match_vec & match_right ) CPPAD_ASSERT_KNOWN(\n        vec_.tape_id_ == right.tape_id_ ,\n        \"VecAD: vector and element are dynamic parameters or variables \"\n        \"on different treads.\"\n    );\n# endif\n\n    if( con_vec )\n    {   CPPAD_ASSERT_UNKNOWN( con_ind );\n\n        // place a copy of vector in tape\n        for(size_t i = 0; i < vec_.length_; ++i)\n            vec_.taddr_[i] = tape->Rec_.put_con_par( vec_.data_[i] );\n        vec_.offset_ = tape->Rec_.put_var_vecad(vec_.length_, vec_.taddr_);\n\n        // advance offset from size of vector to first element in vector\n        (vec_.offset_)++;\n\n        // tape_id corresponding to this vector\n        vec_.tape_id_ = right.tape_id_;\n\n        // VecAD objects go straight from constants to variables; i.e.,\n        // they never are dynamic parameters.\n        vec_.ad_type_ = variable_enum;\n    }\n    CPPAD_ASSERT_UNKNOWN( Variable(vec_) );\n    CPPAD_ASSERT_UNKNOWN( vec_.offset_ > 0 );\n\n    // parameter or variable index for ind_\n    addr_t ind_taddr = ind_.taddr_;\n    if( con_ind )\n        ind_taddr = tape->Rec_.put_con_par(ind_.value_);\n    CPPAD_ASSERT_UNKNOWN( ind_taddr > 0 );\n\n    // parameter or variable index for right\n    addr_t right_taddr = right.taddr_;\n    if( con_right )\n        right_taddr = tape->Rec_.put_con_par(right.value_);\n    CPPAD_ASSERT_UNKNOWN( right_taddr > 0 );\n\n    // record the setting of this array element\n    if( var_right )\n    {   // resulting vector is a variable\n        vec_.ad_type_ = variable_enum;\n\n        // put operator arguments in tape\n        tape->Rec_.PutArg(vec_.offset_, ind_taddr, right_taddr);\n\n        if( con_ind | dyn_ind)\n        {   CPPAD_ASSERT_UNKNOWN( local::NumArg(local::StpvOp) == 3 );\n            CPPAD_ASSERT_UNKNOWN( local::NumRes(local::StpvOp) == 0 );\n\n            // put operator in the tape, ind_ is parameter, right is variable\n            tape->Rec_.PutOp(local::StpvOp);\n\n        }\n        else\n        {   CPPAD_ASSERT_UNKNOWN( var_ind );\n            CPPAD_ASSERT_UNKNOWN( local::NumArg(local::StvvOp) == 3 );\n            CPPAD_ASSERT_UNKNOWN( local::NumRes(local::StvvOp) == 0 );\n\n            // put operator in the tape, ind_ is variable, right is variable\n            tape->Rec_.PutOp(local::StvvOp);\n        }\n    }\n    else\n    {\n        // put operator arguments in tape\n        tape->Rec_.PutArg(vec_.offset_, ind_taddr, right_taddr);\n\n        // record the setting of this array element\n        if( con_ind | dyn_ind )\n        {   CPPAD_ASSERT_UNKNOWN( local::NumArg(local::StppOp) == 3 );\n            CPPAD_ASSERT_UNKNOWN( local::NumRes(local::StppOp) == 0 );\n\n            // put operator in the tape, ind_ is parameter, right is parameter\n            tape->Rec_.PutOp(local::StppOp);\n        }\n        else\n        {   CPPAD_ASSERT_UNKNOWN( local::NumArg(local::StvpOp) == 3 );\n            CPPAD_ASSERT_UNKNOWN( local::NumRes(local::StvpOp) == 0 );\n\n            // put operator in the tape, ind_ is variable, right is parameter\n            tape->Rec_.PutOp(local::StvpOp);\n        }\n    }\n}\ntemplate <class Base>\nvoid VecAD_reference<Base>::operator=(const Base &right)\n{   *this = AD<Base>(right); }\n//\ntemplate <class Base>\nvoid VecAD_reference<Base>::operator=\n(const VecAD_reference<Base> &right)\n{   *this = right.ADBase(); }\n//\ntemplate <class Base>\nvoid VecAD_reference<Base>::operator=(int right)\n{   *this = Base(right); }\n// ---------------------------------------------------------------------------\n\n} // END_CPPAD_NAMESPACE\n\n// preprocessor symbols that are local to this file\n# undef CPPAD_VEC_AD_COMP_ASSIGN\n\n# endif\n"
  },
  {
    "path": "include/cppad/core/zdouble.hpp",
    "content": "# ifndef CPPAD_CORE_ZDOUBLE_HPP\n# define CPPAD_CORE_ZDOUBLE_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin zdouble app}\nzdouble: An AD Base Type With Absolute Zero\n###########################################\n\nDeprecated 2015-09-26\n*********************\nUse the function :ref:`azmul-name` instead.\n\nAbsolute Zero\n*************\nThe ``zdouble`` class acts like the ``double`` type\nwith the added property that zero times any value is zero.\nThis includes zero time :ref:`nan-name` and zero times infinity.\nIn addition, zero divided by any value and any value times zero\nare also zero.\n\nSyntax\n******\n\nConstructor and Assignment\n==========================\n\n| ``zdouble z``\n| ``zdouble z`` ( ``x`` )\n| ``zdouble z`` ( ``i`` )\n| *z1* *op* *x*\n\nwere *i* is a ``size_t`` or *long* or ``int`` ,\n*x* is a ``double`` or ``zdouble`` ,\nand *op* is ``=`` or ``+=`` or ``-=`` or ``*=``\nor ``/=-`` .\n\nComparison Operators\n====================\n\n| *b* = *z* *op* *x*\n| *b* = *x* *op* *z*\n\nwhere *b* is a ``bool`` object,\n*z* is a ``zdouble`` object,\n*x* is a ``double`` or ``zdouble`` object, and\n*op* is ``==`` , ``!=`` , ``<=`` , ``>=`` ,\n``<`` or ``>`` .\n\nArithmetic Operators\n====================\n\n| *z2* = *z1* *op* *x*\n| *z2* = *x* *op* *z1*\n\nwhere *z1* , *z2* are ``zdouble`` objects,\n*x* is a ``double`` or ``zdouble`` object, and\n*op* is ``+`` , ``-`` , ``*`` or ``/`` .\n\nStandard Math\n=============\n\n| *z2* = *fun* ( *z1* )\n| *z3* = ``pow`` ( *z1* , *z2* )\n\nwhere *z1* , *z2* , *z3* are ``zdouble`` objects and\n*fun* is a :ref:`unary_standard_math-name` function.\n\nNan\n===\nThere is a specialization of :ref:`nan-name` so that\n\n    ``z2`` = *nan* ( ``z1`` )\n\nreturns 'not a number' when *z1* has type ``zdouble`` .\nNote that this template function needs to be specialized because\n\n    ``zdouble`` (0.0) == ``zdouble`` (0.0) / ``zdouble`` (0.0)\n\nMotivation\n**********\n\nGeneral\n=======\nOften during computing (and more so in parallel computing) alternative\nvalues for an expression are computed and one of the alternatives\nis chosen using some boolean variable.\nThis is often represented by\n\n    *result* = *flag* * *value_if_true* + (1 ``-`` *flag* ) * *value_if_false*\n\nwhere *flag* is one for true and zero for false.\nThis representation does not work for ``double`` when the value\nbeing multiplied by zero is ``+inf`` , ``-inf`` , or ``nan`` .\n\nCppAD\n=====\nIn CppAD one can use\n:ref:`conditional expressions<CondExp-name>` to achieve the representation\n\n    *result* = *flag* * *value_if_true* + (1 ``-`` *flag* ) * *value_if_false*\n\nThis works fine except when there are\n:ref:`multiple levels of AD<mul_level-name>` ; e.g.,\nwhen using ``AD< AD<double> >`` .\nIn this case the corresponding AD function objects have type\n:ref:`ADFun\\< AD\\<double> ><fun_construct-name>` .\nWhen these AD function objects compute derivatives using\n:ref:`reverse-name` mode, the conditional expressions are represented use\nzeros to multiply the expression that is not used.\nUsing ``AD< AD<zdouble> >`` instead of ``AD< AD<double> >``\nmakes this representation work and fixes the problem.\n\nBase Type Requirements\n**********************\nThe type ``zdouble`` satisfies all of the CppAD\n:ref:`base type requirements<base_require-name>` .\n\n{xrst_end zdouble}\n*/\n# include <cppad/base_require.hpp>\n# include <cppad/utility/nan.hpp>\n\n/*!\n\\file zdouble.hpp\nDefine a class like double but with an absolute zero.\n*/\n\n/*!\n\\def CPPAD_ZDOUBLE_NORMAL_ASSIGN_OPERATOR(op)\nDefine a compound assignment member operator that functions the same\nas corresponding double operator.\n*/\n# define CPPAD_ZDOUBLE_NORMAL_ASSIGN_OPERATOR(op) \\\n    zdouble& operator op (const zdouble& z) \\\n    {   dbl_ op z.dbl_;                     \\\n        return *this;                       \\\n    }                                       \\\n    zdouble& operator op (const double& x)  \\\n    {   dbl_ op x;                          \\\n        return *this;                       \\\n    }\n\n/*!\n\\def CPPAD_ZDOUBLE_UNARY_OPERATOR(op)\nDefine a unary compound assignment member operator.\n*/\n# define CPPAD_ZDOUBLE_UNARY_OPERATOR(op) \\\n    zdouble operator op (void) const      \\\n    {   return zdouble( op dbl_ ); }\n\n/*!\n# define CPPAD_ZDOUBLE_NORMAL_BINARY_OPERATOR(op)\nDefine a binary arithmetic member operator that functions the same\nas corresponding double operator.\n*/\n# define CPPAD_ZDOUBLE_NORMAL_BINARY_OPERATOR(op) \\\n    zdouble operator op (const zdouble& z) const  \\\n    {   return zdouble( dbl_ op z.dbl_ ); }       \\\n    zdouble operator op (const double& x) const   \\\n    {   return zdouble( dbl_ op x ); }\n\n/*!\n\\def CPPAD_ZDOUBLE_COMPARE_OPERATOR(op)\nDefine a comparison member operator.\n*/\n# define CPPAD_ZDOUBLE_COMPARE_OPERATOR(op)   \\\n    bool operator op (const zdouble& z) const \\\n    {   return dbl_ op z.dbl_; }             \\\n    bool operator op (const double& x) const \\\n    {   return dbl_ op x; }\n\n/*!\n\\def CPPAD_ZDOUBLE_OTHER_BINARY_OPERATOR(op)\nDefine a binary arithmetic operator that is not a member because\nthe double operand is on the left.\n*/\n# define CPPAD_ZDOUBLE_OTHER_BINARY_OPERATOR(op) \\\n    inline zdouble operator op(const double& x, const zdouble& z) \\\n    {   return zdouble(x) op z; }\n\n/*!\n\\def CPPAD_ZDOUBLE_OTHER_COMPARE_OPERATOR(op, op_switch)\nDefine a comparison operator that is not a member because\nthe double operand is on the left.\nConvert it to the case where the double operand is on the right by\nby using op_switch instead of op.\n*/\n# define CPPAD_ZDOUBLE_OTHER_COMPARE_OPERATOR(op, op_switch) \\\n    inline bool operator op(const double& x, const zdouble& z)    \\\n    {   return z op_switch x; }\n\n/*!\n\\def CPPAD_ZDOUBLE_STD_MATH_FRIEND(fun)\nDeclare that a standard math function is a friend.\n*/\n# define CPPAD_ZDOUBLE_STD_MATH_FRIEND(fun) \\\n    friend zdouble fun(const zdouble& z);\n/*!\n\\def CPPAD_ZDOUBLE_STD_MATH(fun)\nDefine a standard math function.\n*/\n# define CPPAD_ZDOUBLE_STD_MATH(fun)        \\\n    inline zdouble fun(const zdouble& z )    \\\n    {   return zdouble( std::fun(z.dbl_) ); }\n\nnamespace CppAD { // CPPAD_BEGIN_NAMESPACDE\n\n\n/*!\nClass that is like double, except that it has an absolute zero.\n*/\nclass zdouble {\n    /*!\n    For zdouble objects z1, z2, and std::ostream os,\n    declare the following friends:\n    \\code\n        os << z1\n        Integer(z1)\n        fabs(z1)\n        pow(z1, z2)\n        fabs_geq(z1, z2)\n        fun(z1)\n    \\endcode\n    where fun is any of the standard math unary functions.\n    */\n    friend std::ostream& operator << (std::ostream &os, const zdouble& z);\n    friend int Integer(const zdouble& z);\n    friend zdouble pow(const zdouble& x, const zdouble& y);\n    friend bool abs_geq(const zdouble& x, const zdouble& y);\n    //\n    CPPAD_ZDOUBLE_STD_MATH_FRIEND(acos)\n    CPPAD_ZDOUBLE_STD_MATH_FRIEND(asin)\n    CPPAD_ZDOUBLE_STD_MATH_FRIEND(atan)\n    CPPAD_ZDOUBLE_STD_MATH_FRIEND(cos)\n    CPPAD_ZDOUBLE_STD_MATH_FRIEND(cosh)\n    CPPAD_ZDOUBLE_STD_MATH_FRIEND(exp)\n    CPPAD_ZDOUBLE_STD_MATH_FRIEND(fabs)\n    CPPAD_ZDOUBLE_STD_MATH_FRIEND(log)\n    CPPAD_ZDOUBLE_STD_MATH_FRIEND(log10)\n    CPPAD_ZDOUBLE_STD_MATH_FRIEND(sin)\n    CPPAD_ZDOUBLE_STD_MATH_FRIEND(sinh)\n    CPPAD_ZDOUBLE_STD_MATH_FRIEND(sqrt)\n    CPPAD_ZDOUBLE_STD_MATH_FRIEND(tan)\n    CPPAD_ZDOUBLE_STD_MATH_FRIEND(tanh)\n    //\n    CPPAD_ZDOUBLE_STD_MATH_FRIEND(asinh)\n    CPPAD_ZDOUBLE_STD_MATH_FRIEND(acosh)\n    CPPAD_ZDOUBLE_STD_MATH_FRIEND(atanh)\n    CPPAD_ZDOUBLE_STD_MATH_FRIEND(erf)\n    CPPAD_ZDOUBLE_STD_MATH_FRIEND(erfc)\n    CPPAD_ZDOUBLE_STD_MATH_FRIEND(expm1)\n    CPPAD_ZDOUBLE_STD_MATH_FRIEND(log1p)\n    //\nprivate:\n    /// The value for this object\n    double dbl_;\npublic:\n    /// Default constructor\n    zdouble(void)\n    : dbl_()\n    { }\n    /// Copy constructor\n    zdouble(const zdouble& z)\n    : dbl_(z.dbl_)\n    { }\n    /// Constructor from double\n    zdouble(const double& dbl)\n    : dbl_(dbl)\n    { }\n    /// Constructor from size_t\n    zdouble(const size_t& i)\n    : dbl_( double(i) )\n    { }\n    /// Constructor from long\n    zdouble(const long& i)\n    : dbl_( double(i) )\n    { }\n    /// Constructor from int\n    zdouble(const int& i)\n    : dbl_( double(i) )\n    { }\n    //\n    /// Destructor\n    ~zdouble(void)\n    { }\n    //\n    /// Assignment from zdouble\n    zdouble& operator=(const zdouble& z)\n    {   dbl_ = z.dbl_;\n        return *this;\n    }\n    /// Assignment from double\n    zdouble& operator=(const double& dbl)\n    {   dbl_ = dbl;\n        return *this;\n    }\n    //\n    /// Normal compound assignment\n    CPPAD_ZDOUBLE_NORMAL_ASSIGN_OPERATOR(+=)\n    /// Normal compound assignment\n    CPPAD_ZDOUBLE_NORMAL_ASSIGN_OPERATOR(-=)\n    /// Normal unary operator\n    CPPAD_ZDOUBLE_UNARY_OPERATOR(+)\n    /// Normal unary operator\n    CPPAD_ZDOUBLE_UNARY_OPERATOR(-)\n    /// Normal compare operator\n    CPPAD_ZDOUBLE_COMPARE_OPERATOR(==)\n    /// Normal compare operator\n    CPPAD_ZDOUBLE_COMPARE_OPERATOR(!=)\n    /// Normal compare operator\n    CPPAD_ZDOUBLE_COMPARE_OPERATOR(<=)\n    /// Normal compare operator\n    CPPAD_ZDOUBLE_COMPARE_OPERATOR(>=)\n    /// Normal compare operator\n    CPPAD_ZDOUBLE_COMPARE_OPERATOR(<)\n    /// Normal compare operator\n    CPPAD_ZDOUBLE_COMPARE_OPERATOR(>)\n    //\n    /// Normal binary arithmetic operator\n    CPPAD_ZDOUBLE_NORMAL_BINARY_OPERATOR(+)\n    /// Normal binary arithmetic operator\n    CPPAD_ZDOUBLE_NORMAL_BINARY_OPERATOR(-)\n    //\n    /// Binary arithmetic * with absolute zero\n    zdouble operator * (const zdouble& z) const\n    {   bool zero = (dbl_ == 0.0) || (z.dbl_ == 0.0);\n        return zdouble( zero ? 0.0 : (dbl_ * z.dbl_) );\n    }\n    /// Binary arithmetic * with absolute zero\n    zdouble operator * (const double& x) const\n    {   bool zero = (dbl_ == 0.0) || (x == 0.0);\n        return zdouble( zero ? 0.0 : (dbl_ * x) );\n    }\n    /// Binary arithmetic / with absolute zero\n    zdouble operator / (const zdouble& z) const\n    {   bool zero = (dbl_ == 0.0);\n        return zdouble( zero ? 0.0 : (dbl_ / z.dbl_) );\n    }\n    /// Binary arithmetic / with absolute zero\n    zdouble operator / (const double& x) const\n    {   bool zero = (dbl_ == 0.0);\n        return zdouble( zero ? 0.0 : (dbl_ / x) );\n    }\n    //\n    /// Compute assignment *= with absolute zero\n    zdouble& operator *= (const zdouble& z)\n    {   bool zero = (dbl_ == 0.0) || (z.dbl_ == 0.0);\n        zero ? (dbl_ = 0.0) : (dbl_ *= z.dbl_);\n        return *this;\n    }\n    /// Compute assignment *= with absolute zero\n    zdouble& operator *= (const double& x)\n    {   bool zero = (dbl_ == 0.0) || (x == 0.0);\n        zero ? (dbl_ = 0.0) : (dbl_ *= x);\n        return *this;\n    }\n    //\n    /// Compute assignment /= with absolute zero\n    zdouble& operator /= (const zdouble& z)\n    {   bool zero = (dbl_ == 0.0);\n        zero ? (dbl_ = 0.0) : (dbl_ /= z.dbl_);\n        return *this;\n    }\n    /// Compute assignment /= with absolute zero\n    zdouble& operator /= (const double& x)\n    {   bool zero = (dbl_ == 0.0);\n        zero ? (dbl_ = 0.0) : (dbl_ /= x);\n        return *this;\n    }\n};\n// BEGIN nan\n/// Must specialize CppAD::nan because zdouble 0/0 is not nan.\ntemplate <> inline\nzdouble nan<zdouble>(const zdouble& zero)\n{\n    return zdouble( std::numeric_limits<double>::quiet_NaN() );\n}\n// END nan\n//\n/// Normal non-member compare operator\nCPPAD_ZDOUBLE_OTHER_COMPARE_OPERATOR(==, ==)\n/// Normal non-member compare operator\nCPPAD_ZDOUBLE_OTHER_COMPARE_OPERATOR(!=, !=)\n/// Normal non-member compare operator\nCPPAD_ZDOUBLE_OTHER_COMPARE_OPERATOR(<=, >=)\n/// Normal non-member compare operator\nCPPAD_ZDOUBLE_OTHER_COMPARE_OPERATOR(>=, <=)\n/// Normal non-member compare operator\nCPPAD_ZDOUBLE_OTHER_COMPARE_OPERATOR(<,  >)\n/// Normal non-member compare operator\nCPPAD_ZDOUBLE_OTHER_COMPARE_OPERATOR(>,  <)\n//\n/// Normal binary arithmetic operator\nCPPAD_ZDOUBLE_OTHER_BINARY_OPERATOR(+)\n/// Normal binary arithmetic operator\nCPPAD_ZDOUBLE_OTHER_BINARY_OPERATOR(-)\n/// Binary arithmetic operator with absolute zero\nCPPAD_ZDOUBLE_OTHER_BINARY_OPERATOR(*)\n/// Binary arithmetic operator with absolute zero\nCPPAD_ZDOUBLE_OTHER_BINARY_OPERATOR(/)\n// -------------------------------------------------------------------------\n// Base type requirements\n// -------------------------------------------------------------------------\n\n/// Base type requirement: CondExpOp\ninline zdouble CondExpOp(\n    enum CompareOp     cop          ,\n    const zdouble&       left         ,\n    const zdouble&       right        ,\n    const zdouble&       exp_if_true  ,\n    const zdouble&       exp_if_false )\n{   return CondExpTemplate(cop, left, right, exp_if_true, exp_if_false);\n}\n\n/// Base type requirement: CondExpRel\nCPPAD_COND_EXP_REL(zdouble)\n\n/// Base type requirement: EqualOpSeq\ninline bool EqualOpSeq(const zdouble& x, const zdouble& y)\n{   return x == y; }\n\n/// Base type requirement: Identical\ninline bool IdenticalCon(const zdouble& x)\n{   return true; }\ninline bool IdenticalZero(const zdouble& x)\n{   return (x == 0.0); }\ninline bool IdenticalOne(const zdouble& x)\n{   return (x == 1.); }\ninline bool IdenticalEqualCon(const zdouble& x, const zdouble& y)\n{   return (x == y); }\n\n/// Base type requirement: output operator\ninline std::ostream& operator << (std::ostream &os, const zdouble& z)\n{   os << z.dbl_;\n    return os;\n}\n\n/// Base type requirement: Integer\ninline int Integer(const zdouble& x)\n{   return static_cast<int>(x.dbl_); }\n\n/// Base type requirement: azmul\ninline zdouble azmul(const zdouble& x, const zdouble& y)\n{   return x * y; }\n\n/// Base type requirement: Ordered\ninline bool GreaterThanZero(const zdouble& x)\n{   return x > 0.0; }\ninline bool GreaterThanOrZero(const zdouble& x)\n{   return x >= 0.0; }\ninline bool LessThanZero(const zdouble& x)\n{   return x < 0.0; }\ninline bool LessThanOrZero(const zdouble& x)\n{   return x <= 0.0; }\ninline bool abs_geq(const zdouble& x, const zdouble& y)\n{   return std::fabs(x.dbl_) >= std::fabs(y.dbl_); }\n\n/// Normal standard math function\nCPPAD_ZDOUBLE_STD_MATH(acos)\n/// Normal standard math function\nCPPAD_ZDOUBLE_STD_MATH(asin)\n/// Normal standard math function\nCPPAD_ZDOUBLE_STD_MATH(atan)\n/// Normal standard math function\nCPPAD_ZDOUBLE_STD_MATH(cos)\n/// Normal standard math function\nCPPAD_ZDOUBLE_STD_MATH(cosh)\n/// Normal standard math function\nCPPAD_ZDOUBLE_STD_MATH(exp)\n/// Normal standard math function\nCPPAD_ZDOUBLE_STD_MATH(fabs)\n/// Normal standard math function\nCPPAD_ZDOUBLE_STD_MATH(log)\n/// Normal standard math function\nCPPAD_ZDOUBLE_STD_MATH(log10)\n/// Normal standard math function\nCPPAD_ZDOUBLE_STD_MATH(sin)\n/// Normal standard math function\nCPPAD_ZDOUBLE_STD_MATH(sinh)\n/// Normal standard math function\nCPPAD_ZDOUBLE_STD_MATH(sqrt)\n/// Normal standard math function\nCPPAD_ZDOUBLE_STD_MATH(tan)\n/// Normal standard math function\nCPPAD_ZDOUBLE_STD_MATH(tanh)\n//\n/// C++2011 standard math function\nCPPAD_ZDOUBLE_STD_MATH(asinh)\n/// C++2011 standard math function\nCPPAD_ZDOUBLE_STD_MATH(acosh)\n/// C++2011 standard math function\nCPPAD_ZDOUBLE_STD_MATH(atanh)\n/// C++2011 standard math function\nCPPAD_ZDOUBLE_STD_MATH(erf)\n/// C++2011 standard math function\nCPPAD_ZDOUBLE_STD_MATH(erfc)\n/// C++2011 standard math function\nCPPAD_ZDOUBLE_STD_MATH(expm1)\n/// C++2011 standard math function\nCPPAD_ZDOUBLE_STD_MATH(log1p)\n\n/// Base type requirement: abs\ninline zdouble abs(const zdouble& x)\n{   return fabs(x); }\n\n/// Base type requirement: sign\ninline zdouble sign(const zdouble& x)\n{   if( x > 0.0 )\n        return zdouble(1.);\n    if( x == 0.0 )\n        return zdouble(0.0);\n    return zdouble(-1.);\n}\n\n/// Base type requirement: pow\ninline zdouble pow(const zdouble& x, const zdouble& y)\n{ return std::pow(x.dbl_, y.dbl_); }\n\n/// Base type requirement: limits\nCPPAD_NUMERIC_LIMITS(double, zdouble)\n\n} // CPPAD_END_NAMESPACE\n\n/// undef all macros defined in this file\n# undef CPPAD_ZDOUBLE_NORMAL_ASSIGN_OPERATOR\n# undef CPPAD_ZDOUBLE_UNARY_OPERATOR\n# undef CPPAD_ZDOUBLE_NORMAL_BINARY_OPERATOR\n# undef CPPAD_ZDOUBLE_COMPARE_OPERATOR\n# undef CPPAD_ZDOUBLE_OTHER_BINARY_OPERATOR\n# undef CPPAD_ZDOUBLE_OTHER_COMPARE_OPERATOR\n# undef CPPAD_ZDOUBLE_STD_MATH_FRIEND\n# undef CPPAD_ZDOUBLE_STD_MATH\n\n# endif\n"
  },
  {
    "path": "include/cppad/cppad.hpp",
    "content": "# ifndef CPPAD_CPPAD_HPP\n# define CPPAD_CPPAD_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*!\n\\file cppad.hpp\n\\brief includes the entire CppAD package in the necessary order.\n\n\\namespace CppAD\n\\brief contains all the variables and functions defined by the CppAD package.\n*/\n\n# include <cppad/base_require.hpp> // all base type requirements\n// ---------------------------------------------------------------------------\n// CppAD general purpose library routines (can be included separately)\n# include <cppad/utility.hpp>\n// --------------------------------------------------------------------------\n// System routines that can be used by rest of CppAD with out including\n\n# include <cstddef>\n# include <iostream>\n# include <complex>\n# include <cmath>\n\n// ---------------------------------------------------------------------------\n// definitions needed by rest of includes\n\n// definitions that come from the installation\n# include <cppad/configure.hpp>\n\n// definitions that are local to the CppAD include files\n# include <cppad/local/define.hpp>\n\n// vectors used with CppAD\n# include <cppad/core/testvector.hpp>\n\n// Declare classes and functions that are used before defined\n# include <cppad/local/declare_ad.hpp>\n\n// ---------------------------------------------------------------------------\n// declare the AD<Base> template class\n\n# include <cppad/core/ad.hpp>\n\n// ---------------------------------------------------------------------------\n\n# include <cppad/core/user_ad.hpp>  // AD class methods available to the user\n// tape that tape for AD<Base> acts as a user of Base operations\n// so user_ad.hpp must come before op.hpp\n# include <cppad/local/var_op/var_op.hpp>       // executes taped operations\n# include <cppad/core/ad_fun.hpp>   // ADFun objects\n//\n// Putting these includes in ad_fun.hpp leads to circular including; i.e,\n// a file needs to include itself and the include guard stops it.\n# include <cppad/local/val_graph/fun2val.hpp>\n# include <cppad/local/val_graph/val2fun.hpp>\n\n// ---------------------------------------------------------------------------\n// library routines that require the rest of CppAD\n# include <cppad/core/lu_ratio.hpp>\n# include <cppad/core/bender_quad.hpp>\n# include <cppad/core/opt_val_hes.hpp>\n# include <cppad/local/graph/cpp_graph_op.hpp>\n# include <cppad/local/graph/json_lexer.hpp>\n# if CPPAD_HAS_IPOPT\n# include <cppad/ipopt/solve.hpp>\n# endif\n\n// undo definitions in Define.h\n# include <cppad/core/undef.hpp>\n\n# endif\n"
  },
  {
    "path": "include/cppad/example/atomic_four/lin_ode/base_solver.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_ATOMIC_FOUR_LIN_ODE_BASE_SOLVER_HPP\n# define CPPAD_EXAMPLE_ATOMIC_FOUR_LIN_ODE_BASE_SOLVER_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_four_lin_ode_base_solver.hpp}\n\nAtomic Linear ODE: Example Implementation\n#########################################\n\nSyntax\n******\n| *lin_ode* . ``base_solver`` (\n| |tab| *r* , *step* , *pattern* , *transpose* , *x* , *y*\n| )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_PROTOTYPE\n    // END_PROTOTYPE\n}\n\nNotation\n********\nWe use the notation:\n:ref:`atomic_four_lin_ode@call_id`\n:ref:`atomic_four_lin_ode@r`\n:ref:`atomic_four_lin_ode@pattern`\n:ref:`atomic_four_lin_ode@transpose`\n:ref:`atomic_four_lin_ode@pattern@nnz` ,\n:ref:`atomic_four_lin_ode@pattern@row` ,\n:ref:`atomic_four_lin_ode@pattern@col` ,\n:ref:`atomic_four_lin_ode@x` ,\n:ref:`atomic_four_lin_ode@x@n` ,\n:ref:`atomic_four_lin_ode@x@A(x)` ,\n:ref:`atomic_four_lin_ode@x@b(x)` ,\n:ref:`atomic_four_lin_ode@y(x)` ,\n:ref:`atomic_four_lin_ode@y(x)@m` ,\n:ref:`atomic_four_lin_ode@vk(x)`\n\nRosen34\n*******\nThis example uses one step of\n:ref:`rosen34-name` ODE solver.\nAny initial value ODE solver, with any number of steps, could be used.\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end atomic_four_lin_ode_base_solver.hpp}\n*/\n// BEGIN C++\n# include <cppad/example/atomic_four/lin_ode/lin_ode.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n//\n// base_solver\n// BEGIN_PROTOTYPE\ntemplate <class Base>\nvoid atomic_lin_ode<Base>::base_solver(\n    const Base&                    r         ,\n    const Base&                    step      ,\n    const sparse_rc&               pattern   ,\n    const bool&                    transpose ,\n    const CppAD::vector<Base>&     x         ,\n    CppAD::vector<Base>&           y         )\n// END_PROTOTYPE\n{\n    class Fun {\n    private:\n        const sparse_rc&           pattern_;\n        const bool&                transpose_;\n        const CppAD::vector<Base>& x_;\n    public:\n        Fun(\n            const sparse_rc&           pattern   ,\n            const bool&                transpose ,\n            const CppAD::vector<Base>& x         )\n        : pattern_(pattern), transpose_(transpose), x_(x)\n        { }\n        void Ode(\n            const Base&                t ,\n            const CppAD::vector<Base>& z ,\n            CppAD::vector<Base>&       f )\n        {   size_t m   = z.size();\n            size_t nnz = pattern_.nnz();\n            CPPAD_ASSERT_UNKNOWN( f.size() == m );\n            CPPAD_ASSERT_UNKNOWN( x_.size() == nnz + m );\n            CPPAD_ASSERT_UNKNOWN( pattern_.nr() == m );\n            CPPAD_ASSERT_UNKNOWN( pattern_.nc() == m );\n            //\n            for(size_t i = 0; i < m; ++i)\n                f[i] = Base(0);\n            for(size_t k = 0; k < nnz; ++k)\n            {   size_t i = pattern_.row()[k];\n                size_t j = pattern_.col()[k];\n                if( transpose_ )\n                    std::swap(i, j);\n                f[i] += x_[k] * z[j];\n            }\n        }\n        void Ode_ind(\n            const Base&                t   ,\n            const CppAD::vector<Base>& z   ,\n            CppAD::vector<Base>&       f_t )\n        {   size_t m   = z.size();\n# ifndef NDEBUG\n            size_t nnz = pattern_.nnz();\n            CPPAD_ASSERT_UNKNOWN( f_t.size() == m );\n            CPPAD_ASSERT_UNKNOWN( x_.size() == nnz + m );\n            CPPAD_ASSERT_UNKNOWN( pattern_.nr() == m );\n            CPPAD_ASSERT_UNKNOWN( pattern_.nc() == m );\n# endif\n            //\n            for(size_t i = 0; i < m; ++i)\n                f_t[i] = Base(0);\n        }\n        void Ode_dep(\n            const Base&                t   ,\n            const CppAD::vector<Base>& z   ,\n            CppAD::vector<Base>&       f_x )\n        {   size_t m   = z.size();\n            size_t nnz = pattern_.nnz();\n            CPPAD_ASSERT_UNKNOWN( f_x.size() == m * m );\n            CPPAD_ASSERT_UNKNOWN( x_.size() == nnz + m );\n            CPPAD_ASSERT_UNKNOWN( pattern_.nr() == m );\n            CPPAD_ASSERT_UNKNOWN( pattern_.nc() == m );\n            //\n            for(size_t i = 0; i < m * m; ++i)\n                f_x[i] = Base(0);\n            for(size_t k = 0; k < nnz; ++k)\n            {   size_t i = pattern_.row()[k];\n                size_t j = pattern_.col()[k];\n                if( transpose_ )\n                    std::swap(i, j);\n                f_x[i * m + j] = x_[k];\n            }\n        }\n    };\n    //\n    // nnz\n    size_t nnz = pattern.nnz();\n    // m\n    size_t m     = y.size();\n    CPPAD_ASSERT_UNKNOWN( x.size() == nnz + m );\n    //\n    // fun\n    Fun fun(pattern, transpose, x);\n    //\n    // y\n    Base ti       = Base(0.0);\n    Base tf       = r;\n    size_t n_step = 1;\n    if( step < abs(r) )\n        n_step = size_t( Integer( abs(r) / step ) ) + 1;\n    CppAD::vector<Base> zi(m), e(m);\n    for(size_t j = 0; j < m; ++j)\n        zi[j] = x[nnz + j];\n    y = CppAD::Rosen34(fun, n_step, ti, tf, zi, e);\n    return;\n}\n} // END_CPPAD_NAMESPACE\n// END C++\n# endif\n"
  },
  {
    "path": "include/cppad/example/atomic_four/lin_ode/for_type.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_ATOMIC_FOUR_LIN_ODE_FOR_TYPE_HPP\n# define CPPAD_EXAMPLE_ATOMIC_FOUR_LIN_ODE_FOR_TYPE_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_four_lin_ode_for_type.hpp}\n\nAtomic Linear ODE Forward Type Calculation: Example Implementation\n##################################################################\n\nPurpose\n*******\nThe ``for_type`` routine overrides the virtual functions\nused by the atomic_four base; see\n:ref:`for_type<atomic_four_for_type-name>` .\n\nNotation\n********\nWe use the notation:\n:ref:`atomic_four_lin_ode@call_id`\n:ref:`atomic_four_lin_ode@r`\n:ref:`atomic_four_lin_ode@pattern`\n:ref:`atomic_four_lin_ode@transpose`\n:ref:`atomic_four_lin_ode@pattern@nnz` ,\n:ref:`atomic_four_lin_ode@pattern@row` ,\n:ref:`atomic_four_lin_ode@pattern@col` ,\n:ref:`atomic_four_lin_ode@x` ,\n:ref:`atomic_four_lin_ode@x@n` ,\n:ref:`atomic_four_lin_ode@x@A(x)` ,\n:ref:`atomic_four_lin_ode@x@b(x)` ,\n:ref:`atomic_four_lin_ode@y(x)` ,\n:ref:`atomic_four_lin_ode@y(x)@m` ,\n:ref:`atomic_four_lin_ode@vk(x)` ,\nand the following additional notation:\n\nT(s)\n====\nWe use :math:`\\R{T} ( s )` to denote the ad_type of a scalar value :math:`s`.\nThere are four possible\n:ref:`ad_types<atomic_four_for_type@ad_type>` :\nidentical_zero, constant, dynamic, and variable in that order.\n\nTheory\n******\nThis routine must calculate the following value for\n:math:`i = 0, \\ldots, m-1`; see :ref:`atomic_four_lin_ode@y(x)@m` :\n\n.. math::\n\n    \\R{T} [ y_i (x) ] = \\max_k \\R{T} [  v_i^k (x) ]\n\nThe type :math:`\\R{T} [ v_i^0 (x) ] = \\R{T}[ b_i (x) ]`.\nThis is easy to calculate given the type of the components of *x* ;\nsee :ref:`atomic_four_lin_ode@x@b(x)` .\nFurthermore, for :math:`k > 0`\n\n.. math::\n\n    v_i^k (x)\n    =\n    \\frac{r}{k} \\sum_{j=0}^{m-1} A_{i,j} (x) v_j^{k-1} (x)\n\n.. math::\n\n    \\R{T} [ v_i^k (x) ]\n    =\n    \\max_j \\R{T} [ A_{i,j} (x) v_j^{k-1} (x) ]\n\n.. math::\n\n    \\R{T} [ A_{i,j} (x) v_j^k (x) ]\n    =\n    \\left\\{ \\begin{array}{ll}\n        \\R{identical\\_zero} &\n        \\R{if} A_{i,j} (x) \\W{\\R{or}} v_j^{k-1} (x) \\W{\\R{is}} \\R{identical\\_zero}\n        \\\\\n        \\max\\{ \\R{T} [ A_{i,j} (x) ] \\W{,} \\R{T} [ v_j^{k-1} (x) ] \\} &\n        \\R{otherwise}\n    \\end{array} \\right.\n\nIf :math:`A_{i,j} (x)` is not in the sparsity\n:ref:`atomic_four_lin_ode@pattern` , it is identically zero.\nFurthermore we are allowing for the case where\n:math:`A_{i,j} (x)` is in the pattern and it is identically zero; i.e.,\nthe sparsity pattern is not efficient as it could be.\nThe type :math:`\\R{T} [ A_{i,j} (x) ]` for components in the sparsity pattern\nis easy to calculate given the type of the components of *x* ;\nsee :ref:`atomic_four_lin_ode@x@A(x)` .\nSuppose :math:`\\ell` is such that for all :math:`i`\n\n.. math::\n\n    \\R{T} [ v_i^\\ell (x) ] \\leq \\max_{k < \\ell} \\R{T} [ v_i^k (x) ]\n\nIt follows that\n\n.. math::\n\n    \\R{T} [ v_j^{\\ell+1} (x) ]  = \\max_j \\R{T} [ A_{i,j} (x) v_j^\\ell (x) ]\n\n.. math::\n\n    \\R{T} [ v_j^{\\ell+1} (x) ]\n    \\leq\n    \\max_{k < \\ell} \\max_j \\R{T} [ A_{i,j} (x) v_j^k (x) ]\n\n.. math::\n\n    \\R{T} [ v_j^{\\ell+1} (x) ]\n    \\leq\n    \\max_{k < \\ell} \\R{T} [ v_i^k (x) ]\n\nFrom this it is clear that\n\n.. math::\n\n    \\R{T} [ y_i (x) ] = \\max_{k < \\ell} \\R{T} [  v_i^k (x) ]\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end atomic_four_lin_ode_for_type.hpp}\n*/\n// BEGIN C++\n# include <cppad/example/atomic_four/lin_ode/lin_ode.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n//\n// for_type override\ntemplate <class Base>\nbool atomic_lin_ode<Base>::for_type(\n    size_t                                     call_id     ,\n    const CppAD::vector<CppAD::ad_type_enum>&  type_x      ,\n    CppAD::vector<CppAD::ad_type_enum>&        type_y      )\n{\n    // pattern, transpose, nnz\n    Base      r;\n    Base      step;\n    sparse_rc pattern;\n    bool      transpose;\n    get(call_id, step, r, pattern, transpose);\n    size_t nnz = pattern.nnz();\n    //\n    // m\n    size_t m     = type_y.size();\n    CPPAD_ASSERT_UNKNOWN( pattern.nr() == m );\n    CPPAD_ASSERT_UNKNOWN( pattern.nc() == m );\n    //\n    // type_x\n    CPPAD_ASSERT_UNKNOWN( type_x.size() == nnz + m );\n    //\n    // type_y[i] = type_b[i]\n    // type_y[i] = max T[ v_i^k (x) ] for k = 0\n    for(size_t i = 0; i < m; ++i)\n        type_y[i] = type_x[nnz + i];\n    //\n    // change\n    // Did type_y change during the previous iteration of the while loop\n    bool change = true;\n    while(change)\n    {   change = false;\n        // we use k = 1, 2, ... to denote the pass through this loop\n        // type_y[i] = max q < k T[ v_i^q (x) ]\n        //\n        for(size_t p = 0; p < nnz; ++p)\n        {   size_t i = pattern.row()[p];\n            size_t j = pattern.col()[p];\n            if( transpose )\n                std::swap(i, j);\n            //\n            // type_y[i], change\n            if( type_x[p] != identical_zero_enum )\n            {   // A_ij (x) is not identically zero\n                if( type_y[j] > type_y[i] )\n                {   change = true;\n                    type_y[i] = type_y[j];\n                      }\n            }\n            //\n            // type_y[i], change\n            if( type_y[j] != identical_zero_enum )\n            {   // There is a q < k such that v_j^q (x) not identically zero\n                if( type_x[p] > type_y[i] )\n                {   change = true;\n                    type_y[i] = type_x[p];\n                }\n            }\n        }\n    }\n    return true;\n}\n} // END_CPPAD_NAMESPACE\n// END C++\n# endif\n"
  },
  {
    "path": "include/cppad/example/atomic_four/lin_ode/forward.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_ATOMIC_FOUR_LIN_ODE_FORWARD_HPP\n# define CPPAD_EXAMPLE_ATOMIC_FOUR_LIN_ODE_FORWARD_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_four_lin_ode_forward.hpp}\n\nAtomic Linear ODE Forward Mode: Example Implementation\n######################################################\n\nPurpose\n*******\nThe ``forward`` routine overrides the virtual functions\nused by the atomic_four base; see\n:ref:`forward<atomic_four_forward-name>` .\n\nTheory\n******\nSuppose we are given Taylor coefficients\n:math:`x^0`, :math:`x^1`, for\n:ref:`atomic_four_lin_ode@x` .\nThe zero order Taylor coefficient for\n:ref:`atomic_four_lin_ode@z(t, x)` solves\nthe following initial value ODE:\n\n.. math::\n\n    z_t^0 (t) = A^0 z(t) \\W{,} z^0 (0) = b^0\n\nNote that :math:`A^0` and :math:`b^0`\nare just certain components of :math:`x^0`; see\n:ref:`atomic_four_lin_ode@x@A(x)` and\n:ref:`atomic_four_lin_ode@x@b(x)` .\nThe first order Taylor coefficient for :math:`z(t, x)` solves\nthe following initial value ODE:\n\n.. math::\n\n    z_t^1 (t)\n    =\n    A^0 z^1 (t) + A^1 z^0 (t) \\W{,} z^1 (0) = b^1\n\nNote that :math:`A^1` and :math:`c^1`\nare just certain components of :math:`x^1`.\nWe can solve for :math:`z^1 (t)` using the following extended\ninitial value ODE:\n\n.. math::\n\n    \\left[ \\begin{array}{c}\n    z^0_t (t, x) \\\\\n    z^1_t (t, x)\n    \\end{array} \\right]\n    =\n    \\left[ \\begin{array}{cc}\n    A^0 & 0   \\\\\n    A^1 & A^0\n    \\end{array} \\right]\n    \\left[ \\begin{array}{c}\n    z^0 (t, x) \\\\\n    z^1 (t, x)\n    \\end{array} \\right]\n    \\; , \\;\n    \\left[ \\begin{array}{c}\n    z^0 (0, x) \\\\\n    z^1 (0, x)\n    \\end{array} \\right]\n    =\n    \\left[ \\begin{array}{c}\n    b^0 \\\\\n    b^1\n    \\end{array} \\right]\n\nextend_ode\n**********\nThe extended system above is created form the original system by the\n``extend_ode`` function defined below:\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end atomic_four_lin_ode_forward.hpp}\n*/\n// BEGIN C++\n# include <cppad/example/atomic_four/lin_ode/lin_ode.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n// ----------------------------------------------------------------------------\n// forward override for Base atomic linear ODE\ntemplate <class Base>\nbool atomic_lin_ode<Base>::forward(\n    size_t                                     call_id     ,\n    const CppAD::vector<bool>&                 select_y    ,\n    size_t                                     order_low   ,\n    size_t                                     order_up    ,\n    const CppAD::vector<Base>&                 taylor_x    ,\n    CppAD::vector<Base>&                       taylor_y    )\n{\n    // order_up\n    if( order_up > 1 )\n        return false;\n    //\n    // r, pattern, transpose, nnz\n    Base      r;\n    Base      step;\n    sparse_rc pattern;\n    bool      transpose;\n    get(call_id, r, step, pattern, transpose);\n# ifndef NDEBUG\n    size_t nnz = pattern.nnz();\n# endif\n    //\n    // q\n    size_t q = order_up + 1;\n    //\n    // m\n    CPPAD_ASSERT_UNKNOWN( taylor_y.size() % q == 0 );\n    size_t m = taylor_y.size() / q;\n    CPPAD_ASSERT_UNKNOWN( pattern.nr() == m );\n    CPPAD_ASSERT_UNKNOWN( pattern.nc() == m );\n    //\n    // taylor_x\n    CPPAD_ASSERT_UNKNOWN( taylor_x.size() == (nnz + m) * q );\n    //\n    // taylor_y\n    if( order_up == 0 )\n        base_solver(r, step, pattern, transpose, taylor_x, taylor_y);\n    else\n    {   CPPAD_ASSERT_UNKNOWN( order_up == 1 );\n        //\n        // pattern_extend, x_extend\n        sparse_rc           pattern_extend;\n        CppAD::vector<Base> x_extend;\n        extend_ode(pattern, transpose, taylor_x, pattern_extend, x_extend);\n        //\n        // y_extend\n        size_t m_extend = pattern_extend.nr();\n        CppAD::vector<Base> y_extend(m_extend);\n        bool transpose_extend = false;\n        base_solver(\n            r, step, pattern_extend, transpose_extend, x_extend, y_extend\n        );\n        //\n        // taylor_y\n        if( order_low == 0 )\n        {   for(size_t i = 0; i < m; ++i)\n                taylor_y[i * q + 0] = y_extend[i];\n        }\n        for(size_t i = 0; i < m; ++i)\n            taylor_y[i * q + 1] = y_extend[m + i];\n    }\n    //\n    return true;\n}\n// ----------------------------------------------------------------------------\n// forward override for AD<Base> atomic linear ODE\ntemplate <class Base>\nbool atomic_lin_ode<Base>::forward(\n    size_t                                     call_id     ,\n    const CppAD::vector<bool>&                 select_y    ,\n    size_t                                     order_low   ,\n    size_t                                     order_up    ,\n    const CppAD::vector< CppAD::AD<Base> >&    ataylor_x   ,\n    CppAD::vector< CppAD::AD<Base> >&          ataylor_y   )\n{   //\n    // ad_base\n    typedef CppAD::AD<Base> ad_base;\n    //\n    // order_up\n    if( order_up > 1 )\n        return false;\n    //\n    // r, pattern, transpose, nnz\n    Base            r;\n    Base            step;\n    sparse_rc       pattern;\n    bool            transpose;\n    get(call_id, r, step, pattern, transpose);\n# ifndef NDEBUG\n    size_t nnz = pattern.nnz();\n# endif\n    //\n    // q\n    size_t q = order_up + 1;\n    //\n    // m\n    CPPAD_ASSERT_UNKNOWN( ataylor_y.size() % q == 0 );\n    size_t m = ataylor_y.size() / q;\n    //\n    // ataylor_x\n    CPPAD_ASSERT_UNKNOWN( ataylor_x.size() == (nnz + m) * q );\n    //\n    // ataylor_y\n    if( order_up == 0 )\n        (*this)(call_id, ataylor_x, ataylor_y);\n    else\n    {   CPPAD_ASSERT_UNKNOWN( order_up == 1 );\n        //\n        // pattern_extend, x_extend\n        sparse_rc              pattern_extend;\n        CppAD::vector<ad_base> ax_extend;\n        extend_ode(pattern, transpose, ataylor_x, pattern_extend, ax_extend);\n        //\n        // call_id_2\n        bool transpose_extend = false;\n        size_t call_id_2 = set(r, step, pattern_extend, transpose_extend);\n        //\n        // ay_extend\n        size_t m_extend = pattern_extend.nr();\n        CppAD::vector<ad_base> ay_extend(m_extend);\n        (*this)(call_id_2, ax_extend, ay_extend);\n        //\n        // ataylor_y\n        if( order_low == 0 )\n        {   for(size_t i = 0; i < m; ++i)\n                ataylor_y[i * q + 0] = ay_extend[i];\n        }\n        for(size_t i = 0; i < m; ++i)\n            ataylor_y[i * q + 1] = ay_extend[m + i];\n    }\n    //\n    return true;\n}\n// ---------------------------------------------------------------------------\n// extend_ode\n/*\n[   z_t^0 (t, x^0 )    ] = [ A^0   0    ] * [   z^0 (t, x^0 )    ]\n[ z_t^1 (t, x^0, x^1 ) ]   [ A^1   A^0  ]   [ z^1 (t, x^0, x^1 ) ]\n\n[   z^0 (0, x^0 )    ] = [ b^0 ]\n[ z^1 (0, x^0, x^1 ) ]   [ b^1 ]\n*/\ntemplate <class Base>\ntemplate <class Float>\nvoid atomic_lin_ode<Base>::extend_ode(\n    const CppAD::sparse_rc< CppAD::vector<size_t> >&    pattern         ,\n    const bool&                                         transpose       ,\n    const CppAD::vector<Float>&                         taylor_x        ,\n    CppAD::sparse_rc< CppAD::vector<size_t> >&          pattern_extend  ,\n    CppAD::vector<Float>&                               x_extend        )\n{   //\n    // m\n    size_t m   = pattern.nr();\n    size_t nnz = pattern.nnz();\n    CPPAD_ASSERT_UNKNOWN( pattern.nc() == m );\n    //\n    // q\n    size_t q = 2;\n    CPPAD_ASSERT_UNKNOWN( taylor_x.size() == q * (nnz + m) );\n    //\n    // m_extend\n    size_t m_extend   = 2 * m;\n    size_t nnz_extend = 3 * nnz;\n    //\n    // pattern_extend, x_extend\n    pattern_extend.resize(m_extend, m_extend, nnz_extend);\n    x_extend.resize(nnz_extend + m_extend);\n    for(size_t k = 0; k < nnz; ++k)\n    {   size_t i = pattern.row()[k];\n        size_t j = pattern.col()[k];\n        if( transpose )\n            std::swap(i, j);\n        //\n        // A^0_ij\n        Float A0ij = taylor_x[k * q + 0];\n        //\n        // A^1_ij\n        Float A1ij = taylor_x[k * q + 1];\n        //\n        // upper diagonal\n        pattern_extend.set(3 * k + 0, i, j);\n        x_extend[3 * k + 0] = A0ij;\n        //\n        // lower left\n        pattern_extend.set(3 * k + 1, m + i, j);\n        x_extend[3 * k + 1] = A1ij;\n        //\n        // lower diagonal\n        pattern_extend.set(3 * k + 2, m + i, m + j);\n        x_extend[3 * k + 2] = A0ij;\n    }\n    for(size_t i = 0; i < m; ++i)\n    {   // b^0_i\n        x_extend[nnz_extend + i]     = taylor_x[ (nnz + i) * q + 0 ];\n        // b^1_i\n        x_extend[nnz_extend + m + i] = taylor_x[ (nnz + i) * q + 1 ];\n    }\n    return;\n}\n} // END_CPPAD_NAMESPACE\n// END C++\n# endif\n"
  },
  {
    "path": "include/cppad/example/atomic_four/lin_ode/get.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_ATOMIC_FOUR_LIN_ODE_GET_HPP\n# define CPPAD_EXAMPLE_ATOMIC_FOUR_LIN_ODE_GET_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_four_lin_ode_get.hpp}\n\natomic_lin_ode Get Routine: Example Implementation\n##################################################\n\nSyntax\n******\n| *lin_ode* . ``get`` ( *call_id* , *r* , *step* , *pattern* , *transpose* )\n\nPrototype\n*********\n{xrst_literal\n    include/cppad/example/atomic_four/lin_ode/lin_ode.hpp\n    // BEGIN sparse_rc_type\n    // END sparse_rc_type\n}\n{xrst_literal\n    // BEGIN PROTOTYPE\n    // END PROTOTYPE\n}\n\nPurpose\n*******\nRetrieves the auxiliary information for a an atomic operation that computes\nthe solution of a linear ODE.\n\ncall_id\n*******\nThis input argument identifies the auxiliary information for this ODE.\n\nr\n*\nThis output argument is the final value for the variable that the ODE is with\nrespect to.\n\nstep\n****\nThis is a positive maximum step size to use when solving the ODE.\n\npattern\n*******\nThis output argument is a sparsity pattern.\n\ntranspose\n*********\nIf this output argument is true (false) the sparsity pattern is for\n:math:`A(x)^\\R{T}` (:math:`A(x)`).\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end atomic_four_lin_ode_get.hpp}\n*/\n// BEGIN C++\n# include <cppad/example/atomic_four/lin_ode/lin_ode.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n// BEGIN PROTOTYPE\ntemplate <class Base>\nvoid atomic_lin_ode<Base>::get(\n    size_t call_id, Base& r, Base& step, sparse_rc& pattern, bool& transpose\n)\n// END PROTOTYPE\n{\n    // thread\n    size_t thread = thread_alloc::thread_num();\n    CPPAD_ASSERT_UNKNOWN( work_[thread] != nullptr );\n    //\n    // pattern_vec\n    CppAD::vector<sparse_rc>& pattern_vec( work_[thread]->pattern_vec );\n    //\n    // call_vec\n    CppAD::vector<call_struct>& call_vec( work_[thread]->call_vec );\n    //\n    CPPAD_ASSERT_UNKNOWN( thread == call_vec[call_id].thread );\n    //\n    // r\n    call_struct& call = call_vec[call_id];\n    r         = call.r;\n    step      = call.step;\n    pattern   = pattern_vec[call.pattern_index];\n    transpose = call.transpose;\n    //\n    return;\n}\n} // END_CPPAD_NAMESPACE\n// END C++\n# endif\n"
  },
  {
    "path": "include/cppad/example/atomic_four/lin_ode/hes_sparsity.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_ATOMIC_FOUR_LIN_ODE_HES_SPARSITY_HPP\n# define CPPAD_EXAMPLE_ATOMIC_FOUR_LIN_ODE_HES_SPARSITY_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_four_lin_ode_hes_sparsity.hpp}\n{xrst_spell\n    wk\n}\n\nAtomic Linear ODE Hessian Sparsity Pattern: Example Implementation\n##################################################################\n\nPurpose\n*******\nThe ``hes_sparsity`` routine overrides the virtual functions\nused by the atomic_four base class for Hessian sparsity calculations; see\n:ref:`hes_sparsity<atomic_four_hes_sparsity-name>` .\n\nNotation\n********\nWe use the notation:\n:ref:`atomic_four_lin_ode@call_id`\n:ref:`atomic_four_lin_ode@r`\n:ref:`atomic_four_lin_ode@pattern`\n:ref:`atomic_four_lin_ode@transpose`\n:ref:`atomic_four_lin_ode@pattern@nnz` ,\n:ref:`atomic_four_lin_ode@pattern@row` ,\n:ref:`atomic_four_lin_ode@pattern@col` ,\n:ref:`atomic_four_lin_ode@x` ,\n:ref:`atomic_four_lin_ode@x@n` ,\n:ref:`atomic_four_lin_ode@x@A(x)` ,\n:ref:`atomic_four_lin_ode@x@b(x)` ,\n:ref:`atomic_four_lin_ode@y(x)` ,\n:ref:`atomic_four_lin_ode@y(x)@m` ,\n:ref:`atomic_four_lin_ode@vk(x)` ,\nand the following additional notation:\n\nwk(x)\n=====\nBecause we are using the :ref:`Rosen34-name` solver, our actual sequence\nof operations is only fourth order accurate.\nSo it suffices to compute the sparsity pattern for\n\n.. math::\n\n    \\tilde{y} (x) = \\sum_{k=0}^4 v^k (x)\n\nNote that the factor :math:`r / k`,\nin the definition of :math:`v^k (x)`,\nis constant (with respect to the variables).\nHence it suffices to compute the sparsity pattern for\n\n.. math::\n\n    h (x) = \\sum_{k=0}^4 w^k (x)\n\nwhere :math:`w^0 (x) = b(x)` and for :math:`k = 1, 2, \\ldots`,\n:math:`w^k (x) = A(x) w^{k-1} (x)`.\n\nExample\n*******\nThe file :ref:`atomic_four_lin_ode_sparsity.cpp-name`\ncontains an example and test using this operator.\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end atomic_four_lin_ode_hes_sparsity.hpp}\n*/\n// BEGIN C++\n# include <cppad/example/atomic_four/lin_ode/lin_ode.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n//\n// hes_sparsity override\ntemplate <class Base>\nbool atomic_lin_ode<Base>::hes_sparsity(\n    size_t                                         call_id      ,\n    const CppAD::vector<bool>&                     ident_zero_x ,\n    const CppAD::vector<bool>&                     select_x     ,\n    const CppAD::vector<bool>&                     select_y     ,\n    CppAD::sparse_rc< CppAD::vector<size_t> >&     pattern_out  )\n{   //\n    // adouble\n    typedef AD<double> adouble;\n    //\n    // pattern_A, transpose, nnz\n    Base      r;\n    Base      step;\n    sparse_rc pattern_A;\n    bool      transpose;\n    get(call_id, r, step, pattern_A, transpose);\n    size_t nnz = pattern_A.nnz();\n    //\n    // m, n\n    size_t m = select_y.size();\n    size_t n = select_x.size();\n    //\n    // au\n    vector<adouble> au(n);\n    for(size_t j = 0; j < n; ++j)\n        au[j] = 1.0;\n    Independent( au );\n    //\n    // ax\n    vector<adouble> ax(n);\n    for(size_t j = 0; j < n; ++j)\n        if( ident_zero_x[j] )\n            ax[j] = 0.0;\n        else\n            ax[j] = au[j];\n    //\n    // aw\n    // aw = w^0 (x)\n    vector<adouble> aw(m);\n    for(size_t i = 0; i < m; ++i)\n        aw[i] = ax[nnz + i];\n    //\n    // ah = w^0 (x)\n    vector<adouble> ah = aw;\n    //\n    // ah = sum_k=0^4 w^k (x)\n    vector<adouble> awk(m);\n    for(size_t k = 1; k < 5; ++k)\n    {   // aw = w^{k-1} (x)\n        //\n        // awk = w^k (x)\n        for(size_t i = 0; i < m; ++i)\n            awk[i] = 0.0;\n        for(size_t p = 0; p < nnz; ++p)\n        {   //\n            // i, j\n            size_t i = pattern_A.row()[p];\n            size_t j = pattern_A.col()[p];\n            if( transpose )\n                std::swap(i, j);\n            //\n            // awk\n            awk[i] += ax[p] * aw[j];\n        }\n        //\n        // ah = ah + w^k(x)\n        for(size_t i = 0; i < m; ++i)\n            ah[i] += awk[i];\n        //\n        // aw = w^k (x)\n        aw = awk;\n    }\n    //\n    // h\n    ADFun<double> h;\n    h.Dependent(au, ah);\n    //\n    // pattern_out\n    // can use h.for_hes_sparsity or h.rev_hes_sparsity\n    bool internal_bool = false;\n    h.for_hes_sparsity(select_x, select_y, internal_bool, pattern_out);\n    //\n    return true;\n}\n} // END_CPPAD_NAMESPACE\n// END C++\n# endif\n"
  },
  {
    "path": "include/cppad/example/atomic_four/lin_ode/implement.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin atomic_four_lin_ode_implement}\n\nImplementing Atomic Linear ODE\n##############################\n\nContents\n********\n{xrst_toc_table\n    include/cppad/example/atomic_four/lin_ode/lin_ode.hpp\n    include/cppad/example/atomic_four/lin_ode/set.hpp\n    include/cppad/example/atomic_four/lin_ode/get.hpp\n    include/cppad/example/atomic_four/lin_ode/base_solver.hpp\n    include/cppad/example/atomic_four/lin_ode/for_type.hpp\n    include/cppad/example/atomic_four/lin_ode/forward.hpp\n    include/cppad/example/atomic_four/lin_ode/reverse.hpp\n    include/cppad/example/atomic_four/lin_ode/jac_sparsity.hpp\n    include/cppad/example/atomic_four/lin_ode/hes_sparsity.hpp\n    include/cppad/example/atomic_four/lin_ode/rev_depend.hpp\n}\n\n{xrst_end atomic_four_lin_ode_implement}\n"
  },
  {
    "path": "include/cppad/example/atomic_four/lin_ode/jac_sparsity.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_ATOMIC_FOUR_LIN_ODE_JAC_SPARSITY_HPP\n# define CPPAD_EXAMPLE_ATOMIC_FOUR_LIN_ODE_JAC_SPARSITY_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_four_lin_ode_jac_sparsity.hpp}\n{xrst_spell\n    nnz\n}\n\nAtomic Linear ODE Jacobian Sparsity Pattern: Example Implementation\n###################################################################\n\nPurpose\n*******\nThe ``jac_sparsity`` routine overrides the virtual functions\nused by the atomic_four base class for Jacobian sparsity calculations; see\n:ref:`jac_sparsity<atomic_four_jac_sparsity-name>` .\n\nNotation\n********\nWe use the notation:\n:ref:`atomic_four_lin_ode@call_id`\n:ref:`atomic_four_lin_ode@r`\n:ref:`atomic_four_lin_ode@pattern`\n:ref:`atomic_four_lin_ode@transpose`\n:ref:`atomic_four_lin_ode@pattern@nnz` ,\n:ref:`atomic_four_lin_ode@pattern@row` ,\n:ref:`atomic_four_lin_ode@pattern@col` ,\n:ref:`atomic_four_lin_ode@x` ,\n:ref:`atomic_four_lin_ode@x@n` ,\n:ref:`atomic_four_lin_ode@x@A(x)` ,\n:ref:`atomic_four_lin_ode@x@b(x)` ,\n:ref:`atomic_four_lin_ode@y(x)` ,\n:ref:`atomic_four_lin_ode@y(x)@m` ,\n:ref:`atomic_four_lin_ode@vk(x)` ,\nand the following additional notation:\n\nS[ g(x) ]\n=========\nWe use :math:`S [ g(x) ]` to denote the sparsity pattern\nfor a function :math:`g : \\B{R}^n \\rightarrow \\B{R}^m` as a vector of sets.\nTo be specific, for :math:`i = 0, \\ldots , m-1`,\n:math:`S_i [ g(x) ]` is the set of indices between\nzero and :math:`n - 1` such that\n:math:`\\partial g_i (x) / \\partial x_j` is possibly non-zero.\n\nN [ g(x) ]\n==========\nWe use :math:`N[ g(x) ]` to denote the set of :math:`i`\nsuch that :math:`g_i (x)` is not identically zero.\n\nJ_i [ A(x) ]\n============\nWe use :math:`J_i [ A(x) ]` to denote the set of :math:`j`\nbetween zero and :math:`m-1` such that\n:math:`A_{i,j}` is not known to be identically zero.\n\nP_i [ g(x) ]\n============\nWe use :math:`P_i [ g(x) ]` to denote the set if sparsity pattern indices\n\n.. math::\n\n    P_i [ g(x) ] = \\left\\{ p  \\W{:}\n        0 \\leq p < \\R{nnz} \\W{,}\n        i = \\R{row} [p] \\W{,}\n        \\R{col}[p] \\in N [ g(x) ]\n    \\right\\}\n\nTheory\n******\nThis routine must calculate the following value for\n:math:`i = 0, \\ldots, m-1`; see :ref:`atomic_four_lin_ode@y(x)@m` :\n\n.. math::\n\n    S_i [ y (x) ] = \\bigcup_k S_i [  v^k (x) ]\n\nThe set :math:`S_i [ v^0 (x) ]` has just one element\ncorresponding to :math:`b_i (x)`; i.e,\n\n.. math::\n\n    S_i [ v^0 (x) ] = \\{ \\R{nnz} + i \\}\n\nsee :ref:`atomic_four_lin_ode@x@b(x)` .\nFurthermore, for :math:`k > 0`,\n\n.. math::\n\n    v^k (x) = \\frac{r}{k} A(x) v^{k-1} (x)\n\n.. math::\n\n    S_i [ v^k (x) ] = S_i [ A(x) v^{k-1} (x) ]\n\n.. math::\n\n    S_i [ v^k (x) ] =  P_i [ v^{k-1} (x) ]\n    \\cup \\left\\{ S_j [ v^{k-1} (x) ] \\W{:}  j \\in J_i [ A(x) ] \\right\\}\n\nSuppose that :math:`\\ell` is such that for all :math:`i`\nthe following two conditions hold\n\n.. math::\n\n    N [ v^\\ell (x) ]  \\subset \\bigcup_{k < \\ell} N [ v^k (x) ]\n\n.. math::\n\n    S_i [ v^\\ell (x) ] \\subset \\bigcup_{k < \\ell} S_i [ v^k (x) ]\n\nFrom the first condition above it follows that\n\n.. math::\n\n    P_i [ v^\\ell (x) ] \\subset \\bigcup_{k < \\ell} P_i [ v^k (x) ]\n\nUsing the second condition we have\n\n.. math::\n\n    S_i [ v^{\\ell+1} (x) ] =  P_i [ v^\\ell (x) ]\n    \\cup \\left\\{ S_j [ v^\\ell (x) ] \\W{:} j \\in J_i [ A(x) ] \\right\\}\n\n.. math::\n\n    S_i [ v^{\\ell+1} (x) ] \\subset\n    \\left\\{ S_j [ v^\\ell (x) ] \\W{:} j \\in J_i [ A(x) ] \\right\\}\n        \\bigcup_{k \\leq \\ell } S_i [ v^k (x) ]\n\n.. math::\n\n    S_i [ v^{\\ell+1} (x) ]\n    \\subset\n    \\bigcup_{k \\leq \\ell} S_i [ v^k (x) ] \\cup\n            \\left\\{ S_j [ v^k (x) ] \\W{:} j \\in J_i [ A(x) ] \\right\\}\n\n.. math::\n\n    S_i [ v^{\\ell+1} (x) ]\n    \\subset\n    \\bigcup_{k < \\ell} S_i [ v^k (x) ] \\cup\n            \\left\\{ S_j [ v^k (x) ] \\W{:} j \\in J_i [ A(x) ] \\right\\}\n\n.. math::\n\n    S_i [ v^{\\ell+1} (x) ]\n    \\subset\n    \\bigcup_{k \\leq \\ell} S_i [ v^k (x) ]\n\n.. math::\n\n    S_i [ v^{\\ell+1} (x) ]\n    \\subset\n    \\bigcup_{k < \\ell} S_i [ v^k (x) ]\n\nIt follows that\n\n.. math::\n\n    S_i [ y(x) ] = \\bigcup_{k < \\ell} S_i [ v^k (x) ]\n\nExample\n*******\nThe file :ref:`atomic_four_lin_ode_sparsity.cpp-name`\ncontains an example and test using this operator.\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end atomic_four_lin_ode_jac_sparsity.hpp}\n*/\n// BEGIN C++\n# include <cppad/example/atomic_four/lin_ode/lin_ode.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n//\n// jac_sparsity override\ntemplate <class Base>\nbool atomic_lin_ode<Base>::jac_sparsity(\n    size_t                                         call_id      ,\n    bool                                           dependency   ,\n    const CppAD::vector<bool>&                     ident_zero_x ,\n    const CppAD::vector<bool>&                     select_x     ,\n    const CppAD::vector<bool>&                     select_y     ,\n    CppAD::sparse_rc< CppAD::vector<size_t> >&     pattern_out  )\n{\n    //\n    // pattern_A, transpose, nnz\n    Base      r;\n    Base      step;\n    sparse_rc pattern_A;\n    bool      transpose;\n    get(call_id, r, step, pattern_A, transpose);\n    size_t nnz = pattern_A.nnz();\n    //\n    // m, n\n    size_t m = select_y.size();\n    size_t n = select_x.size();\n    //\n    CPPAD_ASSERT_UNKNOWN( n == nnz + m );\n    CPPAD_ASSERT_UNKNOWN( pattern_A.nr() == m );\n    CPPAD_ASSERT_UNKNOWN( pattern_A.nc() == m );\n    //\n    // pattern_out\n    // Accumulates elements of the sparsity pattern for y(x) that satisfy\n    // select_x and select_y\n    pattern_out.resize(m, n, 0);\n    //\n    // list_setvec\n    // This vector of sets interface is not in the CppAD user API\n    typedef CppAD::local::sparse::list_setvec list_setvec;\n    //\n    // setvec\n    // Accumulates the sparsity pattern for y(x) that satisfy select_x.\n    // There are m sets and the set elements are between zero and n-1.\n    list_setvec setvec;\n    size_t n_set = m;\n    size_t end   = n;\n    setvec.resize(n_set, end);\n    //\n    // setvec, pattern_out\n    // iniialize as equal to S[ v^0 (x) ]\n    for(size_t i = 0; i < m; ++i)\n    {   size_t element = nnz + i;\n        if( select_x[element] )\n        {   setvec.add_element(i, element);\n            if( select_y[i] )\n                pattern_out.push_back(i, element);\n        }\n    }\n    //\n    // non_zero\n    // Accumulates union_k for k < ell, N[ v^k (x) ]\n    // initialize as N[ v^0 (x) ]\n    CppAD::vector<bool> non_zero(m);\n    for(size_t i = 0; i < m; ++i)\n        non_zero[i] = ! ident_zero_x[nnz + i];\n    //\n    // change\n    // Did setvec or non_zero change in previous iteration of while loop\n    bool change = true;\n    while(change)\n    {   change = false;\n        // we use k = 1, 2, ... to denote the pass through this loop\n        // setvec[i] contains union q < k S_i [ v^q (x) ]\n        // non_zero  contains union q < k N [ v^q (x) ]\n        //\n        // For each element of the sparsity pattern for A subject to select_x\n        for(size_t p = 0; p < nnz; ++p) if( select_x[p] )\n        {   CPPAD_ASSERT_UNKNOWN( ! ident_zero_x[p] );\n            size_t i = pattern_A.row()[p];\n            size_t j = pattern_A.col()[p];\n            if( transpose )\n                std::swap(i, j);\n            //\n            if( non_zero[j] )\n            {   // p, corresponding to A_{i,j}, is in P_i [ v^k (x) ]\n                if( ! setvec.is_element(i, p) )\n                {   change = true;\n                    setvec.add_element(i, p);\n                    if( select_y[i] )\n                        pattern_out.push_back(i, p);\n                }\n            }\n            // j is in J_i [ A(x) ]\n            list_setvec::const_iterator itr(setvec, j);\n            size_t element = *itr;\n            while(element != end )\n            {   if( ! setvec.is_element(i, element) )\n                {   change = true;\n                    setvec.add_element(i, element);\n                    if( select_y[i] )\n                        pattern_out.push_back(i, element);\n                      }\n                      ++itr;\n                      element = *itr;\n            }\n            // A_{i,j} update to non_zero\n            if( non_zero[i] == false )\n            {   if( non_zero[j] == true )\n                {   change = true;\n                    non_zero[i] = true;\n                }\n            }\n        }\n    }\n    //\n    return true;\n}\n} // END_CPPAD_NAMESPACE\n// END C++\n# endif\n"
  },
  {
    "path": "include/cppad/example/atomic_four/lin_ode/lin_ode.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_ATOMIC_FOUR_LIN_ODE_LIN_ODE_HPP\n# define CPPAD_EXAMPLE_ATOMIC_FOUR_LIN_ODE_LIN_ODE_HPP\n\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-23 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_four_lin_ode.hpp}\n\nAtomic Linear ODE Class: Example Implementation\n###############################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end atomic_four_lin_ode.hpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n//\ntemplate <class Base>\nclass atomic_lin_ode : public CppAD::atomic_four<Base> {\n//\npublic:\n    // BEGIN sparse_rc_typedef\n    typedef CppAD::sparse_rc< CppAD::vector<size_t> > sparse_rc;\n    // END sparse_rc_typedef\n    //\n    // ctor\n    atomic_lin_ode(const std::string& name) :\n    CppAD::atomic_four<Base>(name)\n    {   for(size_t thread = 0; thread < CPPAD_MAX_NUM_THREADS; ++thread)\n            work_[thread] = nullptr;\n    }\n    // destructor\n    ~atomic_lin_ode(void)\n    {   for(size_t thread = 0; thread < CPPAD_MAX_NUM_THREADS; ++thread)\n        {   if( work_[thread] != nullptr  )\n            {   // allocated in set member function\n                delete work_[thread];\n            }\n        }\n    }\n    // set\n    size_t set(\n        const Base& r,\n        const Base& step,\n        sparse_rc&  pattern,\n        const bool& transpose\n    );\n    //\n    // get\n    void get(\n        size_t     call_id,\n        Base&      r,\n        Base&      step,\n        sparse_rc& pattern,\n        bool&      transpose\n    );\n    //\n    // base_solver\n    static void base_solver(\n        const Base&                r          ,\n        const Base&                step       ,\n        const sparse_rc&           pattern    ,\n        const bool&                transpose  ,\n        const CppAD::vector<Base>& x          ,\n        CppAD::vector<Base>&       y\n    );\n    //\n    // test_rev_depend\n    // public version of this function that is used for example / testing\n    bool test_rev_depend(\n        size_t                                         call_id,\n        CppAD::vector<bool>&                           ident_zero_x,\n        CppAD::vector<bool>&                           depend_x,\n        const CppAD::vector<bool>&                     depend_y)\n    {   bool ok = rev_depend(call_id, ident_zero_x, depend_x, depend_y);\n        return ok;\n    }\nprivate:\n    //\n    // information connected to one call of this atomic function\n    // pattern points to pattern_vec for this thread\n    struct call_struct {\n        size_t thread; Base r; Base step; size_t pattern_index; bool transpose;\n    };\n    //\n    // information connected to each thread\n    // patterns are in a separate vector so do not need one for every call\n    struct thread_struct {\n        CppAD::vector<sparse_rc>   pattern_vec;\n        CppAD::vector<call_struct> call_vec;\n    };\n    //\n    // Use pointers, to avoid false sharing between threads.\n    thread_struct* work_[CPPAD_MAX_NUM_THREADS];\n    //\n    // extend_ode\n    template <class Float>\n    static void extend_ode(\n        const sparse_rc&            pattern         ,\n        const bool&                 transpose       ,\n        const CppAD::vector<Float>& taylor_x        ,\n        sparse_rc&                  pattern_extend  ,\n        CppAD::vector<Float>&       x_extend\n    );\n    //\n    // reverse_one\n    static void reverse_one(\n        const Base&                r           ,\n        const Base&                step        ,\n        const sparse_rc&           pattern     ,\n        const bool&                transpose   ,\n        const CppAD::vector<bool>& select_x    ,\n        const CppAD::vector<Base>& x           ,\n        const CppAD::vector<Base>& w           ,\n        CppAD::vector<Base>&       partial_x\n    );\n    void reverse_one(\n        const size_t&                           call_id     ,\n        const CppAD::vector<bool>&              select_x    ,\n        const CppAD::vector< CppAD::AD<Base> >& x           ,\n        const CppAD::vector< CppAD::AD<Base> >& w           ,\n        CppAD::vector< CppAD::AD<Base> >&       partial_x\n    );\n    // -----------------------------------------------------------------------\n    // overrides\n    // -----------------------------------------------------------------------\n    // for_type\n    bool for_type(\n        size_t                                        call_id,\n        const CppAD::vector<CppAD::ad_type_enum>&     type_x,\n        CppAD::vector<CppAD::ad_type_enum>&           type_y\n    ) override;\n    //\n    // Base forward\n    bool forward(\n        size_t                                           call_id,\n        const CppAD::vector<bool>&                       select_y,\n        size_t                                           order_low,\n        size_t                                           order_up,\n        const CppAD::vector<Base>&                       taylor_x,\n        CppAD::vector<Base>&                             taylor_y\n    ) override;\n    // Cases not yet implemented\n    //\n    // AD<Base> forward\n    bool forward(\n        size_t                                           call_id,\n        const CppAD::vector<bool>&                       select_y,\n        size_t                                           order_low,\n        size_t                                           order_up,\n        const CppAD::vector< CppAD::AD<Base> >&          ataylor_x,\n        CppAD::vector< CppAD::AD<Base> >&                ataylor_y\n    ) override;\n    //\n    // Base reverse\n    bool reverse(\n        size_t                                           call_id,\n        const CppAD::vector<bool>&                       select_x,\n        size_t                                           order_up,\n        const CppAD::vector<Base>&                       taylor_x,\n        const CppAD::vector<Base>&                       taylor_y,\n        CppAD::vector<Base>&                             partial_x,\n        const CppAD::vector<Base>&                       partial_y\n    ) override;\n    //\n    // AD<Base> reverse\n    bool reverse(\n        size_t                                           call_id,\n        const CppAD::vector<bool>&                       select_x,\n        size_t                                           order_up,\n        const CppAD::vector< CppAD::AD<Base> >&          ataylor_x,\n        const CppAD::vector< CppAD::AD<Base> >&          ataylor_y,\n        CppAD::vector< CppAD::AD<Base> >&                apartial_x,\n        const CppAD::vector< CppAD::AD<Base> >&          apartial_y\n    ) override;\n    //\n    // jac_sparsity\n    bool jac_sparsity(\n        size_t                                         call_id,\n        bool                                           dependency,\n        const CppAD::vector<bool>&                     ident_zero_x,\n        const CppAD::vector<bool>&                     select_x,\n        const CppAD::vector<bool>&                     select_y,\n        CppAD::sparse_rc< CppAD::vector<size_t> >&     pattern_out\n    ) override;\n    //\n    // hes_sparsity\n    bool hes_sparsity(\n        size_t                                         call_id,\n        const CppAD::vector<bool>&                     ident_zero_x,\n        const CppAD::vector<bool>&                     select_x,\n        const CppAD::vector<bool>&                     select_y,\n        CppAD::sparse_rc< CppAD::vector<size_t> >&     pattern_out\n    ) override;\n    //\n    // rev_depend\n    bool rev_depend(\n        size_t                                         call_id,\n        const CppAD::vector<bool>&                     ident_zero_x,\n        CppAD::vector<bool>&                           depend_x,\n        const CppAD::vector<bool>&                     depend_y\n    ) override;\n};\n} // END_CPPAD_NAMESPACE\n\n# include <cppad/example/atomic_four/lin_ode/set.hpp>\n# include <cppad/example/atomic_four/lin_ode/get.hpp>\n# include <cppad/example/atomic_four/lin_ode/base_solver.hpp>\n# include <cppad/example/atomic_four/lin_ode/for_type.hpp>\n# include <cppad/example/atomic_four/lin_ode/forward.hpp>\n# include <cppad/example/atomic_four/lin_ode/reverse.hpp>\n# include <cppad/example/atomic_four/lin_ode/jac_sparsity.hpp>\n# include <cppad/example/atomic_four/lin_ode/hes_sparsity.hpp>\n# include <cppad/example/atomic_four/lin_ode/rev_depend.hpp>\n// END C++\n# endif\n"
  },
  {
    "path": "include/cppad/example/atomic_four/lin_ode/lin_ode.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin atomic_four_lin_ode}\n{xrst_spell\n    nnz\n    rosen\n    vk\n}\n\nAtomic First Order Linear ODE Method: Example Implementation\n############################################################\n\nSyntax\n******\n| ``atomic_lin_ode`` *ode* ( *name* )\n| *call_id* = *lin_ode* . ``set`` ( *r* , *step* , *pattern* , *transpose* )\n| *lin_ode* . ``get`` ( *call_id* , *r* , *step* , *pattern* , *transpose* )\n| *lin_ode* . ``base_solver`` ( *r* , *step* , *pattern* , *transpose* , *x* , *y* )\n| *lin_ode* ( *call_id* , *ax* , *ay* )\n\nz(t, x)\n*******\nConstruct an atomic operation that computes an\napproximate solution of the first order linear initial value ODE\n\n.. math::\n\n    z_t (t, x) = A(x) z(t, x) \\W{,} z(0, x) = b(x)\n\nwhere\n:math:`z : \\B{R} \\times \\B{R}^n \\rightarrow \\B{R}^m`,\n:math:`A : \\B{R}^n \\rightarrow \\B{R}^{m \\times m}`,\n:math:`b : \\B{R}^n \\rightarrow  \\B{R}^m`,\nand the subscript :math:`t` denotes partial differentiation w.r.t :math:`t`.\n\ncall_id\n*******\nThis is a return value (argument) for the ``set`` (``get`` ) routine.\n\nr\n*\nThis is the value of *t* at which we are approximating :math:`z(t, x)`.\nThis is a argument (return value) for the ``set`` (``get`` ) routine.\n\nstep\n****\nThis is a positive maximum step size to use when solving the ODE.\n\npattern\n*******\nThis is a sparsity pattern.\nThis is a argument (return value) for the ``set`` (``get`` ) routine.\n\nnnz\n===\nWe use *nnz* to denote *pattern* . ``nnz`` () .\n\nrow\n===\nWe use *row* to denote *pattern* . ``row`` () .\n\ncol\n===\nWe use *col* to denote *pattern* . ``col`` () .\n\ntranspose\n*********\nIf *transpose* is true (false) the sparsity pattern is for\n:math:`A(x)^\\R{T}` (:math:`A(x)`).\nThis is a argument (return value) for the ``set`` (``get`` ) routine.\n\nx\n*\nWe use *x* to denote the argument to the atomic function.\nIn the call to ``base_solver`` it is a CppAD vector with elements\nof type *Base* .\n\nn\n=\nThe size of the vector *x* is\n:math:`n = nnz + m`.\n\nA(x)\n====\nThis matrix stored in the same order as *pattern*\nat the beginning of the vector *x* .\nTo be specific,\nif *transpose* is true (false),\nfor *k* = 0, ..., *nnz* ``-1`` ,\n:math:`A_{j,i} (x)` ( :math:`A_{i,j} (x)` ) is equal to\n:math:`x[k]` where *i* = *row* [ *k* ] and  *j* = *col* [ *k* ] .\n\nb(x)\n====\nThis vector is stored at the end of\n*x* ; i.e. its *j*-th element is\n:math:`b_j (x) = x[ nnz + j ]`\n\ny(x)\n****\nWe use :math:`y(x)` to denote the final value of the ODE; i.e.,\n:math:`y(x) = z(r, x)`.\n\nm\n=\nWe use *m* to denote the size of the vector *y* ( *x* ) .\nThis is the number of equations in the ODE.\n\ny\n=\nIn the call to ``base_solver`` ,\n*y* is a CppAD vector with elements of type *Base* .\nThe input value of its elements does not matter.\nUpon return it contains the value :math:`y(x)`.\n\nax\n**\nIn the call to *lin_ode* , *ax*\nis a simple vector with elements of type ``AD`` < *Base* > .\nThe elements of *ax* have the same meaning as *x* .\n\nay\n**\nIn the call to *lin_ode* , *ay*\nis a simple vector with elements of type ``AD`` < *Base* > .\nThe input value of its elements does not matter.\nUpon return it represents the solution *y* ( *ax* ) .\n\nvk(x)\n*****\nWe sometimes use the following representation for :math:`y(x)`:\n\n.. math::\n\n    y(x) = \\exp [ r A(x) ] b(x) = \\sum_{k=0}^\\infty \\frac{r^k}{k!} A(x)^k b(x)\n\nDefine :math:`v^0 (x) = b(x)` and for :math:`k = 1, 2, \\ldots`,\n:math:`v^k (x) = (r / k) A(x) v^{k-1} (x)`.\nUsing this notation,\n\n.. math::\n\n    y(x) = \\sum_{k=0}^\\infty v^k (x)\n\nApproximations\n**************\n\nRosen34\n=======\nThe :ref:`atomic_four_lin_ode_base_solver.hpp@Rosen34` routine\nis used to approximate the solution of the ODE.\nAny initial value ODE solver can be used for this purpose.\n\nSimpson's Rule\n==============\n:ref:`atomic_four_lin_ode_reverse.hpp@Simpson's Rule`\nis used to approximate the integral\n\n.. math::\n\n    \\int_0^r \\lambda_i (t, x) z_j (r, x) \\R{d} t\n\nAny other approximation for this integral can be used.\n\nContents\n********\n{xrst_toc_table\n    include/cppad/example/atomic_four/lin_ode/implement.xrst\n    example/atomic_four/lin_ode/forward.cpp\n    example/atomic_four/lin_ode/reverse.cpp\n    example/atomic_four/lin_ode/sparsity.cpp\n    example/atomic_four/lin_ode/rev_depend.cpp\n}\n\n{xrst_end atomic_four_lin_ode}\n"
  },
  {
    "path": "include/cppad/example/atomic_four/lin_ode/rev_depend.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_ATOMIC_FOUR_LIN_ODE_REV_DEPEND_HPP\n# define CPPAD_EXAMPLE_ATOMIC_FOUR_LIN_ODE_REV_DEPEND_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_four_lin_ode_rev_depend.hpp}\n{xrst_spell\n    wk\n}\n\nAtomic Linear ODE Forward Type Calculation: Example Implementation\n##################################################################\n\nPurpose\n*******\nThe ``rev_depend`` routine overrides the virtual functions\nused by the atomic_four base; see\n:ref:`rev_depend<atomic_four_rev_depend-name>` .\n\nNotation\n********\nWe use the notation:\n:ref:`atomic_four_lin_ode@call_id`\n:ref:`atomic_four_lin_ode@r`\n:ref:`atomic_four_lin_ode@pattern`\n:ref:`atomic_four_lin_ode@transpose`\n:ref:`atomic_four_lin_ode@pattern@nnz` ,\n:ref:`atomic_four_lin_ode@pattern@row` ,\n:ref:`atomic_four_lin_ode@pattern@col` ,\n:ref:`atomic_four_lin_ode@x` ,\n:ref:`atomic_four_lin_ode@x@n` ,\n:ref:`atomic_four_lin_ode@x@A(x)` ,\n:ref:`atomic_four_lin_ode@x@b(x)` ,\n:ref:`atomic_four_lin_ode@y(x)` ,\n:ref:`atomic_four_lin_ode@y(x)@m` ,\n:ref:`atomic_four_lin_ode@vk(x)` ,\nand the following additional notation:\n\nwk(x)\n=====\nNote that the factor :math:`r / k`,\nin the definition of :math:`v^k (x)`,\nis constant (with respect to the variables).\nHence it suffices to compute the dependency for\n\n.. math::\n\n    h (x) = \\sum_{k=0}^4 w^k (x)\n\nwhere :math:`w^0 (x) = b(x)` and for :math:`k = 1, 2, \\ldots`,\n:math:`w^k (x) = A(x) w^{k-1} (x)`.\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end atomic_four_lin_ode_rev_depend.hpp}\n*/\n// BEGIN C++\n# include <cppad/example/atomic_four/lin_ode/lin_ode.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n//\n// rev_depend override\ntemplate <class Base>\nbool atomic_lin_ode<Base>::rev_depend(\n    size_t                                         call_id,\n    const CppAD::vector<bool>&                     ident_zero_x,\n    CppAD::vector<bool>&                           depend_x,\n    const CppAD::vector<bool>&                     depend_y\n)\n{\n    // nnz\n    Base      r;\n    Base      step;\n    sparse_rc pattern;\n    bool      transpose;\n    get(call_id, r, step, pattern, transpose);\n    size_t nnz = pattern.nnz();\n    //\n    // m\n    size_t m = depend_y.size();\n    CPPAD_ASSERT_UNKNOWN( ident_zero_x.size() == depend_x.size() );\n    CPPAD_ASSERT_UNKNOWN( pattern.nr() == m );\n    CPPAD_ASSERT_UNKNOWN( pattern.nc() == m );\n    //\n    // depend_w\n    CppAD::vector<bool> depend_w = depend_y;\n    //\n    // depend_x\n    for(size_t p = 0; p < nnz; ++p)\n        depend_x[p] = false;\n    for(size_t i = 0; i < m; ++i)\n        depend_x[nnz + i] = depend_y[i];\n    //\n    // change\n    // Did depend_w change during the previous iteration of the while loop\n    bool change = true;\n    while(change)\n    {   change = false;\n        // we use k = 1, 2, ... to denote the pass through this loop\n        //\n        // depend_w, depend_x\n        // include dependency for w^k (x)\n        for(size_t p = 0; p < nnz; ++p) if( ! ident_zero_x[p] )\n        {   size_t i = pattern.row()[p];\n            size_t j = pattern.col()[p];\n            if( transpose )\n                std::swap(i, j);\n            //\n            // back propagate dependency on y\n            if( depend_w[i] && ! depend_w[j] )\n            {   change      = true;\n                depend_w[j] = true;\n            }\n            //\n            // depend_x\n            // for propagate dependency on A_{i,j}\n            if( depend_w[i] && ! depend_x[p] )\n            {   change      = true;\n                depend_x[p] = true;\n            }\n        }\n    }\n    //\n    // depend_x\n    // terms corresponding to b(x)\n    for(size_t i = 0; i < m; ++i)\n        depend_x[nnz + i] = depend_w[i];\n    //\n    return true;\n}\n} // END_CPPAD_NAMESPACE\n\n// END C++\n# endif\n"
  },
  {
    "path": "include/cppad/example/atomic_four/lin_ode/reverse.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_ATOMIC_FOUR_LIN_ODE_REVERSE_HPP\n# define CPPAD_EXAMPLE_ATOMIC_FOUR_LIN_ODE_REVERSE_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_four_lin_ode_reverse.hpp}\n{xrst_spell\n    lll\n    nnz\n}\n\nAtomic Linear ODE Reverse Mode: Example Implementation\n######################################################\n\nPurpose\n*******\nThe ``reverse`` routine overrides the virtual functions\nused by the atomic_four base; see\n:ref:`reverse<atomic_four_reverse-name>` .\n\nFirst Order Theory\n******************\nWe are given a vector :math:`w \\in \\B{R}^m` and need to compute\n\n.. math::\n\n    \\partial_x w^\\R{T} z(r, x)\n\nsee the definition of :ref:`atomic_four_lin_ode@z(t, x)` .\nConsider the Lagrangian corresponding to\n:math:`w^\\R{T} z(r, x)` as the objective and the ODE as the constraint:\n\n.. math::\n\n    L(x, \\lambda)\n    =\n    w^\\R{T} z(r, x) +\n        \\int_0^r \\lambda(t, x)^\\R{T}\n            [ A(x) z(t, x) - z_t (t, x) ] \\R{d} t\n\nwhere :math:`\\lambda : \\R{R} \\times \\B{R}^n \\rightarrow \\B{R}^m`\nis a smooth function.\nIf :math:`z(t, x)` satisfies its ODE, then\n\n.. math::\n\n    \\partial_x w^\\R{T} z(r, x)\n    =\n    \\partial_x L(x, \\lambda)\n\nWe use the following integration by parts to replace the :math:`z_t (t, x)`\nterm in the integral defining :math:`L(x, \\lambda)`:\n\n.. math::\n\n    - \\int_0^r \\lambda(t, x)^\\R{T} z_t (t, x) \\R{d} t\n    =\n    - \\left. \\lambda(t, x)^\\R{T} z(t, x) \\right|_0^r\n    +\n    \\int_0^r \\lambda_t (t, x)^\\R{T} z(t, x) \\R{d} t\n\nAdding the condition :math:`\\lambda(r, x) = w`,\nand noting that :math:`z(0, x) = b(x)`, we have\n\n.. math::\n\n    L(x, \\lambda)\n    =\n    \\lambda(0, x)^\\R{T} z(0, x)\n    +\n    \\int_0^r \\lambda_t (t, x)^\\R{T} z(t, x) \\R{d} t\n    +\n    \\int_0^r \\lambda(t, x)^\\R{T} A(x) z(t, x) \\R{d} t\n\n.. math::\n\n    L(x, \\lambda)\n    =\n    \\lambda(0, x)^\\R{T} b (x)\n    +\n    \\int_0^r [ \\lambda_t (t, x)^\\R{T} + \\lambda(t, x)^\\R{T} A(x) ]\n        z(t, x) \\R{d} t\n\n.. math::\n\n    L(x, \\lambda)\n    =\n    \\lambda(0, x)^\\R{T} b (x)\n    +\n    \\int_0^r z(t, x)^\\R{T}\n        [ \\lambda_t (t, x) + A(x)^\\R{T} \\lambda(t, x) ] \\R{d} t\n\nThe partial derivative\nof :math:`L(x, \\lambda)` with respect to :math:`b_j`,\n(not including the dependence of :math:`\\lambda(t, x)` on :math:`x`)\nis :\n\n.. math::\n\n    \\partial_{b(j)} L(x, \\lambda)\n    =\n    \\lambda_j (0, x)\n\nThe partial derivative\nof :math:`L(x, \\lambda)` with respect to :math:`A_{i,j}`\n(not including The dependence of :math:`\\lambda(t, x)` on :math:`x`)\nis :\n\n.. math::\n\n    \\partial_{A(i,j)} L(x, \\lambda)\n    =\n    \\int_0^r \\partial_{A(i,j)} z(t, x)^\\R{T}\n        [ \\lambda_t (t, x) + A(x)^\\R{T} \\lambda(t, x) ] \\R{d} t\n    +\n    \\int_0^r z_j (t, x) \\lambda_i (t, x) \\R{d} t\n\nIf :math:`\\lambda(t, x)` satisfies the ODE\n\n.. math::\n\n    0 = \\lambda_t (t, x) + A(x)^\\R{T} \\lambda(t, x)\n\nThe partial derivative with respect to :math:`A_{i,j}` is\n\n.. math::\n\n    \\partial_{A(i,j)} L(x, \\lambda)\n    =\n    \\int_0^r z_j (t, x) \\lambda_i (t, x) \\R{d} t\n\nIn summary, we can compute\nan approximate solution for the initial value ODE:\n\n.. math::\n\n    z_t (t, x) = A(x) z(t, x) \\W{,} z(0, x) = b(x)\n\nand approximate solution for the final value ODE:\n\n.. math::\n\n    \\lambda_t (t, x) = - A(x)^\\R{T} \\lambda(t, x)\n    \\W{,}\n    \\lambda(r, x) = w\n\nUsing the notation\n:ref:`atomic_four_lin_ode@pattern@nnz` ,\n:ref:`atomic_four_lin_ode@pattern@row` , and\n:ref:`atomic_four_lin_ode@pattern@col` ,\nWe can compute an approximation for\n\n.. math::\n\n    \\partial_{x(k)} w^\\R{T} z(r, x)\n    =\n    \\left\\{ \\begin{array}{lll}\n    \\int_0^r \\lambda_i (t, x) z_j (r, x) \\R{d} t\n    & \\R{where} \\; i = \\R{row} [k] \\W{,} j = \\R{col}[k]\n    & \\R{if} \\; k < nnz\n    \\\\\n    \\lambda_i (0, x)\n    & \\R{where} \\; i = k - nnz\n    & \\R{otherwise}\n    %\n    \\end{array} \\right.\n\n{xrst_toc_hidden\n    include/cppad/example/atomic_four/lin_ode/reverse_2.xrst\n}\nSecond Order Theory\n*******************\n:ref:`atomic_four_lin_ode_reverse_2-name` .\n\nSimpson's Rule\n**************\nThis example uses Simpson's rule to approximate the integral\n\n.. math::\n\n    \\int_0^r \\lambda_i (t, x) z_j (t, x) \\R{d} t\n\nAny other approximation for this integral can be used.\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end atomic_four_lin_ode_reverse.hpp}\n*/\n// BEGIN C++\n# include <cppad/example/atomic_four/lin_ode/lin_ode.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n// ----------------------------------------------------------------------------\n// reverse override for Base\ntemplate <class Base>\nbool atomic_lin_ode<Base>::reverse(\n    size_t                                     call_id     ,\n    const CppAD::vector<bool>&                 select_x    ,\n    size_t                                     order_up    ,\n    const CppAD::vector<Base>&                 taylor_x    ,\n    const CppAD::vector<Base>&                 taylor_y    ,\n    CppAD::vector<Base>&                       partial_x   ,\n    const CppAD::vector<Base>&                 partial_y   )\n{\n    // order_up\n    if( order_up > 0 )\n        return false;\n    //\n    // r, step, pattern, transpose\n    Base      r;\n    Base      step;\n    sparse_rc pattern;\n    bool      transpose;\n    get(call_id, r, step, pattern, transpose);\n    //\n    reverse_one(\n        r, step, pattern, transpose, select_x, taylor_x, partial_y, partial_x\n    );\n    //\n    return true;\n}\n// ---------------------------------------------------------------------------\n// reverse override for AD<Base>\ntemplate <class Base>\nbool atomic_lin_ode<Base>::reverse(\n    size_t                                           call_id    ,\n    const CppAD::vector<bool>&                       select_x   ,\n    size_t                                           order_up   ,\n    const CppAD::vector< CppAD::AD<Base> >&          ataylor_x  ,\n    const CppAD::vector< CppAD::AD<Base> >&          ataylor_y  ,\n    CppAD::vector< CppAD::AD<Base> >&                apartial_x ,\n    const CppAD::vector< CppAD::AD<Base> >&          apartial_y )\n{\n    // order_up\n    if( order_up > 0 )\n        return false;\n    //\n    reverse_one(call_id, select_x, ataylor_x, apartial_y, apartial_x);\n    //\n    return true;\n}\n// ---------------------------------------------------------------------------\n// reverse_one\n// Base version of first order reverse mode calculation as in Theory above\ntemplate <class Base>\nvoid atomic_lin_ode<Base>::reverse_one(\n    const Base&                                r           ,\n    const Base&                                step        ,\n    const sparse_rc&                           pattern     ,\n    const bool&                                transpose   ,\n    const CppAD::vector<bool>&                 select_x    ,\n    const CppAD::vector<Base>&                 x           ,\n    const CppAD::vector<Base>&                 w           ,\n    CppAD::vector<Base>&                       partial_x   )\n{\n    //\n    // nnz\n    size_t nnz    = pattern.nnz();\n    //\n    // m\n    size_t m = w.size();\n    CPPAD_ASSERT_UNKNOWN( w.size() == m );\n    CPPAD_ASSERT_UNKNOWN( pattern.nr() == m );\n    CPPAD_ASSERT_UNKNOWN( pattern.nc() == m );\n    //\n    // n\n# ifndef NDEBUG\n    size_t n = nnz + m;\n# endif\n    //\n    // x, partial_x\n    CPPAD_ASSERT_UNKNOWN( x.size()  == n );\n    CPPAD_ASSERT_UNKNOWN( partial_x.size() == n );\n    //\n    // n_step\n    size_t n_step = 2;\n    if( step < abs(r) / Base(n_step) )\n        n_step = size_t( abs(r) / step );\n    while( step < abs(r) / Base(n_step) )\n        ++n_step;\n    if( n_step % 2 == 1 )\n        ++n_step;\n    CPPAD_ASSERT_UNKNOWN( n_step % 2 == 0 );\n    //\n    // h\n    Base h = r / Base(n_step);\n    //\n    // x_tmp = [A, b]\n    CppAD::vector<Base> x_tmp = x;\n    //\n    // z_all\n    CppAD::vector< CppAD::vector<Base> > z_all(n_step + 1);\n    //\n    // z_all[0] = z(0, x)\n    z_all[0].resize(m);\n    for(size_t i = 0; i < m; ++i)\n        z_all[0][i] = x[nnz + i];\n    //\n    // p\n    for(size_t p = 0; p < n_step; ++p)\n    {   // x_tmp = [A, z(h*p, x) ]\n        for(size_t i = 0; i < nnz; ++i)\n            x_tmp[nnz + i] = z_all[p][i];\n        //\n        // z_all[p+1] = z( h*(p+1), x)\n        z_all[p+1].resize(m);\n        base_solver(h, step, pattern, transpose, x_tmp, z_all[p+1]);\n    }\n    // lambda_previous = lambda(r, x) = w\n    CppAD::vector<Base> lambda_previous = w;\n    //\n    // lambda_middle, lambda_next\n    CppAD::vector<Base> lambda_middle(m), lambda_next(m);\n    //\n    // partial_x\n    // partial_A L(x, lambda)\n    for(size_t k = 0; k < nnz; ++k)\n        partial_x[k] = Base(0.0);\n    //\n    // p\n    size_t p = n_step - 1;\n    while(p)\n    {   CPPAD_ASSERT_UNKNOWN( p % 2 == 1 );\n        //\n        // x_tmp = [ A, lambda( (p+1)*h, x ) ]\n        for(size_t i = 0; i < m; ++i)\n            x_tmp[nnz + i] = lambda_previous[i];\n        //\n        // lambda_middle = lambda(p*h, x)\n        // We convert the final value ODE to an initial value ODE by changing\n        // the sign of A^T and changing limits from [(p+1)*h, p*h] -> [0, h].\n        base_solver(h, step, pattern, ! transpose, x_tmp, lambda_middle);\n        //\n        // x_tmp = [ A, lambda(p*h, x)]\n        for(size_t i = 0; i < m; ++i)\n            x_tmp[nnz + i] = lambda_middle[i];\n        //\n        // lambda_next = lambda((p-1), x)\n        base_solver(h, step, pattern, ! transpose, x_tmp, lambda_next);\n        //\n        // partial_x\n        // partail_A L(x, lambda)\n        for(size_t k = 0; k < nnz; ++k) if( select_x[k] )\n        {   size_t i = pattern.row()[k];\n            size_t j = pattern.col()[k];\n            if( transpose )\n                std::swap(i, j);\n            //\n            // sum  = lambda_i ((p+1)*h, x) * z_j ((p+1)*h, x)\n            Base sum = lambda_previous[i] * z_all[p+1][j];\n            //\n            // sum += 4 * lambad_i(p*h, x) * z_j(p*h, x)\n            sum += Base(4.0) * lambda_middle[i] * z_all[p][j];\n            //\n            // sum += lambda_i ((p-1)*h, x) * z_j ((p-1)*h, x)\n            sum += lambda_next[i] * z_all[p-1][j];\n            //\n            // Simpson's rule for int_0^2*h lambda_i (t, x) z_j (t, x) dt\n            Base integral = h * sum / Base(3.0);\n            //\n            // partial_{A(i,j)}\n            partial_x[k] += integral;\n        }\n        //\n        // lambda_previous\n        lambda_previous = lambda_next;\n        //\n        // p\n        if( p == 1 )\n            p = 0;\n        else\n            p -= 2;\n    }\n    //\n    // partial_x\n    // partial_b L(x, lambda) = lambda(0, x)\n    for(size_t i = 0; i < m; ++i)\n    {   // partial_{b(i)}\n        partial_x[nnz + i] = lambda_next[i];\n    }\n    //\n    return;\n}\n// ---------------------------------------------------------------------------\n// reverse_one\n// AD version of first order reverse mode calculation as in Theory above\ntemplate <class Base>\nvoid atomic_lin_ode<Base>::reverse_one(\n    const size_t&                              call_id     ,\n    const CppAD::vector<bool>&                 select_x    ,\n    const CppAD::vector< CppAD::AD<Base> >&    ax          ,\n    const CppAD::vector< CppAD::AD<Base> >&    aw          ,\n    CppAD::vector< CppAD::AD<Base> >&          apartial_x  )\n{   typedef CppAD::AD<Base> ad_base;\n    //\n    //\n    // r, step, pattern, transpose\n    Base       r;\n    Base       step;\n    sparse_rc pattern;\n    bool      transpose;\n    get(call_id, step, r, pattern, transpose);\n    //\n    // nnz\n    size_t nnz = pattern.nnz();\n    //\n    // m\n    size_t m = aw.size();\n    CPPAD_ASSERT_UNKNOWN( aw.size() == m );\n    CPPAD_ASSERT_UNKNOWN( pattern.nr() == m );\n    CPPAD_ASSERT_UNKNOWN( pattern.nc() == m );\n    //\n    // n\n# ifndef NDEBUG\n    size_t n = nnz + m;\n# endif\n    //\n    // ax, apartial_x\n    CPPAD_ASSERT_UNKNOWN( ax.size()  == n );\n    CPPAD_ASSERT_UNKNOWN( apartial_x.size() == n );\n    //\n    // n_step\n    size_t n_step = 2;\n    if( step < abs(r) / Base(n_step) )\n        n_step = size_t( abs(r) / step );\n    while( step < abs(r) / Base(n_step) )\n        ++n_step;\n    if( n_step % 2 == 1 )\n        ++n_step;\n    CPPAD_ASSERT_UNKNOWN( n_step % 2 == 0 );\n    //\n    // h\n    Base h = r / Base(n_step);\n    //\n    // ax_tmp = [A, b]\n    CppAD::vector<ad_base> ax_tmp = ax;\n    //\n    // az_all\n    CppAD::vector< CppAD::vector<ad_base> > az_all(n_step + 1);\n    //\n    // az_all[0] = z(0, x)\n    az_all[0].resize(m);\n    for(size_t i = 0; i < m; ++i)\n        az_all[0][i] = ax[nnz + i];\n    //\n    // call_id_1\n    size_t call_id_1 = (*this).set(h, step, pattern, transpose);\n    //\n    // p\n    for(size_t p = 0; p < n_step; ++p)\n    {   // ax_tmp = [A, z(h*p, x) ]\n        for(size_t i = 0; i < nnz; ++i)\n            ax_tmp[nnz + i] = az_all[p][i];\n        //\n        // az_all[p+1] = az( h*(p+1), x)\n        // This interface requires a separate atomic function call for each\n        // step in the Simpson's rule integration. Perhaps it would be more\n        // efficient (but more complicated) to have an option whereby one call\n        // that returns all the values in az_all expect for az_all[0].\n        az_all[p+1].resize(m);\n        (*this)(call_id_1, ax_tmp, az_all[p+1]);\n    }\n    // alambda_previous = lambda(r, x) = w\n    CppAD::vector<ad_base> alambda_previous = aw;\n    //\n    // alambda_middle, alambda_next\n    CppAD::vector<ad_base> alambda_middle(m), alambda_next(m);\n    //\n    // apartial_x\n    // apartial_A L(x, lambda)\n    for(size_t k = 0; k < nnz; ++k)\n        apartial_x[k] = ad_base(0.0);\n    //\n    // call_id_2\n    size_t call_id_2 = (*this).set(h, step, pattern, ! transpose);\n    //\n    //\n    // p\n    size_t p = n_step - 1;\n    while(p)\n    {   CPPAD_ASSERT_UNKNOWN( p % 2 == 1 );\n        //\n        // ax_tmp = [ A, lambda( (p+1)*h, x ) ]\n        for(size_t i = 0; i < m; ++i)\n            ax_tmp[nnz + i] = alambda_previous[i];\n        //\n        // alambda_middle = lambda(p*h, x)\n        // We convert the final value ODE to an initial value ODE by changing\n        // the sign of A^T and changing limits from [(p+1)*h, p*h] -> [0, h].\n        (*this)(call_id_2, ax_tmp, alambda_middle);\n        //\n        // ax_tmp = [ A, lambda(p*h, x)]\n        for(size_t i = 0; i < m; ++i)\n            ax_tmp[nnz + i] = alambda_middle[i];\n        //\n        // alambda_next = lambda((p-1), x)\n        (*this)(call_id_2, ax_tmp, alambda_next);\n        //\n        // apartial_x\n        // partail_A L(x, lambda)\n        for(size_t k = 0; k < nnz; ++k) if( select_x[k] )\n        {   size_t i = pattern.row()[k];\n            size_t j = pattern.col()[k];\n            if( transpose )\n                std::swap(i, j);\n            //\n            // asum  = lambda_i ((p+1)*h, x) * z_j ((p+1)*h, x)\n            ad_base asum = alambda_previous[i] * az_all[p+1][j];\n            //\n            // asum += 4 * lambad_i(p*h, x) * z_j(p*h, x)\n            asum += ad_base(4.0) * alambda_middle[i] * az_all[p][j];\n            //\n            // asum += lambda_i ((p-1)*h, x) * z_j ((p-1)*h, x)\n            asum += alambda_next[i] * az_all[p-1][j];\n            //\n            // Simpson's rule for int_0^2*h lambda_i (t, x) z_j (t, x) dt\n            ad_base aintegral = h * asum / ad_base(3.0);\n            //\n            // apartial_x\n            // partial_{A(i,j)}\n            apartial_x[k] += aintegral;\n        }\n        //\n        // alambda_previous\n        alambda_previous = alambda_next;\n        //\n        // p\n        if( p == 1 )\n            p = 0;\n        else\n            p -= 2;\n    }\n    //\n    // apartial_x\n    // partial_b L(x, lambda) = lambda(0, x)\n    for(size_t i = 0; i < m; ++i)\n    {   // partial_{b(i)}\n        apartial_x[nnz + i] = alambda_next[i];\n    }\n    //\n    return;\n}\n} // END_CPPAD_NAMESPACE\n// END C++\n# endif\n"
  },
  {
    "path": "include/cppad/example/atomic_four/lin_ode/reverse_2.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin atomic_four_lin_ode_reverse_2}\n\nAtomic Linear ODE Second Order Reverse\n######################################\n\nx^1 Partial\n***********\nWe need to compute\n\n.. math::\n\n    \\R{partial\\_x} [ j  * q + 1 ]\n    =\n    \\sum_{i=0}^{m-1} \\R{partial\\_y} [ i * q + 1]\n        ( \\partial y_i^1 ( x^0 , x^1 ) / \\partial x_j^1 )\n\nwhere :math:`q = 2` and :math:`j = 0 , \\ldots , n-1`.\nUsing the :ref:`reverse_identity-name` we have\n\n.. math::\n\n    \\partial y_i^1 ( x^0 , x^1 ) / \\partial x_j^1\n    =\n    \\partial y_i^0 ( x^0 ) / \\partial x_j^0\n\n.. math::\n\n    \\R{partial\\_x} [ j  * q + 1 ]\n    =\n    \\sum_{i=0}^{m-1} \\R{partial\\_y} [ i * q + 1]\n        ( \\partial y_i^0 ( x^0 ) / \\partial x_j^0 )\n\nwhich is the same as the first order\n:ref:`theory<atomic_four_lin_ode_reverse.hpp@First Order Theory>` with\n\n.. math::\n\n    w_i = \\R{partial\\_y} [ i * q + 1]\n\nx^0 Partial\n***********\nWe also need to compute\n\n.. math::\n\n    \\R{partial\\_x} [ j  * q + 0 ]\n    =\n    \\sum_{i=0}^{m-1} \\R{partial\\_y} [ i * q + 0]\n        ( \\partial y_i^0 ( x^0 ) / \\partial x_j^0 )\n    +\n    \\R{partial\\_y} [ i * q + 1]\n        ( \\partial y_i^1 ( x^0 , x^1 ) / \\partial x_j^0 )\n\nNote that we can solve for\n\n.. math::\n\n    y^1 ( x^0 , x^1 ) = z^1 ( r , x^0 , x^1 )\n\nusing the following extended ODE; see\n:ref:`forward theory<atomic_four_lin_ode_forward.hpp@Theory>` .\n\n.. math::\n\n    \\left[ \\begin{array}{c}\n    z^0_t (t, x^0 ) \\\\\n    z^1_t (t, x^0 , x^1 )\n    \\end{array} \\right]\n    =\n    \\left[ \\begin{array}{cc}\n    A^0 & 0   \\\\\n    A^1 & A^0\n    \\end{array} \\right]\n    \\left[ \\begin{array}{c}\n    z^0 (t, x^0 ) \\\\\n    z^1 (t, x^0 , x^1 )\n    \\end{array} \\right]\n    \\; , \\;\n    \\left[ \\begin{array}{c}\n    z^0 (0, x^0 ) \\\\\n    z^1 (0, x^0 , x^1 )\n    \\end{array} \\right]\n    =\n    \\left[ \\begin{array}{c}\n    b^0 \\\\\n    b^1\n    \\end{array} \\right]\n\nNote that\n:math:`A^0`, :math:`b^0` are components of :math:`x^0`\nand\n:math:`A^1`, :math:`b^1` are components of :math:`x^1`.\nWe use the following notation\n\n.. math::\n\n    \\bar{x} = \\left[ \\begin{array}{c}\n        x^0 \\\\ x^1\n    \\end{array} \\right]\n    \\W{,}\n    \\bar{z}(t , \\bar{x} ) = \\left[ \\begin{array}{c}\n        z^0 (t, x^0) \\\\ z^1 ( t, x^0 , x^1 )\n    \\end{array} \\right]\n    \\W{,}\n    \\bar{A} =\n    \\left[ \\begin{array}{cc}\n    A^0 & 0   \\\\\n    A^1 & A^0\n    \\end{array} \\right]\n    \\W{,}\n    \\bar{b} = \\left[ \\begin{array}{c}\n        b^0 \\\\ b^1\n    \\end{array} \\right]\n\nUsing this notation we have\n\n.. math::\n\n    \\bar{z}_t ( t , \\bar{x} ) = \\bar{A} \\bar{z} (t, \\bar{x} )\n    \\W{,}\n    \\bar{z} (0, \\bar{x} ) = \\bar{b}\n\nDefine :math:`\\bar{w} \\in \\B{R}^{m + m}` by\n\n.. math::\n\n    \\bar{w}_i = \\R{partial\\_y}[ i * q + 0 ]\n    \\W{,}\n    \\bar{w}_{m + i} = \\R{partial\\_y}[ i * q + 1 ]\n\nFor this case, we can compute\n\n.. math::\n\n    \\partial_\\bar{x} \\bar{w}^\\R{T} \\bar{z}(r, \\bar{x} )\n\nwhich is same as the first order case but with the extended variables\nand extended ODE.\nWe will only use the components of\n:math:`\\partial_\\bar{x}` that correspond to partials w.r.t. :math:`x^0`.\n\n{xrst_end atomic_four_lin_ode_reverse_2}\n"
  },
  {
    "path": "include/cppad/example/atomic_four/lin_ode/set.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_ATOMIC_FOUR_LIN_ODE_SET_HPP\n# define CPPAD_EXAMPLE_ATOMIC_FOUR_LIN_ODE_SET_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_four_lin_ode_set.hpp}\n\natomic_lin_ode Set Routine: Example Implementation\n##################################################\n\nSyntax\n******\n| *call_id* = *lin_ode* . ``set`` ( *r* , *step* , *pattern* , *transpose* )\n\nPrototype\n*********\n{xrst_literal\n    include/cppad/example/atomic_four/lin_ode/lin_ode.hpp\n    // BEGIN sparse_rc_type\n    // END sparse_rc_type\n}\n{xrst_literal\n    // BEGIN PROTOTYPE\n    // END PROTOTYPE\n}\n\nPurpose\n*******\nStores the auxiliary information for a an atomic operation that computes\nthe solution of a linear ODE.\n\nr\n*\nThis argument is the final value for the variable that the ODE is with\nrespect to.\n\nstep\n****\nThis is a positive maximum step size to use when solving the ODE.\n\npattern\n*******\nThis argument is a sparsity pattern.\nIt would be ``const`` except for the fact that\n*pattern.set_row_major* () is called so that checking for\nequality is faster; see\n:ref:`sparse_rc@set_row_major` .\n\ntranspose\n*********\nIf this argument is true (false) the sparsity pattern is for\n:math:`A(x)\\R{T}` (:math:`A(x)`).\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end atomic_four_lin_ode_set.hpp}\n*/\n// BEGIN C++\n# include <cppad/example/atomic_four/lin_ode/lin_ode.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n// BEGIN PROTOTYPE\ntemplate <class Base>\nsize_t atomic_lin_ode<Base>::set(\n    const Base& r, const Base& step, sparse_rc& pattern, const bool& transpose\n)\n// END PROTOTYPE\n{\n    // pattern\n    // set_row_major so that checking for pattern equality is faster\n    pattern.set_row_major();\n    //\n    // thread\n    size_t thread = thread_alloc::thread_num();\n    //\n    // work_[thread]\n    if( work_[thread] == nullptr )\n        work_[thread] = new thread_struct;\n    //\n    // pattern_vec\n    CppAD::vector<sparse_rc>& pattern_vec( work_[thread]->pattern_vec );\n    //\n    // pattern_index\n    size_t     n_pattern     = pattern_vec.size();\n    size_t     pattern_index = n_pattern;\n    for(size_t i = 0; i < n_pattern; ++i)\n        if( pattern == pattern_vec[i] )\n            pattern_index = i;\n    if( pattern_index == n_pattern )\n    {   pattern_vec.push_back( pattern );\n        CPPAD_ASSERT_UNKNOWN( pattern_vec[pattern_index] == pattern );\n    }\n    //\n    // call_vec\n    CppAD::vector<call_struct>& call_vec( work_[thread]->call_vec );\n    //\n    // call_id\n    size_t call_id = call_vec.size();\n    //\n    // call\n    call_struct call;\n    call.thread        = thread;\n    call.r             = r;\n    call.step          = step;\n    call.pattern_index = pattern_index;\n    call.transpose     = transpose;\n    //\n    // work_[thread]\n    call_vec.push_back( call );\n    //\n    return call_id;\n}\n} // END_CPPAD_NAMESPACE\n// END C++\n# endif\n"
  },
  {
    "path": "include/cppad/example/atomic_four/mat_mul/base_mat_mul.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_ATOMIC_FOUR_MAT_MUL_BASE_MAT_MUL_HPP\n# define CPPAD_EXAMPLE_ATOMIC_FOUR_MAT_MUL_BASE_MAT_MUL_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_four_mat_mul_base_mat_mul.hpp}\n\nAtomic Multiply Base Matrices: Example Implementation\n#####################################################\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end atomic_four_mat_mul_base_mat_mul.hpp}\n*/\n// BEGIN C++\n# include <cppad/example/atomic_four/mat_mul/mat_mul.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n//\n// base_mat_mul\ntemplate <class Base>\nvoid atomic_mat_mul<Base>::base_mat_mul(\n    size_t                         n_left      ,\n    size_t                         n_middle    ,\n    size_t                         n_right     ,\n    const CppAD::vector<Base>&     x           ,\n    CppAD::vector<Base>&           y           )\n{\n# ifndef NDEBUG\n    // n, m\n    size_t n     = x.size();\n    size_t m     = y.size();\n    //\n    // check sizes\n    assert( n == n_middle * (n_left + n_right ) );\n    assert( m == n_left * n_right );\n# endif\n    //\n    // offset\n    size_t offset = n_left * n_middle;\n    //\n    // y\n    // y[ i * n_right + j] = sum_k\n    //      x[i * n_middle + k] * x[ offset + k * n_right + j]\n    // type_y\n    for(size_t i = 0; i < n_left; ++i)\n    {   for(size_t j = 0; j < n_right; ++j)\n        {   Base sum_ij = Base(0);\n            for(size_t k = 0; k < n_middle; ++k)\n            {   Base left_ik  = x[i * n_middle + k];\n                Base right_kj = x[offset + k * n_right + j];\n                sum_ij       += left_ik * right_kj;\n            }\n            y[i * n_right + j] = sum_ij;\n        }\n    }\n    return;\n}\n} // END_CPPAD_NAMESPACE\n// END C++\n# endif\n"
  },
  {
    "path": "include/cppad/example/atomic_four/mat_mul/for_type.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_ATOMIC_FOUR_MAT_MUL_FOR_TYPE_HPP\n# define CPPAD_EXAMPLE_ATOMIC_FOUR_MAT_MUL_FOR_TYPE_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_four_mat_mul_for_type.hpp}\n\nAtomic Matrix Multiply Forward Type Calculation: Example Implementation\n#######################################################################\n\nPurpose\n*******\nThe ``for_type`` routine overrides the virtual functions\nused by the atomic_four base; see\n:ref:`for_type<atomic_four_for_type-name>` .\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end atomic_four_mat_mul_for_type.hpp}\n*/\n// BEGIN C++\n# include <cppad/example/atomic_four/mat_mul/mat_mul.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n//\n// for_type override\ntemplate <class Base>\nbool atomic_mat_mul<Base>::for_type(\n    size_t                                     call_id     ,\n    const CppAD::vector<CppAD::ad_type_enum>&  type_x      ,\n    CppAD::vector<CppAD::ad_type_enum>&        type_y      )\n{\n    //\n    // n_left, n_middle, n_right\n    size_t n_left, n_middle, n_right;\n    get(call_id, n_left, n_middle, n_right);\n# ifndef NDEBUG\n    // n, m\n    size_t n     = type_x.size();\n    size_t m     = type_y.size();\n    //\n    // check sizes\n    assert( n == n_left * n_middle + n_middle * n_right );\n    assert( m == n_left * n_right );\n# endif\n    //\n    // offset\n    size_t offset = n_left * n_middle;\n    //\n    // type_y\n    // y[ i * n_right + j] = sum_k\n    //      x[i * n_middle + k] * x[ offset + k * n_right + j]\n    // treat multiplication by zero like absolute zero\n    for(size_t i = 0; i < n_left; ++i)\n    {   for(size_t j = 0; j < n_right; ++j)\n        {   CppAD::ad_type_enum type_ij = CppAD::identical_zero_enum;\n            for(size_t k = 0; k < n_middle; ++k)\n            {   CppAD::ad_type_enum type_ik = type_x[i * n_middle + k];\n                CppAD::ad_type_enum type_kj = type_x[offset + k * n_right + j];\n                if( type_ik != identical_zero_enum )\n                {   if( type_kj != identical_zero_enum )\n                    {   type_ij = std::max(type_ij, type_ik);\n                        type_ij = std::max(type_ij, type_kj);\n                    }\n                }\n            }\n            type_y[ i * n_right + j] = type_ij;\n        }\n    }\n    return true;\n}\n} // END_CPPAD_NAMESPACE\n// END C++\n# endif\n"
  },
  {
    "path": "include/cppad/example/atomic_four/mat_mul/forward.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_ATOMIC_FOUR_MAT_MUL_FORWARD_HPP\n# define CPPAD_EXAMPLE_ATOMIC_FOUR_MAT_MUL_FORWARD_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_four_mat_mul_forward.hpp}\n\nAtomic Matrix Multiply Forward Mode: Example Implementation\n###########################################################\n\nPurpose\n*******\nThe ``forward`` routine overrides the virtual functions\nused by the atomic_four base; see\n:ref:`forward<atomic_four_forward-name>` .\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end atomic_four_mat_mul_forward.hpp}\n*/\n// BEGIN C++\n# include <cppad/example/atomic_four/mat_mul/mat_mul.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n//\n// forward override for Base matrix multiply\ntemplate <class Base>\nbool atomic_mat_mul<Base>::forward(\n    size_t                                     call_id     ,\n    const CppAD::vector<bool>&                 select_y    ,\n    size_t                                     order_low   ,\n    size_t                                     order_up    ,\n    const CppAD::vector<Base>&                 taylor_x    ,\n    CppAD::vector<Base>&                       taylor_y    )\n{\n    // q\n    size_t q     = order_up + 1;\n    //\n    // n_left, n_middle, n_right\n    size_t n_left, n_middle, n_right;\n    get(call_id, n_left, n_middle, n_right);\n# ifndef NDEBUG\n    // n, m\n    size_t n     = taylor_x.size();\n    size_t m     = taylor_y.size();\n    //\n    // check sizes\n    assert( n == n_middle * ( n_left +  n_right ) * q );\n    assert( m == n_left * n_right * q );\n# endif\n    //\n    // offset\n    size_t offset = n_left * n_middle;\n    //\n    // for k = order_low, ..., order_up :\n    //    C^k = sum_ell A^ell * B^{k-ell}\n    CppAD::vector<Base> x( n_middle * ( n_left + n_right) );\n    CppAD::vector<Base> y(n_left * n_right);\n    CppAD::vector<Base> sum(n_left * n_right);\n    for(size_t k = order_low; k < q; ++k)\n    {   // sum = 0\n        for(size_t i = 0; i < n_left * n_right; ++i)\n            sum[i] = Base(0);\n        for(size_t ell = 0; ell <= k; ++ell)\n        {   // x = [ A^ell, B^{k-ell} ]\n            for(size_t i = 0; i < n_left * n_middle; ++i)\n                x[i] = taylor_x[ i * q + ell ];\n            for(size_t i = 0; i < n_middle * n_right; ++i)\n                x[offset + i] = taylor_x[ (offset + i) * q + (k - ell) ];\n            //\n            // y = A^ell * B^{k-ell}\n            base_mat_mul(n_left, n_middle, n_right, x, y);\n            //\n            // sum += y\n            for(size_t i = 0; i < n_left * n_right; ++i)\n                sum[i] += y[i];\n        }\n        // C^k = sum\n        for(size_t i = 0; i < n_left * n_right; ++i)\n            taylor_y[i * q + k] = sum[i];\n    }\n    return true;\n}\n//\n// forward override for AD<Base> matrix multiply\ntemplate <class Base>\nbool atomic_mat_mul<Base>::forward(\n    size_t                                     call_id     ,\n    const CppAD::vector<bool>&                 select_y    ,\n    size_t                                     order_low   ,\n    size_t                                     order_up    ,\n    const CppAD::vector< CppAD::AD<Base> >&    ataylor_x   ,\n    CppAD::vector< CppAD::AD<Base> >&          ataylor_y   )\n{   //\n    // vector, AD\n    using CppAD::vector;\n    using CppAD::AD;\n    // q\n    size_t q     = order_up + 1;\n    //\n    // n_left, n_middle, n_right\n    size_t n_left, n_middle, n_right;\n    get(call_id, n_left, n_middle, n_right);\n# ifndef NDEBUG\n    // n, m\n    size_t n     = ataylor_x.size();\n    size_t m     = ataylor_y.size();\n    //\n    // check sizes\n    assert( n == n_middle * ( n_left +  n_right ) * q );\n    assert( m == n_left * n_right * q );\n# endif\n    //\n    // offset\n    size_t offset = n_left * n_middle;\n    //\n    // for k = order_low, ..., order_up :\n    //    C^k = sum_ell A^ell * B^{k-ell}\n    vector< AD<Base> > ax( n_middle *( n_left + n_right) );\n    vector< AD<Base> > ay(n_left * n_right);\n    vector< AD<Base> > asum(n_left * n_right);\n    for(size_t k = order_low; k < q; ++k)\n    {   // sum = 0\n        for(size_t i = 0; i < n_left * n_right; ++i)\n            asum[i] = AD<Base>(0);\n        for(size_t ell = 0; ell <= k; ++ell)\n        {   // ax = [ A^ell, B^{k-ell} ]\n            for(size_t i = 0; i < n_left * n_middle; ++i)\n                ax[i] = ataylor_x[ i * q + ell ];\n            for(size_t i = 0; i < n_middle * n_right; ++i)\n                ax[offset + i] = ataylor_x[ (offset + i) * q + (k - ell) ];\n            //\n            // ay = A^ell * B^{k-ell}\n            (*this)(call_id, ax, ay);\n            //\n            // asum += ay\n            for(size_t i = 0; i < n_left * n_right; ++i)\n                asum[i] += ay[i];\n        }\n        // C^k = asum\n        for(size_t i = 0; i < n_left * n_right; ++i)\n            ataylor_y[i * q + k] = asum[i];\n    }\n    return true;\n}\n} // END_CPPAD_NAMESPACE\n// END C++\n# endif\n"
  },
  {
    "path": "include/cppad/example/atomic_four/mat_mul/get.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_ATOMIC_FOUR_MAT_MUL_GET_HPP\n# define CPPAD_EXAMPLE_ATOMIC_FOUR_MAT_MUL_GET_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_four_mat_mul_get.hpp}\n\natomic_mat_mul Get Routine: Example Implementation\n##################################################\n\nSyntax\n******\n| ``mat_mul`` . *get* ( ``call_id`` , ``n_left`` , ``n_middle`` , ``n_right`` )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN PROTOTYPE\n    // END PROTOTYPE\n}\n\nPurpose\n*******\nRetrieves the dimension information for a an atomic operation that computes\nthe matrix product *R* = *A* * *B* .\n\ncall_id\n*******\nThis argument identifies the dimension information for this matrix product.\n\nn_left\n******\nThis result is the row dimension of the matrices *A* and *R* .\n\nn_middle\n********\nThis result is the column dimension of the matrix *A*\nand row dimension of the matrix *B* .\n\nn_right\n*******\nThis result is the column dimension of the matrices *B* and *R* .\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end atomic_four_mat_mul_get.hpp}\n*/\n// BEGIN C++\n# include <cppad/example/atomic_four/mat_mul/mat_mul.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n// BEGIN PROTOTYPE\ntemplate <class Base>\nvoid atomic_mat_mul<Base>::get(\n    size_t call_id, size_t& n_left, size_t& n_middle, size_t& n_right\n)\n// END PROTOTYPE\n{\n    // thread\n    size_t thread = thread_alloc::thread_num();\n    assert( work_[thread] != nullptr );\n    assert( thread == (*work_[thread])[call_id].thread );\n    //\n    // n_left, n_middle, n_right\n    call_struct& call = (*work_[thread])[call_id];\n    n_left   = call.n_left;\n    n_middle = call.n_middle;\n    n_right  = call.n_right;\n    //\n    return;\n}\n} // END_CPPAD_NAMESPACE\n// END C++\n# endif\n"
  },
  {
    "path": "include/cppad/example/atomic_four/mat_mul/hes_sparsity.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_ATOMIC_FOUR_MAT_MUL_HES_SPARSITY_HPP\n# define CPPAD_EXAMPLE_ATOMIC_FOUR_MAT_MUL_HES_SPARSITY_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_four_mat_mul_hes_sparsity.hpp}\n\nAtomic Matrix Multiply Jacobian Sparsity Pattern: Example Implementation\n########################################################################\n\nPurpose\n*******\nThe ``hes_sparsity`` routine overrides the virtual functions\nused by the atomic_four base class for Jacobian sparsity calculations; see\n:ref:`hes_sparsity<atomic_four_hes_sparsity-name>` .\n\nExample\n*******\nThe file :ref:`atomic_four_mat_mul_sparsity.cpp-name`\ncontains an example and test using this operator.\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end atomic_four_mat_mul_hes_sparsity.hpp}\n*/\n// BEGIN C++\n# include <cppad/example/atomic_four/mat_mul/mat_mul.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n//\n// hes_sparsity override\ntemplate <class Base>\nbool atomic_mat_mul<Base>::hes_sparsity(\n    size_t                                         call_id      ,\n    const CppAD::vector<bool>&                     ident_zero_x ,\n    const CppAD::vector<bool>&                     select_x     ,\n    const CppAD::vector<bool>&                     select_y     ,\n    CppAD::sparse_rc< CppAD::vector<size_t> >&     pattern_out  )\n{\n    // n_left, n_middle, n_right\n    size_t n_left, n_middle, n_right;\n    get(call_id, n_left, n_middle, n_right);\n    //\n    // n\n    size_t n     = select_x.size();\n    //\n    // check sizes\n# ifndef NDEBUG\n    size_t m     = select_y.size();\n    assert( n == n_middle * ( n_left +  n_right ) );\n    assert( m == n_left * n_right );\n# endif\n    //\n    // offset\n    size_t offset = n_left * n_middle;\n    //\n    // pattern_out\n    pattern_out.resize(n, n, 0);\n    for(size_t i = 0; i < n_left; ++i)\n    {   for(size_t j = 0; j < n_right; ++j)\n        {   size_t ij = i * n_right + j;               // C_{i,j} = y[ij]\n            if( select_y[ij] ) for(size_t k = 0; k < n_middle; ++k)\n            {   size_t ik = i * n_middle + k;          // A_{i,k} = x[ik]\n                size_t kj = offset + k * n_right + j;  // B_{k,j} = x[kj]\n                if( select_x[ik] && select_x[kj] )\n                {   // an (ik, kj) pair can only occur once in this loop\n                    pattern_out.push_back(ik, kj);\n                    pattern_out.push_back(kj, ik);\n                }\n            }\n        }\n    }\n# ifndef NDEBUG\n    // sorting checks hat there are no duplicate entries\n    pattern_out.row_major();\n# endif\n    //\n    return true;\n}\n} // END_CPPAD_NAMESPACE\n// END C++\n# endif\n"
  },
  {
    "path": "include/cppad/example/atomic_four/mat_mul/implement.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin atomic_four_mat_mul_implement}\n\nImplementing Atomic Matrix Multiply\n###################################\n\nContents\n********\n{xrst_toc_table\n    include/cppad/example/atomic_four/mat_mul/mat_mul.hpp\n    include/cppad/example/atomic_four/mat_mul/set.hpp\n    include/cppad/example/atomic_four/mat_mul/get.hpp\n    include/cppad/example/atomic_four/mat_mul/base_mat_mul.hpp\n    include/cppad/example/atomic_four/mat_mul/for_type.hpp\n    include/cppad/example/atomic_four/mat_mul/forward.hpp\n    include/cppad/example/atomic_four/mat_mul/reverse.hpp\n    include/cppad/example/atomic_four/mat_mul/jac_sparsity.hpp\n    include/cppad/example/atomic_four/mat_mul/hes_sparsity.hpp\n    include/cppad/example/atomic_four/mat_mul/rev_depend.hpp\n}\n\n{xrst_end atomic_four_mat_mul_implement}\n"
  },
  {
    "path": "include/cppad/example/atomic_four/mat_mul/jac_sparsity.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_ATOMIC_FOUR_MAT_MUL_JAC_SPARSITY_HPP\n# define CPPAD_EXAMPLE_ATOMIC_FOUR_MAT_MUL_JAC_SPARSITY_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_four_mat_mul_jac_sparsity.hpp}\n\nAtomic Matrix Multiply Jacobian Sparsity Pattern: Example Implementation\n########################################################################\n\nPurpose\n*******\nThe ``jac_sparsity`` routine overrides the virtual functions\nused by the atomic_four base class for Jacobian sparsity calculations; see\n:ref:`jac_sparsity<atomic_four_jac_sparsity-name>` .\n\nExample\n*******\nThe file :ref:`atomic_four_mat_mul_sparsity.cpp-name`\ncontains an example and test using this operator.\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end atomic_four_mat_mul_jac_sparsity.hpp}\n*/\n// BEGIN C++\n# include <cppad/example/atomic_four/mat_mul/mat_mul.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n//\n// jac_sparsity override\ntemplate <class Base>\nbool atomic_mat_mul<Base>::jac_sparsity(\n    size_t                                         call_id      ,\n    bool                                           dependency   ,\n    const CppAD::vector<bool>&                     ident_zero_x ,\n    const CppAD::vector<bool>&                     select_x     ,\n    const CppAD::vector<bool>&                     select_y     ,\n    CppAD::sparse_rc< CppAD::vector<size_t> >&     pattern_out  )\n{\n    // n_left, n_middle, n_right\n    size_t n_left, n_middle, n_right;\n    get(call_id, n_left, n_middle, n_right);\n    //\n    // n, m\n    size_t n     = select_x.size();\n    size_t m     = select_y.size();\n    //\n    // check sizes\n    assert( n == n_middle * ( n_left +  n_right ) );\n    assert( m == n_left * n_right );\n    //\n    // offset\n    size_t offset = n_left * n_middle;\n    //\n    // pattern_out\n    pattern_out.resize(m, n, 0);\n    for(size_t i = 0; i < n_left; ++i)\n    {   for(size_t j = 0; j < n_right; ++j)\n        {   size_t ij = i * n_right + j;               // C_{i,j} = y[ij]\n            if( select_y[ij] ) for(size_t k = 0; k < n_middle; ++k)\n            {   size_t ik = i * n_middle + k;          // A_{i,k} = x[ik]\n                size_t kj = offset + k * n_right + j;  // B_{k,j} = x[kj]\n                if( select_x[ik] && ! ident_zero_x[kj] )\n                    pattern_out.push_back(ij, ik);\n                if( select_x[kj] && ! ident_zero_x[ij] )\n                    pattern_out.push_back(ij, kj);\n            }\n        }\n    }\n    //\n    return true;\n}\n} // END_CPPAD_NAMESPACE\n// END C++\n# endif\n"
  },
  {
    "path": "include/cppad/example/atomic_four/mat_mul/mat_mul.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_ATOMIC_FOUR_MAT_MUL_MAT_MUL_HPP\n# define CPPAD_EXAMPLE_ATOMIC_FOUR_MAT_MUL_MAT_MUL_HPP\n\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-23 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_four_mat_mul.hpp}\n\nAtomic Matrix Multiply Class: Example Implementation\n####################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end atomic_four_mat_mul.hpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n//\ntemplate <class Base>\nclass atomic_mat_mul : public CppAD::atomic_four<Base> {\n//\npublic:\n    // ctor\n    atomic_mat_mul(const std::string& name) :\n    CppAD::atomic_four<Base>(name)\n    {   for(size_t thread = 0; thread < CPPAD_MAX_NUM_THREADS; ++thread)\n            work_[thread] = nullptr;\n    }\n    // destructor\n    ~atomic_mat_mul(void)\n    {   for(size_t thread = 0; thread < CPPAD_MAX_NUM_THREADS; ++thread)\n        {   if( work_[thread] != nullptr  )\n            {   // allocated in set member function\n                delete work_[thread];\n            }\n        }\n    }\n    // set\n    size_t set(\n        size_t n_left, size_t n_right, size_t n_middle\n    );\n    // get\n    void get(\n        size_t call_id, size_t& n_left, size_t& n_right, size_t& n_middle\n    );\nprivate:\n    //\n    // matrix dimensions corresponding to a call_id\n    struct call_struct {\n        size_t n_left; size_t n_middle; size_t n_right; size_t thread;\n    };\n    // map from call_id to matrix dimensions\n    typedef CppAD::vector<call_struct> call_vector;\n    //\n    // Use pointers, to avoid false sharing between threads.\n    call_vector* work_[CPPAD_MAX_NUM_THREADS];\n    //\n    // base_mat_mul\n    static void base_mat_mul(\n        size_t                     n_left     ,\n        size_t                     n_middle   ,\n        size_t                     n_right    ,\n        const CppAD::vector<Base>& x          ,\n        CppAD::vector<Base>&       y\n    );\n    //\n    // -----------------------------------------------------------------------\n    // overrides\n    // -----------------------------------------------------------------------\n    //\n    // for_type\n    bool for_type(\n        size_t                                        call_id,\n        const CppAD::vector<CppAD::ad_type_enum>&     type_x,\n        CppAD::vector<CppAD::ad_type_enum>&           type_y\n    ) override;\n    //\n    // Base forward\n    bool forward(\n        size_t                                           call_id,\n        const CppAD::vector<bool>&                       select_y,\n        size_t                                           order_low,\n        size_t                                           order_up,\n        const CppAD::vector<Base>&                       taylor_x,\n        CppAD::vector<Base>&                             taylor_y\n    ) override;\n    //\n    // AD<Base> forward\n    bool forward(\n        size_t                                           call_id,\n        const CppAD::vector<bool>&                       select_y,\n        size_t                                           order_low,\n        size_t                                           order_up,\n        const CppAD::vector< CppAD::AD<Base> >&          ataylor_x,\n        CppAD::vector< CppAD::AD<Base> >&                ataylor_y\n    ) override;\n    //\n    // Base reverse\n    bool reverse(\n        size_t                                           call_id,\n        const CppAD::vector<bool>&                       select_x,\n        size_t                                           order_up,\n        const CppAD::vector<Base>&                       taylor_x,\n        const CppAD::vector<Base>&                       taylor_y,\n        CppAD::vector<Base>&                             partial_x,\n        const CppAD::vector<Base>&                       partial_y\n    ) override;\n    //\n    // AD<Base> reverse\n    bool reverse(\n        size_t                                           call_id,\n        const CppAD::vector<bool>&                       select_x,\n        size_t                                           order_up,\n        const CppAD::vector< CppAD::AD<Base> >&          ataylor_x,\n        const CppAD::vector< CppAD::AD<Base> >&          ataylor_y,\n        CppAD::vector< CppAD::AD<Base> >&                apartial_x,\n        const CppAD::vector< CppAD::AD<Base> >&          apartial_y\n    ) override;\n    //\n    // jac_sparsity\n    bool jac_sparsity(\n        size_t                                         call_id,\n        bool                                           dependency,\n        const CppAD::vector<bool>&                     ident_zero_x,\n        const CppAD::vector<bool>&                     select_x,\n        const CppAD::vector<bool>&                     select_y,\n        CppAD::sparse_rc< CppAD::vector<size_t> >&     pattern_out\n    ) override;\n    //\n    // hes_sparsity\n    bool hes_sparsity(\n        size_t                                         call_id,\n        const CppAD::vector<bool>&                     ident_zero_x,\n        const CppAD::vector<bool>&                     select_x,\n        const CppAD::vector<bool>&                     select_y,\n        CppAD::sparse_rc< CppAD::vector<size_t> >&     pattern_out\n    ) override;\n    //\n    // rev_depend\n    bool rev_depend(\n        size_t                                         call_id,\n        const CppAD::vector<bool>&                     ident_zero_x,\n        CppAD::vector<bool>&                           depend_x,\n        const CppAD::vector<bool>&                     depend_y\n    ) override;\n};\n} // END_CPPAD_NAMESPACE\n\n# include <cppad/example/atomic_four/mat_mul/set.hpp>\n# include <cppad/example/atomic_four/mat_mul/get.hpp>\n# include <cppad/example/atomic_four/mat_mul/base_mat_mul.hpp>\n# include <cppad/example/atomic_four/mat_mul/for_type.hpp>\n# include <cppad/example/atomic_four/mat_mul/forward.hpp>\n# include <cppad/example/atomic_four/mat_mul/reverse.hpp>\n# include <cppad/example/atomic_four/mat_mul/jac_sparsity.hpp>\n# include <cppad/example/atomic_four/mat_mul/hes_sparsity.hpp>\n# include <cppad/example/atomic_four/mat_mul/rev_depend.hpp>\n// END C++\n\n# endif\n"
  },
  {
    "path": "include/cppad/example/atomic_four/mat_mul/mat_mul.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin atomic_four_mat_mul}\n{xrst_spell\n    tr\n}\n\nAtomic Matrix Multiply Class: Example Implementation\n####################################################\n\nSyntax\n******\n| ``atomic_mat_mul`` *mat_mul* ( *name* )\n| *call_id* = *mat_mul* . ``set`` ( *n_left* , *n_middle* , *n_right* )\n| *mat_mul* . ``get`` ( *call_id* , *n_left* , *n_middle* , *n_right* )\n| *mat_mul* ( *call_id* , *x* , *y* )\n\nPurpose\n*******\nConstruct an atomic operation that computes the matrix product\n*C* = *A* * *B* .\n\nn_left\n******\nThis is the row dimension of the matrices *A* and *C* .\nThis is an argument (return value) for the ``set`` (``get`` ) routine.\n\nn_middle\n********\nThis is the column dimension of the matrix *A*\nand row dimension of the matrix *B*\nThis is an argument (return value) for the ``set`` (``get`` ) routine.\n\nn_right\n*******\nThis is the column dimension of the matrices *B* and *C* .\nThis is an argument (return value) for the ``set`` (``get`` ) routine.\n\ncall_id\n*******\nThis is a return value (argument) for the ``set`` (``get`` ) routine.\n\nx\n*\nWe use *x* to denote the argument to the atomic function.\nThe size of this vector must be\n\n    *n* = *n_left* * *n_middle* + *n_middle* * *n_right*\n\nThe matrix *A* is stored in row major order at the beginning of\n*x* ; i.e. its ( *i* , *k* ) element is\n\n    *A* ( *i* , *k* ) = *x* [ *i* * *n_middle* + *k* ]\n\nThe matrix *B* is stored in row major order at the end of\n*x* ; i.e. its ( *k* , *j* ) element is\n\n    *B* ( *k* , *j* ) = *x* [ *n_left* * *n_middle* + *k* * *n_right* + *j* ]\n\ny\n*\nWe use *y* to denote the result of the atomic function.\nThe size of this vector must be\n*m* = *n_middle* * *n_right* .\nThe matrix *C* is stored in row major order in *y* ;\ni.e. its ( *i* , *k* ) element is\n\n    *C* ( *i* , *j* ) = *y* [ *i* * *n_right* + *j* ]\n\nTheory\n******\n\nForward\n=======\nFor :math:`k = 0 , \\ldots`, the *k*-th order Taylor coefficient\n:math:`C^{(k)}` is given by\n\n.. math::\n\n    C^{(k)} = \\sum_{\\ell = 0}^{k} A^{(\\ell)} B^{(k-\\ell)}\n\nMatrix Argument Scalar Valued Function\n======================================\nSuppose :math:`\\bar{F}` is the derivative of the\nscalar value function :math:`s(F)` with respect to the matrix :math:`F`; i.e.,\n\n.. math::\n\n    \\bar{F}_{i,j} = \\frac{ \\partial s } { \\partial F_{i,j} }\n\nAlso suppose that :math:`t` is a scalar valued argument and\n\n.. math::\n\n    F(t) = D(t) E(t)\n\nIt follows that\n\n.. math::\n\n    F'(t) = D'(t) E(t) +  D(t) E'(t)\n\n.. math::\n\n    (s \\circ F)'(t)\n    =\n    \\R{tr} [ \\bar{F}^\\R{T} F'(t) ]\n\n.. math::\n\n    =\n    \\R{tr} [ \\bar{F}^\\R{T} D'(t) E(t) ] +\n    \\R{tr} [ \\bar{F}^\\R{T} D(t) E'(t) ]\n\n.. math::\n\n    =\n    \\R{tr} [ E(t) \\bar{F}^\\R{T} D'(t) ] +\n    \\R{tr} [ \\bar{F}^\\R{T} D(t) E'(t) ]\n\nLetting :math:`E(t) = 0` and :math:`D(t) = \\Delta^{i,j} (t)`\n(where :math:`\\Delta^{i,j} (t)` is the matrix that is zero,\nexcept for :math:`i = j` where it is :math:`t`) we have\n\n.. math::\n\n    \\bar{D}_{i,j}\n    = \\frac{ \\partial s } { \\partial D_{i,j} }\n    = (s \\circ F)'(t)\n    = \\R{tr} [ E(t) \\bar{F}^\\R{T} \\Delta^{i,j}(1) ]\n\n.. math::\n\n    \\bar{D}_{i,j}\n    = \\sum_k D_{j,k} \\bar{F}^\\R{T}_{k,i}\n    = \\sum_k \\bar{F}_{i,k} E^\\R{T}_{k,j}\n\n.. math::\n\n    \\bar{D} = \\bar{F} E^\\R{T}\n\nLetting :math:`D(t) = 0` and :math:`E(t) = \\Delta^{i,j} (t)`\nwe have\n\n.. math::\n\n    \\bar{E}_{i,j}\n    = \\frac{ \\partial s } { \\partial E_{i,j} }\n    = (s \\circ F)'(t)\n    = \\R{tr} [ \\bar{F}^\\R{T} D(t) \\Delta^{i,j} ]\n\n.. math::\n\n    \\bar{E}_{i,j}\n    = \\sum_k \\bar{F}^\\R{T}_{j,k} C_{k,i}\n    = \\sum_k D^\\R{T}_{i,k} \\bar{F}_{k,j}\n\n.. math::\n\n    \\bar{E} = D^\\R{T} \\bar{F}\n\nReverse\n=======\nReverse mode eliminates :math:`C^{(k)}` as follows:\nfor :math:`\\ell = 0, \\ldots , k`,\n\n.. math::\n\n    \\bar{A}^{(\\ell)}  = \\bar{A}^{(\\ell)} + \\bar{C}^{(k)} [ B^{(k-\\ell)} ] ^\\R{T}\n\n.. math::\n\n    \\bar{B}^{(k-\\ell)} =  \\bar{B}^{(k-\\ell)} + [ A^{(\\ell)} ]^\\R{T} \\bar{C}^{(k)}\n\nContents\n********\n{xrst_toc_table\n    include/cppad/example/atomic_four/mat_mul/implement.xrst\n    example/atomic_four/mat_mul/forward.cpp\n    example/atomic_four/mat_mul/reverse.cpp\n    example/atomic_four/mat_mul/sparsity.cpp\n    example/atomic_four/mat_mul/rev_depend.cpp\n    example/atomic_four/mat_mul/identical_zero.cpp\n}\n\n{xrst_end atomic_four_mat_mul}\n"
  },
  {
    "path": "include/cppad/example/atomic_four/mat_mul/rev_depend.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_ATOMIC_FOUR_MAT_MUL_REV_DEPEND_HPP\n# define CPPAD_EXAMPLE_ATOMIC_FOUR_MAT_MUL_REV_DEPEND_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-23 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_four_mat_mul_rev_depend.hpp}\n\nAtomic Matrix Multiply Reverse Dependency Analysis: Example Implementation\n##########################################################################\n\nPurpose\n*******\nThe ``rev_depend`` routine is used by :ref:`optimize-name`\nto reduce the number of variables in the recording of a function.\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end atomic_four_mat_mul_rev_depend.hpp}\n*/\n// BEGIN C++\n# include <cppad/example/atomic_four/mat_mul/mat_mul.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n//\n// rev_depend override\ntemplate <class Base>\nbool atomic_mat_mul<Base>::rev_depend(\n    size_t                         call_id  ,\n    const CppAD::vector<bool>&     ident_zero_x,\n    CppAD::vector<bool>&           depend_x ,\n    const CppAD::vector<bool>&     depend_y )\n{\n    //\n    // n_left, n_middle, n_right\n    size_t n_left, n_middle, n_right;\n    get(call_id, n_left, n_middle, n_right);\n# ifndef NDEBUG\n    // n, m\n    size_t n     = depend_x.size();\n    size_t m     = depend_y.size();\n    //\n    // check sizes\n    assert( n == n_left * n_middle + n_middle * n_right );\n    assert( m == n_left * n_right );\n# endif\n    //\n    // offset\n    size_t offset = n_left * n_middle;\n    //\n    // type_y\n    // y[ i * n_right + j] = sum_k\n    //      x[i * n_middle + k] * x[ offset + k * n_right + j]\n    // type_y\n    for(size_t i = 0; i < n_left; ++i)\n    {   for(size_t j = 0; j < n_right; ++j)\n        {   size_t ij = i * n_right + j;\n            if( depend_y[ij] )\n            {   for(size_t k = 0; k < n_middle; ++k)\n                {   size_t ik = i * n_middle + k;\n                    size_t kj = offset + k * n_right + j;\n                    depend_x[ik] = true;\n                    depend_x[kj] = true;\n                }\n            }\n        }\n    }\n    return true;\n}\n} // END_CPPAD_NAMESPACE\n// END C++\n# endif\n"
  },
  {
    "path": "include/cppad/example/atomic_four/mat_mul/reverse.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_ATOMIC_FOUR_MAT_MUL_REVERSE_HPP\n# define CPPAD_EXAMPLE_ATOMIC_FOUR_MAT_MUL_REVERSE_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_four_mat_mul_reverse.hpp}\n\nAtomic Matrix Multiply Reverse Mode: Example Implementation\n###########################################################\n\nPurpose\n*******\nThe ``reverse`` routine overrides the virtual functions\nused by the atomic_four base; see\n:ref:`reverse<atomic_four_reverse-name>` .\n\nTheory\n******\nSee mat_mul :ref:`atomic_four_mat_mul@Theory@Reverse` theory.\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end atomic_four_mat_mul_reverse.hpp}\n*/\n// BEGIN C++\n# include <cppad/example/atomic_four/mat_mul/mat_mul.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n//\n// reverse override for Base matrix multiply\ntemplate <class Base>\nbool atomic_mat_mul<Base>::reverse(\n    size_t                                     call_id     ,\n    const CppAD::vector<bool>&                 select_y    ,\n    size_t                                     order_up    ,\n    const CppAD::vector<Base>&                 taylor_x    ,\n    const CppAD::vector<Base>&                 taylor_y    ,\n    CppAD::vector<Base>&                       partial_x   ,\n    const CppAD::vector<Base>&                 partial_y   )\n{\n    // q\n    size_t q     = order_up + 1;\n    //\n    // n_left, n_middle, n_right\n    size_t n_left, n_middle, n_right;\n    get(call_id, n_left, n_middle, n_right);\n# ifndef NDEBUG\n    // n, m\n    size_t n     = taylor_x.size();\n    size_t m     = taylor_y.size();\n    //\n    // check sizes\n    assert( n == n_middle * ( n_left +  n_right ) * q );\n    assert( m == n_left * n_right * q );\n    assert( n == partial_x.size() );\n    assert( m == partial_y.size() );\n# endif\n    //\n    // offset\n    size_t x_offset = n_left * n_middle;\n    //\n    // u, v, u_offset\n    // note that resize only re-allocates when capacity is not large enough\n    CppAD::vector<Base> u;\n    CppAD::vector<Base> v;\n    size_t u_offset;\n    //\n    // partial_x\n    for(size_t i = 0; i < partial_x.size(); ++i)\n        partial_x[i] = Base(0);\n    //\n    // k\n    size_t k = q;\n    while(k > 0)\n    {   --k;\n        //\n        // for ell = 0, ..., k :\n        //    bar{A}^ell      += bar{C}^k [ B^{k-ell} ]^T\n        //    bar{B}^{k-ell}  += [ A^ell ]^T \\bar{C}^k\n        for(size_t ell = 0; ell < q; ++ell)\n        {   //\n            // u = [ \\bar{C}^k, B^{k-ell}^T ]\n            u.resize(0);\n            u.resize( n_left * n_right + n_right * n_middle );\n            u_offset = n_left * n_right;\n            for(size_t i = 0; i < n_left * n_right; ++i)\n                u[i] = partial_y[ i * q + k ];\n            for(size_t i = 0; i < n_middle; ++i)\n            {   for(size_t j = 0; j < n_right; ++j)\n                {   size_t ij = i * n_right + j;\n                    size_t ji = j * n_middle + i;\n                    u[u_offset + ji] =\n                        taylor_x[(x_offset + ij) * q + (k - ell) ];\n                }\n            }\n            //\n            // v = \\bar{C} * [ B^{k-ell} ]^T\n            v.resize(0);\n            v.resize( n_left * n_middle );\n            base_mat_mul(n_left, n_right, n_middle, u, v);\n            //\n            // \\bar{A}^ell += v\n            for(size_t i = 0; i < n_left * n_middle; ++i)\n                partial_x[i * q + ell] += v[i];\n            //\n            // u = [ A^ell^T , \\bar{C}^k ]\n            u.resize(0);\n            u.resize( n_middle * n_left + n_left * n_right );\n            u_offset = n_middle * n_left;\n            for(size_t i = 0; i < n_left; ++i)\n            {   for(size_t j = 0; j < n_middle; ++j)\n                {   size_t ij = i * n_middle + j;\n                    size_t ji = j * n_left + i;\n                    u[ji] = taylor_x[ij * q + ell];\n                }\n            }\n            for(size_t i = 0; i < n_left * n_right; ++i)\n                u[u_offset + i] = partial_y[ i * q + k ];\n            //\n            // v = [ A^ell ]^T * \\bar{C}^k\n            v.resize(0);\n            v.resize( n_middle * n_right );\n            base_mat_mul(n_middle, n_left, n_right, u, v);\n            //\n            // \\bar{B}^{k-\\ell} += v\n            for(size_t i = 0; i < n_middle * n_right; ++i)\n                partial_x[ (x_offset + i) * q + (k - ell) ] += v[i];\n        }\n    }\n    return true;\n}\n//\n// reverse override for AD<Base> matrix multiply\ntemplate <class Base>\nbool atomic_mat_mul<Base>::reverse(\n    size_t                                     call_id     ,\n    const CppAD::vector<bool>&                 select_y    ,\n    size_t                                     order_up    ,\n    const CppAD::vector< AD<Base> >&           ataylor_x   ,\n    const CppAD::vector< AD<Base> >&           ataylor_y   ,\n    CppAD::vector< AD<Base> >&                 apartial_x  ,\n    const CppAD::vector< AD<Base> >&           apartial_y  )\n{\n    // q\n    size_t q     = order_up + 1;\n    //\n    // n_left, n_middle, n_right\n    size_t n_left, n_middle, n_right;\n    get(call_id, n_left, n_middle, n_right);\n# ifndef NDEBUG\n    // n, m\n    size_t n     = ataylor_x.size();\n    size_t m     = ataylor_y.size();\n    //\n    // check sizes\n    assert( n == n_middle * ( n_left +  n_right ) * q );\n    assert( m == n_left * n_right * q );\n    assert( n == apartial_x.size() );\n    assert( m == apartial_y.size() );\n# endif\n    //\n    // offset\n    size_t x_offset = n_left * n_middle;\n    //\n    // u, v, u_offset\n    // note that resize only re-allocates when capacity is not large enough\n    CppAD::vector< AD<Base> > u;\n    CppAD::vector< AD<Base> > v;\n    size_t u_offset;\n    size_t i_call;\n    //\n    // apartial_x\n    for(size_t i = 0; i < apartial_x.size(); ++i)\n        apartial_x[i] =  AD<Base> (0);\n    //\n    // k\n    size_t k = q;\n    while(k > 0)\n    {   --k;\n        //\n        // for ell = 0, ..., k :\n        //    bar{A}^ell      += bar{C}^k [ B^{k-ell} ]^T\n        //    bar{B}^{k-ell}  += [ A^ell ]^T \\bar{C}^k\n        for(size_t ell = 0; ell < q; ++ell)\n        {   //\n            // u = [ \\bar{C}^k, B^{k-ell}^T ]\n            u.resize(0);\n            u.resize( n_left * n_right + n_right * n_middle );\n            u_offset = n_left * n_right;\n            for(size_t i = 0; i < n_left * n_right; ++i)\n                u[i] = apartial_y[ i * q + k ];\n            for(size_t i = 0; i < n_middle; ++i)\n            {   for(size_t j = 0; j < n_right; ++j)\n                {   size_t ij = i * n_right + j;\n                    size_t ji = j * n_middle + i;\n                    u[u_offset + ji] =\n                        ataylor_x[(x_offset + ij) * q + (k - ell) ];\n                }\n            }\n            //\n            // v = \\bar{C} * [ B^{k-ell} ]^T\n            v.resize(0);\n            v.resize( n_left * n_middle );\n            i_call = set(n_left, n_right, n_middle);\n            (*this)(i_call, u, v);\n            //\n            // \\bar{A}^ell += v\n            for(size_t i = 0; i < n_left * n_middle; ++i)\n                apartial_x[i * q + ell] += v[i];\n            //\n            // u = [ A^ell^T , \\bar{C}^k ]\n            u.resize(0);\n            u.resize( n_middle * n_left + n_left * n_right );\n            u_offset = n_middle * n_left;\n            for(size_t i = 0; i < n_left; ++i)\n            {   for(size_t j = 0; j < n_middle; ++j)\n                {   size_t ij = i * n_middle + j;\n                    size_t ji = j * n_left + i;\n                    u[ji] = ataylor_x[ij * q + ell];\n                }\n            }\n            for(size_t i = 0; i < n_left * n_right; ++i)\n                u[u_offset + i] = apartial_y[ i * q + k ];\n            //\n            // v = [ A^ell ]^T * \\bar{C}^k\n            v.resize(0);\n            v.resize( n_middle * n_right );\n            i_call = set(n_middle, n_left, n_right);\n            (*this)(i_call, u, v);\n            //\n            // \\bar{B}^{k-\\ell} += v\n            for(size_t i = 0; i < n_middle * n_right; ++i)\n                apartial_x[ (x_offset + i) * q + (k - ell) ] += v[i];\n        }\n    }\n    return true;\n}\n} // END_CPPAD_NAMESPACE\n// END C++\n# endif\n"
  },
  {
    "path": "include/cppad/example/atomic_four/mat_mul/set.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_ATOMIC_FOUR_MAT_MUL_SET_HPP\n# define CPPAD_EXAMPLE_ATOMIC_FOUR_MAT_MUL_SET_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_four_mat_mul_set.hpp}\n\natomic_mat_mul Set Routine: Example Implementation\n##################################################\n\nSyntax\n******\n| *call_id* = *mat_mul* . ``set`` ( *n_left* , *n_middle* , *n_right* )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN PROTOTYPE\n    // END PROTOTYPE\n}\n\nPurpose\n*******\nStores the dimension information for a an atomic operation that computes\nthe matrix product *R* = *A* * *B* .\n\nn_left\n******\nThis argument is the row dimension of the matrices *A* and *R* .\n\nn_middle\n********\nThis argument is the column dimension of the matrix *A*\nand row dimension of the matrix *B* .\n\nn_right\n*******\nThis argument is the column dimension of the matrices *B* and *R* .\n\ncall_id\n*******\nThis return value identifies the dimension information above.\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end atomic_four_mat_mul_set.hpp}\n*/\n// BEGIN C++\n# include <cppad/example/atomic_four/mat_mul/mat_mul.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n// BEGIN PROTOTYPE\ntemplate <class Base>\nsize_t atomic_mat_mul<Base>::set(\n    size_t n_left, size_t n_middle, size_t n_right\n)\n// END PROTOTYPE\n{\n    // thread\n    size_t thread = thread_alloc::thread_num();\n    //\n    // work_[thread]\n    if( work_[thread] == nullptr )\n        work_[thread] = new call_vector;\n    //\n    // call_id\n    size_t call_id = work_[thread]->size();\n    //\n    // call\n    call_struct call;\n    call.n_left   = n_left;\n    call.n_middle = n_middle;\n    call.n_right  = n_right;\n    call.thread   = thread;\n    //\n    // work_[thread]\n    work_[thread]->push_back( call );\n    //\n    return call_id;\n}\n} // END_CPPAD_NAMESPACE\n// END C++\n# endif\n"
  },
  {
    "path": "include/cppad/example/atomic_four/vector/add_op.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_ATOMIC_FOUR_VECTOR_ADD_OP_HPP\n# define CPPAD_EXAMPLE_ATOMIC_FOUR_VECTOR_ADD_OP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_four_vector_add_op.hpp}\n\nAtomic Vector Add Operator: Example Implementation\n##################################################\n\nForward Mode\n************\nsee theory for forward mode\n:ref:`forward_theory@Binary Operators@Addition` .\n\nReverse Mode\n************\nsee theory for reverse mode\n:ref:`reverse_theory@Binary Operators@Addition` .\n\nExample\n*******\nThe file :ref:`atomic_four_vector_add.cpp-name` contains an example\nand test for this operator.\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end atomic_four_vector_add_op.hpp}\n*/\n// BEGIN C++\n# include <cppad/example/atomic_four/vector/vector.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n// ---------------------------------------------------------------------------\n// comment below is used by atomic_vector.omh\n// BEGIN forward_add\ntemplate <class Base>\nvoid atomic_vector<Base>::forward_add(\n    size_t                                           m,\n    size_t                                           p,\n    size_t                                           q,\n    const CppAD::vector<Base>&                       tx,\n    CppAD::vector<Base>&                             ty)\n{\n    for(size_t k = p; k < q; ++k)\n    {   for(size_t i = 0; i < m; ++i)\n        {   size_t u_index  =       i * q + k;\n            size_t v_index  = (m + i) * q + k;\n            size_t y_index  =       i * q + k;\n            // y_i^k = u_i^k + v_i^k\n            ty[y_index]     = tx[u_index] + tx[v_index];\n        }\n    }\n}\ntemplate <class Base>\nvoid atomic_vector<Base>::forward_add(\n    size_t                                           m,\n    size_t                                           p,\n    size_t                                           q,\n    const CppAD::vector< CppAD::AD<Base> >&          atx,\n    CppAD::vector< CppAD::AD<Base> >&                aty)\n{   size_t n = 2 * m;\n    assert( atx.size() == n * q );\n    assert( aty.size() == m * q );\n    //\n    // atu, atv\n    ad_const_iterator atu = atx.begin();\n    ad_const_iterator atv = atu + ad_difference_type(m * q);\n    //\n    // ax\n    ad_vector ax(n);\n    ad_iterator au = ax.begin();\n    ad_iterator av = au + ad_difference_type(m);\n    //\n    // ay\n    ad_vector ay(m);\n    //\n    for(size_t k = p; k < q; ++k)\n    {   // au = u^k\n        copy_mat_to_vec(m, q, k, atu, au);\n        // av = v^k\n        copy_mat_to_vec(m, q, k, atv, av);\n        // ay = au + av\n        (*this)(add_enum, ax, ay); // atomic vector add\n        // y^k = ay\n        copy_vec_to_mat(m, q, k, ay.begin(), aty.begin() );\n    }\n}\n// END forward_add\n// comment above is used by atomic_vector.omh\n// ---------------------------------------------------------------------------\n// reverse_add\ntemplate <class Base>\nvoid atomic_vector<Base>::reverse_add(\n    size_t                                           m,\n    size_t                                           q,\n    const CppAD::vector<Base>&                       tx,\n    const CppAD::vector<Base>&                       ty,\n    CppAD::vector<Base>&                             px,\n    const CppAD::vector<Base>&                       py)\n{\n    for(size_t k = 0; k < q; ++k)\n    {   for(size_t i = 0; i < m; ++i)\n        {   size_t u_index  =       i * q + k;\n            size_t v_index  = (m + i) * q + k;\n            size_t y_index  =       i * q + k;\n            // y_i^k = u_i^k + v_i^k\n            px[u_index] = py[y_index];\n            px[v_index] = py[y_index];\n        }\n    }\n}\ntemplate <class Base>\nvoid atomic_vector<Base>::reverse_add(\n    size_t                                           m,\n    size_t                                           q,\n    const CppAD::vector< CppAD::AD<Base> >&          atx,\n    const CppAD::vector< CppAD::AD<Base> >&          aty,\n    CppAD::vector< CppAD::AD<Base> >&                apx,\n    const CppAD::vector< CppAD::AD<Base> >&          apy)\n{\n    //\n    // just copying values does not add any operators to the tape.\n    for(size_t k = 0; k < q; ++k)\n    {   for(size_t i = 0; i < m; ++i)\n        {   size_t u_index  =       i * q + k;\n            size_t v_index  = (m + i) * q + k;\n            size_t y_index  =       i * q + k;\n            // y_i^k = u_i^k + v_i^k\n            apx[u_index] = apy[y_index];\n            apx[v_index] = apy[y_index];\n        }\n    }\n}\n} // END_CPPAD_NAMESPACE\n// END C++\n# endif\n"
  },
  {
    "path": "include/cppad/example/atomic_four/vector/div_op.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_ATOMIC_FOUR_VECTOR_DIV_OP_HPP\n# define CPPAD_EXAMPLE_ATOMIC_FOUR_VECTOR_DIV_OP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_four_vector_div_op.hpp}\n\nAtomic Vector Divide Operator: Example Implementation\n#####################################################\n\nForward Mode\n************\nsee theory for forward mode\n:ref:`forward_theory@Binary Operators@Division` .\n\nReverse Mode\n************\nsee theory for reverse mode\n:ref:`reverse_theory@Binary Operators@Division` .\n\nExample\n*******\nThe file :ref:`atomic_four_vector_div.cpp-name` contains an example\nand test for this operator.\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end atomic_four_vector_div_op.hpp}\n*/\n// BEGIN C++\n# include <cppad/example/atomic_four/vector/vector.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n// ---------------------------------------------------------------------------\n// forward_div\ntemplate <class Base>\nvoid atomic_vector<Base>::forward_div(\n    size_t                                           m,\n    size_t                                           p,\n    size_t                                           q,\n    const CppAD::vector<Base>&                       tx,\n    CppAD::vector<Base>&                             ty)\n{\n    for(size_t i = 0; i < m; ++i)\n    {   for(size_t k = p; k < q; ++k)\n        {   size_t y_index = i * q + k;\n            size_t u_index = i * q + k;\n            // y^k = u^k\n            ty[y_index]     = tx[u_index];\n            for(size_t d = 1; d <= k; d++)\n            {   size_t y_other = i * q + (k-d);\n                size_t v_index = (i + m) * q + d;\n                // y^k -= y^{k-d} * v^d\n                ty[y_index] -= ty[y_other] * tx[v_index];\n            }\n            size_t v0_index = (i + m) * q + 0;\n            // y^k /= v^0\n            ty[y_index] /= tx[v0_index];\n        }\n    }\n}\ntemplate <class Base>\nvoid atomic_vector<Base>::forward_div(\n    size_t                                           m,\n    size_t                                           p,\n    size_t                                           q,\n    const CppAD::vector< CppAD::AD<Base> >&          atx,\n    CppAD::vector< CppAD::AD<Base> >&                aty)\n{\n    size_t n = 2 * m;\n    assert( atx.size() == n * q );\n    assert( aty.size() == m * q );\n    //\n    // atu, atv\n    ad_const_iterator atu = atx.begin();\n    ad_const_iterator atv = atu + ad_difference_type(m * q);\n    //\n    // ax_div\n    ad_vector ax_div(n);\n    ad_iterator au_div = ax_div.begin();\n    ad_iterator av_div = ax_div.begin() + ad_difference_type(m);\n    //\n    // ax_mul\n    ad_vector ax_mul(n);\n    ad_iterator au_mul = ax_mul.begin();\n    ad_iterator av_mul = ax_mul.begin() + ad_difference_type(m);\n    //\n    // ax_sub\n    ad_vector ax_sub(n);\n    ad_iterator au_sub = ax_sub.begin();\n    ad_iterator av_sub = ax_sub.begin() + ad_difference_type(m);\n    //\n    // ay\n    ad_vector ay(m);\n    //\n    for(size_t k = p; k < q; ++k)\n    {   // u_sub = u^k\n        copy_mat_to_vec(m, q, k, atu, au_sub);\n        for(size_t d = 1; d <= k; d++)\n        {   // u_mul = y^{k-d}\n            copy_mat_to_vec(m, q, k-d, aty.begin(), au_mul);\n            // v_mul = v^d\n            copy_mat_to_vec(m, q, d, atv, av_mul);\n            // ay = u_mul * v_mul\n            (*this)(mul_enum, ax_mul, ay); // atomic vector multiply\n            // v_sub = ay\n            for(size_t i = 0; i < m; ++i)\n                av_sub[i] = ay[i];\n            // ay = u_sub - v_sub\n            (*this)(sub_enum, ax_sub, ay); // atomic vector subtract\n            // u_sub = ay\n            for(size_t i = 0; i < m; ++i)\n                au_sub[i] = ay[i];\n        }\n        // u_div = u_sub\n        for(size_t i = 0; i < m; ++i)\n            au_div[i] = *(au_sub + ad_difference_type(i));\n        // v_div = v^0\n        copy_mat_to_vec(m, q, 0, atv, av_div);\n        // ay = u_div / v_div\n        (*this)(div_enum, ax_div, ay); // atomic vector divide\n        // y^k = ay\n        copy_vec_to_mat(m, q, k, ay.begin(), aty.begin());\n    }\n}\n// ---------------------------------------------------------------------------\n// reverse_div\ntemplate <class Base>\nvoid atomic_vector<Base>::reverse_div(\n    size_t                                           m,\n    size_t                                           q,\n    const CppAD::vector<Base>&                       tx,\n    const CppAD::vector<Base>&                       ty,\n    CppAD::vector<Base>&                             px,\n    const CppAD::vector<Base>&                       py)\n{\n# ifndef NDEBUG\n    size_t n = 2 * m;\n    assert( tx.size() == n * q );\n    assert( ty.size() == m * q );\n    assert( px.size() == n * q );\n    assert( py.size() == m * q );\n# endif\n    //\n    // py_copy\n    CppAD::vector<Base> py_copy( py );\n    //\n    // pv\n    for(size_t i = 0; i < m; ++i)\n    {   for(size_t k = 0; k < q; ++k)\n        {   size_t v_index = (i + m) * q + k;\n            px[v_index] = 0.0;\n        }\n    }\n    // px\n    for(size_t i = 0; i < m; ++i)\n    {   size_t v0_index = (i + m) * q + 0;\n        //\n        // k\n        size_t k = q;\n        while(k)\n        {   --k;\n            //\n            // y_index\n            size_t y_index = i * q + k;\n            //\n            // py_scaled\n            double py_scaled = py_copy[y_index] / tx[v0_index];\n            //\n            for(size_t d = 1; d <= k; d++)\n            {   size_t y_other = i * q + (k-d);\n                size_t v_index = (i + m) * q + d;\n                //\n                py_copy[y_other] -= py_scaled * tx[v_index];\n                px[v_index]      -= py_scaled * ty[y_other];\n            }\n            size_t u_index = i * q + k;\n            px[u_index]   = py_scaled;\n            px[v0_index] -= py_scaled * ty[y_index];\n        }\n    }\n}\ntemplate <class Base>\nvoid atomic_vector<Base>::reverse_div(\n    size_t                                           m,\n    size_t                                           q,\n    const CppAD::vector< CppAD::AD<Base> >&          atx,\n    const CppAD::vector< CppAD::AD<Base> >&          aty,\n    CppAD::vector< CppAD::AD<Base> >&                apx,\n    const CppAD::vector< CppAD::AD<Base> >&          apy)\n{   size_t n = 2 * m;\n    assert( atx.size() == n * q );\n    assert( aty.size() == m * q );\n    assert( apx.size() == n * q );\n    assert( apy.size() == m * q );\n    //\n    // atu, atv, apu, apv\n    ad_const_iterator atu = atx.begin();\n    ad_const_iterator atv = atu + ad_difference_type(m * q);\n    ad_iterator       apu = apx.begin();\n    ad_iterator       apv = apu + ad_difference_type(m * q);\n    //\n    // ax_sub\n    ad_vector ax_sub(n);\n    ad_iterator au_sub = ax_sub.begin();\n    ad_iterator av_sub = ax_sub.begin() + ad_difference_type(m);\n    //\n    // ax_mul\n    ad_vector ax_mul(n);\n    ad_iterator au_mul = ax_mul.begin();\n    ad_iterator av_mul = ax_mul.begin() + ad_difference_type(m);\n    //\n    // ax_div\n    ad_vector ax_div(n);\n    ad_iterator au_div = ax_div.begin();\n    ad_iterator av_div = ax_div.begin() + ad_difference_type(m);\n    //\n    // ay, apy_scaled\n    ad_vector ay(m), apy_scaled(m);\n    //\n    // apy_copy\n    ad_vector apy_copy( apy );\n    //\n    // apv\n    for(size_t i = 0; i < m; ++i)\n    {   for(size_t k = 0; k < q; ++k)\n        {   size_t v_index = (i + m) * q + k;\n            apx[v_index] = 0.0;\n        }\n    }\n    //\n    // av_div = atv^0\n    copy_mat_to_vec(m, q, 0, atv, av_div);\n    //\n    // k\n    size_t k = q;\n    while(k)\n    {   --k;\n        //\n        // au_div = apy^k\n        copy_mat_to_vec(m, q, k, apy_copy.begin(), au_div);\n        //\n        // apy_scaled = au_div / av_dir\n        (*this)(div_enum, ax_div, apy_scaled);\n        //\n        // au_mul = apy_scaled\n        for(size_t i = 0; i < m; ++i)\n            au_mul[i] = apy_scaled[i];\n        //\n        for(size_t d = 1; d <= k; ++d)\n        {   //\n            // av_mul = atv^d\n            copy_mat_to_vec(m, q, d, atv, av_mul);\n            //\n            // ay = au_mul * av_mul\n            (*this)(mul_enum, ax_mul, ay);\n            //\n            // au_sub = apy^{k-d}\n            copy_mat_to_vec(m, q, k-d, apy_copy.begin(), au_sub);\n            //\n            // av_sub = ay\n            for(size_t i = 0; i < m; ++i)\n                av_sub[i] = ay[i];\n            //\n            // ay = au_sub - av_sub\n            (*this)(sub_enum, ax_sub, ay);\n            //\n            // apy^{k-d} = ay\n            copy_vec_to_mat(m, q, k-d, ay.begin(), apy_copy.begin());\n            //\n            // av_mul = aty^{k-d}\n            copy_mat_to_vec(m, q, k-d, aty.begin(), av_mul);\n            //\n            // ay = au_mul * av_mul\n            (*this)(mul_enum, ax_mul, ay);\n            //\n            // au_sub = apv^d\n            copy_mat_to_vec(m, q, d, apv, au_sub);\n            //\n            // av_sub = ay\n            for(size_t i = 0; i < m; ++i)\n                av_sub[i] = ay[i];\n            //\n            // ay = au_sub - av_sub\n            (*this)(sub_enum, ax_sub, ay);\n            //\n            // apv^d = ay\n            copy_vec_to_mat(m, q, d, ay.begin(), apv);\n        }\n        //\n        // apu^k = apy_scaled\n        copy_vec_to_mat(m, q, k, apy_scaled.begin(), apu);\n        //\n        // av_mul = aty^k\n        copy_mat_to_vec(m, q, k, aty.begin(), av_mul);\n        //\n        // ay = au_mul * av_mul\n        (*this)(mul_enum, ax_mul, ay);\n        //\n        // au_sub = apv^0\n        copy_mat_to_vec(m, q, 0, apv, au_sub);\n        //\n        // av_sub = ay\n        for(size_t i = 0; i < m; ++i)\n            av_sub[i] = ay[i];\n        //\n        // ay = au_sub - av_sub\n        (*this)(sub_enum, ax_sub, ay);\n        //\n        // apv^0 = ay\n        copy_vec_to_mat(m, q, 0, ay.begin(), apv);\n    }\n}\n} // END_CPPAD_NAMESPACE\n// END C++\n# endif\n"
  },
  {
    "path": "include/cppad/example/atomic_four/vector/for_type.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_ATOMIC_FOUR_VECTOR_FOR_TYPE_HPP\n# define CPPAD_EXAMPLE_ATOMIC_FOUR_VECTOR_FOR_TYPE_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_four_vector_for_type.hpp}\n\nAtomic Vector Forward Type Calculation: Example Implementation\n##############################################################\n\nPurpose\n*******\nThe ``for_type`` routine overrides the virtual functions\nused by the atomic_four base; see\n:ref:`for_type<atomic_four_for_type-name>` .\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end atomic_four_vector_for_type.hpp}\n*/\n// BEGIN C++\n# include <cppad/example/atomic_four/vector/vector.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n//\n// for_type override\ntemplate <class Base>\nbool atomic_vector<Base>::for_type(\n    size_t                                     call_id     ,\n    const CppAD::vector<CppAD::ad_type_enum>&  type_x      ,\n    CppAD::vector<CppAD::ad_type_enum>&        type_y      )\n{\n    // n, m, op\n    size_t n     = type_x.size();\n    size_t m     = type_y.size();\n    op_enum_t op = op_enum_t( call_id );\n    //\n    // type_y\n    if( n == m )\n    {   // unary operator\n        for(size_t i = 0; i < m; ++i)\n            type_y[i] = type_x[i];\n    }\n    else\n    {   // binary operator\n        for(size_t i = 0; i < m; ++i)\n            type_y[i] = std::max( type_x[i] , type_x[m + i] );\n    }\n    switch(op)\n    {\n        // addition, subtraction\n        // not sure result is identically 0 unless both are identically 0\n        case add_enum:\n        case sub_enum:\n        for(size_t i = 0; i < m; ++i)\n            type_y[i] = std::max( type_x[i] , type_x[m + i] );\n        break;\n\n\n        // multiplication\n        // treat multiplication by zero like absolute zero\n        case mul_enum:\n        for(size_t i = 0; i < m; ++i)\n        {   if( type_x[i] == identical_zero_enum )\n                type_y[i] = identical_zero_enum;\n            else if( type_x[m + i] == identical_zero_enum )\n                type_y[i] = identical_zero_enum;\n            else\n                type_y[i] = std::max( type_x[i] , type_x[m + i] );\n        }\n        break;\n\n        // division\n        // treat divition of zero like absolute zero\n        case div_enum:\n        for(size_t i = 0; i < m; ++i)\n        {   if( type_x[i] == identical_zero_enum )\n                type_y[i] = identical_zero_enum;\n            else\n                type_y[i] = std::max( type_x[i] , type_x[m + i] );\n        }\n        break;\n\n        // unary minus\n        case neg_enum:\n        for(size_t i = 0; i < m; ++i)\n            type_y[i] = type_x[i];\n        break;\n\n        // error\n        case number_op_enum:\n        assert(false);\n        break;\n    }\n    return true;\n}\n} // END_CPPAD_NAMESPACE\n// END C++\n# endif\n"
  },
  {
    "path": "include/cppad/example/atomic_four/vector/forward_op.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_ATOMIC_FOUR_VECTOR_FORWARD_OP_HPP\n# define CPPAD_EXAMPLE_ATOMIC_FOUR_VECTOR_FORWARD_OP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_four_vector_forward_op.hpp}\n\nAtomic Vector Forward Mode: Example Implementation\n##################################################\n\nPurpose\n*******\nThe ``forward`` routine overrides the virtual functions\nused by the atomic_four base class for forward mode calculations; see\n:ref:`forward<atomic_four_forward-name>` .\nIt determines which operator is specified for this call and transfers\nthe call to the operator's implementation.\nThere are two versions of the ``forward`` routine, one for *Base*\nand one for ``AD<Base>`` .\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end atomic_four_vector_forward_op.hpp}\n*/\n// BEGIN C++\n# include <cppad/example/atomic_four/vector/vector.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n//\n// forward override\n// this routine called by ADFun<Base> objects\ntemplate <class Base>\nbool atomic_vector<Base>::forward(\n    size_t                                           call_id,\n    const CppAD::vector<bool>&                       select_y,\n    size_t                                           order_low,\n    size_t                                           order_up,\n    const CppAD::vector<Base>&                       tx,\n    CppAD::vector<Base>&                             ty)\n{\n    // p, q\n    size_t p = order_low;\n    size_t q = order_up + 1;\n    CPPAD_ASSERT_UNKNOWN( tx.size() % q == 0 );\n    //\n    // op, m\n    op_enum_t op = op_enum_t( call_id );\n    size_t n     = tx.size() / q;\n    size_t m = n / 2;\n    if( is_unary(op) )\n        m = n;\n    CPPAD_ASSERT_UNKNOWN( ty.size() == m * q );\n    //\n    bool ok = false;\n    switch(op)\n    {\n        // addition\n        case add_enum:\n        forward_add(m, p, q, tx, ty);\n        ok = true;\n        break;\n\n        // subtraction\n        case sub_enum:\n        forward_sub(m, p, q, tx, ty);\n        ok = true;\n        break;\n\n        // multiplication\n        case mul_enum:\n        forward_mul(m, p, q, tx, ty);\n        ok = true;\n        break;\n\n        // division\n        case div_enum:\n        forward_div(m, p, q, tx, ty);\n        ok = true;\n        break;\n\n        // unary minus\n        case neg_enum:\n        forward_neg(m, p, q, tx, ty);\n        ok = true;\n        break;\n\n        // error\n        case number_op_enum:\n        assert(false);\n        break;\n    }\n    return ok;\n}\n// forward override\n// this routine called by ADFun< CppAD::AD<Base> , Base> objects\ntemplate <class Base>\nbool atomic_vector<Base>::forward(\n    size_t                                           call_id,\n    const CppAD::vector<bool>&                       select_y,\n    size_t                                           order_low,\n    size_t                                           order_up,\n    const CppAD::vector< CppAD::AD<Base> >&          atx,\n    CppAD::vector< CppAD::AD<Base> >&                aty         )\n{\n    // p, q\n    size_t p = order_low;\n    size_t q = order_up + 1;\n    CPPAD_ASSERT_UNKNOWN( atx.size() % q == 0 );\n    //\n    // op, m\n    op_enum_t op = op_enum_t( call_id );\n    size_t n     = atx.size() / q;\n    size_t m     = n / 2;\n    if( is_unary(op) )\n        m = n;\n    CPPAD_ASSERT_UNKNOWN( aty.size() == q * m );\n    //\n    bool ok = false;\n    switch(op)\n    {\n        // addition\n        case add_enum:\n        forward_add(m, p, q, atx, aty);\n        ok = true;\n        break;\n\n        // subtraction\n        case sub_enum:\n        forward_sub(m, p, q, atx, aty);\n        ok = true;\n        break;\n\n        // multiplication\n        case mul_enum:\n        forward_mul(m, p, q, atx, aty);\n        ok = true;\n        break;\n\n        // division\n        case div_enum:\n        forward_div(m, p, q, atx, aty);\n        ok = true;\n        break;\n\n        // unary minus\n        case neg_enum:\n        forward_neg(m, p, q, atx, aty);\n        ok = true;\n        break;\n\n        // error\n        case number_op_enum:\n        assert(false);\n        break;\n    }\n    return ok;\n}\n} // END_CPPAD_NAMESPACE\n// END C++\n# endif\n"
  },
  {
    "path": "include/cppad/example/atomic_four/vector/hes_sparsity.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_ATOMIC_FOUR_VECTOR_HES_SPARSITY_HPP\n# define CPPAD_EXAMPLE_ATOMIC_FOUR_VECTOR_HES_SPARSITY_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_four_vector_hes_sparsity.hpp}\n\nAtomic Vector Hessian Sparsity Pattern: Example Implementation\n##############################################################\n\nPurpose\n*******\nThe ``hes_sparsity`` routine overrides the virtual functions\nused by the atomic_four base class for Jacobian sparsity calculations; see\n:ref:`hes_sparsity<atomic_four_hes_sparsity-name>` .\n\nExample\n*******\nThe file :ref:`atomic_four_vector_hes_sparsity.cpp-name`\ncontains an example and test using this operator.\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end atomic_four_vector_hes_sparsity.hpp}\n*/\n// BEGIN C++\n# include <cppad/example/atomic_four/vector/vector.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n//\n// hes_sparsity override\ntemplate <class Base>\nbool atomic_vector<Base>::hes_sparsity(\n    size_t                                         call_id      ,\n    const CppAD::vector<bool>&                     ident_zero_x ,\n    const CppAD::vector<bool>&                     select_x     ,\n    const CppAD::vector<bool>&                     select_y     ,\n    CppAD::sparse_rc< CppAD::vector<size_t> >&     pattern_out  )\n{\n    size_t n = select_x.size();\n    size_t m = select_y.size();\n    assert( n == m || n == 2 * m );\n    //\n    // op\n    op_enum_t op = op_enum_t( call_id );\n    //\n    switch(op)\n    {   // linear operator cases\n        case add_enum:\n        case sub_enum:\n        case neg_enum:\n        //\n        // pattern_out is empty\n        pattern_out.resize(n, n, 0);\n        return true;\n\n        default:\n        break;\n    }\n    //\n    // nnz\n    // number of non-zeros in sparsity pattern\n    size_t nnz = 0;\n    for(size_t i = 0; i < m; ++i) if( select_y[i] )\n    {   size_t j = i;\n        if( select_x[j] && op != mul_enum )\n            ++nnz;\n        if( n != m )\n        {   // binary operator\n            j = m + i;\n            if( select_x[j] )\n                nnz += 2;\n        }\n    }\n    //\n    // pattern_out\n    pattern_out.resize(n, n, nnz);\n    size_t k = 0;\n    for(size_t i = 0; i < m; ++i) if( select_y[i] )\n    {   size_t j = i;\n        if( select_x[j] && op != mul_enum )\n            pattern_out.set(k++, i, j);\n        if( n != m )\n        {   // binary operator\n            j = m + i;\n            if( select_x[j] )\n            {   pattern_out.set(k++, i, j);\n                pattern_out.set(k++, j, i);\n            }\n        }\n    }\n    assert( k == nnz);\n    //\n    return true;\n}\n} // END_CPPAD_NAMESPACE\n// END C++\n# endif\n"
  },
  {
    "path": "include/cppad/example/atomic_four/vector/implement.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin atomic_four_vector_implement}\n\nImplementing Atomic Vector Operations\n#####################################\n\nContents\n********\n{xrst_toc_table\n    include/cppad/example/atomic_four/vector/vector.hpp\n    include/cppad/example/atomic_four/vector/forward_op.hpp\n    include/cppad/example/atomic_four/vector/reverse_op.hpp\n    include/cppad/example/atomic_four/vector/jac_sparsity.hpp\n    include/cppad/example/atomic_four/vector/hes_sparsity.hpp\n    include/cppad/example/atomic_four/vector/for_type.hpp\n    include/cppad/example/atomic_four/vector/rev_depend.hpp\n    include/cppad/example/atomic_four/vector/add_op.hpp\n    include/cppad/example/atomic_four/vector/sub_op.hpp\n    include/cppad/example/atomic_four/vector/mul_op.hpp\n    include/cppad/example/atomic_four/vector/div_op.hpp\n    include/cppad/example/atomic_four/vector/neg_op.hpp\n}\n\n{xrst_end atomic_four_vector_implement}\n"
  },
  {
    "path": "include/cppad/example/atomic_four/vector/jac_sparsity.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_ATOMIC_FOUR_VECTOR_JAC_SPARSITY_HPP\n# define CPPAD_EXAMPLE_ATOMIC_FOUR_VECTOR_JAC_SPARSITY_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_four_vector_jac_sparsity.hpp}\n\nAtomic Vector Jacobian Sparsity Pattern: Example Implementation\n###############################################################\n\nPurpose\n*******\nThe ``jac_sparsity`` routine overrides the virtual functions\nused by the atomic_four base class for Jacobian sparsity calculations; see\n:ref:`jac_sparsity<atomic_four_jac_sparsity-name>` .\n\nExample\n*******\nThe file :ref:`atomic_four_vector_jac_sparsity.cpp-name`\ncontains an example and test using this operator.\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end atomic_four_vector_jac_sparsity.hpp}\n*/\n// BEGIN C++\n# include <cppad/example/atomic_four/vector/vector.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n//\n// jac_sparsity override\ntemplate <class Base>\nbool atomic_vector<Base>::jac_sparsity(\n    size_t                                         call_id      ,\n    bool                                           dependency   ,\n    const CppAD::vector<bool>&                     ident_zero_x ,\n    const CppAD::vector<bool>&                     select_x     ,\n    const CppAD::vector<bool>&                     select_y     ,\n    CppAD::sparse_rc< CppAD::vector<size_t> >&     pattern_out  )\n{\n    size_t n = select_x.size();\n    size_t m = select_y.size();\n    assert( n == m || n == 2 * m );\n    //\n    // nnz\n    // number of non-zeros in sparsity pattern\n    size_t nnz = 0;\n    for(size_t i = 0; i < m; ++i) if( select_y[i] )\n    {   size_t j = i;\n        if( select_x[j] )\n            ++nnz;\n        if( n != m )\n        {   // binary operator\n            j = m + i;\n            if( select_x[j] )\n                ++nnz;\n        }\n    }\n    //\n    // pattern_out\n    pattern_out.resize(m, n, nnz);\n    size_t k = 0;\n    for(size_t i = 0; i < m; ++i) if( select_y[i] )\n    {   size_t j = i;\n        if( select_x[j] )\n            pattern_out.set(k++, i, j);\n        if( n != m )\n        {   // binary operator\n            j = m + i;\n            if( select_x[j] )\n                pattern_out.set(k++, i, j);\n        }\n    }\n    assert( k == nnz);\n    //\n    return true;\n}\n} // END_CPPAD_NAMESPACE\n// END C++\n# endif\n"
  },
  {
    "path": "include/cppad/example/atomic_four/vector/mul_op.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_ATOMIC_FOUR_VECTOR_MUL_OP_HPP\n# define CPPAD_EXAMPLE_ATOMIC_FOUR_VECTOR_MUL_OP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_four_vector_mul_op.hpp}\n\nAtomic Vector Multiply Operator: Example Implementation\n#######################################################\n\nForward Mode\n************\nsee theory for forward mode\n:ref:`forward_theory@Binary Operators@Multiplication` .\n\nReverse Mode\n************\nsee theory for reverse mode\n:ref:`reverse_theory@Binary Operators@Multiplication` .\n\nExample\n*******\nThe file :ref:`atomic_four_vector_mul.cpp-name` contains an example\nand test for this operator.\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end atomic_four_vector_mul_op.hpp}\n*/\n// BEGIN C++\n# include <cppad/example/atomic_four/vector/vector.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n// --------------------------------------------------------------------------\n// forward_mul\ntemplate <class Base>\nvoid atomic_vector<Base>::forward_mul(\n    size_t                                           m,\n    size_t                                           p,\n    size_t                                           q,\n    const CppAD::vector<Base>&                       tx,\n    CppAD::vector<Base>&                             ty)\n{\n    for(size_t i = 0; i < m; ++i)\n    {   for(size_t k = p; k < q; ++k)\n        {   size_t y_index = i * q + k;\n            // y^k = 0\n            ty[y_index]    = 0.0;\n            for(size_t d = 0; d <= k; d++)\n            {   size_t u_index  =       i * q + (k-d);\n                size_t v_index  = (m + i) * q + d;\n                // y^k += u^{k-d} * v^d\n                ty[y_index]    += tx[u_index] * tx[v_index];\n            }\n        }\n    }\n}\ntemplate <class Base>\nvoid atomic_vector<Base>::forward_mul(\n    size_t                                           m,\n    size_t                                           p,\n    size_t                                           q,\n    const CppAD::vector< CppAD::AD<Base> >&          atx,\n    CppAD::vector< CppAD::AD<Base> >&                aty)\n{\n    size_t n = 2 * m;\n    assert( atx.size() == n * q );\n    assert( aty.size() == m * q );\n    //\n    // atu, atv\n    ad_const_iterator atu = atx.begin();\n    ad_const_iterator atv = atu + ad_difference_type(m * q);\n    //\n    // ax_mul\n    ad_vector ax_mul(n);\n    ad_iterator au_mul = ax_mul.begin();\n    ad_iterator av_mul = ax_mul.begin() + ad_difference_type(m);\n    //\n    // ax_add\n    ad_vector ax_add(n);\n    ad_iterator au_add = ax_add.begin();\n    ad_iterator av_add = ax_add.begin() + ad_difference_type(m);\n    //\n    // ay\n    ad_vector ay(m);\n    //\n    for(size_t k = p; k < q; ++k)\n    {   // ay = 0\n        for(size_t i = 0; i < m; ++i)\n            ay[i] = 0.0;\n        for(size_t d = 0; d <= k; d++)\n        {   // u_add = ay\n            for(size_t i = 0; i < m; ++i)\n                au_add[i] = ay[i];\n            //\n            // au_mul = u^{k-d}\n            copy_mat_to_vec(m, q, k-d, atu, au_mul);\n            //\n            // av_mul =  v^d\n            copy_mat_to_vec(m, q, d, atv, av_mul);\n            //\n            // ay = au_mul * av_mul\n            (*this)(mul_enum, ax_mul, ay); // atomic vector multiply\n            //\n            // v_add = ay\n            for(size_t i = 0; i < m; ++i)\n                av_add[i] = ay[i];\n            //\n            // ay = u_add + v_add\n            (*this)(add_enum, ax_add, ay); // atomic vector add\n        }\n        // y^k = ay\n        copy_vec_to_mat(m, q, k, ay.begin(), aty.begin());\n    }\n}\n// --------------------------------------------------------------------------\n// reverse_mul\ntemplate <class Base>\nvoid atomic_vector<Base>::reverse_mul(\n    size_t                                           m,\n    size_t                                           q,\n    const CppAD::vector<Base>&                       tx,\n    const CppAD::vector<Base>&                       ty,\n    CppAD::vector<Base>&                             px,\n    const CppAD::vector<Base>&                       py)\n{   size_t n = 2 * m;\n    assert( tx.size() == n * q );\n    assert( ty.size() == m * q );\n    assert( px.size() == n * q );\n    assert( py.size() == m * q );\n    //\n    // px\n    for(size_t j = 0; j < n; ++j)\n    {   for(size_t k = 0; k < q; ++k)\n            px[j * q + k] = 0.0;\n    }\n    //\n    // px\n    for(size_t i = 0; i < m; ++i)\n    {   // k\n        size_t k = q;\n        while(k)\n        {   --k;\n            //\n            // y_index\n            size_t y_index = i * q + k;\n            //\n            // px\n            for(size_t d = 0; d <= k; ++d)\n            {   size_t u_index  =       i * q + (k-d);\n                size_t v_index  = (m + i) * q + d;\n                //\n                // must use azmul because py[y_index] = 0 may mean that this\n                // component of the function was not selected.\n                px[u_index]    += CppAD::azmul( py[y_index] , tx[v_index] );\n                px[v_index]    += CppAD::azmul( py[y_index] , tx[u_index] );\n            }\n        }\n    }\n}\ntemplate <class Base>\nvoid atomic_vector<Base>::reverse_mul(\n    size_t                                           m,\n    size_t                                           q,\n    const CppAD::vector< CppAD::AD<Base> >&          atx,\n    const CppAD::vector< CppAD::AD<Base> >&          aty,\n    CppAD::vector< CppAD::AD<Base> >&                apx,\n    const CppAD::vector< CppAD::AD<Base> >&          apy)\n{   size_t n = 2 * m;\n    assert( atx.size() == n * q );\n    assert( aty.size() == m * q );\n    assert( apx.size() == n * q );\n    assert( apy.size() == m * q );\n    //\n    // atu, atv, apu, apv\n    ad_const_iterator atu = atx.begin();\n    ad_const_iterator atv = atu + ad_difference_type(m * q);\n    ad_iterator       apu = apx.begin();\n    ad_iterator       apv = apu + ad_difference_type(m * q);\n    //\n    // ax_mul\n    // need azmul_op but it is not yet available\n    ad_vector ax_mul(n);\n    ad_iterator au_mul = ax_mul.begin();\n    ad_iterator av_mul = ax_mul.begin() + ad_difference_type(m);\n    //\n    // ax_add\n    ad_vector ax_add(n);\n    ad_iterator au_add = ax_add.begin();\n    ad_iterator av_add = ax_add.begin() + ad_difference_type(m);\n    //\n    // ay\n    ad_vector ay(m);\n    //\n    // px\n    // assigning to the value zero does not create operators on the tape\n    for(size_t j = 0; j < n; ++j)\n    {   for(size_t k = 0; k < q; ++k)\n            apx[j * q + k] = 0.0;\n    }\n    //\n    // k\n    size_t k = q;\n    while(k)\n    {   --k;\n        //\n        // au_mul = apy^k\n        copy_mat_to_vec(m, q, k, apy.begin(), au_mul);\n        //\n        // d\n        for(size_t d = 0; d <=k; ++d)\n        {   // -------------------------------------------------------------\n            // reverse:\n            //  px[v_index] += CppAD::azmul( py[y_index] , tx[u_index] );\n            // -------------------------------------------------------------\n\n            // av_mul = atu^{k-d}\n            copy_mat_to_vec(m, q, k-d, atu, av_mul);\n            //\n            // ay = au_mul * av_mul\n            (*this)(mul_enum, ax_mul, ay);\n            //\n            // au_add = ay\n            for(size_t i = 0; i < m; ++i)\n                au_add[i] = ay[i];\n            //\n            // av_add = apv^d\n            copy_mat_to_vec(m, q, d, apv, av_add);\n            //\n            // ay = au_add + av_add\n            (*this)(add_enum, ax_add, ay);\n            //\n            // apv^d =  ay\n            copy_vec_to_mat(m, q, d, ay.begin(), apv);\n            // -------------------------------------------------------------\n            // reverse:\n            //  px[u_index] += CppAD::azmul( py[y_index] , tx[v_index] );\n            // -------------------------------------------------------------\n            // av_mul = atv^{k-d}\n            copy_mat_to_vec(m, q, k-d, atv, av_mul);\n            //\n            // ay = au_mul * av_mul\n            (*this)(mul_enum, ax_mul, ay);\n            //\n            // au_add = ay\n            for(size_t i = 0; i < m; ++i)\n                au_add[i] = ay[i];\n            //\n            // av_add = apu^d\n            copy_mat_to_vec(m, q, d, apu, av_add);\n            //\n            // ay = au_add + av_add\n            (*this)(add_enum, ax_add, ay);\n            //\n            // apu^d =  ay\n            copy_vec_to_mat(m, q, d, ay.begin(), apu);\n        }\n    }\n}\n} // END_CPPAD_NAMESPACE\n// END C++\n# endif\n"
  },
  {
    "path": "include/cppad/example/atomic_four/vector/neg_op.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_ATOMIC_FOUR_VECTOR_NEG_OP_HPP\n# define CPPAD_EXAMPLE_ATOMIC_FOUR_VECTOR_NEG_OP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_four_vector_neg_op.hpp}\n\nAtomic Vector Negative Operator: Example Implementation\n#######################################################\n\nExample\n*******\nThe file :ref:`atomic_four_vector_neg.cpp-name` contains an example\nand test for this operator.\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end atomic_four_vector_neg_op.hpp}\n*/\n// BEGIN C++\n# include <cppad/example/atomic_four/vector/vector.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n// ---------------------------------------------------------------------------\ntemplate <class Base>\nvoid atomic_vector<Base>::forward_neg(\n    size_t                                           m,\n    size_t                                           p,\n    size_t                                           q,\n    const CppAD::vector<Base>&                       tx,\n    CppAD::vector<Base>&                             ty)\n{\n    for(size_t k = p; k < q; ++k)\n    {   for(size_t i = 0; i < m; ++i)\n        {   size_t u_index  = i * q + k;\n            size_t y_index  = i * q + k;\n            // y_i^k = - u_i^k\n            ty[y_index] = - tx[u_index];\n        }\n    }\n}\ntemplate <class Base>\nvoid atomic_vector<Base>::forward_neg(\n    size_t                                           m,\n    size_t                                           p,\n    size_t                                           q,\n    const CppAD::vector< CppAD::AD<Base> >&          atx,\n    CppAD::vector< CppAD::AD<Base> >&                aty)\n{   size_t n = m;\n    assert( atx.size() == n * q );\n    assert( aty.size() == m * q );\n    //\n    // atu\n    ad_const_iterator atu = atx.begin();\n    //\n    // ax\n    ad_vector ax(n);\n    ad_iterator au = ax.begin();\n    //\n    // ay\n    ad_vector ay(m);\n    //\n    for(size_t k = p; k < q; ++k)\n    {   // au = u^k\n        copy_mat_to_vec(m, q, k, atu, au);\n        // ay = - au\n        (*this)(neg_enum, ax, ay); // atomic vector neg\n        // y^k = ay\n        copy_vec_to_mat(m, q, k, ay.begin(), aty.begin() );\n    }\n}\n// ---------------------------------------------------------------------------\n// reverse_neg\ntemplate <class Base>\nvoid atomic_vector<Base>::reverse_neg(\n    size_t                                           m,\n    size_t                                           q,\n    const CppAD::vector<Base>&                       tx,\n    const CppAD::vector<Base>&                       ty,\n    CppAD::vector<Base>&                             px,\n    const CppAD::vector<Base>&                       py)\n{\n    for(size_t k = 0; k < q; ++k)\n    {   for(size_t i = 0; i < m; ++i)\n        {   size_t u_index  = i * q + k;\n            size_t y_index  = i * q + k;\n            // y_i^k = - u_i^k\n            px[u_index] = - py[y_index];\n        }\n    }\n}\ntemplate <class Base>\nvoid atomic_vector<Base>::reverse_neg(\n    size_t                                           m,\n    size_t                                           q,\n    const CppAD::vector< CppAD::AD<Base> >&          atx,\n    const CppAD::vector< CppAD::AD<Base> >&          aty,\n    CppAD::vector< CppAD::AD<Base> >&                apx,\n    const CppAD::vector< CppAD::AD<Base> >&          apy)\n{   size_t n = m;\n    assert( atx.size() == n * q );\n    assert( aty.size() == m * q );\n    //\n    // apu\n    ad_iterator apu = apx.begin();\n    //\n    // ax\n    ad_vector ax(n);\n    ad_iterator au = ax.begin();\n    //\n    // ay\n    ad_vector ay(m);\n    //\n    for(size_t k = 0; k < q; ++k)\n    {   // au = py^k\n        copy_mat_to_vec(m, q, k, apy.begin(), au);\n        // ay = - au\n        (*this)(neg_enum, ax, ay); // atomic vector neg\n        // pu^k = ay\n        copy_vec_to_mat(m, q, k, ay.begin(), apu);\n    }\n}\n} // END_CPPAD_NAMESPACE\n// END C++\n# endif\n"
  },
  {
    "path": "include/cppad/example/atomic_four/vector/rev_depend.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_ATOMIC_FOUR_VECTOR_REV_DEPEND_HPP\n# define CPPAD_EXAMPLE_ATOMIC_FOUR_VECTOR_REV_DEPEND_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-23 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_four_vector_rev_depend.hpp}\n\nAtomic Vector Forward Type Calculation: Example Implementation\n##############################################################\n\nPurpose\n*******\nThe ``rev_depend`` routine overrides the virtual functions\nused by the atomic_four base class for Jacobian sparsity calculations; see\n:ref:`rev_depend<atomic_four_rev_depend-name>` .\n\nExample\n*******\nThe file :ref:`atomic_four_vector_rev_depend.cpp-name`\ncontains an example and test that uses this member function.\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end atomic_four_vector_rev_depend.hpp}\n*/\n// BEGIN C++\n# include <cppad/example/atomic_four/vector/vector.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n//\n// rev_depend override\ntemplate <class Base>\nbool atomic_vector<Base>::rev_depend(\n    size_t                         call_id     ,\n    const CppAD::vector<bool>&     ident_zero_x,\n    CppAD::vector<bool>&           depend_x    ,\n    const CppAD::vector<bool>&     depend_y    )\n{\n    // n, m\n    size_t n     = depend_x.size();\n    size_t m     = depend_y.size();\n    //\n    // type_y\n    if( n == m  )\n    {   // unary operator\n        for(size_t i = 0; i < m; ++i)\n            depend_x[i] = depend_y[i];\n    }\n    else\n    {   // binary operator\n        for(size_t i = 0; i < m; ++i)\n        {   depend_x[i]     = depend_y[i];\n            depend_x[m + i] = depend_y[i];\n        }\n    }\n    return true;\n}\n} // END_CPPAD_NAMESPACE\n// END C++\n# endif\n"
  },
  {
    "path": "include/cppad/example/atomic_four/vector/reverse_op.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_ATOMIC_FOUR_VECTOR_REVERSE_OP_HPP\n# define CPPAD_EXAMPLE_ATOMIC_FOUR_VECTOR_REVERSE_OP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_four_vector_reverse_op.hpp}\n\nAtomic Vector Forward Mode: Example Implementation\n##################################################\n\nPurpose\n*******\nThe ``reverse`` routine overrides the virtual functions\nused by the atomic_four base class for reverse mode calculations; see\n:ref:`reverse<atomic_four_reverse-name>` .\nIt determines which operator is specified for this call and transfers\nthe call to the operator's implementation.\nThere are two versions of the ``reverse`` routine, one for *Base*\nand one for ``AD<Base>`` .\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end atomic_four_vector_reverse_op.hpp}\n*/\n// BEGIN C++\n# include <cppad/example/atomic_four/vector/vector.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n//\n// reverse override\n// this routine used by ADFun<Base> objects\ntemplate <class Base>\nbool atomic_vector<Base>::reverse(\n    size_t                                           call_id,\n    const CppAD::vector<bool>&                       select_x,\n    size_t                                           order_up,\n    const CppAD::vector<Base>&                       tx,\n    const CppAD::vector<Base>&                       ty,\n    CppAD::vector<Base>&                             px,\n    const CppAD::vector<Base>&                       py)\n{\n    // q\n    size_t q = order_up + 1;\n    //\n    // op, n, m\n    op_enum_t op = op_enum_t( call_id );\n    size_t n     = select_x.size();\n    size_t m  = n / 2;\n    if( is_unary(op) )\n        m = n;\n    assert( tx.size() == q * n );\n    assert( ty.size() == q * m );\n    //\n    bool ok = false;\n    switch(op)\n    {\n        // addition\n        case add_enum:\n        reverse_add(m, q, tx, ty, px, py);\n        ok = true;\n        break;\n\n        // subtraction\n        case sub_enum:\n        reverse_sub(m, q, tx, ty, px, py);\n        ok = true;\n        break;\n\n        // multiplication\n        case mul_enum:\n        reverse_mul(m, q, tx, ty, px, py);\n        ok = true;\n        break;\n\n        // division\n        case div_enum:\n        reverse_div(m, q, tx, ty, px, py);\n        ok = true;\n        break;\n\n        // unary minus\n        case neg_enum:\n        reverse_neg(m, q, tx, ty, px, py);\n        ok = true;\n        break;\n\n        // error\n        case number_op_enum:\n        assert(false);\n        break;\n    }\n    return ok;\n}\n// reverse override\n// this routine used by ADFun< CppAD::AD<Base> , Base> objects\ntemplate <class Base>\nbool atomic_vector<Base>::reverse(\n    size_t                                           call_id,\n    const CppAD::vector<bool>&                       select_x,\n    size_t                                           order_up,\n    const CppAD::vector< CppAD::AD<Base> >&          atx,\n    const CppAD::vector< CppAD::AD<Base> >&          aty,\n    CppAD::vector< CppAD::AD<Base> >&                apx,\n    const CppAD::vector< CppAD::AD<Base> >&          apy)\n{\n    // q\n    size_t q = order_up + 1;\n    //\n    // op, m\n    op_enum_t op = op_enum_t( call_id );\n    size_t n     = select_x.size();\n    size_t m  = n / 2;\n    if( is_unary(op) )\n        m = n;\n    assert( atx.size() == q * n );\n    assert( aty.size() == q * m );\n    bool ok = false;\n    switch(op)\n    {\n        // addition\n        case add_enum:\n        reverse_add(m, q, atx, aty, apx, apy);\n        ok = true;\n        break;\n\n        // subtraction\n        case sub_enum:\n        reverse_sub(m, q, atx, aty, apx, apy);\n        ok = true;\n        break;\n\n        // multiplication\n        case mul_enum:\n        reverse_mul(m, q, atx, aty, apx, apy);\n        ok = true;\n        break;\n\n        // division\n        case div_enum:\n        reverse_div(m, q, atx, aty, apx, apy);\n        ok = true;\n        break;\n\n        // unary minus\n        case neg_enum:\n        reverse_neg(m, q, atx, aty, apx, apy);\n        ok = true;\n        break;\n\n        // error\n        case number_op_enum:\n        assert(false);\n        break;\n    }\n    return ok;\n}\n} // END_CPPAD_NAMESPACE\n// END C++\n# endif\n"
  },
  {
    "path": "include/cppad/example/atomic_four/vector/sub_op.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_ATOMIC_FOUR_VECTOR_SUB_OP_HPP\n# define CPPAD_EXAMPLE_ATOMIC_FOUR_VECTOR_SUB_OP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_four_vector_sub_op.hpp}\n\nAtomic Vector Subtract Operator: Example Implementation\n#######################################################\n\nForward Mode\n************\nsee theory for forward mode\n:ref:`forward_theory@Binary Operators@Subtraction` .\n\nReverse Mode\n************\nsee theory for reverse mode\n:ref:`reverse_theory@Binary Operators@Subtraction` .\n\nExample\n*******\nThe file :ref:`atomic_four_vector_sub.cpp-name` contains an example\nand test for this operator.\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end atomic_four_vector_sub_op.hpp}\n*/\n// BEGIN C++\n# include <cppad/example/atomic_four/vector/vector.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n// --------------------------------------------------------------------------\n// forward_sub\ntemplate <class Base>\nvoid atomic_vector<Base>::forward_sub(\n    size_t                                           m,\n    size_t                                           p,\n    size_t                                           q,\n    const CppAD::vector<Base>&                       tx,\n    CppAD::vector<Base>&                             ty)\n{\n    for(size_t k = p; k < q; ++k)\n    {   for(size_t i = 0; i < m; ++i)\n        {   size_t u_index  =       i * q + k;\n            size_t v_index  = (m + i) * q + k;\n            size_t y_index  =       i * q + k;\n            // y_i^k = u_i^k - v_i^k\n            ty[y_index]     = tx[u_index] - tx[v_index];\n        }\n    }\n}\ntemplate <class Base>\nvoid atomic_vector<Base>::forward_sub(\n    size_t                                           m,\n    size_t                                           p,\n    size_t                                           q,\n    const CppAD::vector< CppAD::AD<Base> >&          atx,\n    CppAD::vector< CppAD::AD<Base> >&                aty)\n{\n    size_t n = 2 * m;\n    assert( atx.size() == n * q );\n    assert( aty.size() == m * q );\n    //\n    // atu, atv\n    ad_const_iterator atu = atx.begin();\n    ad_const_iterator atv = atu + ad_difference_type(m * q);\n    //\n    // ax\n    ad_vector ax(n);\n    ad_iterator au = ax.begin();\n    ad_iterator av = au + ad_difference_type(m);\n    //\n    // ay\n    ad_vector ay(m);\n    //\n    for(size_t k = p; k < q; ++k)\n    {   // au = u^k\n        copy_mat_to_vec(m, q, k, atu, au);\n        // av = v^k\n        copy_mat_to_vec(m, q, k, atv, av);\n        // ay = au - av\n        (*this)(sub_enum, ax, ay); // atomic vector sub\n        // y^k = ay\n        copy_vec_to_mat(m, q, k, ay.begin(), aty.begin());\n    }\n}\n// --------------------------------------------------------------------------\n// reverse_sub\ntemplate <class Base>\nvoid atomic_vector<Base>::reverse_sub(\n    size_t                                           m,\n    size_t                                           q,\n    const CppAD::vector<Base>&                       tx,\n    const CppAD::vector<Base>&                       ty,\n    CppAD::vector<Base>&                             px,\n    const CppAD::vector<Base>&                       py)\n{\n    for(size_t k = 0; k < q; ++k)\n    {   for(size_t i = 0; i < m; ++i)\n        {   size_t u_index  =       i * q + k;\n            size_t v_index  = (m + i) * q + k;\n            size_t y_index  =       i * q + k;\n            // y_i^k = u_i^k + v_i^k\n            px[u_index] =   py[y_index];\n            px[v_index] = - py[y_index];\n        }\n    }\n}\ntemplate <class Base>\nvoid atomic_vector<Base>::reverse_sub(\n    size_t                                           m,\n    size_t                                           q,\n    const CppAD::vector< CppAD::AD<Base> >&          atx,\n    const CppAD::vector< CppAD::AD<Base> >&          aty,\n    CppAD::vector< CppAD::AD<Base> >&                apx,\n    const CppAD::vector< CppAD::AD<Base> >&          apy)\n{\n# ifndef NDEBUG\n    size_t n = 2 * m;\n    assert( atx.size() == n * q );\n    assert( aty.size() == m * q );\n    assert( apx.size() == n * q );\n    assert( apy.size() == m * q );\n# endif\n    //\n    // apu, apv\n    ad_iterator apu = apx.begin();\n    ad_iterator apv = apu + ad_difference_type(m * q);\n    //\n    // ax\n    ad_vector ax(m);\n    ad_iterator au = ax.begin();\n    //\n    // ay\n    ad_vector ay(m);\n    //\n    for(size_t k = 0; k < q; ++k)\n    {   // au = apy^k\n        copy_mat_to_vec(m, q, k, apy.begin(), au);\n        // apu^k = au\n        copy_vec_to_mat(m, q, k, au, apu);\n        // ay = - au\n        (*this)(neg_enum, ax, ay); // atomic vector neg\n        // apv^k = ay\n        copy_vec_to_mat(m, q, k, ay.begin(), apv);\n    }\n}\n} // END_CPPAD_NAMESPACE\n// END C++\n# endif\n"
  },
  {
    "path": "include/cppad/example/atomic_four/vector/vector.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_ATOMIC_FOUR_VECTOR_VECTOR_HPP\n# define CPPAD_EXAMPLE_ATOMIC_FOUR_VECTOR_VECTOR_HPP\n\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-23 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_four_vector.hpp}\n\nAtomic Vector Class: Example Implementation\n###########################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end atomic_four_vector.hpp}\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\n// declare forward_op and reverse_op for Base and AD<Base> cases\n// where op is an operator name; e.g., forward_add and reverse_add.\n# define CPPAD_ATOMIC_FOUR_FORWARD_AND_REVERSE(op)             \\\n    static void forward_ ## op(                                \\\n        size_t                                           m,    \\\n        size_t                                           p,    \\\n        size_t                                           q,    \\\n        const CppAD::vector<Base>&                       tx,   \\\n        CppAD::vector<Base>&                             ty    \\\n    );                                                         \\\n    void forward_ ## op(                                       \\\n        size_t                                           m,    \\\n        size_t                                           p,    \\\n        size_t                                           q,    \\\n        const CppAD::vector< CppAD::AD<Base> >&          atx,  \\\n        CppAD::vector< CppAD::AD<Base> >&                aty   \\\n    );                                                         \\\n    static void reverse_ ## op(                                \\\n        size_t                                           m,    \\\n        size_t                                           q,    \\\n        const CppAD::vector<Base>&                       tx,   \\\n        const CppAD::vector<Base>&                       ty,   \\\n        CppAD::vector<Base>&                             px,   \\\n        const CppAD::vector<Base>&                       py    \\\n    );                                                         \\\n    void reverse_ ## op(                                       \\\n        size_t                                           m,    \\\n        size_t                                           q,    \\\n        const CppAD::vector< CppAD::AD<Base> >&          atx,  \\\n        const CppAD::vector< CppAD::AD<Base> >&          aty,  \\\n        CppAD::vector< CppAD::AD<Base> >&                apx,  \\\n        const CppAD::vector< CppAD::AD<Base> >&          apy   \\\n    );\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n//\ntemplate <class Base>\nclass atomic_vector : public CppAD::atomic_four<Base> {\n//\npublic:\n    // BEGIN_SORT_THIS_LINE_PLUS_4\n    // BEGIN op_enum_t\n    // atomic_vector::op_enum_t\n    typedef enum {\n        add_enum,\n        div_enum,\n        mul_enum,\n        neg_enum,\n        sub_enum,\n        number_op_enum\n    } op_enum_t;\n    // END op_enum_t\n    // END_SORT_THIS_LINE_MINUS_4\n    //\n    // ctor\n    atomic_vector(const std::string& name) :\n    CppAD::atomic_four<Base>(name)\n    { }\nprivate:\n    typedef CppAD::vector< CppAD::AD<Base> >      ad_vector;\n    typedef typename ad_vector::iterator          ad_iterator;\n    typedef typename ad_vector::const_iterator    ad_const_iterator;\n    typedef typename ad_iterator::difference_type ad_difference_type;\n    //\n    static bool is_unary(op_enum_t op)\n    {   bool result = true;\n        switch(op)\n        {   case add_enum:\n            case sub_enum:\n            case mul_enum:\n            case div_enum:\n            result = false;\n            break;\n\n            default:\n            break;\n        }\n        return result;\n    }\n    // ------------------------------------------------------------------------\n    // copy routines\n    // ------------------------------------------------------------------------\n    static void copy_vec_to_mat(\n        size_t            m,\n        size_t            q,\n        size_t            k ,\n        ad_const_iterator vec,\n        ad_iterator       mat)\n    {   for(size_t i = 0; i < m; ++i)\n        {   size_t index  = i * q + k;\n            *(mat + ad_difference_type(index) ) =\n                *(vec + ad_difference_type(i) );\n        }\n    }\n    // copy_mat_to_vec\n    static void copy_mat_to_vec(\n        size_t            m,\n        size_t            q,\n        size_t            k,\n        ad_const_iterator mat,\n        ad_iterator       vec)\n    {   for(size_t i = 0; i < m; ++i)\n        {   size_t index  = i * q + k;\n            *(vec + ad_difference_type(i) ) =\n                *(mat + ad_difference_type(index) );\n        }\n    }\n    // -----------------------------------------------------------------------\n    // overrides\n    // -----------------------------------------------------------------------\n    //\n    // for_type\n    bool for_type(\n        size_t                                     call_id     ,\n        const CppAD::vector<CppAD::ad_type_enum>&  type_x      ,\n        CppAD::vector<CppAD::ad_type_enum>&        type_y\n    ) override;\n    //\n    // rev_depend\n    bool rev_depend(\n        size_t                         call_id     ,\n        const CppAD::vector<bool>&    ident_zero_x ,\n        CppAD::vector<bool>&           depend_x    ,\n        const CppAD::vector<bool>&     depend_y\n    ) override;\n    //\n    // jac_sparsity\n    bool jac_sparsity(\n        size_t                                         call_id      ,\n        bool                                           dependency   ,\n        const CppAD::vector<bool>&                     ident_zero_x ,\n        const CppAD::vector<bool>&                     select_x     ,\n        const CppAD::vector<bool>&                     select_y     ,\n        CppAD::sparse_rc< CppAD::vector<size_t> >&     pattern_out\n    ) override;\n    //\n    // hes_sparsity\n    bool hes_sparsity(\n        size_t                                         call_id      ,\n        const CppAD::vector<bool>&                     ident_zero_x ,\n        const CppAD::vector<bool>&                     select_x     ,\n        const CppAD::vector<bool>&                     select_y     ,\n        CppAD::sparse_rc< CppAD::vector<size_t> >&     pattern_out\n    ) override;\n    //\n    // Base forward\n    bool forward(\n        size_t                                           call_id,\n        const CppAD::vector<bool>&                       select_y,\n        size_t                                           order_low,\n        size_t                                           order_up,\n        const CppAD::vector<Base>&                       tx,\n        CppAD::vector<Base>&                             ty\n    ) override;\n    //\n    // AD<Base> forward\n    bool forward(\n        size_t                                           call_id,\n        const CppAD::vector<bool>&                       select_y,\n        size_t                                           order_low,\n        size_t                                           order_up,\n        const CppAD::vector< CppAD::AD<Base> >&          atx,\n        CppAD::vector< CppAD::AD<Base> >&                aty\n    ) override;\n    //\n    // Base reverse\n    bool reverse(\n        size_t                                           call_id,\n        const CppAD::vector<bool>&                       select_x,\n        size_t                                           order_up,\n        const CppAD::vector<Base>&                       tx,\n        const CppAD::vector<Base>&                       ty,\n        CppAD::vector<Base>&                             px,\n        const CppAD::vector<Base>&                       py\n    ) override;\n    //\n    // AD<Base> reverse\n    bool reverse(\n        size_t                                           call_id,\n        const CppAD::vector<bool>&                       select_x,\n        size_t                                           order_up,\n        const CppAD::vector< CppAD::AD<Base> >&          atx,\n        const CppAD::vector< CppAD::AD<Base> >&          aty,\n        CppAD::vector< CppAD::AD<Base> >&                apx,\n        const CppAD::vector< CppAD::AD<Base> >&          apy\n    ) override;\n    // ----------------------------------------------------------------------\n    // Forward and Reverse Implementation Routines\n    // ----------------------------------------------------------------------\n    CPPAD_ATOMIC_FOUR_FORWARD_AND_REVERSE(add)\n    CPPAD_ATOMIC_FOUR_FORWARD_AND_REVERSE(sub)\n    CPPAD_ATOMIC_FOUR_FORWARD_AND_REVERSE(mul)\n    CPPAD_ATOMIC_FOUR_FORWARD_AND_REVERSE(div)\n    CPPAD_ATOMIC_FOUR_FORWARD_AND_REVERSE(neg)\n};\n} // END_CPPAD_NAMESPACE\n\n# undef CPPAD_ATOMIC_FOUR_FORWARD_AND_REVERSE\n\n# include <cppad/example/atomic_four/vector/rev_depend.hpp>\n# include <cppad/example/atomic_four/vector/for_type.hpp>\n# include <cppad/example/atomic_four/vector/jac_sparsity.hpp>\n# include <cppad/example/atomic_four/vector/hes_sparsity.hpp>\n# include <cppad/example/atomic_four/vector/reverse_op.hpp>\n# include <cppad/example/atomic_four/vector/forward_op.hpp>\n# include <cppad/example/atomic_four/vector/neg_op.hpp>\n# include <cppad/example/atomic_four/vector/div_op.hpp>\n# include <cppad/example/atomic_four/vector/mul_op.hpp>\n# include <cppad/example/atomic_four/vector/sub_op.hpp>\n# include <cppad/example/atomic_four/vector/add_op.hpp>\n// END C++\n\n# endif\n"
  },
  {
    "path": "include/cppad/example/atomic_four/vector/vector.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin atomic_four_vector}\n\nAtomic Vector Element-wise Operators: Example and Test\n######################################################\n\nSyntax\n******\n| ``atomic_vector_op`` *vec_op* ( *name* )\n| *vec_op* ( *op* , *x* , *y* )\n\nop\n**\nThe value *op* has the following possible values:\n{xrst_literal\n    include/cppad/example/atomic_four/vector/vector.hpp\n    // BEGIN op_enum_t\n    // END op_enum_t\n}\n\nPurpose\n*******\nThis atomic function class can be used as a general purpose utility.\nIt is unclear how much benefit there is do doing so.\nThis is because the number of operations internal to an element-wise\natomic function is not much more than the work required to pass the\narguments to the atomic function.\n\nVector Operations\n=================\nThis atomic function unary operations\n\n    *y* = *op* ( ``u`` )\n\nand binary operations\n\n    *y* = *u* *op* *v*\n\nwhere *op* , *u* and *v* are defined below.\n\natomic_four\n===========\nThis example demonstrates all the callbacks for an\n:ref:`atomic_four-name` function.\n\nbase2ad\n=======\nIt include examples for how one can\ndefine ``AD`` < *Base* > atomic operations using atomic operators.\nThis avoids expanding the atomic operator to an operator for each element\nwhen recording derivative calculations.\nFor example, notice the difference between ``forward_add``\nfor the ``double`` and the ``AD<double>`` cases\n(note that copying an AD variable does not create a new variable):\n{xrst_literal\n    include/cppad/example/atomic_four/vector/add_op.hpp\n    // BEGIN forward_add\n    // END forward_add\n}\n\nx\n*\nWe use *x* to denote the argument to the atomic function.\nThe length of *x* is denoted by *n* .\n\nm\n*\nThis is the length of the vectors in the operations.\nIn the case of unary (binary) operators\n*m* = *n*  ( *m* = *n*  / 2 ).\n\nu\n*\nWe use *u* to denote the following sub-vector of *x* :\n\n    *u* = ( *x* [1] , ... , *x* [ *m* ] )\n\nv\n*\nFor binary operators,\nwe use *v* to denote the following sub-vector of *x* :\n\n    *v* = ( *x* [ *m* + 1] , ... , *x* [2 * *m* ] )\n\ny\n*\nWe use *y* to denote the atomic function return value.\nThe length of *y* is equal to *m* .\n\nAD<double>\n**********\nDuring ``AD<double>`` operations, copying variables\nfrom one vector to another does not add any operations to the\nresulting tape.\n\n\nContents\n********\n{xrst_comment BEGIN_SORT_THIS_LINE_PLUS_2}\n{xrst_toc_table\n    example/atomic_four/vector/add.cpp\n    example/atomic_four/vector/div.cpp\n    example/atomic_four/vector/hes_sparsity.cpp\n    example/atomic_four/vector/jac_sparsity.cpp\n    example/atomic_four/vector/mul.cpp\n    example/atomic_four/vector/neg.cpp\n    example/atomic_four/vector/rev_depend.cpp\n    example/atomic_four/vector/sub.cpp\n    include/cppad/example/atomic_four/vector/implement.xrst\n}\n{xrst_comment END_SORT_THIS_LINE_MINUS_2}\n\n{xrst_end atomic_four_vector}\n"
  },
  {
    "path": "include/cppad/example/atomic_three/mat_mul.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_ATOMIC_THREE_MAT_MUL_HPP\n# define CPPAD_EXAMPLE_ATOMIC_THREE_MAT_MUL_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin atomic_three_mat_mul.hpp}\n{xrst_spell\n    nr\n    px\n    tx\n}\n\nMatrix Multiply as an Atomic Operation\n######################################\n\nSee Also\n********\n:ref:`atomic_two_eigen_mat_mul.hpp-name`\n\nPurpose\n*******\nUse scalar ``double`` operations in an :ref:`atomic_three-name` operation\nthat computes the matrix product for ``AD<double`` operations.\n\nparameter_x\n===========\nThis example demonstrates the use of the\n:ref:`atomic_three_define@parameter_x`\nargument to the :ref:`atomic_three-name` virtual functions.\n\ntype_x\n======\nThis example also demonstrates the use of the\n:ref:`atomic_three_define@type_x`\nargument to the :ref:`atomic_three-name` virtual functions.\n\nMatrix Dimensions\n*****************\nThe first three components of the argument vector *ax*\nin the call *afun* ( *ax* , *ay* )\nare parameters and contain the matrix dimensions.\nThis enables them to be different for each use of the same atomic\nfunction *afun* .\nThese dimensions are:\n\n.. list-table::\n    :widths: auto\n\n    * - *ax* [0]\n      - *nr_left*\n      - number of rows in the left matrix and result matrix\n    * - *ax* [1]\n      - *n_middle*\n      - columns in the left matrix and rows in right matrix\n    * - *ax* [2]\n      - *nc_right*\n      - number of columns in the right matrix and result matrix\n\nLeft Matrix\n***********\nThe number of elements in the left matrix is\n\n    *n_left* = *nr_left* * *n_middle*\n\nThe elements are in\n*ax* [3] through *ax* [2+ *n_left* ] in row major order.\n\nRight Matrix\n************\nThe number of elements in the right matrix is\n\n    *n_right* = *n_middle* * *nc_right*\n\nThe elements are in\n*ax* [3+ *n_left* ] through\n*ax* [2+ *n_left* + *n_right* ] in row major order.\n\nResult Matrix\n*************\nThe number of elements in the result matrix is\n\n    *n_result* = *nr_left* * *nc_right*\n\nThe elements are in\n*ay* [0] through *ay* [ *n_result* ``-1`` ] in row major order.\n\nStart Class Definition\n**********************\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <cppad/cppad.hpp>\nnamespace { // Begin empty namespace\nusing CppAD::vector;\n//\n// matrix result = left * right\nclass atomic_mat_mul : public CppAD::atomic_three<double> {\n/* {xrst_code}\n{xrst_spell_on}\nConstructor\n***********\n{xrst_spell_off}\n{xrst_code cpp} */\npublic:\n    // ---------------------------------------------------------------------\n    // constructor\n    atomic_mat_mul(void) : CppAD::atomic_three<double>(\"mat_mul\")\n    { }\nprivate:\n/* {xrst_code}\n{xrst_spell_on}\nLeft Operand Element Index\n**************************\nIndex in the Taylor coefficient matrix *tx* of a left matrix element.\n{xrst_spell_off}\n{xrst_code cpp} */\n    size_t left(\n        size_t i        , // left matrix row index\n        size_t j        , // left matrix column index\n        size_t k        , // Taylor coeffocient order\n        size_t nk       , // number of Taylor coefficients in tx\n        size_t nr_left  , // rows in left matrix\n        size_t n_middle , // rows in left and columns in right\n        size_t nc_right ) // columns in right matrix\n    {  assert( i < nr_left );\n        assert( j < n_middle );\n        return (3 + i * n_middle + j) * nk + k;\n    }\n/* {xrst_code}\n{xrst_spell_on}\nRight Operand Element Index\n***************************\nIndex in the Taylor coefficient matrix *tx* of a right matrix element.\n{xrst_spell_off}\n{xrst_code cpp} */\n    size_t right(\n        size_t i        , // right matrix row index\n        size_t j        , // right matrix column index\n        size_t k        , // Taylor coeffocient order\n        size_t nk       , // number of Taylor coefficients in tx\n        size_t nr_left  , // rows in left matrix\n        size_t n_middle , // rows in left and columns in right\n        size_t nc_right ) // columns in right matrix\n    {  assert( i < n_middle );\n        assert( j < nc_right );\n        size_t offset = 3 + nr_left * n_middle;\n        return (offset + i * nc_right + j) * nk + k;\n    }\n/* {xrst_code}\n{xrst_spell_on}\nResult Element Index\n********************\nIndex in the Taylor coefficient matrix *ty* of a result matrix element.\n{xrst_spell_off}\n{xrst_code cpp} */\n    size_t result(\n        size_t i        , // result matrix row index\n        size_t j        , // result matrix column index\n        size_t k        , // Taylor coeffocient order\n        size_t nk       , // number of Taylor coefficients in ty\n        size_t nr_left  , // rows in left matrix\n        size_t n_middle , // rows in left and columns in right\n        size_t nc_right ) // columns in right matrix\n    {  assert( i < nr_left  );\n        assert( j < nc_right );\n        return (i * nc_right + j) * nk + k;\n    }\n/* {xrst_code}\n{xrst_spell_on}\nForward Matrix Multiply\n***********************\nForward mode multiply Taylor coefficients in *tx* and sum into\n*ty* (for one pair of left and right orders)\n{xrst_spell_off}\n{xrst_code cpp} */\n    void forward_multiply(\n        size_t                 k_left   , // order for left coefficients\n        size_t                 k_right  , // order for right coefficients\n        const vector<double>&  tx       , // domain space Taylor coefficients\n                  vector<double>&  ty       , // range space Taylor coefficients\n        size_t                 nr_left  , // rows in left matrix\n        size_t                 n_middle , // rows in left and columns in right\n        size_t                 nc_right ) // columns in right matrix\n    {\n        size_t nx       = 3 + (nr_left + nc_right) * n_middle;\n        size_t nk       = tx.size() / nx;\n# ifndef NDEBUG\n        size_t ny       = nr_left * nc_right;\n        assert( nk == ty.size() / ny );\n# endif\n        //\n        size_t k_result = k_left + k_right;\n        assert( k_result < nk );\n        //\n        for(size_t i = 0; i < nr_left; i++)\n        {  for(size_t j = 0; j < nc_right; j++)\n            {  double sum = 0.0;\n                for(size_t ell = 0; ell < n_middle; ell++)\n                {  size_t i_left  = left(\n                        i, ell, k_left, nk, nr_left, n_middle, nc_right\n                    );\n                    size_t i_right = right(\n                        ell, j,  k_right, nk, nr_left, n_middle, nc_right\n                    );\n                    sum           += tx[i_left] * tx[i_right];\n                }\n                size_t i_result = result(\n                    i, j, k_result, nk, nr_left, n_middle, nc_right\n                );\n                ty[i_result]   += sum;\n            }\n        }\n    }\n/* {xrst_code}\n{xrst_spell_on}\nReverse Matrix Multiply\n***********************\nReverse mode partials of Taylor coefficients and sum into *px*\n(for one pair of left and right orders)\n{xrst_spell_off}\n{xrst_code cpp} */\n    void reverse_multiply(\n        size_t                 k_left  , // order for left coefficients\n        size_t                 k_right , // order for right coefficients\n        const vector<double>&  tx      , // domain space Taylor coefficients\n        const vector<double>&  ty      , // range space Taylor coefficients\n                  vector<double>&  px      , // partials w.r.t. tx\n        const vector<double>&  py      , // partials w.r.t. ty\n        size_t                 nr_left  , // rows in left matrix\n        size_t                 n_middle , // rows in left and columns in right\n        size_t                 nc_right ) // columns in right matrix\n    {\n        size_t nx       = 3 + (nr_left + nc_right) * n_middle;\n        size_t nk       = tx.size() / nx;\n# ifndef NDEBUG\n        size_t ny       = nr_left * nc_right;\n        assert( nk == ty.size() / ny );\n# endif\n        assert( tx.size() == px.size() );\n        assert( ty.size() == py.size() );\n        //\n        size_t k_result = k_left + k_right;\n        assert( k_result < nk );\n        //\n        for(size_t i = 0; i < nr_left; i++)\n        {  for(size_t j = 0; j < nc_right; j++)\n            {  size_t i_result = result(\n                    i, j, k_result, nk, nr_left, n_middle, nc_right\n                );\n                for(size_t ell = 0; ell < n_middle; ell++)\n                {  size_t i_left  = left(\n                        i, ell, k_left, nk, nr_left, n_middle, nc_right\n                    );\n                    size_t i_right = right(\n                        ell, j,  k_right, nk, nr_left, n_middle, nc_right\n                    );\n                    // sum        += tx[i_left] * tx[i_right];\n                    px[i_left]    += tx[i_right] * py[i_result];\n                    px[i_right]   += tx[i_left]  * py[i_result];\n                }\n            }\n        }\n        return;\n    }\n/* {xrst_code}\n{xrst_spell_on}\nfor_type\n********\nRoutine called by CppAD during :ref:`afun(ax, ay)<atomic_three_afun-name>` .\n{xrst_spell_off}\n{xrst_code cpp} */\n    // calculate type_y\n    virtual bool for_type(\n        const vector<double>&               parameter_x ,\n        const vector<CppAD::ad_type_enum>&  type_x      ,\n        vector<CppAD::ad_type_enum>&        type_y      )\n    {  assert( parameter_x.size() == type_x.size() );\n        bool ok = true;\n        ok &= type_x[0] == CppAD::constant_enum;\n        ok &= type_x[1] == CppAD::constant_enum;\n        ok &= type_x[2] == CppAD::constant_enum;\n        if( ! ok )\n            return false;\n        //\n        size_t nr_left  = size_t( parameter_x[0] );\n        size_t n_middle = size_t( parameter_x[1] );\n        size_t nc_right = size_t( parameter_x[2] );\n        //\n        ok &= type_x.size() == 3 + (nr_left + nc_right) * n_middle;\n        ok &= type_y.size() == n_middle * nc_right;\n        if( ! ok )\n            return false;\n        //\n        // compute type_y\n        size_t nk = 1; // number of orders\n        size_t k  = 0; // order\n        for(size_t i = 0; i < nr_left; ++i)\n        {  for(size_t j = 0; j < nc_right; ++j)\n            {  // compute type for result[i, j]\n                CppAD::ad_type_enum type_yij = CppAD::constant_enum;\n                for(size_t ell = 0; ell < n_middle; ++ell)\n                {  // index for left(i, ell)\n                    size_t i_left = left(\n                        i, ell, k, nk, nr_left, n_middle, nc_right\n                    );\n                    // index for right(ell, j)\n                    size_t i_right = right(\n                        ell, j, k, nk, nr_left, n_middle, nc_right\n                    );\n                    // multiplication on left or right by the constant zero\n                    // always results in a constant\n                    bool zero_left  = type_x[i_left] == CppAD::constant_enum;\n                    zero_left      &= parameter_x[i_left] == 0.0;\n                    bool zero_right = type_x[i_right] == CppAD::constant_enum;\n                    zero_right     &= parameter_x[i_right] == 0.0;\n                    if( ! (zero_left | zero_right) )\n                    {  type_yij = std::max(type_yij, type_x[i_left] );\n                        type_yij = std::max(type_yij, type_x[i_right] );\n                    }\n                }\n                size_t i_result = result(\n                    i, j, k, nk, nr_left, n_middle, nc_right\n                );\n                type_y[i_result] = type_yij;\n            }\n        }\n        return true;\n    }\n/* {xrst_code}\n{xrst_spell_on}\nforward\n*******\nRoutine called by CppAD during :ref:`Forward-name` mode.\n{xrst_spell_off}\n{xrst_code cpp} */\n    virtual bool forward(\n        const vector<double>&              parameter_x ,\n        const vector<CppAD::ad_type_enum>& type_x ,\n        size_t                             need_y ,\n        size_t                             q      ,\n        size_t                             p      ,\n        const vector<double>&              tx     ,\n        vector<double>&                    ty     )\n    {  size_t n_order  = p + 1;\n        size_t nr_left  = size_t( tx[ 0 * n_order + 0 ] );\n        size_t n_middle = size_t( tx[ 1 * n_order + 0 ] );\n        size_t nc_right = size_t( tx[ 2 * n_order + 0 ] );\n# ifndef NDEBUG\n        size_t nx       = 3 + (nr_left + nc_right) * n_middle;\n        size_t ny       = nr_left * nc_right;\n# endif\n        assert( nx * n_order == tx.size() );\n        assert( ny * n_order == ty.size() );\n        size_t i, j, ell;\n\n        // initialize result as zero\n        size_t k;\n        for(i = 0; i < nr_left; i++)\n        {  for(j = 0; j < nc_right; j++)\n            {  for(k = q; k <= p; k++)\n                {  size_t i_result = result(\n                        i, j, k, n_order, nr_left, n_middle, nc_right\n                    );\n                    ty[i_result] = 0.0;\n                }\n            }\n        }\n        for(k = q; k <= p; k++)\n        {  // sum the produces that result in order k\n            for(ell = 0; ell <= k; ell++)\n                forward_multiply(\n                    ell, k - ell, tx, ty, nr_left, n_middle, nc_right\n                );\n        }\n\n        // all orders are implemented, so always return true\n        return true;\n    }\n/* {xrst_code}\n{xrst_spell_on}\nreverse\n*******\nRoutine called by CppAD during :ref:`Reverse-name` mode.\n{xrst_spell_off}\n{xrst_code cpp} */\n    virtual bool reverse(\n        const vector<double>&              parameter_x ,\n        const vector<CppAD::ad_type_enum>& type_x      ,\n        size_t                             p           ,\n        const vector<double>&              tx          ,\n        const vector<double>&              ty          ,\n        vector<double>&                    px          ,\n        const vector<double>&              py          )\n    {  size_t n_order  = p + 1;\n        size_t nr_left  = size_t( tx[ 0 * n_order + 0 ] );\n        size_t n_middle = size_t( tx[ 1 * n_order + 0 ] );\n        size_t nc_right = size_t( tx[ 2 * n_order + 0 ] );\n# ifndef NDEBUG\n        size_t nx       = 3 + (nr_left + nc_right) * n_middle;\n        size_t ny       = nr_left * nc_right;\n# endif\n        assert( nx * n_order == tx.size() );\n        assert( ny * n_order == ty.size() );\n        assert( px.size() == tx.size() );\n        assert( py.size() == ty.size() );\n\n        // initialize summation\n        for(size_t i = 0; i < px.size(); i++)\n            px[i] = 0.0;\n\n        // number of orders to differentiate\n        size_t k = n_order;\n        while(k--)\n        {  // differentiate the produces that result in order k\n            for(size_t ell = 0; ell <= k; ell++)\n                reverse_multiply(\n                    ell, k - ell, tx, ty, px, py, nr_left, n_middle, nc_right\n                );\n        }\n\n        // all orders are implemented, so always return true\n        return true;\n    }\n/* {xrst_code}\n{xrst_spell_on}\njac_sparsity\n************\n{xrst_spell_off}\n{xrst_code cpp} */\n    // Jacobian sparsity routine called by CppAD\n    virtual bool jac_sparsity(\n        const vector<double>&               parameter_x ,\n        const vector<CppAD::ad_type_enum>&  type_x      ,\n        bool                                dependency  ,\n        const vector<bool>&                 select_x    ,\n        const vector<bool>&                 select_y    ,\n        CppAD::sparse_rc< vector<size_t> >& pattern_out )\n    {\n        size_t n = select_x.size();\n        size_t m = select_y.size();\n        assert( parameter_x.size() == n );\n        assert( type_x.size() == n );\n        //\n        size_t nr_left  = size_t( parameter_x[0] );\n        size_t n_middle = size_t( parameter_x[1] );\n        size_t nc_right = size_t( parameter_x[2] );\n        size_t nk       = 1; // only one order\n        size_t k        = 0; // order zero\n        //\n        // count number of non-zeros in sparsity pattern\n        size_t nnz = 0;\n        for(size_t i = 0; i < nr_left; ++i)\n        {  for(size_t j = 0; j < nc_right; ++j)\n            {  size_t i_result = result(\n                    i, j, k, nk, nr_left, n_middle, nc_right\n                );\n                if( select_y[i_result] )\n                {  for(size_t ell = 0; ell < n_middle; ++ell)\n                    {  size_t i_left = left(\n                            i, ell, k, nk, nr_left, n_middle, nc_right\n                        );\n                        size_t i_right = right(\n                            ell, j, k, nk, nr_left, n_middle, nc_right\n                        );\n                        bool zero_left  =\n                            type_x[i_left] == CppAD::constant_enum;\n                        zero_left      &= parameter_x[i_left] == 0.0;\n                        bool zero_right =\n                            type_x[i_right] == CppAD::constant_enum;\n                        zero_right     &= parameter_x[i_right] == 0.0;\n                        if( ! (zero_left | zero_right ) )\n                        {  bool var_left  =\n                                type_x[i_left] == CppAD::variable_enum;\n                            bool var_right =\n                                type_x[i_right] == CppAD::variable_enum;\n                            if( select_x[i_left] & var_left )\n                                ++nnz;\n                            if( select_x[i_right] & var_right )\n                                ++nnz;\n                        }\n                    }\n                }\n            }\n        }\n        //\n        // fill in the sparsity pattern\n        pattern_out.resize(m, n, nnz);\n        size_t idx = 0;\n        for(size_t i = 0; i < nr_left; ++i)\n        {  for(size_t j = 0; j < nc_right; ++j)\n            {  size_t i_result = result(\n                    i, j, k, nk, nr_left, n_middle, nc_right\n                );\n                if( select_y[i_result] )\n                {  for(size_t ell = 0; ell < n_middle; ++ell)\n                    {  size_t i_left = left(\n                            i, ell, k, nk, nr_left, n_middle, nc_right\n                        );\n                        size_t i_right = right(\n                            ell, j, k, nk, nr_left, n_middle, nc_right\n                        );\n                        bool zero_left  =\n                            type_x[i_left] == CppAD::constant_enum;\n                        zero_left      &= parameter_x[i_left] == 0.0;\n                        bool zero_right =\n                            type_x[i_right] == CppAD::constant_enum;\n                        zero_right     &= parameter_x[i_right] == 0.0;\n                        if( ! (zero_left | zero_right ) )\n                        {  bool var_left  =\n                                type_x[i_left] == CppAD::variable_enum;\n                            bool var_right =\n                                type_x[i_right] == CppAD::variable_enum;\n                            if( select_x[i_left] & var_left )\n                                pattern_out.set(idx++, i_result, i_left);\n                            if( select_x[i_right] & var_right )\n                                pattern_out.set(idx++, i_result, i_right);\n                        }\n                    }\n                }\n            }\n        }\n        assert( idx == nnz );\n        //\n        return true;\n    }\n/* {xrst_code}\n{xrst_spell_on}\nhes_sparsity\n************\n{xrst_spell_off}\n{xrst_code cpp} */\n    // Jacobian sparsity routine called by CppAD\n    virtual bool hes_sparsity(\n        const vector<double>&               parameter_x ,\n        const vector<CppAD::ad_type_enum>&  type_x      ,\n        const vector<bool>&                 select_x    ,\n        const vector<bool>&                 select_y    ,\n        CppAD::sparse_rc< vector<size_t> >& pattern_out )\n    {\n        size_t n = select_x.size();\n        assert( parameter_x.size() == n );\n        assert( type_x.size() == n );\n        //\n        size_t nr_left  = size_t( parameter_x[0] );\n        size_t n_middle = size_t( parameter_x[1] );\n        size_t nc_right = size_t( parameter_x[2] );\n        size_t nk       = 1; // only one order\n        size_t k        = 0; // order zero\n        //\n        // count number of non-zeros in sparsity pattern\n        size_t nnz = 0;\n        for(size_t i = 0; i < nr_left; ++i)\n        {  for(size_t j = 0; j < nc_right; ++j)\n            {  size_t i_result = result(\n                    i, j, k, nk, nr_left, n_middle, nc_right\n                );\n                if( select_y[i_result] )\n                {  for(size_t ell = 0; ell < n_middle; ++ell)\n                    {  // i_left depends on i, ell\n                        size_t i_left = left(\n                            i, ell, k, nk, nr_left, n_middle, nc_right\n                        );\n                        // i_right depens on ell, j\n                        size_t i_right = right(\n                            ell, j, k, nk, nr_left, n_middle, nc_right\n                        );\n                        bool var_left   = select_x[i_left] &&\n                            (type_x[i_left] == CppAD::variable_enum);\n                        bool var_right  = select_x[i_right] &&\n                            (type_x[i_right] == CppAD::variable_enum);\n                        if( var_left & var_right )\n                                nnz += 2;\n                    }\n                }\n            }\n        }\n        //\n        // fill in the sparsity pattern\n        pattern_out.resize(n, n, nnz);\n        size_t idx = 0;\n        for(size_t i = 0; i < nr_left; ++i)\n        {  for(size_t j = 0; j < nc_right; ++j)\n            {  size_t i_result = result(\n                    i, j, k, nk, nr_left, n_middle, nc_right\n                );\n                if( select_y[i_result] )\n                {  for(size_t ell = 0; ell < n_middle; ++ell)\n                    {  size_t i_left = left(\n                            i, ell, k, nk, nr_left, n_middle, nc_right\n                        );\n                        size_t i_right = right(\n                            ell, j, k, nk, nr_left, n_middle, nc_right\n                        );\n                        bool var_left   = select_x[i_left] &&\n                            (type_x[i_left] == CppAD::variable_enum);\n                        bool var_right  = select_x[i_right] &&\n                            (type_x[i_right] == CppAD::variable_enum);\n                        if( var_left & var_right )\n                        {  // Cannot possibly set the same (i_left, i_right)\n                            // pair twice.\n                            assert( i_left != i_right );\n                            pattern_out.set(idx++, i_left, i_right);\n                            pattern_out.set(idx++, i_right, i_left);\n                        }\n                    }\n                }\n            }\n        }\n        assert( idx == nnz );\n        //\n        return true;\n    }\n/* {xrst_code}\n{xrst_spell_on}\nrev_depend\n**********\nRoutine called when a function using ``mat_mul`` is optimized.\n{xrst_spell_off}\n{xrst_code cpp} */\n    // calculate depend_x\n    virtual bool rev_depend(\n        const vector<double>&              parameter_x ,\n        const vector<CppAD::ad_type_enum>& type_x      ,\n        vector<bool>&                      depend_x    ,\n        const vector<bool>&                depend_y    )\n    {  assert( parameter_x.size() == depend_x.size() );\n        assert( parameter_x.size() == type_x.size() );\n        bool ok = true;\n        //\n        size_t nr_left  = size_t( parameter_x[0] );\n        size_t n_middle = size_t( parameter_x[1] );\n        size_t nc_right = size_t( parameter_x[2] );\n        //\n        ok &= depend_x.size() == 3 + (nr_left + nc_right) * n_middle;\n        ok &= depend_y.size() == n_middle * nc_right;\n        if( ! ok )\n            return false;\n        //\n        // initialize depend_x\n        for(size_t ell = 0; ell < 3; ++ell)\n            depend_x[ell] = true; // always need these parameters\n        for(size_t ell = 3; ell < depend_x.size(); ++ell)\n            depend_x[ell] = false; // initialize as false\n        //\n        // compute depend_x\n        size_t nk = 1; // number of orders\n        size_t k  = 0; // order\n        for(size_t i = 0; i < nr_left; ++i)\n        {  for(size_t j = 0; j < nc_right; ++j)\n            {  // check depend for result[i, j]\n                size_t i_result = result(\n                    i, j, k, nk, nr_left, n_middle, nc_right\n                );\n                if( depend_y[i_result] )\n                {  for(size_t ell = 0; ell < n_middle; ++ell)\n                    {  // index for left(i, ell)\n                        size_t i_left = left(\n                            i, ell, k, nk, nr_left, n_middle, nc_right\n                        );\n                        // index for right(ell, j)\n                        size_t i_right = right(\n                            ell, j, k, nk, nr_left, n_middle, nc_right\n                        );\n                        bool zero_left  =\n                            type_x[i_left] == CppAD::constant_enum;\n                        zero_left      &= parameter_x[i_left] == 0.0;\n                        bool zero_right =\n                            type_x[i_right] == CppAD::constant_enum;\n                        zero_right     &= parameter_x[i_right] == 0.0;\n                        if( ! zero_right )\n                            depend_x[i_left]  = true;\n                        if( ! zero_left )\n                            depend_x[i_right] = true;\n                    }\n                }\n            }\n        }\n        return true;\n    }\n/* {xrst_code}\n{xrst_spell_on}\nEnd Class Definition\n********************\n{xrst_spell_off}\n{xrst_code cpp} */\n}; // End of mat_mul class\n}  // End empty namespace\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end atomic_three_mat_mul.hpp}\n*/\n\n\n# endif\n"
  },
  {
    "path": "include/cppad/example/atomic_two/eigen_cholesky.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_ATOMIC_TWO_EIGEN_CHOLESKY_HPP\n# define CPPAD_EXAMPLE_ATOMIC_TWO_EIGEN_CHOLESKY_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin atomic_two_eigen_cholesky.hpp app}\n\natomic_two Eigen Cholesky Factorization Class\n#############################################\n\nPurpose\n*******\nConstruct an atomic operation that computes a lower triangular matrix\n:math:`L` such that :math:`L L^\\R{T} = A`\nfor any positive integer :math:`p`\nand symmetric positive definite matrix :math:`A \\in \\B{R}^{p \\times p}`.\n\nStart Class Definition\n**********************\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <cppad/cppad.hpp>\n# include <Eigen/Dense>\n\n/* {xrst_code}\n{xrst_spell_on}\nPublic\n******\n\nTypes\n=====\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace { // BEGIN_EMPTY_NAMESPACE\n\ntemplate <class Base>\nclass atomic_eigen_cholesky : public CppAD::atomic_base<Base> {\npublic:\n    // -----------------------------------------------------------\n    // type of elements during calculation of derivatives\n    typedef Base              scalar;\n    // type of elements during taping\n    typedef CppAD::AD<scalar> ad_scalar;\n    //\n    // type of matrix during calculation of derivatives\n    typedef Eigen::Matrix<\n        scalar, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>        matrix;\n    // type of matrix during taping\n    typedef Eigen::Matrix<\n        ad_scalar, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor > ad_matrix;\n    //\n    // lower triangular scalar matrix\n    typedef Eigen::TriangularView<matrix, Eigen::Lower>             lower_view;\n/* {xrst_code}\n{xrst_spell_on}\nConstructor\n===========\n{xrst_spell_off}\n{xrst_code cpp} */\n    // constructor\n    atomic_eigen_cholesky(void) : CppAD::atomic_base<Base>(\n        \"atom_eigen_cholesky\"                             ,\n        CppAD::atomic_base<Base>::set_sparsity_enum\n    )\n    { }\n/* {xrst_code}\n{xrst_spell_on}\nop\n==\n{xrst_spell_off}\n{xrst_code cpp} */\n    // use atomic operation to invert an AD matrix\n    ad_matrix op(const ad_matrix& arg)\n    {  size_t nr = size_t( arg.rows() );\n        size_t ny = ( (nr + 1 ) * nr ) / 2;\n        size_t nx = 1 + ny;\n        assert( nr == size_t( arg.cols() ) );\n        // -------------------------------------------------------------------\n        // packed version of arg\n        CPPAD_TESTVECTOR(ad_scalar) packed_arg(nx);\n        size_t index = 0;\n        packed_arg[index++] = ad_scalar( nr );\n        // lower triangle of symmetric matrix A\n        for(size_t i = 0; i < nr; i++)\n        {  for(size_t j = 0; j <= i; j++)\n                packed_arg[index++] = arg( long(i), long(j) );\n        }\n        assert( index == nx );\n        // -------------------------------------------------------------------\n        // packed version of result = arg^{-1}.\n        // This is an atomic_base function call that CppAD uses to\n        // store the atomic operation on the tape.\n        CPPAD_TESTVECTOR(ad_scalar) packed_result(ny);\n        (*this)(packed_arg, packed_result);\n        // -------------------------------------------------------------------\n        // unpack result matrix L\n        ad_matrix result = ad_matrix::Zero( long(nr), long(nr) );\n        index = 0;\n        for(size_t i = 0; i < nr; i++)\n        {  for(size_t j = 0; j <= i; j++)\n                result( long(i), long(j) ) = packed_result[index++];\n        }\n        return result;\n    }\n    /* {xrst_code}\n{xrst_spell_on}\nPrivate\n*******\n\nVariables\n=========\n{xrst_spell_off}\n{xrst_code cpp} */\nprivate:\n    // -------------------------------------------------------------\n    // one forward mode vector of matrices for argument and result\n    CppAD::vector<matrix> f_arg_, f_result_;\n    // one reverse mode vector of matrices for argument and result\n    CppAD::vector<matrix> r_arg_, r_result_;\n    // -------------------------------------------------------------\n/* {xrst_code}\n{xrst_spell_on}\nforward\n=======\n{xrst_spell_off}\n{xrst_code cpp} */\n    // forward mode routine called by CppAD\n    virtual bool forward(\n        // lowest order Taylor coefficient we are evaluating\n        size_t                          p ,\n        // highest order Taylor coefficient we are evaluating\n        size_t                          q ,\n        // which components of x are variables\n        const CppAD::vector<bool>&      vx ,\n        // which components of y are variables\n        CppAD::vector<bool>&            vy ,\n        // tx [ j * (q+1) + k ] is x_j^k\n        const CppAD::vector<scalar>&    tx ,\n        // ty [ i * (q+1) + k ] is y_i^k\n        CppAD::vector<scalar>&          ty\n    )\n    {  size_t n_order = q + 1;\n        size_t nr      = size_t( CppAD::Integer( tx[ 0 * n_order + 0 ] ) );\n        size_t ny      = ((nr + 1) * nr) / 2;\n# ifndef NDEBUG\n        size_t nx      = 1 + ny;\n# endif\n        assert( vx.size() == 0 || nx == vx.size() );\n        assert( vx.size() == 0 || ny == vy.size() );\n        assert( nx * n_order == tx.size() );\n        assert( ny * n_order == ty.size() );\n        //\n        // -------------------------------------------------------------------\n        // make sure f_arg_ and f_result_ are large enough\n        assert( f_arg_.size() == f_result_.size() );\n        if( f_arg_.size() < n_order )\n        {  f_arg_.resize(n_order);\n            f_result_.resize(n_order);\n            //\n            for(size_t k = 0; k < n_order; k++)\n            {  f_arg_[k].resize( long(nr), long(nr) );\n                f_result_[k].resize( long(nr), long(nr) );\n            }\n        }\n        // -------------------------------------------------------------------\n        // unpack tx into f_arg_\n        for(size_t k = 0; k < n_order; k++)\n        {  size_t index = 1;\n            // unpack arg values for this order\n            for(long i = 0; i < long(nr); i++)\n            {  for(long j = 0; j <= i; j++)\n                {  f_arg_[k](i, j) = tx[ index * n_order + k ];\n                    f_arg_[k](j, i) = f_arg_[k](i, j);\n                    index++;\n                }\n            }\n        }\n        // -------------------------------------------------------------------\n        // result for each order\n        // (we could avoid recalculting f_result_[k] for k=0,...,p-1)\n        //\n        Eigen::LLT<matrix> cholesky(f_arg_[0]);\n        f_result_[0]   = cholesky.matrixL();\n        lower_view L_0 = f_result_[0].template triangularView<Eigen::Lower>();\n        for(size_t k = 1; k < n_order; k++)\n        {  // initialize sum as A_k\n            matrix f_sum = f_arg_[k];\n            // compute A_k - B_k\n            for(size_t ell = 1; ell < k; ell++)\n                f_sum -= f_result_[ell] * f_result_[k-ell].transpose();\n            // compute L_0^{-1} * (A_k - B_k) * L_0^{-T}\n            matrix temp = L_0.template solve<Eigen::OnTheLeft>(f_sum);\n            temp   = L_0.transpose().template solve<Eigen::OnTheRight>(temp);\n            // divide the diagonal by 2\n            for(long i = 0; i < long(nr); i++)\n                temp(i, i) /= scalar(2.0);\n            // L_k = L_0 * low[ L_0^{-1} * (A_k - B_k) * L_0^{-T} ]\n            lower_view view = temp.template triangularView<Eigen::Lower>();\n            f_result_[k] = f_result_[0] * view;\n        }\n        // -------------------------------------------------------------------\n        // pack result_ into ty\n        for(size_t k = 0; k < n_order; k++)\n        {  size_t index = 0;\n            for(long i = 0; i < long(nr); i++)\n            {  for(long j = 0; j <= i; j++)\n                {  ty[ index * n_order + k ] = f_result_[k](i, j);\n                    index++;\n                }\n            }\n        }\n        // -------------------------------------------------------------------\n        // check if we are computing vy\n        if( vx.size() == 0 )\n            return true;\n        // ------------------------------------------------------------------\n        // This is a very dumb algorithm that over estimates which\n        // elements of the inverse are variables (which is not efficient).\n        bool var = false;\n        for(size_t i = 0; i < ny; i++)\n            var |= vx[1 + i];\n        for(size_t i = 0; i < ny; i++)\n            vy[i] = var;\n        //\n        return true;\n    }\n/* {xrst_code}\n{xrst_spell_on}\nreverse\n=======\n{xrst_spell_off}\n{xrst_code cpp} */\n    // reverse mode routine called by CppAD\n    virtual bool reverse(\n        // highest order Taylor coefficient that we are computing derivative of\n        size_t                     q ,\n        // forward mode Taylor coefficients for x variables\n        const CppAD::vector<double>&     tx ,\n        // forward mode Taylor coefficients for y variables\n        const CppAD::vector<double>&     ty ,\n        // upon return, derivative of G[ F[ {x_j^k} ] ] w.r.t {x_j^k}\n        CppAD::vector<double>&           px ,\n        // derivative of G[ {y_i^k} ] w.r.t. {y_i^k}\n        const CppAD::vector<double>&     py\n    )\n    {  size_t n_order = q + 1;\n        size_t nr = size_t( CppAD::Integer( tx[ 0 * n_order + 0 ] ) );\n# ifndef NDEBUG\n        size_t ny = ( (nr + 1 ) * nr ) / 2;\n        size_t nx = 1 + ny;\n# endif\n        //\n        assert( nx * n_order == tx.size() );\n        assert( ny * n_order == ty.size() );\n        assert( px.size()    == tx.size() );\n        assert( py.size()    == ty.size() );\n        // -------------------------------------------------------------------\n        // make sure f_arg_ is large enough\n        assert( f_arg_.size() == f_result_.size() );\n        // must have previous run forward with order >= n_order\n        assert( f_arg_.size() >= n_order );\n        // -------------------------------------------------------------------\n        // make sure r_arg_, r_result_ are large enough\n        assert( r_arg_.size() == r_result_.size() );\n        if( r_arg_.size() < n_order )\n        {  r_arg_.resize(n_order);\n            r_result_.resize(n_order);\n            //\n            for(size_t k = 0; k < n_order; k++)\n            {  r_arg_[k].resize( long(nr), long(nr) );\n                r_result_[k].resize( long(nr), long(nr) );\n            }\n        }\n        // -------------------------------------------------------------------\n        // unpack tx into f_arg_\n        for(size_t k = 0; k < n_order; k++)\n        {  size_t index = 1;\n            // unpack arg values for this order\n            for(long i = 0; i < long(nr); i++)\n            {  for(long j = 0; j <= i; j++)\n                {  f_arg_[k](i, j) = tx[ index * n_order + k ];\n                    f_arg_[k](j, i) = f_arg_[k](i, j);\n                    index++;\n                }\n            }\n        }\n        // -------------------------------------------------------------------\n        // unpack py into r_result_\n        for(size_t k = 0; k < n_order; k++)\n        {  r_result_[k] = matrix::Zero( long(nr), long(nr) );\n            size_t index = 0;\n            for(long i = 0; i < long(nr); i++)\n            {  for(long j = 0; j <= i; j++)\n                {  r_result_[k](i, j) = py[ index * n_order + k ];\n                    index++;\n                }\n            }\n        }\n        // -------------------------------------------------------------------\n        // initialize r_arg_ as zero\n        for(size_t k = 0; k < n_order; k++)\n            r_arg_[k]   = matrix::Zero( long(nr), long(nr) );\n        // -------------------------------------------------------------------\n        // matrix reverse mode calculation\n        lower_view L_0 = f_result_[0].template triangularView<Eigen::Lower>();\n        //\n        for(size_t k1 = n_order; k1 > 1; k1--)\n        {  size_t k = k1 - 1;\n            //\n            // L_0^T * bar{L}_k\n            matrix tmp1 = L_0.transpose() * r_result_[k];\n            //\n            //low[ L_0^T * bar{L}_k ]\n            for(long i = 0; i < long(nr); i++)\n                tmp1(i, i) /= scalar(2.0);\n            matrix tmp2 = tmp1.template triangularView<Eigen::Lower>();\n            //\n            // L_0^{-T} low[ L_0^T * bar{L}_k ]\n            tmp1 = L_0.transpose().template solve<Eigen::OnTheLeft>( tmp2 );\n            //\n            // M_k = L_0^{-T} * low[ L_0^T * bar{L}_k ]^{T} L_0^{-1}\n            matrix M_k = L_0.transpose().template\n                solve<Eigen::OnTheLeft>( tmp1.transpose() );\n            //\n            // remove L_k and compute bar{B}_k\n            matrix barB_k = scalar(0.5) * ( M_k + M_k.transpose() );\n            r_arg_[k]    += barB_k;\n            barB_k        = scalar(-1.0) * barB_k;\n            //\n            // 2.0 * lower( bar{B}_k L_k )\n            matrix temp = scalar(2.0) * barB_k * f_result_[k];\n            temp        = temp.template triangularView<Eigen::Lower>();\n            //\n            // remove C_k\n            r_result_[0] += temp;\n            //\n            // remove B_k\n            for(size_t ell = 1; ell < k; ell++)\n            {  // bar{L}_ell = 2 * lower( \\bar{B}_k * L_{k-ell} )\n                temp = scalar(2.0) * barB_k * f_result_[k-ell];\n                r_result_[ell] += temp.template triangularView<Eigen::Lower>();\n            }\n        }\n        // M_0 = L_0^{-T} * low[ L_0^T * bar{L}_0 ]^{T} L_0^{-1}\n        matrix M_0 = L_0.transpose() * r_result_[0];\n        for(long i = 0; i < long(nr); i++)\n            M_0(i, i) /= scalar(2.0);\n        M_0 = M_0.template triangularView<Eigen::Lower>();\n        M_0 = L_0.template solve<Eigen::OnTheRight>( M_0 );\n        M_0 = L_0.transpose().template solve<Eigen::OnTheLeft>( M_0 );\n        // remove L_0\n        r_arg_[0] += scalar(0.5) * ( M_0 + M_0.transpose() );\n        // -------------------------------------------------------------------\n        // pack r_arg into px\n        // note that only the lower triangle of barA_k is stored in px\n        for(size_t k = 0; k < n_order; k++)\n        {  size_t index = 0;\n            px[ index * n_order + k ] = 0.0;\n            index++;\n            for(long i = 0; i < long(nr); i++)\n            {  for(long j = 0; j < i; j++)\n                {  px[ index * n_order + k ] = 2.0 * r_arg_[k](i, j);\n                    index++;\n                }\n                px[ index * n_order + k] = r_arg_[k](i, i);\n                index++;\n            }\n        }\n        // -------------------------------------------------------------------\n        return true;\n    }\n/* {xrst_code}\n{xrst_spell_on}\nEnd Class Definition\n********************\n{xrst_spell_off}\n{xrst_code cpp} */\n}; // End of atomic_eigen_cholesky class\n\n}  // END_EMPTY_NAMESPACE\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end atomic_two_eigen_cholesky.hpp}\n*/\n\n\n# endif\n"
  },
  {
    "path": "include/cppad/example/atomic_two/eigen_mat_inv.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_ATOMIC_TWO_EIGEN_MAT_INV_HPP\n# define CPPAD_EXAMPLE_ATOMIC_TWO_EIGEN_MAT_INV_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin atomic_two_eigen_mat_inv.hpp app}\n{xrst_spell\n    tr\n}\n\natomic_two Eigen Matrix Inversion Class\n#######################################\n\nPurpose\n*******\nConstruct an atomic operation that computes the matrix inverse\n:math:`R = A^{-1}`\nfor any positive integer :math:`p`\nand invertible matrix :math:`A \\in \\B{R}^{p \\times p}`.\n\nMatrix Dimensions\n*****************\nThis example puts the matrix dimension :math:`p`\nin the atomic function arguments,\ninstead of the :ref:`constructor<atomic_two_ctor-name>` ,\nso it can be different for different calls to the atomic function.\n\nTheory\n******\n\nForward\n=======\nThe zero order forward mode Taylor coefficient is give by\n\n.. math::\n\n    R_0 = A_0^{-1}\n\nFor :math:`k = 1 , \\ldots`,\nthe *k*-th order Taylor coefficient of :math:`A R` is given by\n\n.. math::\n\n    0 = \\sum_{\\ell=0}^k A_\\ell R_{k-\\ell}\n\nSolving for :math:`R_k` in terms of the coefficients\nfor :math:`A` and the lower order coefficients for :math:`R` we have\n\n.. math::\n\n    R_k = - R_0 \\left( \\sum_{\\ell=1}^k A_\\ell R_{k-\\ell} \\right)\n\nFurthermore, once we have :math:`R_k` we can compute the sum using\n\n.. math::\n\n    A_0 R_k = - \\left( \\sum_{\\ell=1}^k A_\\ell R_{k-\\ell} \\right)\n\nProduct of Three Matrices\n=========================\nSuppose :math:`\\bar{E}` is the derivative of the\nscalar value function :math:`s(E)` with respect to :math:`E`; i.e.,\n\n.. math::\n\n    \\bar{E}_{i,j} = \\frac{ \\partial s } { \\partial E_{i,j} }\n\nAlso suppose that :math:`t` is a scalar valued argument and\n\n.. math::\n\n    E(t) = B(t) C(t) D(t)\n\nIt follows that\n\n.. math::\n\n    E'(t) = B'(t) C(t) D(t) + B(t) C'(t) D(t) +  B(t) C(t) D'(t)\n\n.. math::\n\n    (s \\circ E)'(t)\n    =\n    \\R{tr} [ \\bar{E}^\\R{T} E'(t) ]\n\n.. math::\n\n    =\n    \\R{tr} [ \\bar{E}^\\R{T} B'(t) C(t) D(t) ] +\n    \\R{tr} [ \\bar{E}^\\R{T} B(t) C'(t) D(t) ] +\n    \\R{tr} [ \\bar{E}^\\R{T} B(t) C(t) D'(t) ]\n\n.. math::\n\n    =\n    \\R{tr} [ B(t) D(t) \\bar{E}^\\R{T} B'(t) ] +\n    \\R{tr} [ D(t) \\bar{E}^\\R{T} B(t) C'(t) ] +\n    \\R{tr} [ \\bar{E}^\\R{T} B(t) C(t) D'(t) ]\n\n.. math::\n\n    \\bar{B} = \\bar{E} (C D)^\\R{T} \\W{,}\n    \\bar{C} = \\B{R}^\\R{T} \\bar{E} D^\\R{T} \\W{,}\n    \\bar{D} = (B C)^\\R{T} \\bar{E}\n\nReverse\n=======\nFor :math:`k > 0`, reverse mode\neliminates :math:`R_k` and expresses the function values\n:math:`s` in terms of the coefficients of :math:`A`\nand the lower order coefficients of :math:`R`.\nThe effect on :math:`\\bar{R}_0`\n(of eliminating :math:`R_k`) is\n\n.. math::\n\n    \\bar{R}_0\n    = \\bar{R}_0 - \\bar{R}_k \\left( \\sum_{\\ell=1}^k A_\\ell R_{k-\\ell} \\right)^\\R{T}\n    = \\bar{R}_0 + \\bar{R}_k ( A_0 R_k )^\\R{T}\n\nFor :math:`\\ell = 1 , \\ldots , k`,\nthe effect on :math:`\\bar{R}_{k-\\ell}` and :math:`A_\\ell`\n(of eliminating :math:`R_k`) is\n\n.. math::\n\n    \\bar{A}_\\ell = \\bar{A}_\\ell - R_0^\\R{T} \\bar{R}_k R_{k-\\ell}^\\R{T}\n\n.. math::\n\n    \\bar{R}_{k-\\ell} = \\bar{R}_{k-\\ell} - ( R_0 A_\\ell )^\\R{T} \\bar{R}_k\n\nWe note that\n\n.. math::\n\n    R_0 '(t) A_0 (t) + R_0 (t) A_0 '(t) = 0\n\n.. math::\n\n    R_0 '(t) = - R_0 (t) A_0 '(t) R_0 (t)\n\nThe reverse mode formula that eliminates :math:`R_0` is\n\n.. math::\n\n    \\bar{A}_0\n    = \\bar{A}_0 - R_0^\\R{T} \\bar{R}_0 R_0^\\R{T}\n\nStart Class Definition\n**********************\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <cppad/cppad.hpp>\n# include <Eigen/Core>\n# include <Eigen/LU>\n\n/* {xrst_code}\n{xrst_spell_on}\nPublic\n******\n\nTypes\n=====\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace { // BEGIN_EMPTY_NAMESPACE\n\ntemplate <class Base>\nclass atomic_eigen_mat_inv : public CppAD::atomic_base<Base> {\npublic:\n    // -----------------------------------------------------------\n    // type of elements during calculation of derivatives\n    typedef Base              scalar;\n    // type of elements during taping\n    typedef CppAD::AD<scalar> ad_scalar;\n    // type of matrix during calculation of derivatives\n    typedef Eigen::Matrix<\n        scalar, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>     matrix;\n    // type of matrix during taping\n    typedef Eigen::Matrix<\n        ad_scalar, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor > ad_matrix;\n/* {xrst_code}\n{xrst_spell_on}\nConstructor\n===========\n{xrst_spell_off}\n{xrst_code cpp} */\n    // constructor\n    atomic_eigen_mat_inv(void) : CppAD::atomic_base<Base>(\n        \"atom_eigen_mat_inv\"                             ,\n        CppAD::atomic_base<Base>::set_sparsity_enum\n    )\n    { }\n/* {xrst_code}\n{xrst_spell_on}\nop\n==\n{xrst_spell_off}\n{xrst_code cpp} */\n    // use atomic operation to invert an AD matrix\n    ad_matrix op(const ad_matrix& arg)\n    {  size_t nr = size_t( arg.rows() );\n        size_t ny = nr * nr;\n        size_t nx = 1 + ny;\n        assert( nr == size_t( arg.cols() ) );\n        // -------------------------------------------------------------------\n        // packed version of arg\n        CPPAD_TESTVECTOR(ad_scalar) packed_arg(nx);\n        packed_arg[0] = ad_scalar( nr );\n        for(size_t i = 0; i < ny; i++)\n            packed_arg[1 + i] = arg.data()[i];\n        // -------------------------------------------------------------------\n        // packed version of result = arg^{-1}.\n        // This is an atomic_base function call that CppAD uses to\n        // store the atomic operation on the tape.\n        CPPAD_TESTVECTOR(ad_scalar) packed_result(ny);\n        (*this)(packed_arg, packed_result);\n        // -------------------------------------------------------------------\n        // unpack result matrix\n        ad_matrix result(nr, nr);\n        for(size_t i = 0; i < ny; i++)\n            result.data()[i] = packed_result[i];\n        return result;\n    }\n    /* {xrst_code}\n{xrst_spell_on}\nPrivate\n*******\n\nVariables\n=========\n{xrst_spell_off}\n{xrst_code cpp} */\nprivate:\n    // -------------------------------------------------------------\n    // one forward mode vector of matrices for argument and result\n    CppAD::vector<matrix> f_arg_, f_result_;\n    // one reverse mode vector of matrices for argument and result\n    CppAD::vector<matrix> r_arg_, r_result_;\n    // -------------------------------------------------------------\n/* {xrst_code}\n{xrst_spell_on}\nforward\n=======\n{xrst_spell_off}\n{xrst_code cpp} */\n    // forward mode routine called by CppAD\n    virtual bool forward(\n        // lowest order Taylor coefficient we are evaluating\n        size_t                          p ,\n        // highest order Taylor coefficient we are evaluating\n        size_t                          q ,\n        // which components of x are variables\n        const CppAD::vector<bool>&      vx ,\n        // which components of y are variables\n        CppAD::vector<bool>&            vy ,\n        // tx [ j * (q+1) + k ] is x_j^k\n        const CppAD::vector<scalar>&    tx ,\n        // ty [ i * (q+1) + k ] is y_i^k\n        CppAD::vector<scalar>&          ty\n    )\n    {  size_t n_order = q + 1;\n        size_t nr      = size_t( CppAD::Integer( tx[ 0 * n_order + 0 ] ) );\n        size_t ny      = nr * nr;\n# ifndef NDEBUG\n        size_t nx      = 1 + ny;\n# endif\n        assert( vx.size() == 0 || nx == vx.size() );\n        assert( vx.size() == 0 || ny == vy.size() );\n        assert( nx * n_order == tx.size() );\n        assert( ny * n_order == ty.size() );\n        //\n        // -------------------------------------------------------------------\n        // make sure f_arg_ and f_result_ are large enough\n        assert( f_arg_.size() == f_result_.size() );\n        if( f_arg_.size() < n_order )\n        {  f_arg_.resize(n_order);\n            f_result_.resize(n_order);\n            //\n            for(size_t k = 0; k < n_order; k++)\n            {  f_arg_[k].resize( long(nr), long(nr) );\n                f_result_[k].resize( long(nr), long(nr) );\n            }\n        }\n        // -------------------------------------------------------------------\n        // unpack tx into f_arg_\n        for(size_t k = 0; k < n_order; k++)\n        {  // unpack arg values for this order\n            for(size_t i = 0; i < ny; i++)\n                f_arg_[k].data()[i] = tx[ (1 + i) * n_order + k ];\n        }\n        // -------------------------------------------------------------------\n        // result for each order\n        // (we could avoid recalculting f_result_[k] for k=0,...,p-1)\n        //\n        f_result_[0] = f_arg_[0].inverse();\n        for(size_t k = 1; k < n_order; k++)\n        {  // initialize sum\n            matrix f_sum = matrix::Zero( long(nr), long(nr) );\n            // compute sum\n            for(size_t ell = 1; ell <= k; ell++)\n                f_sum -= f_arg_[ell] * f_result_[k-ell];\n            // result_[k] = arg_[0]^{-1} * sum_\n            f_result_[k] = f_result_[0] * f_sum;\n        }\n        // -------------------------------------------------------------------\n        // pack result_ into ty\n        for(size_t k = 0; k < n_order; k++)\n        {  for(size_t i = 0; i < ny; i++)\n                ty[ i * n_order + k ] = f_result_[k].data()[i];\n        }\n        // -------------------------------------------------------------------\n        // check if we are computing vy\n        if( vx.size() == 0 )\n            return true;\n        // ------------------------------------------------------------------\n        // This is a very dumb algorithm that over estimates which\n        // elements of the inverse are variables (which is not efficient).\n        bool var = false;\n        for(size_t i = 0; i < ny; i++)\n            var |= vx[1 + i];\n        for(size_t i = 0; i < ny; i++)\n            vy[i] = var;\n        return true;\n    }\n/* {xrst_code}\n{xrst_spell_on}\nreverse\n=======\n{xrst_spell_off}\n{xrst_code cpp} */\n    // reverse mode routine called by CppAD\n    virtual bool reverse(\n        // highest order Taylor coefficient that we are computing derivative of\n        size_t                     q ,\n        // forward mode Taylor coefficients for x variables\n        const CppAD::vector<double>&     tx ,\n        // forward mode Taylor coefficients for y variables\n        const CppAD::vector<double>&     ty ,\n        // upon return, derivative of G[ F[ {x_j^k} ] ] w.r.t {x_j^k}\n        CppAD::vector<double>&           px ,\n        // derivative of G[ {y_i^k} ] w.r.t. {y_i^k}\n        const CppAD::vector<double>&     py\n    )\n    {  size_t n_order = q + 1;\n        size_t nr      = size_t( CppAD::Integer( tx[ 0 * n_order + 0 ] ) );\n        size_t ny      = nr * nr;\n# ifndef NDEBUG\n        size_t nx      = 1 + ny;\n# endif\n        //\n        assert( nx * n_order == tx.size() );\n        assert( ny * n_order == ty.size() );\n        assert( px.size()    == tx.size() );\n        assert( py.size()    == ty.size() );\n        // -------------------------------------------------------------------\n        // make sure f_arg_ is large enough\n        assert( f_arg_.size() == f_result_.size() );\n        // must have previous run forward with order >= n_order\n        assert( f_arg_.size() >= n_order );\n        // -------------------------------------------------------------------\n        // make sure r_arg_, r_result_ are large enough\n        assert( r_arg_.size() == r_result_.size() );\n        if( r_arg_.size() < n_order )\n        {  r_arg_.resize(n_order);\n            r_result_.resize(n_order);\n            //\n            for(size_t k = 0; k < n_order; k++)\n            {  r_arg_[k].resize( long(nr), long(nr) );\n                r_result_[k].resize( long(nr), long(nr) );\n            }\n        }\n        // -------------------------------------------------------------------\n        // unpack tx into f_arg_\n        for(size_t k = 0; k < n_order; k++)\n        {  // unpack arg values for this order\n            for(size_t i = 0; i < ny; i++)\n                f_arg_[k].data()[i] = tx[ (1 + i) * n_order + k ];\n        }\n        // -------------------------------------------------------------------\n        // unpack py into r_result_\n        for(size_t k = 0; k < n_order; k++)\n        {  for(size_t i = 0; i < ny; i++)\n                r_result_[k].data()[i] = py[ i * n_order + k ];\n        }\n        // -------------------------------------------------------------------\n        // initialize r_arg_ as zero\n        for(size_t k = 0; k < n_order; k++)\n            r_arg_[k]   = matrix::Zero( long(nr), long(nr) );\n        // -------------------------------------------------------------------\n        // matrix reverse mode calculation\n        //\n        for(size_t k1 = n_order; k1 > 1; k1--)\n        {  size_t k = k1 - 1;\n            // bar{R}_0 = bar{R}_0 + bar{R}_k (A_0 R_k)^T\n            r_result_[0] +=\n            r_result_[k] * f_result_[k].transpose() * f_arg_[0].transpose();\n            //\n            for(size_t ell = 1; ell <= k; ell++)\n            {  // bar{A}_l = bar{A}_l - R_0^T bar{R}_k R_{k-l}^T\n                r_arg_[ell] -= f_result_[0].transpose()\n                    * r_result_[k] * f_result_[k-ell].transpose();\n                // bar{R}_{k-l} = bar{R}_{k-1} - (R_0 A_l)^T bar{R}_k\n                r_result_[k-ell] -= f_arg_[ell].transpose()\n                    * f_result_[0].transpose() * r_result_[k];\n            }\n        }\n        r_arg_[0] -=\n        f_result_[0].transpose() * r_result_[0] * f_result_[0].transpose();\n        // -------------------------------------------------------------------\n        // pack r_arg into px\n        for(size_t k = 0; k < n_order; k++)\n        {  for(size_t i = 0; i < ny; i++)\n                px[ (1 + i) * n_order + k ] = r_arg_[k].data()[i];\n        }\n        //\n        return true;\n    }\n/* {xrst_code}\n{xrst_spell_on}\nEnd Class Definition\n********************\n{xrst_spell_off}\n{xrst_code cpp} */\n}; // End of atomic_eigen_mat_inv class\n\n}  // END_EMPTY_NAMESPACE\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end atomic_two_eigen_mat_inv.hpp}\n*/\n\n\n# endif\n"
  },
  {
    "path": "include/cppad/example/atomic_two/eigen_mat_mul.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_ATOMIC_TWO_EIGEN_MAT_MUL_HPP\n# define CPPAD_EXAMPLE_ATOMIC_TWO_EIGEN_MAT_MUL_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin atomic_two_eigen_mat_mul.hpp app}\n{xrst_spell\n    nr\n    tr\n}\n\natomic_two Eigen Matrix Multiply Class\n######################################\n\nSee Also\n********\n:ref:`atomic_three_mat_mul.hpp-name`\n\nPurpose\n*******\nConstruct an atomic operation that computes the matrix product,\n:math:`R = A \\times \\B{R}`\nfor any positive integers :math:`r`, :math:`m`, :math:`c`,\nand any :math:`A \\in \\B{R}^{r \\times m}`,\n:math:`B \\in \\B{R}^{m \\times c}`.\n\nMatrix Dimensions\n*****************\nThis example puts the matrix dimensions in the atomic function arguments,\ninstead of the :ref:`constructor<atomic_two_ctor-name>` , so that they can\nbe different for different calls to the atomic function.\nThese dimensions are:\n\n.. list-table::\n    :widths: auto\n\n    * - *nr_left*\n      - number of rows in the left matrix; i.e, :math:`r`\n    * - *n_middle*\n      - rows in the left matrix and columns in right; i.e, :math:`m`\n    * - *nc_right*\n      - number of columns in the right matrix; i.e., :math:`c`\n\nTheory\n******\n\nForward\n=======\nFor :math:`k = 0 , \\ldots`, the *k*-th order Taylor coefficient\n:math:`R_k` is given by\n\n.. math::\n\n    R_k = \\sum_{\\ell = 0}^{k} A_\\ell B_{k-\\ell}\n\nProduct of Two Matrices\n=======================\nSuppose :math:`\\bar{E}` is the derivative of the\nscalar value function :math:`s(E)` with respect to :math:`E`; i.e.,\n\n.. math::\n\n    \\bar{E}_{i,j} = \\frac{ \\partial s } { \\partial E_{i,j} }\n\nAlso suppose that :math:`t` is a scalar valued argument and\n\n.. math::\n\n    E(t) = C(t) D(t)\n\nIt follows that\n\n.. math::\n\n    E'(t) = C'(t) D(t) +  C(t) D'(t)\n\n.. math::\n\n    (s \\circ E)'(t)\n    =\n    \\R{tr} [ \\bar{E}^\\R{T} E'(t) ]\n\n.. math::\n\n    =\n    \\R{tr} [ \\bar{E}^\\R{T} C'(t) D(t) ] +\n    \\R{tr} [ \\bar{E}^\\R{T} C(t) D'(t) ]\n\n.. math::\n\n    =\n    \\R{tr} [ D(t) \\bar{E}^\\R{T} C'(t) ] +\n    \\R{tr} [ \\bar{E}^\\R{T} C(t) D'(t) ]\n\n.. math::\n\n    \\bar{C} = \\bar{E} D^\\R{T} \\W{,}\n    \\bar{D} = C^\\R{T} \\bar{E}\n\nReverse\n=======\nReverse mode eliminates :math:`R_k` as follows:\nfor :math:`\\ell = 0, \\ldots , k-1`,\n\n.. math::\n\n    \\bar{A}_\\ell     = \\bar{A}_\\ell     + \\bar{R}_k B_{k-\\ell}^\\R{T}\n\n.. math::\n\n    \\bar{B}_{k-\\ell} =  \\bar{B}_{k-\\ell} + A_\\ell^\\R{T} \\bar{R}_k\n\nStart Class Definition\n**********************\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <cppad/cppad.hpp>\n# include <Eigen/Core>\n\n/* {xrst_code}\n{xrst_spell_on}\nPublic\n******\n\nTypes\n=====\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace { // BEGIN_EMPTY_NAMESPACE\n\ntemplate <class Base>\nclass atomic_eigen_mat_mul : public CppAD::atomic_base<Base> {\npublic:\n    // -----------------------------------------------------------\n    // type of elements during calculation of derivatives\n    typedef Base              scalar;\n    // type of elements during taping\n    typedef CppAD::AD<scalar> ad_scalar;\n    // type of matrix during calculation of derivatives\n    typedef Eigen::Matrix<\n        scalar, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>     matrix;\n    // type of matrix during taping\n    typedef Eigen::Matrix<\n        ad_scalar, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor > ad_matrix;\n/* {xrst_code}\n{xrst_spell_on}\nConstructor\n===========\n{xrst_spell_off}\n{xrst_code cpp} */\n    // constructor\n    atomic_eigen_mat_mul(void) : CppAD::atomic_base<Base>(\n        \"atom_eigen_mat_mul\"                             ,\n        CppAD::atomic_base<Base>::set_sparsity_enum\n    )\n    { }\n/* {xrst_code}\n{xrst_spell_on}\nop\n==\n{xrst_spell_off}\n{xrst_code cpp} */\n    // use atomic operation to multiply two AD matrices\n    ad_matrix op(\n        const ad_matrix&              left    ,\n        const ad_matrix&              right   )\n    {  size_t  nr_left   = size_t( left.rows() );\n        size_t  n_middle  = size_t( left.cols() );\n        size_t  nc_right  = size_t( right.cols() );\n        assert( n_middle  == size_t( right.rows() )  );\n        size_t  nx      = 3 + (nr_left + nc_right) * n_middle;\n        size_t  ny      = nr_left * nc_right;\n        size_t n_left   = nr_left * n_middle;\n        size_t n_right  = n_middle * nc_right;\n        size_t n_result = nr_left * nc_right;\n        //\n        assert( 3 + n_left + n_right == nx );\n        assert( n_result == ny );\n        // -----------------------------------------------------------------\n        // packed version of left and right\n        CPPAD_TESTVECTOR(ad_scalar) packed_arg(nx);\n        //\n        packed_arg[0] = ad_scalar( nr_left );\n        packed_arg[1] = ad_scalar( n_middle );\n        packed_arg[2] = ad_scalar( nc_right );\n        for(size_t i = 0; i < n_left; i++)\n            packed_arg[3 + i] = left.data()[i];\n        for(size_t i = 0; i < n_right; i++)\n            packed_arg[ 3 + n_left + i ] = right.data()[i];\n        // ------------------------------------------------------------------\n        // Packed version of result = left * right.\n        // This as an atomic_base function call that CppAD uses\n        // to store the atomic operation on the tape.\n        CPPAD_TESTVECTOR(ad_scalar) packed_result(ny);\n        (*this)(packed_arg, packed_result);\n        // ------------------------------------------------------------------\n        // unpack result matrix\n        ad_matrix result(nr_left, nc_right);\n        for(size_t i = 0; i < n_result; i++)\n            result.data()[i] = packed_result[ i ];\n        //\n        return result;\n    }\n/* {xrst_code}\n{xrst_spell_on}\nPrivate\n*******\n\nVariables\n=========\n{xrst_spell_off}\n{xrst_code cpp} */\nprivate:\n    // -------------------------------------------------------------\n    // one forward mode vector of matrices for left, right, and result\n    CppAD::vector<matrix> f_left_, f_right_, f_result_;\n    // one reverse mode vector of matrices for left, right, and result\n    CppAD::vector<matrix> r_left_, r_right_, r_result_;\n    // -------------------------------------------------------------\n/* {xrst_code}\n{xrst_spell_on}\nforward\n=======\n{xrst_spell_off}\n{xrst_code cpp} */\n    // forward mode routine called by CppAD\n    virtual bool forward(\n        // lowest order Taylor coefficient we are evaluating\n        size_t                          p ,\n        // highest order Taylor coefficient we are evaluating\n        size_t                          q ,\n        // which components of x are variables\n        const CppAD::vector<bool>&      vx ,\n        // which components of y are variables\n        CppAD::vector<bool>&            vy ,\n        // tx [ 3 + j * (q+1) + k ] is x_j^k\n        const CppAD::vector<scalar>&    tx ,\n        // ty [ i * (q+1) + k ] is y_i^k\n        CppAD::vector<scalar>&          ty\n    )\n    {  size_t n_order  = q + 1;\n        size_t nr_left  = size_t( CppAD::Integer( tx[ 0 * n_order + 0 ] ) );\n        size_t n_middle = size_t( CppAD::Integer( tx[ 1 * n_order + 0 ] ) );\n        size_t nc_right = size_t( CppAD::Integer( tx[ 2 * n_order + 0 ] ) );\n# ifndef NDEBUG\n        size_t  nx        = 3 + (nr_left + nc_right) * n_middle;\n        size_t  ny        = nr_left * nc_right;\n# endif\n        //\n        assert( vx.size() == 0 || nx == vx.size() );\n        assert( vx.size() == 0 || ny == vy.size() );\n        assert( nx * n_order == tx.size() );\n        assert( ny * n_order == ty.size() );\n        //\n        size_t n_left   = nr_left * n_middle;\n        size_t n_right  = n_middle * nc_right;\n        size_t n_result = nr_left * nc_right;\n        assert( 3 + n_left + n_right == nx );\n        assert( n_result == ny );\n        //\n        // -------------------------------------------------------------------\n        // make sure f_left_, f_right_, and f_result_ are large enough\n        assert( f_left_.size() == f_right_.size() );\n        assert( f_left_.size() == f_result_.size() );\n        if( f_left_.size() < n_order )\n        {  f_left_.resize(n_order);\n            f_right_.resize(n_order);\n            f_result_.resize(n_order);\n            //\n            for(size_t k = 0; k < n_order; k++)\n            {  f_left_[k].resize( long(nr_left), long(n_middle) );\n                f_right_[k].resize( long(n_middle), long(nc_right) );\n                f_result_[k].resize( long(nr_left), long(nc_right) );\n            }\n        }\n        // -------------------------------------------------------------------\n        // unpack tx into f_left and f_right\n        for(size_t k = 0; k < n_order; k++)\n        {  // unpack left values for this order\n            for(size_t i = 0; i < n_left; i++)\n                f_left_[k].data()[i] = tx[ (3 + i) * n_order + k ];\n            //\n            // unpack right values for this order\n            for(size_t i = 0; i < n_right; i++)\n                f_right_[k].data()[i] = tx[ ( 3 + n_left + i) * n_order + k ];\n        }\n        // -------------------------------------------------------------------\n        // result for each order\n        // (we could avoid recalculting f_result_[k] for k=0,...,p-1)\n        for(size_t k = 0; k < n_order; k++)\n        {  // result[k] = sum_ell left[ell] * right[k-ell]\n            f_result_[k] = matrix::Zero( long(nr_left), long(nc_right) );\n            for(size_t ell = 0; ell <= k; ell++)\n                f_result_[k] += f_left_[ell] * f_right_[k-ell];\n        }\n        // -------------------------------------------------------------------\n        // pack result_ into ty\n        for(size_t k = 0; k < n_order; k++)\n        {  for(size_t i = 0; i < n_result; i++)\n                ty[ i * n_order + k ] = f_result_[k].data()[i];\n        }\n        // ------------------------------------------------------------------\n        // check if we are computing vy\n        if( vx.size() == 0 )\n            return true;\n        // ------------------------------------------------------------------\n        // compute variable information for y; i.e., vy\n        // (note that the constant zero times a variable is a constant)\n        scalar zero(0.0);\n        assert( n_order == 1 );\n        for(size_t i = 0; i < nr_left; i++)\n        {  for(size_t j = 0; j < nc_right; j++)\n            {  bool var = false;\n                for(size_t ell = 0; ell < n_middle; ell++)\n                {  // left information\n                    size_t index   = 3 + i * n_middle + ell;\n                    bool var_left  = vx[index];\n                    bool nz_left   = var_left |\n                                 (f_left_[0]( long(i), long(ell) ) != zero);\n                    // right information\n                    index          = 3 + n_left + ell * nc_right + j;\n                    bool var_right = vx[index];\n                    bool nz_right  = var_right |\n                                 (f_right_[0]( long(ell), long(j) ) != zero);\n                    // effect of result\n                    var |= var_left & nz_right;\n                    var |= nz_left  & var_right;\n                }\n                size_t index = i * nc_right + j;\n                vy[index]    = var;\n            }\n        }\n        return true;\n    }\n/* {xrst_code}\n{xrst_spell_on}\nreverse\n=======\n{xrst_spell_off}\n{xrst_code cpp} */\n    // reverse mode routine called by CppAD\n    virtual bool reverse(\n        // highest order Taylor coefficient that we are computing derivative of\n        size_t                     q ,\n        // forward mode Taylor coefficients for x variables\n        const CppAD::vector<double>&     tx ,\n        // forward mode Taylor coefficients for y variables\n        const CppAD::vector<double>&     ty ,\n        // upon return, derivative of G[ F[ {x_j^k} ] ] w.r.t {x_j^k}\n        CppAD::vector<double>&           px ,\n        // derivative of G[ {y_i^k} ] w.r.t. {y_i^k}\n        const CppAD::vector<double>&     py\n    )\n    {  size_t n_order  = q + 1;\n        size_t nr_left  = size_t( CppAD::Integer( tx[ 0 * n_order + 0 ] ) );\n        size_t n_middle = size_t( CppAD::Integer( tx[ 1 * n_order + 0 ] ) );\n        size_t nc_right = size_t( CppAD::Integer( tx[ 2 * n_order + 0 ] ) );\n# ifndef NDEBUG\n        size_t  nx        = 3 + (nr_left + nc_right) * n_middle;\n        size_t  ny        = nr_left * nc_right;\n# endif\n        //\n        assert( nx * n_order == tx.size() );\n        assert( ny * n_order == ty.size() );\n        assert( px.size() == tx.size() );\n        assert( py.size() == ty.size() );\n        //\n        size_t n_left   = nr_left * n_middle;\n        size_t n_right  = n_middle * nc_right;\n        size_t n_result = nr_left * nc_right;\n        assert( 3 + n_left + n_right == nx );\n        assert( n_result == ny );\n        // -------------------------------------------------------------------\n        // make sure f_left_, f_right_ are large enough\n        assert( f_left_.size() == f_right_.size() );\n        assert( f_left_.size() == f_result_.size() );\n        // must have previous run forward with order >= n_order\n        assert( f_left_.size() >= n_order );\n        // -------------------------------------------------------------------\n        // make sure r_left_, r_right_, and r_result_ are large enough\n        assert( r_left_.size() == r_right_.size() );\n        assert( r_left_.size() == r_result_.size() );\n        if( r_left_.size() < n_order )\n        {  r_left_.resize(n_order);\n            r_right_.resize(n_order);\n            r_result_.resize(n_order);\n            //\n            for(size_t k = 0; k < n_order; k++)\n            {  r_left_[k].resize( long(nr_left), long(n_middle) );\n                r_right_[k].resize( long(n_middle), long(nc_right) );\n                r_result_[k].resize( long(nr_left), long(nc_right) );\n            }\n        }\n        // -------------------------------------------------------------------\n        // unpack tx into f_left and f_right\n        for(size_t k = 0; k < n_order; k++)\n        {  // unpack left values for this order\n            for(size_t i = 0; i < n_left; i++)\n                f_left_[k].data()[i] = tx[ (3 + i) * n_order + k ];\n            //\n            // unpack right values for this order\n            for(size_t i = 0; i < n_right; i++)\n                f_right_[k].data()[i] = tx[ (3 + n_left + i) * n_order + k ];\n        }\n        // -------------------------------------------------------------------\n        // unpack py into r_result_\n        for(size_t k = 0; k < n_order; k++)\n        {  for(size_t i = 0; i < n_result; i++)\n                r_result_[k].data()[i] = py[ i * n_order + k ];\n        }\n        // -------------------------------------------------------------------\n        // initialize r_left_ and r_right_ as zero\n        for(size_t k = 0; k < n_order; k++)\n        {  r_left_[k]   = matrix::Zero( long(nr_left), long(n_middle) );\n            r_right_[k]  = matrix::Zero( long(n_middle), long(nc_right) );\n        }\n        // -------------------------------------------------------------------\n        // matrix reverse mode calculation\n        for(size_t k1 = n_order; k1 > 0; k1--)\n        {  size_t k = k1 - 1;\n            for(size_t ell = 0; ell <= k; ell++)\n            {  // nr x nm       = nr x nc      * nc * nm\n                r_left_[ell]    += r_result_[k] * f_right_[k-ell].transpose();\n                // nm x nc       = nm x nr * nr * nc\n                r_right_[k-ell] += f_left_[ell].transpose() * r_result_[k];\n            }\n        }\n        // -------------------------------------------------------------------\n        // pack r_left and r_right int px\n        for(size_t k = 0; k < n_order; k++)\n        {  // dimensions are integer constants\n            px[ 0 * n_order + k ] = 0.0;\n            px[ 1 * n_order + k ] = 0.0;\n            px[ 2 * n_order + k ] = 0.0;\n            //\n            // pack left values for this order\n            for(size_t i = 0; i < n_left; i++)\n                px[ (3 + i) * n_order + k ] = r_left_[k].data()[i];\n            //\n            // pack right values for this order\n            for(size_t i = 0; i < n_right; i++)\n                px[ (3 + i + n_left) * n_order + k] = r_right_[k].data()[i];\n        }\n        //\n        return true;\n    }\n/* {xrst_code}\n{xrst_spell_on}\nfor_sparse_jac\n==============\n{xrst_spell_off}\n{xrst_code cpp} */\n    // forward Jacobian sparsity routine called by CppAD\n    virtual bool for_sparse_jac(\n        // number of columns in the matrix R\n        size_t                                       q ,\n        // sparsity pattern for the matrix R\n        const CppAD::vector< std::set<size_t> >&     r ,\n        // sparsity pattern for the matrix S = f'(x) * R\n        CppAD::vector< std::set<size_t> >&           s ,\n        const CppAD::vector<Base>&                   x )\n    {\n        size_t nr_left  = size_t( CppAD::Integer( x[0] ) );\n        size_t n_middle = size_t( CppAD::Integer( x[1] ) );\n        size_t nc_right = size_t( CppAD::Integer( x[2] ) );\n# ifndef NDEBUG\n        size_t  nx        = 3 + (nr_left + nc_right) * n_middle;\n        size_t  ny        = nr_left * nc_right;\n# endif\n        //\n        assert( nx == r.size() );\n        assert( ny == s.size() );\n        //\n        size_t n_left = nr_left * n_middle;\n        for(size_t i = 0; i < nr_left; i++)\n        {  for(size_t j = 0; j < nc_right; j++)\n            {  // pack index for entry (i, j) in result\n                size_t i_result = i * nc_right + j;\n                s[i_result].clear();\n                for(size_t ell = 0; ell < n_middle; ell++)\n                {  // pack index for entry (i, ell) in left\n                    size_t i_left  = 3 + i * n_middle + ell;\n                    // pack index for entry (ell, j) in right\n                    size_t i_right = 3 + n_left + ell * nc_right + j;\n                    // check if result of for this product is always zero\n                    // note that x is nan for components that are variables\n                    bool zero = x[i_left] == Base(0.0) || x[i_right] == Base(0);\n                    if( ! zero )\n                    {  s[i_result] =\n                            CppAD::set_union(s[i_result], r[i_left] );\n                        s[i_result] =\n                            CppAD::set_union(s[i_result], r[i_right] );\n                    }\n                }\n            }\n        }\n        return true;\n    }\n/* {xrst_code}\n{xrst_spell_on}\nrev_sparse_jac\n==============\n{xrst_spell_off}\n{xrst_code cpp} */\n    // reverse Jacobian sparsity routine called by CppAD\n    virtual bool rev_sparse_jac(\n        // number of columns in the matrix R^T\n        size_t                                      q  ,\n        // sparsity pattern for the matrix R^T\n        const CppAD::vector< std::set<size_t> >&    rt ,\n        // sparsity pattern for the matrix S^T = f'(x)^T * R^T\n        CppAD::vector< std::set<size_t> >&          st ,\n        const CppAD::vector<Base>&                   x )\n    {\n        size_t nr_left  = size_t( CppAD::Integer( x[0] ) );\n        size_t n_middle = size_t( CppAD::Integer( x[1] ) );\n        size_t nc_right = size_t( CppAD::Integer( x[2] ) );\n        size_t  nx        = 3 + (nr_left + nc_right) * n_middle;\n# ifndef NDEBUG\n        size_t  ny        = nr_left * nc_right;\n# endif\n        //\n        assert( nx == st.size() );\n        assert( ny == rt.size() );\n        //\n        // initialize S^T as empty\n        for(size_t i = 0; i < nx; i++)\n            st[i].clear();\n\n        // sparsity for S(x)^T = f'(x)^T * R^T\n        size_t n_left = nr_left * n_middle;\n        for(size_t i = 0; i < nr_left; i++)\n        {  for(size_t j = 0; j < nc_right; j++)\n            {  // pack index for entry (i, j) in result\n                size_t i_result = i * nc_right + j;\n                st[i_result].clear();\n                for(size_t ell = 0; ell < n_middle; ell++)\n                {  // pack index for entry (i, ell) in left\n                    size_t i_left  = 3 + i * n_middle + ell;\n                    // pack index for entry (ell, j) in right\n                    size_t i_right = 3 + n_left + ell * nc_right + j;\n                    //\n                    st[i_left]  = CppAD::set_union(st[i_left],  rt[i_result]);\n                    st[i_right] = CppAD::set_union(st[i_right], rt[i_result]);\n                }\n            }\n        }\n        return true;\n    }\n/* {xrst_code}\n{xrst_spell_on}\nfor_sparse_hes\n==============\n{xrst_spell_off}\n{xrst_code cpp} */\n    virtual bool for_sparse_hes(\n        // which components of x are variables for this call\n        const CppAD::vector<bool>&                   vx,\n        // sparsity pattern for the diagonal of R\n        const CppAD::vector<bool>&                   r ,\n        // sparsity pattern for the vector S\n        const CppAD::vector<bool>&                   s ,\n        // sparsity patternfor the Hessian H(x)\n        CppAD::vector< std::set<size_t> >&           h ,\n        const CppAD::vector<Base>&                   x )\n    {\n        size_t nr_left  = size_t( CppAD::Integer( x[0] ) );\n        size_t n_middle = size_t( CppAD::Integer( x[1] ) );\n        size_t nc_right = size_t( CppAD::Integer( x[2] ) );\n        size_t  nx        = 3 + (nr_left + nc_right) * n_middle;\n# ifndef NDEBUG\n        size_t  ny        = nr_left * nc_right;\n# endif\n        //\n        assert( vx.size() == nx );\n        assert( r.size()  == nx );\n        assert( s.size()  == ny );\n        assert( h.size()  == nx );\n        //\n        // initialize h as empty\n        for(size_t i = 0; i < nx; i++)\n            h[i].clear();\n        //\n        size_t n_left = nr_left * n_middle;\n        for(size_t i = 0; i < nr_left; i++)\n        {  for(size_t j = 0; j < nc_right; j++)\n            {  // pack index for entry (i, j) in result\n                size_t i_result = i * nc_right + j;\n                if( s[i_result] )\n                {  for(size_t ell = 0; ell < n_middle; ell++)\n                    {  // pack index for entry (i, ell) in left\n                        size_t i_left  = 3 + i * n_middle + ell;\n                        // pack index for entry (ell, j) in right\n                        size_t i_right = 3 + n_left + ell * nc_right + j;\n                        if( r[i_left] && r[i_right] )\n                        {  h[i_left].insert(i_right);\n                            h[i_right].insert(i_left);\n                        }\n                    }\n                }\n            }\n        }\n        return true;\n    }\n/* {xrst_code}\n{xrst_spell_on}\nrev_sparse_hes\n==============\n{xrst_spell_off}\n{xrst_code cpp} */\n    // reverse Hessian sparsity routine called by CppAD\n    virtual bool rev_sparse_hes(\n        // which components of x are variables for this call\n        const CppAD::vector<bool>&                   vx,\n        // sparsity pattern for S(x) = g'[f(x)]\n        const CppAD::vector<bool>&                   s ,\n        // sparsity pattern for d/dx g[f(x)] = S(x) * f'(x)\n        CppAD::vector<bool>&                         t ,\n        // number of columns in R, U(x), and V(x)\n        size_t                                       q ,\n        // sparsity pattern for R\n        const CppAD::vector< std::set<size_t> >&     r ,\n        // sparsity pattern for U(x) = g^{(2)} [ f(x) ] * f'(x) * R\n        const CppAD::vector< std::set<size_t> >&     u ,\n        // sparsity pattern for\n        // V(x) = f'(x)^T * U(x) + sum_{i=0}^{m-1} S_i(x) f_i^{(2)} (x) * R\n        CppAD::vector< std::set<size_t> >&           v ,\n        // parameters as integers\n        const CppAD::vector<Base>&                   x )\n    {\n        size_t nr_left  = size_t( CppAD::Integer( x[0] ) );\n        size_t n_middle = size_t( CppAD::Integer( x[1] ) );\n        size_t nc_right = size_t( CppAD::Integer( x[2] ) );\n        size_t  nx        = 3 + (nr_left + nc_right) * n_middle;\n# ifndef NDEBUG\n        size_t  ny        = nr_left * nc_right;\n# endif\n        //\n        assert( vx.size() == nx );\n        assert( s.size()  == ny );\n        assert( t.size()  == nx );\n        assert( r.size()  == nx );\n        assert( v.size()  == nx );\n        //\n        // initialize return sparsity patterns as false\n        for(size_t j = 0; j < nx; j++)\n        {  t[j] = false;\n            v[j].clear();\n        }\n        //\n        size_t n_left = nr_left * n_middle;\n        for(size_t i = 0; i < nr_left; i++)\n        {  for(size_t j = 0; j < nc_right; j++)\n            {  // pack index for entry (i, j) in result\n                size_t i_result = i * nc_right + j;\n                for(size_t ell = 0; ell < n_middle; ell++)\n                {  // pack index for entry (i, ell) in left\n                    size_t i_left  = 3 + i * n_middle + ell;\n                    // pack index for entry (ell, j) in right\n                    size_t i_right = 3 + n_left + ell * nc_right + j;\n                    //\n                    // back propagate T(x) = S(x) * f'(x).\n                    t[i_left]  |= bool( s[i_result] );\n                    t[i_right] |= bool( s[i_result] );\n                    //\n                    // V(x) = f'(x)^T * U(x) +  sum_i S_i(x) * f_i''(x) * R\n                    // U(x)   = g''[ f(x) ] * f'(x) * R\n                    // S_i(x) = g_i'[ f(x) ]\n                    //\n                    // back propagate f'(x)^T * U(x)\n                    v[i_left]  = CppAD::set_union(v[i_left],  u[i_result] );\n                    v[i_right] = CppAD::set_union(v[i_right], u[i_result] );\n                    //\n                    // back propagate S_i(x) * f_i''(x) * R\n                    // (here is where we use vx to check for cross terms)\n                    if( s[i_result] && vx[i_left] && vx[i_right] )\n                    {  v[i_left]  = CppAD::set_union(v[i_left],  r[i_right] );\n                        v[i_right] = CppAD::set_union(v[i_right], r[i_left]  );\n                    }\n                }\n            }\n        }\n        return true;\n    }\n/* {xrst_code}\n{xrst_spell_on}\nEnd Class Definition\n********************\n{xrst_spell_off}\n{xrst_code cpp} */\n}; // End of atomic_eigen_mat_mul class\n\n}  // END_EMPTY_NAMESPACE\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end atomic_two_eigen_mat_mul.hpp}\n*/\n\n\n# endif\n"
  },
  {
    "path": "include/cppad/example/base_adolc.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_BASE_ADOLC_HPP\n# define CPPAD_EXAMPLE_BASE_ADOLC_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin base_adolc.hpp}\n{xrst_spell\n    acosh\n    adouble\n    asinh\n    atrig\n    azmul\n    codassign\n    condassign\n    erfc\n    expm\n    valgrind\n}\n\nEnable use of AD<Base> where Base is Adolc's adouble Type\n#########################################################\n\nSyntax\n******\n| # ``include <cppad/example/base_adolc.hpp>``\n{xrst_toc_hidden\n    example/general/mul_level_adolc.cpp\n}\n\nExample\n*******\nThe file :ref:`mul_level_adolc.cpp-name` contains an example use of\nAdolc's ``adouble`` type for a CppAD *Base* type.\nThe file :ref:`mul_level_adolc_ode.cpp-name` contains a more realistic\n(and complex) example.\n\nInclude Files\n*************\nThis file ``base_adolc.hpp`` requires ``adouble`` to be defined.\nIn addition, it is included before ``<cppad/cppad.hpp>`` ,\nbut it needs to include parts of CppAD that are used by this file.\nThis is done with the following include commands:\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <adolc/adolc.h>\n# include <cppad/base_require.hpp>\n/* {xrst_code}\n{xrst_spell_on}\n\nCondExpOp\n*********\nThe type ``adouble`` supports a conditional assignment function\nwith the syntax\n\n    ``condassign`` ( *a* , *b* , *c* , *d* )\n\nwhich evaluates to\n\n    *a* = ( *b* > 0) ? *c* : *d* ;\n\nThis enables one to include conditionals in the recording of\n``adouble`` operations and later evaluation for different\nvalues of the independent variables\n(in the same spirit as the CppAD :ref:`CondExp-name` function).\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    inline adouble CondExpOp(\n        enum  CppAD::CompareOp     cop ,\n        const adouble            &left ,\n        const adouble           &right ,\n        const adouble        &trueCase ,\n        const adouble       &falseCase )\n    {  adouble result;\n        switch( cop )\n        {\n            case CompareLt: // left < right\n            condassign(result, right - left, trueCase, falseCase);\n            break;\n\n            case CompareLe: // left <= right\n            condassign(result, left - right, falseCase, trueCase);\n            break;\n\n            case CompareEq: // left == right\n            condassign(result, left - right, falseCase, trueCase);\n            condassign(result, right - left, falseCase, result);\n            break;\n\n            case CompareGe: // left >= right\n            condassign(result, right - left, falseCase, trueCase);\n            break;\n\n            case CompareGt: // left > right\n            condassign(result, left - right, trueCase, falseCase);\n            break;\n            default:\n            CppAD::ErrorHandler::Call(\n                true     , __LINE__ , __FILE__ ,\n                \"CppAD::CondExp\",\n                \"Error: for unknown reason.\"\n            );\n            result = trueCase;\n        }\n        return result;\n    }\n}\n/* {xrst_code}\n{xrst_spell_on}\n\nCondExpRel\n**********\nThe :ref:`CPPAD_COND_EXP_REL<base_cond_exp@CondExpRel>` macro invocation\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    CPPAD_COND_EXP_REL(adouble)\n}\n/* {xrst_code}\n{xrst_spell_on}\n\nEqualOpSeq\n**********\nThe Adolc user interface does not specify a way to determine if\ntwo ``adouble`` variables correspond to the same operations sequence.\nMake ``EqualOpSeq`` an error if it gets used:\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    inline bool EqualOpSeq(const adouble &x, const adouble &y)\n    {  CppAD::ErrorHandler::Call(\n            true     , __LINE__ , __FILE__ ,\n            \"CppAD::EqualOpSeq(x, y)\",\n            \"Error: adouble does not support EqualOpSeq.\"\n        );\n        return false;\n    }\n}\n/* {xrst_code}\n{xrst_spell_on}\n\nIdentical\n*********\nThe Adolc user interface does not specify a way to determine if an\n``adouble`` depends on the independent variables.\nTo be safe (but slow) return ``false`` in all the cases below.\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    inline bool IdenticalCon(const adouble &x)\n    {  return false; }\n    inline bool IdenticalZero(const adouble &x)\n    {  return false; }\n    inline bool IdenticalOne(const adouble &x)\n    {  return false; }\n    inline bool IdenticalEqualCon(const adouble &x, const adouble &y)\n    {  return false; }\n}\n/* {xrst_code}\n{xrst_spell_on}\n\nInteger\n*******\n{xrst_spell_off}\n{xrst_code cpp} */\n    inline int Integer(const adouble &x)\n    {    return static_cast<int>( x.getValue() ); }\n/* {xrst_code}\n{xrst_spell_on}\n\nazmul\n*****\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    CPPAD_AZMUL( adouble )\n}\n/* {xrst_code}\n{xrst_spell_on}\n\nOrdered\n*******\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    inline bool GreaterThanZero(const adouble &x)\n    {    return (x > 0); }\n    inline bool GreaterThanOrZero(const adouble &x)\n    {    return (x >= 0); }\n    inline bool LessThanZero(const adouble &x)\n    {    return (x < 0); }\n    inline bool LessThanOrZero(const adouble &x)\n    {    return (x <= 0); }\n    inline bool abs_geq(const adouble& x, const adouble& y)\n    {  return fabs(x) >= fabs(y); }\n}\n/* {xrst_code}\n{xrst_spell_on}\n\nUnary Standard Math\n*******************\nThe following :ref:`required<base_require-name>` functions\nare defined by the Adolc package for the ``adouble`` base case:\n\n``acos`` ,\n``acosh`` ,\n``asin`` ,\n``asinh`` ,\n``atan`` ,\n``atanh`` ,\n``cos`` ,\n``cosh`` ,\n``erf`` ,\n``exp`` ,\n``fabs`` ,\n``log`` ,\n``sin`` ,\n``sinh`` ,\n``sqrt`` ,\n``tan`` .\n\nerfc\n****\nIf you provide ``--enable-atrig-erf`` on the configure command line,\nthe adolc package supports all the c++11 math functions except\n``erfc`` , ``expm1`` , and ``log1p`` .\nFor the reason, we make using ``erfc`` an error:\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n# define CPPAD_BASE_ADOLC_NO_SUPPORT(fun)                         \\\n    inline adouble fun(const adouble& x)                          \\\n    {  CPPAD_ASSERT_KNOWN(                                       \\\n            false,                                                \\\n            #fun \": adolc does not support this function\"         \\\n        );                                                        \\\n        return 0.0;                                               \\\n    }\n    CPPAD_BASE_ADOLC_NO_SUPPORT(erfc)\n    CPPAD_BASE_ADOLC_NO_SUPPORT(expm1)\n    CPPAD_BASE_ADOLC_NO_SUPPORT(log1p)\n# undef CPPAD_BASE_ADOLC_NO_SUPPORT\n}\n/* {xrst_code}\n{xrst_spell_on}\n\nsign\n****\nThis :ref:`required<base_require-name>` function is defined using the\n``codassign`` function so that its ``adouble`` operation sequence\ndoes not depend on the value of *x* .\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    inline adouble sign(const adouble& x)\n    {  adouble s_plus, s_minus, half(.5);\n        // set s_plus to sign(x)/2,  except for case x == 0, s_plus = -.5\n        condassign(s_plus,  +x, -half, +half);\n        // set s_minus to -sign(x)/2, except for case x == 0, s_minus = -.5\n        condassign(s_minus, -x, -half, +half);\n        // set s to sign(x)\n        return s_plus - s_minus;\n    }\n}\n/* {xrst_code}\n{xrst_spell_on}\n\nabs\n***\nThis :ref:`required<base_require-name>` function uses the adolc ``fabs``\nfunction:\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    inline adouble abs(const adouble& x)\n    {  return fabs(x); }\n}\n/* {xrst_code}\n{xrst_spell_on}\n\npow\n***\nThis :ref:`required<base_require-name>` function\nis defined by the Adolc package for the ``adouble`` base case.\n\nnumeric_limits\n**************\nThe following defines the CppAD :ref:`numeric_limits-name`\nfor the type ``adouble`` :\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    CPPAD_NUMERIC_LIMITS(double, adouble)\n}\n/* {xrst_code}\n{xrst_spell_on}\n\nto_string\n*********\nThe following defines the CppAD :ref:`to_string-name` function\nfor the type ``adouble`` :\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    template <> struct to_string_struct<adouble>\n    {  std::string operator()(const adouble& x)\n        {  std::stringstream os;\n            int n_digits = 1 + std::numeric_limits<double>::digits10;\n            os << std::setprecision(n_digits);\n            os << x.value();\n            return os.str();\n        }\n    };\n}\n/* {xrst_code}\n{xrst_spell_on}\n\nhash_code\n*********\nIt appears that an ``adouble`` object can have fields\nthat are not initialized.\nThis results in a ``valgrind`` error when these fields are used by the\n:ref:`base_hash@Default` hashing function.\nFor this reason, the ``adouble`` class overrides the default definition.\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    inline unsigned short hash_code(const adouble& x)\n    {  unsigned short code = 0;\n        double value = x.value();\n        if( value == 0.0 )\n            return code;\n        double log_x = std::log( fabs( value ) );\n        // assume log( std::numeric_limits<double>::max() ) is near 700\n        code = static_cast<unsigned short>(\n            (CPPAD_HASH_TABLE_SIZE / 700 + 1) * log_x\n        );\n        code = code % CPPAD_HASH_TABLE_SIZE;\n        return code;\n    }\n}\n/* {xrst_code}\n{xrst_spell_on}\nNote that after the hash codes match, the\n:ref:`base_adolc.hpp@Identical` function will be used\nto make sure two values are the same and one can replace the other.\nA more sophisticated implementation of the ``Identical`` function\nwould detect which ``adouble`` values depend on the\n``adouble`` independent variables (and hence can change).\n\n{xrst_end base_adolc.hpp}\n*/\n# endif\n"
  },
  {
    "path": "include/cppad/example/code_gen_fun.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_CODE_GEN_FUN_HPP\n# define CPPAD_EXAMPLE_CODE_GEN_FUN_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n// BEGIN C++\n# include <cppad/cg/cppadcg.hpp>\n\n// See https://docs.microsoft.com/en-us/cpp/cpp/\n//      using-dllimport-and-dllexport-in-cpp-classes?view=msvc-160\n// Also see define.hpp where CPPAD_LIB_EXPORTS is also defined and\n// undef.hpp where it gets undefined.\n# ifdef  _MSC_VER\n# ifdef  cppad_lib_EXPORTS\n# define CPPAD_LIB_EXPORT __declspec(dllexport)\n# else\n# define CPPAD_LIB_EXPORT __declspec(dllimport)\n# endif  // cppad_lib_EXPORTS\n# else   // _MSC_VER\n# define CPPAD_LIB_EXPORT\n# endif\n\nclass CPPAD_LIB_EXPORT code_gen_fun {\npublic:\n    // type of evaluation for Jacobians (possibly Hessians in the future)\n    enum evaluation_enum { none_enum, dense_enum, sparse_enum };\nprivate:\n    // dynamic_lib_\n    std::unique_ptr< CppAD::cg::DynamicLib<double> > dynamic_lib_;\n    //\n    // model_ (contains a reference to dynamic_lib_)\n    std::unique_ptr< CppAD::cg::GenericModel<double> > model_;\n    //\npublic:\n    // -----------------------------------------------------------------------\n    // constructors\n    // -----------------------------------------------------------------------\n    // fun_name()\n    code_gen_fun(void);\n    //\n    // fun_name( file_name )\n    code_gen_fun(const std::string& file_name);\n    //\n    // fun_name(file_name, cg_fun, eval_jac)\n    code_gen_fun(\n        const std::string&                     file_name             ,\n        CppAD::ADFun< CppAD::cg::CG<double> >& cg_fun                ,\n        evaluation_enum                        eval_jac = none_enum\n    );\n    // -----------------------------------------------------------------------\n    // operations\n    // -----------------------------------------------------------------------\n    // swap(other_fun)\n    void swap(code_gen_fun& other_fun);\n    //\n    // y = fun_name(x)\n    CppAD::vector<double>  operator()(const CppAD::vector<double> & x);\n    //\n    // J = fun_name.jacobian(x)\n    CppAD::vector<double>  jacobian(const CppAD::vector<double> & x);\n    //\n    // Jrcv = fun_name.sparse_jacobian(x)\n    CppAD::sparse_rcv< CppAD::vector<size_t>, CppAD::vector<double> >\n    sparse_jacobian(const CppAD::vector<double>& x);\n};\n// END C++\n\n# endif\n"
  },
  {
    "path": "include/cppad/example/cppad_eigen.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_CPPAD_EIGEN_HPP\n# define CPPAD_EXAMPLE_CPPAD_EIGEN_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin cppad_eigen.hpp}\n{xrst_spell\n    gitlab\n    libeigen\n}\nEnable Use of Eigen Linear Algebra Package with CppAD\n#####################################################\n\nSyntax\n******\n| # ``include <cppad/example/cppad_eigen.hpp>``\n{xrst_toc_hidden\n    include/cppad/example/eigen_plugin.hpp\n    example/general/eigen_array.cpp\n    example/general/eigen_det.cpp\n}\n\nPurpose\n*******\nEnables the use of the :ref:`eigen-name`\nlinear algebra package with the type *AD* < ``Base`` > ; see\n`Using custom scalar types`_ .\n\n.. _Using custom scalar types: https://\n    libeigen.gitlab.io/eigen/docs-nightly/TopicCustomizing_CustomScalar.html\n\nExample\n*******\nThe files :ref:`eigen_array.cpp-name` and :ref:`eigen_det.cpp-name`\ncontain an example and test of this include file.\nThey return true if they succeed and false otherwise.\n\nCppAD Declarations\n******************\nFirst declare some items that are defined by cppad.hpp:\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    // AD<Base>\n    template <class Base> class AD;\n    // numeric_limits<Float>\n    template <class Float>  class numeric_limits;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\nstd Declarations\n****************\nNext declare some template specializations in std namespace:\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace std {\n    template <class Base> bool isinf(const CppAD::AD<Base> &x);\n    template <class Base> bool isfinite(const CppAD::AD<Base> &x);\n    template <class Base> bool isnan(const CppAD::AD<Base> &x);\n}\n/* {xrst_code}\n{xrst_spell_on}\n\nInclude Eigen/Core\n******************\nNext define the eigen plugin and then include Eigen/Core:\n{xrst_spell_off}\n{xrst_code cpp} */\n\n# define EIGEN_MATRIXBASE_PLUGIN <cppad/example/eigen_plugin.hpp>\n# include <Eigen/Core>\n/* {xrst_code}\n{xrst_spell_on}\n\nEigen NumTraits\n***************\nEigen needs the following definitions, in the Eigen namespace,\nto work properly with ``AD`` < *Base* > scalars:\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace Eigen {\n    template <class Base> struct NumTraits< CppAD::AD<Base> >\n    {  // type that corresponds to the real part of an AD<Base> value\n        typedef CppAD::AD<Base>   Real;\n        // type for AD<Base> operations that result in non-integer values\n        typedef CppAD::AD<Base>   NonInteger;\n        //  type to use for numeric literals such as \"2\" or \"0.5\".\n        typedef CppAD::AD<Base>   Literal;\n        // type for nested value inside an AD<Base> expression tree\n        typedef CppAD::AD<Base>   Nested;\n\n        enum {\n            // does not support complex Base types\n            IsComplex             = 0 ,\n            // does not support integer Base types\n            IsInteger             = 0 ,\n            // only support signed Base types\n            IsSigned              = 1 ,\n            // must initialize an AD<Base> object\n            RequireInitialization = 1 ,\n            // computational cost of the corresponding operations\n            ReadCost              = 1 ,\n            AddCost               = 2 ,\n            MulCost               = 2\n        };\n\n        // machine epsilon with type of real part of x\n        // (use assumption that Base is not complex)\n        static CppAD::AD<Base> epsilon(void)\n        {  return CppAD::numeric_limits< CppAD::AD<Base> >::epsilon(); }\n\n        // relaxed version of machine epsilon for comparison of different\n        // operations that should result in the same value\n        static CppAD::AD<Base> dummy_precision(void)\n        {  return 100. *\n                CppAD::numeric_limits< CppAD::AD<Base> >::epsilon();\n        }\n\n        // minimum normalized positive value\n        static CppAD::AD<Base> lowest(void)\n        {  return CppAD::numeric_limits< CppAD::AD<Base> >::min(); }\n\n        // maximum finite value\n        static CppAD::AD<Base> highest(void)\n        {  return CppAD::numeric_limits< CppAD::AD<Base> >::max(); }\n\n        // number of decimal digits that can be represented without change.\n        static int digits10(void)\n        {  return CppAD::numeric_limits< CppAD::AD<Base> >::digits10; }\n\n        // number of decimal digits necessary to uniquely represent values.\n        static int max_digits10(void)\n        {  return CppAD::numeric_limits< CppAD::AD<Base> >::max_digits10; }\n\n        // not a number\n        static CppAD::AD<Base> quiet_NaN(void)\n        {  return CppAD::numeric_limits< CppAD::AD<Base> >::quiet_NaN(); }\n\n        // positive infinite value\n        static CppAD::AD<Base> infinity(void)\n        {  return CppAD::numeric_limits< CppAD::AD<Base> >::infinity(); }\n    };\n}\n/* {xrst_code}\n{xrst_spell_on}\n\nEigen ScalarBinaryOpTraits\n**************************\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace Eigen {\n    // Inform Eigen that a binary operations between Base and AD<Base>\n    // are allowed and thate the return type is AD<Base>\n    template<typename Base, typename BinOp>\n    struct ScalarBinaryOpTraits<CppAD::AD<Base>, Base, BinOp>{\n        typedef CppAD::AD<Base> ReturnType;\n    };\n    template<typename Base, typename BinOp>\n    struct ScalarBinaryOpTraits<Base, CppAD::AD<Base>, BinOp>\n    {\n        typedef CppAD::AD<Base> ReturnType;\n    };\n}\n/* {xrst_code}\n{xrst_spell_on}\n\nCppAD Namespace\n***************\nEigen needs the following definitions, in the CppAD namespace,\nto work properly with ``AD`` < *Base* > scalars:\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n        // functions that return references\n        template <class Base> const AD<Base>& conj(const AD<Base>& x)\n        {  return x; }\n        template <class Base> const AD<Base>& real(const AD<Base>& x)\n        {  return x; }\n\n        // functions that return values (note abs is defined by cppad.hpp)\n        template <class Base> AD<Base> imag(const AD<Base>& x)\n        {  return CppAD::AD<Base>(0.); }\n        template <class Base> AD<Base> abs2(const AD<Base>& x)\n        {  return x * x; }\n}\n/* {xrst_code}\n{xrst_spell_on}\n\neigen_vector\n************\nThe class ``CppAD::eigen_vector`` is a wrapper for Eigen column vectors\nso that they are :ref:`simple vectors<SimpleVector-name>` .\nTo be specific, it converts ``Eigen::Index`` arguments and\nreturn values to ``size_t`` .\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace CppAD {\n    template <class Scalar>\n    class eigen_vector : public Eigen::Matrix<Scalar, Eigen::Dynamic, 1> {\n    private:\n        // base_class\n        typedef Eigen::Matrix<Scalar, Eigen::Dynamic, 1> base_class;\n    public:\n        // constructor\n        eigen_vector(size_t n) : base_class( Eigen::Index(n) )\n        { }\n        eigen_vector(void) : base_class()\n        { }\n        // operator[]\n        Scalar& operator[](size_t i)\n        {  return base_class::operator[]( Eigen::Index(i) ); }\n        const Scalar& operator[](size_t i) const\n        {  return base_class::operator[]( Eigen::Index(i) ); }\n        // size\n        size_t size(void) const\n        {  return size_t( base_class::size() ); }\n        // resize\n        void resize(size_t n)\n        {  base_class::resize( Eigen::Index(n) ); }\n    };\n}\n/* {xrst_code}\n{xrst_spell_on}\n\nInclude cppad.hpp\n*****************\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <cppad/cppad.hpp>\n/* {xrst_code}\n{xrst_spell_on}\n\nstd Definitions\n***************\nThe definitions below use cppad.hpp.\nNote that :ref:`Value-name` function can only be used with a\n:ref:`constant parameter<glossary@Parameter@Constant>` argument.\n{xrst_spell_off}\n{xrst_code cpp} */\nnamespace std {\n    template <class Base> bool isinf(const CppAD::AD<Base> &x)\n    {  return isinf(CppAD::Value( CppAD::Var2Par(x) ) ); }\n\n    template <class Base> bool isfinite(const CppAD::AD<Base> &x)\n    {  return isfinite(CppAD::Value( CppAD::Var2Par(x) ) ); }\n\n    template <class Base> bool isnan(const CppAD::AD<Base> &x)\n    {  return CppAD::isnan(CppAD::Value( CppAD::Var2Par(x) ) ); }\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end cppad_eigen.hpp}\n*/\n# endif\n"
  },
  {
    "path": "include/cppad/example/eigen_plugin.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_EIGEN_PLUGIN_HPP\n# define CPPAD_EXAMPLE_EIGEN_PLUGIN_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*$\n{xrst_begin eigen_plugin.hpp}\n\nSource Code for eigen_plugin.hpp\n################################\n{xrst_spell_off}\n{xrst_code cpp} */\n// Declaration needed, before eigen-3.3.3, so Eigen vector is a simple vector\ntypedef Scalar value_type;\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end eigen_plugin.hpp}\n*/\n# endif\n"
  },
  {
    "path": "include/cppad/example/valvector/class.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_VALVECTOR_CLASS_HPP\n# define CPPAD_EXAMPLE_VALVECTOR_CLASS_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2024 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin_parent valvector}\n{xrst_spell\n    jax\n    numpy\n    pytorch\n}\n\nvalvector: An Example Machine Learning Base Class\n#################################################\nThis CppAD Base class preforms numerical operations on vectors; e.g.,\nonly one CppAD operation represents the element-by-element addition\nof two vectors. This is similar to the Pytorch Tensors or Jax Numpy Arrays.\n\nscalar_type\n***********\nThe type ``valvector::scalar_type``\nis the type corresponding to each element of a valvector .\nWe use *scalar_type* to denote this type.\n\nGetting Started\n===============\nThe file :ref:`valvector_get_started.cpp-name` is an example\nthat computes derivatives using valvector as the base class.\n\nOther Examples\n==============\nThe file :ref:`valvector.cpp-name` tests that all of the valvector examples\ngit the expected results.\n\nOperations\n**********\n{xrst_toc_table after\n    include/cppad/example/valvector/split_join.hpp\n    include/cppad/example/valvector/sum.hpp\n    example/valvector/get_started.cpp\n    example/valvector/llsq_obj.cpp\n}\n\n\n{xrst_end valvector}\n*/\n# include <cmath>\n# include <iostream>\n# include <cassert>\n# include <cppad/utility/vector.hpp>\n# include <cppad/base_require.hpp>\n// ============================================================================\n// Macros\n// ============================================================================\n# define CPPAD_VALVECTOR_ASSERT_KNOWN(exp, msg) \\\n    if( ! (exp ) ) \\\n    {   std::cerr << \"valvector: \" << msg << \"\\n\"; \\\n        assert( exp ); \\\n    }\n//\n// BEGIN_NOT_AVAILABLE\n# define CPPAD_VALVECTOR_NOT_AVAILABLE(fun) \\\n    inline bool fun(const valvector& x) \\\n    {   CPPAD_VALVECTOR_ASSERT_KNOWN( false, #fun \" is not available\" ) \\\n        return false; \\\n    }\n// END_NOT_AVAILABLE\n//\n# define CPPAD_VALVECTOR_UNARY_STD_MATH(fun) \\\n    inline valvector fun(const valvector &x) \\\n    {   valvector result; \\\n        result.resize( x.size() ); \\\n        for(size_t i = 0; i < x.size(); ++i) \\\n            result[i] = std::fun( x[i] ); \\\n        return result; \\\n    }\n//\n# define CPPAD_VALVECTOR_BINARY_NUMERIC_OP(op, compound_op) \\\n    valvector operator op(const valvector& other) const \\\n    {   CPPAD_VALVECTOR_ASSERT_KNOWN(  \\\n            size() == 1 || other.size() == 1 || size() == other.size() , \\\n            \"size error using \" #op \" operator\" \\\n        ) \\\n        valvector result; \\\n        result.resize( std::max( size(), other.size() ) );   \\\n        for(size_t i = 0; i < result.size(); ++i) \\\n            result[i] = (*this)[i] op other[i]; \\\n        return result; \\\n    } \\\n    valvector& operator compound_op(const valvector& other) \\\n    {   CPPAD_VALVECTOR_ASSERT_KNOWN(  \\\n            size() == 1 || other.size() == 1 || size() == other.size() , \\\n            \"size error using \" #compound_op \" operator\" \\\n        ) \\\n        if( size() == 1 && 1 < other.size()) \\\n        {   vec_.resize( other.size() ); \\\n            for(size_t i = 0; i < size(); ++i) \\\n                vec_[i] = scalar_; \\\n        } \\\n        for(size_t i = 0; i < size(); ++i) \\\n            (*this)[i] compound_op other[i]; \\\n        return *this; \\\n    }\n# define CPPAD_VALVECTOR_BINARY_ORDER_OP(op) \\\n    bool operator op(const valvector& other) const \\\n    {   CPPAD_VALVECTOR_ASSERT_KNOWN( \\\n            size() == 1 && other.size() == 1, \\\n            \"binary \" #op \" operator is only available when both sizes are one\" \\\n        ) \\\n        return (*this)[0] op other[0]; \\\n    }\n// ============================================================================\n// valvector\n// ============================================================================\nclass valvector {\npublic:\n    //\n    // scalar_type\n    typedef double                     scalar_type;\n    //\nprivate:\n    //\n    // vector_type\n    typedef CppAD::vector<scalar_type> vector_type;\n    //\n    // vec_\n    vector_type vec_;\n    //\n    // scalar_\n    scalar_type scalar_;\npublic:\n    /*\n    ---------------------------------------------------------------------------\n    {xrst_begin valvector_ctor}\n    {xrst_spell\n        initializer\n        sj\n    }\n\n    The valvector Constructors\n    ##########################\n    Creates a valvector (called *x* below).\n\n    Syntax\n    ******\n    | ``valvector`` *x*\n    | ``valvector`` *x*( *s* )\n    | ``valvector`` *x*( *v* )\n    | ``valvector`` *x*( { *s0* , *s1* , ... } )\n\n    Default\n    *******\n    The default constructor (no argument)\n    creates the valvector *x* with one element using the\n    :ref:`valvector@scalar_type` default constructor.\n\n    Scalar\n    ******\n    The scalar constructor (argument is *s* )\n    creates the valvector *x* with one element that is equal to\n    *scalar_type* ( *s* ), where\n    *s* has type :ref:`valvector@scalar_type` ,\n    `int``, ``long int``, ``double``, ``long_double`` or ``size_t`` .\n\n    Vector\n    ******\n    The vector constructor (argument is *v*)\n    creates a copy of the valvector *v* .\n\n    List\n    ****\n    In the standard initializer list constructor\n    ( argument is { *s0* , *s1* , .. } )\n    *s0* , *s1* , have valvector :ref:`valvector@scalar_type` .\n    This create a valvector with size equal the length of the list\n    and j-th element equal to *sj* .\n\n    {xrst_toc_hidden\n        example/valvector/ctor.cpp\n    }\n    Example\n    =======\n    The file :ref:`valvector_ctor.cpp-name` is an example and test of these\n    constructors.\n\n    {xrst_end valvector_ctor}\n    ---------------------------------------------------------------------------\n    */\n    // default ctor\n    valvector(void) : vec_(0), scalar_()\n    { }\n    //\n    // ctor of scalar\n    valvector(size_t s) : vec_(0), scalar_( scalar_type(s) )\n    { }\n    valvector(int s) : vec_(0), scalar_( scalar_type(s) )\n    { }\n    valvector(long int s) : vec_(0), scalar_( scalar_type(s) )\n    { }\n    valvector(double s) : vec_(0), scalar_( scalar_type(s) )\n    { }\n    valvector(long double s) : vec_(0), scalar_( scalar_type(s) )\n    { }\n    //\n    valvector(const valvector& other)\n    : vec_( other.vec_), scalar_( other.scalar_)\n    { }\n    valvector(valvector&& other)\n    {  vec_.swap( other.vec_ );\n        scalar_ = other.scalar_;\n    }\n    valvector(std::initializer_list<scalar_type> list) : vec_(0)\n    {  CPPAD_VALVECTOR_ASSERT_KNOWN(\n            list.size() != 0,\n            \"Cannot create a valvector with size zero.\"\n        )\n        std::initializer_list<scalar_type>::iterator itr;\n        if( list.size() == 1 )\n        {  itr     = list.begin();\n            scalar_ = *itr;\n        }\n        else\n        {  vec_.resize( list.size() );\n            itr = list.begin();\n            for(size_t i = 0; i < vec_.size(); ++i)\n            {  vec_[i] = *itr;\n                ++itr;\n            }\n        }\n    }\n    /*\n    ----------------------------------------------------------------------------\n    {xrst_begin valvector_resize}\n    {xrst_spell\n        valvectors\n    }\n\n    Resize a valvector\n    ##################\n    Sets the size of this valvector.\n\n    Prototype\n    *********\n    {xrst_literal ,\n        // BEGIN_RESIZE , // END_RESIZE\n    }\n\n    Use\n    ***\n    This size of a valvector directly after its\n    :ref:`constructor<valvector_ctor-name>` is always one.\n    This function must be used to create valvectors with other sizes.\n\n    n\n    *\n    The argument *n* must not be zero and specifies the number of elements\n    in the valvector.\n\n    Element Values\n    **************\n    Directly after this operation,\n    none of the element values are specified.\n\n    {xrst_toc_hidden\n        example/valvector/resize.cpp\n    }\n    Example\n    =======\n    The file :ref:`valvector_resize.cpp-name` is an example and test of\n    valvector resize.\n\n\n    {xrst_end valvector_resize}\n    ----------------------------------------------------------------------------\n    */\n    // BEGIN_RESIZE\n    void resize(size_t n)\n    // END_RESIZE\n    {  assert( n != 0 );\n        if( n == size() )\n            return;\n        if( n == 1 )\n            vec_.clear();\n        else\n            vec_.resize(n);\n    }\n    /*\n    ----------------------------------------------------------------------------\n    {xrst_begin valvector_assign}\n\n    The valvector Assignment Operator\n    #################################\n    Set the value of this valvector equal to another.\n\n    Prototype\n    *********\n    {xrst_literal ,\n        // BEGIN_ASSIGN_ONE , // END_ASSIGN_ONE\n        // BEGIN_ASSIGN_TWO , // END_ASSIGN_TWO\n    }\n\n    {xrst_toc_hidden\n        example/valvector/assign.cpp\n    }\n    Example\n    =======\n    The file :ref:`valvector_assign.cpp-name` is an example and test of\n    valvector assignment.\n\n    {xrst_end valvector_assign}\n    ----------------------------------------------------------------------------\n    */\n    // BEGIN_ASSIGN_ONE\n    valvector& operator=(const valvector& other)\n    // END_ASSIGN_ONE\n    {  vec_    = other.vec_;\n        scalar_ = other.scalar_;\n        return *this;\n    }\n    // BEGIN_ASSIGN_TWO\n    valvector& operator=(valvector&& other)\n    // END_ASSIGN_TWO\n    {  vec_.swap( other.vec_ );\n        scalar_ = other.scalar_;\n        return *this;\n    }\n    /*\n    ----------------------------------------------------------------------------\n    {xrst_begin valvector_size}\n\n    Size of a valvector\n    ###################\n    Returns the number or elements in this valvector.\n\n    Prototype\n    *********\n    {xrst_literal ,\n        // BEGIN_SIZE , // END_SIZE\n    }\n\n    {xrst_toc_hidden\n        example/valvector/size.cpp\n    }\n    Example\n    =======\n    The file :ref:`valvector_size.cpp-name` is an example and test of\n    valvector size.\n\n    {xrst_end valvector_size}\n    ----------------------------------------------------------------------------\n    */\n    //\n    // BEGIN_SIZE\n    size_t size(void) const\n    // END_SIZE\n    {  assert( vec_.size() != 1 );\n        if( vec_.size() == 0 )\n            return 1;\n        return vec_.size();\n    }\n    /*\n    ----------------------------------------------------------------------------\n    {xrst_begin valvector_sum}\n\n    Sum elements of a valvector\n    ###########################\n    Returns the sum of the elements in this valvector.\n\n    Prototype\n    *********\n    {xrst_literal ,\n        // BEGIN_SUM , // END_SUM\n    }\n\n    {xrst_toc_hidden\n        example/valvector/sum.cpp\n    }\n    Example\n    =======\n    The file :ref:`valvector_sum.cpp-name` is an example and test of\n    valvector sum.\n\n    {xrst_end valvector_sum}\n    ----------------------------------------------------------------------------\n    */\n    //\n    // BEGIN_SUM\n    scalar_type sum(void) const\n    // END_SUM\n    {  scalar_type result = 0.0;\n        for(size_t i = 0; i < size(); ++i)\n            result += (*this)[i];\n        return result;\n    }\n    /*\n    ----------------------------------------------------------------------------\n    {xrst_begin valvector_element}\n\n    Accessing Elements of a valvector\n    #################################\n    Returns a reference to the specified element of this valvector.\n\n    Prototype\n    *********\n    {xrst_literal ,\n        // BEGIN_ELEMENT , // END_ELEMENT\n        // BEGIN_CONST_ELEMENT , // END_CONST_ELEMENT\n    }\n\n    j\n    *\n    This is the index of the element we are accessing.\n\n    #. If the size this valvector is one, *j* can have any value\n       and the return is the single element in this valvector.\n    #. If the size of this valvector is not one, *j* must be less than\n       its size and the return is the j-th element in this valvector.\n\n    {xrst_toc_hidden\n        example/valvector/element.cpp\n    }\n    Example\n    =======\n    The file :ref:`valvector_element.cpp-name` is an example and test of\n    valvector element access.\n\n    {xrst_end valvector_element}\n    ----------------------------------------------------------------------------\n    */\n    // BEGIN_ELEMENT\n    scalar_type& operator[](size_t j)\n    // END_ELEMENT\n    {  CPPAD_VALVECTOR_ASSERT_KNOWN(\n            size() == 1 || j < size(),\n            \"size is not one and index is greater than or equal size\"\n        );\n        if( size() == 1 )\n            return scalar_;\n        return vec_[j];\n    }\n    // BEGIN_CONST_ELEMENT\n    const scalar_type& operator[](size_t j) const\n    // END_CONST_ELEMENT\n    {  CPPAD_VALVECTOR_ASSERT_KNOWN(\n            size() == 1 || j < size(),\n            \"size is not one and index is greater than or equal size\"\n        );\n        if( size() == 1 )\n            return scalar_;\n        return vec_[j];\n    }\n    /*\n    ----------------------------------------------------------------------------\n    {xrst_begin valvector_unary_op}\n\n    The valvector Numeric Unary Operators\n    #####################################\n    Returns the element-by-element result of the unary operators for\n    this valvector.\n\n    Prototype\n    *********\n    {xrst_literal ,\n        // BEGIN_PLUS , END_PLUS\n        // BEGIN_MINUS , END_MINUS\n    }\n\n    {xrst_toc_hidden\n        example/valvector/unary_op.cpp\n    }\n    Example\n    =======\n    The file :ref:`valvector_unary_op.cpp-name` is an example and test of the\n    valvector unary operators.\n\n    {xrst_end valvector_unary_op}\n    ----------------------------------------------------------------------------\n    */\n    // BEGIN_PLUS\n    valvector operator+(void) const\n    // END_PLUS\n    {  return *this; }\n    // BEGIN_MINUS\n    valvector operator-(void) const\n    // END_MINUS\n    {  valvector result;\n        result.resize( size() );\n        for(size_t i = 0; i < size(); ++i)\n            result[i] = - (*this)[i];\n        return result;\n    }\n    /*\n    ----------------------------------------------------------------------------\n    {xrst_begin valvector_binary_op}\n    {xrst_spell\n        valvectors\n    }\n\n    The valvector Numeric Binary Operators\n    ######################################\n    Returns a valvector that is the element-by-element result\n    of the numeric binary operators.\n\n    Syntax\n    ******\n    | *x* *op* *y*\n\n    op\n    **\n    The numeric binary operator *op* is\n    ``+`` (addition) ,\n    ``-`` (subtraction),\n    ``*`` (multiplication) , or\n    ``/`` (division) .\n\n    x, y\n    ****\n    Both *x* and *y* are  ``const`` valvectors.\n\n    {xrst_toc_hidden\n        example/valvector/binary_op.cpp\n    }\n    Example\n    =======\n    The file :ref:`valvector_binary_op.cpp-name` is an example and test of the\n    valvector binary operators.\n\n    {xrst_end valvector_binary_op}\n    ----------------------------------------------------------------------------\n    {xrst_begin valvector_compound_op}\n\n    The valvector Numeric Compound Assignment Operators\n    ###################################################\n    Computes the element-by-element result\n    of the numeric compound assignment operators.\n\n    Syntax\n    ******\n    | *y* *op* *x*\n\n    op\n    **\n    The compound operator *op* is\n    ``+=`` (compound addition) ,\n    ``-=`` (compound subtraction),\n    ``*=`` (compound multiplication) , or\n    ``/=`` (compound division) .\n\n    x\n    *\n    The operand *x* is a ``const`` valvector.\n\n    y\n    *\n    The operand and result *y* is a valvector.\n\n    Return\n    ******\n    The value returned by each of these operators is a reference to *y* .\n\n    {xrst_toc_hidden\n        example/valvector/compound_op.cpp\n    }\n    Example\n    =======\n    The file :ref:`valvector_compound_op.cpp-name` is an example and test of the\n    valvector compound assignment operators.\n\n    {xrst_end valvector_compound_op}\n    */\n    CPPAD_VALVECTOR_BINARY_NUMERIC_OP(+, +=)\n    CPPAD_VALVECTOR_BINARY_NUMERIC_OP(-, -=)\n    CPPAD_VALVECTOR_BINARY_NUMERIC_OP(*, *=)\n    CPPAD_VALVECTOR_BINARY_NUMERIC_OP(/, /=)\n    /*\n    ----------------------------------------------------------------------------\n    {xrst_begin valvector_compare_op}\n\n    The valvector Compare Operators\n    ###############################\n\n    Syntax\n    ******\n    | *y* *op* *x*\n\n    op\n    **\n\n    Equality Operators\n    ==================\n    == , !=\n\n    Ordered Operators\n    =================\n    < , <= , >= , >\n\n    x\n    *\n    The operand *x* is a ``const`` valvector.\n    If *op* is an equality operator,\n    *x* can have any size.\n    Otherwise it must be size one.\n\n    y\n    *\n    The operand *y* is a ``const`` valvector.\n    If *op* is an equality operator,\n    *y* can have any size.\n    Otherwise it must be size one.\n\n    Return\n    ******\n    The value returned by each of these operators is a bool\n\n    {xrst_toc_hidden\n        example/valvector/compare_op.cpp\n    }\n    Example\n    =======\n    The file :ref:`valvector_compare_op.cpp-name` is an example and test of the\n    valvector compare operators.\n\n    {xrst_end valvector_compare_op}\n    */\n    //\n    bool operator==(const valvector& other) const\n    {  bool result = true;\n        CPPAD_VALVECTOR_ASSERT_KNOWN(\n            size() == 1 || other.size() == 1 || size() == other.size() ,\n            \"size error using == operator\"\n        )\n        for(size_t i = 0; i < size(); ++i)\n            result &= (*this)[i] == other[i];\n        return result;\n    }\n    bool operator!=(const valvector& other) const\n    {  return ! (*this == other);\n    }\n    CPPAD_VALVECTOR_BINARY_ORDER_OP(<)\n    CPPAD_VALVECTOR_BINARY_ORDER_OP(<=)\n    CPPAD_VALVECTOR_BINARY_ORDER_OP(>=)\n    CPPAD_VALVECTOR_BINARY_ORDER_OP(>)\n};\n/*\n------------------------------------------------------------------------------\n{xrst_begin valvector_output}\n\nOutputting a valvector\n######################\n\nPrototype\n*********\n{xrst_literal ,\n    // BEGIN_OUTPUT , // END_OUTPUT\n}\n\n{xrst_toc_hidden\n    example/valvector/output.cpp\n}\nExample\n=======\nThe file :ref:`valvector_output.cpp-name` is an example and test of the\nvalvector output.\n\n{xrst_end valvector_output}\n*/\n// BEGIN_OUTPUT\ninline std::ostream& operator << (std::ostream& os, const valvector& x)\n// END_OUTPUT\n{  os << \"{\";\n    for(size_t i = 0; i < x.size(); ++i)\n    {  os << x[i];\n        if( i + 1 < x.size() )\n            os << \", \";\n    }\n    os << \"}\";\n    return os;\n}\n// ============================================================================\n// CppAD namespace\n// ============================================================================\nnamespace CppAD {\n    /*\n    --------------------------------------------------------------------------\n    {xrst_begin valvector_unary_math}\n    {xrst_spell\n        acosh\n        asinh\n        erfc\n        expm\n        signum\n    }\n\n    The valvector Unary Math Functions\n    ##################################\n\n    Syntax\n    ******\n    | *y* = ``CppAD`` :: *fun* ( *x* )\n\n    x\n    *\n    The argument *x* is a ``const`` valvector that is passed by reference.\n\n    y\n    *\n    The result *y* is a valvector with the same size as *x* .\n\n    fun\n    ***\n\n    Standard Math Functions\n    =======================\n    The function name *fun* can be any of the following:\n    ``acos``,\n    ``acosh``,\n    ``asin``,\n    ``asinh``,\n    ``atan``,\n    ``atanh``,\n    ``cos``,\n    ``cosh``,\n    ``erf``,\n    ``erfc``,\n    ``exp``,\n    ``expm1``,\n    ``fabs``,\n    ``log``,\n    ``log1p``,\n    ``log10``,\n    ``sin``,\n    ``sinh``,\n    ``sqrt``,\n    ``tan``,\n    ``tanh``\n\n    abs\n    ===\n    The function name *fun* can be ``abs`` ,\n    which acts the same as the standard function ``fabs`` .\n\n    sign\n    ====\n    The function name *fun* can be ``sign`` ,\n    which computes the sign (or signum) function.\n\n    {xrst_toc_hidden\n        example/valvector/unary_math.cpp\n    }\n    Example\n    =======\n    The file :ref:`valvector_unary_math.cpp-name` is an example and test of the\n    valvector unary math functions.\n\n    {xrst_end valvector_unary_math}\n    */\n    //\n    // standard math function\n    CPPAD_VALVECTOR_UNARY_STD_MATH(acos)\n    CPPAD_VALVECTOR_UNARY_STD_MATH(acosh)\n    CPPAD_VALVECTOR_UNARY_STD_MATH(asin)\n    CPPAD_VALVECTOR_UNARY_STD_MATH(asinh)\n    CPPAD_VALVECTOR_UNARY_STD_MATH(atan)\n    CPPAD_VALVECTOR_UNARY_STD_MATH(atanh)\n    CPPAD_VALVECTOR_UNARY_STD_MATH(cos)\n    CPPAD_VALVECTOR_UNARY_STD_MATH(cosh)\n    CPPAD_VALVECTOR_UNARY_STD_MATH(erf)\n    CPPAD_VALVECTOR_UNARY_STD_MATH(erfc)\n    CPPAD_VALVECTOR_UNARY_STD_MATH(exp)\n    CPPAD_VALVECTOR_UNARY_STD_MATH(expm1)\n    CPPAD_VALVECTOR_UNARY_STD_MATH(fabs)\n    CPPAD_VALVECTOR_UNARY_STD_MATH(log)\n    CPPAD_VALVECTOR_UNARY_STD_MATH(log1p)\n    CPPAD_VALVECTOR_UNARY_STD_MATH(log10)\n    CPPAD_VALVECTOR_UNARY_STD_MATH(sin)\n    CPPAD_VALVECTOR_UNARY_STD_MATH(sinh)\n    CPPAD_VALVECTOR_UNARY_STD_MATH(sqrt)\n    CPPAD_VALVECTOR_UNARY_STD_MATH(tan)\n    CPPAD_VALVECTOR_UNARY_STD_MATH(tanh)\n    //\n    // abs\n    inline valvector abs(const valvector& x)\n    {  return fabs(x); }\n    //\n    // sign\n    inline valvector sign(const valvector& x)\n    {  typedef valvector::scalar_type scalar_type;\n        //\n        valvector result;\n        result.resize( x.size() );\n        scalar_type zero = scalar_type(0);\n        for(size_t i = 0; i < x.size(); ++i)\n        {  if( x[i] < zero )\n                result[i] = scalar_type(-1);\n            if( x[i] == zero )\n                result[i] = zero;\n            if( x[i] > zero )\n                result[i] = scalar_type(1);\n        }\n        return result;\n    }\n    /*\n    --------------------------------------------------------------------------\n    {xrst_begin valvector_pow}\n\n    The valvector Pow Function\n    ##########################\n\n    Syntax\n    ******\n    | *z* = ``CppAD::pow`` ( *x* , *y* )\n\n    x\n    *\n    The argument *x* is a ``const`` valvector that is passed by reference.\n\n    y\n    *\n    The argument *y* is a ``const`` valvector that is passed by reference.\n    If the size of *x* is not one,\n    and the size of *y* is not one,\n    the size of *x* and *y* must be equal.\n\n    z\n    *\n    The result *z* is a valvector with size equal to the maximum of the\n    size of *x* and the size of *y* .\n\n    {xrst_toc_hidden\n        example/valvector/pow.cpp\n    }\n    Example\n    =======\n    The file :ref:`valvector_pow.cpp-name` is an example and test of the\n    valvector pow function.\n\n    {xrst_end valvector_pow}\n    */\n    inline valvector pow(const valvector& x, const valvector& y)\n    {  CPPAD_VALVECTOR_ASSERT_KNOWN(\n            x.size() == 1 || y.size() == 1 || x.size() == y.size() ,\n            \"size error using pow function\"\n        )\n        valvector  result;\n        result.resize( std::max( x.size(), y.size() ) );\n        for(size_t i = 0; i < x.size(); ++i)\n            result[i] = std::pow( x[i] , y[i] );\n        return result;\n    }\n    /*\n    --------------------------------------------------------------------------\n    {xrst_begin valvector_azmul}\n    {xrst_spell\n        valvectors\n    }\n\n    Absolute Zero Multiply of valvectors\n    ####################################\n\n    Syntax\n    ******\n    | *z* = ``CppAD::azmul`` ( *x* , *y* )\n\n    x\n    *\n    The argument *x* is a ``const`` valvector that is passed by reference.\n\n    y\n    *\n    The argument *y* is a ``const`` valvector that is passed by reference.\n    If the size of *x* is not one,\n    and the size of *y* is not one,\n    the size of *x* and *y* must be equal.\n\n    z\n    *\n    In the special where all the elements of *z* are zero,\n    the result *z* is a valvector with size one.\n    Otherwise, *z* is a valvector with size equal to the maximum of the\n    size of *x* and the size of *y* .\n\n    {xrst_toc_hidden\n        example/valvector/azmul.cpp\n    }\n    Example\n    =======\n    The file :ref:`valvector_azmul.cpp-name` is an example and test of the\n    valvector absolute zero multiply function.\n\n    {xrst_end valvector_azmul}\n    */\n    inline valvector azmul(const valvector& x, const valvector& y)\n    {  typedef valvector::scalar_type scalar_type;\n        //\n        CPPAD_VALVECTOR_ASSERT_KNOWN(\n            x.size() == 1 || y.size() == 1 || x.size() == y.size() ,\n            \"size error using azmul function\"\n        )\n        //\n        // special case\n        valvector vec_zero = valvector(0);\n        if( x == vec_zero )\n            return vec_zero;\n        //\n        // element-by-element\n        scalar_type scalar_zero(0);\n        valvector  result;\n        result.resize( std::max( x.size(), y.size() ) );\n        for(size_t i = 0; i < result.size(); ++i)\n        {  if( x[i] == scalar_zero )\n                result[i] = scalar_zero;\n             else\n                result[i] = x[i] * y[i];\n        }\n        return result;\n    }\n    /*\n    ------------------------------------------------------------------------\n    {xrst_begin valvector_condexp}\n    {xrst_spell\n        valvectors\n    }\n\n    The valvector Conditional Expressions\n    #####################################\n    Computes element-by-element :ref:`CondExp-name` values where\n    the arguments are valvectors.\n\n    Syntax\n    ******\n    *result* = ``CondExp`` *Rel* ( *left* , *right* , *if_true* , *if_false* )\n\n    Discussion\n    **********\n    For each valid index *i* , this computes the result\n\n    | |tab| ``if`` ( *left* [ *i* ] *op* *right* [ *i* ]  )\n    | |tab| |tab| *result* [ *i* ] = *if_true* [ *i* ]\n    | |tab| ``else``\n    | |tab| |tab| *result* [ *i* ] = *if_false* [ *i* ]\n\n    where the relational *Rel* and the operator *op*\n    have the following correspondence:\n\n    .. csv-table::\n\n        *Rel* , ``Lt`` , ``Le`` , ``Eq`` , ``Ge`` , ``Gt``\n        *op*  ,  <     , <=     , ==     , >=     , >\n\n    Arguments\n    *********\n    All of the argument are ``const`` valvectors.\n\n    result\n    ******\n    The result has size equal to the maximum of the size of\n    *left* , *right* , *if_true* and *if_false* .\n    The size of each argument must be one, or the same as the size of *result*.\n\n    {xrst_toc_hidden\n        example/valvector/condexp.cpp\n    }\n    Example\n    =======\n    The file :ref:`valvector_condexp.cpp-name` is an example and test of the\n    valvector conditional expressions.\n\n    {xrst_end valvector_condexp}\n    */\n    inline valvector CondExpOp(\n        enum CompareOp         cop          ,\n        const valvector&       left         ,\n        const valvector&       right        ,\n        const valvector&       if_true      ,\n        const valvector&       if_false )\n    {  //\n        // result_size\n        size_t result_size = std::max(left.size(), right.size());\n        result_size        = std::max(result_size, if_true.size());\n        result_size        = std::max(result_size, if_false.size());\n        //\n        // size_ok\n        bool size_ok  = true;\n        size_ok &= left.size()     == 1 || left.size()     == result_size;\n        size_ok &= right.size()    == 1 || right.size()    == result_size;\n        size_ok &= if_true.size()  == 1 || if_true.size()  == result_size;\n        size_ok &= if_false.size() == 1 || if_false.size() == result_size;\n        CPPAD_VALVECTOR_ASSERT_KNOWN(\n            size_ok,\n            \"argument sizes do not agree in conditional expression\"\n        );\n        //\n        // result\n        valvector result;\n        result.resize(result_size);\n        //\n        for(size_t i = 0; i < result_size; ++i)\n        {  switch( cop )\n            {\n                case CompareLt:\n                if( left[i] < right[i] )\n                    result[i] = if_true[i];\n                else\n                    result[i] = if_false[i];;\n                break;\n\n                case CompareLe:\n                if( left[i] <= right[i] )\n                    result[i] = if_true[i];\n                else\n                    result[i] = if_false[i];;\n                break;\n\n                case CompareEq:\n                if( left[i] == right[i] )\n                    result[i] = if_true[i];\n                else\n                    result[i] = if_false[i];;\n                break;\n\n                case CompareGe:\n                if( left[i] >= right[i] )\n                    result[i] = if_true[i];\n                else\n                    result[i] = if_false[i];;\n                break;\n\n                case CompareGt:\n                if( left[i] > right[i] )\n                    result[i] = if_true[i];\n                else\n                    result[i] = if_false[i];;\n                break;\n\n                default:\n                assert(false);\n                result[i] = if_true[i];\n            }\n        }\n        // result\n        return result;\n    }\n    CPPAD_COND_EXP_REL(valvector)\n}\n// ===========================================================================\n/*\n{xrst_begin valvector_base_require}\n{xrst_spell\n    geq\n}\n\nThe valvector Implementation of CppAD Base Type Requirements\n############################################################\n\nOutput Operator\n***************\nThe :ref:`base_require@Output Operator` requirement is satisfied by\n:ref:`valvector_output-name` .\n\n\nConstructors\n************\nThe :ref:`base_member@Constructors` requirements are satisfied by\n:ref:`valvector_ctor-name` .\n\nUnary Operators\n***************\nThe :ref:`base_member@Unary Operators` requirements are satisfied by\n:ref:`valvector_unary_op-name` .\n\nAssignment Operators\n********************\nThe :ref:`base_member@Assignment Operators` requirements are satisfied by\n:ref:`valvector_assign-name` and :ref:`valvector_compound_op-name` .\n\nBinary Operators\n****************\nThe :ref:`base_member@Binary Operators` requirements are satisfied by\n:ref:`valvector_binary_op-name` .\n\nBool Operators\n**************\nThe :ref:`base_member@Bool Operators` requirements are satisfied by\n:ref:`valvector_compare_op-name` .\n\nConditional Expressions\n***********************\nThe :ref:`base_cond_exp-name` requirements are satisfied by\n:ref:`valvector_condexp-name` .\n\nStandard Math\n*************\nThe :ref:`base_std_math-name` requirements are satisfied by\n:ref:`valvector_unary_math-name` and :ref:`valvector_pow-name` .\n\nazmul\n*****\nThe :ref:`base_require@Absolute Zero, azmul` requirement is satisfied by\n:ref:`valvector_azmul-name` .\n\nFeatures Implemented Here\n*************************\n\nInteger\n=======\nThe :ref:`base_require@Integer` requirement is satisfied by:\n{xrst_code hpp} */\nnamespace CppAD {\n    inline int Integer(const valvector& x) { return int( x[0] ); }\n}\n/* {xrst_code}\n\nnumeric_limits\n==============\nThe :ref:`base_limits-name` requirement is satisfied by:\n{xrst_code hpp} */\nnamespace CppAD {\n    CPPAD_NUMERIC_LIMITS(valvector::scalar_type, valvector)\n}\n/* {xrst_code}\n\nto_string\n=========\nThe :ref:`base_to_string-name` requirement is satisfied by:\n{xrst_code hpp} */\nnamespace CppAD {\n    CPPAD_TO_STRING(valvector)\n}\n/* {xrst_code}\n\nEqualOpSeq\n==========\nThe :ref:`base_identical@EqualOpSeq` requirement is satisfied by:\n{xrst_code hpp} */\nnamespace CppAD {\n    inline bool EqualOpSeq(const valvector& left, const valvector& right)\n    {  return left == right; }\n}\n/* {xrst_code}\n\nIdentical\n=========\n{xrst_code hpp} */\nnamespace CppAD {\n    inline bool IdenticalCon(const valvector& x)  {  return true; }\n    inline bool IdenticalZero(const valvector& x) {  return x == valvector(0); }\n    inline bool IdenticalOne(const valvector& x)  {  return x == valvector(1); }\n    inline bool IdenticalEqualCon(const valvector& x, const valvector& y)\n    {  return x == y; }\n}\n/* {xrst_code}\n\nNot Ordered\n===========\nThe :ref:`base_ordered@Not Ordered` requirement is satisfied by:\n{xrst_literal ,\n    // BEGIN_NOT_AVAILABLE , // END_NOT_AVAILABLE\n}\n{xrst_code hpp} */\nnamespace CppAD {\n    CPPAD_VALVECTOR_NOT_AVAILABLE(GreaterThanZero)\n    CPPAD_VALVECTOR_NOT_AVAILABLE(GreaterThanOrZero)\n    CPPAD_VALVECTOR_NOT_AVAILABLE(LessThanZero)\n    CPPAD_VALVECTOR_NOT_AVAILABLE(LessThanOrZero)\n    //\n    // abs_geq\n    inline bool abs_geq(const valvector& x, const valvector& y)\n    {  CPPAD_VALVECTOR_ASSERT_KNOWN(\n            x.size() == 1 || y.size() == 1 || x.size() == y.size() ,\n            \"size error in abs_geq functions\"\n        )\n        size_t max_size = std::max( x.size(), y.size() );\n        valvector::scalar_type abs_x(0), abs_y(0);\n        for(size_t i = 0; i < max_size; ++i)\n        {  abs_x += fabs( x[i] );\n            abs_y += fabs( y[i] );\n        }\n        return abs_x >= abs_y;\n    }\n}\n/* {xrst_code}\n\n{xrst_toc_hidden\n    example/valvector/base_require.cpp\n}\nExample\n=======\nThe file :ref:`valvector_base_require.cpp-name` is an example and test of the\nvalvector :ref:`valvector_base_require@Features Implemented Here` .\n\n\n{xrst_end valvector_base_require}\n*/\n\n# undef CPPAD_VALVECTOR_ASSERT_KNOWN\n# undef CPPAD_VALVECTOR_UNARY_STD_MATH\n# undef CPPAD_VALVECTOR_BINARY_ORDER_OP\n# undef CPPAD_VALVECTOR_BINARY_NUMERIC_OP\n# undef CPPAD_VALVECTOR_NOT_AVAILABLE\n\n\n# endif\n"
  },
  {
    "path": "include/cppad/example/valvector/split_join.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_VALVECTOR_SPLIT_JOIN_HPP\n# define CPPAD_EXAMPLE_VALVECTOR_SPLIT_JOIN_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2024 Bradley M. Bell\n/*\n-------------------------------------------------------------------------------\n{xrst_begin valvector_ad_split}\n{xrst_spell\n    asplit\n}\n\nSplit A AD valvector\n####################\nSplit one AD<valvector> into a vector of AD<valvector> each with size one.\n\nSyntax\n******\n| valvector_ad_split *asplit*\n| *asplit( *ax* , *ay_vec* )\n\nm\n*\nWe use *m* to denote *ay_vec* .size()\n\nax\n**\nThis CppAD::AD<valvector> is ``const`` and passed by reference.\nThe size *ax*.size()  must be equal to one or *m*\n\nay_vec\n******\nThis is a :ref:`SimpleVector-name` with elements of type CppAD::AD<valvector>\nand is passed by reference.\nThe size of *ay_vec* is not changed.\nUpon return, for *i* = 0 , ... , *m* - 1 ,\nthe size *ay* [ *i* ].size() is one and::\n\n    ay[i][0] = ax[i]\n\n{xrst_toc_hidden\n    example/valvector/ad_split.cpp\n}\nExample\n*******\nThe file :ref:`valvector_ad_split.cpp-name` is an example and test\nof this operation.\n\n{xrst_end valvector_ad_split}\n-------------------------------------------------------------------------------\n{xrst_begin valvector_ad_join}\n{xrst_spell\n    ajoin\n    valvectors\n}\n\nJoin a Vector of AD valvectors\n##############################\nJoin a vector of AD<valvector>, each with size one, into one AD<valvector>.\n\nSyntax\n******\n| valvector_ad_join *ajoin*\n| *ajoin( *ax_vec* , *ay* )\n\n\nm\n*\nWe use *m* to denote *ax_vec* .size() .\n\nax_vec\n******\nThis is a :ref:`SimpleVector-name` with elements of type CppAD::AD<valvector> .\nIt is ``const`` and is passed by reference.\nFor *i* = 0 , ... , *m* - 1 ,\nthe size *ax* [ *i* ].size() is one.\n\nay\n**\nThis CppAD::AD<valvector> is passed by reference and its input value\ndoes not matter.\nUpon return, its size in *m* and\nfor *i* = 0 , ... , *m* - 1 ::\n\n    ay[i] = ax_vec[i][0]\n\n\n{xrst_toc_hidden\n    example/valvector/ad_join.cpp\n}\nExample\n*******\nThe file :ref:`valvector_ad_join.cpp-name` is an example and test\nof this operation.\n\n{xrst_end valvector_ad_join}\n-------------------------------------------------------------------------------\n*/\n# include <cppad/example/valvector/class.hpp>\n# include <cppad/cppad.hpp>\n//\n// valvector_split_join\n// split and join are in same atomic function so that in AD version of reverse\n// split can call join and join can call split.\nclass valvector_split_join : public CppAD::atomic_four<valvector> {\npublic:\n    //\n    // ctor\n    valvector_split_join(const std::string& name) :\n    CppAD::atomic_four<valvector>(name)\n    { }\n    //\n    // is_split\n    static bool is_split(size_t call_id)\n    {   return call_id == 1; }\n    //\n    // is_join\n    static bool is_join(size_t call_id)\n    {   return call_id == 2; }\nprivate:\n    //\n    // ad_valvector\n    typedef CppAD::AD<valvector> ad_valvector;\n    //\n    // ------------------------------------------------------------------------\n    // for_type\n    bool for_type(\n        size_t                                     call_id     ,\n        const CppAD::vector<CppAD::ad_type_enum>&  type_x      ,\n        CppAD::vector<CppAD::ad_type_enum>&        type_y      ) override\n    {\n        if( is_split(call_id) )\n        {   //\n            assert( type_x.size() == 1 ); // n\n            //\n            // type_y\n            size_t m = type_y.size();\n            for(size_t i = 0; i < m; ++i)\n                type_y[i] = type_x[0];\n        }\n        else\n        {   assert( is_join(call_id) );\n            //\n            assert( type_y.size() == 1 ); // m\n            //\n            // type_y\n            size_t n  = type_x.size();\n            type_y[0] = CppAD::identical_zero_enum;\n            for(size_t j = 0; j < n; ++j)\n                type_y[0] = std::max( type_y[0], type_x[j] );\n        }\n        return true;\n    }\n    // ------------------------------------------------------------------------\n    // forward\n    bool forward(\n        size_t                              call_id      ,\n        const CppAD::vector<bool>&          select_y     ,\n        size_t                              order_low    ,\n        size_t                              order_up     ,\n        const CppAD::vector<valvector>&     taylor_x     ,\n        CppAD::vector<valvector>&           taylor_y     ) override\n    {   //\n        if( is_split(call_id) )\n        {   //\n            // q, m\n            size_t q = order_up + 1;\n            size_t m = taylor_y.size() / q;\n            //\n# ifndef NDEBUG\n            size_t n = taylor_x.size() / q;\n            assert( n == 1 );\n            assert( m == select_y.size() );\n            for(size_t k = 0; k < q; ++k)\n                assert( taylor_x[k].size() == 1 || taylor_x[k].size() == m );\n# endif\n            //\n            // taylor_y\n            for(size_t i = 0; i < m; ++i) if( select_y[i] )\n            {   for(size_t k = order_low; k < q; ++k)\n                {   //\n                    // taylor_y[i * q + k]\n                    taylor_y[i * q + k].resize(1);\n                    taylor_y[i * q + k][0] = taylor_x[k][i];\n                }\n            }\n        }\n        else\n        {   assert( is_join(call_id) );\n            //\n            // q, n\n            size_t q = order_up + 1;\n            size_t n = taylor_x.size() / q;\n            //\n# ifndef NDEBUG\n            size_t m = taylor_y.size() / q;\n            assert( m == 1 );\n            assert( m == select_y.size() );\n            for(size_t k = 0; k < q; ++k)\n                assert( taylor_x[k].size() == 1 );\n# endif\n            //\n            // taylor_y\n            if( select_y[0] )\n            {   for(size_t k = order_low; k < q; ++k)\n                {   //\n                    // taylor_y[k]\n                    taylor_y[k].resize(n);\n                    for(size_t j = 0; j < n; ++j)\n                        taylor_y[k][j] = taylor_x[j * q + k][0];\n                }\n            }\n            //\n        }\n        return true;\n    }\n    // ------------------------------------------------------------------------\n    // forward\n    bool forward(\n        size_t                                 call_id      ,\n        const CppAD::vector<bool>&             select_y     ,\n        size_t                                 order_low    ,\n        size_t                                 order_up     ,\n        const CppAD::vector<ad_valvector>&     ataylor_x    ,\n        CppAD::vector<ad_valvector>&           ataylor_y    ) override\n    {   //\n        if( is_split(call_id) )\n        {   //\n            // q, m\n            size_t q = order_up + 1;\n            size_t m = ataylor_y.size() / q;\n            //\n# ifndef NDEBUG\n            size_t n = ataylor_x.size() / q;\n            assert( n == 1 );\n            assert( m == select_y.size() );\n# endif\n            //\n            // ax_k, ay_k\n            CppAD::vector<ad_valvector> ax_k(1);\n            CppAD::vector<ad_valvector> ay_k(m);\n            //\n            // ataylor_y\n            for(size_t k = order_low; k < q; ++k)\n            {   ax_k[0] = ataylor_x[k];\n                (*this)(call_id, ax_k, ay_k);\n                {   for(size_t i = 0; i < m; ++i)\n                        ataylor_y[i * q + k] = ay_k[i];\n                }\n            }\n        }\n        else\n        {   assert( is_join(call_id) );\n            //\n            // q, n\n            size_t q = order_up + 1;\n            size_t n = ataylor_x.size() / q;\n            //\n# ifndef NDEBUG\n            size_t m = ataylor_y.size() / q;\n            assert( m == 1 );\n            assert( m == select_y.size() );\n# endif\n            if( select_y[0] )\n            {   //\n                // ax_k, ay_k\n                CppAD::vector<ad_valvector> ax_k(n);\n                CppAD::vector<ad_valvector> ay_k(1);\n                //\n                // ataylor_y\n                for(size_t k = order_low; k < q; ++k)\n                {   for(size_t j = 0; j < n; ++j)\n                        ax_k[j] = ataylor_x[j * q + k];\n                    (*this)(call_id, ax_k, ay_k);\n                    ataylor_y[k] = ay_k[0];\n                }\n            }\n        }\n        return true;\n    }\n    // ------------------------------------------------------------------------\n    // reverse\n    bool reverse(\n        size_t                              call_id      ,\n        const CppAD::vector<bool>&          select_x     ,\n        size_t                              order_up     ,\n        const CppAD::vector<valvector>&     taylor_x     ,\n        const CppAD::vector<valvector>&     taylor_y     ,\n        CppAD::vector<valvector>&           partial_x    ,\n        const CppAD::vector<valvector>&     partial_y    ) override\n    {   //\n        if( is_split(call_id) )\n        {   //\n            // q, m\n            size_t q = order_up + 1;\n            size_t m = taylor_y.size() / q;\n            //\n# ifndef NDEBUG\n            size_t n = taylor_x.size() / q;\n            assert( n == 1 );\n            assert( 1 == select_x.size() );\n# endif\n            if( ! select_x[0] )\n                return true;\n            //\n            // partial_x\n            for(size_t k = 0; k < q; ++k)\n            {   partial_x[k].resize(m);\n                for(size_t i = 0; i < m; ++i)\n                {   //\n                    // partial_x[k][i]\n                    assert( taylor_y[i * q + k].size() == 1 );\n                    partial_x[k][i] = partial_y[i * q + k][0];\n                }\n            }\n        }\n        else\n        {   assert( is_join(call_id) );\n            //\n            // q, m\n            size_t q = order_up + 1;\n            size_t n = taylor_x.size() / q;\n            //\n# ifndef NDEBUG\n            size_t m = taylor_y.size() / q;\n            assert( m == 1 );\n            assert( n == select_x.size() );\n# endif\n            //\n            // partial_x\n            for(size_t k = 0; k < q; ++k)\n            {   assert( taylor_y[k].size() == n );\n                for(size_t j = 0; j < n; ++j)\n                {   partial_x[j * q + k].resize(1);\n                    partial_x[j * q + k][0] = partial_y[k][j];\n                }\n            }\n        }\n        return true;\n    }\n    // ------------------------------------------------------------------------\n    // reverse\n    bool reverse(\n        size_t                                 call_id      ,\n        const CppAD::vector<bool>&             select_x     ,\n        size_t                                 order_up     ,\n        const CppAD::vector<ad_valvector>&     ataylor_x    ,\n        const CppAD::vector<ad_valvector>&     ataylor_y    ,\n        CppAD::vector<ad_valvector>&           apartial_x   ,\n        const CppAD::vector<ad_valvector>&     apartial_y   ) override\n    {   //\n        if( is_split(call_id) )\n        {   //\n            // q, m\n            size_t q = order_up + 1;\n            size_t m = ataylor_y.size() / q;\n            //\n# ifndef NDEBUG\n            size_t n = ataylor_x.size() / q;\n            assert( n == 1 );\n            assert( 1 == select_x.size() );\n# endif\n            if( ! select_x[0] )\n                return true;\n            //\n            // ay_k, ax_k\n            CppAD::vector<ad_valvector> ay_k(m);\n            CppAD::vector<ad_valvector> ax_k(1);\n            //\n            // join_call_id\n            size_t join_call_id = 2;\n            assert( is_join(join_call_id) );\n            //\n            // apartial_x\n            for(size_t k = 0; k < q; ++k)\n            {   for(size_t i = 0; i < m; ++i)\n                    ay_k[i] = apartial_y[i * q + k];\n                // split calls join here\n                (*this)(join_call_id, ay_k, ax_k);\n                apartial_x[k] = ax_k[0];\n            }\n        }\n        else\n        {   assert( is_join(call_id) );\n            //\n            // q, m\n            size_t q = order_up + 1;\n            size_t n = ataylor_x.size() / q;\n            //\n# ifndef NDEBUG\n            size_t m = ataylor_y.size() / q;\n            assert( m == 1 );\n            assert( n == select_x.size() );\n# endif\n            //\n            // ay_k, ax_k\n            CppAD::vector<ad_valvector> ay_k(1);\n            CppAD::vector<ad_valvector> ax_k(n);\n            //\n            // split_call_id\n            size_t split_call_id = 1;\n            assert( is_split(split_call_id) );\n            //\n            // apartial_x\n            for(size_t k = 0; k < q; ++k)\n            {   ay_k[0] = apartial_y[k];\n                // Join calls split here\n                (*this)(split_call_id, ay_k, ax_k);\n                for(size_t j = 0; j < n; ++j)\n                    apartial_x[j * q + k] = ax_k[j];\n            }\n        }\n        return true;\n    }\n    // ------------------------------------------------------------------------\n    // jac_sparsity\n    bool jac_sparsity(\n        size_t                                         call_id      ,\n        bool                                           dependency   ,\n        const CppAD::vector<bool>&                     ident_zero_x ,\n        const CppAD::vector<bool>&                     select_x     ,\n        const CppAD::vector<bool>&                     select_y     ,\n        CppAD::sparse_rc< CppAD::vector<size_t> >&     pattern_out  ) override\n    {   //\n        if( is_split(call_id) )\n        {   //\n            // m, n\n            size_t m = select_y.size();\n            size_t n = select_x.size();\n            //\n            assert( n == 1 );\n            //\n            // nnz\n            size_t nnz = 0;\n            if( select_x[0] )\n            {   for(size_t i = 0; i < m; ++i)\n                {   if( select_y[i] )\n                        ++nnz;\n                }\n            }\n            //\n            // pattern_out\n            pattern_out.resize(m, n, nnz);\n            size_t k = 0;\n            if( select_x[0] )\n            {   for(size_t i = 0; i < m; ++i)\n                {   if( select_y[i] )\n                        pattern_out.set(k++, i, 0);\n                }\n            }\n        }\n        else\n        {   assert( is_join(call_id) );\n            //\n            // m, n\n            size_t m = select_y.size();\n            size_t n = select_x.size();\n            //\n            assert( m == 1 );\n            //\n            // nnz\n            size_t nnz = 0;\n            if( select_y[0] )\n            {   for(size_t j = 0; j < n; ++j)\n                {   if( select_x[j] )\n                        ++nnz;\n                }\n            }\n            //\n            // pattern_out\n            pattern_out.resize(m, n, nnz);\n            size_t k = 0;\n            if( select_y[0] )\n            {   for(size_t j = 0; j < n; ++j)\n                {   if( select_x[j] )\n                        pattern_out.set(k++, 0, j);\n                }\n            }\n        }\n        return true;\n    }\n    // ------------------------------------------------------------------------\n    // hes_sparsity\n    bool hes_sparsity(\n        size_t                                         call_id      ,\n        const CppAD::vector<bool>&                     ident_zero_x ,\n        const CppAD::vector<bool>&                     select_x     ,\n        const CppAD::vector<bool>&                     select_y     ,\n        CppAD::sparse_rc< CppAD::vector<size_t> >&     pattern_out  ) override\n    {   //\n        if( is_split(call_id) )\n        {   //\n            // n\n            size_t n = select_x.size();\n            //\n            assert( n == 1 );\n            assert( n == select_x.size() );\n            //\n            // pattern_out\n            size_t nnz = 0;\n            pattern_out.resize(n, n, nnz);\n        }\n        else\n        {   assert( is_join(call_id) );\n            //\n            // n\n            size_t n = select_x.size();\n            //\n            assert( n == select_x.size() );\n            //\n            // pattern_out\n            size_t nnz = 0;\n            pattern_out.resize(n, n, nnz);\n        }\n        return true;\n    }\n    // ------------------------------------------------------------------------\n    // rev_depend\n    bool rev_depend(\n        size_t                                         call_id      ,\n        const CppAD::vector<bool>&                     ident_zero_x ,\n        CppAD::vector<bool>&                           depend_x     ,\n        const CppAD::vector<bool>&                     depend_y     ) override\n    {   //\n        if( is_split(call_id) )\n        {   //\n            // m\n            size_t m = depend_y.size();\n            //\n# ifndef NDEBUG\n            size_t n = depend_x.size();\n            assert( n == 1 );\n# endif\n            //\n            // depend_x\n            depend_x[0] = false;\n            for(size_t i = 0; i < m; ++i)\n                depend_x[0] |= depend_y[i];\n        }\n        else\n        {   assert( is_join(call_id) );\n            //\n            // n\n            size_t n = depend_x.size();\n            //\n# ifndef NDEBUG\n            size_t m = depend_y.size();\n            assert( m == 1 );\n# endif\n            //\n            // depend_x\n            for(size_t j = 0; j < n; ++j)\n                depend_x[j] = depend_y[0];\n        }\n        return true;\n    }\n};\n// ---------------------------------------------------------------------------\n// valvector_ad_split\nclass valvector_ad_split {\nprivate:\n    typedef CppAD::AD<valvector> ad_valvector;\n    valvector_split_join         atomic_fun_;\npublic:\n    valvector_ad_split(void) : atomic_fun_(\"valvector_split_join\")\n    { }\n    template <class ADVector>\n    void operator()(const ad_valvector&  ax, ADVector& ay)\n    {\n        size_t call_id = 1;\n        assert( atomic_fun_.is_split(call_id) );\n        ADVector ax_vec(1);\n        ax_vec[0] = ax;\n        atomic_fun_(call_id, ax_vec, ay);\n        return;\n    }\n};\n// ---------------------------------------------------------------------------\n// valvector_ad_join\nclass valvector_ad_join {\nprivate:\n    typedef CppAD::AD<valvector> ad_valvector;\n    valvector_split_join         atomic_fun_;\npublic:\n    valvector_ad_join(void) : atomic_fun_(\"valvector_split_join\")\n    { }\n    template <class ADVector>\n    void operator()(const ADVector& ax, ad_valvector&  ay)\n    {\n        size_t call_id = 2;\n        ADVector ay_vec(1);\n        assert( atomic_fun_.is_join(call_id) );\n        atomic_fun_(call_id, ax, ay_vec);\n        ay = ay_vec[0];\n        return;\n    }\n};\n# endif\n"
  },
  {
    "path": "include/cppad/example/valvector/sum.hpp",
    "content": "# ifndef CPPAD_EXAMPLE_VALVECTOR_SUM_HPP\n# define CPPAD_EXAMPLE_VALVECTOR_SUM_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2024 Bradley M. Bell\n/*\n-------------------------------------------------------------------------------\n{xrst_begin valvector_ad_sum}\n{xrst_spell\n    asum\n}\n\nSum The Elements of and AD valvector\n####################################\nSum the elements of an AD<valvector> and return the result as one AD<valvector>\nwith size one.\n\nSyntax\n******\n| valvector_ad_sum *asum*\n| *asum* ( *ax* , *ay* )\n\nax\n**\nThis CppAD::AD<valvector> is ``const`` and passed by reference.\n\nay\n**\nThis CppAD::AD<valvector> is passed by reference.\nIts input value does not matter.\nUpon return, it has size one and its element is the sum of the elements\nin *ax* .\n\n{xrst_toc_hidden\n    example/valvector/ad_sum.cpp\n}\nExample\n*******\nThe file :ref:`valvector_ad_sum.cpp-name` is an example and test\nof this operation.\n\n{xrst_end valvector_ad_sum}\n*/\n# include <cppad/example/valvector/class.hpp>\n# include <cppad/cppad.hpp>\n//\n// valvector_atom_sum\n// split and join are in same atomic function so that in AD version of reverse\n// split can call join and join can call split.\nclass valvector_atom_sum : public CppAD::atomic_four<valvector> {\npublic:\n    //\n    // ctor\n    valvector_atom_sum(const std::string& name) :\n    CppAD::atomic_four<valvector>(name)\n    { }\nprivate:\n    //\n    // ad_valvector\n    typedef CppAD::AD<valvector> ad_valvector;\n    //\n    // scalar_type\n    typedef valvector::scalar_type scalar_type;\n    //\n    // ------------------------------------------------------------------------\n    // for_type\n    bool for_type(\n        size_t                                     call_id     ,\n        const CppAD::vector<CppAD::ad_type_enum>&  type_x      ,\n        CppAD::vector<CppAD::ad_type_enum>&        type_y      ) override\n    {   //\n        assert( call_id == 0 );\n        assert( type_x.size() == 1 );\n        assert( type_y.size() == 1 );\n        //\n        type_y[0] = type_x[0];\n        //\n        return true;\n    }\n    // ------------------------------------------------------------------------\n    // forward\n    bool forward(\n        size_t                              call_id      ,\n        const CppAD::vector<bool>&          select_y     ,\n        size_t                              order_low    ,\n        size_t                              order_up     ,\n        const CppAD::vector<valvector>&     taylor_x     ,\n        CppAD::vector<valvector>&           taylor_y     ) override\n    {   //\n        assert( call_id == 0 );\n        assert( select_y.size() == 1 );\n        //\n        // q\n        size_t q = order_up + 1;\n        assert( taylor_x.size() == q);\n        assert( taylor_y.size() == q);\n        //\n        // taylor_y\n        for(size_t k = order_low; k < q; ++k)\n        {   //\n            taylor_y[k].resize(1);\n            taylor_y[k][0] = taylor_x[k].sum();\n        }\n        return true;\n    }\n    // ------------------------------------------------------------------------\n    // forward\n    bool forward(\n        size_t                                 call_id      ,\n        const CppAD::vector<bool>&             select_y     ,\n        size_t                                 order_low    ,\n        size_t                                 order_up     ,\n        const CppAD::vector<ad_valvector>&     ataylor_x    ,\n        CppAD::vector<ad_valvector>&           ataylor_y    ) override\n    {   //\n        assert( call_id == 0 );\n        assert( select_y.size() == 1 );\n        //\n        // q\n        size_t q = order_up + 1;\n        assert( ataylor_x.size() == q);\n        assert( ataylor_y.size() == q);\n        //\n        //\n        // ax_k, ay_k\n        CppAD::vector<ad_valvector> ax_k(1);\n        CppAD::vector<ad_valvector> ay_k(1);\n        //\n        // ataylor_y\n        for(size_t k = 0; k < q; ++k)\n        {   ax_k[0] = ataylor_x[k];\n            (*this)(ax_k, ay_k);\n            ataylor_y[k] = ay_k[0];\n        }\n        //\n        return true;\n    }\n    // ------------------------------------------------------------------------\n    // reverse\n    bool reverse(\n        size_t                              call_id      ,\n        const CppAD::vector<bool>&          select_x     ,\n        size_t                              order_up     ,\n        const CppAD::vector<valvector>&     taylor_x     ,\n        const CppAD::vector<valvector>&     taylor_y     ,\n        CppAD::vector<valvector>&           partial_x    ,\n        const CppAD::vector<valvector>&     partial_y    ) override\n    {   //\n        assert( call_id == 0  );\n        assert( select_x.size() == 1 );\n        //\n        // q\n        size_t q = order_up + 1;\n        assert( taylor_x.size() == q );\n        assert( taylor_y.size() == q );\n        //\n        if( ! select_x[0] )\n            return true;\n        //\n        // partial_x\n        for(size_t k = 0; k < q; ++k)\n        {   assert( partial_y[k].size() == 1 );\n            partial_x[k] = partial_y[k];\n        }\n        //\n        return true;\n    }\n    // ------------------------------------------------------------------------\n    // reverse\n    bool reverse(\n        size_t                                 call_id      ,\n        const CppAD::vector<bool>&             select_x     ,\n        size_t                                 order_up     ,\n        const CppAD::vector<ad_valvector>&     ataylor_x    ,\n        const CppAD::vector<ad_valvector>&     ataylor_y    ,\n        CppAD::vector<ad_valvector>&           apartial_x   ,\n        const CppAD::vector<ad_valvector>&     apartial_y   ) override\n    {   //\n        assert( call_id == 0  );\n        assert( select_x.size() == 1 );\n        //\n        // q\n        size_t q = order_up + 1;\n        assert( ataylor_x.size() == q );\n        assert( ataylor_y.size() == q );\n        //\n        if( ! select_x[0] )\n            return true;\n        //\n        // apartial_x\n        for(size_t k = 0; k < q; ++k)\n            apartial_x[k] = apartial_y[k];\n        //\n        return true;\n    }\n    // ------------------------------------------------------------------------\n    // jac_sparsity\n    bool jac_sparsity(\n        size_t                                         call_id      ,\n        bool                                           dependency   ,\n        const CppAD::vector<bool>&                     ident_zero_x ,\n        const CppAD::vector<bool>&                     select_x     ,\n        const CppAD::vector<bool>&                     select_y     ,\n        CppAD::sparse_rc< CppAD::vector<size_t> >&     pattern_out  ) override\n    {   //\n        assert( call_id == 0 );\n        assert( select_x.size() == 1 );\n        assert( select_y.size() == 1 );\n        //\n        // m, n\n        size_t m = select_y.size();\n        size_t n = select_x.size();\n        //\n        // nnz\n        size_t nnz = 0;\n        if( select_x[0] && select_y[0] )\n            ++nnz;\n        //\n        // pattern_out\n        pattern_out.resize(m, n, nnz);\n        if( select_x[0] && select_y[0] )\n            pattern_out.set(0, 0, 0);\n        //\n        return true;\n    }\n    // ------------------------------------------------------------------------\n    // hes_sparsity\n    bool hes_sparsity(\n        size_t                                         call_id      ,\n        const CppAD::vector<bool>&                     ident_zero_x ,\n        const CppAD::vector<bool>&                     select_x     ,\n        const CppAD::vector<bool>&                     select_y     ,\n        CppAD::sparse_rc< CppAD::vector<size_t> >&     pattern_out  ) override\n    {   //\n        assert( call_id == 0 );\n        assert( select_x.size() == 1 );\n        assert( select_y.size() == 1 );\n        //\n        size_t n = select_x.size();\n        //\n        // pattern_out\n        size_t nnz = 0;\n        pattern_out.resize(n, n, nnz);\n        //\n        return true;\n    }\n    // ------------------------------------------------------------------------\n    // rev_depend\n    bool rev_depend(\n        size_t                                         call_id      ,\n        const CppAD::vector<bool>&                     ident_zero_x ,\n        CppAD::vector<bool>&                           depend_x     ,\n        const CppAD::vector<bool>&                     depend_y     ) override\n    {   //\n        assert( call_id == 0 );\n        assert( depend_x.size() == 1 );\n        assert( depend_y.size() == 1 );\n        //\n        depend_x[0] = depend_y[0];\n        //\n        return true;\n    }\n};\n// ---------------------------------------------------------------------------\n// valvector_ad_sum\nclass valvector_ad_sum {\nprivate:\n    typedef CppAD::AD<valvector> ad_valvector;\n    valvector_atom_sum           atomic_fun_;\npublic:\n    valvector_ad_sum(void) : atomic_fun_(\"valvector_ad_sum\")\n    { }\n    void operator()(const ad_valvector&  ax, ad_valvector& ay)\n    {   //\n        // ay\n        CppAD::vector<ad_valvector> ax_vec(1), ay_vec(1);\n        ax_vec[0] = ax;\n        atomic_fun_(ax_vec, ay_vec);\n        ay = ay_vec[0];\n        return;\n    }\n};\n# endif\n"
  },
  {
    "path": "include/cppad/ipopt/solve.hpp",
    "content": "# ifndef CPPAD_IPOPT_SOLVE_HPP\n# define CPPAD_IPOPT_SOLVE_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin ipopt_solve}\n{xrst_spell\n    bvector\n    doesn\n    fg\n    gl\n    gu\n    maxiter\n    naninf\n    ng\n    nx\n    rll\n    xl\n    zl\n    zu\n}\n\nUse Ipopt to Solve a Nonlinear Programming Problem\n##################################################\n\nSyntax\n******\n| # ``include <cppad/ipopt/solve.hpp>``\n| ``ipopt::solve`` (\n| |tab| *options* , *xi* , *xl* , *xu* , *gl* , *gu* , *fg_eval* , *solution*\n| )\n\nPurpose\n*******\nThe function ``ipopt::solve`` solves nonlinear programming\nproblems of the form\n\n.. math::\n\n    \\begin{array}{rll}\n    {\\rm minimize}      & f (x)\n    \\\\\n    {\\rm subject \\; to} & gl \\leq g(x) \\leq gu\n    \\\\\n                        & xl  \\leq x   \\leq xu\n    \\end{array}\n\nThis is done using\n`Ipopt <https://coin-or.github.io/Ipopt>`_\noptimizer and CppAD for the derivative and sparsity calculations.\n\nInclude File\n************\nIf :ref:`cmake@include_ipopt` is on the cmake command line,\nthe file ``cppad/ipopt/solve.hpp`` is included by ``cppad/cppad.hpp`` .\nOtherwise,\n``cppad/ipopt/solve.hpp`` can be included directly\n(If ``cppad/cppad.hpp`` has not yet been included,\n``cppad/ipopt/solve.hpp`` will automatically include it.)\n\nBvector\n*******\nThe type *Bvector* must be a :ref:`SimpleVector-name` class with\n:ref:`elements of type<SimpleVector@Elements of Specified Type>`\n``bool`` .\n\nDvector\n*******\nThe type *DVector* must be a :ref:`SimpleVector-name` class with\n:ref:`elements of type<SimpleVector@Elements of Specified Type>`\n``double`` .\n\noptions\n*******\nThe argument *options* has prototype\n\n    ``const std::string`` *options*\n\nIt contains a list of options.\nEach option, including the last option,\nis terminated by the ``'\\n'`` character.\nEach line consists of two or three tokens separated by one or more spaces.\n\nRetape\n======\nYou can set the retape flag with the following syntax:\n\n    ``Retape`` *value*\n\nIf the value is ``true`` , ``ipopt::solve`` with retape the\n:ref:`operation sequence<glossary@Operation@Sequence>` for each\nnew value of *x* .\nIf the value is ``false`` , ``ipopt::solve``\nwill tape the operation sequence at the value\nof *xi* and use that sequence for the entire optimization process.\nThe default value is ``false`` .\n\nSparse\n======\nYou can set the sparse Jacobian and Hessian flag with the following syntax:\n\n    ``Sparse`` *value* *direction*\n\nIf the value is ``true`` , ``ipopt::solve`` will use a sparse\nmatrix representation for the computation of Jacobians and Hessians.\nOtherwise, it will use a full matrix representation for\nthese calculations.\nThe default for *value* is ``false`` .\nIf sparse is true, retape must be false.\n\nIt is unclear if :ref:`sparse_jacobian-name` would be faster user\nforward or reverse mode so you are able to choose the direction.\nIf\n\n    *value* == ``true &&`` *direction* == ``forward``\n\nthe Jacobians will be calculated using ``SparseJacobianForward`` .\nIf\n\n    *value* == ``true &&`` *direction* == ``reverse``\n\nthe Jacobians will be calculated using ``SparseJacobianReverse`` .\n\nString\n======\nYou can set any Ipopt string option using a line with the following syntax:\n\n    ``String`` *name* *value*\n\nHere *name* is any valid Ipopt string option\nand *value* is its setting.\n\nNumeric\n=======\nYou can set any Ipopt numeric option using a line with the following syntax:\n\n    ``Numeric`` *name* *value*\n\nHere *name* is any valid Ipopt numeric option\nand *value* is its setting.\n\nInteger\n=======\nYou can set any Ipopt integer option using a line with the following syntax:\n\n    ``Integer`` *name* *value*\n\nHere *name* is any valid Ipopt integer option\nand *value* is its setting.\n\nxi\n**\nThe argument *xi* has prototype\n\n    ``const`` *Vector* & *xi*\n\nand its size is equal to *nx* .\nIt specifies the initial point where Ipopt starts the optimization process.\n\nxl\n**\nThe argument *xl* has prototype\n\n    ``const`` *Vector* & *xl*\n\nand its size is equal to *nx* .\nIt specifies the lower limits for the argument in the optimization problem.\n\nxu\n**\nThe argument *xu* has prototype\n\n    ``const`` *Vector* & *xu*\n\nand its size is equal to *nx* .\nIt specifies the upper limits for the argument in the optimization problem.\n\ngl\n**\nThe argument *gl* has prototype\n\n    ``const`` *Vector* & *gl*\n\nand its size is equal to *ng* .\nIt specifies the lower limits for the constraints in the optimization problem.\n\ngu\n**\nThe argument *gu* has prototype\n\n    ``const`` *Vector* & *gu*\n\nand its size is equal to *ng* .\nIt specifies the upper limits for the constraints in the optimization problem.\n\nfg_eval\n*******\nThe argument *fg_eval* has prototype\n\n    *FG_eval* *fg_eval*\n\nwhere the class *FG_eval* is unspecified except for the fact that\nit supports the syntax\n\n| |tab| *FG_eval* :: ``ADvector``\n| |tab| *fg_eval* ( *fg* , *x* )\n\nThe type *ADvector*\nand the arguments to *fg* , *x* have the following meaning:\n\nADvector\n========\nThe type *FG_eval* :: ``ADvector`` must be a :ref:`SimpleVector-name` class with\n:ref:`elements of type<SimpleVector@Elements of Specified Type>`\n``AD<double>`` .\n\nx\n=\nThe *fg_eval* argument *x* has prototype\n\n    ``const`` *ADvector* & *x*\n\nwhere *nx* = *x* . ``size`` () .\n\nfg\n==\nThe *fg_eval* argument *fg* has prototype\n\n    *ADvector* & *fg*\n\nwhere 1 + *ng* = *fg* . ``size`` () .\nThe input value of the elements of *fg* does not matter.\nUpon return from *fg_eval* ,\n\n    ``fg`` [0] =\n\n:math:`f (x)`\n\nand   for :math:`i = 0, \\ldots , ng-1`,\n\n    ``fg`` [1 + ``i`` ] =\n\n:math:`g_i (x)`\n\nsolution\n********\nThe argument *solution* has prototype\n\n    ``ipopt::solve_result<`` *Dvector* >& *solution*\n\nAfter the optimization process is completed, *solution* contains\nthe following information:\n\nstatus\n======\nThe *status* field of *solution* has prototype\n\n    ``ipopt::solve_result<`` *Dvector* >:: ``status_type`` *solution* . ``status``\n\nIt is the final Ipopt status for the optimizer.\nHere is a list of the possible values for the status:\n\n.. list-table::\n    :widths: auto\n\n    * - *status*\n      - Meaning\n    * - not_defined\n      - The optimizer did not return a final status for this problem.\n    * - unknown\n      - The status returned by the optimizer is not defined in the Ipopt\n         documentation for ``finalize_solution`` .\n    * - success\n      - Algorithm terminated successfully at a point satisfying the convergence\n         tolerances (see Ipopt options).\n    * - maxiter_exceeded\n      - The maximum number of iterations was exceeded (see Ipopt options).\n    * - stop_at_tiny_step\n      - Algorithm terminated because progress was very slow.\n    * - stop_at_acceptable_point\n      - Algorithm stopped at a point that was converged,\n         not to the 'desired' tolerances, but to 'acceptable' tolerances\n         (see Ipopt options).\n    * - local_infeasibility\n      - Algorithm converged to a non-feasible point\n         (problem may have no solution).\n    * - user_requested_stop\n      - This return value should not happen.\n    * - diverging_iterates\n      - It the iterates are diverging.\n    * - restoration_failure\n      - Restoration phase failed, algorithm doesn't know how to proceed.\n    * - error_in_step_computation\n      - An unrecoverable error occurred while Ipopt tried to\n         compute the search direction.\n    * - invalid_number_detected\n      - Algorithm received an invalid number (such as ``nan`` or ``inf`` )\n         from the users function *fg_info* . ``eval`` or from the CppAD evaluations\n         of its derivatives\n         (see the Ipopt option ``check_derivatives_for_naninf`` ).\n    * - internal_error\n      - An unknown Ipopt internal error occurred.\n         Contact the Ipopt authors through the mailing list.\n\nx\n=\nThe ``x`` field of *solution* has prototype\n\n    *Vector* *solution* . ``x``\n\nand its size is equal to *nx* .\nIt is the final :math:`x` value for the optimizer.\n\nzl\n==\nThe ``zl`` field of *solution* has prototype\n\n    *Vector* *solution* . ``zl``\n\nand its size is equal to *nx* .\nIt is the final Lagrange multipliers for the\nlower bounds on :math:`x`.\n\nzu\n==\nThe ``zu`` field of *solution* has prototype\n\n    *Vector* *solution* . ``zu``\n\nand its size is equal to *nx* .\nIt is the final Lagrange multipliers for the\nupper bounds on :math:`x`.\n\ng\n=\nThe ``g`` field of *solution* has prototype\n\n    *Vector* *solution* . ``g``\n\nand its size is equal to *ng* .\nIt is the final value for the constraint function :math:`g(x)`.\n\nlambda\n======\nThe ``lambda`` field of *solution* has prototype\n\n    *Vector* > *solution* . ``lambda``\n\nand its size is equal to *ng* .\nIt is the final value for the\nLagrange multipliers corresponding to the constraint function.\n\nobj_value\n=========\nThe ``obj_value`` field of *solution* has prototype\n\n    ``double`` *solution* . ``obj_value``\n\nIt is the final value of the objective function :math:`f(x)`.\n{xrst_toc_hidden\n    example/ipopt_solve/get_started.cpp\n    example/ipopt_solve/retape.cpp\n    example/ipopt_solve/ode_inverse.cpp\n}\nExample\n*******\nAll the examples return true if it succeeds and false otherwise.\n\nget_started\n===========\nThe file\n:ref:`example/ipopt_solve/get_started.cpp<ipopt_solve_get_started.cpp-name>`\nis an example and test of ``ipopt::solve``\ntaken from the Ipopt manual.\n\nretape\n======\nThe file\n:ref:`example/ipopt_solve/retape.cpp<ipopt_solve_retape.cpp-name>`\ndemonstrates when it is necessary to specify\n:ref:`ipopt_solve@options@Retape` as true.\n\node_inverse\n===========\nThe file\n:ref:`example/ipopt_solve/ode_inverse.cpp<ipopt_solve_ode_inverse.cpp-name>`\ndemonstrates using Ipopt to solve for parameters in an ODE model.\n\n{xrst_end ipopt_solve}\n-------------------------------------------------------------------------------\n*/\n# include <cppad/cppad.hpp>\n# include <cppad/ipopt/solve_callback.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\nnamespace ipopt {\n/*!\n\\file solve.hpp\n\\brief Implement the ipopt::solve Nonlinear Programming Solver\n*/\n\n/*!\nUse Ipopt to Solve a Nonlinear Programming Problem\n\n\\tparam Bvector\nsimple vector class with elements of type bool.\n\n\\tparam Dvector\nsimple vector class with elements of type double.\n\n\\tparam FG_eval\nfunction object used to evaluate f(x) and g(x); see fg_eval below.\nIt must also support\n\\code\n    FG_eval::ADvector\n\\endcode\nto identify the type used for the arguments to fg_eval.\n\n\\param options\nlist of options, one for each line.\nIpopt options (are optional) and have one of the following forms\n\\code\n    String   name  value\n    Numeric  name  value\n    Integer  name  value\n\\endcode\nThe following other possible options are listed below:\n\\code\n    Retape   value\n\\endcode\n\n\n\\param xi\ninitial argument value to start optimization procedure at.\n\n\\param xl\nlower limit for argument during optimization\n\n\\param xu\nupper limit for argument during optimization\n\n\\param gl\nlower limit for g(x) during optimization.\n\n\\param gu\nupper limit for g(x) during optimization.\n\n\\param fg_eval\nfunction that evaluates the objective and constraints using the syntax\n\\code\n    fg_eval(fg, x)\n\\endcode\n\n\\param solution\nstructure that holds the solution of the optimization.\n*/\ntemplate <class Dvector, class FG_eval>\nvoid solve(\n    const std::string&                   options   ,\n    const Dvector&                       xi        ,\n    const Dvector&                       xl        ,\n    const Dvector&                       xu        ,\n    const Dvector&                       gl        ,\n    const Dvector&                       gu        ,\n    FG_eval&                             fg_eval   ,\n    ipopt::solve_result<Dvector>&        solution  )\n{   bool ok = true;\n\n    typedef typename FG_eval::ADvector ADvector;\n\n    CPPAD_ASSERT_KNOWN(\n        xi.size() == xl.size() && xi.size() == xu.size() ,\n        \"ipopt::solve: size of xi, xl, and xu are not all equal.\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        gl.size() == gu.size() ,\n        \"ipopt::solve: size of gl and gu are not equal.\"\n    );\n    size_t nx = xi.size();\n    size_t ng = gl.size();\n\n    // Create an IpoptApplication\n    using Ipopt::IpoptApplication;\n    Ipopt::SmartPtr<IpoptApplication> app = new IpoptApplication();\n\n    // process the options argument\n    size_t begin_1, end_1, begin_2, end_2, begin_3, end_3;\n    begin_1     = 0;\n    bool retape          = false;\n    bool sparse_forward  = false;\n    bool sparse_reverse  = false;\n    while( begin_1 < options.size() )\n    {   // split this line into tokens\n        while( options[begin_1] == ' ')\n            begin_1++;\n        end_1   = options.find_first_of(\" \\n\", begin_1);\n        begin_2 = end_1;\n        while( options[begin_2] == ' ')\n            begin_2++;\n        end_2   = options.find_first_of(\" \\n\", begin_2);\n        begin_3 = end_2;\n        while( options[begin_3] == ' ')\n            begin_3++;\n        end_3   = options.find_first_of(\" \\n\", begin_3);\n\n        // check for errors\n        CPPAD_ASSERT_KNOWN(\n            (end_1 != std::string::npos)  &\n            (end_2 != std::string::npos)  &\n            (end_3 != std::string::npos)  ,\n            \"ipopt::solve: missing '\\\\n' at end of an option line\"\n        );\n        CPPAD_ASSERT_KNOWN(\n            (end_1 > begin_1) && (end_2 > begin_2) ,\n            \"ipopt::solve: an option line does not have two tokens\"\n        );\n\n        // get first two tokens\n        std::string tok_1 = options.substr(begin_1, end_1 - begin_1);\n        std::string tok_2 = options.substr(begin_2, end_2 - begin_2);\n\n        // get third token\n        std::string tok_3;\n        bool three_tok = false;\n        three_tok |= tok_1 == \"Sparse\";\n        three_tok |= tok_1 == \"String\";\n        three_tok |= tok_1 == \"Numeric\";\n        three_tok |= tok_1 == \"Integer\";\n        if( three_tok )\n        {   CPPAD_ASSERT_KNOWN(\n                (end_3 > begin_3) ,\n                \"ipopt::solve: a Sparse, String, Numeric, or Integer\\n\"\n                \"option line does not have three tokens.\"\n            );\n            tok_3 = options.substr(begin_3, end_3 - begin_3);\n        }\n\n        // switch on option type\n        if( tok_1 == \"Retape\" )\n        {   CPPAD_ASSERT_KNOWN(\n                (tok_2 == \"true\") || (tok_2 == \"false\") ,\n                \"ipopt::solve: Retape value is not true or false\"\n            );\n            retape = (tok_2 == \"true\");\n        }\n        else if( tok_1 == \"Sparse\" )\n        {   CPPAD_ASSERT_KNOWN(\n                (tok_2 == \"true\") || (tok_2 == \"false\") ,\n                \"ipopt::solve: Sparse value is not true or false\"\n            );\n            CPPAD_ASSERT_KNOWN(\n                (tok_3 == \"forward\") || (tok_3 == \"reverse\") ,\n                \"ipopt::solve: Sparse direction is not forward or reverse\"\n            );\n            if( tok_2 == \"false\" )\n            {   sparse_forward = false;\n                sparse_reverse = false;\n            }\n            else\n            {   sparse_forward = tok_3 == \"forward\";\n                sparse_reverse = tok_3 == \"reverse\";\n            }\n        }\n        else if ( tok_1 == \"String\" )\n            app->Options()->SetStringValue(tok_2.c_str(), tok_3.c_str());\n        else if ( tok_1 == \"Numeric\" )\n        {   Ipopt::Number value = std::atof( tok_3.c_str() );\n            app->Options()->SetNumericValue(tok_2.c_str(), value);\n        }\n        else if ( tok_1 == \"Integer\" )\n        {   Ipopt::Index value = std::atoi( tok_3.c_str() );\n            app->Options()->SetIntegerValue(tok_2.c_str(), value);\n        }\n        else\n            CPPAD_ASSERT_KNOWN(\n            false,\n            \"ipopt::solve: First token is not one of\\n\"\n            \"Retape, Sparse, String, Numeric, Integer\"\n        );\n\n        begin_1 = end_3;\n        while( options[begin_1] == ' ')\n            begin_1++;\n        if( options[begin_1] != '\\n' ) CPPAD_ASSERT_KNOWN(\n            false,\n            \"ipopt::solve: either more than three tokens \"\n            \"or no '\\\\n' at end of a line\"\n        );\n        begin_1++;\n    }\n    CPPAD_ASSERT_KNOWN(\n        ! ( retape & (sparse_forward | sparse_reverse) ) ,\n        \"ipopt::solve: retape and sparse both true is not supported.\"\n    );\n\n    // Initialize the IpoptApplication and process the options\n    Ipopt::ApplicationReturnStatus status = app->Initialize();\n    ok    &= status == Ipopt::Solve_Succeeded;\n    if( ! ok )\n    {   solution.status = solve_result<Dvector>::unknown;\n        return;\n    }\n\n    // Create an interface from Ipopt to this specific problem.\n    // Note the assumption here that ADvector is same as cppd_ipopt::ADvector\n    size_t nf = 1;\n    Ipopt::SmartPtr<Ipopt::TNLP> cppad_nlp =\n    new CppAD::ipopt::solve_callback<Dvector, ADvector, FG_eval>(\n        nf,\n        nx,\n        ng,\n        xi,\n        xl,\n        xu,\n        gl,\n        gu,\n        fg_eval,\n        retape,\n        sparse_forward,\n        sparse_reverse,\n        solution\n    );\n\n    // Run the IpoptApplication\n    app->OptimizeTNLP(cppad_nlp);\n\n    return;\n}\n\n} // end ipopt namespace\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/ipopt/solve_callback.hpp",
    "content": "# ifndef CPPAD_IPOPT_SOLVE_CALLBACK_HPP\n# define CPPAD_IPOPT_SOLVE_CALLBACK_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/cppad.hpp>\n# include <coin-or/IpIpoptApplication.hpp>\n# include <coin-or/IpTNLP.hpp>\n# include <cppad/ipopt/solve_result.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\nnamespace ipopt {\n/*!\n\\file solve_callback.hpp\n\\brief Class that connects ipopt::solve to Ipopt\n*/\n\n/*!\nClass that Ipopt uses for obtaining information about this problem.\n\n\n\\section Evaluation_Methods Evaluation Methods\nThe set of evaluation methods for this class is\n\\verbatim\n    { eval_f, eval_grad_f, eval_g, eval_jac_g, eval_h }\n\\endverbatim\nNote that the bool return flag for the evaluations methods\ndoes not appear in the Ipopt documentation.\nLooking at the code, it seems to be a flag telling Ipopt to abort\nwhen the flag is false.\n*/\ntemplate <class Dvector, class ADvector, class FG_eval>\nclass solve_callback : public Ipopt::TNLP\n{\nprivate:\n    // ------------------------------------------------------------------\n    // Types used by this class\n    // ------------------------------------------------------------------\n    /// A Scalar value used by Ipopt\n    typedef Ipopt::Number                         Number;\n    /// An index value used by Ipopt\n    typedef Ipopt::Index                          Index;\n    /// Indexing style used in Ipopt sparsity structure\n    typedef Ipopt::TNLP::IndexStyleEnum           IndexStyleEnum;\n    // ------------------------------------------------------------------\n    // Values directly passed in to constructor\n    // ------------------------------------------------------------------\n    /// dimension of the range space for f(x).\n    /// The objective is sum_i f_i (x).\n    /// Note that, at this point, there is no advantage having nf_ > 1.\n    const size_t                    nf_;\n    /// dimension of the domain space for f(x) and g(x)\n    const size_t                    nx_;\n    /// dimension of the range space for g(x)\n    const size_t                    ng_;\n    /// initial value for x\n    const Dvector&                  xi_;\n    /// lower limit for x\n    const Dvector&                  xl_;\n    /// upper limit for x\n    const Dvector&                  xu_;\n    /// lower limit for g(x)\n    const Dvector&                  gl_;\n    /// upper limit for g(x)\n    const Dvector&                  gu_;\n    /// object that evaluates f(x) and g(x)\n    FG_eval&                        fg_eval_;\n    /// should operation sequence be retaped for each new x.\n    bool                            retape_;\n    /// Should sparse methods be used to compute Jacobians and Hessians\n    /// with forward mode used for Jacobian.\n    bool                            sparse_forward_;\n    /// Should sparse methods be used to compute Jacobians and Hessians\n    /// with reverse mode used for Jacobian.\n    bool                            sparse_reverse_;\n    /// final results are returned to this structure\n    solve_result<Dvector>&          solution_;\n    // ------------------------------------------------------------------\n    // Values that are initialized by the constructor\n    // ------------------------------------------------------------------\n    /// AD function object that evaluates x -> [ f(x) , g(x) ]\n    /// If retape is false, this object is initialized by constructor\n    /// otherwise it is set by cache_new_x each time it is called.\n    CppAD::ADFun<double>            adfun_;\n    /// value of x corresponding to previous new_x\n    Dvector                         x0_;\n    /// value of fg corresponding to previous new_x\n    Dvector                         fg0_;\n    // ----------------------------------------------------------------------\n    // Jacobian information\n    // ----------------------------------------------------------------------\n    /// Sparsity pattern for Jacobian of [f(x), g(x) ].\n    /// If sparse is true, this pattern set by constructor and does not change.\n    /// Otherwise this vector has size zero.\n    CppAD::vectorBool               pattern_jac_;\n    /// Row indices of [f(x), g(x)] for Jacobian of g(x) in row order.\n    /// (Set by constructor and not changed.)\n    CppAD::vector<size_t>           row_jac_;\n    /// Column indices for Jacobian of g(x), same order as row_jac_.\n    /// (Set by constructor and not changed.)\n    CppAD::vector<size_t>           col_jac_;\n    /// col_order_jac_ sorts row_jac_ and col_jac_ in column order.\n    /// (Set by constructor and not changed.)\n    CppAD::vector<size_t>           col_order_jac_;\n    /// Work vector used by SparseJacobian, stored here to avoid recalculation.\n    CppAD::sparse_jacobian_work     work_jac_;\n    // ----------------------------------------------------------------------\n    // Hessian information\n    // ----------------------------------------------------------------------\n    /// Sparsity pattern for Hessian of Lagragian\n    /// \\f[ L(x) = \\sigma \\sum_i f_i (x) + \\sum_i \\lambda_i  g_i (x) \\f]\n    /// If sparse is true, this pattern set by constructor and does not change.\n    /// Otherwise this vector has size zero.\n    CppAD::vectorBool               pattern_hes_;\n    /// Row indices of Hessian lower left triangle in row order.\n    /// (Set by constructor and not changed.)\n    CppAD::vector<size_t>           row_hes_;\n    /// Column indices of Hessian left triangle in same order as row_hes_.\n    /// (Set by constructor and not changed.)\n    CppAD::vector<size_t>           col_hes_;\n    /// Work vector used by SparseJacobian, stored here to avoid recalculation.\n    CppAD::sparse_hessian_work      work_hes_;\n    // ------------------------------------------------------------------\n    // Private member functions\n    // ------------------------------------------------------------------\n    /*!\n    Cache information for a new value of x.\n\n    \\param x\n    is the new value for x.\n\n    \\par x0_\n    the elements of this vector are set to the new value for x.\n\n    \\par fg0_\n    the elements of this vector are set to the new value for [f(x), g(x)]\n\n    \\par adfun_\n    If retape is true, the operation sequence for this function\n    is changes to correspond to the argument x.\n    If retape is false, the operation sequence is not changed.\n    The zero order Taylor coefficients for this function are set\n    so they correspond to the argument x.\n    */\n    void cache_new_x(const Number* x)\n    {   size_t i;\n        if( retape_ )\n        {   // make adfun_, as well as x0_ and fg0_ correspond to this x\n            ADvector a_x(nx_), a_fg(nf_ + ng_);\n            for(i = 0; i < nx_; i++)\n            {   x0_[i] = x[i];\n                a_x[i] = x[i];\n            }\n            CppAD::Independent(a_x);\n            fg_eval_(a_fg, a_x);\n            adfun_.Dependent(a_x, a_fg);\n        }\n        else\n        {   // make x0_ and fg0_ correspond to this x\n            for(i = 0; i < nx_; i++)\n                x0_[i] = x[i];\n        }\n        fg0_ = adfun_.Forward(0, x0_);\n    }\npublic:\n    // ----------------------------------------------------------------------\n    /*!\n    Constructor for the interface between ipopt::solve and Ipopt\n\n    \\param nf\n    dimension of the range space for f(x)\n\n    \\param nx\n    dimension of the domain space for f(x) and g(x).\n\n    \\param ng\n    dimension of the range space for g(x)\n\n    \\param xi\n    initial value of x during the optimization procedure (size nx).\n\n    \\param xl\n    lower limit for x (size nx).\n\n    \\param xu\n    upper limit for x (size nx).\n\n    \\param gl\n    lower limit for g(x) (size ng).\n\n    \\param gu\n    upper limit for g(x) (size ng).\n\n    \\param fg_eval\n    function object that evaluations f(x) and g(x) using fg_eval(fg, x)\n\n    \\param retape\n    should the operation sequence be retaped for each argument value.\n\n    \\param sparse_forward\n    should sparse matrix computations be used for Jacobians and Hessians\n    with forward mode for Jacobian.\n\n    \\param sparse_reverse\n    should sparse matrix computations be used for Jacobians and Hessians\n    with reverse mode for Jacobian.\n    (sparse_forward and sparse_reverse cannot both be true).\n\n    \\param solution\n    object where final results are stored.\n    */\n    solve_callback(\n        size_t                 nf              ,\n        size_t                 nx              ,\n        size_t                 ng              ,\n        const Dvector&         xi              ,\n        const Dvector&         xl              ,\n        const Dvector&         xu              ,\n        const Dvector&         gl              ,\n        const Dvector&         gu              ,\n        FG_eval&               fg_eval         ,\n        bool                   retape          ,\n        bool                   sparse_forward  ,\n        bool                   sparse_reverse  ,\n        solve_result<Dvector>& solution ) :\n    nf_ ( nf ),\n    nx_ ( nx ),\n    ng_ ( ng ),\n    xi_ ( xi ),\n    xl_ ( xl ),\n    xu_ ( xu ),\n    gl_ ( gl ),\n    gu_ ( gu ),\n    fg_eval_ ( fg_eval ),\n    retape_ ( retape ),\n    sparse_forward_ ( sparse_forward ),\n    sparse_reverse_ ( sparse_reverse ),\n    solution_ ( solution )\n    {   CPPAD_ASSERT_UNKNOWN( ! ( sparse_forward_ & sparse_reverse_ ) );\n\n        size_t i, j;\n        size_t nfg = nf_ + ng_;\n\n        // initialize x0_ and fg0_ with proper dimensions and value nan\n        x0_.resize(nx);\n        fg0_.resize(nfg);\n        for(i = 0; i < nx_; i++)\n            x0_[i] = std::numeric_limits<double>::quiet_NaN();\n        for(i = 0; i < nfg; i++)\n            fg0_[i] = std::numeric_limits<double>::quiet_NaN();\n\n        if( ! retape_ )\n        {   // make adfun_ correspond to x -> [ f(x), g(x) ]\n            ADvector a_x(nx_), a_fg(nfg);\n            for(i = 0; i < nx_; i++)\n                a_x[i] = xi_[i];\n            CppAD::Independent(a_x);\n            fg_eval_(a_fg, a_x);\n            adfun_.Dependent(a_x, a_fg);\n            // optimize because we will make repeated use of this tape\n            adfun_.optimize();\n        }\n        if( sparse_forward_ | sparse_reverse_ )\n        {   CPPAD_ASSERT_UNKNOWN( ! retape );\n            size_t m = nf_ + ng_;\n            //\n            // -----------------------------------------------------------\n            // Jacobian\n            pattern_jac_.resize( m * nx_ );\n            if( nx_ <= m )\n            {   // use forward mode to compute sparsity\n\n                // number of bits that are packed into one unit in vectorBool\n                size_t n_column = vectorBool::bit_per_unit();\n\n                // sparsity patterns for current columns\n                vectorBool r(nx_ * n_column), s(m * n_column);\n\n                // compute the sparsity pattern n_column columns at a time\n                size_t n_loop = (nx_ - 1) / n_column + 1;\n                for(size_t i_loop = 0; i_loop < n_loop; i_loop++)\n                {   // starting column index for this iteration\n                    size_t i_column = i_loop * n_column;\n\n                    // pattern that picks out the appropriate columns\n                    for(i = 0; i < nx_; i++)\n                    {   for(j = 0; j < n_column; j++)\n                            r[i * n_column + j] = (i == i_column + j);\n                    }\n                    s = adfun_.ForSparseJac(n_column, r);\n\n                    // fill in the corresponding columns of total_sparsity\n                    for(i = 0; i < m; i++)\n                    {   for(j = 0; j < n_column; j++)\n                        {   if( i_column + j < nx_ )\n                                pattern_jac_[i * nx_ + i_column + j] =\n                                    s[i * n_column + j];\n                        }\n                    }\n                }\n            }\n            else\n            {   // use reverse mode to compute sparsity\n\n                // number of bits that are packed into one unit in vectorBool\n                size_t n_row = vectorBool::bit_per_unit();\n\n                // sparsity patterns for current rows\n                vectorBool r(n_row * m), s(n_row * nx_);\n\n                // compute the sparsity pattern n_row row at a time\n                size_t n_loop = (m - 1) / n_row + 1;\n                for(size_t i_loop = 0; i_loop < n_loop; i_loop++)\n                {   // starting row index for this iteration\n                    size_t i_row = i_loop * n_row;\n\n                    // pattern that picks out the appropriate rows\n                    for(i = 0; i < n_row; i++)\n                    {   for(j = 0; j < m; j++)\n                            r[i * m + j] = (i_row + i ==  j);\n                    }\n                    s = adfun_.RevSparseJac(n_row, r);\n\n                    // fill in corresponding rows of total sparsity\n                    for(i = 0; i < n_row; i++)\n                    {   for(j = 0; j < nx_; j++)\n                            if( i_row + i < m )\n                                pattern_jac_[ (i_row + i) * nx_ + j ] =\n                                    s[ i  * nx_ + j];\n                    }\n                }\n            }\n            /*\n            {   // use reverse mode to compute sparsity\n                CppAD::vectorBool s(m * m);\n                for(i = 0; i < m; i++)\n                {   for(j = 0; j < m; j++)\n                        s[i * m + j] = (i == j);\n                }\n                pattern_jac_ = adfun_.RevSparseJac(m, s);\n            }\n            */\n            // Set row and column indices in Jacoian of [f(x), g(x)]\n            // for Jacobian of g(x). These indices are in row major order.\n            for(i = nf_; i < nfg; i++)\n            {   for(j = 0; j < nx_; j++)\n                {   if( pattern_jac_[ i * nx_ + j ] )\n                    {   row_jac_.push_back(i);\n                        col_jac_.push_back(j);\n                    }\n                }\n            }\n            // Set row and column indices in Jacoian of [f(x), g(x)]\n            // for Jacobian of g(x). These indices are in row major order.\n            // -----------------------------------------------------------\n            // Hessian\n            pattern_hes_.resize(nx_ * nx_);\n\n            // number of bits that are packed into one unit in vectorBool\n            size_t n_column = vectorBool::bit_per_unit();\n\n            // sparsity patterns for current columns\n            vectorBool r(nx_ * n_column), h(nx_ * n_column);\n\n            // sparsity pattern for range space of function\n            vectorBool s(m);\n            for(i = 0; i < m; i++)\n                s[i] = true;\n\n            // compute the sparsity pattern n_column columns at a time\n            size_t n_loop = (nx_ - 1) / n_column + 1;\n            for(size_t i_loop = 0; i_loop < n_loop; i_loop++)\n            {   // starting column index for this iteration\n                size_t i_column = i_loop * n_column;\n\n                // pattern that picks out the appropriate columns\n                for(i = 0; i < nx_; i++)\n                {   for(j = 0; j < n_column; j++)\n                        r[i * n_column + j] = (i == i_column + j);\n                }\n                adfun_.ForSparseJac(n_column, r);\n\n                // sparsity pattern corresponding to paritls w.r.t. (theta, u)\n                // of partial w.r.t. the selected columns\n                bool transpose = true;\n                h = adfun_.RevSparseHes(n_column, s, transpose);\n\n                // fill in the corresponding columns of total_sparsity\n                for(i = 0; i < nx_; i++)\n                {   for(j = 0; j < n_column; j++)\n                    {   if( i_column + j < nx_ )\n                            pattern_hes_[i * nx_ + i_column + j] =\n                                h[i * n_column + j];\n                    }\n                }\n            }\n            // Set row and column indices for Lower triangle of Hessian\n            // of Lagragian.  These indices are in row major order.\n            for(i = 0; i < nx_; i++)\n            {   for(j = 0; j < nx_; j++)\n                {   if( pattern_hes_[ i * nx_ + j ] )\n                    if( j <= i )\n                    {   row_hes_.push_back(i);\n                        col_hes_.push_back(j);\n                    }\n                }\n            }\n        }\n        else\n        {   // Set row and column indices in Jacoian of [f(x), g(x)]\n            // for Jacobian of g(x). These indices are in row major order.\n            for(i = nf_; i < nfg; i++)\n            {   for(j = 0; j < nx_; j++)\n                {   row_jac_.push_back(i);\n                    col_jac_.push_back(j);\n                }\n            }\n            // Set row and column indices for lower triangle of Hessian.\n            // These indices are in row major order.\n            for(i = 0; i < nx_; i++)\n            {   for(j = 0; j <= i; j++)\n                {   row_hes_.push_back(i);\n                    col_hes_.push_back(j);\n                }\n            }\n        }\n\n        // Column order indirect sort of the Jacobian indices\n        col_order_jac_.resize( col_jac_.size() );\n        index_sort( col_jac_, col_order_jac_ );\n    }\n    // -----------------------------------------------------------------------\n    /*!\n    Return dimension information about optimization problem.\n\n    \\param[out] n\n    is set to the value nx_.\n\n    \\param[out] m\n    is set to the value ng_.\n\n    \\param[out] nnz_jac_g\n    is set to ng_ * nx_ (sparsity not yet implemented)\n\n    \\param[out] nnz_h_lag\n    is set to nx_*(nx_+1)/2 (sparsity not yet implemented)\n\n    \\param[out] index_style\n    is set to C_STYLE; i.e., zeoro based indexing is used in the\n    information passed to Ipopt.\n    */\n    virtual bool get_nlp_info(\n        Index&          n            ,\n        Index&          m            ,\n        Index&          nnz_jac_g    ,\n        Index&          nnz_h_lag    ,\n        IndexStyleEnum& index_style  )\n    {\n        n         = static_cast<Index>(nx_);\n        m         = static_cast<Index>(ng_);\n        nnz_jac_g = static_cast<Index>(row_jac_.size());\n        nnz_h_lag = static_cast<Index>(row_hes_.size());\n\n# ifndef NDEBUG\n        if( ! (sparse_forward_ | sparse_reverse_) )\n        {   size_t nnz = static_cast<size_t>(nnz_jac_g);\n            CPPAD_ASSERT_UNKNOWN( nnz == ng_ * nx_);\n            //\n            nnz = static_cast<size_t>(nnz_h_lag);\n            CPPAD_ASSERT_UNKNOWN( nnz == (nx_ * (nx_ + 1)) / 2 );\n        }\n# endif\n\n        // use the fortran index style for row/col entries\n        index_style = C_STYLE;\n\n        return true;\n    }\n    // -----------------------------------------------------------------------\n    /*!\n    Return bound information about optimization problem.\n\n    \\param[in] n\n    is the dimension of the domain space for f(x) and g(x); i.e.,\n    it must be equal to nx_.\n\n    \\param[out] x_l\n    is a vector of size nx_.\n    The input value of its elements does not matter.\n    On output, it is a copy of the lower bound for \\f$ x \\f$; i.e.,\n    xl_.\n\n    \\param[out] x_u\n    is a vector of size nx_.\n    The input value of its elements does not matter.\n    On output, it is a copy of the upper bound for \\f$ x \\f$; i.e.,\n    xu_.\n\n    \\param[in] m\n    is the dimension of the range space for g(x). i.e.,\n    it must be equal to ng_.\n\n    \\param[out] g_l\n    is a vector of size ng_.\n    The input value of its elements does not matter.\n    On output, it is a copy of the lower bound for \\f$ g(x) \\f$; i.e., gl_.\n\n    \\param[out] g_u\n    is a vector of size ng_.\n    The input value of its elements does not matter.\n    On output, it is a copy of the upper bound for \\f$ g(x) \\f$; i.e, gu_.\n    */\n    virtual bool get_bounds_info(\n        Index       n        ,\n        Number*     x_l      ,\n        Number*     x_u      ,\n        Index       m        ,\n        Number*     g_l      ,\n        Number*     g_u      )\n    {   size_t i;\n        // here, the n and m we gave IPOPT in get_nlp_info are passed back\n        CPPAD_ASSERT_UNKNOWN(static_cast<size_t>(n) == nx_);\n        CPPAD_ASSERT_UNKNOWN(static_cast<size_t>(m) == ng_);\n\n        // pass back bounds\n        for(i = 0; i < nx_; i++)\n        {   x_l[i] = xl_[i];\n            x_u[i] = xu_[i];\n        }\n        for(i = 0; i < ng_; i++)\n        {   g_l[i] = gl_[i];\n            g_u[i] = gu_[i];\n        }\n\n        return true;\n    }\n    // -----------------------------------------------------------------------\n    /*!\n    Return initial x value where optimization is started.\n\n    \\param[in] n\n    must be equal to the domain dimension for f(x) and g(x); i.e.,\n    it must be equal to nx_.\n\n    \\param[in] init_x\n    must be equal to true.\n\n    \\param[out] x\n    is a vector of size nx_.\n    The input value of its elements does not matter.\n    On output, it is a copy of the initial value for \\f$ x \\f$; i.e. xi_.\n\n    \\param[in] init_z\n    must be equal to false.\n\n    \\param z_L\n    is not used.\n\n    \\param z_U\n    is not used.\n\n    \\param[in] m\n    must be equal to the domain dimension for f(x) and g(x); i.e.,\n    it must be equal to ng_.\n\n    \\param init_lambda\n    must be equal to false.\n\n    \\param lambda\n    is not used.\n    */\n    virtual bool get_starting_point(\n        Index           n            ,\n        bool            init_x       ,\n        Number*         x            ,\n        bool            init_z       ,\n        Number*         z_L          ,\n        Number*         z_U          ,\n        Index           m            ,\n        bool            init_lambda  ,\n        Number*         lambda       )\n    {   size_t j;\n\n        CPPAD_ASSERT_UNKNOWN(static_cast<size_t>(n) == nx_ );\n        CPPAD_ASSERT_UNKNOWN(static_cast<size_t>(m) == ng_ );\n        CPPAD_ASSERT_UNKNOWN(init_x == true);\n        CPPAD_ASSERT_UNKNOWN(init_z == false);\n        CPPAD_ASSERT_UNKNOWN(init_lambda == false);\n\n        for(j = 0; j < nx_; j++)\n            x[j] = xi_[j];\n\n        return true;\n    }\n    // -----------------------------------------------------------------------\n    /*!\n    Evaluate the objective function f(x).\n\n    \\param[in] n\n    is the dimension of the argument space for f(x); i.e., must be equal nx_.\n\n    \\param[in] x\n    is a vector of size nx_ containing the point at which to evaluate\n    the function sum_i f_i (x).\n\n    \\param[in] new_x\n    is false if the previous call to any one of the\n    \\ref Evaluation_Methods used the same value for x.\n\n    \\param[out] obj_value\n    is the value of the objective sum_i f_i (x) at this value of x.\n\n    \\return\n    The return value is always true; see \\ref Evaluation_Methods.\n    */\n    virtual bool eval_f(\n        Index          n           ,\n        const Number*  x           ,\n        bool           new_x       ,\n        Number&        obj_value   )\n    {   size_t i;\n        if( new_x )\n            cache_new_x(x);\n        //\n        double sum = 0.0;\n        for(i = 0; i < nf_; i++)\n            sum += fg0_[i];\n        obj_value = static_cast<Number>(sum);\n        return true;\n    }\n    // -----------------------------------------------------------------------\n    /*!\n    Evaluate the gradient of f(x).\n\n    \\param[in] n\n    is the dimension of the argument space for f(x); i.e., must be equal nx_.\n\n    \\param[in] x\n    has a vector of size nx_ containing the point at which to evaluate\n    the gradient of f(x).\n\n    \\param[in] new_x\n    is false if the previous call to any one of the\n    \\ref Evaluation_Methods used the same value for x.\n\n    \\param[out] grad_f\n    is a vector of size nx_.\n    The input value of its elements does not matter.\n    The output value of its elements is the gradient of f(x)\n    at this value of.\n\n    \\return\n    The return value is always true; see \\ref Evaluation_Methods.\n    */\n    virtual bool eval_grad_f(\n        Index           n        ,\n        const Number*   x        ,\n        bool            new_x    ,\n        Number*         grad_f   )\n    {   size_t i;\n        if( new_x )\n            cache_new_x(x);\n        //\n        Dvector w(nf_ + ng_), dw(nx_);\n        for(i = 0; i < nf_; i++)\n            w[i] = 1.0;\n        for(i = 0; i < ng_; i++)\n            w[nf_ + i] = 0.0;\n        dw = adfun_.Reverse(1, w);\n        for(i = 0; i < nx_; i++)\n            grad_f[i] = dw[i];\n        return true;\n    }\n    // -----------------------------------------------------------------------\n    /*!\n    Evaluate the function g(x).\n\n    \\param[in] n\n    is the dimension of the argument space for g(x); i.e., must be equal nx_.\n\n    \\param[in] x\n    has a vector of size n containing the point at which to evaluate\n    the gradient of g(x).\n\n    \\param[in] new_x\n    is false if the previous call to any one of the\n    \\ref Evaluation_Methods used the same value for x.\n\n    \\param[in] m\n    is the dimension of the range space for g(x); i.e., must be equal to ng_.\n\n    \\param[out] g\n    is a vector of size ng_.\n    The input value of its elements does not matter.\n    The output value of its elements is\n    the value of the function g(x) at this value of x.\n\n    \\return\n    The return value is always true; see \\ref Evaluation_Methods.\n    */\n    virtual bool eval_g(\n        Index   n            ,\n        const   Number* x    ,\n        bool    new_x        ,\n        Index   m            ,\n        Number* g            )\n    {   size_t i;\n        if( new_x )\n            cache_new_x(x);\n        //\n        for(i = 0; i < ng_; i++)\n            g[i] = fg0_[nf_ + i];\n        return true;\n    }\n    // -----------------------------------------------------------------------\n    /*!\n    Evaluate the Jacobian of g(x).\n\n    \\param[in] n\n    is the dimension of the argument space for g(x);\n    i.e., must be equal nx_.\n\n    \\param x\n    If values is not NULL,\n    x is a vector of size nx_ containing the point at which to evaluate\n    the gradient of g(x).\n\n    \\param[in] new_x\n    is false if the previous call to any one of the\n    \\ref Evaluation_Methods used the same value for  x.\n\n    \\param[in] m\n    is the dimension of the range space for g(x);\n    i.e., must be equal to ng_.\n\n    \\param[in] nele_jac\n    is the number of possibly non-zero elements in the Jacobian of g(x);\n    i.e., must be equal to ng_ * nx_.\n\n    \\param iRow\n    if values is not NULL, iRow is not defined.\n    if values is NULL, iRow\n    is a vector with size nele_jac.\n    The input value of its elements does not matter.\n    On output,\n    For <tt>k = 0 , ... , nele_jac-1, iRow[k]</tt> is the\n    base zero row index for the\n    k-th possibly non-zero entry in the Jacobian of g(x).\n\n    \\param jCol\n    if values is not NULL, jCol is not defined.\n    if values is NULL, jCol\n    is a vector with size nele_jac.\n    The input value of its elements does not matter.\n    On output,\n    For <tt>k = 0 , ... , nele_jac-1, jCol[k]</tt> is the\n    base zero column index for the\n    k-th possibly non-zero entry in the Jacobian of g(x).\n\n    \\param values\n    if values is not NULL, values\n    is a vector with size nele_jac.\n    The input value of its elements does not matter.\n    On output,\n    For <tt>k = 0 , ... , nele_jac-1, values[k]</tt> is the\n    value for the\n    k-th possibly non-zero entry in the Jacobian of g(x).\n\n    \\return\n    The return value is always true; see \\ref Evaluation_Methods.\n    */\n    virtual bool eval_jac_g(\n        Index n,\n        const Number* x,\n        bool new_x,\n\n        Index m,\n        Index nele_jac,\n        Index* iRow,\n        Index *jCol,\n\n        Number* values)\n    {   size_t i, j, k, ell;\n        CPPAD_ASSERT_UNKNOWN(static_cast<size_t>(m)         == ng_ );\n        CPPAD_ASSERT_UNKNOWN(static_cast<size_t>(n)         == nx_ );\n        //\n        size_t nk = row_jac_.size();\n        CPPAD_ASSERT_UNKNOWN( static_cast<size_t>(nele_jac) == nk );\n        //\n        if( new_x )\n            cache_new_x(x);\n\n        if( values == NULL )\n        {   for(k = 0; k < nk; k++)\n            {   i = row_jac_[k];\n                j = col_jac_[k];\n                CPPAD_ASSERT_UNKNOWN( i >= nf_ );\n                iRow[k] = static_cast<Index>(i - nf_);\n                jCol[k] = static_cast<Index>(j);\n            }\n            return true;\n        }\n        //\n        if( nk == 0 )\n            return true;\n        //\n        if( sparse_forward_ )\n        {   Dvector jac(nk);\n            adfun_.SparseJacobianForward(\n                x0_ , pattern_jac_, row_jac_, col_jac_, jac, work_jac_\n            );\n            for(k = 0; k < nk; k++)\n                values[k] = jac[k];\n        }\n        else if( sparse_reverse_ )\n        {   Dvector jac(nk);\n            adfun_.SparseJacobianReverse(\n                x0_ , pattern_jac_, row_jac_, col_jac_, jac, work_jac_\n            );\n            for(k = 0; k < nk; k++)\n                values[k] = jac[k];\n        }\n        else if( nx_ < ng_ )\n        {   // use forward mode\n            Dvector x1(nx_), fg1(nf_ + ng_);\n            for(j = 0; j < nx_; j++)\n                x1[j] = 0.0;\n            // index in col_order_jac_ of next entry\n            ell = 0;\n            k   = col_order_jac_[ell];\n            for(j = 0; j < nx_; j++)\n            {   // compute j-th column of Jacobian of g(x)\n                x1[j] = 1.0;\n                fg1 = adfun_.Forward(1, x1);\n                while( ell < nk && col_jac_[k] <= j )\n                {   CPPAD_ASSERT_UNKNOWN( col_jac_[k] == j );\n                    i = row_jac_[k];\n                    CPPAD_ASSERT_UNKNOWN( i >= nf_ )\n                    values[k] = fg1[i];\n                    ell++;\n                    if( ell < nk )\n                        k = col_order_jac_[ell];\n                }\n                x1[j] = 0.0;\n            }\n        }\n        else\n        {   // user reverse mode\n            size_t nfg = nf_ + ng_;\n            // user reverse mode\n            Dvector w(nfg), dw(nx_);\n            for(i = 0; i < nfg; i++)\n                w[i] = 0.0;\n            // index in row_jac_ of next entry\n            k = 0;\n            for(i = nf_; i < nfg; i++)\n            {   // compute i-th row of Jacobian of g(x)\n                w[i] = 1.0;\n                dw = adfun_.Reverse(1, w);\n                while( k < nk && row_jac_[k] <= i )\n                {   CPPAD_ASSERT_UNKNOWN( row_jac_[k] == i );\n                    j = col_jac_[k];\n                    values[k] = dw[j];\n                    k++;\n                }\n                w[i] = 0.0;\n            }\n        }\n        return true;\n    }\n    // -----------------------------------------------------------------------\n    /*!\n    Evaluate the Hessian of the Lagragian\n\n    \\section The_Hessian_of_the_Lagragian The Hessian of the Lagragian\n    The Hessian of the Lagragian is defined as\n    \\f[\n    H(x, \\sigma, \\lambda )\n    =\n    \\sigma \\nabla^2 f(x) + \\sum_{i=0}^{m-1} \\lambda_i \\nabla^2 g(x)_i\n    \\f]\n\n    \\param[in] n\n    is the dimension of the argument space for g(x);\n    i.e., must be equal nx_.\n\n    \\param x\n    if values is not NULL, x\n    is a vector of size nx_ containing the point at which to evaluate\n    the Hessian of the Lagragian.\n\n    \\param[in] new_x\n    is false if the previous call to any one of the\n    \\ref Evaluation_Methods used the same value for x.\n\n    \\param[in] obj_factor\n    the value \\f$ \\sigma \\f$ multiplying the Hessian of\n    f(x) in the expression for \\ref The_Hessian_of_the_Lagragian.\n\n    \\param[in] m\n    is the dimension of the range space for g(x);\n    i.e., must be equal to ng_.\n\n    \\param[in] lambda\n    if values is not NULL, lambda\n    is a vector of size ng_ specifying the value of \\f$ \\lambda \\f$\n    in the expression for \\ref The_Hessian_of_the_Lagragian.\n\n    \\param[in] new_lambda\n    is true if the previous call to eval_h had the same value for\n    lambda and false otherwise.\n    (Not currently used.)\n\n    \\param[in] nele_hess\n    is the number of possibly non-zero elements in the\n    Hessian of the Lagragian;\n    i.e., must be equal to nx_*(nx_+1)/2.\n\n    \\param iRow\n    if values is not NULL, iRow is not defined.\n    if values is NULL, iRow\n    is a vector with size nele_hess.\n    The input value of its elements does not matter.\n    On output,\n    For <tt>k = 0 , ... , nele_hess-1, iRow[k]</tt> is the\n    base zero row index for the\n    k-th possibly non-zero entry in the Hessian of the Lagragian.\n\n    \\param jCol\n    if values is not NULL, jCol is not defined.\n    if values is NULL, jCol\n    is a vector with size nele_hess.\n    The input value of its elements does not matter.\n    On output,\n    For <tt>k = 0 , ... , nele_hess-1, jCol[k]</tt> is the\n    base zero column index for the\n    k-th possibly non-zero entry in the Hessian of the Lagragian.\n\n    \\param values\n    if values is not NULL, it\n    is a vector with size nele_hess.\n    The input value of its elements does not matter.\n    On output,\n    For <tt>k = 0 , ... , nele_hess-1, values[k]</tt> is the\n    value for the\n    k-th possibly non-zero entry in the Hessian of the Lagragian.\n\n    \\return\n    The return value is always true; see \\ref Evaluation_Methods.\n    */\n    virtual bool eval_h(\n        Index         n              ,\n        const Number* x              ,\n        bool          new_x          ,\n        Number        obj_factor     ,\n        Index         m              ,\n        const Number* lambda         ,\n        bool          new_lambda     ,\n        Index         nele_hess      ,\n        Index*        iRow           ,\n        Index*        jCol           ,\n        Number*       values         )\n    {   size_t i, j, k;\n        CPPAD_ASSERT_UNKNOWN(static_cast<size_t>(m) == ng_ );\n        CPPAD_ASSERT_UNKNOWN(static_cast<size_t>(n) == nx_ );\n        //\n        size_t nk = row_hes_.size();\n        CPPAD_ASSERT_UNKNOWN( static_cast<size_t>(nele_hess) == nk );\n        //\n        if( new_x )\n            cache_new_x(x);\n        //\n        if( values == NULL )\n        {   for(k = 0; k < nk; k++)\n            {   i = row_hes_[k];\n                j = col_hes_[k];\n                iRow[k] = static_cast<Index>(i);\n                jCol[k] = static_cast<Index>(j);\n            }\n            return true;\n        }\n        //\n        if( nk == 0 )\n            return true;\n\n        // weigting vector for Lagragian\n        Dvector w(nf_ + ng_);\n        for(i = 0; i < nf_; i++)\n            w[i] = obj_factor;\n        for(i = 0; i < ng_; i++)\n            w[i + nf_] = lambda[i];\n        //\n        if( sparse_forward_ | sparse_reverse_ )\n        {   Dvector hes(nk);\n            adfun_.SparseHessian(\n                x0_, w, pattern_hes_, row_hes_, col_hes_, hes, work_hes_\n            );\n            for(k = 0; k < nk; k++)\n                values[k] = hes[k];\n        }\n        else\n        {   Dvector hes(nx_ * nx_);\n            hes = adfun_.Hessian(x0_, w);\n            for(k = 0; k < nk; k++)\n            {   i = row_hes_[k];\n                j = col_hes_[k];\n                values[k] = hes[i * nx_ + j];\n            }\n        }\n        return true;\n    }\n    // ----------------------------------------------------------------------\n    /*!\n    Pass solution information from Ipopt to users solution structure.\n\n    \\param[in] status\n    is value that the Ipopt solution status\n    which gets mapped to a corresponding value for\n    \\n\n    <tt>solution_.status</tt>\n\n    \\param[in] n\n    is the dimension of the domain space for f(x) and g(x); i.e.,\n    it must be equal to nx_.\n\n    \\param[in] x\n    is a vector with size nx_ specifying the final solution.\n    This is the output value for\n    \\n\n    <tt>solution_.x</tt>\n\n    \\param[in] z_L\n    is a vector with size nx_ specifying the Lagragian multipliers for the\n    constraint \\f$ x^l \\leq x \\f$.\n    This is the output value for\n    \\n\n    <tt>solution_.zl</tt>\n\n    \\param[in] z_U\n    is a vector with size nx_ specifying the Lagragian multipliers for the\n    constraint \\f$ x \\leq x^u \\f$.\n    This is the output value for\n    \\n\n    <tt>solution_.zu</tt>\n\n    \\param[in] m\n    is the dimension of the range space for g(x). i.e.,\n    it must be equal to ng_.\n\n    \\param[in] g\n    is a vector with size ng_ containing the value of the constraint function\n    g(x) at the final solution x.\n    This is the output value for\n    \\n\n    <tt>solution_.g</tt>\n\n    \\param[in] lambda\n    is a vector with size ng_ specifying the Lagragian multipliers for the\n    constraints \\f$ g^l \\leq g(x) \\leq g^u \\f$.\n    This is the output value for\n    \\n\n    <tt>solution_.lambda</tt>\n\n    \\param[in] obj_value\n    is the value of the objective function f(x) at the final solution x.\n    This is the output value for\n    \\n\n    <tt>solution_.obj_value</tt>\n\n    \\param[in] ip_data\n    is unspecified (by Ipopt) and hence not used.\n\n    \\param[in] ip_cq\n    is unspecified (by Ipopt) and hence not used.\n\n    \\par solution_[out]\n    this is a reference to the solution argument\n    in the constructor for solve_callback.\n    The results are stored here\n    (see documentation above).\n    */\n    virtual void finalize_solution(\n        Ipopt::SolverReturn               status    ,\n        Index                             n         ,\n        const Number*                     x         ,\n        const Number*                     z_L       ,\n        const Number*                     z_U       ,\n        Index                             m         ,\n        const Number*                     g         ,\n        const Number*                     lambda    ,\n        Number                            obj_value ,\n        const Ipopt::IpoptData*           ip_data   ,\n        Ipopt::IpoptCalculatedQuantities* ip_cq\n    )\n    {   size_t i, j;\n\n        CPPAD_ASSERT_UNKNOWN(static_cast<size_t>(n) == nx_ );\n        CPPAD_ASSERT_UNKNOWN(static_cast<size_t>(m) == ng_ );\n\n        switch(status)\n        {   // convert status from Ipopt enum to solve_result<Dvector> enum\n            case Ipopt::SUCCESS:\n            solution_.status = solve_result<Dvector>::success;\n            break;\n\n            case Ipopt::MAXITER_EXCEEDED:\n            solution_.status =\n                solve_result<Dvector>::maxiter_exceeded;\n            break;\n\n            case Ipopt::STOP_AT_TINY_STEP:\n            solution_.status =\n                solve_result<Dvector>::stop_at_tiny_step;\n            break;\n\n            case Ipopt::STOP_AT_ACCEPTABLE_POINT:\n            solution_.status =\n                solve_result<Dvector>::stop_at_acceptable_point;\n            break;\n\n            case Ipopt::LOCAL_INFEASIBILITY:\n            solution_.status =\n                solve_result<Dvector>::local_infeasibility;\n            break;\n\n            case Ipopt::USER_REQUESTED_STOP:\n            solution_.status =\n                solve_result<Dvector>::user_requested_stop;\n            break;\n\n            case Ipopt::DIVERGING_ITERATES:\n            solution_.status =\n                solve_result<Dvector>::diverging_iterates;\n            break;\n\n            case Ipopt::RESTORATION_FAILURE:\n            solution_.status =\n                solve_result<Dvector>::restoration_failure;\n            break;\n\n            case Ipopt::ERROR_IN_STEP_COMPUTATION:\n            solution_.status =\n                solve_result<Dvector>::error_in_step_computation;\n            break;\n\n            case Ipopt::INVALID_NUMBER_DETECTED:\n            solution_.status =\n                solve_result<Dvector>::invalid_number_detected;\n            break;\n\n            case Ipopt::INTERNAL_ERROR:\n            solution_.status =\n                solve_result<Dvector>::internal_error;\n            break;\n\n            default:\n            solution_.status =\n                solve_result<Dvector>::unknown;\n        }\n\n        solution_.x.resize(nx_);\n        solution_.zl.resize(nx_);\n        solution_.zu.resize(nx_);\n        for(j = 0; j < nx_; j++)\n        {   solution_.x[j]   = x[j];\n            solution_.zl[j]  = z_L[j];\n            solution_.zu[j]  = z_U[j];\n        }\n        solution_.g.resize(ng_);\n        solution_.lambda.resize(ng_);\n        for(i = 0; i < ng_; i++)\n        {   solution_.g[i]      = g[i];\n            solution_.lambda[i] = lambda[i];\n        }\n        solution_.obj_value = obj_value;\n        return;\n    }\n};\n\n} // end namespace ipopt\n} // END_CPPAD_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/ipopt/solve_result.hpp",
    "content": "# ifndef CPPAD_IPOPT_SOLVE_RESULT_HPP\n# define CPPAD_IPOPT_SOLVE_RESULT_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\nnamespace ipopt {\n/*!\n\\file solve_result.hpp\nClass that contains information about solve problem result\n*/\n\n/*!\nClass that contains information about solve problem result\n\n\\tparam Dvector\na simple vector with elements of type double\n*/\ntemplate <class Dvector>\nclass solve_result\n{\npublic:\n    /// possible values for the result status\n    enum status_type {\n        not_defined,\n        success,\n        maxiter_exceeded,\n        stop_at_tiny_step,\n        stop_at_acceptable_point,\n        local_infeasibility,\n        user_requested_stop,\n        feasible_point_found,\n        diverging_iterates,\n        restoration_failure,\n        error_in_step_computation,\n        invalid_number_detected,\n        too_few_degrees_of_freedom,\n        internal_error,\n        unknown\n    };\n\n    /// possible values for solution status\n    status_type status;\n    /// the approximation solution\n    Dvector x;\n    /// Lagrange multipliers corresponding to lower bounds on x\n    Dvector zl;\n    /// Lagrange multipliers corresponding to upper bounds on x\n    Dvector zu;\n    /// value of g(x)\n    Dvector g;\n    /// Lagrange multipliers correspondiing constraints on g(x)\n    Dvector lambda;\n    /// value of f(x)\n    double obj_value;\n    /// constructor initializes solution status as not yet defined\n    solve_result(void)\n    {   status = not_defined; }\n};\n\n} // end namespace ipopt\n} // END_CPPAD_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/ad_tape.hpp",
    "content": "# ifndef CPPAD_LOCAL_AD_TAPE_HPP\n# define CPPAD_LOCAL_AD_TAPE_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/local/define.hpp>\n\nnamespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL__NAMESPACE\n\n/*!\nClass used to hold tape that records AD<Base> operations.\n\n\\tparam Base\nAn <tt>AD<Base></tt> object is used to recording <tt>AD<Base></tt> operations.\n*/\n\ntemplate <class Base>\nclass ADTape {\n    // Friends =============================================================\n\n    // classes -------------------------------------------------------------\n    friend class AD<Base>;\n    friend class ADFun<Base>;\n    friend class atomic_base<Base>;\n    friend class atomic_three<Base>;\n    friend class atomic_four<Base>;\n    friend class discrete<Base>;\n    friend class VecAD<Base>;\n    friend class VecAD_reference<Base>;\n\n    // functions -----------------------------------------------------------\n    // PrintFor\n    friend void CppAD::PrintFor <Base> (\n        const AD<Base>&    flag   ,\n        const char*        before ,\n        const AD<Base>&    var    ,\n        const char*        after\n    );\n    // CondExpOp\n    friend AD<Base> CppAD::CondExpOp <Base> (\n        enum CompareOp  cop          ,\n        const AD<Base> &left         ,\n        const AD<Base> &right        ,\n        const AD<Base> &trueCase     ,\n        const AD<Base> &falseCase\n    );\n    // pow\n    friend AD<Base> CppAD::pow <Base>\n        (const AD<Base> &x, const AD<Base> &y);\n    // azmul\n    friend AD<Base> CppAD::azmul <Base>\n        (const AD<Base> &x, const AD<Base> &y);\n    // Parameter\n    friend bool CppAD::Parameter     <Base>\n        (const AD<Base> &u);\n    // Variable\n    friend bool CppAD::Variable      <Base>\n        (const AD<Base> &u);\n    // operators -----------------------------------------------------------\n    // arithematic binary operators\n# if _MSC_VER && !defined(__clang__)\n    // see https://stackoverflow.com/questions/63288453\n    template <class Type> friend AD<Type> CppAD::operator * <Type>\n        (const AD<Type> &left, const AD<Type> &right);\n# else\n    friend AD<Base> CppAD::operator * <Base>\n        (const AD<Base> &left, const AD<Base> &right);\n# endif\n    friend AD<Base> CppAD::operator + <Base>\n        (const AD<Base> &left, const AD<Base> &right);\n    friend AD<Base> CppAD::operator - <Base>\n        (const AD<Base> &left, const AD<Base> &right);\n    friend AD<Base> CppAD::operator / <Base>\n        (const AD<Base> &left, const AD<Base> &right);\n\n    // comparison operators\n# if _MSC_VER && !defined(__clang__)\n    template <class Type> friend bool CppAD::operator == <Type>\n        (const AD<Type> &left, const AD<Type> &right);\n    template <class Type> friend bool CppAD::operator != <Type>\n        (const AD<Type> &left, const AD<Type> &right);\n# else\n    friend bool CppAD::operator == <Base>\n        (const AD<Base> &left, const AD<Base> &right);\n    friend bool CppAD::operator != <Base>\n        (const AD<Base> &left, const AD<Base> &right);\n# endif\n    friend bool CppAD::operator < <Base>\n        (const AD<Base> &left, const AD<Base> &right);\n    friend bool CppAD::operator <= <Base>\n        (const AD<Base> &left, const AD<Base> &right);\n    friend bool CppAD::operator > <Base>\n        (const AD<Base> &left, const AD<Base> &right);\n    friend bool CppAD::operator >= <Base>\n        (const AD<Base> &left, const AD<Base> &right);\n    // ======================================================================\n\n// --------------------------------------------------------------------------\nprivate:\n    // ----------------------------------------------------------------------\n    // private data\n    /*!\n    Unique identifier for this tape.  It is always greater than\n    CPPAD_MAX_NUM_THREADS, and different for every tape (even ones that have\n    been deleted). In addition, id_ % CPPAD_MAX_NUM_THREADS is the thread\n    number for this tape. Set by Independent and effectively const\n    */\n    tape_id_t                    id_;\n    /// Number of independent variables in this tapes reconding.\n    /// Set by Independent and effectively const\n    size_t         size_independent_;\n    /// This is where the information is recorded.\n    local::recorder<Base>              Rec_;\n    // ----------------------------------------------------------------------\n    // private functions\n    //\n    // add a parameter to the tape\n    addr_t RecordParOp(const AD<Base>& y);\n\n    // see CondExp.h\n    void RecordCondExp(\n        enum CompareOp  cop           ,\n        AD<Base>       &returnValue   ,\n        const AD<Base> &left          ,\n        const AD<Base> &right         ,\n        const AD<Base> &trueCase      ,\n        const AD<Base> &falseCase\n    );\n\npublic:\n    // public function only used by CppAD::Independent\n    template <class ADBaseVector>\n    void Independent(\n        ADBaseVector&   x              ,\n        size_t          abort_op_index ,\n        bool            record_compare ,\n        ADBaseVector&   dynamic\n    );\n\n};\n// ---------------------------------------------------------------------------\n// Private functions\n//\n\n/*!\nPlace a parameter in the tape as a variable.\n\nOn rare occasions it is necessary to place a parameter in the tape; e.g.,\nwhen it is one of the dependent variables.\n\n\\param y\nvalue of the parameter that we are placing in the tape as a variable.\n\n\\return\nvariable index (for this recording) corresponding to the parameter.\n\n\\par 2DO\nAll these operates are preformed in Rec_, so we should\nmove this routine from <tt>ADTape<Base></tt> to <tt>recorder<Base></tt>.\n*/\ntemplate <class Base>\naddr_t ADTape<Base>::RecordParOp(const AD<Base>& y)\n{   CPPAD_ASSERT_UNKNOWN( NumRes(ParOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumArg(ParOp) == 1 );\n    addr_t z_taddr = Rec_.PutOp(ParOp);\n    if( Dynamic(y) )\n    {   addr_t ind  = y.taddr_;\n        Rec_.PutArg(ind);\n    }\n    else\n    {   addr_t ind  = Rec_.put_con_par(y.value_);\n        Rec_.PutArg(ind);\n    }\n    return z_taddr;\n}\n\n} } // END_CPPAD_LOCAL_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/atom_state.hpp",
    "content": "# ifndef CPPAD_LOCAL_ATOM_STATE_HPP\n# define CPPAD_LOCAL_ATOM_STATE_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\nnamespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE\n\nenum enum_atom_state {\n    /// next AFunOp marks beginning of a atomic function call\n    start_atom,\n\n    /// next FunapOp (FunavOp) is a parameter (variable) argument\n    arg_atom,\n\n    /// next FunrpOp (FunrvOp) is a parameter (variable) result\n    ret_atom,\n\n    /// next AFunOp marks end of a atomic function call\n    end_atom\n};\n\n} } // END_CPPAD_LOCAL_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/local/atomic_index.hpp",
    "content": "# ifndef CPPAD_LOCAL_ATOMIC_INDEX_HPP\n# define CPPAD_LOCAL_ATOMIC_INDEX_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*!\n{xrst_begin atomic_index dev}\n\nStore and Retrieve Atomic Function Information by Index\n#######################################################\n\nSyntax\n******\n| *index_out* = ``local::atomic_index<`` *Base* >(\n| |tab| *set_null* , *index_in* , *type* , *name* , *ptr*\n| )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_ATOMIC_INDEX\n    // END_PROTOTYPE\n}\n\nBase\n****\nIs the base type for the tape for the atomic functions\nthat we are using an index to identify.\n\nGet Number Case\n***************\nThe get number case is defined by\n*set_null* is true and *index_in* is zero.\nFor this case, *index_out* is set to\nthe number of atomic functions stored in ``atomic_index`` < *Base* >\nand no information is stored or changed.\nIn this case, the atomic functions correspond to *index_in* from\none to *index_out* inclusive.\n\nset_null\n********\nIf *set_null* is true and *index_in* is zero,\nthis argument is just used to signal the get number case.\nOtherwise, *set_null*\nshould only be true during a call to an atomic function destructor.\nIn this case, the *ptr* corresponding to *index_in*\nis set to null\n(so that CppAD knows the corresponding atomic function no longer works).\n\nindex_in\n********\nIf *index_in* is zero and *set_null* is true,\nthis argument is just used to signal the get number case.\nOtherwise, see below:\n\nzero\n====\nThe value *index_in* should only be zero\nduring a call to an atomic function constructor.\nIn this case, a copy of the input value of\n*type* , * *name* , and *ptr* are stored.\nThe value *index_out*\nis the *index_in* value corresponding to these input values.\n\nnon-zero\n========\nIf *index_in* is non-zero,\nthe information corresponding to this index is returned.\n\ntype\n****\nThis argument is not used in the get number case.\nOtherwise if *index_in* is zero, *type* is an input.\nOtherwise it is set to the value corresponding to *index_in* .\nThe type corresponding to an index is intended to be\n2 for :ref:`atomic_two-name` functions,\n3 for :ref:`atomic_three-name` functions, and\n4 for :ref:`atomic_four-name` functions,\n\nname\n****\nThis argument is not used in the get number case.\nOtherwise if *index_in* is zero,\n*name* is an input and must not be null.\nOtherwise, if *name* is not null, * *name*\nis set to the name corresponding to *index_in* .\nAllowing for *name* to be null avoids\na string copy when it is not needed.\n\nptr\n***\nThis argument is not used in the get number case.\nOtherwise if *index_in* is zero, *ptr* is an input.\nOtherwise it is set to the value corresponding to *index_in* .\nIn the special case where *set_null* is true,\n*ptr* is set to the null pointer and this is the *ptr* value\ncorresponding to *index_in* for future calls to ``atomic_index`` .\n\nindex_out\n*********\nIn the get number case, this is the number of atomic functions.\nOtherwise if *index_in* is zero,\n*index_out* is non-zero and is the *index_in* value\ncorresponding to the input values for\n*type* , * *name* , and *ptr* .\nOtherwise, *index_out* is zero.\n\n{xrst_end atomic_index}\n*/\n# include <vector>\n# include <cppad/utility/thread_alloc.hpp>\n\nnamespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE\n\nstruct atomic_index_info {\n    size_t      type;\n    std::string name;\n    void*       ptr;\n};\n\n// BEGIN_ATOMIC_INDEX\ntemplate <class Base>\nsize_t atomic_index(\n    bool               set_null      ,\n    const size_t&      index_in      ,\n    size_t&            type          ,\n    std::string*       name          ,\n    void*&             ptr           )\n// END_PROTOTYPE\n{   //\n    // information for each index\n    static std::vector<atomic_index_info> vec;\n# ifndef NDEBUG\n    if( index_in == 0 || set_null )\n    {   CPPAD_ASSERT_KNOWN( ! thread_alloc::in_parallel(),\n        \"calling atomic function constructor or destructor in parallel mode\"\n        );\n    }\n# endif\n    if( set_null & (index_in == 0) )\n        return vec.size();\n    //\n    // case were we are retrieving information for an atomic function\n    if( 0 < index_in )\n    {   CPPAD_ASSERT_UNKNOWN( index_in <= vec.size() )\n        //\n        // case where we are setting the pointer to null\n        if( set_null )\n            vec[index_in-1].ptr = nullptr;\n        //\n        atomic_index_info& entry = vec[index_in - 1];\n        type = entry.type;\n        ptr  = entry.ptr;\n        if( name != nullptr )\n            *name  = entry.name;\n        return 0;\n    }\n    //\n    // case where we are storing information for an atomic function\n    atomic_index_info entry;\n    entry.type = type;\n    entry.name = *name;\n    entry.ptr  = ptr;\n    vec.push_back(entry);\n    //\n    return vec.size();\n}\n\n} } // END_CPPAD_LOCAL_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/color_general.hpp",
    "content": "# ifndef CPPAD_LOCAL_COLOR_GENERAL_HPP\n# define CPPAD_LOCAL_COLOR_GENERAL_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/configure.hpp>\n# include <cppad/local/cppad_colpack.hpp>\n\nnamespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE\n/*!\n\\file color_general.hpp\nColoring algorithm for a general sparse matrix.\n*/\n// --------------------------------------------------------------------------\n/*!\nDetermine which rows of a general sparse matrix can be computed together;\ni.e., do not have non-zero entries with the same column index.\n\n\\tparam SizeVector\nis a simple vector class with elements of type size_t.\n\n\\tparam SetVector\nis vector_of_sets class.\n\n\\param pattern [in]\nIs a representation of the sparsity pattern for the matrix.\n\n\\param row [in]\nis a vector specifying which row indices to compute.\n\n\\param col [in]\nis a vector, with the same size as row,\nthat specifies which column indices to compute.\nFor each  valid index k, the index pair\n<code>(row[k], col[k])</code> must be present in the sparsity pattern.\nIt may be that some entries in the sparsity pattern do not need to be computed;\ni.e, do not appear in the set of\n<code>(row[k], col[k])</code> entries.\n\n\\param color [out]\nis a vector with size m.\nThe input value of its elements does not matter.\nUpon return, it is a coloring for the rows of the sparse matrix.\n\\n\n\\n\nIf for some i, <code>color[i] == m</code>, then\nthe i-th row does not appear in the vector row.\nOtherwise, <code>color[i] < m</code>.\n\\n\n\\n\nSuppose two different rows, <code>i != r</code> have the same color and\ncolumn index j is such that both of the pairs\n<code>(i, j)</code> and <code>(r, j)</code> appear in the sparsity pattern.\nIt follows that neither of these pairs appear in the set of\n<code>(row[k], col[k])</code> entries.\n\\n\n\\n\nThis routine tries to minimize, with respect to the choice of colors,\nthe maximum, with respct to k, of <code>color[ row[k] ]</code>\n(not counting the indices k for which row[k] == m).\n*/\ntemplate <class SetVector, class SizeVector>\nvoid color_general_cppad(\n    const SetVector&        pattern ,\n    const SizeVector&       row     ,\n    const SizeVector&       col     ,\n    CppAD::vector<size_t>&  color   )\n{\n    size_t K = row.size();\n    size_t m = pattern.n_set();\n    size_t n = pattern.end();\n\n    CPPAD_ASSERT_UNKNOWN( size_t( col.size() )   == K );\n    CPPAD_ASSERT_UNKNOWN( size_t( color.size() ) == m );\n\n    // We define the set of rows, columns, and pairs that appear\n    // by the set ( row[k], col[k] ) for k = 0, ... , K-1.\n\n    // initialize rows that appear\n    CppAD::vector<bool> row_appear(m);\n    for(size_t i = 0; i < m; i++)\n            row_appear[i] = false;\n\n    // rows and columns that appear\n    SetVector c2r_appear, r2c_appear;\n    c2r_appear.resize(n, m);\n    r2c_appear.resize(m, n);\n    for(size_t k = 0;  k < K; k++)\n    {   CPPAD_ASSERT_KNOWN( pattern.is_element(row[k], col[k]) ,\n            \"color_general_cppad: requesting value for a matrix element\\n\"\n            \"that is not in the matrice's sparsity pattern.\\n\"\n            \"Such a value must be zero.\"\n        );\n        row_appear[ row[k] ] = true;\n        c2r_appear.post_element(col[k], row[k]);\n        r2c_appear.post_element(row[k], col[k]);\n    }\n    // process posts\n    for(size_t j = 0; j < n; ++j)\n        c2r_appear.process_post(j);\n    for(size_t i = 0; i < m; ++i)\n        r2c_appear.process_post(i);\n\n    // for each column, which rows are non-zero and do not appear\n    SetVector not_appear;\n    not_appear.resize(n, m);\n    for(size_t i = 0; i < m; i++)\n    {   typename SetVector::const_iterator pattern_itr(pattern, i);\n        size_t j = *pattern_itr;\n        while( j != pattern.end() )\n        {   if( ! c2r_appear.is_element(j , i) )\n                not_appear.post_element(j, i);\n            j = *(++pattern_itr);\n        }\n    }\n    // process posts\n    for(size_t j = 0; j < n; ++j)\n        not_appear.process_post(j);\n\n    // initial coloring\n    color.resize(m);\n    size_t ell = 0;\n    for(size_t i = 0; i < m; i++)\n    {   if( row_appear[i] )\n            color[i] = ell++;\n        else\n            color[i] = m;\n    }\n    /*\n    See GreedyPartialD2Coloring Algorithm Section 3.6.2 of\n    Graph Coloring in Optimization Revisited by\n    Assefaw Gebremedhin, Fredrik Maane, Alex Pothen\n\n    The algorithm above was modified (by Brad Bell) to take advantage of the\n    fact that only the entries (subset of the sparsity pattern) specified by\n    row and col need to be computed.\n    */\n    CppAD::vector<bool> forbidden(m);\n    for(size_t i = 1; i < m; i++) // for each row that appears\n    if( color[i] < m )\n    {\n        // initial all colors as ok for this row\n        // (value of forbidden for ell > initial color[i] does not matter)\n        for(ell = 0; ell <= color[i]; ell++)\n            forbidden[ell] = false;\n\n        // -----------------------------------------------------\n        // Forbid colors for which this row would destroy results:\n        //\n        // for each column that is non-zero for this row\n        typename SetVector::const_iterator pattern_itr(pattern, i);\n        size_t j = *pattern_itr;\n        while( j != pattern.end() )\n        {   // for each row that appears with this column\n            typename SetVector::const_iterator c2r_itr(c2r_appear, j);\n            size_t r = *c2r_itr;\n            while( r != c2r_appear.end() )\n            {   // if this is not the same row, forbid its color\n                if( (r < i) && (color[r] < m) )\n                    forbidden[ color[r] ] = true;\n                r = *(++c2r_itr);\n            }\n            j = *(++pattern_itr);\n        }\n\n\n        // -----------------------------------------------------\n        // Forbid colors that destroy results needed for this row.\n        //\n        // for each column that appears with this row\n        typename SetVector::const_iterator r2c_itr(r2c_appear, i);\n        j = *r2c_itr;\n        while( j != r2c_appear.end() )\n        {   // For each row that is non-zero for this column\n            // (the appear rows have already been checked above).\n            typename SetVector::const_iterator not_itr(not_appear, j);\n            size_t r = *not_itr;\n            while( r != not_appear.end() )\n            {   // if this is not the same row, forbid its color\n                if( (r < i) && (color[r] < m) )\n                    forbidden[ color[r] ] = true;\n                r = *(++not_itr);\n            }\n            j = *(++r2c_itr);\n        }\n\n        // pick the color with smallest index\n        ell = 0;\n        while( forbidden[ell] )\n        {   ell++;\n            CPPAD_ASSERT_UNKNOWN( ell <= color[i] );\n        }\n        color[i] = ell;\n    }\n    return;\n}\n\n# if CPPAD_HAS_COLPACK\n/*!\nColpack version of determining which rows of a sparse matrix\ncan be computed together.\n\n\\copydetails color_general\n*/\ntemplate <class SetVector, class SizeVector>\nvoid color_general_colpack(\n    const SetVector&        pattern ,\n    const SizeVector&       row     ,\n    const SizeVector&       col     ,\n    CppAD::vector<size_t>&  color   )\n{\n    size_t m = pattern.n_set();\n    size_t n = pattern.end();\n\n    // Determine number of non-zero entries in each row\n    CppAD::vector<size_t> n_nonzero(m);\n    size_t n_nonzero_total = 0;\n    for(size_t i = 0; i < m; i++)\n    {   n_nonzero[i] = 0;\n        typename SetVector::const_iterator pattern_itr(pattern, i);\n        size_t j = *pattern_itr;\n        while( j != pattern.end() )\n        {   n_nonzero[i]++;\n            j = *(++pattern_itr);\n        }\n        n_nonzero_total += n_nonzero[i];\n    }\n\n    // Allocate memory and fill in Adolc sparsity pattern\n    CppAD::vector<unsigned int*> adolc_pattern(m);\n    CppAD::vector<unsigned int>  adolc_memory(m + n_nonzero_total);\n    size_t i_memory = 0;\n    for(size_t i = 0; i < m; i++)\n    {   adolc_pattern[i]    = adolc_memory.data() + i_memory;\n        CPPAD_ASSERT_KNOWN(\n            std::numeric_limits<unsigned int>::max() >= n_nonzero[i],\n            \"Matrix is too large for colpack\"\n        );\n        adolc_pattern[i][0] = static_cast<unsigned int>( n_nonzero[i] );\n        typename SetVector::const_iterator pattern_itr(pattern, i);\n        size_t j = *pattern_itr;\n        size_t k = 1;\n        while(j != pattern.end() )\n        {\n            CPPAD_ASSERT_KNOWN(\n                std::numeric_limits<unsigned int>::max() >= j,\n                \"Matrix is too large for colpack\"\n            );\n            adolc_pattern[i][k++] = static_cast<unsigned int>( j );\n            j = *(++pattern_itr);\n        }\n        CPPAD_ASSERT_UNKNOWN( k == 1 + n_nonzero[i] );\n        i_memory += k;\n    }\n    CPPAD_ASSERT_UNKNOWN( i_memory == m + n_nonzero_total );\n\n    // Must use an external routine for this part of the calculation because\n    // ColPack/ColPackHeaders.h has as 'using namespace std' at global level.\n    cppad_colpack_general(color, m, n, adolc_pattern);\n\n    return;\n}\n# endif // CPPAD_HAS_COLPACK\n\n} } // END_CPPAD_LOCAL_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/local/color_symmetric.hpp",
    "content": "# ifndef CPPAD_LOCAL_COLOR_SYMMETRIC_HPP\n# define CPPAD_LOCAL_COLOR_SYMMETRIC_HPP\n# include <cppad/configure.hpp>\n# include <cppad/local/cppad_colpack.hpp>\n\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\nnamespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE\n/*!\n\\file color_symmetric.hpp\nColoring algorithm for a symmetric sparse matrix.\n*/\n// --------------------------------------------------------------------------\n/*!\nCppAD algorithm for determining which rows of a symmetric sparse matrix can be\ncomputed together.\n\n\\tparam SizeVector\nis a simple vector class with elements of type size_t.\n\n\\tparam SetVector\nis a vector_of_sets class.\n\n\\param pattern [in]\nIs a representation of the sparsity pattern for the matrix.\n\n\\param row [in/out]\nis a vector specifying which row indices to compute.\n\n\\param col [in/out]\nis a vector, with the same size as row,\nthat specifies which column indices to compute.\n\\n\n\\n\nInput:\nFor each  valid index k, the index pair\n<code>(row[k], col[k])</code> must be present in the sparsity pattern.\nIt may be that some entries in the sparsity pattern do not need to be computed;\ni.e, do not appear in the set of\n<code>(row[k], col[k])</code> entries.\n\\n\n\\n\nOutput:\nOn output, some of row and column indices may have been swapped\n\\code\n    std::swap( row[k], col[k] )\n\\endcode\nSo the the the color for row[k] can be used to compute entry\n(row[k], col[k]).\n\n\\param color [out]\nis a vector with size m.\nThe input value of its elements does not matter.\nUpon return, it is a coloring for the rows of the sparse matrix.\nNote that if color[i] == m, then there is no index k for which\nrow[k] == i (for the return value of row).\n\\n\n\\n\nFix any (i, j) in the sparsity pattern.\nSuppose that there is a row index i1 with\ni1 != i, color[i1] == color[i] and (i1, j) is in the sparsity pattern.\nIf follows that for all j1 with\nj1 != j and color[j1] == color[j],\n(j1, i ) is not in the sparsity pattern.\n\\n\n\\n\nThis routine tries to minimize, with respect to the choice of colors,\nthe maximum, with respect to k, of <code>color[ row[k] ]</code>.\n*/\ntemplate <class SetVector>\nvoid color_symmetric_cppad(\n    const SetVector&        pattern   ,\n    CppAD::vector<size_t>&  row       ,\n    CppAD::vector<size_t>&  col       ,\n    CppAD::vector<size_t>&  color     )\n{\n    size_t K = row.size();\n    size_t m = pattern.n_set();\n    CPPAD_ASSERT_UNKNOWN( m == pattern.end() );\n    CPPAD_ASSERT_UNKNOWN( color.size() == m );\n    CPPAD_ASSERT_UNKNOWN( col.size()   == K );\n\n    // row, column pairs that appear in ( row[k], col[k] )\n    CppAD::vector< std::set<size_t> > pair_needed(m);\n    std::set<size_t>::iterator itr1, itr2;\n    for(size_t k1 = 0;  k1 < K; k1++)\n    {   CPPAD_ASSERT_UNKNOWN( pattern.is_element(row[k1], col[k1]) );\n        pair_needed[ row[k1] ].insert( col[k1] );\n        pair_needed[ col[k1] ].insert( row[k1] );\n    }\n\n    // order the rows descending by number of pairs needed\n    CppAD::vector<size_t> key(m), order2row(m);\n    for(size_t i1 = 0; i1 < m; i1++)\n    {   CPPAD_ASSERT_UNKNOWN( pair_needed[i1].size() <= m );\n        key[i1] = m - pair_needed[i1].size();\n    }\n    CppAD::index_sort(key, order2row);\n\n    // mapping from order index to row index\n    CppAD::vector<size_t> row2order(m);\n    for(size_t o1 = 0; o1 < m; o1++)\n        row2order[ order2row[o1] ] = o1;\n\n    // initial coloring\n    color.resize(m);\n    size_t c1 = 0;\n    for(size_t o1 = 0; o1 < m; o1++)\n    {   size_t i1 = order2row[o1];\n        if( pair_needed[i1].empty() )\n            color[i1] = m;\n        else\n            color[i1] = c1++;\n    }\n\n    // which colors are forbidden for this row\n    CppAD::vector<bool> forbidden(m);\n\n    // must start with row zero so that we remove results computed for it\n    for(size_t o1 = 0; o1 < m; o1++) // for each row that appears (in order)\n    if( color[ order2row[o1] ] < m )\n    {   size_t i1 = order2row[o1];\n        c1 = color[i1];\n\n        // initial all colors as ok for this row\n        // (value of forbidden for c > c1 does not matter)\n        for(size_t c2 = 0; c2 <= c1; c2++)\n            forbidden[c2] = false;\n\n        // -----------------------------------------------------\n        // Forbid grouping with rows that would destroy results that are\n        // needed for this row.\n        itr1 = pair_needed[i1].begin();\n        while( itr1 != pair_needed[i1].end() )\n        {   // entry (i1, j1) is needed for this row\n            size_t j1 = *itr1;\n\n            // Forbid rows i2 != i1 that have non-zero sparsity at (i2, j1).\n            // Note that this is the same as non-zero sparsity at (j1, i2)\n            typename SetVector::const_iterator pattern_itr(pattern, j1);\n            size_t i2 = *pattern_itr;\n            while( i2 != pattern.end() )\n            {   size_t c2 = color[i2];\n                if( c2 < c1 )\n                    forbidden[c2] = true;\n                i2 = *(++pattern_itr);\n            }\n            itr1++;\n        }\n        // -----------------------------------------------------\n        // Forbid grouping with rows that this row would destroy results for\n        for(size_t o2 = 0; o2 < o1; o2++)\n        {   size_t i2 = order2row[o2];\n            size_t c2 = color[i2];\n            itr2 = pair_needed[i2].begin();\n            while( itr2 != pair_needed[i2].end() )\n            {   size_t j2 = *itr2;\n                // row i2 needs pair (i2, j2).\n                // Forbid grouping with i1 if (i1, j2) has non-zero sparsity\n                if( pattern.is_element(i1, j2) )\n                    forbidden[c2] = true;\n                itr2++;\n            }\n        }\n\n        // pick the color with smallest index\n        size_t c2 = 0;\n        while( forbidden[c2] )\n        {   c2++;\n            CPPAD_ASSERT_UNKNOWN( c2 <= c1 );\n        }\n        color[i1] = c2;\n\n        // no longer need results that are computed by this row\n        itr1 = pair_needed[i1].begin();\n        while( itr1 != pair_needed[i1].end() )\n        {   size_t j1 = *itr1;\n            if( row2order[j1] > o1 )\n            {   itr2 = pair_needed[j1].find(i1);\n                if( itr2 != pair_needed[j1].end() )\n                {   pair_needed[j1].erase(itr2);\n                    if( pair_needed[j1].empty() )\n                        color[j1] = m;\n                }\n            }\n            itr1++;\n        }\n    }\n\n    // determine which sparsity entries need to be reflected\n    for(size_t k1 = 0; k1 < row.size(); k1++)\n    {   size_t i1   = row[k1];\n        size_t j1   = col[k1];\n        itr1 = pair_needed[i1].find(j1);\n        if( itr1 == pair_needed[i1].end() )\n        {   row[k1] = j1;\n            col[k1] = i1;\n# ifndef NDEBUG\n            itr1 = pair_needed[j1].find(i1);\n            CPPAD_ASSERT_UNKNOWN( itr1 != pair_needed[j1].end() );\n# endif\n        }\n    }\n    return;\n}\n\n// --------------------------------------------------------------------------\n/*!\nColpack algorithm for determining which rows of a symmetric sparse matrix\ncan be computed together.\n\n\\copydetails CppAD::local::color_symmetric_cppad\n*/\ntemplate <class SetVector>\nvoid color_symmetric_colpack(\n    const SetVector&        pattern   ,\n    CppAD::vector<size_t>&  row       ,\n    CppAD::vector<size_t>&  col       ,\n    CppAD::vector<size_t>&  color     )\n{\n# if ! CPPAD_HAS_COLPACK\n    CPPAD_ASSERT_UNKNOWN(false);\n    return;\n# else\n    size_t i, j, k;\n    size_t m = pattern.n_set();\n    CPPAD_ASSERT_UNKNOWN( m == pattern.end() );\n    CPPAD_ASSERT_UNKNOWN( row.size() == col.size() );\n\n    // Determine number of non-zero entries in each row\n    CppAD::vector<size_t> n_nonzero(m);\n    size_t n_nonzero_total = 0;\n    for(i = 0; i < m; i++)\n    {   n_nonzero[i] = 0;\n        typename SetVector::const_iterator pattern_itr(pattern, i);\n        j = *pattern_itr;\n        while( j != pattern.end() )\n        {   n_nonzero[i]++;\n            j = *(++pattern_itr);\n        }\n        n_nonzero_total += n_nonzero[i];\n    }\n\n    // Allocate memory and fill in Adolc sparsity pattern\n    CppAD::vector<unsigned int*> adolc_pattern(m);\n    CppAD::vector<unsigned int>  adolc_memory(m + n_nonzero_total);\n    size_t i_memory = 0;\n    for(i = 0; i < m; i++)\n    {   adolc_pattern[i]    = adolc_memory.data() + i_memory;\n        CPPAD_ASSERT_KNOWN(\n            std::numeric_limits<unsigned int>::max() >= n_nonzero[i],\n            \"Matrix is too large for colpack\"\n        );\n        adolc_pattern[i][0] = static_cast<unsigned int>( n_nonzero[i] );\n        typename SetVector::const_iterator pattern_itr(pattern, i);\n        j = *pattern_itr;\n        k = 1;\n        while(j != pattern.end() )\n        {\n            CPPAD_ASSERT_KNOWN(\n                std::numeric_limits<unsigned int>::max() >= j,\n                \"Matrix is too large for colpack\"\n            );\n            adolc_pattern[i][k++] = static_cast<unsigned int>( j );\n            j = *(++pattern_itr);\n        }\n        CPPAD_ASSERT_UNKNOWN( k == 1 + n_nonzero[i] );\n        i_memory += k;\n    }\n    CPPAD_ASSERT_UNKNOWN( i_memory == m + n_nonzero_total );\n\n    // Must use an external routine for this part of the calculation because\n    // ColPack/ColPackHeaders.h has as 'using namespace std' at global level.\n    cppad_colpack_symmetric(color, m, adolc_pattern);\n\n    // determine which sparsity entries need to be reflected\n    for(size_t k1 = 0; k1 < row.size(); k1++)\n    {   size_t i1 = row[k1];\n        size_t j1 = col[k1];\n        bool reflect = false;\n        for(size_t i2 = 0; i2 < m; i2++)\n        if( (i1 != i2) && (color[i1]==color[i2]) )\n        {   for(size_t k2 = 1; k2 <= adolc_pattern[i2][0]; k2++)\n            {   size_t j2 = adolc_pattern[i2][k2];\n                reflect |= (j1 == j2);\n            }\n        }\n        if( reflect )\n        {   row[k1] = j1;\n            col[k1] = i1;\n        }\n    }\n    return;\n# endif // CPPAD_HAS_COLPACK\n}\n\n} } // END_CPPAD_LOCAL_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/cppad_colpack.hpp",
    "content": "# ifndef CPPAD_LOCAL_CPPAD_COLPACK_HPP\n# define CPPAD_LOCAL_CPPAD_COLPACK_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# if CPPAD_HAS_COLPACK\n\nnamespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE\n/*!\n\\file cppad_colpack.hpp\nExternal interface to Colpack routines used by cppad.\n*/\n// ---------------------------------------------------------------------------\n/*!\nLink from CppAD to ColPack used for general sparse matrices.\n\nThis CppAD library routine is necessary because\n<code>ColPack/ColPackHeaders.h</code> has a\n<code>using namespace std</code> at the global level.\n\n\\param m [in]\nis the number of rows in the sparse matrix\n\n\\param n [in]\nis the number of columns in the sparse matrix.\n\n\\param adolc_pattern [in]\nThis vector has size m,\n<code>adolc_pattern[i][0]</code> is the number of non-zeros in row i.\nFor <code>j = 1 , ... , adolc_sparsity[i]<code>,\n<code>adolc_pattern[i][j]</code> is the column index (base zero) for the\nnon-zeros in row i.\n\n\\param color [out]\nis a vector with size m.\nThe input value of its elements does not matter.\nUpon return, it is a coloring for the rows of the sparse matrix.\n\\n\n\\n\nIf for some i, <code>color[i] == m</code>, then\n<code>adolc_pattern[i][0] == 0</code>.\nOtherwise, <code>color[i] < m</code>.\n\\n\n\\n\nSuppose two different rows, <code>i != r</code> have the same color.\nIt follows that for all column indices j;\nit is not the case that both\n<code>(i, j)</code> and <code>(r, j)</code> appear in the sparsity pattern.\n\\n\n\\n\nThis routine tries to minimize, with respect to the choice of colors,\nthe number of colors.\n*/\nCPPAD_LIB_EXPORT void cppad_colpack_general(\n             CppAD::vector<size_t>&         color         ,\n    size_t                               m             ,\n    size_t                               n             ,\n    const CppAD::vector<unsigned int*>&  adolc_pattern\n);\n\n/*!\nLink from CppAD to ColPack used for symmetric sparse matrices\n(not yet used or tested).\n\nThis CppAD library routine is necessary because\n<code>ColPack/ColPackHeaders.h</code> has a\n<code>using namespace std</code> at the global level.\n\n\\param n [in]\nis the number of rows and columns in the symmetric sparse matrix.\n\n\\param adolc_pattern [in]\nThis vector has size n,\n<code>adolc_pattern[i][0]</code> is the number of non-zeros in row i.\nFor <code>j = 1 , ... , adolc_sparsity[i]<code>,\n<code>adolc_pattern[i][j]</code> is the column index (base zero) for the\nnon-zeros in row i.\n\n\\param color [out]\nThe input value of its elements does not matter.\nUpon return, it is a coloring for the rows of the sparse matrix.\nThe properties of this coloring have not yet been determined; see\nEfficient Computation of Sparse Hessians Using Coloring\nand Automatic Differentiation (pdf/ad/gebemedhin14.pdf)\n*/\nCPPAD_LIB_EXPORT void cppad_colpack_symmetric(\n             CppAD::vector<size_t>&         color         ,\n    size_t                               n             ,\n    const CppAD::vector<unsigned int*>&  adolc_pattern\n);\n\n} } // END_CPPAD_LOCAL_NAMESPACE\n\n# endif\n# endif\n"
  },
  {
    "path": "include/cppad/local/declare_ad.hpp",
    "content": "# ifndef CPPAD_LOCAL_DECLARE_AD_HPP\n# define CPPAD_LOCAL_DECLARE_AD_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/configure.hpp>\n# include <cstdint>\n\n/*!\n\\file declare_ad.hpp CppAD forward declarations; i.e., before definition\n*/\n\nnamespace CppAD { namespace local {\n    template <class Base> class ADTape;\n    template <class Base> class player;\n    template <class Base> class dyn_player;\n    template <class Base> class recorder;\n} }\nnamespace CppAD { namespace local { namespace val_graph {\n    template <class Value> class tape_t;\n} } }\n\nnamespace CppAD {\n    // BEGIN_COMPARE_OP\n    enum CompareOp\n    {   // operator // Rel: description\n        CompareLt,  //  Lt: less than\n        CompareLe,  //  Le: less than or equal\n        CompareEq,  //  Eq: equal\n        CompareGe,  //  Ge: greater than or equal\n        CompareGt,  //  Gt: greater than\n        CompareNe   //  Ne: not equal\n    };\n    // END_COMPARE_OP\n\n    // simple typedefs\n    typedef CPPAD_TAPE_ADDR_TYPE addr_t;\n    typedef CPPAD_TAPE_ID_TYPE   tape_id_t;\n\n    // classes\n    class sparse_hes_work;\n    class sparse_jac_work;\n    class sparse_jacobian_work;\n    class sparse_hessian_work;\n    template <class Base> class AD;\n    template <class Base, class RecBase=Base> class ADFun;\n    template <class Base> class atomic_base;\n    template <class Base> class atomic_three;\n    template <class Base> class atomic_four;\n    template <class Base> class discrete;\n    template <class Base> class VecAD;\n    template <class Base> class VecAD_reference;\n\n    // functions with one VecAD<Base> argument\n    template <class Base> bool Constant          (const VecAD<Base> &u);\n    template <class Base> bool Dynamic           (const VecAD<Base> &u);\n    template <class Base> bool Parameter         (const VecAD<Base> &u);\n    template <class Base> bool Variable          (const VecAD<Base> &u);\n\n    // functions with one AD<Base> argument\n    template <class Base> bool Constant          (const AD<Base> &u);\n    template <class Base> bool Dynamic           (const AD<Base> &u);\n    template <class Base> bool Parameter         (const AD<Base> &u);\n    template <class Base> bool Variable          (const AD<Base> &u);\n    //\n    template <class Base> int  Integer           (const AD<Base> &u);\n    template <class Base> bool IdenticalZero     (const AD<Base> &u);\n    template <class Base> bool IdenticalOne      (const AD<Base> &u);\n    template <class Base> bool IdenticalCon      (const AD<Base> &u);\n    template <class Base> bool LessThanZero      (const AD<Base> &u);\n    template <class Base> bool LessThanOrZero    (const AD<Base> &u);\n    template <class Base> bool GreaterThanZero   (const AD<Base> &u);\n    template <class Base> bool GreaterThanOrZero (const AD<Base> &u);\n    template <class Base> AD<Base> Var2Par       (const AD<Base> &u);\n    template <class Base> AD<Base> abs           (const AD<Base> &u);\n    template <class Base> AD<Base> acos          (const AD<Base> &u);\n    template <class Base> AD<Base> asin          (const AD<Base> &u);\n    template <class Base> AD<Base> atan          (const AD<Base> &u);\n    template <class Base> AD<Base> cos           (const AD<Base> &u);\n    template <class Base> AD<Base> cosh          (const AD<Base> &u);\n    template <class Base> AD<Base> exp           (const AD<Base> &u);\n    template <class Base> AD<Base> log           (const AD<Base> &u);\n    template <class Base> AD<Base> log10         (const AD<Base> &u);\n    template <class Base> AD<Base> sin           (const AD<Base> &u);\n    template <class Base> AD<Base> sinh          (const AD<Base> &u);\n    template <class Base> AD<Base> sqrt          (const AD<Base> &u);\n    template <class Base> AD<Base> tan           (const AD<Base> &u);\n    //\n    template <class Base> unsigned short hash_code(const AD<Base>& u);\n\n    // arithematic operators\n    template <class Base> AD<Base> operator + (\n        const AD<Base> &left, const AD<Base> &right);\n    template <class Base> AD<Base> operator - (\n        const AD<Base> &left, const AD<Base> &right);\n    template <class Base> AD<Base> operator * (\n        const AD<Base> &left, const AD<Base> &right);\n    template <class Base> AD<Base> operator / (\n        const AD<Base> &left, const AD<Base> &right);\n\n    // comparison operators\n    template <class Base> bool operator < (\n        const AD<Base> &left, const AD<Base> &right);\n    template <class Base> bool operator <= (\n        const AD<Base> &left, const AD<Base> &right);\n    template <class Base> bool operator > (\n        const AD<Base> &left, const AD<Base> &right);\n    template <class Base> bool operator >= (\n        const AD<Base> &left, const AD<Base> &right);\n    template <class Base> bool operator == (\n        const AD<Base> &left, const AD<Base> &right);\n    template <class Base> bool operator != (\n        const AD<Base> &left, const AD<Base> &right);\n\n    // pow\n    template <class Base> AD<Base> pow (\n        const AD<Base> &x, const AD<Base> &y);\n\n    // azmul\n    template <class Base> AD<Base> azmul (\n        const AD<Base> &x, const AD<Base> &y);\n\n    // NearEqual\n    template <class Base> bool NearEqual(\n    const AD<Base> &x, const AD<Base> &y, const Base &r, const Base &a);\n\n    template <class Base> bool NearEqual(\n    const Base &x, const AD<Base> &y, const Base &r, const Base &a);\n\n    template <class Base> bool NearEqual(\n    const AD<Base> &x, const Base &y, const Base &r, const Base &a);\n\n    // CondExpOp\n    template <class Base> AD<Base> CondExpOp (\n        enum CompareOp         cop ,\n        const AD<Base>       &left ,\n        const AD<Base>      &right ,\n        const AD<Base>   &trueCase ,\n        const AD<Base>  &falseCase\n    );\n\n    // IdenticalEqualCon\n    template <class Base>\n    bool IdenticalEqualCon (const AD<Base> &u, const AD<Base> &v);\n\n    // EqualOpSeq\n    template <class Base>\n    bool EqualOpSeq (const AD<Base> &u, const AD<Base> &v);\n\n    // PrintFor\n    template <class Base>\n    void PrintFor(\n        const AD<Base>&    flag   ,\n        const char*        before ,\n        const AD<Base>&    var    ,\n        const char*        after\n    );\n\n    // Value\n    template <class Base> Base Value(const AD<Base> &x);\n\n    // Pow function\n    template <class Base> AD<Base> pow\n        (const AD<Base> &x, const AD<Base> &y);\n\n    // input operator\n    template <class Base> std::istream&\n        operator >> (std::istream &is, AD<Base> &x);\n\n    // output operator\n    template <class Base> std::ostream&\n        operator << (std::ostream &os, const AD<Base> &x);\n    template <class Base> std::ostream&\n        operator << (std::ostream &os, const VecAD_reference<Base> &e);\n    template <class Base> std::ostream&\n        operator << (std::ostream &os, const VecAD<Base> &vec);\n}\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/define.hpp",
    "content": "# ifndef CPPAD_LOCAL_DEFINE_HPP\n# define CPPAD_LOCAL_DEFINE_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*!\n\\file define.hpp\nDefine processor symbols and macros that are used by CppAD.\n*/\n\n/*!\n\\def CPPAD_VEC_ENUM_TYPE\nIs the type used to store vectors of enum values when the vector\nmay be large and we want to conserve memory. The following must hold for\nany enum_value that is stored using the type CPPAD_VEC_ENUM_TYPE:\n<code>\n        size_t(enum_value) <= std::numeric_limits<CPPAD_VEC_ENUM_TYPE>::max()\n        && is_pod<CPPAD_VEC_ENUM_TYPE>\n</code>\n*/\n# define CPPAD_VEC_ENUM_TYPE unsigned char\n\n// ----------------------------------------------------------------------------\n/*!\n\\def CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION\nA version of the inline command that works with MC compiler.\n\nMicrosoft Visual C++ version 9.0 generates a warning if a template\nfunction is declared as a friend\n(this was not a problem for version 7.0).\nThe warning identifier is\n\\verbatim\n    warning C4396\n\\endverbatim\nand it contains the text\n\\verbatim\n    the inline specifier cannot be used when a friend declaration refers\n    to a specialization of a function template\n\\endverbatim\nThis happens even if the function is not a specialization.\nThis macro is defined as empty for Microsoft compilers.\n*/\n# ifdef _MSC_VER\n# define CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION\n# else\n# define CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION inline\n# endif\n\n// ----------------------------------------------------------------------------\n/*!\n\\def CPPAD_LIB_EXPORT\nSpecial macro for exporting windows DLL symbols; see\nhttps://gitlab.kitware.com/cmake/community/wikis/doc/tutorials/BuildingWinDLL\n*/\n/*\nThis commented out code is for building windows shared libraries which\ncurrently does not work for CppAD:\n# ifdef  _MSC_VER\n# ifdef  cppad_lib_EXPORTS\n# define CPPAD_LIB_EXPORT __declspec(dllexport)\n# else\n# define CPPAD_LIB_EXPORT __declspec(dllimport)\n# endif  // cppad_lib_EXPORTS\n# else   // _MSC_VER\n# define CPPAD_LIB_EXPORT\n# endif\n*/\n# define CPPAD_LIB_EXPORT\n\n// ============================================================================\n/*!\n\\def CPPAD_FOLD_ASSIGNMENT_OPERATOR(Op)\nDeclares automatic coercion for certain AD assignment operations.\n\nThis macro assumes that the operator\n\\verbatim\n    left Op right\n\\endverbatim\nis defined for the case where left and right have type AD<Base>.\nIt uses this case to define the cases where\nleft has type AD<Base> and right has type\nVecAD_reference<Base>,\nBase, or\ndouble.\nThe argument right is const and call by reference.\nThis macro converts the operands to AD<Base> and then\nuses the definition of the same operation for that case.\n*/\n\n# define CPPAD_FOLD_ASSIGNMENT_OPERATOR(Op)                             \\\n/* ----------------------------------------------------------------*/   \\\ntemplate <class Base>                                                   \\\nAD<Base>& operator Op                                            \\\n(AD<Base> &left, double right)                                          \\\n{   return left Op AD<Base>(right); }                                  \\\n                                                                        \\\ntemplate <class Base>                                                   \\\nAD<Base>& operator Op                                            \\\n(AD<Base> &left, const Base &right)                                     \\\n{   return left Op AD<Base>(right); }                                  \\\n                                                                        \\\ninline AD<double>& operator Op                                          \\\n(AD<double> &left, const double &right)                                 \\\n{   return left Op AD<double>(right); }                                \\\n                                                                        \\\ntemplate <class Base>                                                   \\\nAD<Base>& operator Op                                            \\\n(AD<Base> &left, const VecAD_reference<Base> &right)                    \\\n{   return left Op right.ADBase(); }\n\n// =====================================================================\n/*!\n\\def CPPAD_FOLD_AD_VALUED_BINARY_OPERATOR(Op)\nDeclares automatic coercion for certain binary operations with AD result.\n\nThis macro assumes that the operator\n\\verbatim\n    left Op right\n\\endverbatim\nis defined for the case where left and right\nand the result of the operation all\nhave type AD<Base>.\nIt uses this case to define the cases either left\nor right has type VecAD_reference<Base> or AD<Base>\nand the type of the other operand is one of the following:\nVecAD_reference<Base>, AD<Base>, Base, double.\nAll of the arguments are const and call by reference.\nThis macro converts the operands to AD<Base> and then\nuses the definition of the same operation for that case.\n*/\n# define CPPAD_FOLD_AD_VALUED_BINARY_OPERATOR(Op)                      \\\n/* ----------------------------------------------------------------*/  \\\n/* Operations with VecAD_reference<Base> and AD<Base> only*/           \\\n                                                                                              \\\ntemplate <class Base>                                                  \\\nAD<Base> operator Op                                            \\\n(const AD<Base> &left, const VecAD_reference<Base> &right)             \\\n{   return left Op right.ADBase(); }                                  \\\n                                                                                              \\\ntemplate <class Base>                                                  \\\nAD<Base> operator Op                                            \\\n(const VecAD_reference<Base> &left, const VecAD_reference<Base> &right)\\\n{   return left.ADBase() Op right.ADBase(); }                         \\\n                                                                                              \\\ntemplate <class Base>                                                  \\\nAD<Base> operator Op                                            \\\n    (const VecAD_reference<Base> &left, const AD<Base> &right)        \\\n{   return left.ADBase() Op right; }                                  \\\n/* ----------------------------------------------------------------*/  \\\n/* Operations Base */                                                  \\\n                                                                                              \\\ntemplate <class Base>                                                  \\\nAD<Base> operator Op                                            \\\n    (const Base &left, const AD<Base> &right)                         \\\n{   return AD<Base>(left) Op right; }                                 \\\n                                                                                              \\\ntemplate <class Base>                                                  \\\nAD<Base> operator Op                                            \\\n    (const Base &left, const VecAD_reference<Base> &right)            \\\n{   return AD<Base>(left) Op right.ADBase(); }                        \\\n                                                                                              \\\ntemplate <class Base>                                                  \\\nAD<Base> operator Op                                            \\\n    (const AD<Base> &left, const Base &right)                         \\\n{   return left Op AD<Base>(right); }                                 \\\n                                                                                              \\\ntemplate <class Base>                                                  \\\nAD<Base> operator Op                                            \\\n    (const VecAD_reference<Base> &left, const Base &right)            \\\n{   return left.ADBase() Op AD<Base>(right); }                        \\\n                                                                                              \\\n/* ----------------------------------------------------------------*/  \\\n/* Operations double */                                                \\\n                                                                                              \\\ntemplate <class Base>                                                  \\\nAD<Base> operator Op                                            \\\n    (const double &left, const AD<Base> &right)                       \\\n{   return AD<Base>(left) Op right; }                                 \\\n                                                                                              \\\ntemplate <class Base>                                                  \\\nAD<Base> operator Op                                            \\\n    (const double &left, const VecAD_reference<Base> &right)          \\\n{   return AD<Base>(left) Op right.ADBase(); }                        \\\n                                                                                              \\\ntemplate <class Base>                                                  \\\nAD<Base> operator Op                                            \\\n    (const AD<Base> &left, const double &right)                       \\\n{   return left Op AD<Base>(right); }                                 \\\n                                                                                              \\\ntemplate <class Base>                                                  \\\nAD<Base> operator Op                                            \\\n    (const VecAD_reference<Base> &left, const double &right)          \\\n{   return left.ADBase() Op AD<Base>(right); }                        \\\n/* ----------------------------------------------------------------*/  \\\n/* Special case to avoid ambiguity when Base is double */              \\\n                                                                                              \\\ninline AD<double> operator Op                                          \\\n    (const double &left, const AD<double> &right)                     \\\n{   return AD<double>(left) Op right; }                               \\\n                                                                                              \\\ninline AD<double> operator Op                                          \\\n    (const double &left, const VecAD_reference<double> &right)        \\\n{   return AD<double>(left) Op right.ADBase(); }                      \\\n                                                                                              \\\ninline AD<double> operator Op                                          \\\n    (const AD<double> &left, const double &right)                     \\\n{   return left Op AD<double>(right); }                               \\\n                                                                                              \\\ninline AD<double> operator Op                                          \\\n    (const VecAD_reference<double> &left, const double &right)        \\\n{   return left.ADBase() Op AD<double>(right); }\n\n// =======================================================================\n\n/*!\n\\def CPPAD_FOLD_BOOL_VALUED_BINARY_OPERATOR(Op)\nDeclares automatic coercion for certain binary operations with bool result.\n\nThis macro assumes that the operator\n\\verbatim\n    left Op right\n\\endverbatim\nis defined for the case where left and right\nhave type AD<Base> and the result has type bool.\nIt uses this case to define the cases either left\nor right has type\nVecAD_reference<Base> or AD<Base>\nand the type of the other operand is one of the following:\nVecAD_reference<Base>, AD<Base>, Base, double.\nAll of the arguments are const and call by reference.\nThis macro converts the operands to AD<Base> and then\nuses the definition of the same operation for that case.\n*/\n# define CPPAD_FOLD_BOOL_VALUED_BINARY_OPERATOR(Op)                    \\\n/* ----------------------------------------------------------------*/  \\\n/* Operations with VecAD_reference<Base> and AD<Base> only*/           \\\n                                                                                              \\\ntemplate <class Base>                                                  \\\nbool operator Op                                                \\\n(const AD<Base> &left, const VecAD_reference<Base> &right)             \\\n{   return left Op right.ADBase(); }                                  \\\n                                                                                              \\\ntemplate <class Base>                                                  \\\nbool operator Op                                                \\\n(const VecAD_reference<Base> &left, const VecAD_reference<Base> &right)\\\n{   return left.ADBase() Op right.ADBase(); }                         \\\n                                                                                              \\\ntemplate <class Base>                                                  \\\nbool operator Op                                                \\\n    (const VecAD_reference<Base> &left, const AD<Base> &right)        \\\n{   return left.ADBase() Op right; }                                  \\\n/* ----------------------------------------------------------------*/  \\\n/* Operations Base */                                                  \\\n                                                                                              \\\ntemplate <class Base>                                                  \\\nbool operator Op                                                \\\n    (const Base &left, const AD<Base> &right)                         \\\n{   return AD<Base>(left) Op right; }                                 \\\n                                                                                              \\\ntemplate <class Base>                                                  \\\nbool operator Op                                                \\\n    (const Base &left, const VecAD_reference<Base> &right)            \\\n{   return AD<Base>(left) Op right.ADBase(); }                        \\\n                                                                                              \\\ntemplate <class Base>                                                  \\\nbool operator Op                                                \\\n    (const AD<Base> &left, const Base &right)                         \\\n{   return left Op AD<Base>(right); }                                 \\\n                                                                                              \\\ntemplate <class Base>                                                  \\\nbool operator Op                                                \\\n    (const VecAD_reference<Base> &left, const Base &right)            \\\n{   return left.ADBase() Op AD<Base>(right); }                        \\\n                                                                                              \\\n/* ----------------------------------------------------------------*/  \\\n/* Operations double */                                                \\\n                                                                                              \\\ntemplate <class Base>                                                  \\\nbool operator Op                                                \\\n    (const double &left, const AD<Base> &right)                       \\\n{   return AD<Base>(left) Op right; }                                 \\\n                                                                                              \\\ntemplate <class Base>                                                  \\\nbool operator Op                                                \\\n    (const double &left, const VecAD_reference<Base> &right)          \\\n{   return AD<Base>(left) Op right.ADBase(); }                        \\\n                                                                                              \\\ntemplate <class Base>                                                  \\\nbool operator Op                                                \\\n    (const AD<Base> &left, const double &right)                       \\\n{   return left Op AD<Base>(right); }                                 \\\n                                                                                              \\\ntemplate <class Base>                                                  \\\nbool operator Op                                                \\\n    (const VecAD_reference<Base> &left, const double &right)          \\\n{   return left.ADBase() Op AD<Base>(right); }                        \\\n/* ----------------------------------------------------------------*/  \\\n/* Special case to avoid ambiguity when Base is double */              \\\n                                                                                              \\\ninline bool operator Op                                                \\\n    (const double &left, const AD<double> &right)                     \\\n{   return AD<double>(left) Op right; }                               \\\n                                                                                              \\\ninline bool operator Op                                                \\\n    (const double &left, const VecAD_reference<double> &right)        \\\n{   return AD<double>(left) Op right.ADBase(); }                      \\\n                                                                                              \\\ninline bool operator Op                                                \\\n    (const AD<double> &left, const double &right)                     \\\n{   return left Op AD<double>(right); }                               \\\n                                                                                              \\\ninline bool operator Op                                                \\\n    (const VecAD_reference<double> &left, const double &right)        \\\n{   return left.ADBase() Op AD<double>(right); }\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/graph/cpp_graph_itr.hpp",
    "content": "# ifndef CPPAD_LOCAL_GRAPH_CPP_GRAPH_ITR_HPP\n# define CPPAD_LOCAL_GRAPH_CPP_GRAPH_ITR_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/utility/vector.hpp>\n# include <cppad/local/graph/cpp_graph_op.hpp>\n\n// BEGIN_CPPAD_LOCAL_GRAPH_NAMESPACE\nnamespace CppAD { namespace local { namespace graph {\n\nclass cpp_graph_itr {\n/*\n{xrst_begin cpp_graph_itr_data dev}\n\nC++ AD Graph Iterator Private Member Data\n#########################################\n{xrst_spell_off}\n{xrst_code hpp} */\nprivate:\n    // values set by constructor\n    const vector<graph_op_enum>*   operator_vec_;\n    const vector<size_t>*          operator_arg_;\n    //\n    // set by constructor and ++\n    size_t                         op_index_;\n    size_t                         first_arg_;\n    //\n    // set by set_value\n    graph_op_enum                  op_enum_;\n    size_t                         first_node_;\n    size_t                         n_result_;\n    size_t                         call_id_;\n    vector<size_t>                 str_index_;\n    vector<size_t>                 arg_node_;\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end cpp_graph_itr_data}\n------------------------------------------------------------------------------\n{xrst_begin cpp_graph_itr_set_value dev}\n{xrst_spell\n    str\n}\n\nC++ AD Graph Iterator set_value()\n#################################\n\nSyntax\n******\n| *itr* . ``set_value`` ()\n\nop_index\\_\n**********\nThis input is the operator index for the value we are retrieving.\n\nfirst_arg\\_\n***********\nThis input is the first argument index for the value we are retrieving.\n\nfirst_node\\_\n************\nThe input value of this argument does not matter.\nIt is set to the index in ``operator_arg_``\nof the first node argument for this operator.\n\nop_enum\\_\n*********\nThe input value of this argument does not matter.\nIt is set to the :ref:`graph_op_enum-name` for the operator\n\nstr_index\\_\n***********\nThe input value of this argument does not matter.\nUpon return its size is zero except for the special cases\nlisted below:\n\natom_graph_op, atom4_graph_op\n=============================\nIf *op_enum_* is ``atom_graph_op`` or ``atom4_graph_op`` ,\n``str_index_.size() == 1`` and\n``str_index_[0]`` is the index in\n:ref:`cpp_ad_graph@atomic_name_vec`\nfor the function called by this operator.\n\ndiscrete_graph_op\n=================\nIf *op_enum_* is ``discrete_graph_op`` ,\n``str_index_.size() == 1`` and\n``str_index_[0]`` is the index in\n:ref:`cpp_ad_graph@discrete_name_vec`\nfor the function called by this operator.\n\nprint_graph_op\n==============\nIf *op_enum_* is ``print_graph_op`` ,\n``str_index_.size() == 2`` and\n``str_index_[0]`` ( ``str_index_[1]`` )\nis the index in\n:ref:`cpp_ad_graph@print_text_vec` for the\n:ref:`PrintFor@before`  (:ref:`PrintFor@after` ) text.\n\nn_result\\_\n**********\nThe input value of this argument does not matter.\nThis is set to the number of result nodes for this operator.\n\ncall_id\\_\n*********\nIf *op_enum_* is ``atom4_graph_op`` ,\n``call_id_`` is set to the :ref:`atomic_four_call@call_id`\nfor this function call.\nIf *op_enum_* is ``atom_graph_op`` ,\n``call_id`` is set to zero.\n\narg_node\\_\n**********\nThe input value of this argument does not matter.\nUpon return, its size is the number of arguments,\nthat are node indices, for this operator usage.\nThe value of the elements are the node indices.\n\nPrototype\n*********\n{xrst_spell_off}\n{xrst_code hpp} */\n    void set_value(void)\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end cpp_graph_itr_set_value}\n*/\n{  // initialize output values\n    size_t invalid_index   = std::numeric_limits<size_t>::max();\n    size_t n_arg      = invalid_index;\n    first_node_       = invalid_index;\n    n_result_         = invalid_index;\n    call_id_          = invalid_index;\n    str_index_.resize(0);\n    arg_node_.resize(0);\n    //\n    // op_enum\n    op_enum_          = (*operator_vec_)[op_index_];\n    //\n    // n_result_, n_arg, call_id_, str_index_\n    switch( op_enum_ )\n    {\n        // unary operators\n        case abs_graph_op:\n        case acos_graph_op:\n        case acosh_graph_op:\n        case asin_graph_op:\n        case asinh_graph_op:\n        case atan_graph_op:\n        case atanh_graph_op:\n        case cos_graph_op:\n        case cosh_graph_op:\n        case erf_graph_op:\n        case erfc_graph_op:\n        case exp_graph_op:\n        case expm1_graph_op:\n        case log1p_graph_op:\n        case log_graph_op:\n        case neg_graph_op:\n        case sign_graph_op:\n        case sin_graph_op:\n        case sinh_graph_op:\n        case sqrt_graph_op:\n        case tan_graph_op:\n        case tanh_graph_op:\n        first_node_ = first_arg_;\n        n_result_   = 1;\n        n_arg       = 1;\n        break;\n\n        // binary operators\n        case add_graph_op:\n        case azmul_graph_op:\n        case div_graph_op:\n        case mul_graph_op:\n        case pow_graph_op:\n        case sub_graph_op:\n        first_node_ = first_arg_;\n        n_result_   = 1;\n        n_arg       = 2;\n        break;\n\n        // discrete_graph_op\n        case discrete_graph_op:\n        first_node_ = first_arg_ + 1;\n        str_index_.push_back( (*operator_arg_)[first_node_ - 1] );\n        n_result_   = 1;\n        n_arg       = 1;\n        break;\n\n        // atom_graph_op\n        case atom_graph_op:\n        first_node_ = first_arg_ + 3;\n        str_index_.push_back( (*operator_arg_)[first_node_ - 3] );\n        call_id_    = 0;\n        n_result_   = (*operator_arg_)[first_node_ - 2];\n        n_arg       = (*operator_arg_)[first_node_ - 1];\n        break;\n\n        // atom4_graph_op\n        case atom4_graph_op:\n        first_node_ = first_arg_ + 4;\n        str_index_.push_back( (*operator_arg_)[first_node_ - 4] );\n        call_id_    = (*operator_arg_)[first_node_ - 3];\n        n_result_   = (*operator_arg_)[first_node_ - 2];\n        n_arg       = (*operator_arg_)[first_node_ - 1];\n        break;\n\n        // print_graph_op\n        case print_graph_op:\n        first_node_ = first_arg_ + 2;\n        str_index_.push_back( (*operator_arg_)[first_node_ - 2] );\n        str_index_.push_back( (*operator_arg_)[first_node_ - 1] );\n        n_result_   = 0;\n        n_arg       = 2;\n        break;\n\n\n        // conditional expressions\n        case cexp_eq_graph_op:\n        case cexp_le_graph_op:\n        case cexp_lt_graph_op:\n        first_node_ = first_arg_;\n        n_result_   = 1;\n        n_arg       = 4;\n        break;\n\n        // comparison operators\n        case comp_eq_graph_op:\n        case comp_le_graph_op:\n        case comp_lt_graph_op:\n        case comp_ne_graph_op:\n        first_node_ = first_arg_;\n        n_result_   = 0;\n        n_arg       = 2;\n        break;\n\n        // sum_graph_op\n        case sum_graph_op:\n        first_node_ = first_arg_ + 1;\n        n_result_   = 1;\n        n_arg       = (*operator_arg_)[first_node_ - 1];\n        break;\n\n        default:\n        CPPAD_ASSERT_UNKNOWN(false);\n        break;\n    }\n    // set arg_node\n    arg_node_.resize(n_arg);\n    for(size_t i = 0; i < n_arg; i++)\n        arg_node_[i] = (*operator_arg_)[first_node_ + i];\n\n    return;\n}\n/* %$$\n-------------------------------------------------------------------------------\n{xrst_begin cpp_graph_itr_types dev}\n\nC++ AD Graph Iterator Types\n###########################\n\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    typedef struct {\n        graph_op_enum          op_enum;\n        size_t                 n_result;\n        size_t                 call_id;\n        const vector<size_t>*  str_index_ptr;\n        const vector<size_t>*  arg_node_ptr;\n    } value_type;\n    typedef std::input_iterator_tag    iterator_category;\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end cpp_graph_itr_types}\n------------------------------------------------------------------------------\n{xrst_begin cpp_graph_itr_ctor dev}\n\nC++ AD Graph Iterator Constructors\n##################################\n\nSyntax\n******\n\n| ``cpp_graph_itr`` *default*\n| ``cpp_graph_itr`` *itr* ( *operator_vec* , *operator_arg* , *op_index*\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_CTOR\n    // END_CTOR\n}\n\ndefault\n*******\nThe result of the default constructor can only be used as a target\nfor the assignment operator.\n\noperator_vec\n************\nIs the :ref:`cpp_ad_graph@operator_vec`\nfor the ``cpp_graph`` container that this iterator refers to.\n\noperator_arg\n************\nIs the :ref:`operator_arg<cpp_ad_graph@operator_vec>`\nfor the ``cpp_graph`` container that this iterator refers to.\n\nop_index\n********\nThis must be either zero (the ``begin()`` for the container)\nor equal to the size of *operator_vec*\n(the ``end()`` for the container).\n\n{xrst_end cpp_graph_itr_ctor}\n*/\n    cpp_graph_itr(void)\n    : operator_vec_(nullptr), operator_arg_(nullptr)\n    { }\n    // BEGIN_CTOR\n    cpp_graph_itr(\n        const vector<graph_op_enum>& operator_vec   ,\n        const vector<size_t>&        operator_arg   ,\n        size_t                       op_index       )\n    // END_CTOR\n    :\n    operator_vec_(&operator_vec) ,\n    operator_arg_(&operator_arg) ,\n    op_index_(op_index)\n    {  // end constructor\n        if( op_index == operator_vec.size() )\n            return;\n        //\n        // begin constructor\n        CPPAD_ASSERT_KNOWN( op_index == 0,\n            \"cpp_graph_itr: constructor op_index not 0 or operator_vec.size()\"\n        );\n        // start at the beginning of operator_vec\n        first_arg_ = 0;\n        //\n        // get the value, and first_node_, for this operator\n        set_value();\n    }\n/* %$$\n------------------------------------------------------------------------------\n{xrst_begin cpp_graph_itr_input dev}\n\nC++ AD Graph Iterator Input Operations\n######################################\n\n{xrst_spell_off}\n{xrst_code hpp} */\n    // itr == other\n    bool operator==(const cpp_graph_itr& other) const\n    {  return op_index_ == other.op_index_;\n    }\n    // itr != other\n    bool operator!=(const cpp_graph_itr& other) const\n    {  return op_index_ != other.op_index_;\n    }\n    // *itr\n    value_type operator*(void)\n    {  CPPAD_ASSERT_KNOWN( operator_vec_ != nullptr,\n            \"cpp_graph_itr: attempt to dereference default iterator\"\n        );\n        CPPAD_ASSERT_KNOWN( op_index_ < operator_vec_->size(),\n            \"cpp_graph_itr: attempt to dereference past last element in graph\"\n        );\n        value_type ret;\n        ret.op_enum       = op_enum_;\n        ret.n_result      = n_result_;\n        ret.call_id       = call_id_;\n        ret.str_index_ptr = &str_index_;\n        ret.arg_node_ptr  = &arg_node_;\n        return ret;\n    }\n    // ++itr\n    cpp_graph_itr& operator++(void)\n    {  ++op_index_;\n        first_arg_ = first_node_ + arg_node_.size();\n        set_value();\n        return *this;\n    }\n    // itr++\n    cpp_graph_itr operator++(int)\n    {  cpp_graph_itr ret(*this);\n        ++op_index_;\n        first_arg_ = first_node_ + arg_node_.size();\n        set_value();\n        return ret;\n    }\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end cpp_graph_itr_input}\n*/\n\n};\n\n} } } // END_CPPAD_LOCAL_GRAPH_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/graph/cpp_graph_itr.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin cpp_graph_itr dev}\n\nC++ AD Graph Iterator Class\n###########################\n\nContents\n********\n{xrst_toc_table\n    include/cppad/local/graph/cpp_graph_itr.hpp\n}\n\n{xrst_end cpp_graph_itr}\n"
  },
  {
    "path": "include/cppad/local/graph/cpp_graph_op.hpp",
    "content": "# ifndef CPPAD_LOCAL_GRAPH_CPP_GRAPH_OP_HPP\n# define CPPAD_LOCAL_GRAPH_CPP_GRAPH_OP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cstddef>\n# include <string>\n# include <map>\n\n# include <cppad/utility/vector.hpp>\n# include <cppad/configure.hpp>\n# include <cppad/core/graph/graph_op_enum.hpp>\n\nnamespace CppAD { namespace local { namespace graph {\n/*\n{xrst_begin cpp_graph_op dev}\n\nC++ AD Graph Operators\n######################\n\nNamespace\n*********\nAll of these definitions\nare in the ``CppAD::local::graph`` namespace.\n\nCppAD::graph\n************\n{xrst_spell_off}\n{xrst_code hpp} */\n    using namespace CppAD::graph;\n/* {xrst_code}\n{xrst_spell_on}\n\naddr_t\n******\n{xrst_spell_off}\n{xrst_code hpp} */\n    typedef CPPAD_TAPE_ADDR_TYPE addr_t;\n/* {xrst_code}\n{xrst_spell_on}\n\nop_name2enum\n************\nThis is a mapping from the operator name to its enum value.\nThe name is the operator enum without the ``_operator`` at the end.\n{xrst_spell_off}\n{xrst_code hpp} */\n    extern CPPAD_LIB_EXPORT std::map< std::string, graph_op_enum > op_name2enum;\n/* {xrst_code}\n{xrst_spell_on}\n\nop_enum2fixed_n_arg\n*******************\nThis is the number of arguments for the operators that have\na fixed number of arguments and one result.\nFor other operators, this value is zero.\n{xrst_spell_off}\n{xrst_code hpp} */\n    extern CPPAD_LIB_EXPORT size_t op_enum2fixed_n_arg[];\n/* {xrst_code}\n{xrst_spell_on}\n\nop_enum2name\n************\nThis is mapping from operator enum value to its name.\nIn the ``local::graph`` namespace:\n{xrst_spell_off}\n{xrst_code hpp} */\n    extern CPPAD_LIB_EXPORT const char* op_enum2name[];\n/* {xrst_code}\n{xrst_spell_on}\n\nset_operator_info\n*****************\nThis routine sets the values in\n``op_enum2fixed_n_arg`` ,\n``op_enum2name`` , and\n``op_name2enum`` .\n{xrst_spell_off}\n{xrst_code hpp} */\n    extern CPPAD_LIB_EXPORT void set_operator_info(void);\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end cpp_graph_op}\n*/\n\n} } } // END_CPPAD_LOCAL_GRAPH_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/graph/csrc_writer.hpp",
    "content": "# ifndef CPPAD_LOCAL_GRAPH_CSRC_WRITER_HPP\n# define CPPAD_LOCAL_GRAPH_CSRC_WRITER_HPP\n\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <string>\n# include <cppad/local/graph/cpp_graph_op.hpp>\n\n/*\n{xrst_begin csrc_writer dev}\n\nPrototype for csrc_writer\n#########################\n\nSyntax\n******\n| ``csrc_writer`` ( *csrc* , *graph_obj* , *type*  )\n\nPrototype\n*********\n{xrst_spell_off}\n{xrst_code hpp} */\nnamespace CppAD { namespace local { namespace graph {\n    CPPAD_LIB_EXPORT void csrc_writer(\n        std::ostream&       os          ,\n        const cpp_graph&    graph_obj   ,\n        const std::string&  type\n    );\n} } }\n/* {xrst_code}\n{xrst_spell_on}\n\nSee\n***\n:ref:`cpp_csrc_writer-name`\n\n{xrst_end csrc_writer}\n*/\n\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/graph/json_lexer.hpp",
    "content": "# ifndef CPPAD_LOCAL_GRAPH_JSON_LEXER_HPP\n# define CPPAD_LOCAL_GRAPH_JSON_LEXER_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <string>\n# include <cppad/core/cppad_assert.hpp>\n\n// BEGIN_NAMESPACE_CPPAD_LOCAL_GRAPH\nnamespace CppAD { namespace local { namespace graph {\n\n// ===========================================================================\nclass json_lexer {\n// ===========================================================================\n\n/*\n-------------------------------------------------------------------------------\n{xrst_begin json_lexer_member_data dev}\n\njson lexer: Private Data\n########################\n\nMember Variables\n****************\n\ngraph\\_\n=======\nThe :ref:`json_ad_graph-name` .\n\nindex\\_\n=======\nis the index in the graph for the current character.\nIf a token is returned, this corresponds to the last character\nit the token.\n\nline_number\\_\n=============\nline number in the graph for the current character\n\nchar_number\\_\n=============\ncharacter number in the graph for the current character\n\ntoken\\_\n=======\nused to return tokens.\n\nfunction_name\\_\n===============\nis the function name for this graph.\nThis is initialized as empty,\nshould be set as soon as it is parsed,\nand is used for error reporting.\n\ntoken\n*****\nreturns current value of ``token_`` .\n\nline_number\n***********\nreturns current value of ``line_number_``\n(which corresponds to last character in the token).\n\nchar_number\n***********\nreturns current value of ``char_number_`` .\n(which corresponds to last character in the token).\n\nset_function_name\n*****************\nsets the value of ``function_name_`` .\n\nSource Code\n***********\n{xrst_spell_off}\n{xrst_code hpp} */\nprivate:\n    const std::string& json_;\n    size_t             index_;\n    size_t             line_number_;\n    size_t             char_number_;\n    std::string        token_;\n    std::string        function_name_;\npublic:\n    const std::string& token(void)       const;\n    size_t             line_number(void) const;\n    size_t             char_number(void) const;\n    void               set_function_name(const std::string& function_name);\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end json_lexer_member_data}\n-------------------------------------------------------------------------------\n{xrst_begin json_lexer_report_error dev}\n\njson lexer: Report an Error\n###########################\n\nSyntax\n******\n| *json_lexer* . ``report_error`` ( *expected* , *found* )\n\njson_lexer\n**********\nis a ``local::graph::json_lexer`` object.\n\nexpected\n********\nis the token that is expected.\n\nfound\n*****\nis the token or text that was found.\n\nReport\n******\nThe current CppAD :ref:`ErrorHandler-name` is used to report\nan error parsing this Json AD graph.\n\nPrototype\n*********\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    void report_error(const std::string& expected, const std::string& found);\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end json_lexer_report_error}\n-------------------------------------------------------------------------------\n{xrst_begin json_lexer_next_index dev}\n\njson lexer: Advance Index by One\n################################\n\nSyntax\n******\n\n    *json_lexer* . ``next_index`` ()\n\njson_lexer\n**********\nis a ``local::graph::json_lexer`` object.\n\nindex\\_\n*******\nThe input value of ``index_`` is increased by one.\nIt is an error to call this routine when the input value\nof ``index_`` is greater than or equal ``json_.size()`` .\n\nline_number\\_\n*************\nIf the previous character, before  the call, was a new line,\n``line_number_`` is increased by one.\n\nchar_number\\_\n*************\nIf the previous character, before the call, was a new line,\n``char_number`` is set to one.\nOtherwise, ``char_number_`` is increased by one.\n\nPrototype\n*********\n{xrst_spell_off}\n{xrst_code hpp} */\nprivate:\n    void next_index(void);\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end json_lexer_next_index}\n-------------------------------------------------------------------------------\n{xrst_begin json_lexer_skip_white_space dev}\n\njson lexer: Skip White Space That Separates Tokens\n##################################################\n\nSyntax\n******\n\n    *json_lexer* . ``skip_white_space`` ()\n\njson_lexer\n**********\nis a json lexer object.\n\nDiscussion\n**********\nThis member functions is used to increase ``index_`` until either\na non-white space character is found or ``index_`` is equal\nto ``json_.size()`` .\n\nPrototype\n*********\n{xrst_spell_off}\n{xrst_code hpp} */\nprivate:\n    void skip_white_space(void);\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end json_lexer_skip_white_space}\n-------------------------------------------------------------------------------\n{xrst_begin json_lexer_constructor dev}\n\njson lexer: Constructor\n#######################\n\nSyntax\n******\n\n    ``local::graph::lexer`` *json_lexer* ( *json* )\n\njson\n****\nThe argument *json* is an :ref:`json_ad_graph-name`\nand it is assumed that *json* does not change\nfor as long as *json_lexer* exists.\n\nInitialization\n**************\nThe current token, index, line number, and character number\nare set to the first non white space character in ``json_`` .\nIf this is not a left brace character ``'{'`` ,\nthe error is reported and the constructor does not return.\n\nPrototype\n*********\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    json_lexer(const std::string& json);\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end json_lexer_constructor}\n-------------------------------------------------------------------------------\n{xrst_begin json_lexer_check_next_char dev}\n\nGet and Check Next Single Character Token\n#########################################\n\nSyntax\n******\n\n    *json_lexer* . ``check_next_char`` ( *ch* )\n\nindex\\_\n*******\nThe search for the character starts\nat one greater than the input value for ``index_`` and skips white space.\n\nch\n**\nIs a non white space\nsingle character token that is expected.\nIf this character is not found,\nthe error is reported and this function does not return.\nIn the special case where *ch* is ``'\\0'`` ,\nany non-white space character will be accepted\n(but there must be such a character).\n\ntoken\\_\n*******\nIf this routine returns, ``token_`` has size one\nand contains the character that is found.\n\nPrototype\n*********\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    void check_next_char(char ch);\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end json_lexer_check_next_char}\n-------------------------------------------------------------------------------\n{xrst_begin json_lexer_check_next_string dev}\n\nGet and Check Next Single Character Token\n#########################################\n\nSyntax\n******\n\n    *json_lexer* . ``check_next_string`` ( *expected* )\n\nindex\\_\n*******\nThe search for the string starts\nat one greater than the input value for ``index_`` and skips white space.\n\nexpected\n********\nIs the value (not including double quotes) for the string that is expected.\nIf this string is not found, the error is reported\nand this function does not return.\nIn the special case where *expected* is empty,\nany string will be accepted.\n\ntoken\\_\n*******\nIf this routine returns,\n*token_* is the string that was found.\n\nPrototype\n*********\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    void check_next_string(const std::string& expected);\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end json_lexer_check_next_string}\n-------------------------------------------------------------------------------\n{xrst_begin json_lexer_next_non_neg_int dev}\n\nGet Next Non-Negative Integer\n#############################\n\nSyntax\n******\n\n| |tab| *json_lexer* . ``next_non_neg_int`` ()\n| |tab| *value* = *json_lexer* . ``token2size_t`` ()\n\nindex\\_\n*******\nThe search for the non-negative integer starts\nat one greater than the input value for ``index_`` and skips white space.\n\ntoken\\_\n*******\nis set to the non-negative integer.\nIf the next token is not a non-negative integer,\nthe error is reported and this function does not return.\n\nvalue\n*****\nIf the current token is a non-negative integer,\n*value* is the corresponding value.\n\nPrototype\n*********\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    void next_non_neg_int(void);\n    size_t token2size_t(void) const;\n\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end json_lexer_next_non_neg_int}\n-------------------------------------------------------------------------------\n{xrst_begin json_lexer_next_float dev}\n\nGet Next Floating Point Number\n##############################\n\nSyntax\n******\n\n| |tab| *ok* = *json_lexer* . ``next_float`` ()\n| |tab| *value* = *json_lexer* . ``token2double`` ()\n\nindex\\_\n*******\nThe search for the floating point number starts\nat one greater than the input value for ``index_`` and skips white space.\n\ntoken\\_\n*******\nis set to the floating point number.\nIf the next token is not a floating point number,\nthe error is reported and this function does not return.\n\nvalue\n*****\nIf the current token is a floating point number,\n*value* is the corresponding value.\n\nPrototype\n*********\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    void next_float(void);\n    double token2double(void) const;\n\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end json_lexer_next_float}\n*/\n\n// ==========================================================================\n}; // end class lexer\n// ==========================================================================\n\n\n} } } // END_NAMESPACE_CPPAD_LOCAL_GRAPH\n\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/graph/json_lexer.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin json_lexer dev}\n\nLexical Analysis Class for a Json AD Graph\n##########################################\n\nContents\n********\n{xrst_toc_table\n    include/cppad/local/graph/json_lexer.hpp\n}\n\n{xrst_end json_lexer}\n"
  },
  {
    "path": "include/cppad/local/graph/json_parser.hpp",
    "content": "# ifndef CPPAD_LOCAL_GRAPH_JSON_PARSER_HPP\n# define CPPAD_LOCAL_GRAPH_JSON_PARSER_HPP\n\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <string>\n# include <cppad/utility/vector.hpp>\n# include <cppad/local/graph/cpp_graph_op.hpp>\n# include <cppad/core/graph/cpp_graph.hpp>\n\n/*\n{xrst_begin json_parser dev}\n\nJson AD Graph Parser\n####################\n\nSyntax\n******\n| ``json_parser`` ( *json* , *graph_obj* )\n\njson\n****\nThe :ref:`json_ad_graph-name` .\n\ngraph_obj\n*********\nThis is a ``cpp_graph`` object.\nThe input value of the object does not matter.\nUpon return it is a :ref:`cpp_ad_graph-name` representation of this function.\n\nPrototype\n*********\n{xrst_spell_off}\n{xrst_code hpp} */\nnamespace CppAD { namespace local { namespace graph {\n    CPPAD_LIB_EXPORT void json_parser(\n        const std::string&  json      ,\n        cpp_graph&          graph_obj\n    );\n} } }\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end json_parser}\n*/\n\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/graph/json_writer.hpp",
    "content": "# ifndef CPPAD_LOCAL_GRAPH_JSON_WRITER_HPP\n# define CPPAD_LOCAL_GRAPH_JSON_WRITER_HPP\n\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <string>\n# include <cppad/local/graph/cpp_graph_op.hpp>\n\n/*\n{xrst_begin json_writer dev}\n\nJson AD Graph Writer\n####################\n\nSyntax\n******\n| ``json_writer`` ( *json* , *graph_obj*  )\n\njson\n****\nThe input value of *json* does not matter,\nupon return it a :ref:`json<json_ad_graph-name>` representation of the AD graph.\n\ngraph_obj\n*********\nThis is a ``cpp_graph`` object.\n\nPrototype\n*********\n{xrst_spell_off}\n{xrst_code hpp} */\nnamespace CppAD { namespace local { namespace graph {\n    CPPAD_LIB_EXPORT void json_writer(\n        std::string&       json        ,\n        const cpp_graph&   graph_obj\n    );\n} } }\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end json_writer}\n*/\n\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/hash_code.hpp",
    "content": "# ifndef CPPAD_LOCAL_HASH_CODE_HPP\n# define CPPAD_LOCAL_HASH_CODE_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/core/base_hash.hpp>\n/*!\n\\file local/hash_code.hpp\nCppAD hashing utility.\n*/\n\n\nnamespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE\n/*!\nGeneral purpose hash code for an arbitrary value.\n\n\\tparam Value\nis the type of the argument being hash coded.\nIt should be a plain old data class; i.e.,\nthe values included in the equality operator in the object and\nnot pointed to by the object.\n\n\\param value\nthe value that we are generating a hash code for.\nAll of the fields in value should have been set before the hash code\nis computed (otherwise undefined values are used).\n\n\\return\nis a hash code that is between zero and CPPAD_HASH_TABLE_SIZE - 1.\n\n\\par Checked Assertions\n\\li std::numeric_limits<unsigned short>::max() >= CPPAD_HASH_TABLE_SIZE\n\\li sizeof(value) is even\n\\li sizeof(unsigned short)  == 2\n*/\ntemplate <class Value>\nunsigned short local_hash_code(const Value& value)\n{   CPPAD_ASSERT_UNKNOWN(\n        std::numeric_limits<unsigned short>::max()\n        >=\n        CPPAD_HASH_TABLE_SIZE\n    );\n    CPPAD_ASSERT_UNKNOWN( sizeof(unsigned short) == 2 );\n    CPPAD_ASSERT_UNKNOWN( sizeof(value) % 2  == 0 );\n    //\n    const unsigned short* v\n                 = reinterpret_cast<const unsigned short*>(& value);\n    //\n    size_t i = sizeof(value) / 2 - 1;\n    //\n    size_t sum = v[i];\n    //\n    while(i--)\n        sum += v[i];\n    //\n    unsigned short code = static_cast<unsigned short>(\n        sum % CPPAD_HASH_TABLE_SIZE\n    );\n    return code;\n}\n\n/*!\nSpecialized hash code for a CppAD operator and its arguments.\n\n\\param op\nis the operator that we are computing a hash code for.\nIf it is not one of the following operartors, the operator is not\nhash coded and zero is returned:\n\n\\li unary operators:\nAbsOp, AcosOp, AcoshOp, AsinOp, AsinhOp, AtanOp, AtanhOp, CosOp, CoshOp\nExpOp, Expm1Op, LogOp, Log1pOp, SinOp, SinhOp, SqrtOp, TanOp, TanhOp\n\n\\li binary operators where first argument is a parameter:\nAddpvOp, DivpvOp, MulpvOp, PowpvOp, SubpvOp, ZmulpvOp\n\n\\li binary operators where second argument is a parameter:\nDivvpOp, PowvpOp, SubvpOp, Zmulvp\n\n\\li binary operators where first is an index and second is a variable:\nDisOp\n\n\\li binary operators where both arguments are variables:\nAddvvOp, DivvvOp, MulvvOp, PowvvOp, SubvvOp, ZmulvvOp\n\n\\param arg\nis a vector of length NumArg(op) or 2 (which ever is smaller),\ncontaining the corresponding argument indices for this operator.\n\n\\param npar\nis the number of parameters corresponding to this operation sequence.\n\n\\param par\nis a vector of length npar containing the parameters\nfor this operation sequence; i.e.,\ngiven a parameter index of i, the corresponding parameter value is\n par[i].\n\n\n\\return\nis a hash code that is between zero and CPPAD_HASH_TABLE_SIZE - 1.\n\n\\par Checked Assertions\n op must be one of the operators specified above. In addition,\n\\li std::numeric_limits<unsigned short>::max() >= CPPAD_HASH_TABLE_SIZE\n\\li sizeof(size_t) is even\n\\li sizeof(Base) is even\n\\li sizeof(unsigned short)  == 2\n\\li size_t(op) < size_t(NumberOp) <= CPPAD_HASH_TABLE_SIZE\n\\li if the j-th argument for this operation is a parameter, arg[j] < npar.\n*/\n\ntemplate <class Base>\nunsigned short local_hash_code(\n    op_code_var   op      ,\n    const addr_t* arg     ,\n    size_t        npar    ,\n    const Base*   par     )\n{   CPPAD_ASSERT_UNKNOWN(\n        std::numeric_limits<unsigned short>::max()\n        >=\n        CPPAD_HASH_TABLE_SIZE\n    );\n    CPPAD_ASSERT_UNKNOWN( size_t (op) < size_t(NumberOp) );\n    CPPAD_ASSERT_UNKNOWN( sizeof(unsigned short) == 2 );\n    CPPAD_ASSERT_UNKNOWN( sizeof(addr_t) % 2  == 0 );\n    CPPAD_ASSERT_UNKNOWN( sizeof(Base) % 2  == 0 );\n    unsigned short op_fac = static_cast<unsigned short> (\n        CPPAD_HASH_TABLE_SIZE / static_cast<unsigned short>(NumberOp)\n    );\n    CPPAD_ASSERT_UNKNOWN( op_fac > 0 );\n\n    // number of shorts per addr_t value\n    size_t short_addr_t   = sizeof(addr_t) / 2;\n\n    // initialize with value that separates operators as much as possible\n    unsigned short code = static_cast<unsigned short>(\n        static_cast<unsigned short>(op) * op_fac\n    );\n\n    // now code in the operands\n    size_t i;\n    const unsigned short* v;\n\n    // first argument\n    switch(op)\n    {   // Binary operators where first argument is a parameter.\n        // Code parameters by value instead of\n        // by index for two reasons. One, it gives better separation.\n        // Two, different indices can be same parameter value.\n        case AddpvOp:\n        case DivpvOp:\n        case MulpvOp:\n        case PowpvOp:\n        case SubpvOp:\n        case ZmulpvOp:\n        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 );\n        code += hash_code( par[arg[0]] );\n        //\n        v = reinterpret_cast<const unsigned short*>(arg + 1);\n        i = short_addr_t;\n        while(i--)\n            code += v[i];\n        break;\n\n        // Binary operator where first argument is an index and\n        // second is a variable (same as both variables).\n        case DisOp:\n\n        // Binary operators where both arguments are variables\n        case AddvvOp:\n        case DivvvOp:\n        case MulvvOp:\n        case PowvvOp:\n        case SubvvOp:\n        case ZmulvvOp:\n        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 );\n        v = reinterpret_cast<const unsigned short*>(arg + 0);\n        i = 2 * short_addr_t;\n        while(i--)\n            code += v[i];\n        break;\n\n        // Binary operators where second argument is a parameter.\n        case DivvpOp:\n        case PowvpOp:\n        case SubvpOp:\n        case ZmulvpOp:\n        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 );\n        v = reinterpret_cast<const unsigned short*>(arg + 0);\n        i = short_addr_t;\n        while(i--)\n            code += v[i];\n        code += hash_code( par[arg[1]] );\n        break;\n\n        // Unary operators\n        case AbsOp:\n        case AcosOp:\n        case AcoshOp:\n        case AsinOp:\n        case AsinhOp:\n        case AtanOp:\n        case AtanhOp:\n        case CosOp:\n        case CoshOp:\n        case ErfOp:\n        case ErfcOp:\n        case ExpOp:\n        case Expm1Op:\n        case LogOp:\n        case Log1pOp:\n        case SignOp:\n        case SinOp:\n        case SinhOp:\n        case SqrtOp:\n        case TanOp:\n        case TanhOp:\n        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 || op == ErfOp );\n        v = reinterpret_cast<const unsigned short*>(arg + 0);\n        i = short_addr_t;\n        while(i--)\n            code += v[i];\n        break;\n\n        // should have been one of he cases above\n        default:\n        CPPAD_ASSERT_UNKNOWN(false);\n    }\n\n    return code % CPPAD_HASH_TABLE_SIZE;\n}\n\n} } // END_CPPAD_LOCAL_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/independent.hpp",
    "content": "# ifndef CPPAD_LOCAL_INDEPENDENT_HPP\n# define CPPAD_LOCAL_INDEPENDENT_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\nnamespace CppAD { namespace local { //  BEGIN_CPPAD_LOCAL_NAMESPACE\n/*\n\\file local/independent.hpp\nStart recording AD<Base> operations.\n*/\n\n/*!\nStart recording AD<Base> operations: Implementation in local namespace.\n\n\\tparam ADVector\nThis is simple vector type with elements of type AD<Base>.\n\n\\param x\nVector of the independent variables.\n\n\\param abort_op_index\noperator index at which execution will be aborted (during  the recording\n\n\\param record_compare\nshould comparison operators be recorded.\nof operations). The value zero corresponds to not aborting (will not match).\n\n\\param dynamic\nVector of dynamic parameters.\n*/\ntemplate <class Base>\ntemplate <class ADVector>\nvoid ADTape<Base>::Independent(\n    ADVector&    x               ,\n    size_t       abort_op_index  ,\n    bool         record_compare  ,\n    ADVector&    dynamic\n) {\n    // check ADVector is Simple Vector class with AD<Base> elements\n    CheckSimpleVector< AD<Base>, ADVector>();\n\n    // dimension of the domain space\n    size_t n = x.size();\n    CPPAD_ASSERT_KNOWN(\n        n > 0,\n        \"Independent: the argument vector x has zero size\"\n    );\n    CPPAD_ASSERT_UNKNOWN( Rec_.num_var() == 0 );\n    CPPAD_ASSERT_UNKNOWN( Rec_.get_abort_op_index() == 0 );\n    CPPAD_ASSERT_UNKNOWN( Rec_.get_record_compare() == true );\n    CPPAD_ASSERT_UNKNOWN( Rec_.n_dyn_independent()    == 0 );\n\n    // set record_compare and abort_op_index before doing anything else\n    Rec_.set_record_compare(record_compare);\n    Rec_.set_abort_op_index(abort_op_index);\n    Rec_.set_n_dyn_independent( dynamic.size() );\n\n    // mark the beginning of the tape and skip the first variable index\n    // (zero) because parameters use taddr zero\n    CPPAD_ASSERT_NARG_NRES(BeginOp, 1, 1);\n    Rec_.PutOp(BeginOp);\n    Rec_.PutArg(0);\n\n    // place each of the independent variables in the tape\n    CPPAD_ASSERT_NARG_NRES(InvOp, 0, 1);\n    for(size_t j = 0; j < n; j++)\n    {   // tape address for this independent variable\n        CPPAD_ASSERT_UNKNOWN( ! Variable(x[j] ) );\n        x[j].taddr_     = Rec_.PutOp(InvOp);\n        x[j].tape_id_   = id_;\n        x[j].ad_type_   = variable_enum;\n        CPPAD_ASSERT_UNKNOWN( size_t(x[j].taddr_) == j+1 );\n        CPPAD_ASSERT_UNKNOWN( Variable(x[j] ) );\n    }\n\n    // done specifying all of the independent variables\n    size_independent_ = n;\n\n    // parameter index zero is used by dynamic parameter tape\n    // to indicate that an argument is a variable\n    Base nan = CppAD::numeric_limits<Base>::quiet_NaN();\n# ifndef NDEBUG\n    CPPAD_ASSERT_UNKNOWN( Rec_.put_con_par(nan) == 0 );\n# else\n    Rec_.put_con_par(nan);\n# endif\n\n    // Place independent dynamic parameters at beginning of parameter vector,\n    // just after the nan at index zero.\n    CPPAD_ASSERT_UNKNOWN( Rec_.n_dyn_independent() <= dynamic.size() );\n    for(size_t j = 0; j < Rec_.n_dyn_independent(); ++j)\n    {   CPPAD_ASSERT_UNKNOWN( ! Dynamic( dynamic[j] ) );\n        CPPAD_ASSERT_UNKNOWN( Parameter( dynamic[j] ) );\n        //\n        // dynamic parameters are placed at the end, so i == j\n# ifndef NDEBUG\n        addr_t i = Rec_.put_dyn_par(dynamic[j].value_ , ind_dyn);\n        CPPAD_ASSERT_UNKNOWN( size_t(i) == j+1 );\n# else\n        Rec_.put_dyn_par(dynamic[j].value_ , ind_dyn);\n# endif\n        //\n        // make this parameter dynamic\n        dynamic[j].taddr_   = static_cast<addr_t>(j+1);\n        dynamic[j].tape_id_ = id_;\n        dynamic[j].ad_type_ = dynamic_enum;\n        CPPAD_ASSERT_UNKNOWN( Dynamic( dynamic[j] ) );\n    }\n}\n} } // END_CPPAD_LOCAL_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/is_pod.hpp",
    "content": "# ifndef CPPAD_LOCAL_IS_POD_HPP\n# define CPPAD_LOCAL_IS_POD_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin is_pod dev}\n{xrst_spell\n    nullptr\n}\n\nThe is_pod Template Function\n############################\n\nDefault Definition\n******************\nThe default template definition is that\n\n    ``is_pod`` < *Type* >()\n\nis false for all types.\n\nFundamental Types\n*****************\nThis file specializes ``is_pod`` < *Type* > to be true where *Type*\nis any of the c++11 fundamental types that hold data; i.e.,\n``void`` and ``nullptr_t`` are excluded.\n\nOther Type\n**********\nYou can inform CppAD that a particular *Type* is plain old data by\ndefining\n\n| |tab| ``namespace CppAD`` { ``namespace local`` {\n| |tab| |tab| ``template <> inline bool is_pod<`` *Type* >( ``void`` ) { ``return true`` ; }\n| |tab| } }\n\n{xrst_end is_pod}\n*/\nnamespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE\n    //\n    template <class T> inline bool is_pod(void) { return false; }\n    // bool\n    template <> inline bool is_pod<bool>(void)                   {return true;}\n    // short\n    template <> inline bool is_pod<short int>(void)              {return true;}\n    template <> inline bool is_pod<unsigned short int>(void)     {return true;}\n    // int\n    template <> inline bool is_pod<int>(void)                    {return true;}\n    template <> inline bool is_pod<unsigned int>(void)           {return true;}\n    // long\n    template <> inline bool is_pod<long int>(void)               {return true;}\n    template <> inline bool is_pod<unsigned long int>(void)      {return true;}\n    // long long\n    template <> inline bool is_pod<long long int>(void)          {return true;}\n    template <> inline bool is_pod<unsigned long long int>(void) {return true;}\n    // Character types\n    template <> inline bool is_pod<char>(void)                   {return true;}\n    template <> inline bool is_pod<signed char>(void)            {return true;}\n    template <> inline bool is_pod<unsigned char>(void)          {return true;}\n    template <> inline bool is_pod<wchar_t>(void)                {return true;}\n    template <> inline bool is_pod<char16_t>(void)               {return true;}\n    template <> inline bool is_pod<char32_t>(void)               {return true;}\n    // floating point types\n    template <> inline bool is_pod<float>(void)                  {return true;}\n    template <> inline bool is_pod<double>(void)                 {return true;}\n    template <> inline bool is_pod<long double>(void)            {return true;}\n\n} } // END_CPPAD_LOCAL_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/is_pod.hpp.in",
    "content": "# ifndef CPPAD_LOCAL_IS_POD_HPP\n# define CPPAD_LOCAL_IS_POD_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n// make sure size_t is defined because autotools version of\n// is_pod_specialize_98 uses it\n# include <cstddef>\n\n/*!\n\\file is_pod.hpp\nFile that defines is_pod<Type>(void)\n*/\nnamespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE\n/*!\nIs this type plain old data; i.e., its constructor need not be called.\n\nThe default definition is false. This include file defines it as true\nfor all the fundamental types except for void and nullptr_t.\n*/\ntemplate <class T> bool is_pod(void) { return false; }\n// The following command suppresses doxygen processing for the code below\n/// \\cond\n// C++98 Fundamental types\n@is_pod_specialize_98@\n\n// C++11 Fundamental types\n@is_pod_specialize_11@\n\n/// \\endcond\n} } // END_CPPAD_LOCAL_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/op_code_dyn.hpp",
    "content": "# ifndef CPPAD_LOCAL_OP_CODE_DYN_HPP\n# define CPPAD_LOCAL_OP_CODE_DYN_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\nnamespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE\n/*!\n{xrst_begin op_code_dyn dev}\n{xrst_spell\n    zmul\n}\n\nDynamic Parameter Op Codes\n##########################\n\nNamespace\n*********\nThe ``op_code_dyn`` enum type is in the ``CppAD::local`` namespace.\n\nAD Type\n*******\nAll the operators below have no variable arguments,\nat least one dynamic parameter argument,\nand at most one constant argument; see\n:ref:`ad_type_enum-name` .\nFor example, all the unary operators have one dynamic parameter argument\nand one dynamic parameter result.\n\nUnary\n*****\nThe number of arguments for a unary operator is one\nand it is a parameter index.\nAll the unary operators have one result that is a dynamic parameter.\n\nBinary\n******\nThe number of arguments for a binary operator is two\nand they are parameter indices.\nAll the binary operators have one result that is a dynamic parameter.\nFor binary operators the first argument is the left operand\nand the second is the right operand.\n\nzmul_dyn\n========\nThis binary operator has a non-standard name; see :ref:`azmul-name` for\nits definition.\n\nind_dyn\n*******\nThis is an independent dynamic parameter operator.\nIt has no arguments and one result which is the value of the corresponding\nindependent dynamic parameter in the call to :ref:`new_dynamic-name` .\n\n{xrst_comment ------------------------------------------------------------ }\natom_dyn\n********\nThis operator is a call to an atomic function.\nThe number of arguments to this operator is\n*arg* [4+ *n* + *m* ] ; see below.\n\narg[0]\n======\nThis is the index that identifies this atomic function; see\n``local/atomic_index.hpp`` .\n\narg[1]\n======\nThis is the :ref:`atomic_four_call@call_id` for this\nfunction call.\n\narg[2]\n======\nThis is the number of arguments to this atomic function.\nWe use the notation *n* = *arg* [2] below.\n\narg[3]\n======\nThis is the number of results for this atomic function.\nWe use the notation *m* = *arg* [3] below.\n\narg[4]\n======\nThis is the number of result values that are dynamic parameters\nfor this function call.\n\narg[5+j]\n========\nFor *j* = 0 , ... , *n* ``-1`` ,\nthis is the parameter index for the *j*-th argument to this atomic\nfunction call.\n\narg[5+n+i]\n==========\nFor *i* = 0 , ... , *m* ``-1`` ,\nthis is the parameter index for the *i*-th result to this atomic\nfunction call.\n\narg[5+n+m]\n==========\nThis is the number of arguments to this operator; i.e.,\n6+ *n* + *m* .\n\nresult_dyn\n**********\nThis is a place holder for a result of an atomic function call\nthat is a dynamic parameter.\nIt has no arguments, no results, and is only there so that the\nnumber of dynamic parameters and the number of dynamic operators are equal.\n\n{xrst_comment ------------------------------------------------------------ }\ncond_exp_dyn\n************\nThis is a conditional expression operator and has five arguments\nand one result.\n\narg[0]\n======\nThis is the\n:ref:`base_cond_exp@CompareOp` value for this operator.\n\narg[1]\n======\nThis is the parameter index for the left operand to the comparison.\n\narg[2]\n======\nThis is the parameter index for the right operand to the comparison.\n\narg[3]\n======\nThis is the index of the parameter equal to the operator result if\nthe comparison result is true.\n\narg[4]\n======\nThis is the index of the parameter equal to the operator result if\nthe comparison result is false.\n\n{xrst_comment ------------------------------------------------------------ }\ndis_dyn\n*******\nThis is a call to a discrete function.\nThe discrete function has one argument and one result.\nThis operator has two arguments and one result.\nIt is not a binary operator because the first argument\nis not the index of a parameter.\n\narg[0]\n======\nIs the discrete function index which depends on the *Base*\ntype used when this function was recorded.\n\narg[1]\n======\nIs the parameter index for the argument to the function.\n\n{xrst_comment ------------------------------------------------------------ }\nSource\n******\n{xrst_literal\n    // BEGIN_OP_CODE_DYN\n    // END_OP_CODE_DYN\n}\n\n{xrst_end op_code_dyn}\n*/\n\n// BEGIN_SORT_THIS_LINE_PLUS_3\n// BEGIN_OP_CODE_DYN\nenum op_code_dyn {\n    abs_dyn,       // unary\n    acos_dyn,      // unary\n    acosh_dyn,     // unary\n    add_dyn,       // binary\n    asin_dyn,      // unary\n    asinh_dyn,     // unary\n    atan_dyn,      // unary\n    atanh_dyn,     // unary\n    atom_dyn,      // ? arguments: atomic function call\n    cond_exp_dyn,  // 5 arguments: conditional expression\n    cos_dyn,       // unary\n    cosh_dyn,      // unary\n    dis_dyn,       // 2 arguments: discrete function\n    div_dyn,       // binary\n    erf_dyn,       // unary\n    erfc_dyn,      // unary\n    exp_dyn,       // unary\n    expm1_dyn,     // unary\n    fabs_dyn,      // unary\n    ind_dyn,       // 0 arguments: independent parameter\n    log1p_dyn,     // unary\n    log_dyn,       // unary\n    mul_dyn,       // binary\n    neg_dyn,       // unary\n    pow_dyn,       // binary\n    result_dyn,    // 0 arguments: atomic function result\n    sign_dyn,      // unary\n    sin_dyn,       // unary\n    sinh_dyn,      // unary\n    sqrt_dyn,      // unary\n    sub_dyn,       // binary\n    tan_dyn,       // unary\n    tanh_dyn,      // unary\n    zmul_dyn,      // binary\n    number_dyn     // number of operator codes and invalid operator value\n};\n// END_OP_CODE_DYN\n// END_SORT_THIS_LINE_MINUS_4\n\n/*\n{xrst_begin num_arg_dyn dev}\n\nNumber of Arguments to a Dynamic Parameter Operator\n###################################################\n\nSyntax\n******\n| *n_arg* = ``local::num_arg_dyn`` ( *op* )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_NUM_ARG_DYN_PROTOTYPE\n    // END_NUM_ARG_DYN_PROTOTYPE\n}\n\nParallel Mode\n*************\nThis routine has static data so its first call cannot be in Parallel mode.\n\nop\n**\nis the operator in question.\n\nn_arg\n*****\nThe return value is the number of arguments as commented in the\n:ref:`op_code_dyn@Source` for ``enum op_code_dyn`` .\nThere is one exception: if *op* is ``atom_dyn`` ,\n*n_arg* is zero; see :ref:`op_code_dyn@atom_dyn`\nfor the true number of arguments in this case.\n\natom_dyn\n********\nAll of the dynamic parameter operators have a fixed number of arguments\nexcept for the :ref:`op_code_dyn@atom_dyn`\noperator which calls an atomic functions.\nIn this special case the return value *n_arg* is zero\nwhich is not correct.\n\n{xrst_end num_arg_dyn}\n*/\n// BEGIN_NUM_ARG_DYN_PROTOTYPE\ninline size_t num_arg_dyn(op_code_dyn op)\n// END_NUM_ARG_DYN_PROTOTYPE\n{  CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL;\n\n    // BEGIN_SORT_THIS_LINE_PLUS_2\n    static const size_t num_arg_table[] = {\n        /* abs_dyn */      1,\n        /* acos_dyn */     1,\n        /* acosh_dyn */    1,\n        /* add_dyn */      2,\n        /* asin_dyn */     1,\n        /* asinh_dyn */    1,\n        /* atan_dyn */     1,\n        /* atanh_dyn */    1,\n        /* atom_dyn */     0,\n        /* cond_exp_dyn */ 5,\n        /* cos_dyn */      1,\n        /* cosh_dyn */     1,\n        /* dis_dyn */      2,\n        /* div_dyn */      2,\n        /* erf_dyn */      1,\n        /* erfc_dyn */     1,\n        /* exp_dyn */      1,\n        /* expm1_dyn */    1,\n        /* fabs_dyn */     1,\n        /* ind_dyn */      0,\n        /* log1p_dyn */    1,\n        /* log_dyn */      1,\n        /* mul_dyn */      2,\n        /* neg_dyn */      1,\n        /* pow_dyn */      2,\n        /* result_dyn */   0,\n        /* sign_dyn */     1,\n        /* sin_dyn */      1,\n        /* sinh_dyn */     1,\n        /* sqrt_dyn */     1,\n        /* sub_dyn */      2,\n        /* tan_dyn */      1,\n        /* tanh_dyn */     1,\n        /* zmul_dyn */     2,\n        0  // number_dyn (not used)\n    };\n    // END_SORT_THIS_LINE_MINUS_3\n    //\n    static bool first = true;\n    if( first )\n    {  CPPAD_ASSERT_UNKNOWN(\n        size_t(number_dyn)+1 == sizeof(num_arg_table)/sizeof(num_arg_table[0])\n        );\n        first = false;\n    }\n    return num_arg_table[op];\n}\n\n/*\n{xrst_begin op_name_dyn dev}\n\nNumber of Arguments to a Dynamic Parameter Operator\n###################################################\n\nSyntax\n******\n\n    *name* = ``local::op_name_dyn`` ( *op* )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_OP_NAME_DYN_PROTOTYPE\n    // END_OP_NAME_DYN_PROTOTYPE\n}\n\nParallel Mode\n*************\nThis routine has static data so its first call cannot be in Parallel mode.\n\nop\n**\nis the operator in question.\n\nname\n****\nThe return value *name* is the same as the operator enum symbol\n(see :ref:`op_code_dyn@Source` for ``enum op_code_dyn`` )\nwithout the ``_dyn`` at the end. For example,\nthe name corresponding to the\n:ref:`op_code_dyn@cond_exp_dyn` operator is ``cond_exp`` .\n\n{xrst_end op_name_dyn}\n*/\n// BEGIN_OP_NAME_DYN_PROTOTYPE\ninline const char* op_name_dyn(op_code_dyn op)\n// END_OP_NAME_DYN_PROTOTYPE\n{  CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL;\n\n    // BEGIN_SORT_THIS_LINE_PLUS_2\n    static const char* op_name_table[] = {\n        /* abs_dyn */      \"abs\",\n        /* acos_dyn */     \"acos\",\n        /* acosh_dyn */    \"acosh\",\n        /* add_dyn */      \"add\",\n        /* asin_dyn */     \"asin\",\n        /* asinh_dyn */    \"asinh\",\n        /* atan_dyn */     \"atan\",\n        /* atanh_dyn */    \"atanh\",\n        /* atom_dyn */     \"call\",\n        /* cond_exp_dyn */ \"cond_exp\",\n        /* cos_dyn */      \"cos\",\n        /* cosh_dyn */     \"cosh\",\n        /* dis_dyn */      \"dis\",\n        /* div_dyn */      \"div\",\n        /* erf_dyn */      \"erf\",\n        /* erfc_dyn */     \"erfc\",\n        /* exp_dyn */      \"exp\",\n        /* expm1_dyn */    \"expm1\",\n        /* fabs_dyn */     \"fabs\",\n        /* ind_dyn */      \"ind\",\n        /* log1p_dyn */    \"log1p\",\n        /* log_dyn */      \"log\",\n        /* mul_dyn */      \"mul\",\n        /* neg_dyn */      \"neg\",\n        /* pow_dyn */      \"pow\",\n        /* result_dyn */   \"result\",\n        /* sign_dyn */     \"sign\",\n        /* sin_dyn */      \"sin\",\n        /* sinh_dyn */     \"sinh\",\n        /* sqrt_dyn */     \"sqrt\",\n        /* sub_dyn */      \"sub\",\n        /* tan_dyn */      \"tan\",\n        /* tanh_dyn */     \"tanh\",\n        /* zmul_dyn */     \"zmul\",\n        /* number_dyn */   \"number\"\n    };\n    // END_SORT_THIS_LINE_MINUS_3\n    static bool first = true;\n    if( first )\n    {  CPPAD_ASSERT_UNKNOWN(\n        size_t(number_dyn)+1 == sizeof(op_name_table)/sizeof(op_name_table[0])\n        );\n        first = false;\n    }\n    return op_name_table[op];\n}\n\n/*\n{xrst_begin num_non_par_arg_dyn dev}\n\nNumber Non-Parameter Arguments to a Dynamic Parameters Operator\n###############################################################\n\nSyntax\n******\n\n    *num* = ``local::num_non_par_arg_dyn`` ( *op* )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_NUM_NON_PAR_ARG_DYN\n    // END_NUM_NON_PAR_ARG_DYN\n}\n\nop\n**\nis the operator in question.\n\nnum\n***\nThe return value *num* is the number of arguments,\nfor this operator *op* , that are not parameters indices.\nAll of the non-parameter arguments come first\nso *num* is also the offset for the\nfirst argument that is a parameter index.\n\nSpecial Case\n************\nIf :ref:`num_arg_dyn-name` ( *op* ) is zero and *num* is non-zero,\nthis operator has a variable number of arguments.\n(The only such operator so far is ``atom_dyn`` .)\nIn this case the last argument is not a parameter index and\nthere are *num* - 1 arguments that are not parameter indices\nbefore the first parameter index.\n\n{xrst_end num_non_par_arg_dyn}\n*/\n// BEGIN_NUM_NON_PAR_ARG_DYN\ninline size_t num_non_par_arg_dyn(op_code_dyn op)\n// END_NUM_NON_PAR_ARG_DYN\n{\n    size_t num;\n    switch(op)\n    {   case atom_dyn:\n        num = 6;\n        break;\n\n        case cond_exp_dyn:\n        case dis_dyn:\n        num = 1;\n        break;\n\n        default:\n        num = 0;\n    }\n    //\n    return num;\n}\n\n} } // END_CPPAD_LOCAL_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/op_code_var.hpp",
    "content": "# ifndef CPPAD_LOCAL_OP_CODE_VAR_HPP\n# define CPPAD_LOCAL_OP_CODE_VAR_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <string>\n# include <sstream>\n# include <iomanip>\n\n# include <cppad/local/atomic_index.hpp>\n# include <cppad/local/define.hpp>\n# include <cppad/core/cppad_assert.hpp>\n# include <cppad/local/pod_vector.hpp>\n\n// needed before one can use CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL\n# include <cppad/utility/thread_alloc.hpp>\n\nnamespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE\n/*!\n{xrst_begin op_code_var dev}\n{xrst_spell\n    funap\n    funav\n    funrp\n    funrv\n    ldp\n    ldv\n    opcode\n    pri\n}\n\nVariable Op Codes\n#################\n\nNamespace\n*********\nAll of these definitions are in the ``CppAD::local`` namespace.\n\nopcode_t\n********\nThis type is used to save space when storing operator enum type in vectors.\n{xrst_spell_off}\n{xrst_code hpp} */\ntypedef CPPAD_VEC_ENUM_TYPE opcode_t;\n/* {xrst_code}\n{xrst_spell_on}\n\nop_code_var\n***********\nThis enum type is used to distinguish different ``AD`` < *Base* >\natomic operations.\nEach value in the enum type ends with the characters ``Op`` .\nIgnoring the ``Op`` at the end,\nthe operators appear in alphabetical order.\n\narg[i]\n******\nWe use the notation *arg* [ ``i`` ] below\nfor the *i*-th operator argument which is a position integer\nrepresented using the type ``addr_t`` .\n\n{xrst_comment ------------------------------------------------------------- }\nUnary\n*****\nsee :ref:`var_unary_op-name`\n\n{xrst_comment ------------------------------------------------------------- }\nBinary\n******\nsee :ref:`var_binary_op-name`\n\n{xrst_comment ------------------------------------------------------------- }\n{xrst_spell_off}\n\nEqppOp, LeppOp, LtppOp, NeppOp\n******************************\nsee :ref:`var_compare_op@op_code@EqppOp, LeppOp, LtppOp, NeppOp`\n\nEqpvOp, LepvOp, LtpvOp, NepvOp\n******************************\nsee :ref:`var_compare_op@op_code@EqpvOp, LepvOp, LtpvOp, NepvOp`\n\nLevpOp, LtvpOp\n**************\nsee :ref:`var_compare_op@op_code@LevpOp, LtvpOp`\n\nEqvvOp, LevvOp, LtvvOp, NevvOp\n******************************\nsee :ref:`var_compare_op@op_code@EqvvOp, LevvOp, LtvvOp, NevvOp`\n\n{xrst_spell_on}\n{xrst_comment ------------------------------------------------------------- }\n\nAFunOp\n******\nsee :ref:`var_atomic_op@AFunOp`\n\nFunapOp, FunavOp\n****************\nsee :ref:`var_atomic_op@FunapOp, FunavOp`\n\nFunrpOp, FunrvOp\n****************\nsee :ref:`var_atomic_op@FunrpOp, FunrvOp`\n\n\n{xrst_comment ------------------------------------------------------------- }\nBeginOp\n*******\nThis operator marks the start of the tape.\nIt has one parameter index argument that is nan and corresponds\nto parameter index zero.\nIt also has one variable result that has index zero which is used to\nindicate that a value is not a variable.\nfor indicate an parameter.\n\n{xrst_comment ------------------------------------------------------------- }\n\nCExpOp\n******\nsee :ref:`var_cexp_op@CExpOp`\n\n{xrst_comment ------------------------------------------------------------- }\n\nCSkipOp\n*******\nsee :ref:`var_cskip_op@CSkipOp` .\n\n{xrst_comment ------------------------------------------------------------- }\n\nCSumOp\n******\nsee :ref:`var_csum_op@CSumOp`\n\n{xrst_comment ------------------------------------------------------------- }\n\nDisOp\n*****\nsee :ref:`var_dis_op@DisOp`\n\n{xrst_comment ------------------------------------------------------------- }\n\nLdpOp, LdvOp\n============\nsee :ref:`var_load_op@LdpOp, LdvOp`\n\n{xrst_comment ------------------------------------------------------------- }\n{xrst_spell_off}\n\nStppOp, StpvOp, StvpOp, StvvOp\n==============================\nsee :ref:`var_store_op@StppOp, StpvOp, StvpOp, StvvOp`\n\n{xrst_spell_on}\n{xrst_comment ------------------------------------------------------------- }\n\nParOp\n=====\nsee :ref:`var_par_op@ParOp`\n\n{xrst_comment ------------------------------------------------------------- }\n\nPriOp\n*****\nsee :ref:`var_pri_op@PriOp`\n\n{xrst_comment ------------------------------------------------------------- }\n\n{xrst_comment // BEGIN_SORT_THIS_LINE_PLUS_2 }\n{xrst_toc_table\n    include/cppad/local/var_op/atomic_op.hpp\n    include/cppad/local/var_op/binary_op.xrst\n    include/cppad/local/var_op/cexp_op.hpp\n    include/cppad/local/var_op/compare_op.hpp\n    include/cppad/local/var_op/cskip_op.hpp\n    include/cppad/local/var_op/csum_op.hpp\n    include/cppad/local/var_op/dis_op.hpp\n    include/cppad/local/var_op/load_op.hpp\n    include/cppad/local/var_op/one_var.hpp\n    include/cppad/local/var_op/par_op.hpp\n    include/cppad/local/var_op/pri_op.hpp\n    include/cppad/local/var_op/store_op.hpp\n    include/cppad/local/var_op/two_var.hpp\n    include/cppad/local/var_op/unary_op.xrst\n}\n{xrst_comment // END_SORT_THIS_LINE_MINUS_2 }\n\nSource\n******\n{xrst_spell_off}\n{xrst_code hpp} */\n// BEGIN_SORT_THIS_LINE_PLUS_2\nenum op_code_var {\n    AFunOp,   // see its heading above\n    AbsOp,    // unary fabs\n    AcosOp,   // unary acos\n    AcoshOp,  // unary acosh\n    AddpvOp,  // binary +\n    AddvvOp,  // ...\n    AsinOp,   // unary asin\n    AsinhOp,  // unary asinh\n    AtanOp,   // unary atan\n    AtanhOp,  // unary atanh\n    BeginOp,  // see its heading above\n    CExpOp,   // ...\n    CSkipOp,  // see its heading above\n    CSumOp,   // ...\n    CosOp,    // unary cos\n    CoshOp,   // unary cosh\n    DisOp,    // ...\n    DivpvOp,  // binary /\n    DivvpOp,  // ...\n    DivvvOp,  // ...\n    EndOp,    // used to mark the end of the tape\n    EqppOp,   // compare equal\n    EqpvOp,   // ...\n    EqvvOp,   // ...\n    ErfOp,    // unary erf\n    ErfcOp,   // unary erfc\n    ExpOp,    // unary exp\n    Expm1Op,  // unary expm1\n    FunapOp,  // see AFun heading above\n    FunavOp,  // ...\n    FunrpOp,  // ...\n    FunrvOp,  // ...\n    InvOp,    // independent variable, no arguments, one result variable\n    LdpOp,    // see its heading above\n    LdvOp,    // ...\n    LeppOp,   // compare <=\n    LepvOp,   // ...\n    LevpOp,   // ...\n    LevvOp,   // ...\n    Log1pOp,  // unary log1p\n    LogOp,    // unary log\n    LtppOp,   // compare <\n    LtpvOp,   // ...\n    LtvpOp,   // ...\n    LtvvOp,   // ...\n    MulpvOp,  // binary *\n    MulvvOp,  // ...\n    NegOp,    // unary negative\n    NeppOp,   // compare !=\n    NepvOp,   // ...\n    NevvOp,   // ...\n    ParOp,    // see its heading above\n    PowpvOp,  // see its heading above\n    PowvpOp,  // binary pow\n    PowvvOp,  // ..\n    PriOp,    // ..\n    SignOp,   // unary sign\n    SinOp,    // unary sin\n    SinhOp,   // unary sinh\n    SqrtOp,   // unary sqrt\n    StppOp,   // see its heading above\n    StpvOp,   // ...\n    StvpOp,   // ...\n    StvvOp,   // ...\n    SubpvOp,  // binary -\n    SubvpOp,  // ...\n    SubvvOp,  // ...\n    TanOp,    // unary tan\n    TanhOp,   // unary tanh\n    ZmulpvOp, // binary azmul\n    ZmulvpOp, // ...\n    ZmulvvOp, // ...\n    NumberOp  // number of operator codes (not an operator)\n};\n// END_SORT_THIS_LINE_MINUS_3\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end op_code_var}\n*/\n// Note that bin/check_op_code.sh assumes the pattern NumberOp occurs\n// at the end of this list and only at the end of this list.\n\n/*!\nNumber of arguments for a specified operator.\n\n\\return\nNumber of arguments corresponding to the specified operator.\n\n\\param op\nOperator for which we are fetching the number of arguments.\n\n\\par NumArgTable\nthis table specifies the number of arguments stored for each\noccurrence of the operator that is the i-th value in the op_code_var enum type.\nFor example, for the first three op_code_var enum values we have\n\\verbatim\nop_code_var j   NumArgTable[j]  Meaning\nAbsOp    0                1  index of variable we are taking absolute value of\nAcosOp   1                1  index of variable we are taking acos of\nAcoshOp  2                1  index of variable we are taking acosh of\n\\endverbatim\nNote that the meaning of the arguments depends on the operator.\n*/\ninline size_t NumArg( op_code_var op)\n{   CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL;\n\n    // agreement with op_code_var is checked by bin/check_op_code.sh\n    // BEGIN_SORT_THIS_LINE_PLUS_2\n    static const size_t NumArgTable[] = {\n        /* AFunOp   */ 4,\n        /* AbsOp    */ 1,\n        /* AcosOp   */ 1,\n        /* AcoshOp  */ 1,\n        /* AddpvOp  */ 2,\n        /* AddvvOp  */ 2,\n        /* AsinOp   */ 1,\n        /* AsinhOp  */ 1,\n        /* AtanOp   */ 1,\n        /* AtanhOp  */ 1,\n        /* BeginOp  */ 1,  // offset first real argument to have index 1\n        /* CExpOp   */ 6,\n        /* CSkipOp  */ 0,  // (has a variable number of arguments, not zero)\n        /* CSumOp   */ 0,  // (has a variable number of arguments, not zero)\n        /* CosOp    */ 1,\n        /* CoshOp   */ 1,\n        /* DisOp    */ 2,\n        /* DivpvOp  */ 2,\n        /* DivvpOp  */ 2,\n        /* DivvvOp  */ 2,\n        /* EndOp    */ 0,\n        /* EqppOp   */ 2,\n        /* EqpvOp   */ 2,\n        /* EqvvOp   */ 2,\n        /* ErfOp    */ 3,\n        /* ErfcOp   */ 3,\n        /* ExpOp    */ 1,\n        /* Expm1Op  */ 1,\n        /* FunapOp  */ 1,\n        /* FunavOp  */ 1,\n        /* FunrpOp  */ 1,\n        /* FunrvOp  */ 0,\n        /* InvOp    */ 0,\n        /* LdpOp    */ 3,\n        /* LdvOp    */ 3,\n        /* LeppOp   */ 2,\n        /* LepvOp   */ 2,\n        /* LevpOp   */ 2,\n        /* LevvOp   */ 2,\n        /* Log1pOp  */ 1,\n        /* LogOp    */ 1,\n        /* LtppOp   */ 2,\n        /* LtpvOp   */ 2,\n        /* LtvpOp   */ 2,\n        /* LtvvOp   */ 2,\n        /* MulpvOp  */ 2,\n        /* MulvvOp  */ 2,\n        /* NegOp    */ 1,\n        /* NeppOp   */ 2,\n        /* NepvOp   */ 2,\n        /* NevvOp   */ 2,\n        /* ParOp    */ 1,\n        /* PowpvOp  */ 2,\n        /* PowvpOp  */ 2,\n        /* PowvvOp  */ 2,\n        /* PriOp    */ 5,\n        /* SignOp   */ 1,\n        /* SinOp    */ 1,\n        /* SinhOp   */ 1,\n        /* SqrtOp   */ 1,\n        /* StppOp   */ 3,\n        /* StpvOp   */ 3,\n        /* StvpOp   */ 3,\n        /* StvvOp   */ 3,\n        /* SubpvOp  */ 2,\n        /* SubvpOp  */ 2,\n        /* SubvvOp  */ 2,\n        /* TanOp    */ 1,\n        /* TanhOp   */ 1,\n        /* ZmulpvOp */ 2,\n        /* ZmulvpOp */ 2,\n        /* ZmulvvOp */ 2,\n        0  // NumberOp not used\n    };\n    // END_SORT_THIS_LINE_MINUS_3\n# ifndef NDEBUG\n    // only do these checks once to save time\n    static bool first = true;\n    if( first )\n    {   first = false;\n        // check that NumberOp is last value in op code table\n        CPPAD_ASSERT_UNKNOWN(\n            size_t(NumberOp) + 1 == sizeof(NumArgTable)/sizeof(NumArgTable[0])\n        );\n        //Check that the type CPPAD_VEC_ENUM_TYPE as required by define.hpp\n        CPPAD_ASSERT_UNKNOWN( is_pod<opcode_t>() );\n        size_t number_op_size_t = size_t( NumberOp );\n        CPPAD_ASSERT_UNKNOWN(\n            number_op_size_t < std::numeric_limits<opcode_t>::max()\n        );\n    }\n    // do this check every time\n    CPPAD_ASSERT_UNKNOWN( size_t(op) < size_t(NumberOp) );\n# endif\n\n    return NumArgTable[op];\n}\n\n/*!\nNumber of variables resulting from the specified operation.\n\n\\param op\nOperator for which we are fecching the number of results.\n\n\\par NumResTable\ntable specifies the number of variables that result for each\noccurrence of the operator that is the i-th value in the op_code_var enum type.\nFor example, for the first three op_code_var enum values we have\n\\verbatim\nop_code_var j   NumResTable[j]  Meaning\nAbsOp    0                1  variable that is the result of the absolute value\nAcosOp   1                2  acos(x) and sqrt(1-x*x) are required for this op\nAcoshOp  2                2  acosh(x) and sqrt(x*x-1) are required for this op\n\\endverbatim\n*/\ninline size_t NumRes(op_code_var op)\n{   CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL;\n\n    // agreement with op_code_var is checked by bin/check_op_code.sh\n    // BEGIN_SORT_THIS_LINE_PLUS_2\n    static const size_t NumResTable[] = {\n        /* AFunOp   */ 0,\n        /* AbsOp    */ 1,\n        /* AcosOp   */ 2,\n        /* AcoshOp  */ 2,\n        /* AddpvOp  */ 1,\n        /* AddvvOp  */ 1,\n        /* AsinOp   */ 2,\n        /* AsinhOp  */ 2,\n        /* AtanOp   */ 2,\n        /* AtanhOp  */ 2,\n        /* BeginOp  */ 1,  // offsets first variable to have index one (not zero)\n        /* CExpOp   */ 1,\n        /* CSkipOp  */ 0,\n        /* CSumOp   */ 1,\n        /* CosOp    */ 2,\n        /* CoshOp   */ 2,\n        /* DisOp    */ 1,\n        /* DivpvOp  */ 1,\n        /* DivvpOp  */ 1,\n        /* DivvvOp  */ 1,\n        /* EndOp    */ 0,\n        /* EqppOp   */ 0,\n        /* EqpvOp   */ 0,\n        /* EqvvOp   */ 0,\n        /* ErfOp    */ 5,\n        /* ErfcOp   */ 5,\n        /* ExpOp    */ 1,\n        /* Expm1Op  */ 1,\n        /* FunapOp  */ 0,\n        /* FunavOp  */ 0,\n        /* FunrpOp  */ 0,\n        /* FunrvOp  */ 1,\n        /* InvOp    */ 1,\n        /* LdpOp    */ 1,\n        /* LdvOp    */ 1,\n        /* LeppOp   */ 0,\n        /* LepvOp   */ 0,\n        /* LevpOp   */ 0,\n        /* LevvOp   */ 0,\n        /* Log1pOp  */ 1,\n        /* LogOp    */ 1,\n        /* LtppOp   */ 0,\n        /* LtpvOp   */ 0,\n        /* LtvpOp   */ 0,\n        /* LtvvOp   */ 0,\n        /* MulpvOp  */ 1,\n        /* MulvvOp  */ 1,\n        /* NegOp    */ 1,\n        /* NeppOp   */ 0,\n        /* NepvOp   */ 0,\n        /* NevvOp   */ 0,\n        /* ParOp    */ 1,\n        /* PowpvOp  */ 3,\n        /* PowvpOp  */ 1,\n        /* PowvvOp  */ 3,\n        /* PriOp    */ 0,\n        /* SignOp   */ 1,\n        /* SinOp    */ 2,\n        /* SinhOp   */ 2,\n        /* SqrtOp   */ 1,\n        /* StppOp   */ 0,\n        /* StpvOp   */ 0,\n        /* StvpOp   */ 0,\n        /* StvvOp   */ 0,\n        /* SubpvOp  */ 1,\n        /* SubvpOp  */ 1,\n        /* SubvvOp  */ 1,\n        /* TanOp    */ 2,\n        /* TanhOp   */ 2,\n        /* ZmulpvOp */ 1,\n        /* ZmulvpOp */ 1,\n        /* ZmulvvOp */ 1,\n        0  // NumberOp not used and avoids g++ 4.3.2 warn when pycppad builds\n    };\n    // END_SORT_THIS_LINE_MINUS_3\n    // check ensuring conversion to size_t is as expected\n    CPPAD_ASSERT_UNKNOWN( size_t(NumberOp) + 1 ==\n        sizeof(NumResTable) / sizeof(NumResTable[0])\n    );\n    // this test ensures that all indices are within the table\n    CPPAD_ASSERT_UNKNOWN( size_t(op) < size_t(NumberOp) );\n\n    return NumResTable[op];\n}\n\n\n/*!\nFetch the name for a specified operation.\n\n\\return\nname of the specified operation.\n\n\\param op\nOperator for which we are fetching the name\n*/\ninline std::string OpName(op_code_var op)\n{   // agreement with op_code_var is checked by bin/check_op_code.sh\n    // BEGIN_SORT_THIS_LINE_PLUS_2\n    static const char *OpNameTable[] = {\n        \"AFunOp\"  ,\n        \"AbsOp\"   ,\n        \"AcosOp\"  ,\n        \"AcoshOp\" ,\n        \"AddpvOp\" ,\n        \"AddvvOp\" ,\n        \"AsinOp\"  ,\n        \"AsinhOp\" ,\n        \"AtanOp\"  ,\n        \"AtanhOp\" ,\n        \"BeginOp\" ,\n        \"CExpOp\"  ,\n        \"CSkipOp\" ,\n        \"CSumOp\"  ,\n        \"CosOp\"   ,\n        \"CoshOp\"  ,\n        \"DisOp\"   ,\n        \"DivpvOp\" ,\n        \"DivvpOp\" ,\n        \"DivvvOp\" ,\n        \"EndOp\"   ,\n        \"EqppOp\"  ,\n        \"EqpvOp\"  ,\n        \"EqvvOp\"  ,\n        \"ErfOp\"   ,\n        \"ErfcOp\"  ,\n        \"ExpOp\"   ,\n        \"Expm1Op\" ,\n        \"FunapOp\" ,\n        \"FunavOp\" ,\n        \"FunrpOp\" ,\n        \"FunrvOp\" ,\n        \"InvOp\"   ,\n        \"LdpOp\"   ,\n        \"LdvOp\"   ,\n        \"LeppOp\"  ,\n        \"LepvOp\"  ,\n        \"LevpOp\"  ,\n        \"LevvOp\"  ,\n        \"Log1pOp\" ,\n        \"LogOp\"   ,\n        \"LtppOp\"  ,\n        \"LtpvOp\"  ,\n        \"LtvpOp\"  ,\n        \"LtvvOp\"  ,\n        \"MulpvOp\" ,\n        \"MulvvOp\" ,\n        \"NegOp\"   ,\n        \"NeppOp\"  ,\n        \"NepvOp\"  ,\n        \"NevvOp\"  ,\n        \"ParOp\"   ,\n        \"PowpvOp\" ,\n        \"PowvpOp\" ,\n        \"PowvvOp\" ,\n        \"PriOp\"   ,\n        \"SignOp\"  ,\n        \"SinOp\"   ,\n        \"SinhOp\"  ,\n        \"SqrtOp\"  ,\n        \"StppOp\"  ,\n        \"StpvOp\"  ,\n        \"StvpOp\"  ,\n        \"StvvOp\"  ,\n        \"SubpvOp\" ,\n        \"SubvpOp\" ,\n        \"SubvvOp\" ,\n        \"TanOp\"   ,\n        \"TanhOp\"  ,\n        \"ZmulpvOp\",\n        \"ZmulvpOp\",\n        \"ZmulvvOp\",\n        \"Number\"  // not used\n    };\n    // END_SORT_THIS_LINE_MINUS_3\n\n    // check ensuring conversion to size_t is as expected\n    CPPAD_ASSERT_UNKNOWN(\n        size_t(NumberOp) + 1 == sizeof(OpNameTable)/sizeof(OpNameTable[0])\n    );\n    // this test ensures that all indices are within the table\n    CPPAD_ASSERT_UNKNOWN( size_t(op) < size_t(NumberOp) );\n\n    // result\n    std::string result = OpNameTable[op];\n    result             = result.substr(0, result.size() - 2);\n\n    return result;\n}\n\n/*!\nPrints a single field corresponding to an operator.\n\nA specified leader is printed in front of the value\nand then the value is left justified in the following width character.\n\n\\tparam Type\nis the type of the value we are printing.\n\n\\param os\nis the stream that we are printing to.\n\n\\param leader\nare characters printed before the value.\n\n\\param value\nis the value being printed.\n\n\\param width\nis the number of character to print the value in.\nIf the value does not fit in the width, the value is replace\nby width '*' characters.\n*/\ntemplate <class Type>\nvoid printOpField(\n    std::ostream      &os ,\n    const char *   leader ,\n    const Type     &value ,\n    size_t          width )\n{\n    std::ostringstream buffer;\n    std::string        str;\n\n    // first print the leader\n    os << leader;\n\n    // print the value into an internal buffer\n    buffer << value;\n    str = buffer.str();\n\n    // length of the string\n    size_t len = str.size();\n    if( len > width )\n    {\n        for(size_t i = 0; i < width-1; i++)\n            os << str[i];\n        os << \"*\";\n        return;\n    }\n\n    // count number of spaces at beginning\n    size_t nspace = 0;\n    while(str[nspace] == ' ' && nspace < len)\n        nspace++;\n\n    // left justify the string\n    size_t i = nspace;\n    while( i < len )\n        os << str[i++];\n\n    i = width - len + nspace;\n    while(i--)\n        os << \" \";\n}\n\n/*!\nPrints a single operator and its operands\n\n\\tparam Base\nIs the base type for these AD< Base > operations.\n\n\\param os\nis the output stream that the information is printed on.\n\n\\param play\nIs the entire recording for the tape that this operator is in.\n\n\\param i_op\nis the index for the operator corresponding to this operation.\n\n\\param i_var\nis the index for the variable corresponding to the result of this operation\n(if NumRes(op) > 0).\n\n\\param op\nThe operator code (op_code_var) for this operation.\n\n\\param arg\nis the vector of argument indices for this operation\n(must have NumArg(op) elements).\n*/\ntemplate <class Base, class RecBase>\nvoid printOp(\n    std::ostream&          os     ,\n    const local::player<Base>* play,\n    size_t                 i_op   ,\n    size_t                 i_var  ,\n    op_code_var            op     ,\n    const addr_t*          arg    )\n{\n    CPPAD_ASSERT_KNOWN(\n        ! thread_alloc::in_parallel() ,\n        \"cannot print trace of AD operations in parallel mode\"\n    );\n    static const char *CompareOpName[] =\n        { \"Lt\", \"Le\", \"Eq\", \"Ge\", \"Gt\", \"Ne\" };\n\n    // print operator\n    printOpField(os,  \"o=\",      i_op,  5);\n    if( NumRes(op) > 0 && op != BeginOp )\n        printOpField(os,  \"v=\",      i_var, 5);\n    else\n        printOpField(os,  \"v=\",      \"\",    5);\n    if( op == CExpOp || op == CSkipOp )\n    {   printOpField(os, \"\", OpName(op).c_str(), 5);\n        printOpField(os, \"\", CompareOpName[ arg[0] ], 3);\n    }\n    else\n        printOpField(os, \"\", OpName(op).c_str(), 8);\n\n    // print other fields\n    size_t ncol = 5;\n    switch( op )\n    {\n        case CSkipOp:\n        /*\n        arg[0]     = the Rel operator: Lt, Le, Eq, Ge, Gt, or Ne\n        arg[1] & 1 = is left a variable\n        arg[1] & 2 = is right a variable\n        arg[2]     = index corresponding to left\n        arg[3]     = index corresponding to right\n        arg[4] = number of operations to skip if CExpOp comparison is true\n        arg[5] = number of operations to skip if CExpOp comparison is false\n        arg[6] -> arg[5+arg[4]]               = skip operations if true\n        arg[6+arg[4]] -> arg[5+arg[4]+arg[5]] = skip operations if false\n        arg[6+arg[4]+arg[5]] = 6+arg[4]+arg[5]+1\n        */\n        CPPAD_ASSERT_UNKNOWN( arg[6+arg[4]+arg[5]] == 6+arg[4]+arg[5]+1 );\n        CPPAD_ASSERT_UNKNOWN(arg[1] != 0);\n        if( arg[1] & 1 )\n            printOpField(os, \" vl=\", arg[2], ncol);\n        else\n            printOpField(os, \" pl=\", play->par_one( size_t(arg[2]) ), ncol);\n        if( arg[1] & 2 )\n            printOpField(os, \" vr=\", arg[3], ncol);\n        else\n            printOpField(os, \" pr=\", play->par_one( size_t(arg[3]) ), ncol);\n        if( size_t(arg[4]) < 3 )\n        {   for(addr_t i = 0; i < arg[4]; i++)\n                printOpField(os, \" ot=\", arg[6+i], ncol);\n        }\n        else\n        {   printOpField(os, \"\\n\\tot=\", arg[6+0], ncol);\n            for(addr_t i = 1; i < arg[4]; i++)\n                printOpField(os, \" ot=\", arg[6+i], ncol);\n        }\n        if( size_t(arg[5]) < 3 )\n        {   for(addr_t i = 0; i < arg[5]; i++)\n                printOpField(os, \" of=\", arg[6+arg[4]+i], ncol);\n        }\n        else\n        {   printOpField(os, \"\\n\\tof=\", arg[6+arg[4]+0], ncol);\n            {   for(addr_t i = 1; i < arg[5]; i++)\n                    printOpField(os, \" of=\", arg[6+arg[4]+i], ncol);\n            }\n        }\n        break;\n\n        case CSumOp:\n        /*\n        arg[0] = index of parameter that initializes summation\n        arg[1] = end in arg of addition variables in summation\n        arg[2] = end in arg of subtraction variables in summation\n        arg[3] = end in arg of addition dynamic parameters in summation\n        arg[4] = end in arg of subtraction dynamic parameters in summation\n        arg[5],      ... , arg[arg[1]-1]: indices for addition variables\n        arg[arg[1]], ... , arg[arg[2]-1]: indices for subtraction variables\n        arg[arg[2]], ... , arg[arg[3]-1]: indices for addition dynamics\n        arg[arg[3]], ... , arg[arg[4]-1]: indices for subtraction dynamics\n        arg[arg[4]] = arg[4] + 1\n        */\n        CPPAD_ASSERT_UNKNOWN( arg[arg[4]] == arg[4] + 1 );\n        printOpField(os, \" pr=\", play->par_one( size_t(arg[0]) ), ncol);\n        for(addr_t i = 5; i < arg[1]; i++)\n                 printOpField(os, \" +v=\", arg[i], ncol);\n        for(addr_t i = arg[1]; i < arg[2]; i++)\n                 printOpField(os, \" -v=\", arg[i], ncol);\n        for(addr_t i = arg[2]; i < arg[3]; i++)\n                 printOpField(os, \" +d=\", play->par_one( size_t(arg[i]) ), ncol);\n        for(addr_t i = arg[3]; i < arg[4]; i++)\n                 printOpField(os, \" -d=\", play->par_one( size_t(arg[i]) ), ncol);\n        break;\n\n        case LdpOp:\n        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );\n        printOpField(os, \"off=\", arg[0], ncol);\n        printOpField(os, \"  p=\", play->par_one( size_t(arg[1]) ), ncol);\n        break;\n\n        case LdvOp:\n        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );\n        printOpField(os, \"off=\", arg[0], ncol);\n        printOpField(os, \"  v=\", arg[1], ncol);\n        break;\n\n        case StppOp:\n        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );\n        printOpField(os, \"off=\", arg[0], ncol);\n        printOpField(os, \" pl=\", play->par_one( size_t(arg[1]) ), ncol);\n        printOpField(os, \" pr=\", play->par_one( size_t(arg[2]) ), ncol);\n        break;\n\n        case StpvOp:\n        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );\n        printOpField(os, \"off=\", arg[0], ncol);\n        printOpField(os, \"  p=\", play->par_one( size_t(arg[1]) ), ncol);\n        printOpField(os, \"  v=\", arg[2], ncol);\n        break;\n\n        case StvpOp:\n        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );\n        printOpField(os, \"off=\", arg[0], ncol);\n        printOpField(os, \"  v=\", arg[1], ncol);\n        printOpField(os, \"  p=\", play->par_one( size_t(arg[2]) ), ncol);\n        break;\n\n        case StvvOp:\n        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );\n        printOpField(os, \"off=\", arg[0], ncol);\n        printOpField(os, \" vl=\", arg[1], ncol);\n        printOpField(os, \" vr=\", arg[2], ncol);\n        break;\n\n        case AddvvOp:\n        case DivvvOp:\n        case EqvvOp:\n        case LevvOp:\n        case LtvvOp:\n        case NevvOp:\n        case MulvvOp:\n        case PowvvOp:\n        case SubvvOp:\n        case ZmulvvOp:\n        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 );\n        printOpField(os, \" vl=\", arg[0], ncol);\n        printOpField(os, \" vr=\", arg[1], ncol);\n        break;\n\n        case AddpvOp:\n        case EqpvOp:\n        case DivpvOp:\n        case LepvOp:\n        case LtpvOp:\n        case NepvOp:\n        case SubpvOp:\n        case MulpvOp:\n        case PowpvOp:\n        case ZmulpvOp:\n        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 );\n        printOpField(os, \" pl=\", play->par_one( size_t(arg[0]) ), ncol);\n        printOpField(os, \" vr=\", arg[1], ncol);\n        break;\n\n        case DivvpOp:\n        case LevpOp:\n        case LtvpOp:\n        case PowvpOp:\n        case SubvpOp:\n        case ZmulvpOp:\n        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 );\n        printOpField(os, \" vl=\", arg[0], ncol);\n        printOpField(os, \" pr=\", play->par_one( size_t(arg[1]) ), ncol);\n        break;\n\n        case AbsOp:\n        case AcosOp:\n        case AcoshOp:\n        case AsinOp:\n        case AsinhOp:\n        case AtanOp:\n        case AtanhOp:\n        case CosOp:\n        case CoshOp:\n        case ExpOp:\n        case Expm1Op:\n        case LogOp:\n        case Log1pOp:\n        case NegOp:\n        case SignOp:\n        case SinOp:\n        case SinhOp:\n        case SqrtOp:\n        case FunavOp:\n        case TanOp:\n        case TanhOp:\n        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 );\n        printOpField(os, \"  v=\", arg[0], ncol);\n        break;\n\n        case ErfOp:\n        case ErfcOp:\n        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );\n        // arg[1] points to the parameter 0\n        // arg[2] points to the parameter 2 / sqrt(pi)\n        printOpField(os, \"  v=\", arg[0], ncol);\n        break;\n\n        case ParOp:\n        case FunapOp:\n        case FunrpOp:\n        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 );\n        printOpField(os, \"  p=\", play->par_one( size_t(arg[0]) ), ncol);\n        break;\n\n        case AFunOp:\n        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 4 );\n        {\n            // get the name of this atomic function\n            bool         set_null   = false;\n            size_t       atom_index = size_t( arg[0] );\n            size_t       type       = 0;          // set to avoid warning\n            std::string name;\n            void*        v_ptr    = nullptr; // set to avoid warning\n            atomic_index<RecBase>(set_null, atom_index, type, &name, v_ptr);\n            printOpField(os, \" f=\",   name.c_str(), ncol);\n            printOpField(os, \" i=\", arg[1], ncol);\n            printOpField(os, \" n=\", arg[2], ncol);\n            printOpField(os, \" m=\", arg[3], ncol);\n        }\n        break;\n\n        case PriOp:\n        CPPAD_ASSERT_NARG_NRES(op, 5, 0);\n        if( arg[0] & 1 )\n            printOpField(os, \" v=\", arg[1], ncol);\n        else\n            printOpField(os, \" p=\", play->par_one( size_t(arg[1]) ), ncol);\n        os << \"before=\\\"\" << play->GetTxt( size_t(arg[2]) ) << \"\\\"\";\n        if( arg[0] & 2 )\n            printOpField(os, \" v=\", arg[3], ncol);\n        else\n            printOpField(os, \" p=\", play->par_one( size_t(arg[3]) ), ncol);\n        os << \"after=\\\"\" << play->GetTxt( size_t(arg[4]) ) << \"\\\"\";\n        break;\n\n        case BeginOp:\n        // argument not used (created by independent)\n        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 );\n        break;\n\n        case EndOp:\n        case InvOp:\n        case FunrvOp:\n        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 0 );\n        break;\n\n        case DisOp:\n        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 );\n        {   const std::string name = discrete<Base>::name( size_t(arg[0]) );\n            printOpField(os, \" f=\", name.c_str(), ncol);\n            printOpField(os, \" x=\", arg[1], ncol);\n        }\n        break;\n\n\n        case CExpOp:\n        CPPAD_ASSERT_UNKNOWN(arg[1] != 0);\n        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 6 );\n        if( arg[1] & 1 )\n            printOpField(os, \" vl=\", arg[2], ncol);\n        else\n            printOpField(os, \" pl=\", play->par_one( size_t(arg[2]) ), ncol);\n        if( arg[1] & 2 )\n            printOpField(os, \" vr=\", arg[3], ncol);\n        else\n            printOpField(os, \" pr=\", play->par_one( size_t(arg[3]) ), ncol);\n        if( arg[1] & 4 )\n            printOpField(os, \" vt=\", arg[4], ncol);\n        else\n            printOpField(os, \" pt=\", play->par_one( size_t(arg[4]) ), ncol);\n        if( arg[1] & 8 )\n            printOpField(os, \" vf=\", arg[5], ncol);\n        else\n            printOpField(os, \" pf=\", play->par_one( size_t(arg[5]) ), ncol);\n        break;\n\n        case EqppOp:\n        case LeppOp:\n        case LtppOp:\n        case NeppOp:\n        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 );\n        printOpField(os, \" pl=\", play->par_one( size_t(arg[0]) ), ncol);\n        printOpField(os, \" pr=\", play->par_one( size_t(arg[1]) ), ncol);\n        break;\n\n        default:\n        CPPAD_ASSERT_UNKNOWN(0);\n    }\n}\n\n/*!\nPrints the result values corresponding to an operator.\n\n\\tparam Base\nIs the base type for these AD< Base > operations.\n\n\\tparam Value\nDetermines the type of the values that we are printing.\n\n\\param os\nis the output stream that the information is printed on.\n\n\\param nfz\nis the number of forward sweep calculated values of type Value\nthat correspond to this operation\n(ignored if NumRes(op) == 0).\n\n\\param fz\npoints to the first forward calculated value\nthat correspond to this operation\n(ignored if NumRes(op) == 0).\n\n\\param nrz\nis the number of reverse sweep calculated values of type Value\nthat correspond to this operation\n(ignored if NumRes(op) == 0).\n\n\\param rz\npoints to the first reverse calculated value\nthat correspond to this operation\n(ignored if NumRes(op) == 0).\n*/\ntemplate <class Value>\nvoid printOpResult(\n    std::ostream          &os     ,\n    size_t                 nfz    ,\n    const  Value          *fz     ,\n    size_t                 nrz    ,\n    const  Value          *rz     )\n{\n    size_t k;\n    for(k = 0; k < nfz; k++)\n        os << \"| fz[\" << k << \"]=\" << fz[k];\n    for(k = 0; k < nrz; k++)\n        os << \"| rz[\" << k << \"]=\" << rz[k];\n}\n\n/*!\nDetermines which arguments are variaibles for an operator.\n\n\\param op\nis the operator. Note that CSkipOp and CSumOp are special cases\nbecause the true number of arguments is not equal to NumArg(op)\nand the true number of arguments num_arg can be large.\nIt may be more efficient to handle these cases separately\n(see below).\n\n\\param arg\nis the argument vector for this operator.\n\n\\param is_variable\nIf the input value of the elements in this vector do not matter.\nUpon return, resize has been used to set its size to the true number\nof arguments to this operator.\nIf op != CSkipOp and op != CSumOp, is_variable.size() = NumArg(op).\nThe j-th argument for this operator is a\nvariable index if and only if is_variable[j] is true. Note that the variable\nindex 0, for the BeginOp, does not correspond to a real variable and false\nis returned for this case.\n\n\\par CSkipOp\nIn the case of CSkipOp,\n\\code\n        is_variable.size()  = 7 + arg[4] + arg[5];\n        is_variable[2]      = (arg[1] & 1) != 0;\n        is_variable[3]      = (arg[1] & 2) != 0;\n\\endcode\nand all the other is_variable[j] values are false.\n\n\\par CSumOp\nIn the case of CSumOp,\n\\code\n        is_variable.size() = arg[4]\n        for(size_t j = 5; j < arg[2]; ++j)\n            is_variable[j] = true;\n\\endcode\nand all the other is_variable values are false.\n*/\ntemplate <class Addr>\nvoid arg_is_variable(\n    op_code_var       op          ,\n    const Addr*       arg         ,\n    pod_vector<bool>& is_variable )\n{   size_t num_arg = NumArg(op);\n    is_variable.resize( num_arg );\n    //\n    switch(op)\n    {\n        // -------------------------------------------------------------------\n        // cases where true number of arguments = NumArg(op) == 0\n\n        case EndOp:\n        case InvOp:\n        case FunrvOp:\n        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 0 );\n        break;\n\n        // -------------------------------------------------------------------\n        // cases where NumArg(op) == 1\n        case AbsOp:\n        case AcoshOp:\n        case AcosOp:\n        case AsinhOp:\n        case AsinOp:\n        case AtanhOp:\n        case AtanOp:\n        case CoshOp:\n        case CosOp:\n        case Expm1Op:\n        case ExpOp:\n        case Log1pOp:\n        case LogOp:\n        case NegOp:\n        case SignOp:\n        case SinhOp:\n        case SinOp:\n        case SqrtOp:\n        case TanhOp:\n        case TanOp:\n        case FunavOp:\n        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 );\n        is_variable[0] = true;\n        break;\n\n        case BeginOp:\n        case ParOp:\n        case FunapOp:\n        case FunrpOp:\n        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 );\n        is_variable[0] = false;\n        break;\n\n\n        // -------------------------------------------------------------------\n        // cases where NumArg(op) == 2\n\n        case AddpvOp:\n        case DisOp:\n        case DivpvOp:\n        case EqpvOp:\n        case LepvOp:\n        case LtpvOp:\n        case MulpvOp:\n        case NepvOp:\n        case PowpvOp:\n        case SubpvOp:\n        case ZmulpvOp:\n        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 );\n        is_variable[0] = false;\n        is_variable[1] = true;\n        break;\n\n        case DivvpOp:\n        case LevpOp:\n        case LtvpOp:\n        case PowvpOp:\n        case SubvpOp:\n        case ZmulvpOp:\n        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 );\n        is_variable[0] = true;\n        is_variable[1] = false;\n        break;\n\n        case AddvvOp:\n        case DivvvOp:\n        case EqvvOp:\n        case LevvOp:\n        case LtvvOp:\n        case MulvvOp:\n        case NevvOp:\n        case PowvvOp:\n        case SubvvOp:\n        case ZmulvvOp:\n        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 );\n        is_variable[0] = true;\n        is_variable[1] = true;\n        break;\n\n        case ErfOp:\n        case ErfcOp:\n        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );\n        is_variable[0] = true;\n        is_variable[1] = false; // parameter index corresponding to zero\n        is_variable[2] = false; // parameter index corresponding to one\n        break;\n\n        // --------------------------------------------------------------------\n        // cases where NumArg(op) == 3\n\n        case LdpOp:\n        case StppOp:\n        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );\n        is_variable[0] = false;\n        is_variable[1] = false;\n        is_variable[2] = false;\n        break;\n\n        case LdvOp:\n        case StvpOp:\n        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );\n        is_variable[0] = false;\n        is_variable[1] = true;\n        is_variable[2] = false;\n        break;\n\n        case StpvOp:\n        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );\n        is_variable[0] = false;\n        is_variable[1] = false;\n        is_variable[2] = true;\n        break;\n\n        case StvvOp:\n        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );\n        is_variable[0] = false;\n        is_variable[1] = true;\n        is_variable[2] = true;\n        break;\n\n        // --------------------------------------------------------------------\n        // case where NumArg(op) == 4\n        case AFunOp:\n        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 4 );\n        for(size_t i = 0; i < 4; i++)\n            is_variable[i] = false;\n        break;\n\n        // --------------------------------------------------------------------\n        // case where NumArg(op) == 5\n        case PriOp:\n        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 5 );\n        is_variable[0] = false;\n        is_variable[1] = (arg[0] & 1) != 0;\n        is_variable[2] = false;\n        is_variable[3] = (arg[0] & 2) != 0;\n        is_variable[4] = false;\n        break;\n\n        // --------------------------------------------------------------------\n        // case where NumArg(op) == 6\n        case CExpOp:\n        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 6 );\n        is_variable[0] = false;\n        is_variable[1] = false;\n        is_variable[2] = (arg[1] & 1) != 0;\n        is_variable[3] = (arg[1] & 2) != 0;\n        is_variable[4] = (arg[1] & 4) != 0;\n        is_variable[5] = (arg[1] & 8) != 0;\n        break;\n\n        // -------------------------------------------------------------------\n        // CSkipOp:\n        case CSkipOp:\n        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 0 )\n        //\n        // true number of arguments\n        num_arg = size_t(7 + arg[4] + arg[5]);\n        is_variable.resize(num_arg);\n        is_variable[0] = false;\n        is_variable[1] = false;\n        is_variable[2] = (arg[1] & 1) != 0;\n        is_variable[3] = (arg[1] & 2) != 0;\n        for(size_t i = 4; i < num_arg; ++i)\n            is_variable[i] = false;\n        break;\n\n        // -------------------------------------------------------------------\n        // CSumOp:\n        case CSumOp:\n        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 0 )\n        //\n        // true number of arguments\n        num_arg = size_t(arg[4] + 1);\n        //\n        is_variable.resize( num_arg );\n        for(size_t i = 0; i < num_arg; ++i)\n            is_variable[i] = (5 <= i) && (i < size_t(arg[2]));\n        break;\n\n        case EqppOp:\n        case LeppOp:\n        case LtppOp:\n        case NeppOp:\n        CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 );\n        is_variable[0] = false;\n        is_variable[1] = false;\n        break;\n\n        // --------------------------------------------------------------------\n        default:\n        CPPAD_ASSERT_UNKNOWN(false);\n        break;\n    }\n    return;\n}\n\n} } // END_CPPAD_LOCAL_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/local/optimize/cexp_info.hpp",
    "content": "# ifndef CPPAD_LOCAL_OPTIMIZE_CEXP_INFO_HPP\n# define CPPAD_LOCAL_OPTIMIZE_CEXP_INFO_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/local/declare_ad.hpp> // defines CompareOp\n# include <cppad/utility/vector.hpp>\n\n/*!\n{xrst_begin optimize_cexp_info dev}\n{xrst_spell\n    cskip\n    struct\n}\n\nOptimization Information About Conditional Expressions\n######################################################\n\nstruct_cexp_info\n****************\ninformation about a conditional expression\nin the old operation sequence (before optimization).\n{xrst_literal\n    // BEGIN_STRUCT_CEXP_INFO\n    // END_STRUCT_CEXP_INFO\n}\n\ni_op\n====\nis the operator index for this conditional expression.\n\nleft\n====\nis the variable or parameter index (depending on flag)\nfor left operand in the comparison.\n\nright\n=====\nis the variable or parameter index (depending on flag)\nfor right operand in the comparison.\n\nmax_left_right\n==============\nis the maximum of the left and right variable indices.\nThis is a variable index, so parameters correspond to index zero.\n\ncop\n===\nis the comparison operator for this conditional expression.\n\nflag\n====\n\n#. (flag & 1) is true if and only if left is a variable\n#. (flag & 2) is true if and only if right is a variable\n\nstruct_cskip_new\n****************\ninformation about a conditional expression\nin thew new operation sequence (after optimization).\n{xrst_literal\n    // BEGIN_STRUCT_CSKIP_NEW\n    // END_STRUCT_CSKIP_NEW\n}\n\nleft\n====\nis the variable or parameter index (depending on flag)\nfor left operand in the comparison.\n\nright\n=====\nis the variable or parameter index (depending on flag)\nfor right operand in the comparison.\n\nmax_left_right\n==============\nis the maximum of the left and right variable indices.\nThis is a variable index, so parameters correspond to index zero.\n\ni_arg\n=====\nindex where this conditional skips arguments start\n(in the vector or arguments for all operators).\n\n{xrst_end optimize_cexp_info}\n*/\n\n// BEGIN_CPPAD_LOCAL_OPTIMIZE_NAMESPACE\nnamespace CppAD { namespace local { namespace optimize  {\n/*!\nInformation about one conditional expression.\n*/\n// BEGIN_STRUCT_CEXP_INFO\nstruct struct_cexp_info {\n    addr_t                i_op;\n    addr_t                left;\n    addr_t                right;\n    addr_t                max_left_right;\n    CompareOp             cop;\n    unsigned char         flag;\n};\n// END_STRUCT_CEXP_INFO\n\n// BEGIN_STRUCT_CSKIP_NEW\nstruct struct_cskip_new {\n    size_t left;\n    size_t right;\n    size_t max_left_right;\n    size_t i_arg;\n};\n// END_STRUCT_CSKIP_NEW\n\n} } } // END_CPPAD_LOCAL_OPTIMIZE_NAMESPACE\n\nnamespace CppAD { namespace local {\n    template <> inline bool is_pod<optimize::struct_cskip_new>(void)\n    { return true; }\n} }\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/optimize/csum_op_info.hpp",
    "content": "# ifndef CPPAD_LOCAL_OPTIMIZE_CSUM_OP_INFO_HPP\n# define CPPAD_LOCAL_OPTIMIZE_CSUM_OP_INFO_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/local/op_code_var.hpp>\n# include <cppad/local/declare_ad.hpp> // defines addr_t\n\n/*!\n\\file csum_op_info.hpp\nInformation about one old variable that is part of a new CSumOp operation.\n*/\n\n// BEGIN_CPPAD_LOCAL_OPTIMIZE_NAMESPACE\nnamespace CppAD { namespace local { namespace optimize  {\n/*!\nInformation about one old variable that is part of a new CSumOp operation.\n*/\nstruct struct_csum_op_info {\n    /// Pointer to first argument (child) for this old operator.\n    /// Set by the reverse sweep at beginning of optimization.\n    const addr_t*       arg;\n\n    /// Was this old variable added to the summation\n    /// (if not it was subtracted)\n    bool                add;\n\n    /// Operator for which this old variable is the result, NumRes(op) > 0.\n    op_code_var         op;\n};\n\n} } } // END_CPPAD_LOCAL_OPTIMIZE_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/optimize/csum_stacks.hpp",
    "content": "# ifndef CPPAD_LOCAL_OPTIMIZE_CSUM_STACKS_HPP\n# define CPPAD_LOCAL_OPTIMIZE_CSUM_STACKS_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <stack>\n# include <cppad/local/optimize/csum_op_info.hpp>\n\n/*!\n\\file csum_stacks.hpp\nInformation about one cumulative summation operation.\n*/\n\n// BEGIN_CPPAD_LOCAL_OPTIMIZE_NAMESPACE\nnamespace CppAD { namespace local { namespace optimize  {\n/*!\nInformation about one cumulative summation operation.\n*/\nstruct struct_csum_stacks {\n\n    /// old operator indices for this cumulative summation\n    std::stack<struct struct_csum_op_info>      op_info;\n\n    /// old variable indices to be added\n    std::stack<addr_t>                          add_var;\n\n    /// old variable indices to be subtracted\n    std::stack<addr_t>                          sub_var;\n\n    /// dynamic parameter indices to be added\n    std::stack<addr_t>                          add_dyn;\n\n    /// dynamic parameter indices to be subtracted\n    std::stack<addr_t>                          sub_dyn;\n};\n\n} } } // END_CPPAD_LOCAL_OPTIMIZE_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/optimize/extract_option.hpp",
    "content": "# ifndef CPPAD_LOCAL_OPTIMIZE_EXTRACT_OPTION_HPP\n# define CPPAD_LOCAL_OPTIMIZE_EXTRACT_OPTION_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*!\n{xrst_begin optimize_extract_option dev}\n{xrst_spell\n    struct\n}\n\nConvert Optimizer Options From String to Struct\n###############################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_OPTIMIZE_OPTIONS\n    // END_OPTIMIZE_OPTIONS\n}\n\nresult\n******\nThe return value, *result* below,  has the following type\n{xrst_literal\n    // BEGIN_OPTIONS_T\n    // END_OPTIONS_T\n}\n\n\noptions\n*******\nSee :ref:`optimize@options`\n\n{xrst_end optimize_extract_option}\n*/\n\n# include <cppad/core/cppad_assert.hpp>\n\n// BEGIN_CPPAD_LOCAL_OPTIMIZE_NAMESPACE\nnamespace CppAD { namespace local { namespace optimize  {\n\n// BEGIN_SORT_THIS_LINE_PLUS_3\n// BEGIN_OPTIONS_T\nstruct options_t {\n    bool   compare_op;\n    bool   conditional_skip;\n    bool   cumulative_sum_op;\n    bool   print_for_op;\n    bool   val_graph;\n    size_t collision_limit;\n};\n// END_OPTIONS_T\n// END_SORT_THIS_LINE_MINUS_3\n\n// BEGIN_OPTIMIZE_OPTIONS\ninline options_t extract_option(const std::string& options)\n// END_OPTIMIZE_OPTIONS\n{   //\n    // result: default value\n    struct options_t result = {\n        true,  // compare_op\n        true,  // conditional_skip\n        true,  // cumulative_sum_op\n        true,  // print_for_op\n        false, // val_graph\n        10     // collision_limit\n    };\n    size_t index = 0;\n    while( index < options.size() )\n    {   while( index < options.size() && options[index] == ' ' )\n            ++index;\n        std::string option;\n        while( index < options.size() && options[index] != ' ' )\n            option += options[index++];\n        if( option != \"\" )\n        {\n            if( option == \"no_compare_op\" )\n                result.compare_op = false;\n            else if( option == \"no_conditional_skip\" )\n                result.conditional_skip = false;\n            else if( option == \"no_cumulative_sum_op\" )\n                result.cumulative_sum_op = false;\n            else if( option == \"no_print_for_op\" )\n                result.print_for_op = false;\n            else if( option == \"val_graph\" )\n                result.val_graph = true;\n            else if( option.substr(0, 16)  == \"collision_limit=\" )\n            {   std::string value = option.substr(16, option.size());\n                bool value_ok = value.size() > 0;\n                for(size_t i = 0; i < value.size(); ++i)\n                {   value_ok &= '0' <= value[i];\n                    value_ok &= value[i] <= '9';\n                }\n                if( ! value_ok )\n                {   option += \" value is not a sequence of decimal digits\";\n                    CPPAD_ASSERT_KNOWN( false , option.c_str() );\n                }\n                result.collision_limit = size_t( std::atoi( value.c_str() ) );\n                if( result.collision_limit < 1 )\n                {   option += \" value must be greater than zero\";\n                    CPPAD_ASSERT_KNOWN( false , option.c_str() );\n                }\n            }\n            else\n            {   option += \" is not a valid optimize option\";\n                CPPAD_ASSERT_KNOWN( false , option.c_str() );\n            }\n        }\n    }\n    return result;\n}\n\n} } } // END_CPPAD_LOCAL_OPTIMIZE_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/optimize/get_cexp_info.hpp",
    "content": "# ifndef CPPAD_LOCAL_OPTIMIZE_GET_CEXP_INFO_HPP\n# define CPPAD_LOCAL_OPTIMIZE_GET_CEXP_INFO_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/local/optimize/match_op.hpp>\n# include <cppad/local/optimize/cexp_info.hpp>\n# include <cppad/local/optimize/usage.hpp>\n\n// BEGIN_CPPAD_LOCAL_OPTIMIZE_NAMESPACE\nnamespace CppAD { namespace local { namespace optimize {\n\n/*!\n{xrst_begin optimize_get_cexp_info.hpp dev}\n{xrst_spell\n    deallocate\n    funap\n    funav\n    funrp\n    funrv\n}\n\nInformation for Each Conditional Expression\n###########################################\n\nSyntax\n******\n| ``get_cexp_info`` (\n| |tab| *play* ,\n| |tab| *random_itr* ,\n| |tab| *op_previous* ,\n| |tab| *op_usage* ,\n| |tab| *cexp2op* ,\n| |tab| *cexp_set* ,\n| |tab| *cexp_info* ,\n| |tab| *skip_op_true* ,\n| |tab| *skip_op_false*\n| )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_PROTOTYPE\n    // END_PROTOTYPE\n}\n\nRestrictions\n************\nDo not call this routine unless you are optimizing conditional expressions\nand there are conditional expressions in the operation sequence.\n\nBase\n****\nbase type for the operator; i.e., this operation was recorded\nusing AD<Base> and computations by this routine are done using type Base.\n\nplay\n****\nThis is the old operation sequence.\n\nrandom_itr\n**********\nThis is a random iterator for the old operation sequence.\n\ncexp2op\n*******\nThis is the number of conditional expressions in the operation sequence\nand must be non-zero.\n\ncexp_set\n********\nThis is a vector of sets, the i-th set, set[i],\nis a set of elements for the i-th operator.\nIf e is an element of set[i], let j = e / 2 and k = e % 2.\nIf the comparison for the j-th conditional expression is equal to bool(k),\nthe i-th operator can be skipped (is not used by any of the results).\nNote that j indexes the subset of operators that are conditional expressions\nin the old operation sequence.\n\ncexp_info\n*********\nThe input size of this vector must be zero.\nUpon return cexp_info has size equal to the number of conditional expressions\nin the operation sequence; i.e., the number of CExpOp operators.\nThe value cexp_info[j] is the information corresponding to the j-th\nconditional expression in the operation sequence.\nThis vector is in the same order as the operation sequence; i.e.\nif j1 > j2, cexp_info[j1].i_op > cexp_info[j2].i_op.\nNote that skip_op_true and skip_op_false could be part of this structure,\nbut then we would allocate and deallocate two vectors for each conditional\nexpression in the operation sequence.\n\nskip_op_true\n************\nThis vector of sets is empty on input.\nUpon return, the j-th set is the operators that are not used when\ncomparison result for cexp_info[j] is true.\nNote that FunapOp, FunavOp, FunrpOp, and FunrvOp, are not in this\nset and should be skipped when the corresponding AFunOp are skipped.\n\nskip_op_false\n*************\nThis vector of sets is empty on input.\nUpon return, the j-th set is the operators that are not used when\ncomparison result for cexp_info[j] is false.\nNote that FunapOp, FunavOp, FunrpOp, and FunrvOp, are not in this\nset and should be skipped when the corresponding AFunOp are skipped.\n\nop_previous\n***********\nThis argument has size equal to the number of operators\nin the operation sequence; i.e., num_op = play->nun_var_rec().\nIf op_previous[i] == 0, no replacement was found for the i-th operator.\nIf op_previous[i] != 0, op_usage[ op_previous[i] ] == usage_t(yes_usage).\n\nop_usage\n********\nThis argument has size equal to the number of operators\nin the operation sequence; i.e., num_op = play->nun_var_rec().\nThe value op_usage[i] is the usage for\nthe i-th operator in the operation sequence.\n\n{xrst_end optimize_get_cexp_info.hpp}\n*/\n\n// BEGIN_PROTOTYPE\ntemplate <class Addr, class Base>\nvoid get_cexp_info(\n    const player<Base>*                         play                ,\n    const play::const_random_iterator<Addr>&    random_itr          ,\n    const pod_vector<addr_t>&                   op_previous         ,\n    const pod_vector<usage_t>&                  op_usage            ,\n    const pod_vector<addr_t>&                   cexp2op             ,\n    const sparse::list_setvec&                  cexp_set            ,\n    vector<struct_cexp_info>&                   cexp_info           ,\n    sparse::list_setvec&                        skip_op_true        ,\n    sparse::list_setvec&                        skip_op_false       )\n// END_PROTOTYPE\n{\n    CPPAD_ASSERT_UNKNOWN( cexp_set.n_set() > 0  );\n    CPPAD_ASSERT_UNKNOWN( cexp_info.size() == 0 );\n\n    // number of operators in the tape\n    const size_t num_op = play->num_var_op();\n    CPPAD_ASSERT_UNKNOWN( op_usage.size() == num_op );\n    CPPAD_ASSERT_UNKNOWN( op_previous.size() == num_op );\n    //\n    // number of conditional expressions in the tape\n    size_t num_cexp_op = cexp2op.size();\n    //\n    // initialize mapping from variable index to operator index\n    CPPAD_ASSERT_UNKNOWN(\n        size_t( (std::numeric_limits<addr_t>::max)() ) >= num_op\n    );\n    // ----------------------------------------------------------------------\n    // compute cexp_info\n    // ----------------------------------------------------------------------\n    //\n    // initialize information for each conditional expression\n    cexp_info.resize(num_cexp_op);\n    skip_op_true.resize(num_cexp_op, num_op);\n    skip_op_false.resize(num_cexp_op, num_op);\n    //\n    for(size_t i = 0; i < num_cexp_op; i++)\n    {   size_t i_op = size_t( cexp2op[i] );\n        CPPAD_ASSERT_UNKNOWN(\n            op_previous[i_op] == 0 || op_usage[i_op] == usage_t(yes_usage)\n        );\n        op_code_var   op;     // operator\n        const addr_t* arg;    // arguments\n        size_t        i_var;  // variable index of first result\n        random_itr.op_info(i_op, op, arg, i_var);\n        CPPAD_ASSERT_UNKNOWN( op == CExpOp );\n        //\n        struct_cexp_info info;\n        info.i_op       = addr_t(i_op);\n        info.cop        = CompareOp( arg[0] );\n        info.flag       = static_cast<unsigned char>(arg[1]);\n        info.left       = arg[2];\n        info.right      = arg[3];\n        //\n        // max_left_right\n        addr_t index    = 0;\n        if( arg[1] & 1 )\n            index = std::max<addr_t>(index, info.left);\n        if( arg[1] & 2 )\n            index = std::max<addr_t>(index, info.right);\n        info.max_left_right = index;\n        //\n        cexp_info[i] = info;\n    };\n    // Determine which operators can be conditionally skipped\n    size_t i_op = 0;\n    while(i_op < num_op)\n    {   size_t j_op = i_op;\n        bool keep = op_usage[i_op] != usage_t(no_usage);\n        keep     &= op_usage[i_op] != usage_t(csum_usage);\n        keep     &= op_previous[i_op] == 0;\n        if( keep )\n        {   sparse::list_setvec_const_iterator itr(cexp_set, i_op);\n            if( *itr != cexp_set.end() )\n            {   if( play->GetOp(i_op) == AFunOp )\n                {   // i_op is the first operations in this atomic function call.\n                    // Find the last operation in this call.\n                    ++j_op;\n                    while( play->GetOp(j_op) != AFunOp )\n                    {   switch( play->GetOp(j_op) )\n                        {   case FunapOp:\n                            case FunavOp:\n                            case FunrpOp:\n                            case FunrvOp:\n                            break;\n\n                            default:\n                            CPPAD_ASSERT_UNKNOWN(false);\n                        }\n                        ++j_op;\n                    }\n                }\n            }\n            while( *itr != cexp_set.end() )\n            {   size_t element = *itr;\n                size_t index   = element / 2;\n                bool   compare = bool( element % 2 );\n                if( compare == false )\n                {   // cexp_info[index].skip_op_false.push_back(i_op);\n                    skip_op_false.post_element(index, i_op);\n                    if( j_op != i_op )\n                    {   // cexp_info[index].skip_op_false.push_back(j_op);\n                        skip_op_false.post_element(index, j_op);\n                    }\n                }\n                else\n                {   // cexp_info[index].skip_op_true.push_back(i_op);\n                    skip_op_true.post_element(index, i_op);\n                    if( j_op != i_op )\n                    {   // cexp_info[index].skip_op_true.push_back(j_op);\n                        skip_op_true.post_element(index, j_op);\n                    }\n                }\n                ++itr;\n            }\n        }\n        CPPAD_ASSERT_UNKNOWN( i_op <= j_op );\n        i_op += (1 + j_op) - i_op;\n    }\n    // process postings for skip_op_false, skip_op_true\n    for(size_t i = 0; i < num_cexp_op; ++i)\n    {   skip_op_false.process_post(i);\n        skip_op_true.process_post(i);\n    }\n    return;\n}\n\n} } } // END_CPPAD_LOCAL_OPTIMIZE_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/optimize/get_dyn_previous.hpp",
    "content": "# ifndef CPPAD_LOCAL_OPTIMIZE_GET_DYN_PREVIOUS_HPP\n# define CPPAD_LOCAL_OPTIMIZE_GET_DYN_PREVIOUS_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*!\n\\file get_cexp_info.hpp\nCreate operator information tables\n*/\n\n# include <cppad/local/optimize/match_op.hpp>\n# include <cppad/local/optimize/usage.hpp>\n# include <cppad/local/optimize/hash_code.hpp>\n\n// BEGIN_CPPAD_LOCAL_OPTIMIZE_NAMESPACE\nnamespace CppAD { namespace local { namespace optimize {\n\n/*!\nmapping from a dynamic parameter index to its arguments\n\n\\param i_dyn\nis the dynamic parameter index\n\n\\param dyn2par_index\nis the mapping from dynamic parameter index to parameter index\n(size is number of dynamic parameters).\n\n\\param par_is_dyn\ni-th element is true (false) if i-th parameter is (is not) dynamic\n(size is number of parameters).\n\n\\param dyn_arg_offset\nj-th element is the offset in dyn_par_arg of the first argument for j-th\ndynamic parameter's operator (size is number of dynamic parameters).\nThis is only defined for dynamic parameters indices less than or equal i_dyn.\n\n\\param dyn_par_arg\nit the vector of arguments for all the dynamic parameter operators.\nThis is only defined for dynamic parameters indices less than or equal i_dyn.\n\n\\param par_ind2dyn_ind\nis the mapping from parameter index to dynamic parameter index\n(size is number of parameters). This is only defined for parameter\nindices less than or equal the parameter index corresponding to i_dyn.\n\n\\param dyn_previous\nis the mapping from dynamic parameter index to previous dynamic parameter\nthat can be used as a replacement (size is number of dynamic parameters).\nThis is only defined for dynamic parameters indices less than or equal i_dyn.\n\n\\param arg_match\nSize of this vector must be number of arguments for operator for i_dyn.\nThe input value of its elements does not matter.\nUpn return it contains the parameter indices for the arguments\nto use when matching this operator\nArguments that are dynamic parameters, and have previous matches,\nhave been replaced by their previous matches.\n*/\ninline void dyn_arg_match(\n    size_t                    i_dyn           ,\n    const pod_vector<addr_t>& dyn2par_index ,\n    const pod_vector<bool>  & par_is_dyn      ,\n    const pod_vector<addr_t>& dyn_arg_offset  ,\n    const pod_vector<addr_t>& dyn_par_arg     ,\n    const pod_vector<addr_t>& par_ind2dyn_ind ,\n    const pod_vector<addr_t>& dyn_previous    ,\n    pod_vector<addr_t>&       arg_match       )\n{\n    // number of dynamic parameters\n    addr_t num_dynamic_par = addr_t( dyn2par_index.size() );\n    //\n    // check some assumptions\n    CPPAD_ASSERT_UNKNOWN( size_t( num_dynamic_par ) == dyn_arg_offset.size() );\n    CPPAD_ASSERT_UNKNOWN( size_t( num_dynamic_par ) == dyn_previous.size() );\n    CPPAD_ASSERT_UNKNOWN( par_is_dyn.size() == par_ind2dyn_ind.size() );\n    //\n    // number of arguments for this operator\n    addr_t n_arg = addr_t( arg_match.size() );\n    //\n    // index in dyn_par_arg of first argument for this operator\n    addr_t i_arg = dyn_arg_offset[i_dyn];\n    //\n    // loop over arguments for this operator\n    for(addr_t j = 0; j < n_arg; ++j)\n    {   // parameter index for this argument\n        addr_t j_par = dyn_par_arg[i_arg + j];\n        CPPAD_ASSERT_UNKNOWN( j_par < dyn2par_index[i_dyn] );\n        //\n        // map dynamic parameters arguments to previous matches\n        if( par_is_dyn[j_par] )\n        {   addr_t j_dyn = par_ind2dyn_ind[j_par];\n            if( dyn_previous[j_dyn] != num_dynamic_par )\n            {   CPPAD_ASSERT_UNKNOWN( dyn_previous[j_dyn] < j_dyn );\n                // previous dynamic parameter\n                j_dyn = dyn_previous[j_dyn];\n                // corresponding parameter\n                j_par = dyn2par_index[j_dyn];\n            }\n        }\n        arg_match[j] = j_par;\n    }\n    return;\n}\n\n/*!\nGet mapping from each dynamic parameter to a previous dynamic parameter\nthat can be used to replace it (if one exists).\n\n\\tparam Base\nbase type for the operator; i.e., this operation was recorded\nusing AD< Base > and computations by this routine are done using type\n Base.\n\n\\param play\nThis is the old operation sequence.\n\n\\param par_usage\nThe size of this vector is the number of parameters in the\noperation sequence.i.e., play->nun_var_rec().\nIt is the usage counting previous operator optimization of operators.\n\n\\param dyn_previous\nThe input size of this vector must be zero.\nUpon return it has size equal to the number of dynamic parameters in the\noperation sequence; i.e., num_dyn = play->num_dynamic_par().\nLet k = dyn_parvious[j]. If k == num_dyn, no replacement was found for the\nj-th dynamic parameter. If k != num_dyn, the k-th dynamic parameter can be\nused in place of the j-th dynamic parameter, k < j, dyn_previous[k] != num_dyn,\npar_usage[dyn2par_index[k]] == true.\n*/\n\ntemplate <class Base>\nvoid get_dyn_previous(\n    const player<Base>*                         play                ,\n    pod_vector<bool>&                           par_usage           ,\n    pod_vector<addr_t>&                         dyn_previous        )\n{\n    // number of parameters in the recording\n    size_t num_par = play->num_par_all();\n\n    // number of dynamic parameters in the recording\n    size_t num_dynamic_par = play->num_dynamic_par();\n\n    // number of independent dynamic parameters in the recording\n    size_t n_dyn_independent= play->n_dyn_independent();\n\n    // check some assumptions\n    CPPAD_ASSERT_UNKNOWN( dyn_previous.size() == 0 );\n    CPPAD_ASSERT_UNKNOWN( par_usage.size() == num_par );\n    CPPAD_ASSERT_UNKNOWN( num_dynamic_par <= num_par );\n    CPPAD_ASSERT_UNKNOWN( n_dyn_independent <= num_dynamic_par );\n    CPPAD_ASSERT_UNKNOWN( num_arg_dyn( ind_dyn ) == 0 );\n\n    // dynamic parameter information\n    dyn_previous.resize( num_dynamic_par );\n    const pod_vector<addr_t>&   dyn2par_index( play->dyn2par_index() );\n    const pod_vector<bool>&     par_is_dyn( play->par_is_dyn() );\n    const pod_vector<opcode_t>& dyn_par_op( play->dyn_par_op() );\n    const pod_vector<addr_t>&   dyn_par_arg( play->dyn_par_arg() );\n\n    // mapping from parameter index to dynamic parameter index\n    // only defined when par_is_dyn is true\n    pod_vector<addr_t> par_ind2dyn_ind(num_par);\n\n    // mapping from dynamic parameter index to first argument index\n    pod_vector<addr_t> dyn_arg_offset(num_dynamic_par);\n\n    // ----------------------------------------------------------------------\n    // compute dyn_previous\n    // ----------------------------------------------------------------------\n    sparse::list_setvec  hash_table_dyn;\n    hash_table_dyn.resize(CPPAD_HASH_TABLE_SIZE, num_dynamic_par);\n    //\n    // Initialize in dyn_par_arg\n    // (independent dynamic parameters do not have any arguments)\n    size_t i_arg = 0;\n    //\n    // independent dynamic parameters\n    for(size_t i_dyn = 0; i_dyn < n_dyn_independent; ++i_dyn)\n    {   // parameter index\n        size_t i_par = size_t( dyn2par_index[i_dyn] );\n        // dynamic parameter index is one greater because phantom parameter\n        // at index 0 is not dynamic\n        CPPAD_ASSERT_UNKNOWN( i_par == i_dyn + 1 );\n        // mapping from parameter index to dynamic parameter index\n        par_ind2dyn_ind[i_par] = addr_t( i_dyn );\n        // never get optimized out\n        dyn_previous[i_dyn]    = addr_t( num_dynamic_par );\n    }\n    //\n    // other dynamic parameters\n    for(size_t i_dyn = n_dyn_independent; i_dyn < num_dynamic_par; ++i_dyn)\n    {   // Initialize previous for this dynamic parameter. This is only\n        // defined for dynamic parameter indices less than or equal i_dyn\n        dyn_previous[i_dyn] = addr_t( num_dynamic_par );\n        //\n        // mapping from dynamic parameter index to argument offset\n        // is only defined for j_dyn <= i_dyn\n        dyn_arg_offset[i_dyn] = addr_t( i_arg );\n        //\n        // parameter index for this dynamic parameter\n        size_t i_par = size_t( dyn2par_index[i_dyn] );\n        //\n        // mapping from parameter indices to dynamic parameter indices\n        // is only defined when par_is_dyn[i_par] is true and for parameter\n        // indices less than or equal i_par\n        CPPAD_ASSERT_UNKNOWN( par_is_dyn[i_par] );\n        par_ind2dyn_ind[i_par] = addr_t( i_dyn );\n        //\n        // operator for this dynamic parameter\n        op_code_dyn op = op_code_dyn( dyn_par_op[i_dyn] );\n        //\n        // temporary used below and decaled here to reduce memory allocation\n        pod_vector<addr_t> arg_match;\n        //\n        // temporaries used below and decaled here to reduce indentation level\n        bool   match;\n        size_t code;\n        size_t count;\n        //\n        // check for a previous match for i_dyn\n        if( par_usage[i_par] ) switch( op )\n        {\n            // ---------------------------------------------------------------\n            // unary operators\n            case abs_dyn:\n            case acos_dyn:\n            case acosh_dyn:\n            case asin_dyn:\n            case asinh_dyn:\n            case atan_dyn:\n            case atanh_dyn:\n            case cos_dyn:\n            case cosh_dyn:\n            case erf_dyn:\n            case erfc_dyn:\n            case exp_dyn:\n            case expm1_dyn:\n            case fabs_dyn:\n            case log_dyn:\n            case log1p_dyn:\n            case neg_dyn:\n            case sign_dyn:\n            case sin_dyn:\n            case sinh_dyn:\n            case sqrt_dyn:\n            case tan_dyn:\n            case tanh_dyn:\n            CPPAD_ASSERT_UNKNOWN( num_arg_dyn(op) == 1);\n            CPPAD_ASSERT_UNKNOWN( par_is_dyn[i_par] );\n            {   size_t num_arg = 1;\n                arg_match.resize(num_arg);\n                dyn_arg_match(\n                    i_dyn,\n                    dyn2par_index,\n                    par_is_dyn,\n                    dyn_arg_offset,\n                    dyn_par_arg,\n                    par_ind2dyn_ind,\n                    dyn_previous,\n                    arg_match\n                );\n                opcode_t op_t  = opcode_t(op);\n                code           = optimize_hash_code(\n                    op_t, num_arg, arg_match.data()\n                );\n                //\n                // iterator for the set with this hash code\n                sparse::list_setvec_const_iterator itr(hash_table_dyn, code);\n                //\n                // check for a match\n                count = 0;\n                match = false;\n                while( ! match && *itr != num_dynamic_par )\n                {   ++count;\n                    //\n                    // candidate for current dynamic parameter\n                    size_t  k_dyn  = *itr;\n                    CPPAD_ASSERT_UNKNOWN( k_dyn < i_dyn );\n                    //\n                    // argument offset for the candidate\n                    addr_t k_arg   = dyn_arg_offset[k_dyn];\n                    //\n                    match  = op_t == dyn_par_op[k_dyn];\n                    match &= arg_match[0] == dyn_par_arg[k_arg + 0];\n                    if( ! match )\n                        ++itr;\n                }\n                if( match )\n                {   size_t  k_dyn  = *itr;\n                    CPPAD_ASSERT_UNKNOWN( k_dyn < i_dyn );\n                    dyn_previous[i_dyn] = addr_t( k_dyn );\n                }\n                else\n                {   CPPAD_ASSERT_UNKNOWN( count < 11 );\n                    if( count == 10 )\n                    {   // restart list for this hash code\n                        hash_table_dyn.clear(code);\n                    }\n                    // Add this entry to hash table.\n                    // Not using post_element because we need to iterate for\n                    // this code before adding another element for this code.\n                    hash_table_dyn.add_element(code, i_dyn);\n                }\n            }\n            break;\n\n            // ---------------------------------------------------------------\n            // binary operators\n            case add_dyn:\n            case div_dyn:\n            case mul_dyn:\n            case pow_dyn:\n            case sub_dyn:\n            case zmul_dyn:\n            CPPAD_ASSERT_UNKNOWN( num_arg_dyn(op) == 2);\n            CPPAD_ASSERT_UNKNOWN( par_is_dyn[i_par] );\n            match = false;\n            {   size_t num_arg = 2;\n                arg_match.resize(num_arg);\n                dyn_arg_match(\n                    i_dyn,\n                    dyn2par_index,\n                    par_is_dyn,\n                    dyn_arg_offset,\n                    dyn_par_arg   ,\n                    par_ind2dyn_ind,\n                    dyn_previous,\n                    arg_match\n                );\n                opcode_t op_t  = opcode_t(op);\n                code           = optimize_hash_code(\n                    op_t, num_arg, arg_match.data()\n                );\n                //\n                // iterator for the set with this hash code\n                sparse::list_setvec_const_iterator itr(hash_table_dyn, code);\n                //\n                // check for a match\n                count = 0;\n                while( ! match && *itr != num_dynamic_par )\n                {   ++count;\n                    //\n                    // candidate for current dynamic parameter\n                    size_t  k_dyn  = *itr;\n                    CPPAD_ASSERT_UNKNOWN( k_dyn < i_dyn );\n                    //\n                    // argument offset for the candidate\n                    addr_t k_arg   = dyn_arg_offset[k_dyn];\n                    //\n                    match  = op_t == dyn_par_op[k_dyn];\n                    match &= arg_match[0] == dyn_par_arg[k_arg + 0];\n                    match &= arg_match[1] == dyn_par_arg[k_arg + 1];\n                    if( ! match )\n                        ++itr;\n                }\n                if( match )\n                {   size_t  k_dyn  = *itr;\n                    CPPAD_ASSERT_UNKNOWN( k_dyn < i_dyn );\n                    dyn_previous[i_dyn] = addr_t( k_dyn );\n                }\n            }\n            if( (! match) && ( (op == add_dyn) || (op == mul_dyn) ) )\n            {   size_t num_arg = 2;\n                std::swap( arg_match[0], arg_match[1] );\n                opcode_t op_t    = opcode_t(op);\n                size_t code_swp  = optimize_hash_code(\n                    op_t, num_arg, arg_match.data()\n                );\n                //\n                // iterator for the set with this hash code\n                sparse::list_setvec_const_iterator itr(hash_table_dyn, code_swp);\n                //\n                // check for a match\n                while( ! match && *itr != num_dynamic_par )\n                {   //\n                    // candidate for current dynamic parameter\n                    size_t  k_dyn  = *itr;\n                    CPPAD_ASSERT_UNKNOWN( k_dyn < i_dyn );\n                    //\n                    // argument offset for the candidate\n                    addr_t k_arg   = dyn_arg_offset[k_dyn];\n                    //\n                    match  = op_t == dyn_par_op[k_dyn];\n                    match &= arg_match[0] == dyn_par_arg[k_arg + 0];\n                    match &= arg_match[1] == dyn_par_arg[k_arg + 1];\n                    if( ! match )\n                        ++itr;\n                }\n                if( match )\n                {   size_t  k_dyn  = *itr;\n                    CPPAD_ASSERT_UNKNOWN( k_dyn < i_dyn );\n                    dyn_previous[i_dyn] = addr_t( k_dyn );\n                }\n            }\n            if( ! match )\n            {   CPPAD_ASSERT_UNKNOWN( count < 11 );\n                if( count == 10 )\n                {   // restart list for this hash code\n                    hash_table_dyn.clear(code);\n                }\n                // Add the entry to hash table\n                // Not using post_element because we need to iterate for\n                // this code before adding another element for this code.\n                hash_table_dyn.add_element(code, i_dyn);\n            }\n\n            // --------------------------------------------------------------\n            // skipping these cases for now\n            case dis_dyn:\n            case cond_exp_dyn:\n            case atom_dyn:\n            case result_dyn:\n            break;\n\n\n            // --------------------------------------------------------------\n            // should be no other cases; e.g., no ind_dyn or number_dyn.\n            default:\n            CPPAD_ASSERT_UNKNOWN(false);\n            break;\n        }\n        i_arg += num_arg_dyn(op);\n        if( op == atom_dyn )\n        {   CPPAD_ASSERT_UNKNOWN( num_arg_dyn(op) == 0 );\n            size_t n     = size_t( dyn_par_arg[i_arg + 2] );\n            size_t m     = size_t( dyn_par_arg[i_arg + 3] );\n            size_t n_arg = 6 + n + m;\n            i_arg += n_arg;\n        }\n    }\n}\n\n} } } // END_CPPAD_LOCAL_OPTIMIZE_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/optimize/get_op_previous.hpp",
    "content": "# ifndef CPPAD_LOCAL_OPTIMIZE_GET_OP_PREVIOUS_HPP\n# define CPPAD_LOCAL_OPTIMIZE_GET_OP_PREVIOUS_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/local/optimize/match_op.hpp>\n# include <cppad/local/optimize/usage.hpp>\n\n// BEGIN_CPPAD_LOCAL_OPTIMIZE_NAMESPACE\nnamespace CppAD { namespace local { namespace optimize {\n/*\n{xrst_begin optimize_get_op_previous dev}\n{xrst_spell\n    cexp\n}\n\nGet Mapping From Op to Previous Op That is Equivalent\n#####################################################\n\nSyntax\n******\n| *exceed_collision_limit* = ``get_op_previous`` (\n| |tab| *collision_limit* ,\n| |tab| *play* ,\n| |tab| *random_itr* ,\n| |tab| *cexp_set* ,\n| |tab| *op_previous* ,\n| |tab| *op_usage*\n| )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_PROTOTYPE\n    // END_PROTOTYPE\n}\n\nBase\n****\nbase type for the operator; i.e., this operation was recorded\nusing AD<Base> and computations by this routine are done using type Base.\n\ncollision_limit\n***************\nis the maximum number of collisions (matches)\nallowed in the hash expression has table.\n\nplay\n****\nis the old operation sequence.\n\nrandom_itr\n**********\nis a random iterator for the old operation sequence.\n\ncexp_set\n********\nset[i] is a set of elements for the i-th operator.\nSuppose that e is an element of set[i], j = e / 2, k = e % 2.\nIf the comparison for the j-th conditional expression is equal to bool(k),\nthe i-th operator can be skipped (is not used by any of the results).\nNote the j indexes the CExpOp operators in the operation sequence.\nOn input, cexp_set is does not count previous optimization.\nOn output, it does count previous optimization.\n\nop_previous\n***********\nThe input size of this vector must be zero.\nUpon return it has size equal to the number of operators\nin the operation sequence; i.e., num_op = play->nun_var_rec().\nLet j = op_previous[i]. If j = 0, no replacement was found for i-th operator.\nIf j != 0:\n\n#. j < i\n#. op_previous[j] == 0\n#. op_usage[j] == usage_t(yes_usage)\n#. i-th operator has NumArg(op) <= 3\n#. i-th operator has 0 < NumRes(op)\n#. i-th operator is not one of the following:\n   {xrst_spell_off}\n   PriOp, ParOp, InvOp, EndOp, CexpOp, BeginOp.\n   {xrst_spell_on}\n#. i-th operator is not one of the load store operator:\n   {xrst_spell_off}\n   LtpvOp, LtvpOp, LtvvOp, StppOp, StpvOp, StvpOp, StvvOp.\n   {xrst_spell_on}\n#. i-th operator is not a atomic function operator:\n   {xrst_spell_off}\n   AFunOp, FunapOp, FunavOp, FunrpOp, FunrvOp.\n   {xrst_spell_on}\n\nop_usage\n********\nThe size of this vector is the number of operators in the\nold operation sequence.i.e., play->nun_var_rec().\nOn input, op_usage[i] is the usage for\nthe i-th operator in the operation sequence not counting previous\noptimization.\nOn output, it is the usage counting previous operator optimization.\n\nexceed_collision_limit\n**********************\nIf the *collision_limit* is exceeded (is not exceeded),\nthe return value is true (false).\n\n{xrst_end optimize_get_op_previous}\n*/\n\n// BEGIN_PROTOTYPE\ntemplate <class Addr, class Base>\nbool get_op_previous(\n    size_t                                      collision_limit     ,\n    const player<Base>*                         play                ,\n    const play::const_random_iterator<Addr>&    random_itr          ,\n    sparse::list_setvec&                        cexp_set            ,\n    pod_vector<addr_t>&                         op_previous         ,\n    pod_vector<usage_t>&                        op_usage            )\n// END_PROTOTYPE\n{   bool exceed_collision_limit = false;\n    //\n    // number of operators in the tape\n    const size_t num_op = random_itr.num_op();\n    CPPAD_ASSERT_UNKNOWN( op_previous.size() == 0 );\n    CPPAD_ASSERT_UNKNOWN( op_usage.size() == num_op );\n    op_previous.resize( num_op );\n    //\n    // number of conditional expressions in the tape\n    //\n    // initialize mapping from variable index to operator index\n    CPPAD_ASSERT_UNKNOWN(\n        size_t( (std::numeric_limits<addr_t>::max)() ) >= num_op\n    );\n    // ----------------------------------------------------------------------\n    // compute op_previous\n    // ----------------------------------------------------------------------\n    sparse::list_setvec  hash_table_op;\n    hash_table_op.resize(CPPAD_HASH_TABLE_SIZE, num_op);\n    //\n    pod_vector<bool> work_bool;\n    pod_vector<addr_t> work_addr_t;\n    for(size_t i_op = 0; i_op < num_op; ++i_op)\n    {   op_previous[i_op] = 0;\n\n        if( op_usage[i_op] == usage_t(yes_usage) )\n        switch( random_itr.get_op(i_op) )\n        {\n            // ----------------------------------------------------------------\n            // these operators never match previous operators\n            case BeginOp:\n            case CExpOp:\n            case CSkipOp:\n            case CSumOp:\n            case EndOp:\n            case InvOp:\n            case LdpOp:\n            case LdvOp:\n            case ParOp:\n            case PriOp:\n            case StppOp:\n            case StpvOp:\n            case StvpOp:\n            case StvvOp:\n            case AFunOp:\n            case FunapOp:\n            case FunavOp:\n            case FunrpOp:\n            case FunrvOp:\n            break;\n\n            // ----------------------------------------------------------------\n            // check for a previous match\n            // BEGIN_SORT_THIS_LINE_PLUS_1\n            case AbsOp:\n            case AcosOp:\n            case AcoshOp:\n            case AddpvOp:\n            case AddvvOp:\n            case AsinOp:\n            case AsinhOp:\n            case AtanOp:\n            case AtanhOp:\n            case CosOp:\n            case CoshOp:\n            case DisOp:\n            case DivpvOp:\n            case DivvpOp:\n            case DivvvOp:\n            case EqppOp:\n            case EqpvOp:\n            case EqvvOp:\n            case ErfOp:\n            case ErfcOp:\n            case ExpOp:\n            case Expm1Op:\n            case LeppOp:\n            case LepvOp:\n            case LevpOp:\n            case LevvOp:\n            case Log1pOp:\n            case LogOp:\n            case LtppOp:\n            case LtpvOp:\n            case LtvpOp:\n            case LtvvOp:\n            case MulpvOp:\n            case MulvvOp:\n            case NegOp:\n            case NeppOp:\n            case NepvOp:\n            case NevvOp:\n            case PowpvOp:\n            case PowvpOp:\n            case PowvvOp:\n            case SignOp:\n            case SinOp:\n            case SinhOp:\n            case SqrtOp:\n            case SubpvOp:\n            case SubvpOp:\n            case SubvvOp:\n            case TanOp:\n            case TanhOp:\n            case ZmulpvOp:\n            case ZmulvpOp:\n            case ZmulvvOp:\n            // END_SORT_THIS_LINE_MINUS_1\n            exceed_collision_limit |= match_op(\n                collision_limit,\n                random_itr,\n                op_previous,\n                i_op,\n                hash_table_op,\n                work_bool,\n                work_addr_t\n            );\n            if( op_previous[i_op] != 0 )\n            {   // like a unary operator that assigns i_op equal to previous.\n                size_t previous = size_t( op_previous[i_op] );\n                bool sum_op = false;\n                CPPAD_ASSERT_UNKNOWN( previous < i_op );\n                op_inc_arg_usage(\n                    play, sum_op, i_op, previous, op_usage, cexp_set\n                );\n            }\n            break;\n\n            // ----------------------------------------------------------------\n            default:\n            CPPAD_ASSERT_UNKNOWN(false);\n            break;\n        }\n    }\n    /* ---------------------------------------------------------------------\n    // Print out hash code usage summary\n    CppAD::vector<size_t> count(collision_limit + 1);\n    for(size_t i = 0; i <= collision_limit; ++i)\n        count[i] = 0;\n    for(size_t code = 0; code < CPPAD_HASH_TABLE_SIZE; ++code)\n    {   size_t size = hash_table_op.number_elements(code);\n        ++count[size];\n    }\n    std::cout << \"count = \" << count << \"\\n\";\n    --------------------------------------------------------------------- */\n    return exceed_collision_limit;\n}\n\n} } } // END_CPPAD_LOCAL_OPTIMIZE_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/optimize/get_op_usage.hpp",
    "content": "# ifndef CPPAD_LOCAL_OPTIMIZE_GET_OP_USAGE_HPP\n# define CPPAD_LOCAL_OPTIMIZE_GET_OP_USAGE_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/local/optimize/cexp_info.hpp>\n# include <cppad/local/optimize/usage.hpp>\n# include <cppad/local/sweep/call_atomic.hpp>\n\n// BEGIN_CPPAD_LOCAL_OPTIMIZE_NAMESPACE\nnamespace CppAD { namespace local { namespace optimize {\n\n/// Is this an addition or subtraction operator\ninline bool op_add_or_sub(\n    op_code_var op ///< operator we are checking\n)\n{   bool result;\n    switch(op)\n    {\n        case AddpvOp:\n        case AddvvOp:\n        case SubpvOp:\n        case SubvpOp:\n        case SubvvOp:\n        result = true;\n        break;\n\n        default:\n        result = false;\n        break;\n    }\n    return result;\n}\n\n/*!\n{xrst_begin optimize_op_inc_arg_usage dev}\n{xrst_spell\n    cexp\n    csum\n}\n\nIncrease Argument Usage and Propagate cexp_set From Result to Argument\n######################################################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_OP_INC_ARG_USAGE\n    // END_OP_INC_ARG_USAGE\n}\n\nplay\n****\nis the player for the old operation sequence.\n\ncheck_csum\n**********\nis result an addition or subtraction operator,\nand the optimizer is allowed to generate cumulative sum operators.\n\ni_result\n********\nis the operator index for the result operator.\nThere are no posting waiting to be processed for the corresponding cexp_set.\n\ni_arg\n*****\nis the operator index for the argument to the result operator.\nThere may be postings waiting to be processed for the corresponding cexp_set.\n\nop_usage\n********\nstructure that holds the information for each of the operators.\nThe output value of op_usage[i_arg] is increased; to be specific,\nIf check_csum is true and the input value of op_usage[i_arg]\nis usage_t(no_usage), its output value is usage_t(csum_usage).\nOtherwise, the output value of op_usage[i_arg] is usage_t(yes_usage).\n\ncexp_set\n********\nThis is a vector of sets with one set for each operator.\nWe denote the i-th set by set[i].\nThese are the conditional expression conditions that must be\nsatisfied for this argument to be used.\n\n#. In the special case where cexp_set.n_set() is zero,\n   cexp_set is not changed.\n#. If cexp_set.n_set() != 0 and op_usage[i_arg] == usage_t(no_usage),\n   the input value of set[i_arg] must be empty.\n   In this case the output value if set[i_arg] is equal to set[i_result]\n   (which may also be empty).\n#. If cexp_set.n_set() != 0 and op_usage[i_arg] != usage_t(no_usage),\n   the output value of set[i_arg] is the intersection of\n   its input value and set[i_result].\n\n{xrst_end optimize_op_inc_arg_usage}\n*/\n// BEGIN_OP_INC_ARG_USAGE\ntemplate <class Base>\nvoid op_inc_arg_usage(\n    const player<Base>*         play           ,\n    bool                        check_csum     ,\n    size_t                      i_result       ,\n    size_t                      i_arg          ,\n    pod_vector<usage_t>&        op_usage       ,\n    sparse::list_setvec&        cexp_set       )\n// END_OP_INC_ARG_USAGE\n{  // value of argument input on input to this routine\n    enum_usage arg_usage = enum_usage( op_usage[i_arg] );\n    //\n    // new value for usage\n    op_usage[i_arg] = usage_t(yes_usage);\n    if( check_csum )\n    {  if( arg_usage == no_usage )\n        {  op_code_var op_a = play->GetOp(i_arg);\n            if( op_add_or_sub( op_a ) )\n            {  op_usage[i_arg] = usage_t(csum_usage);\n            }\n        }\n    }\n    //\n    // cexp_set\n    if( cexp_set.n_set() == 0 )\n        return;\n    //\n    if( arg_usage == no_usage )\n    {  // set[i_arg] = set[i_result]\n        // not necessary to process posts for set i_result\n        cexp_set.assignment(i_arg, i_result, cexp_set);\n    }\n    else\n    {  // set[i_arg] = set[i_arg] intersect set[i_result]\n        // is necessary to process postts for set i_arg\n        cexp_set.process_post(i_arg);\n        cexp_set.binary_intersection(i_arg, i_arg, i_result, cexp_set);\n    }\n    //\n    return;\n}\n\n/*!\n{xrst_begin optimize_get_op_usage dev}\n{xrst_spell\n    cexp\n    dep\n    pri\n    taddr\n}\n\nUse Reverse Activity Analysis to Get Usage Information for Each Operator\n########################################################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_GET_OP_USAGE\n    // END_GET_OP_USAGE\n}\n\nBase\n****\nBase type for the operator; i.e., this operation was recorded\nusing ``AD`` < *Base* > and computations by this routine are done\nusing type *Base* .\n\nAddr\n****\nType used by random iterator for the player.\n\ncumulative_sum_op\n*****************\nIf this is true (false), cumulative summation operator are allowed\n(not allowed) to be generated by the optimization.\n\ncompare_op\n**********\nif this is true, arguments are considered used if they appear in compare\noperators. This is a side effect because compare operators have boolean\nresults (and the result is not in the tape; i.e. NumRes(op) is zero\nfor these operators. (This is an example of a side effect.)\n\nprint_for_op\n************\nif this is true, arguments are considered used if they appear in\nprint forward operators; i.e., PriOp.\nThis is also a side effect; i.e. NumRes(PriOp) is zero.\n\nconditional_skip\n****************\nIf this is true,\nthe conditional expression information cexp_info will be calculated.\nThis may be time intensive and may not have much benefit in the optimized\nrecording.\n\nplay\n****\nThis is the operation sequence.\n\nrandom_itr\n**********\nThis is a random iterator for the operation sequence.\n\ndep_taddr\n*********\nis a vector of indices for the dependent variables\n(where the reverse activity analysis starts).\n\ncexp2op\n*******\nThe input size of this vector must be zero.\nUpon return it has size equal to the number of conditional expressions,\nCExpOp operators. The value *cexp2op* [ ``j`` ] is the operator\nindex corresponding to the *j*-th conditional expressions.\n\ncexp_set\n********\nThis is a vector of sets that is empty on input.\nIf *conditional_skip* is false, *cexp_usage* is not modified.\nOtherwise, set[i] is a set of elements for the i-th operator.\nSuppose that e is an element of set[i], j = e / 2, k = e % 2.\nIf the comparison for the j-th conditional expression is equal to bool(k),\nthe i-th operator can be skipped (is not used by any of the results).\nNote that j indexes the CExpOp operators in the operation sequence.\n\nvecad_used\n**********\nThe input size of this vector must be zero.\nUpon return it has size equal to the number of VecAD vectors\nin the operations sequences; i.e., play->num_var_vecad().\nThe VecAD vectors are indexed in the order that their indices appear\nin the one large play->GetVecInd that holds all the VecAD vectors.\n\nop_usage\n********\nThe input size of this vector must be zero.\nUpon return it has size equal to the number of operators\nin the operation sequence; i.e., num_op = play->nun_var_rec().\nThe value *op_usage* [ *i* ] has been set to the usage for\nthe i-th operator in the operation sequence.\nAtomic function calls are a special case,\nthe first and second AFunOp have usage corresponding to the entire call.\nThe arguments have the usage for particular parameter or variable.\nThis usage is only for creating variables, not for creating\ndynamic parameters.\n\n{xrst_end optimize_get_op_usage}\n*/\n// BEGIN_GET_OP_USAGE\ntemplate <class Addr, class Base>\nvoid get_op_usage(\n    bool                                        conditional_skip    ,\n    bool                                        compare_op          ,\n    bool                                        print_for_op        ,\n    bool                                        cumulative_sum_op   ,\n    const player<Base>*                         play                ,\n    const play::const_random_iterator<Addr>&    random_itr          ,\n    const pod_vector<size_t>&                   dep_taddr           ,\n    pod_vector<addr_t>&                         cexp2op             ,\n    sparse::list_setvec&                        cexp_set            ,\n    pod_vector<bool>&                           vecad_used          ,\n    pod_vector<usage_t>&                        op_usage            )\n// END_GET_OP_USAGE\n{\n    CPPAD_ASSERT_UNKNOWN( cexp_set.n_set()  == 0 );\n    CPPAD_ASSERT_UNKNOWN( vecad_used.size() == 0 );\n    CPPAD_ASSERT_UNKNOWN( op_usage.size()   == 0 );\n\n    // number of operators in the tape\n    const size_t num_op = play->num_var_op();\n    //\n    // initialize mapping from variable index to operator index\n    CPPAD_ASSERT_UNKNOWN(\n        size_t( (std::numeric_limits<addr_t>::max)() ) >= num_op\n    );\n    // -----------------------------------------------------------------------\n    // information about current operator\n    op_code_var   op;     // operator\n    const addr_t* arg;    // arguments\n    size_t        i_op;   // operator index\n    size_t        i_var;  // variable index of first result\n    // -----------------------------------------------------------------------\n    // information about atomic function calls\n    size_t atom_index=0, atom_old=0, atom_m=0, atom_n=0, atom_i=0, atom_j=0;\n    enum_atom_state atom_state;\n    //\n    // work space used by user atomic functions\n    vector<Base>         atom_x;    // value of parameters in x\n    vector<ad_type_enum> type_x;    // type for each argument\n    vector<size_t>       atom_ix;   // variables indices for argument vector\n    vector<bool>         depend_y;  // results that are used\n    vector<bool>         depend_x;  // arguments that are used\n    //\n    // parameter information (used by atomic function calls)\n# ifndef NDEBUG\n    size_t num_par = play->num_par_all();\n# endif\n    CPPAD_ASSERT_UNKNOWN( num_par > 0 )\n    const Base* parameter = play->par_ptr();\n    // -----------------------------------------------------------------------\n    // vecad information\n    size_t num_vecad      = play->num_var_vecad();\n    size_t num_vecad_ind  = play->num_var_vec_ind();\n    //\n    vecad_used.resize(num_vecad);\n    for(size_t i = 0; i < num_vecad; i++)\n        vecad_used[i] = false;\n    //\n    vector<size_t> arg2vecad(num_vecad_ind);\n    for(size_t i = 0; i < num_vecad_ind; i++)\n        arg2vecad[i] = num_vecad; // invalid value\n    size_t arg_0 = 1; // value of arg[0] for theh first vecad\n    for(size_t i = 0; i < num_vecad; i++)\n    {\n        // mapping from arg[0] value to index for this vecad object.\n        arg2vecad[arg_0] = i;\n        //\n        // length of this vecad object\n        size_t length = play->GetVecInd(arg_0 - 1);\n        //\n        // set to proper index in GetVecInd for next VecAD arg[0] value\n        arg_0        += length + 1;\n    }\n    CPPAD_ASSERT_UNKNOWN( arg_0 == num_vecad_ind + 1 );\n    // -----------------------------------------------------------------------\n    // conditional expression information\n    //\n    size_t num_cexp_op = 0;\n    if( conditional_skip )\n    {   for(i_op = 0; i_op < num_op; ++i_op)\n        {   if( random_itr.get_op(i_op) == CExpOp )\n            {   // count the number of conditional expressions.\n                ++num_cexp_op;\n            }\n        }\n    }\n    //\n    cexp2op.resize( num_cexp_op );\n    //\n    // number of sets\n    size_t num_set = 0;\n    if( conditional_skip && num_cexp_op > 0)\n        num_set = num_op;\n    //\n    // conditional expression index   = element / 2\n    // conditional expression compare = bool ( element % 2)\n    size_t end_set = 2 * num_cexp_op;\n    //\n    if( num_set > 0 )\n        cexp_set.resize(num_set, end_set);\n    // -----------------------------------------------------------------------\n    // initialize operator usage for reverse dependency analysis.\n    op_usage.resize( num_op );\n    for(i_op = 0; i_op < num_op; ++i_op)\n        op_usage[i_op] = usage_t(no_usage);\n    for(size_t i = 0; i < dep_taddr.size(); i++)\n    {   i_op           = random_itr.var2op(dep_taddr[i]);\n        op_usage[i_op] = usage_t(yes_usage);    // dependent variables\n    }\n    // ----------------------------------------------------------------------\n    // Reverse pass to compute usage and cexp_set for each operator\n    // ----------------------------------------------------------------------\n    //\n    // Initialize reverse pass\n    size_t last_atom_i_op = 0;\n    size_t cexp_index     = num_cexp_op;\n    atom_state            = end_atom;\n    i_op = num_op;\n    while(i_op != 0 )\n    {   --i_op;\n        if( num_set > 0 )\n        {   // no more elements will be added to this set\n            cexp_set.process_post(i_op);\n        }\n        //\n        // this operator information\n        random_itr.op_info(i_op, op, arg, i_var);\n        //\n        // Is the result of this operation used.\n        // (This only makes sense when NumRes(op) > 0.)\n        usage_t use_result = op_usage[i_op];\n        //\n        bool check_csum = false;\n        switch( op )\n        {\n            // =============================================================\n            // normal operators\n            // =============================================================\n\n            // Only one variable with index arg[0]\n            case SubvpOp:\n            check_csum = cumulative_sum_op;\n            //\n            case AbsOp:\n            case AcosOp:\n            case AcoshOp:\n            case AsinOp:\n            case AsinhOp:\n            case AtanOp:\n            case AtanhOp:\n            case CosOp:\n            case CoshOp:\n            case DivvpOp:\n            case ErfOp:\n            case ErfcOp:\n            case ExpOp:\n            case Expm1Op:\n            case LogOp:\n            case Log1pOp:\n            case NegOp:\n            case PowvpOp:\n            case SignOp:\n            case SinOp:\n            case SinhOp:\n            case SqrtOp:\n            case TanOp:\n            case TanhOp:\n            case ZmulvpOp:\n            CPPAD_ASSERT_UNKNOWN( NumRes(op) > 0 );\n            if( use_result != usage_t(no_usage) )\n            {   size_t j_op = random_itr.var2op(size_t(arg[0]));\n                op_inc_arg_usage(\n                    play, check_csum, i_op, j_op, op_usage, cexp_set\n                );\n            }\n            break; // --------------------------------------------\n\n            // Only one variable with index arg[1]\n            case AddpvOp:\n            case SubpvOp:\n            check_csum = cumulative_sum_op;\n            //\n            case DisOp:\n            case DivpvOp:\n            case MulpvOp:\n            case PowpvOp:\n            case ZmulpvOp:\n            CPPAD_ASSERT_UNKNOWN( NumRes(op) > 0 );\n            if( use_result != usage_t(no_usage) )\n            {   size_t j_op = random_itr.var2op(size_t(arg[1]));\n                op_inc_arg_usage(\n                    play, check_csum, i_op, j_op, op_usage, cexp_set\n                );\n            }\n            break; // --------------------------------------------\n\n            // arg[0] and arg[1] are the only variables\n            case AddvvOp:\n            case SubvvOp:\n            check_csum = cumulative_sum_op;\n            //\n            case DivvvOp:\n            case MulvvOp:\n            case PowvvOp:\n            case ZmulvvOp:\n            CPPAD_ASSERT_UNKNOWN( NumRes(op) > 0 );\n            if( use_result != usage_t(no_usage) )\n            {   for(size_t i = 0; i < 2; i++)\n                {   size_t j_op = random_itr.var2op(size_t(arg[i]));\n                    op_inc_arg_usage(\n                        play, check_csum, i_op, j_op, op_usage, cexp_set\n                    );\n                }\n            }\n            break; // --------------------------------------------\n\n            // Conditional expression operators\n            // arg[2], arg[3], arg[4], arg[5] are parameters or variables\n            case CExpOp:\n            CPPAD_ASSERT_UNKNOWN( NumRes(op) > 0 );\n            if( conditional_skip )\n            {   --cexp_index;\n                cexp2op[ cexp_index ] = addr_t(i_op);\n            }\n            if( use_result != usage_t(no_usage) )\n            {   CPPAD_ASSERT_UNKNOWN( NumArg(CExpOp) == 6 );\n                // propagate from result to left argument\n                if( arg[1] & 1 )\n                {   size_t j_op = random_itr.var2op(size_t(arg[2]));\n                    op_inc_arg_usage(\n                        play, check_csum, i_op, j_op, op_usage, cexp_set\n                    );\n                }\n                // propagate from result to right argument\n                if( arg[1] & 2 )\n                {   size_t j_op = random_itr.var2op(size_t(arg[3]));\n                    op_inc_arg_usage(\n                            play, check_csum, i_op, j_op, op_usage, cexp_set\n                    );\n                }\n                // are if_true and if_false cases the same variable\n                bool same_variable = (arg[1] & 4) != 0;\n                same_variable     &= (arg[1] & 8) != 0;\n                same_variable     &= arg[4] == arg[5];\n                //\n                // if_true\n                if( arg[1] & 4 )\n                {   size_t j_op = random_itr.var2op(size_t(arg[4]));\n                    bool can_skip = conditional_skip & (! same_variable);\n                    can_skip     &= op_usage[j_op] == usage_t(no_usage);\n                    op_inc_arg_usage(\n                        play, check_csum, i_op, j_op, op_usage, cexp_set\n                    );\n                    if( can_skip )\n                    {   // j_op corresponds to the value used when the\n                        // comparison result is true. It can be skipped when\n                        // the comparison is false (0).\n                        size_t element = 2 * cexp_index + 0;\n                        cexp_set.post_element(j_op, element);\n                        //\n                        op_usage[j_op] = usage_t(yes_usage);\n                    }\n                }\n                //\n                // if_false\n                if( arg[1] & 8 )\n                {   size_t j_op = random_itr.var2op(size_t(arg[5]));\n                    bool can_skip = conditional_skip & (! same_variable);\n                    can_skip     &= op_usage[j_op] == usage_t(no_usage);\n                    op_inc_arg_usage(\n                        play, check_csum, i_op, j_op, op_usage, cexp_set\n                    );\n                    if( can_skip )\n                    {   // j_op corresponds to the value used when the\n                        // comparison result is false. It can be skipped when\n                        // the comparison is true (0).\n                        size_t element = 2 * cexp_index + 1;\n                        cexp_set.post_element(j_op, element);\n                        //\n                        op_usage[j_op] = usage_t(yes_usage);\n                    }\n                }\n            }\n            break;  // --------------------------------------------\n\n            // Operations that are never used\n            // (new CSkip options are generated if conditional_skip is true)\n            case CSkipOp:\n            case ParOp:\n            break;\n\n            // Operators that are always used\n            case InvOp:\n            case BeginOp:\n            case EndOp:\n            op_usage[i_op] = usage_t(yes_usage);\n            break;  // -----------------------------------------------\n\n            // The print forward operator\n            case PriOp:\n            CPPAD_ASSERT_NARG_NRES(op, 5, 0);\n            if( print_for_op )\n            {   op_usage[i_op] = usage_t(yes_usage);\n                if( arg[0] & 1 )\n                {   // arg[1] is a variable\n                    size_t j_op = random_itr.var2op(size_t(arg[1]));\n                    op_inc_arg_usage(\n                        play, check_csum, i_op, j_op, op_usage, cexp_set\n                    );\n                }\n                if( arg[0] & 2 )\n                {   // arg[3] is a variable\n                    size_t j_op = random_itr.var2op(size_t(arg[3]));\n                    op_inc_arg_usage(\n                        play, check_csum, i_op, j_op, op_usage, cexp_set\n                    );\n                }\n            }\n            break; // -----------------------------------------------------\n\n            // =============================================================\n            // Comparison operators\n            // =============================================================\n\n            // Compare operator were none of the operatros are variables\n            case EqppOp:\n            case LeppOp:\n            case LtppOp:\n            case NeppOp:\n            if( compare_op )\n                op_usage[i_op] = usage_t(yes_usage);\n            break; // ----------------------------------------------\n\n            // Compare operators where arg[1] is only variable\n            case LepvOp:\n            case LtpvOp:\n            case EqpvOp:\n            case NepvOp:\n            CPPAD_ASSERT_UNKNOWN( NumRes(op) == 0 );\n            if( compare_op )\n            {   op_usage[i_op] = usage_t(yes_usage);\n                //\n                size_t j_op = random_itr.var2op(size_t(arg[1]));\n                op_inc_arg_usage(\n                    play, check_csum, i_op, j_op, op_usage, cexp_set\n                );\n            }\n            break; // ----------------------------------------------\n\n            // Compare operators where arg[0] is only variable\n            case LevpOp:\n            case LtvpOp:\n            CPPAD_ASSERT_UNKNOWN( NumRes(op) == 0 );\n            if( compare_op )\n            {   op_usage[i_op] = usage_t(yes_usage);\n                //\n                size_t j_op = random_itr.var2op(size_t(arg[0]));\n                op_inc_arg_usage(\n                    play, check_csum, i_op, j_op, op_usage, cexp_set\n                );\n            }\n            break; // ----------------------------------------------\n\n            // Compare operators where arg[0] and arg[1] are variables\n            case LevvOp:\n            case LtvvOp:\n            case EqvvOp:\n            case NevvOp:\n            CPPAD_ASSERT_UNKNOWN( NumRes(op) == 0 );\n            if( compare_op )\n            {   op_usage[i_op] = usage_t(yes_usage);\n                //\n                for(size_t i = 0; i < 2; i++)\n                {   size_t j_op = random_itr.var2op(size_t(arg[i]));\n                    op_inc_arg_usage(\n                        play, check_csum, i_op, j_op, op_usage, cexp_set\n                    );\n                }\n            }\n            break; // ----------------------------------------------\n\n            // =============================================================\n            // VecAD operators\n            // =============================================================\n\n            // load operator using a parameter index\n            case LdpOp:\n            CPPAD_ASSERT_UNKNOWN( NumRes(op) > 0 );\n            if( use_result != usage_t(no_usage) )\n            {   size_t i_vec = arg2vecad[ arg[0] ];\n                vecad_used[i_vec] = true;\n            }\n            break; // --------------------------------------------\n\n            // load operator using a variable index\n            case LdvOp:\n            CPPAD_ASSERT_UNKNOWN( NumRes(op) > 0 );\n            if( use_result != usage_t(no_usage) )\n            {   size_t i_vec = arg2vecad[ arg[0] ];\n                vecad_used[i_vec] = true;\n                //\n                size_t j_op = random_itr.var2op(size_t(arg[1]));\n                op_usage[j_op] = usage_t(yes_usage);\n            }\n            break; // --------------------------------------------\n\n            // Store a variable using a parameter index\n            case StpvOp:\n            CPPAD_ASSERT_UNKNOWN( NumRes(op) == 0 );\n            if( vecad_used[ arg2vecad[ arg[0] ] ] )\n            {   op_usage[i_op] = usage_t(yes_usage);\n                //\n                size_t j_op = random_itr.var2op(size_t(arg[2]));\n                op_usage[j_op] = usage_t(yes_usage);\n            }\n            break; // --------------------------------------------\n\n            // Store a variable using a variable index\n            case StvvOp:\n            CPPAD_ASSERT_UNKNOWN( NumRes(op) == 0 );\n            if( vecad_used[ arg2vecad[ arg[0] ] ] )\n            {   op_usage[i_op] = usage_t(yes_usage);\n                //\n                size_t j_op = random_itr.var2op(size_t(arg[1]));\n                op_usage[j_op] = usage_t(yes_usage);\n                size_t k_op = random_itr.var2op(size_t(arg[2]));\n                op_usage[k_op] = usage_t(yes_usage);\n            }\n            break; // -----------------------------------------------------\n\n            // =============================================================\n            // cumulative summation operator\n            // ============================================================\n            case CSumOp:\n            CPPAD_ASSERT_UNKNOWN( NumRes(op) == 1 );\n            {\n                for(size_t i = 5; i < size_t(arg[2]); i++)\n                {   size_t j_op = random_itr.var2op(size_t(arg[i]));\n                    op_inc_arg_usage(\n                        play, check_csum, i_op, j_op, op_usage, cexp_set\n                    );\n                }\n            }\n            break;\n\n            // =============================================================\n            // user defined atomic operators\n            // ============================================================\n\n            case AFunOp:\n            // start or end atomic operation sequence\n            if( atom_state == end_atom )\n            {   // reverse_user using random_itr instead of play\n                atom_index        = size_t(arg[0]);\n                atom_old          = size_t(arg[1]);\n                atom_n            = size_t(arg[2]);\n                atom_m            = size_t(arg[3]);\n                atom_j            = atom_n;\n                atom_i            = atom_m;\n                atom_state        = ret_atom;\n                // -------------------------------------------------------\n                last_atom_i_op = i_op;\n                CPPAD_ASSERT_UNKNOWN( i_op > atom_n + atom_m + 1 );\n                CPPAD_ASSERT_UNKNOWN(\n                    op_usage[last_atom_i_op] == usage_t(no_usage)\n                );\n# ifndef NDEBUG\n                if( cexp_set.n_set() > 0 )\n                {   cexp_set.process_post(last_atom_i_op);\n                    CPPAD_ASSERT_UNKNOWN(\n                        cexp_set.number_elements(last_atom_i_op) == 0\n                    );\n                }\n# endif\n                //\n                atom_x.resize(  atom_n );\n                type_x.resize( atom_n );\n                atom_ix.resize( atom_n );\n                //\n                depend_y.resize( atom_m );\n                depend_x.resize( atom_n );\n                for(size_t i = 0; i < atom_m; i++)\n                    depend_y[ i ] = false;\n            }\n            else\n            {   // reverse_user using random_itr instead of play\n                CPPAD_ASSERT_UNKNOWN( atom_state == start_atom );\n                CPPAD_ASSERT_UNKNOWN( atom_n == size_t(arg[2]) );\n                CPPAD_ASSERT_UNKNOWN( atom_m == size_t(arg[3]) );\n                CPPAD_ASSERT_UNKNOWN( atom_j == 0 );\n                CPPAD_ASSERT_UNKNOWN( atom_i == 0 );\n                atom_state = end_atom;\n                // -------------------------------------------------------\n                CPPAD_ASSERT_UNKNOWN(\n                    i_op + atom_n + atom_m + 1 == last_atom_i_op\n                );\n                if( op_usage[last_atom_i_op] != usage_t(no_usage) )\n                {   // call atomic function for this operation\n                    sweep::call_atomic_rev_depend<Base, Base>(\n                    atom_index, atom_old, atom_x, type_x, depend_x, depend_y\n                    );\n                    for(size_t j = 0; j < atom_n; j++)\n                    if( depend_x[j] )\n                    {   // The parameter or variable corresponding to the j-th\n                        // argument gets used\n                        op_usage[i_op + 1 + j] = true;\n                        if( type_x[j] == variable_enum )\n                        {   CPPAD_ASSERT_UNKNOWN( atom_ix[j] > 0 );\n                            if( depend_x[j] )\n                            {   size_t j_op = random_itr.var2op(atom_ix[j]);\n                                op_inc_arg_usage(play, check_csum,\n                                    last_atom_i_op, j_op, op_usage, cexp_set\n                                );\n                            }\n                        }\n                    }\n                }\n                // copy set information from last to first\n                if( cexp_set.n_set() > 0 )\n                {   cexp_set.process_post(last_atom_i_op);\n                    cexp_set.assignment(i_op, last_atom_i_op, cexp_set);\n                }\n                // copy usage information from last to first\n                op_usage[i_op] = op_usage[last_atom_i_op];\n            }\n            break; // -------------------------------------------------------\n\n            case FunapOp:\n            // parameter argument in an atomic operation sequence\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );\n            //\n            // reverse_user using random_itr instead of play\n            CPPAD_ASSERT_NARG_NRES(op, 1, 0);\n            CPPAD_ASSERT_UNKNOWN( 0 < atom_j && atom_j <= atom_n );\n            --atom_j;\n            if( atom_j == 0 )\n                atom_state = start_atom;\n            // -------------------------------------------------------------\n            atom_ix[atom_j] = 0;\n            //\n            // parameter arguments\n            atom_x[atom_j] = parameter[arg[0]];\n            if( play->par_is_dyn()[arg[0]] )\n                type_x[atom_j] = dynamic_enum;\n            else\n                type_x[atom_j] = constant_enum;\n            //\n            break;\n\n            case FunavOp:\n            // variable argument in an atomic operation sequence\n            CPPAD_ASSERT_UNKNOWN( 0 < arg[0] );\n            //\n            // reverse_user using random_itr instead of play\n            CPPAD_ASSERT_NARG_NRES(op, 1, 0);\n            CPPAD_ASSERT_UNKNOWN( 0 < atom_j && atom_j <= atom_n );\n            --atom_j;\n            if( atom_j == 0 )\n                atom_state = start_atom;\n            // -------------------------------------------------------------\n            atom_ix[atom_j] = size_t(arg[0]);\n            //\n            // variable arguments as parameters\n            atom_x[atom_j] = CppAD::numeric_limits<Base>::quiet_NaN();\n            type_x[atom_j] = variable_enum;\n            //\n            break;\n\n            case FunrvOp:\n            // variable result in an atomic operation sequence\n            //\n            // reverse_user using random_itr instead of play\n            CPPAD_ASSERT_NARG_NRES(op, 0, 1);\n            CPPAD_ASSERT_UNKNOWN( 0 < atom_i && atom_i <= atom_m );\n            --atom_i;\n            if( atom_i == 0 )\n                atom_state = arg_atom;\n            // -------------------------------------------------------------\n            if( use_result )\n            {   depend_y[atom_i] = true;\n                op_inc_arg_usage(\n                    play, check_csum, i_op, last_atom_i_op, op_usage, cexp_set\n                );\n            }\n            break; // --------------------------------------------------------\n\n            case FunrpOp:\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );\n            //\n            // reverse_user using random_itr instead of play\n            CPPAD_ASSERT_NARG_NRES(op, 1, 0);\n            CPPAD_ASSERT_UNKNOWN( 0 < atom_i && atom_i <= atom_m );\n            --atom_i;\n            if( atom_i == 0 )\n                atom_state = arg_atom;\n            break;\n            // ============================================================\n\n            // all cases should be handled above\n            default:\n            CPPAD_ASSERT_UNKNOWN(0);\n        }\n    }\n    return;\n}\n\n} } } // END_CPPAD_LOCAL_OPTIMIZE_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/optimize/get_par_usage.hpp",
    "content": "# ifndef CPPAD_LOCAL_OPTIMIZE_GET_PAR_USAGE_HPP\n# define CPPAD_LOCAL_OPTIMIZE_GET_PAR_USAGE_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*!\n\\file get_cexp_info.hpp\nCreate operator information tables\n*/\n# include <cppad/local/optimize/get_op_usage.hpp>\n\n// BEGIN_CPPAD_LOCAL_OPTIMIZE_NAMESPACE\nnamespace CppAD { namespace local { namespace optimize {\n\n/*!\n{xrst_begin optimize_get_par_usage dev}\n\nUse Reverse Activity Analysis to Get Usage for Each Parameter\n#############################################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_GET_PAR_USAGE\n    // END_PROTOTYPE\n}\n\nBase\n****\nBase type for the operator; i.e., this operation was recorded\nusing ``AD`` < *Base* >\nand computations by this routine are done using type *Base* .\n\nAddr\n****\nType used by random iterator for the player.\n\nplay\n****\nThis is the operation sequence.\n\nrandom_itr\n**********\nThis is a random iterator for the operation sequence.\n\nop_usage\n********\nThis argument has size equal to the number of operators\nin the operation sequence; i.e., num_op = play->nun_var_rec().\nThe value *op_usage* [ *i* ] have been set to the usage for\nthe i-th operator in the operation sequence.\n\nvecad_used\n**********\nThis argument has size equal to the number of VecAD vectors\nin the operations sequences; i.e., play->num_var_vecad().\nThe VecAD vectors are indexed in the order that their indices appear\nin the one large play->GetVecInd that holds all the VecAD vectors.\n\npar_usage\n*********\nThe input size of this vector must be zero.\nUpon return it has size equal to the number of parameters\nin the operation sequence; i.e., play->num_par_all();\nThe value *par_usage* [ *i* ] is true if an only if\nthe i-th parameter is used to compute a dependent variable\nor parameter.\nThe nan at the beginning of the parameter vector\nand the independent dynamic parameters are always used.\n\n{xrst_end optimize_get_par_usage}\n*/\n\n// BEGIN_GET_PAR_USAGE\ntemplate <class Addr, class Base>\nvoid get_par_usage(\n    const player<Base>*                         play                ,\n    const play::const_random_iterator<Addr>&    random_itr          ,\n    const pod_vector<usage_t>&                  op_usage            ,\n    pod_vector<bool>&                           vecad_used          ,\n    pod_vector<bool>&                           par_usage           )\n// END_PROTOTYPE\n{\n    CPPAD_ASSERT_UNKNOWN( op_usage.size()   == play->num_var_op() );\n    CPPAD_ASSERT_UNKNOWN( par_usage.size()  == 0 );\n    //\n    // number of operators in the tape\n    const size_t num_op = play->num_var_op();\n    //\n    // number of parameters in the tape\n    const size_t num_par = play->num_par_all();\n    //\n    // number of dynamic parameters\n    const size_t num_dynamic_par = play->num_dynamic_par();\n    //\n    // number of independent dynamic parameters\n    size_t n_dyn_independent = play->n_dyn_independent();\n    //\n    // number of VecAD vectors\n    size_t num_vecad_vec = play->num_var_vecad();\n    //\n    // dynamic parameter information\n    const pod_vector<bool>&        par_is_dyn( play->par_is_dyn() );\n    const pod_vector<opcode_t>&    dyn_par_op( play->dyn_par_op() );\n    const pod_vector<addr_t>&      dyn_par_arg( play->dyn_par_arg() );\n    const pod_vector<addr_t>&      dyn2par_index( play->dyn2par_index() );\n    const pod_vector_maybe<Base>&  par_all( play->par_all() );\n    // -----------------------------------------------------------------------\n    // initialize par_usage\n    par_usage.resize(num_par);\n    par_usage[0] = true; // true for nan at beginning of parameter vector\n    for(size_t i_par = 1; i_par <= n_dyn_independent; ++i_par)\n        par_usage[i_par] = true;  // true for independent dynamic parameters\n    for(size_t i_par = n_dyn_independent+1; i_par < num_par; ++i_par)\n        par_usage[i_par] = false; // initialize as false for other parameters\n    //\n    // -----------------------------------------------------------------------\n    // set usage to true for VecAD parameters that get used\n    size_t start_this_vector = 0;\n    for(size_t i_vec = 0; i_vec < num_vecad_vec; ++i_vec)\n    {   // length of this vector (note length is not a parameter)\n        size_t length = play->GetVecInd(start_this_vector);\n        //\n        if( vecad_used[i_vec] )\n        {   // this vector gets used\n            for(size_t k = 1; k <= length; ++k)\n            {   // index of parameter used by this VecAD vector\n                size_t i_par = play->GetVecInd(start_this_vector + k);\n                // must not be a dynamic parameter\n                CPPAD_ASSERT_UNKNOWN( ! par_is_dyn[i_par] );\n                // set usage for this parameter\n                par_usage[i_par] = true;\n            }\n        }\n        start_this_vector += length + 1;\n    }\n    CPPAD_ASSERT_UNKNOWN( start_this_vector == play->num_var_vec_ind() );\n    //\n    // -----------------------------------------------------------------------\n    // forward pass to mark which parameters are used by necessary operators\n    // -----------------------------------------------------------------------\n    //\n    // information about atomic function calls\n    size_t atom_index=0, call_id=0, atom_m=0, atom_n=0, atom_i=0, atom_j=0;\n    enum_atom_state atom_state = start_atom;\n    //\n    // work space used by user atomic functions\n    vector<Base>         parameter_x; // value of parameters in x\n    vector<ad_type_enum> type_x;      // type for each component of z\n    vector<size_t>       atom_ix;     // variables indices for argument vector\n    vector<bool>         depend_y;    // results that are used\n    vector<bool>         depend_x;    // arguments that are used\n    //\n    for(size_t i_op = 0; i_op < num_op; ++i_op)\n    {\n        // information about current operator\n        op_code_var   op;     // operator\n        const addr_t* arg;    // arguments\n        size_t        i_var;  // variable index of first result\n        random_itr.op_info(i_op, op, arg, i_var);\n        //\n        bool skip = op_usage[i_op] == usage_t(no_usage);\n        skip     &= atom_state == start_atom;\n        if( ! skip ) switch( op )\n        {\n            // add or subtract with left a parameter and right a variable\n            case AddpvOp:\n            case SubpvOp:\n            if( par_is_dyn[ arg[0] ] )\n                par_usage[ arg[0] ] = true;\n            else\n            {   // determine if this parameter will be absorbed by csum\n                if( ! (op_usage[i_op] == csum_usage) )\n                {   // determine operator corresponding to variable\n                    size_t j_op = random_itr.var2op(size_t(arg[1]));\n                    CPPAD_ASSERT_UNKNOWN( op_usage[j_op] != no_usage );\n                    if( op_usage[j_op] != csum_usage )\n                        par_usage[ arg[0] ] = true;\n                }\n            }\n            break;\n\n            // subtract with left a variable and right a parameter\n            case SubvpOp:\n            if( par_is_dyn[ arg[1] ] )\n                par_usage[ arg[1] ] = true;\n            else\n            {   // determine if this parameter will be absorbed by csum\n                if( ! (op_usage[i_op] == csum_usage) )\n                {   // determine operator corresponding to variable\n                    size_t j_op = random_itr.var2op(size_t(arg[0]));\n                    CPPAD_ASSERT_UNKNOWN( op_usage[j_op] != no_usage );\n                    if( op_usage[j_op] != csum_usage )\n                        par_usage[ arg[1] ] = true;\n                }\n            }\n            break;\n\n\n\n            // cases with no parameter arguments\n            case AbsOp:\n            case AcosOp:\n            case AcoshOp:\n            case AddvvOp:\n            case AsinOp:\n            case AsinhOp:\n            case AtanOp:\n            case AtanhOp:\n            case BeginOp:\n            case CosOp:\n            case CoshOp:\n            case CSkipOp:\n            case DisOp:\n            case DivvvOp:\n            case EndOp:\n            case EqvvOp:\n            case ExpOp:\n            case Expm1Op:\n            case InvOp:\n            case LdvOp:\n            case LevvOp:\n            case LogOp:\n            case Log1pOp:\n            case LtvvOp:\n            case MulvvOp:\n            case NegOp:\n            case NevvOp:\n            case PowvvOp:\n            case SignOp:\n            case SinOp:\n            case SinhOp:\n            case SqrtOp:\n            case StvvOp:\n            case SubvvOp:\n            case TanOp:\n            case TanhOp:\n            case ZmulvvOp:\n            break;\n\n            // cases where first and second arguments are parameters\n            case EqppOp:\n            case LeppOp:\n            case LtppOp:\n            case NeppOp:\n            CPPAD_ASSERT_UNKNOWN( 2 <= NumArg(op) )\n            par_usage[arg[0]] = true;\n            par_usage[arg[1]] = true;\n            break;\n\n\n            // cases where only first argument is a parameter\n            case CSumOp:\n            case EqpvOp:\n            case DivpvOp:\n            case LepvOp:\n            case LtpvOp:\n            case MulpvOp:\n            case NepvOp:\n            case ParOp:\n            case PowpvOp:\n            case ZmulpvOp:\n            CPPAD_ASSERT_UNKNOWN( 1 <= NumArg(op) || op == CSumOp )\n            par_usage[arg[0]] = true;\n            break;\n\n            // cases where only second argument is a parameter\n            case DivvpOp:\n            case LevpOp:\n            case LdpOp:\n            case LtvpOp:\n            case PowvpOp:\n            case StpvOp:\n            case ZmulvpOp:\n            CPPAD_ASSERT_UNKNOWN( 2 <= NumArg(op) )\n            par_usage[arg[1]] = true;\n            break;\n\n            // cases where second and third arguments are parameters\n            case ErfOp:\n            case ErfcOp:\n            case StppOp:\n            CPPAD_ASSERT_UNKNOWN( 3 <= NumArg(op) )\n            par_usage[arg[1]] = true;\n            par_usage[arg[2]] = true;\n            break;\n\n            // cases where only third argument is a parameter\n            case StvpOp:\n            CPPAD_ASSERT_UNKNOWN( 3 <= NumArg(op) )\n            par_usage[arg[2]] = true;\n            break;\n\n            // conditional expression operator\n            case CExpOp:\n            CPPAD_ASSERT_UNKNOWN( 6 == NumArg(op) )\n            if( (arg[1] & 1) == 0 )\n                par_usage[arg[2]] = true;\n            if( (arg[1] & 2) == 0 )\n                par_usage[arg[3]] = true;\n            if( (arg[1] & 4) == 0 )\n                par_usage[arg[4]] = true;\n            if( (arg[1] & 8) == 0 )\n                par_usage[arg[5]] = true;\n            break;\n\n            // print function\n            case PriOp:\n            if( (arg[0] & 1) == 0 )\n                par_usage[arg[1]] = true;\n            if( (arg[0] & 2) == 0 )\n                par_usage[arg[3]] = true;\n            CPPAD_ASSERT_UNKNOWN( 5 == NumArg(op) )\n            break;\n\n            // --------------------------------------------------------------\n            // atomic function calls\n            case AFunOp:\n            if( atom_state == start_atom )\n            {   atom_index        = size_t(arg[0]);\n                call_id           = size_t(arg[1]);\n                atom_n            = size_t(arg[2]);\n                atom_m            = size_t(arg[3]);\n                atom_j            = 0;\n                atom_i            = 0;\n                atom_state        = arg_atom;\n                // -------------------------------------------------------\n                parameter_x.resize(  atom_n );\n                type_x.resize( atom_n );\n                atom_ix.resize( atom_n );\n                //\n                depend_y.resize( atom_m );\n                depend_x.resize( atom_n );\n            }\n            else\n            {   CPPAD_ASSERT_UNKNOWN( atom_state == end_atom );\n                CPPAD_ASSERT_UNKNOWN( atom_n == size_t(arg[2]) );\n                CPPAD_ASSERT_UNKNOWN( atom_m == size_t(arg[3]) );\n                CPPAD_ASSERT_UNKNOWN( atom_j == atom_n );\n                CPPAD_ASSERT_UNKNOWN( atom_i == atom_m );\n                atom_state = start_atom;\n                //\n                // call atomic function for this operation\n                sweep::call_atomic_rev_depend<Base, Base>(\n                atom_index, call_id, parameter_x, type_x, depend_x, depend_y\n                );\n                for(size_t j = 0; j < atom_n; j++)\n                if( depend_x[j] && type_x[j] != variable_enum )\n                {   // This user argument is a parameter that is needed\n                    CPPAD_ASSERT_UNKNOWN( atom_ix[j] > 0 );\n                    par_usage[ atom_ix[j] ] = true;\n                }\n            }\n            break;\n\n            case FunavOp:\n            // this argument is a variable\n            CPPAD_ASSERT_UNKNOWN( atom_state == arg_atom );\n            atom_ix[atom_j]     = 0;\n            parameter_x[atom_j] = par_all[0]; // variables get value nan\n            type_x[atom_j]      = variable_enum;\n            ++atom_j;\n            if( atom_j == atom_n )\n                atom_state = ret_atom;\n            break;\n\n            case FunapOp:\n            // this argument is a parameter\n            CPPAD_ASSERT_UNKNOWN( atom_state == arg_atom );\n            atom_ix[atom_j]     = size_t( arg[0] );\n            parameter_x[atom_j] = par_all[arg[0]]; // parameter value\n            if( par_is_dyn[arg[0]] )\n                type_x[atom_j] = dynamic_enum;\n            else\n                type_x[atom_j] = constant_enum;\n            ++atom_j;\n            if( atom_j == atom_n )\n                atom_state = ret_atom;\n            break;\n\n            case FunrpOp:\n            // this result is a parameter\n            CPPAD_ASSERT_UNKNOWN( atom_state == ret_atom );\n            depend_y[atom_i] = op_usage[i_op] != usage_t(no_usage);\n            ++atom_i;\n            if( atom_i == atom_m )\n                atom_state = end_atom;\n            break;\n\n            case FunrvOp:\n            // this result is a variable\n            CPPAD_ASSERT_UNKNOWN( atom_state == ret_atom );\n            depend_y[atom_i] = op_usage[i_op] != usage_t(no_usage);\n            ++atom_i;\n            if( atom_i == atom_m )\n                atom_state = end_atom;\n            break;\n            // --------------------------------------------------------------\n\n\n            default:\n            CPPAD_ASSERT_UNKNOWN(false);\n        }\n    }\n    // -----------------------------------------------------------------------\n    // reverse pass to determine which dynamic parameters are necessary\n    // -----------------------------------------------------------------------\n    size_t i_arg = dyn_par_arg.size(); // index in dyn_par_arg\n    size_t i_dyn = num_dynamic_par;    // index in dyn2par_index\n      while(i_dyn)\n    {   // next dynamic parameter in reverse order\n        --i_dyn;\n        op_code_dyn op = op_code_dyn( dyn_par_op[i_dyn] );\n        while( op == result_dyn )\n        {   --i_dyn;\n            op = op_code_dyn( dyn_par_op[i_dyn] );\n            CPPAD_ASSERT_UNKNOWN( op == result_dyn || op == atom_dyn );\n        }\n        if( op == atom_dyn )\n        {   // number of arguments for this operator\n            size_t n_arg = size_t( dyn_par_arg[i_arg - 1] );\n            //\n            // index of first argument for this operation\n            i_arg -= n_arg;\n            //\n            atom_index = size_t( dyn_par_arg[i_arg + 0] );\n            call_id    = size_t( dyn_par_arg[i_arg + 1] );\n            size_t n   = size_t( dyn_par_arg[i_arg + 2] );\n            size_t m   = size_t( dyn_par_arg[i_arg + 3] );\n            CPPAD_ASSERT_UNKNOWN( n_arg == 6 + n + m );\n            //\n            // parameter_x, type_x\n            parameter_x.resize(n);\n            type_x.resize(n);\n            for(size_t j = 0; j < n; ++j)\n            {   // parameter index zero is used for variable\n                CPPAD_ASSERT_UNKNOWN( CppAD::isnan( par_all[0] ) );\n                addr_t arg_j = dyn_par_arg[i_arg + 5 + j];\n                parameter_x[j] = par_all[arg_j];\n                if( arg_j == 0 )\n                    type_x[j] = variable_enum;\n                else if( par_is_dyn[arg_j] )\n                    type_x[j] = dynamic_enum;\n                else\n                    type_x[j] = constant_enum;\n            }\n            //\n            // depend_y\n            depend_y.resize(m);\n            for(size_t i = 0; i < m; ++i)\n            {   // a constant parameter cannot depend on a dynamic parameter\n                // so do not worry about constant parameters in depend_y\n                size_t i_par = size_t( dyn_par_arg[i_arg + 5 + n + i] );\n                depend_y[i]  = par_usage[i_par];\n            }\n            //\n            // call back to atomic function for this operation\n            depend_x.resize(n);\n            sweep::call_atomic_rev_depend<Base, Base>(\n                atom_index, call_id, parameter_x, type_x, depend_x, depend_y\n            );\n            //\n            // transfer depend_x to par_usage\n            for(size_t j = 0; j < n; ++j)\n            {   size_t i_par = size_t( dyn_par_arg[i_arg + 5 + j] );\n                par_usage[i_par] = par_usage[i_par] || depend_x[j];\n            }\n        }\n        else\n        {   // corresponding parameter index\n            size_t i_par = size_t( dyn2par_index[i_dyn] );\n            CPPAD_ASSERT_UNKNOWN( par_is_dyn[i_par] );\n            //\n            // number of arguments to this operator\n            size_t n_arg = num_arg_dyn(op);\n            //\n            // index of first argument for this operator\n            CPPAD_ASSERT_UNKNOWN( op != atom_dyn );\n            i_arg -= n_arg;\n            //\n            // if this dynamic parameter is needed\n            if( par_usage[i_par] )\n            {   // need dynamic parameters that are used to generate this one\n                size_t offset = num_non_par_arg_dyn(op);\n                for(size_t i = offset; i < n_arg; ++i)\n                    par_usage[ dyn_par_arg[i_arg + i] ] = true;\n            }\n        }\n    }\n    CPPAD_ASSERT_UNKNOWN( i_arg == 0 );\n    //\n    return;\n}\n\n} } } // END_CPPAD_LOCAL_OPTIMIZE_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/optimize/hash_code.hpp",
    "content": "# ifndef CPPAD_LOCAL_OPTIMIZE_HASH_CODE_HPP\n# define CPPAD_LOCAL_OPTIMIZE_HASH_CODE_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*!\n\\file local/optimize/hash_code.hpp\nCppAD hashing utility.\n*/\n\n\n// BEGIN_CPPAD_LOCAL_OPTIMIZE_NAMESPACE\nnamespace CppAD { namespace local { namespace optimize {\n/*!\nSpecialized hash code for a CppAD operator and its arguments\n(used during optimization).\n\n\\param op\nis the operator that we are computing a hash code for.\n\n\\param num_arg\nnumber of elements of arg to include in the hash code.\n\n\\param arg\nis a vector of length num_arg\ncontaining the corresponding argument indices for this operator.\n\n\\return\nis a hash code that is between zero and CPPAD_HASH_TABLE_SIZE - 1.\n*/\n\ninline size_t optimize_hash_code(\n    opcode_t      op      ,\n    size_t        num_arg ,\n    const addr_t* arg     )\n{   CPPAD_ASSERT_UNKNOWN( num_arg < 4 );\n    size_t prime = 1;\n    size_t sum   = prime * size_t(op);\n    for(size_t i = 0; i < num_arg; i++)\n    {   prime    = prime + 2;  // 3, 5, 7 in that order\n        sum += prime * size_t(arg[i]);\n    }\n    //\n    return sum % CPPAD_HASH_TABLE_SIZE;\n}\n\n} } } // END_CPPAD_LOCAL_OPTIMIZE_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/optimize/match_op.hpp",
    "content": "# ifndef CPPAD_LOCAL_OPTIMIZE_MATCH_OP_HPP\n# define CPPAD_LOCAL_OPTIMIZE_MATCH_OP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/local/optimize/hash_code.hpp>\n// BEGIN_CPPAD_LOCAL_OPTIMIZE_NAMESPACE\nnamespace CppAD { namespace local { namespace optimize  {\n/*\n{xrst_begin optimize_match_op dev}\n{xrst_spell\n    erfc\n}\n\nSearch for a Previous Operator that Matches Current Operator\n############################################################\n\nSyntax\n******\n| *exceed_collision_limit* = ``match_op`` (\n| |tab| ``collision_limit`` ,\n| |tab| ``random_itr`` ,\n| |tab| ``op_previous`` ,\n| |tab| ``current`` ,\n| |tab| ``hash_tape_op`` ,\n| |tab| ``work_bool`` ,\n| |tab| ``work_addr_t``\n| )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_PROTOTYPE\n    // END_PROTOTYPE\n}\n\nOperator Arguments\n******************\nIf an argument for the current operator is a variable,\nand the argument has previous match,\nthe previous match for the argument is used when checking for a match\nfor the current operator.\n\ncollision_limit\n***************\nis the maximum number of collisions (matches) allowed for one\nexpression hash code value.\n\nrandom_itr\n**********\nis a random iterator for the old operation sequence.\n\nop_previous\n***********\nMapping from operator index to previous operator that can replace this one.\nThe input value of\n\n    *previous* = *op_previous* [ *current* ]\n\nis assumed to be zero.  If a match if found, the output value of\n*previous* is set to the matching operator index,\notherwise it is left as is.  Note that *previous* < *current*\nand *op_previous* [ ``previous`` ] is zero.\n\ncurrent\n*******\nis the index of the current operator which cannot be any of the\noperators in the list below:\n{xrst_literal\n    // BEGIN_INVALID_OP\n    // END_INVALID_OP\n}\nAfter this initialization, the value of *current*\nincreases with each call to match_op.\n\nerf\n===\nThe operators ``ErfOp`` and ``ErfcOp`` have\nthree arguments, but only one true argument (the others are always the same).\n\nhash_table_op\n*************\nis assumed to be initialized as a vector of empty sets before the\nfirst call to match_op (for a pass of the operation sequence).\n\n| |tab| *hash_table_op* . ``n_set`` () == ``CPPAD_HASH_TABLE_SIZE``\n| |tab| *hash_table_op* . ``end`` ()   == *op_previous* . ``size`` ()\n\nIf *i_op* is an element of the j-th set,\nthen the operation *op_previous* [ *i_op* ] has hash code j,\nand does not match any other element of the j-th set.\nAn entry to j-th set for the current operator is added each time\nmatch_op is called and a match for the current operator is not found.\n\nwork_bool\n*********\nwork space that is used by match_op between calls to increase speed.\nShould be empty on first call for this forward pass of the operation\nsequence and not modified until forward pass is done\n\nwork_addr_t\n***********\nwork space that is used by match_op between calls to increase speed.\nShould be empty on first call for this forward pass of the operation\nsequence and not modified until forward pass is done\n\nexceed_collision_limit\n**********************\nIf the *collision_limit* is exceeded (is not exceeded),\nthe return value is true (false).\n\n{xrst_end optimize_match_op}\n*/\n// BEGIN_PROTOTYPE\ntemplate <class Addr>\nbool match_op(\n    size_t                                      collision_limit ,\n    const play::const_random_iterator<Addr>&    random_itr      ,\n    pod_vector<addr_t>&                         op_previous     ,\n    size_t                                      current         ,\n    sparse::list_setvec&                        hash_table_op   ,\n    pod_vector<bool>&                           work_bool       ,\n    pod_vector<addr_t>&                         work_addr_t     )\n// END_PROTOTYPE\n{\n# ifndef NDEBUG\n    switch( random_itr.get_op(current) )\n    {\n        // BEGIN_INVALID_OP\n        case BeginOp:\n        case CExpOp:\n        case CSkipOp:\n        case CSumOp:\n        case EndOp:\n        case InvOp:\n        case LdpOp:\n        case LdvOp:\n        case ParOp:\n        case PriOp:\n        case StppOp:\n        case StpvOp:\n        case StvpOp:\n        case StvvOp:\n        case AFunOp:\n        case FunapOp:\n        case FunavOp:\n        case FunrpOp:\n        case FunrvOp:\n        // END_INVALID_OP\n        CPPAD_ASSERT_UNKNOWN(false);\n        break;\n\n        default:\n        break;\n    }\n# endif\n    // initialize return value\n    bool exceed_collision_limit = false;\n    // num_op\n    size_t num_op = random_itr.num_op();\n    //\n    // num_var\n    size_t num_var = random_itr.num_var();\n    //\n    // variable is a reference to, and better name for, work_bool\n    pod_vector<bool>&  variable(work_bool);\n    //\n    // var2previous_var is a reference to, and better name for, work_addr_t\n    pod_vector<addr_t>&  var2previous_var(work_addr_t);\n    if( var2previous_var.size() == 0 )\n    {   var2previous_var.resize(num_var);\n        for(size_t i = 0; i < num_var; ++i)\n            var2previous_var[i] = addr_t(i);\n    }\n    //\n    CPPAD_ASSERT_UNKNOWN( var2previous_var.size() == num_var );\n    CPPAD_ASSERT_UNKNOWN( num_op == op_previous.size() );\n    CPPAD_ASSERT_UNKNOWN( op_previous[current] == 0 );\n    CPPAD_ASSERT_UNKNOWN(\n        hash_table_op.n_set() == CPPAD_HASH_TABLE_SIZE\n    );\n    CPPAD_ASSERT_UNKNOWN( hash_table_op.end() == num_op );\n    CPPAD_ASSERT_UNKNOWN( current < num_op );\n    //\n    // op, arg, i_var\n    op_code_var   op;\n    const addr_t* arg;\n    size_t        i_var;\n    random_itr.op_info(current, op, arg, i_var);\n    //\n    // num_arg\n    size_t num_arg = NumArg(op);\n    CPPAD_ASSERT_UNKNOWN( 0 < num_arg );\n    CPPAD_ASSERT_UNKNOWN(\n        (num_arg < 3) || ( (num_arg == 3) && (op == ErfOp || op == ErfcOp) )\n    );\n    //\n    arg_is_variable(op, arg, variable);\n    CPPAD_ASSERT_UNKNOWN( variable.size() == num_arg );\n    //\n    // If j-th argument to this operator is a variable, and a previous\n    // variable will be used in its place, use the previous variable for\n    // hash coding and matching.\n    addr_t arg_match[] = {\n        // Invalid value that will not be used. This initialization avoid\n        // a warning on some compilers\n        std::numeric_limits<addr_t>::max(),\n        std::numeric_limits<addr_t>::max(),\n        std::numeric_limits<addr_t>::max()\n    };\n    if( (op == AddvvOp) || (op == MulvvOp ) )\n    {   // in special case where operator is commutative and operands are variables,\n        // put lower index first so hash code does not depend on operator order\n        CPPAD_ASSERT_UNKNOWN( num_arg == 2 );\n        arg_match[0] = var2previous_var[ arg[0] ];\n        arg_match[1] = var2previous_var[ arg[1] ];\n        if( arg_match[1] < arg_match[0] )\n            std::swap( arg_match[0], arg_match[1] );\n    }\n    else for(size_t j = 0; j < num_arg; ++j)\n    {   arg_match[j] = arg[j];\n        if( variable[j] )\n            arg_match[j] = var2previous_var[ arg[j] ];\n    }\n\n    //\n    size_t code = optimize_hash_code(opcode_t(op), num_arg, arg_match);\n    //\n    // iterator for the set with this hash code\n    sparse::list_setvec_const_iterator itr(hash_table_op, code);\n    //\n    // check for a match\n    size_t count = 0;\n    while( *itr != num_op )\n    {   ++count;\n        //\n        // candidate previous for current operator\n        size_t  candidate  = *itr;\n        CPPAD_ASSERT_UNKNOWN( candidate < current );\n        CPPAD_ASSERT_UNKNOWN( op_previous[candidate] == 0 );\n        //\n        op_code_var   op_c;\n        const addr_t* arg_c;\n        size_t        i_var_c;\n        random_itr.op_info(candidate, op_c, arg_c, i_var_c);\n        //\n        // check for a match\n        bool match = op == op_c;\n        size_t j   = 0;\n        while( match & (j < num_arg) )\n        {   if( variable[j] )\n                match &= arg_match[j] == var2previous_var[ arg_c[j] ];\n            else\n                match &= arg_match[j] == arg_c[j];\n            ++j;\n        }\n        if( (! match) && ( (op == AddvvOp) || (op == MulvvOp) ) )\n        {   // communative so check for reverse order match\n            match  = op == op_c;\n            //\n            // 2024-02-14:\n            // If op_c is not AddvvOp or MulvvOp, its arguments may not be\n            // variables and the code below could attempt to access\n            // var2previous_var out of range. See 2024@mm-dd@02-14.\n            if( match )\n            {   match &= arg_match[0] == var2previous_var[ arg_c[1] ];\n                match &= arg_match[1] == var2previous_var[ arg_c[0] ];\n            }\n        }\n        if( match )\n        {   op_previous[current] = static_cast<addr_t>( candidate );\n            if( NumRes(op) > 0 )\n            {   CPPAD_ASSERT_UNKNOWN( i_var_c < i_var );\n                var2previous_var[i_var] = addr_t( i_var_c );\n            }\n            return exceed_collision_limit;\n        }\n        ++itr;\n    }\n\n    // see print (that is commented out) at bottom of get_op_previous.hpp\n    CPPAD_ASSERT_UNKNOWN( count <= collision_limit );\n    if( count == collision_limit )\n    {   // restart the list\n        hash_table_op.clear(code);\n        // limit has been exceeded\n        exceed_collision_limit = true;\n    }\n    // No match was found. Add this operator to the set for this hash code\n    // Not using post_element because we need to iterate for\n    // this code before adding another element for this code.\n    hash_table_op.add_element(code, current);\n    //\n    return exceed_collision_limit;\n}\n\n} } } // END_CPPAD_LOCAL_OPTIMIZE_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/optimize/optimize_run.hpp",
    "content": "# ifndef CPPAD_LOCAL_OPTIMIZE_OPTIMIZE_RUN_HPP\n# define CPPAD_LOCAL_OPTIMIZE_OPTIMIZE_RUN_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <stack>\n# include <iterator>\n# include <cppad/local/optimize/extract_option.hpp>\n# include <cppad/local/optimize/get_op_usage.hpp>\n# include <cppad/local/optimize/get_par_usage.hpp>\n# include <cppad/local/optimize/get_dyn_previous.hpp>\n# include <cppad/local/optimize/get_op_previous.hpp>\n# include <cppad/local/optimize/get_cexp_info.hpp>\n# include <cppad/local/optimize/size_pair.hpp>\n# include <cppad/local/optimize/csum_stacks.hpp>\n# include <cppad/local/optimize/cexp_info.hpp>\n# include <cppad/local/optimize/record_pv.hpp>\n# include <cppad/local/optimize/record_vp.hpp>\n# include <cppad/local/optimize/record_vv.hpp>\n# include <cppad/local/optimize/record_csum.hpp>\n\n// BEGIN_CPPAD_LOCAL_OPTIMIZE_NAMESPACE\nnamespace CppAD { namespace local { namespace optimize  {\n\n/*!\n{xrst_begin optimize_run dev}\n{xrst_spell\n    dep\n    pri\n    substring\n    taddr\n}\n\nConvert a player object to an optimized recorder object\n#######################################################\n\nSyntax\n******\n| *exceed_collision_limit* = ``local::optimize::optimize_run`` (\n| |tab| ``options`` , ``n`` , ``dep_taddr`` , ``play`` , ``rec``\n| )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_PROTOTYPE\n    // END_PROTOTYPE\n}\n\nAddr\n****\nType to use for array elements in ``const_random_iterator`` .\n\nBase\n****\nBase type for the operator; i.e., this operation was recorded\nusing ``AD`` < *Base* >\nand computations by this routine are done using type *Base* .\n\noptions\n*******\n\nno_conditional_skip\n===================\nIf this sub-string appears,\nconditional skip operations will not be generated.\nThis may make the optimize routine use significantly less memory\nand take significantly less time.\n\nno_compare_op\n=============\nIf this sub-string appears,\nthen comparison operators will be removed from the optimized tape.\nThese operators are necessary for the :ref:`compare_change-name` feature to be\nmeaningful in the resulting recording.\nOn the other hand, they are not necessary and take extra time\nwhen this feature is not needed.\n\nno_print_for_op\n===============\nIf this sub-string appears,\nthen :ref:`printfor-name` operators ``PriOp``\nwill be removed from the optimized tape.\nThese operators are useful for reporting problems evaluating derivatives\nat independent variable values different from those used to record a function.\n\nno_cumulative_sum_op\n====================\nIf this sub-string appears,\nno cumulative sum operations will be generated during the optimization; see\n:ref:`optimize_cumulative_sum.cpp-name` .\n\ncollision_limit=value\n=====================\nIf this substring appears,\nwhere *value* is a sequence of decimal digits,\nthe optimizer's hash code collision limit will be set to *value* .\nWhen the collision limit is exceeded, the expressions with that hash code\nare removed and a new lists of expressions with that has code is started.\nThe larger *value* , the more identical expressions the optimizer\ncan recognize, but the slower the optimizer may run.\nThe default for *value* is ``10`` .\n\nn\n*\nis the number of independent variables on the tape.\n\ndep_taddr\n*********\nOn input this vector contains the indices for each of the dependent\nvariable values in the operation sequence corresponding to *play* .\nUpon return it contains the indices for the same variables but in\nthe operation sequence corresponding to *rec* .\n\nplay\n****\nThis is the operation sequence that we are optimizing.\nIt is ``const`` except for the fact that\n*play* ``->setup_random`` () is called.\n\nrec\n***\nThe input contents of this recording must be empty; i.e.,\nit corresponds to directly after the default constructor.\nUpon return, it contains an optimized version of the\noperation sequence corresponding to *play* .\n\nexceed_collision_limit\n**********************\nIf the *collision_limit* is exceeded (is not exceeded),\nthe return value is true (false).\n\nContents\n********\n{xrst_toc_table\n    include/cppad/local/optimize/extract_option.hpp\n    include/cppad/local/optimize/cexp_info.hpp\n    include/cppad/local/optimize/get_cexp_info.hpp\n    include/cppad/local/optimize/get_op_usage.hpp\n    include/cppad/local/optimize/get_par_usage.hpp\n    include/cppad/local/optimize/record_csum.hpp\n    include/cppad/local/optimize/match_op.hpp\n    include/cppad/local/optimize/get_op_previous.hpp\n}\n\n{xrst_end optimize_run}\n*/\n\n// BEGIN_PROTOTYPE\ntemplate <class Addr, class Base>\nbool optimize_run(\n    const std::string&                         options    ,\n    size_t                                     n          ,\n    pod_vector<size_t>&                        dep_taddr  ,\n    player<Base>*                              play       ,\n    recorder<Base>*                            rec        )\n// END_PROTOTYPE\n{   bool exceed_collision_limit = false;\n    //\n    // check that recorder is empty\n    CPPAD_ASSERT_UNKNOWN( rec->num_var_op() == 0 );\n    //\n    // get a random iterator for this player\n    Addr not_used;\n    play->setup_random( not_used );\n    local::play::const_random_iterator<Addr> random_itr =\n        play->get_random( not_used );\n    //\n    // compare_op, conditional_skip, cumulative_sum_op, print_for_op,\n    // collision_limit\n    options_t result         = extract_option(options);\n    bool compare_op          = result.compare_op;\n    bool conditional_skip    = result.conditional_skip;\n    bool cumulative_sum_op   = result.cumulative_sum_op;\n    bool print_for_op        = result.print_for_op;\n    size_t collision_limit   = result.collision_limit;\n    CPPAD_ASSERT_UNKNOWN( result.val_graph == false );\n    //\n    // number of operators in the player\n    const size_t num_op = play->num_var_op();\n    CPPAD_ASSERT_UNKNOWN(\n        num_op < size_t( (std::numeric_limits<addr_t>::max)() )\n    );\n\n    // number of variables in the player\n# ifndef NDEBUG\n    const size_t num_var = play->num_var();\n# endif\n\n    // number of parameter in the player\n    const size_t num_par = play->num_par_all();\n\n    // number of  VecAD indices\n    size_t num_vecad_ind   = play->num_var_vec_ind();\n\n    // number of VecAD vectors\n    size_t num_vecad_vec   = play->num_var_vecad();\n\n    // number of independent dynamic parameters\n    size_t n_dyn_independent = play->n_dyn_independent();\n\n    // number of dynamic parameters\n    size_t num_dynamic_par = play->num_dynamic_par();\n\n    // mapping from dynamic parameter index to parameter index\n    const pod_vector<addr_t>& dyn2par_index( play->dyn2par_index() );\n\n    // number of dynamic parameters\n    CPPAD_ASSERT_UNKNOWN( n_dyn_independent <= play->num_dynamic_par () );\n\n    // -----------------------------------------------------------------------\n    // operator information\n    pod_vector<addr_t>        cexp2op;\n    sparse::list_setvec       cexp_set;\n    pod_vector<bool>          vecad_used;\n    pod_vector<usage_t>       op_usage;\n    get_op_usage(\n        conditional_skip,\n        compare_op,\n        print_for_op,\n        cumulative_sum_op,\n        play,\n        random_itr,\n        dep_taddr,\n        cexp2op,\n        cexp_set,\n        vecad_used,\n        op_usage\n    );\n    pod_vector<addr_t>        op_previous;\n    exceed_collision_limit |= get_op_previous(\n        collision_limit,\n        play,\n        random_itr,\n        cexp_set,\n        op_previous,\n        op_usage\n    );\n    size_t num_cexp = cexp2op.size();\n    CPPAD_ASSERT_UNKNOWN( conditional_skip || num_cexp == 0 );\n    vector<struct_cexp_info>  cexp_info; // struct_cexp_info not POD\n    sparse::list_setvec       skip_op_true;\n    sparse::list_setvec       skip_op_false;\n    //\n    if( cexp2op.size() > 0 ) get_cexp_info(\n        play,\n        random_itr,\n        op_previous,\n        op_usage,\n        cexp2op,\n        cexp_set,\n        cexp_info,\n        skip_op_true,\n        skip_op_false\n    );\n\n    // We no longer need cexp_set, and cexp2op, so free their memory\n    cexp_set.resize(0, 0);\n    cexp2op.clear();\n    // -----------------------------------------------------------------------\n    // dynamic parameter information\n    pod_vector<bool> par_usage;\n    get_par_usage(\n        play,\n        random_itr,\n        op_usage,\n        vecad_used,\n        par_usage\n    );\n    pod_vector<addr_t> dyn_previous;\n    get_dyn_previous(\n        play                ,\n        par_usage           ,\n        dyn_previous\n    );\n    // -----------------------------------------------------------------------\n    // conditional expression information\n    //\n    // Size of the conditional expression information structure.\n    // This is equal to the number of conditional expressions when\n    // conditional_skip is true, otherwise it is zero.\n    //\n    // sort the conditional expression information by max_left_right\n    // this is the conditional skip order\n    vector<size_t> cskip_order(num_cexp);\n    if( num_cexp > 0 )\n    {   vector<size_t> keys(num_cexp);\n        for(size_t i = 0; i < num_cexp; i++)\n            keys[i] = size_t( cexp_info[i].max_left_right );\n        CppAD::index_sort(keys, cskip_order);\n    }\n    // initial index in conditional skip order\n    size_t cskip_order_next = 0;\n    //\n    // initialize index in conditional expression order\n    size_t cexp_next = 0;\n\n    // mapping from conditional expression index to conditional skip\n    // information on new tape\n    pod_vector<struct_cskip_new> cskip_new(num_cexp);\n    //\n    // flag used to indicate that there is no conditional skip\n    // for this conditional expression\n    for(size_t i = 0; i < num_cexp; i++)\n        cskip_new[i].i_arg = 0;\n    // =======================================================================\n    // Create new recording\n    // =======================================================================\n    //\n    // dynamic parameter information in player\n    const pod_vector<bool>&     par_is_dyn( play->par_is_dyn() );\n    const pod_vector<opcode_t>& dyn_par_op( play->dyn_par_op() );\n    const pod_vector<addr_t>&   dyn_par_arg( play->dyn_par_arg() );\n    //\n    // start mapping from old parameter indices to new parameter indices\n    // for all parameters that get used.\n    pod_vector<addr_t> new_par( num_par );\n    addr_t addr_t_max = (std::numeric_limits<addr_t>::max)();\n    for(size_t i_par = 0; i_par < num_par; ++i_par)\n        new_par[i_par] = addr_t_max; // initialize as not used\n    //\n    // start new recording\n    CPPAD_ASSERT_UNKNOWN( rec->num_var_op() == 0 );\n    rec->set_n_dyn_independent(n_dyn_independent);\n    rec->set_abort_op_index(0);\n    rec->set_record_compare( compare_op );\n\n    // copy parameters with index 0\n    CPPAD_ASSERT_UNKNOWN( ! par_is_dyn[0] && CppAD::isnan( play->par_one(0) ) );\n    rec->put_con_par( play->par_one(0) );\n    new_par[0] = 0;\n\n    // set new_par for the independent dynamic parameters\n    for(size_t i_par = 1; i_par <= n_dyn_independent; i_par++)\n    {   CPPAD_ASSERT_UNKNOWN( par_is_dyn[i_par] );\n        addr_t i = rec->put_dyn_par(play->par_one(i_par), ind_dyn);\n        CPPAD_ASSERT_UNKNOWN( size_t(i) == i_par );\n        new_par[i_par] = i;\n    }\n\n    // set new_par for the constant parameters that are used\n    for(size_t i_par = n_dyn_independent + 1; i_par < num_par; ++i_par)\n    if( ! par_is_dyn[i_par] )\n    {   CPPAD_ASSERT_UNKNOWN( i_par == 0 || n_dyn_independent < i_par );\n        if( par_usage[i_par] )\n        {   // value of this parameter\n            Base par       = play->par_one(i_par);\n            new_par[i_par] = rec->put_con_par(par);\n        }\n    }\n\n    // index corresponding to the parameter zero\n    addr_t zero_par_index = rec->put_con_par( Base(0) );\n\n    // set new_par for the dependent dynamic parameters\n    size_t i_dyn = n_dyn_independent;// dynamic parameter index\n    size_t i_arg = 0;                // dynamic parameter argument index\n    pod_vector<addr_t> arg_vec;\n    for(size_t i_par = n_dyn_independent + 1; i_par < num_par; ++i_par)\n    if( par_is_dyn[i_par] )\n    {   // operator for this dynamic parameter\n        op_code_dyn op = op_code_dyn( dyn_par_op[i_dyn] );\n        //\n        // number of arguments for this dynamic parameter\n        size_t n_arg   = num_arg_dyn(op);\n        //\n        // number of dynamic parameter results for this operator\n        size_t n_dyn   = 1;\n        //\n        if( op == atom_dyn )\n        {   size_t atom_index = size_t( dyn_par_arg[i_arg + 0]  );\n            size_t call_id    = size_t( dyn_par_arg[i_arg + 1]  );\n            size_t atom_n     = size_t( dyn_par_arg[i_arg + 2]  );\n            size_t atom_m     = size_t( dyn_par_arg[i_arg + 3]  );\n            n_dyn             = size_t( dyn_par_arg[i_arg + 4]  );\n            n_arg             = 6 + atom_n + atom_m;\n            //\n            // check if any dynamic parameter result for this operator is used\n            bool call_used = false;\n# ifndef NDEBUG\n            bool found_i_par = false;\n            for(size_t i = 0; i < atom_m; ++i)\n            {   size_t j_par = size_t( dyn_par_arg[i_arg + 5 + atom_n + i] );\n                if( par_is_dyn[j_par] )\n                {   call_used |= par_usage[j_par];\n                    CPPAD_ASSERT_UNKNOWN( j_par == i_par || found_i_par );\n                    // j_par > i_par corresponds to result_dyn operator\n                    CPPAD_ASSERT_UNKNOWN( j_par >= i_par );\n                    found_i_par |= j_par == i_par;\n                }\n            }\n            CPPAD_ASSERT_UNKNOWN( found_i_par );\n# else\n            for(size_t i = 0; i < atom_m; ++i)\n            {   size_t j_par = size_t( dyn_par_arg[i_arg + 5 + atom_n + i] );\n                if( par_is_dyn[j_par] )\n                    call_used |= par_usage[j_par];\n            }\n# endif\n            if( call_used )\n            {   arg_vec.resize(0);\n                arg_vec.push_back( addr_t( atom_index ) );\n                arg_vec.push_back( addr_t( call_id ) );\n                arg_vec.push_back( addr_t( atom_n ) );\n                arg_vec.push_back( addr_t( atom_m ) );\n                arg_vec.push_back( addr_t( n_dyn ) );\n                for(size_t j = 0; j < atom_n; ++j)\n                {   addr_t arg_j = dyn_par_arg[i_arg + 5 + j];\n                    if( arg_j > 0 && par_usage[arg_j] )\n                        arg_vec.push_back( new_par[ arg_j ] );\n                    else\n                        arg_vec.push_back(0);\n                }\n                bool first_dynamic_result = true;\n                for(size_t i = 0; i < atom_m; ++i)\n                {   addr_t res_i = dyn_par_arg[i_arg + 5 + atom_n + i];\n                    CPPAD_ASSERT_UNKNOWN( par_is_dyn[res_i] || res_i == 0 );\n                    //\n                    if( par_is_dyn[res_i] )\n                    {   Base par = play->par_one( size_t(res_i) );\n                        if( first_dynamic_result )\n                        {   first_dynamic_result = false;\n                            new_par[res_i] = rec->put_dyn_par(par, atom_dyn);\n                        }\n                        else\n                            new_par[res_i] = rec->put_dyn_par(par, result_dyn);\n                        arg_vec.push_back( new_par[res_i] );\n                    }\n                    else\n                    {   // this result is a constant parameter\n                        if( new_par[res_i] != addr_t_max )\n                            arg_vec.push_back( new_par[res_i] );\n                        else\n                        {   // this constant parameter is not used\n                            arg_vec.push_back(0); // phantom parameter\n                        }\n                    }\n                }\n                arg_vec.push_back( addr_t(6 + atom_n + atom_m ) );\n                rec->put_dyn_arg_vec( arg_vec );\n            }\n        }\n        else if( par_usage[i_par] && (op != result_dyn) )\n        {   size_t j_dyn = size_t( dyn_previous[i_dyn] );\n            if( j_dyn != num_dynamic_par )\n            {   size_t j_par = size_t( dyn2par_index[j_dyn] );\n                CPPAD_ASSERT_UNKNOWN( j_par < i_par );\n                new_par[i_par] = new_par[j_par];\n            }\n            else\n            {\n                // value of this parameter\n                Base par       = play->par_one(i_par);\n                //\n                if( op == cond_exp_dyn )\n                {   // cond_exp_dyn\n                    CPPAD_ASSERT_UNKNOWN( n_dyn_independent <= i_par );\n                    CPPAD_ASSERT_UNKNOWN( n_arg == 5 );\n                    new_par[i_par] = rec->put_dyn_cond_exp(\n                        par                                ,   // par\n                        CompareOp( dyn_par_arg[i_arg + 0] ),   // cop\n                        new_par[ dyn_par_arg[i_arg + 1] ]  ,   // left\n                        new_par[ dyn_par_arg[i_arg + 2] ]  ,   // right\n                        new_par[ dyn_par_arg[i_arg + 3] ]  ,   // if_true\n                        new_par[ dyn_par_arg[i_arg + 4] ]      // if_false\n                    );\n                }\n                else if(  op == dis_dyn )\n                {   // dis_dyn\n                    CPPAD_ASSERT_UNKNOWN( n_arg == 2 );\n                    new_par[i_par] = rec->put_dyn_par(\n                        par                               ,  // par\n                        op                                ,  // op\n                        dyn_par_arg[i_arg + 0]            ,  // index\n                        new_par[ dyn_par_arg[i_arg + 1] ]    // parameter\n                    );\n                }\n                else if( n_arg == 1 )\n                {   // cases with one argument\n                    CPPAD_ASSERT_UNKNOWN( num_non_par_arg_dyn(op) == 0 );\n                    CPPAD_ASSERT_UNKNOWN( n_dyn_independent <= i_par );\n                    new_par[i_par] = rec->put_dyn_par( par, op,\n                        new_par[ dyn_par_arg[i_arg + 0] ]\n                    );\n                }\n                else if( n_arg == 2 )\n                {   // cases with two arguments\n                    CPPAD_ASSERT_UNKNOWN( n_dyn_independent <= i_par );\n                    CPPAD_ASSERT_UNKNOWN( num_non_par_arg_dyn(op) == 0 );\n                    new_par[i_par] = rec->put_dyn_par( par, op,\n                        new_par[ dyn_par_arg[i_arg + 0] ],\n                        new_par[ dyn_par_arg[i_arg + 1] ]\n                    );\n                }\n                else\n                {   // independent dynamic parameter case\n                    CPPAD_ASSERT_UNKNOWN( op == ind_dyn )\n                    CPPAD_ASSERT_UNKNOWN( i_par <= n_dyn_independent );\n                    CPPAD_ASSERT_UNKNOWN( n_arg == 0 );\n                    new_par[i_par] = rec->put_dyn_par( par, op);\n                }\n            }\n        }\n        ++i_dyn;\n        i_arg += n_arg;\n    }\n    // -----------------------------------------------------------------------\n    // There is an additional constant parameter for each cumulative summation\n    // (that does not have a corresponding old parameter index).\n    // ------------------------------------------------------------------------\n    // initialize mapping from old VecAD index to new VecAD index\n    CPPAD_ASSERT_UNKNOWN(\n        size_t( (std::numeric_limits<addr_t>::max)() ) >= num_vecad_ind\n    );\n    pod_vector<addr_t> new_vecad_ind(num_vecad_ind);\n    for(size_t i = 0; i < num_vecad_ind; i++)\n        new_vecad_ind[i] = addr_t( num_vecad_ind ); // invalid index\n    {\n        size_t j = 0;     // index into the old set of indices\n        for(size_t i = 0; i < num_vecad_vec; i++)\n        {   // length of this VecAD\n            size_t length = play->GetVecInd(j);\n            if( vecad_used[i] )\n            {   // Put this VecAD vector in new recording\n                CPPAD_ASSERT_UNKNOWN(length < num_vecad_ind);\n                new_vecad_ind[j] = rec->put_var_vecad_ind( addr_t(length) );\n                for(size_t k = 1; k <= length; k++) new_vecad_ind[j+k] =\n                    rec->put_var_vecad_ind(\n                        new_par[ play->GetVecInd(j+k) ]\n                );\n            }\n            // start of next VecAD\n            j       += length + 1;\n        }\n        CPPAD_ASSERT_UNKNOWN( j == num_vecad_ind );\n    }\n\n    // temporary buffer for new argument values\n    addr_t new_arg[6];\n\n    // temporary work space used by record_csum\n    // (declared here to avoid realloaction of memory)\n    struct_csum_stacks csum_work;\n\n    // temporary used to hold a size_pair\n    struct_size_pair size_pair;\n    //\n    // Mapping from old operator index to new variable index,\n    // zero is invalid except for new_var[0].\n    pod_vector<addr_t> new_var(num_op);\n    //\n    // Mapping from old operator index to new operator index will share\n    // memory with op_previous. Must get op_previous[i_op] for this operator\n    // before over writing it with new_op[i_op].\n    pod_vector<addr_t>& new_op( op_previous );\n    CPPAD_ASSERT_UNKNOWN( new_op.size() == num_op );\n    // -------------------------------------------------------------\n    // information for current operator\n    size_t          i_op;   // index\n    op_code_var     op;     // operator\n    const addr_t*   arg;    // arguments\n    size_t          i_var;  // variable index of primary (last) result\n    //\n    // information about atomic function\n    enum_atom_state atom_state = start_atom;\n    size_t atom_i              = 0;\n    size_t atom_j              = 0;\n    //\n    i_var      = 0;\n    for(i_op = 0; i_op < num_op; ++i_op)\n    {   // if non-zero, use previous result in place of this operator.\n        // Must get this information before writing new_op[i_op].\n        size_t previous = size_t( op_previous[i_op] );\n        //\n        // zero is invalid except for new_op[0].\n        new_op[i_op] = 0;\n        //\n        // Zero is invalid except for new_var[0] and previous is zero unless\n        // this operator is replace by a previous operator.\n        new_var[i_op] = 0;\n        if( op_usage[i_op] == usage_t(yes_usage) )\n            new_var[i_op] = new_var[previous];\n        //\n        // temporary used in some switch cases\n        addr_t mask;\n        //\n        // this operator information\n        size_t i_tmp;\n        random_itr.op_info(i_op, op, arg, i_tmp);\n        if( NumRes(op) > 0 )\n            i_var = i_tmp;\n        //\n        // is this new result the top of a cumulative summation\n        bool top_csum;\n        //\n        // determine if we should insert a conditional skip here\n        bool skip  = conditional_skip;\n        if( skip )\n        {   skip      &= cskip_order_next < num_cexp;\n            skip      &= op != BeginOp;\n            skip      &= op != InvOp;\n            skip      &= atom_state == start_atom;\n            if( skip )\n            {   size_t j = cskip_order[cskip_order_next];\n                if( NumRes(op) > 0 )\n                    skip &= size_t( cexp_info[j].max_left_right ) < i_var;\n                else\n                    skip &= size_t( cexp_info[j].max_left_right ) <= i_var;\n            }\n            if( skip )\n            {   size_t j = cskip_order[cskip_order_next];\n                cskip_order_next++;\n                size_t n_true   = skip_op_true.number_elements(j);\n                size_t n_false  = skip_op_false.number_elements(j);\n                skip &= n_true > 0 || n_false > 0;\n                if( skip )\n                {   CPPAD_ASSERT_UNKNOWN( NumRes(CSkipOp) == 0 );\n                    size_t n_arg   = 7 + size_t(n_true) + size_t(n_false);\n                    // reserve space for the arguments to this operator but\n                    // delay setting them until we have all the new addresses\n                    cskip_new[j].i_arg = rec->ReserveArg(n_arg);\n                    // i_arg == 0 is used to check if conditional expression\n                    // has been skipped.\n                    CPPAD_ASSERT_UNKNOWN( cskip_new[j].i_arg > 0 );\n                    // There is no corresponding old operator in this case\n                    rec->PutOp(CSkipOp);\n                }\n            }\n        }\n        //\n        CPPAD_ASSERT_UNKNOWN(\n            size_t( (std::numeric_limits<addr_t>::max)() ) >= rec->num_var_op()\n        );\n        //\n        // For each call, first and second AFunOp will have same op_usage\n        skip  = op_usage[i_op] != usage_t( yes_usage );\n        skip &= atom_state != arg_atom && atom_state != ret_atom;\n        if( skip )\n        {   if( op == CExpOp )\n                ++cexp_next;\n            //\n            if( op == AFunOp )\n            {   if( atom_state == start_atom )\n                    atom_state = end_atom;\n                else\n                {   CPPAD_ASSERT_UNKNOWN( atom_state == end_atom );\n                    atom_state = start_atom;\n                }\n            }\n        }\n        else switch( op )\n        {   // op_usage[i_op] == usage_t(yes_usage)\n\n            case BeginOp:\n            CPPAD_ASSERT_UNKNOWN( previous == 0 );\n            CPPAD_ASSERT_NARG_NRES(op, 1, 1);\n            // Put BeginOp at beginning of recording\n            new_op[i_op]  = addr_t( rec->num_var_op() );\n            new_var[i_op] = rec->PutOp(BeginOp);\n            rec->PutArg(arg[0]);\n            break;\n\n            // --------------------------------------------------------------\n            // Unary operators, argument a variable, one result\n            case AbsOp:\n            case AcosOp:\n            case AcoshOp:\n            case AsinOp:\n            case AsinhOp:\n            case AtanOp:\n            case AtanhOp:\n            case CosOp:\n            case CoshOp:\n            case ErfOp:\n            case ErfcOp:\n            case ExpOp:\n            case Expm1Op:\n            case LogOp:\n            case Log1pOp:\n            case NegOp:\n            case SignOp:\n            case SinOp:\n            case SinhOp:\n            case SqrtOp:\n            case TanOp:\n            case TanhOp:\n            if( previous == 0 )\n            {   //\n                new_arg[0]   = new_var[ random_itr.var2op(size_t(arg[0])) ];\n                rec->PutArg( new_arg[0] );\n                //\n                new_op[i_op]  = addr_t( rec->num_var_op() );\n                new_var[i_op] = rec->PutOp(op);\n                CPPAD_ASSERT_UNKNOWN(\n                    new_arg[0] < new_var[random_itr.var2op(i_var)]\n                );\n                if( op == ErfOp || op == ErfcOp )\n                {   CPPAD_ASSERT_NARG_NRES(op, 3, 5);\n                    // Error function is a special case\n                    // second argument is always the parameter 0\n                    // third argument is always the parameter 2 / sqrt(pi)\n                    CPPAD_ASSERT_UNKNOWN( NumArg(ErfOp) == 3 );\n                    rec->PutArg( rec->put_con_par( Base(0.0) ) );\n                    rec->PutArg( rec->put_con_par(\n                        Base( 1.0 / std::sqrt( std::atan(1.0) ) )\n                    ) );\n                }\n                else\n                {   // some of these operators have an auxiliary result;\n                    // e.g. sine and cosine are computed together.\n                    CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 );\n                    CPPAD_ASSERT_UNKNOWN( NumRes(op) ==1 || NumRes(op) == 2 );\n                }\n            }\n            break;\n            // ---------------------------------------------------\n            // Binary operators, left variable, right parameter, one result\n            case SubvpOp:\n            // check if this is the top of a csum connection\n            i_tmp    = random_itr.var2op(size_t(arg[0]));\n            top_csum = op_usage[i_tmp] == usage_t(csum_usage);\n            if( top_csum )\n            {   CPPAD_ASSERT_UNKNOWN( previous == 0 );\n                //\n                // convert to a sequence of summation operators\n                size_pair = record_csum(\n                    play                ,\n                    random_itr          ,\n                    op_usage            ,\n                    new_par             ,\n                    new_var             ,\n                    i_var               ,\n                    rec                 ,\n                    csum_work\n                );\n                new_op[i_op]  = addr_t( size_pair.i_op );\n                new_var[i_op] = addr_t( size_pair.i_var );\n                // abort rest of this case\n                break;\n            }\n            case DivvpOp:\n            case PowvpOp:\n            case ZmulvpOp:\n            if( previous == 0 )\n            {   //\n                size_pair = record_vp(\n                    play                ,\n                    random_itr          ,\n                    new_par             ,\n                    new_var             ,\n                    i_op                ,\n                    rec\n                );\n                new_op[i_op]  = addr_t( size_pair.i_op );\n                new_var[i_op] = addr_t( size_pair.i_var );\n            }\n            break;\n            // ---------------------------------------------------\n            // Binary operators, left index, right variable, one result\n            case DisOp:\n            CPPAD_ASSERT_NARG_NRES(op, 2, 1);\n            if( previous == 0 )\n            {   //\n                new_arg[0] = arg[0];\n                new_arg[1] = new_var[ random_itr.var2op(size_t(arg[1])) ];\n                rec->PutArg( new_arg[0], new_arg[1] );\n                //\n                new_op[i_op]  = addr_t( rec->num_var_op() );\n                new_var[i_op] = rec->PutOp(op);\n                CPPAD_ASSERT_UNKNOWN(\n                    new_arg[1] < new_var[random_itr.var2op(i_var)]\n                );\n            }\n            break;\n\n            // ---------------------------------------------------\n            // Binary operators, left parameter, right variable, one result\n            case SubpvOp:\n            case AddpvOp:\n            // check if this is the top of a csum connection\n            i_tmp    = random_itr.var2op(size_t(arg[1]));\n            top_csum = op_usage[i_tmp] == usage_t(csum_usage);\n            if( top_csum )\n            {   CPPAD_ASSERT_UNKNOWN( previous == 0 );\n                //\n                // convert to a sequence of summation operators\n                size_pair = record_csum(\n                    play                ,\n                    random_itr          ,\n                    op_usage            ,\n                    new_par             ,\n                    new_var             ,\n                    i_var               ,\n                    rec                 ,\n                    csum_work\n                );\n                new_op[i_op]  = addr_t( size_pair.i_op );\n                new_var[i_op] = addr_t( size_pair.i_var );\n                // abort rest of this case\n                break;\n            }\n            case DivpvOp:\n            case MulpvOp:\n            case PowpvOp:\n            case ZmulpvOp:\n            if( previous == 0 )\n            {   //\n                size_pair = record_pv(\n                    play                ,\n                    random_itr          ,\n                    new_par             ,\n                    new_var             ,\n                    i_op                ,\n                    rec\n                );\n                new_op[i_op]  = addr_t( size_pair.i_op );\n                new_var[i_op] = addr_t( size_pair.i_var );\n            }\n            break;\n            // ---------------------------------------------------\n            // Binary operator, left and right variables, one result\n            case AddvvOp:\n            case SubvvOp:\n            // check if this is the top of a csum connection\n            i_tmp     = random_itr.var2op(size_t(arg[0]));\n            top_csum  = op_usage[i_tmp] == usage_t(csum_usage);\n            i_tmp     = random_itr.var2op(size_t(arg[1]));\n            top_csum |= op_usage[i_tmp] == usage_t(csum_usage);\n            if( top_csum )\n            {   CPPAD_ASSERT_UNKNOWN( previous == 0 );\n                //\n                // convert to a sequence of summation operators\n                size_pair = record_csum(\n                    play                ,\n                    random_itr          ,\n                    op_usage            ,\n                    new_par             ,\n                    new_var             ,\n                    i_var               ,\n                    rec                 ,\n                    csum_work\n                );\n                new_op[i_op]  = addr_t( size_pair.i_op );\n                new_var[i_op] = addr_t( size_pair.i_var );\n                // abort rest of this case\n                break;\n            }\n            case DivvvOp:\n            case MulvvOp:\n            case PowvvOp:\n            case ZmulvvOp:\n            if( previous == 0 )\n            {   //\n                size_pair = record_vv(\n                    play                ,\n                    random_itr          ,\n                    new_var             ,\n                    i_op                ,\n                    rec\n                );\n                new_op[i_op]  = addr_t( size_pair.i_op );\n                new_var[i_op] = addr_t( size_pair.i_var );\n            }\n            break;\n            // ---------------------------------------------------\n            // Conditional expression operators\n            case CExpOp:\n            CPPAD_ASSERT_UNKNOWN( previous == 0 );\n            CPPAD_ASSERT_NARG_NRES(op, 6, 1);\n            new_arg[0] = arg[0];\n            new_arg[1] = arg[1];\n            mask = 1;\n            for(size_t i = 2; i < 6; i++)\n            {   if( arg[1] & mask )\n                {   new_arg[i] = new_var[ random_itr.var2op(size_t(arg[i])) ];\n                    CPPAD_ASSERT_UNKNOWN(\n                        size_t(new_arg[i]) < num_var\n              );\n                }\n                else\n                    new_arg[i] = new_par[ arg[i] ];\n                mask = mask << 1;\n            }\n            rec->PutArg(\n                new_arg[0] ,\n                new_arg[1] ,\n                new_arg[2] ,\n                new_arg[3] ,\n                new_arg[4] ,\n                new_arg[5]\n            );\n            new_op[i_op]  = addr_t( rec->num_var_op() );\n            new_var[i_op] = rec->PutOp(op);\n            //\n            // The new addresses for left and right are used during\n            // fill in the arguments for the CSkip operations. This does not\n            // affect max_left_right which is used during this sweep.\n            if( conditional_skip )\n            {   CPPAD_ASSERT_UNKNOWN( cexp_next < num_cexp );\n                CPPAD_ASSERT_UNKNOWN(\n                    size_t( cexp_info[cexp_next].i_op ) == i_op\n                );\n                cskip_new[ cexp_next ].left  = size_t( new_arg[2] );\n                cskip_new[ cexp_next ].right = size_t( new_arg[3] );\n                ++cexp_next;\n            }\n            break;\n            // ---------------------------------------------------\n            // Operations with no arguments and no results\n            case EndOp:\n            CPPAD_ASSERT_UNKNOWN( previous == 0 );\n            CPPAD_ASSERT_NARG_NRES(op, 0, 0);\n            new_op[i_op] = addr_t( rec->num_var_op() );\n            rec->PutOp(op);\n            break;\n            // ---------------------------------------------------\n            // Comparison operations: two arguments and no results\n            //\n            case LeppOp:\n            case LtppOp:\n            case EqppOp:\n            case NeppOp:\n            CPPAD_ASSERT_UNKNOWN( compare_op );\n            CPPAD_ASSERT_NARG_NRES(op, 2, 0);\n            if( previous == 0 )\n            {   new_arg[0] = new_par[ arg[0] ];\n                new_arg[1] = new_par[ arg[1] ];\n                rec->PutArg(new_arg[0], new_arg[1]);\n                new_op[i_op] = addr_t( rec->num_var_op() );\n                rec->PutOp(op);\n            }\n            break;\n            //\n            case LepvOp:\n            case LtpvOp:\n            case EqpvOp:\n            case NepvOp:\n            CPPAD_ASSERT_UNKNOWN( compare_op );\n            CPPAD_ASSERT_NARG_NRES(op, 2, 0);\n            if( previous == 0 )\n            {   new_arg[0] = new_par[ arg[0] ];\n                new_arg[1] = new_var[ random_itr.var2op(size_t(arg[1])) ];\n                rec->PutArg(new_arg[0], new_arg[1]);\n                new_op[i_op] = addr_t( rec->num_var_op() );\n                rec->PutOp(op);\n            }\n            break;\n            //\n            case LevpOp:\n            case LtvpOp:\n            CPPAD_ASSERT_UNKNOWN( compare_op );\n            CPPAD_ASSERT_NARG_NRES(op, 2, 0);\n            if( previous == 0 )\n            {   new_arg[0] = new_var[ random_itr.var2op(size_t(arg[0])) ];\n                new_arg[1] = new_par[ arg[1] ];\n                rec->PutArg(new_arg[0], new_arg[1]);\n                new_op[i_op] = addr_t( rec->num_var_op() );\n                rec->PutOp(op);\n            }\n            break;\n            //\n            case LevvOp:\n            case LtvvOp:\n            case EqvvOp:\n            case NevvOp:\n            CPPAD_ASSERT_UNKNOWN( compare_op );\n            CPPAD_ASSERT_NARG_NRES(op, 2, 0);\n            if( previous == 0 )\n            {   new_arg[0] = new_var[ random_itr.var2op(size_t(arg[0])) ];\n                new_arg[1] = new_var[ random_itr.var2op(size_t(arg[1])) ];\n                rec->PutArg(new_arg[0], new_arg[1]);\n                new_op[i_op] = addr_t( rec->num_var_op() );\n                rec->PutOp(op);\n            }\n            break;\n\n            // ---------------------------------------------------\n            // Operations with no arguments and one result\n            case InvOp:\n            CPPAD_ASSERT_UNKNOWN( previous == 0 );\n            CPPAD_ASSERT_NARG_NRES(op, 0, 1);\n            new_op[i_op]  = addr_t( rec->num_var_op() );\n            new_var[i_op] = rec->PutOp(op);\n            break;\n\n            // ---------------------------------------------------\n            // Unary operators, argument a parameter, one result\n            case ParOp:\n            CPPAD_ASSERT_UNKNOWN( previous == 0 );\n            CPPAD_ASSERT_NARG_NRES(op, 1, 1);\n            new_arg[0] = new_par[ arg[0] ];\n            rec->PutArg( new_arg[0] );\n            //\n            new_op[i_op]  = addr_t( rec->num_var_op() );\n            new_var[i_op] = rec->PutOp(op);\n            break;\n\n            // ---------------------------------------------------\n            // print forward operator\n            case PriOp:\n            CPPAD_ASSERT_UNKNOWN( previous == 0 );\n            CPPAD_ASSERT_NARG_NRES(op, 5, 0);\n            // arg[0]\n            new_arg[0] = arg[0];\n            //\n            // arg[1]\n            if( arg[0] & 1 )\n            {   new_arg[1] = new_var[ random_itr.var2op(size_t(arg[1])) ];\n                CPPAD_ASSERT_UNKNOWN( size_t(new_arg[1]) < num_var );\n            }\n            else\n            {   new_arg[1] = new_par[ arg[1] ];\n            }\n            //\n            // arg[3]\n            if( arg[0] & 2 )\n            {   new_arg[3] = new_var[ random_itr.var2op(size_t(arg[3])) ];\n                CPPAD_ASSERT_UNKNOWN( size_t(new_arg[3]) < num_var );\n            }\n            else\n            {   new_arg[3] = new_par[ arg[3] ];\n            }\n            new_arg[2] = rec->PutTxt( play->GetTxt(size_t(arg[2])) );\n            new_arg[4] = rec->PutTxt( play->GetTxt(size_t(arg[4])) );\n            //\n            rec->PutArg(\n                new_arg[0] ,\n                new_arg[1] ,\n                new_arg[2] ,\n                new_arg[3] ,\n                new_arg[4]\n            );\n            // new operator\n            new_op[i_op]  = addr_t( rec->num_var_op() );\n            // no new variable\n            rec->PutOp(op);\n            break;\n\n            // ---------------------------------------------------\n            // VecAD operators\n\n            // Load using a parameter index\n            case LdpOp:\n            CPPAD_ASSERT_UNKNOWN( previous == 0 );\n            CPPAD_ASSERT_NARG_NRES(op, 3, 1);\n            new_arg[0] = new_vecad_ind[ arg[0] ];\n            new_arg[1] = new_par[ arg[1] ];\n            CPPAD_ASSERT_UNKNOWN(\n                size_t( (std::numeric_limits<addr_t>::max)() ) >= rec->num_var_load()\n            );\n            new_arg[2] = addr_t( rec->num_var_load() );\n            CPPAD_ASSERT_UNKNOWN( size_t(new_arg[0]) < num_vecad_ind );\n            rec->PutArg(\n                new_arg[0],\n                new_arg[1],\n                new_arg[2]\n            );\n            new_op[i_op]  = addr_t( rec->num_var_op() );\n            new_var[i_op] = rec->PutLoadOp(op);\n            break;\n\n            // Load using a variable index\n            case LdvOp:\n            CPPAD_ASSERT_UNKNOWN( previous == 0 );\n            CPPAD_ASSERT_NARG_NRES(op, 3, 1);\n            new_arg[0] = new_vecad_ind[ arg[0] ];\n            new_arg[1] = new_var[ random_itr.var2op(size_t(arg[1])) ];\n            CPPAD_ASSERT_UNKNOWN(\n                size_t( (std::numeric_limits<addr_t>::max)() ) >= rec->num_var_load()\n            );\n            new_arg[2] = addr_t( rec->num_var_load() );\n            CPPAD_ASSERT_UNKNOWN( size_t(new_arg[0]) < num_vecad_ind );\n            CPPAD_ASSERT_UNKNOWN( size_t(new_arg[1]) < num_var );\n            rec->PutArg(\n                new_arg[0],\n                new_arg[1],\n                new_arg[2]\n            );\n            new_op[i_op]  = addr_t( rec->num_var_op() );\n            new_var[i_op] = rec->PutLoadOp(op);\n            break;\n\n            // Store a parameter using a parameter index\n            case StppOp:\n            CPPAD_ASSERT_UNKNOWN( previous == 0 );\n            CPPAD_ASSERT_NARG_NRES(op, 3, 0);\n            new_arg[0] = new_vecad_ind[ arg[0] ];\n            new_arg[1] = new_par[ arg[1] ];\n            new_arg[2] = new_par[ arg[2] ];\n            CPPAD_ASSERT_UNKNOWN( size_t(new_arg[0]) < num_vecad_ind );\n            rec->PutArg(\n                new_arg[0],\n                new_arg[1],\n                new_arg[2]\n            );\n            new_op[i_op] = addr_t( rec->num_var_op() );\n            rec->PutOp(op);\n            break;\n\n            // Store a parameter using a variable index\n            case StvpOp:\n            CPPAD_ASSERT_UNKNOWN( previous == 0 );\n            CPPAD_ASSERT_NARG_NRES(op, 3, 0);\n            new_arg[0] = new_vecad_ind[ arg[0] ];\n            new_arg[1] = new_var[ random_itr.var2op(size_t(arg[1])) ];\n            new_arg[2] = new_par[ arg[2] ];\n            CPPAD_ASSERT_UNKNOWN( size_t(new_arg[0]) < num_vecad_ind );\n            CPPAD_ASSERT_UNKNOWN( size_t(new_arg[1]) < num_var );\n            rec->PutArg(\n                new_arg[0],\n                new_arg[1],\n                new_arg[2]\n            );\n            new_op[i_op] = addr_t( rec->num_var_op() );\n            rec->PutOp(op);\n            break;\n\n            // Store a variable using a parameter index\n            case StpvOp:\n            CPPAD_ASSERT_UNKNOWN( previous == 0 );\n            CPPAD_ASSERT_NARG_NRES(op, 3, 0);\n            new_arg[0] = new_vecad_ind[ arg[0] ];\n            new_arg[1] = new_par[ arg[1] ];\n            new_arg[2] = new_var[ random_itr.var2op(size_t(arg[2])) ];\n            CPPAD_ASSERT_UNKNOWN( size_t(new_arg[0]) < num_vecad_ind );\n            CPPAD_ASSERT_UNKNOWN( size_t(new_arg[2]) < num_var );\n            rec->PutArg(\n                new_arg[0],\n                new_arg[1],\n                new_arg[2]\n            );\n            new_op[i_op] = addr_t( rec->num_var_op() );\n            rec->PutOp(op);\n            break;\n\n            // Store a variable using a variable index\n            case StvvOp:\n            CPPAD_ASSERT_UNKNOWN( previous == 0 );\n            CPPAD_ASSERT_NARG_NRES(op, 3, 0);\n            new_arg[0] = new_vecad_ind[ arg[0] ];\n            new_arg[1] = new_var[ random_itr.var2op(size_t(arg[1])) ];\n            new_arg[2] = new_var[ random_itr.var2op(size_t(arg[2])) ];\n            CPPAD_ASSERT_UNKNOWN( size_t(new_arg[0]) < num_vecad_ind );\n            CPPAD_ASSERT_UNKNOWN( size_t(new_arg[1]) < num_var );\n            CPPAD_ASSERT_UNKNOWN( size_t(new_arg[2]) < num_var );\n            rec->PutArg(\n                new_arg[0],\n                new_arg[1],\n                new_arg[2]\n            );\n            new_op[i_op] = addr_t( rec->num_var_op() );\n            rec->PutOp(op);\n            break;\n\n            // -----------------------------------------------------------\n            // atomic function call operators\n\n            case AFunOp:\n            CPPAD_ASSERT_UNKNOWN( previous == 0 );\n            CPPAD_ASSERT_NARG_NRES(op, 4, 0);\n            // atom_index, atom_old, atom_n, atom_m\n            rec->PutArg(arg[0], arg[1], arg[2], arg[3]);\n            new_op[i_op] = addr_t( rec->num_var_op() );\n            rec->PutOp(AFunOp);\n            if( atom_state == start_atom )\n            {   atom_state = arg_atom;\n                atom_j     = size_t( arg[2] ); // just for counting arguments\n                atom_i     = size_t( arg[3] ); // just for counting results\n                CPPAD_ASSERT_UNKNOWN( atom_j > 0 );\n                CPPAD_ASSERT_UNKNOWN( atom_i > 0 );\n            }\n            else\n            {   CPPAD_ASSERT_UNKNOWN( atom_state == end_atom );\n                atom_state = start_atom;\n            }\n            break;\n\n            case FunapOp:\n            CPPAD_ASSERT_UNKNOWN( previous == 0 );\n            CPPAD_ASSERT_NARG_NRES(op, 1, 0);\n            new_arg[0] = new_par[ arg[0] ];\n            if( new_arg[0] == addr_t_max )\n            {   // This parameter is not used, so we put zero here. If we\n                // put nan here, atomic reverse mode would have to use azmul.\n                new_arg[0] = zero_par_index;\n            }\n            rec->PutArg(new_arg[0]);\n            new_op[i_op] = addr_t( rec->num_var_op() );\n            rec->PutOp(FunapOp);\n            CPPAD_ASSERT_UNKNOWN( atom_state == arg_atom );\n            --atom_j;\n            if( atom_j == 0 )\n                atom_state = ret_atom;\n            break;\n\n            case FunavOp:\n            CPPAD_ASSERT_UNKNOWN( previous == 0 );\n            CPPAD_ASSERT_NARG_NRES(op, 1, 0);\n            new_arg[0] = new_var[ random_itr.var2op(size_t(arg[0])) ];\n            CPPAD_ASSERT_UNKNOWN( size_t(new_arg[0]) < num_var );\n            if( new_arg[0] != 0 )\n            {   rec->PutArg(new_arg[0]);\n                new_op[i_op] = addr_t( rec->num_var_op() );\n                rec->PutOp(FunavOp);\n            }\n            else\n            {   // This argument does not affect the result.\n                new_arg[0] = zero_par_index;\n                rec->PutArg(new_arg[0]);\n                new_op[i_op] = addr_t( rec->num_var_op() );\n                rec->PutOp(FunapOp);\n            }\n            CPPAD_ASSERT_UNKNOWN( atom_state == arg_atom );\n            --atom_j;\n            if( atom_j == 0 )\n                atom_state = ret_atom;\n            break;\n\n            case FunrpOp:\n            CPPAD_ASSERT_UNKNOWN( previous == 0 );\n            CPPAD_ASSERT_NARG_NRES(op, 1, 0);\n            new_arg[0] = new_par[ arg[0] ];\n            if( new_arg[0] == addr_t_max )\n            {   // This parameter is not used here or anywhere.\n                CPPAD_ASSERT_UNKNOWN( op_usage[i_op] == usage_t(no_usage) );\n                new_arg[0] = zero_par_index;\n            }\n            rec->PutArg(new_arg[0]);\n            //\n            new_op[i_op] = addr_t( rec->num_var_op() );\n            rec->PutOp(FunrpOp);\n            CPPAD_ASSERT_UNKNOWN( atom_state == ret_atom );\n            --atom_i;\n            if( atom_i == 0 )\n                atom_state = end_atom;\n            break;\n\n            case FunrvOp:\n            CPPAD_ASSERT_UNKNOWN( previous == 0 );\n            CPPAD_ASSERT_NARG_NRES(op, 0, 1);\n            new_op[i_op]  = addr_t( rec->num_var_op() );\n            if( op_usage[i_op] == usage_t(yes_usage) )\n                new_var[i_op] = rec->PutOp(FunrvOp);\n            else\n            {   // This result is not used.\n                CPPAD_ASSERT_UNKNOWN( op_usage[i_op] == usage_t(no_usage) );\n                CPPAD_ASSERT_NARG_NRES(FunrpOp, 1, 0);\n                rec->PutArg( zero_par_index );\n                rec->PutOp(FunrpOp);\n            }\n\n            --atom_i;\n            if( atom_i == 0 )\n                atom_state = end_atom;\n            break;\n            // ---------------------------------------------------\n            case CSumOp:\n            // ---------------------------------------------------\n            CPPAD_ASSERT_UNKNOWN( previous == 0 );\n            //\n            // check if more entries can be included in this summation\n            size_pair = record_csum(\n                play                ,\n                random_itr          ,\n                op_usage            ,\n                new_par             ,\n                new_var             ,\n                i_var               ,\n                rec                 ,\n                csum_work\n            );\n            new_op[i_op]  = addr_t( size_pair.i_op );\n            new_var[i_op] = addr_t( size_pair.i_var );\n            break;\n            // ---------------------------------------------------\n\n            // all cases should be handled above\n            default:\n            CPPAD_ASSERT_UNKNOWN(false);\n        }\n    }\n    // modify the dependent variable vector to new indices\n    for(size_t i = 0; i < dep_taddr.size(); i++ )\n    {   dep_taddr[i] = size_t(new_var[ random_itr.var2op(dep_taddr[i]) ]);\n        CPPAD_ASSERT_UNKNOWN( size_t(dep_taddr[i]) < num_var );\n    }\n\n# ifndef NDEBUG\n    for(i_op = 0; i_op < num_op; i_op++)\n    {   random_itr.op_info(i_op, op, arg, i_var);\n        if( NumRes(op) > 0 )\n            CPPAD_ASSERT_UNKNOWN(\n                size_t(new_op[i_op]) < rec->num_var_op()\n            );\n    }\n# endif\n    // make sure that all the conditional expressions have been\n    // checked to see if they are still present\n    CPPAD_ASSERT_UNKNOWN( cskip_order_next == num_cexp );\n    // fill in the arguments for the CSkip operations\n    for(size_t i = 0; i < num_cexp; i++)\n    {   // if cskip_new[i].i_arg == 0, this conditional expression was skipped\n        if( cskip_new[i].i_arg > 0 )\n        {   // size_t i_arg\n            struct_cexp_info info = cexp_info[i];\n            addr_t n_true  = addr_t( skip_op_true.number_elements(i) );\n            addr_t n_false = addr_t( skip_op_false.number_elements(i) );\n            i_arg          = cskip_new[i].i_arg;\n            addr_t left    = addr_t( cskip_new[i].left );\n            addr_t right   = addr_t( cskip_new[i].right );\n            rec->ReplaceArg(i_arg++, addr_t(info.cop)   );\n            rec->ReplaceArg(i_arg++, addr_t(info.flag)  );\n            rec->ReplaceArg(i_arg++, left  );\n            rec->ReplaceArg(i_arg++, right );\n            rec->ReplaceArg(i_arg++, n_true     );\n            rec->ReplaceArg(i_arg++, n_false    );\n            sparse::list_setvec::const_iterator itr_true(skip_op_true, i);\n            while( *itr_true != skip_op_true.end() )\n            {   i_op = *itr_true;\n                // op_usage[i_op] == usage_t(yes_usage)\n                CPPAD_ASSERT_UNKNOWN( new_op[i_op] != 0 );\n                rec->ReplaceArg(i_arg++, new_op[i_op] );\n                //\n                ++itr_true;\n            }\n            sparse::list_setvec::const_iterator itr_false(skip_op_false, i);\n            while( *itr_false != skip_op_false.end() )\n            {   i_op   = *itr_false;\n                // op_usage[i_op] == usage_t(yes_usage)\n                CPPAD_ASSERT_UNKNOWN( new_op[i_op] != 0 );\n                rec->ReplaceArg(i_arg++, new_op[i_op] );\n                //\n                ++itr_false;\n            }\n            rec->ReplaceArg(i_arg++, 7 + n_true + n_false);\n# ifndef NDEBUG\n            size_t n_arg   = 7 + size_t(n_true) + size_t(n_false);\n            CPPAD_ASSERT_UNKNOWN( cskip_new[i].i_arg + n_arg == i_arg );\n# endif\n        }\n    }\n    return exceed_collision_limit;\n}\n\n} } } // END_CPPAD_LOCAL_OPTIMIZE_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/optimize/record_csum.hpp",
    "content": "# ifndef CPPAD_LOCAL_OPTIMIZE_RECORD_CSUM_HPP\n# define CPPAD_LOCAL_OPTIMIZE_RECORD_CSUM_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n// BEGIN_CPPAD_LOCAL_OPTIMIZE_NAMESPACE\nnamespace CppAD { namespace local { namespace optimize  {\n\n/*!\n{xrst_begin optimize_record_csum dev}\n{xrst_spell\n    addpv\n    addvv\n    subpv\n    subvp\n    subvv\n}\n\nRecording a Cumulative Summation Operator\n#########################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_RECORD_CSUM\n    // END_PROTOTYPE\n}\n\nplay\n****\nplayer object corresponding to the old recording.\n\nrandom_itr\n**********\nis a random iterator corresponding to the old operation sequence.\n\nop_usage\n********\nmapping from old operator index to how it is used.\n\nnew_par\n*******\nmapping from old parameter index to parameter index in new recording.\n\nnew_var\n*******\nmapping from old operator index to variable index in new recording.\n\ncurrent\n*******\nis the index in the old operation sequence for\nthe variable corresponding to the result for the current operator.\nWe use the notation *i_op* = *random_itr* . ``var2op`` ( *current* ) .\nIt follows that  NumRes( random_itr.get_op[i_op] ) > 0.\nIf 0 < j_op < i_op, either op_usage[j_op] == usage_t(csum_usage),\nop_usage[j_op] = usage_t(no_usage), or new_var[j_op] != 0.\n\nrec\n***\nis the object that will record the new operations.\n\nreturn\n******\nis the operator and variable indices in the new operation sequence.\n\nstack\n*****\nIs temporary work space. On input and output,\nstack.op_info, stack.add_var, and stack.sub_var, are all empty.\nThese stacks are passed in so that they are created once\nand then be reused with calls to ``record_csum`` .\n\nAssumptions\n***********\n\n#. random_itr.get_op[i_op] must be one of the following:\n   CSumOp, AddpvOp, AddvvOp, SubpvOp, SubvpOp, SubvvOp.\n#. op_usage[i_op] == usage_t(yes_usage).\n#. Either this is a CSumOp, or\n   op_usage[j_op] == usage_t(csum_usage) is true from some\n   j_op that corresponds to a variable that is an argument to\n   random_itr.get_op[i_op].\n\n{xrst_end optimize_record_csum}\n*/\n\n// BEGIN_RECORD_CSUM\ntemplate <class Addr, class Base>\nstruct_size_pair record_csum(\n    const player<Base>*                                play           ,\n    const play::const_random_iterator<Addr>&           random_itr     ,\n    const pod_vector<usage_t>&                         op_usage       ,\n    const pod_vector<addr_t>&                          new_par        ,\n    const pod_vector<addr_t>&                          new_var        ,\n    size_t                                             current        ,\n    recorder<Base>*                                    rec            ,\n    // local information passed so stacks need not be allocated for every call\n    struct_csum_stacks&                                stack          )\n// END_PROTOTYPE\n{\n# ifndef NDEBUG\n    // number of parameters corresponding to the old operation sequence.\n    size_t npar = play->num_par_all();\n# endif\n\n    // vector of length npar containing the parameters the old operation\n    // sequence; i.e., given a parameter index i < npar, the corresponding\n    // parameter value is par[i].\n    const Base* par = play->par_ptr();\n\n    // which parameters are dynamic\n    const pod_vector<bool>& par_is_dyn( play->par_is_dyn() );\n\n    // check assumption about work space\n    CPPAD_ASSERT_UNKNOWN( stack.op_info.empty() );\n    CPPAD_ASSERT_UNKNOWN( stack.add_var.empty() );\n    CPPAD_ASSERT_UNKNOWN( stack.sub_var.empty() );\n    //\n    // this operator is not csum connected to some other result\n    size_t i_op = random_itr.var2op(current);\n    CPPAD_ASSERT_UNKNOWN( ! ( op_usage[i_op] == usage_t(csum_usage) ) );\n    //\n    // information corresponding to the root node in the cumulative summation\n    struct struct_csum_op_info info;\n    size_t not_used;\n    random_itr.op_info(i_op, info.op, info.arg, not_used);\n    info.add = true;  // was parent operator positive or negative\n    //\n    // initialize stack as containing this one operator\n    stack.op_info.push( info );\n    //\n    // initialize sum of parameter values as zero\n    Base sum_par(0);\n    //\n# ifndef NDEBUG\n    // one argument of this operator must have been csum connected to it\n    bool ok = info.op == CSumOp;\n    if( (! ok) && (info.op != SubpvOp) && (info.op != AddpvOp) )\n    {   // first argument is a variable being added\n        i_op = random_itr.var2op(size_t(info.arg[0]));\n        ok  |= op_usage[i_op] == usage_t(csum_usage);\n    }\n    if( (! ok) && (info.op != SubvpOp) )\n    {   // second argument is a variable being added or subtracted\n        i_op = random_itr.var2op(size_t(info.arg[1]));\n        ok  |= op_usage[i_op] == usage_t(csum_usage);\n    }\n    CPPAD_ASSERT_UNKNOWN( ok );\n# endif\n    //\n    // while there are operators left on the stack\n    while( ! stack.op_info.empty() )\n    {   // get this summation operator\n        info = stack.op_info.top();\n        stack.op_info.pop();\n        op_code_var   op      = info.op;\n        const addr_t* arg     = info.arg;\n        bool          add     = info.add;\n        CPPAD_ASSERT_UNKNOWN( NumRes(op) == 1 );\n        //\n        if( op == CSumOp )\n        {   // ---------------------------------------------------------------\n            // Begin op == CSumOp\n            //\n            // arg[0] is constant parameter that initializes the sum\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < npar );\n            CPPAD_ASSERT_UNKNOWN( ! par_is_dyn[ arg[0] ] );\n            if( add )\n                sum_par += par[arg[0]];\n            else\n                sum_par -= par[arg[0]];\n            //\n            // stack entries for addition variable\n            size_t var_start = 5;                  // start addition variables\n            size_t var_end   = size_t( arg[1] );   // end addition variables\n            bool   add_var   = add;                // addition variables\n            for(size_t j = 0; j < 2; ++j)\n            {   for(size_t i = var_start; i < var_end; ++i)\n                {   //\n                    // check if the i-th argument has csum usage\n                    i_op = random_itr.var2op(size_t(arg[i]));\n                    if( op_usage[i_op] == usage_t(csum_usage) )\n                    {   // there is no result corresponding to i-th argument\n                        CPPAD_ASSERT_UNKNOWN( size_t( new_var[i_op]) == 0 );\n\n                        // push operator corresponding to the i-th argument\n                        random_itr.op_info(i_op, info.op, info.arg, not_used);\n                        info.add = add;\n                        stack.op_info.push( info );\n                    }\n                    else\n                    {   // there are no nodes below this one\n                        CPPAD_ASSERT_UNKNOWN( size_t(arg[i]) < current );\n                        if( add_var )\n                            stack.add_var.push(arg[i]);\n                        else\n                            stack.sub_var.push(arg[i]);\n                    }\n                }\n                var_start = var_end;  // start subtraction variables\n                var_end   = size_t( arg[2] ); // end subtraction variables\n                add_var   = ! add;    // subtraction variables\n            }\n            //\n            // stack entries for addition dynamic parameters\n            size_t dyn_start = var_end;           // start addition dynamics\n            size_t dyn_end   = size_t( arg[3] );  // end addition dynamics\n            bool   dny_add   = add;               // addition dynamics\n            for(size_t j = 0; j < 2; ++j)\n            {   for(size_t i = dyn_start; i < dyn_end; ++i)\n                {   // i-th argument is a dynamic parameter\n                    // (can't yet be a result, so no nodes below)\n                    CPPAD_ASSERT_UNKNOWN( par_is_dyn[ arg[i] ] );\n                    if( dny_add )\n                        stack.add_dyn.push(arg[i]);\n                    else\n                        stack.sub_dyn.push(arg[i]);\n                }\n                dyn_start = dyn_end; // start subtraction dynamics\n                dyn_end   = size_t( arg[4] ); // end subtraction dynamics\n                dny_add   = ! add;   // subtraction dynamics\n            }\n            // End op == CSumOp\n            // ---------------------------------------------------------------\n        }\n        else\n        {   // ---------------------------------------------------------------\n            // Begin op != CSumOp\n            //\n            // is this a subtraction operator\n            bool subtract = (op==SubpvOp) || (op==SubvpOp) || (op==SubvvOp);\n            //\n            // is the i-th argument a parameter\n            CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 );\n            bool par_arg[2];\n            switch(op)\n            {   case SubpvOp:\n                case AddpvOp:\n                par_arg[0] = true;\n                par_arg[1] = false;\n                break;\n                //\n                case SubvpOp:\n                par_arg[0] = false;\n                par_arg[1] = true;\n                break;\n                //\n                default:\n                par_arg[0] = false;\n                par_arg[1] = false;\n                break;\n            }\n            //\n            // loop over the arguments to this operator\n            for(size_t i = 0; i < 2; ++i)\n            {   if( subtract & (i == 1) )\n                    add = ! add;\n                if( par_arg[i] )\n                {   // case where i-th argument is a parameter\n                    CPPAD_ASSERT_UNKNOWN( size_t(arg[i]) < npar );\n                    //\n                    if( par_is_dyn[ arg[i] ] )\n                    {   // i-th argument is a dynamic parameter\n                        // (can't yet be a result, so no nodes below)\n                        if( add )\n                            stack.add_dyn.push(arg[i]);\n                        else\n                            stack.sub_dyn.push(arg[i]);\n                    }\n                    else\n                    {   // i-th argument is constant parameter\n                        if( add )\n                            sum_par += par[arg[i]];\n                        else\n                            sum_par -= par[arg[i]];\n                    }\n                }\n                else\n                {     // case where i-th argument is a variable\n                    //\n                    // check if the i-th argument has csum usage\n                    i_op = random_itr.var2op(size_t(arg[i]));\n                    if( op_usage[i_op] == usage_t(csum_usage) )\n                    {   // there is no result corresponding to i-th argument\n                        CPPAD_ASSERT_UNKNOWN( size_t( new_var[i_op]) == 0 );\n\n                        // push operator corresponding to the i-th argument\n                        random_itr.op_info(i_op, info.op, info.arg, not_used);\n                        info.add = add;\n                        stack.op_info.push( info );\n                    }\n                    else\n                    {   // there are no nodes below this one\n                        CPPAD_ASSERT_UNKNOWN( size_t(arg[i]) < current );\n                        if( add )\n                            stack.add_var.push(arg[i]);\n                        else\n                            stack.sub_var.push(arg[i]);\n                    }\n                }\n            }\n            // End op != CSumOp\n            // ---------------------------------------------------------------\n        }\n    }\n    // number of variables to add in this cumulative sum operator\n    size_t n_add_var = stack.add_var.size();\n\n    // number of variables to subtract in this cumulative sum operator\n    size_t n_sub_var = stack.sub_var.size();\n\n    // number of dynamics to add in this cumulative sum operator\n    size_t n_add_dyn = stack.add_dyn.size();\n\n    // number of dynamics to subtract in this cumulative sum operator\n    size_t n_sub_dyn = stack.sub_dyn.size();\n\n    // first five arguments to cumulative sum operator\n    addr_t new_arg = rec->put_con_par(sum_par);\n    rec->PutArg(new_arg);            // arg[0]: initial sum\n    size_t end   = n_add_var + 5;\n    rec->PutArg( addr_t(end) );      // arg[1]: end for add variables\n    end           += n_sub_var;\n    rec->PutArg( addr_t(end) );      // arg[2]: end for sub variables\n    end           += n_add_dyn;\n    rec->PutArg( addr_t(end) );      // arg[3]: end for add dynamics\n    end           += n_sub_dyn;\n    rec->PutArg( addr_t(end) );      // arg[4]: end for sub dynamics\n\n    // addition variable arguments\n    for(size_t i = 0; i < n_add_var; i++)\n    {   CPPAD_ASSERT_UNKNOWN( ! stack.add_var.empty() );\n        addr_t old_arg = stack.add_var.top();\n        new_arg        = new_var[ random_itr.var2op(size_t(old_arg)) ];\n        CPPAD_ASSERT_UNKNOWN( 0 < new_arg && size_t(new_arg) < current );\n        rec->PutArg(new_arg);         // arg[5+i]\n        stack.add_var.pop();\n    }\n\n    // subtraction variable arguments\n    for(size_t i = 0; i < n_sub_var; i++)\n    {   CPPAD_ASSERT_UNKNOWN( ! stack.sub_var.empty() );\n        addr_t old_arg = stack.sub_var.top();\n        new_arg        = new_var[ random_itr.var2op(size_t(old_arg)) ];\n        CPPAD_ASSERT_UNKNOWN( 0 < new_arg && size_t(new_arg) < current );\n        rec->PutArg(new_arg);      // arg[arg[1] + i]\n        stack.sub_var.pop();\n    }\n\n    // addition dynamic arguments\n    for(size_t i = 0; i < n_add_dyn; ++i)\n    {   addr_t old_arg = stack.add_dyn.top();\n        new_arg        = new_par[ old_arg ];\n        rec->PutArg(new_arg);      // arg[arg[2] + i]\n        stack.add_dyn.pop();\n    }\n\n    // subtraction dynamic arguments\n    for(size_t i = 0; i < n_sub_dyn; ++i)\n    {   addr_t old_arg = stack.sub_dyn.top();\n        new_arg        = new_par[ old_arg ];\n        rec->PutArg(new_arg);      // arg[arg[3] + i]\n        stack.sub_dyn.pop();\n    }\n\n    // number of arguments to this operator\n    rec->PutArg( addr_t(end + 1) );    // arg[4] + 1\n    //\n    // return value\n    struct_size_pair ret;\n    ret.i_op  = rec->num_var_op();\n    ret.i_var = size_t(rec->PutOp(CSumOp));\n    //\n    return ret;\n}\n\n} } } // END_CPPAD_LOCAL_OPTIMIZE_NAMESPACE\n\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/optimize/record_pv.hpp",
    "content": "# ifndef CPPAD_LOCAL_OPTIMIZE_RECORD_PV_HPP\n# define CPPAD_LOCAL_OPTIMIZE_RECORD_PV_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*!\n\\file record_pv.hpp\nRecord an operation of the form (parameter op variable).\n*/\n// BEGIN_CPPAD_LOCAL_OPTIMIZE_NAMESPACE\nnamespace CppAD { namespace local { namespace optimize  {\n\n/*!\nRecord an operation of the form (parameter op variable).\n\n\\param play\nplayer object corresponding to the old recroding.\n\n\\param random_itr\nrandom iterator corresponding to old recording.\n\n\\param new_par\nmapping from old parameter index to parameter index in new recording.\n\n\\param new_var\nmapping from old operator index to variable index in new recording.\n\n\\param i_op\nis the index in the old operation sequence for this operator.\nThe operator must be one of the following:\nAddpvOp, DivpvOp, MulpvOp, PowpvOp, SubpvOp, ZmulpvOp.\n\n\\param rec\nis the object that will record the new operations.\n\n\\return\nis the operator and variable indices in the new operation sequence.\n*/\ntemplate <class Addr, class Base>\nstruct_size_pair record_pv(\n    const player<Base>*                                play           ,\n    const play::const_random_iterator<Addr>&           random_itr     ,\n    const pod_vector<addr_t>&                          new_par        ,\n    const pod_vector<addr_t>&                          new_var        ,\n    size_t                                             i_op           ,\n    recorder<Base>*                                    rec            )\n{\n    // get_op_info\n    op_code_var   op;\n    const addr_t* arg;\n    size_t        i_var;\n    random_itr.op_info(i_op, op, arg, i_var);\n    //\n# ifndef NDEBUG\n    switch(op)\n    {   case AddpvOp:\n        case DivpvOp:\n        case MulpvOp:\n        case PowpvOp:\n        case SubpvOp:\n        case ZmulpvOp:\n        break;\n\n        default:\n        CPPAD_ASSERT_UNKNOWN(false);\n    }\n    // number of parameters corresponding to the old operation sequence.\n    size_t npar = play->num_par_all();\n# endif\n    //\n    // vector of length npar containing the parameters the old operation\n    // sequence; i.e., given a parameter index i < npar, the corresponding\n    // parameter value is par[i].\n    //\n    CPPAD_ASSERT_UNKNOWN( NumRes(op) > 0 );\n    CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < npar  );\n    CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < i_var ); // DAG condition\n    //\n    addr_t new_arg[2];\n    new_arg[0]   = new_par[ arg[0] ];\n    new_arg[1]   = new_var[ random_itr.var2op(size_t(arg[1])) ];\n    rec->PutArg( new_arg[0], new_arg[1] );\n    //\n    struct_size_pair ret;\n    ret.i_op  = rec->num_var_op();\n    ret.i_var = size_t(rec->PutOp(op));\n    CPPAD_ASSERT_UNKNOWN( 0 < new_arg[1] && size_t(new_arg[1]) < ret.i_var );\n    return ret;\n}\n\n} } } // END_CPPAD_LOCAL_OPTIMIZE_NAMESPACE\n\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/optimize/record_vp.hpp",
    "content": "# ifndef CPPAD_LOCAL_OPTIMIZE_RECORD_VP_HPP\n# define CPPAD_LOCAL_OPTIMIZE_RECORD_VP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*!\n\\file record_vp.hpp\nRecord an operation of the form (variable op parameter).\n*/\n// BEGIN_CPPAD_LOCAL_OPTIMIZE_NAMESPACE\nnamespace CppAD { namespace local { namespace optimize  {\n\n\n/*!\nRecord an operation of the form (variable op parameter).\n\n\\param play\nplayer object corresponding to the old recroding.\n\n\\param random_itr\nis a random iterator corresponding to the old recording.\n\n\\param new_par\nmapping from old parameter index to parameter index in new recording.\n\n\\param new_var\nmapping from old operator index to variable index in new recording.\n\n\\param i_op\nis the index in the old operation sequence for this operator.\nthe must be one of the following:\nDivvpOp, PowvpOp, SubvpOp, ZmulvpOp.\n\n\\param rec\nis the object that will record the new operations.\n\n\\return\nis the operator and variable indices in the new operation sequence.\n*/\ntemplate <class Addr, class Base>\nstruct_size_pair record_vp(\n    const player<Base>*                                play           ,\n    const play::const_random_iterator<Addr>&           random_itr     ,\n    const pod_vector<addr_t>&                          new_par        ,\n    const pod_vector<addr_t>&                          new_var        ,\n    size_t                                             i_op           ,\n    recorder<Base>*                                    rec            )\n{\n    // get_op_info\n    op_code_var   op;\n    const addr_t* arg;\n    size_t        i_var;\n    random_itr.op_info(i_op, op, arg, i_var);\n    //\n# ifndef NDEBUG\n    switch(op)\n    {   case DivvpOp:\n        case PowvpOp:\n        case SubvpOp:\n        case ZmulvpOp:\n        break;\n\n        default:\n        CPPAD_ASSERT_UNKNOWN(false);\n    }\n    // number of parameters corresponding to the old operation sequence.\n    size_t npar = play->num_par_all();\n# endif\n\n    // vector of length npar containing the parameters the old operation\n    // sequence; i.e., given a parameter index i < npar, the corresponding\n    // parameter value is par[i].\n    //\n    CPPAD_ASSERT_UNKNOWN( NumRes(op) > 0 );\n    CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < i_var ); // DAG condition\n    CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < npar  );\n    //\n    addr_t new_arg[2];\n    new_arg[0]   = new_var[ random_itr.var2op(size_t(arg[0])) ];\n    new_arg[1]   = new_par[ arg[1] ];\n    rec->PutArg( new_arg[0], new_arg[1] );\n    //\n    struct_size_pair ret;\n    ret.i_op  = rec->num_var_op();\n    ret.i_var = size_t(rec->PutOp(op));\n    CPPAD_ASSERT_UNKNOWN( 0 < new_arg[0] && size_t(new_arg[0]) < ret.i_var );\n    return ret;\n}\n\n} } } // END_CPPAD_LOCAL_OPTIMIZE_NAMESPACE\n\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/optimize/record_vv.hpp",
    "content": "# ifndef CPPAD_LOCAL_OPTIMIZE_RECORD_VV_HPP\n# define CPPAD_LOCAL_OPTIMIZE_RECORD_VV_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*!\n\\file record_vv.hpp\nRecord an operation of the form (variable op variable).\n*/\n// BEGIN_CPPAD_LOCAL_OPTIMIZE_NAMESPACE\nnamespace CppAD { namespace local { namespace optimize  {\n/*!\nRecord an operation of the form (variable op variable).\n\n\\param play\nplayer object corresponding to the old recroding.\n\n\\param random_itr\nrandom iterator corresponding to the old recording.\n\n\\param new_var\nmapping from old operator index to variable index in new recording.\n\n\\param i_op\nis the index in the old operation sequence for this operator.\nthe must be one of the following:\nAddvvOp, DivvvOp, MulvvOp, PowvvOp, SubvvOp, ZmulvvOp.\n\n\\param rec\nis the object that will record the new operations.\n\n\\return\nis the operator and variable indices in the new operation sequence.\n*/\ntemplate <class Addr, class Base>\nstruct_size_pair record_vv(\n    const player<Base>*                                play           ,\n    const play::const_random_iterator<Addr>&           random_itr     ,\n    const pod_vector<addr_t>&                          new_var        ,\n    size_t                                             i_op           ,\n    recorder<Base>*                                    rec            )\n{\n    // get_op_info\n    op_code_var   op;\n    const addr_t* arg;\n    size_t        i_var;\n    random_itr.op_info(i_op, op, arg, i_var);\n    //\n# ifndef NDEBUG\n    switch(op)\n    {   case AddvvOp:\n        case DivvvOp:\n        case MulvvOp:\n        case PowvvOp:\n        case SubvvOp:\n        case ZmulvvOp:\n        break;\n\n        default:\n        CPPAD_ASSERT_UNKNOWN(false);\n    }\n# endif\n    CPPAD_ASSERT_UNKNOWN( NumRes(op) > 0 );\n    CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < i_var ); // DAG condition\n    CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < i_var ); // DAG condition\n    //\n    addr_t new_arg[2];\n    new_arg[0]   = new_var[ random_itr.var2op(size_t(arg[0])) ];\n    new_arg[1]   = new_var[ random_itr.var2op(size_t(arg[1])) ];\n    rec->PutArg( new_arg[0], new_arg[1] );\n    //\n    struct_size_pair ret;\n    ret.i_op  = rec->num_var_op();\n    ret.i_var = size_t(rec->PutOp(op));\n    CPPAD_ASSERT_UNKNOWN( 0 < new_arg[0] && size_t(new_arg[0]) < ret.i_var );\n    CPPAD_ASSERT_UNKNOWN( 0 < new_arg[1] && size_t(new_arg[1]) < ret.i_var );\n    return ret;\n}\n\n} } } // END_CPPAD_LOCAL_OPTIMIZE_NAMESPACE\n\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/optimize/size_pair.hpp",
    "content": "# ifndef CPPAD_LOCAL_OPTIMIZE_SIZE_PAIR_HPP\n# define CPPAD_LOCAL_OPTIMIZE_SIZE_PAIR_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*!\n\\file size_pair.hpp\nInformation for one variable and one operation sequence.\n*/\n// BEGIN_CPPAD_LOCAL_OPTIMIZE_NAMESPACE\nnamespace CppAD { namespace local { namespace optimize  {\n\n/*!\n\\file size_pair.hpp\nInformation for one variable in one operation sequence.\n*/\nstruct struct_size_pair {\n    size_t i_op;  /// operator index for this variable\n    size_t i_var; /// variable index for this variable\n};\n\n} } } // END_CPPAD_LOCAL_OPTIMIZE_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/optimize/usage.hpp",
    "content": "# ifndef CPPAD_LOCAL_OPTIMIZE_USAGE_HPP\n# define CPPAD_LOCAL_OPTIMIZE_USAGE_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/local/define.hpp>\n\n// BEGIN_CPPAD_LOCAL_OPTIMIZE_NAMESPACE\nnamespace CppAD { namespace local { namespace optimize {\n\ntypedef CPPAD_VEC_ENUM_TYPE usage_t;\n\nenum enum_usage {\n    /// This operator is not used.\n    no_usage,\n\n    /// This operator is used one or more times.\n    yes_usage,\n\n    /*!\n    This operator is only used once, it is a summation operator,\n    and its parent is a summation operator. Furthermore, its result is not\n    a dependent variable. Hence case it can be removed as part of a\n    cumulative summation starting at its parent or above.\n    */\n    csum_usage\n};\n\n\n} } } // END_CPPAD_LOCAL_OPTIMIZE_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/local/play/addr_enum.hpp",
    "content": "# ifndef CPPAD_LOCAL_PLAY_ADDR_ENUM_HPP\n# define CPPAD_LOCAL_PLAY_ADDR_ENUM_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n// BEGIN_CPPAD_LOCAL_PLAY_NAMESPACE\nnamespace CppAD { namespace local { namespace play {\n\n/*!\n\\file addr_enum.hpp\n*/\n/// enum corresponding to type used for addressing iterators for a player\nenum addr_enum {\n    unsigned_short_enum  ,\n    addr_t_enum    ,\n    size_t_enum\n};\n\n} } } // BEGIN_CPPAD_LOCAL_PLAY_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/play/atom_op_info.hpp",
    "content": "# ifndef CPPAD_LOCAL_PLAY_ATOM_OP_INFO_HPP\n# define CPPAD_LOCAL_PLAY_ATOM_OP_INFO_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n// BEGIN_CPPAD_LOCAL_PLAY_NAMESPACE\nnamespace CppAD { namespace local { namespace play {\n\n/*!\n\\file atom_op_info.hpp\n*/\n\n/*!\n\\brief\nUnpack extra information corresponding to a AFunOp\n\n\\param op [in]\nmust be a AFunOp\n\n\\param op_arg [in]\nis the arguments for this operator\n\n\\param atom_index [out]\nis the index in local::atomic_index corresponding to this atomic functions.\n\n\\param call_id  [out]\nis the call_id for this atomic function call.\n\n\\param atom_m   [out]\nis the number of results for this user atomic function.\n\n\\param atom_n   [out]\nis the number of arguments for this user atomic function.\n\n\\return\nIs a pointer to this atomic function.\n*/\n// MUSTDO: change return to void once all sweeps switch to use call_atomic.\ntemplate <class Base>\natomic_base<Base>* atom_op_info(\n    const op_code_var op         ,\n    const addr_t*    op_arg     ,\n    size_t&          atom_index ,\n    size_t&          call_id    ,\n    size_t&          atom_m     ,\n    size_t&          atom_n     )\n{   atomic_base<Base>* atom_fun;\n    //\n    CPPAD_ASSERT_UNKNOWN( op == AFunOp );\n    CPPAD_ASSERT_NARG_NRES(op, 4, 0);\n    //\n    atom_index = size_t(op_arg[0]);\n    call_id    = size_t(op_arg[1]);\n    atom_n     = size_t(op_arg[2]);\n    atom_m     = size_t(op_arg[3]);\n    CPPAD_ASSERT_UNKNOWN( atom_n > 0 );\n    //\n    bool         set_null = false;\n    size_t       type     = 0;          // set to avoid warning\n    std::string* name_ptr = nullptr;\n    void*        v_ptr    = nullptr; // set to avoid warning\n    local::atomic_index<Base>(set_null, atom_index, type, name_ptr, v_ptr);\n    if( type == 3 )\n        return nullptr;\n# ifndef NDEBUG\n    if( v_ptr == nullptr )\n    {   // atom_fun is null so cannot use atom_fun->atomic_name()\n        std::string msg = atomic_base<Base>::class_name(atom_index)\n            + \": atomic_base function has been deleted\";\n        CPPAD_ASSERT_KNOWN(false, msg.c_str() );\n    }\n# endif\n    // the atomic_base object corresponding to this atomic function\n    atom_fun = reinterpret_cast< atomic_base<Base>* >( v_ptr );\n    return atom_fun;\n}\n\n} } } // END_CPPAD_LOCAL_PLAY_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/play/dyn_player.hpp",
    "content": "# ifndef CPPAD_LOCAL_PLAY_DYN_PLAYER_HPP\n# define CPPAD_LOCAL_PLAY_DYN_PLAYER_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/local/pod_vector.hpp>\n\n/*\n------------------------------------------------------------------------------\n{xrst_begin dyn_player dev}\n\nClass That Records a Dynamic Parameter Operation Sequence\n#########################################################\n\ndyn_play\n********\nWe use dyn_play to denote a dynamic player create with one of these\nconstructors.\n{xrst_literal ,\n    // BEGIN_CLASS , // END_CLASS\n    // BEGIN_DYN_PLAY , // END_DYN_PLAY\n}\n\n\ncheck_dynamic_dag\n*****************\nThis checks that the dynamic parameter operation sequence is an acyclic graph.\n{xrst_literal\n    // BEGIN_CHECK_DYNAMIC_DAG\n    // END_CHECK_DYNAMIC_DAG\n}\n\nAssignment\n**********\n{xrst_literal ,\n    // BEGIN_MOVE_ASSIGNMENT , // END_MOVE_ASSIGNMENT\n    // BEGIN_COPY_ASSIGNMENT , // END_COPY_ASSIGNMENT\n}\n\nswap\n****\nThis switches the contents of the two players.\n{xrst_literal\n    // BEGIN_SWAP\n    // END_SWAP\n}\n\nbase2ad\n*******\nThis returns a AD<Base> player corresponding with the same operation sequence.\n{xrst_literal\n    // BEGIN_BASE2AD\n    // END_BASE2AD\n}\n\nget_recording\n*************\nThis transfers a dynamic parameter recording to a dynamic parameter player.\n{xrst_literal\n    // BEGIN_GET_RECORDING\n    // END_GET_RECORDING\n}\n\ndyn_rec\n=======\nThe contents of *dyn_rec* are modified in an unspecified way by this operation.\n\npar_all\n*******\nThis vector holds all the parameter values (constant and dynamic parameters).\n{xrst_literal\n    // BEGIN_PAR_ALL\n    // END_PAR_ALL\n}\n\npar_is_dyn\n**********\nThis vector identifies which parameters are dynamic.\n{xrst_literal\n    // BEGIN_PAR_IS_DYN\n    // END_PAR_IS_DYN\n}\n\ndyn2par_index\n*************\nThis vector maps the dynamic parameter index to the\ncorresponding index in the vector of all the parameters.\n{xrst_literal\n    // BEGIN_DYN2PAR_INDEX\n    // END_DYN2PAR_INDEX\n}\n\npar_ptr\n*******\n{xrst_literal\n    // BEGIN_PAR_PTR\n    // END_PAR_PTR\n}\n\npar_one\n*******\n{xrst_literal\n    // BEGIN_PAR_ONE\n    // END_PAR_ONE\n}\n\npar_value\n=========\nis the value of one of the parameters.\n\npar_ptr\n=======\nis a raw pointer to all of the parameters\n\nn_dyn_independent\n*****************\nis the number of independent dynamic parameters\n{xrst_literal\n    // BEGIN_N_DYN_INDEPENDENT\n    // END_N_DYN_INDEPENDENT\n}\n\nnum_dynamic_par\n***************\nis the number of dynamic parameters\n{xrst_literal\n    // BEGIN_NUM_DYNAMIC_PAR\n    // END_NUM_DYNAMIC_PAR\n}\n\nnum_dynamic_arg\n***************\nis the length of the dynamic parameter argument vector\n{xrst_literal\n    // BEGIN_NUM_DYNAMIC_ARG\n    // END_NUM_DYNAMIC_ARG\n}\n\nsize_op_seq\n***********\nThis is a measure of how may bytes are needed to store the operation sequence.\nJust lengths (not capacities) are used for this computation.\nThis used to compute :ref:`fun_property@size_op_seq` for an ADFun object.\n{xrst_literal\n    // BEGIN_SIZE_OP_SEQ\n    // END_SIZE_OP_SEQ\n}\n\n{xrst_end dyn_player}\n*/\n\n// BEGIN_CPPAD_LOCAL_NAMESPACE\n// BEGIN_CLASS\nnamespace CppAD { namespace local {\ntemplate <class Base> class dyn_player {\n    // END_CLASS\n    //\n    // friend\n    template <class AnotherBase> friend class dyn_player;\nprivate:\n    //\n    // n_dyn_independent_\n    // Number of dynamic parameters in the recording\n    size_t n_dyn_independent_;\n    //\n    // par_all_;\n    // Vector containing all the parameters in the recording.\n    // Use pod_vector_maybe because Base may not be plain old data.\n    pod_vector_maybe<Base> par_all_;\n    //\n    // par_is_dyn_\n    // Which elements of par_all_ are dynamic parameters\n    // (same size are par_all_)\n    pod_vector<bool> par_is_dyn_;\n    //\n    // dyn2par_index_\n    // mapping from dynamic parameter index to parameter index\n    // dyn2par_index_.size() equal to number of dynamic parameters\n    // dyn2par_index_[j] < dyn2par_index_[j+1]\n    pod_vector<addr_t> dyn2par_index_;\n    //\n    // dyn_par_op_\n    // operators for just the dynamic parameters in par_all_\n         pod_vector<opcode_t> dyn_par_op_;\n    //\n    // dyn_par_arg_\n    // arguments for the dynamic parameter operators\n    pod_vector<addr_t> dyn_par_arg_;\n    //\npublic:\n    // set all scalars to zero to avoid valgraind warning when ani assignment\n    // occurs before values get set.\n    // BEGIN_DYN_PLAY\n    // dyn_player<Base> dyn_play\n    // dyn_player<Base> dyn_play(play)\n    dyn_player(void)\n    : n_dyn_independent_(0)\n    { }\n    dyn_player(dyn_player& dyn_play)\n    {   swap(dyn_play);  }\n    // END_DYN_PLAY\n    //\n    // destructor\n    ~dyn_player(void)\n    { }\n    //\n    // check_dynamic_dag\n    // Check dynamic parameter graph to make sure arguments have value less\n    // than or equal to the previously created dynamic parameter.\n    // This is the directed acyclic graph condition (DAG).\n# ifdef NDEBUG\n    void check_dynamic_dag(void) const\n    {   return; }\n# else\n    // BEGIN_CHECK_DYNAMIC_DAG\n    void check_dynamic_dag(void) const\n    // END_CHECK_DYNAMIC_DAG\n    {   // number of dynamic parameters\n        size_t num_dyn = dyn_par_op_.size();\n        //\n        size_t i_arg = 0; // initialize dynamic parameter argument index\n        for(size_t i_dyn = 0; i_dyn < num_dyn; ++i_dyn)\n        {   // i_par is parameter index\n            addr_t i_par = dyn2par_index_[i_dyn];\n            CPPAD_ASSERT_UNKNOWN( par_is_dyn_[i_par] );\n            //\n            // operator for this dynamic parameter\n            op_code_dyn op = op_code_dyn( dyn_par_op_[i_dyn] );\n            //\n            // number of arguments for this dynamic parameter\n            size_t n_arg       = num_arg_dyn(op);\n            if( op == atom_dyn )\n            {   size_t n = size_t( dyn_par_arg_[i_arg + 2] );\n                size_t m = size_t( dyn_par_arg_[i_arg + 3] );\n                n_arg    = 6 + n + m;\n                CPPAD_ASSERT_UNKNOWN(\n                    n_arg == size_t( dyn_par_arg_[i_arg + 5 + n + m] )\n                );\n                for(size_t i = 5; i < n - 1; ++i)\n                    CPPAD_ASSERT_UNKNOWN( dyn_par_arg_[i_arg + i] <  i_par );\n# ifndef NDEBUG\n                for(size_t i = 5+n; i < 5+n+m; ++i)\n                {   addr_t j_par = dyn_par_arg_[i_arg + i];\n                    CPPAD_ASSERT_UNKNOWN( (j_par == 0) || (j_par >= i_par) );\n                }\n# endif\n            }\n            else\n            {   size_t num_non_par = num_non_par_arg_dyn(op);\n                for(size_t i = num_non_par; i < n_arg; ++i)\n                    CPPAD_ASSERT_UNKNOWN( dyn_par_arg_[i_arg + i] < i_par);\n            }\n            //\n            // next dynamic parameter\n            i_arg += n_arg;\n        }\n        return;\n    }\n# endif\n    // BEGIN_MOVE_ASSIGNMENT\n    // dyn_play_1 = dyn_play_2\n    void operator=(dyn_player&& dyn_play)\n    // END_MOVE_ASSIGNMENT\n    {   swap(dyn_play); }\n    //\n    // BEGIN_COPY_ASSIGNMENT\n    // dyn_play_1 = dyn_play_2\n    void operator=(const dyn_player& dyn_play)\n    // END_COPY_ASSIGNMENT\n    {\n        // size_t objects\n        n_dyn_independent_  = dyn_play.n_dyn_independent_;\n        //\n        // pod_vectors\n        par_is_dyn_         = dyn_play.par_is_dyn_;\n        dyn2par_index_      = dyn_play.dyn2par_index_;\n        dyn_par_op_         = dyn_play.dyn_par_op_;\n        dyn_par_arg_        = dyn_play.dyn_par_arg_;\n        //\n        // pod_maybe_vectors\n        par_all_            = dyn_play.par_all_;\n    }\n    //\n    // BEGIN_BASE2AD\n    // ad_dyn_play = dyn_play\n    dyn_player< AD<Base> > base2ad(void) const\n    // END_BASE2AD\n    {   //\n        // dyn_play\n        dyn_player< AD<Base> > dyn_play;\n        //\n        // size_t objects\n        dyn_play.n_dyn_independent_  = n_dyn_independent_;\n        //\n        // pod_vectors\n        dyn_play.par_is_dyn_         = par_is_dyn_;\n        dyn_play.dyn2par_index_      = dyn2par_index_;\n        dyn_play.dyn_par_op_         = dyn_par_op_;\n        dyn_play.dyn_par_arg_        = dyn_par_arg_;\n        //\n        // pod_maybe_vector< AD<Base> > = pod_maybe_vector<Base>\n        dyn_play.par_all_.resize( par_all_.size() );\n        for(size_t i = 0; i < par_all_.size(); ++i)\n            dyn_play.par_all_[i] = par_all_[i];\n        //\n        return dyn_play;\n    }\n    // BEGIN_SWAP\n    // dyn_play_1.swap( dyn_play_2 )\n    void swap(dyn_player& other)\n    // END_SWAP\n    {   // size_t objects\n        std::swap(n_dyn_independent_,  other.n_dyn_independent_);\n        //\n        // pod_vectors\n        par_is_dyn_.swap(         other.par_is_dyn_);\n        dyn2par_index_.swap(      other.dyn2par_index_);\n        dyn_par_op_.swap(         other.dyn_par_op_);\n        dyn_par_arg_.swap(        other.dyn_par_arg_);\n        //\n        // pod_maybe_vectors\n        par_all_.swap(    other.par_all_);\n    }\n    //\n    // BEGIN_GET_RECORDING\n    void get_recording(dyn_recorder<Base>& dyn_rec)\n    // END_GET_RECORDING\n    {   //\n# ifndef NDEBUG\n        size_t addr_t_max = size_t( std::numeric_limits<addr_t>::max() );\n        CPPAD_ASSERT_UNKNOWN( dyn_rec.par_is_dyn_.size() < addr_t_max );\n        CPPAD_ASSERT_UNKNOWN( dyn_rec.dyn_par_op_.size() < addr_t_max );\n        CPPAD_ASSERT_UNKNOWN( dyn_rec.dyn_par_arg_.size() < addr_t_max );\n        CPPAD_ASSERT_UNKNOWN( dyn_rec.par_all_.size() < addr_t_max );\n# endif\n\n        // size_t values\n        n_dyn_independent_ = dyn_rec.n_dyn_independent_;\n        //\n        // pod_vectors\n        par_is_dyn_.swap( dyn_rec.par_is_dyn_ );\n        dyn_par_op_.swap( dyn_rec.dyn_par_op_ );\n        dyn_par_arg_.swap( dyn_rec.dyn_par_arg_ );\n        //\n        // pod_maybe\n        par_all_.swap( dyn_rec.par_all_ );\n        //\n        // dyn2par_index_\n        dyn2par_index_.resize( dyn_par_op_.size() );\n        size_t i_dyn = 0;\n        for(size_t i_par = 0; i_par < par_all_.size(); ++i_par)\n        {   if( par_is_dyn_[i_par] )\n            {   dyn2par_index_[i_dyn] = addr_t( i_par );\n                ++i_dyn;\n            }\n        }\n        CPPAD_ASSERT_UNKNOWN( i_dyn == dyn2par_index_.size() );\n        //\n        // check_dynamic_dag\n        check_dynamic_dag();\n    }\n    //\n    // BEGIN_PAR_ALL\n    // par_all = dyn_play.par_all()\n    pod_vector_maybe<Base>& par_all(void)\n    // END_PAR_ALL\n    {   return par_all_; }\n    const pod_vector_maybe<Base>& par_all(void) const\n    {   return par_all_; }\n    //\n    // BEGIN_PAR_IS_DYN\n    // par_is_dyn = dyn_play.par_is_dyn()\n    const pod_vector<bool>& par_is_dyn(void) const\n    // END_PAR_IS_DYN\n    {   return par_is_dyn_; }\n    //\n    // BEGIN_DYN2PAR_INDEX\n    // dyn2par_index = dyn_play.dyn2par_index()\n    const pod_vector<addr_t>& dyn2par_index(void) const\n    // END_DYN2PAR_INDEX\n    {   return dyn2par_index_; }\n    //\n    // BEGIN_DYN_OP_ALL\n    // dyn_par_op = dyn_play.dyn_par_op()\n    const pod_vector<opcode_t>& dyn_par_op(void) const\n    // END_DYN_OP_ALL\n    {   return dyn_par_op_; }\n    //\n    // BEGIN_DYN_ARG_ALL\n    // dyn_par_arg = dyn_play.dyn_par_arg()\n    const pod_vector<addr_t>& dyn_par_arg(void) const\n    {   return dyn_par_arg_; }\n    // END_DYN_ARG_ALL\n    //\n    // BEGIN_PAR_ONE\n    // par_one = dyn_play.par_one(i)\n    Base par_one(size_t i) const\n    // END_PAR_ONE\n    {   return par_all_[i]; }\n    //\n    // BEGIN_PAR_PTR\n    // par_ptr = dyn_play.par_ptr()\n    const Base* par_ptr(void) const\n    // END_PAR_PTR\n    {   return par_all_.data(); }\n    //\n    // BEGIN_N_DYN_INDEPENDENT\n    // n_dyn_independent\n    size_t n_dyn_independent(void) const\n    // END_N_DYN_INDEPENDENT\n    {   return n_dyn_independent_; }\n    //\n    // BEGIN_NUM_DYNAMIC_PAR\n    // num_dynamic_par = dy_play.num_dynamic_par()\n    size_t num_dynamic_par(void) const\n    // END_NUM_DYNAMIC_PAR\n    {   return dyn_par_op_.size(); }\n    //\n    // BEGIN_NUM_DYNAMIC_ARG\n    // num_dynamic_arg = dyn_play.num_dynamic_arg()\n    size_t num_dynamic_arg(void) const\n    // END_NUM_DYNAMIC_ARG\n    {   return dyn_par_arg_.size(); }\n    //\n    // BEGIN_NUM_PAR_REC\n    // num_par_all = dyn_play.rec()\n    size_t num_par_all(void) const\n    // END_NUM_PAR_REC\n    {   return par_all_.size(); }\n    //\n    // BEGIN_SIZE_OP_SEQ\n    // size_op_seq = dyn_play.size_op_seq()\n    size_t size_op_seq(void) const\n    // END_SIZE_OP_SEQ\n    {   return 0\n            + par_all_.size()       * sizeof(Base)\n            + par_is_dyn_.size()    * sizeof(bool)\n            + dyn2par_index_.size() * sizeof(addr_t)\n            + dyn_par_op_.size()    * sizeof(opcode_t)\n            + dyn_par_arg_.size()   * sizeof(addr_t)\n        ;\n    }\n};\n\n} } // END_CPPAD_lOCAL_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/local/play/player.hpp",
    "content": "# ifndef CPPAD_LOCAL_PLAY_PLAYER_HPP\n# define CPPAD_LOCAL_PLAY_PLAYER_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/local/play/addr_enum.hpp>\n# include <cppad/local/play/sequential_iterator.hpp>\n# include <cppad/local/play/subgraph_iterator.hpp>\n# include <cppad/local/play/dyn_player.hpp>\n# include <cppad/local/play/random_setup.hpp>\n# include <cppad/local/atom_state.hpp>\n# include <cppad/local/is_pod.hpp>\n\nnamespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE\n/*!\n\\file player.hpp\nFile used to define the player class.\n*/\n\n/*!\nClass used to store and play back an operation sequence recording.\n\n\\tparam Base\nThese were AD< Base > operations when recorded. Operations during playback\nare done using the type Base .\n*/\n\n// random_itr_info\nstruct random_itr_info_t {\n    //\n    // *_op2arg\n    // index in var_arg_ corresponding to the first argument for each operator\n    pod_vector<unsigned  short> short_op2arg;\n    pod_vector<addr_t>          addr_t_op2arg;\n    pod_vector<size_t>          size_t_op2arg;\n    /*\n    *_op2var\n    Index of the result variable for each operator. If the operator has\n    no results, this is not defined. The invalid index num_var_ is used\n    when NDEBUG is not defined. If the operator has more than one result, this\n    is the primary result; i.e., the last result. Auxiliary results are only\n    used by the current operator and not used by other operators.\n    */\n    pod_vector<unsigned  short> short_op2var;\n    pod_vector<addr_t>          addr_t_op2var;\n    pod_vector<size_t>          size_t_op2var;\n    /*\n    *_var2op\n    Mapping from primary variable index to corresponding operator index.\n    This is used to traverse sub-graphs of the operation sequence.\n    This value is valid (invalid) for primary (auxiliary) variables.\n    */\n    pod_vector<unsigned  short> short_var2op;\n    pod_vector<addr_t>          addr_t_var2op;\n    pod_vector<size_t>          size_t_var2op;\n    //\n    // swap\n    void swap( random_itr_info_t& other )\n    {   //\n        short_op2arg.swap( other.short_op2arg );\n        short_op2var.swap( other.short_op2var );\n        short_var2op.swap( other.short_var2op );\n        //\n        addr_t_op2arg.swap( other.addr_t_op2arg );\n        addr_t_op2var.swap( other.addr_t_op2var );\n        addr_t_var2op.swap( other.addr_t_var2op );\n        //\n        size_t_op2arg.swap( other.size_t_op2arg );\n        size_t_op2var.swap( other.size_t_op2var );\n        size_t_var2op.swap( other.size_t_var2op );\n    }\n    //\n    // clear\n    void clear(void)\n    {   //\n        short_op2arg.clear();\n        short_op2var.clear();\n        short_var2op.clear();\n        //\n        addr_t_op2arg.clear();\n        addr_t_op2var.clear();\n        addr_t_var2op.clear();\n        //\n        size_t_op2arg.clear();\n        size_t_op2var.clear();\n        size_t_var2op.clear();\n    }\n    //\n    // size\n    size_t size(void) const\n    {   //\n        CPPAD_ASSERT_UNKNOWN( short_op2arg.size()  == short_op2var.size() );\n        CPPAD_ASSERT_UNKNOWN( addr_t_op2arg.size() == addr_t_op2var.size() );\n        CPPAD_ASSERT_UNKNOWN( size_t_op2arg.size() == size_t_op2var.size() );\n        //\n        size_t short_num_arg  = short_op2arg.size();\n        size_t int_num_arg    = addr_t_op2arg.size();\n        size_t size_t_num_arg = size_t_op2arg.size();\n        //\n        size_t short_num_var  = short_var2op.size();\n        size_t int_num_var= addr_t_var2op.size();\n        size_t size_t_num_var = size_t_var2op.size();\n        //\n        // result\n        size_t result = 0;\n        //\n        // result\n        if( short_num_arg != 0 )\n        {   CPPAD_ASSERT_UNKNOWN( int_num_arg    == 0 );\n            CPPAD_ASSERT_UNKNOWN( size_t_num_arg == 0 );\n            //\n            result = 2 * short_num_arg + short_num_var;\n        }\n        else\n            CPPAD_ASSERT_UNKNOWN( short_num_var == 0 );\n        //\n        // result\n        if( int_num_arg != 0 )\n        {   CPPAD_ASSERT_UNKNOWN( short_num_arg  == 0 );\n            CPPAD_ASSERT_UNKNOWN( size_t_num_arg == 0 );\n            //\n            result = 2 * int_num_arg + int_num_var;\n        }\n        else\n            CPPAD_ASSERT_UNKNOWN( int_num_var == 0 );\n        //\n        // result\n        if( size_t_num_arg != 0 )\n        {   CPPAD_ASSERT_UNKNOWN( short_num_arg  == 0 );\n            CPPAD_ASSERT_UNKNOWN( int_num_arg    == 0 );\n            //\n            result = 2 * size_t_num_arg + size_t_num_var;\n        }\n        else\n            CPPAD_ASSERT_UNKNOWN( size_t_num_var == 0 );\n        //\n        return result;\n    }\n};\n\ntemplate <class Base>\nclass player {\n    //\n    // friend\n    // player<Base> must be a friend of player< AD<Base> > for base2ad to work\n    template <class AnotherBase> friend class player;\nprivate:\n    // ----------------------------------------------------------------------\n    //\n    // dyn_play_\n    dyn_player<Base> dyn_play_;\n    //\n    // num_var_\n         // Number of variables in the recording.\n    size_t num_var_;\n\n    // num_var_load_\n         // number of vecad load operations in the reconding\n    size_t num_var_load_;\n\n    // num_var_vecad_\n         // Number of VecAD vectors in the recording\n    size_t num_var_vecad_;\n\n    // var_op_\n    // The operators in the recording.\n    pod_vector<opcode_t> var_op_;\n\n    // var_arg_\n    // The operation argument indices in the recording\n    pod_vector<addr_t> var_arg_;\n\n    // var_text_\n    // Character strings ('\\\\0' terminated) in the recording.\n    pod_vector<char> var_text_;\n\n    // var_vecad_ind_\n         // The VecAD indices in the recording.\n    pod_vector<addr_t> var_vecad_ind_;\n    //\n    // random_itr_info_\n    // Information needed to use member functions that begin with random_\n    // and for using const_subgraph_iterator.\n    random_itr_info_t random_itr_info_;\n    //\npublic:\n    //\n    /// default constructor\n    // set all scalars to zero to avoid valgraind warning when ani assignment\n    // occurs before values get set.\n    player(void)\n    : num_var_(0)\n    , num_var_load_(0)\n    , num_var_vecad_(0)\n    { }\n    //\n    // move semantics constructor\n    // (none of the default constructor values matter to the destructor)\n    player(player& play)\n    {   swap(play);  }\n    //\n    // destructor\n    ~player(void)\n    { }\n    //\n    // address_type\n    // type used for addressing iterators for this player\n    play::addr_enum address_type(void) const\n    {\n        // required\n        size_t required = 0;\n        required = std::max(required, num_var_       );  // number variables\n        required = std::max(required, var_op_.size()  ); // number operators\n        required = std::max(required, var_arg_.size() ); // number arguments\n        //\n        // unsigned short\n        if( required <= std::numeric_limits<unsigned short>::max() )\n            return play::unsigned_short_enum;\n        //\n        // addr_t\n        if( required <= std::numeric_limits<addr_t>::max() )\n            return play::addr_t_enum;\n        //\n        // unsigned size_t\n        CPPAD_ASSERT_UNKNOWN(\n            required <= std::numeric_limits<size_t>::max()\n        );\n        return play::size_t_enum;\n    }\n    //\n    // get_recording\n    /*!\n    Moving an operation sequence from a recorder to this player\n\n    \\param rec\n    the object that was used to record the operation sequence. After this\n    operation, the state of the recording is no longer defined. For example,\n    the pod_vector member variables in this have been swapped with rec.\n\n    \\param n_ind\n    the number of independent variables (only used for error checking\n    when NDEBUG is not defined).\n\n    \\par\n    Use an assert to check that the length of the following vectors is\n    less than the maximum possible value for addr_t; i.e., that an index\n    in these vectors can be represented using the type addr_t:\n    var_op_, var_vecad_ind_, var_arg_, test_vec_, par_all_, var_text_,\n    dyn_par_arg_.\n    */\n    void get_recording(recorder<Base>& rec, size_t n_ind)\n    {\n# ifndef NDEBUG\n        size_t addr_t_max = size_t( std::numeric_limits<addr_t>::max() );\n# endif\n        //\n        // dyn_play_\n        dyn_play_.get_recording( rec.dyn_record_ );\n\n        // size_t values\n        num_var_            = rec.num_var_;\n        num_var_load_       = rec.num_var_load_;\n\n        // var_op_\n        var_op_.swap(rec.var_op_);\n        CPPAD_ASSERT_UNKNOWN(var_op_.size() < addr_t_max );\n\n        // var_arg_\n        var_arg_.swap(rec.var_arg_);\n        CPPAD_ASSERT_UNKNOWN(var_arg_.size()    < addr_t_max );\n\n        // var_text_\n        var_text_.swap(rec.var_text_);\n        CPPAD_ASSERT_UNKNOWN(var_text_.size() < addr_t_max );\n\n        // var_vecad_ind_\n             var_vecad_ind_.swap(rec.var_vecad_ind_);\n        CPPAD_ASSERT_UNKNOWN(var_vecad_ind_.size() < addr_t_max );\n\n        // num_var_vecad_\n             num_var_vecad_ = 0;\n        {   // var_vecad_ind_ contains size of each VecAD followed by\n            // the parameter indices used to initialize it.\n            size_t i = 0;\n            while( i < var_vecad_ind_.size() )\n            {   num_var_vecad_++;\n                i += size_t( var_vecad_ind_[i] ) + 1;\n            }\n            CPPAD_ASSERT_UNKNOWN( i == var_vecad_ind_.size() );\n        }\n\n        // random access information\n        clear_random();\n\n        // some checks\n        check_inv_op(n_ind);\n        check_variable_dag();\n    }\n    //\n    // check_inv_op\n# ifdef NDEBUG\n    void check_inv_op(size_t n_ind) const\n    {   return; }\n# else\n    void check_inv_op(size_t n_ind) const\n    {   play::const_sequential_iterator itr = begin();\n        op_code_var   op;\n        const addr_t* op_arg;\n        size_t        var_index;\n        itr.op_info(op, op_arg, var_index);\n        CPPAD_ASSERT_UNKNOWN( op == BeginOp );\n        size_t i_op = 0;\n        while( op != EndOp )\n        {   // start at second operator\n            (++itr).op_info(op, op_arg, var_index);\n            ++i_op;\n            CPPAD_ASSERT_UNKNOWN( (op == InvOp) == (i_op <= n_ind) );\n        }\n        return;\n    }\n# endif\n    //\n    // check_variable_dag\n# ifdef NDEBUG\n    void check_variable_dag(void) const\n    {   return; }\n# else\n    void check_variable_dag(void) const\n    {   play::const_sequential_iterator itr = begin();\n        op_code_var   op;\n        const addr_t* op_arg;\n        size_t        var_index;\n        itr.op_info(op, op_arg, var_index);\n        CPPAD_ASSERT_UNKNOWN( op == BeginOp );\n        //\n        addr_t arg_var_bound = 0;\n        while( op != EndOp )\n        {   (++itr).op_info(op, op_arg, var_index);\n            switch(op)\n            {\n                // cases where nothing to do\n                case BeginOp:\n                case EndOp:\n                case EqppOp:\n                case InvOp:\n                case LdpOp:\n                case LeppOp:\n                case LtppOp:\n                case NeppOp:\n                case ParOp:\n                case AFunOp:\n                case FunapOp:\n                case FunrpOp:\n                case FunrvOp:\n                case StppOp:\n                break;\n\n                // only first argument is a variable\n                case AbsOp:\n                case AcosOp:\n                case AcoshOp:\n                case AsinOp:\n                case AsinhOp:\n                case AtanOp:\n                case AtanhOp:\n                case CosOp:\n                case CoshOp:\n                case DivvpOp:\n                case ErfOp:\n                case ErfcOp:\n                case ExpOp:\n                case Expm1Op:\n                case LevpOp:\n                case LogOp:\n                case Log1pOp:\n                case LtvpOp:\n                case NegOp:\n                case PowvpOp:\n                case SignOp:\n                case SinOp:\n                case SinhOp:\n                case SqrtOp:\n                case SubvpOp:\n                case TanOp:\n                case TanhOp:\n                case FunavOp:\n                case ZmulvpOp:\n                CPPAD_ASSERT_UNKNOWN(op_arg[0] <= arg_var_bound );\n                break;\n\n                // only second argument is a variable\n                case AddpvOp:\n                case DisOp:\n                case DivpvOp:\n                case EqpvOp:\n                case LdvOp:\n                case LepvOp:\n                case LtpvOp:\n                case MulpvOp:\n                case NepvOp:\n                case PowpvOp:\n                case StvpOp:\n                case SubpvOp:\n                case ZmulpvOp:\n                CPPAD_ASSERT_UNKNOWN(op_arg[1] <= arg_var_bound );\n                break;\n\n                // only first and second arguments are variables\n                case AddvvOp:\n                case DivvvOp:\n                case EqvvOp:\n                case LevvOp:\n                case LtvvOp:\n                case MulvvOp:\n                case NevvOp:\n                case PowvvOp:\n                case SubvvOp:\n                case ZmulvvOp:\n                CPPAD_ASSERT_UNKNOWN(op_arg[0] <= arg_var_bound );\n                CPPAD_ASSERT_UNKNOWN(op_arg[1] <= arg_var_bound );\n                break;\n\n                // StpvOp\n                case StpvOp:\n                CPPAD_ASSERT_UNKNOWN(op_arg[2] <= arg_var_bound );\n                break;\n\n                // StvvOp\n                case StvvOp:\n                CPPAD_ASSERT_UNKNOWN(op_arg[1] <= arg_var_bound );\n                CPPAD_ASSERT_UNKNOWN(op_arg[2] <= arg_var_bound );\n                break;\n\n                // CSumOp\n                case CSumOp:\n                {   CPPAD_ASSERT_UNKNOWN( 5 < op_arg[2] );\n                    for(addr_t j = 5; j < op_arg[2]; j++)\n                        CPPAD_ASSERT_UNKNOWN(op_arg[j] <= arg_var_bound);\n                }\n                itr.correct_before_increment();\n                break;\n\n                // CExpOp\n                case CExpOp:\n                if( op_arg[1] & 1 )\n                    CPPAD_ASSERT_UNKNOWN( op_arg[2] <= arg_var_bound);\n                if( op_arg[1] & 2 )\n                    CPPAD_ASSERT_UNKNOWN( op_arg[3] <= arg_var_bound);\n                if( op_arg[1] & 4 )\n                    CPPAD_ASSERT_UNKNOWN( op_arg[4] <= arg_var_bound);\n                if( op_arg[1] & 8 )\n                    CPPAD_ASSERT_UNKNOWN( op_arg[5] <= arg_var_bound);\n                break;\n\n                // PriOp\n                case PriOp:\n                if( op_arg[0] & 1 )\n                    CPPAD_ASSERT_UNKNOWN( op_arg[1] <= arg_var_bound);\n                if( op_arg[0] & 2 )\n                    CPPAD_ASSERT_UNKNOWN( op_arg[3] <= arg_var_bound);\n                break;\n\n                // CSkipOp\n                case CSkipOp:\n                if( op_arg[1] & 1 )\n                    CPPAD_ASSERT_UNKNOWN( op_arg[2] <= arg_var_bound);\n                if( op_arg[1] & 2 )\n                    CPPAD_ASSERT_UNKNOWN( op_arg[3] <= arg_var_bound);\n                itr.correct_before_increment();\n                break;\n\n                default:\n                CPPAD_ASSERT_UNKNOWN(false);\n                break;\n\n\n            }\n            if( NumRes(op) > 0 )\n            {   if( var_index > 0 )\n                {   CPPAD_ASSERT_UNKNOWN(size_t(arg_var_bound) < var_index);\n                }\n                else\n                {   CPPAD_ASSERT_UNKNOWN(size_t(arg_var_bound) == var_index);\n                }\n                //\n                arg_var_bound = addr_t(var_index);\n            }\n        }\n        return;\n    }\n# endif\n    //\n    // operator=\n    // move semantics assignment\n    void operator=(player&& play)\n    {   swap(play); }\n    //\n    // operator=\n    void operator=(const player& play)\n    {\n        //\n        // dyn_play_\n        dyn_play_           = play.dyn_play_;\n        //\n        // size_t objects\n        num_var_            = play.num_var_;\n             num_var_load_       = play.num_var_load_;\n             num_var_vecad_      = play.num_var_vecad_;\n             //\n        // pod_vectors\n        var_op_             = play.var_op_;\n        var_arg_            = play.var_arg_;\n        var_text_           = play.var_text_;\n        var_vecad_ind_      = play.var_vecad_ind_;\n        //\n        // random_itr_info_\n        random_itr_info_    = play.random_itr_info_;\n    }\n    //\n    // base2ad\n    // Create a player< AD<Base> > from this player<Base>\n    player< AD<Base> > base2ad(void) const\n    {   player< AD<Base> > play;\n        //\n        // dyn_play_\n        play.dyn_play_            = dyn_play_.base2ad();\n        //\n        // size_t objects\n        play.num_var_            = num_var_;\n             play.num_var_load_       = num_var_load_;\n             play.num_var_vecad_      = num_var_vecad_;\n             //\n        // pod_vectors\n        play.var_op_             = var_op_;\n        play.var_arg_            = var_arg_;\n        play.var_text_           = var_text_;\n        play.var_vecad_ind_      = var_vecad_ind_;\n        //\n        // random_itr_info_\n        play.random_itr_info_    = random_itr_info_;\n        //\n        return play;\n    }\n    //\n    // swap\n    /// used for move semantics version of ADFun assignment operation\n    void swap(player& other)\n    {   //\n        // dyn_play_\n        dyn_play_.swap( other.dyn_play_ );\n        //\n        // size_t objects\n        std::swap(num_var_,            other.num_var_);\n        std::swap(num_var_load_,       other.num_var_load_);\n        std::swap(num_var_vecad_,      other.num_var_vecad_);\n        //\n        // pod_vectors\n        var_op_.swap(             other.var_op_);\n        var_arg_.swap(            other.var_arg_);\n        var_text_.swap(           other.var_text_);\n        var_vecad_ind_.swap(  other.var_vecad_ind_);\n        //\n        // random_itr_info_\n        random_itr_info_.swap(    other.random_itr_info_);\n    }\n    //\n    // setup_random\n    /// Enable use of const_subgraph_iterator and member functions that begin\n    // with random_(no work if already setup).\n    void setup_random(unsigned short& not_used)\n    {   play::random_setup(\n            num_var_                            ,\n            var_op_                             ,\n            var_arg_                            ,\n            &random_itr_info_.short_op2arg      ,\n            &random_itr_info_.short_op2var      ,\n            &random_itr_info_.short_var2op\n        );\n    }\n    void setup_random(addr_t& not_used)\n    {   play::random_setup(\n            num_var_                            ,\n            var_op_                             ,\n            var_arg_                            ,\n            &random_itr_info_.addr_t_op2arg     ,\n            &random_itr_info_.addr_t_op2var     ,\n            &random_itr_info_.addr_t_var2op\n        );\n    }\n# if ! CPPAD_IS_SAME_TAPE_ADDR_TYPE_SIZE_T\n    void setup_random(size_t& not_used)\n    {   play::random_setup(\n            num_var_                            ,\n            var_op_                             ,\n            var_arg_                            ,\n            &random_itr_info_.size_t_op2arg     ,\n            &random_itr_info_.size_t_op2var     ,\n            &random_itr_info_.size_t_var2op\n        );\n    }\n# endif\n    //\n    // clear_\n    /// Free memory used for functions that begin with random_\n    /// and random iterators and subgraph iterators\n    void clear_random(void)\n    {   random_itr_info_.clear();\n        CPPAD_ASSERT_UNKNOWN( random_itr_info_.size() == 0  );\n    }\n    //\n    // par_all\n         pod_vector_maybe<Base>& par_all(void)\n    {   return dyn_play_.par_all(); }\n    const pod_vector_maybe<Base>& par_all(void) const\n    {   return dyn_play_.par_all(); }\n    //\n    // par_is_dyn\n    const pod_vector<bool>& par_is_dyn(void) const\n    {   return dyn_play_.par_is_dyn(); }\n    //\n    // dyn2par_index\n    const pod_vector<addr_t>& dyn2par_index(void) const\n    {   return dyn_play_.dyn2par_index(); }\n    //\n    // dyn_par_op\n    const pod_vector<opcode_t>& dyn_par_op(void) const\n    {   return dyn_play_.dyn_par_op(); }\n    //\n    // dyn_par_arg\n    const pod_vector<addr_t>& dyn_par_arg(void) const\n    {   return dyn_play_.dyn_par_arg(); }\n    //\n    // GetOp\n    /*!\n    \\brief\n    fetch an operator from the recording.\n\n    \\return\n    the i-th operator in the recording.\n\n    \\param i\n    the index of the operator in recording\n    */\n    op_code_var GetOp (size_t i) const\n    {   return op_code_var(var_op_[i]); }\n    //\n    // GetVecInd\n    /*!\n    \\brief\n    Fetch a VecAD index from the recording.\n\n    \\return\n    the i-th VecAD index in the recording.\n\n    \\param i\n    the index of the VecAD index in recording\n    */\n    size_t GetVecInd (size_t i) const\n    {   return size_t( var_vecad_ind_[i] ); }\n    //\n    // par_one\n    Base par_one(size_t i) const\n    {   return dyn_play_.par_one(i);  }\n    //\n    // par_ptr\n    const Base* par_ptr(void) const\n    {   return dyn_play_.par_ptr(); }\n    //\n    // GetTxt\n    /*!\n    \\brief\n    Fetch a '\\\\0' terminated string from the recording.\n\n    \\return\n    the beginning of the string.\n\n    \\param i\n    the index where the string begins.\n    */\n    const char *GetTxt(size_t i) const\n    {   CPPAD_ASSERT_UNKNOWN(i < var_text_.size() );\n        return var_text_.data() + i;\n    }\n    //\n    // n_dyn_independent\n    size_t n_dyn_independent(void) const\n    {   return dyn_play_.n_dyn_independent(); }\n    //\n    // num_dynamic_par\n    size_t num_dynamic_par(void) const\n    {   return dyn_play_.num_dynamic_par(); }\n    //\n    // num_dynamic_arg\n    size_t num_dynamic_arg(void) const\n    {   return dyn_play_.num_dynamic_arg(); }\n    //\n    // num_var\n    size_t num_var(void) const\n    {   return num_var_; }\n    //\n    // num_var_load\n    size_t num_var_load(void) const\n    {   return num_var_load_; }\n    //\n    // num_var_op\n    size_t num_var_op(void) const\n    {   return var_op_.size(); }\n    //\n    // num_var_vecad_ind\n    size_t num_var_vec_ind(void) const\n    {   return var_vecad_ind_.size(); }\n    //\n    // num_var_vecad\n    size_t num_var_vecad(void) const\n    {   return num_var_vecad_; }\n    //\n    // num_var_arg\n    size_t num_var_arg(void) const\n    {   return var_arg_.size(); }\n    //\n    // num_par_all\n    size_t num_par_all(void) const\n    {   return dyn_play_.num_par_all(); }\n    //\n    // num_var_text\n    size_t num_var_text(void) const\n    {   return var_text_.size(); }\n    //\n    // size_op_seq\n    // A measure of amount of memory used to store\n    // the operation sequence, just lengths, not capacities.\n    // In user api as f.size_op_seq(); see the file fun_property.omh.\n    size_t size_op_seq(void) const\n    {   return 0\n            + dyn_play_.size_op_seq()\n            + var_op_.size()            * sizeof(opcode_t)\n            + var_arg_.size()           * sizeof(addr_t)\n            + var_text_.size()          * sizeof(char)\n            + var_vecad_ind_.size() * sizeof(addr_t)\n        ;\n    }\n    // size_random\n    // A measure of amount of memory used for random access routine\n    // In user api as f.size_random(); see the file fun_property.omh.\n    size_t size_random(void) const\n    {   return random_itr_info_.size(); }\n    //\n    // begin\n    /// const sequential iterator begin\n    play::const_sequential_iterator begin(void) const\n    {   size_t op_index = 0;\n        size_t num_var      = num_var_;\n             return play::const_sequential_iterator(\n            num_var, &var_op_, &var_arg_, op_index\n        );\n    }\n    //\n    // end\n    play::const_sequential_iterator end(void) const\n    {   size_t op_index = var_op_.size() - 1;\n        size_t num_var      = num_var_;\n             return play::const_sequential_iterator(\n            num_var, &var_op_, &var_arg_, op_index\n        );\n    }\n    //\n    // begin_subgraph\n    play::const_subgraph_iterator<addr_t>  begin_subgraph(\n        const play::const_random_iterator<addr_t>& random_itr ,\n        const pod_vector<addr_t>*                  subgraph   ) const\n    {   size_t subgraph_index = 0;\n        return play::const_subgraph_iterator<addr_t>(\n            random_itr,\n            subgraph,\n            subgraph_index\n        );\n    }\n    //\n    // end_subgraph\n    template <class Addr>\n    play::const_subgraph_iterator<Addr>  end_subgraph(\n        const play::const_random_iterator<Addr>&   random_itr ,\n        const pod_vector<addr_t>*                  subgraph   ) const\n    {   size_t subgraph_index = subgraph->size() - 1;\n        return play::const_subgraph_iterator<Addr>(\n            random_itr,\n            subgraph,\n            subgraph_index\n        );\n    }\n    //\n    /// const random iterator\n    play::const_random_iterator<unsigned short>\n    get_random(unsigned short& not_used) const\n    {   return play::const_random_iterator<unsigned short>(\n            var_op_                             ,\n            var_arg_                            ,\n            &random_itr_info_.short_op2arg      ,\n            &random_itr_info_.short_op2var      ,\n            &random_itr_info_.short_var2op\n        );\n    }\n    play::const_random_iterator<addr_t>\n    get_random(addr_t& not_used) const\n    {   return play::const_random_iterator<addr_t>(\n            var_op_                             ,\n            var_arg_                            ,\n            &random_itr_info_.addr_t_op2arg     ,\n            &random_itr_info_.addr_t_op2var     ,\n            &random_itr_info_.addr_t_var2op\n        );\n    }\n# if ! CPPAD_IS_SAME_TAPE_ADDR_TYPE_SIZE_T\n    play::const_random_iterator<size_t>\n    get_random(size_t& not_used)\n    {   return play::const_random_iterator<size_t>(\n            var_op_                             ,\n            var_arg_                            ,\n            &random_itr_info_.size_t_op2arg     ,\n            &random_itr_info_.size_t_op2var     ,\n            &random_itr_info_.size_t_var2op\n        );\n    }\n# endif\n};\n\n} } // END_CPPAD_lOCAL_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/local/play/random_iterator.hpp",
    "content": "# ifndef CPPAD_LOCAL_PLAY_RANDOM_ITERATOR_HPP\n# define CPPAD_LOCAL_PLAY_RANDOM_ITERATOR_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n// BEGIN_CPPAD_LOCAL_PLAY_NAMESPACE\nnamespace CppAD { namespace local { namespace play {\n\n/*!\n\\file random_iterator.hpp\n*/\n\n/*!\nConstant random iterator for a player object.\n\n\\tparam Addr\nAn integer type capable of representing the largest value in the vectors\nvar_arg, op2arg_index, op2var_index, var2op_index.\n*/\ntemplate <class Addr>\nclass const_random_iterator {\nprivate:\n    /// vector of operators on the tape\n    const pod_vector<opcode_t>* var_op_;\n\n    /// vector of arguments for all the operators\n    /// (note that this is same type as used in recorder; i.e., addr_t)\n    const pod_vector<addr_t>* var_arg_;\n\n    /// mapping from operator index to index of first argument in var_arg_\n    const pod_vector<Addr>* op2arg_index_;\n\n    /// mapping from operator index to index of primary (last) result\n    const pod_vector<Addr>* op2var_index_;\n\n    /// mapping from primary variable index to operator index\n    /// (only specified for primary variables)\n    const pod_vector<Addr>* var2op_index_;\n\npublic:\n    /// index_t\n    typedef Addr index_t;\n    //\n    /// default constructor\n    const_random_iterator(void) :\n    var_op_(nullptr)     ,\n    var_arg_(nullptr)    ,\n    op2arg_index_(nullptr) ,\n    op2var_index_(nullptr) ,\n    var2op_index_(nullptr)\n    { }\n    /// default assignment operator\n    void operator=(const const_random_iterator& rhs)\n    {\n        var_op_          = rhs.var_op_;\n        op2arg_index_    = rhs.op2arg_index_;\n        op2var_index_    = rhs.op2var_index_;\n        var2op_index_    = rhs.var2op_index_;\n        return;\n    }\n    /*!\n    Create a random iterator\n\n    \\par var2op_index\n    This variable is not needed and can be null if the var2op member\n    function is not used.\n    */\n    const_random_iterator(\n        const pod_vector<opcode_t>&           var_op     , ///< var_op_\n        const pod_vector<addr_t>&             var_arg    , ///< var_arg_\n        const pod_vector<Addr>*               op2arg_index , ///< op2ar_vec_\n        const pod_vector<Addr>*               op2var_index , ///< op2var_index_\n        const pod_vector<Addr>*               var2op_index ) ///< var2op_index_\n    :\n    var_op_          ( &var_op    )   ,\n    var_arg_         ( &var_arg   )   ,\n    op2arg_index_    ( op2arg_index )   ,\n    op2var_index_    ( op2var_index )   ,\n    var2op_index_    ( var2op_index )\n    { }\n    /*!\n    \\brief\n    fetch the information corresponding to an operator\n\n    \\param op_index\n    index for this operator [in]\n\n    \\param op [out]\n    op code for this operator.\n\n    \\param op_arg [out]\n    pointer to the first argument to this operator.\n\n    \\param var_index [out]\n    index of the last variable (primary variable) for this operator.\n    If there is no primary variable for this operator, i_var not specified\n    and could have any value.\n    */\n    void op_info(\n        size_t         op_index   ,\n        op_code_var&   op         ,\n        const addr_t*& op_arg     ,\n        size_t&        var_index  ) const\n    {   op        = op_code_var( (*var_op_)[op_index] );\n        op_arg    = (*op2arg_index_)[op_index] + var_arg_->data();\n        var_index = size_t( (*op2var_index_)[op_index] );\n        return;\n    }\n    /*!\n    \\brief\n    map variable index to operator index.\n\n    \\param var_index\n    must be the index of a primary variable.\n\n    \\return\n    is the index of the operator corresponding to this primary variable.\n    */\n    size_t var2op(size_t var_index) const\n    {   // check that var2op_index was not null in constructor\n        CPPAD_ASSERT_UNKNOWN( var2op_index_ != nullptr );\n        //\n        // operator index\n        size_t op_index = size_t( (*var2op_index_)[var_index] );\n        //\n        // check that var_index is a primary variable index (see random_setup)\n        CPPAD_ASSERT_UNKNOWN( op_index < var_op_->size() );\n        //\n        return op_index;\n    }\n    /// get operator corresponding to operator index\n    op_code_var get_op(size_t op_index) const\n    {   return op_code_var( (*var_op_)[op_index] );\n    }\n    /// number of operators\n    size_t num_op(void) const\n    {   return var_op_->size(); }\n    //\n    /// number of variables\n    size_t num_var(void) const\n    {   return var2op_index_->size(); }\n};\n\n} } } // BEGIN_CPPAD_LOCAL_PLAY_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/play/random_setup.hpp",
    "content": "# ifndef CPPAD_LOCAL_PLAY_RANDOM_SETUP_HPP\n# define CPPAD_LOCAL_PLAY_RANDOM_SETUP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n// BEGIN_CPPAD_LOCAL_PLAY_NAMESPACE\nnamespace CppAD { namespace local { namespace play {\n\n/*!\n\\file random_setup.hpp\n*/\n\n/*!\nSet up random access to a player object.\n\n\\tparam Addr\nAn integer type capable of representing the largest value in the vectors\nvar_arg, op2arg_index, op2var_index, var2op_index.\n\n\\param num_var\nnum_var is the number of variables in this operation sequence.\n\n\\param var_op\nThe mapping\n<code>op = op_code_var[ var_op[op_index] ]</code>\nmaps from operator index op_index to the operator op.\n\n\\param var_arg\nis a vector of all the arguments for all the operators.\nThe mapping op2arg_index will map from operator indices\nto index in this vector.\n\n\\param op2arg_index\nOn input, op2arg_index is either the empty vector\n(or contains the proper result from a previous call to random_setup).\nUpon return it maps each operator index to the index in op_var_arg of its\nfirst argument for the operator.\n\n\\param op2var_index\nOn input, op2var_index is either the empty vector\n(or contains the proper result from a previous call to random_setup).\nUpon return it maps each operator index to the primary (last)\nresult for the operator. If there are no results for the operator,\nthe return value map value is not specified.\n\n\\param var2op_index\nOn input, var2op_index is either the empty vector\n(or contains the proper result from a previous call to random_setup).\nUpon return it maps each primary variable index to the corresponding\noperator index. The value of the map is only specified for primary variable\nindices.\n*/\ntemplate <class Addr>\nvoid random_setup(\n    size_t                                    num_var    ,\n    const pod_vector<opcode_t>&               var_op     ,\n    const pod_vector<addr_t>&                 var_arg    ,\n    pod_vector<Addr>*                         op2arg_index ,\n    pod_vector<Addr>*                         op2var_index ,\n    pod_vector<Addr>*                         var2op_index )\n{\n    if( op2arg_index->size() != 0 )\n    {   CPPAD_ASSERT_UNKNOWN( op2arg_index->size() == var_op.size() );\n        CPPAD_ASSERT_UNKNOWN( op2var_index->size() == var_op.size() );\n        CPPAD_ASSERT_UNKNOWN( var2op_index->size() == num_var        );\n        return;\n    }\n    CPPAD_ASSERT_UNKNOWN( op2var_index->size() == 0         );\n    CPPAD_ASSERT_UNKNOWN( op2var_index->size() == 0         );\n    CPPAD_ASSERT_UNKNOWN( var2op_index->size() == 0         );\n    CPPAD_ASSERT_UNKNOWN( op_code_var( var_op[0] ) == BeginOp );\n    CPPAD_ASSERT_NARG_NRES(BeginOp, 1, 1);\n    //\n    size_t num_op     = var_op.size();\n    size_t  var_index = 0;\n    size_t  arg_index = 0;\n    //\n    op2arg_index->resize( num_op );\n    op2var_index->resize( num_op );\n    var2op_index->resize( num_var  );\n# ifndef NDEBUG\n    // value of var2op for auxiliary variables is num_op (invalid)\n    for(size_t i_var = 0; i_var < num_var; ++i_var)\n        (*var2op_index)[i_var] = Addr( num_op );\n    // value of op2var is num_var (invalid) when NumRes(op) = 0\n    for(size_t i_op = 0; i_op < num_op; ++i_op)\n        (*op2var_index)[i_op] = Addr( num_var );\n# endif\n    for(size_t i_op = 0; i_op < num_op; ++i_op)\n    {   op_code_var op          = op_code_var( var_op[i_op] );\n        //\n        // index of first argument for this operator\n        (*op2arg_index)[i_op]   = Addr( arg_index );\n        arg_index            += NumArg(op);\n        //\n        // index of first result for next operator\n        var_index  += NumRes(op);\n        if( NumRes(op) > 0 )\n        {   // index of last (primary) result for this operator\n            (*op2var_index)[i_op] = Addr( var_index - 1 );\n            //\n            // mapping from primary variable to its operator\n            (*var2op_index)[var_index - 1] = Addr( i_op );\n        }\n        // CSumOp\n        if( op == CSumOp )\n        {   CPPAD_ASSERT_UNKNOWN( NumArg(CSumOp) == 0 );\n            //\n            // pointer to first argument for this operator\n            const addr_t* op_arg = var_arg.data() + arg_index;\n            //\n            // The actual number of arguments for this operator is\n            // op_arg[4] + 1\n            // Correct index of first argument for next operator\n            arg_index += size_t(op_arg[4] + 1);\n        }\n        //\n        // CSkip\n        if( op == CSkipOp )\n        {   CPPAD_ASSERT_UNKNOWN( NumArg(CSumOp) == 0 );\n            //\n            // pointer to first argument for this operator\n            const addr_t* op_arg = var_arg.data() + arg_index;\n            //\n            // The actual number of arguments for this operator is\n            // 7 + op_arg[4] + op_arg[5].\n            // Correct index of first argument for next operator.\n            arg_index += size_t(7 + op_arg[4] + op_arg[5]);\n        }\n    }\n}\n\n} } } // BEGIN_CPPAD_LOCAL_PLAY_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/play/sequential_iterator.hpp",
    "content": "# ifndef CPPAD_LOCAL_PLAY_SEQUENTIAL_ITERATOR_HPP\n# define CPPAD_LOCAL_PLAY_SEQUENTIAL_ITERATOR_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n// BEGIN_CPPAD_LOCAL_PLAY_NAMESPACE\nnamespace CppAD { namespace local { namespace play {\n\n/*!\n\\file sequential_iterator.hpp\n*/\n\n/*!\nConstant sequential iterator for a player object.\n\n\\tparam Addr\nAn integer type capable of representing the largest value in the vectors\nvar_arg, op2arg_index, op2var_index, var2op_index.\n\n\\par\nExcept for constructor, the public API for this class is the same as\nfor the subgraph_iterator class.\n*/\nclass const_sequential_iterator {\nprivate:\n    /// pointer to the first operator in the player, BeginOp = *op_begin_\n    const opcode_t*           op_begin_;\n\n    /// pointer one past last operator in the player, EndOp = *(op_end_ - 1)\n    const opcode_t*           op_end_;\n\n    /// pointer to the first argument for the first operator\n    const addr_t*             arg_begin_;\n\n    /// pointer on past last argument for last operator\n    const addr_t*             arg_end_;\n\n    /// pointer to current operator\n    const opcode_t*           op_cur_;\n\n    /// pointer to first argument for current operator\n    const addr_t*             arg_;\n\n    /// number of variables in tape (not const for assignment operator)\n    size_t                    num_var_;\n\n    /// index of last result for current operator\n    size_t                    var_index_;\n\n    /// value of current operator; i.e. op_ = *op_cur_\n    op_code_var               op_;\npublic:\n    /// default constructor\n    const_sequential_iterator(void) :\n    op_begin_(nullptr)  ,\n    op_end_(nullptr)    ,\n    arg_begin_(nullptr) ,\n    arg_end_(nullptr)   ,\n    op_cur_(nullptr)    ,\n    arg_(nullptr)       ,\n    num_var_(0)            ,\n    var_index_(0)          ,\n    op_(NumberOp)\n    { }\n    /// assignment operator\n    void operator=(const const_sequential_iterator& rhs)\n    {\n        op_begin_  = rhs.op_begin_;\n        op_end_    = rhs.op_end_;\n        arg_begin_ = rhs.arg_begin_;\n        arg_end_   = rhs.arg_end_;\n        op_cur_    = rhs.op_cur_;\n        arg_       = rhs.arg_;\n        num_var_   = rhs.num_var_;\n        var_index_ = rhs.var_index_;\n        op_        = rhs.op_;\n        return;\n    }\n    /*!\n    Create a sequential iterator starting either at beginning or end of tape\n\n    \\param num_var\n    is the number of variables in the tape.\n\n    \\param var_op\n    is the vector of operators on the tape.\n\n    \\param var_arg\n    is the vector of arguments for all the operators\n\n    \\param op_index\n    is the operator index that iterator will start at.\n    It must be zero or var_op_->size() - 1.\n\n    \\par Assumptions\n    - op_code_var(var_op_[0]) == BeginOp\n    - op_code_var(var_op_[var_op_->size() - 1]) == EndOp\n    */\n    const_sequential_iterator(\n        size_t                                num_var    ,\n        const pod_vector<opcode_t>*           var_op     ,\n        const pod_vector<addr_t>*             var_arg    ,\n        size_t                                op_index   )\n    :\n    op_begin_   ( var_op->data() )                   ,\n    op_end_     ( var_op->data() + var_op->size() )  ,\n    arg_begin_  ( var_arg->data() )                  ,\n    arg_end_    ( var_arg->data() + var_arg->size() ),\n    num_var_    ( num_var )\n    {   if( op_index == 0 )\n        {\n            // index of last result for BeginOp\n            var_index_ = 0;\n            //\n            // first argument to BeginOp\n            arg_       = var_arg->data();\n            //\n            // BeginOp\n            op_cur_    = op_begin_;\n            op_        = op_code_var( *op_cur_ );\n            CPPAD_ASSERT_UNKNOWN( op_ == BeginOp );\n            CPPAD_ASSERT_NARG_NRES(op_, 1, 1);\n        }\n        else\n        {   CPPAD_ASSERT_UNKNOWN(op_index == var_op->size()-1);\n            //\n            // index of last result for EndOp\n            var_index_ = num_var - 1;\n            //\n            // first argument to EndOp (has no arguments)\n            arg_ = var_arg->data() + var_arg->size();\n            //\n            // EndOp\n            op_cur_    = op_end_ - 1;\n            op_        = op_code_var( *op_cur_ );\n            CPPAD_ASSERT_UNKNOWN( op_ == EndOp );\n            CPPAD_ASSERT_NARG_NRES(op_, 0, 0);\n        }\n    }\n    /*!\n    Advance iterator to next operator\n    */\n    const_sequential_iterator& operator++(void)\n    {\n        // first argument for next operator\n        arg_ += NumArg(op_);\n        //\n        // next operator\n        ++op_cur_;\n        op_ = op_code_var( *op_cur_ );\n        //\n        // last result for next operator\n        var_index_ += NumRes(op_);\n        //\n        return *this;\n    }\n    /*!\n    Correction applied before ++ operation when current operator\n    is CSumOp, CSkipOp, or AFunOP.\n    */\n    void correct_before_increment(void)\n    {   //\n        // arg_\n        // actual number of arguments for this operator depends on argument data\n        CPPAD_ASSERT_UNKNOWN( NumArg(op_) == 0 );\n        const addr_t* arg = arg_;\n        //\n        switch( op_ )\n        {   //\n            default:\n            CPPAD_ASSERT_UNKNOWN( false );\n            break;\n            //\n            // CSumOp\n            case CSumOp:\n            CPPAD_ASSERT_UNKNOWN( arg + 4 < arg_end_ );\n            arg_ += arg[4] + 1;\n            CPPAD_ASSERT_UNKNOWN( *(arg_ - 1) == arg[4] + 1 );\n            break;\n            //\n            // CSkipOp\n            case CSkipOp:\n            CPPAD_ASSERT_UNKNOWN( arg + 5 < arg_end_ );\n            arg_ += 7 + arg[4] + arg[5];\n            CPPAD_ASSERT_UNKNOWN( *(arg_ - 1) == 7 + arg[4] + arg[5] );\n            break;\n        }\n        CPPAD_ASSERT_UNKNOWN( arg_ <= arg_end_ );\n        return;\n    }\n    /*!\n    Backup iterator to previous operator\n    */\n    const_sequential_iterator& operator--(void)\n    {   //\n        // last result for next operator\n        var_index_ -= NumRes(op_);\n        //\n        // next operator\n        --op_cur_;\n        op_ = op_code_var( *op_cur_ );\n        //\n        // first argument for next operator\n        arg_ -= NumArg(op_);\n        //\n        return *this;\n    }\n    /*!\n    Correction applied after -- operation when current operator\n    is CSumOp or CSkipOp.\n\n    \\param arg [out]\n    corrected point to arguments for this operation.\n    */\n    void correct_after_decrement(const addr_t*& arg)\n    {   //\n        // arg\n        // actual number of arguments for this operator depends on argument data\n        CPPAD_ASSERT_UNKNOWN( NumArg(op_) == 0 );\n        CPPAD_ASSERT_UNKNOWN( arg_begin_ < arg_ );\n        //\n        switch( op_ )\n        {   //\n            default:\n            CPPAD_ASSERT_UNKNOWN( false );\n            break;\n            //\n            // CSumOp\n            case CSumOp:\n            {   // index of arg[4]\n                addr_t n_arg = *(arg_ - 1);\n                arg          = arg_ - n_arg;\n                CPPAD_ASSERT_UNKNOWN( arg[4] + 1 == n_arg );\n            }\n            break;\n            //\n            // CSkipOp\n            case CSkipOp:\n            {   addr_t n_arg = *(arg_ - 1);\n                arg          = arg_ - n_arg;\n                CPPAD_ASSERT_UNKNOWN( 7 + arg[4] + arg[5] == n_arg );\n            }\n            break;\n        }\n        //\n        // arg_\n        CPPAD_ASSERT_UNKNOWN( arg_begin_ <= arg );\n        CPPAD_ASSERT_UNKNOWN( arg + NumArg(op_) <= arg_end_ );\n        arg_ = arg;\n    }\n    /*!\n    \\brief\n    Get information corresponding to current operator.\n\n    \\param op [out]\n    op code for this operator.\n\n    \\param arg [out]\n    pointer to the first argument to this operator.\n\n    \\param var_index [out]\n    index of the last variable (primary variable) for this operator.\n    If there is no primary variable for this operator, var_index\n    is not specified and could have any value.\n    */\n    void op_info(\n        op_code_var&   op         ,\n        const addr_t*& arg        ,\n        size_t&        var_index  ) const\n    {   // op\n        CPPAD_ASSERT_UNKNOWN( op_begin_ <= op_cur_ && op_cur_ < op_end_ )\n        op        = op_;\n        //\n        // arg\n        arg = arg_;\n        CPPAD_ASSERT_UNKNOWN( arg_begin_ <= arg );\n        CPPAD_ASSERT_UNKNOWN( arg + NumArg(op) <= arg_end_ );\n        //\n        // var_index\n        CPPAD_ASSERT_UNKNOWN( var_index_ < num_var_ || NumRes(op) == 0 );\n        var_index = var_index_;\n    }\n    /// current operator index\n    size_t op_index(void)\n    {   return size_t(op_cur_ - op_begin_); }\n};\n\n} } } // BEGIN_CPPAD_LOCAL_PLAY_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/play/subgraph_iterator.hpp",
    "content": "# ifndef CPPAD_LOCAL_PLAY_SUBGRAPH_ITERATOR_HPP\n# define CPPAD_LOCAL_PLAY_SUBGRAPH_ITERATOR_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/local/play/random_iterator.hpp>\n\n// BEGIN_CPPAD_LOCAL_PLAY_NAMESPACE\nnamespace CppAD { namespace local { namespace play {\n\n/*!\n\\file random_iterator.hpp\n*/\n\n/*!\nConstant subgraph iterator for a player object.\n\n\\tparam Addr\nAn integer type capable of representing the largest value in the vectors\nvar_arg, op2arg_index, op2var_index, var2op_index.\n\nExcept for constructor, the public API for this class is the same as\nfor the sequential iterator class.\n*/\ntemplate <class Addr>\nclass const_subgraph_iterator {\nprivate:\n    /// a random iterator used to access player information\n    const const_random_iterator<Addr>* random_itr_;\n\n    /// sorted subset of operator indices that we will include\n    const pod_vector<addr_t>* subgraph_;\n\n    /// index in subgraph of current operator\n    /// The initial value for this index must be zero or subgraph.size()-1.\n    size_t subgraph_index_;\n\npublic:\n    /// default constructor\n    const_subgraph_iterator(void) :\n    random_itr_(nullptr) ,\n    subgraph_(nullptr)   ,\n    subgraph_index_(0)\n    { }\n    /// default assignment operator\n    void operator=(const const_subgraph_iterator& rhs)\n    {\n        random_itr_      = rhs.random_itr_;\n        subgraph_        = rhs.subgraph_;\n        subgraph_index_  = rhs.subgraph_index_;\n        return;\n    }\n    /*!\n    Create a subgraph iterator starting either at beginning or end of subgraph\n    */\n    const_subgraph_iterator(\n        const const_random_iterator<Addr>&    random_itr , ///< random_itr_\n        const pod_vector<addr_t>*             subgraph   , ///< subgraph_\n        size_t subgraph_index                            ) ///< subgraph_index_\n    :\n    random_itr_      ( &random_itr )       ,\n    subgraph_        ( subgraph )          ,\n    subgraph_index_  ( subgraph_index )\n    {   CPPAD_ASSERT_UNKNOWN(\n            subgraph_index == 0 || subgraph_index == subgraph->size() - 1\n        );\n    }\n    /*!\n    Advance iterator to next operator\n    */\n    const_subgraph_iterator<Addr>& operator++(void)\n    {   ++subgraph_index_;\n        return *this;\n    }\n    /// No correction necessary when using random access to player\n    void correct_before_increment(void)\n    {   return; }\n    /*!\n    Backup iterator to previous operator\n    */\n    const_subgraph_iterator<Addr>& operator--(void)\n    {   --subgraph_index_;\n        return *this;\n    }\n    /*!\n    No correction necessary when using random access to player.\n\n    \\param op_arg\n    not used or modified.\n    */\n    void correct_after_decrement(const addr_t*& op_arg)\n    {   return; }\n    /*!\n    \\brief\n    Get information corresponding to current operator.\n\n    \\param op [out]\n    op code for this operator.\n\n    \\param op_arg [out]\n    pointer to the first argument to this operator.\n\n    \\param var_index [out]\n    index of the last variable (primary variable) for this operator.\n    If there is no primary variable for this operator, var_index\n    is not specified and could have any value.\n    */\n    void op_info(\n        op_code_var&   op         ,\n        const addr_t*& op_arg     ,\n        size_t&        var_index  ) const\n    {   // op\n        size_t op_index = size_t( (*subgraph_)[subgraph_index_] );\n        random_itr_->op_info(op_index, op, op_arg, var_index);\n    }\n    /// current operator index\n    size_t op_index(void)\n    {   return size_t( (*subgraph_)[subgraph_index_] ); }\n};\n\n} } } // BEGIN_CPPAD_LOCAL_PLAY_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/pod_vector.hpp",
    "content": "# ifndef CPPAD_LOCAL_POD_VECTOR_HPP\n# define CPPAD_LOCAL_POD_VECTOR_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# if CPPAD_CSTDINT_HAS_8_TO_64\n# include <cstdint>\n# endif\n# include <cstring>\n# include <algorithm>\n# include <cppad/utility/thread_alloc.hpp>\n# include <cppad/core/cppad_assert.hpp>\n# include <cppad/local/is_pod.hpp>\n\n/*\n{xrst_begin_parent pod_vector dev}\n\nA Template Vector Class That does not construct or destruct Elements\n####################################################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_POD_VECTOR_CLASS\n    // END_POD_VECTOR_CLASS\n}\n\nMember Functions\n****************\nAll the member functions in this class are public.\n\nis_pod\n******\nThe :ref:`is_pod-name` function must return true for this *Type* .\n\n{xrst_end pod_vector}\n*/\n// BEGIN_POD_VECTOR_CLASS\nnamespace CppAD { namespace local {\ntemplate <class Type> class pod_vector\n// END_POD_VECTOR_CLASS\n{\n/*\n{xrst_begin pod_vector_private dev}\n\npod_vector Private Data\n#######################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_PRIVATE\n    // END_PRIVATE\n}\n\nsize\\_\n******\nis the number of elements currently in this vector.\n\ncapacity\\_\n**********\nis the maximum number of elements that the current allocation can hold.\nIt is always greater than or equal size\\_ .\nThe only operations that can decrease the capacity are\n:ref:`pod_vector_vector@swap` and :ref:`pod_vector_resize@clear` .\n\ndata\\_\n******\nis a pointer to the first element of the vector.\nThis is the null pointer when capacity\\_ is zero.\n\n{xrst_end pod_vector_private}\n*/\n// BEGIN_PRIVATE\nprivate:\n    size_t size_;\n    size_t capacity_;\n    Type   *data_;\n// END_PRIVATE\n// ---------------------------------------------------------------------------\npublic:\n// ---------------------------------------------------------------------------\n/*\n{xrst_begin pod_vector_ctor dev}\n\npod_vector Constructors and Destructor\n######################################\n\nCopy\n****\n{xrst_literal\n    // BEGIN_COPY_CTOR\n    // END_COPY_CTOR\n}\nThis constructor cannot be used.\n\nDefault\n*******\n{xrst_literal\n    // BEGIN_DEFAULT_CTOR\n    // END_DEFAULT_CTOR\n}\nThis constructor sets the size and capacity to zero.\n\nSize\n****\n{xrst_literal\n    // BEGIN_SIZE_CTOR\n    // END_SIZE_CTOR\n}\nThis constructor sets the size (capacity) equal *n*\n( greater that or equal *n* ).\n\nDestructor\n**********\n{xrst_literal\n    // BEGIN_DESTRUCTOR\n    // END_DESTRUCTOR\n}\nThe memory is returned using :ref:`ta_return_memory-name` .\n\n\n{xrst_end pod_vector_ctor}\n*/\n    // BEGIN_COPY_CTOR\n    pod_vector(const pod_vector&) = delete;\n    // END_COPY_CTOR\n\n    // BEGIN_DEFAULT_CTOR\n    pod_vector(void)\n    // END_DEFAULT_CTOR\n    : size_(0), capacity_(0), data_(nullptr)\n    {  CPPAD_ASSERT_UNKNOWN( is_pod<Type>() );\n    }\n\n    // BEGIN_SIZE_CTOR\n    pod_vector(size_t n)\n    // END_SIZE_CTOR\n    : size_(0), capacity_(0), data_(nullptr)\n    {  CPPAD_ASSERT_UNKNOWN( is_pod<Type>() );\n        extend(n);\n    }\n\n    // BEGIN_DESTRUCTOR\n    ~pod_vector(void)\n    // END_DESTRUCTOR\n    {  if( capacity_ > 0 )\n        {\n            void* v_ptr = reinterpret_cast<void*>( data_ );\n            thread_alloc::return_memory(v_ptr);\n        }\n    }\n/*\n------------------------------------------------------------------------------\n{xrst_begin pod_vector_state dev}\n\nThe Current State of a pod_vector\n#################################\n\nsize\n****\n{xrst_literal\n    // BEGIN_SIZE_STATE\n    // END_SIZE_STATE\n}\n\ncapacity\n********\n{xrst_literal\n    // BEGIN_CAPACITY_STATE\n    // END_CAPACITY_STATE\n}\n\ndata\n****\n{xrst_literal\n    // BEGIN_DATA_STATE\n    // END_DATA_STATE\n}\nThis pointer is no longer valid after the following operations:\nextend, resize, clear, assignment, destructor.\n\n{xrst_end pod_vector_state}\n*/\n\n    // BEGIN_SIZE_STATE\n    size_t size(void) const\n    {  return size_; }\n    // END_SIZE_STATE\n\n    // BEGIN_CAPACITY_STATE\n    size_t capacity(void) const\n    {  return capacity_; }\n    // END_CAPACITY_STATE\n\n    // BEGIN_DATA_STATE\n    Type* data(void)\n    {  return data_; }\n    const Type* data(void) const\n    {  return data_; }\n    // END_DATA_STATE\n\n/*\n------------------------------------------------------------------------------\n{xrst_begin pod_vector_element dev}\n\nAccess and Change an Element of a pod_vector\n############################################\n\nNot Constant\n************\n{xrst_literal\n    // BEGIN_ELEMENT\n    // END_ELEMENT\n}\nThis accesses the element at the specified index\n(in a way that allows the element's value to be changed).\nAn assert is generated the index is greater than or equal to\n`size_`` for this vector.\n\nConstant\n********\n{xrst_literal\n    // BEGIN_CONST_ELEMENT\n    // END_CONST_ELEMENT\n}\nThis accesses the element at the specified index\n(in a way that does not allow the element's value to be changed).\nAn assert is generated the index is greater than or equal to\n`size_`` for this vector.\n\npush_back\n*********\n{xrst_literal\n    // BEGIN_PUSH_BACK\n    // END_PUSH_BACK\n}\nThis increases the size by one and places the specified element\nat the end (highest valid index) of the vector.\n\n{xrst_end pod_vector_element}\n*/\n    // BEGIN_ELEMENT\n    template <class Index>\n    Type& operator[](Index index)\n    // END_ELEMENT\n    {  CPPAD_ASSERT_UNKNOWN( size_t(index)  < size_ );\n        return data_[index];\n    }\n    // BEGIN_CONST_ELEMENT\n    template <class Index>\n    const Type& operator[](Index index) const\n    // END_CONST_ELEMENT\n    {  CPPAD_ASSERT_UNKNOWN( size_t(index)  < size_ );\n        return data_[index];\n    }\n    // BEGIN_PUSH_BACK\n    void push_back(const Type& element)\n    // END_PUSH_BACK\n    {  size_t i = extend(1);\n        data_[i] = element;\n    }\n/*\n-------------------------------------------------------------------------------\n{xrst_begin pod_vector_vector dev}\n\npod_vector Operations With Vector Arguments\n###########################################\n\nswap\n****\n{xrst_literal\n    // BEGIN_SWAP\n    // END_SWAP\n}\nThis exchanges this all the information in this vector with another vector.\nIt is faster that assignment because it does not allocate or free memory and\ndoes not do any element by element operations.\n\nAssignment\n**********\n{xrst_literal\n    // BEGIN_ASSIGNMENT\n    // END_ASSIGNMENT\n}\nThis copies all the information from the other vector to this vector.\nIt copies each element from other and it may free and allocate memory.\n\n{xrst_end pod_vector_vector}\n*/\n    // BEGIN_SWAP\n    void swap(pod_vector& other)\n    // END_SWAP\n    {   std::swap(capacity_,      other.capacity_);\n        std::swap(size_,          other.size_);\n        std::swap(data_,          other.data_);\n    }\n    // BEGIN_ASSIGNMENT\n    void operator=(const pod_vector& other)\n    // END_ASSIGNMENT\n    {   resize( other.size_ );\n        if( size_ > 0 )\n        {   size_t bytes      = size_ * sizeof(Type);\n            void* v_ptr       = reinterpret_cast<void*>( data_ );\n            void* v_ptr_other = reinterpret_cast<void*>( other.data_ );\n            std::memcpy(v_ptr, v_ptr_other, bytes);\n        }\n    }\n/*\n-------------------------------------------------------------------------------\n{xrst_begin pod_vector_resize dev}\n\nChanging the Size of a pod_vector\n#################################\n\nextent\n******\n{xrst_literal\n    // BEGIN_EXTEND\n    // END_EXTEND\n}\n#. This increases the size of the vector by *n* .\n#. It returns the size before the increase\n   which is the index of the first new element added to the vector.\n#. All of the elements in the vector, before the extension,\n   are preserved by this operation.\n\nresize\n******\n{xrst_literal\n    // BEGIN_RESIZE\n    // END_RESIZE\n}\n#. This changes the size of the vector to *n* .\n#. If on input, *n* is less that or equal :ref:`pod_vector_private@capacity\\_` ,\n   all the elements in the vector, before the extension,\n   are preserved by this operation.\n#. If on input, *n* is greater than capacity\\_ ,\n   the elements in the vector are lost.\n\nclear\n*****\n{xrst_literal\n    // BEGIN_CLEAR\n    // END_CLEAR\n}\nThis sets the size and capacity for the vector to zero\nand frees all the memory that it was using.\n\n\n{xrst_end pod_vector_resize}\n*/\n    // BEGIN_EXTEND\n    size_t extend(size_t n)\n    // END_EXTEND\n    {   size_t old_size   = size_;\n        size_              += n;\n\n        // check if we can use current memory\n        if( size_ <= capacity_ )\n            return old_size;\n\n        // save more old information\n        size_t old_capacity = capacity_;\n        void* old_v_ptr     = reinterpret_cast<void*>(data_);\n\n        // get new memory and set capacity\n        size_t byte_capacity;\n        size_t bytes = size_ * sizeof(Type);\n        void* v_ptr  = thread_alloc::get_memory(bytes, byte_capacity);\n        capacity_    = byte_capacity / sizeof(Type);\n        data_        = reinterpret_cast<Type*>(v_ptr);\n\n        // copy old data to new\n        if( old_size >  0 )\n            std::memcpy(v_ptr, old_v_ptr, old_size * sizeof(Type));\n\n        // return old memory to available pool\n        if( old_capacity > 0 )\n            thread_alloc::return_memory(old_v_ptr);\n\n        // return value for extend(n) is the old length\n        CPPAD_ASSERT_UNKNOWN( size_ <= capacity_ );\n        return old_size;\n    }\n    // BEGIN_RESIZE\n    void resize(size_t n)\n    // END_RESIZE\n    {   size_      = n;\n\n        // check if we must allocate new memory\n        if( capacity_ < size_ )\n        {   void* v_ptr;\n            //\n            if( capacity_ > 0 )\n            {   // return old memory to available pool\n                v_ptr = reinterpret_cast<void*>( data_ );\n                thread_alloc::return_memory(v_ptr);\n            }\n            //\n            // get new memory and set capacity\n            size_t byte_capacity;\n            size_t bytes = size_ * sizeof(Type);\n            v_ptr        = thread_alloc::get_memory(bytes, byte_capacity);\n            capacity_    = byte_capacity / sizeof(Type);\n            data_        = reinterpret_cast<Type*>(v_ptr);\n            //\n        }\n        CPPAD_ASSERT_UNKNOWN( size_ <= capacity_ );\n    }\n    // BEGIN_CLEAR\n    void clear(void)\n    // END_CLEAR\n    {   if( capacity_ > 0 )\n        {\n            void* v_ptr = reinterpret_cast<void*>( data_ );\n            thread_alloc::return_memory(v_ptr);\n        }\n        data_        = nullptr;\n        capacity_    = 0;\n        size_        = 0;\n    }\n};\n// ---------------------------------------------------------------------------\n/*!\nA vector class with that does not use element constructors or destructors\nwhen is_pod<Type> is true.\n*/\ntemplate <class Type>\nclass pod_vector_maybe {\nprivate:\n    /// maximum number of Type elements current allocation can hold\n    size_t capacity_;\n\n    /// number of elements currently in this vector\n    size_t length_;\n\n    /// pointer to the first type elements\n    /// (not defined and should not be used when capacity_ = 0)\n    Type   *data_;\n\n    /// do not use the copy constructor\n    explicit pod_vector_maybe(const pod_vector_maybe& )\n    {   CPPAD_ASSERT_UNKNOWN(false); }\npublic:\n    /// default constructor sets capacity_ = length_ = data_ = 0\n    pod_vector_maybe(void)\n    : capacity_(0), length_(0), data_(nullptr)\n    {   CPPAD_ASSERT_UNKNOWN( is_pod<size_t>() );\n    }\n\n    /// sizing constructor\n    pod_vector_maybe(\n        /// number of elements in this vector\n        size_t n )\n    : capacity_(0), length_(0), data_(nullptr)\n    {   extend(n); }\n\n\n    /// Destructor: returns allocated memory to thread_alloc;\n    /// see extend and resize.  If this is not plain old data,\n    /// the destructor for each element is called.\n    ~pod_vector_maybe(void)\n    {   if( capacity_ > 0 )\n        {   if( ! is_pod<Type>() )\n            {   // call destructor for each element\n                for(size_t i = 0; i < capacity_; i++)\n                    (data_ + i)->~Type();\n            }\n            void* v_ptr = reinterpret_cast<void*>( data_ );\n            thread_alloc::return_memory(v_ptr);\n        }\n    }\n\n    /// current number of elements in this vector.\n    size_t size(void) const\n    {   return length_; }\n\n    /// current capacity (amount of allocated storage) for this vector.\n    size_t capacity(void) const\n    {   return capacity_; }\n\n    /// current data pointer is no longer valid after any of the following:\n    /// extend, resize, erase, clear, assignment, and destructor.\n    Type* data(void)\n    {   return data_; }\n\n    /// const version of data pointer (see non-const documentation)\n    const Type* data(void) const\n    {   return data_; }\n    // ----------------------------------------------------------------------\n    /// non-constant element access; i.e., we can change this element value\n    Type& operator[](\n        /// element index, must be less than length\n        size_t i\n    )\n    {   CPPAD_ASSERT_UNKNOWN( i < length_ );\n        return data_[i];\n    }\n    /// non-constant element access; i.e., we can change this element value\n    template <class Index>\n    Type& operator[](\n        /// element index, must be less than length and convertible to size_t\n        Index i\n    )\n    {   return (*this)[size_t(i)]; }\n\n    // ----------------------------------------------------------------------\n    /// constant element access; i.e., we cannot change this element value\n    const Type& operator[](\n        /// element index, must be less than length\n        size_t i\n    ) const\n    {   CPPAD_ASSERT_UNKNOWN( i < length_ );\n        return data_[i];\n    }\n    /// constant element access; i.e., we cannot change this element value\n    template <class Index>\n    const Type& operator[](\n        /// element index, must be less than length and convertible to size_t\n        Index i\n    ) const\n    {   return (*this)[size_t(i)]; }\n\n    // ----------------------------------------------------------------------\n    /*!\n    Add an element to theh back of this vector\n\n    \\param e\n    is the element we are adding to the back of the vector.\n    */\n    void push_back(const Type& e)\n    {   size_t i = extend(1);\n        data_[i] = e;\n    }\n\n    /*!\n    Swap all properties of this vector with another.\n    This is useful when moving a vector that grows after it has reached\n    its final size (without copying every element).\n\n    \\param other\n    is the other vector that we are swapping this vector with.\n    */\n    void swap(pod_vector_maybe& other)\n    {   std::swap(capacity_, other.capacity_);\n        std::swap(length_,   other.length_);\n        std::swap(data_,     other.data_);\n    }\n    // ----------------------------------------------------------------------\n    /*!\n    Increase the number of elements the end of this vector\n    (existing elements are always preserved).\n\n    \\param n\n    is the number of elements to add to end of this vector.\n\n    \\return\n    is the number of elements in the vector before it was extended.\n    This is the index of the first new element added to the vector.\n\n    - If Type is plain old data, new elements are not initialized;\n    i.e., their constructor is not called. Otherwise, the constructor\n    is called for each new element.\n\n    - This and resize are the only routine that allocate memory for\n    pod_vector_maybe. They uses thread_alloc for this allocation.\n    */\n    size_t extend(size_t n)\n    {   size_t old_length   = length_;\n        length_            += n;\n\n        // check if we can use current memory\n        if( length_ <= capacity_ )\n            return old_length;\n\n        // save more old information\n        size_t old_capacity = capacity_;\n        Type* old_data      = data_;\n\n        // get new memory and set capacity\n        size_t length_bytes = length_ * sizeof(Type);\n        size_t capacity_bytes;\n        void* v_ptr = thread_alloc::get_memory(length_bytes, capacity_bytes);\n        capacity_   = capacity_bytes / sizeof(Type);\n        data_       = reinterpret_cast<Type*>(v_ptr);\n\n        if( ! is_pod<Type>() )\n        {   // call constructor for each new element\n            for(size_t i = 0; i < capacity_; i++)\n                new(data_ + i) Type();\n        }\n\n        // copy old data to new\n        for(size_t i = 0; i < old_length; i++)\n            data_[i] = old_data[i];\n\n        // return old memory to available pool\n        if( old_capacity > 0 )\n        {   if( ! is_pod<Type>() )\n            {   for(size_t i = 0; i < old_capacity; i++)\n                    (old_data + i)->~Type();\n            }\n            v_ptr = reinterpret_cast<void*>( old_data );\n            thread_alloc::return_memory(v_ptr);\n        }\n\n        // return value for extend(n) is the old length\n        CPPAD_ASSERT_UNKNOWN( length_ <= capacity_ );\n        return old_length;\n    }\n    // ----------------------------------------------------------------------\n    /*!\n    resize the vector (existing elements preserved when n <= capacity_).\n\n    \\param n\n    is the new size for this vector.\n\n    \\par\n    if n <= capacity(), no memory is freed or allocated, the capacity\n    is not changed, and existing elements are preserved.\n    If n > capacity(), new memory is allocates and all the\n    data in the vector is lost.\n\n    - If  Type is plain old data, new elements are not initialized;\n    i.e., their constructor is not called. Otherwise, the constructor\n    is called for each new element.\n\n    - This and extend are the only routine that allocate memory for\n    pod_vector_maybe. They uses thread_alloc for this allocation.\n    */\n    void resize(size_t n)\n    {   length_ = n;\n\n        // check if we must allocate new memory\n        if( capacity_ < length_ )\n        {   void* v_ptr;\n            //\n            // return old memory to available pool\n            if( capacity_ > 0 )\n            {   if( ! is_pod<Type>() )\n                {   // call destructor for each old element\n                    for(size_t i = 0; i < capacity_; i++)\n                        (data_ + i)->~Type();\n                }\n                v_ptr = reinterpret_cast<void*>( data_ );\n                thread_alloc::return_memory(v_ptr);\n            }\n            //\n            // get new memory and set capacity\n            size_t length_bytes = length_ * sizeof(Type);\n            size_t capacity_bytes;\n            v_ptr     = thread_alloc::get_memory(length_bytes, capacity_bytes);\n            capacity_ = capacity_bytes / sizeof(Type);\n            data_     = reinterpret_cast<Type*>(v_ptr);\n            //\n            CPPAD_ASSERT_UNKNOWN( length_ <= capacity_ );\n            //\n            if( ! is_pod<Type>() )\n            {   // call constructor for each new element\n                for(size_t i = 0; i < capacity_; i++)\n                    new(data_ + i) Type();\n            }\n        }\n    }\n    // ----------------------------------------------------------------------\n    /*!\n    Remove all the elements from this vector and free its memory.\n    */\n    void clear(void)\n    {   if( capacity_ > 0 )\n        {   if( ! is_pod<Type>() )\n            {   // call destructor for each element\n                for(size_t i = 0; i < capacity_; i++)\n                    (data_ + i)->~Type();\n            }\n            void* v_ptr = reinterpret_cast<void*>( data_ );\n            thread_alloc::return_memory(v_ptr);\n        }\n        data_     = nullptr;\n        capacity_ = 0;\n        length_   = 0;\n    }\n    // -----------------------------------------------------------------------\n    /// vector assignment operator\n    void operator=(\n        /// right hand size of the assignment operation\n        const pod_vector_maybe& x\n    )\n    {   resize( x.length_ );\n        //\n        CPPAD_ASSERT_UNKNOWN( length_   == x.length_ );\n        for(size_t i = 0; i < length_; i++)\n        {   data_[i] = x.data_[i]; }\n    }\n};\n\n} } // END_CPPAD_LOCAL_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/local/record/comp_op.hpp",
    "content": "# ifndef CPPAD_LOCAL_RECORD_COMP_OP_HPP\n# define CPPAD_LOCAL_RECORD_COMP_OP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/local/record/recorder.hpp>\n\nnamespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE\n/*\n{xrst_begin recorder_put_comp_op dev}\n{xrst_spell\n    aleft\n    dyn\n    taddr\n}\n\nPut Compare Operators in Recording\n##################################\n\nSyntax\n******\n| *rec* . ``put_comp_`` *rel* ( *aleft* , *aright* , *result* )\n\nrel\n===\nThe text *rel* in the function name above\nis ``eq`` (for equals),\n``le`` (for less than or equal), or\n``lt`` (for less than).\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_COMP_EQ\n    // END_COMP_EQ\n}\nThe other prototypes for the functions ``comp_le`` and ``comp_lt``\nare same except for the function name.\n\nvar_left\n********\nis true if the left operand is a variable.\n\nvar_right\n*********\nis true if the right operand is a variable.\n\ndyn_left\n********\nis true if the left operand is a dynamic parameter.\n\ndyn_right\n*********\nis true if the right operand is a dynamic parameter.\n\naleft\n*****\nis the compare operator left operand.\n\naright\n******\nis the compare operator right operand.\n\ntaddr\\_\n*******\nThe values *aleft.taddr_* and *aright* . ``taddr_``\nare the proper address for dynamic parameters and variables\nand does not matter for constants.\n\nvalue\\_\n*******\nThe values *aleft.value_* and *aright* . ``value_``\nare the proper address for constants and does not matter\nfor variables and dynamic parameters.\n\nresult\n******\nThis is the result for this comparison corresponding to this\nrecording (sequence of operations).\n\n{xrst_end recorder_put_comp_op}\n*/\n// BEGIN_COMP_EQ\ntemplate <class Base>\nvoid recorder<Base>::comp_eq(\n    bool                        var_left     ,\n    bool                        var_right    ,\n    bool                        dyn_left     ,\n    bool                        dyn_right    ,\n    const AD<Base>&             aleft        ,\n    const AD<Base>&             aright       ,\n    bool                        result       )\n// END_COMP_EQ\n{   if( var_left )\n    {   if( var_right )\n        {   // variable == variable\n            PutArg(aleft.taddr_, aright.taddr_);\n            if( result )\n                PutOp(EqvvOp);\n            else\n                PutOp(NevvOp);\n        }\n        else\n        {   // variable == parameter\n            addr_t p = aright.taddr_;\n            if( ! dyn_right )\n                p = put_con_par(aright.value_);\n            PutArg(p, aleft.taddr_);\n            if( result )\n                PutOp(EqpvOp);\n            else\n                PutOp(NepvOp);\n        }\n    }\n    else if ( var_right )\n    {   // parameter == variable\n        addr_t p = aleft.taddr_;\n        if( ! dyn_left )\n            p = put_con_par(aleft.value_);\n        PutArg(p, aright.taddr_);\n        if( result )\n            PutOp(EqpvOp);\n        else\n            PutOp(NepvOp);\n    }\n    else if( dyn_left | dyn_right )\n    {   // parameter == parameter\n        addr_t arg0 = aleft.taddr_;\n        addr_t arg1 = aright.taddr_;\n        if( ! dyn_left )\n            arg0 = put_con_par(aleft.value_);\n        if( ! dyn_right )\n            arg1 = put_con_par(aright.value_);\n        //\n        PutArg(arg0, arg1);\n        if( result )\n            PutOp(EqppOp);\n        else\n            PutOp(NeppOp);\n    }\n}\n// ---------------------------------------------------------------------------\n// comp_le\ntemplate <class Base>\nvoid recorder<Base>::comp_le(\n    bool                        var_left     ,\n    bool                        var_right    ,\n    bool                        dyn_left     ,\n    bool                        dyn_right    ,\n    const AD<Base>&             aleft        ,\n    const AD<Base>&             aright       ,\n    bool                        result       )\n{\n    if( var_left )\n    {   if( var_right )\n        {   // variable <= variable\n            if( result )\n            {   PutOp(LevvOp);\n                PutArg(aleft.taddr_, aright.taddr_);\n            }\n            else\n            {   PutOp(LtvvOp);\n                PutArg(aright.taddr_, aleft.taddr_);\n            }\n        }\n        else\n        {   // variable <= parameter\n            addr_t p = aright.taddr_;\n            if( ! dyn_right )\n                p = put_con_par(aright.value_);\n            if( result )\n            {   PutOp(LevpOp);\n                PutArg(aleft.taddr_, p);\n            }\n            else\n            {   PutOp(LtpvOp);\n                PutArg(p, aleft.taddr_);\n            }\n        }\n    }\n    else if ( var_right )\n    {   // parameter <= variable\n        addr_t p = aleft.taddr_;\n        if( ! dyn_left )\n            p = put_con_par(aleft.value_);\n        if( result )\n        {   PutOp(LepvOp);\n            PutArg(p, aright.taddr_);\n        }\n        else\n        {   PutOp(LtvpOp);\n            PutArg(aright.taddr_, p);\n        }\n    }\n    else if( dyn_left | dyn_right )\n    {   // parameter <= parameter\n        addr_t arg0 = aleft.taddr_;\n        addr_t arg1 = aright.taddr_;\n        if( ! dyn_left )\n            arg0 = put_con_par(aleft.value_);\n        if( ! dyn_right )\n            arg1 = put_con_par(aright.value_);\n        //\n        if( result )\n        {   PutOp(LeppOp);\n            PutArg(arg0, arg1);\n        }\n        else\n        {   PutOp(LtppOp);\n            PutArg(arg1, arg0);\n        }\n    }\n}\n// --------------------------------------------------------------------------\n// comp_lt\ntemplate <class Base>\nvoid recorder<Base>::comp_lt(\n    bool                        var_left     ,\n    bool                        var_right    ,\n    bool                        dyn_left     ,\n    bool                        dyn_right    ,\n    const AD<Base>&             aleft        ,\n    const AD<Base>&             aright       ,\n    bool                        result       )\n{\n    if( var_left )\n    {   if( var_right )\n        {   // variable < variable\n            if( result )\n            {   PutOp(LtvvOp);\n                PutArg(aleft.taddr_, aright.taddr_);\n            }\n            else\n            {   PutOp(LevvOp);\n                PutArg(aright.taddr_, aleft.taddr_);\n            }\n        }\n        else\n        {   // variable < parameter\n            addr_t p = aright.taddr_;\n            if( ! dyn_right )\n                p = put_con_par(aright.value_);\n            if( result )\n            {   PutOp(LtvpOp);\n                PutArg(aleft.taddr_, p);\n            }\n            else\n            {   PutOp(LepvOp);\n                PutArg(p, aleft.taddr_);\n            }\n        }\n    }\n    else if ( var_right )\n    {   // parameter < variable\n        addr_t p = aleft.taddr_;\n        if( ! dyn_left )\n            p = put_con_par(aleft.value_);\n        if( result )\n        {   PutOp(LtpvOp);\n            PutArg(p, aright.taddr_);\n        }\n        else\n        {   PutOp(LevpOp);\n            PutArg(aright.taddr_, p);\n        }\n    }\n    else if( dyn_left | dyn_right )\n    {   // parameter < parameter\n        addr_t arg0 = aleft.taddr_;\n        addr_t arg1 = aright.taddr_;\n        if( ! dyn_left )\n            arg0 = put_con_par(aleft.value_);\n        if( ! dyn_right )\n            arg1 = put_con_par(aright.value_);\n        //\n        if( result )\n        {   PutOp(LtppOp);\n            PutArg(arg0, arg1);\n        }\n        else\n        {   PutOp(LeppOp);\n            PutArg(arg1, arg0);\n        }\n    }\n}\n} } // END_CPPAD_LOCAL_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/local/record/cond_exp.hpp",
    "content": "# ifndef CPPAD_LOCAL_RECORD_COND_EXP_HPP\n# define CPPAD_LOCAL_RECORD_COND_EXP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/local/record/recorder.hpp>\n\nnamespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE\n/*\n{xrst_begin recorder_cond_exp dev}\n\nRecord a Variable or Dynamic Parameter Conditional Expression\n#############################################################\n\nSyntax\n******\n| *rec* . ``cond_exp`` (\n| |tab| *tape_id* , *cop* , *result* , *left* , *right* , *if_true* , *if_false*\n| )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_COND_EXP\n    // END_COND_EXP\n}\n\ntape_id\n*******\nidentifier for the tape that this operation is being recorded on.\nPassing tape_id avoids having to call tape_ptr() in case where\nleft, right, if_true, and if_false are all be constant at this AD level\n(but left and right are not identically constant).\n\ncop\n***\nWhich :ref:`comparison operator<base_cond_exp@CompareOp>` ;\ni.e., <, <=, ==, >=, >, or !=.\n\nresult\n******\nis the result for this operation conditional expression.\nOn input, *result* . ``value_`` is the proper value and\nthe other fields do not matter.\nUpon return, the other fields have been set to their proper values.\nIt is an error to call this routine when all the arguments are constants; i.e.,\nwhen the result is a constant.\n\nleft\n****\nvalue of the left operand in the comparison.\nIf *left* . ``tape_id_`` is not zero it must equal *tape_id* .\n\nright\n*****\nvalue of the right operand in the comparison.\nIf *right* . ``tape_id_`` is not zero it must equal *tape_id* .\n\nif_true\n*******\nvalue of the result if the comparison value is true.\nIf *if_true* . ``tape_id_`` is not zero it must equal *tape_id* .\n\nif_false\n********\nvalue of the result if the comparison value is false.\nIf *if_false* . ``tape_id_`` is not zero it must equal *tape_id* .\n\n{xrst_end recorder_cond_exp}\n*/\n// BEGIN_COND_EXP\ntemplate <class Base>\nvoid recorder<Base>::cond_exp(\n    tape_id_t       tape_id     ,\n    enum CompareOp  cop         ,\n    AD<Base>       &result      ,\n    const AD<Base> &left        ,\n    const AD<Base> &right       ,\n    const AD<Base> &if_true     ,\n    const AD<Base> &if_false    )\n// END_COND_EXP\n{   // check for invalid tape_id\n    CPPAD_ASSERT_UNKNOWN( tape_id != 0 );\n\n    // arg[0] = cop\n    addr_t arg0 = addr_t( cop );\n\n    // arg[1] = base 2 representation of the value\n    // [Var(left), Var(right), Var(if_true), Var(if_false)]\n    addr_t arg1 = 0;\n\n    // arg[2] = left address\n    // set first bit in arg1\n    addr_t arg2 = left.taddr_;\n    if( Constant(left) )\n        arg2 = put_con_par(left.value_);\n    else\n    {   CPPAD_ASSERT_KNOWN( tape_id == left.tape_id_ ,\n        \"CondExpRel: arguments are variables or dynamics for different thread\"\n        );\n        if(left.ad_type_ != dynamic_enum)\n            arg1 += 1;\n    }\n\n    // arg[3] = right address\n    // set second bit in arg1\n    addr_t arg3 = right.taddr_;\n    if( Constant(right) )\n        arg3 = put_con_par(right.value_);\n    else\n    {   CPPAD_ASSERT_KNOWN( tape_id == right.tape_id_ ,\n        \"CondExpRel: arguments are variables or dynamics for different thread\"\n        );\n        if(right.ad_type_ != dynamic_enum)\n            arg1 += 2;\n    }\n\n    // arg[4] = if_true address\n    // set third bit in arg1\n    addr_t arg4 = if_true.taddr_;\n    if( Constant(if_true) )\n        arg4 = put_con_par(if_true.value_);\n    else\n    {   CPPAD_ASSERT_KNOWN( tape_id == if_true.tape_id_ ,\n        \"CondExpRel: arguments are variables or dynamics for different thread\"\n        );\n        if(if_true.ad_type_ != dynamic_enum)\n            arg1 += 4;\n    }\n\n    // arg[5] =  if_false address\n    // set fourth bit in arg1\n    addr_t arg5 = if_false.taddr_;\n    if( Constant(if_false) )\n        arg5 = put_con_par(if_false.value_);\n    else\n    {   CPPAD_ASSERT_KNOWN( tape_id == if_false.tape_id_ ,\n        \"CondExpRel: arguments are variables or dynamics for different thread\"\n        );\n        if(if_false.ad_type_ != dynamic_enum)\n            arg1 += 8;\n    }\n    if( arg1 == 0 )\n    {   // none of the arguments are variables, record cond_exp_dyn\n\n        // put the result at the end of the parameter vector as dynamic\n        // put_dyn_cond_exp(par, cop, left, right, if_true, if_false)\n        result.taddr_   = put_dyn_cond_exp(\n            result.value_, CompareOp(arg0), arg2, arg3, arg4, arg5\n        );\n        result.ad_type_ = dynamic_enum;\n        result.tape_id_ = tape_id;\n\n        // check that result is a dynamic parameter\n        CPPAD_ASSERT_UNKNOWN( Dynamic(result) );\n    }\n    else\n    {   CPPAD_ASSERT_UNKNOWN( NumArg(CExpOp) == 6 );\n        CPPAD_ASSERT_UNKNOWN( NumRes(CExpOp) == 1 );\n\n        // put operator in tape\n        result.taddr_ = PutOp(CExpOp);\n        PutArg(arg0, arg1, arg2, arg3, arg4, arg5);\n\n        // make result a variable\n        CPPAD_ASSERT_UNKNOWN( result.ad_type_ == constant_enum );\n        result.ad_type_ = variable_enum;\n        result.tape_id_ = tape_id;\n\n        // check that result is a variable\n        CPPAD_ASSERT_UNKNOWN( Variable(result) );\n    }\n}\n} } // END_CPPAD_LOCAL_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/local/record/dyn_recorder.hpp",
    "content": "# ifndef CPPAD_LOCAL_RECORD_DYN_RECORDER_HPP\n# define CPPAD_LOCAL_RECORD_DYN_RECORDER_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/core/hash_code.hpp>\n# include <cppad/local/pod_vector.hpp>\n# include <cppad/core/ad_type.hpp>\n/*\n-- ----------------------------------------------------------------------------\n{xrst_begin_parent dyn_recorder dev}\n\nClass That Records a Dynamic Parameter Operation Sequence\n#########################################################\n\ndyn_record\n**********\n{xrst_literal ,\n    // BEGIN_CLASS , // END_CLASS\n    // BEGIN_DYN_RECORD , // END_DYN_RECORD\n}\n\nset_n_dyn_independent\n*********************\n{xrst_literal\n    // BEGIN_SET_NUM_DYNAMIC_IND\n    // END_SET_NUM_DYNAMIC_IND\n}\n\nn_dyn_independent\n*****************\n{xrst_literal\n    // BEGIN_N_DYN_INDEPENDENT\n    // END_N_DYN_INDEPENDENT\n}\n\npar_all\n*******\n{xrst_literal\n    // BEGIN_PAR_ALL\n    // END_PAR_ALL\n}\n\nmemory\n******\n{xrst_literal\n    // BEGIN_MEMORY\n    // END_MEMORY\n}\n\n\n{xrst_end dyn_recorder}\n*/\n// BEGIN_CPPAD_LOCAL_NAMESPACE\n// BEGIN_CLASS\nnamespace CppAD { namespace local {\ntemplate <class Base> class dyn_recorder {\n// END_CLASS\n    //\n    // friend\n    friend class dyn_player<Base>;\n//\nprivate:\n    //\n    // n_dyn_independent_\n    // Number of dynamic parameters in the recording\n    size_t n_dyn_independent_;\n    //\n    // all_dyn_vec_ind_;\n    // The VecAD indices in the recording.\n    pod_vector<addr_t> dyn_vecad_ind_;\n    //\n    // par_hash_table_\n    // Hash table to reduced number of duplicate parameters in par_all_\n         pod_vector<addr_t> par_hash_table_;\n    //\n    // par_all_;\n    // Vector containing all the parameters in the recording.\n    // Use pod_vector_maybe because Base may not be plain old data.\n    pod_vector_maybe<Base> par_all_;\n    //\n    // par_is_dyn_\n    // Which elements of par_all_ are dynamic parameters\n    // (same size are par_all_)\n    pod_vector<bool> par_is_dyn_;\n    //\n    // dyn_par_op_\n    // operators for just the dynamic parameters in par_all_\n         pod_vector<opcode_t> dyn_par_op_;\n    //\n    // dyn_par_arg_\n    // arguments for the dynamic parameter operators\n    pod_vector<addr_t> dyn_par_arg_;\n//\npublic:\n    // BEGIN_DYN_RECORD\n    // dyn_recorder<Base> dyn_record\n    dyn_recorder(void)\n    // END_DYN_RECORD\n    : n_dyn_independent_(0)\n    , par_hash_table_( CPPAD_HASH_TABLE_SIZE )\n    {  //\n        // par_hash_table_\n        // It does not matter if uninitialized hash codes match but this\n        // initilaization is here to avoid valgrind warnings.\n        void*  ptr   = static_cast<void*>( par_hash_table_.data() );\n        int    value = 0;\n        size_t num   = CPPAD_HASH_TABLE_SIZE * sizeof(addr_t);\n        std::memset(ptr, value, num);\n    }\n    //\n    // Destructor\n    ~dyn_recorder(void)\n    { }\n    //\n    // BEGIN_SET_NUM_DYNAMIC_IND\n    // dyn_record.set_n_dyn_independent(n_dyn_independent)\n    void set_n_dyn_independent(size_t n_dyn_independent)\n    // END_SET_NUM_DYNAMIC_IND\n    {  n_dyn_independent_ = n_dyn_independent; }\n    //\n    // BEGIN_N_DYN_INDEPENDENT\n    // n_dyn_independent = dyn_record.n_dyn_independent()\n    size_t n_dyn_independent(void) const\n    // END_N_DYN_INDEPENDENT\n    {  return n_dyn_independent_; }\n    //\n    // put_dyn_par\n    addr_t put_dyn_par(\n        const Base &par, op_code_dyn op\n    );\n    addr_t put_dyn_par(\n        const Base &par, op_code_dyn op, addr_t a0\n    );\n    addr_t put_dyn_par(\n        const Base &par, op_code_dyn op, addr_t a0, addr_t a1\n    );\n    //\n    // put_dyn_cond_exp\n    addr_t put_dyn_cond_exp(const Base &par, CompareOp cop,\n        addr_t left, addr_t right, addr_t if_true, addr_t if_false\n    );\n    //\n    // put_dyn_arg_vec\n    void put_dyn_arg_vec(const pod_vector<addr_t>& arg);\n    //\n    // put_con_par\n    addr_t put_con_par(const Base &par);\n    //\n    // put_dyn_atomic\n    template <class VectorAD>\n    void put_dyn_atomic(\n        tape_id_t                   tape_id    ,\n        size_t                      atom_index ,\n        size_t                      call_id    ,\n        const vector<ad_type_enum>& type_x     ,\n        const vector<ad_type_enum>& type_y     ,\n        const VectorAD&             ax         ,\n        VectorAD&                   ay\n    );\n    //\n    // BEGIN_PAR_ALL\n    // par_all = dyn_record.par_all()\n    const pod_vector_maybe<Base>& par_all(void) const\n    {  return par_all_; }\n    // END_PAR_ALL\n    //\n    // BEGIN_MEMORY\n    /// memory = dyn_record.Memory()\n    size_t Memory(void) const\n    // END_MEMORY\n    {  return 0\n            + dyn_vecad_ind_.capacity() * sizeof(addr_t)\n            + par_hash_table_.capacity()    * sizeof(addr_t)\n            + par_all_.capacity()       * sizeof(Base)\n            + par_is_dyn_.capacity()        * sizeof(bool)\n            + dyn_par_op_.capacity()        * sizeof(opcode_t)\n            + dyn_par_arg_.capacity()       * sizeof(addr_t)\n        ;\n    }\n\n};\n/*\n------------------------------------------------------------------------------\n{xrst_begin put_dyn_par dev}\n\nPut a Dynamic Parameter at End of Parameter Vector\n##################################################\n\nSyntax\n******\n| *par_index* = *dyn_record* . ``put_dyn_par`` ( *par* , *op* )\n| *par_index* = *dyn_record* . ``put_dyn_par`` ( *par* , *op* , *a0* )\n| *par_index* = *dyn_record* . ``put_dyn_par`` ( *par* , *op* , *a0* , *a1* )\n\npar\n***\nis value of dynamic parameter to be placed at the end of the\nparameter vector.\n\nop\n**\nis the operator for this dynamic parameter.\n\na0\n**\nis the first argument for this operation.\nIt must be present if :ref:`num_arg_dyn@n_arg` for this\noperator is greater than zero.\n\na1\n**\nis the second argument for this operation.\nIt must be present if :ref:`num_arg_dyn@n_arg` for this\noperator is greater than one.\n\npar_index\n*********\nis the index of this dynamic parameter in the vector of all parameters.\n\nPrototype\n*********\n{xrst_literal ,\n    // BEGIN_PUT_DYN_PAR_0 , // END_PUT_DYN_PAR_0\n    // BEGIN_PUT_DYN_PAR_1 , // END_PUT_DYN_PAR_1\n    // BEGIN_PUT_DYN_PAR_2 , // END_PUT_DYN_PAR_2\n}\n\n{xrst_end put_dyn_par}\n*/\n// BEGIN_PUT_DYN_PAR_0\ntemplate <class Base> addr_t dyn_recorder<Base>::put_dyn_par(\n    const Base &par, op_code_dyn op\n)\n// END_PUT_DYN_PAR_0\n{\n    CPPAD_ASSERT_UNKNOWN(\n        op == ind_dyn || op == result_dyn || op == atom_dyn\n    );\n    CPPAD_ASSERT_UNKNOWN( num_arg_dyn(op) == 0 );\n    par_all_.push_back( par );\n    par_is_dyn_.push_back(true);\n    dyn_par_op_.push_back( opcode_t(op) );\n    return static_cast<addr_t>( par_all_.size() - 1 );\n}\n// BEGIN_PUT_DYN_PAR_1\ntemplate <class Base> addr_t dyn_recorder<Base>::put_dyn_par(\n    const Base &par, op_code_dyn op, addr_t a0\n)\n// END_PUT_DYN_PAR_1\n{\n    CPPAD_ASSERT_UNKNOWN( num_arg_dyn(op) == 1 );\n    par_all_.push_back( par );\n    par_is_dyn_.push_back(true);\n    dyn_par_op_.push_back( opcode_t(op) );\n    dyn_par_arg_.push_back(a0);\n    return static_cast<addr_t>( par_all_.size() - 1 );\n}\n// BEGIN_PUT_DYN_PAR_2\ntemplate <class Base> addr_t dyn_recorder<Base>::put_dyn_par(\n    const Base &par, op_code_dyn op, addr_t a0, addr_t a1\n)\n// END_PUT_DYN_PAR_2\n{\n    CPPAD_ASSERT_UNKNOWN( num_arg_dyn(op) == 2 );\n    par_all_.push_back( par );\n    par_is_dyn_.push_back(true);\n    dyn_par_op_.push_back( opcode_t(op) );\n    dyn_par_arg_.push_back(a0);\n    dyn_par_arg_.push_back(a1);\n    return static_cast<addr_t>( par_all_.size() - 1 );\n}\n/*\n------------------------------------------------------------------------------\n{xrst_begin put_dyn_cond_exp dev}\n\nPut a Conditional Expression Dynamic Parameter at End of Parameter Vector\n#########################################################################\n\nSyntax\n******\n| *par_index* = *dyn_record* . ``put_dyn_cond_exp`` (\n|     *par* , *cop* , *left* , *right* , *if_true* , *if_false*\n| )\n\npar\n***\nis value of dynamic parameter to be placed at the end of the\nparameter vector.\n\ncop\n***\nis the operator comparison operator; i.e., Lt, Le, Eq, Ge, Gt, or Ne.\n\nleft\n****\nis the left argument in conditional expression (which is a parameter).\n\nright\n*****\nis the right argument in conditional expression (which is a parameter).\n\nif_true\n*******\nis the if_true argument in conditional expression (which is a parameter).\n\nif_false\n********\nis the if_false argument in conditional expression (which is a parameter).\n\npar_index\n*********\nis the index of this dynamic parameter in the vector of all parameters.\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_PUT_DYN_COND_EXP\n    // END_PUT_DYN_COND_EXP\n}\n\n{xrst_end put_dyn_cond_exp}\n*/\n// BEGIN_PUT_DYN_COND_EXP\ntemplate <class Base> addr_t dyn_recorder<Base>::put_dyn_cond_exp(\n    const Base &par,\n    CompareOp   cop,\n    addr_t      left,\n    addr_t      right,\n    addr_t      if_true,\n    addr_t      if_false\n)\n// END_PUT_DYN_COND_EXP\n{\n    CPPAD_ASSERT_UNKNOWN( num_arg_dyn(cond_exp_dyn) == 5 );\n    addr_t ret = addr_t( par_all_.size() );\n    par_all_.push_back( par );\n    par_is_dyn_.push_back(true);\n    dyn_par_op_.push_back( opcode_t(cond_exp_dyn) );\n    dyn_par_arg_.push_back( addr_t(cop) );\n    dyn_par_arg_.push_back(left);\n    dyn_par_arg_.push_back(right);\n    dyn_par_arg_.push_back(if_true);\n    dyn_par_arg_.push_back(if_false);\n    return ret;\n}\n/*\n------------------------------------------------------------------------------\n{xrst_begin put_dyn_arg_vec dev}\n\nPut a Vector of Arguments at End of Dynamic Parameter Argument Vector\n#####################################################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_PUT_DYN_ARG_VEC\n    // END_PUT_DYN_ARG_VEC\n}\n\narg_vec\n*******\nis the vector of values to be added at the end of the\ndynamic parameter operator argument vector.\n\n{xrst_end put_dyn_arg_vec}\n*/\n// BEGIN_PUT_DYN_ARG_VEC\n// dyn_record.put_dyn_arg_vec(arg_vec)\ntemplate <class Base>\nvoid dyn_recorder<Base>::put_dyn_arg_vec(const pod_vector<addr_t>& arg_vec)\n// END_PUT_DYN_ARG_VEC\n{  for(size_t i = 0; i < arg_vec.size(); ++i)\n        dyn_par_arg_.push_back( arg_vec[i] );\n}\n/*\n------------------------------------------------------------------------------\n{xrst_begin put_con_par dev}\n\nFind or Add a Constant Parameter to Current Parameter Vector\n############################################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_PUT_CON_PAR\n    // END_PUT_CON_PAR\n}\n\npar\n***\nis the parameter to be found or placed in the vector of parameters.\n\npar_index\n*********\nis the index in the parameter vector corresponding to this parameter value.\nThis value is not necessarily placed at the end of the vector\n(because values that are identically equal may be reused).\n\n\n{xrst_end put_con_par}\n*/\n// BEGIN_PUT_CON_PAR\n// par_index = dyn_record.put_con_par(par)\ntemplate <class Base> addr_t dyn_recorder<Base>::put_con_par(const Base &par)\n// END_PUT_CON_PAR\n{\n# ifndef NDEBUG\n    // index zero is used to signify that a value is not a parameter;\n    // i.e., it is a variable.\n    if( par_all_.size() == 0 )\n        CPPAD_ASSERT_UNKNOWN( CppAD::isnan(par) );\n# endif\n    // ---------------------------------------------------------------------\n    // check for a match with a previous parameter\n    //\n    // get hash code for this value\n    size_t code  = static_cast<size_t>( hash_code(par) );\n\n    // current index in par_all_ corresponding to this hash code\n    size_t index = static_cast<size_t>( par_hash_table_[code] );\n\n    // check if the old parameter matches the new one\n    if( (0 < index) && (index < par_all_.size()) )\n    {   if( ! par_is_dyn_[index] )\n            if( IdenticalEqualCon(par_all_[index], par) )\n                return static_cast<addr_t>( index );\n    }\n    // ---------------------------------------------------------------------\n    // put parameter in par_all_ and replace hash entry for this codee\n    //\n    index = par_all_.size();\n    par_all_.push_back( par );\n    par_is_dyn_.push_back(false);\n    //\n    // change the hash table for this code to point to new value\n    par_hash_table_[code] = static_cast<addr_t>( index );\n    //\n    // return the parameter index\n    CPPAD_ASSERT_KNOWN(\n        static_cast<size_t>( std::numeric_limits<addr_t>::max() ) >= index,\n        \"cppad_tape_addr_type maximum value has been exceeded\"\n    )\n    return static_cast<addr_t>( index );\n}\n\n} } // END_CPPAD_LOCAL_NAMESPACE\n\n// ----------------------------------------------------------------------------\n// member function implementations\n# include <cppad/local/record/put_dyn_atomic.hpp>\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/record/put_dyn_atomic.hpp",
    "content": "# ifndef CPPAD_LOCAL_RECORD_PUT_DYN_ATOMIC_HPP\n# define CPPAD_LOCAL_RECORD_PUT_DYN_ATOMIC_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/local/record/recorder.hpp>\n\nnamespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE\n/*\n{xrst_begin recorder_put_dyn_atomic dev}\n{xrst_spell\n    taddr\n}\n\nPut a Dynamic Parameter Atomic Call Operator in Recording\n#########################################################\n\nSyntax\n******\n| *dyn_record* . ``put_dyn_atomic`` (\n| |tab| *tape_id* , *atomic_index* , *call_id* , *type_x* , *type_y* , *ax* , *ay*\n| )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_PUT_DYN_ATOMIC\n    // END_PROTOTYPE\n}\n\ntape_id\n*******\nidentifies the tape that this recording corresponds to.\nThis is zero if and only if there is no tape for this recording; i.e.\n``AD`` < *Base* >. ``tape_ptr`` () is null.\n\natomic_index\n************\nis the :ref:`atomic_index-name` for this atomic function.\n\ncall_id\n*******\nis the :ref:`atomic_four_call@call_id` for this atomic function.\n\ntype_x\n******\nis the :ref:`ad_type_enum-name` for each of the atomic function arguments.\n\ntype_y\n******\nis the ``ad_type_enum`` for each of the atomic function results.\n\nax\n**\nis the atomic function argument vector for this call.\n\nvalue\\_\n=======\nThe value *ax* [ *j* ]. ``value_`` is the proper value for\nparameters and does not matter for variables.\n\ntaddr\\_\n=======\nThe value *ax* [ *j* ]. ``taddr_`` is the proper address for\ndynamic parameters and does not matter for constants or variables.\n\nay\n**\nis the atomic function result vector for this call.\n\nInput\n=====\nOn input, *ay* [ *j* ]. ``value_`` has the proper value for parameters\n(result for the atomic function).\n\nOutput\n======\nUpon return, if the *i*-th result is a dynamic parameter,\n\n| |tab| *ay* [ *i* ]. ``ad_type_`` = ``dynamic_enum``\n| |tab| *ay* [ *i* ]. ``tape_id_`` = *tape_id*\n| |tab| *ay* [ *i* ]. ``taddr_`` = *p_index*\n\nwhere *p_index* is the index of this dynamic parameter\nin the vector of all parameters.\n\n{xrst_end recorder_put_dyn_atomic}\n*/\n\n// BEGIN_PUT_DYN_ATOMIC\ntemplate <class Base> template <class VectorAD>\nvoid dyn_recorder<Base>::put_dyn_atomic(\n    tape_id_t                   tape_id      ,\n    size_t                      atomic_index ,\n    size_t                      call_id      ,\n    const vector<ad_type_enum>& type_x       ,\n    const vector<ad_type_enum>& type_y       ,\n    const VectorAD&             ax           ,\n    VectorAD&                   ay           )\n// END_PROTOTYPE\n{   CPPAD_ASSERT_UNKNOWN(\n        (tape_id == 0) == (AD<Base>::tape_ptr() == nullptr)\n    );\n    CPPAD_ASSERT_UNKNOWN( ax.size() == type_x.size() );\n    CPPAD_ASSERT_UNKNOWN( ay.size() == type_y.size() );\n    size_t n       = ax.size();\n    size_t m       = ay.size();\n    size_t num_dyn = 0;\n    for(size_t i = 0; i < m; ++i)\n        if( type_y[i] == dynamic_enum )\n            ++num_dyn;\n    CPPAD_ASSERT_UNKNOWN( num_dyn > 0 );\n    //\n    dyn_par_arg_.push_back( addr_t(atomic_index )); // arg[0] = atomic_index\n    dyn_par_arg_.push_back( addr_t(call_id ));      // arg[1] = call_id\n    dyn_par_arg_.push_back( addr_t( n ) );          // arg[2] = n\n    dyn_par_arg_.push_back( addr_t( m ) );          // arg[3] = m\n    dyn_par_arg_.push_back( addr_t( num_dyn ) );    // arg[4] = num_dyn\n    // arg[5 + j] for j = 0, ... , n-1\n    for(size_t j = 0; j < n; ++j)\n    {   addr_t arg = 0;\n        switch( type_x[j] )\n        {   case identical_zero_enum:\n            case constant_enum:\n            arg = put_con_par( ax[j].value_ );\n            break;\n\n            case dynamic_enum:\n            arg = ax[j].taddr_;\n            break;\n\n            case variable_enum:\n            arg = 0; // phantom parameter index\n            CPPAD_ASSERT_UNKNOWN( CppAD::isnan( par_all_[arg] ) )\n            break;\n\n            default:\n            arg = 0;\n            CPPAD_ASSERT_UNKNOWN( false );\n        }\n        dyn_par_arg_.push_back( arg );              // arg[5 + j]\n    }\n    // arg[5 + n + i] for i = 0, ... , m-1\n    bool first_dynamic_result = true;\n    for(size_t i = 0; i < m; ++i)\n    {   addr_t arg;\n        switch( type_y[i] )\n        {   case identical_zero_enum:\n            case constant_enum:\n            arg = 0; // phantom parameter index\n            break;\n\n            case dynamic_enum:\n            // one operator for each dynamic parameter result\n            // so number of operators is equal number of dynamic parameters\n            if( first_dynamic_result )\n                arg = put_dyn_par(ay[i].value_, atom_dyn );    // atom_dyn\n            else\n                arg = put_dyn_par(ay[i].value_, result_dyn );  // result_dyn\n            ay[i].ad_type_ = dynamic_enum;\n            ay[i].taddr_   = arg;\n            ay[i].tape_id_ = tape_id;\n            first_dynamic_result = false;\n            break;\n\n            case variable_enum:\n            arg = 0; // phantom parameter (has value nan)\n            break;\n\n            default:\n            arg = 0;\n            CPPAD_ASSERT_UNKNOWN( false );\n        }\n        dyn_par_arg_.push_back( arg );              // arg[5 + n + i]\n    }\n    dyn_par_arg_.push_back( addr_t(6 + n + m) );    // arg[5 + n + m]\n}\n\n} } // END_CPPAD_LOCAL_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/local/record/put_var_atomic.hpp",
    "content": "# ifndef CPPAD_LOCAL_RECORD_PUT_VAR_ATOMIC_HPP\n# define CPPAD_LOCAL_RECORD_PUT_VAR_ATOMIC_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/local/record/recorder.hpp>\n\nnamespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE\n/*\n{xrst_begin recorder_put_var_atomic dev}\n{xrst_spell\n    taddr\n}\n\nPut a Variable Atomic Call Operator in Recording\n################################################\n\nSyntax\n******\n| *rec* . ``put_var_atomic`` (\n| |tab| *tape_id* , *atomic_index* , *call_id* , *type_x* , *type_y* , *ax* , *ay*\n| )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_PUT_VAR_ATOMIC\n    // END_PROTOTYPE\n}\n\ntape_id\n*******\nidentifies the tape that this recording corresponds to.\nThis is zero if and only if there is no tape for this recording; i.e.\n``AD`` < *Base* >. ``tape_ptr`` () is null.\n\natomic_index\n************\nis the :ref:`atomic_index-name` for this atomic function.\n\ncall_id\n*******\nIs the :ref:`atomic_four_call@call_id` for this\natomic function call.\n\ntype_x\n******\nis the :ref:`ad_type_enum-name` for each of the atomic function arguments.\nThis is one of the rare cases where constants can have type\n``identical_zero_enum`` .\n\ntype_y\n******\nis the ``ad_type_enum`` for each of the atomic function results.\nThis is one of the rare cases where constants can have type\n``identical_zero_enum`` .\n\nax\n**\nis the atomic function argument vector for this call.\n\nvalue\\_\n=======\nThe value *ax* [ *j* ]. ``value_`` is the proper value for all arguments.\n\ntaddr\\_\n=======\nThe value *ax* [ *j* ]. ``taddr_`` is the proper address\nfor dynamic parameters and variables and  does not matter for constants.\n\nay\n**\nis the atomic function result vector for this call.\n\nInput\n=====\nOn input, *ay* [ *i* ] has all the correct values for\nparameters and does not matter for variables.\n\nOutput\n======\nUpon return, if the *i*-th result is a variable,\n\n| |tab| *ay* [ *i* ]. ``ad_type_`` = ``dynamic_enum``\n| |tab| *ay* [ *i* ]. ``tape_id_`` = *tape_id*\n| |tab| *ay* [ *i* ]. ``taddr_`` = *v_index*\n\nwhere *v_index* is the index of this variable\nin the arrays containing all the variables.\n\n{xrst_end recorder_put_var_atomic}\n*/\n// BEGIN_PUT_VAR_ATOMIC\ntemplate <class Base> template <class VectorAD>\nvoid recorder<Base>::put_var_atomic(\n    tape_id_t                   tape_id      ,\n    size_t                      atomic_index ,\n    size_t                      call_id      ,\n    const vector<ad_type_enum>& type_x       ,\n    const vector<ad_type_enum>& type_y       ,\n    const VectorAD&             ax           ,\n    VectorAD&                   ay           )\n// END_PROTOTYPE\n{   CPPAD_ASSERT_KNOWN(\n        size_t( std::numeric_limits<addr_t>::max() ) >=\n            std::max( std::max(atomic_index, ax.size() ), ay.size() ),\n        \"atomic_three: cppad_tape_addr_type maximum not large enough\"\n    );\n    CPPAD_ASSERT_UNKNOWN(\n        (tape_id == 0) == (AD<Base>::tape_ptr() == nullptr)\n    );\n    // Operator that marks beginning of this atomic operation\n    CPPAD_ASSERT_NARG_NRES(local::AFunOp, 4, 0 );\n    size_t n = ax.size();\n    size_t m = ay.size();\n    PutArg(addr_t(atomic_index), addr_t(call_id), addr_t(n), addr_t(m));\n    PutOp(local::AFunOp);\n\n    // Now put n operators, one for each element of argument vector\n    CPPAD_ASSERT_NARG_NRES(local::FunavOp, 1, 0 );\n    CPPAD_ASSERT_NARG_NRES(local::FunapOp, 1, 0 );\n    for(size_t j = 0; j < n; j++)\n    {   if( type_x[j] == variable_enum )\n        {   // information for an argument that is a variable\n            PutArg(ax[j].taddr_);\n            PutOp(local::FunavOp);\n        }\n        else\n        {   // information for an argument that is parameter\n            addr_t par = ax[j].taddr_;\n            if( type_x[j] <= constant_enum )\n                par = put_con_par(ax[j].value_);\n            PutArg(par);\n            PutOp(local::FunapOp);\n        }\n    }\n\n    // Now put m operators, one for each element of result vector\n    CPPAD_ASSERT_NARG_NRES(local::FunrvOp, 0, 1);\n    CPPAD_ASSERT_NARG_NRES(local::FunrpOp, 1, 0);\n    for(size_t i = 0; i < m; i++)\n    {   if( type_y[i] == variable_enum )\n        {   ay[i].taddr_    = PutOp(local::FunrvOp);\n            ay[i].tape_id_  = tape_id;\n            ay[i].ad_type_  = variable_enum;\n        }\n        else\n        {   addr_t par = ay[i].taddr_;\n            if( type_y[i] <= constant_enum )\n                par = put_con_par( ay[i].value_ );\n            PutArg(par);\n            PutOp(local::FunrpOp);\n        }\n    }\n\n    // Put a duplicate AFunOp at end of AFunOp sequence\n    PutArg(addr_t(atomic_index), addr_t(call_id), addr_t(n), addr_t(m));\n    PutOp(local::AFunOp);\n}\n\n} } // END_CPPAD_LOCAL_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/local/record/put_var_vecad.hpp",
    "content": "# ifndef CPPAD_LOCAL_RECORD_PUT_VAR_VECAD_HPP\n# define CPPAD_LOCAL_RECORD_PUT_VAR_VECAD_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/local/record/recorder.hpp>\n\nnamespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE\n/*\n------------------------------------------------------------------------------\n{xrst_begin put_var_vecad_ind dev}\n\nAdd One Index to End of Combined Variable VecAD Vector\n######################################################\n\nSyntax\n******\n| *offset* = *rec* . ``put_var_vecad_ind`` ( *vec_ind* )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_PUT_VAR_VECAD_IND\n    // END_PUT_VAR_VECAD_IND\n}\n\nPurpose\n*******\nFor each variable VecAD vector, this routine is used to store the length\nof the vector followed by the parameter index corresponding to initial\nvalue in the vector; i.e., the values just before it changed from a parameter\nto a variable.\n\nvec_ind\n*******\nis the index to be placed at the end of the combined vector of VecAD indices.\n\noffset\n******\nis the index in the combined variable VecAD vector\nwhere the value *vec_ind* is stored.\nThis index starts at zero after the recorder default constructor and\nincrements by one for each call to put_var_vecad_ind.\n\n{xrst_end put_var_vecad_ind}\n*/\n// BEGIN_PUT_VAR_VECAD_IND\ntemplate <class Base>\naddr_t recorder<Base>::put_var_vecad_ind(addr_t vec_ind)\n// END_PUT_VAR_VECAD_IND\n{  size_t offset = var_vecad_ind_.size();\n    var_vecad_ind_.push_back( vec_ind );\n    CPPAD_ASSERT_KNOWN(\n        size_t( addr_t( offset ) ) == offset,\n        \"cppad_tape_addr_type cannot support needed index range\"\n    );\n    return static_cast<addr_t>( offset );\n}\n/*\n------------------------------------------------------------------------------\n{xrst_begin recorder_put_var_vecad dev}\n{xrst_spell\n    taddr\n}\nTape Initialization for a Variable VecAD Object\n###############################################\n\nSyntax\n******\n*offset* = *rec* . ``put_var_vecad`` ( *length* , *taddr* )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_PUT_VAR_VECAD_VEC\n    // END_PUT_VAR_VECAD_VEC\n}\n\nUsage\n*****\nThis routine should be called once for each variable VecAD object just\nbefore it changes from a parameter to a variable.\n\nlength\n******\nis the size of the VecAD object.\n\ntaddr\n*****\nvector of parameter indices corresponding to the value of this VecAD vector\njust before it becomes a variable.\n\noffset\n******\nindex of the start of this VecAD vector in the combined variable VecAD vector.\nThe value corresponding to *offset* is the length of this VecAD vector.\nThere are *length* more indices following the length.\nThese values are the parameter indices.\n\n{xrst_end recorder_put_var_vecad}\n*/\n// BEGIN_PUT_VAR_VECAD_VEC\ntemplate <class Base>\naddr_t recorder<Base>::put_var_vecad(\n    size_t                        length   ,\n    const pod_vector<addr_t>&     taddr    )\n// END_PUT_VAR_VECAD_VEC\n{   CPPAD_ASSERT_UNKNOWN( length > 0 );\n    CPPAD_ASSERT_UNKNOWN( length == taddr.size() );\n    CPPAD_ASSERT_KNOWN(\n        size_t( std::numeric_limits<addr_t>::max() ) >= length,\n        \"A VecAD vector length is too large fur cppad_tape_addr_type\"\n    );\n\n    // store the length in VecInd\n    addr_t start = put_var_vecad_ind( addr_t(length) );\n\n    // store indices of the values in VecInd\n    for(size_t i = 0; i < length; i++)\n        put_var_vecad_ind( taddr[i] );\n\n    // return the taddr of the length (where the vector starts)\n    return start;\n}\n\n} } // END_CPPAD_LOCAL_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/local/record/recorder.hpp",
    "content": "# ifndef CPPAD_LOCAL_RECORD_RECORDER_HPP\n# define CPPAD_LOCAL_RECORD_RECORDER_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/core/hash_code.hpp>\n# include <cppad/local/pod_vector.hpp>\n# include <cppad/core/ad_type.hpp>\n# include <cppad/local/record/dyn_recorder.hpp>\n/*\n-------------------------------------------------------------------------------\n{xrst_begin_parent recorder dev}\n{xrst_spell\n    getters\n}\n\nClass That Records Both Variable and Dynamic Parameter Operations\n#################################################################\n\nSyntax\n******\n| CppAD::local::recorder *record*\n\nrecord\n******\n{xrst_literal\n    // BEGIN_CLASS\n    // END_CLASS\n}\n\nBase\n****\nis the base type for this recording; i.e., we are recording\n``AD`` < *Base* > operations.\n\nDynamic Parameter Operations\n****************************\nThe :ref:`dyn_recorder-name` functions can be accessed using *record* ; e.g.,\n\n| |tab| *record* . ``set_n_dyn_independent`` ( *n_dyn_independent* )\n\naccesses the :ref:`dyn_recorder@set_n_dyn_independent` function.\n\nSetters\n*******\n\nset_record_compare\n==================\n{xrst_literal\n    // BEGIN_SET_RECORD_COMPARE\n    // END_SET_RECORD_COMPARE\n}\n\nset_abort_op_index\n==================\n{xrst_literal\n    // BEGIN_SET_ABORT_OP_INDEX\n    // END_SET_ABORT_OP_INDEX\n}\n\nGetters\n*******\n\nget_record_compare\n==================\n{xrst_literal\n    // BEGIN_GET_RECORD_COMPARE\n    // END_GET_RECORD_COMPARE\n}\n\nget_abort_op_index\n==================\n{xrst_literal\n    // BEGIN_GET_ABORT_OP_INDEX\n    // END_GET_ABORT_OP_INDEX\n}\n\nnum_var\n=======\n{xrst_literal\n    // BEGIN_NUM_VAR_REC\n    // END_NUM_VAR_REC\n}\n\nnum_var_load\n============\n{xrst_literal\n    // BEGIN_NUM_VAR_LOAD_REC\n    // END_NUM_VAR_LOAD_REC\n}\n\nnum_var_op\n==========\n{xrst_literal\n    // BEGIN_NUM_OP_REC\n    // END_NUM_OP_REC\n}\n\n\nMemory\n******\n{xrst_literal\n    // BEGIN_MEMORY\n    // END_MEMORY\n}\n\n\nContents\n********\n{xrst_toc_table after\n    include/cppad/local/record/put_var_vecad.hpp\n    include/cppad/local/record/put_dyn_atomic.hpp\n    include/cppad/local/record/put_var_atomic.hpp\n    include/cppad/local/record/cond_exp.hpp\n    include/cppad/local/record/comp_op.hpp\n    include/cppad/local/record/dyn_recorder.hpp\n}\n\n\n\n{xrst_end recorder}\n-------------------------------------------------------------------------------\n*/\n// BEGIN_CPPAD_LOCAL_NAMESPACE\n// BEGIN_CLASS\nnamespace CppAD { namespace local {\ntemplate <class Base> class recorder {\n    // END_CLASS\n    //\n    friend class player<Base>;\n    //\nprivate:\n    //\n    // dyn_record_\n    dyn_recorder<Base> dyn_record_;\n    //\n    // record_compare\n    // are comparison operators being recorded\n    bool record_compare_;\n    //\n    // abort_op_index_\n    // operator index at which to abort recording with an error\n    // (do not abort when zero)\n    size_t abort_op_index_;\n    //\n    // num_var_\n         // Number of variables in the recording.\n    size_t num_var_;\n         //\n    // num_var_load_\n         // Number vecad load operations (LdpOp or LdvOp) currently in recording.\n    size_t num_var_load_;\n         //\n    // var_op_\n    // The operators in the recording.\n    pod_vector<opcode_t> var_op_;\n    //\n    // var_vecad_ind_\n         // The VecAD indices in the recording.\n    pod_vector<addr_t> var_vecad_ind_;\n    //\n    // var_arg_\n    // The argument indices in the recording\n    pod_vector<addr_t> var_arg_;\n    //\n    // var_text_\n    // Character strings ('\\\\0' terminated) in the recording.\n    pod_vector<char> var_text_;\n    //\npublic:\n    //\n    // Constructor\n    recorder(void)\n    : record_compare_(true)\n    , abort_op_index_(0)\n    , num_var_(0)\n    , num_var_load_(0)\n    { }\n    //\n    // Destructor\n    ~recorder(void)\n    { }\n    // ------------------------------------------------------------------------\n    // Parameter Operations\n    // ------------------------------------------------------------------------\n    // set_n_dyn_independent\n void set_n_dyn_independent(size_t n_dyn_independent)\n    {   dyn_record_.set_n_dyn_independent(n_dyn_independent); }\n    //\n    // n_dyn_independent\n size_t n_dyn_independent(void) const\n    {   return dyn_record_.n_dyn_independent(); }\n    //\n    // put_dyn_atomic\n    template <class VectorAD>\n    void put_dyn_atomic(\n        tape_id_t                   tape_id    ,\n        size_t                      atom_index ,\n        size_t                      call_id    ,\n        const vector<ad_type_enum>& type_x     ,\n        const vector<ad_type_enum>& type_y     ,\n        const VectorAD&             ax         ,\n        VectorAD&                   ay\n    )\n    {   dyn_record_.put_dyn_atomic(\n            tape_id, atom_index, call_id, type_x, type_y, ax, ay\n        );\n    }\n    //\n    // par_all\n         const pod_vector_maybe<Base>& par_all(void) const\n    {   return dyn_record_.par_all(); }\n    //\n    // put_con_par\n    addr_t put_con_par(const Base &par)\n    {    return dyn_record_.put_con_par(par); }\n    //\n    addr_t put_dyn_par(const Base &par, op_code_dyn op)\n    {   return dyn_record_.put_dyn_par(par, op); }\n    addr_t put_dyn_par( const Base &par, op_code_dyn op, addr_t a0)\n    {   return dyn_record_.put_dyn_par(par, op, a0); }\n    addr_t put_dyn_par( const Base &par, op_code_dyn op, addr_t a0, addr_t a1)\n    {   return dyn_record_.put_dyn_par(par, op, a0, a1); }\n    //\n    // put_dyn_cond_exp\n    addr_t put_dyn_cond_exp(const Base &par, CompareOp cop,\n        addr_t left, addr_t right, addr_t if_true, addr_t if_false\n    )\n    {   return dyn_record_.put_dyn_cond_exp(\n            par, cop, left, right, if_true, if_false\n        );\n    }\n    // put_dyn_arg_vec\n    void put_dyn_arg_vec(const pod_vector<addr_t>& arg_vec)\n    {   dyn_record_.put_dyn_arg_vec(arg_vec); }\n    // ------------------------------------------------------------------------\n    //\n    // BEGIN_SET_RECORD_COMPARE\n    // recorder.set_record_compare(record_compare)\n    void set_record_compare(bool record_compare)\n    // END_SET_RECORD_COMPARE\n    {   record_compare_ = record_compare; }\n    //\n    // BEGIN_SET_ABORT_OP_INDEX\n    // recorder.set_abort_op_index(abort_op_index)\n    void set_abort_op_index(size_t abort_op_index)\n    // END_SET_ABORT_OP_INDEX\n    {   abort_op_index_ = abort_op_index; }\n    //\n    // BEGIN_GET_RECORD_COMPARE\n    // record_compare = recorder.get_record_compare()\n    bool get_record_compare(void) const\n    // END_GET_RECORD_COMPARE\n    {   return record_compare_; }\n    //\n    // BEGIN_GET_ABORT_OP_INDEX\n    // abort_op_index = recorder.get_abort_op_index()\n    size_t get_abort_op_index(void) const\n    // END_GET_ABORT_OP_INDEX\n    {   return abort_op_index_; }\n    //\n    // BEGIN_NUM_VAR_REC\n    /// num_var = recorder.num_var()\n    size_t num_var(void) const\n    // END_NUM_VAR_REC\n    {   return num_var_; }\n    //\n    // BEGIN_NUM_VAR_LOAD_REC\n    // num_var_load = recorder.num_var_load()\n    size_t num_var_load(void) const\n    // END_NUM_VAR_LOAD_REC\n    {   return num_var_load_; }\n    //\n    // BEGIN_NUM_OP_REC\n    // num_var_op = recorder.num_var_op()\n    size_t num_var_op(void) const\n    // END_NUM_OP_REC\n    {   return  var_op_.size(); }\n    //\n    // BEGIN_MEMORY\n    // memory = recorder.memory()\n    size_t Memory(void) const\n    // END_MEMORY\n    {   return 0\n            + dyn_record_.Memory()\n            + var_op_.capacity()             * sizeof(opcode_t)\n            + var_vecad_ind_.capacity()  * sizeof(addr_t)\n            + var_arg_.capacity()            * sizeof(addr_t)\n            + var_text_.capacity()           * sizeof(char)\n        ;\n    }\n    //\n    // PutOp\n    addr_t PutOp(op_code_var op);\n    //\n    // PutArg\n    void PutArg(addr_t a0);\n    void PutArg(addr_t a0, addr_t a1);\n    void PutArg(addr_t a0, addr_t a1, addr_t a2);\n    void PutArg(addr_t a0, addr_t a1, addr_t a2, addr_t a3);\n    void PutArg(addr_t a0, addr_t a1, addr_t a2, addr_t a3, addr_t a4);\n    void PutArg(\n        addr_t a0, addr_t a1, addr_t a2, addr_t a3, addr_t a4, addr_t a5\n    );\n    //\n    // PutLoadOp\n    addr_t PutLoadOp(op_code_var op);\n    //\n    // ReserveArg\n    size_t ReserveArg(size_t n_arg);\n    //\n    // ReplaceArg\n    void ReplaceArg(size_t i_arg, addr_t value);\n    //\n    // PutTxt\n    addr_t PutTxt(const char *text);\n    //\n    // put_var_vecad_ind\n    addr_t put_var_vecad_ind(addr_t vec_ind);\n    //\n    // put_var_vecad\n    addr_t put_var_vecad(size_t length, const pod_vector<addr_t>& taddr);\n    //\n    // put_var_atomic\n    template <class VectorAD>\n    void put_var_atomic(\n        tape_id_t                   tape_id    ,\n        size_t                      atom_index ,\n        size_t                      call_id    ,\n        const vector<ad_type_enum>& type_x     ,\n        const vector<ad_type_enum>& type_y     ,\n        const VectorAD&             ax         ,\n        VectorAD&                   ay\n    );\n\n    /// record a variable or dynamic parameter conditional expression\n    void cond_exp(\n        tape_id_t       tape_id     ,\n        enum CompareOp  cop         ,\n        AD<Base>       &result      ,\n        const AD<Base> &left        ,\n        const AD<Base> &right       ,\n        const AD<Base> &if_true     ,\n        const AD<Base> &if_false\n    );\n\n    /// record a comparison operators for variables or just dynamic parameters\n    void comp_eq(\n        bool                        var_left     ,\n        bool                        var_right    ,\n        bool                        dyn_left     ,\n        bool                        dyn_right    ,\n        const AD<Base>&             aleft        ,\n        const AD<Base>&             aright       ,\n        bool                        result\n    );\n    void comp_le(\n        bool                        var_left     ,\n        bool                        var_right    ,\n        bool                        dyn_left     ,\n        bool                        dyn_right    ,\n        const AD<Base>&             aleft        ,\n        const AD<Base>&             aright       ,\n        bool                        result\n    );\n    void comp_lt(\n        bool                        var_left     ,\n        bool                        var_right    ,\n        bool                        dyn_left     ,\n        bool                        dyn_right    ,\n        const AD<Base>&             aleft        ,\n        const AD<Base>&             aright       ,\n        bool                        result\n    );\n\n};\n/*\n------------------------------------------------------------------------------\n{xrst_begin var_put_op dev}\n{xrst_spell\n    ldv\n    ldp\n}\n\nPut Next Operator in the Variable Operation Sequence\n####################################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_PUT_OP\n    // END_PUT_OP\n}\n\nDescription\n***********\nThis sets the op code for the next operation in this recording.\nThis call must be followed by putting the corresponding\nargument in the recording.\n\nop\n**\nis the op code corresponding to the operation that is being recorded.\nThe LdpOp and LdvOp operators are special cases and must use the\n:ref:`var_put_load_op-name` function.\n\nvar_index\n*********\nis the index of the primary (last) variable\ncorresponding to the result of this operation.\nThe number of variables corresponding to the operation is given by\n``NumRes`` ( *op* ) .\nWith each call to PutOp or PutLoadOp,\n*var_index* increases by the number of variables corresponding to the call.\nThis index starts at zero after the default constructor.\n\n{xrst_end var_put_op}\n*/\n// BEGIN_PUT_OP\n// var_index = record.PutOp(op)\ntemplate <class Base> addr_t recorder<Base>::PutOp(op_code_var op)\n// END_PUT_OP\n{  size_t i    = var_op_.extend(1);\n    CPPAD_ASSERT_KNOWN(\n        (abort_op_index_ == 0) || (abort_op_index_ != i),\n        \"Operator index equals abort_op_index in Independent\"\n    );\n    var_op_[i]  = static_cast<opcode_t>(op);\n    CPPAD_ASSERT_UNKNOWN( var_op_.size() == i + 1 );\n    CPPAD_ASSERT_UNKNOWN( (op != LdpOp) && (op != LdvOp) );\n\n    // first operator should be a BeginOp and NumRes( BeginOp ) > 0\n    num_var_ += NumRes(op);\n    CPPAD_ASSERT_UNKNOWN( num_var_ > 0 );\n\n    // index of last variable corresponding to this operation\n    // (if NumRes(op) > 0)\n    CPPAD_ASSERT_KNOWN(\n        (size_t) std::numeric_limits<addr_t>::max() >= num_var_ - 1,\n        \"cppad_tape_addr_type maximum value has been exceeded\"\n    )\n\n    return static_cast<addr_t>( num_var_ - 1 );\n}\n/*\n-------------------------------------------------------------------------------\n{xrst_begin var_put_arg dev}\n{xrst_spell\n    etc\n}\n\nPut Operator Arguments in the Variable Operation Sequence\n#########################################################\n\nSyntax\n******\n| *recorder* . ``PutArg`` ( *a0* )\n| *recorder* . ``PutArg`` ( *a0*  , *a1* )\n| ...\n| *recorder* . ``PutArg`` ( *a0*  , *a1* , *a2* , *a3* , *a4* , *a5* )\n\nDescription\n***********\nPlaces the values passed to ``PutArg`` at the end of the\ncurrent operation argument indices for the recording;\n*a0* comes before *a1* etc.\nThe number of the operation argument indices starts at zero\nafter the default constructor.\nThe proper number of operation arguments\ncorresponding to the operation code *op* is given by\n``NumArg`` ( *op* ) (except for the CSumOP and CSkipOp operators).\n\na0\n**\nis the first argument to place at the end of the operator argument vector.\n\na1\n**\nif present, is places after *a0* at the end of the operator argument vector.\n\na2\n**\nif present, is places after *a1* at the end of the operator argument vector.\n\na3\n**\nif present, is places after *a2* at the end of the operator argument vector.\n\na4\n**\nif present, is places after *a3* at the end of the operator argument vector.\n\na5\n**\nif present, is places after *a4* at the end of the operator argument vector.\n\nPrototype\n*********\n{xrst_literal ,\n    // BEGIN_PUT_ARG_0 , END_PUT_ARG_0\n    // BEGIN_PUT_ARG_1 , END_PUT_ARG_1\n    // BEGIN_PUT_ARG_2 , END_PUT_ARG_2\n    // BEGIN_PUT_ARG_3 , END_PUT_ARG_3\n    // BEGIN_PUT_ARG_4 , END_PUT_ARG_4\n    // BEGIN_PUT_ARG_5 , END_PUT_ARG_5\n}\n{xrst_end var_put_arg}\n*/\n// BEGIN_PUT_ARG_0\ntemplate <class Base> void recorder<Base>::PutArg(addr_t a0)\n// END_PUT_ARG_0\n{\n    size_t i      =  var_arg_.extend(1);\n    var_arg_[i]   =  a0;\n    CPPAD_ASSERT_UNKNOWN( var_arg_.size()    == i + 1 );\n}\n// BEGIN_PUT_ARG_1\ntemplate <class Base> void recorder<Base>::PutArg(addr_t a0, addr_t a1)\n// END_PUT_ARG_1\n{\n    size_t i      =  var_arg_.extend(2);\n    var_arg_[i++] =  a0;\n    var_arg_[i]   =  a1;\n    CPPAD_ASSERT_UNKNOWN( var_arg_.size()    == i + 1 );\n}\n// BEGIN_PUT_ARG_2\ntemplate <class Base> void recorder<Base>::PutArg(\n    addr_t a0, addr_t a1, addr_t a2\n)\n// END_PUT_ARG_2\n{\n    size_t i      =  var_arg_.extend(3);\n    var_arg_[i++] =  a0;\n    var_arg_[i++] =  a1;\n    var_arg_[i]   =  a2;\n    CPPAD_ASSERT_UNKNOWN( var_arg_.size()    == i + 1 );\n}\n// BEGIN_PUT_ARG_3\ntemplate <class Base> void recorder<Base>::PutArg(\n    addr_t a0, addr_t a1, addr_t a2, addr_t a3\n)\n// END_PUT_ARG_3\n{\n    size_t i      =  var_arg_.extend(4);\n    var_arg_[i++] =  a0;\n    var_arg_[i++] =  a1;\n    var_arg_[i++] =  a2;\n    var_arg_[i]   =  a3;\n    CPPAD_ASSERT_UNKNOWN( var_arg_.size()    == i + 1 );\n\n}\n// BEGIN_PUT_ARG_4\ntemplate <class Base> void recorder<Base>::PutArg(\n    addr_t a0, addr_t a1, addr_t a2, addr_t a3, addr_t a4\n)\n// END_PUT_ARG_4\n{\n    size_t i      =  var_arg_.extend(5);\n    var_arg_[i++] =  a0;\n    var_arg_[i++] =  a1;\n    var_arg_[i++] =  a2;\n    var_arg_[i++] =  a3;\n    var_arg_[i]   =  a4;\n    CPPAD_ASSERT_UNKNOWN( var_arg_.size()    == i + 1 );\n\n}\n// BEGIN_PUT_ARG_5\ntemplate <class Base> void recorder<Base>::PutArg(\n    addr_t a0, addr_t a1, addr_t a2, addr_t a3, addr_t a4, addr_t a5\n)\n// END_PUT_ARG_5\n{\n    size_t i      =  var_arg_.extend(6);\n    var_arg_[i++] =  a0;\n    var_arg_[i++] =  a1;\n    var_arg_[i++] =  a2;\n    var_arg_[i++] =  a3;\n    var_arg_[i++] =  a4;\n    var_arg_[i]   =  a5;\n    CPPAD_ASSERT_UNKNOWN( var_arg_.size()    == i + 1 );\n}\n/*\n-------------------------------------------------------------------------------\n{xrst_begin var_put_load_op dev}\n{xrst_spell\n    ldv\n    ldp\n}\n\nPut Next LdpOp or LdvOp Operator in Operation Sequence\n######################################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_PUT_LOAD_OP\n    // END_PUT_LOAD_OP\n}\n\nDescription\n***********\nThis sets the op code for a load instruction.\nThis call must be followed by putting the corresponding\nargument indices in the recording.\n\nop\n**\nIs the op code corresponding to the operation that is being\nrecorded (which must be LdpOp or LdvOp).\n\nvar_index\n*********\nThe return value is the index of the variable\ncorresponding to the result of this operation  must be one.\nWith each call to PutLoadOp or PutOp,\nthe return index increases by the number of variables corresponding\nto this call to the call.\nThis index starts at zero after the default constructor.\n\nnum_var_load\n************\nThe return value for ``num_var_load()``\nincreases by one after each call to this function.\n\n{xrst_end var_put_load_op}\n*/\n// BEGIN_PUT_LOAD_OP\n// var_index = recorder.PutLoadOp(op)\ntemplate <class Base> addr_t recorder<Base>::PutLoadOp(op_code_var op)\n// END_PUT_LOAD_OP\n{  size_t i    = var_op_.extend(1);\n    CPPAD_ASSERT_KNOWN(\n        (abort_op_index_ == 0) || (abort_op_index_ != i),\n        \"This is the abort operator index specified by \"\n        \"Independent(x, abort_op_index).\"\n    );\n    var_op_[i]  = op;\n    CPPAD_ASSERT_UNKNOWN( var_op_.size() == i + 1 );\n    CPPAD_ASSERT_UNKNOWN( (op == LdpOp) || (op == LdvOp) );\n\n    // first operator should be a BeginOp and NumRes( BeginOp ) > 0\n    num_var_ += NumRes(op);\n    CPPAD_ASSERT_UNKNOWN( num_var_ > 0 );\n\n    // count this vecad load operation\n    num_var_load_++;\n\n    // index of last variable corresponding to this operation\n    // (if NumRes(op) > 0)\n    CPPAD_ASSERT_KNOWN(\n        (size_t) std::numeric_limits<addr_t>::max() >= num_var_ - 1,\n        \"cppad_tape_addr_type maximum value has been exceeded\"\n    )\n    return static_cast<addr_t>( num_var_ - 1 );\n}\n/*\n-------------------------------------------------------------------------------\n{xrst_begin var_reserve_arg dev}\n\nReserve Space for Variable Recording Arguments, Delay Placing Values There\n##########################################################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_RESERVE_ARG\n    // END_RESERVE_ARG\n}\n\nn_arg\n*****\nnumber of arguments to reserve space for\n\narg_index\n*********\nis the index in the argument vector corresponding to the\nfirst of the arguments being reserved.\n\n{xrst_end var_reserve_arg}\n*/\n// BEGIN_RESERVE_ARG\n// arg_index = recorder.ReserveArg(n_arg)\ntemplate <class Base> size_t recorder<Base>::ReserveArg(size_t n_arg)\n// END_RESERVE_ARG\n{\n    size_t i      =  var_arg_.extend(n_arg);\n    CPPAD_ASSERT_UNKNOWN( var_arg_.size()    == i + n_arg );\n    return i;\n}\n/*\n-------------------------------------------------------------------------------\n{xrst_begin var_replace_arg dev}\n\nReplace an Argument Value in the Variable Recording\n###################################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_REPLACE_ARG\n    // END_REPLACE_ARG\n}\n\nPurpose\n*******\nThis is intended to be used to replace reserved values.\n\narg_index\n*********\nis the index, in argument vector, for the value that is replaced.\n\nvalue\n*****\nis the new value for the argument with the specified index.\n\n{xrst_end var_replace_arg}\n*/\n// BEGIN_REPLACE_ARG\n// recorder.ReplaceArg(arg_index, value)\ntemplate <class Base> void recorder<Base>::ReplaceArg(\n    size_t arg_index, addr_t value\n)\n// END_REPLACE_ARG\n{   var_arg_[arg_index] =  value; }\n// --------------------------------------------------------------------------\n/*\n{xrst_begin var_put_txt dev}\n\nPut a Character String in the Text for This Variable Recording\n##############################################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_PUT_TXT\n    // END_PUT_TXT\n}\n\ntext\n****\nis a ``\\\\0`` terminated character string that is to be put in the\nvector of characters corresponding to this recording.\nThe terminator ``\\\\0`` is included.\n\ntxt_index\n*********\nis the offset with in the text vector for this recording at which\nthe character string starts.\n\n{xrst_end var_put_txt}\n*/\n// BEGIN_PUT_TXT\n// txt_index = recorder.PutTxt(text)\ntemplate <class Base> addr_t recorder<Base>::PutTxt(const char *text)\n// END_PUT_TXT\n{\n    // determine length of the text including terminating '\\0'\n    size_t n = 0;\n    while( text[n] != '\\0' )\n        n++;\n    CPPAD_ASSERT_UNKNOWN( n <= 1000 );\n    n++;\n    CPPAD_ASSERT_UNKNOWN( text[n-1] == '\\0' );\n\n    // copy text including terminating '\\0'\n    size_t i = var_text_.extend(n);\n    size_t j;\n    for(j = 0; j < n; j++)\n        var_text_[i + j] = text[j];\n    CPPAD_ASSERT_UNKNOWN( var_text_.size() == i + n );\n\n    CPPAD_ASSERT_KNOWN(\n        size_t( std::numeric_limits<addr_t>::max() ) >= i,\n        \"cppad_tape_addr_type maximum value has been exceeded\"\n    );\n    //\n    return static_cast<addr_t>( i );\n}\n\n} } // END_CPPAD_LOCAL_NAMESPACE\n\n// ----------------------------------------------------------------------------\n// member function implementations\n# include <cppad/local/record/put_var_vecad.hpp>\n# include <cppad/local/record/put_var_atomic.hpp>\n# include <cppad/local/record/cond_exp.hpp>\n# include <cppad/local/record/comp_op.hpp>\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/set_get_in_parallel.hpp",
    "content": "# ifndef CPPAD_LOCAL_SET_GET_IN_PARALLEL_HPP\n# define CPPAD_LOCAL_SET_GET_IN_PARALLEL_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cassert>\nnamespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE\n/*\n{xrst_begin set_get_in_parallel dev}\n{xrst_spell\n    nullptr\n}\n\nSet in_parallel Routine or Get In Parallel Mode\n###############################################\nSet and call the routine that determine if we are in parallel execution mode.\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN PROTOTYPE\n    // END PROTOTYPE\n}\n\nset\n===\nIf *set* is true, set are setting the current in_parallel routine.\nIn this case we must be in sequential execution mode; i.e., not parallel.\nIf *set* is false,\nwe are getting the result for the current in_parallel routine.\n\nin_parallel_new\n***************\n#. If *set* is true, *in_parallel_new* becomes the\n   most recent setting for the user's in_parallel routine.\n   The nullptr in_parallel routine will always return false.\n#. If *set* is false, the value of *in_parallel_new* does not matter.\n\nflag\n****\n#. If *set* is false, the return value *flag* is the current value\n   for the current in_parallel routine. (It is false if the current\n   in_parallel routine is the nullptr.)\n#. If *set* is true, the return value *flag* is unspecified.\n\n{xrst_end set_get_in_parallel}\n*/\n// BEGIN PROTOTYPE\n// flag = CppAD::local::set_get_inparallel( .. )\ninline bool set_get_in_parallel(\n    bool set                      = false   ,\n    bool (*in_parallel_new)(void) = nullptr )\n// END PROTOTYPE\n{   typedef bool (*function_ptr)(void);\n    static function_ptr in_parallel_user = nullptr;\n\n    if( set )\n    {   in_parallel_user = in_parallel_new;\n        // Doing a raw assert in this case because set_get_in_parallel is used\n        // by ErrorHandler and hence cannot use ErrorHandler.\n        // CPPAD_ASSERT_UNKNOWN( in_parallel_user() == false )\n        assert(in_parallel_user == nullptr || in_parallel_user() == false);\n        return false;\n    }\n    //\n    if( in_parallel_user == nullptr )\n        return false;\n    //\n    return in_parallel_user();\n}\n\n} } // END_CPPAD_LOCAL_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/sparse/dev_sparse.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin dev_sparse dev}\n\nDeveloper Sparse Documentation\n##############################\n\nContents\n********\n{xrst_toc_table\n    include/cppad/local/sparse/setvector.xrst\n}\n\n{xrst_end dev_sparse}\n"
  },
  {
    "path": "include/cppad/local/sparse/internal.hpp",
    "content": "# ifndef CPPAD_LOCAL_SPARSE_INTERNAL_HPP\n# define CPPAD_LOCAL_SPARSE_INTERNAL_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n// necessary definitions\n# include <cppad/local/define.hpp>\n# include <cppad/local/sparse/pack_setvec.hpp>\n# include <cppad/local/sparse/list_setvec.hpp>\n# include <cppad/local/sparse/svec_setvec.hpp>\n\n// BEGIN_CPPAD_LOCAL_SPARSE_NAMESPACE\nnamespace CppAD { namespace local { namespace sparse {\n\n/*!\n\\file sparse_internal.hpp\nRoutines that enable code to be independent of which internal spasity pattern\nis used.\n*/\n// ---------------------------------------------------------------------------\n/*!\nTemplate structure used obtain the internal sparsity pattern type\nform the corresponding element type.\nThe general form is not valid, must use a specialization.\n\n\\tparam Element_type\ntype of an element in the sparsity structure.\n\n\\par <code>internal_pattern<Element_type>::pattern_type</code>\nis the type of the corresponding internal sparsity pattern.\n*/\ntemplate <class Element_type> struct internal_pattern;\n/// Specialization for bool elements.\ntemplate <>\nstruct internal_pattern<bool>\n{\n    typedef sparse::pack_setvec pattern_type;\n};\n/// Specialization for <code>std::set<size_t></code> elements.\ntemplate <>\nstruct internal_pattern< std::set<size_t> >\n{\n    typedef list_setvec pattern_type;\n};\n// ---------------------------------------------------------------------------\n/*!\nUpdate the internal sparsity pattern for a sub-set of rows\n\n\\tparam SizeVector\nThe type used for index sparsity patterns. This is a simple vector\nwith elements of type size_t.\n\n\\tparam InternalSparsitiy\nThe type used for internal sparsity patterns. This can be either\nsparse::pack_setvec or list_setvec.\n\n\\param zero_empty\nIf this is true, the internal sparstity pattern corresponds to row zero\nmust be empty on input and will be empty output; i.e., any corresponding\nvalues in pattern_in will be ignored.\n\n\\param input_empty\nIf this is true, the initial sparsity pattern for row\ninternal_index[i] is empty for all i.\nIn this case, one is setting the sparsity patterns; i.e.,\nthe output pattern in row internal_index[i] is the corresponding\nentries in pattern.\n\n\\param transpose\nIf this is true, pattern_in is transposed.\n\n\\param internal_index\nThis specifies the sub-set of rows in internal_pattern that we are updating.\nIf transpose is false (true),\nthis is the mapping from row (column) index in pattern_in to the corresponding\nrow index in the internal_pattern.\n\n\\param internal_pattern\nOn input, the number of sets internal_pattern.n_set(),\nand possible elements internal_pattern.end(), have been set.\nIf input_empty is true, and all of the sets\nin internal_index are empty on input.\nOn output, the entries in pattern_in are added to internal_pattern.\nTo be specific, suppose transpose is false, and (i, j) is a possibly\nnon-zero entry in pattern_in, the entry (internal_index[i], j) is added\nto internal_pattern.\nOn the other hand, if transpose is true,\nthe entry (internal_index[j], i) is added to internal_pattern.\n\n\\param pattern_in\nThis is the sparsity pattern for variables,\nor its transpose, depending on the value of transpose.\n*/\ntemplate <class SizeVector, class InternalSparsity>\nvoid set_internal_pattern(\n    bool                          zero_empty       ,\n    bool                          input_empty      ,\n    bool                          transpose        ,\n    const pod_vector<size_t>&     internal_index   ,\n    InternalSparsity&             internal_pattern ,\n    const sparse_rc<SizeVector>&  pattern_in       )\n{\n    size_t nr = internal_index.size();\n# ifndef NDEBUG\n    size_t nc = internal_pattern.end();\n    if( transpose )\n    {   CPPAD_ASSERT_UNKNOWN( pattern_in.nr() == nc );\n        CPPAD_ASSERT_UNKNOWN( pattern_in.nc() == nr );\n    }\n    else\n    {   CPPAD_ASSERT_UNKNOWN( pattern_in.nr() == nr );\n        CPPAD_ASSERT_UNKNOWN( pattern_in.nc() == nc );\n    }\n    if( input_empty ) for(size_t i = 0; i < nr; i++)\n    {   size_t i_var = internal_index[i];\n        CPPAD_ASSERT_UNKNOWN( internal_pattern.number_elements(i_var) == 0 );\n    }\n# endif\n    const SizeVector& row( pattern_in.row() );\n    const SizeVector& col( pattern_in.col() );\n    size_t nnz = row.size();\n    for(size_t k = 0; k < nnz; k++)\n    {   size_t r = row[k];\n        size_t c = col[k];\n        if( transpose )\n            std::swap(r, c);\n        //\n        size_t i_var = internal_index[r];\n        CPPAD_ASSERT_UNKNOWN( i_var < internal_pattern.n_set() );\n        CPPAD_ASSERT_UNKNOWN( c < nc );\n        bool ignore  = zero_empty && i_var == 0;\n        if( ! ignore )\n            internal_pattern.post_element( internal_index[r], c );\n    }\n    // process posts\n    for(size_t i = 0; i < nr; ++i)\n        internal_pattern.process_post( internal_index[i] );\n}\ntemplate <class InternalSparsity>\nvoid set_internal_pattern(\n    bool                          zero_empty       ,\n    bool                          input_empty      ,\n    bool                          transpose        ,\n    const pod_vector<size_t>&     internal_index   ,\n    InternalSparsity&             internal_pattern ,\n    const vectorBool&             pattern_in       )\n{   size_t nr = internal_index.size();\n    size_t nc = internal_pattern.end();\n# ifndef NDEBUG\n    CPPAD_ASSERT_UNKNOWN( pattern_in.size() == nr * nc );\n    if( input_empty ) for(size_t i = 0; i < nr; i++)\n    {   size_t i_var = internal_index[i];\n        CPPAD_ASSERT_UNKNOWN( internal_pattern.number_elements(i_var) == 0 );\n    }\n# endif\n    for(size_t i = 0; i < nr; i++)\n    {   for(size_t j = 0; j < nc; j++)\n        {   bool flag = pattern_in[i * nc + j];\n            if( transpose )\n                flag = pattern_in[j * nr + i];\n            if( flag )\n            {   size_t i_var = internal_index[i];\n                CPPAD_ASSERT_UNKNOWN( i_var < internal_pattern.n_set() );\n                CPPAD_ASSERT_UNKNOWN( j < nc );\n                bool ignore  = zero_empty && i_var == 0;\n                if( ! ignore )\n                    internal_pattern.post_element( i_var, j);\n            }\n        }\n    }\n    // process posts\n    for(size_t i = 0; i < nr; ++i)\n        internal_pattern.process_post( internal_index[i] );\n    return;\n}\ntemplate <class InternalSparsity>\nvoid set_internal_pattern(\n    bool                          zero_empty       ,\n    bool                          input_empty      ,\n    bool                          transpose        ,\n    const pod_vector<size_t>&     internal_index   ,\n    InternalSparsity&             internal_pattern ,\n    const vector<bool>&           pattern_in       )\n{   size_t nr = internal_index.size();\n    size_t nc = internal_pattern.end();\n# ifndef NDEBUG\n    CPPAD_ASSERT_UNKNOWN( pattern_in.size() == nr * nc );\n    if( input_empty ) for(size_t i = 0; i < nr; i++)\n    {   size_t i_var = internal_index[i];\n        CPPAD_ASSERT_UNKNOWN( internal_pattern.number_elements(i_var) == 0 );\n    }\n# endif\n    for(size_t i = 0; i < nr; i++)\n    {   for(size_t j = 0; j < nc; j++)\n        {   bool flag = pattern_in[i * nc + j];\n            if( transpose )\n                flag = pattern_in[j * nr + i];\n            if( flag )\n            {   size_t i_var = internal_index[i];\n                CPPAD_ASSERT_UNKNOWN( i_var < internal_pattern.n_set() );\n                CPPAD_ASSERT_UNKNOWN( j < nc );\n                bool ignore  = zero_empty && i_var == 0;\n                if( ! ignore )\n                    internal_pattern.post_element( i_var, j);\n            }\n        }\n    }\n    // process posts\n    for(size_t i = 0; i < nr; ++i)\n        internal_pattern.process_post( internal_index[i] );\n    return;\n}\ntemplate <class InternalSparsity>\nvoid set_internal_pattern(\n    bool                               zero_empty       ,\n    bool                               input_empty      ,\n    bool                               transpose        ,\n    const pod_vector<size_t>&          internal_index   ,\n    InternalSparsity&                  internal_pattern ,\n    const vector< std::set<size_t> >&  pattern_in       )\n{   size_t nr = internal_index.size();\n    size_t nc = internal_pattern.end();\n# ifndef NDEBUG\n    if( input_empty ) for(size_t i = 0; i < nr; i++)\n    {   size_t i_var = internal_index[i];\n        CPPAD_ASSERT_UNKNOWN( internal_pattern.number_elements(i_var) == 0 );\n    }\n# endif\n    if( transpose )\n    {   CPPAD_ASSERT_UNKNOWN( pattern_in.size() == nc );\n        for(size_t j = 0; j < nc; j++)\n        {   std::set<size_t>::const_iterator itr( pattern_in[j].begin() );\n            while( itr != pattern_in[j].end() )\n            {   size_t i = *itr;\n                size_t i_var = internal_index[i];\n                CPPAD_ASSERT_UNKNOWN( i_var < internal_pattern.n_set() );\n                CPPAD_ASSERT_UNKNOWN( j < nc );\n                bool ignore  = zero_empty && i_var == 0;\n                if( ! ignore )\n                    internal_pattern.post_element( i_var, j);\n                ++itr;\n            }\n        }\n    }\n    else\n    {   CPPAD_ASSERT_UNKNOWN( pattern_in.size() == nr );\n        for(size_t i = 0; i < nr; i++)\n        {   std::set<size_t>::const_iterator itr( pattern_in[i].begin() );\n            while( itr != pattern_in[i].end() )\n            {   size_t j = *itr;\n                size_t i_var = internal_index[i];\n                CPPAD_ASSERT_UNKNOWN( i_var < internal_pattern.n_set() );\n                CPPAD_ASSERT_UNKNOWN( j < nc );\n                bool ignore  = zero_empty && i_var == 0;\n                if( ! ignore )\n                    internal_pattern.post_element( i_var, j);\n                ++itr;\n            }\n        }\n    }\n    // process posts\n    for(size_t i = 0; i < nr; ++i)\n        internal_pattern.process_post( internal_index[i] );\n    return;\n}\n// ---------------------------------------------------------------------------\n/*!\nGet sparsity pattern for a sub-set of variables\n\n\\tparam SizeVector\nThe type used for index sparsity patterns. This is a simple vector\nwith elements of type size_t.\n\n\\tparam InternalSparsitiy\nThe type used for internal sparsity patterns. This can be either\nsparse::pack_setvec or list_setvec.\n\n\\param transpose\nIf this is true, pattern_out is transposed.\n\n\\param internal_index\nIf transpose is false (true)\nthis is the mapping from row (column) an index in pattern_out\nto the corresponding row index in internal_pattern.\n\n\\param internal_pattern\nThis is the internal sparsity pattern.\n\n\\param pattern_out\nThe input value of pattern_out does not matter.\nUpon return it is an index sparsity pattern for each of the variables\nin internal_index, or its transpose, depending on the value of transpose.\n*/\ntemplate <class SizeVector, class InternalSparsity>\nvoid get_internal_pattern(\n    bool                          transpose         ,\n    const pod_vector<size_t>&     internal_index    ,\n    const InternalSparsity&       internal_pattern  ,\n    sparse_rc<SizeVector>&        pattern_out        )\n{   typedef typename InternalSparsity::const_iterator iterator;\n    // number variables\n    size_t nr = internal_index.size();\n    // column size of internal sparstiy pattern\n    size_t nc = internal_pattern.end();\n    // determine nnz, the number of possibly non-zero index pairs\n    size_t nnz = 0;\n    for(size_t i = 0; i < nr; i++)\n    {   CPPAD_ASSERT_UNKNOWN( internal_index[i] < internal_pattern.n_set() );\n        iterator itr(internal_pattern, internal_index[i]);\n        size_t j = *itr;\n        while( j < nc )\n        {   ++nnz;\n            j = *(++itr);\n        }\n    }\n    // transposed\n    if( transpose )\n    {   pattern_out.resize(nc, nr, nnz);\n        //\n        size_t k = 0;\n        for(size_t i = 0; i < nr; i++)\n        {   iterator itr(internal_pattern, internal_index[i]);\n            size_t j = *itr;\n            while( j < nc )\n            {   pattern_out.set(k++, j, i);\n                j = *(++itr);\n            }\n        }\n        return;\n    }\n    // not transposed\n    pattern_out.resize(nr, nc, nnz);\n    //\n    size_t k = 0;\n    for(size_t i = 0; i < nr; i++)\n    {   iterator itr(internal_pattern, internal_index[i]);\n        size_t j = *itr;\n        while( j < nc )\n        {   pattern_out.set(k++, i, j);\n            j = *(++itr);\n        }\n    }\n    return;\n}\ntemplate <class InternalSparsity>\nvoid get_internal_pattern(\n    bool                          transpose         ,\n    const pod_vector<size_t>&     internal_index    ,\n    const InternalSparsity&       internal_pattern  ,\n    vectorBool&                   pattern_out       )\n{   typedef typename InternalSparsity::const_iterator iterator;\n    // number variables\n    size_t nr = internal_index.size();\n    //\n    // column size of internal sparstiy pattern\n    size_t nc = internal_pattern.end();\n    //\n    pattern_out.resize(nr * nc);\n    for(size_t ij = 0; ij < nr * nc; ij++)\n        pattern_out[ij] = false;\n    //\n    for(size_t i = 0; i < nr; i++)\n    {   CPPAD_ASSERT_UNKNOWN( internal_index[i] < internal_pattern.n_set() );\n        iterator itr(internal_pattern, internal_index[i]);\n        size_t j = *itr;\n        while( j < nc )\n        {   if( transpose )\n                pattern_out[j * nr + i] = true;\n            else\n                pattern_out[i * nc + j] = true;\n            j = *(++itr);\n        }\n    }\n    return;\n}\ntemplate <class InternalSparsity>\nvoid get_internal_pattern(\n    bool                          transpose         ,\n    const pod_vector<size_t>&     internal_index    ,\n    const InternalSparsity&       internal_pattern  ,\n    vector<bool>&                 pattern_out       )\n{   typedef typename InternalSparsity::const_iterator iterator;\n    // number variables\n    size_t nr = internal_index.size();\n    //\n    // column size of internal sparstiy pattern\n    size_t nc = internal_pattern.end();\n    //\n    pattern_out.resize(nr * nc);\n    for(size_t ij = 0; ij < nr * nc; ij++)\n        pattern_out[ij] = false;\n    //\n    for(size_t i = 0; i < nr; i++)\n    {   CPPAD_ASSERT_UNKNOWN( internal_index[i] < internal_pattern.n_set() );\n        iterator itr(internal_pattern, internal_index[i]);\n        size_t j = *itr;\n        while( j < nc )\n        {   if( transpose )\n                pattern_out[j * nr + i] = true;\n            else\n                pattern_out[i * nc + j] = true;\n            j = *(++itr);\n        }\n    }\n    return;\n}\ntemplate <class InternalSparsity>\nvoid get_internal_pattern(\n    bool                          transpose         ,\n    const pod_vector<size_t>&     internal_index    ,\n    const InternalSparsity&       internal_pattern  ,\n    vector< std::set<size_t> >&   pattern_out       )\n{   typedef typename InternalSparsity::const_iterator iterator;\n    // number variables\n    size_t nr = internal_index.size();\n    //\n    // column size of internal sparstiy pattern\n    size_t nc = internal_pattern.end();\n    //\n    if( transpose )\n        pattern_out.resize(nc);\n    else\n        pattern_out.resize(nr);\n    for(size_t k = 0; k < pattern_out.size(); k++)\n        pattern_out[k].clear();\n    //\n    for(size_t i = 0; i < nr; i++)\n    {   CPPAD_ASSERT_UNKNOWN( internal_index[i] < internal_pattern.n_set() );\n        iterator itr(internal_pattern, internal_index[i]);\n        size_t j = *itr;\n        while( j < nc )\n        {   if( transpose )\n                pattern_out[j].insert(i);\n            else\n                pattern_out[i].insert(j);\n            j = *(++itr);\n        }\n    }\n    return;\n}\n\n\n\n} } } // END_CPPAD_LOCAL_SPARSE_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/sparse/list_setvec.hpp",
    "content": "# ifndef CPPAD_LOCAL_SPARSE_LIST_SETVEC_HPP\n# define CPPAD_LOCAL_SPARSE_LIST_SETVEC_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/local/define.hpp>\n# include <cppad/local/is_pod.hpp>\n# include <cppad/local/sparse/size_setvec.hpp>\n\n// BEGIN_CPPAD_LOCAL_SPARSE_NAMESPACE\nnamespace CppAD { namespace local { namespace sparse {\n\n/*\n{xrst_begin_parent list_setvec dev}\n{xrst_spell\n    typedef\n}\n\nThe list_setvec Class\n#####################\nThis class is a :ref:`SetVector-title` with elements of type ``size_t``.\nIt is implemented using the template class\n:ref:`size_setvec-name` where the elements any positive integer type.\n{xrst_code cpp} */\ntypedef size_setvec<size_t>                 list_setvec;\ntypedef size_setvec_const_iterator<size_t>  list_setvec_const_iterator;\n/*{xrst_code}\n\n{xrst_toc_table\n    include/cppad/local/sparse/size_setvec.hpp\n}\n\n{xrst_end list_setvec}\n// ----------------------------------------------------------------------------\n{xrst_begin sparsity_user2internal_list_setvec dev}\n{xrst_spell\n    msg\n}\n\nCopy A Vector of Standard Sets To A list_setvec Object\n######################################################\n\nSetVector\n*********\nis a :ref:`simple vector<SimpleVector-name>` type with elements of type\n``std::set<size_t>`` .\n\ninternal\n********\nThe input value of this object does not matter.\nUpon return it contains the same sparsity pattern as *user*\n(or its transpose).\n\nuser\n****\nis the sparsity pattern we are copying to *internal* .\n\nn_set\n*****\nis the number of sets in the output sparsity pattern *internal* .\nIf *transpose* is false, *n_set* is equal to\n*user* . ``size`` () .\n\nend\n***\nis the end value for the output sparsity pattern *internal* .\n``list_setvec`` sparsity pattern *internal* .\nIf *transpose* is true, *end* is equal to\n*user* . ``size`` () .\n\ntranspose\n*********\nIf *transpose* is false,\nelement *j* is in the *i*-th *internal* set if\n*j* is in the *user* [ *i* ] .\nOtherwise,\nelement *j* is in the *i*-th *internal* set if\n*i* is in the *user* [ *j* ] .\n\nerror_msg\n*********\nis the error message to display if some values in the *user*\nsparsity pattern are not valid.\n\nPrototype\n*********\n{xrst_spell_off}\n{xrst_code hpp} */\ntemplate<class SetVector>\nvoid sparsity_user2internal(\n    list_setvec&            internal  ,\n    const SetVector&        user      ,\n    size_t                  n_set     ,\n    size_t                  end       ,\n    bool                    transpose ,\n    const char*             error_msg )\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end sparsity_user2internal_list_setvec}\n**/\n{\n# ifndef NDEBUG\n    if( transpose )\n        CPPAD_ASSERT_KNOWN( end == size_t( user.size() ), error_msg);\n    if( ! transpose )\n        CPPAD_ASSERT_KNOWN( n_set == size_t( user.size() ), error_msg);\n# endif\n\n    // iterator for user set\n    std::set<size_t>::const_iterator itr;\n\n    // size of internal sparsity pattern\n    internal.resize(n_set, end);\n\n    if( transpose )\n    {   // transposed pattern case\n        for(size_t j = 0; j < end; j++)\n        {   itr = user[j].begin();\n            while(itr != user[j].end())\n            {   size_t i = *itr++;\n                CPPAD_ASSERT_KNOWN(i < n_set, error_msg);\n                internal.post_element(i, j);\n            }\n        }\n        for(size_t i = 0; i < n_set; ++i)\n            internal.process_post(i);\n    }\n    else\n    {   for(size_t i = 0; i < n_set; i++)\n        {   itr = user[i].begin();\n            while(itr != user[i].end())\n            {   size_t j = *itr++;\n                CPPAD_ASSERT_KNOWN( j < end, error_msg);\n                internal.post_element(i, j);\n            }\n            internal.process_post(i);\n        }\n    }\n    return;\n}\n\n} } } // END_CPPAD_LOCAL_SPARSE_NAMESPACE\n\n// =========================================================================\n// Tell pod_vector class that each pair_size_t is plain old data and hence\n// the corresponding constructor need not be called.\nnamespace CppAD { namespace local {\n    template <> inline bool\n    is_pod<sparse::size_setvec<size_t>::pair_s_type>(void)\n    {   return true; }\n} }\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/sparse/pack_setvec.hpp",
    "content": "# ifndef CPPAD_LOCAL_SPARSE_PACK_SETVEC_HPP\n# define CPPAD_LOCAL_SPARSE_PACK_SETVEC_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/core/cppad_assert.hpp>\n# include <cppad/local/pod_vector.hpp>\n\n// BEGIN_CPPAD_LOCAL_SPARSE_NAMESPACE\nnamespace CppAD { namespace local { namespace sparse {\n\n// forward declaration of iterator class\nclass pack_setvec_const_iterator;\n\n// ============================================================================\nclass pack_setvec {\n// ============================================================================\n/*\n{xrst_begin pack_setvec_member_data dev}\n\nclass pack_setvec: Private Member Data\n######################################\n\nPack\n****\nType used to pack multiple elements of a set (multiple bits) onto one\n*Pack* value.\n\nn_bit\\_\n*******\nNumber of bits (elements) per *Pack* value.\n\nzero\\_\n******\nThe *Pack* value with all bits zero.\n\none\\_\n*****\nThe *Pack* value with all bits zero, except for the lowest order bit.\n\nn_set\\_\n*******\nNumber of sets that we are representing.\n\nend\\_\n*****\nThe possible elements in each set are ``0`` , ``1`` , ...,\n``end_-1`` .\n\nn_pack\\_\n********\nNumber of Pack values used to represent one set in the vector; i.e.,\nto represent ``end_`` bits.\n\ndata\\_\n******\nData for all of the sets.\n\nSource Code\n***********\n{xrst_spell_off}\n{xrst_code hpp} */\nprivate:\n    typedef size_t    Pack;\n    const size_t      n_bit_;\n    const Pack        zero_;\n    const Pack        one_;\n    size_t            n_set_;\n    size_t            end_;\n    size_t            n_pack_;\n    pod_vector<Pack>  data_;\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end pack_setvec_member_data}\n-----------------------------------------------------------------------------\n{xrst_begin pack_setvec_vec_memory dev}\n\nclass pack_setvec: Approximate Memory Used by Vector\n####################################################\n\nPublic\n******\nThis function is declared public, but is not part of\n:ref:`SetVector-name` concept.\n\nImplementation\n**************\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    size_t memory(void) const\n    {  return data_.capacity() * sizeof(Pack); }\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end pack_setvec_vec_memory}\n-------------------------------------------------------------------------------\n{xrst_begin pack_setvec_vec_print dev}\n\nclass pack_setvec: Print a Vector of Sets\n#########################################\n\nPublic\n******\nThis function is declared public, but is not part of\n:ref:`SetVector-name` concept.\n\nPrototype\n*********\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    void print(void) const;\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end pack_setvec_vec_print}\n-------------------------------------------------------------------------------\n{xrst_begin pack_setvec_iterators dev}\n{xrst_spell\n    typedef\n}\n\nclass pack_setvec: Iterators\n############################\n\nSetVector Concept\n*****************\n:ref:`SetVector@const_iterator`\n\ntypedef\n*******\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    /// declare a const iterator\n    friend class pack_setvec_const_iterator;\n    typedef pack_setvec_const_iterator const_iterator;\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end pack_setvec_iterators}\n-------------------------------------------------------------------------------\n{xrst_begin pack_setvec_default_ctor dev}\n\nclass pack_setvec: Default Constructor\n######################################\n\nSetVector Concept\n*****************\n:ref:`SetVector@Vector Operations@Constructor`\n\nn_bit\\_\n*******\nThis member variable is set to the number of bits in a *Pack* value.\n\none\\_\n*****\nThis member variable has only its lowest order bit non-zero;\n\ndata\\_\n******\nThis member is initialized as the empty vector; i.e., size zero..\n\nOther\n*****\nAll the other member data are ``size_t`` values\nthat are initialized as zero.\n\nImplementation\n**************\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    pack_setvec(void) :\n    n_bit_( std::numeric_limits<Pack>::digits ),\n    zero_(0), one_(1), n_set_(0), end_(0), n_pack_(0), data_(0)\n    { }\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end pack_setvec_default_ctor}\n-------------------------------------------------------------------------------\n{xrst_begin pack_setvec_destructor dev}\n\nclass pack_setvec: Destructor\n#############################\n\nImplementation\n**************\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    ~pack_setvec(void)\n    { }\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end pack_setvec_destructor}\n-------------------------------------------------------------------------------\n{xrst_begin pack_setvec_copy_ctor dev}\n\nclass pack_setvec: Copy Constructor\n###################################\n\nv\n*\nThe vector of sets that we are attempting to make a copy of.\n\nImplementation\n**************\nUsing the copy constructor is probably due to a ``pack_setvec``\nbeing passed by value instead of by reference.\nThis is a CppAD programing error (not CppAD user error).\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    pack_setvec(const pack_setvec& v) :\n    n_bit_( std::numeric_limits<Pack>::digits ), zero_(0), one_(1)\n    {  CPPAD_ASSERT_UNKNOWN(0); }\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end pack_setvec_copy_ctor}\n-------------------------------------------------------------------------------\n{xrst_begin pack_setvec_vec_resize dev}\n\nclass pack_setvec: Vector resize\n################################\n\nSetVector Concept\n*****************\n:ref:`vector resize<SetVector@Vector Operations@resize>`\n\nPrototype\n*********\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    void resize(size_t n_set, size_t end)\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end pack_setvec_vec_resize}\n*/\n    {  n_set_          = n_set;\n        end_            = end;\n        if( n_set_ == 0 )\n        {  CPPAD_ASSERT_UNKNOWN( end == 0 );\n            data_.clear();\n            return;\n        }\n        // now start a new vector with empty sets\n        Pack zero(0);\n        //\n        n_pack_         = ( 1 + (end_ - 1) / n_bit_ );\n        size_t i        = n_set_ * n_pack_;\n        //\n        data_.resize(i);\n        while(i--)\n            data_[i] = zero;\n    }\n/* %$$\n-------------------------------------------------------------------------------\n{xrst_begin pack_setvec_vec_n_set dev}\n\nclass pack_setvec: Number of Sets\n#################################\n\nSetVector Concept\n*****************\n:ref:`SetVector@Vector Operations@n_set`\n\nImplementation\n**************\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    size_t n_set(void) const\n    {  return n_set_;  }\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end pack_setvec_vec_n_set}\n-------------------------------------------------------------------------------\n{xrst_begin pack_setvec_vec_end dev}\n\nclass pack_setvec: End Value\n############################\n\nSetVector Concept\n*****************\n:ref:`SetVector@Vector Operations@end`\n\nImplementation\n**************\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    size_t end(void) const\n    {  return end_; }\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end pack_setvec_vec_end}\n-------------------------------------------------------------------------------\n{xrst_begin pack_setvec_vec_assignment dev}\n\nclass pack_setvec: Vector Assignment\n####################################\n\nSetVector Concept\n*****************\n:ref:`vector assignment<SetVector@Vector Operations@Assignment>`\n\nPrototype\n*********\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    void operator=(const pack_setvec& other)\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end pack_setvec_vec_assignment}\n*/\n    {  CPPAD_ASSERT_UNKNOWN( n_bit_  == other.n_bit_);\n        CPPAD_ASSERT_UNKNOWN( zero_   == other.zero_);\n        CPPAD_ASSERT_UNKNOWN( one_    == other.one_);\n        n_set_  = other.n_set_;\n        end_    = other.end_;\n        n_pack_ = other.n_pack_;\n        data_   = other.data_;\n    }\n/*\n-------------------------------------------------------------------------------\n{xrst_begin pack_setvec_vec_swap dev}\n\nclass pack_setvec: Vector Swap\n##############################\n\nSetVector Concept\n*****************\n:ref:`vector swap<SetVector@Vector Operations@swap>`\n\nPrototype\n*********\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    void swap(pack_setvec& other)\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end pack_setvec_vec_swap}\n*/\n    {  // size_t objects\n        CPPAD_ASSERT_UNKNOWN( n_bit_  == other.n_bit_);\n        CPPAD_ASSERT_UNKNOWN( zero_   == other.zero_);\n        CPPAD_ASSERT_UNKNOWN( one_    == other.one_);\n        std::swap(n_set_  , other.n_set_);\n        std::swap(end_    , other.end_);\n        std::swap(n_pack_ , other.n_pack_);\n        //\n        // pod_vectors\n        data_.swap(other.data_);\n    }\n/*\n-------------------------------------------------------------------------------\n{xrst_begin pack_setvec_number_elements dev}\n\nclass pack_setvec: Number of Elements in a Set\n##############################################\n\nSetVector Concept\n*****************\n:ref:`SetVector@number_elements`\n\nPrototype\n*********\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    size_t number_elements(size_t i) const\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end pack_setvec_number_elements}\n*/\n    {  CPPAD_ASSERT_UNKNOWN( i < n_set_ );\n        //\n        // special case where data_[i] is 0 or 1\n        if( end_ == 1 )\n        {  CPPAD_ASSERT_UNKNOWN( n_pack_ == 1 );\n            return size_t( data_[i] );\n        }\n        //\n        // initialize count of non-zero bits in this set\n        size_t count = 0;\n        //\n        // mask corresponding to first bit in Pack\n        Pack mask = one_;\n        //\n        // number of bits in last Packing unit\n        size_t n_last = (end_ - 1) % n_bit_ + 1;\n        //\n        // count bits in last unit\n        Pack unit = data_[(i + 1) * n_pack_ - 1];\n        for(size_t bit = 0; bit < n_last; ++bit)\n        {  CPPAD_ASSERT_UNKNOWN( mask >= one_ );\n            if( mask & unit )\n                ++count;\n            mask = mask << 1;\n        }\n        if( n_pack_ == 1 )\n            return count;\n        //\n        // count bits in other units\n        for(size_t bit = 0; bit < n_bit_; ++bit)\n        {  CPPAD_ASSERT_UNKNOWN( mask >= one_ );\n            size_t k = n_pack_;\n            while(--k)\n            {  if( data_[i * n_pack_ + k] & mask )\n                    ++count;\n            }\n            mask = mask << 1;\n        }\n        return count;\n    }\n/*\n-------------------------------------------------------------------------------\n{xrst_begin pack_setvec_add_element dev}\n\nclass pack_setvec: Add an Elements to a Set\n###########################################\n\nSetVector Concept\n*****************\n:ref:`SetVector@add_element`\n\nPrototype\n*********\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    void add_element(size_t i, size_t element)\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end pack_setvec_add_element}\n*/\n    {  CPPAD_ASSERT_UNKNOWN( i   < n_set_ );\n        CPPAD_ASSERT_UNKNOWN( element < end_ );\n        if( end_ == 1 )\n            data_[i] |= one_;\n        else\n        {  size_t j  = element / n_bit_;\n            size_t k  = element - j * n_bit_;\n            Pack mask = one_ << k;\n            data_[ i * n_pack_ + j] |= mask;\n        }\n    }\n/*\n-------------------------------------------------------------------------------\n{xrst_begin pack_setvec_post_element dev}\n\nclass pack_setvec: Add an Elements to a Set\n###########################################\n\nSetVector Concept\n*****************\n:ref:`SetVector@post_element`\n\nImplementation\n**************\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    void post_element(size_t i, size_t element)\n    {  add_element(i, element); }\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end pack_setvec_post_element}\n*/\n/*\n-------------------------------------------------------------------------------\n{xrst_begin pack_setvec_process_post dev}\n\nclass pack_setvec: Add Posted Elements to a Set\n###############################################\n\nSetVector Concept\n*****************\n:ref:`SetVector@process_post`\n\nImplementation\n**************\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    void process_post(size_t i)\n    {  return; }\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end pack_setvec_process_post}\n-------------------------------------------------------------------------------\n{xrst_begin pack_setvec_is_element dev}\n\nclass pack_setvec: Is an Element in a Set\n#########################################\n\nSetVector Concept\n*****************\n:ref:`SetVector@is_element`\n\nPrototype\n*********\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    bool is_element(size_t i, size_t element) const\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end pack_setvec_is_element}\n*/\n    {  CPPAD_ASSERT_UNKNOWN( i   < n_set_ );\n        CPPAD_ASSERT_UNKNOWN( element < end_ );\n        if( end_ == 1 )\n            return data_[i] != zero_;\n        //\n        size_t j  = element / n_bit_;\n        size_t k  = element - j * n_bit_;\n        Pack mask = one_ << k;\n        return (data_[i * n_pack_ + j] & mask) != zero_;\n    }\n/*\n-------------------------------------------------------------------------------\n{xrst_begin pack_setvec_clear dev}\n\nclass pack_setvec: Assign a Set to be Empty\n###########################################\n\nSetVector Concept\n*****************\n:ref:`SetVector@clear`\n\nPrototype\n*********\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    void clear(size_t target)\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end pack_setvec_clear}\n*/\n    {  CPPAD_ASSERT_UNKNOWN( target < n_set_ );\n        size_t t = target * n_pack_;\n\n        size_t j = n_pack_;\n        while(j--)\n            data_[t++] = zero_;\n    }\n/*\n-------------------------------------------------------------------------------\n{xrst_begin pack_setvec_assignment dev}\n\nclass pack_setvec: Assign a Set To Equal Another Set\n####################################################\n\nSetVector Concept\n*****************\n:ref:`SetVector@assignment`\n\nPrototype\n*********\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    void assignment(\n        size_t               this_target  ,\n        size_t               other_value  ,\n        const pack_setvec&   other        )\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end pack_setvec_assignment}\n*/\n    {  CPPAD_ASSERT_UNKNOWN( this_target  <   n_set_        );\n        CPPAD_ASSERT_UNKNOWN( other_value  <   other.n_set_  );\n        CPPAD_ASSERT_UNKNOWN( n_pack_      ==  other.n_pack_ );\n        size_t t = this_target * n_pack_;\n        size_t v = other_value * n_pack_;\n\n        size_t j = n_pack_;\n        while(j--)\n            data_[t++] = other.data_[v++];\n    }\n/*\n-------------------------------------------------------------------------------\n{xrst_begin pack_setvec_binary_union dev}\n\nclass pack_setvec: Assign a Set To Equal Union of Two Sets\n##########################################################\n\nSetVector Concept\n*****************\n:ref:`SetVector@binary_union`\n\nPrototype\n*********\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    void binary_union(\n        size_t                  this_target  ,\n        size_t                  this_left    ,\n        size_t                  other_right  ,\n        const pack_setvec&      other        )\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end pack_setvec_binary_union}\n*/\n    {  CPPAD_ASSERT_UNKNOWN( this_target < n_set_         );\n        CPPAD_ASSERT_UNKNOWN( this_left   < n_set_         );\n        CPPAD_ASSERT_UNKNOWN( other_right < other.n_set_   );\n        CPPAD_ASSERT_UNKNOWN( n_pack_    ==  other.n_pack_ );\n\n        size_t t  = this_target * n_pack_;\n        size_t l  = this_left  * n_pack_;\n        size_t r  = other_right * n_pack_;\n\n        size_t j = n_pack_;\n        while(j--)\n            data_[t++] = ( data_[l++] | other.data_[r++] );\n    }\n/*\n-------------------------------------------------------------------------------\n{xrst_begin pack_setvec_binary_intersection dev}\n\nclass pack_setvec: Assign a Set To Intersection of Two Sets\n###########################################################\n\nSetVector Concept\n*****************\n:ref:`SetVector@binary_intersection`\n\nPrototype\n*********\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    void binary_intersection(\n        size_t                  this_target  ,\n        size_t                  this_left    ,\n        size_t                  other_right  ,\n        const pack_setvec&      other        )\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end pack_setvec_binary_intersection}\n*/\n    {   CPPAD_ASSERT_UNKNOWN( this_target < n_set_         );\n        CPPAD_ASSERT_UNKNOWN( this_left   < n_set_         );\n        CPPAD_ASSERT_UNKNOWN( other_right < other.n_set_   );\n        CPPAD_ASSERT_UNKNOWN( n_pack_    ==  other.n_pack_ );\n\n        size_t t  = this_target * n_pack_;\n        size_t l  = this_left  * n_pack_;\n        size_t r  = other_right * n_pack_;\n\n        size_t j = n_pack_;\n        while(j--)\n            data_[t++] = ( data_[l++] & other.data_[r++] );\n    }\n// ==========================================================================\n}; // END_CLASS_PACK_SETVEC\n// ==========================================================================\n\n\n// =========================================================================\nclass pack_setvec_const_iterator { // BEGIN_CLASS_PACK_SETVEC_CONST_ITERATOR\n// =========================================================================\n\n/*\n{xrst_begin pack_setvec_const_iterator_member_data dev}\n\nclass pack_setvec_const_iterator private: Member Data\n#####################################################\n\nPack\n****\nThis is the same type as\n:ref:`pack_setvec Pack<pack_setvec_member_data@Pack>` .\n\nn_bit\\_\n*******\nThis is a reference to\n:ref:`pack_setvec n_bit_<pack_setvec_member_data@n_bit_>` .\n\none\\_\n*****\nThis is a reference to\n:ref:`pack_setvec one_<pack_setvec_member_data@one_>` .\n\nn_pack\\_\n********\nThis is a reference to\n:ref:`pack_setvec n_pack_<pack_setvec_member_data@n_pack_>` .\n\nend\\_\n*****\nThis is a reference to\n:ref:`pack_setvec end_<pack_setvec_member_data@end_>` .\n\ndata\\_\n******\nThis is a reference to\n:ref:`pack_setvec data_<pack_setvec_member_data@data_>` .\n\ndata_index\\_\n************\nIndex in ``data_`` where the next element is located.\n\nnext_element\n************\nValue of the next element in this set\nIf ``next_element_`` equals ``end_`` ,\nno next element exists; i.e., past end of the set.\n\nSource Code\n***********\n{xrst_spell_off}\n{xrst_code hpp} */\nprivate:\n    typedef pack_setvec::Pack Pack;\n    const size_t&             n_bit_;\n    const Pack&               one_;\n    const size_t&             n_pack_;\n    const size_t&             end_;\n    const pod_vector<Pack>&   data_;\n    size_t                    data_index_;\n    size_t                    next_element_;\npublic:\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end pack_setvec_const_iterator_member_data}\n-------------------------------------------------------------------------------\n{xrst_begin pack_setvec_const_iterator_ctor dev}\n\nclass pack_setvec_const_iterator: Constructor\n#############################################\n\nSetVector Concept\n*****************\n:ref:`iterator constructor<SetVector@const_iterator@Constructor>`\n\nPrototype\n*********\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    pack_setvec_const_iterator (const pack_setvec& pack, size_t set_index)\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end pack_setvec_const_iterator_ctor}\n*/\n    :\n    n_bit_         ( pack.n_bit_ )        ,\n    one_           ( pack.one_   )        ,\n    n_pack_        ( pack.n_pack_ )       ,\n    end_           ( pack.end_ )          ,\n    data_          ( pack.data_ )         ,\n    data_index_    ( set_index * n_pack_ )\n    {  CPPAD_ASSERT_UNKNOWN( set_index < pack.n_set_ );\n        CPPAD_ASSERT_UNKNOWN( 0 < end_ );\n        //\n        next_element_ = 0;\n        if( data_[data_index_] & one_ )\n            return;\n        //\n        // element with index zero is not in this set of integers,\n        // advance to first element or end\n        ++(*this);\n    }\n/*\n-------------------------------------------------------------------------------\n{xrst_begin pack_setvec_const_iterator_dereference dev}\n\nclass pack_setvec_const_iterator: Dereference\n#############################################\n\nSetVector Concept\n*****************\n:ref:`iterator deference<SetVector@const_iterator@Dereference>`\n\nImplementation\n**************\n{xrst_spell_off}\n{xrst_code hpp} */\n    size_t operator*(void) const\n    {  return next_element_; }\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end pack_setvec_const_iterator_dereference}\n-------------------------------------------------------------------------------\n{xrst_begin pack_setvec_const_iterator_increment dev}\n\nclass pack_setvec_const_iterator: Increment\n###########################################\n\nSetVector Concept\n*****************\n:ref:`iterator increment<SetVector@const_iterator@Increment>`\n\nPrototype\n*********\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    pack_setvec_const_iterator& operator++(void)\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end pack_setvec_const_iterator_increment}\n*/\n    {   CPPAD_ASSERT_UNKNOWN( next_element_ <= end_ );\n        if( next_element_ == end_ )\n            return *this;\n        //\n        ++next_element_;\n        if( next_element_ == end_ )\n            return *this;\n        //\n        // bit index corresponding to next element\n        size_t bit = next_element_ % n_bit_;\n        //\n        // check if we have advanced to the next data index\n        if( bit == 0 )\n            ++data_index_;\n        //\n        // initialize mask\n        size_t mask = one_ << bit;\n        //\n        while( next_element_ < end_ )\n        {   // check if this element is in the set\n            if( data_[data_index_] & mask )\n                return *this;\n            //\n            // try next larger element\n            ++next_element_;\n            ++bit;\n            mask <<= 1;\n            //\n            // check if we must go to next packed data index\n            CPPAD_ASSERT_UNKNOWN( bit <= n_bit_ );\n            if( bit == n_bit_ )\n            {   // get next packed value\n                bit   = 0;\n                mask  = one_;\n                ++data_index_;\n            }\n        }\n        CPPAD_ASSERT_UNKNOWN( next_element_ == end_ );\n        return *this;\n    }\n// =========================================================================\n}; // END_CLASS_PACK_SETVEC_CONST_ITERATOR\n// =========================================================================\n\n// Implemented after pack_setvec_const_iterator so can use it\ninline void pack_setvec::print(void) const\n{   std::cout << \"pack_setvec:\\n\";\n    for(size_t i = 0; i < n_set(); i++)\n    {   std::cout << \"set[\" << i << \"] = {\";\n        const_iterator itr(*this, i);\n        while( *itr != end() )\n        {   std::cout << *itr;\n            if( *(++itr) != end() )\n                std::cout << \",\";\n        }\n        std::cout << \"}\\n\";\n    }\n    return;\n}\n\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin sparsity_user2internal_pack_setvec dev}\n{xrst_spell\n    msg\n}\n\nCopy A Boolean Sparsity Pattern To A pack_setvec Object\n#######################################################\n\nSetVector\n*********\nis a :ref:`simple vector<SimpleVector-name>` type with elements of type\n``bool`` containing the input sparsity pattern.\n\ninternal\n********\nThe input value of this object does not matter.\nUpon return it contains the same sparsity pattern as *user*\n(or its transpose).\n\nuser\n****\nis the sparsity pattern we are copying to *internal* .\n\nn_set\n*****\nis the number of sets in the output sparsity pattern *internal* .\n\nend\n***\nis the end value for the output sparsity pattern *internal* .\n\ntranspose\n*********\nIf *transpose* is false,\nelement *j* is in the *i*-th *internal* set if\n\n    *user* [ *i* * *end* + *j*  ]\n\nOtherwise,\nelement *j* is in the *i*-th *internal* set if\n\n    *user* [ *i* * *n_set* + *j*  ]\n\nerror_msg\n*********\nis the error message to display if\n\n    *n_set* * *end* != *user* . ``size`` ()\n\nPrototype\n*********\n{xrst_spell_off}\n{xrst_code hpp} */\ntemplate<class SetVector>\nvoid sparsity_user2internal(\n    pack_setvec&            internal  ,\n    const SetVector&        user      ,\n    size_t                  n_set     ,\n    size_t                  end       ,\n    bool                    transpose ,\n    const char*             error_msg )\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end sparsity_user2internal_pack_setvec}\n*/\n{   CPPAD_ASSERT_KNOWN(size_t( user.size() ) == n_set * end, error_msg );\n\n    // size of internal sparsity pattern\n    internal.resize(n_set, end);\n\n    if( transpose )\n    {   // transposed pattern case\n        for(size_t j = 0; j < end; j++)\n        {   for(size_t i = 0; i < n_set; i++)\n            {   // no advantage to using post_element for pack_setvec\n                if( user[ j * n_set + i ] )\n                    internal.add_element(i, j);\n            }\n        }\n        return;\n    }\n    else\n    {   for(size_t i = 0; i < n_set; i++)\n        {   for(size_t j = 0; j < end; j++)\n            {   // no advantage to using post_element for pack_setvec\n                if( user[ i * end + j ] )\n                    internal.add_element(i, j);\n            }\n        }\n    }\n    return;\n}\n\n} } } // END_CPPAD_LOCAL_SPARSE_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/sparse/pack_setvec.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin pack_setvec dev}\n\nImplement SetVector Using Packed Boolean Values\n###############################################\n\nNamespace\n*********\nThis class is in the ``CppAD::local::sparse`` namespace.\n\nPublic\n******\nThe public member function for the ``list_setvec`` class implement the\n:ref:`SetVector-name` concept.\n\nContents\n********\n{xrst_toc_table\n    include/cppad/local/sparse/pack_setvec.hpp\n}\n\n{xrst_end pack_setvec}\n"
  },
  {
    "path": "include/cppad/local/sparse/setvector.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin SetVector dev}\n{xrst_spell\n    dereference\n    setvec\n}\n\nC++ Concept: Vector of Sets With size_t Elements\n################################################\n\nPurpose\n*******\nThe main CppAD use of this C++ Concept is to compute sparsity patterns\nas fast as possible.\nIt is also used for conditional expression optimization.\nWe refer to a type that supports this concept as *SetVector* below.\n\nVector Operations\n*****************\n\nConstructor\n===========\nIn the specifications below, *vec* and *other*\nare *SetVector* objects created using the default constructor; e.g.,\n\n    *SetVector* *vec* , *other* ;\n\nAfter this constructor the vectors are empty; i.e.,\nthere are no sets in either vector.\nThe ``resize`` for *vec* and *other* can\nhave different :ref:`SetVector@Vector Operations@n_set` values,\nbut must have the same :ref:`SetVector@Vector Operations@end` value.\n\nresize\n======\nThis operation has the following syntax:\n\n    *vec* . ``resize`` ( *n_set* , *end* )\n\nThe argument *n_set* has type ``size_t`` and is the\nnumber of sets in *vec* .\nThe argument *end* has type ``size_t`` and is greater than\nany element allowed in any set in *vec* .\nAny information in *vec* before this operation is lost.\nAfter this operation, all the sets in *vec* are empty.\nIf *n_set* is zero,\nany allocated memory to keep track of this vector of sets is freed.\n\nn_set\n=====\nThe syntax\n\n    *n_set* = *vec* . ``n_set`` ()\n\nsets the ``size_t`` value *n_set* equal to the\nnumber of sets in *vec* .\nThe *vec* object is ``const`` for this operation.\n\nend\n===\nThe syntax\n\n    *end* = *vec* . ``end`` ()\n\nsets the ``size_t`` value *end* equal to the\nend value for the sets in *vec* .\n(This is one greater than the maximum value for any element\nin any set in *vec* .)\nThe *vec* object is ``const`` for this operation.\n\nAssignment\n==========\nThe following\nmakes *vec* into a separate copy of *other* :\n\n    *vec* = *other*\n\nThe *other* object is ``const`` for this operation.\n\nswap\n====\nThe following\nexchanges to vector of sets in *vec* and *other* :\n\n    *vec* . ``swap`` ( *other* )\n\nnumber_elements\n***************\nIf *i* is a ``size_t`` value less than *n_set* ,\n\n    *count* = *vec* . ``number_elements`` ( *i* )\n\nreturns the ``size_t`` value *count*\nequal to the number of elements in the *i*-th set.\nThe *vec* object is ``const`` for this operation.\nIt is an error to have postings to *i*-th that have not been processed.\n\nadd_element\n***********\nIf *i* is a ``size_t`` value less than *n_set*\nand *element* is a ``size_t`` value less than *end* ,\n\n    *vec* . ``add_element`` ( *i* , *element* )\n\nadds the specified element to the *i*-th set.\n\npost_element\n************\nIf *i* is a ``size_t`` value less than *n_set*\nand *element* is a ``size_t`` value less than *end* ,\n\n    *vec* . ``post_element`` ( *i* , *element* )\n\npost the specified element for addition to the *i*-th set.\nPosting multiple elements to one set and then processing them may be faster\nthan adding one element at a time.\nIt is an error to use *vec* ,\nin a way that depends on the values in the *i*-th set,\nbetween a ``post_element`` and the corresponding ``process_post`` .\n\nprocess_post\n************\nIf *i* is a ``size_t`` value less than *n_set* ,\n\n    *vec* . ``process_post`` ( *i* )\n\nProcesses all of the posts that have been made for the *i*-th set; i.e.,\nadds the posted elements to the set.\n\nis_element\n**********\nIf *i* is a ``size_t`` value less than *n_set*\nand *element* is a ``size_t`` value less than *end* ,\n\n    *find* = *vec* . ``is_element`` ( *i* , *element* )\n\nreturns the ``bool`` value *find*\nwhich is  true (false) if the specified element is in\n(is not in) the *i*-th set.\nThe *vec* object is ``const`` for this operation.\n\nclear\n*****\nIf *i* is a ``size_t`` value less than *n_set* ,\n\n    *vec* . ``clear`` ( *i* )\n\nassigns the empty set to the *i*-th set.\nIt is OK to have postings to *i*-th that have not been processed\n(they are removed).\n\nassignment\n**********\nIf *this_target* and *other_source*\nare ``size_t`` with value less than the end value,\n\n    *vec* . ``assignment`` ( *this_target* , *other_source* , *other* )\n\nsets the *this_target* set in *vec*\nequal to the *other_source* set in *other* .\nIf *vec* and *other* are the same object,\nthis operation may save memory and time using smart pointers.\nThe *other* object is ``const`` for this operation.\nIt is OK (is an error) to have postings to *this_target*\n( *other_source* ) that have not been processed.\n\nbinary_union\n************\nIf *this_target* , *this_left* , and *other_right*\nare ``size_t`` with value less than the end value,\n\n| |tab| *vec* . ``binary_union`` (\n| |tab| |tab| *this_target* , *this_left* , *other_right* , *other*\n| |tab| )\n\nsets the *this_target* set in *vec* equal to the union of\nthe *this_left* set in *vec* and\nthe *other_right* set in *other* .\nIf the resulting set is equal to the left set (right set),\nthis operation may use save memory and time using smart pointers\n(provided *vec* and *other* are the same object),\nThe *other* object is ``const`` for this operation.\nIt is OK (is an error) to have postings to *this_target*\n( *this_left* and ``other_right`` ) that have not been processed.\n\nbinary_intersection\n*******************\nIf *this_target* , *this_left* , and *other_right*\nare ``size_t`` with value less than the end value,\n\n| |tab| *vec* . ``binary_intersection`` (\n| |tab| |tab| *this_target* , *this_left* , *other_right* , *other*\n| |tab| )\n\nsets the *this_target* set in *vec* equal to the intersection of\nthe *this_left* set in *vec* and\nthe *other_right* set in *other* .\nIf the resulting set is equal to the left set (right set),\nthis operation may use save memory and time using smart pointers\n(provided *vec* and *other* are the same object),\nThe *other* object is ``const`` for this operation.\nIt is OK (is an error) to have postings to *this_target*\n( *this_left* and ``other_right`` ) that have not been processed.\n\nconst_iterator\n**************\n\nConstructor\n===========\nGiven a *SetVector* object *vec* ,\nand a ``size_t`` index *i* ,\na constant iterator *itr* is constructed as follows:\n\n    *SetVector* :: ``const_iterator`` *itr* ( *vec* , *i* )\n\nAfter this constructor, *itr* points to the first\n(smallest) element in the *i*-th set.\nThe *vec* object is ``const`` for this operation.\nIt is an error to have postings to *i*-th that have not been processed.\n\nDereference\n===========\nThe operation\n\n    ``element`` = * ``itr``\n\nsets the ``size_t`` value *element* to the current element value.\nIf *element* is equal to value *vec* . ``end`` () ,\nwe have iterated through all the elements of the set\n( *element* is not in the set).\nIt is an error to have postings to *i*-th that have not been processed.\n\nIncrement\n=========\nThe operation ++ *itr* points *itr* to the next larger\nelement in the set.\nThe increment operation is not defined when the value of\n* *itr* is equal to *vec* . ``end`` () .\nThe operation\n\n    *element* = * (++ *itr* )\n\nincrements the iterator *itr* and sets *element*\nto the deference after the increment (see dereference above).\nIt is an error to have postings to *i*-th that have not been processed.\n\nImplementation\n**************\n{xrst_toc_hidden\n    include/cppad/local/sparse/list_setvec.hpp\n    include/cppad/local/sparse/pack_setvec.xrst\n}\n\n.. csv-table::\n    :widths: auto\n\n    list_setvec,:ref:`list_setvec-title`\n    pack_setvec,:ref:`pack_setvec-title`\n\n{xrst_end SetVector}\n"
  },
  {
    "path": "include/cppad/local/sparse/size_setvec.hpp",
    "content": "# ifndef CPPAD_LOCAL_SPARSE_SIZE_SETVEC_HPP\n# define CPPAD_LOCAL_SPARSE_SIZE_SETVEC_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/local/pod_vector.hpp>\n/*\n{xrst_begin_parent size_setvec dev}\n\nImplement SetVector Using Singly Linked Lists\n#############################################\n\nNamespace\n*********\nThis class is in the ``CppAD::local::sparse`` namespace.\n\nPublic\n******\nThe public member functions for the ``size_setvec`` class implements the\n:ref:`SetVector-name` concept when *s_type* is ``size_t`` .\n\n{xrst_end size_setvec}\n*/\n\n// BEGIN_CPPAD_LOCAL_SPARSE_NAMESPACE\nnamespace CppAD { namespace local { namespace sparse {\n\n// forward declaration of iterator class\ntemplate <class s_type> class size_setvec_const_iterator;\n\n// =========================================================================\ntemplate <class s_type>\nclass size_setvec { // BEGIN_CLASS_LIST_SETVEC\n// =========================================================================\n\n/*\n-------------------------------------------------------------------------------\n{xrst_begin size_setvec_member_data dev}\n{xrst_spell\n    struct\n}\n\nclass size_setvec: Private Member Data\n######################################\n\npair_s_type\n***********\nThis ``struct`` is local to the ``size_setvec`` class.\nIt is the type used for each entry in a singly linked list\nand has the following fields:\n\nvalue\n=====\nThe is the value of an entry in the list\n(for sets, the first entry in the list is a reference count).\n\nnext\n====\nThis is the index in ``data_`` for the next entry in the list.\nIf there are no more entries in the list, this value is zero; i.e.,\n``data_[0]`` is used to represent the end of a list.\n\nend\\_\n*****\nThe possible elements in each set are ``0`` , ``1`` , ...,\n``end_-1``\n\nnumber_not_used\\_\n*****************\nNumber of elements of the ``data_`` vector that are not being used.\n\ndata_not_used\\_\n***************\nIndex in ``data_`` for the start of the linked list of elements\nthat are not being used.\n\ndata\\_\n******\nThe data for all the singly linked lists.\nIf *n_set*  > 0 ,\n``data`` [0]. ``value`` == ``end_`` and\n``data`` [0]. ``next`` == 0 .\n\nstart\\_\n*******\nThe size of this vector is the number of set; i.e.,\n:ref:`SetVector@Vector Operations@n_set` .\nThe starting index for *i*-th set is ``start_`` [ *i* ] .\nIf ``start_`` [ *i* ] == 0 , the i-th set has no elements.\nOtherwise it is the index of the reference count for the list.\n\nReference Count\n===============\nIf ``start_`` [ *i* ] != 0 , ``data_`` [ ``start_`` [ *i* ]]. ``value``\nis the reference count for the *i*-th list\n(not the value of an element in the list).\nThe reference count must be greater than zero.\n\nFirst Element\n=============\nIf ``start_`` [ *i* ] != 0 ,\n\n    *first_index* = ``data_`` [ ``start_`` [ *i* ]]. ``next``\n\nis the index of the first element in the list.\nThis must be non-zero because the list is empty.\n\nNext Element\n============\nStarting with *index* = *first_index* ,\nwhile *index*  != 0 ,\nThe value of the corresponding element in the list is\n``data_`` [ *index* ]. ``value`` (which must be less than ``end_`` ).\nThe *index* for the next element of the list is\n``data_`` [ *index* ]. ``next`` .\n\nLast Element\n============\nAn index *last* corresponds to the last element of a list if\n``data_`` [ *last* ]. ``next`` == 0 .\n(Note that ``data_[0].value == end_`` ).\n\npost\\_\n******\nThe size of this vector is the number of set; i.e.,\n:ref:`SetVector@Vector Operations@n_set` .\nStarting with *index* = ``post_`` [ *i* ] ,\nwhile *index*  != 0 ,\nThe value of the next element posted to the *i*-th list is\n``data_`` [ *index* ]. ``value`` (which must be less than ``end_`` ).\nThe *index* for the next element posted to the *i*-th list is\n``data_`` [ *index* ]. ``next`` .\n\ntemporary\\_\n***********\nA temporary vector, used by member functions, that keeps its capacity\nto avoid re-allocating memory.\nIf a member function calls another,\nno conditions about ``temporary_`` should be assumed during that call.\n\nSource Code\n***********\n{xrst_spell_off}\n{xrst_code hpp} */\nprivate:\n    struct pair_s_type {s_type value; s_type next; };\n    friend bool CppAD::local::is_pod<pair_s_type>(void);\n    //\n    s_type                   end_;\n    s_type                   number_not_used_;\n    s_type                   data_not_used_;\n    //\n    pod_vector<pair_s_type> data_;\n    pod_vector<s_type>      start_;\n    pod_vector<s_type>      post_;\n    pod_vector<s_type>      temporary_;\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end size_setvec_member_data}\n------------------------------------------------------------------------------\n{xrst_begin size_setvec_reference_count dev}\n\nclass size_setvec private: Number of References to a Set\n########################################################\n\nSyntax\n******\n| *count* = *vec* . ``reference_count`` ( *i* )\n\nvec\n***\nIs a ``size_setvec`` object and can be ``const`` .\n\ni\n*\nis the index of the set that we are retrieving the references for.\n\ncount\n*****\nis the reference count.\n\nPrototype\n*********\n{xrst_spell_off}\n{xrst_code hpp} */\nprivate:\n    s_type reference_count(s_type i) const\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end size_setvec_reference_count}\n*/\n    {   // start data index\n        s_type start = start_[i];\n        if( start == 0 )\n            return 0;\n        //\n        // reference count\n        return data_[start].value;\n    }\n/*\n------------------------------------------------------------------------------\n{xrst_begin size_setvec_drop dev}\nclass size_setvec private: Drop a Set No Longer Being Used\n##########################################################\n\nSyntax\n******\n*not_used* = *vec* . ``drop`` ( *i* )\n\ni\n*\nis the index of the set that is dropped.\n\nreference_count\n***************\nif the set is non-empty, the\n:ref:`size_setvec_member_data@start_@Reference Count`\nis decremented.\n\nstart\\_\n*******\nThe value ``start_`` [ *i* ] is set to zero; i.e.,\nthe *i*-th set is empty after the call.\n\npost\\_\n******\nThe value ``post_`` [ *i* ] is set to zero; i.e.,\nany postings to the list are also dropped.\n\ndata_not_used\\_\n***************\nThe elements of ``data_`` were information for the *i*-th set,\nand are no longer being used, are added to the linked list starting at\n``data_not_used`` .\nThis includes both set elements and postings.\n\nnot_used\n********\nis the number of elements of ``data_`` that were begin used for the\n*i*-th set and are no longer being used; i.e., the number of elements\nmoved to ``data_not_used`` .\n\nPrototype\n*********\n{xrst_spell_off}\n{xrst_code hpp} */\nprivate:\n    s_type drop(s_type i)\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end size_setvec_drop}\n*/\n    {   // initialize count of addition elements not being used.\n        s_type number_drop = 0;\n\n        // the elements in the post list will no longer be used\n        s_type post = post_[i];\n        if( post != 0 )\n        {   // drop this posting\n            post_[i]    = 0;\n            //\n            // count elements in this posting\n            ++number_drop;\n            s_type previous = post;\n            s_type next     = data_[previous].next;\n            while( next != 0 )\n            {   previous = next;\n                next     = data_[previous].next;\n                ++number_drop;\n            }\n            //\n            // add the posting elements to data_not_used_\n            data_[previous].next = data_not_used_;\n            data_not_used_       = post;\n        }\n\n        // check for empty set\n        s_type start = start_[i];\n        if( start == 0 )\n            return number_drop;\n\n        // decrement reference counter\n        CPPAD_ASSERT_UNKNOWN( data_[start].value > 0 );\n        data_[start].value--;\n\n        // set this set to empty\n        start_[i] = 0;\n\n        // If new reference count is positive, the list corresponding to\n        // start is still being used.\n        if( data_[start].value > 0 )\n            return number_drop;\n\n        //\n        // count elements representing this set\n        ++number_drop;\n        s_type previous = start;\n        s_type next     = data_[previous].next;\n        while( next != 0 )\n        {   previous = next;\n            next     = data_[previous].next;\n            ++number_drop;\n        }\n        //\n        // add representing this set to data_not_used_\n        data_[previous].next = data_not_used_;\n        data_not_used_       = start;\n        //\n        return number_drop;\n    }\n/*\n------------------------------------------------------------------------------\n{xrst_begin size_setvec_get_data_index dev}\n\nclass size_setvec private: Get a New List Pair\n##############################################\n\nSyntax\n******\n*index* = *vec* . ``get_data_index`` ()\n\nvec\n***\nIs a ``size_setvec`` object.\n\ndata_not_used\\_\n***************\nIf the input value of ``data_not_used_`` is zero,\nit is not changed.\nOtherwise, the index for the element at the front of that list is returned.\nIn this case,\n``data_not_used`` is advanced to the next element in that list.\n\nnumber_not_used\\_\n*****************\nIf the input value of ``data_not_used_`` is zero,\n``number_not_used_`` is not changed.\nOtherwise it is decremented by one.\n\nindex\n*****\nIf the input value of ``data_not_used_`` is zero,\nthe size of ``data_`` is increased by one and index corresponding\nto the end of ``data_`` is returned.\nOtherwise, the input value for ``data_not_used_`` is returned.\n\nPrototype\n*********\n{xrst_spell_off}\n{xrst_code hpp} */\nprivate:\n    s_type get_data_index(void)\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end size_setvec_get_data_index}\n*/\n    {  s_type index;\n        if( data_not_used_ > 0 )\n        {  CPPAD_ASSERT_UNKNOWN( number_not_used_ > 0 );\n            --number_not_used_;\n            index          = data_not_used_;\n            data_not_used_ = data_[index].next;\n        }\n        else\n        {  index = s_type( data_.extend(1) );\n        }\n        return index;\n    }\n/*\n-------------------------------------------------------------------------------\n{xrst_begin size_setvec_check_data_structure dev}\n\nclass size_setvec private: Check Data Structure\n###############################################\n\nSyntax\n******\n*vec* . ``check_data_structure`` ()\n\nvec\n***\nIs a ``size_setvec`` object that is effectively const.\nIt is not declared const because the data structure is modified and\nthen restored.\n\nNDEBUG\n******\nIf ``NDEBUG`` is defined, the routine does nothing.\nOtherwise, if an error is found in the data structure,\na ``CPPAD_ASSERT_UNKNOWN`` is generated.\n\nPrototype\n*********\n{xrst_spell_off}\n{xrst_code hpp} */\nprivate:\n    void check_data_structure(void)\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end size_setvec_check_data_structure}\n*/\n# ifdef NDEBUG\n    {  return; }\n# else\n    {  // number of sets\n        CPPAD_ASSERT_UNKNOWN( s_type( post_.size() ) == s_type( start_.size() ) );\n        s_type n_set = s_type( start_.size() );\n        if( n_set == 0 )\n        {  CPPAD_ASSERT_UNKNOWN( end_ == 0 );\n            CPPAD_ASSERT_UNKNOWN( number_not_used_ == 0 );\n            CPPAD_ASSERT_UNKNOWN( data_not_used_ == 0 );\n            CPPAD_ASSERT_UNKNOWN( s_type( data_.size() ) == 0 );\n            CPPAD_ASSERT_UNKNOWN( s_type( start_.size() ) == 0 );\n            return;\n        }\n        // check data index zero\n        CPPAD_ASSERT_UNKNOWN( data_[0].value == end_ );\n        CPPAD_ASSERT_UNKNOWN( data_[0].next  == 0  );\n        // -----------------------------------------------------------\n        // save a copy of the reference counters in temporary_\n        temporary_.resize( size_t(n_set) );\n        for(s_type i = 0; i < n_set; i++)\n            temporary_[i] = reference_count(i);\n        // -----------------------------------------------------------\n        // Initialize number of entries in data used by sets and posts.\n        // Start with 1 for data_[0].\n        s_type number_used_by_sets = 1;\n        // -----------------------------------------------------------\n        // count the number of entries in data_ that are used by sets\n        for(s_type i = 0; i < n_set; i++)\n        {  s_type start = start_[i];\n            if( start > 0 )\n            {  // check structure for this non-empty set\n                s_type reference_count = data_[start].value;\n                s_type next            = data_[start].next;\n                CPPAD_ASSERT_UNKNOWN( reference_count > 0 );\n                CPPAD_ASSERT_UNKNOWN( next != 0 );\n                CPPAD_ASSERT_UNKNOWN( data_[next].value < end_ );\n                //\n                // decrement the reference counter\n                data_[start].value--;\n                //\n                // count the entries when find last reference\n                if( data_[start].value == 0 )\n                {\n                    // restore reference count\n                    data_[start].value = temporary_[i];\n\n                    // number of data entries used for this set\n                    number_used_by_sets += number_elements(i) + 1;\n                    /*\n                    number of elements checks that value < end_\n                    .resizeeach pair in the list except for the start pair\n                    and the pair with index zero.\n                    */\n                }\n            }\n        }\n        // ------------------------------------------------------------------\n        // count the number of entries in data_ that are used by posts\n        s_type number_used_by_posts = 0;\n        for(s_type i = 0; i < n_set; i++)\n        {  s_type post = post_[i];\n            if( post > 0 )\n            {  s_type value = data_[post].value;\n                s_type next  = data_[post].next;\n                CPPAD_ASSERT_UNKNOWN( value < end_ );\n                //\n                while( value < end_ )\n                {  ++number_used_by_posts;\n                    value = data_[next].value;\n                    next  = data_[next].next;\n                }\n            }\n        }\n        // ------------------------------------------------------------------\n        // count number of entries in data_not_used_\n        s_type count = 0;\n        s_type next = data_not_used_;\n        while( next != 0 )\n        {  ++count;\n            next = data_[next].next;\n        }\n        CPPAD_ASSERT_UNKNOWN( number_not_used_ == count );\n        // ------------------------------------------------------------------\n        s_type number_used = number_used_by_sets + number_used_by_posts;\n        CPPAD_ASSERT_UNKNOWN(\n            number_used + number_not_used_ == s_type( data_.size() )\n        );\n        return;\n    }\n# endif\n/*\n-------------------------------------------------------------------------------\n{xrst_begin size_setvec_vec_memory dev}\n\nclass size_setvec: Approximate Memory Used by Vector\n####################################################\n\nPublic\n******\nThis function is declared public, but is not part of\n:ref:`SetVector-name` concept.\n\nImplementation\n**************\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    s_type memory(void) const\n    {  return data_.capacity() * sizeof(pair_s_type); }\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end size_setvec_vec_memory}\n-------------------------------------------------------------------------------\n{xrst_begin size_setvec_vec_print dev}\n\nclass size_setvec: Print a Vector of Sets\n#########################################\n\nPublic\n******\nThis function is declared public, but is not part of\n:ref:`SetVector-name` concept.\n\nPrototype\n*********\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    void print(void) const;\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end size_setvec_vec_print}\n-------------------------------------------------------------------------------\n{xrst_begin size_setvec_iterators dev}\n{xrst_spell\n    typedef\n}\n\nclass size_setvec: Iterators\n############################\n\nSetVector Concept\n*****************\n:ref:`SetVector@const_iterator`\n\ntypedef\n*******\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    friend class size_setvec_const_iterator<s_type>;\n    typedef size_setvec_const_iterator<s_type> const_iterator;\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end size_setvec_iterators}\n-------------------------------------------------------------------------------\n{xrst_begin size_setvec_default_ctor dev}\n\nclass size_setvec: Default Constructor\n######################################\n\nSetVector Concept\n*****************\n:ref:`SetVector@Vector Operations@Constructor`\n\ns_type Members\n**************\nAll of the ``s_type`` member variables are initialized as zero.\n\npod_vector Members\n******************\nAll of the ``pod_vector`` member variables are initialized\nusing their default constructors.\n\nImplementation\n**************\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    size_setvec(void)\n    : end_(0), number_not_used_(0), data_not_used_(0)\n    { }\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end size_setvec_default_ctor}\n-------------------------------------------------------------------------------\n{xrst_begin size_setvec_destructor dev}\n\nclass size_setvec: Destructor\n#############################\n\nImplementation\n**************\nIf ``NDEBUG`` is not defined,\n:ref:`check data structure<size_setvec_check_data_structure-name>` .\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    ~size_setvec(void)\n    {  check_data_structure(); }\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end size_setvec_destructor}\n-------------------------------------------------------------------------------\n{xrst_begin size_setvec_copy_ctor dev}\n\nclass size_setvec: Copy Constructor\n###################################\n\nv\n*\nThe vector of sets that we are attempting to make a copy of.\n\nImplementation\n**************\nUsing the copy constructor is probably due to a ``size_setvec``\nbeing passed by value instead of by reference.\nThis is a CppAD programing error (not CppAD user error).\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    size_setvec(const size_setvec& v)\n    {  CPPAD_ASSERT_UNKNOWN(false); }\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end size_setvec_copy_ctor}\n-------------------------------------------------------------------------------\n{xrst_begin size_setvec_vec_resize dev}\n\nclass size_setvec: Vector resize\n################################\n\nSetVector Concept\n*****************\n:ref:`vector resize<SetVector@Vector Operations@resize>`\n\nPrototype\n*********\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    void resize(s_type n_set, s_type end)\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end size_setvec_vec_resize}\n*/\n    {  check_data_structure();\n\n        if( n_set == 0 )\n        {  CPPAD_ASSERT_UNKNOWN( end == 0 );\n            //\n            // restore object to start after constructor\n            // (no memory allocated for this object)\n            data_.clear();\n            start_.clear();\n            post_.clear();\n            number_not_used_  = 0;\n            data_not_used_    = 0;\n            end_              = 0;\n            //\n            return;\n        }\n        end_                   = end;\n        //\n        start_.resize( size_t(n_set) );\n        post_.resize(  size_t(n_set) );\n        //\n        for(s_type i = 0; i < n_set; i++)\n        {  start_[i] = 0;\n            post_[i]  = 0;\n        }\n        //\n        // last element, marks the end for all lists\n        data_.resize(1);\n        data_[0].value    = end_;\n        data_[0].next     = 0;\n        //\n        number_not_used_  = 0;\n        data_not_used_    = 0;\n    }\n/* %$$\n-------------------------------------------------------------------------------\n{xrst_begin size_setvec_vec_n_set dev}\n\nclass size_setvec: Number of Sets\n#################################\n\nSetVector Concept\n*****************\n:ref:`SetVector@Vector Operations@n_set`\n\nImplementation\n**************\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    s_type n_set(void) const\n    {  return s_type( start_.size() ); }\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end size_setvec_vec_n_set}\n-------------------------------------------------------------------------------\n{xrst_begin size_setvec_vec_end dev}\n\nclass size_setvec: End Value\n############################\n\nSetVector Concept\n*****************\n:ref:`SetVector@Vector Operations@end`\n\nImplementation\n**************\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    s_type end(void) const\n    {  return end_; }\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end size_setvec_vec_end}\n-------------------------------------------------------------------------------\n{xrst_begin size_setvec_vec_assignment dev}\n\nclass size_setvec: Vector Assignment\n####################################\n\nSetVector Concept\n*****************\n:ref:`vector assignment<SetVector@Vector Operations@Assignment>`\n\nPrototype\n*********\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    void operator=(const size_setvec& other)\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end size_setvec_vec_assignment}\n*/\n    {  end_             = other.end_;\n        number_not_used_ = other.number_not_used_;\n        data_not_used_   = other.data_not_used_;\n        data_            = other.data_;\n        start_           = other.start_;\n        post_            = other.post_;\n    }\n/*\n-------------------------------------------------------------------------------\n{xrst_begin size_setvec_vec_swap dev}\n\nclass size_setvec: Vector Swap\n##############################\n\nSetVector Concept\n*****************\n:ref:`vector swap<SetVector@Vector Operations@swap>`\n\nPrototype\n*********\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    void swap(size_setvec& other)\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end size_setvec_vec_swap}\n*/\n    {  // s_type objects\n        std::swap(end_             , other.end_);\n        std::swap(number_not_used_ , other.number_not_used_);\n        std::swap(data_not_used_   , other.data_not_used_);\n\n        // pod_vectors\n        data_.swap(       other.data_);\n        start_.swap(      other.start_);\n        post_.swap(       other.post_);\n        temporary_.swap(  other.temporary_);\n    }\n/*\n-------------------------------------------------------------------------------\n{xrst_begin size_setvec_number_elements dev}\n\nclass size_setvec: Number of Elements in a Set\n##############################################\n\nSetVector Concept\n*****************\n:ref:`SetVector@number_elements`\n\nPrototype\n*********\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    s_type number_elements(s_type i) const\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end size_setvec_number_elements}\n*/\n    {  CPPAD_ASSERT_UNKNOWN( post_[i] == 0 );\n\n        // check if the set is empty\n        s_type start   = start_[i];\n        if( start == 0 )\n            return 0;\n\n        // initialize counter\n        s_type count   = 0;\n\n        // advance to the first element in the set\n        s_type next    = data_[start].next;\n        while( next != 0 )\n        {  CPPAD_ASSERT_UNKNOWN( data_[next].value < end_ );\n            count++;\n            next  = data_[next].next;\n        }\n        CPPAD_ASSERT_UNKNOWN( count > 0 );\n        return count;\n    }\n/*\n-------------------------------------------------------------------------------\n{xrst_begin size_setvec_add_element dev}\n\nclass size_setvec: Add an Elements to a Set\n###########################################\n\nSetVector Concept\n*****************\n:ref:`SetVector@add_element`\n\nPrototype\n*********\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    void add_element(s_type i, s_type element)\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end size_setvec_add_element}\n*/\n    {   CPPAD_ASSERT_UNKNOWN( i < s_type( start_.size() ) );\n        CPPAD_ASSERT_UNKNOWN( element < end_ );\n\n        // check for case where starting set is empty\n        s_type start = start_[i];\n        if( start == 0 )\n        {   start              = get_data_index();\n            start_[i]          = start;\n            data_[start].value = 1; // reference count\n            //\n            s_type next        = get_data_index();\n            data_[start].next  = next;\n            //\n            data_[next].value  = element;\n            data_[next].next   = 0;\n            return;\n        }\n        //\n        // start of set with this index\n        s_type previous = start_[i];\n        //\n        // first entry in this set\n        s_type next     = data_[previous].next;\n        s_type value    = data_[next].value;\n        //\n        // locate place to insert this element\n        while( value < element )\n        {   previous = next;\n            next     = data_[next].next;\n            value = data_[next].value;\n        }\n        //\n        // check for case where element is in the set\n        if( value == element )\n            return;\n        //\n        //\n        // check for case where this is the only reference to this set\n        CPPAD_ASSERT_UNKNOWN( element < value );\n        if( data_[start].value == 1 )\n        {   s_type insert         = get_data_index();\n            data_[insert].next    = next;\n            data_[insert].value   = element;\n            data_[previous].next  = insert;\n            //\n            return;\n        }\n        //\n        // must make a separate copy with new element inserted\n        CPPAD_ASSERT_UNKNOWN( data_[start].value > 1 );\n        data_[start].value--;   // reverence counter for old list\n        //\n        s_type start_new       = get_data_index();\n        data_[start_new].value = 1;         // reference counter for new list\n        s_type previous_new    = start_new;\n        //\n        // start of old set with this index\n        previous  = start_[i];\n        //\n        // first entry in old set\n        next    = data_[previous].next;\n        value   = data_[next].value;\n        //\n        // locate place to insert this element\n        while( value < element )\n        {   // copy to new list\n            s_type next_new          = get_data_index();\n            data_[previous_new].next = next_new;\n            data_[next_new].value    = value;\n            previous_new             = next_new;\n            //\n            // get next value\n            previous = next;\n            next     = data_[next].next;\n            value = data_[next].value;\n        }\n        CPPAD_ASSERT_UNKNOWN( element < value );\n        //\n        // insert the element\n        s_type next_new          = get_data_index();\n        data_[previous_new].next = next_new;\n        data_[next_new].value    = element;\n        previous_new             = next_new;\n        //\n        // copy rest of the old set\n        while( value < end_ )\n        {   // copy to new list\n            next_new                 = get_data_index();\n            data_[previous_new].next = next_new;\n            data_[next_new].value    = value;\n            previous_new             = next_new;\n            //\n            // get next value\n            previous = next;\n            next     = data_[next].next;\n            value = data_[next].value;\n        }\n        CPPAD_ASSERT_UNKNOWN( next == 0 );\n        data_[previous_new].next = 0;\n        //\n        // hook up new list\n        start_[i] = start_new;\n        return;\n    }\n/*\n-------------------------------------------------------------------------------\n{xrst_begin size_setvec_post_element dev}\n\nclass size_setvec: Post an Elements for Addition to a Set\n#########################################################\n\nSetVector Concept\n*****************\n:ref:`SetVector@post_element`\n\npost\\_\n******\nThe element is added at the front of the linked list\nthat starts at ``post_`` .\n\nPrototype\n*********\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    void post_element(s_type i, s_type element)\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end size_setvec_post_element}\n*/\n    {   CPPAD_ASSERT_UNKNOWN( i < s_type( start_.size() ) );\n        CPPAD_ASSERT_UNKNOWN( element < end_ );\n\n        // put element at the front of this list\n        s_type next         = post_[i];\n        s_type post         = get_data_index();\n        post_[i]            = post;\n        data_[post].value   = element;\n        data_[post].next    = next;\n\n        return;\n    }\n/*\n-------------------------------------------------------------------------------\n{xrst_begin size_setvec_process_post dev}\n\nclass size_setvec: Add Posted Elements to a Set\n###############################################\n\nSetVector Concept\n*****************\n:ref:`SetVector@process_post`\n\npost\\_\n******\nUpon call, ``post_`` [ *i* ] is the linked list of elements to\nbe added to the *i*-th set.\nUpon return, ``post_`` [ *i* ] is zero; i.e., the list is empty.\n\nPrototype\n*********\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    void process_post(s_type i)\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end size_setvec_process_post}\n*/\n    {  // post\n        s_type post = post_[i];\n        //\n        // check if there are no elements to process\n        if( post == 0 )\n            return;\n        //\n        // check if there is only one element to process\n        s_type next  = data_[post].next;\n        if( next == 0 )\n        {  // done with this posting\n            s_type value     = data_[post].value;\n            post_[i]         = 0;\n            data_[post].next = data_not_used_;\n            data_not_used_   = post;\n            ++number_not_used_;\n            //\n            add_element(i, value);\n            //\n            return;\n        }\n        //\n        // copy posting to temporary_\n        temporary_.resize(0);\n        s_type previous  = post;\n        s_type value     = data_[previous].value;\n        CPPAD_ASSERT_UNKNOWN( value < end_ );\n        temporary_.push_back(value);\n        while( next != 0 )\n        {  previous = next;\n            value    = data_[previous].value;\n            CPPAD_ASSERT_UNKNOWN( value < end_ );\n            temporary_.push_back(value);\n            next     = data_[previous].next;\n        }\n        s_type number_post = s_type( temporary_.size() );\n        //\n        // done with this posting\n        post_[i]              = 0;\n        data_[previous].next  = data_not_used_;\n        data_not_used_        = post;\n        number_not_used_     += number_post;;\n        //\n        // sort temporary_\n        CPPAD_ASSERT_UNKNOWN( number_post > 1 );\n        std::sort( temporary_.data(), temporary_.data() + number_post);\n        // posting is the set { temporary_[0], ... , [number_post-1] }\n        // -------------------------------------------------------------------\n        // put union of posting and set i in\n        // temporary_[number_post], ... , temporary_[ temporary_.size()-1 ]\n        //\n        s_type i_next  = start_[i];\n        s_type i_value = end_;\n        if( i_next > 0 )\n        {  // skip reference count\n            i_next  = data_[i_next].next;\n            i_value = data_[i_next].value;\n        }\n        bool   post_is_subset = true;\n        s_type previous_post = end_;\n        for(s_type j =0; j < number_post; ++j)\n        {  s_type post_value = temporary_[j];\n            CPPAD_ASSERT_UNKNOWN( post_value < end_ );\n            while( i_value < post_value )\n            {  // i_value is in union\n                temporary_.push_back(i_value);\n                i_next  = data_[i_next].next;\n                i_value = data_[i_next].value;\n            }\n            if( i_value == post_value )\n            {  i_next  = data_[i_next].next;\n                i_value = data_[i_next].value;\n            }\n            else\n                post_is_subset = false;\n            //\n            if( previous_post != post_value )\n            {  // post_value is in union\n                temporary_.push_back(post_value);\n            }\n            previous_post = post_value;\n        }\n        // check if posting is a subset of set i\n        if( post_is_subset )\n            return;\n        //\n        // rest of elements in set i\n        while( i_value < end_ )\n        {  temporary_.push_back(i_value);\n            i_next  = data_[i_next].next;\n            i_value = data_[i_next].value;\n        }\n\n        // adjust number_not_used_\n        s_type number_drop = drop(i);\n        number_not_used_  += number_drop;\n\n        // put new set in linked list for set i\n        CPPAD_ASSERT_UNKNOWN( s_type( temporary_.size() ) >= number_post + 1 );\n        s_type index        = get_data_index();\n        start_[i]           = index; // start for the union\n        data_[index].value  = 1;    // reference count for the union\n        for(s_type j = number_post; j < s_type( temporary_.size() ); ++j)\n        {  next              = get_data_index();\n            data_[index].next = next;\n            data_[next].value = temporary_[j]; // next element in union\n            index             = next;\n        }\n        data_[index].next = 0; // end of union\n        //\n        return;\n    }\n/*\n-------------------------------------------------------------------------------\n{xrst_begin size_setvec_is_element dev}\n\nclass size_setvec: Is an Element in a Set\n#########################################\n\nSetVector Concept\n*****************\n:ref:`SetVector@is_element`\n\nPrototype\n*********\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    bool is_element(s_type i, s_type element) const\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end size_setvec_is_element}\n*/\n    {  CPPAD_ASSERT_UNKNOWN( post_[i] == 0 );\n        CPPAD_ASSERT_UNKNOWN( element < end_ );\n        //\n        s_type start = start_[i];\n        if( start == 0 )\n            return false;\n        //\n        s_type next  = data_[start].next;\n        s_type value = data_[next].value;\n        while( value < element )\n        {  next  = data_[next].next;\n            value = data_[next].value;\n        }\n        return element == value;\n    }\n/*\n-------------------------------------------------------------------------------\n{xrst_begin size_setvec_clear dev}\n\nclass size_setvec: Assign a Set to be Empty\n###########################################\n\nSetVector Concept\n*****************\n:ref:`SetVector@clear`\n\nPrototype\n*********\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    void clear(s_type target)\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end size_setvec_clear}\n*/\n    {  CPPAD_ASSERT_UNKNOWN( target < s_type( start_.size() ) );\n\n        // adjust number_not_used_\n        s_type number_drop = drop(target);\n        number_not_used_  += number_drop;\n\n        return;\n    }\n/*\n-------------------------------------------------------------------------------\n{xrst_begin size_setvec_assignment dev}\n\nclass size_setvec: Assign a Set To Equal Another Set\n####################################################\n\nSetVector Concept\n*****************\n:ref:`SetVector@assignment`\n\nPrototype\n*********\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    void assignment(\n        s_type               this_target  ,\n        s_type               other_source ,\n        const size_setvec&   other        )\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end size_setvec_assignment}\n*/\n    {  CPPAD_ASSERT_UNKNOWN( other.post_[ other_source ] == 0 );\n        //\n        CPPAD_ASSERT_UNKNOWN( this_target < s_type( start_.size() )        );\n        CPPAD_ASSERT_UNKNOWN( other_source <   s_type( other.start_.size() )  );\n        CPPAD_ASSERT_UNKNOWN( end_        == other.end_   );\n\n        // check if we are assigning a set to itself\n        if( (this == &other) && (this_target == other_source) )\n            return;\n\n        // set depending on cases below\n        s_type this_start;\n\n        // If this and other are the same, use another reference to same list\n        s_type other_start = other.start_[other_source];\n        if( this == &other )\n        {  this_start = other_start;\n            if( other_start != 0 )\n            {  data_[other_start].value++; // increment reference count\n                CPPAD_ASSERT_UNKNOWN( data_[other_start].value > 1 );\n            }\n        }\n        else if( other_start  == 0 )\n        {  this_start = 0;\n        }\n        else\n        {  // make a copy of the other list in this size_setvec\n            this_start        = get_data_index();\n            s_type this_next  = get_data_index();\n            data_[this_start].value = 1; // reference count\n            data_[this_start].next  = this_next;\n            //\n            s_type next  = other.data_[other_start].next;\n            CPPAD_ASSERT_UNKNOWN( next != 0 );\n            while( next != 0 )\n            {  data_[this_next].value = other.data_[next].value;\n                next                   = other.data_[next].next;\n                if( next == 0 )\n                    data_[this_next].next = 0;\n                else\n                {  s_type tmp = get_data_index();\n                    data_[this_next].next = tmp;\n                    this_next             = tmp;\n                }\n            }\n        }\n\n        // adjust number_not_used_\n        s_type number_drop = drop(this_target);\n        number_not_used_  += number_drop;\n\n        // set the new start value for this_target\n        start_[this_target] = this_start;\n\n        return;\n    }\n/*\n-------------------------------------------------------------------------------\n{xrst_begin size_setvec_binary_union dev}\n\nclass size_setvec: Assign a Set To Union of Two Sets\n####################################################\n\nSetVector Concept\n*****************\n:ref:`SetVector@binary_union`\n\nPrototype\n*********\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    void binary_union(\n        s_type                  this_target  ,\n        s_type                  this_left    ,\n        s_type                  other_right  ,\n        const size_setvec&      other        )\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end size_setvec_binary_union}\n*/\n    {  CPPAD_ASSERT_UNKNOWN( post_[this_left] == 0 );\n        CPPAD_ASSERT_UNKNOWN( other.post_[ other_right ] == 0 );\n        //\n        CPPAD_ASSERT_UNKNOWN( this_target < s_type( start_.size() )         );\n        CPPAD_ASSERT_UNKNOWN( this_left < s_type( start_.size() )         );\n        CPPAD_ASSERT_UNKNOWN( other_right < s_type( other.start_.size() )   );\n        CPPAD_ASSERT_UNKNOWN( end_        == other.end_           );\n\n        // start indices for left and right sets\n        s_type start_left    = start_[this_left];\n        s_type start_right   = other.start_[other_right];\n\n        // if right is empty, the result is the left set\n        if( start_right == 0 )\n        {  assignment(this_target, this_left, *this);\n            return;\n        }\n        // if left is empty, the result is the right set\n        if( start_left == 0 )\n        {  assignment(this_target, other_right, other);\n            return;\n        }\n        // if neither case holds, then both left and right are non-empty\n        CPPAD_ASSERT_UNKNOWN( reference_count(this_left) > 0 );\n        CPPAD_ASSERT_UNKNOWN( other.reference_count(other_right) > 0 );\n\n        // we will use temporary_ for temporary storage of the union\n        temporary_.resize(0);\n\n        // for left next and value\n        s_type next_left   = data_[start_left].next;\n        s_type value_left  = data_[next_left].value;\n\n        // right next and value\n        s_type next_right  = other.data_[start_right].next;\n        s_type value_right = other.data_[next_right].value;\n\n        // both left and right set are non-empty\n        CPPAD_ASSERT_UNKNOWN( value_left < end_ && value_right < end_ );\n\n        // flag that detects if left is or right is a subset of the other\n        bool left_is_subset  = true;\n        bool right_is_subset = true;\n\n        while( (value_left < end_) && (value_right < end_) )\n        {  if( value_left == value_right )\n            {  // value is in both sets\n                temporary_.push_back(value_left);\n                //\n                // advance left\n                next_left  = data_[next_left].next;\n                value_left = data_[next_left].value;\n                //\n                // advance right\n                next_right  = other.data_[next_right].next;\n                value_right = other.data_[next_right].value;\n            }\n            else if( value_left < value_right )\n            {  // need a value from left that is not in right\n                left_is_subset = false;\n                temporary_.push_back(value_left);\n                //\n                // advance left to its next element\n                next_left  = data_[next_left].next;\n                value_left = data_[next_left].value;\n            }\n            else\n            {  CPPAD_ASSERT_UNKNOWN( value_right < value_left )\n                // need a value from right that is not in left\n                right_is_subset = false;\n                temporary_.push_back(value_right);\n                //\n                // advance right to its next element\n                next_right  = other.data_[next_right].next;\n                value_right = other.data_[next_right].value;\n            }\n        }\n        right_is_subset &= value_right == end_;\n        left_is_subset  &= value_left  == end_;\n        //\n        // check right first in case they are equal will do this assignment\n        if( right_is_subset )\n        {  assignment(this_target, this_left, *this);\n            return;\n        }\n        if( left_is_subset )\n        {  assignment(this_target, other_right, other);\n            return;\n        }\n        while( value_left < end_ )\n        {  CPPAD_ASSERT_UNKNOWN( value_right == end_);\n            temporary_.push_back(value_left);\n            next_left  = data_[next_left].next;\n            value_left = data_[next_left].value;\n        }\n        while( value_right < end_ )\n        {  CPPAD_ASSERT_UNKNOWN( value_left == end_);\n            temporary_.push_back(value_right);\n            next_right  = other.data_[next_right].next;\n            value_right = other.data_[next_right].value;\n        }\n\n        // adjust number_not_used_\n        s_type number_drop = drop(this_target);\n        number_not_used_  += number_drop;\n\n        // put new set in linked for this_target\n        CPPAD_ASSERT_UNKNOWN( s_type( temporary_.size() ) >= 2 );\n        s_type index        = get_data_index();\n        start_[this_target] = index; // start for the union\n        data_[index].value  = 1;    // reference count for the union\n        for(s_type i = 0; i < s_type( temporary_.size() ); ++i)\n        {  s_type next       = get_data_index();\n            data_[index].next = next;\n            data_[next].value = temporary_[i]; // next element in union\n            index             = next;\n        }\n        data_[index].next = 0; // end of union\n\n        return;\n    }\n/*\n-------------------------------------------------------------------------------\n{xrst_begin size_setvec_binary_intersection dev}\n\nclass size_setvec: Assign a Set To Equal Another Set\n####################################################\n\nSetVector Concept\n*****************\n:ref:`SetVector@binary_intersection`\n\nPrototype\n*********\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    void binary_intersection(\n        s_type                  this_target  ,\n        s_type                  this_left    ,\n        s_type                  other_right  ,\n        const size_setvec&      other        )\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end size_setvec_binary_intersection}\n*/\n    {   CPPAD_ASSERT_UNKNOWN( post_[this_left] == 0 );\n        CPPAD_ASSERT_UNKNOWN( other.post_[ other_right ] == 0 );\n        //\n        CPPAD_ASSERT_UNKNOWN( this_target < s_type( start_.size() )         );\n        CPPAD_ASSERT_UNKNOWN( this_left < s_type( start_.size() )         );\n        CPPAD_ASSERT_UNKNOWN( other_right < s_type( other.start_.size() )   );\n        CPPAD_ASSERT_UNKNOWN( end_        == other.end_           );\n\n        // start indices for left and right sets\n        s_type start_left    = start_[this_left];\n        s_type start_right   = other.start_[other_right];\n\n        // if left or right is empty, the result is empty\n        if( (start_left == 0) || (start_right == 0) )\n        {   clear(this_target);\n            return;\n        }\n        // if neither case holds, then both left and right are non-empty\n        CPPAD_ASSERT_UNKNOWN( reference_count(this_left) > 0 );\n        CPPAD_ASSERT_UNKNOWN( other.reference_count(other_right) > 0 );\n\n        // we will use temporary_ for temporary storage of the intersection\n        temporary_.resize(0);\n\n        // left next and value\n        s_type next_left   = data_[start_left].next;\n        s_type value_left  = data_[next_left].value;\n\n        // right next and value\n        s_type next_right  = other.data_[start_right].next;\n        s_type value_right = other.data_[next_right].value;\n\n        // both left and right set are non-empty\n        CPPAD_ASSERT_UNKNOWN( value_left < end_ && value_right < end_ );\n\n        // flag that detects if left is or right is a subset of the other\n        bool left_is_subset  = true;\n        bool right_is_subset = true;\n\n        while( (value_left < end_) && (value_right < end_) )\n        {   if( value_left == value_right )\n            {   // value is in both sets\n                temporary_.push_back(value_left);\n                //\n                // advance left\n                next_left  = data_[next_left].next;\n                value_left = data_[next_left].value;\n                //\n                // advance right\n                next_right  = other.data_[next_right].next;\n                value_right = other.data_[next_right].value;\n            }\n            else if( value_left < value_right )\n            {   // there is a value in left that is not in right\n                left_is_subset = false;\n                //\n                // advance left to its next element\n                next_left  = data_[next_left].next;\n                value_left = data_[next_left].value;\n            }\n            else\n            {   CPPAD_ASSERT_UNKNOWN( value_right < value_left )\n                // there is a value in right that is not in left\n                right_is_subset = false;\n                //\n                // advance right to its next element\n                next_right  = other.data_[next_right].next;\n                value_right = other.data_[next_right].value;\n            }\n        }\n        right_is_subset &= value_right == end_;\n        left_is_subset  &= value_left  == end_;\n        //\n        // check left first in case they are equal will do this assignment\n        if( left_is_subset )\n        {   assignment(this_target, this_left, *this);\n            return;\n        }\n        if( right_is_subset )\n        {   assignment(this_target, other_right, other);\n            return;\n        }\n\n        // adjust number_not_used_\n        s_type number_drop = drop(this_target);\n        number_not_used_  += number_drop;\n\n        // check for empty result\n        if( s_type( temporary_.size() ) == 0 )\n            return;\n\n        // put new set in linked for this_target\n        s_type index        = get_data_index();\n        start_[this_target] = index; // start for the union\n        data_[index].value  = 1;    // reference count for the union\n        for(s_type i = 0; i < s_type( temporary_.size() ); ++i)\n        {   s_type next       = get_data_index();\n            data_[index].next = next;\n            data_[next].value = temporary_[i]; // next element in union\n            index             = next;\n        }\n        data_[index].next = 0; // end of union\n\n        return;\n    }\n// =========================================================================\n}; // END_CLASS_LIST_SETVEC\n// =========================================================================\n\n// =========================================================================\ntemplate <class s_type>\nclass size_setvec_const_iterator { // BEGIN_CLASS_SIZE_SETVEC_CONST_ITERATOR\n// =========================================================================\n\n/*\n{xrst_begin size_setvec_const_iterator_member_data dev}\n\nclass size_setvec_const_iterator private: Member Data\n#####################################################\n\npair_s_type\n***********\nThis type is the same as\n:ref:`size_setvec pair_s_type<size_setvec_member_data@pair_s_type>` .\n\nend\\_\n*****\nThis is\n:ref:`size_setvec_member_data@end_`\nfor the ``size_setvec`` object this iterator refers to.\n\ndata\\_\n******\nThis is\n:ref:`size_setvec_member_data@data_`\nfor the ``size_setvec`` object this iterator refers to.\n\nnext_pair\\_\n***********\nNext element in the set that this iterator refers to.\nIf ``next_pair_.value == end_`` there are no more elements in the set.\n\nSource Code\n***********\n{xrst_spell_off}\n{xrst_code hpp} */\nprivate:\n    typedef typename size_setvec<s_type>::pair_s_type pair_s_type;\n    const s_type                     end_;\n    const pod_vector<pair_s_type>&   data_;\n    pair_s_type                      next_pair_;\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end size_setvec_const_iterator_member_data}\n-------------------------------------------------------------------------------\n{xrst_begin size_setvec_const_iterator_ctor dev}\n\nclass size_setvec_const_iterator: Constructor\n#############################################\n\nSetVector Concept\n*****************\n:ref:`iterator constructor<SetVector@const_iterator@Constructor>`\n\nPrototype\n*********\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    size_setvec_const_iterator (const size_setvec<s_type>& list, s_type i)\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end size_setvec_const_iterator_ctor}\n*/\n    : end_ ( list.end_ ), data_( list.data_ )\n    {  CPPAD_ASSERT_UNKNOWN( list.post_[i] == 0 );\n        //\n        s_type start = list.start_[i];\n        if( start == 0 )\n        {  next_pair_.next  = 0;\n            next_pair_.value = end_;\n        }\n        else\n        {  // value for this entry is reference count for list\n            CPPAD_ASSERT_UNKNOWN( data_[start].value > 0 );\n\n            // data index where list truly starts\n            s_type next = data_[start].next;\n            CPPAD_ASSERT_UNKNOWN( next != 0 );\n\n            // true first entry in the list\n            next_pair_ = data_[next];\n            CPPAD_ASSERT_UNKNOWN( next_pair_.value < end_ );\n        }\n    }\n/*\n-------------------------------------------------------------------------------\n{xrst_begin size_setvec_const_iterator_dereference dev}\n\nclass size_setvec_const_iterator: Dereference\n#############################################\n\nSetVector Concept\n*****************\n:ref:`iterator deference<SetVector@const_iterator@Dereference>`\n\nImplementation\n**************\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    s_type operator*(void)\n    {  return next_pair_.value; }\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end size_setvec_const_iterator_dereference}\n-------------------------------------------------------------------------------\n{xrst_begin size_setvec_const_iterator_increment dev}\n\nclass size_setvec_const_iterator: Increment\n###########################################\n\nSetVector Concept\n*****************\n:ref:`iterator increment<SetVector@const_iterator@Increment>`\n\nImplementation\n**************\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    size_setvec_const_iterator& operator++(void)\n    {  next_pair_  = data_[next_pair_.next];\n        return *this;\n    }\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end size_setvec_const_iterator_increment}\n*/\n// ===========================================================================\n}; // END_CLASS_SIZE_SETVEC_CONST_ITERATOR\n// ===========================================================================\n\n// Implemented after size_setvec_const_iterator so can use it\ntemplate <class s_type>\ninline void size_setvec<s_type>::print(void) const\n{   std::cout << \"size_setvec:\\n\";\n    for(s_type i = 0; i < n_set(); i++)\n    {   std::cout << \"set[\" << i << \"] = {\";\n        const_iterator itr(*this, i);\n        while( *itr != end() )\n        {   std::cout << *itr;\n            if( *(++itr) != end() ) std::cout << \",\";\n        }\n        std::cout << \"}\\n\";\n    }\n    return;\n}\n// ----------------------------------------------------------------------------\n\n} } } // END_CPPAD_LOCAL_SPARSE_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/sparse/svec_setvec.hpp",
    "content": "# ifndef CPPAD_LOCAL_SPARSE_SVEC_SETVEC_HPP\n# define CPPAD_LOCAL_SPARSE_SVEC_SETVEC_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/local/define.hpp>\n# include <cppad/local/is_pod.hpp>\n# include <list>\n\n// BEGIN_CPPAD_LOCAL_SPARSE_NAMESPACE\nnamespace CppAD { namespace local { namespace sparse {\n\n/*!\n\\file svec_setvec.hpp\nVector of sets of positive integers stored as size_t vector\nwith the element values strictly increasing.\n\nTesting indicates this does not work as well as using sparse::list_setvec\n(not currently being used except by test_more/general/local/vector_set.cpp).\n*/\nclass svec_setvec_const_iterator;\n\n// =========================================================================\n/*!\nVector of sets of positive integers, each set stored as a size_t vector.\n\nAll the public members for this class are also in the\nsparse::pack_setvec and sparse::list_setvec classes.\nThis defines the CppAD vector_of_sets concept.\n*/\nclass svec_setvec {\n    friend class svec_setvec_const_iterator;\nprivate:\n    /// Possible elements in each set are 0, 1, ..., end_ - 1;\n    size_t end_;\n\n    /// number of elements in data_ that have been allocated\n    /// and are no longer being used.\n    size_t data_not_used_;\n\n    /// The data for all the singly linked lists.\n    pod_vector<size_t> data_;\n\n    /*!\n    Starting point for i-th set is start_[i].\n\n    \\li\n    If the i-th set has no elements, start_[i] is zero.\n    Othersize the conditions below hold.\n\n    \\li\n    data_[ start_[i] ] is the reference count for this set\n\n    \\li\n    data_[ start_[i] + 1 ] is the first element in this set.\n\n    \\li\n    data_[ start_[i] + 2 ] is the first element in this set.\n\n    \\li\n    data_[ start_[i] + 2 + n ] = end_ where n is the number of\n    elements in this set\n    */\n    pod_vector<size_t> start_;\n\n    /*!\n    Vectors of elements that have not yet been added to corresponding sets.\n\n    \\li\n    If all the post_element calls for the i-th set have been added,\n    post_[i] is zero. Otherwise the conditions below hold.\n\n    \\li\n    data_[ post_[i] ]  the number of elements that have been posted,\n    but not yet added, to set i.\n\n    \\li\n    data_[ post_[i] + 1 ] is the capacity for holding elements\n    which is greater than or equal the number of elements.\n\n    \\li\n    data_[ post_[i] + 2 ] is the first element that has been posted,\n    but not yet added, to set i.\n\n    \\li\n    data_[ post_[i] + 1 + n] is the last element that has been posted,\n    but not yet added, to set i.\n    Here n is the number of elements that are posted and not yet added\n    to set i.\n    */\n    pod_vector<size_t> post_;\n    // -----------------------------------------------------------------\n    /*!\n    Counts references to a set.\n\n    \\param i\n    is the index of the set that we are counting the references to.\n\n    \\return\n    if the set is empty, the return value is zero.\n    Otherwise it is the number of sets that share the same vector.\n    */\n    size_t reference_count(size_t i) const\n    {   // start data index\n        size_t start = start_[i];\n        if( start == 0 )\n            return 0;\n        //\n        // reference count\n        return data_[start];\n    }\n    // -----------------------------------------------------------------\n    /*!\n    drop a set.\n\n    \\param i\n    is the index of the set that will be dropped.\n\n    \\par reference_count\n    if the set is non-empty,\n    the reference count corresponding to index will be decremented.\n\n    \\return\n    is the number of elements of data_ that will be lost when the set is\n    dropped. This is non-zero when the initial reference count is one.\n    */\n    size_t drop(size_t i)\n    {\n        // reference count\n        size_t ref_count = reference_count(i);\n\n        // empty set case\n        if( ref_count == 0 )\n            return 0;\n\n        // start\n        size_t start = start_[i];\n        CPPAD_ASSERT_UNKNOWN( data_[start] == ref_count );\n\n        // decrement reference counter\n        data_[start]--;\n\n        // nothing lost unless new reference count is zero\n        if( ref_count != 1 )\n            return 0;\n\n        // number of elements in the set\n        size_t length = data_[start + 1];\n\n        // reference count, length, end marker, plus elements in set\n        size_t number_lost = 3 + length;\n\n        // number_lost\n        return number_lost;\n    }\n    // -----------------------------------------------------------------\n    /*!\n    Checks data structure\n    (effectively const, but modifies and restores values)\n    */\n# ifdef NDEBUG\n    void check_data_structure(void)\n    {   return; }\n# else\n    void check_data_structure(void)\n    {   // number of sets\n        CPPAD_ASSERT_UNKNOWN( post_.size() == start_.size() );\n        size_t n_set = start_.size();\n        if( n_set == 0 )\n        {   CPPAD_ASSERT_UNKNOWN( end_ == 0 );\n            CPPAD_ASSERT_UNKNOWN( data_not_used_ == 0 );\n            CPPAD_ASSERT_UNKNOWN( data_.size() == 0 );\n            CPPAD_ASSERT_UNKNOWN( start_.size() == 0 );\n            CPPAD_ASSERT_UNKNOWN( post_.size() == 0 );\n            return;\n        }\n        // ------------------------------------------------------------------\n        // save the reference counters\n        pod_vector<size_t> ref_count(n_set);\n        for(size_t i = 0; i < n_set; i++)\n            ref_count[i] = reference_count(i);\n        // ------------------------------------------------------------------\n\n        // ------------------------------------------------------------------\n        // count the number of entries in data_ that are used by sets\n        size_t data_used_by_sets = 0;\n        for(size_t i = 0; i < n_set; i++)\n        {   size_t start = start_[i];\n            if( start > 0 )\n            {   // check structure for this non-empty set\n                size_t reference_count = data_[start + 0];\n                size_t length          = data_[start + 1];\n                size_t first           = data_[start + 2];\n                size_t last            = data_[start + 2 + length];\n                CPPAD_ASSERT_UNKNOWN( reference_count > 0 );\n                CPPAD_ASSERT_UNKNOWN( length          > 0 );\n                CPPAD_ASSERT_UNKNOWN( first < end_);\n                CPPAD_ASSERT_UNKNOWN( last == end_);\n                //\n                // decrement the reference counter\n                data_[start]--;\n                //\n                // count the entries when find last reference\n                if( data_[start] == 0 )\n                {\n                    // restore reference count\n                    data_[start] = ref_count[i];\n\n                    // number of data_ entries used for this set\n                    data_used_by_sets += number_elements(i) + 3;\n                }\n            }\n        }\n        // ------------------------------------------------------------------\n        // count the number of entries in data_ that are used by posts\n        size_t data_used_by_posts = 0;\n        for(size_t i = 0; i < n_set; i++)\n        {   size_t post = post_[i];\n            if( post > 0 )\n            {   CPPAD_ASSERT_UNKNOWN( data_[post] > 0 );\n                CPPAD_ASSERT_UNKNOWN( data_[post + 1] > 0 );\n                CPPAD_ASSERT_UNKNOWN( data_[post + 2] < end_ );\n                //\n                size_t capacity     = data_[post + 1];\n                data_used_by_posts += capacity + 2;\n            }\n        }\n        // ------------------------------------------------------------------\n        size_t data_used = data_used_by_sets + data_used_by_posts;\n        CPPAD_ASSERT_UNKNOWN(\n            data_used + data_not_used_ == data_.size()\n        );\n        return;\n    }\n# endif\n    // -----------------------------------------------------------------\n    /*!\n    Check if one of two sets is a subset of the other set\n\n    \\param one_this\n    is the index in this svec_setvec object of the first set.\n\n    \\param two_other\n    is the index in other svec_setvec object of the second set.\n\n    \\param other\n    is the other svec_setvec object which may be the same as this object.\n\n    \\return\n    If zero, neither set is a subset of the other.\n    If one, then one is a subset of two and they are not equal.\n    If two, then two is a subset of one and they are not equal.\n    If three, then the sets are equal.\n    */\n    size_t is_subset(\n        size_t                     one_this    ,\n        size_t                     two_other   ,\n        const svec_setvec&         other       ) const\n    {\n        CPPAD_ASSERT_UNKNOWN( one_this  < start_.size()         );\n        CPPAD_ASSERT_UNKNOWN( two_other < other.start_.size()   );\n        CPPAD_ASSERT_UNKNOWN( end_  == other.end_               );\n        //\n        // start\n        size_t start_one    = start_[one_this];\n        size_t start_two    = other.start_[two_other];\n        //\n        if( start_one == 0 )\n        {   // set one is empty\n            if( start_two == 0 )\n            {   // set two is empty\n                return 3;\n            }\n            // set one is empty and two is not empty\n            return 1;\n        }\n        if( start_two == 0 )\n        {   // set two is empty and one is not empty\n            return 2;\n        }\n        //\n        // data index\n        size_t index_one    = start_one + 2;\n        size_t index_two    = start_two + 2;\n        //\n        // value\n        size_t value_one    = data_[index_one];\n        size_t value_two    = other.data_[index_two];\n        //\n        bool one_subset     = true;\n        bool two_subset     = true;\n        //\n        size_t value_union = std::min(value_one, value_two);\n        while( (one_subset | two_subset) && (value_union < end_) )\n        {   //\n            if( value_one > value_union )\n                two_subset = false;\n            else\n            {   // value_one <= value_two and value_one < end_\n                value_one = data_[++index_one];\n            }\n            //\n            if( value_two > value_union )\n                one_subset = false;\n            else\n            {   // value_two <= value_one and value_two < end_\n                value_two = other.data_[++index_two];\n            }\n            value_union = std::min(value_one, value_two);\n        }\n        if( one_subset )\n        {   if( two_subset )\n            {   // sets are equal\n                return 3;\n            }\n            // one is a subset of two\n            return 1;\n        }\n        if( two_subset )\n        {   // two is a subset of one\n            return 2;\n        }\n        //\n        // neither is a subset\n        return 0;\n    }\n    // -----------------------------------------------------------------\n    /*!\n    Does garbage collection when indicated.\n\n    This routine should be called when more entries are not being used.\n    If a significant proportion are not being used, the data structure\n    will be compacted.\n\n    The size of data_ should equal the number of entries used by the sets\n    plus the number of entries that are not being used data_not_used_.\n    Note that data_[0] never gets used.\n    */\n    void collect_garbage(void)\n    {   if( data_not_used_ < data_.size() / 2 +  100)\n            return;\n        check_data_structure();\n        //\n        // number of sets including empty ones\n        size_t n_set  = start_.size();\n        //\n        // use temporary to hold copy of data_ and start_\n        pod_vector<size_t> data_tmp(1); // data_tmp[0] will not be used\n        pod_vector<size_t> start_tmp(n_set);\n        //\n        for(size_t i = 0; i < n_set; i++)\n        {   size_t start    = start_[i];\n            if( start == 0 )\n                start_tmp[i] = 0;\n            else\n            {   // check if this set has already been copied\n                if( data_[start] == 0 )\n                {   // starting address in data_tmp has been stored here\n                    start_tmp[i] = data_[start + 1];\n                }\n                else\n                {   size_t tmp_start          = data_tmp.extend(2);\n                    start_tmp[i]              = tmp_start;\n                    data_tmp[tmp_start + 0]   = data_[start + 0];\n                    data_tmp[tmp_start + 1]   = data_[start + 1];\n                    //\n                    for(size_t j = 2; data_[start + j] != end_; ++j)\n                        data_tmp.push_back( data_[start + j] );\n                    data_tmp.push_back(end_);\n                    //\n                    // flag that indicates this set already copied\n                    data_[start] = 0;\n                    //\n                    // store the starting address here\n                    data_[start + 1] = tmp_start;\n                }\n            }\n        }\n\n        // swap the tmp and old data vectors\n        start_.swap(start_tmp);\n        data_.swap(data_tmp);\n\n        // all of the elements, except the first, are used\n        data_not_used_ = 1;\n    }\n    // -----------------------------------------------------------------\n    /*!\n    Assign a set equal to the union of a set and a vector;\n\n    \\param target\n    is the index in this svec_setvec object of the set being assigned.\n\n    \\param left\n    is the index in this svec_setvec object of the\n    left operand for the union operation.\n    It is OK for target and left to be the same value.\n\n    \\param right\n    is a vector of size_t, sorted in ascending order.\n    right operand for the union operation.\n    Elements can be repeated in right, but are not be repeated in the\n    resulting set.\n    All of the elements must have value less than end();\n    */\n    void binary_union(\n        size_t                    target ,\n        size_t                    left   ,\n        const pod_vector<size_t>& right  )\n    {   CPPAD_ASSERT_UNKNOWN( post_[left] == 0 );\n        //\n        CPPAD_ASSERT_UNKNOWN( target < start_.size() );\n        CPPAD_ASSERT_UNKNOWN( left   < start_.size() );\n\n        size_t start_left   = start_[left];\n        // -------------------------------------------------------------------\n        // Check if right is a subset of left so that we used reference count\n        // and not make copies of identical sets.\n        //\n        // initialize index for left and right sets\n        size_t current_left  = start_left;\n        size_t current_right = 0;\n        //\n        // initialize value_left\n        size_t value_left  = end_;\n        if( current_left > 0 )\n        {   // advance from reference counter to data\n            current_left = current_left + 2;\n            value_left   = data_[current_left];\n            CPPAD_ASSERT_UNKNOWN( value_left < end_);\n        }\n        //\n        // initialize value_right\n        size_t value_right = end_;\n        if( right.size() > 0 )\n            value_right = right[current_right];\n        //\n        bool subset = true;\n        while( subset & (value_right < end_) )\n        {   while( value_left < value_right )\n            {   // advance left\n                value_left = data_[++current_left];\n            }\n            if( value_right < value_left )\n                subset = false;\n            else\n            {   // advance right\n                ++current_right;\n                if( current_right == right.size() )\n                    value_right = end_;\n                else\n                    value_right = right[current_right];\n            }\n        }\n        //\n        if( subset )\n        {   // target = left will use reference count for identical sets\n            assignment(target, left, *this);\n            return;\n        }\n\n        // -------------------------------------------------------------------\n        // number of elements that will be deleted by removing old version\n        // of target\n        size_t number_lost = drop(target);\n\n        // drop any posting for the target set\n        size_t post = post_[target];\n        if( post > 0 )\n        {   CPPAD_ASSERT_UNKNOWN( target != left );\n            size_t capacity = data_[post + 1];\n            number_lost += capacity + 2;\n            post_[target] = 0;\n        }\n        //\n        // start new version of target\n        size_t start       = data_.extend(2);\n        start_[target]     = start;\n        data_[start]       = 1; // reference count\n        // data_[start + 1] = length is not yet known\n        //\n        // initialize value_left\n        current_left = start_left;\n        value_left   = end_;\n        if( current_left > 0 )\n        {   // advance from reference counter to data\n            current_left = current_left + 2;\n            value_left   = data_[current_left];\n            CPPAD_ASSERT_UNKNOWN( value_left < end_);\n        }\n        //\n        // initialize value_right\n        value_right = end_;\n        if( right.size() > 0 )\n            value_right = right[current_right];\n        //\n        // merge\n        while( (value_left < end_) || (value_right < end_) )\n        {   if( value_left == value_right)\n            {   // advance left so left and right are no longer equal\n                ++current_left;\n                value_left = data_[current_left];\n                CPPAD_ASSERT_UNKNOWN( value_right < value_left );\n            }\n            //\n            if( value_left < value_right )\n            {   // value_left case\n                CPPAD_ASSERT_UNKNOWN( value_left < end_ );\n                data_.push_back( value_left );\n                //\n                // advance left\n                ++current_left;\n                value_left = data_[current_left];\n            }\n            else\n            {   CPPAD_ASSERT_UNKNOWN( value_right < value_left )\n                // value_right case\n                CPPAD_ASSERT_UNKNOWN( value_right < end_);\n                data_.push_back( value_right );\n                //\n                // advance right (skip values equal to this one)\n                size_t previous_value = value_right;\n                while( value_right == previous_value )\n                {   ++current_right;\n                    if( current_right == right.size() )\n                        value_right = end_;\n                    else\n                    {   value_right = right[current_right];\n                        CPPAD_ASSERT_UNKNOWN( value_right < end_ );\n                    }\n                }\n            }\n        }\n        // make end of target list\n        data_.push_back( end_ );\n        //\n        // reference count, length, and end_ are not elements of set\n        CPPAD_ASSERT_UNKNOWN( data_.size() > start + 3 );\n        size_t length    = data_.size() - (start + 3);\n        data_[start + 1] = length;\n        //\n\n        // adjust data_not_used_\n        data_not_used_ += number_lost;\n        collect_garbage();\n    }\npublic:\n    /// declare a const iterator\n    typedef svec_setvec_const_iterator const_iterator;\n    // -----------------------------------------------------------------\n    /*!\n    Default constructor (no sets)\n    */\n    svec_setvec(void) :\n    end_(0)            ,\n    data_not_used_(0)  ,\n    data_(0)           ,\n    start_(0)          ,\n    post_(0)\n    { }\n    // -----------------------------------------------------------------\n    /// Destructor\n    ~svec_setvec(void)\n    {   check_data_structure();\n    }\n    // -----------------------------------------------------------------\n    /*!\n    Using copy constructor is a programing (not user) error\n\n    \\param v\n    vector of sets that we are attempting to make a copy of.\n    */\n    svec_setvec(const svec_setvec& v)\n    {   // Error: Probably a svec_setvec argument has been passed by value\n        CPPAD_ASSERT_UNKNOWN(false);\n    }\n    // -----------------------------------------------------------------\n    /*!\n    Assignment operator.\n\n    \\param other\n    this svec_setvec with be set to a deep copy of other.\n    */\n    void operator=(const svec_setvec& other)\n    {   end_           = other.end_;\n        data_not_used_ = other.data_not_used_;\n        data_          = other.data_;\n        start_         = other.start_;\n        post_          = other.post_;\n    }\n    // -----------------------------------------------------------------\n    /*!\n    swap (used by move semantics version of ADFun assignment operator)\n\n    \\param other\n    this sparse::list_setvec with be swapped with other.\n\n    \\par vector_of_sets\n    This public member function is not yet part of\n    the vector_of_sets concept.\n    */\n    void swap(svec_setvec& other)\n    {   // size_t objects\n        std::swap(end_             , other.end_);\n        std::swap(data_not_used_   , other.data_not_used_);\n\n        // pod_vectors\n        data_.swap(       other.data_);\n        start_.swap(      other.start_);\n        post_.swap(       other.post_);\n    }\n    // -----------------------------------------------------------------\n    /*!\n    Start a new vector of sets.\n\n    \\param n_set\n    is the number of sets in this vector of sets.\n    \\li\n    If n_set is zero, any memory currently allocated for this object\n    is freed.\n    \\li\n    If n_set is non-zero, a vector of n_set sets is created and all\n    the sets are initialized as empty.\n\n    \\param end\n    is the maximum element plus one (the minimum element is 0).\n    If n_set is zero, end must also be zero.\n    */\n    void resize(size_t n_set, size_t end)\n    {   check_data_structure();\n\n        if( n_set == 0 )\n        {   CPPAD_ASSERT_UNKNOWN(end == 0 );\n            //\n            // restore object to start after constructor\n            // (no memory allocated for this object)\n            data_.clear();\n            start_.clear();\n            post_.clear();\n            data_not_used_  = 0;\n            end_            = 0;\n            //\n            return;\n        }\n        end_                   = end;\n        //\n        start_.resize(n_set);\n        post_.resize(n_set);\n        for(size_t i = 0; i < n_set; i++)\n        {   start_[i] = 0;\n            post_[i]  = 0;\n        }\n        //\n        data_.resize(1);     // first element is not used\n        data_not_used_  = 1;\n    }\n    // -----------------------------------------------------------------\n    /*!\n    Return number of elements in a set.\n\n    \\param i\n    is the index of the set we are checking number of the elements of.\n    */\n    size_t number_elements(size_t i) const\n    {   CPPAD_ASSERT_UNKNOWN( post_[i] == 0 );\n        //\n        size_t start = start_[i];\n        if( start == 0 )\n            return 0;\n        return data_[start + 1];\n    }\n    // ------------------------------------------------------------------\n    /*!\n    Post an element for delayed addition to a set.\n\n    \\param i\n    is the index for this set in the vector of sets.\n\n    \\param element\n    is the value of the element that we are posting.\n    The same element may be posted multiple times.\n\n    \\par\n    It is faster to post multiple elements to set i and then call\n    process_post(i) then to add each element individually.\n    It is an error to call any member function,\n    that depends on the value of set i,\n    before processing the posts to set i.\n    */\n    void post_element(size_t i, size_t element)\n    {   CPPAD_ASSERT_UNKNOWN( i < start_.size() );\n        CPPAD_ASSERT_UNKNOWN( element < end_ );\n\n        size_t post = post_[i];\n        if( post == 0 )\n        {   // minimum capacity for an post vector\n            size_t min_capacity = 10;\n            size_t post_new = data_.extend(min_capacity + 2);\n            data_[post_new]     = 1;            // length\n            data_[post_new + 1] = min_capacity; // capacity\n            data_[post_new + 2] = element;\n            post_[i]            = post_new;\n        }\n        else\n        {   size_t length   = data_[post];\n            size_t capacity = data_[post + 1];\n            if( length == capacity )\n            {\n                size_t post_new = data_.extend( 2 * capacity );\n                //\n                data_[post_new]     = length + 1;\n                data_[post_new + 1] = 2 * capacity;\n                //\n                for(size_t j = 0; j < length; j++)\n                    data_[post_new + 2 + j] = data_[post + 2 + j];\n                data_[post_new + 2 + length] = element;\n                //\n                post_[i]            = post_new;\n                size_t number_lost = length + 2;\n                data_not_used_    += number_lost;\n            }\n            else\n            {   data_[post]              = length + 1;\n                data_[post + 2 + length] = element;\n            }\n        }\n\n        // check amount of data_not_used_\n        collect_garbage();\n\n        return;\n    }\n    // -----------------------------------------------------------------\n    /*!\n    process post entries for a specific set.\n\n    \\param i\n    index of the set for which we are processing the post entries.\n\n    \\par post_\n    Upon call, post_[i] is location in data_ of the elements that get\n    added to the i-th set.  Upon return, post_[i] is zero.\n    */\n    void process_post(size_t i)\n    {   // start\n        size_t start = start_[i];\n        // post\n        size_t post = post_[i];\n        //\n        // check if there are no elements to process\n        if( post == 0 )\n            return;\n        //\n        // sort the elements that need to be processed\n        size_t  length_post   = data_[post];\n        size_t  capacity_post = data_[post + 1];\n        size_t* first_post    = data_.data() + post + 2;\n        size_t* last_post     = first_post + length_post;\n        std::sort(first_post, last_post);\n        // -------------------------------------------------------------------\n        // check if posted elements are a subset of set\n        //\n        // first element of the set\n        size_t current_set = start;\n        size_t value_set   = end_;\n        if( start > 0 )\n        {   current_set = start + 2;\n            value_set   = data_[current_set];\n        }\n        //\n        // first element to post\n        size_t* current_post = first_post;\n        size_t  value_post   = *current_post;\n        //\n        bool subset = true;\n        while( subset & (value_post != end_) )\n        {   while( value_set < value_post )\n                value_set = data_[++current_set];\n            if( value_post < value_set )\n                subset = false;\n            else\n            {   ++current_post;\n                if( current_post == last_post )\n                    value_post = end_;\n                else\n                    value_post = *current_post;\n            }\n        }\n        //\n        if( subset )\n        {   // drop the post_ elements\n            post_[i] = 0;\n            //\n            size_t number_lost = capacity_post + 2;\n            data_not_used_    += number_lost;\n            collect_garbage();\n            //\n            // nothing else to do\n            return;\n        }\n        // -------------------------------------------------------------------\n        // number of element that will be lost by removing old i-th set\n        size_t number_lost = drop(i);\n\n        // start new version of i-th set\n        size_t start_new  = data_.extend(2);\n        start_[i]         = start_new;\n        data_[start_new]  = 1; // reference count\n        // data[start_new + 1] = length_new is not yet known\n        //\n        // first element of the set\n        current_set = start;\n        value_set   = end_;\n        if( start > 0 )\n        {   current_set = start + 2;\n            value_set   = data_[current_set];\n        }\n        //\n        // first element to process\n        current_post = first_post;\n        value_post   = *current_post;\n        //\n        // merge\n        while( (value_set < end_) || (current_post != last_post ) )\n        {   if( value_set == value_post )\n            {   // advance left so left and right are no longer equal\n                ++current_set;\n                value_set = data_[current_set];\n                CPPAD_ASSERT_UNKNOWN( value_post < value_set );\n            }\n            //\n            if( value_set < value_post )\n            {   // add value_set\n                CPPAD_ASSERT_UNKNOWN( value_set < end_ );\n                data_.push_back( value_set );\n                //\n                // advance set\n                ++current_set;\n                value_set = data_[current_set];\n            }\n            else\n            {   CPPAD_ASSERT_UNKNOWN( value_post < value_set )\n                // add value_post\n                CPPAD_ASSERT_UNKNOWN( value_post < end_);\n                data_.push_back( value_post );\n                //\n                // advance post (skip values equal to this one)\n                size_t value_previous = value_post;\n                while( value_post == value_previous )\n                {   ++current_post;\n                    if( current_post == last_post )\n                        value_post = end_;\n                    else\n                        value_post = *current_post;\n                }\n            }\n        }\n        // make end of target list\n        data_.push_back( end_ );\n        //\n        // reference count, length, and end_ are not elements of set\n        CPPAD_ASSERT_UNKNOWN( data_.size() > start_new + 3 );\n        size_t length_new    = data_.size() - (start_new + 3);\n        data_[start_new + 1] = length_new;\n        CPPAD_ASSERT_UNKNOWN( data_[start_new + length_new + 2] == end_ );\n        //\n        // drop to post_ elements for this set\n        post_[i] = 0;\n        //\n        number_lost    += capacity_post + 2;\n        data_not_used_ += number_lost;\n        collect_garbage();\n        //\n        return;\n    }\n    // -----------------------------------------------------------------\n    /*!\n    Add one element to a set.\n\n    \\param i\n    is the index for this set in the vector of sets.\n\n    \\param element\n    is the element we are adding to the set.\n    */\n    void add_element(size_t i, size_t element)\n    {   CPPAD_ASSERT_UNKNOWN( i   < start_.size() );\n        CPPAD_ASSERT_UNKNOWN( element < end_ );\n\n        // check if element is already in the set\n        if( is_element(i, element) )\n            return;\n\n        // check for case where old set is empty\n        size_t start = start_[i];\n        if( start == 0 )\n        {   start            = data_.extend(4);\n            start_[i]        = start;\n            data_[start]     = 1;        // reference count\n            data_[start + 1] = 1;        // length\n            data_[start + 2] = element;  // the element\n            data_[start + 3] = end_;     // end marker\n            return;\n        }\n        //\n        size_t number_lost = drop(i);\n        //\n        // start of new set\n        size_t length         = data_[start + 1];\n        size_t new_start      = data_.extend(2);\n        data_[new_start]      = 1;          // reference count\n        data_[new_start + 1]  = length + 1; // new length\n        //\n        size_t count = 0;\n        size_t value     = data_[start + 2 + count];\n        // before new element\n        while( value < element)\n        {   data_.push_back( value );\n            ++count;\n            value   = data_[start + 2 + count];\n        }\n        CPPAD_ASSERT_UNKNOWN( element < value )\n        // new element\n        data_.push_back( element );\n        // after new element\n        while( value < end_ )\n        {   data_.push_back( value );\n            ++count;\n            value   = data_[start + 2 + count];\n        }\n        data_.push_back( end_ );\n\n        //\n        // connect up new set\n        start_[i] = new_start;\n\n        // adjust data_not_used_\n        data_not_used_ += number_lost;\n        collect_garbage();\n        //\n        return;\n    }\n    // -----------------------------------------------------------------\n    /*!\n    Check if an element is in a set.\n\n    \\param i\n    is the index for this set in the vector of sets.\n\n    \\param element\n    is the element we are checking to see if it is in the set.\n    */\n    bool is_element(size_t i, size_t element) const\n    {   CPPAD_ASSERT_UNKNOWN( post_[i] == 0 );\n        CPPAD_ASSERT_UNKNOWN( element < end_ );\n        //\n        size_t start = start_[i];\n        if( start == 0 )\n            return false;\n        //\n        size_t length       = data_[start + 1];\n        const size_t* first = data_.data() + start + 2;\n        const size_t* last  = first + length;\n        if( length < 10 )\n        {   bool result = false;\n            while( last > first )\n                result |= *(--last) == element;\n            return result;\n        }\n        //\n        return std::binary_search(first, last, element);\n    }\n    // -----------------------------------------------------------------\n    /*!\n    Assign the empty set to one of the sets.\n\n    \\param target\n    is the index of the set we are setting to the empty set.\n\n    \\par data_not_used_\n    increments this value by number of data_ elements that are lost\n    (unlinked) by this operation.\n    */\n    void clear(size_t target)\n    {\n        // number of data_ elements used for this set\n        size_t number_lost = drop( target );\n\n        // set target to empty set\n        start_[target] = 0;\n\n        // drop the posted elements\n        if( post_[target] != 0 )\n        {   size_t capacity = post_[target + 1];\n            number_lost    += capacity + 2;\n            //\n            post_[target] = 0;\n        }\n\n        // adjust data_not_used_\n        data_not_used_ += number_lost;\n        collect_garbage();\n    }\n    // -----------------------------------------------------------------\n    /*!\n    Assign one set equal to another set.\n\n    \\param this_target\n    is the index in this svec_setvec object of the set being assigned.\n\n    \\param other_source\n    is the index in the other svec_setvec object of the\n    set that we are using as the value to assign to the target set.\n\n    \\param other\n    is the other svec_setvec object (which may be the same as this\n    svec_setvec object). This must have the same value for end_.\n\n    \\par data_not_used_\n    increments this value by number of elements lost.\n    */\n    void assignment(\n        size_t                  this_target  ,\n        size_t                  other_source ,\n        const svec_setvec&      other        )\n    {   CPPAD_ASSERT_UNKNOWN( other.post_[ other_source ] == 0 );\n        //\n        CPPAD_ASSERT_UNKNOWN( this_target  <   start_.size()        );\n        CPPAD_ASSERT_UNKNOWN( other_source <   other.start_.size()  );\n        CPPAD_ASSERT_UNKNOWN( end_        == other.end_   );\n\n        // check if we are assigning a set to itself\n        if( (this == &other) && (this_target == other_source) )\n            return;\n\n        // number of elements that will be deleted by this operation\n        size_t number_lost = drop(this_target);\n\n        // drop any posting for the target set\n        size_t post = post_[this_target];\n        if( post > 0 )\n        {   // do not need to worry about target being same as source\n            size_t capacity = data_[post + 1];\n            number_lost += capacity + 2;\n            post_[this_target] = 0;\n        }\n\n        // If this and other are the same, use another reference to same list\n        size_t other_start = other.start_[other_source];\n        if( this == &other )\n        {   CPPAD_ASSERT_UNKNOWN( this_target != other_source );\n            start_[this_target] = other_start;\n            if( other_start != 0 )\n            {   // increment reference count\n                data_[other_start]++;\n            }\n        }\n        else if( other_start  == 0 )\n        {   // the target list is empty\n            start_[this_target] = 0;\n        }\n        else\n        {   // make a copy of the other list in this svec_setvec\n            size_t length         = other.data_[other_start + 1];\n            size_t this_start     = data_.extend(2);\n            start_[this_target]   = this_start;\n            data_[this_start]     = 1;      // reference count\n            data_[this_start + 1] = length; // length\n            for(size_t j = 0; j < length; ++j)\n                data_.push_back( other.data_[other_start + 2 + j] );\n            data_.push_back(end_);\n        }\n\n        // adjust data_not_used_\n        data_not_used_ += number_lost;\n        collect_garbage();\n    }\n    // -----------------------------------------------------------------\n    /*!\n    Assign a set equal to the union of two other sets.\n\n    \\param this_target\n    is the index in this svec_setvec object of the set being assigned.\n\n    \\param this_left\n    is the index in this svec_setvec object of the\n    left operand for the union operation.\n    It is OK for this_target and this_left to be the same value.\n\n    \\param other_right\n    is the index in the other svec_setvec object of the\n    right operand for the union operation.\n    It is OK for this_target and other_right to be the same value.\n\n    \\param other\n    is the other svec_setvec object (which may be the same as this\n    svec_setvec object).\n    */\n    void binary_union(\n        size_t                this_target  ,\n        size_t                this_left    ,\n        size_t                other_right  ,\n        const svec_setvec& other        )\n    {   CPPAD_ASSERT_UNKNOWN( post_[this_left] == 0 );\n        CPPAD_ASSERT_UNKNOWN( other.post_[ other_right ] == 0 );\n        //\n        CPPAD_ASSERT_UNKNOWN( this_target < start_.size()         );\n        CPPAD_ASSERT_UNKNOWN( this_left   < start_.size()         );\n        CPPAD_ASSERT_UNKNOWN( other_right < other.start_.size()   );\n        CPPAD_ASSERT_UNKNOWN( end_        == other.end_           );\n\n        // check if one of the two operands is a subset of the the other\n        size_t subset = is_subset(this_left, other_right, other);\n\n        // case where right is a subset of left or right and left are equal\n        if( subset == 2 || subset == 3 )\n        {   assignment(this_target, this_left, *this);\n            return;\n        }\n        // case where the left is a subset of right and they are not equal\n        if( subset == 1 )\n        {   assignment(this_target, other_right, other);\n            return;\n        }\n        // if neither case holds, then both left and right are non-empty\n        CPPAD_ASSERT_UNKNOWN( reference_count(this_left) > 0 );\n        CPPAD_ASSERT_UNKNOWN( other.reference_count(other_right) > 0 );\n\n        // must get all the start indices before modify start_this\n        // (in case start_this is the same as start_left or start_right)\n        size_t start_left    = start_[this_left];\n        size_t start_right   = other.start_[other_right];\n\n        // number of list elements that will be deleted by this operation\n        size_t number_lost = drop(this_target);\n\n        // drop any posting for the target set\n        size_t post = post_[this_target];\n        if( post > 0 )\n        {   // do not need to worry about target being same as left or right\n            size_t capacity = data_[post + 1];\n            number_lost += capacity + 2;\n            post_[this_target] = 0;\n        }\n\n        // start the new list\n        size_t start        = data_.extend(2);\n        start_[this_target] = start;\n        data_[start]        = 1; // reference count\n        // data_[start + 1] = length is not yet known\n\n        // initialize left\n        CPPAD_ASSERT_UNKNOWN( start_left != 0 );\n        size_t current_left = start_left + 2;\n        size_t value_left   = data_[current_left];\n        CPPAD_ASSERT_UNKNOWN( value_left < end_ );\n\n        // initialize right\n        CPPAD_ASSERT_UNKNOWN( start_right != 0 );\n        size_t current_right = start_right + 2;\n        size_t value_right   = other.data_[current_right];\n        CPPAD_ASSERT_UNKNOWN( value_right < end_ );\n\n\n        CPPAD_ASSERT_UNKNOWN( value_left < end_ && value_right < end_ );\n        while( (value_left < end_) || (value_right < end_) )\n        {   if( value_left == value_right )\n            {   // advance right so left and right are no longer equal\n                ++current_right;\n                value_right = other.data_[current_right];\n            }\n            if( value_left < value_right )\n            {   data_.push_back( value_left );\n                // advance left to its next element\n                ++current_left;\n                value_left = data_[current_left];\n            }\n            else\n            {   CPPAD_ASSERT_UNKNOWN( value_right < value_left )\n                data_.push_back( value_right );\n                // advance right to its next element\n                ++current_right;\n                value_right = other.data_[current_right];\n            }\n        }\n        // make end of target list\n        data_.push_back( end_ );\n        //\n        // reference count, length, and end_ are not elements of set\n        CPPAD_ASSERT_UNKNOWN( data_.size() > start + 3 );\n        size_t length = data_.size() - (start + 3);\n        data_[start + 1] = length;\n\n        // adjust data_not_used_\n        data_not_used_ += number_lost;\n        collect_garbage();\n    }\n    // -----------------------------------------------------------------\n    /*!\n    Assign a set equal to the intersection of two other sets.\n\n    \\param this_target\n    is the index in this svec_setvec object of the set being assigned.\n\n    \\param this_left\n    is the index in this svec_setvec object of the\n    left operand for the intersection operation.\n    It is OK for this_target and this_left to be the same value.\n\n    \\param other_right\n    is the index in the other svec_setvec object of the\n    right operand for the intersection operation.\n    It is OK for this_target and other_right to be the same value.\n\n    \\param other\n    is the other svec_setvec object (which may be the same as this\n    svec_setvec object).\n    */\n    void binary_intersection(\n        size_t                  this_target  ,\n        size_t                  this_left    ,\n        size_t                  other_right  ,\n        const svec_setvec&      other        )\n    {   CPPAD_ASSERT_UNKNOWN( post_[this_left] == 0 );\n        CPPAD_ASSERT_UNKNOWN( other.post_[ other_right ] == 0 );\n        //\n        CPPAD_ASSERT_UNKNOWN( this_target < start_.size()         );\n        CPPAD_ASSERT_UNKNOWN( this_left   < start_.size()         );\n        CPPAD_ASSERT_UNKNOWN( other_right < other.start_.size()   );\n        CPPAD_ASSERT_UNKNOWN( end_        == other.end_           );\n        //\n        // check if one of the two operands is a subset of the the other\n        size_t subset = is_subset(this_left, other_right, other);\n\n        // case where left is a subset of right or left and right are equal\n        if( subset == 1 || subset == 3 )\n        {   assignment(this_target, this_left, *this);\n            return;\n        }\n        // case where the right is a subset of left and they are not equal\n        if( subset == 2 )\n        {   assignment(this_target, other_right, other);\n            return;\n        }\n        // if neither case holds, then both left and right are non-empty\n        CPPAD_ASSERT_UNKNOWN( reference_count(this_left) > 0 );\n        CPPAD_ASSERT_UNKNOWN( other.reference_count(other_right) > 0 );\n\n        // must get all the start indices before modify start_this\n        // (in case start_this is the same as start_left or start_right)\n        size_t start_left    = start_[this_left];\n        size_t start_right   = other.start_[other_right];\n\n\n        // number of list elements that will be deleted by this operation\n        size_t number_lost = drop(this_target);\n\n        // drop any posting for the target set\n        size_t post = post_[this_target];\n        if( post > 0 )\n        {   // do not need to worry about target being same as left or right\n            size_t capacity = data_[post + 1];\n            number_lost += capacity + 2;\n            post_[this_target] = 0;\n        }\n\n        // initialize intersection as empty\n        size_t start        = 0;\n        start_[this_target] = start;\n\n        // initialize left\n        CPPAD_ASSERT_UNKNOWN( start_left != 0 );\n        size_t current_left = start_left + 2;\n        size_t value_left   = data_[current_left];\n        CPPAD_ASSERT_UNKNOWN( value_left < end_ );\n\n        // initialize right\n        CPPAD_ASSERT_UNKNOWN( start_right != 0 );\n        size_t current_right = start_right + 2;\n        size_t value_right   = other.data_[current_right];\n        CPPAD_ASSERT_UNKNOWN( value_right < end_ );\n\n        while( (value_left < end_) && (value_right < end_) )\n        {   if( value_left == value_right )\n            {   if( start == 0 )\n                {   // this is the first element in the intersection\n                    start               = data_.extend(2);\n                    start_[this_target] = start;\n                    data_[start]        = 1; // reference count\n                    // data_[start + 1] = length is not yet known\n                }\n                data_.push_back( value_left );\n                //\n                // advance left to its next element\n                ++current_left;\n                value_left = data_[current_left];\n            }\n            if( value_left > value_right )\n            {   // advance right\n                ++current_right;\n                value_right = other.data_[current_right];\n            }\n            if( value_right > value_left )\n            {   // advance left\n                ++current_left;\n                value_left = data_[current_left];\n            }\n        }\n        if( start != 0 )\n        {   data_.push_back(end_);\n            CPPAD_ASSERT_UNKNOWN( data_.size() > start + 3 );\n            size_t length = data_.size() - (start + 3);\n            data_[start + 1] = length;\n        }\n\n        // adjust data_not_used_\n        data_not_used_ += number_lost;\n        collect_garbage();\n    }\n    // -----------------------------------------------------------------\n    /*! Fetch n_set for vector of sets object.\n\n    \\return\n    Number of from sets for this vector of sets object\n    */\n    size_t n_set(void) const\n    {   return start_.size(); }\n    // -----------------------------------------------------------------\n    /*! Fetch end for this vector of sets object.\n\n    \\return\n    is the maximum element value plus one (the minimum element value is 0).\n    */\n    size_t end(void) const\n    {   return end_; }\n    // -----------------------------------------------------------------\n    /*! Amount of memory used by this vector of sets\n\n    \\return\n    The amount of memory in units of type unsigned char memory.\n    */\n    size_t memory(void) const\n    {   return data_.capacity() * sizeof(size_t);\n    }\n    /*!\n    Print the vector of sets (used for debugging)\n    */\n    void print(void) const;\n};\n// =========================================================================\n/*!\ncons_iterator for one set of positive integers in a svec_setvec object.\n\nAll the public member functions for this class are also in the\nsparse::pack_setvec_const_iterator and sparse::list_setvec_const_iterator classes.\nThis defines the CppAD vector_of_sets iterator concept.\n*/\nclass svec_setvec_const_iterator {\nprivate:\n    /// data for the entire vector of sets\n    const pod_vector<size_t>& data_;\n\n    /// Possible elements in a list are 0, 1, ..., end_ - 1;\n    const size_t                   end_;\n\n    /// data index of next entry, zero for no more entries\n    size_t                         data_index_;\npublic:\n    /// construct a const_iterator for a set in a svec_setvec object\n    svec_setvec_const_iterator (const svec_setvec& vec_set, size_t i)\n    :\n    data_( vec_set.data_ ) ,\n    end_ ( vec_set.end_ )\n    {   CPPAD_ASSERT_UNKNOWN( vec_set.post_[i] == 0 );\n        //\n        size_t start = vec_set.start_[i];\n        if( start == 0 )\n        {   data_index_ = 0;\n        }\n        else\n        {   // data index of the first element in the set\n            data_index_ = start + 2;\n            CPPAD_ASSERT_UNKNOWN( data_[data_index_] < end_ );\n        }\n    }\n\n    /// advance to next element in this list\n    svec_setvec_const_iterator& operator++(void)\n    {   if( data_index_ != 0 )\n        {   ++data_index_;\n            if( data_[data_index_] == end_ )\n                data_index_ = 0;\n        }\n        return *this;\n    }\n\n    /// obtain value of this element of the set of positive integers\n    /// (end_ for no such element)\n    size_t operator*(void)\n    {   if( data_index_ == 0 )\n            return end_;\n        return data_[data_index_];\n    }\n};\n// =========================================================================\n/*!\nPrint the vector of sets (used for debugging)\n*/\ninline void svec_setvec::print(void) const\n{   std::cout << \"svec_setvec:\\n\";\n    for(size_t i = 0; i < n_set(); i++)\n    {   std::cout << \"set[\" << i << \"] = {\";\n        const_iterator itr(*this, i);\n        while( *itr != end() )\n        {   std::cout << *itr;\n            if( *(++itr) != end() )\n                std::cout << \",\";\n        }\n        std::cout << \"}\\n\";\n    }\n    return;\n}\n\n/*!\nCopy a user vector of sets sparsity pattern to an internal svec_setvec object.\n\n\\tparam SetVector\nis a simple vector with elements of type std::set<size_t>.\n\n\\param internal\nThe input value of sparisty does not matter.\nUpon return it contains the same sparsity pattern as user\n(or the transposed sparsity pattern).\n\n\\param user\nsparsity pattern that we are placing internal.\n\n\\param n_set\nnumber of sets (rows) in the internal sparsity pattern.\n\n\\param end\nend of set value (number of columns) in the internal sparsity pattern.\n\n\\param transpose\nif true, the user sparsity patter is the transposed.\n\n\\param error_msg\nis the error message to display if some values in the user sparstiy\npattern are not valid.\n*/\ntemplate<class SetVector>\nvoid sparsity_user2internal(\n    svec_setvec&            internal  ,\n    const SetVector&        user      ,\n    size_t                  n_set     ,\n    size_t                  end       ,\n    bool                    transpose ,\n    const char*             error_msg )\n{\n# ifndef NDEBUG\n    if( transpose )\n        CPPAD_ASSERT_KNOWN( end == size_t( user.size() ), error_msg);\n    if( ! transpose )\n        CPPAD_ASSERT_KNOWN( n_set == size_t( user.size() ), error_msg);\n# endif\n\n    // iterator for user set\n    std::set<size_t>::const_iterator itr;\n\n    // size of internal sparsity pattern\n    internal.resize(n_set, end);\n\n    if( transpose )\n    {   // transposed pattern case\n        for(size_t j = 0; j < end; j++)\n        {   itr = user[j].begin();\n            while(itr != user[j].end())\n            {   size_t i = *itr++;\n                CPPAD_ASSERT_KNOWN(i < n_set, error_msg);\n                internal.add_element(i, j);\n            }\n        }\n    }\n    else\n    {   for(size_t i = 0; i < n_set; i++)\n        {   itr = user[i].begin();\n            while(itr != user[i].end())\n            {   size_t j = *itr++;\n                CPPAD_ASSERT_KNOWN( j < end, error_msg);\n                internal.add_element(i, j);\n            }\n        }\n    }\n    return;\n}\n\n} } } // END_CPPAD_LOCAL_SPARSE_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/local/std_set.hpp",
    "content": "# ifndef CPPAD_LOCAL_STD_SET_HPP\n# define CPPAD_LOCAL_STD_SET_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/local/define.hpp>\n\n// needed before one can use CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL\n# include <cppad/utility/thread_alloc.hpp>\n\nnamespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE\n/*!\n\\file std_set.hpp\nTwo constant standard sets (currently used for concept checking).\n*/\n\n/*!\nA standard set with one element.\n*/\ntemplate <class Scalar>\nconst std::set<Scalar>& one_element_std_set(void)\n{   CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL;\n    static std::set<Scalar> one;\n    if( one.empty() )\n        one.insert(1);\n    return one;\n}\n/*!\nA standard set with a two elements.\n*/\ntemplate <class Scalar>\nconst std::set<Scalar>& two_element_std_set(void)\n{   CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL;\n    static std::set<Scalar> two;\n    if( two.empty() )\n    {   two.insert(1);\n        two.insert(2);\n    }\n    return two;\n}\n\n} } // END_CPPAD_LOCAL_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/local/subgraph/arg_variable.hpp",
    "content": "# ifndef CPPAD_LOCAL_SUBGRAPH_ARG_VARIABLE_HPP\n# define CPPAD_LOCAL_SUBGRAPH_ARG_VARIABLE_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/local/pod_vector.hpp>\n\n// BEGIN_CPPAD_LOCAL_SUBGRAPH_NAMESPACE\nnamespace CppAD { namespace local { namespace subgraph {\n/*!\n\\file arg_variable.hpp\nDetermine arguments that are variables.\n*/\n\n/*!\nDetermine the set of arguments, for an operator, that are variables.\n\n\\tparam Addr\nType used for indices in random iterator.\n\n\\param random_itr\nis a random iterator for this operation sequence.\n\n\\param i_op\nis the operator index. If this operator is part of a atomic function call,\nit must be the first AFunOp in the call. (There is a AFunOp at the\nbeginning and end of each call.)\n\n\\param variable\nis the set of argument variables corresponding to this operator.\nIf the operator is a AFunOp, the arguments are the variables\nthat are passed into the function call.\n\n\\param work\nthis is work space used by arg_variable to make subsequent calls\nfaster. It should not be used by the calling routine. In addition,\nit is better if work does not drop out of scope between calls.\n*/\ntemplate <class Addr>\nvoid get_argument_variable(\n    const play::const_random_iterator<Addr>& random_itr  ,\n    size_t                                   i_op        ,\n    pod_vector<size_t>&                      variable    ,\n    pod_vector<bool>&                        work        )\n{\n    // reset to size zero, but keep allocated memory\n    variable.resize(0);\n    //\n    // operator corresponding to i_op\n    op_code_var   op;\n    const addr_t* op_arg;\n    size_t        i_var;\n    random_itr.op_info(i_op, op, op_arg, i_var);\n    //\n    // partial check of assumptions on atomic function calls\n    CPPAD_ASSERT_UNKNOWN(\n        op != FunapOp && op != FunavOp && op != FunrpOp && op != FunrvOp\n    );\n    //\n    // we assume this is the first AFunOp of the call\n    if( op == AFunOp )\n    {   random_itr.op_info(++i_op, op, op_arg, i_var);\n        while( op != AFunOp )\n        {   switch(op)\n            {\n                case FunavOp:\n                {   CPPAD_ASSERT_NARG_NRES(op, 1, 0);\n                    size_t j_var = size_t( op_arg[0] );\n                    variable.push_back(j_var);\n                }\n                break;\n\n                case FunrvOp:\n                case FunrpOp:\n                case FunapOp:\n                break;\n\n                default:\n                // cannot find second AFunOp in this call\n                CPPAD_ASSERT_UNKNOWN(false);\n                break;\n            }\n            random_itr.op_info(++i_op, op, op_arg, i_var);\n        }\n        CPPAD_ASSERT_UNKNOWN( variable.size() > 0 );\n        return;\n    }\n    // is_variable is a reference to work with a better name\n    pod_vector<bool>& is_variable(work);\n    arg_is_variable(op, op_arg, is_variable);\n    size_t num_arg = is_variable.size();\n    for(size_t j = 0; j < num_arg; ++j)\n    {   if( is_variable[j] )\n        {   size_t j_var = size_t( op_arg[j] );\n            variable.push_back(j_var);\n        }\n    }\n    return;\n}\n\n} } } // END_CPPAD_LOCAL_SUBGRAPH_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/subgraph/entire_call.hpp",
    "content": "# ifndef CPPAD_LOCAL_SUBGRAPH_ENTIRE_CALL_HPP\n# define CPPAD_LOCAL_SUBGRAPH_ENTIRE_CALL_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/local/pod_vector.hpp>\n\n// BEGIN_CPPAD_LOCAL_SUBGRAPH_NAMESPACE\nnamespace CppAD { namespace local { namespace subgraph {\n/*!\n\\file entire_call.hpp\ninclude entire function call in a subgraph\n*/\n// ===========================================================================\n/*!\nConvert from just first AFunOp to entire atomic function call in a subgraph.\n\n\\tparam Addr\nType used for indices in the random iterator.\n\n\\param random_itr\nis a random iterator for this operation sequence.\n\n\\param subgraph\nIt a set of operator indices in this recording.\nIf the corresponding operator is a AFunOp, it assumed to be the\nfirst one in the corresponding atomic function call.\nThe other call operators are included in the subgraph.\n*/\ntemplate <class Addr>\nvoid entire_call(\n    const play::const_random_iterator<Addr>& random_itr ,\n    pod_vector<addr_t>&                      subgraph   )\n{\n    // add extra operators corresponding to rest of atomic function calls\n    size_t n_sub = subgraph.size();\n    for(size_t k = 0; k < n_sub; ++k)\n    {   size_t i_op = size_t( subgraph[k] );\n        //\n        if( random_itr.get_op(i_op) == AFunOp )\n        {   // This is the first AFunOp of this atomic function call\n            while( random_itr.get_op(++i_op) != AFunOp )\n            {   switch(random_itr.get_op(i_op))\n                {\n                    case FunavOp:\n                    case FunrvOp:\n                    case FunrpOp:\n                    case FunapOp:\n                    subgraph.push_back( addr_t(i_op) );\n                    break;\n\n                    default:\n                    // cannot find second AFunOp in this call\n                    CPPAD_ASSERT_UNKNOWN(false);\n                    break;\n                }\n            }\n            // THis is the second AFunOp of this atomic function call\n            subgraph.push_back( addr_t(i_op) );\n        }\n    }\n\n}\n\n} } } // END_CPPAD_LOCAL_SUBGRAPH_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/subgraph/get_rev.hpp",
    "content": "# ifndef CPPAD_LOCAL_SUBGRAPH_GET_REV_HPP\n# define CPPAD_LOCAL_SUBGRAPH_GET_REV_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/local/pod_vector.hpp>\n# include <cppad/local/subgraph/arg_variable.hpp>\n# include <cppad/local/subgraph/info.hpp>\n\n// BEGIN_CPPAD_LOCAL_SUBGRAPH_NAMESPACE\nnamespace CppAD { namespace local { namespace subgraph {\n/*!\n\\file get_rev.hpp\nGet subgraph corresponding to a dependent variable.\n*/\n\n// ===========================================================================\n/*!\nGet the subgraph corresponding to a dependent variables\n(and a selected set of independent variables).\n\n\\tparam Addr\nType used for indices in the random iterator.\n\n\\param random_itr\nis a random iterator for this operation sequence.\n\n\\param dep_taddr\nis the vector mapping user dependent variable indices\nto the corresponding variable in the recording.\n\n\\param i_dep\nis the user index for his dependent variable;\nthat i_dep < n_dep_.\n\n\\param subgraph\nthe input size and contents of this vector do not matter.\nRepeated calls with the same subgraph vector should reduce\nthe amount of memory allocation.\nUpon return it contains the operator indices for the subgraph\ncorresponding to the dependent and the selected independent variables.\nOnly selected independent variable operators InvOp are included\nin the subgraph.\nFurthermore the operator indices in subgraph are unique; i.e.,\nif i_op != j_op then subgraph[i_op] != subgraph[j_op].\n\n\\par map_user_op_\nThis vector must be set.\n\n\\par in_subgraph_\nhas size equal to the number of operators in play.\nIf in_subgraph[i_op] <= n_dep_,\nthe result for this operator depends on the selected independent variables.\nIn addition, upon input, there is no i_op such that in_subgraph[i_op] == i_dep.\nNote that for atomic function call operators i_op,\n\\code\n    n_dep_ < in_subgraph[i_op]\n\\endcode\nexcept for the first AFunOp in the atomic function call sequence.\nFor the first AFunOp,\n\\code\n    in_subgraph[i_op] <= n_dep_\n\\endcode\nif any result for the atomic function call\ndepends on the selected independent variables.\nExcept for UserOP, only operators with NumRes(op) > 0 are included\nin the dependency; e.g., comparison operators are not included.\nUpon return, some of the i_op for which in_subgraph[i_op] <= n_dep_,\nwill be changed to in_subgraph[i_op] = i_dep.\n\n\\par process_range_\nThe value process_range_[i_dep] is checked to make sure it is false.\nIt is then set to have value true.\n*/\ntemplate <class Addr>\nvoid subgraph_info::get_rev(\n    const play::const_random_iterator<Addr>&   random_itr  ,\n    const pod_vector<size_t>&                  dep_taddr   ,\n    addr_t                                     i_dep       ,\n    pod_vector<addr_t>&                        subgraph    )\n{   // check sizes\n    CPPAD_ASSERT_UNKNOWN( map_user_op_.size()   == n_op_ );\n\n    // process_range_\n    CPPAD_ASSERT_UNKNOWN( process_range_[i_dep] == false );\n    process_range_[i_dep] = true;\n\n    // special value; see init_rev_in_subgraph\n    addr_t depend_yes = addr_t( n_dep_ );\n\n    // assumption on i_dep\n    CPPAD_ASSERT_UNKNOWN( i_dep < depend_yes );\n\n    // start with an empty subgraph for this dependent variable\n    subgraph.resize(0);\n\n    // tape index corresponding to this dependent variable\n    size_t i_var = dep_taddr[i_dep];\n\n    // operator corresponding to this dependent variable\n    size_t i_op = random_itr.var2op(i_var);\n    i_op        = size_t( map_user_op_[i_op] );\n\n    // if this variable depends on the selected independent variables\n    // process its subgraph\n    CPPAD_ASSERT_UNKNOWN( in_subgraph_[i_op] != i_dep )\n    if( in_subgraph_[i_op] <= depend_yes )\n    {   subgraph.push_back( addr_t(i_op) );\n        in_subgraph_[i_op] = i_dep;\n    }\n\n    // space used to return set of arguments that are variables\n    pod_vector<size_t> argument_variable;\n\n    // temporary space used by get_argument_variable\n    pod_vector<bool> work;\n\n    // scan all the operators in this subgraph\n    size_t sub_index = 0;\n    while(sub_index < subgraph.size() )\n    {   // this operator connected to this dependent and selected independent\n        i_op = size_t( subgraph[sub_index] );\n        CPPAD_ASSERT_UNKNOWN( in_subgraph_[i_op] == i_dep );\n        //\n        // There must be a result for this operator\n# ifndef NDEBUG\n        op_code_var op = random_itr.get_op(i_op);\n        CPPAD_ASSERT_UNKNOWN(op == AFunOp || NumRes(op) > 0 );\n# endif\n        //\n        // which variables are connected to this operator\n        get_argument_variable(random_itr, i_op, argument_variable, work);\n        for(size_t j = 0; j < argument_variable.size(); ++j)\n        {   // add the corresponding operators to the subgraph\n            size_t j_var = argument_variable[j];\n            size_t j_op  = random_itr.var2op(j_var);\n            j_op         = size_t( map_user_op_[j_op] );\n            bool add = in_subgraph_[j_op] <= depend_yes;\n            add     &= in_subgraph_[j_op] != i_dep;\n            if( random_itr.get_op(j_op) == InvOp )\n            {   CPPAD_ASSERT_UNKNOWN( j_op == j_var );\n                add &= select_domain_[j_var - 1];\n            }\n            if( add )\n            {   subgraph.push_back( addr_t(j_op) );\n                in_subgraph_[j_op] = i_dep;\n            }\n        }\n        // we are done scanning this subgraph operator\n        ++sub_index;\n    }\n}\n\n} } } // END_CPPAD_LOCAL_SUBGRAPH_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/subgraph/info.hpp",
    "content": "# ifndef CPPAD_LOCAL_SUBGRAPH_INFO_HPP\n# define CPPAD_LOCAL_SUBGRAPH_INFO_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/local/play/random_iterator.hpp>\n# include <cppad/local/pod_vector.hpp>\n# include <cppad/local/subgraph/arg_variable.hpp>\n\n// BEGIN_CPPAD_LOCAL_SUBGRAPH_NAMESPACE\nnamespace CppAD { namespace local { namespace subgraph {\n/*!\n\\file info.hpp\nsubgraph information attached to a operation sequence\n*/\n\n/// class for maintaining subgraph information attached to on ADFun object.\nclass subgraph_info {\nprivate:\n    // -----------------------------------------------------------------------\n    // private member data set by constructor, resize, and assign\n    // -----------------------------------------------------------------------\n    /// number of independent variables for this function\n    size_t  n_ind_;\n\n    /// number of dependent variables for this function\n    size_t  n_dep_;\n\n    /// number of operatros in operation sequence\n    size_t  n_op_;\n\n    /// number of variables in operation sequence\n    size_t n_var_;\n\n    // -----------------------------------------------------------------------\n    // private member data set by set_map_user_op\n    // -----------------------------------------------------------------------\n\n    /// Mapping atomic call operators to AFunOp that begins call sequence,\n    /// other operators are not changed by the map.\n    /// (size zero after constructor or resize)\n    pod_vector<addr_t> map_user_op_;\n\n    // -----------------------------------------------------------------------\n    // other private member data\n    // -----------------------------------------------------------------------\n\n    /// flags which operators are in subgraph\n    /// (size zero or n_op_).\n    pod_vector<addr_t> in_subgraph_;\n\n    /// flags which dependent variables are selected\n    pod_vector<bool> select_domain_;\n\n    /// flags which dependent variables have been processed since\n    /// the previous init_rev\n    pod_vector<bool> process_range_;\n\npublic:\n    // -----------------------------------------------------------------------\n    // const public functions\n    // -----------------------------------------------------------------------\n    /// number of independent variables\n    size_t n_ind(void) const\n    {   return n_ind_; }\n\n    /// number of dependent variables\n    size_t n_dep(void) const\n    {   return n_dep_; }\n\n    /// number of operators\n    size_t n_op(void) const\n    {   return n_op_; }\n\n    // number of variables\n    size_t n_var(void) const\n    {   return n_var_; }\n\n    /// map atomic function calls to first operator in the call\n    const pod_vector<addr_t>& map_user_op(void) const\n    {   return map_user_op_; }\n\n    /// previous select_domain argument to init_rev\n    const pod_vector<bool>& select_domain(void) const\n    {   return select_domain_; }\n\n    /// dependent variables that have been processed since previous init_rev\n    const pod_vector<bool>& process_range(void) const\n    {   return process_range_; }\n\n    /// amount of memory corresponding to this object\n    size_t memory(void) const\n    {   size_t sum = map_user_op_.size()   * sizeof(addr_t);\n        sum       += in_subgraph_.size()   * sizeof(addr_t);\n        sum       += select_domain_.size() * sizeof(bool);\n        sum       += process_range_.size() * sizeof(bool);\n        return sum;\n    }\n\n    /// free memory used for calculating subgraph\n    void clear(void)\n    {   map_user_op_.clear();\n        in_subgraph_.clear();\n        select_domain_.clear();\n        process_range_.clear();\n    }\n    // -----------------------------------------------------------------------\n    /*!\n    check that the value of map_user_op is OK for this operation sequence\n\n    \\param play\n    is the player for this operation sequence.\n\n    \\return\n    is true, if map_user_op has the correct value for this operation sequence\n    (is the same as it would be after a set_map_user_op).\n    */\n    template <class Base>\n    bool check_map_user_op(const player<Base>* play) const\n    {   if( map_user_op_.size() != n_op_ )\n            return false;\n        bool   ok   = true;\n        size_t i_op = 0;\n        while( i_op < n_op_ )\n        {   op_code_var op = play->GetOp(i_op);\n            ok       &= map_user_op_[i_op] == addr_t( i_op );\n            if( op == AFunOp )\n            {   addr_t begin = addr_t( i_op );\n                op           = play->GetOp(++i_op);\n                while( op != AFunOp )\n                {   CPPAD_ASSERT_UNKNOWN(\n                    op==FunapOp || op==FunavOp || op==FunrpOp || op==FunrvOp\n                    );\n                    ok  &= map_user_op_[i_op] == begin;\n                    op   = play->GetOp(++i_op);\n                }\n                ok  &= map_user_op_[i_op] == begin;\n            }\n            ++i_op;\n        }\n        return ok;\n    }\n    // -----------------------------------------------------------------------\n    // non const public functions\n    // -----------------------------------------------------------------------\n\n    /// flag which operators that are in the subgraph\n    pod_vector<addr_t>& in_subgraph(void)\n    {   return in_subgraph_; }\n\n\n    /// default constructor (all sizes are zero)\n    subgraph_info(void)\n    : n_ind_(0), n_dep_(0), n_op_(0), n_var_(0)\n    {   CPPAD_ASSERT_UNKNOWN( map_user_op_.size()   == 0 );\n        CPPAD_ASSERT_UNKNOWN( in_subgraph_.size()   == 0 );\n    }\n    // -----------------------------------------------------------------------\n    /// assignment operator\n    void operator=(const subgraph_info& info)\n    {   n_ind_            = info.n_ind_;\n        n_dep_            = info.n_dep_;\n        n_op_             = info.n_op_;\n        n_var_            = info.n_var_;\n        map_user_op_      = info.map_user_op_;\n        in_subgraph_      = info.in_subgraph_;\n        select_domain_    = info.select_domain_;\n        process_range_    = info.process_range_;\n        return;\n    }\n    // -----------------------------------------------------------------------\n    /// swap\n    /// (used for move semantics version of ADFun assignment)\n    void swap(subgraph_info& info)\n    {   // size_t objects\n        std::swap(n_ind_ , info.n_ind_);\n        std::swap(n_dep_ , info.n_dep_);\n        std::swap(n_op_  , info.n_op_);\n        std::swap(n_var_ , info.n_var_);\n        //\n        // pod_vectors\n        map_user_op_.swap(   info.map_user_op_);\n        in_subgraph_.swap(   info.in_subgraph_);\n        select_domain_.swap( info.select_domain_);\n        process_range_.swap( info.process_range_);\n        //\n        return;\n    }\n    // -----------------------------------------------------------------------\n    /*!\n    set sizes for this object (the default sizes are zero)\n\n    \\param n_ind\n    number of independent variables.\n\n    \\param n_dep\n    number of dependent variables.\n\n    \\param n_op\n    number of operators.\n\n    \\param n_var\n    number of variables.\n\n    \\par map_user_op_\n    is resized to zero.\n\n    \\par in_subgraph_\n    is resized to zero.\n    */\n    void resize(size_t n_ind, size_t n_dep, size_t n_op, size_t n_var)\n    {   CPPAD_ASSERT_UNKNOWN(\n            n_op <= size_t( std::numeric_limits<addr_t>::max() )\n        );\n        // n_ind_\n        n_ind_ = n_ind;\n        // n_dep_\n        n_dep_ = n_dep;\n        // n_op_\n        n_op_  = n_op;\n        // n_var_\n        n_var_ = n_var;\n\n        //\n        // map_user_op_\n        map_user_op_.resize(0);\n        //\n        // in_subgraph_\n        in_subgraph_.resize(0);\n        //\n        return;\n    }\n    // -----------------------------------------------------------------------\n    /*!\n    set the value of map_user_op for this operation sequence\n\n    \\param play\n    is the player for this operation sequence. It must same number of\n    operators and variables as this subgraph_info object.\n\n    \\par map_user_op_\n    This size of map_user_op_ must be zero when this function is called\n    (which is true after a resize operation).\n    This function sets its size to the number of operations in play.\n    We use the term user OpCocde for the any one of the following:\n    AFunOp, FunapOp, FunavOp, FunrpOp, or FunrvOp. Suppose\n    \\code\n        OpCodce op_i = play->GetOp(i_op);\n        size_t  j_op = map_user_op[i_op];\n        op_code_var op_j = play->GetOP(j_op);\n    \\endcode\n    If op is a user op_code_var, j_op is the index of the first operator\n    in the corresponding atomic function call and op_j == AFunOp.\n    Otherwise j_op == i_op;\n\n    */\n    template <class Base>\n    void set_map_user_op(const player<Base>* play)\n    {   CPPAD_ASSERT_UNKNOWN( map_user_op_.size()   == 0 );\n        //\n        CPPAD_ASSERT_UNKNOWN( n_op_  == play->num_var_op() );\n        CPPAD_ASSERT_UNKNOWN( n_var_ == play->num_var() );\n        //\n        // resize map_user_op_\n        map_user_op_.resize(n_op_);\n        //\n        // set map_user_op for each operator\n        for(size_t i_op = 0; i_op < n_op_; ++i_op)\n        {   // this operator\n            op_code_var op = play->GetOp(i_op);\n            //\n            // value of map_user_op when op is not in atomic function call)\n            map_user_op_[i_op] = addr_t( i_op );\n            //\n            if( op == AFunOp )\n            {   // first AFunOp in an atomic function call sequence\n                //\n                // All operators in this atomic call sequence will be\n                // mapped to the AFunOp that begins this call.\n                addr_t begin = addr_t( i_op );\n                op           = play->GetOp(++i_op);\n                while( op != AFunOp )\n                {   CPPAD_ASSERT_UNKNOWN(\n                    op==FunapOp || op==FunavOp || op==FunrpOp || op==FunrvOp\n                    );\n                    // map this operator to the beginning of the call\n                    map_user_op_[i_op] = begin;\n                    op                 = play->GetOp(++i_op);\n                }\n                // map the second AFunOp to the beginning of the call\n                map_user_op_[i_op] = begin;\n            }\n        }\n        return;\n    }\n    // -----------------------------------------------------------------------\n    // see init_rev.hpp\n    template <class Addr, class BoolVector>\n    void init_rev(\n        const play::const_random_iterator<Addr>& random_itr ,\n        const BoolVector&                        select_domain\n    );\n    template <class Addr, class Base, class BoolVector>\n    void init_rev(\n        player<Base>*        play          ,\n        const BoolVector&    select_domain\n    );\n    // -----------------------------------------------------------------------\n    // see get_rev.hpp\n    template <class Addr>\n    void get_rev(\n        const play::const_random_iterator<Addr>&   random_itr   ,\n        const pod_vector<size_t>&                  dep_taddr    ,\n        addr_t                                     i_dep        ,\n        pod_vector<addr_t>&                        subgraph\n    );\n};\n\n} } } // END_CPPAD_LOCAL_SUBGRAPH_NAMESPACE\n\n// routines that operate on in_subgraph\n# include <cppad/local/subgraph/init_rev.hpp>\n# include <cppad/local/subgraph/get_rev.hpp>\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/subgraph/init_rev.hpp",
    "content": "# ifndef CPPAD_LOCAL_SUBGRAPH_INIT_REV_HPP\n# define CPPAD_LOCAL_SUBGRAPH_INIT_REV_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/local/subgraph/info.hpp>\n\n// BEGIN_CPPAD_LOCAL_SUBGRAPH_NAMESPACE\nnamespace CppAD { namespace local { namespace subgraph {\n/*!\n\\file init_rev.hpp\ninitialize for a reverse mode subgraph calculation\n*/\n\n// -----------------------------------------------------------------------\n/*!\nInitialize in_subgraph corresponding to a single dependent variable\n(and a selected set of independent variables).\n\n\\tparam Addr\nis the type used for indices in the random iterator.\n\n\\param random_itr\nIs a random iterator for this operation sequence.\n\n\\param select_domain\nis a vector with, size equal to the number of independent variables\nin the recording. It determines the selected independent variables.\n\n\\par in_subgraph_\nWe use depend_yes (depend_no) for the value n_dep_ (n_dep_ + 1).\nThe important properties are that depend_yes < depend_no and\nfor a valid independent variable index i_ind < depend_yes.\nThe input size and elements of in_subgraph_ do not matter.\nIf in_subgraph_[i_op] == depend_yes (depend_no),\nthe result for this operator depends (does not depend)\non the selected independent variables.\nNote that for atomic function call operators i_op,\nin_subgraph[i_op] is depend_no except for the first AFunOp in the\natomic function call sequence. For the first AFunOp,\nit is depend_yes (depend_no) if any of the results for the call sequence\ndepend (do not depend) on the selected independent variables.\nExcept for UserOP, only operators with NumRes(op) > 0 have in_subgraph_\nvalue depend_yes;\ne.g., comparison operators have in_subgraph_ value depend_no.\n\n\\par select_domain_\nThis vector is is set equal to the select_domain argument.\n\n\\par process_range_\nThis vector is to to size n_dep_ and its values are set to false\n*/\ntemplate <class Addr, class BoolVector>\nvoid subgraph_info::init_rev(\n    const local::play::const_random_iterator<Addr>&  random_itr    ,\n    const BoolVector&                                select_domain )\n{\n    // check sizes\n    CPPAD_ASSERT_UNKNOWN( map_user_op_.size()   == n_op_ );\n    CPPAD_ASSERT_UNKNOWN( random_itr.num_op()   == n_op_ );\n    CPPAD_ASSERT_UNKNOWN( size_t( select_domain.size() ) == n_ind_ );\n\n    // depend_yes and depend_no\n    addr_t depend_yes = addr_t( n_dep_ );\n    addr_t depend_no  = addr_t( n_dep_ + 1 );\n\n    // select_domain_\n    select_domain_.resize(n_ind_);\n    for(size_t j = 0; j < n_ind_; ++j)\n        select_domain_[j]  = select_domain[j];\n\n    // process_range_\n    process_range_.resize(n_dep_);\n    for(size_t i = 0; i < n_dep_; ++i)\n        process_range_[i] = false;\n\n    // set in_subgraph to have proper size\n    in_subgraph_.resize(n_op_);\n\n    // space used to return set of arguments that are variables\n    pod_vector<size_t> argument_variable;\n\n    // temporary space used by get_argument_variable\n    pod_vector<bool> work;\n\n# ifndef NDEBUG\n    size_t count_independent = 0;\n# endif\n    bool begin_atomic_call = false;\n    for(size_t i_op = 0; i_op < n_op_; ++i_op)\n    {   op_code_var op = random_itr.get_op(i_op);\n        //\n        // default value for this operator\n        in_subgraph_[i_op] = depend_no;\n        //\n        switch(op)\n        {   case InvOp:\n            CPPAD_ASSERT_UNKNOWN( NumRes(op) > 0 );\n            CPPAD_ASSERT_UNKNOWN( i_op > 0 );\n            {   // get user index for this independent variable\n                size_t j = i_op - 1;\n                CPPAD_ASSERT_UNKNOWN( j < n_ind_ );\n                //\n                // set in_subgraph_[i_op]\n                if( select_domain[j] )\n                    in_subgraph_[i_op] = depend_yes;\n            }\n# ifndef NDEBUG\n            ++count_independent;\n# endif\n            break;\n\n            // only mark both first AFunOp for each call as depending\n            // on the selected independent variables\n            case AFunOp:\n            begin_atomic_call  = ! begin_atomic_call;\n            if( begin_atomic_call )\n            {   get_argument_variable(random_itr, i_op, argument_variable, work);\n                for(size_t j = 0; j < argument_variable.size(); ++j)\n                {   size_t j_var = argument_variable[j];\n                    size_t j_op  = random_itr.var2op(j_var);\n                    j_op         = size_t( map_user_op_[j_op] );\n                    CPPAD_ASSERT_UNKNOWN( j_op < i_op );\n                    if( in_subgraph_[j_op] == depend_yes )\n                        in_subgraph_[i_op] =  depend_yes;\n                }\n            }\n            break;\n\n            // skip FunrvOp (gets mapped to first AFunOp in this call)\n            case FunrvOp:\n            CPPAD_ASSERT_UNKNOWN( NumRes(op) > 0 );\n            break;\n\n            default:\n            // Except for AFunOp, only include when NumRes(op) > 0.\n            if( NumRes(op) > 0 )\n            {   get_argument_variable(random_itr, i_op, argument_variable, work);\n                for(size_t j = 0; j < argument_variable.size(); ++j)\n                {   size_t j_var = argument_variable[j];\n                    size_t j_op  = random_itr.var2op(j_var);\n                    j_op         = size_t( map_user_op_[j_op] );\n                    CPPAD_ASSERT_UNKNOWN( j_op < i_op );\n                    if( in_subgraph_[j_op] == depend_yes )\n                        in_subgraph_[i_op] =  depend_yes;\n                }\n            }\n            break;\n        }\n    }\n    CPPAD_ASSERT_UNKNOWN(\n        count_independent == size_t(select_domain.size())\n    );\n    //\n    return;\n}\n// -----------------------------------------------------------------------\n/*!\nInitialize in_subgraph corresponding to a single dependent variable\n(and a selected set of independent variables).\n\n\\tparam Addr\nis the type used for indices in the random iterator.\n\n\\tparam Base\nthis recording was made using ADFun<Base>\n\n\\param play\nis a player for this ADFun<Base> object.\n\n\\param select_domain\nis a vector with, size equal to the number of independent variables\nin the recording. It determines the selected independent variables.\n\n\\par in_subgraph_\nWe use depend_yes (depend_no) for the value n_dep_ (n_dep_ + 1).\nThe important properties are that depend_yes < depend_no and\nfor a valid independent variable index i_ind < depend_yes.\nThe input size and elements of in_subgraph_ do not matter.\nIf in_subgraph_[i_op] == depend_yes (depend_no),\nthe result for this operator depends (does not depend)\non the selected independent variables.\nNote that for atomic function call operators i_op,\nin_subgraph[i_op] is depend_no except for the first AFunOp in the\natomic function call sequence. For the first AFunOp,\nit is depend_yes (depend_no) if any of the results for the call sequence\ndepend (do not depend) on the selected independent variables.\nExcept for UserOP, only operators with NumRes(op) > 0 have in_subgraph_\nvalue depend_yes;\ne.g., comparison operators have in_subgraph_ value depend_no.\n\n\\par select_domain_\nThis vector is is set equal to the select_domain argument.\n\n\\par process_range_\nThis vector is to to size n_dep_ and its values are set to false\n*/\ntemplate <class Addr, class Base, class BoolVector>\nvoid subgraph_info::init_rev(\n    player<Base>*       play          ,\n    const BoolVector&   select_domain )\n{\n    // get random access iterator for this player\n    Addr not_used;\n    play->setup_random( not_used );\n    local::play::const_random_iterator<Addr> random_itr =\n        play->get_random( not_used );\n    //\n    init_rev(random_itr, select_domain);\n    //\n    return;\n}\n\n\n} } } // END_CPPAD_LOCAL_SUBGRAPH_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/subgraph/sparsity.hpp",
    "content": "# ifndef CPPAD_LOCAL_SUBGRAPH_SPARSITY_HPP\n# define CPPAD_LOCAL_SUBGRAPH_SPARSITY_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/local/pod_vector.hpp>\n# include <cppad/local/subgraph/arg_variable.hpp>\n# include <cppad/local/subgraph/info.hpp>\n# include <cppad/local/subgraph/entire_call.hpp>\n\n// BEGIN_CPPAD_LOCAL_SUBGRAPH_NAMESPACE\nnamespace CppAD { namespace local { namespace subgraph {\n/*!\n\\file sparsity.hpp\nCompute dependency sparsity pattern using subgraph technique.\n*/\n// ===========================================================================\n/*!\nCompute dependency sparsity pattern for an ADFun<Base> function.\n\n\\tparam Addr\ntype used for indices in random iterator\n(must correspond to play->addr_type())\n\n\\tparam Base\nthe operation sequence was recorded using AD<Base>.\n\n\\tparam BoolVector\na simple vector class with elements of type bool.\n\n\\param play\nis the operation sequence corresponding to the ADFun<Base> function.\nIt is effectively const except that play->setup_random() is called.\n\n\n\\param sub_info\nis the subgraph information for this ADFun object.\n\n\\param dep_taddr\nmapping from user dependent variable index to variable index in play\n(must have size sub_info.n_dep()).\n\n\\param select_domain\nonly the selected independent variables will be included in the sparsity\npattern (must have size sub_info.n_ind()).\n\n\\param select_range\nonly the selected dependent variables will be included in the sparsity pattern\n(must have size sub_info.n_dep()).\n\n\\param row_out\nThe input size and elements of row_out do not matter.\nWe use number of non-zeros (nnz) to denote the number of elements\nin row_out. For k = 0 , ... , nnz-1, row_out[k] is the row index\nof the k-th no-zero element of the dependency sparsitiy pattern for\nthe function corresponding to the recording.\n\\code\n    0 <= row_out[k] < dep_taddr.size()\n    select_range[ row_out[k] ] == true\n\\endcode\n\n\\param col_out\nThe input size and elements of col_out do not matter.\nUpon return is has the same size as row_out; i.e., nnz.\nFor k = 0 , ... , nnz-1, col_out[k] is the column index\nof the k-th no-zero element of the dependency sparsitiy pattern for\nthe function corresponding to the recording.\n\\code\n    0 <= col_out[k] < sub_info.n_ind()\n    select_domain[ col_out[k] ] == true\n\\endcode\n\n\\par AFunOp\nAll of the inputs and outputs for an atomic function call are considered\nto be connected.\n2DO: It would be good to use the sparsity patters for atomic function calls\nto to make the sparsity pattern more efficient.\n*/\n\ntemplate <class Addr, class Base, class BoolVector>\nvoid subgraph_sparsity(\n    player<Base>*                              play          ,\n    subgraph_info&                             sub_info      ,\n    const pod_vector<size_t>&                  dep_taddr     ,\n    const BoolVector&                          select_domain ,\n    const BoolVector&                          select_range  ,\n    pod_vector<size_t>&                        row_out       ,\n    pod_vector<size_t>&                        col_out       )\n{\n    // get random access iterator for this player\n    Addr not_used;\n    play->setup_random( not_used );\n    local::play::const_random_iterator<Addr> random_itr =\n        play->get_random( not_used );\n\n    // check dimension assumptions\n    CPPAD_ASSERT_UNKNOWN(\n        dep_taddr.size() == sub_info.n_dep()\n    );\n    CPPAD_ASSERT_UNKNOWN(\n        size_t(select_domain.size()) == sub_info.n_ind()\n    );\n    CPPAD_ASSERT_UNKNOWN(\n        size_t(select_range.size()) == sub_info.n_dep()\n    );\n\n    // number of dependent variables\n    size_t n_dep = dep_taddr.size();\n    CPPAD_ASSERT_UNKNOWN( size_t(select_range.size()) == n_dep );\n\n    // start with an empty sparsity pattern\n    row_out.resize(0);\n    col_out.resize(0);\n\n    // map_user_op\n    if( sub_info.map_user_op().size() == 0 )\n        sub_info.set_map_user_op(play);\n    else\n    {   CPPAD_ASSERT_UNKNOWN( sub_info.check_map_user_op(play) );\n    }\n    CPPAD_ASSERT_UNKNOWN(\n            sub_info.map_user_op().size() == play->num_var_op()\n    );\n\n    // subgraph of operators that are are connected to one of the selected\n    // dependent variables and depend on the selected independent variables\n    pod_vector<addr_t> subgraph;\n\n    // initialize a reverse mode subgraph calculation\n    sub_info.init_rev(random_itr, select_domain);\n    CPPAD_ASSERT_UNKNOWN(\n        sub_info.in_subgraph().size() == play->num_var_op()\n    );\n    //\n# ifndef NDEBUG\n    addr_t depend_yes = addr_t( n_dep );\n# endif\n\n    // for each of the selected dependent variables\n# ifndef NDEBUG\n    addr_t depend_no  = addr_t( n_dep + 1 );\n# endif\n    CPPAD_ASSERT_UNKNOWN( depend_yes < depend_no );\n    CPPAD_ASSERT_UNKNOWN( NumRes(BeginOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(InvOp) == 1 );\n    for(size_t i_dep = 0; i_dep < n_dep; ++i_dep) if( select_range[i_dep] )\n    {   CPPAD_ASSERT_UNKNOWN( i_dep < size_t( depend_yes ) );\n        //\n        // subgraph of operators connected to i_dep\n        sub_info.get_rev(\n            random_itr, dep_taddr, addr_t(i_dep), subgraph\n        );\n        //\n        for(size_t k = 0; k < subgraph.size(); k++)\n        {   size_t i_op = size_t( subgraph[k] );\n            //\n            // operator corresponding to this index\n            op_code_var op = play->GetOp(i_op);\n            //\n            // This version of the subgraph only has first AFunOp\n            // for each atomic functionc all.\n            CPPAD_ASSERT_UNKNOWN( NumRes(op) > 0 || op == AFunOp );\n            //\n            // independent variable entries correspond to sparsity pattern\n            if( op == InvOp )\n            {   CPPAD_ASSERT_NARG_NRES(op, 0, 1);\n                // i_var is equal i_op because BeginOp and InvOp have 1 result\n                size_t i_var = i_op;       // tape index for this variable\n                size_t i_ind = i_var - 1;  // user index for this variable\n                CPPAD_ASSERT_UNKNOWN( random_itr.var2op(i_var) == i_op );\n                CPPAD_ASSERT_UNKNOWN( select_domain[i_ind] );\n                //\n                // put this pair in the sparsity pattern\n                row_out.push_back(i_dep);\n                col_out.push_back(i_ind);\n            }\n        }\n    }\n}\n\n} } } // END_CPPAD_LOCAL_SUBGRAPH_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/sweep/call_atomic.hpp",
    "content": "# ifndef CPPAD_LOCAL_SWEEP_CALL_ATOMIC_HPP\n# define CPPAD_LOCAL_SWEEP_CALL_ATOMIC_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/local/atomic_index.hpp>\n# include <cppad/core/atomic/two/atomic.hpp>\n# include <cppad/core/atomic/three/atomic.hpp>\n# include <cppad/core/atomic/four/atomic.hpp>\n\n// BEGIN_CPAPD_LOCAL_SWEEP_NAMESPACE\nnamespace CppAD { namespace local { namespace sweep {\n\n/*\n// ----------------------------------------------------------------------------\n{xrst_begin_parent call_atomic dev}\n\nAtomic Function Callbacks\n#########################\n\n{xrst_end call_atomic}\n// ----------------------------------------------------------------------------\n{xrst_begin atomic_forward_callback dev}\n\nForward Mode Callback to Atomic Functions\n#########################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_FORWARD\n    // END_FORWARD\n}\n\nBase\n****\nIs the base type corresponding to the atomic function call.\n\nRecBase\n*******\nIs the base type corresponding to this atomic function call.\n\nvector\n******\nis the CppAD::vector template class.\n\nparameter_x\n***********\ncontains the values, in afun(ax, ay), for arguments that are parameters.\n\ntype_x\n******\nwhat is the type, in the call, for each component of x.\n\nneed_y\n******\nspecifies which components of taylor_y are necessary.\nOnly the components of y with the type equal to need_y need\nto be computed. If need_y is greater than variable_enum,\nthen all the components of y must be computed.\n\nselect_y\n********\nspecifies which components of taylor_y are necessary.\n\norder_low\n*********\nlowest order for this forward mode calculation.\n\norder_up\n********\nhighest order for this forward mode calculation.\n\natom_index\n**********\nis the index, in local::atomic_index, corresponding to this atomic function.\n\ncall_id\n*******\nsee the atomic_four :ref:`atomic_four_call@call_id` and\nthe atomic_one :ref:`atomic_one@id` .\n\ntaylor_x\n********\nTaylor coefficients corresponding to x.\n\ntaylor_y\n********\nTaylor coefficient corresponding to y.\n\n{xrst_end atomic_forward_callback}\n*/\n// BEGIN_FORWARD\ntemplate <class Base, class RecBase>\nvoid call_atomic_forward(\n    const vector<Base>&          parameter_x ,\n    const vector<ad_type_enum>&  type_x      ,\n    size_t                       need_y      ,\n    const vector<bool>&          select_y    ,\n    size_t                       order_low   ,\n    size_t                       order_up    ,\n    size_t                       atom_index  ,\n    size_t                       call_id     ,\n    const vector<Base>&          taylor_x    ,\n    vector<Base>&                taylor_y    )\n// END_FORWARD\n{  CPPAD_ASSERT_UNKNOWN( 0 < atom_index );\n    bool         set_null = false;\n    size_t       type     = 0;          // set to avoid warning\n    std::string* name_ptr = nullptr;\n    void*        v_ptr    = nullptr; // set to avoid warning\n    local::atomic_index<RecBase>(set_null, atom_index, type, name_ptr, v_ptr);\n# ifndef NDEBUG\n    bool ok = v_ptr != nullptr;\n    if( ok )\n    {\n        if( type == 2 )\n        {  atomic_base<RecBase>* afun =\n                reinterpret_cast< atomic_base<RecBase>* >(v_ptr);\n            afun->set_old(call_id);\n            vector<ad_type_enum> empty;\n            ok = afun->forward(\n                order_low, order_up, empty, empty, taylor_x, taylor_y\n            );\n        }\n        else if( type == 3 )\n        {  CPPAD_ASSERT_UNKNOWN( type == 3 );\n            atomic_three<RecBase>* afun =\n                reinterpret_cast< atomic_three<RecBase>* >(v_ptr);\n            ok = afun->forward(\n                parameter_x, type_x,\n                need_y, order_low, order_up, taylor_x, taylor_y\n            );\n        }\n        else\n        {  CPPAD_ASSERT_UNKNOWN( type == 4 );\n            atomic_four<RecBase>* afun =\n                reinterpret_cast< atomic_four<RecBase>* >(v_ptr);\n            ok = afun->forward(\n                call_id, select_y, order_low, order_up, taylor_x, taylor_y\n            );\n        }\n    }\n    if( ! ok )\n    {  // now take the extra time to copy the name\n        std::string name;\n        local::atomic_index<RecBase>(set_null, atom_index, type, &name, v_ptr);\n        std::string msg = name;\n        if( v_ptr == nullptr )\n            msg += \": this atomic function has been deleted\";\n        else\n            msg += \": atomic forward returned false\";\n        CPPAD_ASSERT_KNOWN(false, msg.c_str() );\n    }\n# else\n    if( type == 2 )\n    {  atomic_base<RecBase>* afun =\n            reinterpret_cast< atomic_base<RecBase>* >(v_ptr);\n        vector<ad_type_enum> empty;\n        afun->set_old(call_id);\n        afun->forward(\n            order_low, order_up, empty, empty, taylor_x, taylor_y\n        );\n    }\n    else if( type == 3 )\n    {  atomic_three<RecBase>* afun =\n            reinterpret_cast< atomic_three<RecBase>* >(v_ptr);\n        afun->forward(\n            parameter_x, type_x,\n            need_y, order_low, order_up, taylor_x, taylor_y\n        );\n    }\n    else\n    {  atomic_four<RecBase>* afun =\n            reinterpret_cast< atomic_four<RecBase>* >(v_ptr);\n        afun->forward(\n            call_id, select_y, order_low, order_up, taylor_x, taylor_y\n        );\n    }\n# endif\n}\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_reverse_callback dev}\n\nReverse Mode callback to Atomic Functions\n#########################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_REVERSE\n    // END_REVERSE\n}\n\nBase\n****\nIs the base type corresponding to the atomic function call.\n\nRecBase\n*******\nIs the base type corresponding to this atomic function call.\n\nvector\n******\nis the CppAD::vector template class.\n\nparameter_x\n***********\nvalue of the parameter arguments to the atomic function\n(other arguments have the value nan).\n\ntype_x\n******\ntype for each component of x (not used by atomic_two interface).\n\nselect_x\n********\nspecifies which components of partial_x are necessary.\n\norder_up\n********\nhighest order for this reverse mode calculation.\n\natom_index\n**********\nis the index, in local::atomic_index, corresponding to this atomic function.\n\ncall_id\n*******\nsee the atomic_four :ref:`atomic_four_call@call_id` and\nthe atomic_one :ref:`atomic_one@id` .\n\ntaylor_x\n********\nTaylor coefficients corresponding to x.\n\ntaylor_y\n********\nTaylor coefficient corresponding to y.\n\npartial_x\n*********\nPartials w.r.t the x Taylor coefficients.\n\npartial_y\n*********\nPartials w.r.t the y Taylor coefficients.\n\n{xrst_end atomic_reverse_callback}\n*/\n// BEGIN_REVERSE\ntemplate <class Base, class RecBase>\nvoid call_atomic_reverse(\n    const vector<Base>&          parameter_x ,\n    const vector<ad_type_enum>&  type_x      ,\n    const vector<bool>&          select_x    ,\n    size_t                       order_up    ,\n    size_t                       atom_index  ,\n    size_t                       call_id     ,\n    const vector<Base>&          taylor_x    ,\n    const vector<Base>&          taylor_y    ,\n    vector<Base>&                partial_x   ,\n    const vector<Base>&          partial_y   )\n// END_REVERSE\n{  CPPAD_ASSERT_UNKNOWN( 0 < atom_index );\n    bool         set_null = false;\n    size_t       type     = 0;          // set to avoid warning\n    std::string* name_ptr = nullptr;\n    void*        v_ptr    = nullptr; // set to avoid warning\n    local::atomic_index<RecBase>(set_null, atom_index, type, name_ptr, v_ptr);\n# ifndef NDEBUG\n    bool ok = v_ptr != nullptr;\n    if( ok )\n    {\n        if( type == 2 )\n        {  atomic_base<RecBase>* afun =\n                reinterpret_cast< atomic_base<RecBase>* >(v_ptr);\n            afun->set_old(call_id);\n            ok = afun->reverse(\n                order_up, taylor_x, taylor_y, partial_x, partial_y\n            );\n        }\n        else if( type == 3 )\n        {  atomic_three<RecBase>* afun =\n                reinterpret_cast< atomic_three<RecBase>* >(v_ptr);\n            ok = afun->reverse(\n                parameter_x, type_x,\n                order_up, taylor_x, taylor_y, partial_x, partial_y\n            );\n        }\n        else\n        {  CPPAD_ASSERT_UNKNOWN( type == 4 );\n            atomic_four<RecBase>* afun =\n                reinterpret_cast< atomic_four<RecBase>* >(v_ptr);\n            ok = afun->reverse(\n                call_id, select_x,\n                order_up, taylor_x, taylor_y, partial_x, partial_y\n            );\n        }\n    }\n    if( ! ok )\n    {  // now take the extra time to copy the name\n        std::string name;\n        local::atomic_index<RecBase>(set_null, atom_index, type, &name, v_ptr);\n        std::string msg = name;\n        if( v_ptr == nullptr )\n            msg += \": this atomic function has been deleted\";\n        else\n            msg += \": atomic reverse returned false\";\n        CPPAD_ASSERT_KNOWN(false, msg.c_str() );\n    }\n# else\n    if( type == 2 )\n    {  atomic_base<RecBase>* afun =\n            reinterpret_cast< atomic_base<RecBase>* >(v_ptr);\n        afun->set_old(call_id);\n        afun->reverse(\n            order_up, taylor_x, taylor_y, partial_x, partial_y\n        );\n    }\n    else if( type == 3 )\n    {  atomic_three<RecBase>* afun =\n            reinterpret_cast< atomic_three<RecBase>* >(v_ptr);\n        afun->reverse(\n            parameter_x, type_x,\n            order_up, taylor_x, taylor_y, partial_x, partial_y\n        );\n    }\n    else\n    {  atomic_four<RecBase>* afun =\n            reinterpret_cast< atomic_four<RecBase>* >(v_ptr);\n        afun->reverse(\n            call_id, select_x,\n            order_up, taylor_x, taylor_y, partial_x, partial_y\n        );\n    }\n# endif\n}\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_for_jac_sparsity_callback dev}\n{xrst_spell\n    setvec\n}\n\nForward Jacobian Sparsity Callback to Atomic Functions\n######################################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_FOR_JAC_SPARSITY\n    // END_FOR_JAC_SPARSITY\n}\n\nBase\n****\nIs the base type corresponding to the atomic function call.\n\nvector\n******\nis the CppAD::vector template class.\n\nInternalSparsity\n****************\nis the internal type used to represent sparsity; i.e.,\nsparse::pack_setvec or sparse::list_setvec.\n\natom_index\n**********\nis the index, in local::atomic_index, corresponding to this atomic function.\n\ncall_id\n*******\nsee the atomic_four :ref:`atomic_four_call@call_id` and\nthe atomic_one :ref:`atomic_one@id` .\n\ndependency\n**********\nis this a dependency or sparsity calculation.\n\nparameter_x\n***********\nvalue of the parameter arguments to the atomic function\n(other arguments have the value nan).\n\ntype_x\n******\ntype for each component of x (not used by atomic_two interface).\n\nx_index\n*******\nis a mapping from the index of an atomic function argument\nto the corresponding variable on the tape.\n\ny_index\n*******\nis a mapping from the index of an atomic function result\nto the corresponding variable on the tape.\n\nvar_sparsity\n************\nOn input, for j = 0, ... , n-1, the sparsity pattern with index x_index[j],\nis the sparsity for the j-th argument to this atomic function.\nOn output, for i = 0, ... , m-1, the sparsity pattern with index y_index[i],\nis the sparsity for the i-th result for this atomic function.\n\n{xrst_end atomic_for_jac_sparsity_callback}\n*/\n// BEGIN_FOR_JAC_SPARSITY\ntemplate <class Base, class RecBase, class InternalSparsity>\nvoid call_atomic_for_jac_sparsity(\n    size_t                       atom_index    ,\n    size_t                       call_id       ,\n    bool                         dependency    ,\n    const vector<Base>&          parameter_x   ,\n    const vector<ad_type_enum>&  type_x        ,\n    const vector<size_t>&        x_index       ,\n    const vector<size_t>&        y_index       ,\n    InternalSparsity&            var_sparsity  )\n// END_FOR_JAC_SPARSITY\n{  CPPAD_ASSERT_UNKNOWN( 0 < atom_index );\n    bool         set_null = false;\n    size_t       type     = 0;       // set to avoid warning\n    std::string* name_ptr = nullptr;\n    void*        v_ptr    = nullptr; // set to avoid warning\n    local::atomic_index<RecBase>(set_null, atom_index, type, name_ptr, v_ptr);\n    //\n    // ident_zero_x\n    vector<bool> ident_zero_x;\n    if( type == 4 )\n    {  size_t n = x_index.size();\n        ident_zero_x.resize(n);\n        for(size_t j = 0; j < n; ++j)\n        {  if( type_x[j] > constant_enum )\n                ident_zero_x[j] = false;\n            else\n                ident_zero_x[j] = IdenticalZero( parameter_x[j] );\n        }\n    }\n# ifndef NDEBUG\n    bool ok = v_ptr != nullptr;\n    if ( ok )\n    {\n        if( type == 2 )\n        {  atomic_base<RecBase>* afun =\n                reinterpret_cast< atomic_base<RecBase>* >(v_ptr);\n            afun->set_old(call_id);\n            ok = afun->for_sparse_jac(\n                parameter_x, x_index, y_index, var_sparsity\n            );\n        }\n        else if( type == 3 )\n        {  atomic_three<RecBase>* afun =\n                reinterpret_cast< atomic_three<RecBase>* >(v_ptr);\n            ok = afun->for_jac_sparsity(\n            dependency, parameter_x, type_x, x_index, y_index, var_sparsity\n            );\n        }\n        else\n        {  CPPAD_ASSERT_UNKNOWN( type == 4 );\n            atomic_four<RecBase>* afun =\n                reinterpret_cast< atomic_four<RecBase>* >(v_ptr);\n            ok = afun->for_jac_sparsity( call_id,\n                dependency, ident_zero_x, x_index, y_index, var_sparsity\n            );\n        }\n    }\n    if( ! ok )\n    {  // now take the extra time to copy the name\n        std::string name;\n        local::atomic_index<RecBase>(\n            set_null, atom_index, type, &name, v_ptr\n        );\n        std::string msg = name;\n        if( v_ptr == nullptr )\n            msg += \": this atomic function has been deleted\";\n        else\n            msg += \": atomic jac_sparsity returned false\";\n        CPPAD_ASSERT_KNOWN(false, msg.c_str() );\n    }\n# else\n    if( type == 2 )\n    {  atomic_base<RecBase>* afun =\n            reinterpret_cast< atomic_base<RecBase>* >(v_ptr);\n        afun->set_old(call_id);\n        afun->for_sparse_jac(\n            parameter_x, x_index, y_index, var_sparsity\n        );\n    }\n    else if( type == 3 )\n    {  atomic_three<RecBase>* afun =\n            reinterpret_cast< atomic_three<RecBase>* >(v_ptr);\n        afun->for_jac_sparsity(\n            dependency, parameter_x, type_x, x_index, y_index, var_sparsity\n        );\n    }\n    else\n    {  atomic_four<RecBase>* afun =\n            reinterpret_cast< atomic_four<RecBase>* >(v_ptr);\n        afun->for_jac_sparsity( call_id,\n            dependency, ident_zero_x, x_index, y_index, var_sparsity\n        );\n    }\n# endif\n}\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_rev_jac_sparsity_callback dev}\n{xrst_spell\n    setvec\n}\n\nReverse Jacobian sparsity Callback to Atomic Functions\n######################################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_REV_JAC_SPARSITY\n    // END_REV_JAC_SPARSITY\n}\n\nBase\n****\nis the type corresponding to parameter_x\nand to this atomic function.\n\nInternalSparsity\n****************\nis the internal type used to represent sparsity; i.e.,\nsparse::pack_setvec or sparse::list_setvec.\n\natom_index\n**********\nis the index, in local::atomic_index, corresponding to this atomic function.\n\ncall_id\n*******\nsee the atomic_four :ref:`atomic_four_call@call_id` and\nthe atomic_one :ref:`atomic_one@id` .\n\ndependency\n**********\nis this a dependency or sparsity calculation.\n\nparameter_x\n***********\nvalue of the parameter arguments to the atomic function\n(other arguments have the value nan).\n\ntype_x\n******\ntype for each component of x (not used by atomic_two interface).\n\nx_index\n*******\nis a mapping from the index of an atomic function argument\nto the corresponding variable on the tape.\n\ny_index\n*******\nis a mapping from the index of an atomic function result\nto the corresponding variable on the tape.\n\nvar_sparsity [in/out]\n*********************\nOn input, for i = 0, ... , m-1, the sparsity pattern with index y_index[i],\nis the sparsity for the i-th argument to this atomic function.\nOn output, for j = 0, ... , n-1, the sparsity pattern with index x_index[j],\nthe sparsity has been updated to remove y as a function of x.\n\n{xrst_end atomic_rev_jac_sparsity_callback}\n*/\n// BEGIN_REV_JAC_SPARSITY\ntemplate <class Base, class RecBase, class InternalSparsity>\nvoid call_atomic_rev_jac_sparsity(\n    size_t                       atom_index    ,\n    size_t                       call_id       ,\n    bool                         dependency    ,\n    const vector<Base>&          parameter_x   ,\n    const vector<ad_type_enum>&  type_x        ,\n    const vector<size_t>&        x_index       ,\n    const vector<size_t>&        y_index       ,\n    InternalSparsity&            var_sparsity  )\n// END_REV_JAC_SPARSITY\n{  CPPAD_ASSERT_UNKNOWN( 0 < atom_index );\n    bool         set_null = false;\n    size_t       type     = 0;          // set to avoid warning\n    std::string* name_ptr = nullptr;\n    void*        v_ptr    = nullptr; // set to avoid warning\n    local::atomic_index<RecBase>(set_null, atom_index, type, name_ptr, v_ptr);\n    //\n    // ident_zero_x\n    vector<bool> ident_zero_x;\n    if( type == 4 )\n    {  size_t n = x_index.size();\n        ident_zero_x.resize(n);\n        for(size_t j = 0; j < n; ++j)\n        {  if( type_x[j] > constant_enum )\n                ident_zero_x[j] = false;\n            else\n                ident_zero_x[j] = IdenticalZero( parameter_x[j] );\n        }\n    }\n# ifndef NDEBUG\n    bool ok = v_ptr != nullptr;\n    if( ok )\n    {\n        if( type == 2 )\n        {  atomic_base<RecBase>* afun =\n                reinterpret_cast< atomic_base<RecBase>* >(v_ptr);\n            afun->set_old(call_id);\n            ok = afun->rev_sparse_jac(\n                parameter_x, x_index, y_index, var_sparsity\n            );\n        }\n        else if( type == 3 )\n        {  atomic_three<RecBase>* afun =\n                reinterpret_cast< atomic_three<RecBase>* >(v_ptr);\n            ok = afun->rev_jac_sparsity(\n            dependency, parameter_x, type_x, x_index, y_index, var_sparsity\n            );\n        }\n        else\n        {  CPPAD_ASSERT_UNKNOWN( type == 4 );\n            atomic_four<RecBase>* afun =\n                reinterpret_cast< atomic_four<RecBase>* >(v_ptr);\n            ok = afun->rev_jac_sparsity(call_id,\n                dependency, ident_zero_x, x_index, y_index, var_sparsity\n            );\n        }\n    }\n    if( ! ok )\n    {  // now take the extra time to copy the name\n        std::string name;\n        local::atomic_index<RecBase>(\n            set_null, atom_index, type, &name, v_ptr\n        );\n        std::string msg = name;\n        if( v_ptr == nullptr )\n            msg += \": this atomic function has been deleted\";\n        else\n            msg += \": atomic jac_sparsity returned false\";\n        CPPAD_ASSERT_KNOWN(false, msg.c_str() );\n    }\n# else\n    if( type == 2 )\n    {  atomic_base<RecBase>* afun =\n            reinterpret_cast< atomic_base<RecBase>* >(v_ptr);\n        afun->set_old(call_id);\n        afun->rev_sparse_jac(\n            parameter_x, x_index, y_index, var_sparsity\n        );\n    }\n    else if( type == 3 )\n    {  atomic_three<RecBase>* afun =\n            reinterpret_cast< atomic_three<RecBase>* >(v_ptr);\n        afun->rev_jac_sparsity(\n            dependency, parameter_x, type_x, x_index, y_index, var_sparsity\n        );\n    }\n    else\n    {  atomic_four<RecBase>* afun =\n            reinterpret_cast< atomic_four<RecBase>* >(v_ptr);\n        afun->rev_jac_sparsity(call_id,\n            dependency, ident_zero_x, x_index, y_index, var_sparsity\n        );\n    }\n# endif\n}\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_for_hes_sparsity_callback dev}\n{xrst_spell\n    setvec\n}\n\nForward Hessian Sparsity Callback to Atomic Functions\n#####################################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_FOR_HES_SPARSITY\n    // END_FOR_HES_SPARSITY\n}\n\nBase\n****\nis the type corresponding to *parameter_x*\nand to this atomic function.\n\nInternalSparsity\n****************\nis the internal type used to represent sparsity; i.e.,\n``sparse::pack_setvec`` or ``sparse::list_setvec`` .\n\natom_index\n**********\nis the index, in local::atomic_index, corresponding to this atomic function.\n\ncall_id\n*******\nsee the atomic_four :ref:`atomic_four_call@call_id` and\nthe atomic_one :ref:`atomic_one@id` .\n\nparameter_x\n***********\nvalue of the parameter arguments to the atomic function\n(other arguments have the value nan).\n\ntype_x\n******\ntype for each component of x (not used by atomic_two interface).\n\nx_index\n*******\nis a mapping from the index of an atomic function argument\nto the corresponding variable on the tape.\nWe use *m_x* to denote the maximum value w.r.t *i* of\n*x_index* [ *i* ] .\n\ny_index\n*******\nis a mapping from the index of an atomic function result\nto the corresponding variable on the tape.\nIt should hold that *m_i* < ``y_index`` [ ``i`` ] for all *i* .\n\nnp1\n***\nThis is the number of independent variables plus one;\ni.e. size of *x* plus one.\n\nnum_var\n*******\nThis is the total number of variables in the tape.\n\nrev_jac_sparsity\n****************\nFor i = 0, ... , m-1, the sparsity pattern with index y_index[i],\nis the reverse Jacobian sparsity for the i-th result to this atomic function.\nThis shows which components of the result affect the function we are\ncomputing the Hessian of.\n\nfor_sparsity\n************\nWe have the conditions *np1* = *for_sparsity* . ``end`` ()\nand *for_sparsity* . ``n_set`` () = *np1* + *num_var* .\n\nInput Jacobian Sparsity\n=======================\nFor *i* = 0, ..., *m_x* ,\nthe *np1* + *i* row of *for_sparsity* is the Jacobian sparsity\nfor the *i*-th variable. These values do not change.\nNote that *i* =0 corresponds to a parameter and\nthe corresponding Jacobian sparsity is empty.\n\nInput Hessian Sparsity\n======================\nFor *i* =1, ..., *n* ,\nthe *i*-th row of *for_sparsity* is the Hessian sparsity\nbefore including the function :math:`y = f(x)`.\n\nOutput Jacobian Sparsity\n========================\nFor *i* =0, ..., *y_index* . ``size`` () ,\nrow *np1* + *y_index* [ *i* ]\nof *for_sparsity* is the Jacobian sparsity\nfor the variable with index *y_index* [ *i* ] .\n\nOutput Hessian Sparsity\n=======================\nFor *i* =1, ..., *n* ,\nthe *i*-th row of *for_sparsity* is the Hessian sparsity\nafter including the function :math:`y = f(x)`.\n\n{xrst_end atomic_for_hes_sparsity_callback}\n*/\n// BEGIN_FOR_HES_SPARSITY\ntemplate <class Base, class RecBase, class InternalSparsity>\nvoid call_atomic_for_hes_sparsity(\n    size_t                       atom_index        ,\n    size_t                       call_id           ,\n    const vector<Base>&          parameter_x       ,\n    const vector<ad_type_enum>&  type_x            ,\n    const vector<size_t>&        x_index           ,\n    const vector<size_t>&        y_index           ,\n    size_t                       np1               ,\n    size_t                       num_var           ,\n    const InternalSparsity&      rev_jac_sparsity  ,\n    InternalSparsity&            for_sparsity      )\n// END_FOR_HES_SPARSITY\n{  CPPAD_ASSERT_UNKNOWN( 0 < atom_index );\n    CPPAD_ASSERT_UNKNOWN( for_sparsity.end() == np1 );\n    CPPAD_ASSERT_UNKNOWN( for_sparsity.n_set() == np1 + num_var );\n\n    bool         set_null = false;\n    size_t       type     = 0;          // set to avoid warning\n    std::string* name_ptr = nullptr;\n    void*        v_ptr    = nullptr; // set to avoid warning\n    local::atomic_index<RecBase>(set_null, atom_index, type, name_ptr, v_ptr);\n    //\n    // ident_zero_x\n    vector<bool> ident_zero_x;\n    if( type == 4 )\n    {  size_t n = x_index.size();\n        ident_zero_x.resize(n);\n        for(size_t j = 0; j < n; ++j)\n        {  if( type_x[j] > constant_enum )\n                ident_zero_x[j] = false;\n            else\n                ident_zero_x[j] = IdenticalZero( parameter_x[j] );\n        }\n    }\n# ifndef NDEBUG\n    bool ok = v_ptr != nullptr;\n    if( ok )\n    {\n        if( type == 2 )\n        {  atomic_base<RecBase>* afun =\n                reinterpret_cast< atomic_base<RecBase>* >(v_ptr);\n            afun->set_old(call_id);\n            ok = afun->for_sparse_hes(\n                parameter_x,\n                x_index,\n                y_index,\n                np1,\n                num_var,\n                rev_jac_sparsity,\n                for_sparsity\n            );\n        }\n        else if( type == 3 )\n        {  atomic_three<RecBase>* afun =\n                reinterpret_cast< atomic_three<RecBase>* >(v_ptr);\n            ok = afun->for_hes_sparsity(\n                parameter_x,\n                type_x,\n                x_index,\n                y_index,\n                np1,\n                num_var,\n                rev_jac_sparsity,\n                for_sparsity\n            );\n        }\n        else\n        {  CPPAD_ASSERT_UNKNOWN( type == 4 );\n            atomic_four<RecBase>* afun =\n                reinterpret_cast< atomic_four<RecBase>* >(v_ptr);\n            ok = afun->for_hes_sparsity(\n                call_id,\n                ident_zero_x,\n                x_index,\n                y_index,\n                np1,\n                num_var,\n                rev_jac_sparsity,\n                for_sparsity\n            );\n        }\n    }\n    if( ! ok )\n    {  // now take the extra time to copy the name\n        std::string name;\n        local::atomic_index<RecBase>(\n            set_null, atom_index, type, &name, v_ptr\n        );\n        std::string msg = name;\n        if( v_ptr == nullptr )\n            msg += \": this atomic function has been deleted\";\n        else\n            msg += \": atomic hes_sparsity returned false\";\n        CPPAD_ASSERT_KNOWN(false, msg.c_str() );\n    }\n# else\n    if( type == 2 )\n    {  atomic_base<RecBase>* afun =\n            reinterpret_cast< atomic_base<RecBase>* >(v_ptr);\n        afun->set_old(call_id);\n        afun->for_sparse_hes(\n            parameter_x,\n            x_index,\n            y_index,\n            np1,\n            num_var,\n            rev_jac_sparsity,\n            for_sparsity\n        );\n    }\n    else if( type == 3 )\n    {  atomic_three<RecBase>* afun =\n            reinterpret_cast< atomic_three<RecBase>* >(v_ptr);\n        afun->for_hes_sparsity(\n            parameter_x,\n            type_x,\n            x_index,\n            y_index,\n            np1,\n            num_var,\n            rev_jac_sparsity,\n            for_sparsity\n        );\n    }\n    else\n    {  atomic_four<RecBase>* afun =\n            reinterpret_cast< atomic_four<RecBase>* >(v_ptr);\n        afun->for_hes_sparsity(\n            call_id,\n            ident_zero_x,\n            x_index,\n            y_index,\n            np1,\n            num_var,\n            rev_jac_sparsity,\n            for_sparsity\n        );\n    }\n# endif\n}\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_rev_hes_sparsity_callback dev}\n{xrst_spell\n    setvec\n}\n\nReverse Hessian Sparsity Callback to Atomic Functions\n#####################################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_REV_HES_SPARSITY\n    // END_REV_HES_SPARSITY\n}\n\nBase\n****\nis the type corresponding to parameter_x\nand to this atomic function.\n\nInternalSparsity\n****************\nis the internal type used to represent sparsity; i.e.,\nsparse::pack_setvec or sparse::list_setvec.\n\ncall_id\n*******\nsee the atomic_four :ref:`atomic_four_call@call_id` and\nthe atomic_one :ref:`atomic_one@id` .\n\nparameter_x\n***********\nvalue of the parameter arguments to the atomic function\n(other arguments have the value nan).\n\ntype_x\n******\ntype for each component of x (not used by atomic_two interface).\n\nx_index\n*******\nis a mapping from the index of an atomic function argument\nto the corresponding variable on the tape.\n\ny_index\n*******\nis a mapping from the index of an atomic function result\nto the corresponding variable on the tape.\n\nfor_jac_sparsity\n****************\nFor j = 0, ... , n-1, the sparsity pattern with index x_index[j],\nis the forward Jacobian sparsity for the j-th argument to this atomic function.\n\nrev_jac_flag\n************\nOn input, for i = 0, ... , m-1, rev_jac_flag[ y_index[i] ] is true\nif the function (we are computing the sparsity for)\ndepends on the variable y_index[i].\nUpon return, for j = 0, ..., n-1, rev_jac_flag[ x_index[j] ] has been set to\ntrue any of the y_index variables are flagged depend on x_index[j].\nOtherwise, rev_jac_flag[ x_index[j] ] is not modified.\n\nrev_hes_sparsity\n****************\nThis is the sparsity pattern for the Hessian.\nOn input, for i = 0, ... , m-1, row y_index[i] is the reverse Hessian sparsity\nwith one of the partials with respect to y_index[i].\nUpon return, for j = 0, ..., n-1, the row x_index[j] has been\nmodified to include components that have a non-zero hessian through\nthe atomic function with one of the partials w.r.t. x_index[j].\n\n{xrst_end atomic_rev_hes_sparsity_callback}\n*/\n// BEGIN_REV_HES_SPARSITY\ntemplate <class Base, class RecBase, class InternalSparsity>\nvoid call_atomic_rev_hes_sparsity(\n    size_t                       atom_index        ,\n    size_t                       call_id           ,\n    const vector<Base>&          parameter_x       ,\n    const vector<ad_type_enum>&  type_x            ,\n    const vector<size_t>&        x_index           ,\n    const vector<size_t>&        y_index           ,\n    const InternalSparsity&      for_jac_sparsity  ,\n    bool*                        rev_jac_flag      ,\n    InternalSparsity&            rev_hes_sparsity  )\n// END_REV_HES_SPARSITY\n{  CPPAD_ASSERT_UNKNOWN( 0 < atom_index );\n    bool         set_null = false;\n    size_t       type     = 0;          // set to avoid warning\n    std::string* name_ptr = nullptr;\n    void*        v_ptr    = nullptr; // set to avoid warning\n    local::atomic_index<RecBase>(set_null, atom_index, type, name_ptr, v_ptr);\n    //\n    // ident_zero_x\n    vector<bool> ident_zero_x;\n    if( type == 4 )\n    {  size_t n = x_index.size();\n        ident_zero_x.resize(n);\n        for(size_t j = 0; j < n; ++j)\n        {  if( type_x[j] > constant_enum )\n                ident_zero_x[j] = false;\n            else\n                ident_zero_x[j] = IdenticalZero( parameter_x[j] );\n        }\n    }\n# ifndef NDEBUG\n    bool ok = v_ptr != nullptr;\n    if( ok )\n    {\n        if( type == 2 )\n        {  atomic_base<RecBase>* afun =\n                reinterpret_cast< atomic_base<RecBase>* >(v_ptr);\n            afun->set_old(call_id);\n            ok = afun->rev_sparse_hes(\n                parameter_x,\n                x_index,\n                y_index,\n                for_jac_sparsity,\n                rev_jac_flag,\n                rev_hes_sparsity\n            );\n        }\n        else if( type == 3 )\n        {  atomic_three<RecBase>* afun =\n                reinterpret_cast< atomic_three<RecBase>* >(v_ptr);\n            ok = afun->rev_hes_sparsity(\n                parameter_x,\n                type_x,\n                x_index,\n                y_index,\n                for_jac_sparsity,\n                rev_jac_flag,\n                rev_hes_sparsity\n            );\n        }\n        else\n        {  CPPAD_ASSERT_UNKNOWN( type == 4 );\n            atomic_four<RecBase>* afun =\n                reinterpret_cast< atomic_four<RecBase>* >(v_ptr);\n            ok = afun->rev_hes_sparsity(\n                call_id,\n                ident_zero_x,\n                x_index,\n                y_index,\n                for_jac_sparsity,\n                rev_jac_flag,\n                rev_hes_sparsity\n            );\n        }\n    }\n    if( ! ok )\n    {  // now take the extra time to copy the name\n        std::string name;\n        local::atomic_index<RecBase>(\n            set_null, atom_index, type, &name, v_ptr\n        );\n        std::string msg = name;\n        if( v_ptr == nullptr )\n            msg += \": this atomic function has been deleted\";\n        else\n            msg += \": atomic hes_sparsity returned false\";\n        CPPAD_ASSERT_KNOWN(false, msg.c_str() );\n    }\n# else\n    if( type == 2 )\n    {  atomic_base<RecBase>* afun =\n            reinterpret_cast< atomic_base<RecBase>* >(v_ptr);\n        afun->set_old(call_id);\n        afun->rev_sparse_hes(\n            parameter_x,\n            x_index,\n            y_index,\n            for_jac_sparsity,\n            rev_jac_flag,\n            rev_hes_sparsity\n        );\n    }\n    else if( type == 3 )\n    {  atomic_three<RecBase>* afun =\n            reinterpret_cast< atomic_three<RecBase>* >(v_ptr);\n        afun->rev_hes_sparsity(\n            parameter_x,\n            type_x,\n            x_index,\n            y_index,\n            for_jac_sparsity,\n            rev_jac_flag,\n            rev_hes_sparsity\n        );\n    }\n    else\n    {  atomic_four<RecBase>* afun =\n            reinterpret_cast< atomic_four<RecBase>* >(v_ptr);\n        afun->rev_hes_sparsity(\n            call_id,\n            ident_zero_x,\n            x_index,\n            y_index,\n            for_jac_sparsity,\n            rev_jac_flag,\n            rev_hes_sparsity\n        );\n    }\n# endif\n}\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin atomic_rev_depend_callback dev}\n\nReverse Dependency Callback to Atomic Functions\n###############################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_REV_DEPEND\n    // END_REV_DEPEND\n}\n\natom_index\n**********\nis the index, in local::atomic_index, corresponding to this atomic function.\n\ncall_id\n*******\nsee the atomic_four :ref:`atomic_four_call@call_id` and\nthe atomic_one :ref:`atomic_one@id` .\n\nparameter_x\n***********\nis the value of the parameters in the corresponding atomic function call.\n\ntype_x\n******\nis the type for each x component in the corresponding atomic function call.\n\ndepend_x\n********\nwhich components of x affect values we are interested in.\nThis is the only output for this routine.\n\ndepend_y\n********\nwhich components of y affect values we are interested in.\n\n{xrst_end atomic_rev_depend_callback}\n*/\n// BEGIN_REV_DEPEND\ntemplate <class Base, class RecBase>\nvoid call_atomic_rev_depend(\n    size_t                      atom_index   ,\n    size_t                      call_id      ,\n    const vector<Base>&         parameter_x  ,\n    const vector<ad_type_enum>& type_x       ,\n    vector<bool>&               depend_x     ,\n    const vector<bool>&         depend_y     )\n// END_REV_DEPEND\n{   CPPAD_ASSERT_UNKNOWN( 0 < atom_index );\n    bool         set_null = false;\n    size_t       type     = 0;          // set to avoid warning\n    std::string* name_ptr = nullptr;\n    void*        v_ptr    = nullptr; // set to avoid warning\n    local::atomic_index<RecBase>(set_null, atom_index, type, name_ptr, v_ptr);\n    //\n    // ident_zero_x\n    vector<bool> ident_zero_x;\n    if( type == 4 )\n    {   size_t n = parameter_x.size();\n        ident_zero_x.resize(n);\n        for(size_t j = 0; j < n; ++j)\n        {   if( type_x[j] > constant_enum )\n                ident_zero_x[j] = false;\n            else\n                ident_zero_x[j] = IdenticalZero( parameter_x[j] );\n        }\n    }\n# ifndef NDEBUG\n    bool ok = v_ptr != nullptr;\n    if( ok )\n    {\n        if( type == 2 )\n        {   atomic_base<RecBase>* afun =\n                reinterpret_cast< atomic_base<RecBase>* >(v_ptr);\n            afun->set_old(call_id);\n            vector<ad_type_enum> empty;\n            ok = afun->rev_depend(parameter_x, type_x, depend_x, depend_y);\n        }\n        else if( type == 3 )\n        {   atomic_three<RecBase>* afun =\n                reinterpret_cast< atomic_three<RecBase>* >(v_ptr);\n            ok = afun->rev_depend(parameter_x, type_x, depend_x, depend_y);\n        }\n        else\n        {   CPPAD_ASSERT_UNKNOWN( type == 4 );\n            atomic_four<RecBase>* afun =\n                reinterpret_cast< atomic_four<RecBase>* >(v_ptr);\n            // rev_depend does not have a wrapper that drops back to\n            // deprecated version of this function.\n            ok = afun->rev_depend(call_id, ident_zero_x, depend_x, depend_y);\n            if( ! ok ) ok = afun->rev_depend(call_id, depend_x, depend_y);\n        }\n    }\n    if( ! ok )\n    {   // now take the extra time to copy the name\n        std::string name;\n        local::atomic_index<RecBase>(set_null, atom_index, type, &name, v_ptr);\n        std::string msg = name;\n        if( v_ptr == nullptr )\n            msg += \": this atomic function has been deleted\";\n        else\n            msg += \": atomic rev_depend returned false\";\n        CPPAD_ASSERT_KNOWN(false, msg.c_str() );\n    }\n# else\n    if( type == 2 )\n    {   atomic_base<RecBase>* afun =\n            reinterpret_cast< atomic_base<RecBase>* >(v_ptr);\n        vector<ad_type_enum> empty;\n        afun->set_old(call_id);\n        afun->rev_depend(parameter_x, type_x, depend_x, depend_y);\n    }\n    else if( type == 3 )\n    {   atomic_three<RecBase>* afun =\n            reinterpret_cast< atomic_three<RecBase>* >(v_ptr);\n        afun->rev_depend(parameter_x, type_x, depend_x, depend_y);\n    }\n    else\n    {   atomic_four<RecBase>* afun =\n            reinterpret_cast< atomic_four<RecBase>* >(v_ptr);\n        // rev_depend does not have a wrapper that drops back to\n        // deprecated version of this function.\n        bool ok = afun->rev_depend(call_id, ident_zero_x, depend_x, depend_y);\n        if( ! ok ) afun->rev_depend(call_id, depend_x, depend_y);\n    }\n# endif\n}\n\n\n} } } // END_CPAPD_LOCAL_SWEEP_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/local/sweep/dev_sweep.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin dev_sweep dev}\n\nDeveloper Sweep Documentation\n#############################\n\nContents\n********\n{xrst_toc_table\n    include/cppad/local/sweep/forward_0.hpp\n    include/cppad/local/sweep/forward_any.hpp\n    include/cppad/local/sweep/forward_dir.hpp\n    include/cppad/local/sweep/for_hes.hpp\n    include/cppad/local/sweep/rev_jac.hpp\n    include/cppad/local/sweep/call_atomic.hpp\n}\n\n{xrst_end dev_sweep}\n"
  },
  {
    "path": "include/cppad/local/sweep/dynamic.hpp",
    "content": "# ifndef CPPAD_LOCAL_SWEEP_DYNAMIC_HPP\n# define CPPAD_LOCAL_SWEEP_DYNAMIC_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/local/play/atom_op_info.hpp>\n\n// BEGIN_CPPAD_LOCAL_SWEEP_NAMESPACE\nnamespace CppAD { namespace local { namespace sweep {\n/*!\n\\file sweep/dynamic.hpp\nUnder Construction\n*/\n\n/*!\n\\def CPPAD_DYNAMIC_TRACE\nThis value is either zero or one.\nZero is the normal operational value.\nIf it is one, a trace for each dynamic parameter is computation is printed.\nSometimes it is useful to trace f.new_dynamic with the same\ndynamic parameter values as during the recording\n(to debug the recording process).\n*/\n# define CPPAD_DYNAMIC_TRACE 0\n\n/*!\nCompute dynamic parameters.\n\n\\tparam Base\nThe type of the parameters.\n\n\\tparam BaseVector\nis a simple vector class with elements of type Base.\n\n\\param ind_dynamic\nnew value for the independent dynamic parameter vector.\n\n\\param par_all\nis the vector of all the parameters.\nThe constant parameters are inputs and the dynamic parameters are outputs.\n\n\\param par_is_dyn\nis a vector with the same length as par_vec.\nThe i-th parameter is dynamic if and only if par_is_dyn[i] is true.\n\n\\param dyn2par_index\nis a vector with length equal to the number of dynamic parameters.\nThe element dyn2par_index[j] is the index in par_all corresponding\nto the j-th dynamic parameter.\nNote that if par_is_dyn[i] is false, the i-th parameter does not\nappear in this vector.\n\n\\param dyn_par_op\nis a vector with length equal to the number of dynamic parameters.\nThe element dyn_par_op_[j] is the operator for the j-th dynamic parameter.\nNote that if par_is_dyn[i] is false, the i-th parameter does not\nhave a parameter in this list.\n\n\\param dyn_par_arg\nis a vector containing the arguments for the dynamic parameters.\nThe first argument for the j-th dynamic parameter is dyn_par_arg[k]\nwhere\n\\code\n    k = NumArg( dyn_par_op[0] ) + ... + NumArg( dyn_par_op[j-1] )\n\\endcode\nThe arguments for each dynamic parameter have index value\nlower than the index value for the parameter.\n\n\\param not_used_rec_base\nSpecifies RecBase for this call.\n*/\n\ntemplate <class RecBase>\nRecBase discrete_eval(size_t index, const RecBase& x, const RecBase& not_used)\n{   return discrete<RecBase>::eval(index, x); }\ntemplate <class RecBase>\nAD<RecBase> discrete_eval(\n    size_t index, const AD<RecBase>& ax, const RecBase& not_used\n)\n{   return discrete<RecBase>::ad_eval(index, ax); }\n\n\n\ntemplate <class Base, class BaseVector, class RecBase>\nvoid dynamic(\n    pod_vector_maybe<Base>&       par_all            ,\n    const BaseVector&             ind_dynamic        ,\n    const pod_vector<bool>&       par_is_dyn         ,\n    const pod_vector<addr_t>&     dyn2par_index      ,\n    const pod_vector<opcode_t>&   dyn_par_op         ,\n    const pod_vector<addr_t>&     dyn_par_arg        ,\n    const RecBase&                not_used_rec_base  )\n{\n    // number of dynamic parameters\n    size_t num_dynamic_par = dyn2par_index.size();\n\n    // vectors used in call to atomic functions\n    vector<ad_type_enum> type_x;\n    vector<Base>         taylor_x, taylor_y;\n    vector<bool>         select_y;\n# ifndef NDEBUG\n    for(size_t j = 0; j < ind_dynamic.size(); ++j)\n        CPPAD_ASSERT_UNKNOWN(\n            par_is_dyn[j+1] && op_code_dyn( dyn_par_op[j] ) == ind_dyn\n    );\n# endif\n# if CPPAD_DYNAMIC_TRACE\n    const char* cond_exp_name[] = {\n        \"CondExpLt\",\n        \"CondExpLe\",\n        \"CondExpEq\",\n        \"CondExpGe\",\n        \"CondExpGt\",\n        \"CondExpNe\"\n    };\n    std::cout\n    << std::endl\n    << std::setw(10) << std::left << \"index\"\n    << std::setw(10) << std::left << \"old\"\n    << std::setw(10) << std::left << \"new\"\n    << std::setw(11) << std::left << \"op\"\n    << std::setw(26) << std::right << \"dynamic i=, constant v=\"\n    << std::endl;\n# endif\n    // used to hold the first two parameter arguments\n    const Base* par[2];\n    for(size_t j = 0; j < 2; ++j)\n        par[j] = nullptr;\n    //\n    // Initialize index in dyn_par_arg\n    size_t i_arg = 0;\n    //\n    // Loop throubh the dynamic parameters\n    size_t i_dyn = 0;\n    while(i_dyn < num_dynamic_par)\n    {   // number of dynamic parameters created by this operator\n        size_t n_dyn = 1;\n        //\n        // parameter index for this dynamic parameter\n        size_t i_par = size_t( dyn2par_index[i_dyn] );\n        //\n# if CPPAD_DYNAMIC_TRACE\n        Base old_value = par_all[i_par];\n# endif\n        //\n        // operator for this dynamic parameter\n        op_code_dyn op = op_code_dyn( dyn_par_op[i_dyn] );\n        //\n        // number of arguments for this operator\n        size_t n_arg       = num_arg_dyn(op);\n        //\n        // for unary or binary operators\n        bool unary_or_binary = true;\n        unary_or_binary &= op != atom_dyn;\n        unary_or_binary &= op != cond_exp_dyn;\n        unary_or_binary &= op != dis_dyn;\n        unary_or_binary &= op != ind_dyn;\n        unary_or_binary &= op != result_dyn;\n        if( unary_or_binary )\n        {   CPPAD_ASSERT_UNKNOWN( n_arg == 1 || n_arg == 2 );\n              for(size_t j = 0; j < n_arg; ++j)\n                par[j] = & par_all[ dyn_par_arg[i_arg + j] ];\n        }\n        //\n        switch(op)\n        {\n            // ---------------------------------------------------------------\n            // standard_math_98\n            // acos\n            case acos_dyn:\n            CPPAD_ASSERT_UNKNOWN( n_arg == 1 );\n            par_all[i_par] = acos( *par[0] );\n            break;\n\n            // asin\n            case asin_dyn:\n            CPPAD_ASSERT_UNKNOWN( n_arg == 1 );\n            par_all[i_par] = asin( *par[0] );\n            break;\n\n            // atan\n            case atan_dyn:\n            CPPAD_ASSERT_UNKNOWN( n_arg == 1 );\n            par_all[i_par] = atan( *par[0] );\n            break;\n\n            // cos\n            case cos_dyn:\n            CPPAD_ASSERT_UNKNOWN( n_arg == 1 );\n            par_all[i_par] = cos( *par[0] );\n            break;\n\n            // cosh\n            case cosh_dyn:\n            CPPAD_ASSERT_UNKNOWN( n_arg == 1 );\n            par_all[i_par] = cosh( *par[0] );\n            break;\n\n            // ind\n            case ind_dyn:\n            CPPAD_ASSERT_UNKNOWN( n_arg == 0 );\n            CPPAD_ASSERT_UNKNOWN( i_par == i_dyn + 1 );\n            par_all[i_par] = ind_dynamic[i_dyn];\n            break;\n\n            // exp\n            case exp_dyn:\n            CPPAD_ASSERT_UNKNOWN( n_arg == 1 );\n            par_all[i_par] = exp( *par[0] );\n            break;\n\n            // fabs\n            case fabs_dyn:\n            CPPAD_ASSERT_UNKNOWN( n_arg == 1 );\n            par_all[i_par] = fabs( *par[0] );\n            break;\n\n            // log\n            case log_dyn:\n            CPPAD_ASSERT_UNKNOWN( n_arg == 1 );\n            par_all[i_par] = log( *par[0] );\n            break;\n\n            // sin\n            case sin_dyn:\n            CPPAD_ASSERT_UNKNOWN( n_arg == 1 );\n            par_all[i_par] = sin( *par[0] );\n            break;\n\n            // sinh\n            case sinh_dyn:\n            CPPAD_ASSERT_UNKNOWN( n_arg == 1 );\n            par_all[i_par] = sinh( *par[0] );\n            break;\n\n            // sqrt\n            case sqrt_dyn:\n            CPPAD_ASSERT_UNKNOWN( n_arg == 1 );\n            par_all[i_par] = sqrt( *par[0] );\n            break;\n\n            // tan\n            case tan_dyn:\n            CPPAD_ASSERT_UNKNOWN( n_arg == 1 );\n            par_all[i_par] = tan( *par[0] );\n            break;\n\n            // tanh\n            case tanh_dyn:\n            CPPAD_ASSERT_UNKNOWN( n_arg == 1 );\n            par_all[i_par] = tanh( *par[0] );\n            break;\n\n            // ---------------------------------------------------------------\n            // asinh\n            case asinh_dyn:\n            CPPAD_ASSERT_UNKNOWN( n_arg == 1 );\n            par_all[i_par] = asinh( *par[0] );\n            break;\n\n            // acosh\n            case acosh_dyn:\n            CPPAD_ASSERT_UNKNOWN( n_arg == 1 );\n            par_all[i_par] = acosh( *par[0] );\n            break;\n\n            // atanh\n            case atanh_dyn:\n            CPPAD_ASSERT_UNKNOWN( n_arg == 1 );\n            par_all[i_par] = atanh( *par[0] );\n            break;\n\n            // expm1\n            case expm1_dyn:\n            CPPAD_ASSERT_UNKNOWN( n_arg == 1 );\n            par_all[i_par] = expm1( *par[0] );\n            break;\n\n            // erf\n            case erf_dyn:\n            CPPAD_ASSERT_UNKNOWN( n_arg == 1 );\n            par_all[i_par] = erf( *par[0] );\n            break;\n\n            // erfc\n            case erfc_dyn:\n            CPPAD_ASSERT_UNKNOWN( n_arg == 1 );\n            par_all[i_par] = erfc( *par[0] );\n            break;\n\n            // log1p\n            case log1p_dyn:\n            CPPAD_ASSERT_UNKNOWN( n_arg == 1 );\n            par_all[i_par] = log1p( *par[0] );\n            break;\n            // ---------------------------------------------------------------\n            // abs\n            case abs_dyn:\n            CPPAD_ASSERT_UNKNOWN( n_arg == 1 );\n            par_all[i_par] = fabs( *par[0] );\n            break;\n\n            // add\n            case add_dyn:\n            CPPAD_ASSERT_UNKNOWN( n_arg == 2 );\n            par_all[i_par] = *par[0] + *par[1];\n            break;\n\n            // div\n            case div_dyn:\n            CPPAD_ASSERT_UNKNOWN( n_arg == 2 );\n            par_all[i_par] = *par[0] / *par[1];\n            break;\n\n            // mul\n            case mul_dyn:\n            CPPAD_ASSERT_UNKNOWN( n_arg == 2 );\n            par_all[i_par] = *par[0] * *par[1];\n            break;\n\n            // neg\n            case neg_dyn:\n            CPPAD_ASSERT_UNKNOWN( n_arg == 1 );\n            par_all[i_par] = - *par[0];\n            break;\n\n            // pow\n            case pow_dyn:\n            CPPAD_ASSERT_UNKNOWN( n_arg == 2 );\n            par_all[i_par] = pow( *par[0], *par[1] );\n            break;\n\n            // sign\n            case sign_dyn:\n            CPPAD_ASSERT_UNKNOWN( n_arg == 1 );\n            par_all[i_par] = sign( *par[0] );\n            break;\n\n            // sub\n            case sub_dyn:\n            CPPAD_ASSERT_UNKNOWN( n_arg == 2 );\n            par_all[i_par] = *par[0] - *par[1];\n            break;\n\n            // zmul\n            case zmul_dyn:\n            CPPAD_ASSERT_UNKNOWN( n_arg == 2 );\n            par_all[i_par] = azmul( *par[0],  *par[1] );\n            break;\n\n            // ---------------------------------------------------------------\n            // discrete(index, argument)\n            case dis_dyn:\n            par_all[i_par] = discrete_eval(\n                    size_t(      dyn_par_arg[i_arg + 0] ) , // index\n                    par_all[ dyn_par_arg[i_arg + 1] ] , // argument\n                    RecBase(0)                              // not_used\n            );\n# if CPPAD_DYNAMIC_TRACE\n            std::cout\n            << std::setw(10) << std::left << i_par\n            << std::setw(10) << std::left << old_value\n            << std::setw(10) << std::left << par_all[i_par]\n            << \"=\"\n            << std::setw(10) << std::right << op_name_dyn(op)\n            << \"(\"\n            << std::setw(12) << std::right <<\n                discrete<Base>::name( size_t( dyn_par_arg[i_arg + 0] ) );\n            if( par_is_dyn[ dyn_par_arg[i_arg + 1] ] )\n            {   std::cout << \", i=\" << std::setw(10) << std::right\n                << dyn_par_arg[i_arg + 1];\n            }\n            else\n            {   std::cout << \", v=\" << std::setw(10) << std::right\n                << par_all[ dyn_par_arg[i_arg + 1] ];\n            }\n            std::cout << \")\" << std::endl;\n# endif\n            break;\n\n            // ---------------------------------------------------------------\n            // cond_exp(cop, left, right, if_true, if_false)\n            // (not yet implemented)\n            case cond_exp_dyn:\n            CPPAD_ASSERT_UNKNOWN( n_arg == 5 );\n            par_all[i_par] = CondExpOp(\n                CompareOp(   dyn_par_arg[i_arg + 0] ) , // cop\n                par_all[ dyn_par_arg[i_arg + 1] ] , // left\n                par_all[ dyn_par_arg[i_arg + 2] ] , // right\n                par_all[ dyn_par_arg[i_arg + 3] ] , // if_true\n                par_all[ dyn_par_arg[i_arg + 4] ]   // if_false\n            );\n# if CPPAD_DYNAMIC_TRACE\n            std::cout\n            << std::setw(10) << std::left << i_par\n            << std::setw(10) << std::left << old_value\n            << std::setw(10) << std::left << par_all[i_par]\n            << \"=\"\n            << std::setw(10) << std::right\n            << cond_exp_name[ dyn_par_arg[i_arg + 0] ]\n            << \"(\";\n            for(size_t i = 1; i < 5; ++i)\n            {   if( par_is_dyn[ dyn_par_arg[i_arg + i] ] )\n                {   std::cout << \"i=\" << std::setw(10) << std::right\n                    << dyn_par_arg[i_arg + i];\n                }\n                else\n                {   std::cout << \"v=\" << std::setw(10) << std::right\n                    << par_all[ dyn_par_arg[i_arg + i] ];\n                }\n                if( i < 4 )\n                    std::cout << \",\";\n            }\n            std::cout << \")\" << std::endl;\n# endif\n            break;\n            // ---------------------------------------------------------------\n            // atomic function results\n            case result_dyn:\n            break;\n\n            // atomic function call\n            case atom_dyn:\n            {   size_t atom_index = size_t( dyn_par_arg[i_arg + 0] );\n                size_t call_id    = size_t( dyn_par_arg[i_arg + 1] );\n                size_t n          = size_t( dyn_par_arg[i_arg + 2] );\n                size_t m          = size_t( dyn_par_arg[i_arg + 3] );\n                n_dyn             = size_t( dyn_par_arg[i_arg + 4] );\n                n_arg             = 6 + n + m;\n                CPPAD_ASSERT_UNKNOWN(\n                    size_t( dyn_par_arg[i_arg + 5 + n + m] ) == n_arg\n                );\n                //\n                size_t need_y    = size_t(dynamic_enum);\n                size_t order_low = 0;\n                size_t order_up  = 0;\n                type_x.resize(n);\n                taylor_x.resize(n);\n                taylor_y.resize(m);\n                select_y.resize(m);\n                //\n                // taylor_x, type_x\n                for(size_t j = 0; j < n; ++j)\n                {   addr_t arg_j = dyn_par_arg[i_arg + 5 + j];\n                    taylor_x[j]   = par_all[ arg_j ];\n                    if( arg_j == 0 )\n                        type_x[j] = variable_enum;\n                    else if ( par_is_dyn[arg_j] )\n                        type_x[j] = dynamic_enum;\n                    else\n                        type_x[j] = constant_enum;\n                }\n                // select_y\n                for(size_t i = 0; i < m; ++i)\n                {   i_par = size_t( dyn_par_arg[i_arg + 5 + n + i] );\n                    select_y[i] = par_is_dyn[i_par];\n                }\n                call_atomic_forward<Base, RecBase>(\n                    taylor_x,\n                    type_x,\n                    need_y,\n                    select_y,\n                    order_low,\n                    order_up,\n                    atom_index,\n                    call_id,\n                    taylor_x,\n                    taylor_y\n                );\n# if CPPAD_DYNAMIC_TRACE\n                // get the name of this atomic function\n                bool         set_null = false;\n                size_t       type     = 0;          // set to avoid warning\n                std::string name;\n                void*        v_ptr    = nullptr; // set to avoid warning\n                atomic_index<RecBase>(\n                    set_null, atom_index, type, &name, v_ptr\n                );\n                std::cout << \"atom_dyn \" << name << \" arguments\\n\";\n                for(size_t j = 0; j < n; ++j)\n                {   std::cout << \"index = \" << j\n                    << \", value = \" << taylor_x[j] << std::endl;\n                }\n                std::cout << \"atom_dyn \" << name << \" results\\n\";\n# endif\n# ifndef NDEBUG\n                size_t count_dyn = 0;\n# endif\n                for(size_t i = 0; i < m; ++i)\n                {   i_par = size_t( dyn_par_arg[i_arg + 5 + n + i] );\n                    if( par_is_dyn[i_par] )\n                    {   CPPAD_ASSERT_UNKNOWN( i_par != 0 );\n                        par_all[i_par] = taylor_y[i];\n# ifndef NDEBUG\n                        ++count_dyn;\n# endif\n# if CPPAD_DYNAMIC_TRACE\n                        std::cout\n                        << std::setw(10) << std::left << i_par\n                        << std::setw(10) << std::left << old_value\n                        << std::setw(10) << std::left << par_all[i_par]\n                        << \"= \" << name << \"_\" << i << std::endl;\n# endif\n                    }\n                }\n                CPPAD_ASSERT_UNKNOWN( count_dyn == n_dyn );\n# if CPPAD_DYNAMIC_TRACE\n                std::cout << \"end atomic dynamic parameter results\\n\";\n# endif\n            }\n            break;\n\n            // ---------------------------------------------------------------\n            default:\n            std::cerr << \"op_code_dyn = \" << op_name_dyn(op) << std::endl;\n            CPPAD_ASSERT_UNKNOWN(false);\n            break;\n        }\n# if CPPAD_DYNAMIC_TRACE\n        if(\n            (op != cond_exp_dyn) &\n            (op != dis_dyn )     &\n            (op != atom_dyn )    &\n            (op != result_dyn )  )\n        {\n            std::cout\n            << std::setw(10) << std::left << i_par\n            << std::setw(10) << std::left << old_value\n            << std::setw(10) << std::left << par_all[i_par]\n            << \"=\"\n            << std::setw(10) << std::right << op_name_dyn(op)\n            << \"(\";\n            if( 0 < n_arg )\n            {   if( par_is_dyn[ dyn_par_arg[i_arg + 0] ] )\n                {   std::cout << \"i=\" << std::setw(10) << std::right\n                    << dyn_par_arg[i_arg + 0];\n                }\n                else\n                {   std::cout << \"v=\" << std::setw(10) << std::right\n                    << par_all[ dyn_par_arg[i_arg + 0] ];\n                }\n            }\n            if( 1 < n_arg )\n            {   if( par_is_dyn[ dyn_par_arg[i_arg + 1] ] )\n                {   std::cout << \", i=\" << std::setw(10) << std::right\n                    << dyn_par_arg[i_arg + 1];\n                }\n                else\n                {   std::cout << \", v=\" << std::setw(10) << std::right\n                    << par_all[ dyn_par_arg[i_arg + 1] ];\n                }\n            }\n            std::cout << \")\" << std::endl;\n        }\n# endif\n        i_arg += n_arg;\n        i_dyn += n_dyn;\n    }\n    CPPAD_ASSERT_UNKNOWN( i_arg == dyn_par_arg.size() )\n    return;\n}\n\n// preprocessor symbols that are local to this file\n# undef CPPAD_DYNAMIC_TRACE\n\n} } } // END_CPPAD_LOCAL_SWEEP_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/sweep/for_hes.hpp",
    "content": "# ifndef CPPAD_LOCAL_SWEEP_FOR_HES_HPP\n# define CPPAD_LOCAL_SWEEP_FOR_HES_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/local/play/atom_op_info.hpp>\n# include <cppad/local/var_op/load_op.hpp>\n# include <cppad/local/var_op/store_op.hpp>\n# include <cppad/local/var_op/csum_op.hpp>\n\n/*\n{xrst_begin local_sweep_for_hes dev}\n{xrst_spell\n    inv\n}\n\nForward Mode Hessian Sparsity Patterns\n######################################\n\nSyntax\n******\n| ``local::sweep::for_hes`` (\n| |tab| *play*               ,\n| |tab| *n*                  ,\n| |tab| *num_var*        ,\n| |tab| *select_domain*      ,\n| |tab| *rev_jac_sparse*     ,\n| |tab| *for_hes_sparse*     ,\n| |tab| ``not_used_rec_base``\n| )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN PROTOTYPE\n    // END PROTOTYPE\n}\n\nPurpose\n*******\nGiven the forward Jacobian sparsity pattern for all the variables,\nand the reverse Jacobian sparsity pattern for the dependent variables,\n``for_hes`` computes the Hessian sparsity pattern for all the independent\nvariables.\n\nCPPAD_FOR_HES_TRACE\n*******************\nThis value is either zero or one.  Zero is the normal operational value.\nIf it is one, a trace of Jacobian and Hessian sparsity result for every\noperation for every ``for_hes`` sweep is printed.\nThe sparsity patterns are printed as binary numbers with 1 (0) meaning that\nthe corresponding index is (is not) in the set.\n{xrst_code hpp} */\n# define CPPAD_FOR_HES_TRACE 0\n/* {xrst_code}\n\nBase\n****\nThe operation sequence in *play* was recorded using\n``AD`` < *Base* > .\n\nRecBase\n*******\nIs the base type when this function was recorded.\nThis is different from *Base* if\nthis function object was created by :ref:`base2ad-name` .\n\nSetVector\n*********\nThis is a :ref:`SetVector-name` type.\n\nplay\n****\nThe information stored in play\nis a recording of the operations corresponding to a function\n:math:`F : \\B{R}^n \\rightarrow \\B{R}^m`\nwhere *m* is the number of dependent variables.\n\nn\n*\nis the number of independent variables in the tape.\n\nnum_var\n*******\nis the total number of variables in the tape; i.e.,\n*play* ``->num_var`` () .\nThis is also the number of sets in all the sparsity patterns.\n\nselect_domain\n*************\nis a vector with size *n* that specifies\nwhich components of the domain to include in the Hessian sparsity pattern.\nFor *j* = 0, ..., *n* ``-1`` , the *j*-th independent variable\nwill be included if and only if *select_domain* [ *j* ] is true.\nThis assumes that the order of the independent variables is the same\nas the order of the InvOp operators.\n\nrev_jac_sparse\n**************\nIs a sparsity pattern with size *num_var* by one.\nFor *i* =1, ..., *num_var* ``-1`` ,\nthe if the scalar valued function we are computing the Hessian sparsity for\nhas a non-zero derivative w.r.t. variable with index *i* ,\nthe set with index *i* has the element zero.\nOtherwise it has no elements.\n\nfor_hes_sparse\n**************\nThis is a sparsity pattern with *n* + 1 + *num_var* sets\nand end value *n* + 1 .\nOn input, all of the sets are empty.\nOn output, it contains the two sparsity patterns described below:\n\nHessian Sparsity\n================\nFor *j* equal 1 to *n* ,\nif *i* is in set with index *j* ,\nthe Hessian may have a non-zero partial with respect to the\nindependent variables with indices ( *i* - 1, *j* - 1 ) .\nNote that the index zero is not used because it corresponds to the\nphantom variable on the tape.\n\nJacobian Sparsity\n=================\nFor *k* equal 1 to *num_var* - 1 ,\nif *i* is in the set with index *n* + 1 + *k* ,\nthe variable with index *k* may have a non-zero partial with resect to the\nindependent variable with index *i* - 1 .\n\nMethod\n======\nFor *k* equal 1 to *num_var* - 1,\nthe Jacobian sparsity pattern for variable with index *k* is computed using\nthe previous Jacobian sparsity patterns.\nThe Hessian sparsity pattern is updated using linear and non-linear\ninteractions for the variable with index *k* and the previous Jacobian\nsparsity patterns.\n\nnot_used_rec_base\n*****************\nThis argument is only used to specify the type *RecBase* for this call.\n\n{xrst_end local_sweep_for_hes}\n*/\n\n// BEGIN_CPPAD_LOCAL_SWEEP_NAMESPACE\nnamespace CppAD { namespace local { namespace sweep {\n\n// BEGIN PROTOTYPE\ntemplate <class Base, class SetVector, class RecBase>\nvoid for_hes(\n    const local::player<Base>* play                ,\n    size_t                     n                   ,\n    size_t                     num_var             ,\n    const pod_vector<bool>&    select_domain       ,\n    const SetVector&           rev_jac_sparse      ,\n    SetVector&                 for_hes_sparse      ,\n    const RecBase&             not_used_rec_base   )\n// END PROTOTYPE\n{\n    // length of the parameter vector (used by CppAD assert macros)\n# ifndef NDEBUG\n    const size_t num_par = play->num_par_all();\n# endif\n\n    // check arguments\n    size_t np1 = n+1;\n    CPPAD_ASSERT_UNKNOWN( select_domain.size()   == n );\n    CPPAD_ASSERT_UNKNOWN( play->num_var()        == num_var );\n    CPPAD_ASSERT_UNKNOWN( rev_jac_sparse.n_set() == num_var );\n    CPPAD_ASSERT_UNKNOWN( for_hes_sparse.n_set() == np1+num_var );\n    //\n    CPPAD_ASSERT_UNKNOWN( rev_jac_sparse.end()   == 1   );\n    CPPAD_ASSERT_UNKNOWN( for_hes_sparse.end()   == np1 );\n    //\n    CPPAD_ASSERT_UNKNOWN( num_var > 0 );\n    //\n    // vecad_sparsity: forward Jacobian sparsity pattern for each VecAD object.\n    // vecad_ind: maps the VecAD index at beginning of the VecAD object\n    //            to the index for the corresponding set in vecad_sparsity.\n    size_t num_vecad_ind   = play->num_var_vec_ind();\n    size_t num_vecad_vec   = play->num_var_vecad();\n    SetVector vecad_sparsity;\n    pod_vector<size_t> vecad_ind;\n    if( num_vecad_vec > 0 )\n    {   size_t length;\n        vecad_sparsity.resize(num_vecad_vec, np1);\n        vecad_ind.extend(num_vecad_ind);\n        size_t j  = 0;\n        for(size_t i = 0; i < num_vecad_vec; i++)\n        {   // length of this VecAD\n            length   = play->GetVecInd(j);\n            // set vecad_ind to proper index for this VecAD\n            vecad_ind[j] = i;\n            // make all other values for this vector invalid\n            for(size_t k = 1; k <= length; k++)\n                vecad_ind[j+k] = num_vecad_vec;\n            // start of next VecAD\n            j       += length + 1;\n        }\n        CPPAD_ASSERT_UNKNOWN( j == play->num_var_vec_ind() );\n    }\n    // ------------------------------------------------------------------------\n    // work space used by atomic functions\n    var_op::atomic_op_work<Base> atom_work;\n    //\n    //\n    // pointer to the beginning of the parameter vector\n    // (used by atomic functions)\n    CPPAD_ASSERT_UNKNOWN( num_par > 0 )\n    const Base* parameter = play->par_ptr();\n    //\n    // skip the BeginOp at the beginning of the recording\n    play::const_sequential_iterator itr = play->begin();\n    // op_info\n    op_code_var   op;\n    size_t        i_var;\n    const addr_t* arg;\n    itr.op_info(op, arg, i_var);\n    CPPAD_ASSERT_UNKNOWN( op == BeginOp );\n# if CPPAD_FOR_HES_TRACE\n    std::cout << std::endl;\n    bool atom_trace = true;\n# else\n    bool atom_trace = false;\n# endif\n    bool   more_operators = true;\n    size_t count_independent = 0;\n    while(more_operators)\n    {   bool linear[3];\n\n        // next op\n        (++itr).op_info(op, arg, i_var);\n\n        // does the Hessian in question have a non-zero derivative\n        // with respect to this variable\n        bool include = NumRes(op) > 0;\n        if( include )\n            include = rev_jac_sparse.is_element(i_var, 0);\n        switch( op )\n        {\n            // include\n            // operators that must always be included\n            case EndOp:\n            case CSkipOp:\n            case AFunOp:\n            case FunapOp:\n            case FunavOp:\n            case FunrpOp:\n            case FunrvOp:\n            case StppOp:\n            case StpvOp:\n            case StvpOp:\n            case StvvOp:\n            include = true;\n            break;\n\n            // count_independent\n            case InvOp:\n            if( ! include )\n                ++count_independent;\n            break;\n\n            // itr\n            case CSumOp:\n            if( ! include )\n                itr.correct_before_increment();\n            break;\n\n            // default\n            default:\n            break;\n        }\n        //\n        if( include ) switch( op )\n        {   // operators that should not occur\n            // case BeginOp\n\n            // operators that do not affect Jacobian or Hessian\n            // and where with a fixed number of arguments and results\n            case CExpOp:\n            case DisOp:\n            case ParOp:\n            case PriOp:\n            case SignOp:\n            break;\n            // -------------------------------------------------\n\n            // independent variable operator: set J(i_var) = { i_var }\n            case InvOp:\n            CPPAD_ASSERT_UNKNOWN( for_hes_sparse.number_elements(i_var) == 0 );\n            if( select_domain[count_independent] )\n            {   // Not using post_element because only adding one element\n                // per set\n                for_hes_sparse.add_element(np1 + i_var, i_var);\n            }\n            ++count_independent;\n            break;\n\n            // -------------------------------------------------\n            // linear operators where arg[0] is the only variable\n            case AbsOp:\n            case DivvpOp:\n            case SubvpOp:\n            case ZmulvpOp:\n            linear[0] = true;\n            var_op::one_var_for_hes(\n                np1, num_var, i_var, size_t(arg[0]), linear, for_hes_sparse\n            );\n            break;\n\n            // -------------------------------------------------\n            // linear operators where arg[1] is the only variable\n            case AddpvOp:\n            case MulpvOp:\n            case SubpvOp:\n            linear[0] = true;\n            var_op::one_var_for_hes(\n                np1, num_var, i_var, size_t(arg[1]), linear, for_hes_sparse\n            );\n            break;\n\n            // -------------------------------------------------\n            // linear operators where arg[0] and arg[1] are variables\n            case AddvvOp:\n            case SubvvOp:\n            linear[0] = true;\n            linear[1] = true;\n            linear[2] = true;\n            var_op::two_var_for_hes(\n                np1, num_var, i_var, arg, linear, for_hes_sparse\n            );\n            break;\n\n            // ------------------------------------------------------\n            // VecAD load operators\n            case LdvOp:\n            case LdpOp:\n            var_op::load_for_hes(\n                op, arg, num_vecad_ind, i_var, n,\n                vecad_ind, vecad_sparsity, for_hes_sparse\n            );\n            break;\n            //\n            // VecAD store operators\n            case StppOp:\n            case StpvOp:\n            case StvpOp:\n            case StvvOp:\n            var_op::store_for_hes(op,\n                arg, num_vecad_ind, n,\n                vecad_ind, vecad_sparsity, for_hes_sparse\n            );\n            break;\n\n            // ------------------------------------------------------\n            // nonlinear operators where arg[0] is the only variable\n            case AcosOp:\n            case AsinOp:\n            case AtanOp:\n            case CosOp:\n            case CoshOp:\n            case ExpOp:\n            case LogOp:\n            case NegOp:\n            case SinOp:\n            case SinhOp:\n            case SqrtOp:\n            case TanOp:\n            case TanhOp:\n            case AcoshOp:\n            case AsinhOp:\n            case AtanhOp:\n            case Expm1Op:\n            case Log1pOp:\n            case ErfOp:\n            case ErfcOp:\n            CPPAD_ASSERT_UNKNOWN( 0 < NumArg(op) )\n            linear[0] = false;\n            var_op::one_var_for_hes(\n                    np1, num_var, i_var, size_t(arg[0]), linear, for_hes_sparse\n            );\n            break;\n            // -------------------------------------------------\n\n            case CSkipOp:\n            itr.correct_before_increment();\n            break;\n            // -------------------------------------------------\n\n            case CSumOp:\n            var_op::csum_for_hes(arg, i_var, n, for_hes_sparse);\n            itr.correct_before_increment();\n            break;\n            // -------------------------------------------------\n\n            case DivvvOp:\n            linear[0] = true;\n            linear[1] = false;\n            linear[2] = false;\n            CPPAD_ASSERT_NARG_NRES(op, 2, 1)\n            var_op::two_var_for_hes(\n                np1, num_var, i_var, arg, linear, for_hes_sparse\n            );\n            break;\n            // -------------------------------------------------\n            // nonlinear operators where arg[1] is the only variable\n            case DivpvOp:\n            CPPAD_ASSERT_NARG_NRES(op, 2, 1)\n            linear[0] = false;\n            var_op::one_var_for_hes(\n                    np1, num_var, i_var, size_t(arg[1]), linear, for_hes_sparse\n            );\n            break;\n            // -------------------------------------------------\n\n            case EndOp:\n            CPPAD_ASSERT_NARG_NRES(op, 0, 0);\n            more_operators = false;\n            break;\n\n            // -------------------------------------------------\n            // logical comparison operators\n            case EqppOp:\n            case EqpvOp:\n            case EqvvOp:\n            case LtppOp:\n            case LtpvOp:\n            case LtvpOp:\n            case LtvvOp:\n            case LeppOp:\n            case LepvOp:\n            case LevpOp:\n            case LevvOp:\n            case NepvOp:\n            case NeppOp:\n            case NevvOp:\n            CPPAD_ASSERT_NARG_NRES(op, 2, 0);\n            break;\n            // -------------------------------------------------\n\n            case MulvvOp:\n            case ZmulvvOp:\n            linear[0] = true;\n            linear[1] = true;\n            linear[2] = false;\n            CPPAD_ASSERT_NARG_NRES(op, 2, 1)\n            var_op::two_var_for_hes(\n                np1, num_var, i_var, arg, linear, for_hes_sparse\n            );\n            break;\n            // -------------------------------------------------\n\n            case PowpvOp:\n            CPPAD_ASSERT_NARG_NRES(op, 2, 3)\n            linear[0] = false;\n            var_op::one_var_for_hes(\n                    np1, num_var, i_var, size_t(arg[1]), linear, for_hes_sparse\n            );\n            break;\n            // -------------------------------------------------\n\n            case PowvpOp:\n            CPPAD_ASSERT_NARG_NRES(op, 2, 1)\n            linear[0] = false;\n            var_op::one_var_for_hes(\n                    np1, num_var, i_var, size_t(arg[0]), linear, for_hes_sparse\n            );\n            break;\n            // -------------------------------------------------\n\n            case PowvvOp:\n            linear[0] = false;\n            linear[1] = false;\n            linear[2] = false;\n            CPPAD_ASSERT_NARG_NRES(op, 2, 3)\n            var_op::two_var_for_hes(\n                np1, num_var, i_var, arg, linear, for_hes_sparse\n            );\n            break;\n            // -------------------------------------------------\n\n            case AFunOp:\n            var_op::atomic_for_hes<SetVector, Base, RecBase>(\n                itr,\n                play,\n                parameter,\n                atom_trace,\n                atom_work,\n                np1,\n                rev_jac_sparse,\n                for_hes_sparse\n            );\n            break;\n\n            case FunapOp:\n            case FunavOp:\n            case FunrpOp:\n            case FunrvOp:\n            CPPAD_ASSERT_UNKNOWN( false );\n            break;\n            // -------------------------------------------------\n\n            default:\n            CPPAD_ASSERT_UNKNOWN(0);\n        }\n# if CPPAD_FOR_HES_TRACE\n        if( op != AFunOp )\n        {   //\n            printOp<Base, RecBase>(\n                std::cout,\n                play,\n                itr.op_index(),\n                i_var,\n                op,\n                arg\n            );\n            //\n            if( NumRes(op) > 0 )\n            {   typedef typename SetVector::const_iterator itr_sparse_t;\n                CPPAD_ASSERT_UNKNOWN( np1 == for_hes_sparse.end() );\n                CppAD::vectorBool jac_row(np1);\n                for(size_t j = 0; j < np1; ++j)\n                    jac_row[j] = false;\n                itr_sparse_t itr_jac(for_hes_sparse, np1 + i_var);\n                {   size_t j = *itr_jac;\n                    while( j < np1 )\n                    {   jac_row[j] = true;\n                        j = *(++itr_jac);\n                    }\n                }\n                printOpResult(\n                    std::cout,\n                    1,\n                    &jac_row,\n                    0,\n                    (CppAD::vectorBool *) nullptr\n                );\n                std::cout << std::endl;\n                //\n                CppAD::vector< CppAD::vectorBool > hes(np1);\n                for(size_t i = 0; i < np1; ++i)\n                {   hes[i].resize(np1);\n                    for(size_t j = 0; j < np1; ++j)\n                        hes[i][j] = false;\n                    itr_sparse_t itr_hes(for_hes_sparse, i);\n                    size_t j = *itr_hes;\n                    while( j < np1 )\n                    {   hes[i][j] = true;\n                        j = *(++itr_hes);\n                    }\n                }\n                printOpResult(\n                    std::cout,\n                    np1,\n                    hes.data(),\n                    0,\n                    (CppAD::vectorBool *) nullptr\n                );\n                std::cout << std::endl;\n            }\n        }\n    }\n    std::cout << std::endl;\n# else\n    }\n# endif\n\n    return;\n}\n} } } // END_CPPAD_LOCAL_SWEEP_NAMESPACE\n\n// preprocessor symbols that are local to this file\n# undef CPPAD_FOR_HES_TRACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/sweep/for_jac.hpp",
    "content": "# ifndef CPPAD_LOCAL_SWEEP_FOR_JAC_HPP\n# define CPPAD_LOCAL_SWEEP_FOR_JAC_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <set>\n# include <cppad/local/pod_vector.hpp>\n# include <cppad/local/play/atom_op_info.hpp>\n# include <cppad/local/sweep/call_atomic.hpp>\n\n// BEGIN_CPPAD_LOCAL_SWEEP_NAMESPACE\nnamespace CppAD { namespace local { namespace sweep {\n/*!\n\\file sweep/for_jac.hpp\nCompute Forward mode Jacobian sparsity patterns.\n*/\n\n/*!\n\\def CPPAD_FOR_JAC_TRACE\nThis value is either zero or one.\nZero is the normal operational value.\nIf it is one, a trace of every for_jac_sweep computation is printed.\n*/\n# define CPPAD_FOR_JAC_TRACE 0\n\n/*!\nGiven the sparsity pattern for the independent variables,\nForJacSweep computes the sparsity pattern for all the other variables.\n\n\\tparam Base\nthis operation sequence was recorded using AD<Base>.\n\n\\tparam Vector_set\nis the type used for vectors of sets. It can be either\nsparse::pack_setvec or sparse::list_setvec.\n\n\\param dependency\nAre the derivatives with respect to left and right of the expression below\nconsidered to be non-zero:\n\\code\n    CondExpRel(left, right, if_true, if_false)\n\\endcode\nThis is used by the optimizer to obtain the correct dependency relations.\n\n\\param n\nis the number of independent variables on the tape.\n\n\\param num_var\nis the total number of variables on the tape; i.e.,\n play->num_var().\n\n\\param play\nThe information stored in play\nis a recording of the operations corresponding to a function\n\\f[\n    F : {\\bf R}^n \\rightarrow {\\bf R}^m\n\\f]\nwhere \\f$ n \\f$ is the number of independent variables\nand \\f$ m \\f$ is the number of dependent variables.\n\n\\param var_sparsity\n\\b Input: For j = 1 , ... , n,\nthe sparsity pattern for the independent variable with index (j-1)\ncorresponds to the set with index j in var_sparsity.\n\\n\n\\n\n\\b Output: For i = n + 1 , ... , num_var - 1,\nthe sparsity pattern for the variable with index i on the tape\ncorresponds to the set with index i in var_sparsity.\n\n\\par Checked Assertions:\n\\li num_var == var_sparsity.n_set()\n\\li num_var == play->num_var()\n\n\\param not_used_rec_base\nSpecifies RecBase for this call.\n*/\n\ntemplate <class Vector_set, class Base, class RecBase>\nvoid for_jac(\n    const local::player<Base>* play,\n    bool                       dependency        ,\n    size_t                     n                 ,\n    size_t                     num_var           ,\n    Vector_set&                var_sparsity,\n    const RecBase&             not_used_rec_base\n)\n{\n    size_t            i, j, k;\n\n    // check num_var argument\n    CPPAD_ASSERT_UNKNOWN( play->num_var()      == num_var );\n    CPPAD_ASSERT_UNKNOWN( var_sparsity.n_set() == num_var );\n\n    // length of the parameter vector (used by CppAD assert macros)\n    const size_t num_par = play->num_par_all();\n\n    // cum_sparsity accumulates sparsity pattern a cumulative sum\n    size_t limit = var_sparsity.end();\n\n    // vecad_sparsity contains a sparsity pattern from each VecAD object\n    // to all the other variables.\n    // vecad_ind maps a VecAD index (the beginning of the\n    // VecAD object) to its from index in vecad_sparsity\n    size_t num_vecad_ind   = play->num_var_vec_ind();\n    size_t num_vecad_vec   = play->num_var_vecad();\n    Vector_set  vecad_sparsity;\n    pod_vector<size_t> vecad_ind;\n    if( num_vecad_vec > 0 )\n    {   size_t length;\n        vecad_sparsity.resize(num_vecad_vec, limit);\n        vecad_ind.extend(num_vecad_ind);\n        j             = 0;\n        for(i = 0; i < num_vecad_vec; i++)\n        {   // length of this VecAD\n            length   = play->GetVecInd(j);\n            // set to proper index for this VecAD\n            vecad_ind[j] = i;\n            for(k = 1; k <= length; k++)\n                vecad_ind[j+k] = num_vecad_vec; // invalid index\n            // start of next VecAD\n            j       += length + 1;\n        }\n        CPPAD_ASSERT_UNKNOWN( j == play->num_var_vec_ind() );\n    }\n\n    // work space used by atomic functions\n    var_op::atomic_op_work<Base> atom_work;\n    //\n    //\n    // pointer to the beginning of the parameter vector\n    // (used by atomic functions)\n    CPPAD_ASSERT_UNKNOWN( num_par > 0 )\n    const Base* parameter = play->par_ptr();\n    //\n# if CPPAD_FOR_JAC_TRACE\n    std::cout << std::endl;\n    CppAD::vectorBool z_value(limit);\n    bool atom_trace = true;\n# else\n    bool atom_trace = false;\n# endif\n\n    // skip the BeginOp at the beginning of the recording\n    play::const_sequential_iterator itr = play->begin();\n    // op_info\n    op_code_var op;\n    size_t i_var;\n    const addr_t*   arg;\n    itr.op_info(op, arg, i_var);\n    CPPAD_ASSERT_UNKNOWN( op == BeginOp );\n    //\n    bool more_operators = true;\n    while(more_operators)\n    {   //\n        // this op\n        (++itr).op_info(op, arg, i_var);\n        //\n        // rest of information depends on the case\n        switch( op )\n        {   //\n            // operators with one primary result and\n            // where the first argument is the only variable\n            case AbsOp:\n            case AcosOp:\n            case AcoshOp:\n            case AsinOp:\n            case AsinhOp:\n            case AtanOp:\n            case AtanhOp:\n            case CosOp:\n            case CoshOp:\n            case DivvpOp:\n            case ErfOp:\n            case ErfcOp:\n            case ExpOp:\n            case Expm1Op:\n            case LogOp:\n            case NegOp:\n            case Log1pOp:\n            case PowvpOp:\n            case SinOp:\n            case SinhOp:\n            case SqrtOp:\n            case SubvpOp:\n            case TanOp:\n            case TanhOp:\n            case ZmulvpOp:\n            CPPAD_ASSERT_UNKNOWN( 0 < NumArg(op) );\n            var_op::one_var_for_jac(\n                i_var, size_t(arg[0]), var_sparsity\n            );\n            break;\n            // -------------------------------------------------\n\n            // operators with one primary result and\n            // where the second argument is the only variable\n            case AddpvOp:\n            case DivpvOp:\n            case MulpvOp:\n            case PowpvOp:\n            case SubpvOp:\n            case ZmulpvOp:\n            CPPAD_ASSERT_UNKNOWN( 1 < NumArg(op) );\n            var_op::one_var_for_jac(\n                i_var, size_t(arg[1]), var_sparsity\n            );\n            break;\n            // -------------------------------------------------\n\n            case AddvvOp:\n            CPPAD_ASSERT_NARG_NRES(op, 2, 1);\n            var_op::two_var_for_jac(\n                i_var, arg, var_sparsity\n            );\n            break;\n            // -------------------------------------------------\n\n            case CSkipOp:\n            itr.correct_before_increment();\n            break;\n            // -------------------------------------------------\n\n            case CSumOp:\n            var_op::csum_for_jac(\n                i_var, arg, var_sparsity\n            );\n            itr.correct_before_increment();\n            break;\n            // -------------------------------------------------\n\n            case CExpOp:\n            var_op::cexp_for_jac(\n                dependency, i_var, arg, num_par, var_sparsity\n            );\n            break;\n            // --------------------------------------------------\n\n            case DisOp:\n            CPPAD_ASSERT_NARG_NRES(op, 2, 1);\n            // derivative is identically zero but dependency is not\n            if( dependency ) var_op::one_var_for_jac(\n                i_var, size_t(arg[1]), var_sparsity\n            );\n            else\n                var_sparsity.clear(i_var);\n            break;\n            // -------------------------------------------------\n\n            case DivvvOp:\n            CPPAD_ASSERT_NARG_NRES(op, 2, 1);\n            var_op::two_var_for_jac(\n                i_var, arg, var_sparsity\n            );\n            break;\n            // -------------------------------------------------\n\n            case EndOp:\n            CPPAD_ASSERT_NARG_NRES(op, 0, 0);\n            more_operators = false;\n            break;\n            // -------------------------------------------------\n\n            case InvOp:\n            CPPAD_ASSERT_NARG_NRES(op, 0, 1);\n            // sparsity pattern is already defined\n            break;\n            // -------------------------------------------------\n\n            case LdpOp:\n            case LdvOp:\n            var_op::load_for_jac(\n                op,\n                num_vecad_ind,\n                i_var,\n                arg,\n                dependency,\n                vecad_ind,\n                var_sparsity,\n                vecad_sparsity\n            );\n            break;\n            // -------------------------------------------------\n\n            case EqppOp:\n            case EqpvOp:\n            case EqvvOp:\n            case LtppOp:\n            case LtpvOp:\n            case LtvpOp:\n            case LtvvOp:\n            case LeppOp:\n            case LepvOp:\n            case LevpOp:\n            case LevvOp:\n            case NeppOp:\n            case NepvOp:\n            case NevvOp:\n            CPPAD_ASSERT_NARG_NRES(op, 2, 0);\n            break;\n            // -------------------------------------------------\n            case MulvvOp:\n            CPPAD_ASSERT_NARG_NRES(op, 2, 1);\n            var_op::two_var_for_jac(\n                i_var, arg, var_sparsity\n            );\n            break;\n            // -------------------------------------------------\n\n            case ParOp:\n            CPPAD_ASSERT_NARG_NRES(op, 1, 1);\n            var_sparsity.clear(i_var);\n            break;\n            // -------------------------------------------------\n\n            case PowvvOp:\n            CPPAD_ASSERT_NARG_NRES(op, 2, 3);\n            var_op::two_var_for_jac(\n                i_var, arg, var_sparsity\n            );\n            break;\n            // -------------------------------------------------\n\n            case PriOp:\n            CPPAD_ASSERT_NARG_NRES(op, 5, 0);\n            break;\n            // -------------------------------------------------\n\n            case SignOp:\n            CPPAD_ASSERT_NARG_NRES(op, 1, 1);\n            // derivative is identically zero but dependency is not\n            if( dependency ) var_op::one_var_for_jac(\n                i_var, size_t(arg[0]), var_sparsity\n            );\n            else\n                var_sparsity.clear(i_var);\n            break;\n            // -------------------------------------------------\n\n            case StppOp:\n            case StpvOp:\n            case StvpOp:\n            case StvvOp:\n            var_op::store_for_jac(\n                op,\n                num_vecad_ind,\n                arg,\n                dependency,\n                vecad_ind,\n                var_sparsity,\n                vecad_sparsity\n            );\n            break;\n            // -------------------------------------------------\n\n            case SubvvOp:\n            CPPAD_ASSERT_NARG_NRES(op, 2, 1);\n            var_op::two_var_for_jac(\n                i_var, arg, var_sparsity\n            );\n            break;\n            // -------------------------------------------------\n\n            case AFunOp:\n            var_op:: atomic_for_jac<Vector_set, Base, RecBase>(\n                itr,\n                play,\n                parameter,\n                atom_trace,\n                atom_work,\n                dependency,\n                var_sparsity\n            );\n            break;\n\n            case FunapOp:\n            case FunavOp:\n            case FunrpOp:\n            case FunrvOp:\n            CPPAD_ASSERT_UNKNOWN( false );\n            break;\n            // -------------------------------------------------\n\n            case ZmulvvOp:\n            CPPAD_ASSERT_NARG_NRES(op, 2, 1);\n            var_op::two_var_for_jac(\n                i_var, arg, var_sparsity\n            );\n            break;\n            // -------------------------------------------------\n\n            default:\n            CPPAD_ASSERT_UNKNOWN(0);\n        }\n# if CPPAD_FOR_JAC_TRACE\n        if( op != AFunOp )\n        {   // value for this variable\n            for(j = 0; j < limit; j++)\n                z_value[j] = false;\n            typename Vector_set::const_iterator sparse_itr(var_sparsity, i_var);\n            j = *sparse_itr;\n            while( j < limit )\n            {   z_value[j] = true;\n                j = *(++sparse_itr);\n            }\n            printOp<Base, RecBase>(\n                std::cout,\n                play,\n                itr.op_index(),\n                i_var,\n                op,\n                arg\n            );\n            if( NumRes(op) > 0 ) printOpResult(\n                std::cout,\n                1,\n                &z_value,\n                0,\n                (CppAD::vectorBool *) nullptr\n            );\n            std::cout << std::endl;\n        }\n# endif\n    }\n    return;\n}\n\n} } } // END_CPPAD_LOCAL_SWEEP_NAMESPACE\n\n// preprocessor symbols that are local to this file\n# undef CPPAD_FOR_JAC_TRACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/sweep/forward_0.hpp",
    "content": "# ifndef CPPAD_LOCAL_SWEEP_FORWARD_0_HPP\n# define CPPAD_LOCAL_SWEEP_FORWARD_0_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/local/play/atom_op_info.hpp>\n# include <cppad/local/sweep/call_atomic.hpp>\n# include <cppad/local/var_op/compare_op.hpp>\n# include <cppad/local/var_op/atomic_op.hpp>\n\n# define CPPAD_FORWARD_0_TRACE 0\n\n// BEGIN_CPPAD_LOCAL_SWEEP_NAMESPACE\nnamespace CppAD { namespace local { namespace sweep {\n/*\n ------------------------------------------------------------------------------\n{xrst_begin sweep_forward_0 dev}\n{xrst_spell\n    cskip\n}\n\n{xrst_template ;\n    include/cppad/local/sweep/template/forward_sweep.xrst\n\n    headers all:     CPPAD_@NAME@_TRACE, Portotype, Base, RecBase, play, num_var\n    headers all:     cap_order, cskip, load_op2var, taylor\n    headers 0 & any: change_count, change_number, change_op_index, sout, print\n\n    @title@  The title for this forward sweep\n    @#####@  Underlining for the tilte\n    @NAME@   is one of FORWARD_0, FORWARD_ANY, FORWARD_DIR\n    @****@   Underlining for @NAME@\n\n    @title@ ; Compute Zero Order Forward Mode Taylor Coefficients\n    @#####@ ; ###################################################\n    @NAME@  ; FORWARD_0\n    @****@  ; *********\n}\n\n{xrst_end sweep_forward_0}\n*/\n\n// BEGIN_FORWARD_0\ntemplate <class Base, class RecBase>\nvoid forward_0(\n    const RecBase&             not_used_rec_base,\n    const local::player<Base>* play,\n    size_t                     num_var,\n    size_t                     cap_order,\n    bool*                      cskip_op,\n    pod_vector<addr_t>&        load_op2var,\n    size_t                     change_count,\n    size_t&                    change_number,\n    size_t&                    change_op_index,\n    std::ostream&              s_out,\n    bool                       print,\n    Base*                      taylor\n)\n// END_FORWARD_0\n{   CPPAD_ASSERT_UNKNOWN( cap_order >= 1 );\n    CPPAD_ASSERT_UNKNOWN( play->num_var() == num_var );\n\n    // use p, q, r so other forward sweeps can use code defined here\n    size_t order_low = 0;\n    size_t order_up  = 0;\n    size_t r = 1;\n\n    // initialize the comparison operator counter\n    if( order_low == 0 )\n    {   change_number   = 0;\n        change_op_index = 0;\n    }\n\n    // If this includes a zero calculation, initialize this information\n    pod_vector<bool>   vec_ad2isvar;\n    pod_vector<size_t> vec_ad2index;\n    if( order_low == 0 )\n    {   size_t i;\n\n        // this includes order zero calculation, initialize vector indices\n        size_t num = play->num_var_vec_ind();\n        if( num > 0 )\n        {   vec_ad2isvar.extend(num);\n            vec_ad2index.extend(num);\n            for(i = 0; i < num; i++)\n            {   vec_ad2index[i] = play->GetVecInd(i);\n                vec_ad2isvar[i] = false;\n            }\n        }\n        // includes zero order, so initialize conditional skip flags\n        num = play->num_var_op();\n        for(i = 0; i < num; i++)\n            cskip_op[i] = false;\n    }\n\n    // information used by atomic function operators\n\n    // work space used by atomic functions\n    var_op::atomic_op_work<Base> atom_work;\n\n    // length of the parameter vector (used by CppAD assert macros)\n    const size_t num_par = play->num_par_all();\n\n    // pointer to the beginning of the parameter vector\n    CPPAD_ASSERT_UNKNOWN( num_par > 0 )\n    const Base* parameter = play->par_ptr();\n\n    // length of the text vector (used by CppAD assert macros)\n    const size_t num_text = play->num_var_text();\n\n    // pointer to the beginning of the text vector\n    const char* text = nullptr;\n    if( num_text > 0 )\n        text = play->GetTxt(0);\n\n# if CPPAD_FORWARD_0_TRACE\n    // flag as to when to trace atomic function values\n    bool atom_trace  = true;\n# else\n    bool atom_trace  = false;\n# endif\n\n    // skip the BeginOp at the beginning of the recording\n    play::const_sequential_iterator itr = play->begin();\n    // op_info\n    op_code_var   op;\n    size_t        i_var;\n    const addr_t* arg;\n    itr.op_info(op, arg, i_var);\n    CPPAD_ASSERT_UNKNOWN( op == BeginOp );\n    //\n# if CPPAD_FORWARD_0_TRACE\n    std::cout << std::endl;\n# endif\n    bool more_operators = true;\n    while(more_operators)\n    {\n        // next op\n        (++itr).op_info(op, arg, i_var);\n        CPPAD_ASSERT_UNKNOWN( itr.op_index() < play->num_var_op() );\n\n        // check if we are skipping this operation\n        while( cskip_op[itr.op_index()] )\n        {   switch(op)\n            {\n                case AFunOp:\n                {   // get information for this atomic function call\n                    size_t atom_index, atom_id, atom_m, atom_n;\n                    play::atom_op_info<Base>(\n                        op, arg, atom_index, atom_id, atom_m, atom_n\n                    );\n                    //\n                    // skip to the second AFunOp\n                    for(size_t i = 0; i < atom_m + atom_n + 1; ++i)\n                        ++itr;\n# ifndef NDEBUG\n                    itr.op_info(op, arg, i_var);\n                    CPPAD_ASSERT_UNKNOWN( op == AFunOp );\n# endif\n                }\n                break;\n\n                case CSkipOp:\n                case CSumOp:\n                itr.correct_before_increment();\n                break;\n\n                default:\n                break;\n            }\n            (++itr).op_info(op, arg, i_var);\n        }\n\n        // action to take depends on the case\n        switch( op )\n        {\n            case EqppOp:\n            case EqpvOp:\n            case EqvvOp:\n            case LeppOp:\n            case LepvOp:\n            case LevpOp:\n            case LevvOp:\n            case LtppOp:\n            case LtpvOp:\n            case LtvpOp:\n            case LtvvOp:\n            case NeppOp:\n            case NepvOp:\n            case NevvOp:\n            var_op::compare_forward_any(op,\n                arg, parameter, cap_order, taylor, itr.op_index(),\n                change_count, change_number, change_op_index\n            );\n            break;\n            // -------------------------------------------------\n\n            case AbsOp:\n            var_op::abs_forward_0(i_var, arg, cap_order, taylor);\n            break;\n            // -------------------------------------------------\n\n            case AddvvOp:\n            var_op::addvv_forward_0(i_var, arg, parameter, cap_order, taylor);\n            break;\n            // -------------------------------------------------\n\n            case AddpvOp:\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );\n            var_op::addpv_forward_0(i_var, arg, parameter, cap_order, taylor);\n            break;\n            // -------------------------------------------------\n\n            case AcosOp:\n            // sqrt(1 - x * x), acos(x)\n            CPPAD_ASSERT_UNKNOWN( i_var < num_var  );\n            var_op::acos_forward_0(i_var, arg, cap_order, taylor);\n            break;\n            // -------------------------------------------------\n\n            case AcoshOp:\n            // sqrt(x * x - 1), acosh(x)\n            CPPAD_ASSERT_UNKNOWN( i_var < num_var  );\n            var_op::acosh_forward_0(i_var, arg, cap_order, taylor);\n            break;\n            // -------------------------------------------------\n\n            case AsinOp:\n            // sqrt(1 - x * x), asin(x)\n            CPPAD_ASSERT_UNKNOWN( i_var < num_var  );\n            var_op::asin_forward_0(i_var, arg, cap_order, taylor);\n            break;\n            // -------------------------------------------------\n\n            case AsinhOp:\n            // sqrt(1 + x * x), asinh(x)\n            CPPAD_ASSERT_UNKNOWN( i_var < num_var  );\n            var_op::asinh_forward_0(i_var, arg, cap_order, taylor);\n            break;\n            // -------------------------------------------------\n\n            case AtanOp:\n            // 1 + x * x, atan(x)\n            CPPAD_ASSERT_UNKNOWN( i_var < num_var  );\n            var_op::atan_forward_0(i_var, arg, cap_order, taylor);\n            break;\n            // -------------------------------------------------\n\n            case AtanhOp:\n            // 1 - x * x, atanh(x)\n            CPPAD_ASSERT_UNKNOWN( i_var < num_var  );\n            var_op::atanh_forward_0(i_var, arg, cap_order, taylor);\n            break;\n            // -------------------------------------------------\n\n            case CExpOp:\n            // Use the general case with d == 0\n            // (could create an optimized version for this case)\n            var_op::cexp_forward_0(\n                i_var, arg, num_par, parameter, cap_order, taylor\n            );\n            break;\n            // ---------------------------------------------------\n\n            case CosOp:\n            // sin(x), cos(x)\n            CPPAD_ASSERT_UNKNOWN( i_var < num_var  );\n            var_op::cos_forward_0(i_var, arg, cap_order, taylor);\n            break;\n            // ---------------------------------------------------\n\n            case CoshOp:\n            // sinh(x), cosh(x)\n            CPPAD_ASSERT_UNKNOWN( i_var < num_var  );\n            var_op::cosh_forward_0(i_var, arg, cap_order, taylor);\n            break;\n            // -------------------------------------------------\n\n            case CSkipOp:\n            var_op::cskip_forward_0(\n                i_var, arg, num_par, parameter, cap_order, taylor, cskip_op\n            );\n            itr.correct_before_increment();\n            break;\n            // -------------------------------------------------\n\n            case CSumOp:\n            var_op::csum_forward_any(\n                0, 0, i_var, arg, num_par, parameter, cap_order, taylor\n            );\n            itr.correct_before_increment();\n            break;\n            // -------------------------------------------------\n\n            case DisOp:\n            var_op::dis_forward_dir<RecBase>(\n                order_low, order_up, r, i_var, arg, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case DivvvOp:\n            var_op::divvv_forward_0(i_var, arg, parameter, cap_order, taylor);\n            break;\n            // -------------------------------------------------\n\n            case DivpvOp:\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );\n            var_op::divpv_forward_0(i_var, arg, parameter, cap_order, taylor);\n            break;\n            // -------------------------------------------------\n\n            case DivvpOp:\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par );\n            var_op::divvp_forward_0(i_var, arg, parameter, cap_order, taylor);\n            break;\n            // -------------------------------------------------\n\n            case EndOp:\n            CPPAD_ASSERT_NARG_NRES(op, 0, 0);\n            more_operators = false;\n            break;\n            // -------------------------------------------------\n\n            case ErfOp:\n            case ErfcOp:\n            var_op::erf_forward_0(op, i_var, arg, parameter, cap_order, taylor);\n            break;\n            // -------------------------------------------------\n\n            case ExpOp:\n            var_op::exp_forward_0(i_var, arg, cap_order, taylor);\n            break;\n            // -------------------------------------------------\n\n            case Expm1Op:\n            var_op::expm1_forward_0(i_var, arg, cap_order, taylor);\n            break;\n            // -------------------------------------------------\n\n            case InvOp:\n            CPPAD_ASSERT_NARG_NRES(op, 0, 1);\n            break;\n            // ---------------------------------------------------\n\n            case LdpOp:\n            case LdvOp:\n            var_op::load_forward_0(\n                op,\n                i_var,\n                play->num_var_vec_ind(),\n                arg,\n                num_var,\n                num_par,\n                parameter,\n                cap_order,\n                taylor,\n                vec_ad2isvar,\n                vec_ad2index,\n                load_op2var\n            );\n            break;\n            // -------------------------------------------------\n\n            case LogOp:\n            var_op::log_forward_0(i_var, arg, cap_order, taylor);\n            break;\n            // -------------------------------------------------\n\n            case Log1pOp:\n            var_op::log1p_forward_0(i_var, arg, cap_order, taylor);\n            break;\n            // -------------------------------------------------\n\n            case MulpvOp:\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );\n            var_op::mulpv_forward_0(i_var, arg, parameter, cap_order, taylor);\n            break;\n            // -------------------------------------------------\n\n            case MulvvOp:\n            var_op::mulvv_forward_0(i_var, arg, parameter, cap_order, taylor);\n            break;\n            // -------------------------------------------------\n\n            case NegOp:\n            var_op::neg_forward_0(i_var, arg, cap_order, taylor);\n            break;\n\n            // -------------------------------------------------\n\n            case ParOp:\n            var_op::par_forward_0(\n                i_var, arg, num_par, parameter, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case PowvpOp:\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par );\n            var_op::powvp_forward_0(i_var, arg, parameter, cap_order, taylor);\n            break;\n            // -------------------------------------------------\n\n            case PowpvOp:\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );\n            var_op::powpv_forward_0(i_var, arg, parameter, cap_order, taylor);\n            break;\n            // -------------------------------------------------\n\n            case PowvvOp:\n            var_op::powvv_forward_0(i_var, arg, parameter, cap_order, taylor);\n            break;\n            // -------------------------------------------------\n\n            case PriOp:\n            if( print ) var_op::pri_forward_0(s_out,\n                arg, num_text, text, num_par, parameter, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case SignOp:\n            // cos(x), sin(x)\n            CPPAD_ASSERT_UNKNOWN( i_var < num_var  );\n            var_op::sign_forward_0(i_var, arg, cap_order, taylor);\n            break;\n            // -------------------------------------------------\n\n            case SinOp:\n            // cos(x), sin(x)\n            CPPAD_ASSERT_UNKNOWN( i_var < num_var  );\n            var_op::sin_forward_0(i_var, arg, cap_order, taylor);\n            break;\n            // -------------------------------------------------\n\n            case SinhOp:\n            // cosh(x), sinh(x)\n            CPPAD_ASSERT_UNKNOWN( i_var < num_var  );\n            var_op::sinh_forward_0(i_var, arg, cap_order, taylor);\n            break;\n            // -------------------------------------------------\n\n            case SqrtOp:\n            var_op::sqrt_forward_0(i_var, arg, cap_order, taylor);\n            break;\n            // -------------------------------------------------\n\n            case StppOp:\n            case StpvOp:\n            case StvpOp:\n            case StvvOp:\n            var_op::store_forward_0(\n                op,\n                arg,\n                num_var,\n                num_par,\n                parameter,\n                cap_order,\n                taylor,\n                vec_ad2isvar,\n                vec_ad2index\n            );\n            break;\n            // -------------------------------------------------\n\n            case SubvvOp:\n            var_op::subvv_forward_0(i_var, arg, parameter, cap_order, taylor);\n            break;\n            // -------------------------------------------------\n\n            case SubpvOp:\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );\n            var_op::subpv_forward_0(i_var, arg, parameter, cap_order, taylor);\n            break;\n            // -------------------------------------------------\n\n            case SubvpOp:\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par );\n            var_op::subvp_forward_0(i_var, arg, parameter, cap_order, taylor);\n            break;\n            // -------------------------------------------------\n\n            case TanOp:\n            // tan(x)^2, tan(x)\n            CPPAD_ASSERT_UNKNOWN( i_var < num_var  );\n            var_op::tan_forward_0(i_var, arg, cap_order, taylor);\n            break;\n            // -------------------------------------------------\n\n            case TanhOp:\n            // tanh(x)^2, tanh(x)\n            CPPAD_ASSERT_UNKNOWN( i_var < num_var  );\n            var_op::tanh_forward_0(i_var, arg, cap_order, taylor);\n            break;\n            // -------------------------------------------------\n\n            case AFunOp:\n            // start of an atomic function call\n            var_op::atomic_forward_any<Base, RecBase>(\n                itr,\n                play,\n                parameter,\n                atom_trace,\n                atom_work,\n                cap_order,\n                order_low,\n                order_up,\n                taylor\n            );\n            break;\n\n            case FunapOp:\n            case FunavOp:\n            case FunrpOp:\n            case FunrvOp:\n            CPPAD_ASSERT_UNKNOWN( false );\n            break;\n            // -------------------------------------------------\n\n            case ZmulpvOp:\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );\n            var_op::zmulpv_forward_0(i_var, arg, parameter, cap_order, taylor);\n            break;\n            // -------------------------------------------------\n\n            case ZmulvpOp:\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par );\n            var_op::zmulvp_forward_0(i_var, arg, parameter, cap_order, taylor);\n            break;\n            // -------------------------------------------------\n\n            case ZmulvvOp:\n            var_op::zmulvv_forward_0(i_var, arg, parameter, cap_order, taylor);\n            break;\n            // -------------------------------------------------\n\n            default:\n            CPPAD_ASSERT_UNKNOWN(false);\n        }\n# if CPPAD_FORWARD_0_TRACE\n        size_t  d  = 0;\n        Base*           Z_tmp   = taylor + i_var * cap_order;\n        if( op != AFunOp )\n        {\n            printOp<Base, RecBase>(\n                std::cout,\n                play,\n                itr.op_index(),\n                i_var,\n                op,\n                arg\n            );\n            if( NumRes(op) > 0 ) printOpResult(\n                std::cout,\n                d + 1,\n                Z_tmp,\n                0,\n                (Base *) nullptr\n            );\n            std::cout << std::endl;\n        }\n    }\n    std::cout << std::endl;\n# else\n    }\n# endif\n\n    return;\n}\n\n} } } // END_CPPAD_LOCAL_SWEEP_NAMESPACE\n\n// preprocessor symbols that are local to this file\n# undef CPPAD_FORWARD_0_TRACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/sweep/forward_any.hpp",
    "content": "# ifndef CPPAD_LOCAL_SWEEP_FORWARD_ANY_HPP\n# define CPPAD_LOCAL_SWEEP_FORWARD_ANY_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/local/play/atom_op_info.hpp>\n# include <cppad/local/sweep/call_atomic.hpp>\n# include <cppad/local/var_op/compare_op.hpp>\n# include <cppad/local/var_op/atomic_op.hpp>\n\n# define CPPAD_FORWARD_ANY_TRACE 0\n\n// BEGIN_CPPAD_LOCAL_SWEEP_NAMESPACE\nnamespace CppAD { namespace local { namespace sweep {\n/*\n ------------------------------------------------------------------------------\n{xrst_begin sweep_forward_any dev}\n{xrst_spell\n    cskip\n}\n\n{xrst_template ;\n    include/cppad/local/sweep/template/forward_sweep.xrst\n\n    headers all:     CPPAD_@NAME@_TRACE, Portotype, Base, RecBase, play, num_var\n    headers all:     cap_order, cskip, load_op2var, taylor\n    headers 0 & any: change_count, change_number, change_op_index, sout, print\n    headers any:     order_low, order_up\n\n    @title@  The title for this forward sweep\n    @#####@  Underlining for the tilte\n    @NAME@   is one of FORWARD_0, FORWARD_ANY, FORWARD_DIR\n    @****@   Underlining for @NAME@\n\n    @title@ ; Compute Any Order Forward Mode Taylor Coefficients\n    @#####@ ; ##################################################\n    @NAME@  ; FORWARD_ANY\n    @****@  ; ***********\n}\n\n{xrst_end sweep_forward_any}\n*/\n// BEGIN_FORWARD_ANY\ntemplate <class Base, class RecBase>\nvoid forward_any(\n    const RecBase&             not_used_rec_base,\n    const local::player<Base>* play,\n    const size_t               num_var,\n    const size_t               cap_order,\n    bool*                      cskip_op,\n    pod_vector<addr_t>&        load_op2var,\n    size_t                     change_count,\n    size_t&                    change_number,\n    size_t&                    change_op_index,\n    std::ostream&              s_out,\n    const bool                 print,\n    const size_t               order_low,\n    const size_t               order_up,\n    Base*                      taylor\n)\n// END_FORWARD_ANY\n{\n    // number of directions\n    const size_t r = 1;\n\n    CPPAD_ASSERT_UNKNOWN(order_low <= order_up );\n    CPPAD_ASSERT_UNKNOWN( cap_order >= order_up + 1 );\n    CPPAD_ASSERT_UNKNOWN( play->num_var() == num_var );\n\n    /*\n    <!-- replace forward0sweep_code_define -->\n    */\n\n    // initialize the comparison operator counter\n    if( order_low == 0 )\n    {   change_number   = 0;\n        change_op_index = 0;\n    }\n\n    // If this includes a zero calculation, initialize this information\n    pod_vector<bool>   vec_ad2isvar;\n    pod_vector<size_t> vec_ad2index;\n    if( order_low == 0 )\n    {   size_t i;\n\n        // this includes order zero calculation, initialize vector indices\n        size_t num = play->num_var_vec_ind();\n        if( num > 0 )\n        {   vec_ad2isvar.extend(num);\n            vec_ad2index.extend(num);\n            for(i = 0; i < num; i++)\n            {   vec_ad2index[i] = play->GetVecInd(i);\n                vec_ad2isvar[i] = false;\n            }\n        }\n        // includes zero order, so initialize conditional skip flags\n        num = play->num_var_op();\n        for(i = 0; i < num; i++)\n            cskip_op[i] = false;\n    }\n\n    // information used by atomic function operators\n\n    // work space used by atomic functions\n    var_op::atomic_op_work<Base> atom_work;\n\n    // information defined by atomic function operators\n    size_t atom_index, atom_id, atom_m, atom_n;\n\n    // length of the parameter vector (used by CppAD assert macros)\n    const size_t num_par = play->num_par_all();\n\n    // pointer to the beginning of the parameter vector\n    CPPAD_ASSERT_UNKNOWN( num_par > 0 )\n    const Base* parameter = play->par_ptr();\n\n    // length of the text vector (used by CppAD assert macros)\n    const size_t num_text = play->num_var_text();\n\n    // pointer to the beginning of the text vector\n    const char* text = nullptr;\n    if( num_text > 0 )\n        text = play->GetTxt(0);\n    /*\n    <!-- end forward0sweep_code_define -->\n    */\n    // temporary indices\n    size_t i;\n\n    // skip the BeginOp at the beginning of the recording\n    play::const_sequential_iterator itr = play->begin();\n    // op_info\n    op_code_var   op;\n    size_t        i_var;\n    const addr_t* arg;\n    itr.op_info(op, arg, i_var);\n    CPPAD_ASSERT_UNKNOWN( op == BeginOp );\n    //\n# if CPPAD_FORWARD_ANY_TRACE\n    // flag as to when to trace atomic function values\n    bool atom_trace  = true;\n# else\n    bool atom_trace  = false;\n# endif\n    //\n    bool more_operators = true;\n    while(more_operators)\n    {\n        // next op\n        (++itr).op_info(op, arg, i_var);\n        CPPAD_ASSERT_UNKNOWN( itr.op_index() < play->num_var_op() );\n\n        // check if we are skipping this operation\n        while( cskip_op[itr.op_index()] )\n        {   switch(op)\n            {\n                case AFunOp:\n                {   // get information for this atomic function call\n                    play::atom_op_info<Base>(\n                        op, arg, atom_index, atom_id, atom_m, atom_n\n                    );\n                    //\n                    // skip to the second AFunOp\n                    for(i = 0; i < atom_m + atom_n + 1; ++i)\n                        ++itr;\n# ifndef NDEBUG\n                    itr.op_info(op, arg, i_var);\n                    CPPAD_ASSERT_UNKNOWN( op == AFunOp );\n# endif\n                }\n                break;\n\n                case CSkipOp:\n                case CSumOp:\n                itr.correct_before_increment();\n                break;\n\n                default:\n                break;\n            }\n            (++itr).op_info(op, arg, i_var);\n        }\n\n        // action depends on the operator\n        switch( op )\n        {\n            case EqppOp:\n            case EqpvOp:\n            case EqvvOp:\n            case LeppOp:\n            case LepvOp:\n            case LevpOp:\n            case LevvOp:\n            case LtppOp:\n            case LtpvOp:\n            case LtvpOp:\n            case LtvvOp:\n            case NeppOp:\n            case NepvOp:\n            case NevvOp:\n            var_op::compare_forward_any(op,\n                arg, parameter, cap_order, taylor, itr.op_index(),\n                change_count, change_number, change_op_index\n            );\n            break;\n            // -------------------------------------------------\n\n            case AbsOp:\n            var_op::abs_forward_any(\n                order_low, order_up, i_var, arg, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case AddvvOp:\n            var_op::addvv_forward_any(\n                order_low, order_up, i_var, arg, parameter, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case AddpvOp:\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );\n            var_op::addpv_forward_any(\n                order_low, order_up, i_var, arg, parameter, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case AcosOp:\n            // sqrt(1 - x * x), acos(x)\n            CPPAD_ASSERT_UNKNOWN( i_var < num_var  );\n            var_op::acos_forward_any(\n                order_low, order_up, i_var, arg, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case AcoshOp:\n            // sqrt(x * x - 1), acosh(x)\n            CPPAD_ASSERT_UNKNOWN( i_var < num_var  );\n            var_op::acosh_forward_any(\n                order_low, order_up, i_var, arg, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case AsinOp:\n            // sqrt(1 - x * x), asin(x)\n            CPPAD_ASSERT_UNKNOWN( i_var < num_var  );\n            var_op::asin_forward_any(\n                order_low, order_up, i_var, arg, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case AsinhOp:\n            // sqrt(1 + x * x), asinh(x)\n            CPPAD_ASSERT_UNKNOWN( i_var < num_var  );\n            var_op::asinh_forward_any(\n                order_low, order_up, i_var, arg, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case AtanOp:\n            // 1 + x * x, atan(x)\n            CPPAD_ASSERT_UNKNOWN( i_var < num_var  );\n            var_op::atan_forward_any(\n                order_low, order_up, i_var, arg, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case AtanhOp:\n            // 1 - x * x, atanh(x)\n            CPPAD_ASSERT_UNKNOWN( i_var < num_var  );\n            var_op::atanh_forward_any(\n                order_low, order_up, i_var, arg, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case CExpOp:\n            var_op::cexp_forward_any(\n                order_low, order_up, i_var, arg, num_par, parameter, cap_order, taylor\n            );\n            break;\n            // ---------------------------------------------------\n\n            case CosOp:\n            // sin(x), cos(x)\n            CPPAD_ASSERT_UNKNOWN( i_var < num_var  );\n            var_op::cos_forward_any(\n                order_low, order_up, i_var, arg, cap_order, taylor\n            );\n            break;\n            // ---------------------------------------------------\n\n            case CoshOp:\n            // sinh(x), cosh(x)\n            CPPAD_ASSERT_UNKNOWN( i_var < num_var  );\n            var_op::cosh_forward_any(\n                order_low, order_up, i_var, arg, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case CSkipOp:\n            if( order_low == 0 )\n            {   var_op::cskip_forward_0(\n                    i_var, arg, num_par, parameter, cap_order, taylor, cskip_op\n                );\n            }\n            itr.correct_before_increment();\n            break;\n            // -------------------------------------------------\n\n            case CSumOp:\n            var_op::csum_forward_any(\n                order_low, order_up, i_var, arg, num_par, parameter, cap_order, taylor\n            );\n            itr.correct_before_increment();\n            break;\n            // -------------------------------------------------\n\n            case DisOp:\n            var_op::dis_forward_dir<RecBase>(\n                order_low, order_up, r, i_var, arg, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case DivvvOp:\n            var_op::divvv_forward_any(\n                order_low, order_up, i_var, arg, parameter, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case DivpvOp:\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );\n            var_op::divpv_forward_any(\n                order_low, order_up, i_var, arg, parameter, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case DivvpOp:\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par );\n            var_op::divvp_forward_any(\n                order_low, order_up, i_var, arg, parameter, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case EndOp:\n            CPPAD_ASSERT_NARG_NRES(op, 0, 0);\n            more_operators = false;\n            break;\n            // -------------------------------------------------\n\n            case ErfOp:\n            case ErfcOp:\n            var_op::erf_forward_any(\n                op, order_low, order_up, i_var, arg, parameter, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case ExpOp:\n            var_op::exp_forward_any(\n                order_low, order_up, i_var, arg, cap_order, taylor\n            );\n            break;\n            // ---------------------------------------------------\n\n            case Expm1Op:\n            var_op::expm1_forward_any(\n                order_low, order_up, i_var, arg, cap_order, taylor\n            );\n            break;\n            // ---------------------------------------------------\n\n            case InvOp:\n            CPPAD_ASSERT_NARG_NRES(op, 0, 1);\n            break;\n            // -------------------------------------------------\n\n            case LdpOp:\n            case LdvOp:\n            if( order_low == 0 )\n            {   var_op::load_forward_0(\n                    op,\n                    i_var,\n                    play->num_var_vec_ind(),\n                    arg,\n                    num_var,\n                    num_par,\n                    parameter,\n                    cap_order,\n                    taylor,\n                    vec_ad2isvar,\n                    vec_ad2index,\n                    load_op2var\n                );\n                if(order_low < order_up ) var_op::load_forward_nonzero(\n                    op,\n                    i_var,\n                    arg,\n                    order_low + 1,\n                    order_up,\n                    r,\n                    cap_order,\n                    load_op2var,\n                    taylor\n                );\n            }\n            else\n                var_op::load_forward_nonzero(\n                op,\n                i_var,\n                arg,\n                order_low,\n                order_up,\n                r,\n                cap_order,\n                load_op2var,\n                taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case LogOp:\n            var_op::log_forward_any(\n                order_low, order_up, i_var, arg, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case Log1pOp:\n            var_op::log1p_forward_any(\n                order_low, order_up, i_var, arg, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case MulpvOp:\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );\n            var_op::mulpv_forward_any(\n                order_low, order_up, i_var, arg, parameter, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case MulvvOp:\n            var_op::mulvv_forward_any(\n                order_low, order_up, i_var, arg, parameter, cap_order, taylor\n            );\n            break;\n            // --------------------------------------------------\n\n            case NegOp:\n            var_op::neg_forward_any(\n                order_low, order_up, i_var, arg, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case ParOp:\n            var_op::par_forward_any(\n                order_low, order_up, i_var, arg, num_par, parameter, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case PowvpOp:\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par );\n            var_op::powvp_forward_any(\n                order_low, order_up, i_var, arg, parameter, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case PowpvOp:\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );\n            var_op::powpv_forward_any(\n                order_low, order_up, i_var, arg, parameter, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case PowvvOp:\n            var_op::powvv_forward_any(\n                order_low, order_up, i_var, arg, parameter, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case PriOp:\n            if( ( order_low == 0 ) & print ) var_op::pri_forward_0(s_out,\n                arg, num_text, text, num_par, parameter, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case SignOp:\n            // sign(x)\n            CPPAD_ASSERT_UNKNOWN( i_var < num_var  );\n            var_op::sign_forward_any(\n                order_low, order_up, i_var, arg, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case SinOp:\n            // cos(x), sin(x)\n            CPPAD_ASSERT_UNKNOWN( i_var < num_var  );\n            var_op::sin_forward_any(\n                order_low, order_up, i_var, arg, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case SinhOp:\n            // cosh(x), sinh(x)\n            CPPAD_ASSERT_UNKNOWN( i_var < num_var  );\n            var_op::sinh_forward_any(\n                order_low, order_up, i_var, arg, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case SqrtOp:\n            var_op::sqrt_forward_any(\n                order_low, order_up, i_var, arg, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case StppOp:\n            case StpvOp:\n            case StvpOp:\n            case StvvOp:\n            if( order_low == 0 )\n            {   var_op::store_forward_0(\n                    op,\n                    arg,\n                    num_var,\n                    num_par,\n                    parameter,\n                    cap_order,\n                    taylor,\n                    vec_ad2isvar,\n                    vec_ad2index\n                );\n            }\n            break;\n            // -------------------------------------------------\n\n            case SubvvOp:\n            var_op::subvv_forward_any(\n                order_low, order_up, i_var, arg, parameter, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case SubpvOp:\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );\n            var_op::subpv_forward_any(\n                order_low, order_up, i_var, arg, parameter, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case SubvpOp:\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par );\n            var_op::subvp_forward_any(\n                order_low, order_up, i_var, arg, parameter, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case TanOp:\n            // tan(x)^2, tan(x)\n            CPPAD_ASSERT_UNKNOWN( i_var < num_var  );\n            var_op::tan_forward_any(\n                order_low, order_up, i_var, arg, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case TanhOp:\n            // tanh(x)^2, tanh(x)\n            CPPAD_ASSERT_UNKNOWN( i_var < num_var  );\n            var_op::tanh_forward_any(\n                order_low, order_up, i_var, arg, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case AFunOp:\n            // start of an atomic function call\n            var_op::atomic_forward_any<Base, RecBase>(\n                itr,\n                play,\n                parameter,\n                atom_trace,\n                atom_work,\n                cap_order,\n                order_low,\n                order_up,\n                taylor\n            );\n            break;\n\n            case FunapOp:\n            case FunavOp:\n            case FunrpOp:\n            case FunrvOp:\n            CPPAD_ASSERT_UNKNOWN( false );\n            break;\n            // -------------------------------------------------\n\n            case ZmulpvOp:\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );\n            var_op::zmulpv_forward_any(\n                order_low, order_up, i_var, arg, parameter, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case ZmulvpOp:\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par );\n            var_op::zmulvp_forward_any(\n                order_low, order_up, i_var, arg, parameter, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case ZmulvvOp:\n            var_op::zmulvv_forward_any(\n                order_low, order_up, i_var, arg, parameter, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            default:\n            CPPAD_ASSERT_UNKNOWN(false);\n        }\n# if CPPAD_FORWARD_ANY_TRACE\n        Base*           Z_tmp   = taylor + cap_order * i_var;\n        if( op != AFunOp )\n        {\n            printOp<Base, RecBase>(\n                std::cout,\n                play,\n                itr.op_index(),\n                i_var,\n                op,\n                arg\n            );\n            if( NumRes(op) > 0 ) printOpResult(\n                std::cout,\n                order_up + 1,\n                Z_tmp,\n                0,\n                (Base *) nullptr\n            );\n            std::cout << std::endl;\n        }\n    }\n    std::cout << std::endl;\n# else\n    }\n# endif\n    if( ( order_low == 0 ) && (change_count == 0) )\n        change_number = 0;\n    return;\n}\n\n// preprocessor symbols that are local to this file\n# undef CPPAD_FORWARD_ANY_TRACE\n\n} } } // END_CPPAD_LOCAL_SWEEP_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/local/sweep/forward_dir.hpp",
    "content": "# ifndef CPPAD_LOCAL_SWEEP_FORWARD_DIR_HPP\n# define CPPAD_LOCAL_SWEEP_FORWARD_DIR_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/local/play/atom_op_info.hpp>\n# include <cppad/local/sweep/call_atomic.hpp>\n# include <cppad/local/var_op/atomic_op.hpp>\n\n# define CPPAD_FORWARD_DIR_TRACE 0\n\n// BEGIN_CPPAD_LOCAL_SWEEP_NAMESPACE\nnamespace CppAD { namespace local { namespace sweep {\n/*\n ------------------------------------------------------------------------------\n{xrst_begin sweep_forward_dir dev}\n{xrst_spell\n    cskip\n}\n\n{xrst_template ;\n    include/cppad/local/sweep/template/forward_sweep.xrst\n\n    headers all:     CPPAD_@NAME@_TRACE, Portotype, Base, RecBase, play, num_var\n    headers all:     cap_order, cskip, load_op2var, taylor\n    headers dir:     order_up, n_dir\n\n    @title@  The title for this forward sweep\n    @#####@  Underlining for the tilte\n    @NAME@   is one of FORWARD_0, FORWARD_ANY, FORWARD_DIR\n    @****@   Underlining for @NAME@\n\n    @title@ ; Compute One Order Multiple Directions Forward Taylor Coefficients\n    @#####@ ; #################################################################\n    @NAME@  ; FORWARD_DIR\n    @****@  ; ***********\n}\n\n{xrst_end sweep_forward_dir}\n*/\n// BEGIN_FORWARD_DIR\ntemplate <class Base, class RecBase>\nvoid forward_dir(\n    const RecBase&              not_used_rec_base,\n    const local::player<Base>*  play,\n    const size_t                num_var,\n    const size_t                cap_order,\n    const bool*                 cskip_op,\n    const pod_vector<addr_t>&   load_op2var,\n    const size_t                order_up,\n    const size_t                n_dir,\n    Base*                       taylor\n)\n// END_FORWARD_DIR\n{\n    CPPAD_ASSERT_UNKNOWN( order_up > 0 );\n    CPPAD_ASSERT_UNKNOWN( cap_order >= order_up + 1 );\n    CPPAD_ASSERT_UNKNOWN( play->num_var() == num_var );\n\n    // only compute one order at a time when using multi-direction forward\n    size_t order_low = order_up;\n\n    // information used by atomic function operators\n\n    // work space used by atomic functions\n    var_op::atomic_op_work<Base> atom_work;\n\n    // information defined by atomic function operators\n    size_t atom_index=0, atom_id=0, atom_m=0, atom_n=0;\n    //\n    // length of the parameter vector (used by CppAD assert macros)\n    const size_t num_par = play->num_par_all();\n\n    // pointer to the beginning of the parameter vector\n    CPPAD_ASSERT_UNKNOWN( num_par > 0 )\n    const Base* parameter = play->par_ptr();\n\n    // temporary indices\n    size_t i;\n\n    // skip the BeginOp at the beginning of the recording\n    play::const_sequential_iterator itr = play->begin();\n    // op_info\n    op_code_var     op;\n    size_t          i_var;\n    const addr_t*   arg;\n    itr.op_info(op, arg, i_var);\n    CPPAD_ASSERT_UNKNOWN( op == BeginOp );\n# if CPPAD_FORWARD_DIR_TRACE\n    bool atom_trace  = true;\n    std::cout << std::endl;\n    CppAD::vector<Base> Z_vec(order_up + 1);\n# else\n    bool atom_trace = false;\n# endif\n    bool more_operators = true;\n    while(more_operators)\n    {\n        // next op\n        (++itr).op_info(op, arg, i_var);\n        CPPAD_ASSERT_UNKNOWN( itr.op_index() < play->num_var_op() );\n\n        // check if we are skipping this operation\n        while( cskip_op[itr.op_index()] )\n        {   switch(op)\n            {\n                case AFunOp:\n                {   // get information for this atomic function call\n                    play::atom_op_info<Base>(\n                        op, arg, atom_index, atom_id, atom_m, atom_n\n                    );\n                    //\n                    // skip to the second AFunOp\n                    for(i = 0; i < atom_m + atom_n + 1; ++i)\n                        ++itr;\n# ifndef NDEBUG\n                    itr.op_info(op, arg, i_var);\n                    CPPAD_ASSERT_UNKNOWN( op == AFunOp );\n# endif\n                }\n                break;\n\n                case CSkipOp:\n                case CSumOp:\n                itr.correct_before_increment();\n                break;\n\n                default:\n                break;\n            }\n            (++itr).op_info(op, arg, i_var);\n        }\n\n        // action depends on the operator\n        switch( op )\n        {\n            case AbsOp:\n            var_op::abs_forward_dir(\n                order_up, n_dir, i_var, arg, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case AddvvOp:\n            var_op::addvv_forward_dir(\n                order_up, n_dir, i_var, arg, parameter, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case AddpvOp:\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );\n            var_op::addpv_forward_dir(\n                order_up, n_dir, i_var, arg, parameter, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case AcosOp:\n            // sqrt(1 - x * x), acos(x)\n            CPPAD_ASSERT_UNKNOWN( i_var < num_var  );\n            var_op::acos_forward_dir(\n                order_up, n_dir, i_var, arg, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case AcoshOp:\n            // sqrt(x * x - 1), acosh(x)\n            CPPAD_ASSERT_UNKNOWN( i_var < num_var  );\n            var_op::acosh_forward_dir(\n                order_up, n_dir, i_var, arg, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case AsinOp:\n            // sqrt(1 - x * x), asin(x)\n            CPPAD_ASSERT_UNKNOWN( i_var < num_var  );\n            var_op::asin_forward_dir(\n                order_up, n_dir, i_var, arg, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case AsinhOp:\n            // sqrt(1 + x * x), asinh(x)\n            CPPAD_ASSERT_UNKNOWN( i_var < num_var  );\n            var_op::asinh_forward_dir(\n                order_up, n_dir, i_var, arg, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case AtanOp:\n            // 1 + x * x, atan(x)\n            CPPAD_ASSERT_UNKNOWN( i_var < num_var  );\n            var_op::atan_forward_dir(\n                order_up, n_dir, i_var, arg, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case AtanhOp:\n            // 1 - x * x, atanh(x)\n            CPPAD_ASSERT_UNKNOWN( i_var < num_var  );\n            var_op::atanh_forward_dir(\n                order_up, n_dir, i_var, arg, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case CExpOp:\n            var_op::cexp_forward_dir(\n                order_up, n_dir, i_var, arg, num_par, parameter, cap_order, taylor\n            );\n            break;\n            // ---------------------------------------------------\n\n            case CosOp:\n            // sin(x), cos(x)\n            CPPAD_ASSERT_UNKNOWN( i_var < num_var  );\n            var_op::cos_forward_dir(\n                order_up, n_dir, i_var, arg, cap_order, taylor\n            );\n            break;\n            // ---------------------------------------------------\n\n            case CoshOp:\n            // sinh(x), cosh(x)\n            CPPAD_ASSERT_UNKNOWN( i_var < num_var  );\n            var_op::cosh_forward_dir(\n                order_up, n_dir, i_var, arg, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case CSkipOp:\n            // CSkipOp only does something on order zero.\n            CPPAD_ASSERT_UNKNOWN( order_low > 0 );\n            itr.correct_before_increment();\n            break;\n            // -------------------------------------------------\n\n            case CSumOp:\n            var_op::csum_forward_dir(\n                order_up, i_var, arg, num_par, parameter, n_dir, cap_order, taylor\n            );\n            itr.correct_before_increment();\n            break;\n            // -------------------------------------------------\n\n            case DisOp:\n            var_op::dis_forward_dir<RecBase>(\n                order_low, order_up, n_dir, i_var, arg, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case DivvvOp:\n            var_op::divvv_forward_dir(\n                order_up, n_dir, i_var, arg, parameter, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case DivpvOp:\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );\n            var_op::divpv_forward_dir(\n                order_up, n_dir, i_var, arg, parameter, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case DivvpOp:\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par );\n            var_op::divvp_forward_dir(\n                order_up, n_dir, i_var, arg, parameter, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case EndOp:\n            // needed for sparse_jacobian test\n            CPPAD_ASSERT_NARG_NRES(op, 0, 0);\n            more_operators = false;\n            break;\n            // -------------------------------------------------\n\n            case ErfOp:\n            case ErfcOp:\n            var_op::erf_forward_dir(\n                op, order_up, n_dir, i_var, arg, parameter, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case ExpOp:\n            var_op::exp_forward_dir(\n                order_up, n_dir, i_var, arg, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case Expm1Op:\n            var_op::expm1_forward_dir(\n                order_up, n_dir, i_var, arg, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case InvOp:\n            CPPAD_ASSERT_NARG_NRES(op, 0, 1);\n            break;\n            // -------------------------------------------------\n\n            case LdpOp:\n            case LdvOp:\n            var_op::load_forward_nonzero(\n                op,\n                i_var,\n                arg,\n                order_low,\n                order_up,\n                n_dir,\n                cap_order,\n                load_op2var,\n                taylor\n            );\n            break;\n            // ---------------------------------------------------\n\n            case EqppOp:\n            case EqpvOp:\n            case EqvvOp:\n            case LtppOp:\n            case LtpvOp:\n            case LtvpOp:\n            case LtvvOp:\n            case LeppOp:\n            case LepvOp:\n            case LevpOp:\n            case LevvOp:\n            case NeppOp:\n            case NepvOp:\n            case NevvOp:\n            CPPAD_ASSERT_UNKNOWN( order_up > 0 );\n            break;\n            // -------------------------------------------------\n\n            case LogOp:\n            var_op::log_forward_dir(\n                order_up, n_dir, i_var, arg, cap_order, taylor\n            );\n            break;\n            // ---------------------------------------------------\n\n            case Log1pOp:\n            var_op::log1p_forward_dir(\n                order_up, n_dir, i_var, arg, cap_order, taylor\n            );\n            break;\n            // ---------------------------------------------------\n\n            case MulpvOp:\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );\n            var_op::mulpv_forward_dir(\n                order_up, n_dir, i_var, arg, parameter, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case MulvvOp:\n            var_op::mulvv_forward_dir(\n                order_up, n_dir, i_var, arg, parameter, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case NegOp:\n            var_op::neg_forward_dir(\n                order_up, n_dir, i_var, arg, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case ParOp:\n            var_op::par_forward_dir(\n                order_up, n_dir, i_var, arg, num_par, parameter, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case PowpvOp:\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );\n            var_op::powpv_forward_dir(\n                order_up, n_dir, i_var, arg, parameter, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case PowvpOp:\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par );\n            var_op::powvp_forward_dir(\n                order_up, n_dir, i_var, arg, parameter, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case PowvvOp:\n            var_op::powvv_forward_dir(\n                order_up, n_dir, i_var, arg, parameter, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case PriOp:\n            CPPAD_ASSERT_UNKNOWN( order_up > 0 );\n            break;\n            // -------------------------------------------------\n\n            case SignOp:\n            // sign(x)\n            CPPAD_ASSERT_UNKNOWN( i_var < num_var  );\n            var_op::sign_forward_dir(\n                order_up, n_dir, i_var, arg, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case SinOp:\n            // cos(x), sin(x)\n            CPPAD_ASSERT_UNKNOWN( i_var < num_var  );\n            var_op::sin_forward_dir(\n                order_up, n_dir, i_var, arg, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case SinhOp:\n            // cosh(x), sinh(x)\n            CPPAD_ASSERT_UNKNOWN( i_var < num_var  );\n            var_op::sinh_forward_dir(\n                order_up, n_dir, i_var, arg, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case SqrtOp:\n            var_op::sqrt_forward_dir(\n                order_up, n_dir, i_var, arg, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case StppOp:\n            case StpvOp:\n            case StvpOp:\n            case StvvOp:\n            CPPAD_ASSERT_UNKNOWN( order_up > 0 );\n            break;\n            // -------------------------------------------------\n\n            case SubvvOp:\n            var_op::subvv_forward_dir(\n                order_up, n_dir, i_var, arg, parameter, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case SubpvOp:\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );\n            var_op::subpv_forward_dir(\n                order_up, n_dir, i_var, arg, parameter, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case SubvpOp:\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par );\n            var_op::subvp_forward_dir(\n                order_up, n_dir, i_var, arg, parameter, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case TanOp:\n            // tan(x)^2, tan(x)\n            CPPAD_ASSERT_UNKNOWN( i_var < num_var  );\n            var_op::tan_forward_dir(\n                order_up, n_dir, i_var, arg, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case TanhOp:\n            // tanh(x)^2, tanh(x)\n            CPPAD_ASSERT_UNKNOWN( i_var < num_var  );\n            var_op::tanh_forward_dir(\n                order_up, n_dir, i_var, arg, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case AFunOp:\n            var_op::atomic_forward_dir<Base, RecBase>(\n                itr,\n                play,\n                parameter,\n                atom_trace,\n                atom_work,\n                cap_order,\n                order_up,\n                n_dir,\n                taylor\n            );\n            break;\n\n            case FunapOp:\n            case FunavOp:\n            case FunrpOp:\n            case FunrvOp:\n            break;\n            // -------------------------------------------------\n\n            case ZmulpvOp:\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );\n            var_op::zmulpv_forward_dir(\n                order_up, n_dir, i_var, arg, parameter, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case ZmulvpOp:\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par );\n            var_op::zmulvp_forward_dir(\n                order_up, n_dir, i_var, arg, parameter, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            case ZmulvvOp:\n            var_op::zmulvv_forward_dir(\n                order_up, n_dir, i_var, arg, parameter, cap_order, taylor\n            );\n            break;\n            // -------------------------------------------------\n\n            default:\n            CPPAD_ASSERT_UNKNOWN(0);\n        }\n# if CPPAD_FORWARD_DIR_TRACE\n        if( op != AFunOp )\n        {   printOp<Base, RecBase>(\n                std::cout,\n                play,\n                itr.op_index(),\n                i_var,\n                op,\n                arg\n            );\n            Base* Z_tmp = nullptr;\n            if( op == FunavOp )\n                Z_tmp = taylor + size_t(arg[0])*((cap_order - 1) * n_dir + 1);\n            else if( NumRes(op) > 0 )\n                Z_tmp = taylor + i_var*((cap_order - 1)*n_dir + 1);\n            if( Z_tmp != nullptr )\n            {   Z_vec[0]    = Z_tmp[0];\n                for(size_t ell = 0; ell < n_dir; ell++)\n                {   std::cout << std::endl << \"     \";\n                    for(size_t p_tmp = 1; p_tmp <= order_up; p_tmp++)\n                        Z_vec[p_tmp] = Z_tmp[ (p_tmp-1)*n_dir + ell + 1];\n                    printOpResult(\n                        std::cout,\n                        order_up + 1,\n                        Z_vec.data(),\n                        0,\n                        (Base *) nullptr\n                    );\n                }\n            }\n            std::cout << std::endl;\n        }\n    }\n    std::cout << std::endl;\n# else\n    }\n# endif\n\n    return;\n}\n\n// preprocessor symbols that are local to this file\n# undef CPPAD_FORWARD_DIR_TRACE\n\n} } } // END_CPPAD_LOCAL_SWEEP_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/local/sweep/rev_hes.hpp",
    "content": "# ifndef CPPAD_LOCAL_SWEEP_REV_HES_HPP\n# define CPPAD_LOCAL_SWEEP_REV_HES_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/local/play/atom_op_info.hpp>\n# include <cppad/local/sweep/call_atomic.hpp>\n\n// BEGIN_CPPAD_LOCAL_SWEEP_NAMESPACE\nnamespace CppAD { namespace local { namespace sweep {\n/*!\n\\file sweep/rev_hes.hpp\nCompute Reverse mode Hessian sparsity patterns.\n*/\n\n/*!\n\\def CPPAD_REV_HES_TRACE\nThis value is either zero or one.\nZero is the normal operational value.\nIf it is one, a trace of every rev_hes_sweep computation is printed.\n*/\n# define CPPAD_REV_HES_TRACE 0\n\n/*!\nGiven the forward Jacobian sparsity pattern for all the variables,\nand the reverse Jacobian sparsity pattern for the dependent variables,\nRevHesSweep computes the Hessian sparsity pattern for all the independent\nvariables.\n\n\\tparam Base\nthis operation sequence was recorded using AD<Base>.\n\n\\tparam Vector_set\nis the type used for vectors of sets. It can be either\nsparse::pack_setvec or sparse::list_setvec.\n\n\\param n\nis the number of independent variables on the tape.\n\n\\param num_var\nis the total number of variables on the tape; i.e.,\n play->num_var().\nThis is also the number of rows in the entire sparsity pattern\n rev_hes_sparse.\n\n\\param play\nThe information stored in play\nis a recording of the operations corresponding to a function\n\\f[\n    F : {\\bf R}^n \\rightarrow {\\bf R}^m\n\\f]\nwhere \\f$ n \\f$ is the number of independent variables\nand \\f$ m \\f$ is the number of dependent variables.\n\n\\param for_jac_sparse\nFor i = 0 , ... , num_var - 1,\n(for all the variables on the tape),\nthe forward Jacobian sparsity pattern for the variable with index i\ncorresponds to the set with index i in for_jac_sparse.\n\n\\param RevJac\n\\b Input:\nFor i = 0, ... , num_var - 1\nthe if the variable with index i on the tape is an dependent variable and\nincluded in the Hessian, RevJac[ i ] is equal to true,\notherwise it is equal to false.\n\\n\n\\n\n\\b Output: The values in RevJac upon return are not specified; i.e.,\nit is used for temporary work space.\n\n\\param rev_hes_sparse\nThe reverse Hessian sparsity pattern for the variable with index i\ncorresponds to the set with index i in rev_hes_sparse.\n\\n\n\\n\n\\b Input: For i = 0 , ... , num_var - 1\nthe reverse Hessian sparsity pattern for the variable with index i is empty.\n\\n\n\\n\n\\b Output: For j = 1 , ... , n,\nthe reverse Hessian sparsity pattern for the independent dependent variable\nwith index (j-1) is given by the set with index j\nin rev_hes_sparse.\nThe values in the rest of rev_hes_sparse are not specified; i.e.,\nthey are used for temporary work space.\n\n\\param not_used_rec_base\nSpecifies RecBase for this call.\n*/\n\ntemplate <class Base, class Vector_set, class RecBase>\nvoid rev_hes(\n    const local::player<Base>* play,\n    size_t                     num_var,\n    const Vector_set&          for_jac_sparse,\n    bool*                      RevJac,\n    Vector_set&                rev_hes_sparse,\n    const RecBase&             not_used_rec_base\n)\n{\n    // length of the parameter vector (used by CppAD assert macros)\n    const size_t num_par = play->num_par_all();\n\n    size_t             i, j, k;\n\n    // check num_var argument\n    CPPAD_ASSERT_UNKNOWN( play->num_var()        == num_var );\n    CPPAD_ASSERT_UNKNOWN( for_jac_sparse.n_set() == num_var );\n    CPPAD_ASSERT_UNKNOWN( rev_hes_sparse.n_set() == num_var );\n    CPPAD_ASSERT_UNKNOWN( num_var > 0 );\n\n    // upper limit exclusive for set elements\n    size_t limit   = rev_hes_sparse.end();\n    CPPAD_ASSERT_UNKNOWN( for_jac_sparse.end() == limit );\n\n    // check number of sets match\n    CPPAD_ASSERT_UNKNOWN(\n        for_jac_sparse.n_set() == rev_hes_sparse.n_set()\n    );\n\n    // vecad_sparsity contains a sparsity pattern for each VecAD object.\n    // vecad_ind maps a VecAD index (beginning of the VecAD object)\n    // to the index for the corresponding set in vecad_sparsity.\n    size_t num_vecad_ind   = play->num_var_vec_ind();\n    size_t num_vecad_vec   = play->num_var_vecad();\n    Vector_set vecad_sparse;\n    pod_vector<size_t> vecad_ind;\n    pod_vector<bool>   vecad_jac;\n    if( num_vecad_vec > 0 )\n    {   size_t length;\n        vecad_sparse.resize(num_vecad_vec, limit);\n        vecad_ind.extend(num_vecad_ind);\n        vecad_jac.extend(num_vecad_vec);\n        j             = 0;\n        for(i = 0; i < num_vecad_vec; i++)\n        {   // length of this VecAD\n            length   = play->GetVecInd(j);\n            // set vecad_ind to proper index for this VecAD\n            vecad_ind[j] = i;\n            // make all other values for this vector invalid\n            for(k = 1; k <= length; k++)\n                vecad_ind[j+k] = num_vecad_vec;\n            // start of next VecAD\n            j       += length + 1;\n            // initialize this vector's reverse jacobian value\n            vecad_jac[i] = false;\n        }\n        CPPAD_ASSERT_UNKNOWN( j == play->num_var_vec_ind() );\n    }\n\n    // ----------------------------------------------------------------------\n    //\n    // work space used by atomic functions\n    var_op::atomic_op_work<Base> atom_work;\n    //\n    // pointer to the beginning of the parameter vector\n    // (used by atomic functions\n    CPPAD_ASSERT_UNKNOWN( num_par > 0 )\n    const Base* parameter = play->par_ptr();\n    //\n    // skip the EndOp at the end of the recording\n    play::const_sequential_iterator itr = play->end();\n    // op_info\n    op_code_var   op;\n    size_t        i_var;\n    const addr_t* arg;\n    itr.op_info(op, arg, i_var);\n    CPPAD_ASSERT_UNKNOWN( op == EndOp );\n# if CPPAD_REV_HES_TRACE\n    std::cout << std::endl;\n    CppAD::vectorBool zf_value(limit);\n    CppAD::vectorBool zh_value(limit);\n    bool atom_trace = true;\n# else\n    bool atom_trace = false;\n# endif\n    bool more_operators = true;\n    while(more_operators)\n    {   bool linear[3];\n        //\n        // next op\n        (--itr).op_info(op, arg, i_var);\n\n        // rest of information depends on the case\n        switch( op )\n        {   //\n            // linear operators with one primary result\n            // and where the first argument is the only variable\n            case AbsOp:\n            case DivvpOp:\n            case NegOp:\n            case SubvpOp:\n            case ZmulvpOp:\n            CPPAD_ASSERT_UNKNOWN( 0 < NumArg(op) );\n            linear[0] = true;\n            var_op::one_var_rev_hes(\n                i_var, size_t(arg[0]), linear,\n                RevJac, for_jac_sparse, rev_hes_sparse\n            );\n            break;\n            // -------------------------------------------------\n\n            // non-linear operators with one primary result\n            // and where the first argument is the only variable\n            case AcosOp:\n            case AcoshOp:\n            case AsinOp:\n            case AsinhOp:\n            case AtanOp:\n            case AtanhOp:\n            case CosOp:\n            case CoshOp:\n            case ErfOp:\n            case ErfcOp:\n            case ExpOp:\n            case Expm1Op:\n            case LogOp:\n            case Log1pOp:\n            case PowvpOp:\n            case SinOp:\n            case SinhOp:\n            case SqrtOp:\n            case TanOp:\n            case TanhOp:\n            CPPAD_ASSERT_UNKNOWN( 0 < NumArg(op) );\n            linear[0] = false;\n            var_op::one_var_rev_hes(\n                i_var, size_t(arg[0]), linear,\n                RevJac, for_jac_sparse, rev_hes_sparse\n            );\n            break;\n            // -------------------------------------------------\n\n            // linear and non-liner operators with one primary result\n            // and where the second argument is the only variable\n            case AddpvOp:\n            case MulpvOp:\n            case SubpvOp:\n            case ZmulpvOp:\n            CPPAD_ASSERT_UNKNOWN( 1 < NumArg(op) );\n            linear[0] = true;\n            var_op::one_var_rev_hes(\n                i_var, size_t(arg[1]), linear,\n                RevJac, for_jac_sparse, rev_hes_sparse\n            );\n            break;\n\n            case PowpvOp:\n            case DivpvOp:\n            CPPAD_ASSERT_UNKNOWN( 1 < NumArg(op) );\n            linear[0] = false;\n            var_op::one_var_rev_hes(\n                i_var, size_t(arg[1]), linear,\n                RevJac, for_jac_sparse, rev_hes_sparse\n            );\n            break;\n            // -------------------------------------------------\n\n            case AddvvOp:\n            case SubvvOp:\n            linear[0] = true;\n            linear[1] = true;\n            linear[2] = true;\n            var_op::two_var_rev_hes(\n                i_var, arg, linear, RevJac, for_jac_sparse, rev_hes_sparse\n            );\n            break;\n            // -------------------------------------------------\n\n            case BeginOp:\n            CPPAD_ASSERT_NARG_NRES(op, 1, 1)\n            more_operators = false;\n            break;\n            // -------------------------------------------------\n\n            case CSkipOp:\n            itr.correct_after_decrement(arg);\n            break;\n            // -------------------------------------------------\n\n            case CSumOp:\n            itr.correct_after_decrement(arg);\n            var_op::csum_rev_hes(\n                i_var, arg, RevJac, rev_hes_sparse\n            );\n            break;\n            // -------------------------------------------------\n\n            case CExpOp:\n            var_op::cexp_rev_hes(\n                i_var, arg, num_par, RevJac, rev_hes_sparse\n            );\n            break;\n            // -------------------------------------------------\n\n            case DisOp:\n            CPPAD_ASSERT_NARG_NRES(op, 2, 1)\n            // derivativve is identically zero\n            break;\n            // -------------------------------------------------\n\n            case DivvvOp:\n            linear[0] = true;\n            linear[1] = false;\n            linear[2] = false;\n            CPPAD_ASSERT_NARG_NRES(op, 2, 1)\n            var_op::two_var_rev_hes(\n                i_var, arg, linear, RevJac, for_jac_sparse, rev_hes_sparse\n            );\n            break;\n            // -------------------------------------------------\n\n            case InvOp:\n            CPPAD_ASSERT_NARG_NRES(op, 0, 1)\n            // Z is already defined\n            break;\n            // -------------------------------------------------\n\n            case LdpOp:\n            case LdvOp:\n            var_op::load_rev_hes(\n                op,\n                arg,\n                num_vecad_ind,\n                i_var,\n                vecad_ind,\n                rev_hes_sparse,\n                vecad_sparse,\n                RevJac,\n                vecad_jac\n            );\n            break;\n            // -------------------------------------------------\n\n            case EqppOp:\n            case EqpvOp:\n            case EqvvOp:\n            case LtppOp:\n            case LtpvOp:\n            case LtvpOp:\n            case LtvvOp:\n            case LeppOp:\n            case LepvOp:\n            case LevpOp:\n            case LevvOp:\n            case NeppOp:\n            case NepvOp:\n            case NevvOp:\n            CPPAD_ASSERT_NARG_NRES(op, 2, 0);\n            break;\n            // -------------------------------------------------\n\n            case MulvvOp:\n            case ZmulvvOp:\n            linear[0] = true;\n            linear[1] = true;\n            linear[2] = false;\n            CPPAD_ASSERT_NARG_NRES(op, 2, 1)\n            var_op::two_var_rev_hes(\n                i_var, arg, linear, RevJac, for_jac_sparse, rev_hes_sparse\n            );\n            break;\n            // -------------------------------------------------\n\n            case ParOp:\n            CPPAD_ASSERT_NARG_NRES(op, 1, 1)\n            break;\n            // -------------------------------------------------\n\n            case PowvvOp:\n            linear[0] = false;\n            linear[1] = false;\n            linear[2] = false;\n            CPPAD_ASSERT_NARG_NRES(op, 2, 3)\n            var_op::two_var_rev_hes(\n                i_var, arg, linear, RevJac, for_jac_sparse, rev_hes_sparse\n            );\n            break;\n            // -------------------------------------------------\n\n            case PriOp:\n            CPPAD_ASSERT_NARG_NRES(op, 5, 0);\n            break;\n            // -------------------------------------------------\n\n            case SignOp:\n            CPPAD_ASSERT_NARG_NRES(op, 1, 1);\n            // Derivative is identiaclly zero\n            break;\n            // -------------------------------------------------\n\n            case StppOp:\n            case StpvOp:\n            case StvpOp:\n            case StvvOp:\n            var_op::store_rev_hes(\n                op,\n                arg,\n                num_vecad_ind,\n                vecad_ind,\n                rev_hes_sparse,\n                vecad_sparse,\n                RevJac,\n                vecad_jac\n            );\n            break;\n            // -------------------------------------------------\n\n            case AFunOp:\n            var_op::atomic_rev_hes<Vector_set, Base, RecBase>(\n                itr,\n                play,\n                parameter,\n                atom_trace,\n                atom_work,\n                for_jac_sparse,\n                RevJac,\n                rev_hes_sparse\n            );\n            break;\n\n            case FunapOp:\n            case FunavOp:\n            case FunrpOp:\n            case FunrvOp:\n            CPPAD_ASSERT_UNKNOWN(false);\n            break;\n            // -------------------------------------------------\n\n            default:\n            CPPAD_ASSERT_UNKNOWN(0);\n        }\n# if CPPAD_REV_HES_TRACE\n        if( op != AFunOp )\n        {   for(j = 0; j < limit; j++)\n            {   zf_value[j] = false;\n                zh_value[j] = false;\n            }\n            typename Vector_set::const_iterator itr_jac(for_jac_sparse, i_var);\n            j = *itr_jac;\n            while( j < limit )\n            {   zf_value[j] = true;\n                j = *(++itr_jac);\n            }\n            typename Vector_set::const_iterator itr_hes(rev_hes_sparse, i_var);\n            j = *itr_hes;\n            while( j < limit )\n            {   zh_value[j] = true;\n                j = *(++itr_hes);\n            }\n            printOp<Base, RecBase>(\n                std::cout,\n                play,\n                itr.op_index(),\n                i_var,\n                op,\n                arg\n            );\n            // should also print RevJac[i_var], but printOpResult does not\n            // yet allow for this\n            if( NumRes(op) > 0 && op != BeginOp ) printOpResult(\n                std::cout,\n                1,\n                &zf_value,\n                1,\n                &zh_value\n            );\n            std::cout << std::endl;\n        }\n    }\n    std::cout << std::endl;\n# else\n    }\n# endif\n    // values corresponding to BeginOp\n    CPPAD_ASSERT_UNKNOWN( itr.op_index() == 0 );\n    CPPAD_ASSERT_UNKNOWN( i_var == 0 );\n\n    return;\n}\n} } } // END_CPPAD_LOCAL_SWEEP_NAMESPACE\n\n// preprocessor symbols that are local to this file\n# undef CPPAD_REV_HES_TRACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/sweep/rev_jac.hpp",
    "content": "# ifndef CPPAD_LOCAL_SWEEP_REV_JAC_HPP\n# define CPPAD_LOCAL_SWEEP_REV_JAC_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/local/play/atom_op_info.hpp>\n# include <cppad/local/sweep/call_atomic.hpp>\n\n// This value is either zero or one.  Zero is the normal operational value.\n// If it is one, a trace of every rev_jac_sweep computation is printed.\n# define CPPAD_REV_JAC_TRACE 0\n\n/*\n{xrst_begin local_sweep_rev_jac dev}\n{xrst_spell\n    setvec\n}\n\nReverse Mode Jacobian Sparsity Patterns\n#######################################\n\nSyntax\n******\n| ``local::sweep::rev_jac`` (\n| |tab| *play*               ,\n| |tab| *dependency*         ,\n| |tab| *n*                  ,\n| |tab| *num_var*        ,\n| |tab| *var_sparsity*       ,\n| |tab| ``not_used_rec_base``\n| )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_PROTOTYPE\n    // END_PROTOTYPE\n}\n\nBase\n****\nthis operation sequence was recorded using ``AD`` < *Base* > .\n\nVector_set\n**********\nis the type used for vectors of sets. It can be either\n``sparse::pack_setvec`` or ``sparse::list_setvec`` .\n{xrst_comment 2DO: in previous line change code to cref}\n\nRecBase\n*******\nIs the base type when this function was recorded.\nThis is different from *Base* if\nthis function object was created by :ref:`base2ad-name` .\n\nplay\n****\nThe information stored in play\nis a recording of the operations corresponding to a function\n:math:`F : \\B{R}^n \\rightarrow \\B{R}^m`\nwhere *m* is the number of dependent variables.\n\ndependency\n**********\nAre we computing dependency relations, or only concerned with\npossibly non-zero derivatives. For example,\nare the derivatives with respect to\n*left* and *right* of the expression below\nconsidered to be non-zero:\n\n    ``CondExpRel`` ( *left* , *right* , *if_true* , *if_false* )\n\nThis is used by the optimizer to obtain the correct dependency relations.\n\nn\n*\nis the number of independent variables in the tape.\n\nnum_var\n*******\nis the total number of variables in the tape; i.e.,\n*play* ``->num_var`` () .\nThis is also the number of rows in all the sparsity patterns.\n\nvar_sparsity\n************\n\nOn Input\n========\nFor *i* = 0 , ... , *num_var* ``-1`` ,\nif *i* corresponds to a dependent variables,\nthe set with index *i* is an input.\nOtherwise the set with index *i* is empty.\n\nOn Output\n=========\nFor *i* = 0 , ... , *num_var* ``-1`` ,\nthe sparsity pattern for the variable with index *j* ``-1``\nis given by the set with index *j* in *var_sparsity* .\nNote that one dependent variable may depend on the value of another,\nin which case its output sparsity pattern may be different than its\ninput pattern.\n\nnot_used_rec_base\n*****************\nSpecifies *RecBase* for this call.\n\n{xrst_end local_sweep_rev_jac}\n*/\n\n// BEGIN_CPPAD_LOCAL_SWEEP_NAMESPACE\nnamespace CppAD { namespace local { namespace sweep {\n\n// BEGIN_PROTOTYPE\ntemplate <class Base, class Vector_set, class RecBase>\nvoid rev_jac(\n    const local::player<Base>* play               ,\n    bool                       dependency         ,\n    size_t                     n                  ,\n    size_t                     num_var            ,\n    Vector_set&                var_sparsity       ,\n    const RecBase&             not_used_rec_base  )\n// END_PROTOTYPE\n{\n    size_t            i, j, k;\n\n    // length of the parameter vector (used by CppAD assert macros)\n    const size_t num_par = play->num_par_all();\n\n    // check num_var argument\n    CPPAD_ASSERT_UNKNOWN( num_var > 0 );\n    CPPAD_ASSERT_UNKNOWN( play->num_var()       == num_var );\n    CPPAD_ASSERT_UNKNOWN( var_sparsity.n_set() == num_var );\n\n    // upper limit (exclusive) for elements in the set\n    size_t limit = var_sparsity.end();\n\n    // vecad_sparsity contains a sparsity pattern for each VecAD object.\n    // vecad_ind maps a VecAD index (beginning of the VecAD object)\n    // to the index of the corresponding set in vecad_sparsity.\n    size_t num_vecad_ind   = play->num_var_vec_ind();\n    size_t num_vecad_vec   = play->num_var_vecad();\n    Vector_set  vecad_sparsity;\n    pod_vector<size_t> vecad_ind;\n    if( num_vecad_vec > 0 )\n    {   size_t length;\n        vecad_sparsity.resize(num_vecad_vec, limit);\n        vecad_ind.extend(num_vecad_ind);\n        j             = 0;\n        for(i = 0; i < num_vecad_vec; i++)\n        {   // length of this VecAD\n            length   = play->GetVecInd(j);\n            // set to proper index for this VecAD\n            vecad_ind[j] = i;\n            for(k = 1; k <= length; k++)\n                vecad_ind[j+k] = num_vecad_vec; // invalid index\n            // start of next VecAD\n            j       += length + 1;\n        }\n        CPPAD_ASSERT_UNKNOWN( j == play->num_var_vec_ind() );\n    }\n    // ----------------------------------------------------------------------\n    //\n    // work space used by atomic functions\n    var_op::atomic_op_work<Base> atom_work;\n    //\n    // pointer to the beginning of the parameter vector\n    // (used by atomic functions\n    CPPAD_ASSERT_UNKNOWN( num_par > 0 )\n    const Base* parameter = play->par_ptr();\n    //\n    // skip the EndOp at the end of the recording\n    play::const_sequential_iterator itr = play->end();\n    // op_info\n    op_code_var   op;\n    size_t        i_var;\n    const addr_t* arg;\n    itr.op_info(op, arg, i_var);\n    CPPAD_ASSERT_UNKNOWN( op == EndOp );\n# if CPPAD_REV_JAC_TRACE\n    std::cout << std::endl;\n    CppAD::vectorBool z_value(limit);\n    bool atom_trace = true;\n# else\n    bool atom_trace = false;\n# endif\n    bool more_operators = true;\n    while(more_operators)\n    {   //\n        // next op\n        (--itr).op_info(op, arg, i_var);\n\n        // rest of information depends on the case\n        switch( op )\n        {   //\n            // operators with one primary result and\n            // where the first argument is the only variable\n            case AbsOp:\n            case AcosOp:\n            case AcoshOp:\n            case AsinOp:\n            case AsinhOp:\n            case AtanOp:\n            case AtanhOp:\n            case CosOp:\n            case CoshOp:\n            case DivvpOp:\n            case ErfOp:\n            case ErfcOp:\n            case ExpOp:\n            case Expm1Op:\n            case LogOp:\n            case NegOp:\n            case Log1pOp:\n            case PowvpOp:\n            case SinOp:\n            case SinhOp:\n            case SqrtOp:\n            case SubvpOp:\n            case TanOp:\n            case TanhOp:\n            case ZmulvpOp:\n            CPPAD_ASSERT_UNKNOWN( 0 < NumArg(op) );\n            var_op::one_var_rev_jac(\n                i_var, size_t(arg[0]), var_sparsity\n            );\n            break;\n            // -------------------------------------------------\n\n            // operators with one primary result and\n            // where the second argument is the only variable\n            case AddpvOp:\n            case DivpvOp:\n            case MulpvOp:\n            case PowpvOp:\n            case SubpvOp:\n            case ZmulpvOp:\n            CPPAD_ASSERT_UNKNOWN( 1 < NumArg(op) );\n            var_op::one_var_rev_jac(\n                i_var, size_t(arg[1]), var_sparsity\n            );\n            break;\n            // -------------------------------------------------\n\n            case AddvvOp:\n            CPPAD_ASSERT_NARG_NRES(op, 2, 1);\n            var_op::two_var_rev_jac(\n                i_var, arg, var_sparsity\n            );\n            break;\n            // -------------------------------------------------\n\n            case BeginOp:\n            CPPAD_ASSERT_NARG_NRES(op, 1, 1);\n            more_operators = false;\n            break;\n            // -------------------------------------------------\n\n            case CSkipOp:\n            itr.correct_after_decrement(arg);\n            break;\n            // -------------------------------------------------\n\n            case CSumOp:\n            itr.correct_after_decrement(arg);\n            var_op::csum_rev_jac(\n                i_var, arg, var_sparsity\n            );\n            break;\n            // -------------------------------------------------\n\n            case CExpOp:\n            var_op::cexp_rev_jac(\n                dependency, i_var, arg, num_par, var_sparsity\n            );\n            break;\n            // ---------------------------------------------------\n\n            case DisOp:\n            CPPAD_ASSERT_NARG_NRES(op, 2, 1);\n            // derivative is identically zero but dependency is not\n            if( dependency ) var_op::one_var_rev_jac(\n                i_var, size_t(arg[1]), var_sparsity\n            );\n            break;\n            // -------------------------------------------------\n\n            case DivvvOp:\n            CPPAD_ASSERT_NARG_NRES(op, 2, 1);\n            var_op::two_var_rev_jac(\n                i_var, arg, var_sparsity\n            );\n            break;\n            // -------------------------------------------------\n\n            case InvOp:\n            CPPAD_ASSERT_NARG_NRES(op, 0, 1);\n            break;\n            // -------------------------------------------------\n\n            case LdpOp:\n            case LdvOp:\n            var_op::load_rev_jac(\n                op,\n                num_vecad_ind,\n                i_var,\n                arg,\n                dependency,\n                vecad_ind,\n                var_sparsity,\n                vecad_sparsity\n            );\n            break;\n            // -------------------------------------------------\n\n            case EqppOp:\n            case EqpvOp:\n            case EqvvOp:\n            case LtppOp:\n            case LtpvOp:\n            case LtvpOp:\n            case LtvvOp:\n            case LeppOp:\n            case LepvOp:\n            case LevpOp:\n            case LevvOp:\n            case NeppOp:\n            case NepvOp:\n            case NevvOp:\n            CPPAD_ASSERT_NARG_NRES(op, 2, 0);\n            break;\n            // -------------------------------------------------\n\n            case MulvvOp:\n            CPPAD_ASSERT_NARG_NRES(op, 2, 1);\n            var_op::two_var_rev_jac(\n                i_var, arg, var_sparsity\n            );\n            break;\n            // -------------------------------------------------\n\n            case ParOp:\n            CPPAD_ASSERT_NARG_NRES(op, 1, 1);\n\n            break;\n            // -------------------------------------------------\n\n            case PowvvOp:\n            CPPAD_ASSERT_NARG_NRES(op, 2, 3);\n            var_op::two_var_rev_jac(\n                i_var, arg, var_sparsity\n            );\n            break;\n            // -------------------------------------------------\n\n            case PriOp:\n            CPPAD_ASSERT_NARG_NRES(op, 5, 0);\n            break;\n            // -------------------------------------------------\n\n            case SignOp:\n            CPPAD_ASSERT_NARG_NRES(op, 1, 1);\n            // derivative is identically zero but dependency is not\n            if( dependency ) var_op::one_var_rev_jac(\n                i_var, size_t(arg[0]), var_sparsity\n            );\n            break;\n            // -------------------------------------------------\n\n            case StppOp:\n            case StpvOp:\n            case StvpOp:\n            case StvvOp:\n            var_op::store_rev_jac(\n                op,\n                num_vecad_ind,\n                arg,\n                dependency,\n                vecad_ind,\n                var_sparsity,\n                vecad_sparsity\n            );\n            break;\n            // -------------------------------------------------\n\n            case SubvvOp:\n            CPPAD_ASSERT_NARG_NRES(op, 2, 1);\n            var_op::two_var_rev_jac(\n                i_var, arg, var_sparsity\n            );\n            break;\n            // -------------------------------------------------\n\n            case AFunOp:\n            var_op::atomic_rev_jac<Vector_set, Base, RecBase>(\n                itr,\n                play,\n                parameter,\n                atom_trace,\n                atom_work,\n                dependency,\n                var_sparsity\n            );\n            break;\n\n            case FunapOp:\n            case FunavOp:\n            case FunrpOp:\n            case FunrvOp:\n            CPPAD_ASSERT_UNKNOWN( false );\n            break;\n            // -------------------------------------------------\n\n            case ZmulvvOp:\n            CPPAD_ASSERT_NARG_NRES(op, 2, 1);\n            var_op::two_var_rev_jac(\n                i_var, arg, var_sparsity\n            );\n            break;\n            // -------------------------------------------------\n\n            default:\n            CPPAD_ASSERT_UNKNOWN(0);\n        }\n# if CPPAD_REV_JAC_TRACE\n        if( op != AFunOp )\n        {   for(j = 0; j < limit; j++)\n                z_value[j] = false;\n            typename Vector_set::const_iterator itr_sparse(var_sparsity, i_var);\n            j = *itr_sparse;\n            while( j < limit )\n            {   z_value[j] = true;\n                j          = *(++itr_sparse);\n            }\n            printOp<Base, RecBase>(\n                std::cout,\n                play,\n                itr.op_index(),\n                i_var,\n                op,\n                arg\n            );\n            // Note that sparsity for FunrvOp are computed before call to\n            // atomic function so no need to delay printing (as in forward mode)\n            if( NumRes(op) > 0 && op != BeginOp ) printOpResult(\n                std::cout,\n                0,\n                (CppAD::vectorBool *) nullptr,\n                1,\n                &z_value\n            );\n            std::cout << std::endl;\n        }\n    }\n    std::cout << std::endl;\n# else\n    }\n# endif\n    // values corresponding to BeginOp\n    CPPAD_ASSERT_UNKNOWN( itr.op_index() == 0 );\n    CPPAD_ASSERT_UNKNOWN( i_var == 0 );\n\n    return;\n}\n\n// preprocessor symbols that are local to this file\n# undef CPPAD_REV_JAC_TRACE\n\n} } } // END_CPPAD_LOCAL_SWEEP_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/sweep/reverse.hpp",
    "content": "# ifndef CPPAD_LOCAL_SWEEP_REVERSE_HPP\n# define CPPAD_LOCAL_SWEEP_REVERSE_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n\n# include <cppad/local/play/atom_op_info.hpp>\n\n// BEGIN_CPPAD_LOCAL_SWEEP_NAMESPACE\nnamespace CppAD { namespace local { namespace sweep {\n/*!\n\\file sweep/reverse.hpp\nCompute derivatives of arbitrary order Taylor coefficients.\n*/\n\n/*!\n\\def CPPAD_REVERSE_TRACE\nThis value is either zero or one.\nZero is the normal operational value.\nIf it is one, a trace of every reverse_sweep computation is printed.\n*/\n# define CPPAD_REVERSE_TRACE 0\n\n/*!\nCompute derivative of arbitrary order forward mode Taylor coefficients.\n\n\\tparam Base\nthis operation sequence was recorded using AD<Base>\nand computations by this routine are done using type Base.\n\n\\param n\nis the number of independent variables on the tape.\n\n\\param num_var\nis the total number of variables on the tape.\nThis is also equal to the number of rows in the matrix Taylor; i.e.,\nplay->num_var().\n\n\\param play\nThe information stored in play\nis a recording of the operations corresponding to the function\n\\f[\n    F : {\\bf R}^n \\rightarrow {\\bf R}^m\n\\f]\nwhere \\f$ n \\f$ is the number of independent variables and\n\\f$ m \\f$ is the number of dependent variables.\nWe define \\f$ u^{(k)} \\f$ as the value of <code>x_k</code> in the previous call\nof the form\n<code>\n    f.Forward(k, x_k)\n</code>\nWe define\n\\f$ X : {\\bf R}^{n \\times d} \\rightarrow {\\bf R}^n \\f$ by\n\\f[\n    X(t, u) =  u^{(0)} + u^{(1)} t + \\cdots + u^{(d)} t^d\n\\f]\nWe define\n\\f$ Y : {\\bf R}^{n \\times d} \\rightarrow {\\bf R}^m \\f$ by\n\\f[\n    Y(t, u) =  F[ X(t, u) ]\n\\f]\nWe define the function\n\\f$ W : {\\bf R}^{n \\times d} \\rightarrow {\\bf R} \\f$ by\n\\f[\nW(u)\n=\n\\sum_{k=0}^{d} ( w^{(k)} )^{\\rm T}\n    \\frac{1}{k !} \\frac{\\partial^k}{\\partial t^k} Y(0, u)\n\\f]\n(The matrix \\f$ w \\in {\\bf R}^m \\f$,\nis defined below under the heading Partial.)\nNote that the scale factor  1 / k  converts\nthe k-th partial derivative to the k-th order Taylor coefficient.\nThis routine computes the derivative of \\f$ W(u) \\f$\nwith respect to all the Taylor coefficients\n\\f$ u^{(k)} \\f$ for \\f$ k = 0 , ... , d \\f$.\n\n\\param J\nIs the number of columns in the coefficient matrix Taylor.\nThis must be greater than or equal d + 1.\n\n\\param Taylor\nFor i = 1 , ... , num_var, and for k = 0 , ... , d,\n Taylor [ i * J + k ]\nis the k-th order Taylor coefficient corresponding to\nvariable with index i on the tape.\nThe value \\f$ u \\in {\\bf R}^{n \\times d} \\f$,\nat which the derivative is computed,\nis defined by\n\\f$ u_j^{(k)} \\f$ = Taylor [ j * J + k ]\nfor j = 1 , ... , n, and for k = 0 , ... , d.\n\n\\param K\nIs the number of columns in the partial derivative matrix Partial.\nIt must be greater than or equal d + 1.\n\n\\param Partial\n\\b Input:\nThe last \\f$ m \\f$ rows of Partial are inputs.\nThe matrix \\f$ w \\f$, used to define \\f$ W(u) \\f$,\nis specified by these rows.\nFor i = 0 , ... , m - 1,\nfor k = 0 , ... , d,\n<code>Partial [ (num_var - m + i ) * K + k ] = w[i,k]</code>.\n\\n\n\\n\n\\b Temporary:\nFor i = n+1 , ... , num_var - 1 and for k = 0 , ... , d,\nthe value of Partial [ i * K + k ] is used for temporary work space\nand its output value is not defined.\n\\n\n\\n\n\\b Output:\nFor j = 1 , ... , n and for k = 0 , ... , d,\n Partial [ j * K + k ]\nis the partial derivative of \\f$ W( u ) \\f$ with\nrespect to \\f$ u_j^{(k)} \\f$.\n\n\\param cskip_op\nIs a vector with size play->num_var_op().\nIf cskip_op[i] is true, the operator index i in the recording\ndoes not affect any of the dependent variable (given the value\nof the independent variables).\nNote that all the operators in an atomic function call are skipped as a block,\nso only the last AFunOp fore each call needs to have cskip_op[i] true.\n\n\\param load_op2var\nis a vector with size play->num_var_load().\nIt contains the variable index corresponding to each load instruction.\nIn the case where the index is zero,\nthe instruction corresponds to a parameter (not variable).\n\n\\tparam Iterator\nThis is either player::const_iteratoror player::const_subgraph_iterator.\n\n\\param play_itr\nOn input this is either play->end(), for the entire graph,\nor play->end(subgraph), for a subgraph.\nThis routine mode will use --play_itr to iterate over the graph or subgraph.\nIt is assumes that the iterator starts just past the EndOp and it will\ncontinue until it reaches the BeginOp.\nIf i_var is a variable index, and the corresponding operator\nis not in the subgraph,\nthen the partials with respect to i_var are not modified and need to be\ninitialized as zero. Note that this means the partial for the independent\nvariables, that are not in the subgraph are not calculated.\nIf part of an atomic function call is in the subgraph,\nthe entire atomic function call must be in the subgraph.\n\n\\param not_used_rec_base\nSpecifies RecBase for this call.\n\n\\par Assumptions\nThe first operator on the tape is a BeginOp,\nand the next n operators are InvOp operations for the\ncorresponding independent variables; see play->check_inv_op(n_ind).\n*/\ntemplate <class Base, class Iterator, class RecBase>\nvoid reverse(\n    size_t                      num_var,\n    const local::player<Base>*  play,\n    size_t                      cap_order,\n    const Base*                 Taylor,\n    size_t                      K,\n    Base*                       Partial,\n    bool*                       cskip_op,\n    const pod_vector<addr_t>&   load_op2var,\n    Iterator&                   play_itr,\n    const RecBase&              not_used_rec_base\n)\n{\n    // check num_var argument\n    CPPAD_ASSERT_UNKNOWN( play->num_var() == num_var );\n    CPPAD_ASSERT_UNKNOWN( num_var > 0 );\n\n    // length of the parameter vector (used by CppAD assert macros)\n    const size_t num_par = play->num_par_all();\n\n    // pointer to the beginning of the parameter vector\n    CPPAD_ASSERT_UNKNOWN( num_par > 0 )\n    const Base* parameter = play->par_ptr();\n\n    // work space used by atomic functions\n    var_op::atomic_op_work<Base> atom_work;\n\n    //\n    // information defined by atomic forward\n    size_t atom_index=0, atom_old=0, atom_m=0, atom_n=0;\n\n    // A vector with unspecified contents declared here so that operator\n    // routines do not need to re-allocate it\n    vector<Base> work;\n\n    // Initialize\n# if CPPAD_REVERSE_TRACE\n    std::cout << std::endl;\n    bool atom_trace = true;\n# else\n    bool atom_trace = false;\n# endif\n    op_code_var   op;\n    const addr_t* arg;\n    size_t        i_var;\n    play_itr.op_info(op, arg, i_var);\n    CPPAD_ASSERT_UNKNOWN( op == EndOp );\n    while(op != BeginOp )\n    {   //\n        // next op\n        (--play_itr).op_info(op, arg, i_var);\n\n        // check if we are skipping this operation\n        size_t i_op = play_itr.op_index();\n        while( cskip_op[i_op] )\n        {   switch(op)\n            {\n                case CSumOp:\n                case CSkipOp:\n                // cases that never happen but the code reads better with them\n                play_itr.correct_after_decrement(arg);\n                break;\n\n                case AFunOp:\n                {   // get information for this atomic function call\n                    play::atom_op_info<Base>(\n                        op, arg, atom_index, atom_old, atom_m, atom_n\n                    );\n                    //\n                    // skip to the first AFunOp\n                    for(size_t i = 0; i < atom_m + atom_n + 1; ++i)\n                        --play_itr;\n                    play_itr.op_info(op, arg, i_var);\n                    CPPAD_ASSERT_UNKNOWN( op == AFunOp );\n                }\n                break;\n\n                default:\n                break;\n            }\n            (--play_itr).op_info(op, arg, i_var);\n            i_op = play_itr.op_index();\n        }\n# if CPPAD_REVERSE_TRACE\n        if( op != AFunOp )\n        {\n            size_t       i_tmp  = i_var;\n            const Base*  Z_tmp  = Taylor + i_var * cap_order;\n            const Base*  pZ_tmp = Partial + i_var * K;\n            printOp<Base, RecBase>(\n                std::cout,\n                play,\n                i_op,\n                i_tmp,\n                op,\n                arg\n            );\n            if( NumRes(op) > 0 && op != BeginOp ) printOpResult(\n                std::cout,\n                K,\n                Z_tmp,\n                K,\n                pZ_tmp\n            );\n            std::cout << std::endl;\n        }\n# endif\n        switch( op )\n        {\n            case AbsOp:\n            var_op::abs_reverse(\n                i_var, arg, cap_order, Taylor, K, Partial\n            );\n            break;\n            // --------------------------------------------------\n\n            case AcosOp:\n            // sqrt(1 - x * x), acos(x)\n            CPPAD_ASSERT_UNKNOWN( i_var < num_var );\n            var_op::acos_reverse(\n                i_var, arg, cap_order, Taylor, K, Partial\n            );\n            break;\n            // --------------------------------------------------\n\n            case AcoshOp:\n            // sqrt(x * x - 1), acosh(x)\n            CPPAD_ASSERT_UNKNOWN( i_var < num_var );\n            var_op::acosh_reverse(\n                i_var, arg, cap_order, Taylor, K, Partial\n            );\n            break;\n            // --------------------------------------------------\n\n            case AddvvOp:\n            var_op::addvv_reverse(\n                i_var, arg, parameter, cap_order, Taylor, K, Partial\n            );\n            break;\n            // --------------------------------------------------\n\n            case AddpvOp:\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );\n            var_op::addpv_reverse(\n                i_var, arg, parameter, cap_order, Taylor, K, Partial\n            );\n            break;\n            // --------------------------------------------------\n\n            case AsinOp:\n            // sqrt(1 - x * x), asin(x)\n            CPPAD_ASSERT_UNKNOWN( i_var < num_var );\n            var_op::asin_reverse(\n                i_var, arg, cap_order, Taylor, K, Partial\n            );\n            break;\n            // --------------------------------------------------\n\n            case AsinhOp:\n            // sqrt(1 + x * x), asinh(x)\n            CPPAD_ASSERT_UNKNOWN( i_var < num_var );\n            var_op::asinh_reverse(\n                i_var, arg, cap_order, Taylor, K, Partial\n            );\n            break;\n            // --------------------------------------------------\n\n            case AtanOp:\n            // 1 + x * x, atan(x)\n            CPPAD_ASSERT_UNKNOWN( i_var < num_var );\n            var_op::atan_reverse(\n                i_var, arg, cap_order, Taylor, K, Partial\n            );\n            break;\n            // -------------------------------------------------\n\n            case AtanhOp:\n            // 1 - x * x, atanh(x)\n            CPPAD_ASSERT_UNKNOWN( i_var < num_var );\n            var_op::atanh_reverse(\n                i_var, arg, cap_order, Taylor, K, Partial\n            );\n            break;\n            // -------------------------------------------------\n\n            case BeginOp:\n            CPPAD_ASSERT_NARG_NRES(op, 1, 1);\n            CPPAD_ASSERT_UNKNOWN( i_op == 0 );\n            break;\n            // --------------------------------------------------\n\n            case CSkipOp:\n            // CSkipOp has a zero order forward action.\n            play_itr.correct_after_decrement(arg);\n            break;\n            // -------------------------------------------------\n\n            case CSumOp:\n            play_itr.correct_after_decrement(arg);\n            var_op::csum_reverse(\n                i_var, arg, K, Partial\n            );\n            // end of a cumulative summation\n            break;\n            // -------------------------------------------------\n\n            case CExpOp:\n            var_op::cexp_reverse(\n                i_var,\n                arg,\n                num_par,\n                parameter,\n                cap_order,\n                Taylor,\n                K,\n                Partial\n            );\n            break;\n            // --------------------------------------------------\n\n            case CosOp:\n            CPPAD_ASSERT_UNKNOWN( i_var < num_var );\n            var_op::cos_reverse(\n                i_var, arg, cap_order, Taylor, K, Partial\n            );\n            break;\n            // --------------------------------------------------\n\n            case CoshOp:\n            CPPAD_ASSERT_UNKNOWN( i_var < num_var );\n            var_op::cosh_reverse(\n                i_var, arg, cap_order, Taylor, K, Partial\n            );\n            break;\n            // --------------------------------------------------\n\n            case DisOp:\n            // Derivative of discrete operation is zero so no\n            // contribution passes through this operation.\n            break;\n            // --------------------------------------------------\n\n            case DivvvOp:\n            var_op::divvv_reverse(\n                i_var, arg, parameter, cap_order, Taylor, K, Partial\n            );\n            break;\n            // --------------------------------------------------\n\n            case DivpvOp:\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );\n            var_op::divpv_reverse(\n                i_var, arg, parameter, cap_order, Taylor, K, Partial\n            );\n            break;\n            // --------------------------------------------------\n\n            case DivvpOp:\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par );\n            var_op::divvp_reverse(\n                i_var, arg, parameter, cap_order, Taylor, K, Partial\n            );\n            break;\n            // --------------------------------------------------\n            case EndOp:\n            CPPAD_ASSERT_UNKNOWN(\n                i_op == play->num_var_op() - 1\n            );\n            break;\n\n            // --------------------------------------------------\n\n            case ErfOp:\n            case ErfcOp:\n            var_op::erf_reverse(\n                op, i_var, arg, parameter, cap_order, Taylor, K, Partial\n            );\n            break;\n            // --------------------------------------------------\n\n            case ExpOp:\n            var_op::exp_reverse(\n                i_var, arg, cap_order, Taylor, K, Partial\n            );\n            break;\n            // --------------------------------------------------\n\n            case Expm1Op:\n            var_op::expm1_reverse(\n                i_var, arg, cap_order, Taylor, K, Partial\n            );\n            break;\n            // --------------------------------------------------\n\n            case InvOp:\n            break;\n            // --------------------------------------------------\n\n            case LdpOp:\n            case LdvOp:\n            var_op::load_reverse(\n                op, i_var, arg, load_op2var, cap_order, K, Partial\n            );\n            break;\n            // -------------------------------------------------\n\n            case EqppOp:\n            case EqpvOp:\n            case EqvvOp:\n            case LtppOp:\n            case LtpvOp:\n            case LtvpOp:\n            case LtvvOp:\n            case LeppOp:\n            case LepvOp:\n            case LevpOp:\n            case LevvOp:\n            case NeppOp:\n            case NepvOp:\n            case NevvOp:\n            break;\n            // -------------------------------------------------\n\n            case LogOp:\n            var_op::log_reverse(\n                i_var, arg, cap_order, Taylor, K, Partial\n            );\n            break;\n            // --------------------------------------------------\n\n            case Log1pOp:\n            var_op::log1p_reverse(\n                i_var, arg, cap_order, Taylor, K, Partial\n            );\n            break;\n            // --------------------------------------------------\n\n            case MulpvOp:\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );\n            var_op::mulpv_reverse(\n                i_var, arg, parameter, cap_order, Taylor, K, Partial\n            );\n            break;\n            // --------------------------------------------------\n\n            case MulvvOp:\n            var_op::mulvv_reverse(\n                i_var, arg, parameter, cap_order, Taylor, K, Partial\n            );\n            break;\n            // -------------------------------------------------\n\n            case NegOp:\n            var_op::neg_reverse(\n                i_var, arg, cap_order, Taylor, K, Partial\n            );\n            break;\n            // --------------------------------------------------\n\n            case ParOp:\n            break;\n            // --------------------------------------------------\n\n            case PowvpOp:\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par );\n            var_op::powvp_reverse(\n                i_var, arg, parameter, cap_order, Taylor, K, Partial, work\n            );\n            break;\n            // -------------------------------------------------\n\n            case PowpvOp:\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );\n            var_op::powpv_reverse(\n                i_var, arg, parameter, cap_order, Taylor, K, Partial\n            );\n            break;\n            // -------------------------------------------------\n\n            case PowvvOp:\n            var_op::powvv_reverse(\n                i_var, arg, parameter, cap_order, Taylor, K, Partial\n            );\n            break;\n            // --------------------------------------------------\n\n            case PriOp:\n            // no result so nothing to do\n            break;\n            // --------------------------------------------------\n\n            case SignOp:\n            CPPAD_ASSERT_UNKNOWN( i_var < num_var );\n            var_op::sign_reverse(\n                i_var, arg, cap_order, Taylor, K, Partial\n            );\n            break;\n            // -------------------------------------------------\n\n            case SinOp:\n            CPPAD_ASSERT_UNKNOWN( i_var < num_var );\n            var_op::sin_reverse(\n                i_var, arg, cap_order, Taylor, K, Partial\n            );\n            break;\n            // -------------------------------------------------\n\n            case SinhOp:\n            CPPAD_ASSERT_UNKNOWN( i_var < num_var );\n            var_op::sinh_reverse(\n                i_var, arg, cap_order, Taylor, K, Partial\n            );\n            break;\n            // --------------------------------------------------\n\n            case SqrtOp:\n            var_op::sqrt_reverse(\n                i_var, arg, cap_order, Taylor, K, Partial\n            );\n            break;\n            // --------------------------------------------------\n\n            case StppOp:\n            break;\n            // --------------------------------------------------\n\n            case StpvOp:\n            break;\n            // -------------------------------------------------\n\n            case StvpOp:\n            break;\n            // -------------------------------------------------\n\n            case StvvOp:\n            break;\n            // --------------------------------------------------\n\n            case SubvvOp:\n            var_op::subvv_reverse(\n                i_var, arg, parameter, cap_order, Taylor, K, Partial\n            );\n            break;\n            // --------------------------------------------------\n\n            case SubpvOp:\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );\n            var_op::subpv_reverse(\n                i_var, arg, parameter, cap_order, Taylor, K, Partial\n            );\n            break;\n            // --------------------------------------------------\n\n            case SubvpOp:\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par );\n            var_op::subvp_reverse(\n                i_var, arg, parameter, cap_order, Taylor, K, Partial\n            );\n            break;\n            // -------------------------------------------------\n\n            case TanOp:\n            CPPAD_ASSERT_UNKNOWN( i_var < num_var );\n            var_op::tan_reverse(\n                i_var, arg, cap_order, Taylor, K, Partial\n            );\n            break;\n            // -------------------------------------------------\n\n            case TanhOp:\n            CPPAD_ASSERT_UNKNOWN( i_var < num_var );\n            var_op::tanh_reverse(\n                i_var, arg, cap_order, Taylor, K, Partial\n            );\n            break;\n            // --------------------------------------------------\n\n            case AFunOp:\n            var_op::atomic_reverse<Base, RecBase, Iterator>(\n                play_itr,\n                play,\n                parameter,\n                atom_trace,\n                atom_work,\n                cap_order,\n                K,\n                Taylor,\n                Partial\n            );\n            break;\n\n            case FunapOp:\n            case FunavOp:\n            case FunrpOp:\n            case FunrvOp:\n            CPPAD_ASSERT_UNKNOWN(false);\n            break;\n            // ------------------------------------------------------------\n\n            case ZmulpvOp:\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );\n            var_op::zmulpv_reverse(\n                i_var, arg, parameter, cap_order, Taylor, K, Partial\n            );\n            break;\n            // --------------------------------------------------\n\n            case ZmulvpOp:\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par );\n            var_op::zmulvp_reverse(\n                i_var, arg, parameter, cap_order, Taylor, K, Partial\n            );\n            break;\n            // --------------------------------------------------\n\n            case ZmulvvOp:\n            var_op::zmulvv_reverse(\n                i_var, arg, parameter, cap_order, Taylor, K, Partial\n            );\n            break;\n            // --------------------------------------------------\n\n            default:\n            CPPAD_ASSERT_UNKNOWN(false);\n        }\n    }\n# if CPPAD_REVERSE_TRACE\n    std::cout << std::endl;\n# endif\n}\n\n} } } // END_CPPAD_LOCAL_SWEEP_NAMESPACE\n\n// preprocessor symbols that are local to this file\n# undef CPPAD_REVERSE_TRACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/sweep/template/forward_sweep.xrst",
    "content": "{xrst_comment\nSPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\nSPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\nSPDX-FileContributor: 2024-25 Bradley M. Bell\n\nUnder Construction:\n\nThis file is intended to help document the forward_* sweep functions.\n    headers all:     CPPAD_@NAME@_TRACE, Portotype, Base, RecBase, play, num_var\n    headers all:     cap_order, cskip, load_op2var, taylor\n    headers 0 & any: change_count, change_number, change_op_index, sout, print\n    headers any:     order_low, order_up\n    headers dir:     order_up, n_dir\n\nIt has the following xrst template replacements:\n    @title@  The title for this forward sweep\n    @#####@  Underlining for the tilte\n    @NAME@   is one of FORWARD_0, FORWARD_ANY, FORWARD_DIR\n                Prototype is surrounded by // BEGIN_@NAME@ and // END_@NAME@\n    @****@   Underlining for @NAME@\n}\n\n@title@\n@#####@\n\nCPPAD_@NAME@_TRACE\n******@****@******\nThis value is defined in the source code for this function\nand is either zero or one.\nZero is the normal operational value.\nIf it is one, a trace of every zero order forward mode computation is printed.\n\n{xrst_comment ----------------------------------------------------------------}\n{xrst_suspend @NAME@ != FORWARD_0}\n\norder_low\n*********\nWe use *order_low* for the lowest order Taylor coefficient that is computed\nwhich is zero for this case.\n\n{xrst_resume}\n{xrst_comment ----------------------------------------------------------------}\n{xrst_suspend @NAME@ != FORWARD_DIR}\n\norder_low\n*********\nWe use *order_low* for the lowest order Taylor coefficient that is computed\nwhich is equal to *order_up* and non-zero for this case.\n\n{xrst_resume}\n{xrst_comment ----------------------------------------------------------------}\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_@NAME@\n    // END_@NAME@\n}\n\nBase\n****\nThe type used during the forward mode computations.\n\nRecBase\n*******\nThe type use to record these operations.\nThis is the same as Base except for the :ref:`base2ad-name` case\nwhere Base = AD< RecBase > .\n\nnot_used_rec_base\n*****************\nThis only present so that *RecBase* can be determined without it having\nto be specified as a template parameter in a call.\n\nplay\n****\nThe information stored in play\nis a recording of the operations corresponding to a function\n\n.. math::\n\n    f : \\B{R}^n \\rightarrow \\B{R}^m\n\nwhere *n* is the number of independent variables and\n*m* is the number of dependent variables.\n\nnum_var\n*******\nis the total number of variables on the tape; i.e.,\n*play* ``->num_var()`` .\n\ncap_order\n*********\nIs the maximum number of Taylor coefficients, for each variable,\nthat can fit in *taylor*.\nThis must be greater than or equal one.\n\ncskip_op\n********\nIs a vector with size *play* ``->num_op_rec()`` .\n\norder_low is zero\n=================\nIf *order_low* is zero,\nthe input value of the elements of *cskip_op* does not matter.\nUpon return, if *cskip_op* [ *i* ] is true,\nthe operator with index *i* does not affect any of the dependent variable\n(given the value of the independent variables).\n\norder_low is non-zero\n=====================\nIf *order_low* is non-zero, *cskip_op* is not modified.\nIf the value *cskip_op* [ *i* ] is true,\nthe operator with index *i* does not affect any of the dependent variable\n(given the value of the independent variables).\n\nload_op2var\n***********\nIs a vector with size *play* ``->num_var_load()`` .\n\norder_low is zero\n=================\nIf *order_low* is zero,\nthe input value of the elements of *load_op2var* does not matter.\nUpon return, *load_op2var* [ *i* ]\nis the variable index corresponding to the *i*-th variable VecAD load operator.\nNote that even though the VecAD vector is a variable, the load\ncan correspond to an element that is a parameter in which case\n*load_op2var* [ *i* ] is zero.\n\norder_low is non-zero\n=====================\nIf *order_low* is non-zero, *load_op2var* is not modified.\nThe value *load_op2var* [ *i* ]\nis the variable index corresponding to the *i*-th variable VecAD load operator.\n\n{xrst_comment ----------------------------------------------------------------}\n{xrst_suspend @NAME@ == FORWARD_DIR}\n\nchange_count\n************\nIf *change_count* is non-zero (zero),\nthe comparison changes are counted (not counted).\nFurthermore, if *change_count* is non-zero,\nit is the compare change count value for which *change_op_index* is returned.\n\nchange_number\n*************\nIf *change_count* is zero, this value is set to zero.\nOtherwise, the return value is the number of comparison operations\nthat have a different result from when the information in\n*play* was recorded.\n\nchange_op_index\n***************\nIf *change_count* is zero, this value is set to zero.\nOtherwise it is the operator index (see forward_next) for the\ncomparison operation that has a different result from when the information in\nplay was recorded.\nThis is not the first comparison that is different,\nbut rather the *change_count* comparison.\n\ns_out\n*****\nIs the stream where output corresponding to\n{xrst_spell_off}\nPriOp\n{xrst_spell_on}\noperations is written.\n\nprint\n*****\nIf print is false,\nsuppress the output that is otherwise generated by the\n{xrst_spell_off}\nPriOp\n{xrst_spell_on}\ninstructions.\n\n{xrst_resume}\n{xrst_comment ----------------------------------------------------------------}\n{xrst_suspend @NAME@ != FORWARD_0}\n\ntaylor\n******\nThe vector *taylor* has size *num_var* * *cap_order* .\nWe use *n* to denote the number of independent variables.\n\nInput\n=====\n::\n\n    for j = 1 , ... , n\n        taylor [ j * cap_order + 0 ] is an input\n\nOutput\n======\n::\n\n    for j = n  + 1 , ... , num_var - 1\n        taylor [ j * cap_order + 0 ] is an output\n\n{xrst_resume}\n{xrst_comment ----------------------------------------------------------------}\n{xrst_suspend @NAME@ != FORWARD_ANY}\n\norder_low\n*********\nis the lowest order of the Taylor coefficients that are computed by this call.\n\norder_up\n********\nis the highest order of the Taylor coefficients that are computed by this call.\n\ntaylor\n******\nThe vector *taylor* has size *num_var* * *cap_order* .\nWe use *n* to denote the number of independent variables.\n\nInput\n=====\n::\n\n    for j = 1 , ... , num_var - 1\n        for k = 0 , ... , order_low - 1\n            taylor [ j * cap_order + k ] is an input\n\n    for j = 1 , ... , n\n        for k = order_low , ... , order_up\n            taylor [ j * cap_order + k ] is an input\n\n\nOutput\n======\n::\n\n    for j = n + 1 , ... , num_var - 1\n        for k = order_low , ... , order_up\n            taylor [ j * cap_order + k ] is an output\n\n\n{xrst_resume}\n{xrst_comment ----------------------------------------------------------------}\n{xrst_suspend @NAME@ != FORWARD_DIR}\n\norder_up\n********\nis the order of the Taylor coefficients that are computed by this call.\n\nn_dir\n*****\nnumber of directions that we are computing the Taylor coefficient for.\n\ntaylor\n******\nWe use *n* to denote the number of independent variables.\n\nper_variable\n============\nFor each variable there is one Taylor coefficient of order zero\nand *n_dir* coefficients for orders greater than zero.\nThe taylor coefficients capacity per variable is::\n\n    per_variable = (cap_order - 1) * n_dir + 1\n\nThe vector *taylor* has size *num_var* * *per_variable* .\n\n(j, k, ell)\n===========\nFor variable index j, order k, and direction index ell::\n\n    if k == 0\n        (j, k, ell) = j * per_variable\n    else\n        (j, k, ell) = j * per_variable + (k-1) * n_dir + 1 + ell\n\nThe value taylor[ (j, k, ell) ] is the\nTaylor coefficient corresponding to\nthe variable with index j, the order k, and the direction with index ell.\n\nn_dir = 1\n=========\nIf *n_dir* is equal to one then *ell* is zero and::\n\n    (j, k, ell) = j * cap_order + k\n\nInput\n=====\n::\n\n    for j = 1, ..., n\n        for k = 0 , ... , order_up\n            for ell = 0 , ... , n_dir - 1\n                taylor [ (j, k, ell) ] is an input\n\n    for j = n + 1, ..., num_var - 1\n        for k = 0 , ... , order_up - 1\n            for ell = 0 , ... , n_dir - 1\n                taylor [ (j, k, ell) ] is an input\n\nOutput\n======\n::\n\n    for j = n + 1, ..., num_var - 1\n        for ell = 0 , ... , n_dir - 1\n            taylor [ (j, order_up, ell) ] is an output\n\n{xrst_resume}\n{xrst_comment ----------------------------------------------------------------}\n"
  },
  {
    "path": "include/cppad/local/temp_file.hpp",
    "content": "# ifndef CPPAD_LOCAL_TEMP_FILE_HPP\n# define CPPAD_LOCAL_TEMP_FILE_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <string>\n# include <iostream>\n\nnamespace CppAD { namespace local {\n    std::string temp_file(void);\n} }\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/utility/cppad_vector_itr.hpp",
    "content": "# ifndef CPPAD_LOCAL_UTILITY_CPPAD_VECTOR_ITR_HPP\n# define CPPAD_LOCAL_UTILITY_CPPAD_VECTOR_ITR_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cstddef>\n# include <cppad/core/cppad_assert.hpp>\n/*\n------------------------------------------------------------------------------\n{xrst_begin cppad_vector_itr_define dev}\n{xrst_spell\n    undef\n}\n\nVector Class Iterator Preprocessor Definitions\n##############################################\n\nSyntax\n******\n{xrst_code cpp}\n# define CPPAD_CONST 0\n# include <cppad/local/utility/cppad_vector_itr.hpp>\n# undef CPPAD_LOCAL_UTILITY_CPPAD_VECTOR_ITR_HPP\n# define CPPAD_CONST 1\n# include <cppad/local/utility/cppad_vector_itr.hpp>\n{xrst_code}\n\nBeginning of cppad_vector_itr.hpp\n*********************************\nThe following preprocessor definition appears at the beginning of\n``cppad_vector_itr.hpp`` and is used for the class definition in this file:\n::\n\n    # if CPPAD_CONST\n    # define CPPAD_VECTOR_ITR const_cppad_vector_itr\n    # else\n    # define CPPAD_VECTOR_ITR cppad_vector_itr\n    # endif\n\nEnd of cppad_vector_itr.hpp\n***************************\nThe following preprocessor definition appears at the end of\n``cppad_vector_itr.hpp`` so that it can be included with a different\nvalue for ``CPPAD_CONST`` :\n::\n\n    # undef CPPAD_CONST\n    # undef CPPAD_VECTOR_ITR\n\n{xrst_end cppad_vector_itr_define}\n*/\n# if CPPAD_CONST\n# define CPPAD_VECTOR_ITR const_cppad_vector_itr\n# else\n# define CPPAD_VECTOR_ITR cppad_vector_itr\n# endif\n\n\n// BEGIN_CPPAD_LOCAL_UTILITY_NAMESPACE\nnamespace CppAD { namespace local { namespace utility {\n\n// const_cppad_vector_itr\n// declare here can be make it a friend in cppad_vector_itr<Type>\ntemplate <class Type> class const_cppad_vector_itr;\n\n// ==========================================================================\ntemplate <class Type> class CPPAD_VECTOR_ITR {\n// ==========================================================================\n/*\n-----------------------------------------------------------------------------\n{xrst_begin cppad_vector_itr_traits dev}\n\nVector Class Iterator Traits and Friends\n########################################\n\n{xrst_spell_off}\n{xrst_code hpp} */\n# if ! CPPAD_CONST\n    friend class const_cppad_vector_itr<Type>;\n# endif\npublic:\n    typedef std::random_access_iterator_tag    iterator_category;\n    typedef Type                               value_type;\n    typedef std::ptrdiff_t                     difference_type;\n    typedef Type*                              pointer;\n    typedef Type&                              reference;\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end cppad_vector_itr_traits}\n-------------------------------------------------------------------------------\n{xrst_begin cppad_vector_itr_ctor dev}\n\nVector Class Iterator Member Data and Constructors\n##################################################\n\nConstructors\n************\n\nConstant\n========\n\n| ``const_cppad_vector_itr`` *itr* ()\n| ``const_cppad_vector_itr`` *itr* ( *data* , *length* , *index* )\n| ``const_cppad_vector_itr`` *itr* ( *other* )\n| ``const_cppad_vector_itr`` *itr* ( *non_const_other* )\n\nNot Constant\n============\n\n| ``cppad_vector_itr`` *itr* ()\n| ``cppad_vector_itr`` *itr* ( *data* , *length* , *index* )\n| ``cppad_vector_itr`` *itr* ( *other* )\n\nNamespace\n*********\nThese definitions are in the ``CppAD::local::utility`` namespace.\n\nIndirection\n***********\nWe use an extra level of indirection in this routine so that\nthe iterator has the same values as the vector even if the vector changes.\n\ndata\\_\n******\nis a pointer to a constant pointer to data for this vector\n(used by operations that are not supported by constant iterators).\n\nlength\\_\n********\nis a pointer to the length of the corresponding vector.\n\nindex\\_\n*******\nis the current vector index corresponding to this iterator.\n\ncheck_element\n*************\ngenerates an assert with a known cause when the ``index_``\ndoes not correspond go a valid element and\n``NDEBUG`` is not defined.\n\ncheck_cop\n*********\nGenerates an assert with a known cause when the ``data_``\nfor this vector is different from the other vector and\n``NDEBUG`` is not defined.\nThis should be used by operators that compare iterators.\n\nSource\n******\n{xrst_spell_off}\n{xrst_code hpp} */\nprivate:\n# if CPPAD_CONST\n    const Type* const* data_;\n# else\n    Type* const*       data_;\n# endif\n    const size_t*      length_;\n    difference_type    index_;\n    void check_element(void) const CPPAD_NDEBUG_NOEXCEPT\n    {  CPPAD_ASSERT_KNOWN( 0 <= index_ && size_t(index_) < *length_,\n            \"CppAD vector iterator: accessing element out of range\"\n        );\n    }\n    void check_cop(const CPPAD_VECTOR_ITR& other) const CPPAD_NDEBUG_NOEXCEPT\n    {  CPPAD_ASSERT_KNOWN( data_ == other.data_,\n            \"CppAD vector iterator: comparing indices from different vectors\"\n        );\n    }\npublic:\n    CPPAD_VECTOR_ITR(void) noexcept\n    : data_(nullptr), length_(nullptr), index_(0)\n    { }\n# if CPPAD_CONST\n    // ctor\n    const_cppad_vector_itr(\n        const Type* const* data, const size_t* length, difference_type index\n    ) noexcept\n    : data_(data), length_(length), index_( difference_type(index) )\n    { }\n    // ctor a const_iterator from an iterator. Here is were we need\n    //  const_cppad_vector_itr to be friend of cppad_vector_itr\n    const_cppad_vector_itr(\n        const cppad_vector_itr<Type>& non_const_other\n    ) noexcept\n    {  data_       = non_const_other.data_;\n        length_     = non_const_other.length_;\n        index_      = non_const_other.index_;\n    }\n# else\n    // ctor\n    cppad_vector_itr(\n        Type* const* data, const size_t* length, difference_type index\n    ) noexcept\n    : data_(data), length_(length), index_( difference_type(index) )\n    { }\n# endif\n    void operator=(const CPPAD_VECTOR_ITR& other) noexcept\n    {  data_       = other.data_;\n        length_     = other.length_;\n        index_      = other.index_;\n    }\n    CPPAD_VECTOR_ITR(const CPPAD_VECTOR_ITR& other) noexcept\n    {  *this = other; }\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end cppad_vector_itr_ctor}\n-------------------------------------------------------------------------------\n{xrst_begin cppad_vector_itr_inc dev}\n\nVector Class Iterator Increment Operators\n#########################################\n\nSyntax\n******\n\n| ++ *itr*\n| ``--`` *itr*\n| *itr* ++\n| *itr* ``--``\n\nSource\n******\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    CPPAD_VECTOR_ITR& operator++(void) noexcept\n    {  ++index_;\n        return *this;\n    }\n    CPPAD_VECTOR_ITR& operator--(void) noexcept\n    {  --index_;\n        return *this;\n    }\n    CPPAD_VECTOR_ITR operator++(int) noexcept\n    {  CPPAD_VECTOR_ITR ret(*this);\n        ++index_;\n        return ret;\n    }\n    CPPAD_VECTOR_ITR operator--(int) noexcept\n    {  CPPAD_VECTOR_ITR ret(*this);\n        --index_;\n        return ret;\n    }\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end cppad_vector_itr_inc}\n-------------------------------------------------------------------------------\n{xrst_begin cppad_vector_itr_equal dev}\n\nVector Class Iterator Equality Operators\n########################################\n\nSyntax\n******\n\n| *itr* == *other*\n| *itr* != *other*\n\nRestrictions\n************\nIt is an error to compare iterators corresponding to different\n``data_`` vectors\n\nSource\n******\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    bool operator==(const CPPAD_VECTOR_ITR& other) const CPPAD_NDEBUG_NOEXCEPT\n    {  check_cop(other);\n        return index_ == other.index_;\n    }\n    bool operator!=(const CPPAD_VECTOR_ITR& other) const CPPAD_NDEBUG_NOEXCEPT\n    {  check_cop(other);\n        return index_ != other.index_;\n    }\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end cppad_vector_itr_equal}\n-------------------------------------------------------------------------------\n{xrst_begin cppad_vector_itr_element dev}\n\nVector Class Iterator Access Elements\n#####################################\n\nSyntax\n******\n\n| *element* = * *itr*\n| * *itr* = *element*\n| *element* = *itr* [ *n* ]\n| *itr* [ *n* ] = *element*\n\nSource\n******\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n# if CPPAD_CONST\n    const Type& operator*(void) const\n    {  check_element();\n        return (*data_)[index_];\n    }\n    const Type& operator[](difference_type n) const\n    {  return *(*this + n);\n    }\n    const Type& operator[](size_t n) const\n    {  return *( *this + difference_type(n) );\n    }\n# else\n    Type& operator*(void) const\n    {  check_element();\n        return (*data_)[index_];\n    }\n    Type& operator[](difference_type n) const\n    {  return *(*this + n);\n    }\n    Type& operator[](size_t n) const\n    {  return *( *this + difference_type(n) );\n    }\n# endif\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end cppad_vector_itr_element}\n-------------------------------------------------------------------------------\n{xrst_begin cppad_vector_itr_random dev}\n\nVector Class Iterator Random Access\n###################################\n\nSyntax\n******\n\n| *itr* + *-* = *n*\n| *itr* = *other* + *-* *n*\n| *itr* = *n* + *-* *other*\n| *n* = *itr* ``-`` *other*\n| *b* = *itr* *cop* *other*\n\nPlus or Minus\n*************\nThe notation + *-* above is either ``+`` or ``-`` .\n\ncop\n***\nis one of the following:\n``<`` , ``<=`` ,\n``>`` , ``>=`` .\n\nitr, other\n**********\nare iterators of the same type.\n\nn\n*\nis a ``difference_type`` object.\n\nb\n*\nis a ``bool`` .\n\nRestrictions\n************\nIt is an error to use a *cop* with iterators corresponding to different\n``data_`` vectors\n\nSource\n******\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    // sum and difference operators\n    CPPAD_VECTOR_ITR& operator+=(difference_type n) noexcept\n    {  index_ += n;\n        return *this;\n    }\n    CPPAD_VECTOR_ITR& operator-=(difference_type n) noexcept\n    {  index_ -= n;\n        return *this;\n    }\n    CPPAD_VECTOR_ITR operator+(difference_type n) const noexcept\n    {  return CPPAD_VECTOR_ITR(data_, length_, index_ + n);\n    }\n    CPPAD_VECTOR_ITR operator-(difference_type n) const noexcept\n    {  return CPPAD_VECTOR_ITR(data_, length_, index_ - n);\n    }\n    difference_type  operator-(const CPPAD_VECTOR_ITR& other) const\n    noexcept\n    {  return index_ - other.index_;\n    }\n    // comparison operators\n    bool operator<(const CPPAD_VECTOR_ITR& other) const CPPAD_NDEBUG_NOEXCEPT\n    {  check_cop(other);\n        return index_ < other.index_;\n    }\n    bool operator<=(const CPPAD_VECTOR_ITR& other) const CPPAD_NDEBUG_NOEXCEPT\n    {  check_cop(other);\n        return index_ <= other.index_;\n    }\n    bool operator>(const CPPAD_VECTOR_ITR& other) const CPPAD_NDEBUG_NOEXCEPT\n    {  check_cop(other);\n        return index_ > other.index_;\n    }\n    bool operator>=(const CPPAD_VECTOR_ITR& other) const CPPAD_NDEBUG_NOEXCEPT\n    {  check_cop(other);\n        return index_ >= other.index_;\n    }\n/* {xrst_code}\n{xrst_spell_on}\n{xrst_literal\n    // BEGIN_BINARY_OP\n    // END_BINARY_OP\n}\n\n{xrst_end cppad_vector_itr_random}\n*/\n// ==========================================================================\n}; // END_TEMPLATE_CLASS_CPPAD_VECTOR_ITR\n// ==========================================================================\n\n// BEGIN_BINARY_OP\ntemplate <class Type> CPPAD_VECTOR_ITR<Type> operator+(\n    typename CPPAD_VECTOR_ITR<Type>::difference_type n  ,\n    const CPPAD_VECTOR_ITR<Type>&               other   ) noexcept\n{   return other + n;\n}\n// END_BINARY_OP\n\n} } } // END_CPPAD_LOCAL_UTILITY_NAMESPACE\n\n# undef CPPAD_CONST\n# undef CPPAD_VECTOR_ITR\n# endif\n"
  },
  {
    "path": "include/cppad/local/utility/vector_bool.hpp",
    "content": "# ifndef CPPAD_LOCAL_UTILITY_VECTOR_BOOL_HPP\n# define CPPAD_LOCAL_UTILITY_VECTOR_BOOL_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cstddef>\n\n// BEGIN_CPPAD_LOCAL_UTILITY_NAMESPACE\nnamespace CppAD { namespace local { namespace utility {\n/*\n{xrst_begin vector_bool_element dev}\n\nvectorBoolElement Class\n#######################\n\nSyntax\n******\n| ``local::utility::vectorBoolElement`` *element* ( *unit* , *mask* )\n| ``local::utility::vectorBoolElement`` *element* ( *other* )\n| *value* = *element*\n| *element* = *value*\n| *element* = *element*\n\nunit_t\n******\nType used to pack multiple boolean (bit) values into one unit.\nLogical operations are preformed one unit at a time.\n\nunit\\_\n******\npointer to the unit that holds the value for this element.\n\nmask\\_\n******\nmask for the bit corresponding to this element; i.e., all the bits\nare zero except for bit that corresponds to this element which is one.\n\nvalue\n*****\nis a ``bool`` .\n\nSource\n******\n{xrst_spell_off}\n{xrst_code hpp} */\nclass vectorBoolElement {\nprivate:\n    typedef size_t unit_t;\n    unit_t* unit_;\n    unit_t  mask_;\npublic:\n    vectorBoolElement(unit_t* unit, unit_t mask )\n    : unit_(unit) , mask_(mask)\n    { }\n    vectorBoolElement(const vectorBoolElement& other)\n    : unit_(other.unit_) , mask_(other.mask_)\n    { }\n    operator bool() const\n    {  return (*unit_ & mask_) != 0; }\n    vectorBoolElement& operator=(bool value)\n    {  if(value) *unit_ |= mask_;\n        else      *unit_ &= ~mask_;\n        return *this;\n    }\n    vectorBoolElement& operator=(const vectorBoolElement& element)\n    {  if( *(element.unit_) & element.mask_ ) *unit_ |= mask_;\n        else                                   *unit_ &= ~mask_;\n        return *this;\n    }\n};\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end vector_bool_element}\n*/\n} } } // END_CPPAD_LOCAL_UTILITY_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/local/val_graph/base_op.hpp",
    "content": "# ifndef  CPPAD_LOCAL_VAL_GRAPH_BASE_OP_HPP\n# define  CPPAD_LOCAL_VAL_GRAPH_BASE_OP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2023-23 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/local/val_graph/val_type.hpp>\n# include <cstdio>\nnamespace CppAD { namespace local { namespace val_graph {\n/*\n{xrst_begin val_base_op dev}\n\nThe Value Operator Base Class\n#############################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_BASE_OP_T\n    // END_BASE_OP_T\n}\n\nPurpose\n*******\nThis section describes the value operator base class\n(all the value operators are derived from this class).\n\nMember Variables\n****************\nNone of the value operators have any member variables,\nso their functions are like static functions but cannot be declared as\nsuch because they are virtual or override functions.\n\nValue\n*****\nThis template parameter is the type used for each element of the\n:ref:`val_graph@Value Vector` .\n\nbase_op\n*******\nThis is the base class used for operators.\nAll of its functions are public and pure virtual; i.e.,\nthey all must be defined in order for a derived class object to be used.\n\nop_enum\n*******\nThis member function returns the enum value corresponding to this operator;\nsee :ref:`val_graph_type@op_enum_t` .\n{xrst_literal\n    // BEGIN_OP_ENUM\n    // END_OP_ENUM\n}\n\nn_before\n********\nThis member function returns the number of auxiliary arguments\nthat come before the arguments that are value vector indices.\n{xrst_literal\n    // BEGIN_N_BEFORE\n    // END_N_BEFORE\n}\n\nn_after\n*******\nThis member function returns the number of auxiliary arguments\nthat come after the arguments that are value vector indices.\nThis can only be zero or one.\n{xrst_literal\n    // BEGIN_N_AFTER\n    // END_N_AFTER\n}\n\n\nn_arg\n*****\nThis member function returns the number of arguments for this operator.\n{xrst_literal\n    // BEGIN_N_ARG\n    // END_N_ARG\n}\n\nFixed\n=====\nIf *n_after* returns zero, this operator has a fixed number of arguments.\nIn this case, the *arg_index* and *arg_vec* arguments to this function.\nYou can set *arg_index* to\n*arg_vec*.size() (an invalid value) if you know this is not a call operator.\n\nVariable\n========\nIf *n_after* returns one, this operator has a variable number of arguments.\nIn this case the last argument is an auxiliary argument and is\nequal to the number of arguments for this use of this operator.\n\nn_res\n*****\nThis member function returns the number of results for this operator.\n{xrst_literal\n    // BEGIN_N_RES\n    // END_N_RES\n}\n\neval\n****\nThe values in *val_vec* with index less than *res_index*\nare inputs to this member function.\nThe *n_res* values starting at *res_index* in *val_vec* are\ncomputed by this function.\n{xrst_literal\n    // BEGIN_EVAL\n    // END_EVAL\n}\n\ntape\n====\nThis is a pointer to the tape that the operator is being evaluated for.\nWe use arg_vec to denote tape->arg_vec() below.\n\ntrace\n=====\nif this is true (false) the operator is (is not) printed\nat the end of the eval operation.\n\nind_vec_vec\n===========\nThe size of this vector is equal to the number of dynamic vectors.\nThe size of each element of this vector is equal to the size of the\ncorresponding dynamic vector.\nIf there are no dynamic vectors in the tape this argument must\nbe empty (or not present).\nThis argument is only used by the :ref:`val_vector_op-name` operations.\n\ncompare_false\n=============\nThis is the number of :ref:`val_comp_op-name` that had a false\nresult for their comparisons.\nThis is both an input and output; i.e., each false comparison\nwill add one to this value.\n\nname\n****\nis a short name, 5 or less characters, for this operator.\n\narg_index\n*********\nis the index in *arg_vec* where the *n_arg* arguments to this function start.\n\nres_index\n*********\nis the index in *val_vec* where the results for this operator start.\n\nval_vec\n*******\nis the entire :ref:`val_graph@Value Vector` .\n\narg_vec\n*******\nDuring  the eval function, arg_vec below denotes tape->arg_vec() .\n\nUnary Operators\n===============\nIf this operator is a unary operator\n\n#. arg_vec[arg_index + 0] < res_index\n#. val_vec[ arg_vec[ arg_index + 0 ] ] is the operand\n#. val_vec[ res_index] is the result computed by eval\n\nBinary Operators\n================\nIf this operator is a binary operator\n\n#. arg_vec[arg_index + 0] < res_index\n#. arg_vec[arg_index + 1] < res_index\n#. val_vec[ arg_vec[ arg_index + 1 ] ] is the left operand\n#. val_vec[ arg_vec[ arg_index + 2 ] ] is the right operand\n#. val_vec[ res_index] is the result computed by eval\n\nis_unary\n********\nis true (false) if this is (is not) a unary operator;\nsee :ref:`val_unary_op-name`.\n{xrst_literal\n    // BEGIN_IS_UNARY\n    // END_IS_UNARY\n}\n\nis_binary\n*********\nis true (false) if this is (is not) a binary operator;\nsee :ref:`val_binary_op-name`.\n{xrst_literal\n    // BEGIN_IS_BINARY\n    // END_IS_BINARY\n}\n\n\nOperator Classes\n****************\n{xrst_comment BEGIN_SORT_THIS_LINE_PLUS_2}\n{xrst_toc_table\n    include/cppad/local/val_graph/binary_op.hpp\n    include/cppad/local/val_graph/call_op.hpp\n    include/cppad/local/val_graph/cexp_op.hpp\n    include/cppad/local/val_graph/comp_op.hpp\n    include/cppad/local/val_graph/con_op.hpp\n    include/cppad/local/val_graph/csum_op.hpp\n    include/cppad/local/val_graph/dis_op.hpp\n    include/cppad/local/val_graph/pri_op.hpp\n    include/cppad/local/val_graph/unary_op.hpp\n    include/cppad/local/val_graph/vector_op.hpp\n}\n{xrst_comment END_SORT_THIS_LINE_MINUS_2}\n\n{xrst_end val_base_op}\n*/\n//\n// tape_t\ntemplate<class Value> class tape_t;\n\n// BEGIN_BASE_OP_T\ntemplate <class Value> class base_op_t {\npublic:\n// END_BASE_OP_T\n    // BEGIN_OP_ENUM\n    virtual op_enum_t op_enum(void)  const = 0;\n    // END_OP_ENUM\n    //\n    // BEGIN_N_BEFORE\n    virtual addr_t    n_before(void) const = 0;\n    // END_N_BEFORE\n    //\n    // BEGIN_N_AFTER\n    virtual addr_t    n_after(void)  const = 0;\n    // END_N_AFTER\n    //\n    // BEGIN_N_ARG\n    virtual addr_t n_arg(\n        addr_t                arg_index    ,\n        const Vector<addr_t>& arg_vec      ) const = 0;\n    // END_N_ARG\n    //\n    // BEGIN_N_RES\n    virtual addr_t n_res(\n        addr_t                arg_index    ,\n        const Vector<addr_t>& arg_vec      ) const = 0;\n    // END_N_RES\n    //\n    // BEGIN_EVAL\n    virtual void eval(\n        const tape_t<Value>*       tape          ,\n        bool                       trace         ,\n        addr_t                     arg_index     ,\n        addr_t                     res_index     ,\n        Vector<Value>&             val_vec       ,\n        Vector< Vector<addr_t> >&  ind_vec_vec   ,\n        size_t&                    compare_false ) const = 0;\n    // END_EVAL\n    //\n    // BEGIN_IS_UNARY\n    virtual bool is_unary(void) const\n    // END_IS_UNARY\n    {   return false; }\n    //\n    // BEGIN_IS_BINARY\n    virtual bool is_binary(void) const\n    // END_IS_BINARY\n    {   return false; }\n};\n\n} } } // END_CPPAD_LOCAL_VAL_GRAPH_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/val_graph/binary_op.hpp",
    "content": "# ifndef  CPPAD_LOCAL_VAL_GRAPH_BINARY_OP_HPP\n# define  CPPAD_LOCAL_VAL_GRAPH_BINARY_OP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2023-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/local/val_graph/base_op.hpp>\n# include <cppad/local/val_graph/print_op.hpp>\n# include <cppad/base_require.hpp>\n\nnamespace CppAD { namespace local { namespace val_graph {\n\n# define CPPAD_VAL_GRAPH_BINARY(Name, Op) \\\n    template <class Value> \\\n    class Name##_op_t : public binary_op_t<Value> { \\\n    public: \\\n        /* get_instance */ \\\n        static Name##_op_t* get_instance(void) \\\n        {   CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL; \\\n            static Name##_op_t instance; \\\n            return &instance; \\\n        } \\\n        /* op_enum */ \\\n        op_enum_t op_enum(void) const override \\\n        {   return Name##_op_enum;  \\\n        } \\\n        /* eval */ \\\n        void eval( \\\n            const tape_t<Value>*      tape          , \\\n            bool                      trace         , \\\n            addr_t                    arg_index     , \\\n            addr_t                    res_index     , \\\n            Vector<Value>&            val_vec       , \\\n            Vector< Vector<addr_t> >& ind_vec_vec   , \\\n            size_t&                   compare_false ) const override \\\n        {   const Vector<addr_t>& arg_vec( tape->arg_vec() ); \\\n            const Value& left   = val_vec[ arg_vec[arg_index + 0] ]; \\\n            const Value& right  = val_vec[ arg_vec[arg_index + 1] ]; \\\n            val_vec[res_index]  = left Op right; \\\n            if( trace ) this->print_op( \\\n                #Name , arg_index, tape->arg_vec(), res_index, val_vec \\\n            ); \\\n        } \\\n    }\n\n/*\n------------------------------------------------------------------------------\n{xrst_begin_parent val_binary_op dev}\n\nBinary Value Operators\n######################\n\n{xrst_end val_binary_op}\n------------------------------------------------------------------------------\n{xrst_begin val_binary_base_op dev}\n\nThe Value Operator Binary Class\n###############################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_BINARY_OP_T\n    // END_BINARY_OP_T\n}\n\nPurpose\n*******\nThe class is derived from :ref:`base_op <val_base_op-name>`.\nIt overrides the\n*is_binary*, *n_before*, *n_after*, *n_arg*, *n_res_*, and *print_op*\nmember functions.\nThe *op_enum* and *eval* member functions are still pure virtual.\n\nis_binary\n*********\nThis override of :ref:`val_base_op@is_binary` returns true.\n\nn_before\n********\nThis override of :ref:`val_base_op@n_before` returns 0.\n\nn_after\n*******\nThis override of :ref:`val_base_op@n_after` returns 0.\n\nn_arg\n*****\nThis override of :ref:`val_base_op@n_arg` returns 2.\n\nn_res\n*****\nThis override of :ref:`val_base_op@n_res` returns 1.\n\nprint_op\n********\n{xrst_literal\n    // BEGIN_PRINT_OP\n    // END_PRINT_OP\n}\nThis member function uses :ref:`val_print_op-name`\nto print binary operators.\n\n{xrst_end val_binary_base_op}\n*/\n\n// BEGIN_BINARY_OP_T\ntemplate <class Value>\nclass binary_op_t : public base_op_t<Value> {\n// END_BINARY_OP_T\npublic:\n    // n_before\n    addr_t n_before(void) const override\n    {   return 0; }\n    //\n    // n_after\n    addr_t n_after(void) const override\n    {   return 0; }\n    //\n    // is_binary\n    bool is_binary(void) const override\n    {   return true; }\n    //\n    // n_arg\n    addr_t n_arg(\n        addr_t                arg_index    ,\n        const Vector<addr_t>& arg_vec      ) const override\n    {   return 2; }\n    //\n    // n_res\n    addr_t n_res(\n        addr_t                arg_index    ,\n        const Vector<addr_t>& arg_vec      ) const override\n    {   return 1; }\n    //\n    // op_enum\n    virtual op_enum_t op_enum(void) const override = 0;\n    //\n    // eval\n    virtual void eval(\n        const tape_t<Value>*      tape          ,\n        bool                      trace         ,\n        addr_t                    arg_index     ,\n        addr_t                    res_index     ,\n        Vector<Value>&            val_vec       ,\n        Vector< Vector<addr_t> >& ind_vec_vec   ,\n        size_t&                   compare_false ) const override = 0;\n    //\n    // BEGIN_PRINT_OP\n    void print_op(\n        const char*           name         ,\n        addr_t                arg_index    ,\n        const Vector<addr_t>& arg_vec      ,\n        addr_t                res_index    ,\n        Vector<Value>&        val_vec      ) const\n    // END_PRINT_OP\n    {   //\n        addr_t left_index            = arg_vec[ arg_index + 0 ];\n        addr_t right_index           = arg_vec[ arg_index + 1 ];\n        Vector<addr_t> arg_val_index = { left_index, right_index };\n        Vector<Value>  res_value     = { val_vec[res_index] };\n        CppAD::local::val_graph::print_op(\n            name, arg_val_index, res_index, res_value\n        );\n    }\n};\n/*\n------------------------------------------------------------------------------\n{xrst_begin val_binary_op_derived dev}\n\nThe Binary Value Operator Derived Classes\n#########################################\n\nPrototype\n*********\n| |tab| ``template <class Value>``\n| |tab| ``class`` *Name*\\ ``_opt_t : public binary_op_t<Value>``\n\n*Name*\n******\nUnary operators are defined for the following names:\n\n.. csv-table:: Unary Operators\n    :widths: auto\n    :header-rows: 1\n\n    Name,description\n    add,result is the sum of the two operands\n    sub,result is the first operand minus the second\n\nContext\n*******\nThis class is derived from :ref:`val_binary_op-name` .\nIt overrides the *op_enum* and *eval* member functions\nand is a concrete class (it has no pure virtual functions).\n\nget_instance\n************\nThis static member function returns a pointer to a\n*Name*\\ ``_op_t`` object.\n\nop_enum\n*******\nThis override of :ref:`val_base_op@op_enum` returns\n*Name*\\ ``_op_enum`` .\n\neval\n****\nThis override of :ref:`val_base_op@eval` sets\nthe result equal to the binary operator applied to the operands; see\n:ref:`val_base_op@arg_vec@Unary Operators` .\n\n\n{xrst_toc_hidden\n    val_graph/binary_xam.cpp\n}\nExample\n*******\nThe file :ref:`binary_xam.cpp <val_binary_xam.cpp-name>`\nis an example and test that uses a binary operator.\n\n{xrst_end val_binary_op_derived}\n*/\nCPPAD_VAL_GRAPH_BINARY(add, +);\nCPPAD_VAL_GRAPH_BINARY(sub, -);\nCPPAD_VAL_GRAPH_BINARY(mul, *);\nCPPAD_VAL_GRAPH_BINARY(div, /);\n\ntemplate <class Value>\nclass pow_op_t : public binary_op_t<Value> {\npublic:\n    /* get_instance */\n    static pow_op_t* get_instance(void)\n    {   CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL;\n        static pow_op_t instance;\n        return &instance;\n    }\n    /* op_enum */\n    op_enum_t op_enum(void) const override\n    {   return pow_op_enum;\n    }\n    /* eval */\n    void eval(\n        const tape_t<Value>*      tape          ,\n        bool                      trace         ,\n        addr_t                    arg_index     ,\n        addr_t                    res_index     ,\n        Vector<Value>&            val_vec       ,\n        Vector< Vector<addr_t> >& ind_vec_vec   ,\n        size_t&                   compare_false ) const override\n    {   const Vector<addr_t>& arg_vec( tape->arg_vec() );\n        const Value& left   = val_vec[ arg_vec[arg_index + 0] ];\n        const Value& right  = val_vec[ arg_vec[arg_index + 1] ];\n        // Only the line directly below is different from\n        // CPPAD_VAL_GRAPH_BINARY(pow, pow)\n        val_vec[res_index]  = pow(left, right);\n        if( trace ) this->print_op(\n            \"pow\", arg_index, tape->arg_vec(), res_index, val_vec\n        );\n    }\n};\n\n} } } // END_CPPAD_LOCAL_VAL_GRAPH_NAMESPACE\n\n# undef CPPAD_VAL_GRAPH_BINARY\n# endif\n"
  },
  {
    "path": "include/cppad/local/val_graph/call_atomic.hpp",
    "content": "# ifndef CPPAD_LOCAL_VAL_GRAPH_CALL_ATOMIC_HPP\n# define CPPAD_LOCAL_VAL_GRAPH_CALL_ATOMIC_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-23 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/local/atomic_index.hpp>\n# include <cppad/core/atomic/two/atomic.hpp>\n# include <cppad/core/atomic/three/atomic.hpp>\n# include <cppad/core/atomic/four/atomic.hpp>\nnamespace CppAD { namespace local { namespace val_graph {\n/*\nThis is similar to the routines in cppad/local/sweep/call_atomic.hpp,\nbut it is used by val_graph instead of the sweeps.\n*/\n/*\n{xrst_begin atomic_for_type_callback dev}\n\nForward Type Callback to Atomic Functions\n#########################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_FORWARD\n    // END_FORWARD\n}\n\nValue\n*****\nis the base type corresponding to the atomic function.\n\nCppAD::vector\n*************\nthis routine uses the CppAD::vector template class\n(and not CppAD::local::val_graph::Vector) because atomic functions expect\nCppAD::vector.\n\nconstant_x\n**********\ncontains the values, in afun(ax, ay), for arguments that are constants.\n\ntype_x\n******\nwhat is the type, in the call, for each component of x.\n\ntype_y\n******\nthe input values in this vector do not matter.\nUpon return it is the type for each component of y.\n\natom_index\n**********\nis the index, in local::atomic_index, corresponding to this atomic function.\n\ncall_id\n*******\nsee the atomic_four :ref:`atomic_four_call@call_id` and\nthe atomic_one :ref:`atomic_one@id` .\n\n{xrst_end atomic_for_type_callback}\n*/\n// BEGIN_FORWARD\ntemplate <class Value>\nvoid call_atomic_for_type(\n    const CppAD::vector<Value>&         constant_x  ,\n    const CppAD::vector<ad_type_enum>&  type_x      ,\n    CppAD::vector<ad_type_enum>&        type_y      ,\n    size_t                              atom_index  ,\n    size_t                              call_id     )\n// END_FORWARD\n{   CPPAD_ASSERT_UNKNOWN( 0 < atom_index );\n    //\n    // type, v_ptr\n    bool         set_null = false;\n    size_t       type     = 0;       // set to avoid warning\n    std::string  name;\n    void*        v_ptr    = nullptr; // set to avoid warning\n    local::atomic_index<Value>(set_null, atom_index, type, &name, v_ptr);\n//\n# ifndef NDEBUG\n    bool ok = v_ptr != nullptr;\n    if( ok )\n    {\n        if( type == 2 )\n        {   size_t p = 0, q = 0, nx = type_x.size(), ny = type_y.size();\n            CppAD::vector<bool> vx(nx), vy(ny);\n            for(size_t i = 0; i < nx; ++i)\n                vx[i] = type_x[i] > constant_enum;\n            const CppAD::vector<Value>& taylor_x = constant_x;\n            CppAD::vector<Value> taylor_y(ny);\n            atomic_base<Value>* afun =\n                reinterpret_cast< atomic_base<Value>* >(v_ptr);\n            afun->set_old(call_id);\n            ok = afun->forward(\n                p, q, vx, vy, taylor_x, taylor_y\n            );\n            for(size_t i = 0; i < ny; ++i)\n            {   if( vy[i] )\n                    type_y[i] = variable_enum;\n                else\n                    type_y[i] = constant_enum;\n            }\n        }\n        else if( type == 3 )\n        {   CPPAD_ASSERT_UNKNOWN( type == 3 );\n            atomic_three<Value>* afun =\n                reinterpret_cast< atomic_three<Value>* >(v_ptr);\n            ok = afun->for_type(constant_x, type_x, type_y );\n        }\n        else\n        {   CPPAD_ASSERT_UNKNOWN( type == 4 );\n            atomic_four<Value>* afun =\n                reinterpret_cast< atomic_four<Value>* >(v_ptr);\n            ok = afun->for_type(call_id, type_x, type_y);\n        }\n    }\n    if( ! ok )\n    {   // now take the extra time to copy the name\n        std::string msg = name;\n        if( v_ptr == nullptr )\n            msg += \": this atomic function has been deleted\";\n        else\n            msg += \": atomic for_type returned false\";\n        CPPAD_ASSERT_KNOWN(false, msg.c_str() );\n    }\n# else\n    if( type == 2 )\n    {   size_t p = 0, q = 0, nx = type_x.size(), ny = type_y.size();\n        CppAD::vector<bool> vx(nx), vy(ny);\n        for(size_t i = 0; i < nx; ++i)\n            vx[i] = type_x[i] > constant_enum;\n        const CppAD::vector<Value>& taylor_x = constant_x;\n        CppAD::vector<Value> taylor_y(ny);\n        atomic_base<Value>* afun =\n            reinterpret_cast< atomic_base<Value>* >(v_ptr);\n        afun->set_old(call_id);\n        afun->forward(\n            p, q, vx, vy, taylor_x, taylor_y\n        );\n        for(size_t i = 0; i < ny; ++i)\n        {   if( vy[i] )\n                type_y[i] = variable_enum;\n            else\n                type_y[i] = constant_enum;\n        }\n    }\n    else if( type == 3 )\n    {   CPPAD_ASSERT_UNKNOWN( type == 3 );\n        atomic_three<Value>* afun =\n            reinterpret_cast< atomic_three<Value>* >(v_ptr);\n        afun->for_type(constant_x, type_x, type_y );\n    }\n    else\n    {   CPPAD_ASSERT_UNKNOWN( type == 4 );\n        atomic_four<Value>* afun =\n            reinterpret_cast< atomic_four<Value>* >(v_ptr);\n        afun->for_type(call_id, type_x, type_y);\n    }\n# endif\n}\n\n} } } // END_CPPAD_LOCAL_VAL_GRAPH_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/val_graph/call_op.hpp",
    "content": "# ifndef  CPPAD_LOCAL_VAL_GRAPH_CALL_OP_HPP\n# define  CPPAD_LOCAL_VAL_GRAPH_CALL_OP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2023-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cstdio>\n# include <cppad/local/val_graph/base_op.hpp>\n# include <cppad/local/atomic_index.hpp>\n# include <cppad/core/atomic/four/atomic.hpp>\n# include <cppad/local/sweep/call_atomic.hpp>\n# include <cppad/local/val_graph/print_op.hpp>\n\n// define CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL\n# include <cppad/utility/thread_alloc.hpp>\n\nnamespace CppAD { namespace local { namespace val_graph {\n/*\n{xrst_begin val_call_op dev}\n\nThe Call Value Operator\n#######################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_CALL_OP_T\n    // END_CALL_OP_T\n}\n\nContext\n*******\nThe class is derived from :ref:`val_base_op-name` .\nIt overrides all its base class virtual member functions\nand is a concrete class (it has no pure virtual functions).\n\nget_instance\n************\nThis static member function returns a pointer to a call_op_t object.\n\nop_enum\n*******\nThis override of :ref:`val_base_op@op_enum` returns ``call_op_enum`` .\n\nn_before\n********\nThis override of :ref:`val_base_op@n_before` returns 4.\n{xrst_literal\n    // BEGIN_ARG_BEFORE\n    // END_ARG_BEFORE\n}\n\nn_after\n*******\nThis override of :ref:`val_base_op@n_after` returns 1.\nThis is for a second copy of *n_arg* that can be used to iterate\nthrough the operators in reverse.\n\nn_arg\n*****\nsee base_op :ref:`val_base_op@n_arg` .\n\nn_res\n*****\nsee base_op :ref:`val_base_op@n_res` .\n\natomic_index\n************\nThis member function returns the *atomic_index* for the mapping; see\n:ref:`atomic_index@index_out` in the case where *index_in* is zero.\n\ncall_id\n*******\nThis member function returns the *call_id* for this use of the mapping; see\n:ref:`atomic_four_call@call_id` .\n\neval\n****\nThis override of :ref:`val_base_op@eval` makes the atomic function call\nidentified by *atomic_index* , with the *call_id*,\nto evaluate *n_res* results given *n_arg* - 4 arguments.\n\n#. The arguments for the function call are\n   ::\n\n        val_vec[ arg_vec[ arg_index + 4 ] ] ,\n        val_vec[ arg_vec[ arg_index + 5 ] ] ,\n        ...\n        val_vec[ arg_vec[ arg_index + n_arg - 1 ] ]\n\n#. The results of the function call are placed in\n   ::\n\n        val_vec[res_index + 0] ,\n        val_vec[res_index + 1] ,\n        ...\n        val_vec[res_index + n_res - 1]\n\ntrace\n=====\nIf trace is true, :ref:`val_print_op-name` is called to print this operator.\n\n{xrst_toc_hidden\n    val_graph/call_xam.cpp\n}\nExample\n*******\nThe file :ref:`call_xam.cpp <val_call_xam.cpp-name>`\nis an example and test that uses this operator.\n\n{xrst_end val_call_op}\n*/\n// BEGIN_CALL_OP_T\ntemplate <class Value>\nclass call_op_t : public base_op_t<Value> {\npublic:\n    // n_before\n    addr_t n_before(void) const override\n    {   return 4; }\n    //\n    // n_after\n    addr_t n_after(void) const override\n    {   return 1; }\n    //\n    // get_instance\n    static call_op_t* get_instance(void)\n    {   CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL;\n        static call_op_t instance;\n        return &instance;\n    }\n    // op_enum\n    // type of this operator\n    op_enum_t op_enum(void) const override\n    {   return call_op_enum; }\n    //\n    // n_arg\n    addr_t n_arg(\n        addr_t                arg_index    ,\n        const Vector<addr_t>& arg_vec      ) const override\n    {   return arg_vec[arg_index + 0]; }\n    //\n    // n_res\n    addr_t n_res(\n        addr_t                arg_index    ,\n        const Vector<addr_t>& arg_vec      ) const override\n    {   return arg_vec[arg_index + 1]; }\n    //\n    // atomic_index\n    size_t atomic_index(\n        addr_t                arg_index    ,\n        const Vector<addr_t>& arg_vec      )\n    {   return size_t( arg_vec[arg_index + 2] ); }\n    //\n    // call_id\n    size_t call_id(\n        addr_t                arg_index    ,\n        const Vector<addr_t>& arg_vec      )\n    {   return size_t( arg_vec[arg_index + 3] ); }\n    //\n    // eval\n    void eval(\n        const tape_t<Value>*      tape          ,\n        bool                      trace         ,\n        addr_t                    arg_index     ,\n        addr_t                    res_index     ,\n        Vector<Value>&            val_vec       ,\n        Vector< Vector<addr_t> >& ind_vec_vec   ,\n        size_t&                   compare_false\n     ) const override;\n// END_CALL_OP_T\n};\n//\n// eval\ntemplate <class Value>\nvoid call_op_t<Value>::eval(\n    const tape_t<Value>*      tape          ,\n    bool                      trace         ,\n    addr_t                    arg_index     ,\n    addr_t                    res_index     ,\n    Vector<Value>&            val_vec       ,\n    Vector< Vector<addr_t> >& ind_vec_vec   ,\n    size_t&                   compare_false ) const\n{   //\n    // arg_vec\n    const Vector<addr_t>& arg_vec( tape->arg_vec() );\n    //\n    // n_arg, n_res, atomic_index, call_id\n    // BEGIN_ARG_BEFORE\n    addr_t n_arg         =  arg_vec[arg_index + 0] ;\n    addr_t n_res         =  arg_vec[arg_index + 1] ;\n    size_t atomic_index  = size_t( arg_vec[arg_index + 2] );\n    size_t call_id       = size_t( arg_vec[arg_index + 3] );\n    CPPAD_ASSERT_UNKNOWN( atomic_index != 0 );\n    // END_ARG_BEFORE\n    //\n    // n_x\n    addr_t n_x = n_arg - n_before() - n_after();\n    //\n    // x\n    CppAD::vector<Value> x(n_x);\n    for(addr_t i = 0; i < n_x; ++i)\n        x[i] = val_vec[ arg_vec[arg_index + n_before() + i] ];\n    //\n    // type_x\n    CppAD::vector<ad_type_enum> type_x(n_x);\n    for(addr_t i = 0; i < n_x; ++i)\n        type_x[i] = variable_enum;\n    //\n    // need_y\n    size_t need_y = size_t( number_ad_type_enum );\n    //\n    // order_low, order_up\n    size_t order_low = 0, order_up = 0;\n    //\n    // select_y\n    CppAD::vector<bool> select_y(n_res);\n    for(addr_t i = 0; i < n_res; ++i)\n        select_y[i] = true;\n    //\n    // y\n    CppAD::vector<Value> y(n_res);\n    local::sweep::call_atomic_forward<Value,Value>(\n        x, type_x, need_y, select_y, order_low, order_up,\n        atomic_index, call_id, x, y\n    );\n    //\n    // val_vec\n    for(addr_t i = 0; i < n_res; ++i)\n        val_vec[res_index + i] = y[i];\n    //\n    // trace\n    if( ! trace )\n        return;\n    //\n    // v_ptr, name\n    bool         set_null = false;\n    size_t       type     = 0;       // result: set to avoid warning\n    std::string  name;               // result:\n    void*        v_ptr    = nullptr; // result: set to avoid warning\n    local::atomic_index<Value>(set_null, atomic_index, type, &name, v_ptr);\n    //\n    Vector<addr_t> arg_val_index(n_x);\n    for(addr_t i = 0; i < n_x; ++i)\n        arg_val_index[i] = arg_vec[arg_index + n_before() + i];\n    //\n    Vector<Value> res_value(n_res);\n    for(addr_t i = 0; i < n_res; ++i)\n        res_value[i] = val_vec[res_index + i];\n    //\n    print_op(name, arg_val_index, res_index, res_value);\n    return;\n}\n\n} } } // END_CPPAD_LOCAL_VAL_GRAPH_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/val_graph/cexp_op.hpp",
    "content": "# ifndef  CPPAD_LOCAL_VAL_GRAPH_CEXP_OP_HPP\n# define  CPPAD_LOCAL_VAL_GRAPH_CEXP_OP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2023-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/local/val_graph/base_op.hpp>\n\n// define CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL\n# include <cppad/utility/thread_alloc.hpp>\n\nnamespace CppAD { namespace local { namespace val_graph {\n/*\n{xrst_begin val_cexp_op dev}\n\nThe Conditional Expression Value Operator\n#########################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_CEXP_OP_T\n    // END_CEXP_OP_T\n}\n\nContext\n*******\nThis class computes the result for a\n:ref:`conditional expression <condexp-name>` .\nIt is derived from :ref:`val_base_op-name` .\nIt overrides all its base class virtual member functions\nand is a concrete class (it has no pure virtual functions).\n\nget_instance\n************\nThis static member function returns a pointer to a cexp_op_t object.\n\nop_enum\n*******\nThis override of :ref:`val_base_op@op_enum` returns ``cexp_op_enum`` .\n\nn_before\n********\nThis override of :ref:`val_base_op@n_before` returns 1.\n\nn_after\n*******\nThis override of :ref:`val_base_op@n_after` returns 0.\n\nn_arg\n*****\nThis override of :ref:`val_base_op@n_arg` returns 5.\n\nn_res\n*****\nThis override of :ref:`val_base_op@n_res` returns 1.\n\neval\n****\nThis override of :ref:`val_base_op@eval` .\nIf the comparison is false (true), one (zero) is added to\nthe compare_false argument to eval.\n{xrst_literal\n    // BEGIN_ARGS\n    // END_ARGS\n}\n\ntrace\n=====\nIf trace is true, :ref:`val_print_op-name` is called to print this operator.\n\n{xrst_toc_hidden\n    val_graph/cexp_xam.cpp\n}\nExample\n*******\nThe file :ref:`com_xam.cpp <val_cexp_xam.cpp-name>`\nis an example and test that uses this operator.\n\n{xrst_end val_cexp_op}\n*/\n// BEGIN_CEXP_OP_T\ntemplate <class Value>\nclass cexp_op_t : public base_op_t<Value> {\npublic:\n    // n_before\n    addr_t n_before(void) const override\n    {   return 1; }\n    //\n    // n_after\n    addr_t n_after(void) const override\n    {   return 0; }\n    //\n    // get_instance\n    static cexp_op_t* get_instance(void)\n    {   CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL;\n        static cexp_op_t instance;\n        return &instance;\n    }\n    // op_enum\n    op_enum_t op_enum(void) const override\n    {   return cexp_op_enum; }\n// END_CEXP_OP_T\n    //\n    // n_arg\n    addr_t n_arg(\n        addr_t                arg_index    ,\n        const Vector<addr_t>& arg_vec      ) const override\n    {   return 5; }\n    //\n    // n_res\n    addr_t n_res(\n        addr_t                arg_index    ,\n        const Vector<addr_t>& arg_vec      ) const override\n    {   return 1; }\n    //\n    // eval\n    void eval(\n        const tape_t<Value>*      tape            ,\n        bool                      trace           ,\n        addr_t                    arg_index       ,\n        addr_t                    res_index       ,\n        Vector<Value>&            val_vec         ,\n        Vector< Vector<addr_t> >& ind_vec_vec     ,\n        size_t&                   compare_false   ) const override\n    {   //\n        // arg_vec\n        const Vector<addr_t>& arg_vec( tape->arg_vec() );\n        //\n        // compare_enum, left_index, right_index\n        // BEGIN_ARGS\n        compare_enum_t compare_enum = compare_enum_t( arg_vec[arg_index + 0] );\n        addr_t left_index           = arg_vec[arg_index + 1];\n        addr_t right_index          = arg_vec[arg_index + 2];\n        addr_t if_true_index        = arg_vec[arg_index + 3];\n        addr_t if_false_index       = arg_vec[arg_index + 4];\n        // END_ARGS\n        //\n        // left, right\n        const Value&   left          = val_vec[left_index];\n        const Value&   right         = val_vec[right_index];\n        const Value&   if_true       = val_vec[if_true_index];\n        const Value&   if_false      = val_vec[if_false_index];\n        //\n        // res, name\n        const char* name;\n        switch( compare_enum )\n        {   //\n            // e_eq\n            case compare_eq_enum:\n            val_vec[res_index]  = CondExpEq(left, right, if_true, if_false);\n            name = \"e_eq\";\n            break;\n            //\n            // e_lt\n            case compare_lt_enum:\n            val_vec[res_index]  = CondExpLt(left, right, if_true, if_false);\n            name = \"e_lt\";\n            break;\n            //\n            // e_le\n            case compare_le_enum:\n            val_vec[res_index]  = CondExpLe(left, right, if_true, if_false);\n            name = \"e_le\";\n            break;\n            //\n            default:\n            CPPAD_ASSERT_UNKNOWN(false);\n            val_vec[res_index]  = CppAD::numeric_limits<Value>::quiet_NaN();\n            name = \"\";\n        }\n        //\n        // trace\n        if( ! trace )\n            return;\n        //\n        // print_op\n        Vector<addr_t> arg_val_index(4);\n        for(addr_t i = 0; i < 4; ++i)\n            arg_val_index[i] = arg_vec[arg_index + i + 1];\n        Vector<Value>  res_value = { val_vec[res_index] };\n        print_op(name, arg_val_index, res_index, res_value);\n        //\n        return;\n    }\n};\n\n} } } // END_CPPAD_LOCAL_VAL_GRAPH_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/val_graph/comp_op.hpp",
    "content": "# ifndef  CPPAD_LOCAL_VAL_GRAPH_COMP_OP_HPP\n# define  CPPAD_LOCAL_VAL_GRAPH_COMP_OP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2023-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/local/val_graph/base_op.hpp>\n# include <cppad/local/val_graph/print_op.hpp>\n\n// define CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL\n# include <cppad/utility/thread_alloc.hpp>\n\nnamespace CppAD { namespace local { namespace val_graph {\n/*\n{xrst_begin val_comp_op dev}\n\nThe Compare Value Operator\n##########################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_COMP_OP_T\n    // END_COMP_OP_T\n}\n\nContext\n*******\nThis class checks if the comparison between two values has changed.\nIt is derived from :ref:`val_base_op-name` .\nIt overrides all its base class virtual member functions\nand is a concrete class (it has no pure virtual functions).\n\nget_instance\n************\nThis static member function returns a pointer to a comp_op_t object.\n\nop_enum\n*******\nThis override of :ref:`val_base_op@op_enum` returns ``comp_op_enum`` .\n\nn_before\n********\nThis override of :ref:`val_base_op@n_before` returns 1.\n\nn_after\n*******\nThis override of :ref:`val_base_op@n_after` returns 0.\n\nn_arg\n*****\nThis override of :ref:`val_base_op@n_arg` returns 3.\n\nn_res\n*****\nThis override of :ref:`val_base_op@n_res` returns 1.\n\neval\n****\nThis override of :ref:`val_base_op@eval` .\nIf the comparison is false (true), one (zero) is added to\nthe compare_false argument to eval.\n{xrst_literal\n    // BEGIN_ARGS\n    // END_ARGS\n}\n\ntrace\n=====\nIf trace is true, :ref:`val_print_comp_op-name`\nis called to print this operator.\n\n{xrst_toc_hidden\n    val_graph/comp_xam.cpp\n}\nExample\n*******\nThe file :ref:`com_xam.cpp <val_comp_xam.cpp-name>`\nis an example and test that uses this operator.\n\n{xrst_end val_comp_op}\n*/\n// BEGIN_COMP_OP_T\ntemplate <class Value>\nclass comp_op_t : public base_op_t<Value> {\npublic:\n    // n_before\n    addr_t n_before(void) const override\n    {   return 1; }\n    //\n    // n_after\n    addr_t n_after(void) const override\n    {   return 0; }\n    //\n    // get_instance\n    static comp_op_t* get_instance(void)\n    {   CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL;\n        static comp_op_t instance;\n        return &instance;\n    }\n    // op_enum\n    op_enum_t op_enum(void) const override\n    {   return comp_op_enum; }\n// END_COMP_OP_T\n    //\n    // n_arg\n    addr_t n_arg(\n        addr_t                arg_index    ,\n        const Vector<addr_t>& arg_vec      ) const override\n    {   return 3; }\n    //\n    // n_res\n    addr_t n_res(\n        addr_t                arg_index    ,\n        const Vector<addr_t>& arg_vec      ) const override\n    {   return 0; }\n    //\n    // eval\n    void eval(\n        const tape_t<Value>*      tape            ,\n        bool                      trace           ,\n        addr_t                    arg_index       ,\n        addr_t                    res_index       ,\n        Vector<Value>&            val_vec         ,\n        Vector< Vector<addr_t> >& ind_vec_vec     ,\n        size_t&                   compare_false   ) const override\n    {   //\n        // arg_vec\n        const Vector<addr_t>& arg_vec( tape->arg_vec() );\n        //\n        // compare_enum, left_index, right_index\n        // BEGIN_ARGS\n        compare_enum_t compare_enum = compare_enum_t( arg_vec[arg_index + 0] );\n        addr_t left_index           = arg_vec[arg_index + 1];\n        addr_t right_index          = arg_vec[arg_index + 2];\n        // END_ARGS\n        //\n        // left, right\n        const Value&   left          = val_vec[left_index];\n        const Value&   right         = val_vec[right_index];\n        //\n        // result, comp_name\n        bool result;\n        const char* comp_name;\n        switch( compare_enum )\n        {   //\n            case compare_eq_enum:\n            result    = left == right;\n            comp_name = \"eq\";\n            break;\n            //\n            // ne\n            case compare_ne_enum:\n            result    = left != right;\n            comp_name = \"ne\";\n            break;\n            //\n            // lt\n            case compare_lt_enum:\n            result    = left < right;\n            comp_name = \"lt\";\n            break;\n            //\n            // le\n            case compare_le_enum:\n            result    = left <= right;\n            comp_name = \"le\";\n            break;\n            //\n            // no\n            case compare_no_enum:\n            result    = true;\n            comp_name = \"no\";\n            break;\n            //\n            default:\n            CPPAD_ASSERT_UNKNOWN(false);\n            result    = false; // to avoid compiler warning\n            comp_name = \"\";\n        }\n        //\n        // compare_false\n        if( ! result )\n            ++compare_false;\n        //\n        // trace\n        if( ! trace )\n            return;\n        //\n        // print_comp_op\n        print_comp_op(comp_name, left_index, right_index, result);\n    }\n};\n\n} } } // END_CPPAD_LOCAL_VAL_GRAPH_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/val_graph/compress.hpp",
    "content": "# ifndef  CPPAD_LOCAL_VAL_GRAPH_COMPRESS_HPP\n# define  CPPAD_LOCAL_VAL_GRAPH_COMPRESS_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2023-25 Bradley M. Bell\n// ---------------------------------------------------------------------------\n# include <cppad/local/val_graph/tape.hpp>\n# include <cppad/local/val_graph/op_hash_table.hpp>\n# include <cppad/local/val_graph/rev_depend.hpp>\nnamespace CppAD { namespace local { namespace val_graph {\n/*\n{xrst_begin val_tape_compress dev}\n{xrst_spell\n    dep\n}\n\nTape Compression\n################\nThis is :ref:`val_tape_renumber-name` and :ref:`val_tape_dead_code-name`\nin one step. I should be faster, and require more memory,\nthan separate execution. (Testing with :ref:`cppad_det_minor.cpp-name`\nindicates that it is only slightly faster.)\n\nChanges\n*******\nOnly the following values, for this tape, are guaranteed to be same:\n#. The number of independent values :ref:`val_tape@n_ind` .\n#. The size of the dependent vector :ref:`dep_vec.size() <val_tape@dep_vec>` .\n#. The mapping from the independent to the dependent variables.\n\nkeep_compare\n************\nsee :ref:`val_tape_option@keep_compare` .\nIf *keep_compare* is false, no comparison operators are in the new tape.\nOtherwise, if two or more comparison operators are identical,\nonly the first such operator is in the new tape.\n\nkeep_print\n**********\nsee :ref:`val_tape_option@keep_print` .\nIf *keep_print* is false, no print operators are in the new tape.\nOtherwise, if two or more print operators are identical,\nonly the first such operator is in the new tape.\n\nAlgorithm\n*********\n#. The dependent variables are marked as used.\n#. The operators are scanned in reverse and if an operator's result is\n   used, the corresponding arguments are marked as used.\n   The call operator has a more complicated version of this marking.\n#. A forward pass is made though the operators and only the operators that\n   are used ones are considered.\n#. If an operator is equivalent to a previous operator,\n   the previous operator is used in it's place.\n#. An operators result may have a new index\n   because some previous results were left out.\n   A mapping from the old result indices to the new result indices\n   enables subsequent operators to adjust their argument indices.\n#. After the forward pass, the mapping from old indices to new indices\n   is used to adjust the dependent variable indices.\n\n{xrst_toc_hidden\n    val_graph/compress_xam.cpp\n}\nExample\n*******\nThe file :ref:`compress_xam.cpp <val_compress_xam.cpp-name>` is an\nexample and test of tape.compress().\n\n{xrst_end val_tape_compress}\n*/\n\n// BEGIN_COMPRESS\n// new_use_val = compress()\ntemplate <class Value>\nvectorBool tape_t<Value>::compress(void)\n// END_COMPRESS\n{\n# if CPPAD_VAL_GRAPH_TAPE_TRACE\n    // thread, initial_inuse\n    size_t thread        = thread_alloc::thread_num();\n    size_t initial_inuse = thread_alloc::inuse(thread);\n# endif\n    //\n    // val_use_case, vec_last_load\n    Vector<addr_t> val_use_case, vec_last_load;\n    rev_depend(val_use_case, vec_last_load);\n    //\n    // op2arg_index, op2res_index\n    Vector<addr_t> op2arg_index( n_op() ), op2res_index( n_op() );\n    {   op_iterator<Value> op_itr(*this, 0);\n        for(addr_t i_op = 0; i_op < n_op(); ++i_op)\n        {   op2arg_index[i_op] = op_itr.arg_index();\n            op2res_index[i_op] = op_itr.res_index();\n            ++op_itr;\n        }\n    }\n    //\n    // op_hash_table\n    addr_t n_hash_code = 1 + (n_val_ / 2);\n    op_hash_table_t<Value>  op_hash_table(*this, op2arg_index, n_hash_code);\n    //\n    // keep_compare\n    bool keep_compare = option_map_[\"keep_compare\"] == \"true\";\n    //\n    // keep_print\n    bool keep_print = option_map_[\"keep_print\"] == \"true\";\n    //\n    // new_tape\n    tape_t new_tape;\n    new_tape.set_ind(n_ind_);\n    //\n    // new_which_vec\n    // initialize all dynamic vectors as not used\n    Vector<addr_t> new_which_vec( vec_initial_.size() );\n    for(size_t i = 0; i < vec_initial_.size(); ++i)\n        new_which_vec[i] = addr_t( vec_initial_.size() );\n    //\n    // new_val_index\n    // include nan at index n_ind_ in val_vec\n    Vector<addr_t> new_val_index( n_val_ );\n    for(addr_t i = 0; i <= n_ind_; ++i)\n        new_val_index[i] = addr_t(i);\n    for(addr_t i = n_ind_ + 1; i < n_val_; ++i)\n        new_val_index[i] = addr_t( n_val_ );\n    //\n# ifndef NDEBUG\n    // nan at index n_ind_\n    assert( op_enum_t( new_tape.op_enum_vec_[0] ) == con_op_enum );\n    assert( new_tape.var_arg_[0] == 0 );\n    assert( CppAD::isnan( new_tape.con_vec_[0] ) );\n# endif\n    //\n    // new_use_val\n    // Because the call operator can have more than one result, not all the\n    // results for all the needed operators are used. Initialize as all the\n    // independent values and the nan after them are used.\n    vectorBool new_use_val(n_ind_ + 1);\n    for(addr_t i = 0; i <= n_ind_; ++i)\n        new_use_val[i] = true;\n    //\n    // work\n    Vector<addr_t> work;\n    //\n    //\n    // i_op\n    for(addr_t i_op = 1; i_op < n_op(); ++i_op)\n    {   //\n        // op_ptr\n        const base_op_t<Value>* op_ptr   = base_op_ptr(i_op);\n        //\n        // arg_index_i, res_index_i\n        addr_t arg_index_i = op2arg_index[i_op];\n        addr_t res_index_i = op2res_index[i_op];\n        addr_t n_res        = op_ptr->n_res(arg_index_i, var_arg_);\n        //\n        // use_op\n        bool use_op = false;\n        if( n_res == 0 )\n        {   op_enum_t op_enum = op_ptr->op_enum();\n            if( op_enum == vec_op_enum || op_enum == store_op_enum )\n            {   addr_t which_vector = var_arg_[arg_index_i + 0];\n                use_op              = i_op < vec_last_load[which_vector];\n            }\n            else if( op_enum == pri_op_enum )\n                use_op  = keep_print;\n            else\n            {   CPPAD_ASSERT_UNKNOWN( op_enum == comp_op_enum );\n                use_op  = keep_compare;\n            }\n        }\n        else for(addr_t k = 0; k < n_res; ++k)\n            use_op |= 0 != val_use_case[ res_index_i + k];\n        //\n        if(use_op)\n        {   //\n            // j_op\n            addr_t j_op = op_hash_table.match_op(i_op, new_val_index);\n            //\n            if( j_op != i_op )\n            {   // use j_op every where that i_op was used\n                assert( j_op < i_op );\n                //\n                // new_val_index\n                // mapping so use op_j results in place of op_i results.\n                addr_t res_index_j = op2res_index[j_op];\n                for(addr_t k = 0; k < n_res; ++k)\n                    new_val_index[res_index_i + k] = res_index_j + k;\n            }\n            else\n            {   // record i_op operator on the new tape\n                addr_t new_res_index = record_new(\n                    new_tape        ,\n                    new_which_vec   ,\n                    work            ,\n                    new_val_index   ,\n                    val_use_case    ,\n                    op_ptr          ,\n                    arg_index_i     ,\n                    res_index_i\n                );\n                //\n                // new_val_index\n                for(addr_t k = 0; k < n_res; ++k)\n                    new_val_index[ res_index_i + k ] = new_res_index + k;\n                //\n                // new_use_val\n                for(addr_t k = 0; k < n_res; ++k)\n                {   bool use_val_k = val_use_case[ res_index_i + k ] != 0;\n                    new_use_val.push_back( use_val_k );\n                }\n            }\n        }\n    }\n    //\n    // dep_vec\n    Vector<addr_t> dep_vec( dep_vec_.size() );\n    for(size_t k = 0; k < dep_vec_.size(); ++k)\n        dep_vec[k] = new_val_index[ dep_vec_[k] ];\n    new_tape.set_dep( dep_vec );\n    //\n    // swap\n    swap(new_tape);\n    //\n# if CPPAD_VAL_GRAPH_TAPE_TRACE\n    // inuse\n    size_t final_inuse = thread_alloc::inuse(thread);\n    std::cout << \"dead_code:  inuse = \" << final_inuse - initial_inuse << \"\\n\";\n# endif\n    // BEGIN_RETURN\n    CPPAD_ASSERT_UNKNOWN( size_t( n_val() ) == new_use_val.size() );\n    return new_use_val;\n    // END_RETURN\n}\n} } } // END_CPPAD_LOCAL_VAL_GRAPH_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/local/val_graph/con_op.hpp",
    "content": "# ifndef  CPPAD_LOCAL_VAL_GRAPH_CON_OP_HPP\n# define  CPPAD_LOCAL_VAL_GRAPH_CON_OP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2023-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/local/val_graph/base_op.hpp>\n\n// define CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL\n# include <cppad/utility/thread_alloc.hpp>\n\nnamespace CppAD { namespace local { namespace val_graph {\n/*\n{xrst_begin val_con_op dev}\n\nThe Constant Value Operator\n###########################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_CON_OP_T\n    // END_CON_OP_T\n}\n\nContext\n*******\nThe class is derived from :ref:`val_base_op-name` .\nIt overrides all its base class virtual member functions\nand is a concrete class (it has no pure virtual functions).\nThis is not a unary operator because the operand is in the\nconstant vector and not the value vector.\n\nget_instance\n************\nThis static member function returns a pointer to a con_op_t object.\n\nop_enum\n*******\nThis override of :ref:`val_base_op@op_enum` returns ``con_op_enum`` .\n\nn_before\n********\nThis override of :ref:`val_base_op@n_before` returns 1.\n\nn_after\n*******\nThis override of :ref:`val_base_op@n_after` returns 0.\n\nn_arg\n*****\nThis override of :ref:`val_base_op@n_arg` returns 1.\n\nn_res\n*****\nThis override of :ref:`val_base_op@n_res` returns 1.\n\neval\n****\nThis override of :ref:`val_base_op@eval` sets\nthe result equal to\n::\n\n        con_vec[ arg_vec[ arg_index + 0 ] ]\n\ntrace\n=====\nIf trace is true, :ref:`val_print_con_op-name`\nis called to print this operator.\n\n{xrst_toc_hidden\n    val_graph/con_xam.cpp\n}\nExample\n*******\nThe file :ref:`con_xam.cpp <val_con_xam.cpp-name>`\nis an example and test that uses this operator.\n\n{xrst_end val_con_op}\n*/\n// BEGIN_CON_OP_T\ntemplate <class Value>\nclass con_op_t : public base_op_t<Value> {\npublic:\n    // n_before\n    addr_t n_before(void) const override\n    {   return 1; }\n    //\n    // n_after\n    addr_t n_after(void) const override\n    {   return 0; }\n    // get_instance\n    static con_op_t* get_instance(void)\n    {   CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL;\n        static con_op_t instance;\n        return &instance;\n    }\n    // op_enum\n    op_enum_t op_enum(void) const override\n    {   return con_op_enum; }\n// END_CON_OP_T\n    //\n    // n_arg\n    addr_t n_arg(\n        addr_t                arg_index    ,\n        const Vector<addr_t>& arg_vec      ) const override\n    {   return 1; }\n    //\n    // n_res\n    addr_t n_res(\n        addr_t                arg_index    ,\n        const Vector<addr_t>& arg_vec      ) const override\n    {   return 1; }\n    //\n    // eval\n    void eval(\n        const tape_t<Value>*      tape          ,\n        bool                      trace         ,\n        addr_t                    arg_index     ,\n        addr_t                    res_index     ,\n        Vector<Value>&            val_vec       ,\n        Vector< Vector<addr_t> >& ind_vec_vec   ,\n        size_t&                   compare_false ) const override\n    {   //\n        // arg_vec, con_vec\n        const Vector<addr_t>& arg_vec( tape->arg_vec() );\n        const Vector<Value>&  con_vec( tape->con_vec() );\n        //\n        // val_index, val_vec\n        addr_t val_index    = arg_vec[ arg_index + 0 ];\n        val_vec[res_index]  = con_vec[ val_index ];\n        //\n        // trace\n        if( ! trace )\n            return;\n        //\n        // print_con_op\n        Vector<addr_t> arg = { arg_vec[ arg_index + 0 ] };\n        Vector<Value> res_value = { val_vec[res_index] };\n        print_con_op(arg, res_index, res_value);\n    }\n};\n\n} } } // END_CPPAD_LOCAL_VAL_GRAPH_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/val_graph/csum_op.hpp",
    "content": "# ifndef  CPPAD_LOCAL_VAL_GRAPH_CSUM_OP_HPP\n# define  CPPAD_LOCAL_VAL_GRAPH_CSUM_OP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2023-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cstdio>\n# include <cppad/local/val_graph/base_op.hpp>\n# include <cppad/local/atomic_index.hpp>\n# include <cppad/core/atomic/four/atomic.hpp>\n# include <cppad/local/sweep/call_atomic.hpp>\n# include <cppad/local/val_graph/print_op.hpp>\n\n// define CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL\n# include <cppad/utility/thread_alloc.hpp>\n\nnamespace CppAD { namespace local { namespace val_graph {\n/*\n{xrst_begin val_csum_op dev}\n\nThe Cumulative Summation Value Operator\n#######################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_CSUM_OP_T\n    // END_CSUM_OP_T\n}\n\nContext\n*******\nThe class is derived from :ref:`val_base_op-name` .\nIt overrides all its base class virtual member functions\nand is a concrete class (it has no pure virtual functions).\n\nget_instance\n************\nThis static member function returns a pointer to a csum_op_t object.\n\nop_enum\n*******\nThis override of :ref:`val_base_op@op_enum` returns ``csum_op_enum`` .\n\nn_before\n********\nThis override of :ref:`val_base_op@n_before` returns 2.\n{xrst_literal\n    // BEGIN_ARG_BEFORE\n    // END_ARG_BEFORE\n}\n\nn_after\n*******\nThis override of :ref:`val_base_op@n_after` returns 1.\nThis is for a copy of *n_arg* that can be used to iterate\nthrough the operators in reverse.\n\nn_res\n*****\nThis override of :ref:`val_base_op@n_res` returns 1.\n\nn_arg\n*****\nsee base_op :ref:`val_base_op@n_arg` .\n\nn_add\n*****\nThis member function returns the number of additions in the summation.\n\nn_sub\n*****\nThis member function returns the number of subtractions in the summation.\n\neval\n****\nThis override of :ref:`val_base_op@eval` computes the summation.\n\n#. The additions in the summation are\n   ::\n\n        val_vec[ arg_vec[ arg_index + 2 ] ] ,\n        val_vec[ arg_vec[ arg_index + 3 ] ] ,\n        ...\n        val_vec[ arg_vec[ arg_index + 1 + n_add ] ]\n\n#. The subtractions in the summation are\n   ::\n\n        val_vec[ arg_vec[ arg_index + 2 + n_add ] ] ,\n        val_vec[ arg_vec[ arg_index + 3 + n_add ] ] ,\n        ...\n        val_vec[ arg_vec[ arg_index + 1 + n_add + n_sub ] ]\n\ntrace\n=====\nIf trace is true, :ref:`val_print_csum_op-name`\nis called to print this operator.\n\n{xrst_toc_hidden\n    val_graph/csum_xam.cpp\n}\nExample\n*******\nThe file :ref:`csum_xam.cpp <val_csum_xam.cpp-name>`\nis an example and test that uses this operator.\n\n{xrst_end val_csum_op}\n*/\n// BEGIN_CSUM_OP_T\ntemplate <class Value>\nclass csum_op_t : public base_op_t<Value> {\npublic:\n    // n_before\n    addr_t n_before(void) const override\n    {   return 2; }\n    //\n    // n_after\n    addr_t n_after(void) const override\n    {   return 1; }\n    //\n    // get_instance\n    static csum_op_t* get_instance(void)\n    {   CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL;\n        static csum_op_t instance;\n        return &instance;\n    }\n    // op_enum\n    // type of this operator\n    op_enum_t op_enum(void) const override\n    {   return csum_op_enum; }\n    //\n    // n_arg\n    addr_t n_arg(\n        addr_t                arg_index    ,\n        const Vector<addr_t>& arg_vec      ) const override\n    {   addr_t n_add = arg_vec[arg_index + 0];\n        addr_t n_sub = arg_vec[arg_index + 1];\n        return 3 + n_add + n_sub;\n    }\n    //\n    // n_res\n    addr_t n_res(\n        addr_t                arg_index    ,\n        const Vector<addr_t>& arg_vec      ) const override\n    {   return 1; }\n    //\n    // n_add\n    addr_t n_add(\n        addr_t                arg_index    ,\n        const Vector<addr_t>& arg_vec      ) const\n    {   return size_t( arg_vec[arg_index + 0] ); }\n    //\n    // n_sub\n    addr_t n_sub(\n        addr_t                arg_index    ,\n        const Vector<addr_t>& arg_vec      ) const\n    {   return size_t( arg_vec[arg_index + 1] ); }\n    //\n    // eval\n    void eval(\n        const tape_t<Value>*      tape          ,\n        bool                      trace         ,\n        addr_t                    arg_index     ,\n        addr_t                    res_index     ,\n        Vector<Value>&            val_vec       ,\n        Vector< Vector<addr_t> >& ind_vec_vec   ,\n        size_t&                   compare_false\n     ) const override;\n// END_CSUM_OP_T\n};\n//\n// eval\ntemplate <class Value>\nvoid csum_op_t<Value>::eval(\n    const tape_t<Value>*      tape          ,\n    bool                      trace         ,\n    addr_t                    arg_index     ,\n    addr_t                    res_index     ,\n    Vector<Value>&            val_vec       ,\n    Vector< Vector<addr_t> >& ind_vec_vec   ,\n    size_t&                   compare_false ) const\n{   //\n    // arg_vec\n    const Vector<addr_t>& arg_vec( tape->arg_vec() );\n    //\n    // n_add, n_sub\n    // BEGIN_ARG_BEFORE\n    addr_t n_add         =  arg_vec[arg_index + 0] ;\n    addr_t n_sub         =  arg_vec[arg_index + 1] ;\n    // END_ARG_BEFORE\n    //\n    // sum\n    Value sum(0.0);\n    for(addr_t i = 0; i < n_add; ++i)\n        sum += val_vec[ arg_vec[arg_index + 2 + i] ];\n    for(addr_t i = 0; i < n_sub; ++i)\n        sum -= val_vec[ arg_vec[arg_index + 2 + n_add + i] ];\n    //\n    // val_vec\n    val_vec[res_index] = sum;\n    //\n    // trace\n    if( ! trace )\n        return;\n    //\n    // print_csum_op\n    Vector<addr_t> arg(3 + n_add + n_sub);\n    for(addr_t i = 0; i < addr_t( arg.size() ); ++i)\n        arg[i] = arg_vec[ arg_index + i ];\n    Vector<Value> res_value = { val_vec[res_index] };\n    print_csum_op(arg, res_index, res_value );\n    //\n    return;\n}\n\n} } } // END_CPPAD_LOCAL_VAL_GRAPH_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/val_graph/cumulative.hpp",
    "content": "# ifndef  CPPAD_LOCAL_VAL_GRAPH_CUMULATIVE_HPP\n# define  CPPAD_LOCAL_VAL_GRAPH_CUMULATIVE_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2023-25 Bradley M. Bell\n// ---------------------------------------------------------------------------\n# include <cppad/local/val_graph/tape.hpp>\nnamespace CppAD { namespace local { namespace val_graph {\n/*\n{xrst_begin val_op2csum dev}\n{xrst_spell\n    neg\n}\n\nConvert Add, Subtract, or Negative to Cumulative Summation\n##########################################################\nThese are ideas under construction for a better way to combine\ncumulative summation operators; i.e., an alternative to the summation.hpp file.\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_OP2CSUM\n    // END_OP2CSUM\n}\n\nReplacement Operator\n********************\nThis will replace an addition, subtraction, or negative value operator\nwith an equivalent cumulative summation operator.\n\nop_index\n********\nIs the operator index in this tape for the operator that is being replaced.\nOn input it must correspond to an\nadd_op_enum, sub_op_enum, or neg_op_enum value operator.\nUpon return it will correspond to a csum_op_enum operator.\n\n{xrst_toc_hidden\n    val_graph/cumulative_xam.cpp\n}\nExample\n*******\nsee :ref:`val_cumulative_xam-name` .\n\n{xrst_end val_op2csum}\n*/\n// BEGIN_OP2CSUM\ntemplate <class Value>\nvoid tape_t<Value>::op2csum(addr_t op_index)\n// END_OP2CSUM\n{\n    // op2arg_index_\n    CPPAD_ASSERT_UNKNOWN( op2arg_index_.size() == size_t( n_op() ) );\n    //\n    // arg_index\n    addr_t arg_index = op2arg_index_[op_index];\n    //\n    // op_ptr\n    const base_op_t< Value>* op_ptr = base_op_ptr(op_index);\n    //\n    // op_enum\n    op_enum_t op_enum = op_ptr->op_enum();\n    //\n    // n_add, n_sub\n    addr_t n_add = 0;\n    addr_t n_sub = 0;\n    //\n    // n_add, n_sub\n    switch( op_enum )\n    {   //\n        default :\n        // op_enum is not add_op, sub_op, or neg_op\n        CPPAD_ASSERT_UNKNOWN( false );\n        break;\n\n        // add_op_enum\n        case add_op_enum:\n        n_add = 2;\n        break;\n\n        // sub_op_enum\n        case sub_op_enum:\n        n_add = 1;\n        n_sub = 1;\n        break;\n\n        // neg_op_enum\n        case neg_op_enum:\n        n_add = 0;\n        n_sub = 1;\n        break;\n    }\n    //\n    // op_enum_vec_\n    op_enum_vec_[op_index] = uint8_t( csum_op_enum );\n    //\n    // op2arg_index_\n    op2arg_index_[op_index] = addr_t( var_arg_.size() );\n    //\n    // var_arg_\n    var_arg_.push_back( n_add );\n    var_arg_.push_back( n_sub );\n    for(addr_t i = 0; i < n_add + n_sub; ++i)\n    {   addr_t arg_i = var_arg_[arg_index + i];\n        var_arg_.push_back( arg_i );\n    }\n    //\n    // var_arg_\n    addr_t n_arg = 3 + n_add + n_sub;\n    var_arg_.push_back( n_arg );\n    //\n    return;\n}\n\n} } } // END_CPPAD_LOCAL_VAL_GRAPH_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/local/val_graph/dead_code.hpp",
    "content": "# ifndef  CPPAD_LOCAL_VAL_GRAPH_DEAD_CODE_HPP\n# define  CPPAD_LOCAL_VAL_GRAPH_DEAD_CODE_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2023-25 Bradley M. Bell\n// ---------------------------------------------------------------------------\n# include <cppad/local/val_graph/tape.hpp>\n# include <cppad/local/val_graph/rev_depend.hpp>\nnamespace CppAD { namespace local { namespace val_graph {\n/*\n{xrst_begin val_tape_dead_code dev}\n{xrst_spell\n    comp\n    dep\n}\n\nDead Code Elimination\n#####################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_DEAD_CODE\n    // END_DEAD_CODE\n}\n\nkeep_compare\n************\nsee :ref:`val_tape_option@keep_compare`:\n\n#. If this is false, all the :ref`val_comp_op-name` operators will be removed.\n   In this case future calls to eval will not modify\n   :ref:`val_tape@eval@compare_false` .\n#. If this is true, the compare_no_enum compare operators are removed and\n   other comparisons are kept.\n\nkeep_print\n**********\nsee :ref:`val_tape_option@keep_print`:\n\n\nAlgorithm\n*********\n#. The dependent variables are marked as needed.\n#. The operators are scanned in reverse and if an operator's result is\n   needed, the corresponding arguments are marked as needed.\n   The call operator has a more complicated version of this marking.\n#. A forward pass is made though the operators and only the needed\n   ones are included.\n#. An operators result may have a new index\n   because some previous results were left out.\n   A mapping from the old result indices to the new result indices\n   enables subsequent operators to adjust their argument indices.\n#. After the forward pass, the mapping from old indices to new indices\n   is used to adjust the dependent variable indices.\n\n\nChanges\n*******\nOnly the following values, for this tape, are guaranteed to be same:\n#. The number of independent values :ref:`val_tape@n_ind` .\n#. The size of the dependent vector :ref:`dep_vec.size() <val_tape@dep_vec>` .\n#. The mapping from the independent to the dependent variables.\n\nnew_use_val\n***********\nThe i-th element of the return vector *new_use_val* is true (false),\nif and only if\nthe i-th element of the value vector is used to compute the dependent values.\nThere are two exceptions to this rule. One exception is that all the independent\nvalues are marked as used no matter what.\nThe other exception is that the nan, after the independent variables,\nis also marked as used no matter what.\nIf *new_use_val*\\ [i] is false, the i-th value must be the result of a\ncall operator. In addition, at least one result for each call will\nhave a corresponding *new_use_val* of true.\n\nReference\n*********\n`dead-code elimination <https://en.wikipedia.org/wiki/Dead-code_elimination>`_\n\n{xrst_toc_hidden\n    val_graph/dead_xam.cpp\n}\nExample\n*******\nThe file :ref:`dead_xam.cpp <val_dead_xam.cpp-name>` is an\nexample and test of tape.dead_code().\n\n{xrst_end val_tape_dead_code}\n*/\n// BEGIN_DEAD_CODE\n// new_use_val = dead_code()\ntemplate <class Value>\nvectorBool tape_t<Value>::dead_code(void)\n// END_DEAD_CODE\n{   // -----------------------------------------------------------------------\n    // Dead Code Elimination\n    // https://en.wikipedia.org/wiki/Dead-code_elimination\n    // -----------------------------------------------------------------------\n# if CPPAD_VAL_GRAPH_TAPE_TRACE\n    // thread, initial_inuse\n    size_t thread        = thread_alloc::thread_num();\n    size_t initial_inuse = thread_alloc::inuse(thread);\n# endif\n    //\n    // keep_compare\n    bool keep_compare = option_map_[\"keep_compare\"] == \"true\";\n    //\n    // keep_print\n    bool keep_print = option_map_[\"keep_print\"] == \"true\";\n    //\n    // val_use_case, vec_last_load\n    Vector<addr_t> val_use_case, vec_last_load;\n    rev_depend(val_use_case, vec_last_load);\n    //\n    // new_tape\n    tape_t new_tape;\n    new_tape.set_ind(n_ind_);\n    //\n    // new_which_vec\n    // initialize all dynamic vectors as not used\n    Vector<addr_t> new_which_vec( vec_initial_.size() );\n    for(size_t i = 0; i < vec_initial_.size(); ++i)\n        new_which_vec[i] = addr_t( vec_initial_.size() );\n    //\n    // new_val_index\n    // include nan at index n_ind_ in val_vec\n    Vector<addr_t> new_val_index( n_val_ );\n    for(addr_t i = 0; i <= n_ind_; ++i)\n        new_val_index[i] = addr_t(i);\n    for(addr_t i = n_ind_ + 1; i < n_val_; ++i)\n        new_val_index[i] = addr_t( n_val_ );\n    //\n# ifndef NDEBUG\n    // nan at index n_ind_\n    assert( op_enum_t( new_tape.op_enum_vec_[0] ) == con_op_enum );\n    assert( new_tape.var_arg_[0] == 0 );\n    assert( CppAD::isnan( new_tape.con_vec_[0] ) );\n# endif\n    //\n    // new_use_val\n    // Because the call operator can have more than one result, not all the\n    // results for all the needed operators are used. Initialize as all the\n    // independent values and the nan after them are used.\n    vectorBool new_use_val(n_ind_ + 1);\n    for(addr_t i = 0; i <= n_ind_; ++i)\n        new_use_val[i] = true;\n    //\n    // work\n    Vector<addr_t> work;\n    //\n    // op_itr_forward\n    op_iterator<Value> op_itr_forward(*this, 0);\n    //\n    // i_op\n    for(addr_t i_op = 1; i_op < n_op(); ++i_op)\n    {   //\n        // op_itr_forward\n        ++op_itr_forward; // skip index zero\n        //\n        // op_ptr, arg_index, res_index\n        const base_op_t<Value>* op_ptr    = op_itr_forward.op_ptr();\n        addr_t                  res_index = op_itr_forward.res_index();\n        addr_t                  arg_index = op_itr_forward.arg_index();\n        //\n        // op_enum, n_res\n        op_enum_t  op_enum   = op_ptr->op_enum();\n        addr_t     n_res     = op_ptr->n_res(arg_index, var_arg_);\n        //\n        // need_op\n        bool need_op = false;\n        if( n_res == 0 )\n        {   if( op_enum == vec_op_enum || op_enum == store_op_enum )\n            {   addr_t which_vector = var_arg_[arg_index + 0];\n                need_op             = i_op < vec_last_load[which_vector];\n            }\n            else if( op_enum == pri_op_enum )\n            {   need_op  = keep_print;\n                need_op &= var_arg_[arg_index + 2] != this->n_ind();\n            }\n            else\n            {   CPPAD_ASSERT_UNKNOWN( op_enum == comp_op_enum );\n                need_op  = keep_compare;\n                need_op &= var_arg_[arg_index + 0] != addr_t(compare_no_enum);\n            }\n        }\n        else for(addr_t k = 0; k < n_res; ++k)\n            need_op |= 0 != val_use_case[ res_index + k];\n        //\n        if( need_op )\n        {   addr_t new_res_index = record_new(\n                new_tape        ,\n                new_which_vec   ,\n                work            ,\n                new_val_index   ,\n                val_use_case    ,\n                op_ptr          ,\n                arg_index       ,\n                res_index\n            );\n            //\n            // new_val_index\n            for(addr_t k = 0; k < n_res; ++k)\n                new_val_index[ res_index + k ] = new_res_index + k;\n            //\n            // new_use_val\n            for(addr_t k = 0; k < n_res; ++k)\n            {   bool use_val_k = val_use_case[ res_index + k ] != 0;\n                new_use_val.push_back( use_val_k );\n            }\n        }\n    }\n    //\n    // dep_vec\n    Vector<addr_t> dep_vec( dep_vec_.size() );\n    for(size_t k = 0; k < dep_vec_.size(); ++k)\n        dep_vec[k] = new_val_index[ dep_vec_[k] ];\n    new_tape.set_dep( dep_vec );\n    //\n    // swap\n    swap(new_tape);\n    //\n# if CPPAD_VAL_GRAPH_TAPE_TRACE\n    // inuse\n    size_t final_inuse = thread_alloc::inuse(thread);\n    std::cout << \"dead_code:  inuse = \" << final_inuse - initial_inuse << \"\\n\";\n# endif\n    // BEGIN_RETURN\n    CPPAD_ASSERT_UNKNOWN( size_t( n_val() ) == new_use_val.size() );\n    return new_use_val;\n    // END_RETURN\n}\n\n} } } // END_CPPAD_LOCAL_VAL_GRAPH_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/val_graph/dis_op.hpp",
    "content": "# ifndef  CPPAD_LOCAL_VAL_GRAPH_DIS_OP_HPP\n# define  CPPAD_LOCAL_VAL_GRAPH_DIS_OP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2023-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/local/val_graph/base_op.hpp>\n# include <cppad/local/val_graph/print_op.hpp>\n# include <cppad/core/discrete/discrete.hpp>\n\n// define CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL\n# include <cppad/utility/thread_alloc.hpp>\n\nnamespace CppAD { namespace local { namespace val_graph {\n/*\n{xrst_begin val_dis_op dev}\n\nThe Discrete Value Operator\n###########################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_DIS_OP_T\n    // END_DIS_OP_T\n}\n\nContext\n*******\nThe class is derived from :ref:`val_base_op-name` .\nIt overrides all its base class virtual member functions\nand is a concrete class (it has no pure virtual functions).\n\nget_instance\n************\nThis static member function returns a pointer to a dis_op_t object.\n\nop_enum\n*******\nThis override of :ref:`val_base_op@op_enum` returns ``dis_op_enum`` .\n\nn_before\n********\nThis override of :ref:`val_base_op@n_before` returns 1.\n{xrst_literal\n    // BEGIN_ARG_BEFORE\n    // END_ARG_BEFORE\n}\n\nn_after\n*******\nThis override of :ref:`val_base_op@n_after` returns 0.\n\nn_arg\n*****\nThis override of :ref:`val_base_op@n_arg` returns 2.\n\nn_res\n*****\nThis override of :ref:`val_base_op@n_res` returns 1.\n\neval\n****\nThis override of :ref:`val_base_op@eval` sets\nthe result equal to the discrete function evaluated at\n::\n\n        val_vec[ arg_vec[ arg_index + 1 ] ]\n\ntrace\n=====\nIf trace is true, :ref:`val_print_op-name` is called to print this operator.\n\n{xrst_toc_hidden\n    val_graph/dis_xam.cpp\n}\nExample\n*******\nThe file :ref:`dis_xam.cpp <val_dis_xam.cpp-name>`\nis an example and test that uses this operator.\n\n{xrst_end val_dis_op}\n*/\n// BEGIN_DIS_OP_T\ntemplate <class Value>\nclass dis_op_t : public base_op_t<Value> {\npublic:\n    // n_before\n    addr_t n_before(void) const override\n    {   return 1; }\n    //\n    // n_after\n    addr_t n_after(void) const override\n    {   return 0; }\n    //\n    // get_instance\n    static dis_op_t* get_instance(void)\n    {   CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL;\n        static dis_op_t instance;\n        return &instance;\n    }\n    // op_enum\n    op_enum_t op_enum(void) const override\n    {   return dis_op_enum; }\n    //\n    // discrete_index\n    size_t discrete_index(\n        addr_t                arg_index    ,\n        const Vector<addr_t>& arg_vec      )\n    {   return size_t( arg_vec[arg_index + 0] ); }\n// END_DIS_OP_T\n    //\n    // n_arg\n    addr_t n_arg(\n        addr_t                arg_index    ,\n        const Vector<addr_t>& arg_vec      ) const override\n    {   return 2; }\n    //\n    // n_res\n    addr_t n_res(\n        addr_t                arg_index    ,\n        const Vector<addr_t>& arg_vec      ) const override\n    {   return 1; }\n    //\n    // eval\n    void eval(\n        const tape_t<Value>*      tape          ,\n        bool                      trace         ,\n        addr_t                    arg_index     ,\n        addr_t                    res_index     ,\n        Vector<Value>&            val_vec       ,\n        Vector< Vector<addr_t> >& ind_vec_vec   ,\n        size_t&                   compare_false ) const override\n    {   //\n        // arg_vec\n        const Vector<addr_t>& arg_vec( tape->arg_vec() );\n        //\n        // discrete_index\n        // BEGIN_ARG_BEFORE\n        size_t       discrete_index = size_t( arg_vec[arg_index + 0] );\n        // END_ARG_BEFORE\n        //\n        // val_vec\n        addr_t       val_index      = arg_vec[ arg_index + 1 ];\n        const Value& value          = val_vec[val_index];\n        val_vec[res_index] = discrete<Value>::eval(discrete_index, value);\n        //\n        // trace\n        if( ! trace )\n            return;\n        //\n        std::string name = discrete<Value>::name(discrete_index);\n        Vector<addr_t> arg_val_index = { arg_vec[arg_index + 1] };\n        Vector<Value> res_value      = { val_vec[res_index] };\n        print_op(name, arg_val_index, res_index, res_value);\n        //\n        return;\n    }\n};\n\n} } } // END_CPPAD_LOCAL_VAL_GRAPH_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/val_graph/dyn_type.hpp",
    "content": "# ifndef  CPPAD_LOCAL_VAL_GRAPH_DYN_TYPE_HPP\n# define  CPPAD_LOCAL_VAL_GRAPH_DYN_TYPE_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2023-23 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n-------------------------------------------------------------------------------\n{xrst_begin_parent type_dyn_op dev}\n\nTypes of Dynamic Parameter Operators\n####################################\n\n{xrst_end type_dyn_op}\n-------------------------------------------------------------------------------\n{xrst_begin unary_dyn_op dev}\n\nIs This a Binary Dynamic Parameter Operator\n###########################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_UNARY_DYN_OP\n    // END_UNARY_DYN_OP\n}\n\ndyn_op\n******\nis the dynamic parameter operator.\n\nReturn\n******\nThe return is true if this operator has one operands and is recorded by\nspecifying the operator and parameter address of the operand on the tape.\n\n{xrst_end unary_dyn_op}\n*/\nnamespace CppAD { namespace local { namespace val_graph {\n\n// BEGIN_UNARY_DYN_OP\ninline bool unary_dyn_op(op_code_dyn dyn_op)\n// END_UNARY_DYN_OP\n{  bool result;\n    switch(dyn_op)\n    {  default:\n        result = false;\n        break;\n        //\n        case abs_dyn:\n        case acos_dyn:\n        case acosh_dyn:\n        case asin_dyn:\n        case asinh_dyn:\n        case atan_dyn:\n        case atanh_dyn:\n        case cos_dyn:\n        case cosh_dyn:\n        case erf_dyn:\n        case erfc_dyn:\n        case exp_dyn:\n        case expm1_dyn:\n        case fabs_dyn:\n        case log1p_dyn:\n        case log_dyn:\n        case neg_dyn:\n        case sign_dyn:\n        case sin_dyn:\n        case sinh_dyn:\n        case sqrt_dyn:\n        case tan_dyn:\n        case tanh_dyn:\n        result = true;\n        break;\n    }\n    return result;\n}\n/*\n-------------------------------------------------------------------------------\n{xrst_begin binary_dyn_op dev}\n\nIs This a Binary Dynamic Parameter Operator\n###########################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_BINARY_DYN_OP\n    // END_BINARY_DYN_OP\n}\n\ndyn_op\n******\nis the dynamic parameter operator.\n\nReturn\n******\nThe return is true if this operator has two operands and is recorded by\nspecifying the operator and parameter address for each of the operands.\n\n{xrst_end binary_dyn_op}\n*/\n// BEGIN_BINARY_DYN_OP\ninline bool binary_dyn_op(op_code_dyn dyn_op)\n// END_BINARY_DYN_OP\n{   bool result;\n    switch(dyn_op)\n    {   default:\n        result = false;\n        break;\n        case add_dyn:\n        case div_dyn:\n        case mul_dyn:\n        case pow_dyn:\n        case sub_dyn:\n        case zmul_dyn:\n        result = true;\n        break;\n    }\n    return result;\n}\n\n} } } // END_CPPAD_LOCAL_VAL_GRAPH_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/val_graph/enable_parallel.hpp",
    "content": "# ifndef  CPPAD_LOCAL_VAL_GRAPH_ENABLE_PARALLEL_HPP\n# define  CPPAD_LOCAL_VAL_GRAPH_ENABLE_PARALLEL_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2023-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n// BEGIN_SORT_THIS_LINE_PLUS_1\n# include <cppad/local/val_graph/base_op.hpp>\n# include <cppad/local/val_graph/binary_op.hpp>\n# include <cppad/local/val_graph/call_op.hpp>\n# include <cppad/local/val_graph/cexp_op.hpp>\n# include <cppad/local/val_graph/comp_op.hpp>\n# include <cppad/local/val_graph/con_op.hpp>\n# include <cppad/local/val_graph/csum_op.hpp>\n# include <cppad/local/val_graph/dis_op.hpp>\n# include <cppad/local/val_graph/pri_op.hpp>\n# include <cppad/local/val_graph/unary_op.hpp>\n# include <cppad/local/val_graph/vector_op.hpp>\n// END_SORT_THIS_LINE_MINUS_1\n//\nnamespace CppAD { namespace local { namespace val_graph {\n/*\n{xrst_begin val_enable_parallel dev}\n\nEnable val_graph Operators During Parallel Mode\n###############################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_ENABLE_PARALLEL\n    // END_ENABLE_PARALLEL\n}\n\nPurpose\n*******\nConvert an operator enum type :ref:`val_graph_type@op_enum_t`\nto a pointer to an operator base class object :ref:`val_base_op-name` .\n\n{xrst_end val_enable_parallel}\n*/\n// ----------------------------------------------------------------------------\n\n// BEGIN_ENABLE_PARALLEL\n// CppAD::local::val_graph enable_parallel()\ntemplate <class Value> void enable_parallel(void)\n// END_ENABLE_PARALLEL\n{   //\n    // BEGIN_SORT_THIS_LINE_PLUS_1\n    abs_op_t<Value>::get_instance();\n    acos_op_t<Value>::get_instance();\n    acosh_op_t<Value>::get_instance();\n    add_op_t<Value>::get_instance();\n    asin_op_t<Value>::get_instance();\n    asinh_op_t<Value>::get_instance();\n    atan_op_t<Value>::get_instance();\n    atanh_op_t<Value>::get_instance();\n    call_op_t<Value>::get_instance();\n    cexp_op_t<Value>::get_instance();\n    comp_op_t<Value>::get_instance();\n    con_op_t<Value>::get_instance();\n    cos_op_t<Value>::get_instance();\n    cosh_op_t<Value>::get_instance();\n    csum_op_t<Value>::get_instance();\n    dis_op_t<Value>::get_instance();\n    div_op_t<Value>::get_instance();\n    erf_op_t<Value>::get_instance();\n    erfc_op_t<Value>::get_instance();\n    exp_op_t<Value>::get_instance();\n    expm1_op_t<Value>::get_instance();\n    load_op_t<Value>::get_instance();\n    log1p_op_t<Value>::get_instance();\n    log_op_t<Value>::get_instance();\n    mul_op_t<Value>::get_instance();\n    neg_op_t<Value>::get_instance();\n    pow_op_t<Value>::get_instance();\n    pri_op_t<Value>::get_instance();\n    sign_op_t<Value>::get_instance();\n    sin_op_t<Value>::get_instance();\n    sinh_op_t<Value>::get_instance();\n    sqrt_op_t<Value>::get_instance();\n    store_op_t<Value>::get_instance();\n    sub_op_t<Value>::get_instance();\n    tan_op_t<Value>::get_instance();\n    tanh_op_t<Value>::get_instance();\n    vec_op_t<Value>::get_instance();\n    // END_SORT_THIS_LINE_MINUS_1\n    return;\n}\n\n} } } // END_CPPAD_LOCAL_VAL_GRAPH_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/val_graph/fold_con.hpp",
    "content": "# ifndef  CPPAD_LOCAL_VAL_GRAPH_FOLD_CON_HPP\n# define  CPPAD_LOCAL_VAL_GRAPH_FOLD_CON_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2023-25 Bradley M. Bell\n/*\n-------------------------------------------------------------------------------\n{xrst_begin val_tape_fold_con dev}\n{xrst_spell\n    dep\n}\n\nConstant Folding\n################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_FOLD_CON\n    // END_FOLD_CON\n}\n\nDiscussion\n**********\nThis is like :ref:`value numbering <val_tape_renumber-title>` but a major\ndifference is that it adds a new operator for each folded constant.\n\n#. operator results that are constants get replaced by con_op operators.\n   Thus all the constants that are used to compute the dependent values\n   are the result of a con_op operator.\n#. If all the results for an operator get replaced, the operator becomes\n   dead code.\n\nCppAD\n=====\nCppAD functions fold constants before recording but constants\nthat result from an atomic function do not have separate constant operators.\n\n#. Perhaps fun2val could make a separate operator for these constants\n   and it would not be necessary to fold constants here.\n#. On the other hand, folding will be necessary if we allow for creating a new\n   tape where some of the independent values are constants\n#. Currently, this uses more memory than the other optimization steps\n   and is of dubious value in the context of CppAD.\n\n\nChanges\n*******\nOnly the following values, for this tape, are guaranteed to be same:\n#. The number of independent values :ref:`val_tape@n_ind` .\n#. The size of the dependent vector :ref:`dep_vec.size() <val_tape@dep_vec>` .\n\nReference\n*********\n`constant folding <https://en.wikipedia.org/wiki/Constant_folding>`_ .\n\n{xrst_toc_hidden\n    val_graph/fold_con_xam.cpp\n}\nExample\n*******\nThe file :ref:`fold_con_xam.cpp <val_fold_con_xam.cpp-name>`\nis an example and test of tape.fold_con().\n\n{xrst_end val_tape_fold_con}\n-------------------------------------------------------------------------------\n*/\n# include <cppad/local/val_graph/tape.hpp>\n# include <cppad/local/val_graph/call_atomic.hpp>\n\nnamespace CppAD { namespace local { namespace val_graph {\n\n// BEGIN_FOLD_CON\ntemplate <class Value>\nvoid tape_t<Value>::fold_con(void)\n// END_FOLD_CON\n{\n# if CPPAD_VAL_GRAPH_TAPE_TRACE\n    // thread, initial_inuse\n    size_t thread        = thread_alloc::thread_num();\n    size_t initial_inuse = thread_alloc::inuse(thread);\n# endif\n    //\n    // nan\n    Value nan = CppAD::numeric_limits<Value>::quiet_NaN();\n    //\n    // val_index2con\n    Vector<Value> val_index2con(n_val_);\n    for(addr_t i = 0; i < n_ind_; ++i)\n        val_index2con[i] = nan;\n    bool trace           = false;\n    eval(trace, val_index2con);\n    //\n    // is_constant\n    vectorBool is_constant( static_cast<size_t>(n_val_) );\n    for(addr_t i = 0; i < n_val_; ++i)\n        is_constant[i] = false;\n    //\n    // con_x, type_x, type_y\n    // use CppAD::vector because call_atomic_for_type expects it\n    CppAD::vector<Value> con_x;\n    CppAD::vector<ad_type_enum> type_x, type_y;\n    //\n    // op_arg\n    Vector<addr_t> op_arg;\n    //\n    // new_tape\n    tape_t new_tape;\n    new_tape.set_ind(n_ind_);\n    //\n    // old2new_index\n    Vector<addr_t> old2new_index;\n    for(addr_t i = 0; i < n_ind_; ++i)\n        old2new_index.push_back( i );\n    //\n    // we will skip nan at index zero\n    old2new_index.push_back( n_ind_ );\n    is_constant[n_ind_] = true;\n    //\n    // op_itr\n    op_iterator<Value> op_itr(*this, 0);\n    //\n    // i_op\n    for(addr_t i_op = 1; i_op < n_op(); ++i_op)\n    {   //\n        // op_itr\n        ++op_itr; // skip nan at index zero\n        //\n        // op_ptr, arg_index, res_index\n        const base_op_t<Value>* op_ptr    = op_itr.op_ptr();\n        addr_t                  arg_index = op_itr.arg_index();\n        addr_t                  res_index = op_itr.res_index();\n        //\n        // op_enum, n_arg, n_before, n_after, n_res\n        op_enum_t  op_enum   = op_ptr->op_enum();\n        addr_t     n_before  = op_ptr->n_before();\n        addr_t     n_after   = op_ptr->n_after();\n        addr_t     n_arg     = op_ptr->n_arg(arg_index, var_arg_);\n        addr_t     n_res     = op_ptr->n_res(arg_index, var_arg_);\n        //\n        CPPAD_ASSERT_UNKNOWN( size_t( res_index ) == old2new_index.size() );\n        //\n        // new_tape, is_constant, old2new_index\n        if( n_res == 1 && op_enum != con_op_enum )\n        {   bool fold = true;\n            for(addr_t i = n_before; i < n_arg - n_after; ++i)\n                fold &= is_constant[ var_arg_[arg_index + i] ];\n            if( fold )\n            {   is_constant[res_index]  = true;\n                const Value& value      = val_index2con[res_index];\n                addr_t new_res_index    = new_tape.record_con_op(value);\n                old2new_index.push_back( new_res_index );\n            }\n            else\n            {   op_arg.resize(n_arg);\n                for(addr_t k = 0; k < n_before; ++k)\n                    op_arg[k] = var_arg_[arg_index + k];\n                for(addr_t k = n_before; k < n_arg - n_after; ++k)\n                {   addr_t old_index = var_arg_[arg_index + k];\n                    assert( old_index < res_index );\n                    op_arg[k] = old2new_index[old_index];\n                }\n                for(addr_t k = 1; k <= n_after; ++k)\n                    op_arg[n_arg - k] = var_arg_[arg_index + n_arg - k];\n                //\n                addr_t new_res_index = new_tape.record_op(op_enum, op_arg);\n                old2new_index.push_back( new_res_index );\n            }\n        }\n        else switch(op_enum)\n        {   //\n            // default\n            default:\n            CPPAD_ASSERT_KNOWN(false,\n                \"val_graph::fold_con: This operator not yet implemented\"\n            );\n            break;\n            // ----------------------------------------------------------------\n            // con_op\n            case con_op_enum:\n            CPPAD_ASSERT_UNKNOWN( n_arg == 1);\n            {   is_constant[res_index] = true;\n                const Value& value   = val_index2con[res_index];\n                addr_t new_res_index = new_tape.record_con_op(value);\n                old2new_index.push_back( new_res_index );\n            }\n            break;\n            // ----------------------------------------------------------------\n            // call_op\n            case call_op_enum:\n            {   //\n                // atomic_index, call_id\n                addr_t atomic_index = var_arg_[arg_index + 2];\n                addr_t call_id      = var_arg_[arg_index + 3];\n                CPPAD_ASSERT_UNKNOWN( atomic_index > 0 );\n                //\n                // n_before, n_x\n                addr_t n_x      = n_arg - n_before - op_ptr->n_after();\n                //\n                // con_x, type_x\n                type_x.resize(n_x);\n                con_x.resize(n_x);\n                for(addr_t i = 0; i < n_x; ++i)\n                {   addr_t val_index =  var_arg_[arg_index + n_before + i];\n                    con_x[i] = val_index2con[val_index];\n                    if( is_constant[val_index] )\n                        type_x[i] = constant_enum;\n                    else\n                        type_x[i] = variable_enum;;\n                }\n                //\n                // type_y\n                type_y.resize(n_res);\n                call_atomic_for_type<Value>(\n                    con_x, type_x, type_y, size_t(atomic_index), size_t(call_id)\n                );\n                //\n                // new_tape, new_res_index\n                // record the function call\n                op_arg.resize(n_x);\n                for(addr_t k = 0; k < n_x; ++k)\n                {   addr_t old_index   = var_arg_[arg_index + n_before + k];\n                    op_arg[k]      = old2new_index[old_index];\n                }\n                addr_t new_res_index = new_tape.record_call_op(\n                    atomic_index, call_id, n_res, op_arg\n                );\n                //\n                // is_constant, new_tape, old2new_index\n                for(addr_t i = 0; i < n_res; ++i)\n                {   is_constant[res_index + i] = type_y[i] <= constant_enum;\n                    if( is_constant[res_index + i] )\n                    {   const Value& value      = val_index2con[res_index + i];\n                        addr_t con_res_index    = new_tape.record_con_op(value);\n                        old2new_index.push_back( con_res_index );\n                    }\n                    else\n                    {   // if none of these results get used, this call is dead code\n                        old2new_index.push_back(new_res_index + i);\n                    }\n                }\n            }\n            break;\n        }\n    }\n    //\n    // dep_vec\n    Vector<addr_t> dep_vec( dep_vec_.size() );\n    for(size_t k = 0; k < dep_vec_.size(); ++k)\n        dep_vec[k] = old2new_index[ dep_vec_[k] ];\n    new_tape.set_dep( dep_vec );\n    //\n    // swap\n    swap(new_tape);\n# if CPPAD_VAL_GRAPH_TAPE_TRACE\n    // inuse\n    size_t final_inuse = thread_alloc::inuse(thread);\n    std::cout << \"fold_con:  inuse = \" << final_inuse - initial_inuse << \"\\n\";\n# endif\n    return;\n}\n\n} } } // END_CPPAD_LOCAL_VAL_GRAPH_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/val_graph/fun2val.hpp",
    "content": "# ifndef  CPPAD_LOCAL_VAL_GRAPH_FUN2VAL_HPP\n# define  CPPAD_LOCAL_VAL_GRAPH_FUN2VAL_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// --------------------------------------------------------------------------\n/*\n------------------------------------------------------------------------------\n{xrst_begin fun2val_graph dev}\n\nCreate a Value Graph Corresponding to an ADFun Object\n#####################################################\n\nSyntax\n******\n| |tab| ``ADFun`` < *Base* > *fun*\n| |tab| *fun* . ``fun2val`` ( *val_tape* )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_PROTOTYPE\n    // END_PROTOTYPE\n}\n\nBase\n****\nis the type corresponding to this :ref:`adfun-name` object;\ni.e., its calculations are done using the type *Base* .\nIt is also :ref:`val_tape@Value` type for the tape.\n\nRecBase\n*******\nin the prototype above, *RecBase* is the same type as *Base* .\n\nval_tape\n********\nThis is a :ref:`val_tape-name` object.\nThe input contents of the tape does not matter.\nUpon return it is a\n:ref:`val_graph-name` representation of the function.\nThe independent dynamic parameters have the same order as in\n*fun* and come first (in the value graph independent vector).\nThe independent variables have the same order as in\n*fun* and come after the independent dynamic parameters.\n\nfun\n***\nThis is the function that the value graph will correspond to.\n\nUnder Construction\n******************\nThis routine is under construction and is only implemented\nfor a few of the possible :ref:`ADFun-name` operators.\n\n{xrst_toc_hidden\n    val_graph/fun2val_xam.cpp\n}\nExamples\n********\nThe file :ref:`val_fun2val_xam.cpp-name`\nis an example an test of this conversion.\n\n{xrst_end fun2val_graph}\n*/\n\n# include <cppad/core/ad_fun.hpp>\n# include <cppad/local/op_code_dyn.hpp>\n# include <cppad/local/val_graph/tape.hpp>\n# include <cppad/local/pod_vector.hpp>\n# include <cppad/local/val_graph/var_type.hpp>\n# include <cppad/local/val_graph/dyn_type.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n\n// BEGIN_PROTOTYPE\ntemplate <class Base, class RecBase>\nvoid ADFun<Base, RecBase>::fun2val(\n    local::val_graph::tape_t<Base>& val_tape  )\n// END_PROTOTYPE\n{   //\n    // Vector, addr_t, op_enum_t\n    using local::val_graph::Vector;\n    using local::val_graph::addr_t;\n    using local::val_graph::op_enum_t;\n    op_enum_t number_op_enum = local::val_graph::number_op_enum;\n    //\n    // op_code_dyn, number_dyn, op_code_var\n    using local::op_code_dyn;\n    op_code_dyn number_dyn = local::number_dyn;\n    using local::op_code_var;\n    //\n    // pod_vector, opcode_t\n    using local::pod_vector;\n    using local::opcode_t;\n    //\n    // invalid_addr_t\n    addr_t invalid_addr_t = std::numeric_limits<addr_t>::max();\n    //\n    // parameter\n    const Base* parameter = play_.par_ptr();\n    //\n    // dyn_op2val_op\n    Vector<op_enum_t> dyn_op2val_op(number_dyn);\n    for(size_t i = 0; i < size_t(number_dyn); ++i)\n        dyn_op2val_op[i] = number_op_enum; // invalid\n    dyn_op2val_op[local::add_dyn] = local::val_graph::add_op_enum;\n    dyn_op2val_op[local::neg_dyn] = local::val_graph::neg_op_enum;\n    dyn_op2val_op[local::sub_dyn] = local::val_graph::sub_op_enum;\n    // ------------------------------------------------------------------------\n    // var_op2val_op\n    Vector<op_enum_t> var_op2val_op(local::NumberOp);\n    for(size_t i = 0; i < size_t(local::NumberOp); ++i)\n        var_op2val_op[i] = number_op_enum; // invalid\n    //\n    // unary operators\n    // BEGIN_SORT_THIS_LINE_PLUS_1\n    var_op2val_op[local::AbsOp]    = local::val_graph::abs_op_enum;\n    var_op2val_op[local::AcosOp]   = local::val_graph::acos_op_enum;\n    var_op2val_op[local::AcoshOp]  = local::val_graph::acosh_op_enum;\n    var_op2val_op[local::AsinOp]   = local::val_graph::asin_op_enum;\n    var_op2val_op[local::AsinhOp]  = local::val_graph::asinh_op_enum;\n    var_op2val_op[local::AtanOp]   = local::val_graph::atan_op_enum;\n    var_op2val_op[local::AtanhOp]  = local::val_graph::atanh_op_enum;\n    var_op2val_op[local::CosOp]    = local::val_graph::cos_op_enum;\n    var_op2val_op[local::CoshOp]   = local::val_graph::cosh_op_enum;\n    var_op2val_op[local::ErfOp]    = local::val_graph::erf_op_enum;\n    var_op2val_op[local::ErfcOp]   = local::val_graph::erfc_op_enum;\n    var_op2val_op[local::ExpOp]    = local::val_graph::exp_op_enum;\n    var_op2val_op[local::Expm1Op]  = local::val_graph::expm1_op_enum;\n    var_op2val_op[local::Log1pOp]  = local::val_graph::log1p_op_enum;\n    var_op2val_op[local::LogOp]    = local::val_graph::log_op_enum;\n    var_op2val_op[local::NegOp]    = local::val_graph::neg_op_enum;\n    var_op2val_op[local::SignOp]   = local::val_graph::sign_op_enum;\n    var_op2val_op[local::SinOp]    = local::val_graph::sin_op_enum;\n    var_op2val_op[local::SinhOp]   = local::val_graph::sinh_op_enum;\n    var_op2val_op[local::SqrtOp]   = local::val_graph::sqrt_op_enum;\n    var_op2val_op[local::TanOp]    = local::val_graph::tan_op_enum;\n    var_op2val_op[local::TanhOp]   = local::val_graph::tanh_op_enum;\n    // END_SORT_THIS_LINE_MINUS_1\n    //\n    // add\n    var_op2val_op[local::AddpvOp] = local::val_graph::add_op_enum;\n    var_op2val_op[local::AddvvOp] = local::val_graph::add_op_enum;\n    //\n    // sub\n    var_op2val_op[local::SubpvOp] = local::val_graph::sub_op_enum;\n    var_op2val_op[local::SubvpOp] = local::val_graph::sub_op_enum;\n    var_op2val_op[local::SubvvOp] = local::val_graph::sub_op_enum;\n    //\n    // mul\n    var_op2val_op[local::MulpvOp] = local::val_graph::mul_op_enum;\n    var_op2val_op[local::MulvvOp] = local::val_graph::mul_op_enum;\n    //\n    // div\n    var_op2val_op[local::DivpvOp] = local::val_graph::div_op_enum;\n    var_op2val_op[local::DivvpOp] = local::val_graph::div_op_enum;\n    var_op2val_op[local::DivvvOp] = local::val_graph::div_op_enum;\n    //\n    // pow\n    var_op2val_op[local::PowpvOp] = local::val_graph::pow_op_enum;\n    var_op2val_op[local::PowvpOp] = local::val_graph::pow_op_enum;\n    var_op2val_op[local::PowvvOp] = local::val_graph::pow_op_enum;\n    // ------------------------------------------------------------------------\n    //\n    // dyn_par_op\n    // mapping from dynamic parameter index to operator\n    const pod_vector<opcode_t>& dyn_par_op ( play_.dyn_par_op()  );\n    //\n    // dyn2par_index\n      // mapping from dynamic parameter index to parameter index\n    const pod_vector<addr_t>& dyn2par_index ( play_.dyn2par_index() );\n    //\n    // dyn_par_arg\n    // vector that contains arguments to all the dynamic parameter operators\n    const pod_vector<addr_t>&  dyn_par_arg( play_.dyn_par_arg() );\n    //\n    // n_parameter\n    // number of parameters\n    size_t n_parameter = play_.num_par_all();\n    //\n    // n_dynamic\n    // number of dynamic parameters\n    size_t n_dynamic = dyn2par_index.size();\n    //\n    // n_dynamic_ind\n    // number of independent dynamic parameters\n    size_t n_dynamic_ind = play_.n_dyn_independent();\n    //\n    // n_variables\n    // number of variables\n    const size_t n_variable = play_.num_var();\n    //\n    // n_variable_ind\n    // number of independent variables\n    size_t n_variable_ind = ind_taddr_.size();\n    //\n    // n_val_ind\n    // number of independent values\n    addr_t n_val_ind = addr_t( n_dynamic_ind + n_variable_ind );\n    //\n# ifndef NDEBUG\n    // nan_val_index\n    // initialize value vector tape\n    addr_t nan_val_index = val_tape.set_ind( n_val_ind );\n    CPPAD_ASSERT_UNKNOWN( nan_val_index == n_val_ind );\n# else\n    val_tape.set_ind( n_val_ind );\n# endif\n    //\n    // val_tape, vec_info_vec\n    // Put dynamic vectors in val_tape and create vec_info_vec\n    struct vec_info_t { size_t size; size_t offset; };\n    Vector<vec_info_t> vec_info_vec;\n    {   size_t n_vecad_ind = play_.num_var_vec_ind();\n        size_t index         = 0;\n        while(index < n_vecad_ind)\n        {   size_t size         = play_.GetVecInd(index++);\n            size_t offset       = index;\n            //\n            Vector<addr_t> initial(size);\n            for(size_t i = 0; i < size; ++i)\n            {   size_t par_index = play_.GetVecInd(index++);\n                addr_t val_index = val_tape.record_con_op( parameter[par_index] );\n                initial[i]       = val_index;\n            }\n# ifdef NDEBUG\n            val_tape.record_vec_op(initial);\n# else\n            addr_t which_vector = val_tape.record_vec_op(initial);\n            CPPAD_ASSERT_UNKNOWN( size_t(which_vector) == vec_info_vec.size() );\n# endif\n            vec_info_t vec_info = {size, offset};\n            vec_info_vec.push_back( vec_info );\n        }\n    }\n    //\n    // vec_offset2index\n    // mapping from vecad offset to index in vec_info_vec\n    auto vec_offset2index = [&vec_info_vec](addr_t offset)\n    {   addr_t index    = 0;\n        size_t offset_s = size_t(offset);\n        while( vec_info_vec[index].offset < offset_s )\n            ++index;\n        CPPAD_ASSERT_UNKNOWN( vec_info_vec[index].offset == offset_s );\n        return index;\n    };\n    //\n    // par2val_index\n    // Initialize mapping from parameter index to index in value vector.\n    Vector<addr_t> par2val_index(n_parameter);\n    for(size_t i = 0; i < n_parameter; ++i)\n        par2val_index[i] = invalid_addr_t;\n    for(addr_t i = 0; i < addr_t( n_dynamic_ind ); ++i)\n        par2val_index[i + 1] = i;\n    //\n    // val_op_arg, var_op_res, res_is_par;\n    Vector<addr_t> val_op_arg, var_op_res;\n    Vector<bool>   res_is_par;\n    //\n    // i_arg\n    // initial index in dyn_par_arg\n    addr_t i_arg = 0;\n    //\n    // ensure_par2val_index\n    // val_tape, par2val_index\n    auto ensure_par2val_index =\n    [&val_tape, &par2val_index, &parameter, invalid_addr_t] (addr_t par_index)\n    {   addr_t result = par2val_index[par_index];\n        if( result == invalid_addr_t )\n        {   Base constant            = parameter[par_index];\n            result                   = val_tape.record_con_op(constant);\n            par2val_index[par_index] = result;\n        }\n        return result;\n    };\n    //\n    // val_tape\n    // record dynamic parameter operations\n    //\n    // val_tape, val_index, par2val_index\n    addr_t val_index = invalid_addr_t;\n    for(size_t i_dyn = n_dynamic_ind; i_dyn < n_dynamic; ++i_dyn)\n    {   //\n        // i_par\n        size_t i_par = size_t( dyn2par_index[i_dyn] );\n        //\n        // dyn_op\n        // operator for this dynamic parameter\n        local::op_code_dyn dyn_op = local::op_code_dyn( dyn_par_op[i_dyn] );\n        //\n        // is_unary, is_binary\n        bool is_unary  = local::val_graph::unary_dyn_op(dyn_op);\n        bool is_binary = local::val_graph::binary_dyn_op(dyn_op);\n        //\n        // n_arg, val_tape, val_index, par2val_index\n        addr_t n_arg;\n        if( is_unary || is_binary )\n        {   //\n            // val_tape, val_index, par2val_index\n            n_arg = addr_t( num_arg_dyn(dyn_op) );\n            val_op_arg.resize(n_arg);\n            for(addr_t i = 0; i < n_arg; ++i)\n            {   addr_t par_index = dyn_par_arg[i_arg + i];\n                val_op_arg[i]    = ensure_par2val_index(par_index);\n            }\n            // val_tape, val_index\n            op_enum_t val_op = dyn_op2val_op[dyn_op];\n            val_index = val_tape.record_op(val_op, val_op_arg);\n        }\n        else switch( dyn_op )\n        {   //\n            default:\n            CPPAD_ASSERT_KNOWN(false,\n                \"val_graph::fun2val: This dynamic operator not yet implemented\"\n            );\n            // -------------------------------------------------------------------\n            // result_dyn\n            // This is a place holder for multiple result operators\n            case local::result_dyn:\n            CPPAD_ASSERT_UNKNOWN( val_index != invalid_addr_t );\n            n_arg      = 0;\n            val_index += 1;\n            break;\n            // -------------------------------------------------------------------\n            // dis_dyn\n            case local::dis_dyn:\n            {   // val_tape, val_index, par2val_index\n                val_op_arg.resize(1);\n                addr_t discrete_index = dyn_par_arg[i_arg + 0];\n                addr_t par_index      = dyn_par_arg[i_arg + 1];\n                val_op_arg[0]         = ensure_par2val_index(par_index);\n                //\n                // n_arg, val_tape, val_index\n                n_arg = 2;\n                val_index = val_tape.record_dis_op(\n                    discrete_index, val_op_arg[0]\n                );\n            }\n            break;\n            // -------------------------------------------------------------------\n            // cond_exp\n            case local::cond_exp_dyn:\n            {   CompareOp cop = CompareOp( dyn_par_arg[i_arg + 0] );\n                addr_t left     = ensure_par2val_index( dyn_par_arg[i_arg + 1] );\n                addr_t right    = ensure_par2val_index( dyn_par_arg[i_arg + 2] );\n                addr_t if_true  = ensure_par2val_index( dyn_par_arg[i_arg + 3] );\n                addr_t if_false = ensure_par2val_index( dyn_par_arg[i_arg + 4] );\n                local::val_graph::compare_enum_t compare_enum;\n                switch( cop )\n                {   case CompareLt:\n                    compare_enum = local::val_graph::compare_lt_enum;\n                    break;\n\n                    case CompareLe:\n                    compare_enum = local::val_graph::compare_le_enum;\n                    break;\n\n                    case CompareEq:\n                    compare_enum = local::val_graph::compare_eq_enum;\n                    break;\n\n                    case CompareGe:\n                    compare_enum = local::val_graph::compare_lt_enum;\n                    std::swap(if_true, if_false);\n                    break;\n\n                    case CompareGt:\n                    compare_enum = local::val_graph::compare_le_enum;\n                    std::swap(if_true, if_false);\n                    break;\n\n                    case CompareNe:\n                    compare_enum = local::val_graph::compare_eq_enum;\n                    std::swap(if_true, if_false);\n                    break;\n\n                    default:\n                    CPPAD_ASSERT_UNKNOWN(false);\n                    // avoid warning about value not set\n                    compare_enum = local::val_graph::compare_no_enum;\n                    break;\n                }\n                //\n                // n_arg, val_tape, val_index\n                n_arg     = 5;\n                val_index = val_tape.record_cexp_op(\n                    compare_enum, left, right, if_true, if_false\n                );\n            }\n            break;\n            // -------------------------------------------------------------------\n            // atom_dyn\n            case local::atom_dyn:\n            {   //\n                // atomic_index, call_id, n_call_arg, n_res\n                addr_t atomic_index = dyn_par_arg[i_arg + 0];\n                addr_t call_id      = dyn_par_arg[i_arg + 1];\n                addr_t n_call_arg   = dyn_par_arg[i_arg + 2];\n                addr_t n_res        =  dyn_par_arg[i_arg + 3] ;\n                // num_dyn          = size_t( dyn_par_arg[i_age + 4] );\n                //\n                // val_op_arg, val_tape, par2val_index\n                val_op_arg.resize( n_call_arg );\n                for(addr_t i = 0; i < n_call_arg; i++)\n                {   addr_t par_index = dyn_par_arg[i_arg + i + 5];\n                    val_op_arg[i] = ensure_par2val_index(par_index);\n                }\n                // n_arg, val_tape, val_index\n                n_arg     = n_call_arg + 5;\n                val_index = val_tape.record_call_op(\n                    atomic_index, call_id, n_res, val_op_arg\n                );\n            }\n            break;\n        }\n        // par2val_index\n        // Each dyn_op has one result, result_dyn ops are added to make this so\n        par2val_index[i_par] = val_index;\n        //\n        // i_arg\n        i_arg += n_arg;\n    }\n    //\n    // var2val_index\n    // Initialize mapping from variable index to index in value vector.\n    Vector<addr_t> var2val_index(n_variable);\n    for(size_t i = 0; i < n_variable; ++i)\n        var2val_index[i] = invalid_addr_t;\n    for(addr_t i = 0; i < addr_t(n_variable_ind); ++i)\n        var2val_index[i + 1] = addr_t( n_dynamic_ind )  + i;\n    //\n    // itr, is_var, more_operators\n    local::play::const_sequential_iterator itr  = play_.begin();\n    Vector<bool>       is_var(2);\n    bool more_operators = true;\n    bool in_atomic_call = false;\n    //\n    // val_tape, var2val_index, par2val_index\n    while(more_operators)\n    {   //\n        //\n        // itr, var_op, var_op_arg, i_var\n        local::op_code_var var_op;\n        const            addr_t* var_op_arg;\n        size_t           i_var;\n        (++itr).op_info(var_op, var_op_arg, i_var);\n        //\n        // is_unary, is_binary, is_compare\n        // initialize to avoid compiler warning\n        bool is_unary = false, is_binary = false, is_compare = false;\n        local::val_graph::type_var_op(\n            var_op, is_unary, is_binary, is_compare\n        );\n        // ----------------------------------------------------------------------\n        if( is_unary )\n        {   //\n            // val_op\n            op_enum_t val_op = var_op2val_op[var_op];\n            CPPAD_ASSERT_UNKNOWN( val_op < number_op_enum );\n            //\n            // val_tape, val_index\n            val_op_arg.resize(1);\n            val_op_arg[0] = var2val_index[ var_op_arg[0] ];\n            val_index = val_tape.record_op(val_op, val_op_arg);\n            //\n            // var2val_index\n            var2val_index[i_var] = val_index;\n        }\n        // ----------------------------------------------------------------------\n        else if( is_binary )\n        {    switch( var_op )\n            {\n                default:\n                CPPAD_ASSERT_KNOWN(false,\n                    \"val_graph::fun2val: This variable operator not yet implemented\"\n                );\n\n                // first argument a parameter, second argument a variable\n                case local::AddpvOp:\n                case local::SubpvOp:\n                case local::MulpvOp:\n                case local::DivpvOp:\n                case local::PowpvOp:\n                is_var[0]   = false;\n                is_var[1]   = true;\n                break;\n\n                // first argument a variable, second argument a parameter\n                case local::SubvpOp:\n                case local::DivvpOp:\n                case local::PowvpOp:\n                is_var[0]   = true;\n                is_var[1]   = false;\n                break;\n\n                // first argument a variable, second argument a variable\n                case local::AddvvOp:\n                case local::SubvvOp:\n                case local::MulvvOp:\n                case local::DivvvOp:\n                case local::PowvvOp:\n                is_var[0]   = true;\n                is_var[1]   = true;\n                break;\n            }\n            //\n            // varl_op_arg, val_tape, par2val_index\n            val_op_arg.resize(2);\n            for(size_t i = 0; i < 2; ++i)\n            {   if( is_var[i] )\n                    val_op_arg[i] = var2val_index[ var_op_arg[i] ];\n                else\n                    val_op_arg[i] = ensure_par2val_index( var_op_arg[i] );\n            }\n            //\n            // val_op\n            op_enum_t val_op = var_op2val_op[var_op];\n            CPPAD_ASSERT_UNKNOWN( val_op < number_op_enum );\n            //\n            // record_op, val_index\n            val_index = val_tape.record_op(val_op, val_op_arg);\n            //\n            // var2val_index\n            var2val_index[i_var] = val_index;\n        }\n        // ----------------------------------------------------------------------\n        else if( is_compare )\n        {   //\n            // left_index, right_index\n            addr_t left_index, right_index;\n            switch( var_op )\n            {\n                // default\n                default:\n                CPPAD_ASSERT_UNKNOWN(false);\n                left_index  = 0; // to avoid compiler warning\n                right_index = 0;\n                break;\n\n                // both nodes parameters\n                case local::EqppOp:\n                case local::NeppOp:\n                case local::LtppOp:\n                case local::LeppOp:\n                left_index  = par2val_index[ var_op_arg[0] ];\n                right_index = par2val_index[ var_op_arg[1] ];\n                break;\n\n                // first node parameter, second variable\n                case local::EqpvOp:\n                case local::NepvOp:\n                case local::LtpvOp:\n                case local::LepvOp:\n                left_index  = par2val_index[ var_op_arg[0] ];\n                right_index = var2val_index[ var_op_arg[1] ];\n                break;\n\n                // first node variable, second parameter\n                case local::LtvpOp:\n                case local::LevpOp:\n                left_index  = var2val_index[ var_op_arg[0] ];\n                right_index = par2val_index[ var_op_arg[1] ];\n                break;\n\n                // both nodes variables\n                case local::EqvvOp:\n                case local::NevvOp:\n                case local::LtvvOp:\n                case local::LevvOp:\n                left_index  = var2val_index[ var_op_arg[0] ];\n                right_index = var2val_index[ var_op_arg[1] ];\n                break;\n\n            }\n            // compare_enum\n            local::val_graph::compare_enum_t compare_enum;\n            // Set graph_op\n            switch( var_op )\n            {\n                // default\n                default:\n                CPPAD_ASSERT_UNKNOWN(false);\n                // set to avoid compiler warning\n                compare_enum = local::val_graph::number_compare_enum;\n                break;\n\n                case local::EqppOp:\n                case local::EqpvOp:\n                case local::EqvvOp:\n                compare_enum = local::val_graph::compare_eq_enum;\n                break;\n\n                case local::NeppOp:\n                case local::NepvOp:\n                case local::NevvOp:\n                compare_enum = local::val_graph::compare_ne_enum;\n                break;\n\n                case local::LtppOp:\n                case local::LtpvOp:\n                case local::LtvpOp:\n                case local::LtvvOp:\n                compare_enum = local::val_graph::compare_lt_enum;\n                break;\n\n                case local::LeppOp:\n                case local::LepvOp:\n                case local::LevpOp:\n                case local::LevvOp:\n                compare_enum = local::val_graph::compare_le_enum;\n                break;\n\n            }\n            //\n            // tape\n            val_index = val_tape.record_comp_op(\n                compare_enum, left_index, right_index\n            );\n            CPPAD_ASSERT_UNKNOWN(val_index == 0); // no result for this operator\n        }\n        // ----------------------------------------------------------------------\n        else switch(var_op)\n        {\n            default:\n            CPPAD_ASSERT_KNOWN(false,\n                \"val_graph::fun2val: This variable operator not yet implemented\"\n            );\n            break;\n\n            // ParOp:\n            // val_tape, par2val_index, var2val_index\n            case local::ParOp:\n            val_index            = ensure_par2val_index( var_op_arg[0] );\n            var2val_index[i_var] = val_index;\n            break;\n\n            // EndOp:\n            case local::EndOp:\n            more_operators = false;\n            break;\n\n            // InvOp:\n            // The independent variable indices are already assigned\n            case local::InvOp:\n            break;\n            //\n            // DisOp\n            case local::DisOp:\n            {   // val_tape, var2val_index\n                val_op_arg.resize(1);\n                addr_t discrete_index = var_op_arg[0];\n                val_op_arg[0]         = var2val_index[ var_op_arg[1] ];\n                val_index             = val_tape.record_dis_op(\n                    discrete_index, val_op_arg[0]\n                );\n                var2val_index[i_var]  = val_index;\n            }\n            break;\n            // --------------------------------------------------------------\n            case local::LdpOp:\n            {   addr_t which_vector = vec_offset2index( var_op_arg[0] );\n                addr_t vector_index = ensure_par2val_index( var_op_arg[1] );\n                //\n                var2val_index[i_var] = val_tape.record_load_op(\n                    which_vector, vector_index\n                );\n            }\n            break;\n            //\n            case local::LdvOp:\n            {   addr_t which_vector = vec_offset2index( var_op_arg[0] );\n                addr_t vector_index = var2val_index[ var_op_arg[1] ];\n                //\n                var2val_index[i_var] = val_tape.record_load_op(\n                    which_vector, vector_index\n                );\n            }\n            break;\n            //\n            case local::StppOp:\n            {   addr_t which_vector = vec_offset2index( var_op_arg[0] );\n                addr_t vector_index = ensure_par2val_index( var_op_arg[1] );\n                addr_t value_index  = ensure_par2val_index( var_op_arg[2] );\n                //\n                val_tape.record_store_op(\n                    which_vector, vector_index, value_index\n                );\n            }\n            break;\n            //\n            case local::StpvOp:\n            {   addr_t which_vector = vec_offset2index( var_op_arg[0] );\n                addr_t vector_index = ensure_par2val_index( var_op_arg[1] );\n                addr_t value_index  = var2val_index[ var_op_arg[2] ];\n                //\n                val_tape.record_store_op(\n                    which_vector, vector_index, value_index\n                );\n            }\n            break;\n            //\n            case local::StvpOp:\n            {   addr_t which_vector = vec_offset2index( var_op_arg[0] );\n                addr_t vector_index = var2val_index[ var_op_arg[1] ];\n                addr_t value_index  = ensure_par2val_index( var_op_arg[2] );\n                //\n                val_tape.record_store_op(\n                    which_vector, vector_index, value_index\n                );\n            }\n            break;\n            //\n            case local::StvvOp:\n            {   addr_t which_vector = vec_offset2index( var_op_arg[0] );\n                addr_t vector_index = var2val_index[ var_op_arg[1] ];\n                addr_t value_index  = var2val_index[ var_op_arg[2] ];\n                //\n                val_tape.record_store_op(\n                    which_vector, vector_index, value_index\n                );\n            }\n            break;\n            // --------------------------------------------------------------\n            case local::PriOp:\n            {   //\n                // before, after\n                std::string before( play_.GetTxt( size_t( var_op_arg[2] ) ) );\n                std::string after(  play_.GetTxt( size_t( var_op_arg[4] ) ) );\n                //\n                // flag_index\n                addr_t flag_index;\n                if( var_op_arg[0] & 1 )\n                    flag_index = var2val_index[ var_op_arg[1] ];\n                else\n                    flag_index = ensure_par2val_index( var_op_arg[1] );\n                //\n                // value_index\n                addr_t value_index;\n                if( var_op_arg[0] & 1 )\n                    value_index = var2val_index[ var_op_arg[3] ];\n                else\n                    value_index = ensure_par2val_index( var_op_arg[3] );\n                //\n                val_index = val_tape.record_pri_op(\n                    before, after, flag_index, value_index\n                );\n            }\n            CPPAD_ASSERT_UNKNOWN(val_index == 0); // no result for this operator\n            break;\n            // --------------------------------------------------------------\n            case local::CSumOp:\n            {   //\n                // add, sub\n                Vector<addr_t> add, sub;\n                //\n                // add: constant term\n                add.push_back( ensure_par2val_index( var_op_arg[0] ) );\n                //\n                // add: variables\n                for(addr_t i = 5; i < var_op_arg[1]; ++i)\n                    add.push_back( var2val_index[ var_op_arg[i] ] );\n                //\n                // sub: variables\n                for(addr_t i = var_op_arg[1]; i < var_op_arg[2]; ++i)\n                    sub.push_back( var2val_index[ var_op_arg[i] ] );\n                //\n                // add: dynamic parameters\n                for(addr_t i = var_op_arg[2]; i < var_op_arg[3]; ++i)\n                    add.push_back( ensure_par2val_index( var_op_arg[i] ) );\n                //\n                // sub: dynamic parameters\n                for(addr_t i = var_op_arg[3]; i < var_op_arg[4]; ++i)\n                    sub.push_back( ensure_par2val_index( var_op_arg[i] ) );\n                //\n                // val_tape, var2val_index\n                var2val_index[i_var] = val_tape.record_csum_op(add, sub);\n            }\n            itr.correct_before_increment();\n            break;\n            // --------------------------------------------------------------\n            case local::CExpOp:\n            {   // cop, left, right, if_true, if_false\n                CompareOp cop = CompareOp( var_op_arg[0] );\n                addr_t left, right, if_true, if_false;\n                if( var_op_arg[1] & 1 )\n                    left = var2val_index[ var_op_arg[2] ];\n                else\n                    left = ensure_par2val_index( var_op_arg[2] );\n                if( var_op_arg[1] & 2 )\n                    right = var2val_index[ var_op_arg[3] ];\n                else\n                    right = ensure_par2val_index( var_op_arg[3] );\n                if( var_op_arg[1] & 4 )\n                    if_true = var2val_index[ var_op_arg[4] ];\n                else\n                    if_true = ensure_par2val_index( var_op_arg[4] );\n                if( var_op_arg[1] & 8 )\n                    if_false = var2val_index[ var_op_arg[5] ];\n                else\n                    if_false = ensure_par2val_index( var_op_arg[5] );\n                //\n                // compare_enum\n                local::val_graph::compare_enum_t compare_enum;\n                switch( cop )\n                {   case CompareLt:\n                    compare_enum = local::val_graph::compare_lt_enum;\n                    break;\n\n                    case CompareLe:\n                    compare_enum = local::val_graph::compare_le_enum;\n                    break;\n\n                    case CompareEq:\n                    compare_enum = local::val_graph::compare_eq_enum;\n                    break;\n\n                    case CompareGe:\n                    compare_enum = local::val_graph::compare_lt_enum;\n                    std::swap(if_true, if_false);\n                    break;\n\n                    case CompareGt:\n                    compare_enum = local::val_graph::compare_le_enum;\n                    std::swap(if_true, if_false);\n                    break;\n\n                    case CompareNe:\n                    compare_enum = local::val_graph::compare_eq_enum;\n                    std::swap(if_true, if_false);\n                    break;\n\n                    default:\n                    CPPAD_ASSERT_UNKNOWN(false);\n                    // set to avoid compiler warning\n                    compare_enum = local::val_graph::number_compare_enum;\n                    break;\n                }\n                val_index = val_tape.record_cexp_op(\n                    compare_enum, left, right, if_true, if_false\n                );\n                var2val_index[i_var] = val_index;\n            }\n            break;\n\n            // --------------------------------------------------------------\n            case local::FunapOp:\n            val_op_arg.push_back( ensure_par2val_index( var_op_arg[0] ) );\n            break;\n\n            case local::FunavOp:\n            CPPAD_ASSERT_UNKNOWN( size_t(var_op_arg[0]) <= i_var );\n            val_op_arg.push_back( var2val_index[var_op_arg[0]] );\n            break;\n\n            case local::FunrpOp:\n            var_op_res.push_back( var_op_arg[0] );\n            res_is_par.push_back(true);\n            break;\n\n            case local::FunrvOp:\n            var_op_res.push_back( addr_t(i_var) );\n            res_is_par.push_back(false);\n            break;\n\n            case local::AFunOp:\n            in_atomic_call = ! in_atomic_call;\n            if( in_atomic_call )\n            {   val_op_arg.resize(0);\n                var_op_res.resize(0);\n                res_is_par.resize(0);\n            }\n            else\n            {   // atomic_index, call_id, n_res\n                addr_t atomic_index = var_op_arg[0];\n                addr_t call_id      = var_op_arg[1];\n                addr_t n_res        = var_op_arg[3];\n# ifndef NDEBUG\n                addr_t n_arg        = var_op_arg[2];\n                CPPAD_ASSERT_UNKNOWN( val_op_arg.size() == size_t(n_arg) );\n                CPPAD_ASSERT_UNKNOWN( var_op_res.size() == size_t(n_res) );\n                CPPAD_ASSERT_UNKNOWN( res_is_par.size() == size_t(n_res) );\n# endif\n                // var2val_index\n                addr_t res_index = val_tape.record_call_op(\n                    atomic_index, call_id, n_res, val_op_arg\n                );\n                for(addr_t i = 0; i < n_res; ++i)\n                {   if( res_is_par[i] )\n                        par2val_index[ var_op_res[i] ] = res_index + i;\n                    else\n                        var2val_index[ var_op_res[i] ] = res_index + i;\n                }\n            }\n            break;\n        }\n    }\n    // dep_vec\n    size_t n_dependent = dep_taddr_.size();\n    Vector<addr_t> dep_vec(n_dependent);\n    for(size_t i = 0; i < n_dependent; ++i)\n        dep_vec[i] = var2val_index[ dep_taddr_[i] ];\n    val_tape.set_dep( dep_vec );\n}\n\n} // END_CPPAD_NAMESPACE\n// --------------------------------------------------------------------------\n# endif\n"
  },
  {
    "path": "include/cppad/local/val_graph/op2arg_index.hpp",
    "content": "# ifndef  CPPAD_LOCAL_VAL_GRAPH_OP2ARG_INDEX_HPP\n# define  CPPAD_LOCAL_VAL_GRAPH_OP2ARG_INDEX_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2023-23 Bradley M. Bell\n// ---------------------------------------------------------------------------\n# include <cppad/local/val_graph/tape.hpp>\n# include <cppad/local/val_graph/rev_depend.hpp>\nnamespace CppAD { namespace local { namespace val_graph {\n/*\n-------------------------------------------------------------------------------\n{xrst_begin val_op2arg_index dev}\n\nSet and Get the op2arg_index Vector\n###################################\nThis vector maps an operator index to the corresponding arg_index; i.e.,\nthe index in arg_vec of the first argument for this operator.\n\nset\n***\nThis ensures that the op2arg_index vector has been set.\n{xrst_literal\n    // BEGIN_SET_OP2ARG_INDEX\n    // END_SET_OP2ARG_INDEX\n}\n\nget\n***\nThis gets th op2arg_index vector.\nIf its size is zero, it has not been set.\n{xrst_literal\n    // BEGIN_OP2ARG_INDEX\n    // END_OP2ARG_INDEX\n}\n\n\n{xrst_end val_op2arg_index}\n*/\n// BEGIN_SET_OP2ARG_INDEX\ntemplate <class Value>\nvoid tape_t<Value>::set_op2arg_index(void)\n// END_SET_OP2ARG_INDEX\n{   if( 0 < op2arg_index_.size() )\n    {   CPPAD_ASSERT_UNKNOWN( op2arg_index_.size() == size_t( n_op() ) );\n        return;\n    }\n    //\n    // op2arg_indeex\n    Vector<addr_t> op2arg_index( n_op() );\n    op_iterator<Value> op_itr(*this, 0);\n    for(addr_t i_op = 0; i_op < n_op(); ++i_op)\n    {    op2arg_index[i_op] = op_itr.arg_index();\n        ++op_itr;\n    }\n    //\n    // op2arg_index_\n    // We needed a complete op2arg_index, before we could set op2arg_index_,\n    // otherwise op_iterator would not work properly.\n    op2arg_index_.swap(op2arg_index);\n}\n//\n// BEGIN_OP2ARG_INDEX\ntemplate <class Value>\nconst Vector<addr_t>& tape_t<Value>::op2arg_index(void) const\n// END_OP2ARG_INDEX\n{   return op2arg_index_; }\n\n} } } // END_CPPAD_LOCAL_VAL_GRAPH_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/val_graph/op_enum2class.hpp",
    "content": "# ifndef  CPPAD_LOCAL_VAL_GRAPH_OP_ENUM2CLASS_HPP\n# define  CPPAD_LOCAL_VAL_GRAPH_OP_ENUM2CLASS_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2023-23 Bradley M. Bell\n// ----------------------------------------------------------------------------\n// BEGIN_SORT_THIS_LINE_PLUS_1\n# include <cppad/local/val_graph/base_op.hpp>\n# include <cppad/local/val_graph/binary_op.hpp>\n# include <cppad/local/val_graph/call_op.hpp>\n# include <cppad/local/val_graph/cexp_op.hpp>\n# include <cppad/local/val_graph/comp_op.hpp>\n# include <cppad/local/val_graph/con_op.hpp>\n# include <cppad/local/val_graph/csum_op.hpp>\n# include <cppad/local/val_graph/dis_op.hpp>\n# include <cppad/local/val_graph/pri_op.hpp>\n# include <cppad/local/val_graph/unary_op.hpp>\n# include <cppad/local/val_graph/vector_op.hpp>\n// END_SORT_THIS_LINE_MINUS_1\n//\nnamespace CppAD { namespace local { namespace val_graph {\n/*\n{xrst_begin val_op_enum2class dev}\n\nMapping From Operator Enum To Class\n###################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_OP_ENUM2CLASS\n    // END_OP_ENUM2CLASS\n}\n\nPurpose\n*******\nConvert an operator enum type :ref:`val_graph_type@op_enum_t`\nto a pointer to an operator base class object :ref:`val_base_op-name` .\n\n{xrst_end val_op_enum2class}\n*/\n// ----------------------------------------------------------------------------\n// BEGIN_OP_ENUM2CLASS\n\n# define CPPAD_VAL_GRAPH_INSTANCE(name) \\\n    case name##_op_enum: \\\n    op_ptr = name##_op_t<Value>::get_instance(); \\\n    break;\n\ntemplate <class Value>\nbase_op_t<Value>* op_enum2class(op_enum_t op_enum)\n// END_OP_ENUM2CLASS\n{   //\n    base_op_t<Value>* op_ptr;\n    switch(op_enum)\n    {\n        default:\n        assert( false );\n        op_ptr = nullptr; // set in this case to avoid compiler warning\n        break;\n\n        // BEGIN_SORT_THIS_LINE_PLUS_1\n        CPPAD_VAL_GRAPH_INSTANCE(abs)\n        CPPAD_VAL_GRAPH_INSTANCE(acos)\n        CPPAD_VAL_GRAPH_INSTANCE(acosh)\n        CPPAD_VAL_GRAPH_INSTANCE(add)\n        CPPAD_VAL_GRAPH_INSTANCE(asin)\n        CPPAD_VAL_GRAPH_INSTANCE(asinh)\n        CPPAD_VAL_GRAPH_INSTANCE(atan)\n        CPPAD_VAL_GRAPH_INSTANCE(atanh)\n        CPPAD_VAL_GRAPH_INSTANCE(call)\n        CPPAD_VAL_GRAPH_INSTANCE(cexp)\n        CPPAD_VAL_GRAPH_INSTANCE(comp)\n        CPPAD_VAL_GRAPH_INSTANCE(con)\n        CPPAD_VAL_GRAPH_INSTANCE(cos)\n        CPPAD_VAL_GRAPH_INSTANCE(cosh)\n        CPPAD_VAL_GRAPH_INSTANCE(csum)\n        CPPAD_VAL_GRAPH_INSTANCE(dis)\n        CPPAD_VAL_GRAPH_INSTANCE(div)\n        CPPAD_VAL_GRAPH_INSTANCE(erf)\n        CPPAD_VAL_GRAPH_INSTANCE(erfc)\n        CPPAD_VAL_GRAPH_INSTANCE(exp)\n        CPPAD_VAL_GRAPH_INSTANCE(expm1)\n        CPPAD_VAL_GRAPH_INSTANCE(load)\n        CPPAD_VAL_GRAPH_INSTANCE(log)\n        CPPAD_VAL_GRAPH_INSTANCE(log1p)\n        CPPAD_VAL_GRAPH_INSTANCE(mul)\n        CPPAD_VAL_GRAPH_INSTANCE(neg)\n        CPPAD_VAL_GRAPH_INSTANCE(pow)\n        CPPAD_VAL_GRAPH_INSTANCE(pri)\n        CPPAD_VAL_GRAPH_INSTANCE(sign)\n        CPPAD_VAL_GRAPH_INSTANCE(sin)\n        CPPAD_VAL_GRAPH_INSTANCE(sinh)\n        CPPAD_VAL_GRAPH_INSTANCE(sqrt)\n        CPPAD_VAL_GRAPH_INSTANCE(store)\n        CPPAD_VAL_GRAPH_INSTANCE(sub)\n        CPPAD_VAL_GRAPH_INSTANCE(tan)\n        CPPAD_VAL_GRAPH_INSTANCE(tanh)\n        CPPAD_VAL_GRAPH_INSTANCE(vec)\n        // END_SORT_THIS_LINE_MINUS_1\n    }\n    return op_ptr;\n}\n\n# undef CPPAD_VAL_GRAPH_INSTANCE\n\n} } } // END_CPPAD_LOCAL_VAL_GRAPH_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/val_graph/op_hash_table.hpp",
    "content": "# ifndef  CPPAD_LOCAL_VAL_GRAPH_OP_HASH_TABLE_HPP\n# define  CPPAD_LOCAL_VAL_GRAPH_OP_HASH_TABLE_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2023-25 Bradley M. Bell\n// ---------------------------------------------------------------------------\n# include <cppad/local/sparse/size_setvec.hpp>\n# include <cppad/local/val_graph/tape.hpp>\n# include <cppad/local/is_pod.hpp>\n/*\n{xrst_begin val_op_hash_table dev}\n\nThe Value Operator Hash Table\n#############################\n\nConstructor\n***********\n{xrst_literal\n    // BEGIN_OP_HASH_TABLE_T\n    // END_OP_HASH_TABLE_T\n}\n\nop_hash_table\n=============\nThis is the operator hash table that is constructed\n\ntape\n====\nA reference to *tape* is stored in *op_hash_tale* ; i.e.,\n*tape* must not be destroyed before *op_hash_table* .\n\nop2arg_index\n============\nThis is a mapping from operator index to corresponding offset in the\ntape argument vector *tape*.var_arg_ .\n\nn_hash_code\n===========\nThis is the number of possible hash codes in the operator hash table\n*op_hash_table* .\n\nmatch_op\n********\n{xrst_literal\n    // BEGIN_MATCH_OP\n    // END_MATCH_OP\n}\n\nop_hash_table\n=============\nThis is a hash table for the tape.\n\ni_op\n====\nThis is the index of the operator that we are searching for a match.\n\nnew_val_index\n=============\nThis maps old value indices to new value indices\nfor indices less than the first result for the *i_op* operator.\nNew value indices are the result of using previous operator matches.\nFor arguments that are value indices,\nthe new indices are used when checking to see if operators match.\n\nj_op\n====\nThe return value *j_op* is the lowest operator index that corresponds to a\nmatch for *i_op* . If it is equal to *i_op* , then this operator has been placed\nin the hash table (for future matches).\nOtherwise *j_op* is less than *i_op* and its results are equivalent to *i_op*.\n\nsize_count\n**********\n{xrst_literal\n    // BEGIN_SIZE_COUNT\n    // END_SIZE_COUNT\n}\nFor each valid index *i*, *size_count* ()[ *i* ]\nis the number of hash code values, in the table, that have *i* collisions.\nA collision occurs when two operators that do not match have the same hash code.\n\n{xrst_end val_op_hash_table}\n*/\n\n// Tell pod_vector class that each size_setvec<addr_t>::pair_s_type is\n// plain old data and hence the corresponding constructor need not be called.\nnamespace CppAD { namespace local {\n# if ! CPPAD_IS_SAME_TAPE_ADDR_TYPE_SIZE_T\n    // This pair gets defined in list_setvec.hpp for the type size_t.\n    // Would be better to have conditional compile depending of if defined.\n    template <> inline bool\n    is_pod< sparse::size_setvec<addr_t>::pair_s_type > (void)\n    {   return true; }\n# endif\n} }\n\nnamespace CppAD { namespace local { namespace val_graph {\n\n// hash_value\ntemplate <class Value>\nsize_t hash_value(const Value& value)\n{\n    CPPAD_ASSERT_UNKNOWN( sizeof(unsigned short) == 2 );\n    CPPAD_ASSERT_UNKNOWN( sizeof(value) % 2  == 0 );\n    //\n    // v\n    const unsigned short* v\n                 = reinterpret_cast<const unsigned short*>(& value);\n    //\n    // sum\n    size_t i   = sizeof(value) / 2 - 1;\n    size_t sum = v[i];\n    while(i--)\n        sum += v[i];\n    //\n    return sum;\n}\n\n//\n// op_hash_table_t\ntemplate <class Value>\nclass op_hash_table_t {\nprivate:\n    //\n    // tape_\n    const tape_t<Value>& tape_;\n    //\n    // op2arg_index_\n    const Vector<addr_t>& op2arg_index_;\n    //\n    // table\n    CppAD::local::sparse::size_setvec<addr_t> table_;\n    //\n    // hash_code\n    addr_t hash_code(\n        const base_op_t<Value>* op_ptr        ,\n        addr_t                  arg_index     ,\n        const Vector<addr_t>&   new_val_index )\n    {   //\n        // arg_vec, con_vec, op_enum\n        const Vector<addr_t>& arg_vec = tape_.arg_vec();\n        const Vector<Value>&  con_vec = tape_.con_vec();\n        op_enum_t             op_enum = op_ptr->op_enum();\n        //\n        size_t code;\n        if( op_enum == con_op_enum )\n            code = hash_value( con_vec[  arg_vec[arg_index] ] );\n        else\n        {   addr_t n_arg    = op_ptr->n_arg(arg_index, arg_vec);\n            addr_t n_before = op_ptr->n_before();\n            addr_t n_after  = op_ptr->n_after();\n            //\n            // code\n            code = 0;\n            //\n            // These are auxiliary indices\n            for(addr_t i = 0; i < n_before; ++i)\n                code += size_t( arg_vec[arg_index + i] );\n            //\n            // These arguments are indices in the value vector, so check for a\n            // match with the lowest equivalent value vector index.\n            for(addr_t i = n_before; i < n_arg - n_after; ++i)\n                code += size_t( new_val_index[ arg_vec[arg_index + i] ] );\n            //\n            // These are auxiliary indices\n            for(addr_t i = n_arg - n_after; i < n_arg ; ++i)\n                code += size_t( arg_vec[arg_index + i] );\n        }\n        code = code % size_t( table_.n_set() );\n        return addr_t( code );\n    }\npublic:\n    // -------------------------------------------------------------------------\n    // BEGIN_OP_HASH_TABLE_T\n    // op_hash_table_t op_hash_table(tape, op2arg_index, n_hash_code)\n    op_hash_table_t(\n            const tape_t<Value>&     tape         ,\n            const Vector<addr_t>&    op2arg_index ,\n            addr_t                   n_hash_code  )\n    // END_OP_HASH_TABLE_T\n    : tape_( tape ), op2arg_index_(op2arg_index)\n    {   // table_\n        addr_t n_op = tape.n_op();\n        //\n        table_.resize( n_hash_code, n_op );\n    }\n    // -------------------------------------------------------------------------\n    // BEGIN_SIZE_COUNT\n    // size_count = op_hash_table.size_count()\n    Vector<addr_t> size_count(void)\n    // END_SIZE_COUNT\n    {   Vector<addr_t> count;\n        addr_t n_set  = table_.n_set();\n        for(addr_t i = 0; i < n_set; ++i)\n        {   addr_t number_elements = table_.number_elements(i);\n            if( size_t( number_elements ) >= count.size() )\n            {   size_t old_size = count.size();\n                addr_t new_size = number_elements + 1;\n                count.resize(new_size);\n                for(size_t j = old_size; j < new_size; ++j)\n                    count[j] = 0;\n            }\n            count[number_elements] += 1;\n        }\n        return count;\n    }\n    // -------------------------------------------------------------------------\n    // BEGIN_MATCH_OP\n    // j_op = op_hash_table.match_op(i_op, new_val_index)\n    addr_t match_op(addr_t i_op, const Vector<addr_t>& new_val_index)\n    // END_MATCH_OP\n    {   assert( i_op < table_.end() );\n        //\n        // arg_vec, con_vec\n        const Vector<addr_t>&    arg_vec     = tape_.arg_vec();\n        const Vector<Value>&     con_vec     = tape_.con_vec();\n        //\n        // op_enum, op_ptr\n        const base_op_t<Value>* op_ptr = tape_.base_op_ptr(i_op);\n        op_enum_t op_enum              = op_ptr->op_enum();\n        //\n        // arg_index, n_arg\n        addr_t arg_index = op2arg_index_[i_op];\n        addr_t n_arg     = op_ptr->n_arg(arg_index, arg_vec);\n        //\n        // nan\n        if( op_enum == con_op_enum )\n        {   if( CppAD::isnan( con_vec[ arg_vec[arg_index] ] ) )\n            {   CPPAD_ASSERT_UNKNOWN( op2arg_index_[0] == 0 );\n                CPPAD_ASSERT_UNKNOWN( arg_vec[0] == 0 );\n                CPPAD_ASSERT_UNKNOWN( CppAD::isnan( con_vec[0] ) );\n                return 0;\n            }\n        }\n        //\n        // code\n        addr_t code = hash_code(op_ptr, arg_index, new_val_index);\n        //\n        // itr\n        local::sparse::size_setvec_const_iterator<addr_t> itr(table_, code);\n        while( *itr != table_.end() )\n        {   // op_enum_j, arg_index_j\n            addr_t                  j_op = *itr;\n            const base_op_t<Value>* op_ptr_j = tape_.base_op_ptr(j_op);\n            op_enum_t op_enum_j   = op_ptr_j->op_enum();\n            addr_t    arg_index_j = op2arg_index_[j_op];\n            addr_t     n_arg_j    = op_ptr_j->n_arg(arg_index_j, arg_vec);\n            //\n            // match\n            bool match = (op_enum == op_enum_j) && (n_arg == n_arg_j);\n            if( match && op_enum == con_op_enum )\n            {   //\n                const Value& c = con_vec[ arg_vec[arg_index] ];\n                const Value& c_j = con_vec[ arg_vec[arg_index_j] ];\n                match            = IdenticalEqualCon(c, c_j);\n            }\n            else if( match )\n            {   addr_t n_before = op_ptr->n_before();\n                addr_t n_after  = op_ptr->n_after();\n                //\n                for(addr_t k = 0; k < n_before; ++k)\n                    match &= arg_vec[arg_index + k] == arg_vec[arg_index_j + k];\n                //\n                for(addr_t k = n_before; k < n_arg - n_after; ++k)\n                {   addr_t val_index   = new_val_index[ arg_vec[arg_index + k] ];\n                    addr_t val_index_j = new_val_index[ arg_vec[arg_index_j + k] ];\n                    match &= val_index == val_index_j;\n                }\n                //\n                for(addr_t k = n_arg - n_after; k < n_arg; ++k)\n                    match &= arg_vec[arg_index + k] == arg_vec[arg_index_j + k];\n                //\n                bool communative = op_enum == add_op_enum;\n                communative     |= op_enum == mul_op_enum;\n                if( communative && ! match )\n                {   addr_t val_index   = new_val_index[ arg_vec[arg_index + 0] ];\n                    addr_t val_index_j = new_val_index[ arg_vec[arg_index_j + 1] ];\n                    match = val_index == val_index_j;\n                    //\n                    val_index   = new_val_index[ arg_vec[arg_index + 1] ];\n                    val_index_j = new_val_index[ arg_vec[arg_index_j + 0] ];\n                    match &= val_index == val_index_j;\n                }\n            }\n            if( match )\n                return j_op;\n            //\n            // itr\n            ++itr;\n        }\n        table_.add_element(code, i_op);\n        return i_op;\n    }\n};\n} } } // END_CPPAD_LOCAL_VAL_GRAPH_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/local/val_graph/op_iterator.hpp",
    "content": "# ifndef  CPPAD_LOCAL_VAL_GRAPH_OP_ITERATOR_HPP\n# define  CPPAD_LOCAL_VAL_GRAPH_OP_ITERATOR_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// --------------------------------------------------------------------------\n/*\n------------------------------------------------------------------------------\n{xrst_begin val_op_iterator dev}\n\nClass For Iterating Over Operators in a Value Tape\n##################################################\n\nSyntax\n******\n| |tab| ``op_iterator`` < *Value* > *op_itr* ( *tape* , *op_index* )\n| |tab| *op_itr* . ``op_ptr`` ()\n| |tab| *op_itr* . ``arg_index`` ()\n| |tab| *op_itr* . ``res_index`` ()\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_CTOR\n    // END_CTOR\n}\n{xrst_literal\n    // BEGIN_MEMBER_FUNCTIONS\n    // END_MEMBER_FUNCTIONS\n}\n\nValue\n*****\nis the :ref:`val_tape@Value` type for the tape.\n\n\ntape\n****\nis the :ref:`val_tape-name` containing the operators we are\niterating over.\n\nop_index\n********\nis the operator index where the iterator starts.\nThis must be zero (for the beginning of the tape)\nor the number of operators in the tape (for the end of the tape).\n\nop_itr\n******\nis the operator iterator.\n\n{xrst_end val_op_iterator}\n*/\n# include <cppad/local/val_graph/op_enum2class.hpp>\n# include <cppad/core/cppad_assert.hpp>\n\n// BEGIN_CPPAD_LOCAL_VAL_GRAPH_NAMESPACE\nnamespace CppAD { namespace local { namespace val_graph  {\n\n//\n// tape_t;\ntemplate <class Value> class tape_t;\n\ntemplate <class Value>\nclass op_iterator {\n//\nprivate:\n    //\n    // tape_\n    const tape_t<Value>& tape_;\n    //\n    // op_ptr_\n    base_op_t<Value>* op_ptr_;\n    //\n    // op_index_\n    addr_t op_index_;\n    //\n    // arg_index_\n    addr_t arg_index_;\n    //\n    // res_index_\n    addr_t res_index_;\n    //\npublic:\n    //\n    // BEGIN_MEMBER_FUNCTIONS\n    const base_op_t<Value>* op_ptr(void) const\n    {   return op_ptr_; }\n    addr_t arg_index(void) const\n    {   return arg_index_; }\n    addr_t res_index(void) const\n    {   return res_index_; }\n    // END_MEMBER_FUNCTIONS\n    //\n    // BEGIN_CTOR\n    op_iterator(const tape_t<Value>& tape, addr_t op_index)\n    // END_CTOR\n    :\n    tape_ ( tape )         ,\n    op_ptr_(nullptr)       ,\n    op_index_ ( op_index )\n    {   addr_t n_op = tape.n_op();\n        //\n        if( op_index == 0 )\n        {   op_enum_t op_enum = op_enum_t( tape.op_enum_vec()[op_index] );\n            //\n            arg_index_ = 0;\n            res_index_ = tape.n_ind();\n            op_ptr_    = op_enum2class<Value>(op_enum);\n        }\n        else if( op_index == n_op )\n        {   arg_index_ = addr_t( tape.arg_vec().size() );\n            res_index_ = tape.n_val();\n        }\n        else\n        {   CPPAD_ASSERT_KNOWN( false,\n                \"op_iterator: op_index is not zero or number of operators in tape\"\n            );\n        }\n    }\n    //\n    // BEGIN_INCREMENT\n    void operator++(void)\n    // END_INCREMENT\n    {   CPPAD_ASSERT_KNOWN( op_index_ < addr_t( tape_.n_op() ),\n            \"op_iterator: attempt to increment past the end of the tape\"\n        );\n        //\n        // n_arg, n_res\n        addr_t n_arg = op_ptr_->n_arg(arg_index_, tape_.arg_vec());\n        addr_t n_res = op_ptr_->n_res(arg_index_, tape_.arg_vec());\n        //\n        // op_index_, arg_index_, res_index_\n        ++op_index_;\n        res_index_ += n_res;\n        //\n        // op_ptr_\n        if( op_index_ == tape_.n_op() )\n        {   op_ptr_    = nullptr;\n            arg_index_ = addr_t( tape_.arg_vec().size() ); // invalid value\n        }\n        else\n        {   if( tape_.op2arg_index().size() == 0 )\n                arg_index_ += n_arg;\n            else\n                arg_index_ = tape_.op2arg_index()[op_index_];\n            //\n            op_enum_t op_enum = op_enum_t( tape_.op_enum_vec()[op_index_] );\n            op_ptr_           = op_enum2class<Value>(op_enum);\n        }\n    }\n    //\n    // BEGIN_DECREMENT\n    void operator--(void)\n    // END_DECREMENT\n    {   CPPAD_ASSERT_KNOWN( 0 < op_index_,\n            \"op_iterator: attempt to decrement below the beginning of the tape\"\n        );\n        //\n        // op_index_\n        --op_index_;\n        //\n        // op_ptr_\n        op_enum_t op_enum = op_enum_t( tape_.op_enum_vec()[op_index_] );\n        op_ptr_           = op_enum2class<Value>(op_enum);\n        //\n        // n_after\n        addr_t n_after = op_ptr_->n_after();\n        CPPAD_ASSERT_UNKNOWN( n_after == 0 || n_after == 1 );\n        //\n        // arg_index_\n        if( 0 < tape_.op2arg_index().size() )\n            arg_index_ = tape_.op2arg_index()[op_index_];\n        else\n        {   addr_t n_arg;\n            if( n_after )\n                n_arg = tape_.arg_vec()[arg_index_ - 1];\n            else\n            {   // arg_index\n                // set to an invalid value for an index in the arg_vec vector.\n                addr_t arg_index = addr_t( tape_.arg_vec().size() );\n                n_arg = op_ptr_->n_arg(arg_index, tape_.arg_vec());\n            }\n            arg_index_ -= n_arg;\n        }\n        //\n        // res_index_\n        addr_t n_res = op_ptr_->n_res(arg_index_, tape_.arg_vec());\n        res_index_ -= n_res;\n    }\n};\n\n\n} } } // END_CPPAD_LOCAL_VAL_GRAPH_NAMESPACE\n// --------------------------------------------------------------------------\n# endif\n"
  },
  {
    "path": "include/cppad/local/val_graph/option.hpp",
    "content": "# ifndef  CPPAD_LOCAL_VAL_GRAPH_OPTION_HPP\n# define  CPPAD_LOCAL_VAL_GRAPH_OPTION_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2023-23 Bradley M. Bell\n// ---------------------------------------------------------------------------\n# include <cppad/local/val_graph/tape.hpp>\n\nnamespace CppAD { namespace local { namespace val_graph {\n/*\n-------------------------------------------------------------------------------\n{xrst_begin val_tape_option dev}\n\nSet an Option's Value\n#####################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_SET_OPTION\n    // END_SET_OPTION\n}\n\nkeep_compare\n************\nIf *name* is keep_compare, *value* must be true or false .\nIf it is false (true), :ref:`val_comp_op-name` operators will (will not)\nbe removed during :ref:`val_tape_dead_code-name` optimization.\n\nkeep_print\n**********\nIf *name* is keep_print, *value* must be true or false .\nIf it is false (true), :ref:`val_pri_op-name` operators will (will not)\nbe removed during dead code optimization.\n\n{xrst_end val_tape_option}\n*/\n// ---------------------------------------------------------------------------\n// BEGIN_INITIALIZE_OPTION\ntemplate <class Value>\nvoid tape_t<Value>::initialize_option(void)\n// END_INITIALIZE_OPTION\n{\n    option_map_[\"keep_compare\"] = \"true\";\n    option_map_[\"keep_print\"]   = \"true\";\n    //\n    return;\n}\n// ---------------------------------------------------------------------------\n// BEGIN_SET_OPTION\ntemplate <class Value>\nvoid tape_t<Value>::set_option(\n    const std::string& name  ,\n    const std::string& value )\n// END_SET_OPTION\n{   //\n    if( option_map_.find(name) == option_map_.end() )\n    {   std::string msg = \"value tape: There is no option named \" + name;\n        CPPAD_ASSERT_KNOWN(false, msg.c_str() );\n    }\n    if( value != \"true\" && value != \"false\" )\n    {   std::string msg = \"value tape: option [\" + name + \"]\";\n        msg            += \" value is not true or false \";\n        CPPAD_ASSERT_KNOWN(false, msg.c_str() );\n    }\n    option_map_[name] = value;\n    //\n    return;\n}\n\n} } } // END_CPPAD_LOCAL_VAL_GRAPH_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/local/val_graph/pri_op.hpp",
    "content": "# ifndef  CPPAD_LOCAL_VAL_GRAPH_PRI_OP_HPP\n# define  CPPAD_LOCAL_VAL_GRAPH_PRI_OP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2023-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/local/val_graph/base_op.hpp>\n\n// define CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL\n# include <cppad/utility/thread_alloc.hpp>\n\nnamespace CppAD { namespace local { namespace val_graph {\n/*\n{xrst_begin val_pri_op dev}\n{xrst_spell\n    str\n}\n\nThe Print Value Operator\n########################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_PRI_OP_T\n    // END_PRI_OP_T\n}\n\nContext\n*******\nThe class is derived from :ref:`val_base_op-name` .\nIt overrides all its base class virtual member functions\nand is a concrete class (it has no pure virtual functions).\n\nget_instance\n************\nThis static member function returns a pointer to a pri_op_t object.\n\nop_enum\n*******\nThis override of :ref:`val_base_op@op_enum` returns ``pri_op_enum`` .\n\nn_before\n********\nThis override of :ref:`val_base_op@n_before` returns 2.\n\nn_after\n*******\nThis override of :ref:`val_base_op@n_after` returns 0.\n\nn_arg\n*****\nThis override of :ref:`val_base_op@n_arg` returns 4.\n\nn_res\n*****\nThis override of :ref:`val_base_op@n_res` returns 0.\n\neval\n****\nThis override of :ref:`val_base_op@eval` defines the following values:\n\n.. csv-table::\n    :header: Type,Name,Definition\n\n    string, *before*  ,  str_vec[ arg_vec[ arg_index + 0 ] ]\n    string, *after*   ,  str_vec[ arg_vec[ arg_index + 1 ] ]\n    Value,    *flag*  ,  val_vec[ arg_vec[ arg_index + 2 ] ]\n    Value,    *value* ,  val_vec[ arg_vec[ arg_index + 3 ] ]\n\nbefore\n======\nThis text is printed before the value.\n\nafter\n=====\nThis text is printed after the value.\n\nflag\n====\nIf *flag* is less than or equal zero, print the output.\nIf *flag* is greater than zero, nothing is printed by this operator.\nIn the special case where\n\n    arg_vec[ arg_index + 2] == tape.n_ind()\n\n*flag* has the value nan and nothing is printed.\nThis fact is used by :ref:`val_tape_renumber-name` to change repeated\nprints of the same value to no-ops.\nThe :ref:`val_tape_dead_code-name` routine will remove this operators.\n\nvalue\n=====\nThis value is printed between *before* and *after*.\n\ntrace\n=====\nIf trace is true, :ref:`val_print_pri_op-name`\nis used to print this operator.\nPrinting the operator is separate from printing the value.\n\n{xrst_toc_hidden\n    val_graph/pri_xam.cpp\n}\nExample\n*******\nThe file :ref:`pri_xam.cpp <val_pri_xam.cpp-name>`\nis an example and test that uses this operator.\n\n{xrst_end val_pri_op}\n*/\n// BEGIN_PRI_OP_T\ntemplate <class Value>\nclass pri_op_t : public base_op_t<Value> {\npublic:\n    // n_before\n    addr_t n_before(void) const override\n    {   return 2; }\n    //\n    // n_after\n    addr_t n_after(void) const override\n    {   return 0; }\n    //\n    // get_instance\n    static pri_op_t* get_instance(void)\n    {   CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL;\n        static pri_op_t instance;\n        return &instance;\n    }\n    // op_enum\n    op_enum_t op_enum(void) const override\n    {   return pri_op_enum; }\n// END_PRI_OP_T\n    //\n    // n_arg\n    addr_t n_arg(\n        addr_t                arg_index    ,\n        const Vector<addr_t>& arg_vec      ) const override\n    {   return 4; }\n    //\n    // n_res\n    addr_t n_res(\n        addr_t                arg_index    ,\n        const Vector<addr_t>& arg_vec      ) const override\n    {   return 0; }\n    //\n    // eval\n    void eval(\n        const tape_t<Value>*      tape          ,\n        bool                      trace         ,\n        addr_t                    arg_index     ,\n        addr_t                    res_index     ,\n        Vector<Value>&            val_vec       ,\n        Vector< Vector<addr_t> >& ind_vec_vec   ,\n        size_t&                   compare_false ) const override\n    {   //\n        // arg_vec, str_vec\n        const Vector<addr_t>&       arg_vec( tape->arg_vec() );\n        const Vector<std::string>&  str_vec( tape->str_vec() );\n        //\n        // Special case where flag is nan and this is a no op.\n        if( arg_vec[ arg_index + 2] == tape->n_ind() )\n            return;\n        //\n        // arg\n        Vector<addr_t> arg(4);\n        for(addr_t i = 0; i < 4; ++i)\n            arg[i] = arg_vec[ arg_index + i ];\n        //\n        if( trace )\n        {   // print_pri_op(before_index, after_index, flag_index, value_index)\n            print_pri_op(arg[0], arg[1], arg[2], arg[3]);\n        }\n        //\n        // before, after, flag, value\n        const std::string& before  = str_vec[ arg[0] ];\n        const std::string& after   = str_vec[ arg[1] ];\n        const Value&       flag    = val_vec[ arg[2] ];\n        const Value&       value   = val_vec[ arg[3] ];\n        if( flag <= Value(0) )\n            std::cout << before << value << after;\n    }\n};\n\n} } } // END_CPPAD_LOCAL_VAL_GRAPH_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/val_graph/print_op.hpp",
    "content": "# ifndef  CPPAD_LOCAL_VAL_GRAPH_PRINT_OP_HPP\n# define  CPPAD_LOCAL_VAL_GRAPH_PRINT_OP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2023-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <iostream>\n# include <iomanip>\n/*\n{xrst_begin_parent val_print_op dev}\n\nPrinting Value Operators\n########################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_PRINT_OP\n    // END_PRINT_OP\n}\n\nOutput Notation\n***************\n#. The first column is a value index and the second column is the\n   corresponding value.\n#. Values inside of parenthesis are arguments that are result indices\n   for the operator name  that comes before the left parenthesis.\n#. Values inside of brackets are indices for vector name that\n   comes before the left bracket.\n\nname\n****\nIs the name of this operator. In the case of a function call operator,\nit is the name of the function being called.\n\nval_arg\n*******\nis a vector containing the operator arguments that are value indices\n(in order).\n\nres_index\n*********\nis the index of the first result for this operator.\n\nres_value\n*********\nis a non-empty vector of results for this operator.\n\nSpecial Cases\n*************\n{xrst_toc_table\n}\n\n{xrst_end val_print_op}\n*/\n\n// BEGIN_CPPAD_LOCAL_VAL_GRAPH_NAMESPACE\nnamespace CppAD { namespace local { namespace val_graph {\n\n// BEGIN_PRINT_OP\ntemplate <class Value>\nvoid print_op(\n    const std::string&    name            ,\n    const Vector<addr_t>& val_arg         ,\n    addr_t                res_index       ,\n    const Vector<Value>&  res_value       )\n// END_PRINT_OP\n{  size_t n_arg = val_arg.size();\n    size_t n_res = res_value.size();\n    using std::setw;\n    using std::right;\n    using std::cout;\n    //\n    // One result\n    if( n_res == 1 )\n    {  cout << right << setw(5) << res_index;\n        cout << \" \" << right << setw(10) << res_value[0];\n        cout << \" = \" << right << setw(5)  << name << \"(\";\n        for(size_t i = 0; i < n_arg; ++i)\n        {  cout << right << setw(5) << std::right << val_arg[i];\n            if( i + 1 < n_arg )\n                cout << \",\";\n        }\n        cout << \")\" << std::endl;\n        return;\n    }\n    //\n    // Multiple results\n    CPPAD_ASSERT_UNKNOWN( n_res > 1 );\n    cout << right << setw(5) << name << \"(\";\n    for(size_t i = 0; i < n_arg; ++i)\n    {  cout << right << setw(5) << val_arg[i];\n        if( i + 1 < n_arg )\n                cout << \",\";\n        else\n                cout << \")\";\n    }\n    for(addr_t i = 0; i < addr_t( n_res ); ++i)\n    {  cout << std::endl;\n        cout << right << setw(5) << res_index + i;\n        cout << \" \" << setw(10) << res_value[i];\n    }\n    cout << std::endl;\n}\n/*\n------------------------------------------------------------------------------\n{xrst_begin val_print_con_op dev}\n\nPrinting Constant Operators\n###########################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_PRINT_CON_OP\n    // END_PRINT_CON_OP\n}\n\narg\n***\nis a vector containing all the operator arguments (must be length one).\n\nres_index\n*********\nis the index of the result for this operator.\n\nres_value\n*********\nis a vector of results for this operator (must be length one).\n\n{xrst_end val_print_con_op}\n*/\n// BEGIN_PRINT_CON_OP\ntemplate <class Value>\nvoid print_con_op(\n    const Vector<addr_t>& arg             ,\n    addr_t                res_index       ,\n    const Vector<Value>&  res_value       )\n// END_PRINT_CON_OP\n{  CPPAD_ASSERT_UNKNOWN( arg.size() == 1 );\n    CPPAD_ASSERT_UNKNOWN( res_value.size() == 1 );\n    using std::setw;\n    using std::right;\n    using std::cout;\n    {  cout << right << setw(5) << res_index;\n        cout << \" \" << right << setw(10) << res_value[0];\n        cout << \" = \" << right << setw(5)  << \"con\" << \"[\";\n        cout << right << setw(5) << std::right << arg[0] << \"]\";\n        cout << std::endl;\n        return;\n    }\n}\n/*\n------------------------------------------------------------------------------\n{xrst_begin val_print_csum_op dev}\n\nPrinting Cumulative Summation Operators\n#######################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_PRINT_CSUM_OP\n    // END_PRINT_CSUM_OP\n}\n\narg\n***\nis a vector containing all the operator arguments (must be length one).\n\nres_index\n*********\nis the index of the result for this operator.\n\nres_value\n*********\nis a vector of results for this operator (must be length one).\n\n{xrst_end val_print_csum_op}\n*/\n// BEGIN_PRINT_CSUM_OP\ntemplate <class Value>\nvoid print_csum_op(\n    const Vector<addr_t>& arg             ,\n    addr_t                res_index       ,\n    const Vector<Value>&  res_value       )\n// END_PRINT_CSUM_OP\n{  CPPAD_ASSERT_UNKNOWN( res_value.size() == 1);\n    //\n    using std::setw;\n    using std::right;\n    using std::cout;\n    //\n    // n_add, n_sub\n    addr_t n_add = arg[0];\n    addr_t n_sub = arg[1];\n    //\n    CPPAD_ASSERT_UNKNOWN( arg.size() == size_t(3 + n_add + n_sub ) );\n    //\n    cout << right << setw(5) << res_index;\n    cout << \" \" << right << setw(10) << res_value[0] << \" = \";\n    if( n_add > 0 )\n    {  cout << right << setw(5)  << \"csum+\" << \"(\";\n        for(addr_t i = 0; i < n_add; ++i)\n        {  cout << right << setw(5) << arg[2 + i];\n            if( i + 1 < n_add )\n                cout << \",\";\n        }\n        cout << \")\" << std::endl;\n        if( n_sub > 0 )\n        {  cout << setw(19) << \"\" << right << setw(5)  << \"csum-\" << \"(\";\n            for(addr_t i = 0; i < n_sub; ++i)\n            {  cout << right << setw(5) << arg[2 + n_add + i];\n                if( i + 1 < n_sub )\n                    cout << \",\";\n            }\n            cout << \")\" << std::endl;\n        }\n    }\n    else\n    {  CPPAD_ASSERT_UNKNOWN( n_sub > 0 );\n        cout << right << setw(5)  << \"csum-\" << \"(\";\n        for(addr_t i = 0; i < n_sub; ++i)\n        {  cout << right << setw(5) << arg[2 + n_add + i];\n            if( i + 1 < n_sub )\n                cout << \",\";\n        }\n        cout << \")\" << std::endl;\n    }\n}\n/*\n------------------------------------------------------------------------------\n{xrst_begin val_print_comp_op dev}\n\nPrinting Compare Operators\n##########################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_PRINT_COMP_OP\n    // END_PRINT_COMP_OP\n}\n\ncomp_name\n*********\nis the name of the comparison operator; e.g., \"lt\"\n\nleft_index\n**********\nis the value index corresponding to the left operand in the comparison.\n\nright_index\n***********\nis the value index corresponding to the right operand in the comparison.\n\nresult\n******\nis the result of the comparison.\n\n{xrst_end val_print_comp_op}\n*/\n// BEGIN_PRINT_COMP_OP\ninline void print_comp_op(\n    const char* comp_name   ,\n    addr_t      left_index  ,\n    addr_t      right_index ,\n    bool        result      )\n// END_PRINT_COMP_OP\n{  //\n    using std::setw;\n    using std::right;\n    using std::cout;\n    //\n    const char* res_str;\n    if( result )\n        res_str = \"true\";\n    else\n        res_str = \"false\";\n    //\n    cout << setw(19) << \"\" << right << setw(5)  << comp_name << \"(\";\n    cout << right << setw(5) << left_index  << \",\";\n    cout << right << setw(5) << right_index << \") = \";\n    cout << right << setw(5) << res_str << std::endl;\n}\n/*\n------------------------------------------------------------------------------\n{xrst_begin val_print_pri_op dev}\n{xrst_spell\n    str\n}\n\nPrinting Print Operators\n########################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_PRINT_PRI_OP\n    // END_PRINT_PRI_OP\n}\n\nbefore_index\n************\nis the index in str_vec corresponding to the before text.\n\nafter_index\n***********\nis the index in str_vec corresponding to the after text.\n\nflag_index\n**********\nis the index in the value vector corresponding to the flag.\n\nvalue_index\n***********\nis the index in the value vector corresponding to the value that is printed\nif the flag is positive.\n\n\n{xrst_end val_print_pri_op}\n*/\n// BEGIN_PRINT_PRI_OP\ninline void print_pri_op(\n    addr_t       before_index ,\n    addr_t       after_index  ,\n    addr_t       flag_index   ,\n    addr_t       value_index  )\n// END_PRINT_PRI_OP\n{  //\n    using std::setw;\n    using std::right;\n    using std::cout;\n    //\n    cout << setw(19) << \"\" << right << setw(5)  << \"pri\" << \"[\";\n    cout << right << setw(5) << before_index  << \",\";\n    cout << right << setw(5) << after_index   << \"](\";\n    cout << right << setw(5) << flag_index    << \",\";\n    cout << right << setw(5) << value_index << \")\" << std::endl;\n}\n/*\n------------------------------------------------------------------------------\n{xrst_begin val_print_store_op dev}\n\nPrinting Store Operators\n########################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_PRINT_STORE_OP\n    // END_PRINT_STORE_OP\n}\n\nwhich_vector\n************\nis the index in val_vec_vec corresponding to this vector.\n\nvector_index\n************\nis the index in val_vec corresponding to the index for this vector element.\n\nvalue_index\n***********\nis the index in val_vec corresponding to the new value for this vector element.\n\n\n{xrst_end val_print_store_op}\n*/\n// BEGIN_PRINT_STORE_OP\ninline void print_store_op(\n    addr_t       which_vector ,\n    addr_t       vector_index ,\n    addr_t       value_index  )\n// END_PRINT_STORE_OP\n{  //\n    using std::setw;\n    using std::right;\n    using std::cout;\n    //\n    cout << setw(19) << \"\" << right << setw(5)  << \"store\" << \"[\";\n    cout << right << setw(5) << which_vector  << \"](\";\n    cout << right << setw(5) << vector_index  << \",\";\n    cout << right << setw(5) << value_index << \")\" << std::endl;\n}\n/*\n------------------------------------------------------------------------------\n{xrst_begin val_print_load_op dev}\n\nPrinting Load Operators\n#######################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_PRINT_LOAD_OP\n    // END_PRINT_LOAD_OP\n}\n\nwhich_vector\n************\nis the index in val_vec_vec corresponding to this vector.\n\nvector_index\n************\nis the index in val_vec corresponding to the index for this vector element.\n\nres_index\n*********\nin the index in val_vec corresponding to the result for this operator.\n\n{xrst_end val_print_load_op}\n*/\n// BEGIN_PRINT_LOAD_OP\ntemplate <class Value>\ninline void print_load_op(\n    addr_t       which_vector ,\n    addr_t       vector_index ,\n    addr_t       res_index    ,\n    const Value& res_value    )\n// END_PRINT_LOAD_OP\n{  //\n    using std::setw;\n    using std::right;\n    using std::cout;\n    //\n    cout << right << setw(5) << res_index;\n    cout << \" \" << right << setw(10) << res_value;\n    cout << \" = \" << setw(5)  << \"load\" << \"[\";\n    cout << right << setw(5) << which_vector  << \"](\";\n    cout << right << setw(5) << vector_index << \")\" << std::endl;\n}\n/*\n------------------------------------------------------------------------------\n{xrst_begin val_print_vec_op dev}\n\nPrinting New Dynamic Vector Operators\n#####################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_PRINT_VEC_OP\n    // END_PRINT_VEC_OP\n}\n\nwhich_vector\n************\nis the index in val_vec_vec corresponding to this vector.\n\ninitial\n*******\nis the vector of indices in val_vec (the value vector)\ncorresponding to the initial values for this dynamic vector.\n\n{xrst_end val_print_vec_op}\n*/\n// BEGIN_PRINT_VEC_OP\ninline void print_vec_op(\n    addr_t                which_vector ,\n    const Vector<addr_t>& initial      )\n// END_PRINT_VEC_OP\n{   //\n    using std::setw;\n    using std::right;\n    using std::cout;\n    //\n    cout << setw(19) << \"\" << right << setw(5)  << \"vec\" << \"[\";\n    cout << right << setw(5) << which_vector  << \"](\";\n    for(size_t i = 0; i < initial.size(); ++i)\n    {   cout << right << setw(5) << initial[i];\n        if( i + 1 < initial.size() )\n            cout << \",\";\n    }\n    cout << \")\" << std::endl;\n}\n\n} } } // END_CPPAD_LOCAL_VAL_GRAPH_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/val_graph/record.hpp",
    "content": "# ifndef  CPPAD_LOCAL_VAL_GRAPH_RECORD_HPP\n# define  CPPAD_LOCAL_VAL_GRAPH_RECORD_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2023-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/local/val_graph/tape.hpp>\n# include <cppad/local/val_graph/op_enum2class.hpp>\n# include <cppad/core/numeric_limits.hpp>\n//\nnamespace CppAD { namespace local { namespace val_graph {\n/*\n{xrst_begin_parent val_record dev}\n\nRecording Value Operations on a Tape\n####################################\n\nPurpose\n*******\nThese operations store a function in the :ref:`val_tape-name`.\n\n{xrst_end val_record}\n------------------------------------------------------------------------------\n{xrst_begin val_set_ind dev}\n{xrst_spell\n    str\n}\n\nSetting Independent Variables\n#############################\n\nset_ind\n*******\n{xrst_literal\n    // BEGIN_SET_IND\n    // END_SET_IND\n}\nThis is the first step in a creating a recording. It does the following:\n\n#. Clear all of the memory that is currently used by the tape except\n   for the options settings.\n#. Set the number of independent values.\n#. The empty string is placed in the string constant vector str_vec\\_.\n   This string has index zero in the string constant vector str_vec\\_.\n#. Place the constant nan directly after the last independent value.\n   This value has index zero in the value constant vector con_vec\\_.\n#. The return value is the index in the value vector where the nan\n   will be placed; i.e., *n_ind* .\n\nDirectly after this operation:\n{xrst_literal\n    // BEGIN_POST_CONDITION\n    // END_POST_CONDITION\n}\n\n{xrst_end val_set_ind}\n*/\n// ----------------------------------------------------------------------------\n// BEGIN_SET_IND\ntemplate <class Value>\naddr_t tape_t<Value>::set_ind(addr_t n_ind)\n// END_SET_IND\n{  Value nan = CppAD::numeric_limits<Value>::quiet_NaN();\n    n_ind_ = n_ind;\n    n_val_ = n_ind;\n    var_arg_.clear();\n    con_vec_.clear();\n    str_vec_.clear();\n    vec_initial_.clear();\n    dep_vec_.clear();\n    op_enum_vec_.clear();\n    op2arg_index_.clear();\n    // option_map_ does not change during this operation.\n# if CPPAD_VAL_GRAPH_TAPE_TRACE\n    // set_ind_inue\n    size_t thread  = thread_alloc::thread_num();\n    set_ind_inuse_ = thread_alloc::inuse(thread);\n# endif\n    //\n    str_vec_.push_back( \"\" );\n    addr_t nan_addr = record_con_op(nan);\n    assert( n_val_ == n_ind + 1 );\n    //\n    // BEGIN_POST_CONDITION\n    CPPAD_ASSERT_UNKNOWN( op_enum_vec_.size() == 1 ); // one operator\n    CPPAD_ASSERT_UNKNOWN( var_arg_.size() == 1 );     // one argument\n    CPPAD_ASSERT_UNKNOWN( con_vec_.size() == 1 );     // one value constant\n    CPPAD_ASSERT_UNKNOWN( str_vec_[0] == \"\" );        // empty string\n    CPPAD_ASSERT_UNKNOWN( vec_initial_.size() == 0 );    // no dynamic vectors\n    CPPAD_ASSERT_UNKNOWN( nan_addr == n_ind );        // return value\n    return nan_addr;\n    // END_POST_CONDITION\n}\n/*\n-------------------------------------------------------------------------------\n{xrst_begin val_set_dep dev}\n\nSetting the Dependent Variables\n###############################\n\nset_dep\n*******\n{xrst_literal\n    // BEGIN_SET_DEP\n    // END_SET_DEP\n}\nThis sets the dependent vector to the corresponding indices\nin the value vector.\nThis is last step in creating a recording.\n\n{xrst_end val_set_dep}\n*/\n// ----------------------------------------------------------------------------\n// BEGIN_SET_DEP\ntemplate <class Value>\nvoid tape_t<Value>::set_dep(const Vector<addr_t>& dep_vec)\n// END_SET_DEP\n{   dep_vec_ = dep_vec;\n# if CPPAD_VAL_GRAPH_TAPE_TRACE\n    // inuse\n    size_t thread        = thread_alloc::thread_num();\n    size_t set_dep_inuse = thread_alloc::inuse(thread);\n    std::cout << \"tape:       inuse = \" << set_dep_inuse-set_ind_inuse_ << \"\\n\";\n# endif\n}\n/*\n-------------------------------------------------------------------------------\n{xrst_begin val_record_op dev}\n\nRecording Operators with One Result\n###################################\n\nrecord_op\n*********\n{xrst_literal\n    // BEGIN_RECORD_OP\n    // END_RECORD_OP\n}\nThis can be used to place any operator that has one result in the tape;\ne.g., the unary and binary operators.\n\nop_enum\n*******\nThe argument identifies the operator.\n\nop_arg\n******\nThe vector contains the arg_vec values for this operator.\nIts size must be equal to :ref:`val_base_op@n_arg` for this operator.\n\nreturn\n******\nThe return value is the index were the result of the operation\nis placed in the value vector.\n\n{xrst_end val_record_op}\n*/\n// ----------------------------------------------------------------------------\n// BEGIN_RECORD_OP\ntemplate <class Value>\naddr_t tape_t<Value>::record_op(op_enum_t op_enum, const Vector<addr_t>& op_arg)\n// END_RECORD_OP\n{  //\n    // res_index\n    addr_t res_index = n_val_;\n# ifndef NDEBUG\n    // arg_index\n    addr_t arg_index = addr_t( var_arg_.size() );\n# endif\n    //\n    // op_enum_vec_\n    op_enum_vec_.push_back( uint8_t( op_enum ) );\n    //\n    // var_arg_\n    for(size_t i = 0; i < op_arg.size(); ++i)\n        var_arg_.push_back( op_arg[i] );\n    //\n    // n_val_\n    ++n_val_;\n    //\n# ifndef NDEBUG\n    base_op_t<Value>* op_ptr = op_enum2class<Value>(op_enum);\n    CPPAD_ASSERT_UNKNOWN(\n        size_t( op_ptr->n_arg(arg_index, var_arg_) ) == op_arg.size()\n    );\n    CPPAD_ASSERT_UNKNOWN(\n        size_t( op_ptr->n_res(arg_index, var_arg_) ) == 1\n    );\n# endif\n    //\n    return res_index;\n}\n/*\n{xrst_betin val_record_con_op dev}\n\nRecording Constants\n###################\n\nrecord_con_op\n*************\n{xrst_literal\n    // BEGIN_RECORD_CON_OP\n    // END_RECORD_CON_OP\n}\nThis places a :ref:`val_con_op-name` operator in the tape.\nThe return value is the index were *constant* will be placed\nin the value vector.\nNote that if *constant* is nan, the return value will always be *n_ind*; i.e,\nonly one nan gets paced in the constant vector.\n\n{xrst_end val_record_con_op}\n*/\n// ----------------------------------------------------------------------------\n// BEGIN_RECORD_CON_OP\ntemplate <class Value>\naddr_t tape_t<Value>::record_con_op(const Value& constant)\n// END_RECORD_CON_OP\n{  //\n    // nan\n    if( op_enum_vec_.size() == 0 )\n    {  CPPAD_ASSERT_UNKNOWN( CppAD::isnan(constant) && n_val_ == n_ind_ );\n    }\n    else if( CppAD::isnan(constant) )\n        return n_ind_;\n    //\n    // con_index\n    addr_t con_index = addr_t( con_vec_.size() );\n    con_vec_.push_back( constant );\n    //\n    // res_index\n    addr_t res_index = n_val_;\n    //\n    // op_enum_vec_\n    op_enum_vec_.push_back( uint8_t( con_op_enum ) );\n    //\n    // var_arg_\n    var_arg_.push_back( con_index );\n    //\n    // n_val_\n    ++n_val_;\n    //\n    return res_index;\n}\n/*\n-------------------------------------------------------------------------------\n{xrst_begin val_record_dis_op dev}\n\nRecording The Discrete Operations\n#################################\n\nrecord_dis_op\n*************\n{xrst_literal\n    // BEGIN_RECORD_DIS_OP\n    // END_RECORD_DIS_OP\n}\nThis places a :ref:`val_dis_op-name` operator in the tape.\nThe argument *discrete_index* identifies which discrete function to use.\nThe argument *val_index* is the index of the operand\nin the value vector.\nThe return value is the index were the result will be placed\nin the value vector.\n{xrst_end val_record_dis_op}\n*/\n// ----------------------------------------------------------------------------\n// BEGIN_RECORD_DIS_OP\ntemplate <class Value>\naddr_t tape_t<Value>::record_dis_op(addr_t discrete_index, addr_t val_index)\n// END_RECORD_DIS_OP\n{  //\n    // res_index\n    addr_t res_index = n_val_;\n    //\n    // op_enum_vec_\n    op_enum_vec_.push_back( uint8_t( dis_op_enum ) );\n    //\n    // var_arg_\n    var_arg_.push_back( discrete_index );\n    var_arg_.push_back( val_index );\n    //\n    // n_val_\n    ++n_val_;\n    //\n    return res_index;\n}\n/*\n------------------------------------------------------------------------------\n{xrst_begin val_record_comp_op dev}\n\nRecording Comparison Operations\n###############################\n\nrecord_comp_op\n**************\n{xrst_literal\n    // BEGIN_RECORD_COMP_OP\n    // END_RECORD_COMP_OP\n}\nThis places a :ref:`val_comp_op-name` operator in the tape.\nThe return value is always zero because there is\nno value vector result for this operator.\n\ncompare_enum\n============\nThis identifies which comparison is done by this use of the compare operator.\n\nleft_index\n==========\nThis is the value vector index for the left operand in the comparison.\n\nright_index\n===========\nThis is the value vector index for the right operand in the comparison.\n\nreturn\n======\nThe return value is zero because this operator does not have a result\n(and zero is used for an invalid result value).\n\n{xrst_end val_record_comp_op}\n*/\n// ----------------------------------------------------------------------------\n// BEGIN_RECORD_COMP_OP\ntemplate <class Value>\naddr_t tape_t<Value>::record_comp_op(\n    compare_enum_t compare_enum ,\n    addr_t         left_index   ,\n    addr_t         right_index  )\n// END_RECORD_COMP_OP\n{  // res_index\n    addr_t res_index = 0; // invalid result index\n    //\n    // op_enum_vec_\n    op_enum_vec_.push_back( uint8_t( comp_op_enum ) );\n    //\n    // var_arg_\n    var_arg_.push_back( addr_t(compare_enum) );\n    var_arg_.push_back( left_index );\n    var_arg_.push_back( right_index );\n    //\n    return res_index;\n}\n/*\n------------------------------------------------------------------------------\n{xrst_begin val_record_call_op dev}\n\nRecording Call Operations\n#########################\n\nrecord_call_op\n**************\n{xrst_literal\n    // BEGIN_RECORD_CALL_OP\n    // END_RECORD_CALL_OP\n}\nThis places a :ref:`val_call_op-name` operator in the tape.\n\natomic_index\n============\nThis is the *atomic_index* for the atomic function; see\n:ref:`atomic_index@index_out` in the case where *index_in* is zero.\n\ncall_id\n=======\nThis is the *call_id* for this use of the atomic function; see\n:ref:`atomic_four_call@call_id` .\n\nn_res\n=====\nThis is the number of values returned by the atomic function call\nand placed in the value vector.\n\nfun_arg\n=======\nThis vector has size equal to the number of arguments to the atomic function\nfor this *call_id* .\n(The combination of *atomic_index* and *call_id* must specify a function.)\nThe *j*-th element of *fun_arg* is the index on the value vector of\nthe *j*-th argument to the function.\n\nreturn\n======\nThe ``record_con_op`` function returns the index in the value vector where\nthe first result is placed in the value vector.\nA total of *n_res* results are placed in the value vector.\n\n{xrst_end val_record_call_op}\n*/\n// ----------------------------------------------------------------------------\n// BEGIN_RECORD_CALL_OP\ntemplate <class Value>\naddr_t tape_t<Value>::record_call_op(\n    addr_t  atomic_index          ,\n    addr_t  call_id               ,\n    addr_t  n_res                 ,\n    const Vector<addr_t>& fun_arg )\n// END_RECORD_CALL_OP\n{  //\n    // res_index\n    addr_t res_index = n_val_;\n    //\n    // op_enum_vec_\n    op_enum_vec_.push_back( uint8_t( call_op_enum ) );\n    //\n    // var_arg_\n    addr_t n_arg = 5 + addr_t( fun_arg.size() );\n    var_arg_.push_back( n_arg );\n    var_arg_.push_back( n_res );\n    var_arg_.push_back( atomic_index );\n    var_arg_.push_back( call_id );\n    for(size_t i = 0; i < fun_arg.size(); ++i)\n        var_arg_.push_back( fun_arg[i] );\n    var_arg_.push_back( n_arg );\n    //\n    // n_val_\n    n_val_ = n_val_ + addr_t(n_res);\n    //\n    return res_index;\n}\n/*\n------------------------------------------------------------------------------\n{xrst_begin val_record_csum_op dev}\n\nRecording Cumulative Summation Operations\n#########################################\n\nrecord_csum_op\n**************\n{xrst_literal\n    // BEGIN_RECORD_CSUM_OP\n    // END_RECORD_CSUM_OP\n}\nThis places a :ref:`val_csum_op-name` operator in the tape.\n\nadd\n===\nThis is the vector of value indices corresponding to the values\nthat are added to the sum.\n\nsub\n===\nThis is the vector of value indices corresponding to the values\nthat are subtracted from the sum.\n\nreturn\n======\nThe ``record_con_op`` function returns the index in the value vector where\nthe sum is placed.\n\n{xrst_end val_record_csum_op}\n*/\n// ----------------------------------------------------------------------------\n// BEGIN_RECORD_CSUM_OP\ntemplate <class Value>\naddr_t tape_t<Value>::record_csum_op(\n    const Vector<addr_t>& add ,\n    const Vector<addr_t>& sub )\n// END_RECORD_CSUM_OP\n{  //\n    // n_add, n_sub, n_arg\n    addr_t n_add = addr_t( add.size() );\n    addr_t n_sub = addr_t( sub.size() );\n    addr_t n_arg = 3 + n_add + n_sub;\n    //\n    // res_index\n    addr_t res_index = n_val_;\n    //\n    // op_enum_vec_\n    op_enum_vec_.push_back( uint8_t( csum_op_enum ) );\n    //\n    // var_arg_\n    var_arg_.push_back( n_add );\n    var_arg_.push_back( n_sub );\n    for(size_t i = 0; i < add.size(); ++i)\n        var_arg_.push_back( add[i] );\n    for(size_t i = 0; i < sub.size(); ++i)\n        var_arg_.push_back( sub[i] );\n    var_arg_.push_back( n_arg );\n    //\n    // n_val_\n    ++n_val_;\n    //\n    return res_index;\n}\n/*\n------------------------------------------------------------------------------\n{xrst_begin val_record_cexp_op dev}\n\nRecording Comparison Operations\n###############################\n\nrecord_cexp_op\n**************\n{xrst_literal\n    // BEGIN_RECORD_CEXP_OP\n    // END_RECORD_CEXP_OP\n}\nThis places a :ref:`val_cexp_op-name` operator in the tape.\n\ncompare_enum\n============\nThis identifies which comparison is used by this conditional expression.\n\nleft\n====\nThis is the value vector index for the left operand in the comparison.\n\nright\n=====\nThis is the value vector index for the right operand in the comparison.\n\nif_true\n=======\nThis is the index of the value of the value that is used for the result if\nthe comparison is true.\n\nif_false\n========\nThis is the index of the value of the value that is used for the result if\nthe comparison is false.\n\nreturn\n======\nThe ``record_con_op`` function returns the index in the value vector where\nthe result is placed in the value vector.\n\n{xrst_end val_record_cexp_op}\n*/\n// ----------------------------------------------------------------------------\n// BEGIN_RECORD_CEXP_OP\ntemplate <class Value>\naddr_t tape_t<Value>::record_cexp_op(\n    compare_enum_t comp_enum ,\n    addr_t         left      ,\n    addr_t         right     ,\n    addr_t         if_true   ,\n    addr_t         if_false  )\n// END_RECORD_CEXP_OP\n{   //\n    // res_index\n    addr_t res_index = n_val_;\n    //\n    // op_enum_vec_\n    op_enum_vec_.push_back( uint8_t(cexp_op_enum) );\n    //\n    // var_arg_\n    var_arg_.push_back( addr_t(comp_enum) );\n    var_arg_.push_back( left );\n    var_arg_.push_back( right );\n    var_arg_.push_back( if_true );\n    var_arg_.push_back( if_false );\n    //\n    // n_val_\n    ++n_val_;\n    //\n    return res_index;\n}\n/*\n------------------------------------------------------------------------------\n{xrst_begin val_record_pri_op dev}\n{xrst_spell\n    str\n}\n\nRecording Print Operations\n##########################\n\nrecord_pri_op\n*************\n{xrst_literal\n    // BEGIN_RECORD_PRI_OP\n    // END_RECORD_PRI_OP\n}\nThis places a :ref:`val_pri_op-name` operator in the tape.\nThe return value is always zero because there is\nno value vector result for this operator.\n\nbefore\n======\nThis is the text that is printed before the value when *flag* is positive.\nIf a previous str_vec\\_ entry is equal to before, it is used.\nOtherwise a new entry equal to before is added to str_vec\\_.\n\nafter\n=====\nThis is the text that is printed after the value when *flag* is positive.\nIf a previous str_vec\\_ entry is equal to after, it is used.\nOtherwise a new entry equal to after is added to str_vec\\_.\n\nflag_index\n==========\nThis is the value vector index for the flag operand.\n\nvalue_index\n===========\nThis is the value vector index for the value that is printed\nwhen the flag is positive.\n\nreturn\n======\nThe return value is zero because this operator does not have a result\n(and zero is used for an invalid result value).\n\n{xrst_end val_record_pri_op}\n*/\n// ----------------------------------------------------------------------------\n// BEGIN_RECORD_PRI_OP\ntemplate <class Value>\naddr_t tape_t<Value>::record_pri_op(\n    const std::string& before      ,\n    const std::string& after       ,\n    addr_t             flag_index  ,\n    addr_t             value_index )\n// END_RECORD_PRI_OP\n{  //\n    // str_index\n    using std::string;\n    auto str_index = [](const string& str, Vector<string>& str_vec)\n    {  size_t result = str_vec.size();\n        for(size_t i = 0; i < str_vec.size(); ++i)\n        {  if( str == str_vec[i] )\n                result = i;\n        }\n        if( result == str_vec.size() )\n            str_vec.push_back(str);\n        return addr_t( result );\n    };\n    // empty string\n    CPPAD_ASSERT_UNKNOWN( str_vec_[0] == \"\" );\n    //\n    // res_index\n    addr_t res_index = 0; // invalid result index\n    //\n    // op_enum_vec_\n    op_enum_vec_.push_back( uint8_t(pri_op_enum) );\n    //\n    // str_vec_, var_arg_: before_index\n    addr_t before_index = str_index(before, str_vec_);\n    var_arg_.push_back( before_index );\n    //\n    // str_vec_, var_arg_: after_index\n    addr_t after_index = str_index(after, str_vec_);\n    var_arg_.push_back( after_index );\n    //\n    // var_arg_: flag_index, value_index\n    var_arg_.push_back( flag_index );\n    var_arg_.push_back( value_index );\n    //\n    return res_index;\n}\n/*\n------------------------------------------------------------------------------\n{xrst_begin val_record_vec_op dev}\n\nRecord Adding a Dynamic Vector\n##############################\n\nrecord_vec_op\n*************\n{xrst_literal\n    // BEGIN_RECORD_VEC_OP\n    // END_RECORD_VEC_OP\n}\nThis creates a new dynamic vector with the specified initial values.\nA dynamic vector must be created before a load or store can be recorded\nfor the corresponding vector.\n\ninitial\n*******\nThe size of this vector is the size of the dynamic vector being created.\nThe initial value for the dynamic vector at index *vector_index* is\nthe value vector at index *initial*[ *vector_index* ]; i.e.,\n\n    *val_vec* [ *initial* [ *vector_index* ] ]\n\nwhere *val_vec* is the value vector.\n\nwhich_vector\n************\nThe return value is an index identifying\nwhich dynamic vector is created.\nThis is the *which_vector* argument for subsequent\n:ref:`load <val_load_op@eval@which_vector>` and\n:ref:`store <val_store_op@eval@which_vector>` operators\nthat use this dynamic vector.\n\n\n{xrst_end val_record_vec_op}\n*/\n// BEGIN_RECORD_VEC_OP\ntemplate <class Value>\naddr_t tape_t<Value>::record_vec_op(const Vector<addr_t>& initial)\n// END_RECORD_VEC_OP\n{  //\n    // which_vector\n    addr_t which_vector = addr_t( vec_initial_.size() );\n    //\n    // vec_initial_\n    vec_initial_.push_back( initial );\n    //\n    // op_enum_vec_\n    op_enum_vec_.push_back( uint8_t(vec_op_enum) );\n    //\n    // var_arg_\n    var_arg_.push_back( which_vector );\n    //\n    return which_vector;\n}\n/*\n------------------------------------------------------------------------------\n{xrst_begin val_record_load_op dev}\n\nRecording Load Operations\n#########################\n\nrecord_load_op\n**************\n{xrst_literal\n    // BEGIN_RECORD_LOAD_OP\n    // END_RECORD_LOAD_OP\n}\nThis places a :ref:`val_load_op-name` operator in the tape.\n\nwhich_vector\n============\nThis is the index returned by :ref:`val_vec_op-name`\nwhen it created this dynamic vector.\n\nvector_index\n============\nThis is the index, in the value vector, of the index in the dynamic vector,\nof the element for this load operation.\n\nreturn\n******\nThe return value is the index were the result of the operation\nis placed in the value vector.\n\n{xrst_end val_record_load_op}\n*/\n// ----------------------------------------------------------------------------\n// BEGIN_RECORD_LOAD_OP\ntemplate <class Value>\naddr_t tape_t<Value>::record_load_op(\n    addr_t   which_vector  ,\n    addr_t   vector_index  )\n// END_RECORD_LOAD_OP\n{  //\n    // check that vec_op_enum comes before load_op_enum\n    CPPAD_ASSERT_UNKNOWN( size_t(which_vector) < vec_initial_.size() );\n    //\n    // res_index\n    addr_t res_index = n_val_;\n    //\n    // op_enum_vec_\n    op_enum_vec_.push_back( uint8_t(load_op_enum) );\n    //\n    // var_arg_\n    var_arg_.push_back( which_vector );\n    var_arg_.push_back( vector_index );\n    //\n    // n_val_\n    ++n_val_;\n    //\n    return res_index;\n}\n/*\n------------------------------------------------------------------------------\n{xrst_begin val_record_store_op dev}\n\nRecording Store Operations\n##########################\n\nrecord_store_op\n***************\n{xrst_literal\n    // BEGIN_RECORD_STORE_OP\n    // END_RECORD_STORE_OP\n}\nThis places a :ref:`val_store_op-name` operator in the tape.\n\nwhich_vector\n============\nThis is the index returned by :ref:`val_vec_op-name`\nwhen it created this dynamic vector.\n\nvector_index\n============\nThis is the index, in the value vector, of the index in the dynamic vector,\nof the element for this store operation.\n\nreturn\n******\nThe return value is always zero because there is\nno value vector result for this operator.\n\n{xrst_end val_record_store_op}\n*/\n// ----------------------------------------------------------------------------\n// BEGIN_RECORD_STORE_OP\ntemplate <class Value>\naddr_t tape_t<Value>::record_store_op(\n    addr_t   which_vector  ,\n    addr_t   vector_index  ,\n    addr_t   value_index   )\n// END_RECORD_STORE_OP\n{   //\n    // check that vec_op_enum comes before store_op_enum\n    CPPAD_ASSERT_UNKNOWN( size_t(which_vector) < vec_initial_.size() );\n    //\n    // res_index\n    addr_t res_index = 0;\n    //\n    // op_enum_vec_\n    op_enum_vec_.push_back( uint8_t(store_op_enum) );\n    //\n    // var_arg_\n    var_arg_.push_back( which_vector );\n    var_arg_.push_back( vector_index );\n    var_arg_.push_back( value_index  );\n    //\n    return res_index;\n}\n\n} } } // END_CPPAD_LOCAL_VAL_GRAPH_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/val_graph/record_new.hpp",
    "content": "# ifndef  CPPAD_LOCAL_VAL_GRAPH_RECORD_NEW_HPP\n# define  CPPAD_LOCAL_VAL_GRAPH_RECORD_NEW_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2023-25 Bradley M. Bell\n// ---------------------------------------------------------------------------\n# include <cppad/local/val_graph/op_iterator.hpp>\nnamespace CppAD { namespace local { namespace val_graph {\n/*\n{xrst_begin val_record_new dev}\n\nCopy an Old Operator to a New Tape\n##################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_RECORD_NEW\n    // END_RECORD_NEW\n}\n\nOld Tape\n********\nWe refer to ``*this`` as the old tape.\n\nnew_tape\n********\nThe is the new tape that the operator is recorded on.\n\nnew_which_vec\n*************\nThis vector has size ``vec_initial_.size()`` .\nIt is a mapping from each dynamic vector index in the old tape\nto the corresponding dynamic vector index in the new tape.\n\n#. This starts out as the invalid value\n   ``vec_initial_.size()`` for each old dynamic vector index.\n\n#. If the operator being recorded is an ``vec_op_enum`` operator,\n   a dynamic vector is added to the new tape and the corresponding\n   *new_which_vec* entry is modified.\n\n#. If this is a load or store operation, *new_which_vec* is used to map\n   from the dynamic vector index in the old tape to the dynamic vector\n   index in the new tape.\n\nwork\n****\nThis is work space used by record_new and not otherwise specified.\n\nnew_val_index\n*************\nThis vector has size ``n_val()``\nbut it is only defined for indices less than *res_index* (see below).\nIt is a mapping from each value index in the old tape\nto the corresponding value index in the new tape.\n\nval_use_case\n************\nIf *val_use_case* [ *val_index* ] is zero,\nthe value with index *val_index* is not needed to compute\nthe dependent variables.\n\nop_ptr\n******\nThis is a pointer to the :ref:`val_base_op-name` for the operator on this tape.\n\narg_index\n*********\nThis is the value index corresponding to the first argument for the operator\non this tape.\n\nres_index\n*********\nThis is the value index corresponding to the first result for the operator\non this tape.\n\nnew_res_index\n*************\nThis is the value index in the new tape that corresponds to the first result\nfor this operator.\n\n{xrst_end val_record_new}\n*/\n// BEGIN_RECORD_NEW\n// new_res_index = record_new( ... )\ntemplate <class Value>\naddr_t tape_t<Value>::record_new(\n    tape_t&                   new_tape         ,\n    Vector<addr_t>&           new_which_vec    ,\n    Vector<addr_t>&           work             ,\n    const Vector<addr_t>&     new_val_index    ,\n    const Vector<addr_t>&     val_use_case     ,\n    const base_op_t<Value>*   op_ptr           ,\n    addr_t                    arg_index        ,\n    addr_t                    res_index        )\n// END_RECORD_NEW\n{\n    //\n    // op_arg\n    Vector<addr_t>& op_arg(work);\n    //\n    // new_res_index\n    // set to avoid compiler warning\n    addr_t new_res_index = 0;\n    //\n    // op_enum, n_arg, n_before, n_after, n_res\n    op_enum_t  op_enum   = op_ptr->op_enum();\n    addr_t     n_before  = op_ptr->n_before();\n    addr_t     n_after   = op_ptr->n_after();\n    addr_t     n_arg     = op_ptr->n_arg(arg_index, var_arg_);\n    addr_t     n_res     = op_ptr->n_res(arg_index, var_arg_);\n    //\n    // new_tape, new_res_index\n    bool simple = n_res == 1;\n    simple     &= op_enum != con_op_enum;\n    simple     &= op_enum != call_op_enum;\n    simple     &= op_enum != load_op_enum;\n    if( simple )\n    {   op_arg.resize(n_arg);\n        for(addr_t k = 0; k < n_before; ++k)\n            op_arg[k] = var_arg_[arg_index + k];\n        for(addr_t k = n_before; k < n_arg - n_after; ++k)\n        {   addr_t old_index = var_arg_[arg_index + k];\n            assert( old_index < res_index );\n            CPPAD_ASSERT_UNKNOWN( val_use_case[old_index] != 0 );\n            op_arg[k] = new_val_index[old_index];\n        }\n        for(addr_t k = 1; k <= n_after; ++k)\n            op_arg[n_arg - k] = var_arg_[arg_index + n_arg - k];\n        //\n        new_res_index = new_tape.record_op(op_enum, op_arg);\n    }\n    else switch( op_enum )\n    {   //\n        // default\n        default:\n        CPPAD_ASSERT_UNKNOWN(false);\n        //\n        // new_res_index\n        break;\n        //\n        // load_op_enum\n        // new_val_index\n        case load_op_enum:\n        CPPAD_ASSERT_UNKNOWN( n_res == 1);\n        {   addr_t which_vector = new_which_vec[ var_arg_[arg_index + 0] ];\n            addr_t vector_index = new_val_index[ var_arg_[arg_index + 1] ];\n            //\n            // record_con_op, new_val_index\n            new_res_index = new_tape.record_load_op( which_vector, vector_index);\n        }\n        break;\n        //\n        // con_op_enum\n        // new_val_index\n        case con_op_enum:\n        CPPAD_ASSERT_UNKNOWN( n_res == 1 );\n        {   Value value = con_vec_[ var_arg_[ arg_index ] ];\n            //\n            // record_con_op, new_val_index\n            new_res_index = new_tape.record_con_op(value);\n        }\n        break;\n        //\n        // store_op_enum\n        case store_op_enum:\n        CPPAD_ASSERT_UNKNOWN( n_res == 0 );\n        {   addr_t which_vector = new_which_vec[ var_arg_[arg_index + 0] ];\n            addr_t vector_index = new_val_index[ var_arg_[arg_index + 1] ];\n            addr_t value_index  = new_val_index[ var_arg_[arg_index + 2] ];\n            CPPAD_ASSERT_UNKNOWN( val_use_case[ var_arg_[arg_index + 1] ] != 0 );\n            CPPAD_ASSERT_UNKNOWN( val_use_case[ var_arg_[arg_index + 2] ] != 0 );\n            new_tape.record_store_op(\n                which_vector, vector_index, value_index\n            );\n        }\n        break;\n        //\n        // vec_op_enum\n        case vec_op_enum:\n        CPPAD_ASSERT_UNKNOWN( n_res == 0 );\n        {   addr_t old_which_vector       = var_arg_[arg_index + 0];\n            const Vector<addr_t>& initial = vec_initial_[old_which_vector];\n            addr_t which_vector           = new_tape.record_vec_op(initial);\n            //\n            // new_which_vec\n            new_which_vec[old_which_vector] = which_vector;\n        }\n        break;\n        //\n        // comp_op_enum\n        case comp_op_enum:\n        CPPAD_ASSERT_UNKNOWN( n_res == 0 );\n        {   compare_enum_t compare_enum;\n            compare_enum       = compare_enum_t( var_arg_[arg_index + 0] );\n            addr_t left_index  = new_val_index[ var_arg_[arg_index + 1] ];\n            addr_t right_index = new_val_index[ var_arg_[arg_index + 2] ];\n            CPPAD_ASSERT_UNKNOWN( val_use_case[ var_arg_[arg_index + 1] ] != 0 );\n            CPPAD_ASSERT_UNKNOWN( val_use_case[ var_arg_[arg_index + 2] ] != 0 );\n            new_tape.record_comp_op(\n                compare_enum, left_index, right_index\n            );\n        }\n        break;\n        //\n        // pri_op_enum\n        CPPAD_ASSERT_UNKNOWN( n_res == 0 );\n        case pri_op_enum:\n        {   std::string before = str_vec_[ var_arg_[arg_index + 0] ];\n            std::string after  = str_vec_[ var_arg_[arg_index + 1] ];\n            addr_t left_index  = new_val_index[ var_arg_[arg_index + 2] ];\n            addr_t right_index = new_val_index[ var_arg_[arg_index + 3] ];\n            CPPAD_ASSERT_UNKNOWN( val_use_case[ var_arg_[arg_index + 2] ] != 0 );\n            CPPAD_ASSERT_UNKNOWN( val_use_case[ var_arg_[arg_index + 3] ] != 0 );\n            new_tape.record_pri_op(\n                before, after, left_index, right_index\n            );\n        }\n        break;\n        //\n        // call_op_enum\n        // new_val_index\n        case call_op_enum:\n        {   //\n            // n_x\n            addr_t n_x = n_arg - n_before - op_ptr->n_after();\n# ifndef NDEBUG\n            bool one_arg_needed = false;\n# endif\n            //\n            op_arg.resize(n_x);\n            for(addr_t k = 0; k < n_x; ++k)\n            {   addr_t val_index = var_arg_[arg_index + n_before + k];\n                if( val_use_case[val_index] != 0 )\n                {   op_arg[k] = new_val_index[val_index];\n# ifndef NDEBUG\n                    one_arg_needed =  true;\n# endif\n                }\n                else\n                {   // nan in the new tape\n                    op_arg[k] = new_tape.n_ind();\n                }\n            }\n            CPPAD_ASSERT_UNKNOWN( one_arg_needed );\n            addr_t atomic_index = var_arg_[arg_index + 2];\n            addr_t call_id      = var_arg_[arg_index + 3];\n            new_res_index       = new_tape.record_call_op(\n                atomic_index, call_id, n_res, op_arg\n            );\n        }\n        break;\n    }\n    return new_res_index;\n}\n\n} } } // END_CPPAD_LOCAL_VAL_GRAPH_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/val_graph/renumber.hpp",
    "content": "# ifndef  CPPAD_LOCAL_VAL_GRAPH_RENUMBER_HPP\n# define  CPPAD_LOCAL_VAL_GRAPH_RENUMBER_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2023-25 Bradley M. Bell\n// ---------------------------------------------------------------------------\n# include <cppad/local/val_graph/op_hash_table.hpp>\n\n/*\n-------------------------------------------------------------------------------\n{xrst_begin val_tape_renumber dev}\n{xrst_spell\n    dep\n}\n\nValue Re-Numbering\n##################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_RENUMBER\n    // END_RENUMBER\n}\n\nDiscussion\n**********\nThis routine uses hash coding to find operators that are equivalent\nto a previous operators in the tape.\nIt changes the use of an operator's results to use of the\nresults for the equivalent previous operator with lowest index.\nThis creates an equivalent tape where replaced operators are not removed,\nbut the are dead code in the new tape.\n\nCompare Operators\n*****************\nIf two or more compare operators are identical, the first will be kept as\nis and the others will be changed to compare_no_enum operators.\nIn this case future calls to eval will on add one to\n:ref:`val_tape@eval@compare_false`,\nfor each unique comparison that is false.\nbe removed.\n\nChanges\n*******\nOnly the following values, for this tape, are guaranteed to be same:\n#. The number of independent values :ref:`val_tape@n_ind` .\n#. The size of the dependent vector :ref:`dep_vec.size() <val_tape@dep_vec>` .\n#. The mapping from the independent to the dependent variables.\n\nReference\n*********\n`value numbering <https://en.wikipedia.org/wiki/Value_numbering>`_ .\n\n{xrst_toc_hidden\n    val_graph/renumber_xam.cpp\n}\nExample\n*******\nThe file :ref:`renumber_xam.cpp <val_renumber_xam.cpp-name>` is an\nexample and test of tape.renumber().\n\n{xrst_end val_tape_renumber}\n-------------------------------------------------------------------------------\n*/\nnamespace CppAD { namespace local { namespace val_graph {\n\n// BEGIN_RENUMBER\ntemplate <class Value>\nvoid tape_t<Value>::renumber(void)\n// END_RENUMBER\n{\n    // -----------------------------------------------------------------------\n    // SAS Global Value Renumbering\n    // https://en.wikipedia.org/wiki/Value_numbering\n    // -----------------------------------------------------------------------\n# if CPPAD_VAL_GRAPH_TAPE_TRACE\n    // thread, initial_inuse\n    size_t thread        = thread_alloc::thread_num();\n    size_t initial_inuse = thread_alloc::inuse(thread);\n# endif\n    //\n    // op2arg_index, op2res_index\n    Vector<addr_t> op2arg_index( n_op() ), op2res_index( n_op() );\n    {   op_iterator<Value> op_itr(*this, 0);\n        for(addr_t i_op = 0; i_op < n_op(); ++i_op)\n        {   op2arg_index[i_op] = op_itr.arg_index();\n            op2res_index[i_op] = op_itr.res_index();\n            ++op_itr;\n        }\n    }\n    //\n    // op_hash_table\n    addr_t n_hash_code = 1 + (n_val_ / 2);\n    op_hash_table_t<Value>  op_hash_table(*this, op2arg_index, n_hash_code);\n    //\n    // new_val_index\n    // value used for operators that are not replaced.\n    Vector<addr_t> new_val_index( n_val_ );\n    for(addr_t i = 0; i < addr_t(n_val_); ++i)\n        new_val_index[i] = i;\n    //\n    // i_op\n    for(addr_t i_op = 0; i_op < n_op(); ++i_op)\n    {   //\n        // op_ptr\n        const base_op_t<Value>* op_ptr   = base_op_ptr(i_op);\n        //\n        // arg_index_i, res_index_i\n        addr_t arg_index_i = op2arg_index[i_op];\n        addr_t res_index_i = op2res_index[i_op];\n        //\n        // j_op\n        addr_t j_op = op_hash_table.match_op(i_op, new_val_index);\n        if( j_op != i_op )\n        {   assert( j_op < i_op );\n            //\n            // new_val_index\n            // mapping so that op_j results will be used instead of op_i results;\n            // i.e., op_i becomes dead code.\n            addr_t res_index_j = op2res_index[j_op];\n            addr_t n_res       = op_ptr->n_res(arg_index_i, var_arg_);\n            if( n_res == 0 )\n            {   //\n                // change the i_op operator to a no op\n                if( op_ptr->op_enum() == pri_op_enum )\n                    var_arg_[arg_index_i + 2] = this->n_ind();\n                else\n                {\n                    CPPAD_ASSERT_UNKNOWN( op_ptr->op_enum() == comp_op_enum );\n                    var_arg_[arg_index_i + 0] = compare_no_enum;\n                }\n            }\n            else for(addr_t k = 0; k < n_res; ++k)\n                new_val_index[res_index_i + k] = res_index_j + k;\n        }\n    }\n    //\n    // var_arg_\n    for(addr_t i_op = 0; i_op < n_op(); ++i_op)\n    {   //\n        // op_ptr\n        const base_op_t<Value>* op_ptr   = base_op_ptr(i_op);\n        //\n        // arg_index, n_arg\n        addr_t    arg_index = op2arg_index[i_op];\n        addr_t    n_arg     = op_ptr->n_arg(arg_index, var_arg_);\n        //\n        // n_before, n_x\n        addr_t n_before = op_ptr->n_before();\n        addr_t n_x = n_arg - n_before - op_ptr->n_after();\n        //\n        for(addr_t i = 0; i < n_x; ++i)\n        {   addr_t val_index = arg_index + n_before + i;\n            var_arg_[val_index] = new_val_index[ var_arg_[val_index] ];\n        }\n    }\n    //\n    // dep_vec_\n    for(size_t i = 0; i < dep_vec_.size(); ++i)\n        dep_vec_[i] = new_val_index[ dep_vec_[i] ];\n\n# if CPPAD_VAL_GRAPH_TAPE_TRACE\n    // A set size more than one represents a collision\n    Vector<addr_t> size_count = op_hash_table.size_count();\n    for(size_t i = 0; i < size_count.size(); ++i)\n        std::cout << \"size = \" << i << \", count = \" << size_count[i] << \"\\n\";\n    //\n    // inuse\n    size_t final_inuse = thread_alloc::inuse(thread);\n    std::cout << \"renumber:   inuse = \" << final_inuse - initial_inuse << \"\\n\";\n# endif\n    return;\n}\n} } } // END_CPPAD_LOCAL_VAL_GRAPH_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/local/val_graph/rev_depend.hpp",
    "content": "# ifndef  CPPAD_LOCAL_VAL_GRAPH_REV_DEPEND_HPP\n# define  CPPAD_LOCAL_VAL_GRAPH_REV_DEPEND_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2023-25 Bradley M. Bell\n// ---------------------------------------------------------------------------\n# include <cppad/local/val_graph/tape.hpp>\n# include <cppad/local/atomic_index.hpp>\nnamespace CppAD { namespace local { namespace val_graph {\n/*\n{xrst_begin val_tape_rev_depend dev}\n\nReverse Dependency Analysis\n###########################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_REV_DEPEND\n    // END_REV_DEPEND\n}\n\ntape\n****\nIs the :ref:`val_tape-name` that we are analyzing.\n\nval_use_case\n************\nThis vector is empty on input.\nUpon return, it has size equal to the number of values; i.e.,\n:ref:`val_tape@n_val` .\n\nZero\n====\nIf *val_use_case* [ *val_index* ] is zero,\nthe value with index *val_index* is not needed\nto compute the dependent variables.\n\nn_op\n====\nIf *val_use_case* [ *val_index* ] is equal to n_op (the number of operators),\nthe value with index *val_index* satisfies one of the following conditions:\n\n#. It is a dependent variable.\n#. It is used by more than one operator.\n#. It is used more than once by one operator and that operator is not a\n   binary operator.\n\nOtherwise\n=========\nIf *val_use_case* [ *val_index* ] is not zero or n_op,\nit is the index of the only operator that\nuses the value with index *val_index* as an argument.\n\nvec_last_load\n*************\nThis vector is empty on input.\nUpon return, it has size equal the number of dynamic vectors; i.e.,\nvec_size\\_.size() .\nThe value\n\n    *i_op* = *vec_last_load* [ *which_vector* ]\n\nis the index of the last load operator,\nthat used the dynamic vector with index *which_vector* ,\nand is needed to compute the dependent variables.\n\nImprovement\n===========\nThis could be done differently as a vector of maps.\n\n    *i_op* = *vec_last_load*[ *which_vector* ] [ *value_index* ]\n\nwould be the operator index of the last load operator with the same\n:ref:`val_load_op@eval@which_vector` and :ref:`val_load_op@eval@vector_index` .\nThen we could avoid two stores to the same vector and index with no\nload in between.\n\n{xrst_end val_tape_rev_depend}\n*/\n// BEGIN_REV_DEPEND\n// tape.rev_depend(val_use_case, vec_last_load)\ntemplate <class Value>\nvoid tape_t<Value>::rev_depend(\n    Vector<addr_t>& val_use_case  ,\n    Vector<addr_t>& vec_last_load )\n// END_REV_DEPEND\n{   CPPAD_ASSERT_UNKNOWN( val_use_case.size() == 0 );\n    CPPAD_ASSERT_UNKNOWN( vec_last_load.size() == 0 );\n    //\n# if CPPAD_VAL_GRAPH_TAPE_TRACE\n    // thread, initial_inuse\n    size_t thread        = thread_alloc::thread_num();\n    size_t initial_inuse = thread_alloc::inuse(thread);\n# endif\n    //\n    // con_x, type_x, depend_x, depend_y\n    // use CppAD::vector because call_atomic_rev_depend expect it\n    CppAD::vector<Value> con_x;\n    CppAD::vector<ad_type_enum> type_x;\n    CppAD::vector<bool> depend_x, depend_y;\n    //\n    // val_index2con\n    Vector< Vector<Value> > val_vec_vec( vec_initial_.size() );\n    for(size_t i = 0; i < vec_initial_.size(); ++i)\n        val_vec_vec[i].resize( vec_initial_[i].size() );\n    Value nan = CppAD::numeric_limits<Value>::quiet_NaN();\n    Vector<Value> val_index2con(n_val_);\n    for(addr_t i = 0; i < n_val_; ++i)\n        val_index2con[i] = nan;\n    bool trace           = false;\n    eval(trace, val_index2con);\n    //\n    // val_use_case\n    // initialize as no operator uses any value\n    val_use_case.resize(n_val_);\n    for(addr_t i = 0; i < n_val_; ++i)\n        val_use_case[i] = 0;\n    //\n    // vec_last_load\n    // initialize as the no operator uses any dynamic vector\n    vec_last_load.resize( vec_initial_.size() );\n    for(size_t i = 0; i < vec_initial_.size(); ++i)\n        vec_last_load[i] = 0;\n    //\n    // val_use_case\n    for(size_t i = 0; i < dep_vec_.size(); ++i)\n        val_use_case[ dep_vec_[i] ] = n_op(); // result is a dependent var\n    //\n    // inc_val_use_case\n    auto inc_val_use_case =\n        [this, &val_use_case](addr_t val_index, addr_t op_index)\n    {   if( val_use_case[val_index] == 0 )\n            val_use_case[val_index] = op_index; // only used by this operator\n        else\n            val_use_case[val_index] = n_op();   // is used multiple times\n    };\n    //\n    // op_itr\n    op_iterator<Value> op_itr(*this, n_op() );\n    //\n    // use_case\n    addr_t i_op = n_op();\n    while( i_op-- )\n    {   //\n        // op_itr\n        --op_itr;\n        //\n        // op_ptr, arg_index, res_index\n        const base_op_t<Value>* op_ptr    = op_itr.op_ptr();\n        addr_t                  res_index = op_itr.res_index();\n        addr_t                  arg_index = op_itr.arg_index();\n        //\n        // op_enum, n_before, n_after, n_arg, n_res, is_binary\n        op_enum_t op_enum   = op_ptr->op_enum();\n        addr_t    n_before  = op_ptr->n_before();\n        addr_t    n_after   = op_ptr->n_after();\n        addr_t    n_arg     = op_ptr->n_arg(arg_index, var_arg_);\n        addr_t    n_res     = op_ptr->n_res(arg_index, var_arg_);\n        bool      is_binary = op_ptr->is_binary();\n        //\n        if( 0 < n_res && op_enum != call_op_enum )\n        {   CPPAD_ASSERT_UNKNOWN( n_res == 1 );\n            //\n            // need_op\n            bool need_op = bool( val_use_case[res_index + 0] );\n            //\n            // val_use_case\n            if( need_op )\n            {   if( is_binary )\n                {   addr_t left_index  = var_arg_[arg_index + 0];\n                    addr_t right_index = var_arg_[arg_index + 1];\n                    inc_val_use_case(left_index, i_op);\n                    if( left_index != right_index )\n                        inc_val_use_case(right_index, i_op);\n                }\n                else if( op_enum == load_op_enum )\n                {   CPPAD_ASSERT_UNKNOWN( i_op != 0 );\n                    addr_t which_vector = var_arg_[arg_index + 0];\n                    addr_t val_index    = var_arg_[arg_index + 1];\n                    if( vec_last_load[which_vector] == 0 )\n                        vec_last_load[which_vector] = i_op;\n                    inc_val_use_case(val_index, i_op);\n                }\n                else\n                {   for(addr_t i = n_before; i < n_arg - n_after; ++i)\n                    {   addr_t val_index = var_arg_[arg_index + i];\n                        inc_val_use_case(val_index, i_op);\n                    }\n                }\n            }\n        }\n        else if( 0 < n_res )\n        {   //\n            // call_op_enum\n            CPPAD_ASSERT_UNKNOWN( op_enum == call_op_enum );\n            //\n            size_t atomic_index  = size_t( var_arg_[arg_index + 2] );\n            size_t call_id       = size_t( var_arg_[arg_index + 3] );\n            //\n            // n_x\n            addr_t n_x = n_arg - n_before - n_after;\n            size_t nx  = size_t(n_x);\n            //\n            // con_x, type_x\n            con_x.resize(nx);\n            type_x.resize(nx);\n            for(addr_t i = 0; i < n_x; ++i)\n            {   con_x[i] = val_index2con[ var_arg_[arg_index + n_before + i] ];\n                if( CppAD::isnan( con_x[i] ) )\n                    type_x[i] = variable_enum;\n                else\n                    type_x[i] = constant_enum;\n            }\n            //\n            // depend_y\n            depend_y.resize(n_res);\n            for(addr_t i = 0; i < n_res; ++i)\n                depend_y[i] = bool( val_use_case[ res_index + i ] );\n            //\n            // depend_x\n            // only constants (not dynamic parameters) are included in con_x\n            depend_x.resize(nx);\n            local::sweep::call_atomic_rev_depend<Value, Value>(\n                atomic_index, call_id, con_x, type_x, depend_x, depend_y\n            );\n            //\n            // val_use_case\n            for(addr_t k = 0; k < n_x; ++k)\n            {   addr_t val_index = var_arg_[arg_index + n_before + k];\n                if( depend_x[k] )\n                    inc_val_use_case(val_index, i_op);\n            }\n        }\n    }\n# if CPPAD_VAL_GRAPH_TAPE_TRACE\n    // inuse\n    size_t final_inuse = thread_alloc::inuse(thread);\n    std::cout << \"rev_depend: inuse = \" << final_inuse - initial_inuse << \"\\n\";\n# endif\n    return;\n}\n\n} } } // END_CPPAD_LOCAL_VAL_GRAPH_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/val_graph/summation.hpp",
    "content": "# ifndef  CPPAD_LOCAL_VAL_GRAPH_SUMMATION_HPP\n# define  CPPAD_LOCAL_VAL_GRAPH_SUMMATION_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2023-25 Bradley M. Bell\n// ---------------------------------------------------------------------------\n# include <cppad/local/val_graph/tape.hpp>\n# include <cppad/local/val_graph/rev_depend.hpp>\nnamespace CppAD { namespace local { namespace val_graph {\n/*\n------------------------------------------------------------------------------\n{xrst_begin_parent val_summation dev}\n{xrst_spell\n    csum\n    dep\n    neg\n}\n\nCombine Multiple sum Operators into a csum Operator\n###################################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_SUMMATION\n    // END_SUMMATION\n}\n\n\nDiscussion\n**********\nWe refer to an add, sub, neg, or csum operator as a sum operation.\nIf the result for one of these operations is only used by a sum operator,\nthe two operations can be replaced by a single csum operator.\nThis process is repeated until the result is used by some other operation\nor the result is a dependent variable.\n\nLimitation\n**********\nThe process above terminates before reaching a csum operator in the\noriginal tape. To get full optimization in this case, csum operators\nshould first be converted to add and sub operations.\n\nChanges\n*******\nOnly the following values, for this tape, are guaranteed to be same:\n#. The number of independent values :ref:`val_tape@n_ind` .\n#. The size of the dependent vector :ref:`dep_vec.size() <val_tape@dep_vec>` .\n\nExample\n*******\nThe file :ref:`val_summation_xam.cpp-name` is an example and test using\ntape.summation().\n\nContents\n********\n{xrst_toc_table\n    val_graph/summation_xam.cpp\n}\n\n{xrst_end val_summation}\n-----------------------------------------------------------------------------\n{xrst_begin val_csum_info dev}\n{xrst_spell\n    ctor\n    struct\n}\n\nInformation for a Cumulative Summation\n######################################\n\n{xrst_code cpp} */\nstruct csum_info_t {\n    bool  first_done;  // is first operator argument included in lists\n    bool  second_done; // is second operator argument included in lists\n    std::list<addr_t> add_list; // list of value indices to add\n    std::list<addr_t> sub_list; // list of value indices to subtract\n    // ctor\n    csum_info_t() : first_done(false), second_done(false) { }\n};\n/* {xrst_code}\n{xrst_end val_csum_info}\n------------------------------------------------------------------------------\n{xrst_begin val_replace_csum_op dev}\n{xrst_spell\n    neg\n}\n\nReplace An Operator with a Cumulative Summation\n###############################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_REPLACE_CSUM_OP\n    // END_REPLACE_CSUM_OP\n}\n\nReplacement Operator Use\n************************\nThis will replace an operator use in the tape.\nThe :ref:`set_op2arg_index <val_op2arg_index@set>` must have been\nexecuted on this tape before a replacement can be done.\n\nres_index\n*********\nis the value index of the result for this operator.\n\nop_index\n********\nis the index of the operator that we are replacing\nThis operator must have just one result with index res_index.\n\ncsum_info\n*********\nIs the cumulative summation information for the operator\nthat we are replacing.\nThe idea here is that there are multiple add, sub, and neg operators\nthat become dead code when this replacement is done.\n\n{xrst_end val_replace_csum_op}\n*/\n//\n// BEGIN_REPLACE_CSUM_OP\ntemplate <class Value>\nvoid tape_t<Value>::replace_csum_op(\n    addr_t       res_index ,\n    addr_t       i_op      ,\n    csum_info_t& csum_info )\n// END_REPLACE_CSUM_OP\n{\n    //\n    // This is a replace\n    //\n    // op_enum_vec_\n    op_enum_vec_[i_op] = uint8_t( csum_op_enum );\n    //\n    // arg_index_vec_\n    op2arg_index_[i_op] = addr_t( var_arg_.size() );\n    //\n    // n_add, var_arg_\n    addr_t n_add  = addr_t( csum_info.add_list.size() );\n    var_arg_.push_back( n_add );\n    //\n    // n_sub, var_arg_\n    addr_t n_sub  = addr_t( csum_info.sub_list.size() );\n    var_arg_.push_back( n_sub );\n    //\n    // itr\n    std::list<addr_t>::const_iterator itr;\n    //\n    // var_arg_: addition variables\n    for(itr = csum_info.add_list.begin(); itr != csum_info.add_list.end(); ++itr)\n    {   CPPAD_ASSERT_UNKNOWN( *itr < res_index );\n        var_arg_.push_back( *itr );\n    }\n    //\n    // var_arg_: subtraction variables\n    for(itr = csum_info.sub_list.begin(); itr != csum_info.sub_list.end(); ++itr)\n    {   CPPAD_ASSERT_UNKNOWN( *itr < res_index );\n        var_arg_.push_back( *itr );\n    }\n    //\n    // n_arg, var_arg_\n    addr_t n_arg = 3 + n_add + n_sub;\n    var_arg_.push_back( n_arg );\n    //\n    return;\n}\n// ---------------------------------------------------------------------------\n// BEGIN_SUMMATION\ntemplate <class Value>\nvoid tape_t<Value>::summation(void)\n// END_SUMMATION\n{   //\n# if CPPAD_VAL_GRAPH_TAPE_TRACE\n    // thread, initial_inuse\n    size_t thread        = thread_alloc::thread_num();\n    size_t initial_inuse = thread_alloc::inuse(thread);\n# endif\n    //\n    // op_arg\n    Vector<addr_t> op_arg;\n    //\n    // csum_map\n    // information for all the cumulative summation operations\n    std::map<addr_t, csum_info_t> csum_map;\n    //\n    // sum_op\n    auto sum_op = [] (op_enum_t op_enum)\n    {   bool result = false;\n        result     |= op_enum == neg_op_enum;\n        result     |= op_enum == add_op_enum;\n        result     |= op_enum == sub_op_enum;\n        return result;\n    };\n    //\n    // splice_list\n    auto splice_list = [] (std::list<addr_t>& des, std::list<addr_t>& src)\n    {   std::list<addr_t>::iterator itr_pos = des.end();\n        des.splice(itr_pos, src);\n        return;\n    };\n    //\n    // cat_list\n    auto cat_list = [] (std::list<addr_t>& des, std::list<addr_t>& src)\n    {   std::list<addr_t>::iterator itr_pos         = des.end();\n        std::list<addr_t>::const_iterator itr_begin = src.begin();\n        std::list<addr_t>::const_iterator itr_end   = src.end();\n        des.insert(itr_pos, itr_begin, itr_end);\n        return;\n    };\n    //\n    // set_op2arg_index\n    // This is necessary before calling replace_csum_op.\n    set_op2arg_index();\n    //\n    // val_use_case, vec_last_load\n    Vector<addr_t> val_use_case, vec_last_load;\n    rev_depend(val_use_case, vec_last_load);\n    //\n    // op_itr\n    op_iterator<Value> op_itr(*this, 0);\n    //\n    // i_op\n    for(addr_t i_op = 1; i_op < n_op(); ++i_op)\n    {   //\n        // op_itr\n        ++op_itr; // skip index zero\n        //\n        // op_ptr, arg_index, res_index\n        const base_op_t<Value>* op_ptr_i    = op_itr.op_ptr();\n        addr_t                  res_index_i = op_itr.res_index();\n        addr_t                  arg_index_i = op_itr.arg_index();\n        //\n        // op_enum_i, n_arg\n        op_enum_t op_enum_i  = op_ptr_i->op_enum();\n        addr_t    n_arg      = op_ptr_i->n_arg(arg_index_i, var_arg_);\n        //\n        // use_i, sum_i\n        bool sum_i   = sum_op( op_enum_i );\n        bool use_i   = false;\n        if( sum_i )\n        {\n# ifndef NDEBUG\n            addr_t n_res = op_ptr_i->n_res(arg_index_i, var_arg_);\n            CPPAD_ASSERT_UNKNOWN( n_res == 1 );\n# endif\n            use_i = 0 != val_use_case[res_index_i];\n        }\n        if( use_i & sum_i )\n        {   // i_op is one of neg, add, or sub\n            //\n            // op_arg\n            op_arg.resize(n_arg);\n            for(addr_t i = 0; i < n_arg; ++i)\n                op_arg[i] = var_arg_[arg_index_i + i];\n            //\n            // op_arg_equal_i\n            bool op_arg_equal_i = false;\n            if( op_ptr_i->is_binary() )\n                op_arg_equal_i = op_arg[0] == op_arg[1];\n            //\n            // is_csum_i, csum_map[i_op]\n            bool is_csum_i  = 0 < csum_map.count(i_op);\n            if( is_csum_i )\n            {   csum_info_t& csum_info_i = csum_map[i_op];\n                switch(op_enum_i)\n                {   //\n                    default:\n                    CPPAD_ASSERT_UNKNOWN(false);\n                    break;\n                    //\n                    case neg_op_enum:\n                    CPPAD_ASSERT_UNKNOWN( csum_info_i.first_done );\n                    break;\n                    //\n                    case add_op_enum:\n                    if( ! csum_info_i.first_done )\n                    {   CPPAD_ASSERT_UNKNOWN( ! op_arg_equal_i );\n                        csum_info_i.add_list.push_back(op_arg[0]);\n                    }\n                    if( ! csum_info_i.second_done )\n                    {   CPPAD_ASSERT_UNKNOWN( ! op_arg_equal_i );\n                        csum_info_i.add_list.push_back(op_arg[1]);\n                    }\n                    break;\n                    //\n                    case sub_op_enum:\n                    if( ! csum_info_i.first_done )\n                    {   CPPAD_ASSERT_UNKNOWN( ! op_arg_equal_i );\n                        csum_info_i.add_list.push_back(op_arg[0]);\n                    }\n                    if( ! csum_info_i.second_done )\n                    {   CPPAD_ASSERT_UNKNOWN( ! op_arg_equal_i );\n                        csum_info_i.sub_list.push_back(op_arg[1]);\n                    }\n                    break;\n                }\n                csum_info_i.first_done  = true;\n                csum_info_i.second_done = true;\n            }\n            //\n            if( val_use_case[res_index_i] == n_op() )\n            {   // i_op is a dependent variable or used more than once\n                //\n                if( is_csum_i )\n                {   replace_csum_op(res_index_i, i_op, csum_map[i_op]);\n                    csum_map.erase( i_op );\n                }\n            }\n            else\n            {   //\n                // j_op\n                // i_op result is only used by the j_op operator\n                addr_t j_op = val_use_case[res_index_i];\n                //\n                // op_enum_j\n                op_enum_t op_enum_j = op_enum_t( op_enum_vec_[j_op] );\n                //\n                // sum_j\n                bool sum_j = sum_op( op_enum_j );\n                //\n                if( ! sum_j )\n                {   // The only use of i_op is not a summation operator\n                    if( is_csum_i )\n                    {   replace_csum_op(res_index_i, i_op,  csum_map[i_op]);\n                        csum_map.erase( i_op );\n                    }\n                }\n                else\n                {   // The only use of i_op result is in a summation operator\n                    //\n                    // csum_map[i_op]\n                    if( ! is_csum_i )\n                    {   csum_info_t csum_info;\n                        switch(op_enum_i)\n                        {   //\n                            default:\n                            CPPAD_ASSERT_UNKNOWN(false);\n                            break;\n                            //\n                            // neg_op_enum\n                            case neg_op_enum:\n                            csum_info.sub_list.push_back(op_arg[0]);\n                            break;\n                            //\n                            // add_op_enum\n                            case add_op_enum:\n                            csum_info.add_list.push_back(op_arg[0]);\n                            csum_info.add_list.push_back(op_arg[1]);\n                            break;\n                            //\n                            // sub_op_enum\n                            // no use is adding and subtracting the same argument\n                            case sub_op_enum:\n                            if( ! op_arg_equal_i )\n                            {   csum_info.add_list.push_back(op_arg[0]);\n                                csum_info.sub_list.push_back(op_arg[1]);\n                            }\n                            break;\n                        }\n                        csum_map[i_op] = csum_info;\n                    }\n                    //\n                    // csum_info_i\n                    csum_info_t& csum_info_i = csum_map[i_op];\n                    //\n                    // second_operand\n                    bool second_operand = false;\n                    bool op_arg_equal_j = false;\n                    if( (op_enum_j == add_op_enum) || (op_enum_j == sub_op_enum) )\n                    {   addr_t          arg_index_j = op2arg_index_[j_op];\n                        addr_t          right_index = var_arg_[arg_index_j + 1];\n                        addr_t          left_index  = var_arg_[arg_index_j + 0];\n                        second_operand  = right_index == res_index_i;\n                        op_arg_equal_j  = right_index == left_index;\n                        CPPAD_ASSERT_UNKNOWN(\n                            left_index == res_index_i || right_index == res_index_i\n                        );\n                    }\n                    //\n                    // is_csum_j\n                    bool is_csum_j = 0 < csum_map.count(j_op);\n                    //\n                    // csum_map[j_op]\n                    if( ! is_csum_j )\n                        csum_map[j_op] = csum_info_t();\n                    csum_info_t& csum_info_j = csum_map[j_op];\n                    switch( op_enum_j )\n                    {   //\n                        default:\n                        CPPAD_ASSERT_UNKNOWN(false)\n                        break;\n                        //\n                        case neg_op_enum:\n                        splice_list(csum_info_j.add_list, csum_info_i.sub_list);\n                        splice_list(csum_info_j.sub_list, csum_info_i.add_list);\n                        break;\n                        //\n                        case add_op_enum:\n                        if( op_arg_equal_j )\n                        {   cat_list(csum_info_j.add_list, csum_info_i.add_list);\n                            cat_list(csum_info_j.sub_list, csum_info_i.sub_list);\n                        }\n                        splice_list(csum_info_j.add_list, csum_info_i.add_list);\n                        splice_list(csum_info_j.sub_list, csum_info_i.sub_list);\n                        break;\n                        //\n                        case sub_op_enum:\n                        if( second_operand )\n                        {   if( ! op_arg_equal_j )\n                            {   splice_list(csum_info_j.add_list, csum_info_i.sub_list);\n                                splice_list(csum_info_j.sub_list, csum_info_i.add_list);\n                            }\n                        }\n                        else if( op_arg_equal_j )\n                        {   cat_list(csum_info_j.add_list, csum_info_i.add_list);\n                            cat_list(csum_info_j.sub_list, csum_info_i.sub_list);\n                            splice_list(csum_info_j.add_list, csum_info_i.add_list);\n                            splice_list(csum_info_j.sub_list, csum_info_i.sub_list);\n                        }\n                        else\n                        {   splice_list(csum_info_j.add_list, csum_info_i.add_list);\n                            splice_list(csum_info_j.sub_list, csum_info_i.sub_list);\n                        }\n                        break;\n                    }\n                    if( op_arg_equal_j )\n                    {   csum_info_j.first_done  = true;\n                        csum_info_j.second_done = true;\n                    }\n                    else if( second_operand )\n                        csum_info_j.second_done = true;\n                    else\n                        csum_info_j.first_done = true;\n                }\n            }\n        }\n    }\n# if CPPAD_VAL_GRAPH_TAPE_TRACE\n    // inuse\n    size_t final_inuse = thread_alloc::inuse(thread);\n    std::cout << \"summation:  inuse = \" << final_inuse - initial_inuse << \"\\n\";\n# endif\n}\n\n} } } // END_CPPAD_LOCAL_VAL_GRAPH_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/val_graph/tape.hpp",
    "content": "# ifndef  CPPAD_LOCAL_VAL_GRAPH_TAPE_HPP\n# define  CPPAD_LOCAL_VAL_GRAPH_TAPE_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2023-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/local/val_graph/op_iterator.hpp>\n# include <cppad/local/val_graph/op_enum2class.hpp>\n# include <cppad/local/val_graph/val_type.hpp>\n# include <cppad/local/val_graph/op_iterator.hpp>\n\n# define CPPAD_VAL_GRAPH_TAPE_TRACE 0\n\nnamespace CppAD { namespace local { namespace val_graph {\n\n// csum_info_t: forward declare\nstruct csum_info_t;\n\n/*\n{xrst_begin val_tape dev}\n{xrst_spell\n    dep\n    str\n}\n\nThe Value Operator Tape\n#######################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_TAPE_T\n    // END_TAPE_T\n}\n\nPurpose\n*******\nThis class is used to define a function using a sequence of operators.\n\nValue\n*****\nThis is the type used for evaluations using the tape.\n\nop_ptr\n******\n{xrst_literal\n    // BEGIN_OP_PTR\n    // END_OP_PTR\n}\nThis is the :ref:`base_op <val_base_op-name>` corresponding to\n*op_index* in this tape.\n\nn_val\n*****\n{xrst_literal\n    // BEGIN_N_VAL\n    // END_N_VAL\n}\nThis is the number of elements in the value vector.\n\nn_op\n****\n{xrst_literal\n    // BEGIN_N_OP\n    // END_N_OP\n}\nThis is the number of operators in the tape.\n\nn_ind\n*****\n{xrst_literal\n    // BEGIN_N_IND\n    // END_N_IND\n}\nThis is the size of the independent vector.\n\narg_vec\n*******\n{xrst_literal\n    // BEGIN_ARG_VEC\n    // END_ARG_VEC\n}\nThe elements of this vector at non-negative integers that connect\nwith an operator to make an operator usage.\n\ncon_vec\n*******\n{xrst_literal\n    // BEGIN_CON_VEC\n    // END_CON_VEC\n}\nThis is the vector of value constants.\n\nstr_vec\n*******\n{xrst_literal\n    // BEGIN_STR_VEC\n    // END_STR_VEC\n}\nThis is the vector of string constants.\n\nvec_initial\n***********\n{xrst_literal\n    // BEGIN_VEC_INITIAL\n    // END_VEC_INITIAL\n}\nThis vector has length equal to the number of dynamic vectors.\nThis i-th element of this vector is the vector of initial indices\nfor the i-th dynamic vector; see :ref:`val_vec_op-name` .\n\nop_enum_vec\n***********\n{xrst_literal\n    // BEGIN_OP_ENUM_VEC\n    // END_OP_ENUM_VEC\n}\nEach element of this vector corresponds to an operator usage.\nThe order of the vector is the order of operations.\n\ndep_vec\n*******\n{xrst_literal\n    // BEGIN_DEP_VEC\n    // END_DEP_VEC\n}\nThis is the vector of dependent indices in the value vector.\nThe function corresponding to a tape maps the independent values\nto the dependent values.\n\nswap\n****\n{xrst_literal\n    // BEGIN_SWAP\n    // END_SWAP\n}\nThis swaps the contents of this tape with another tape.\n\neval\n****\n{xrst_literal\n    // BEGIN_EVAL\n    // END_EVAL\n}\nGiven the independent values, this routine execute the operators\nin order to evaluate the rest of the value vector and the compare_false\ncounter.\n\ntrace\n=====\nIf this is true, the :ref:`val_print_op-name` functions are used\nto print the operators.\n\nval_vec\n=======\nThis vector has size equal to *n_val*.\nThe first *n_ind* elements are inputs.\nThe rest of the elements are outputs.\n\ncompare_false\n=============\nThis argument is optional.\nIt is the number of :ref:`val_comp_op-name` that had a false\nresult for their comparisons.\nThis is both an input and output; i.e., each false comparison\nwill add one to this value.\n\nOperations on Tape\n******************\n{xrst_comment BEGIN_SORT_THIS_LINE_PLUS_2}\n{xrst_toc_table\n    include/cppad/local/val_graph/compress.hpp\n    include/cppad/local/val_graph/cumulative.hpp\n    include/cppad/local/val_graph/dead_code.hpp\n    include/cppad/local/val_graph/fold_con.hpp\n    include/cppad/local/val_graph/op2arg_index.hpp\n    include/cppad/local/val_graph/op_hash_table.hpp\n    include/cppad/local/val_graph/op_iterator.hpp\n    include/cppad/local/val_graph/option.hpp\n    include/cppad/local/val_graph/record.hpp\n    include/cppad/local/val_graph/record_new.hpp\n    include/cppad/local/val_graph/renumber.hpp\n    include/cppad/local/val_graph/rev_depend.hpp\n    include/cppad/local/val_graph/summation.hpp\n}\n{xrst_comment END_SORT_THIS_LINE_MINUS_2}\n\n\n{xrst_end val_tape}\n*/\n// BEGIN_TAPE_T\ntemplate <class Value> class tape_t {\n// END_TAPE_T\nprivate :\n    addr_t              n_ind_;       // number of independent values\n    addr_t              n_val_;       // total number of values\n    Vector<addr_t>      var_arg_;     // arguments for all operator uses\n    Vector<Value>       con_vec_;     // value constants\n    Vector<std::string> str_vec_;     // string constants\n    Vector<addr_t>      dep_vec_;     // dependent variable indices in val_vec\n    Vector<uint8_t>     op_enum_vec_; // one byte per operator enum value.\n    //\n    // vec_initial_\n    // initial indices for all the dynamic vectors\n    Vector< Vector<addr_t> > vec_initial_;\n    //\n    // op2arg_index_\n    // Optional vector that changes how op_iterator works; e.g.,\n    // this is necessary is we are using replace_csum_op with this tape.\n    Vector<addr_t> op2arg_index_;\n    //\n    // option_map_\n    std::map< std::string, std::string > option_map_;\n    //\n# if CPPAD_VAL_GRAPH_TAPE_TRACE\n    // set by set_ind, used by set_dep\n    size_t  set_ind_inuse_;\n# endif\n    //\npublic :\n    // default constructor\n    tape_t(void)\n    {   initialize_option(); }\n    //\n    // BEGIN_OP_PTR\n    const base_op_t<Value>* base_op_ptr(addr_t op_index) const\n    {   op_enum_t op_enum = op_enum_t( op_enum_vec_[op_index] );\n        return op_enum2class<Value>(op_enum);\n    }\n    // END_OP_PTR\n    // ------------------------------------------------------------------------\n    // BEGIN_N_VAL\n    addr_t n_val(void) const\n    {   return n_val_; }\n    // END_N_VAL\n    //\n    // BEGIN_N_OP\n    addr_t n_op(void) const\n    {   return addr_t( op_enum_vec_.size() ); }\n    // END_N_OP\n    //\n    // BEGIN_N_IND\n    addr_t n_ind(void) const\n    {   return n_ind_; }\n    // END_N_IND\n    //\n    // BEGIN_ARG_VEC\n    const Vector<addr_t>& arg_vec(void) const\n    {   return var_arg_; }\n    // END_ARG_VEC\n    //\n    // BEGIN_CON_VEC\n    const Vector<Value>& con_vec(void) const\n    {   return con_vec_; }\n    // END_CON_VEC\n    //\n    // BEGIN_STR_VEC\n    const Vector<std::string>& str_vec(void) const\n    {   return str_vec_; }\n    // END_STR_VEC\n    //\n    // BEGIN_VEC_INITIAL\n    const Vector< Vector<addr_t> >& vec_initial(void) const\n    {   return vec_initial_; }\n    // END_VEC_INITIAL\n    //\n    // BEGIN_OP_ENUM_VEC\n    const Vector<uint8_t>& op_enum_vec(void) const\n    {   return op_enum_vec_; }\n    // END_OP_ENUM_VEC\n    //\n    // BEGIN_DEP_VEC\n    const Vector<addr_t>& dep_vec(void) const\n    {   return dep_vec_; }\n    // END_DEP_VEC\n    // ------------------------------------------------------------------------\n    // BEGIN_SWAP\n    void swap(tape_t& other)\n    // END_SWAP\n    {   // same order as declaration of member variables just below private:\n        std::swap( n_ind_, other.n_ind_ );\n        std::swap( n_val_, other.n_val_);\n        var_arg_.swap( other.var_arg_ );\n        con_vec_.swap( other.con_vec_ );\n        str_vec_.swap( other.str_vec_ );\n        dep_vec_.swap( other.dep_vec_ );\n        op_enum_vec_.swap( other.op_enum_vec_ );\n        vec_initial_.swap( other.vec_initial_ );\n        op2arg_index_.swap( other.op2arg_index_ );\n        option_map_.swap( other.option_map_ );\n    }\n    // eval(trace, val_vec)\n    void eval(\n        bool           trace         ,\n        Vector<Value>& val_vec       ) const\n    {   size_t                  compare_false = 0;\n        eval(trace, val_vec, compare_false);\n    }\n    // BEGIN_EVAL\n    // eval(trace, val_vec, compare_false)\n    void eval(\n        bool                      trace         ,\n        Vector<Value>&            val_vec       ,\n        size_t&                   compare_false ) const\n    // END_EVAL\n    {   CPPAD_ASSERT_KNOWN(\n            val_vec.size() == size_t(n_val_),\n            \"eval: size of val_vec not equal to tape.n_val()\"\n        );\n        using std::setw;\n        using std::right;\n        using std::cout;\n        //\n        // ind_vec_vec\n        // Only the vector_op routines use this eval argument\n        Vector< Vector<addr_t> > ind_vec_vec;\n        //\n        // trace\n        if( trace )\n        {   // no operators for independent variables\n            std::cout << \"independent vector\\n\";\n            for(addr_t res_index = 0; res_index < n_ind_; ++res_index)\n            {   Value res = val_vec[res_index];\n                cout << right << setw(5) << res_index;\n                cout << \" \" << right << setw(10) << res << \"\\n\";\n            }\n            std::printf(\"operators\\n\");\n        }\n        //\n        // op_itr, i_op\n        op_iterator<Value> op_itr(*this, 0);\n        for(addr_t i_op = 0; i_op < n_op(); ++i_op)\n        {   //\n            // op_ptr, arg_index, res_index\n            const base_op_t<Value>* op_ptr     = op_itr.op_ptr();\n            addr_t                  arg_index  = op_itr.arg_index();\n            addr_t                  res_index  = op_itr.res_index();\n            //\n            // base_op_t<Value>::eval\n            op_ptr->eval(\n                this,\n                trace,\n                arg_index,\n                res_index,\n                val_vec,\n                ind_vec_vec,\n                compare_false\n            );\n            //\n            // op_itr\n            ++op_itr;\n        }\n        // trace\n        if( trace )\n        {   // no operators for dependent variables\n            std::cout << \"dependent vector\\n\";\n            for(size_t i = 0; i < dep_vec_.size(); ++i)\n            {   addr_t res_index = dep_vec_[i];\n                Value res        = val_vec[res_index];\n                cout << right << setw(5) << res_index;\n                cout << \" \" << right << setw(10) << res << \"\\n\";\n            }\n            // space after end of this tape\n            std::printf(\"\\n\");\n        }\n        return;\n    }\n    // ------------------------------------------------------------------------\n    // functions in record.hpp\n    // ------------------------------------------------------------------------\n    //\n    // set_ind\n    addr_t set_ind(addr_t n_ind);\n    //\n    // record_op\n    addr_t record_op(op_enum_t op_enum, const Vector<addr_t>& op_arg);\n    //\n    // record_con_op\n    addr_t record_con_op(const Value& constant);\n    //\n    // record_dis_op\n    addr_t record_dis_op(addr_t discrete_index, addr_t op_arg);\n    //\n    // record_comp_op\n    addr_t record_comp_op(\n        compare_enum_t compare_enum ,\n        addr_t         left_index   ,\n        addr_t         right_index\n    );\n    //\n    // record_call_op\n    addr_t record_call_op(\n        addr_t atomic_index           ,\n        addr_t call_id                ,\n        addr_t n_res                  ,\n        const Vector<addr_t>& fun_arg\n    );\n    //\n    // record_csum_op\n    addr_t record_csum_op(\n        const Vector<addr_t>& add,\n        const Vector<addr_t>& sub\n    );\n    //\n    // record_cexp_op\n    addr_t record_cexp_op(\n        compare_enum_t compare_enum ,\n        addr_t         left         ,\n        addr_t         right        ,\n        addr_t         if_true      ,\n        addr_t         if_false\n    );\n    //\n    // record_pri_op\n    addr_t record_pri_op(\n        const std::string& before      ,\n        const std::string& after       ,\n        addr_t             flag_index  ,\n        addr_t             value_index\n    );\n    //\n    // record_vec_op\n    addr_t record_vec_op(const Vector<addr_t>& initial);\n    //\n    // record_load_op\n    addr_t record_load_op(\n        addr_t   which_vector  ,\n        addr_t   vector_index\n    );\n    //\n    // record_store_op\n    addr_t record_store_op(\n        addr_t   which_vector  ,\n        addr_t   vector_index  ,\n        addr_t   value_index\n    );\n    //\n    // set_dep\n    void set_dep(const Vector<addr_t>& dep_vec);\n    // ------------------------------------------------------------------------\n    // functions in their own files\n    // ------------------------------------------------------------------------\n    //\n    // fold_con\n    void fold_con(void);\n    //\n    // renumber\n    void renumber(void);\n    //\n    // rev_depend\n    void rev_depend(\n        Vector<addr_t>& val_use_case  ,\n        Vector<addr_t>& vec_last_load\n    );\n    //\n    // dead_code\n    vectorBool dead_code(void);\n    //\n    // compress\n    vectorBool compress(void);\n    //\n    // record_new\n    addr_t record_new(\n        tape_t&                   new_tape         ,\n        Vector<addr_t>&           new_which_vec    ,\n        Vector<addr_t>&           work             ,\n        const Vector<addr_t>&     new_val_index    ,\n        const Vector<addr_t>&     val_use_case     ,\n        const base_op_t<Value>*   op_ptr           ,\n        addr_t                    arg_index        ,\n        addr_t                    res_index\n    );\n    //\n    // ------------------------------------------------------------------------\n    // functions in summation.hpp\n    // ------------------------------------------------------------------------\n    //\n    // summation\n    void summation(void);\n    //\n    // set_op2arg_index\n    void set_op2arg_index();\n    //\n    // op2arg_index\n    const Vector<addr_t>& op2arg_index(void) const;\n    //\n    // replace_csum_op\n    void replace_csum_op(\n        addr_t       res_index ,\n        addr_t       i_op      ,\n        csum_info_t& csum_info\n    );\n    // -----------------------------------------------------------------------\n    // functions in cumulative.hpp\n    // -----------------------------------------------------------------------\n    //\n    // op2csum\n    void op2csum(addr_t op_index);\n    //\n    // ------------------------------------------------------------------------\n    // functions in option.hpp\n    // ------------------------------------------------------------------------\n    //\n    // initialize_option\n    void initialize_option(void);\n    //\n    // set_option\n    void set_option(const std::string& name, const std::string& value);\n};\n} } } // END_CPPAD_LOCAL_VAL_GRAPH_NAMESPACE\n\n// BEGIN_SORT_THIS_LINE_PLUS_1\n# include <cppad/local/val_graph/compress.hpp>\n# include <cppad/local/val_graph/cumulative.hpp>\n# include <cppad/local/val_graph/dead_code.hpp>\n# include <cppad/local/val_graph/fold_con.hpp>\n# include <cppad/local/val_graph/op2arg_index.hpp>\n# include <cppad/local/val_graph/op_hash_table.hpp>\n# include <cppad/local/val_graph/option.hpp>\n# include <cppad/local/val_graph/record.hpp>\n# include <cppad/local/val_graph/record_new.hpp>\n# include <cppad/local/val_graph/renumber.hpp>\n# include <cppad/local/val_graph/summation.hpp>\n// END_SORT_THIS_LINE_MINUS_1\n\n# undef CPPAD_VAL_GRAPH_TAPE_TRACE\n# endif\n"
  },
  {
    "path": "include/cppad/local/val_graph/unary_op.hpp",
    "content": "# ifndef  CPPAD_LOCAL_VAL_GRAPH_UNARY_OP_HPP\n# define  CPPAD_LOCAL_VAL_GRAPH_UNARY_OP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2023-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/local/val_graph/base_op.hpp>\n# include <cppad/local/val_graph/print_op.hpp>\n\n# define CPPAD_VAL_GRAPH_UNARY(Name, Op) \\\n    template <class Value> \\\n    class Name##_op_t : public unary_op_t<Value> { \\\n    public: \\\n        /* get_instance */ \\\n        static Name##_op_t* get_instance(void) \\\n        {   CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL; \\\n            static Name##_op_t instance; \\\n            return &instance; \\\n        } \\\n        /* op_enum */ \\\n        op_enum_t op_enum(void) const override \\\n        {   return Name##_op_enum; \\\n        } \\\n        /* eval */ \\\n        void eval( \\\n            const tape_t<Value>*      tape          , \\\n            bool                      trace         , \\\n            addr_t                    arg_index     , \\\n            addr_t                    res_index     , \\\n            Vector<Value>&            val_vec       , \\\n            Vector< Vector<addr_t> >& ind_vec_vec   , \\\n            size_t&                   compare_false ) const override \\\n        {   const Vector<addr_t>& arg_vec( tape->arg_vec() ); \\\n            const Value& value  = val_vec[ arg_vec[arg_index + 0] ]; \\\n            val_vec[res_index]  = Op ( value ); \\\n            if( trace ) this->print_op( \\\n                #Name , arg_index, arg_vec, res_index, val_vec \\\n            ); \\\n        } \\\n    }\n\nnamespace CppAD { namespace local { namespace val_graph {\n/*\n------------------------------------------------------------------------------\n{xrst_begin_parent val_unary_op dev}\n\nUnary Value Operators\n#####################\n\n{xrst_end val_unary_op}\n------------------------------------------------------------------------------\n{xrst_begin val_unary_base_op dev}\n\nThe Unary Value Operator Base Class\n###################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_UNARY_OP_T\n    // END_UNARY_OP_T\n}\n\nPurpose\n*******\nThe class is derived from :ref:`base_op <val_base_op-name>`.\nIt overrides the\n*is_unary*, *n_before*, *n_after*, *n_arg*, *n_res_*, and *print_op*\nmember functions.\nThe *op_enum* and *eval* member functions are still pure virtual.\n\nis_unary\n********\nThis override of :ref:`val_base_op@is_unary` returns true.\n\nn_before\n********\nThis override of :ref:`val_base_op@n_before` returns 0.\n\nn_after\n*******\nThis override of :ref:`val_base_op@n_after` returns 0.\n\nn_arg\n*****\nThis override of :ref:`val_base_op@n_arg` returns 1.\n\nn_res\n*****\nThis override of :ref:`val_base_op@n_res` returns 1.\n\nprint_op\n********\n{xrst_literal\n    // BEGIN_PRINT_OP\n    // END_PRINT_OP\n}\nThis member function uses :ref:`val_print_op-name` to print unary operators.\n\n{xrst_end val_unary_base_op}\n*/\n\n// BEGIN_UNARY_OP_T\ntemplate <class Value>\nclass unary_op_t : public base_op_t<Value> {\n// END_UNARY_OP_T\npublic:\n    // n_before\n    addr_t n_before(void) const override\n    {   return 0; }\n    //\n    // n_after\n    addr_t n_after(void) const override\n    {   return 0; }\n    //\n    // is_unary\n    bool is_unary(void) const override\n    {   return true; }\n    //\n    // n_arg\n    addr_t n_arg(\n        addr_t                arg_index    ,\n        const Vector<addr_t>& arg_vec      ) const override\n    {   return 1; }\n    //\n    // n_res\n    addr_t n_res(\n        addr_t                arg_index    ,\n        const Vector<addr_t>& arg_vec      ) const override\n    {   return 1; }\n    //\n    // op_enum\n    virtual op_enum_t op_enum(void) const override = 0;\n    //\n    // eval\n    virtual void eval(\n        const tape_t<Value>*      tape          ,\n        bool                      trace         ,\n        addr_t                    arg_index     ,\n        addr_t                    res_index     ,\n        Vector<Value>&            val_vec       ,\n        Vector< Vector<addr_t> >& ind_vec_vec   ,\n        size_t&                   compare_false ) const override = 0;\n    //\n    // BEGIN_PRINT_OP\n    void print_op(\n        const char*           name         ,\n        addr_t                arg_index    ,\n        const Vector<addr_t>& arg_vec      ,\n        addr_t                res_index    ,\n        Vector<Value>&        val_vec      ) const\n    // END_PRINT_OP\n    {   //\n        Vector<addr_t> arg_val_index  = { arg_vec[ arg_index + 0 ] };\n        Vector<Value>  res_value      = { val_vec[res_index] };\n        CppAD::local::val_graph::print_op(\n            name, arg_val_index, res_index, res_value\n        );\n    }\n};\n/*\n------------------------------------------------------------------------------\n{xrst_begin val_unary_op_derived dev}\n{xrst_spell\n    neg\n}\n\nThe Unary Value Operator Derived Classes\n########################################\n\nPrototype\n*********\n| |tab| ``template <class Value>``\n| |tab| ``class`` *Name*\\ ``_opt_t : public unary_op_t<Value>``\n\n*Name*\n******\nUnary operators are defined for the following names:\n\n.. csv-table:: Unary Operators\n    :widths: auto\n    :header-rows: 1\n\n    Name,description\n    neg,result is negative of operand\n\nContext\n*******\nThis class is derived from :ref:`val_unary_op-name` .\nIt overrides the *op_enum* and *eval* member functions\nand is a concrete class (it has no pure virtual functions).\n\nget_instance\n************\nThis static member function returns a pointer to a\n*Name*\\ ``_op_t`` object.\n\nop_enum\n*******\nThis override of :ref:`val_base_op@op_enum` returns\n*Name*\\ ``_op_enum`` .\n\neval\n****\nThis override of :ref:`val_base_op@eval` sets\nthe result equal to the unary operator applied to the operand; see\n:ref:`val_base_op@arg_vec@Unary Operators` .\n\n\n{xrst_toc_hidden\n    val_graph/unary_xam.cpp\n}\nExample\n*******\nThe file :ref:`unary_xam.cpp <val_unary_xam.cpp-name>`\nis an example and test that uses a unary operator.\n\n{xrst_end val_unary_op_derived}\n*/\n// BEGIN_SORT_THIS_LINE_PLUS_1\nCPPAD_VAL_GRAPH_UNARY(abs,   fabs);\nCPPAD_VAL_GRAPH_UNARY(acos,  acos);\nCPPAD_VAL_GRAPH_UNARY(acosh, acosh);\nCPPAD_VAL_GRAPH_UNARY(asin,  asin);\nCPPAD_VAL_GRAPH_UNARY(asinh, asinh);\nCPPAD_VAL_GRAPH_UNARY(atan,  atan);\nCPPAD_VAL_GRAPH_UNARY(atanh, atanh);\nCPPAD_VAL_GRAPH_UNARY(cos,   cos);\nCPPAD_VAL_GRAPH_UNARY(cosh,  cosh);\nCPPAD_VAL_GRAPH_UNARY(erf,   erf);\nCPPAD_VAL_GRAPH_UNARY(erfc,  erfc);\nCPPAD_VAL_GRAPH_UNARY(exp,   exp);\nCPPAD_VAL_GRAPH_UNARY(expm1, expm1);\nCPPAD_VAL_GRAPH_UNARY(log,   log);\nCPPAD_VAL_GRAPH_UNARY(log1p, log1p);\nCPPAD_VAL_GRAPH_UNARY(neg,   -);\nCPPAD_VAL_GRAPH_UNARY(sign,  sign);\nCPPAD_VAL_GRAPH_UNARY(sin,   sin);\nCPPAD_VAL_GRAPH_UNARY(sinh,  sinh);\nCPPAD_VAL_GRAPH_UNARY(sqrt,  sqrt);\nCPPAD_VAL_GRAPH_UNARY(tan,   tan);\nCPPAD_VAL_GRAPH_UNARY(tanh,  tanh);\n// END_SORT_THIS_LINE_MINUS_1\n\n// ---------------------------------------------------------------------------\n} } } // END_CPPAD_LOCAL_VAL_GRAPH_NAMESPACE\n\n# undef CPPAD_VAL_GRAPH_UNARY\n# endif\n"
  },
  {
    "path": "include/cppad/local/val_graph/val2fun.hpp",
    "content": "# ifndef  CPPAD_LOCAL_VAL_GRAPH_VAL2FUN_HPP\n# define  CPPAD_LOCAL_VAL_GRAPH_VAL2FUN_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// --------------------------------------------------------------------------\n/*\n{xrst_begin val2fun_graph dev}\n{xrst_spell\n    dyn\n}\n\nCreate an ADFun Object Corresponding to a Value Graph\n#####################################################\n\nSyntax\n******\n| |tab| ``ADFun`` < *Base* > *fun*\n| |tab| *fun* . ``val2fun`` ( *val_tape* , *dyn_ind* , *var_ind* )\n| |tab| *fun* . ``val2fun`` ( *val_tape* , *dyn_ind* , *var_ind* , *use_val* )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_PROTOTYPE\n    // END_PROTOTYPE\n}\n\nBase\n****\nis the type corresponding to this :ref:`adfun-name` object;\ni.e., its calculations are done using the type *Base* .\nIt is also :ref:`val_tape@Value` type for the tape.\n\nRecBase\n*******\nin the prototype above, *RecBase* is the same type as *Base* .\n\nval_tape\n********\nThis is a :ref:`val_tape-name` representation of the function.\n\n*dyn_ind*\n*********\nThe *i*-th element of the vector is the index in the value graph\nof the *i*-th independent dynamic parameter in *fun* .\n\n*var_ind*\n*********\nThe *i*-th element of the vector is the index in *val_tape*\nof the *i*-th independent variable in *fun* .\nNo two elements of *dyn_ind* or *var_ind* can have the same value.\nFurthermore, the total number of elements in these two vectors\nmust be the number of independent variables in *val_tape* .\n\nuse_val\n*******\nIf this vector is present extra detection is done to convert\nvariables to parameters.\nIt has size equal to *val_tape*\\ .n_val().\nFor each value index, that is a result for a\n:ref:`val_call_op-name`, the corresponding *use_val*\\ [i] is true (false)\nif the result is used to compute one of the dependent variables.\n\n*fun*\n*****\nThe input contents of *fun* do not matter.\nUpon return it is an ADFun representation of the function.\n\nUnder Construction\n******************\nThis routine is under construction and is only implemented\nfor a few of the possible :ref:`ADFun-name` operators.\n\n{xrst_toc_hidden\n    val_graph/val2fun_xam.cpp\n}\nExamples\n********\nThe file :ref:`val_val2fun_xam.cpp-name`\nis an example an test of this conversion.\n\n{xrst_end val2fun_graph}\n*/\n\n# include <cppad/core/ad_fun.hpp>\n# include <cppad/local/op_code_dyn.hpp>\n# include <cppad/local/val_graph/tape.hpp>\n# include <cppad/local/val_graph/op_iterator.hpp>\n# include <cppad/local/val_graph/call_atomic.hpp>\n# include <cppad/local/pod_vector.hpp>\n# include <cppad/core/cppad_assert.hpp>\n\n# define CPPAD_VAL2FUN_DYN_UNARY(name)                  \\\n    case local::val_graph::name##_op_enum:               \\\n    tmp_addr = rec.put_dyn_par(                          \\\n        nan, local::name##_dyn, fun_arg[0]                \\\n    );                                                   \\\n    break;\n\n# define CPPAD_VAL2FUN_DYN_BINARY(name)                 \\\n    case local::val_graph::name##_op_enum:               \\\n    tmp_addr = rec.put_dyn_par(                          \\\n        nan, local::name##_dyn, fun_arg[0], fun_arg[1]    \\\n    );                                                   \\\n    break;\n\n# define CPPAD_VAL2FUN_VAR_UNARY(name, Op)              \\\n    case local::val_graph::name##_op_enum:               \\\n    tmp_addr = rec.PutOp(local::Op);                     \\\n    rec.PutArg( fun_arg[0] );                            \\\n    break;\n\n# define CPPAD_VAL2FUN_VAR_BINARY(name, Op)             \\\n    case local::val_graph::name##_op_enum:               \\\n    tmp_addr = rec.PutOp(local::Op);                     \\\n    break;\n\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n\ntemplate <class Base, class RecBase>\nvoid ADFun<Base, RecBase>::val2fun(\n    const local::val_graph::tape_t<Base>&                   val_tape  ,\n    const CppAD::local::val_graph::Vector<size_t>&          dyn_ind   ,\n    const CppAD::local::val_graph::Vector<size_t>&          var_ind   )\n{   vectorBool use_val;\n    val2fun(val_tape, dyn_ind, var_ind, use_val);\n}\n\n// BEGIN_PROTOTYPE\ntemplate <class Base, class RecBase>\nvoid ADFun<Base, RecBase>::val2fun(\n    const local::val_graph::tape_t<Base>&                   val_tape  ,\n    const CppAD::local::val_graph::Vector<size_t>&          dyn_ind   ,\n    const CppAD::local::val_graph::Vector<size_t>&          var_ind   ,\n    const CppAD::vectorBool&                                use_val   )\n// END_PROTOTYPE\n{   //\n    // vector\n    using CppAD::local::val_graph::Vector;\n    //\n    // base_op_t, op_enum_t, compare_enum_t\n    using local::val_graph::base_op_t;\n    using local::val_graph::op_enum_t;\n    using local::val_graph::compare_enum_t;\n    //\n    // val_arg_vec, val_con_vec, val_str_vec, val_dep_vec\n    const Vector<addr_t>&      val_arg_vec = val_tape.arg_vec();\n    const Vector<Base>&        val_con_vec = val_tape.con_vec();\n    const Vector<std::string>& val_str_vec = val_tape.str_vec();\n    const Vector<addr_t>&      val_dep_vec = val_tape.dep_vec();\n    //\n    // nan\n    Base nan = CppAD::numeric_limits<Base>::quiet_NaN();\n    //\n    // par_addr\n    // a temporary parameter index\n    addr_t par_addr;\n    //\n    // var_addr\n    // a temporary variable index\n    addr_t var_addr;\n    //\n    // tmp_addr\n    // a parameter or variable temporary index\n    // initialize to zero to avoid compiler warnings\n    addr_t tmp_addr = 0;\n    //\n# ifndef NDEBUG\n    // val_n_ind\n    // size of the independent value vector\n    size_t val_n_ind = size_t( val_tape.n_ind() );\n# endif\n    //\n    // dyn_n_ind\n    // number of independent dynamic parameters\n    size_t dyn_n_ind = dyn_ind.size();\n    //\n    // var_n_ind\n    // number of independent variables\n    size_t var_n_ind = var_ind.size();\n    //\n    // val_n_op\n    addr_t val_n_op = val_tape.n_op();\n    //\n    CPPAD_ASSERT_KNOWN( dyn_n_ind + var_n_ind == val_n_ind,\n        \"val2fun: The number of independent variables and dynamic parameters\\n\"\n        \"is not equal to the size of the independent value vector\"\n    );\n    //\n    // n_val\n    addr_t n_val = val_tape.n_val();\n    //\n    // fun_ad_type\n    Vector<ad_type_enum> fun_ad_type(n_val);\n    for(addr_t i = 0; i < n_val; ++i)\n        fun_ad_type[i] = number_ad_type_enum; // invalid\n    //\n    // val_index2con\n    // After fold_con, all the constants that get used are op_con results.\n    Vector<Base> val_index2con(n_val);\n    for(addr_t i = 0; i < n_val; ++i)\n        val_index2con[i] = nan;\n    bool trace           = false;\n    val_tape.eval(trace, val_index2con);\n    //\n    // val2fun_index\n    // mapping from value index to index in the AD function object.\n    // The meaning of this index depends on its ad_type.\n    Vector<addr_t> val2fun_index(n_val);\n    for(addr_t i = 0; i < n_val; ++i)\n        val2fun_index[i] = std::numeric_limits<addr_t>::max(); // invalid\n    //\n    // rec\n    // start a function recording\n    local::recorder<Base> rec;\n    CPPAD_ASSERT_UNKNOWN( rec.num_var_op() == 0 );\n    rec.set_n_dyn_independent(dyn_n_ind);\n    rec.set_abort_op_index(0);\n    rec.set_record_compare(false);\n    //\n    // parameter\n# ifndef NDEBUG\n    const local::pod_vector_maybe<Base>& parameter( rec.par_all());\n    CPPAD_ASSERT_UNKNOWN( parameter.size() == 0 );\n# endif\n    //\n    // rec\n    // initialize with the value nan at index nan\n    par_addr = rec.put_con_par(nan);\n    CPPAD_ASSERT_UNKNOWN( par_addr == 0 );\n    CPPAD_ASSERT_UNKNOWN( CppAD::isnan( parameter[par_addr] ) );\n    //\n    // rec\n    // Place the variable with index 0 in the tape\n    CPPAD_ASSERT_UNKNOWN( NumArg(local::BeginOp) == 1);\n    CPPAD_ASSERT_UNKNOWN( NumRes(local::BeginOp) == 1);\n    rec.PutOp(local::BeginOp);\n    rec.PutArg(0); // parameter argument is the nan above\n    //\n    // rec, vecad_offset\n    // place the VecAD objects in the recording\n    Vector<addr_t> vecad_offset;\n    addr_t         offset = 1;\n    for(size_t i = 0; i < val_tape.vec_initial().size(); ++i)\n    {   const Vector<addr_t>& val_initial = val_tape.vec_initial()[i];\n        size_t size = val_initial.size();\n        local::pod_vector<addr_t>  fun_initial(size);\n        for(size_t j = 0; j < size; ++j)\n        {   addr_t val_index  = val_initial[j];\n            const Base& value = val_index2con[val_index];\n            CPPAD_ASSERT_KNOWN( ! CppAD::isnan(value),\n                \"val2fun: an initial value for a dynamic array is not constant\"\n            );\n            fun_initial[j] =  rec.put_con_par( value );\n        }\n        rec.put_var_vecad(size, fun_initial);\n        vecad_offset.push_back( offset );\n        offset += addr_t(size + 1);\n    }\n    //\n    // rec, fun_ad_type, val2fun_index\n    // put the independent dynamic parameters in the function recording\n    for(size_t i = 0; i < dyn_n_ind; ++i)\n    {   CPPAD_ASSERT_KNOWN( dyn_ind[i] < val_n_ind,\n            \"val2fun: number of independent values is <= dyn_ind[i]\"\n        );\n        CPPAD_ASSERT_KNOWN( fun_ad_type[ dyn_ind[i] ] == number_ad_type_enum,\n            \"val2fun: dep_ind[i] == dep_ind[j] for some i and j\"\n        );\n        fun_ad_type[ dyn_ind[i] ]  = dynamic_enum;\n        par_addr                    = rec.put_dyn_par(nan, local::ind_dyn);\n        val2fun_index[ dyn_ind[i] ] = par_addr;\n        CPPAD_ASSERT_UNKNOWN( CppAD::isnan( parameter[par_addr] ) );\n    }\n    // put the independent variables in the function recording\n    for(size_t i = 0; i < var_n_ind; ++i)\n    {   CPPAD_ASSERT_KNOWN( var_ind[i] < val_n_ind,\n            \"val2fun: number of independent values is <= var_ind[i]\"\n        );\n        CPPAD_ASSERT_KNOWN( fun_ad_type[ var_ind[i] ] == number_ad_type_enum,\n            \"val2fun: var_ind[i] == dep_ind[j] for some i and j\\n\"\n            \"or var_ind[i] == var_ind[j] for some i and j\"\n        );\n        fun_ad_type[ var_ind[i] ]   = variable_enum;\n        var_addr                    = rec.PutOp( local::InvOp );\n        val2fun_index[ var_ind[i] ] = var_addr;\n    }\n    //\n    // ind_taddr_\n    // address of the independent variables on variable tape\n    ind_taddr_.resize(var_n_ind);\n    for(size_t i = 0; i < var_n_ind; ++i)\n        ind_taddr_[i] = i + 1;\n    //\n    // rec_con_index\n    // First constant in CppAD recording and val_graph is nan\n    Vector<addr_t> rec_con_index( val_con_vec.size() );\n    CPPAD_ASSERT_UNKNOWN( CppAD::isnan( val_con_vec[0] ) );\n    rec_con_index[0] = 0;\n    for(size_t i = 1; i < val_con_vec.size(); ++i)\n        rec_con_index[i] = rec.put_con_par( val_con_vec[i] );\n    //\n    // zero_index\n    addr_t zero_index = rec.put_con_par( Base(0.0) );\n    //\n    // two_sqrt_pi_index: 2 / sqrt(pi)\n    addr_t two_sqrt_pi_index = rec.put_con_par(\n        Base(1.0) / sqrt( atan( Base(1.0) ) )\n    );\n    //\n    // rec_str_index\n    Vector<addr_t> rec_str_index( val_str_vec.size() );\n    for(size_t i = 0; i < val_str_vec.size(); ++i)\n    {   const std::string& str = val_str_vec[i];\n        rec_str_index[i]       = rec.PutTxt( str.c_str() );\n    }\n    //\n    // ad_type_x, ad_type_y, fun_arg, csum_arg, select_y\n    Vector<addr_t>       fun_arg, csum_arg;\n    Vector<bool>         select_y;\n    Vector< AD<Base> >   ax, ay;\n    //\n    // con_x, at_type_x, ad_type_y;\n    // Use CppAD::vector because call_atomic_for_type requires it\n    CppAD::vector<Base>  con_x;\n    CppAD::vector<ad_type_enum> ad_type_x, ad_type_y;\n    //\n    // op_itr\n    local::val_graph::op_iterator<Base> op_itr(val_tape, 0);\n    //\n    // i_op\n    for(addr_t i_op = 0; i_op < val_n_op; ++i_op)\n    {   //\n        // op_itr\n        if( 0 < i_op )\n            ++op_itr;\n        //\n        // op_ptr, arg_index, res_index\n        const base_op_t<Base>* op_ptr    = op_itr.op_ptr();\n        addr_t                 arg_index = op_itr.arg_index();\n        addr_t                 res_index = op_itr.res_index();\n        //\n        // op_enum, is_unary, is_binary, n_arg\n        op_enum_t        op_enum   = op_ptr->op_enum();\n        bool             is_unary  = op_ptr->is_unary();\n        bool             is_binary = op_ptr->is_binary();\n        addr_t           n_before  = op_ptr->n_before();\n        addr_t           n_after   = op_ptr->n_after();\n        addr_t           n_arg     = op_ptr->n_arg(arg_index, val_arg_vec);\n        CPPAD_ASSERT_UNKNOWN( n_before + n_after <= n_arg );\n        //\n        // n_x\n        addr_t n_x = n_arg - n_before - n_after;\n        //\n        // ad_type_x, fun_arg, con_x, max_ad_type\n        ad_type_x.resize(n_x);\n        fun_arg.resize(n_x);\n        con_x.resize(n_x);\n        ad_type_enum max_ad_type = constant_enum;\n        for(addr_t i = 0; i < n_x; ++i)\n        {   addr_t val_index     = val_arg_vec[arg_index + n_before + i];\n            ad_type_x[i] = fun_ad_type[val_index];\n            fun_arg[i]   = val2fun_index[val_index];\n            con_x[i]     = val_index2con[val_index];\n            max_ad_type  = std::max(max_ad_type, ad_type_x[i] );\n        }\n        /*\n        CPPAD_ASSERT_KNOWN(\n            n_x == 0 || constant_enum < max_ad_type,\n            \"val2fun: must first call fold_con\"\n        );\n        */\n        //\n        // rec, fun_ad_type, val2fun_index\n        if( is_unary )\n        {   //\n            fun_ad_type[res_index] = max_ad_type;\n            CPPAD_ASSERT_UNKNOWN( n_arg == 1 );\n            //\n            // rec, val2fun_index\n            if( max_ad_type == dynamic_enum )\n            {   switch( op_enum )\n                {   //\n                    // default\n                    default:\n                    CPPAD_ASSERT_UNKNOWN(false);\n                    tmp_addr = 0; // to avoid compiler warning\n                    break;\n                    //\n                    // BEGIN_SORT_THIS_LINE_PLUS_1\n                    CPPAD_VAL2FUN_DYN_UNARY(abs);\n                    CPPAD_VAL2FUN_DYN_UNARY(acos);\n                    CPPAD_VAL2FUN_DYN_UNARY(acosh);\n                    CPPAD_VAL2FUN_DYN_UNARY(asin);\n                    CPPAD_VAL2FUN_DYN_UNARY(asinh);\n                    CPPAD_VAL2FUN_DYN_UNARY(atan);\n                    CPPAD_VAL2FUN_DYN_UNARY(atanh);\n                    CPPAD_VAL2FUN_DYN_UNARY(cos);\n                    CPPAD_VAL2FUN_DYN_UNARY(cosh);\n                    CPPAD_VAL2FUN_DYN_UNARY(erf);\n                    CPPAD_VAL2FUN_DYN_UNARY(erfc);\n                    CPPAD_VAL2FUN_DYN_UNARY(exp);\n                    CPPAD_VAL2FUN_DYN_UNARY(expm1);\n                    CPPAD_VAL2FUN_DYN_UNARY(log);\n                    CPPAD_VAL2FUN_DYN_UNARY(log1p);\n                    CPPAD_VAL2FUN_DYN_UNARY(neg);\n                    CPPAD_VAL2FUN_DYN_UNARY(sign);\n                    CPPAD_VAL2FUN_DYN_UNARY(sin);\n                    CPPAD_VAL2FUN_DYN_UNARY(sinh);\n                    CPPAD_VAL2FUN_DYN_UNARY(sqrt);\n                    CPPAD_VAL2FUN_DYN_UNARY(tan);\n                    // END_SORT_THIS_LINE_MINUS_1\n                }\n            }\n            else\n            {   switch( op_enum )\n                {\n                    // default\n                    default:\n                    CPPAD_ASSERT_UNKNOWN(false);\n                    tmp_addr = 0; // to avoid compiler warning\n                    break;\n                    //\n                    // BEGIN_SORT_THIS_LINE_PLUS_1\n                    CPPAD_VAL2FUN_VAR_UNARY(abs,     AbsOp);\n                    CPPAD_VAL2FUN_VAR_UNARY(acos,    AcosOp);\n                    CPPAD_VAL2FUN_VAR_UNARY(acosh,   AcoshOp);\n                    CPPAD_VAL2FUN_VAR_UNARY(asin,    AsinOp);\n                    CPPAD_VAL2FUN_VAR_UNARY(asinh,   AsinhOp);\n                    CPPAD_VAL2FUN_VAR_UNARY(atan,    AtanOp);\n                    CPPAD_VAL2FUN_VAR_UNARY(atanh,   AtanhOp);\n                    CPPAD_VAL2FUN_VAR_UNARY(cos,     CosOp);\n                    CPPAD_VAL2FUN_VAR_UNARY(cosh,    CoshOp);\n                    CPPAD_VAL2FUN_VAR_UNARY(exp,     ExpOp);\n                    CPPAD_VAL2FUN_VAR_UNARY(expm1,   Expm1Op);\n                    CPPAD_VAL2FUN_VAR_UNARY(log,     LogOp);\n                    CPPAD_VAL2FUN_VAR_UNARY(log1p,   Log1pOp);\n                    CPPAD_VAL2FUN_VAR_UNARY(neg,     NegOp);\n                    CPPAD_VAL2FUN_VAR_UNARY(sign,    SignOp);\n                    CPPAD_VAL2FUN_VAR_UNARY(sin,     SinOp);\n                    CPPAD_VAL2FUN_VAR_UNARY(sinh,    SinhOp);\n                    CPPAD_VAL2FUN_VAR_UNARY(sqrt,    SqrtOp);\n                    CPPAD_VAL2FUN_VAR_UNARY(tan,     TanOp);\n                    CPPAD_VAL2FUN_VAR_UNARY(tanh,    TanhOp);\n                    // END_SORT_THIS_LINE_MINUS_1\n                    //\n                    // erf\n                    case local::val_graph::erf_op_enum:\n                    {   tmp_addr = rec.PutOp(local::ErfOp);\n                        CPPAD_ASSERT_UNKNOWN( NumArg(local::ErfOp) == 3 );\n                        rec.PutArg( fun_arg[0] );\n                        rec.PutArg( zero_index );\n                        rec.PutArg( two_sqrt_pi_index );\n                    }\n                    break;\n                    //\n                    // erfc\n                    case local::val_graph::erfc_op_enum:\n                    {   tmp_addr = rec.PutOp(local::ErfcOp);\n                        CPPAD_ASSERT_UNKNOWN( NumArg(local::ErfcOp) == 3 );\n                        rec.PutArg( fun_arg[0] );\n                        rec.PutArg( zero_index );\n                        rec.PutArg( two_sqrt_pi_index );\n                    }\n                    break;\n                }\n            }\n            val2fun_index[res_index] = tmp_addr;\n        }\n        else if( is_binary )\n        {   //\n            fun_ad_type[res_index] = max_ad_type;\n            CPPAD_ASSERT_UNKNOWN( n_arg == 2 );\n            //\n            if( max_ad_type == dynamic_enum )\n            {   switch(op_enum)\n                {   default:\n                    CPPAD_ASSERT_UNKNOWN(false);\n                    break;\n                    //\n                    CPPAD_VAL2FUN_DYN_BINARY(add);\n                    CPPAD_VAL2FUN_DYN_BINARY(sub);\n                    CPPAD_VAL2FUN_DYN_BINARY(mul);\n                    CPPAD_VAL2FUN_DYN_BINARY(div);\n                    CPPAD_VAL2FUN_DYN_BINARY(pow);\n                }\n                CPPAD_ASSERT_UNKNOWN( CppAD::isnan( parameter[tmp_addr] ) );\n            }\n            else if(\n                ad_type_x[0] == variable_enum &&\n                ad_type_x[1] == variable_enum )\n            {   switch(op_enum)\n                {   default:\n                    CPPAD_ASSERT_UNKNOWN(false);\n                    break;\n                    //\n                    CPPAD_VAL2FUN_VAR_BINARY(add, AddvvOp);\n                    CPPAD_VAL2FUN_VAR_BINARY(sub, SubvvOp);\n                    CPPAD_VAL2FUN_VAR_BINARY(mul, MulvvOp);\n                    CPPAD_VAL2FUN_VAR_BINARY(div, DivvvOp);\n                    CPPAD_VAL2FUN_VAR_BINARY(pow, PowvvOp);\n                }\n                rec.PutArg(fun_arg[0], fun_arg[1]);\n            }\n            else if( ad_type_x[1] == variable_enum )\n            {   switch(op_enum)\n                {   default:\n                    CPPAD_ASSERT_UNKNOWN(false);\n                    break;\n                    //\n                    CPPAD_VAL2FUN_VAR_BINARY(add, AddpvOp);\n                    CPPAD_VAL2FUN_VAR_BINARY(sub, SubpvOp);\n                    CPPAD_VAL2FUN_VAR_BINARY(mul, MulpvOp);\n                    CPPAD_VAL2FUN_VAR_BINARY(div, DivpvOp);\n                    CPPAD_VAL2FUN_VAR_BINARY(pow, PowpvOp);\n                }\n                rec.PutArg(fun_arg[0], fun_arg[1]);\n            }\n            else\n            {   CPPAD_ASSERT_UNKNOWN( ad_type_x[0] == variable_enum );\n                switch(op_enum)\n                {   default:\n                    CPPAD_ASSERT_UNKNOWN(false);\n                    break;\n                    //\n                    // add\n                    case local::val_graph::add_op_enum:\n                    tmp_addr = rec.PutOp(local::AddpvOp);\n                    std::swap(fun_arg[0], fun_arg[1]);\n                    break;\n                    //\n                    // mul\n                    case local::val_graph::mul_op_enum:\n                    tmp_addr = rec.PutOp(local::MulpvOp);\n                    std::swap(fun_arg[0], fun_arg[1]);\n                    break;\n                    //\n                    CPPAD_VAL2FUN_VAR_BINARY(sub, SubvpOp);\n                    CPPAD_VAL2FUN_VAR_BINARY(div, DivvpOp);\n                    CPPAD_VAL2FUN_VAR_BINARY(pow, PowvpOp);\n                }\n                rec.PutArg(fun_arg[0], fun_arg[1]);\n            }\n            val2fun_index[res_index] = tmp_addr;\n        }\n        else switch( op_enum )\n        {   // ! ( is_unary || is_binary)\n            //\n            // default\n            default:\n            CPPAD_ASSERT_KNOWN( op_enum > local::val_graph::number_op_enum,\n                \"val_graph::val2fun: op_enum is not yet implemented\"\n            );\n            // ------------------------------------------------------------------\n            // dis_op\n            // rec, fun_ad_type, val2fun_index\n            case local::val_graph::dis_op_enum:\n            fun_arg.resize(1);\n            CPPAD_ASSERT_UNKNOWN( n_arg = 2 );\n            {   addr_t dynamic_index  = val_arg_vec[arg_index + 0];\n                if( max_ad_type == dynamic_enum )\n                {   tmp_addr = rec.put_dyn_par(\n                        nan, local::dis_dyn, dynamic_index, fun_arg[0]\n                    );\n                }\n                else\n                {   CPPAD_ASSERT_UNKNOWN( max_ad_type == variable_enum );\n                    tmp_addr = rec.PutOp(local::DisOp);\n                    rec.PutArg( dynamic_index );\n                    rec.PutArg( fun_arg[0] );\n                }\n                fun_ad_type[res_index]   = max_ad_type;\n                val2fun_index[res_index] = tmp_addr;\n            }\n            break;\n            // ------------------------------------------------------------------\n            // con_op\n            // rec, fun_ad_type, val2fun_index\n            case local::val_graph::con_op_enum:\n            CPPAD_ASSERT_UNKNOWN( n_arg = 1 );\n            {   par_addr                 = rec_con_index[ val_arg_vec[arg_index] ];\n                fun_ad_type[res_index]   = constant_enum;\n                val2fun_index[res_index] = par_addr;\n# ifndef NDEBUG\n                const Base& constant = val_con_vec[ val_arg_vec[arg_index] ];\n                CPPAD_ASSERT_UNKNOWN(\n                    CppAD::isnan(constant) || parameter[par_addr] == constant\n                );\n# endif\n            }\n            break;\n            // -------------------------------------------------------------------\n            // pri_op: rec\n            case local::val_graph::pri_op_enum:\n            {   //\n                // before, after, flag, value\n                addr_t before = rec_str_index[ val_arg_vec[arg_index + 0] ];\n                addr_t after  = rec_str_index[ val_arg_vec[arg_index + 1] ];\n                addr_t flag   = fun_arg[0];\n                addr_t value  = fun_arg[1];\n                //\n                // is_var\n                // base 2 representation of [ is_var(flag), is_var(value) ]\n                addr_t is_var = 0;\n                if( fun_ad_type[flag] == variable_enum )\n                    is_var += 1;\n                if( fun_ad_type[value] == variable_enum )\n                    is_var += 2;\n                //\n                // rec\n                rec.PutOp(local::PriOp);\n                rec.PutArg(is_var, flag, before, value, after);\n            }\n            break;\n            // -------------------------------------------------------------------\n            // cexp_op\n            case local::val_graph::cexp_op_enum:\n            {   //\n                // compare, compare_enum, cop\n                addr_t         compare       = val_arg_vec[arg_index + 0];\n                compare_enum_t compare_enum = compare_enum_t( compare );\n                CompareOp      cop;\n                if( compare_enum == local::val_graph::compare_eq_enum )\n                    cop = CompareEq;\n                else if( compare_enum == local::val_graph::compare_le_enum )\n                    cop = CompareLe;\n                else\n                {   CPPAD_ASSERT_UNKNOWN(\n                        compare_enum == local::val_graph::compare_lt_enum\n                    );\n                    cop = CompareLt;\n                }\n                if( max_ad_type == dynamic_enum )\n                {   tmp_addr = rec.put_dyn_cond_exp(\n                        nan, cop, fun_arg[0], fun_arg[1], fun_arg[2], fun_arg[3]\n                    );\n                }\n                else\n                {   addr_t flag = 0;\n                    addr_t bit  = 1;\n                    for(size_t j = 0; j < 4; ++j)\n                    {   if( ad_type_x[j] == variable_enum )\n                            flag |= bit;\n                        bit = 2 * bit;\n                    }\n                    CPPAD_ASSERT_UNKNOWN( flag != 0 );\n                    rec.PutArg(\n                        cop, flag, fun_arg[0], fun_arg[1], fun_arg[2], fun_arg[3]\n                    );\n                    tmp_addr = rec.PutOp(local::CExpOp);\n                }\n                fun_ad_type[res_index]   = max_ad_type;\n                val2fun_index[res_index] = tmp_addr;\n            }\n            break;\n            // -------------------------------------------------------------------\n            // comp_op\n            // rec\n            case local::val_graph::comp_op_enum:\n            {   //\n                // compare\n                addr_t compare  = val_arg_vec[arg_index + 0];\n                //\n                // var_left, var_right, dyn_left, dyn_right\n                bool var_left  = ad_type_x[0] == variable_enum;\n                bool var_right = ad_type_x[1] == variable_enum;\n                bool dyn_left  = ad_type_x[0] == dynamic_enum;\n                bool dyn_right = ad_type_x[1] == dynamic_enum;\n                //\n                // ax\n                ax.resize(2);\n                //\n                if( var_left | dyn_left )\n                    ax[0].taddr_ = fun_arg[0];\n                else\n                    ax[0].value_ = con_x[0];\n                //\n                if( var_right | dyn_right )\n                    ax[1].taddr_ = fun_arg[1];\n                else\n                    ax[1].value_ = con_x[1];\n                //\n                // res, compare_enum\n                compare_enum_t compare_enum = compare_enum_t( compare );\n                bool res;\n                switch(compare_enum)\n                {   //\n                    default:\n                    CPPAD_ASSERT_UNKNOWN(false);\n                    break;\n                    //\n                    case local::val_graph::compare_eq_enum:\n                    res = true;\n                    rec.comp_eq(\n                        var_left, var_right, dyn_left, dyn_right, ax[0], ax[1], res\n                    );\n                    break;\n                    //\n                    case local::val_graph::compare_le_enum:\n                    res = true;\n                    rec.comp_le(\n                        var_left, var_right, dyn_left, dyn_right, ax[0], ax[1], res\n                    );\n                    break;\n                    //\n                    case local::val_graph::compare_lt_enum:\n                    res = true;\n                    rec.comp_lt(\n                        var_left, var_right, dyn_left, dyn_right, ax[0], ax[1], res\n                    );\n                    break;\n                    //\n                    case local::val_graph::compare_ne_enum:\n                    res = false;\n                    rec.comp_eq(\n                        var_left, var_right, dyn_left, dyn_right, ax[0], ax[1], res\n                    );\n                    break;\n                    //\n                    case local::val_graph::compare_no_enum:\n                    break;\n                }\n            }\n            break;\n            // -------------------------------------------------------------------\n            // csum_op\n            // rec, fun_ad_type, val2fun_index\n            case local::val_graph::csum_op_enum:\n            if( dynamic_enum <= max_ad_type )\n            {   //\n                // n_add, n_sub, n_arg\n                addr_t n_add =  val_arg_vec[arg_index + 0];\n                addr_t n_sub =  val_arg_vec[arg_index + 1];\n                CPPAD_ASSERT_UNKNOWN( n_arg == 3 + n_add + n_sub );\n                //\n                // sum_constant\n                Base sum_constant = Base(0.0);\n                for(addr_t i = 0; i < n_add; ++i)\n                {   if( ad_type_x[i] <= constant_enum )\n                        sum_constant += con_x[i];\n                }\n                for(addr_t i = 0; i < n_sub; ++i)\n                {   if( ad_type_x[n_add + i] <= constant_enum )\n                        sum_constant -= con_x[n_add + i];\n                }\n                // rec, sum_constant_addr\n                addr_t sum_constant_addr = rec.put_con_par(sum_constant);\n                CPPAD_ASSERT_UNKNOWN(parameter[sum_constant_addr] == sum_constant);\n                //\n                if( max_ad_type == dynamic_enum )\n                {   tmp_addr = sum_constant_addr;\n                    for(addr_t i = 0; i < n_x; ++i)\n                    {   tmp_addr = rec.put_dyn_par(\n                            nan, local::add_dyn, tmp_addr, fun_arg[i]\n                        );\n                        CPPAD_ASSERT_UNKNOWN( CppAD::isnan( parameter[tmp_addr] ) );\n                    }\n                }\n                else if( max_ad_type == variable_enum )\n                {   //\n                    // n_add_var, n_add_dyn\n                    addr_t n_add_dyn = 0;\n                    addr_t n_add_var = 0;\n                    for(addr_t i = 0; i < n_add; ++i)\n                    {   if( ad_type_x[i] == dynamic_enum )\n                            ++n_add_dyn;\n                        if( ad_type_x[i] == variable_enum )\n                            ++n_add_var;\n                    }\n                    //\n                    // n_add_var, n_add_dyn\n                    addr_t n_sub_dyn = 0;\n                    addr_t n_sub_var = 0;\n                    for(addr_t i = 0; i < n_sub; ++i)\n                    {   if( ad_type_x[n_add + i] == dynamic_enum )\n                            ++n_sub_dyn;\n                        if( ad_type_x[n_add + i] == variable_enum )\n                            ++n_sub_var;\n                    }\n                    //\n                    // csum_arg\n                    addr_t n_tot = 6 + n_add_var + n_sub_var + n_add_dyn + n_sub_dyn;\n                    csum_arg.resize(n_tot);\n                    csum_arg[0] = sum_constant_addr;\n                    csum_arg[1] = 5 + n_add_var;\n                    csum_arg[2] = csum_arg[1] + n_sub_var;\n                    csum_arg[3] = csum_arg[2] + n_add_dyn;\n                    csum_arg[4] = csum_arg[3] + n_sub_dyn;\n                    //\n                    addr_t i_variable = 5;\n                    addr_t i_dynamic  = i_variable + n_add_var + n_sub_var;\n                    for(addr_t i = 0; i < n_add; ++i)\n                    {   if( ad_type_x[i] == dynamic_enum )\n                            csum_arg[i_dynamic++]  = fun_arg[i];\n                        if( ad_type_x[i] == variable_enum )\n                            csum_arg[i_variable++] = fun_arg[i];\n                    }\n                    for(addr_t i = 0; i < n_sub; ++i)\n                    {   if( ad_type_x[n_add + i] == dynamic_enum )\n                            csum_arg[i_dynamic++]  = fun_arg[n_add + i];\n                        if( ad_type_x[n_add + i] == variable_enum )\n                            csum_arg[i_variable++] = fun_arg[n_add + i];\n                    }\n                    CPPAD_ASSERT_UNKNOWN( i_dynamic == n_tot - 1 );\n                    csum_arg[n_tot - 1] = n_tot;\n                    //\n                    // rec, tmp_addr\n                    tmp_addr = rec.PutOp(local::CSumOp);\n                    for(addr_t i = 0; i < n_tot; ++i)\n                        rec.PutArg( csum_arg[i] );\n                    CPPAD_ASSERT_UNKNOWN( local::NumRes(local::CSumOp) == 1 );\n                }\n                fun_ad_type[res_index]   = max_ad_type;\n                val2fun_index[res_index] = tmp_addr;\n            }\n            break;\n            // -------------------------------------------------------------------\n            // vec_op\n            case local::val_graph::vec_op_enum:\n            // All the VecAD objects have already been initialized\n            break;\n            //\n            // load_op\n            case local::val_graph::load_op_enum:\n            {   addr_t which_vector  = val_arg_vec[arg_index + 0];\n                offset               = vecad_offset[which_vector];\n                addr_t load_op_index = addr_t( rec.num_var_load() );\n                rec.PutArg(offset, fun_arg[0], load_op_index);\n                if( ad_type_x[0] < variable_enum )\n                    var_addr = rec.PutLoadOp(local::LdpOp);\n                else\n                    var_addr = rec.PutLoadOp(local::LdvOp);\n                //\n                // The result of a load function is always a variable\n                fun_ad_type[res_index]   = variable_enum;\n                val2fun_index[res_index] = var_addr;\n            }\n            break;\n            //\n            // store_op\n            case local::val_graph::store_op_enum:\n            {   addr_t which_vector = val_arg_vec[arg_index + 0];\n                offset              = vecad_offset[which_vector];\n                rec.PutArg(offset, fun_arg[0], fun_arg[1] );\n                if( ad_type_x[0] < variable_enum )\n                {   if( ad_type_x[1] < variable_enum )\n                        rec.PutOp(local::StppOp);\n                    else\n                        rec.PutOp(local::StpvOp);\n                }\n                else\n                {   if( ad_type_x[1] < variable_enum )\n                        rec.PutOp(local::StvpOp);\n                    else\n                        rec.PutOp(local::StvvOp);\n                }\n            }\n            break;\n            //\n            // -------------------------------------------------------------------\n            // call_op\n            // rec, fun_ad_type, val2fun_index\n            case local::val_graph::call_op_enum:\n            {   //\n                // atomic_index, call_id\n                addr_t n_res        =  val_arg_vec[arg_index + 1];\n                size_t atomic_index = size_t( val_arg_vec[arg_index + 2] );\n                size_t call_id      = size_t( val_arg_vec[arg_index + 3] );\n                //\n                // ad_type_y\n                ad_type_y.resize(n_res);\n                local::val_graph::call_atomic_for_type<Base>(\n                    con_x, ad_type_x, ad_type_y, atomic_index, call_id\n                );\n                //\n                // record_dynamic, record_variable\n                bool record_dynamic  = false;\n                bool record_variable = false;\n                for(addr_t i = 0; i < n_res; ++i)\n                {   CPPAD_ASSERT_UNKNOWN( ad_type_y[i] <= variable_enum );\n                    record_dynamic  |= ad_type_y[i] == dynamic_enum;\n                    record_variable |= ad_type_y[i] == variable_enum;\n                }\n                // tape_id\n                // tape_id is zero because not a true recording\n                tape_id_t tape_id = 0;\n                //\n                // ax, ay\n                if( record_dynamic || record_variable )\n                {   //\n                    // ax\n                    ax.resize(n_x);\n                    for(addr_t j = 0; j < n_x; ++j)\n                    {   addr_t val_index = val_arg_vec[arg_index + n_before + j];\n                        ax[j].taddr_   = val2fun_index[val_index];\n                        ax[j].value_   = val_index2con[val_index];\n                    }\n                    // ay, ad_type_y\n                    ay.resize(n_res);\n                    for(addr_t j = 0; j < n_res; ++j)\n                    {   ay[j].taddr_     = 0; // not used\n                        ay[j].value_     = val_index2con[res_index + j];\n                        if( use_val.size() != 0 )\n                        {   if( ! use_val[res_index + j] )\n                            {   ay[j].value_  = nan;\n                                if( ad_type_y[j] == variable_enum )\n                                    ad_type_y[j] = constant_enum;\n                            }\n                        }\n                    }\n                }\n                if( record_dynamic ) rec.put_dyn_atomic(\n                    tape_id, atomic_index, call_id, ad_type_x, ad_type_y, ax, ay\n                );\n                if( record_variable ) rec.put_var_atomic(\n                    tape_id, atomic_index, call_id, ad_type_x, ad_type_y, ax, ay\n                );\n                //\n                // val2fun_index, fun_ad_type\n                for(addr_t i = 0; i < n_res; ++i)\n                {   val2fun_index[res_index + i] = ay[i].taddr_;\n                    fun_ad_type[res_index + i]   = ad_type_y[i];\n                }\n            }\n            break;\n        }\n    }\n    // dep_taddr_, dep_parameter, rec\n    // dep_taddr_ is address of the dependent variables on variable tape\n    dep_taddr_.resize( val_dep_vec.size() );\n    dep_parameter_.resize( val_dep_vec.size() );\n    for(size_t i = 0; i < val_dep_vec.size(); ++i)\n    {   addr_t val_index     = val_dep_vec[i];\n        ad_type_enum ad_type = fun_ad_type[val_index];\n        addr_t fun_index     = val2fun_index[val_index];\n        dep_parameter_[i]    = ad_type < variable_enum;\n        if( dep_parameter_[i] )\n        {   // see RecordParOp(const AD<Base>& y)\n            rec.PutArg( fun_index );\n            fun_index = rec.PutOp(local::ParOp);\n        }\n        dep_taddr_[i] = size_t( fun_index );\n    }\n    // rec\n    rec.PutOp(local::EndOp);\n    //\n    //\n    // ----------------------------------------------------------------------\n    // End recording, set private member data except for\n    // ----------------------------------------------------------------------\n    //\n    // bool values in this object except check_for_nan_\n    has_been_optimized_        = false;\n    //\n    // size_t values in this object\n    compare_change_count_      = 1;\n    compare_change_number_     = 0;\n    compare_change_op_index_   = 0;\n    num_order_taylor_          = 0;\n    cap_order_taylor_          = 0;\n    num_direction_taylor_      = 0;\n    num_var_tape_              = rec.num_var();\n    //\n    // taylor_\n    taylor_.resize(0);\n    //\n    // cskip_op_\n    cskip_op_.resize( rec.num_var_op() );\n    //\n    // load_op2var_\n    load_op2var_.resize( rec.num_var_load() );\n    //\n    // play_\n    // Now that each dependent variable has a place in the recording,\n    // and there is a EndOp at the end of the record, we can transfer the\n    // recording to the player and and erase the recording.\n    play_.get_recording(rec, var_n_ind);\n    //\n    // ind_taddr_\n    // Note that play_ has been set, we can use it to check operators\n    CPPAD_ASSERT_UNKNOWN( var_n_ind < num_var_tape_);\n    for(size_t j = 0; j < var_n_ind; j++)\n    {   CPPAD_ASSERT_UNKNOWN( play_.GetOp(j+1) == local::InvOp );\n        CPPAD_ASSERT_UNKNOWN( ind_taddr_[j] = j+1 );\n    }\n    //\n    // for_jac_sparse_pack_, for_jac_sparse_set_\n    for_jac_sparse_pack_.resize(0, 0);\n    for_jac_sparse_set_.resize(0,0);\n    //\n    // resize subgraph_info_\n    subgraph_info_.resize(\n        ind_taddr_.size(),   // n_dep\n        dep_taddr_.size(),   // n_ind\n        play_.num_var_op(),  // n_op\n        play_.num_var()      // n_var\n    );\n    //\n    // set the function name\n    function_name_ = \"\";\n    //\n    //\n    return;\n}\n\n# undef CPPAD_VAL2FUN_DYN_UNARY\n# undef CPPAD_VAL2FUN_DYN_BINARY\n# undef CPPAD_VAL2FUN_VAR_UNARY\n# undef CPPAD_VAL2FUN_VAR_BINARY\n\n} // END_CPPAD_NAMESPACE\n// --------------------------------------------------------------------------\n# endif\n"
  },
  {
    "path": "include/cppad/local/val_graph/val_graph.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-23 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin val_graph dev}\n\nValue Operator Representation of a Function\n###########################################\n\nSee Also\n********\n:ref:`json_ad_graph-name`, :ref:`cpp_ad_graph-name`\n\nStatic Single-Assignment\n************************\nThis is an\n`SSA <https://en.wikipedia.org/wiki/Static_single-assignment_form>`_\nrepresentation of a function :math:`y = f(x)`.\nThe vector *x* is called the independent vector,\nand *y* is called the dependent vector.\nA value may be a CppAD\n:ref:`glossary@Parameter@Constant`,\n:ref:`glossary@Parameter@Dynamic` parameter ,\nor a :ref:`glossary@Variable` .\n\nValue Vector\n************\nThe values are ordered in a vector\n:math:`( v_0 , \\ldots ,  v_{p-1} )` where *p* is the number of values.\n\nIndependent Vector\n==================\nThe independent sub-vector is\n\n.. math::\n\n    x = ( v_0 , \\cdots , v_{n-1} )\n\nwhere :math:`n \\leq p` is the length of the dependent vector.\n\nResult Vector\n=============\nThe result sub-vector is\n:math:`( v_n , \\ldots , v_{p-1} )` .\nThese are the values computed by the algorithm.\nThis is a static single assignment SSA representation; i.e.,\neach result has one and only one assignment.\n\nDependent Vector\n================\nThere is a vector of non-negative integer indices\n:math:`( d_0 , \\cdots , d_{m-1} )`\nthat specify the dependent vector as follows\n\n.. math::\n\n    y  = ( v_{d[0]} , \\cdots , v_{d[m-1]} )\n\nnote that :math:`d[j]` is used in place of :math:`d_j` above to\navoid having two levels of sub-scripting.\n\nConstant Vector\n***************\nThere is a separate constant vector\n:math:`( c_0 , \\ldots ,  c_{q-1} )` where *q* is the number of constants.\n\nOperator\n********\nEach component of the result vector is computed by an operator.\n\nConstant Operator\n=================\nThe constant operator copies a constant from the constant vector\nto the result vector; i.e.\n:math:`v_\\ell = c_k` where\n:math:`n \\leq \\ell < p` and\n:math:`0 \\leq k < q` .\n\nUnary Operator\n==============\nA unary operator has one value argument and one result; i.e.,\n:math:`v_\\ell = \\phi ( v_k )` where\n:math:`n \\leq \\ell < p`,\n:math:`0 \\leq k < \\ell` and\n:math:`\\phi` is the function corresponding to the operator.\n\nBinary Operator\n===============\nA binary operator has two value arguments and one result; i.e.,\n:math:`v_\\ell = \\phi ( v_j , v_k )` where\n:math:`n \\leq \\ell < p`,\n:math:`0 \\leq j < \\ell` ,\n:math:`0 \\leq k < \\ell` and\n:math:`\\phi` is the function corresponding to the operator.\n\nFunction Operator\n=================\nEach function operator has its own number of argument and result values.\nThe arguments need not be sequential, but the results are; i.e.,\n\n.. math::\n\n        ( v_\\ell , v_{\\ell+1} , \\cdots ) = \\phi ( v_j , v_k , \\cdots )\n\nwhere\n:math:`n \\leq \\ell < p`,\n:math:`0 \\leq j < \\ell` ,\n:math:`0 \\leq k < \\ell` , ... , and\n:math:`\\phi` is the function corresponding to the operator.\n\nImplementation\n**************\n{xrst_toc_table\n    include/cppad/local/val_graph/val_type.hpp\n    include/cppad/local/val_graph/base_op.hpp\n    include/cppad/local/val_graph/print_op.hpp\n    include/cppad/local/val_graph/tape.hpp\n    include/cppad/local/val_graph/op_enum2class.hpp\n    include/cppad/local/val_graph/fun2val.hpp\n    include/cppad/local/val_graph/val2fun.hpp\n    include/cppad/local/val_graph/val_optimize.hpp\n    include/cppad/local/val_graph/dyn_type.hpp\n    include/cppad/local/val_graph/var_type.hpp\n    include/cppad/local/val_graph/call_atomic.hpp\n    include/cppad/local/val_graph/enable_parallel.hpp\n}\n\n\n{xrst_end val_graph}\n"
  },
  {
    "path": "include/cppad/local/val_graph/val_optimize.hpp",
    "content": "# ifndef  CPPAD_LOCAL_VAL_GRAPH_VAL_OPTIMIZE_HPP\n# define  CPPAD_LOCAL_VAL_GRAPH_VAL_OPTIMIZE_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-23 Bradley M. Bell\n// --------------------------------------------------------------------------\n/*\n------------------------------------------------------------------------------\n{xrst_begin val_optimize dev}\n\n\nOptimize the Value Graph Corresponding to This Function\n#######################################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_VAL_OPTIMIZE\n    // END_VAL_OPTIMIZE\n}\n\noptions\n=======\nSee :ref:`optimize@options` .\n\n{xrst_end val_optimize}\n*/\n\n# include <cppad/core/ad_fun.hpp>\n# include <cppad/local/val_graph/tape.hpp>\n# include <cppad/local/optimize/extract_option.hpp>\n\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n\n// BEGIN_VAL_OPTIMIZE\ntemplate <class Base, class RecBase>\nvoid ADFun<Base, RecBase>::val_optimize(const std::string& options)\n// END_VAL_OPTIMIZE\n{   //\n    // compare_op, cumulative_sum_op, print_for_op,\n    local::optimize::options_t result = local::optimize::extract_option(options);\n    bool compare_op          = result.compare_op;\n    bool cumulative_sum_op   = result.cumulative_sum_op;\n    bool print_for_op        = result.print_for_op;\n    //\n    CPPAD_ASSERT_UNKNOWN( result.val_graph == true );\n    CPPAD_ASSERT_KNOWN( result.conditional_skip == false,\n        \"optimize options: \"\n        \"val_graph is present and no_conditional_skip is not present\"\n    );\n    // n_dyn_ind, n_var_ind\n    size_t n_dyn_ind = size_dyn_ind();\n    size_t n_var_ind = Domain();\n    //\n    // dyn_ind, var_ind\n    using CppAD::local::val_graph::Vector;\n    Vector<size_t> dyn_ind(n_dyn_ind), var_ind(n_var_ind);\n    for(size_t j = 0; j < n_dyn_ind; ++j)\n        dyn_ind[j] = j;\n    for(size_t j = 0; j < n_var_ind; ++j)\n        var_ind[j] = n_dyn_ind + j;\n    //\n    // val_tape\n    // value operator representation corresponding to this function\n    local::val_graph::tape_t<Base> val_tape;\n    fun2val(val_tape);\n    //\n    //\n    // this\n    // free all the memory associated with this function\n    {   ADFun<Base> g;\n        swap(g);\n    }\n    /*\n    Vector<Base> val_vec( val_tape.n_val() );\n    for(addr_t i = 0; i < val_tape.n_ind(); ++i)\n        val_vec[i] = Base(i + 1);\n    bool   trace = true;\n    val_tape.eval(trace, val_vec);\n    */\n    // val_tape: renumber\n    val_tape.renumber();\n    //\n    // val_tape: fold_con();\n    //\n    // val_tape: summation\n    if( cumulative_sum_op )\n        val_tape.summation();\n    //\n    // val_tape: dead_code, val_use\n    if( compare_op )\n        val_tape.set_option(\"keep_compare\", \"true\");\n    else\n        val_tape.set_option(\"keep_compare\", \"false\");\n    if( print_for_op )\n        val_tape.set_option(\"keep_print\", \"true\");\n    else\n        val_tape.set_option(\"keep_print\", \"false\");\n    vectorBool use_val = val_tape.dead_code();\n    /*\n    val_vec.resize( val_tape.n_val() );\n    val_tape.eval(trace, val_vec);\n    */\n    // this\n    // convert optimized value graph to fun\n    val2fun(val_tape, dyn_ind, var_ind, use_val);\n    //\n    // no collision limit in value graph representation.\n    return;\n}\n\n} // END_CPPAD_NAMESPACE\n// --------------------------------------------------------------------------\n# endif\n"
  },
  {
    "path": "include/cppad/local/val_graph/val_type.hpp",
    "content": "# ifndef  CPPAD_LOCAL_VAL_GRAPH_VAL_TYPE_HPP\n# define  CPPAD_LOCAL_VAL_GRAPH_VAL_TYPE_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2023-24 Bradley M. Bell\n// -------------------------------------------------------------\n# include <vector>\n# include <cassert>\n# include <cstddef>\n# include <cppad/utility/vector.hpp>\n# include <cppad/configure.hpp>\n\nnamespace CppAD { namespace local { namespace val_graph {\n/*\n{xrst_begin val_graph_type dev}\n{xrst_spell\n    typedef\n}\n\nValue Operator Type Definitions\n###############################\n\naddr_t\n******\nThis type is used to store vectors of non-negative integers.\nIt must be able to support an index equal to the length of the arg_vec vector.\nA signed type can be used for testing, but an unsigned type will support\nmore indices with the same memory usage.\n{xrst_code hpp} */\ntypedef CPPAD_TAPE_ADDR_TYPE addr_t;\n/* {xrst_code}\n\nVector\n******\nThis is a :ref:`SimpleVector-name` template class.\nIn addition, these vectors have the following member functions\n``push_back`` , ``clear`` .\nThese member functions have he same specifications as for std::vector.\nThe std::vector and CppAD::vector are two example template vector\nclasses that can be used.\n{xrst_code hpp} */\ntemplate <class Value> using Vector = CppAD::vector<Value>;\n/* {xrst_code}\n\nop_enum_t\n*********\nA concrete class does not have any pure virtual functions.\nThis enum type is used to identify the concrete operator class types.\n{xrst_spell_off}\n{xrst_comment BEGIN_SORT_THIS_LINE_PLUS_3}\n{xrst_code hpp}*/\nenum op_enum_t {\n    abs_op_enum,      // absolute value\n    acos_op_enum,     // inverse cosine\n    acosh_op_enum,    // inverse hyperbolic cosine\n    add_op_enum,      // addition\n    asin_op_enum,     // inverse sine\n    asinh_op_enum,    // inverse hyperbolic sine\n    atan_op_enum,     // inverse tangent\n    atanh_op_enum,    // inverse hyperbolic tangent\n    call_op_enum,     // atomic functions\n    cexp_op_enum,     // conditional expression\n    comp_op_enum,     // comparison\n    con_op_enum,      // constants\n    cos_op_enum,      // cosine\n    cosh_op_enum,     // hyperbolic cosine\n    csum_op_enum,     // cumulative summation\n    dis_op_enum,      // discrete functions\n    div_op_enum,      // division\n    erf_op_enum,      // error function\n    erfc_op_enum,     // complementary error function\n    exp_op_enum,      // exponential function\n    expm1_op_enum,    // exponential function minus one\n    load_op_enum,     // load an element from a dynamic vector\n    log1p_op_enum,    // one plust natural log\n    log_op_enum,      // natural log function\n    mul_op_enum,      // multiplication\n    neg_op_enum,      // negative\n    pow_op_enum,      // power function\n    pri_op_enum,      // print\n    sign_op_enum,     // sign function (1, 0, -1)\n    sin_op_enum,      // sine function\n    sinh_op_enum,     // hyperbolic sine\n    sqrt_op_enum,     // square root\n    store_op_enum,    // store an element in a dynamic vector\n    sub_op_enum,      // subtraction\n    tan_op_enum,      // tangent\n    tanh_op_enum,     // hyperbolic tangent\n    vec_op_enum,      // create a new dynamic vector\n    number_op_enum\n};\n/* {xrst_code}\n{xrst_comment END_SORT_THIS_LINE_MINUS_4}\n{xrst_spell_on}\nThe ``number_op_enum`` entry is used for the number of concrete\noperator class types (and does not correspond to an operator).\n\ncompare_op_enum_t\n*****************\nThis enum type is used to identify which comparison a :ref:`val_comp_op-name`\ndoes.\n{xrst_code hpp}*/\nenum compare_enum_t {\n    compare_eq_enum,    // equal\n    compare_ne_enum,    // not equal\n    compare_lt_enum,    // less than\n    compare_le_enum,    // less than or equal\n    compare_no_enum,    // no comparison (used during optimization)\n    number_compare_enum\n};\n/*{xrst_code}\n{xrst_end val_graph_type}\n*/\n} } } // END_CPPAD_LOCAL_VAL_GRAPH_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/val_graph/var_type.hpp",
    "content": "# ifndef  CPPAD_LOCAL_VAL_GRAPH_VAR_TYPE_HPP\n# define  CPPAD_LOCAL_VAL_GRAPH_VAR_TYPE_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2023-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n-------------------------------------------------------------------------------\n{xrst_begin type_var_op dev}\n\nTypes of Variable Operators\n###########################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_TYPE_VAR_OP\n    // END_TYPE_VAR_OP\n}\n\nvar_op\n******\nis the variable operator.\n\nis_unary\n********\nIf the return value for is_unary is true,\nthis operator has one operand, one result, and is recorded by\nspecifying the operator and variable address of the operand on the tape.\n\nis_binary\n*********\nIf the return value for is_binary is true,\nthis operator has two operands, one result, and is recorded by\nspecifying the operator and variable or parameter address for each operand.\n\nis_compare\n**********\nIf the return value for is_compare is true, this is a compare operator.\nIt has two operands, no result, and is recorded by\nspecifying the operator and variable or parameter address for each operand.\n\n{xrst_end type_var_op}\n*/\nnamespace CppAD { namespace local { namespace val_graph {\n\n// BEGIN_TYPE_VAR_OP\ninline void type_var_op(\n    op_code_var var_op     ,\n    bool& is_unary    ,\n    bool& is_binary   ,\n    bool& is_compare  )\n// END_TYPE_VAR_OP\n{   //\n    switch(var_op)\n    {   //\n        default:\n        CPPAD_ASSERT_UNKNOWN(false);\n        break;\n        // BEGIN_SORT_THIS_LINE_PLUS_1\n        case AFunOp:\n        case BeginOp:\n        case CExpOp:\n        case CSumOp:\n        case DisOp:\n        case EndOp:\n        case FunapOp:\n        case FunavOp:\n        case FunrpOp:\n        case FunrvOp:\n        case InvOp:\n        case LdpOp:\n        case LdvOp:\n        case ParOp:\n        case PriOp:\n        case StppOp:\n        case StpvOp:\n        case StvpOp:\n        case StvvOp:\n        // END_SORT_THIS_LINE_MINUS_1\n        is_unary   = false;\n        is_binary  = false;\n        is_compare = false;\n        break;\n        //\n        // unary operators\n        // BEGIN_SORT_THIS_LINE_PLUS_1\n        case AbsOp:\n        case AcosOp:\n        case AcoshOp:\n        case AsinOp:\n        case AsinhOp:\n        case AtanOp:\n        case AtanhOp:\n        case CosOp:\n        case CoshOp:\n        case ErfOp:\n        case ErfcOp:\n        case ExpOp:\n        case Expm1Op:\n        case Log1pOp:\n        case LogOp:\n        case NegOp:\n        case SignOp:\n        case SinOp:\n        case SinhOp:\n        case SqrtOp:\n        case TanOp:\n        case TanhOp:\n        // END_SORT_THIS_LINE_MINUS_1\n        is_unary   = true;\n        is_binary  = false;\n        is_compare = false;\n        break;\n        //\n        // binary operators\n        // BEGIN_SORT_THIS_LINE_PLUS_1\n        case AddpvOp:\n        case AddvvOp:\n        case DivpvOp:\n        case DivvpOp:\n        case DivvvOp:\n        case MulpvOp:\n        case MulvvOp:\n        case PowpvOp:\n        case PowvpOp:\n        case PowvvOp:\n        case SubpvOp:\n        case SubvpOp:\n        case SubvvOp:\n        case ZmulpvOp:\n        case ZmulvpOp:\n        case ZmulvvOp:\n        // END_SORT_THIS_LINE_MINUS_1\n        is_unary   = false;\n        is_binary  = true;\n        is_compare = false;\n        break;\n        //\n        // compare operators\n        // BEGIN_SORT_THIS_LINE_PLUS_1\n        case local::EqppOp:\n        case local::EqpvOp:\n        case local::EqvvOp:\n        case local::LeppOp:\n        case local::LepvOp:\n        case local::LevpOp:\n        case local::LevvOp:\n        case local::LtppOp:\n        case local::LtpvOp:\n        case local::LtvpOp:\n        case local::LtvvOp:\n        case local::NeppOp:\n        case local::NepvOp:\n        case local::NevvOp:\n        // END_SORT_THIS_LINE_MINUS_1\n        is_unary   = false;\n        is_binary  = false;\n        is_compare = true;\n        break;\n    }\n    return;\n}\n\n} } } // END_CPPAD_LOCAL_VAL_GRAPH_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/val_graph/vector_op.hpp",
    "content": "# ifndef  CPPAD_LOCAL_VAL_GRAPH_VECTOR_OP_HPP\n# define  CPPAD_LOCAL_VAL_GRAPH_VECTOR_OP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2023-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/local/val_graph/base_op.hpp>\n# include <cppad/local/val_graph/print_op.hpp>\n\n// define CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL\n# include <cppad/utility/thread_alloc.hpp>\n\nnamespace CppAD { namespace local { namespace val_graph {\n/*\n{xrst_begin_parent val_vector_op dev}\n\nThe Dynamic Vector Value Operators\n##################################\nThese classes implement dynamic vectors; i.e., vector were\nthe indices may depend on the independent values.\n\nind_vec_vec\n***********\nThe size of this vector is equal to the number of dynamic vectors.\nThe size of each element of this vector is equal to the size of the\ncorresponding dynamic vector plus one.\nIt is a vector of value indices mapping dynamic vector indices to the\nindex in the value vector for the current value of the dynamic vector.\nThe last element for each dynamic vector is a flag.\nIf it is nan, an index value for a store operation was nan.\nIn this case, all the subsequent load operation results (for that vector)\nwill be nan.\nIn addition, if the index for a load operation is nan,\nthe corresponding result will be nan.\n\n{xrst_toc_hidden\n    val_graph/vec_xam.cpp\n}\nOperators\n*********\nOnly the following operators use the eval\n:ref:`val_base_op@eval@ind_vec_vec` argument:\n`:ref:val_vec_op-name` ,\n`:ref:val_load_op-name` ,\n`:ref:val_store_op-name` .\n\n\nExample\n*******\nThe file :ref:`com_xam.cpp <val_vec_xam.cpp-name>`\nis an example and test that uses this operator.\n\n{xrst_end val_vector_op}\n// ---------------------------------------------------------------------------\n{xrst_begin val_vec_op dev}\n\nCreate A Dynamic Vector Operator\n################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_VEC_OP_T\n    // END_VEC_OP_T\n}\n\nContext\n*******\nIt is derived from :ref:`val_base_op-name` .\nIt overrides all its base class virtual member functions\nand is a concrete class (it has no pure virtual functions).\n\nget_instance\n************\nThis static member function returns a pointer to a vec_op_t object.\n\nop_enum\n*******\nThis override of :ref:`val_base_op@op_enum` returns ``vec_op_enum`` .\n\nn_before\n********\nThis override of :ref:`val_base_op@n_before` returns 1.\n{xrst_literal\n    // BEGIN_VEC_ARG_BEFORE\n    // END_VEC_ARG_BEFORE\n}\n\nn_after\n*******\nThis override of :ref:`val_base_op@n_after` returns 0.\n\nn_arg\n*****\nThis override of :ref:`val_base_op@n_arg` returns 1.\n\nn_res\n*****\nThis override of :ref:`val_base_op@n_res` return 0.\n\neval\n****\nThis override of :ref:`val_base_op@eval` implement a\ncreate dynamic vector operation.\n\ntrace\n=====\nIf trace is true, :ref:`val_print_vec_op-name`\nis called to print this operator.\n\n{xrst_end val_vec_op}\n*/\n// BEGIN_VEC_OP_T\ntemplate <class Value>\nclass vec_op_t : public base_op_t<Value> {\npublic:\n    // n_before\n    addr_t n_before(void) const override\n    {  return 1; }\n    //\n    // n_after\n    addr_t n_after(void) const override\n    {  return 0; }\n    //\n    // get_instance\n    static vec_op_t* get_instance(void)\n    {  CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL;\n        static vec_op_t instance;\n        return &instance;\n    }\n    // op_enum\n    op_enum_t op_enum(void) const override\n    {  return vec_op_enum; }\n// END_VEC_OP_T\n    //\n    // n_arg\n    addr_t n_arg(\n        addr_t                arg_index    ,\n        const Vector<addr_t>& arg_vec      ) const override\n    {  return 1; }\n    //\n    // n_res\n    addr_t n_res(\n        addr_t                arg_index    ,\n        const Vector<addr_t>& arg_vec      ) const override\n    {  return 0; }\n    //\n    // eval\n    void eval(\n        const tape_t<Value>*      tape           ,\n        bool                      trace          ,\n        addr_t                    arg_index      ,\n        addr_t                    res_index      ,\n        Vector<Value>&            val_vec        ,\n        Vector< Vector<addr_t> >& ind_vec_vec    ,\n        size_t&                   compare_false  ) const override\n    {  //\n        // arg_vec, vec_vec\n        const Vector<addr_t>& arg_vec( tape->arg_vec() );\n        //\n        // which_vector\n        // BEGIN_VEC_ARG_BEFORE\n        addr_t  which_vector = arg_vec[arg_index + 0];\n        // END_VEC_ARG_BEFORE\n        //\n        // initial\n        const Vector<addr_t> initial = tape->vec_initial()[which_vector];\n# ifndef NDEBUG\n        for(size_t i = 0; i < initial.size(); ++i)\n        {  CPPAD_ASSERT_KNOWN(\n                initial[i] < res_index,\n                \"vec_op: initial indices must come before index of next result\"\n            );\n        }\n# endif\n        //\n        // ind_vec_vec\n        CPPAD_ASSERT_UNKNOWN( ind_vec_vec.size() == size_t(which_vector) );\n        ind_vec_vec.push_back(initial);\n        ind_vec_vec[which_vector].resize( initial.size() + 1 );\n        //\n        // ind_vec_vec\n        // Does not point to the nan in the tape which is at index tape->n_ind()\n        CPPAD_ASSERT_UNKNOWN( 0 < tape->n_ind() );\n        ind_vec_vec[which_vector][ initial.size() ] = 0;\n        //\n        if( ! trace )\n            return;\n        //\n        // print_vec_op\n        print_vec_op(which_vector, initial);\n    }\n};\n// ---------------------------------------------------------------------------\n/*\n{xrst_begin val_load_op dev}\n\nDynamic Vector Load Operator\n############################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_LOAD_OP_T\n    // END_LOAD_OP_T\n}\n\nContext\n*******\nIt is derived from :ref:`val_base_op-name` .\nIt overrides all its base class virtual member functions\nand is a concrete class (it has no pure virtual functions).\n\nget_instance\n************\nThis static member function returns a pointer to a load_op_t object.\n\nop_enum\n*******\nThis override of :ref:`val_base_op@op_enum` returns ``load_op_enum`` .\n\nn_before\n********\nThis override of :ref:`val_base_op@n_before` returns 1.\n{xrst_literal\n    // BEGIN_LOAD_ARG_BEFORE\n    // END_LOAD_ARG_BEFORE\n}\n\nn_after\n*******\nThis override of :ref:`val_base_op@n_after` returns 0.\n\nn_arg\n*****\nThis override of :ref:`val_base_op@n_arg` returns 2.\n\nn_res\n*****\nThis override of :ref:`val_base_op@n_res` return 1.\n\neval\n****\nThis override of :ref:`val_base_op@eval` implement a\ndynamic vector load operation.\n\nwhich_vector\n============\nWe use *which_vector* to denote the index corresponding to this\ndynamic vector; i.e.  arg_vec[arg_index + 0].\n\nvector_index\n============\nWe use *vector_index* to denote the index, in the value vector,\nof the index in the dynamic vector, of the element for this load; i.e.\narg_vec[arg_index + 1].\n\ntrace\n=====\nIf trace is true, :ref:`val_print_load_op-name`\nis called to print this operator.\n\n{xrst_end val_load_op}\n*/\n// BEGIN_LOAD_OP_T\ntemplate <class Value>\nclass load_op_t : public base_op_t<Value> {\npublic:\n    // n_before\n    addr_t n_before(void) const override\n    {  return 1; }\n    //\n    // n_after\n    addr_t n_after(void) const override\n    {  return 0; }\n    //\n    // get_instance\n    static load_op_t* get_instance(void)\n    {  CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL;\n        static load_op_t instance;\n        return &instance;\n    }\n    // op_enum\n    op_enum_t op_enum(void) const override\n    {  return load_op_enum; }\n// END_LOAD_OP_T\n    //\n    // n_arg\n    addr_t n_arg(\n        addr_t                arg_index    ,\n        const Vector<addr_t>& arg_vec      ) const override\n    {  return 2; }\n    //\n    // n_res\n    addr_t n_res(\n        addr_t                arg_index    ,\n        const Vector<addr_t>& arg_vec      ) const override\n    {  return 1; }\n    //\n    // eval\n    void eval(\n        const tape_t<Value>*      tape           ,\n        bool                      trace          ,\n        addr_t                    arg_index      ,\n        addr_t                    res_index      ,\n        Vector<Value>&            val_vec        ,\n        Vector< Vector<addr_t> >& ind_vec_vec    ,\n        size_t&                   compare_false  ) const override\n    {  //\n        // arg_vec, vec_vec\n        const Vector<addr_t>& arg_vec( tape->arg_vec() );\n        //\n        // this_vector\n        // BEGIN_LOAD_ARG_BEFORE\n        addr_t          which_vector = arg_vec[arg_index + 0];\n        Vector<addr_t>& this_vector  = ind_vec_vec[which_vector];\n        // END_LOAD_ARG_BEFORE\n        //\n        // vector_index\n        addr_t vector_index = arg_vec[arg_index + 1];\n        //\n        // index\n        Value index          = val_vec[vector_index];\n        //\n        // val_vec\n        addr_t flag = this_vector[ this_vector.size() - 1 ];\n        if( flag == tape->n_ind() || CppAD::isnan(index) )\n        {  val_vec[res_index] = val_vec[ tape->n_ind() ];\n            CPPAD_ASSERT_UNKNOWN( CppAD::isnan( val_vec[res_index] ) );\n        }\n        else\n        {  //\n            // dynamic_index\n            addr_t dynamic_index = addr_t( Integer(index) );\n            CPPAD_ASSERT_KNOWN( size_t(dynamic_index) + 1 < this_vector.size(),\n                \"dynamic vector index is greater than or equal vector size\"\n            );\n            //\n            // val_vec\n            val_vec[res_index] = val_vec[ this_vector[dynamic_index] ];\n        }\n        //\n        // trace\n        if( ! trace )\n            return;\n        //\n        // print_load_op\n        Value res_value = val_vec[res_index];\n        print_load_op(which_vector, vector_index, res_index, res_value);\n    }\n};\n// ---------------------------------------------------------------------------\n/*\n{xrst_begin val_store_op dev}\n\nDynamic Vector Store Operator\n#############################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_STORE_OP_T\n    // END_STORE_OP_T\n}\n\nContext\n*******\nIt is derived from :ref:`val_base_op-name` .\nIt overrides all its base class virtual member functions\nand is a concrete class (it has no pure virtual functions).\n\nget_instance\n************\nThis static member function returns a pointer to a store_op_t object.\n\nop_enum\n*******\nThis override of :ref:`val_base_op@op_enum` returns ``store_op_enum`` .\n\nn_before\n********\nThis override of :ref:`val_base_op@n_before` returns 1.\n{xrst_literal\n    // BEGIN_STORE_ARG_BEFORE\n    // END_STORE_ARG_BEFORE\n}\n\nn_after\n*******\nThis override of :ref:`val_base_op@n_after` returns 0.\n\nn_arg\n*****\nThis override of :ref:`val_base_op@n_arg` returns 3.\n\nn_res\n*****\nThis override of :ref:`val_base_op@n_res` return 0.\n\neval\n****\nThis override of :ref:`val_base_op@eval` implement a\ndynamic vector store operation.\n\nwhich_vector\n============\nWe use *which_vector* to denote the index corresponding to this\ndynamic vector; i.e.  arg_vec[arg_index + 0].\n\nvector_index\n============\nWe use *vector_index* to denote the index, in the value vector,\nof the index in the dynamic vector, of the element for this store; i.e.\narg_vec[arg_index + 1].\n\nvalue_index\n===========\nWe use *value_index* to denote the index,\nin the val_vec vector, of the element for this store; i.e.\narg_vec[arg_index + 2].\n\ntrace\n=====\nIf trace is true, :ref:`val_print_store_op-name`\nis called to print this operator.\n\n{xrst_end val_store_op}\n*/\n// BEGIN_STORE_OP_T\ntemplate <class Value>\nclass store_op_t : public base_op_t<Value> {\npublic:\n    // n_before\n    addr_t n_before(void) const override\n    {   return 1; }\n    //\n    // n_after\n    addr_t n_after(void) const override\n    {   return 0; }\n    //\n    // get_instance\n    static store_op_t* get_instance(void)\n    {   CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL;\n        static store_op_t instance;\n        return &instance;\n    }\n    // op_enum\n    op_enum_t op_enum(void) const override\n    {   return store_op_enum; }\n// END_STORE_OP_T\n    //\n    // n_arg\n    addr_t n_arg(\n        addr_t                arg_index    ,\n        const Vector<addr_t>& arg_vec      ) const override\n    {   return 3; }\n    //\n    // n_res\n    addr_t n_res(\n        addr_t                arg_index    ,\n        const Vector<addr_t>& arg_vec      ) const override\n    {   return 0; }\n    //\n    // eval\n    void eval(\n        const tape_t<Value>*      tape           ,\n        bool                      trace          ,\n        addr_t                    arg_index      ,\n        addr_t                    res_index      ,\n        Vector<Value>&            val_vec        ,\n        Vector< Vector<addr_t> >& ind_vec_vec    ,\n        size_t&                   compare_false  ) const override\n    {   //\n        // arg_vec, vec_vec\n        const Vector<addr_t>& arg_vec( tape->arg_vec() );\n        //\n        // this_vector\n        // BEGIN_STORE_ARG_BEFORE\n        addr_t          which_vector = arg_vec[arg_index + 0];\n        Vector<addr_t>& this_vector  = ind_vec_vec[which_vector];\n        // END_STORE_ARG_BEFORE\n        //\n        // vector_index, value_index\n        addr_t vector_index = arg_vec[arg_index + 1];\n        addr_t value_index  = arg_vec[arg_index + 2];\n        //\n        // index\n        Value index          = val_vec[vector_index];\n        if( CppAD::isnan(index) )\n        {   // set flag for this vector\n            this_vector[ this_vector.size() - 1 ] = tape->n_ind();\n        }\n        else\n        {   // dynamic_index\n            addr_t dynamic_index = addr_t( Integer(index) );\n            CPPAD_ASSERT_KNOWN( size_t(dynamic_index) + 1 < this_vector.size(),\n                \"dynamic vector index is greater than or equal vector size\"\n            );\n            //\n            // val_vec_vec\n            this_vector[dynamic_index] = value_index;\n        }\n        //\n        // trace\n        if( ! trace )\n            return;\n        //\n        // print_store_op\n        print_store_op(which_vector, vector_index, value_index);\n    }\n};\n\n} } } // END_CPPAD_LOCAL_VAL_GRAPH_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/var_op/abs_op.hpp",
    "content": "# ifndef CPPAD_LOCAL_VAR_OP_ABS_OP_HPP\n# define CPPAD_LOCAL_VAR_OP_ABS_OP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n\nnamespace CppAD { namespace local { namespace var_op {\n\n// See dev documentation: forward_unary_op\ntemplate <class Base>\ninline void abs_forward_any(\n    size_t        order_low   ,\n    size_t        order_up    ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // p, q\n    size_t p = order_low;\n    size_t q = order_up;\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(AbsOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(AbsOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n    CPPAD_ASSERT_UNKNOWN( p <= q );\n\n    // Taylor coefficients corresponding to argument and result\n    Base* x = taylor + i_x * cap_order;\n    Base* z = taylor + i_z * cap_order;\n\n    for(size_t j = p; j <= q; j++)\n        z[j] = sign(x[0]) * x[j];\n}\n\n// See dev documentation: forward_unary_op\ntemplate <class Base>\ninline void abs_forward_dir(\n    size_t        order_up    ,\n    size_t        n_dir       ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // q, r\n    size_t q = order_up;\n    size_t r = n_dir;\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(AbsOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(AbsOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( 0 < q );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n\n    // Taylor coefficients corresponding to argument and result\n    size_t num_taylor_per_var = (cap_order-1) * r + 1;\n    Base* x = taylor + i_x * num_taylor_per_var;\n    Base* z = taylor + i_z * num_taylor_per_var;\n\n    size_t m = (q-1) * r + 1;\n    for(size_t ell = 0; ell < r; ell++)\n        z[m + ell] = sign(x[0]) * x[m + ell];\n}\n\n// See dev documentation: forward_unary_op\ntemplate <class Base>\ninline void abs_forward_0(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{   //\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(AbsOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(AbsOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( 0 < cap_order );\n\n    // Taylor coefficients corresponding to argument and result\n    Base x0 = *(taylor + i_x * cap_order);\n    Base* z = taylor + i_z * cap_order;\n\n    z[0] = fabs(x0);\n}\n\n// See dev documentation: reverse_unary_op\ntemplate <class Base>\ninline void abs_reverse(\n    size_t        i_z          ,\n    const addr_t* arg          ,\n    size_t        cap_order    ,\n    const Base*   taylor       ,\n    size_t        n_order      ,\n    Base*         partial      )\n{   //\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    //\n    size_t j;\n\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(AbsOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(AbsOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( n_order <= cap_order );\n\n    // Taylor coefficients and partials corresponding to argument\n    const Base* x  = taylor  + i_x * cap_order;\n    Base* px       = partial + i_x * n_order;\n\n    // Taylor coefficients and partials corresponding to result\n    Base* pz       = partial +    i_z * n_order;\n\n    // do not need azmul because sign is either +1, -1, or zero\n    for(j = 0; j < n_order; j++)\n        px[j] += sign(x[0]) * pz[j];\n}\n\n} } } // END namespace\n# endif\n"
  },
  {
    "path": "include/cppad/local/var_op/acos_op.hpp",
    "content": "# ifndef CPPAD_LOCAL_VAR_OP_ACOS_OP_HPP\n# define CPPAD_LOCAL_VAR_OP_ACOS_OP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n\nnamespace CppAD { namespace local { namespace var_op {\n\n\n// See dev documentation: forward_unary_op\ntemplate <class Base>\ninline void acos_forward_any(\n    size_t        order_low   ,\n    size_t        order_up    ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // p, q\n    size_t p = order_low;\n    size_t q = order_up;\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(AcosOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(AcosOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n    CPPAD_ASSERT_UNKNOWN( p <= q );\n\n    // Taylor coefficients corresponding to argument and result\n    Base* x = taylor + i_x * cap_order;\n    Base* z = taylor + i_z * cap_order;\n    Base* b = z      -       cap_order;  // called y in documentation\n\n    size_t k;\n    Base uj;\n    if( p == 0 )\n    {   z[0] = acos( x[0] );\n        uj   = Base(1.0) - x[0] * x[0];\n        b[0] = sqrt( uj );\n        p++;\n    }\n    for(size_t j = p; j <= q; j++)\n    {   uj = Base(0.0);\n        for(k = 0; k <= j; k++)\n            uj -= x[k] * x[j-k];\n        b[j] = Base(0.0);\n        z[j] = Base(0.0);\n        for(k = 1; k < j; k++)\n        {   b[j] -= Base(double(k)) * b[k] * b[j-k];\n            z[j] -= Base(double(k)) * z[k] * b[j-k];\n        }\n        b[j] /= Base(double(j));\n        z[j] /= Base(double(j));\n        //\n        b[j] += uj / Base(2.0);\n        z[j] -= x[j];\n        //\n        b[j] /= b[0];\n        z[j] /= b[0];\n    }\n}\n// See dev documentation: forward_unary_op\ntemplate <class Base>\ninline void acos_forward_dir(\n    size_t        order_up    ,\n    size_t        n_dir       ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // q, r\n    size_t q = order_up;\n    size_t r = n_dir;\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(AcosOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(AcosOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( 0 < q );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n\n    // Taylor coefficients corresponding to argument and result\n    size_t num_taylor_per_var = (cap_order-1) * r + 1;\n    Base* x = taylor + i_x * num_taylor_per_var;\n    Base* z = taylor + i_z * num_taylor_per_var;\n    Base* b = z - num_taylor_per_var;  // called y in documentation\n\n    size_t k, ell;\n    size_t m = (q-1) * r + 1;\n    for(ell = 0; ell < r; ell ++)\n    {   Base uq = - 2.0 * x[m + ell] * x[0];\n        for(k = 1; k < q; k++)\n            uq -= x[(k-1)*r+1+ell] * x[(q-k-1)*r+1+ell];\n        b[m+ell] = Base(0.0);\n        z[m+ell] = Base(0.0);\n        for(k = 1; k < q; k++)\n        {   b[m+ell] += Base(double(k)) * b[(k-1)*r+1+ell] * b[(q-k-1)*r+1+ell];\n            z[m+ell] += Base(double(k)) * z[(k-1)*r+1+ell] * b[(q-k-1)*r+1+ell];\n        }\n        b[m+ell] =  ( uq / Base(2.0) - b[m+ell] / Base(double(q)) ) / b[0];\n        z[m+ell] = -( x[m+ell]     + z[m+ell] / Base(double(q)) ) / b[0];\n    }\n}\n\n// See dev documentation: forward_unary_op\ntemplate <class Base>\ninline void acos_forward_0(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{   //\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(AcosOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(AcosOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( 0 < cap_order );\n\n    // Taylor coefficients corresponding to argument and result\n    Base* x = taylor + i_x * cap_order;\n    Base* z = taylor + i_z * cap_order;\n    Base* b = z      -       cap_order; // called y in documentation\n\n    z[0] = acos( x[0] );\n    b[0] = sqrt( Base(1.0) - x[0] * x[0] );\n}\n\n// See dev documentation: reverse_unary_op\ntemplate <class Base>\ninline void acos_reverse(\n    size_t        i_z          ,\n    const addr_t* arg          ,\n    size_t        cap_order    ,\n    const Base*   taylor       ,\n    size_t        n_order      ,\n    Base*         partial      )\n{   // d  //\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    size_t d = n_order - 1;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(AcosOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(AcosOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( n_order <= cap_order );\n\n    // Taylor coefficients and partials corresponding to argument\n    const Base* x  = taylor  + i_x * cap_order;\n    Base* px       = partial + i_x * n_order;\n\n    // Taylor coefficients and partials corresponding to first result\n    const Base* z  = taylor  + i_z * cap_order;\n    Base* pz       = partial + i_z * n_order;\n\n    // Taylor coefficients and partials corresponding to auxiliary result\n    const Base* b  = z  - cap_order; // called y in documentation\n    Base* pb       = pz - n_order;\n\n    Base inv_b0 = Base(1.0) / b[0];\n\n    // number of indices to access\n    size_t j = d;\n    size_t k;\n    while(j)\n    {\n        // scale partials w.r.t b[j] by 1 / b[0]\n        pb[j]  = azmul(pb[j], inv_b0);\n\n        // scale partials w.r.t z[j] by 1 / b[0]\n        pz[j]  = azmul(pz[j], inv_b0);\n\n        // update partials w.r.t b^0\n        pb[0] -= azmul(pz[j], z[j]) + azmul(pb[j], b[j]);\n\n        // update partial w.r.t. x^0\n        px[0] -= azmul(pb[j], x[j]);\n\n        // update partial w.r.t. x^j\n        px[j] -= pz[j] + azmul(pb[j], x[0]);\n\n        // further scale partial w.r.t. z[j] by 1 / j\n        pz[j] /= Base(double(j));\n\n        for(k = 1; k < j; k++)\n        {   // update partials w.r.t b^(j-k)\n            pb[j-k] -= Base(double(k)) * azmul(pz[j], z[k]) + azmul(pb[j], b[k]);\n\n            // update partials w.r.t. x^k\n            px[k]   -= azmul(pb[j], x[j-k]);\n\n            // update partials w.r.t. z^k\n            pz[k]   -= Base(double(k)) * azmul(pz[j], b[j-k]);\n        }\n        --j;\n    }\n\n    // j == 0 case\n    px[0] -= azmul( pz[0] + azmul(pb[0], x[0]), inv_b0);\n}\n\n} } } // END namespace\n# endif\n"
  },
  {
    "path": "include/cppad/local/var_op/acosh_op.hpp",
    "content": "# ifndef CPPAD_LOCAL_VAR_OP_ACOSH_OP_HPP\n# define CPPAD_LOCAL_VAR_OP_ACOSH_OP_HPP\n\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n\nnamespace CppAD { namespace local { namespace var_op {\n\n\n// See dev documentation: forward_unary_op\ntemplate <class Base>\ninline void acosh_forward_any(\n    size_t        order_low   ,\n    size_t        order_up    ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // p, q\n    size_t p = order_low;\n    size_t q = order_up;\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(AcoshOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(AcoshOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n    CPPAD_ASSERT_UNKNOWN( p <= q );\n\n    // Taylor coefficients corresponding to argument and result\n    Base* x = taylor + i_x * cap_order;\n    Base* z = taylor + i_z * cap_order;\n    Base* b = z      -       cap_order;  // called y in documentation\n\n    size_t k;\n    Base uj;\n    if( p == 0 )\n    {   z[0] = acosh( x[0] );\n        uj   = x[0] * x[0] - Base(1.0);\n        b[0] = sqrt( uj );\n        p++;\n    }\n    for(size_t j = p; j <= q; j++)\n    {   uj = Base(0.0);\n        for(k = 0; k <= j; k++)\n            uj += x[k] * x[j-k];\n        b[j] = Base(0.0);\n        z[j] = Base(0.0);\n        for(k = 1; k < j; k++)\n        {   b[j] -= Base(double(k)) * b[k] * b[j-k];\n            z[j] -= Base(double(k)) * z[k] * b[j-k];\n        }\n        b[j] /= Base(double(j));\n        z[j] /= Base(double(j));\n        //\n        b[j] += uj / Base(2.0);\n        z[j] += x[j];\n        //\n        b[j] /= b[0];\n        z[j] /= b[0];\n    }\n}\n// See dev documentation: forward_unary_op\ntemplate <class Base>\ninline void acosh_forward_dir(\n    size_t        order_up    ,\n    size_t        n_dir       ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // q, r\n    size_t q = order_up;\n    size_t r = n_dir;\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(AcoshOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(AcoshOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( 0 < q );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n\n    // Taylor coefficients corresponding to argument and result\n    size_t num_taylor_per_var = (cap_order-1) * r + 1;\n    Base* x = taylor + i_x * num_taylor_per_var;\n    Base* z = taylor + i_z * num_taylor_per_var;\n    Base* b = z - num_taylor_per_var;  // called y in documentation\n\n    size_t k, ell;\n    size_t m = (q-1) * r + 1;\n    for(ell = 0; ell < r; ell ++)\n    {   Base uq = 2.0 * x[m + ell] * x[0];\n        for(k = 1; k < q; k++)\n            uq += x[(k-1)*r+1+ell] * x[(q-k-1)*r+1+ell];\n        b[m+ell] = Base(0.0);\n        z[m+ell] = Base(0.0);\n        for(k = 1; k < q; k++)\n        {   b[m+ell] += Base(double(k)) * b[(k-1)*r+1+ell] * b[(q-k-1)*r+1+ell];\n            z[m+ell] += Base(double(k)) * z[(k-1)*r+1+ell] * b[(q-k-1)*r+1+ell];\n        }\n        b[m+ell] =  ( uq / Base(2.0) - b[m+ell] / Base(double(q)) ) / b[0];\n        z[m+ell] = ( x[m+ell]     - z[m+ell] / Base(double(q)) ) / b[0];\n    }\n}\n\n// See dev documentation: forward_unary_op\ntemplate <class Base>\ninline void acosh_forward_0(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{   //\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(AcoshOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(AcoshOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( 0 < cap_order );\n\n    // Taylor coefficients corresponding to argument and result\n    Base* x = taylor + i_x * cap_order;\n    Base* z = taylor + i_z * cap_order;\n    Base* b = z      -       cap_order; // called y in documentation\n\n    z[0] = acosh( x[0] );\n    b[0] = sqrt( x[0] * x[0] - Base(1.0) );\n}\n\n// See dev documentation: reverse_unary_op\ntemplate <class Base>\ninline void acosh_reverse(\n    size_t        i_z          ,\n    const addr_t* arg          ,\n    size_t        cap_order    ,\n    const Base*   taylor       ,\n    size_t        n_order      ,\n    Base*         partial      )\n{   // d  //\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    size_t d = n_order - 1;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(AcoshOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(AcoshOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( n_order <= cap_order );\n\n    // Taylor coefficients and partials corresponding to argument\n    const Base* x  = taylor  + i_x * cap_order;\n    Base* px       = partial + i_x * n_order;\n\n    // Taylor coefficients and partials corresponding to first result\n    const Base* z  = taylor  + i_z * cap_order;\n    Base* pz       = partial + i_z * n_order;\n\n    // Taylor coefficients and partials corresponding to auxiliary result\n    const Base* b  = z  - cap_order; // called y in documentation\n    Base* pb       = pz - n_order;\n\n    Base inv_b0 = Base(1.0) / b[0];\n\n    // number of indices to access\n    size_t j = d;\n    size_t k;\n    while(j)\n    {\n        // scale partials w.r.t b[j] by 1 / b[0]\n        pb[j]  = azmul(pb[j], inv_b0);\n\n        // scale partials w.r.t z[j] by 1 / b[0]\n        pz[j]  = azmul(pz[j], inv_b0);\n\n        // update partials w.r.t b^0\n        pb[0] -= azmul(pz[j], z[j]) + azmul(pb[j], b[j]);\n\n        // update partial w.r.t. x^0\n        px[0] += azmul(pb[j], x[j]);\n\n        // update partial w.r.t. x^j\n        px[j] += pz[j] + azmul(pb[j], x[0]);\n\n        // further scale partial w.r.t. z[j] by 1 / j\n        pz[j] /= Base(double(j));\n\n        for(k = 1; k < j; k++)\n        {   // update partials w.r.t b^(j-k)\n            pb[j-k] -= Base(double(k)) * azmul(pz[j], z[k]) + azmul(pb[j], b[k]);\n\n            // update partials w.r.t. x^k\n            px[k]   += azmul(pb[j], x[j-k]);\n\n            // update partials w.r.t. z^k\n            pz[k]   -= Base(double(k)) * azmul(pz[j], b[j-k]);\n        }\n        --j;\n    }\n\n    // j == 0 case\n    px[0] += azmul(pz[0] + azmul(pb[0], x[0]),  inv_b0);\n}\n\n} } } // END namespace\n# endif\n"
  },
  {
    "path": "include/cppad/local/var_op/add_op.hpp",
    "content": "# ifndef CPPAD_LOCAL_VAR_OP_ADD_OP_HPP\n# define CPPAD_LOCAL_VAR_OP_ADD_OP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\nnamespace CppAD { namespace local { namespace var_op {\n\n// --------------------------- Addvv -----------------------------------------\n\n// See dev documentation: forward_unary_op\n// See dev documentation: forward_binary_op\ntemplate <class Base>\ninline void addvv_forward_any(\n    size_t        order_low   ,\n    size_t        order_up    ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // p, q\n    size_t p = order_low;\n    size_t q = order_up;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(AddvvOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(AddvvOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n    CPPAD_ASSERT_UNKNOWN( p <= q  );\n\n    // Taylor coefficients corresponding to arguments and result\n    Base* x = taylor + size_t(arg[0]) * cap_order;\n    Base* y = taylor + size_t(arg[1]) * cap_order;\n    Base* z = taylor + i_z    * cap_order;\n\n    for(size_t j = p; j <= q; j++)\n        z[j] = x[j] + y[j];\n}\n\n// See dev documentation: forward_unary_op\n// See dev documentation: forward_binary_op\ntemplate <class Base>\ninline void addvv_forward_dir(\n    size_t        order_up    ,\n    size_t        n_dir       ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // q, r\n    size_t q = order_up;\n    size_t r = n_dir;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(AddvvOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(AddvvOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n    CPPAD_ASSERT_UNKNOWN( 0 < q  );\n\n    // Taylor coefficients corresponding to arguments and result\n    size_t num_taylor_per_var = (cap_order-1) * r + 1;\n    Base* x = taylor + size_t(arg[0]) * num_taylor_per_var;\n    Base* y = taylor + size_t(arg[1]) * num_taylor_per_var;\n    Base* z = taylor +    i_z * num_taylor_per_var;\n\n    size_t m = (q-1)*r + 1 ;\n    for(size_t ell = 0; ell < r; ell++)\n        z[m+ell] = x[m+ell] + y[m+ell];\n}\n\n\n// See dev documentation: forward_unary_op\n// See dev documentation: forward_binary_op\ntemplate <class Base>\ninline void addvv_forward_0(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{   //\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(AddvvOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(AddvvOp) == 1 );\n\n    // Taylor coefficients corresponding to arguments and result\n    Base* x = taylor + size_t(arg[0]) * cap_order;\n    Base* y = taylor + size_t(arg[1]) * cap_order;\n    Base* z = taylor + i_z    * cap_order;\n\n    z[0] = x[0] + y[0];\n}\n\n\n// See dev documentation: reverse_unary_op\n// See dev documentation: reverse_binary_op\ntemplate <class Base>\ninline void addvv_reverse(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    const Base*   taylor      ,\n    size_t        n_order     ,\n    Base*         partial     )\n{   // d\n    //\n    size_t d = n_order - 1;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(AddvvOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(AddvvOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( n_order <= cap_order );\n\n    // Partial derivatives corresponding to arguments and result\n    Base* px = partial + size_t(arg[0]) * n_order;\n    Base* py = partial + size_t(arg[1]) * n_order;\n    Base* pz = partial + i_z    * n_order;\n\n    // number of indices to access\n    size_t i = d + 1;\n    while(i)\n    {   --i;\n        px[i] += pz[i];\n        py[i] += pz[i];\n    }\n}\n\n// --------------------------- Addpv -----------------------------------------\n// See dev documentation: forward_unary_op\n// See dev documentation: forward_binary_op\ntemplate <class Base>\ninline void addpv_forward_any(\n    size_t        order_low   ,\n    size_t        order_up    ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // p, q\n    size_t p = order_low;\n    size_t q = order_up;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(AddpvOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(AddpvOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n    CPPAD_ASSERT_UNKNOWN( p <= q );\n\n    // Taylor coefficients corresponding to arguments and result\n    Base* y = taylor + size_t(arg[1]) * cap_order;\n    Base* z = taylor + i_z    * cap_order;\n\n    if( p == 0 )\n    {   // Paraemter value\n        Base x = parameter[ arg[0] ];\n        z[0] = x + y[0];\n        p++;\n    }\n    for(size_t j = p; j <= q; j++)\n        z[j] = y[j];\n}\n// See dev documentation: forward_unary_op\n// See dev documentation: forward_binary_op\ntemplate <class Base>\ninline void addpv_forward_dir(\n    size_t        order_up    ,\n    size_t        n_dir       ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // q, r\n    size_t q = order_up;\n    size_t r = n_dir;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(AddpvOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(AddpvOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( 0 < q );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n\n    // Taylor coefficients corresponding to arguments and result\n    size_t num_taylor_per_var = (cap_order-1) * r + 1;\n    size_t m                  = (q-1) * r + 1;\n    Base* y = taylor + size_t(arg[1]) * num_taylor_per_var + m;\n    Base* z = taylor + i_z    * num_taylor_per_var + m;\n\n    for(size_t ell = 0; ell < r; ell++)\n        z[ell] = y[ell];\n}\n\n// See dev documentation: forward_unary_op\n// See dev documentation: forward_binary_op\ntemplate <class Base>\ninline void addpv_forward_0(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{   //\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(AddpvOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(AddpvOp) == 1 );\n\n    // Paraemter value\n    Base x = parameter[ arg[0] ];\n\n    // Taylor coefficients corresponding to arguments and result\n    Base* y = taylor + size_t(arg[1]) * cap_order;\n    Base* z = taylor + i_z    * cap_order;\n\n    z[0] = x + y[0];\n}\n\n\n// See dev documentation: reverse_unary_op\n// See dev documentation: reverse_binary_op\ntemplate <class Base>\ninline void addpv_reverse(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    const Base*   taylor      ,\n    size_t        n_order     ,\n    Base*         partial     )\n{   // d\n    //\n    size_t d = n_order - 1;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(AddvvOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(AddvvOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( n_order <= cap_order );\n\n    // Partial derivatives corresponding to arguments and result\n    Base* py = partial + size_t(arg[1]) * n_order;\n    Base* pz = partial + i_z    * n_order;\n\n    // number of indices to access\n    size_t i = d + 1;\n    while(i)\n    {   --i;\n        py[i] += pz[i];\n    }\n}\n\n\n} } } // END namespace\n# endif\n"
  },
  {
    "path": "include/cppad/local/var_op/asin_op.hpp",
    "content": "# ifndef CPPAD_LOCAL_VAR_OP_ASIN_OP_HPP\n# define CPPAD_LOCAL_VAR_OP_ASIN_OP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n\nnamespace CppAD { namespace local { namespace var_op {\n\n\n// See dev documentation: forward_unary_op\ntemplate <class Base>\ninline void asin_forward_any(\n    size_t        order_low   ,\n    size_t        order_up    ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // p, q\n    size_t p = order_low;\n    size_t q = order_up;\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(AsinOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(AsinOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n    CPPAD_ASSERT_UNKNOWN( p <= q );\n\n    // Taylor coefficients corresponding to argument and result\n    Base* x = taylor + i_x * cap_order;\n    Base* z = taylor + i_z * cap_order;\n    Base* b = z      -       cap_order;  // called y in documentation\n\n    size_t k;\n    Base uj;\n    if( p == 0 )\n    {   z[0] = asin( x[0] );\n        uj   = Base(1.0) - x[0] * x[0];\n        b[0] = sqrt( uj );\n        p++;\n    }\n    for(size_t j = p; j <= q; j++)\n    {   uj = Base(0.0);\n        for(k = 0; k <= j; k++)\n            uj -= x[k] * x[j-k];\n        b[j] = Base(0.0);\n        z[j] = Base(0.0);\n        for(k = 1; k < j; k++)\n        {   b[j] -= Base(double(k)) * b[k] * b[j-k];\n            z[j] -= Base(double(k)) * z[k] * b[j-k];\n        }\n        b[j] /= Base(double(j));\n        z[j] /= Base(double(j));\n        //\n        b[j] += uj / Base(2.0);\n        z[j] += x[j];\n        //\n        b[j] /= b[0];\n        z[j] /= b[0];\n    }\n}\n// See dev documentation: forward_unary_op\ntemplate <class Base>\ninline void asin_forward_dir(\n    size_t        order_up    ,\n    size_t        n_dir       ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // q, r\n    size_t q = order_up;\n    size_t r = n_dir;\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(AcosOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(AcosOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( 0 < q );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n\n    // Taylor coefficients corresponding to argument and result\n    size_t num_taylor_per_var = (cap_order-1) * r + 1;\n    Base* x = taylor + i_x * num_taylor_per_var;\n    Base* z = taylor + i_z * num_taylor_per_var;\n    Base* b = z - num_taylor_per_var;  // called y in documentation\n\n    size_t k, ell;\n    size_t m = (q-1) * r + 1;\n    for(ell = 0; ell < r; ell ++)\n    {   Base uq = - 2.0 * x[m + ell] * x[0];\n        for(k = 1; k < q; k++)\n            uq -= x[(k-1)*r+1+ell] * x[(q-k-1)*r+1+ell];\n        b[m+ell] = Base(0.0);\n        z[m+ell] = Base(0.0);\n        for(k = 1; k < q; k++)\n        {   b[m+ell] += Base(double(k)) * b[(k-1)*r+1+ell] * b[(q-k-1)*r+1+ell];\n            z[m+ell] += Base(double(k)) * z[(k-1)*r+1+ell] * b[(q-k-1)*r+1+ell];\n        }\n        b[m+ell] = ( uq / Base(2.0) - b[m+ell] / Base(double(q)) ) / b[0];\n        z[m+ell] = ( x[m+ell]     - z[m+ell] / Base(double(q)) ) / b[0];\n    }\n}\n\n// See dev documentation: forward_unary_op\ntemplate <class Base>\ninline void asin_forward_0(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{   //\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(AsinOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(AsinOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( 0 < cap_order );\n\n    // Taylor coefficients corresponding to argument and result\n    Base* x = taylor + i_x * cap_order;\n    Base* z = taylor + i_z * cap_order;\n    Base* b = z      -       cap_order; // called y in documentation\n\n    z[0] = asin( x[0] );\n    b[0] = sqrt( Base(1.0) - x[0] * x[0] );\n}\n\n// See dev documentation: reverse_unary_op\ntemplate <class Base>\ninline void asin_reverse(\n    size_t        i_z          ,\n    const addr_t* arg          ,\n    size_t        cap_order    ,\n    const Base*   taylor       ,\n    size_t        n_order      ,\n    Base*         partial      )\n{   // d  //\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    size_t d = n_order - 1;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(AsinOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(AsinOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( n_order <= cap_order );\n\n    // Taylor coefficients and partials corresponding to argument\n    const Base* x  = taylor  + i_x * cap_order;\n    Base* px       = partial + i_x * n_order;\n\n    // Taylor coefficients and partials corresponding to first result\n    const Base* z  = taylor  + i_z * cap_order;\n    Base* pz       = partial + i_z * n_order;\n\n    // Taylor coefficients and partials corresponding to auxiliary result\n    const Base* b  = z  - cap_order; // called y in documentation\n    Base* pb       = pz - n_order;\n\n    Base inv_b0 = Base(1.0) / b[0];\n\n    // number of indices to access\n    size_t j = d;\n    size_t k;\n    while(j)\n    {\n        // scale partials w.r.t b[j] by 1 / b[0]\n        pb[j]  = azmul(pb[j], inv_b0);\n\n        // scale partials w.r.t z[j] by 1 / b[0]\n        pz[j]  = azmul(pz[j], inv_b0);\n\n        // update partials w.r.t b^0\n        pb[0] -= azmul(pz[j], z[j]) + azmul(pb[j], b[j]);\n\n        // update partial w.r.t. x^0\n        px[0] -= azmul(pb[j], x[j]);\n\n        // update partial w.r.t. x^j\n        px[j] += pz[j] - azmul(pb[j], x[0]);\n\n        // further scale partial w.r.t. z[j] by 1 / j\n        pz[j] /= Base(double(j));\n\n        for(k = 1; k < j; k++)\n        {   // update partials w.r.t b^(j-k)\n            pb[j-k] -= Base(double(k)) * azmul(pz[j], z[k]) + azmul(pb[j], b[k]);\n\n            // update partials w.r.t. x^k\n            px[k]   -= azmul(pb[j], x[j-k]);\n\n            // update partials w.r.t. z^k\n            pz[k]   -= Base(double(k)) * azmul(pz[j], b[j-k]);\n        }\n        --j;\n    }\n\n    // j == 0 case\n    px[0] += azmul(pz[0] - azmul(pb[0], x[0]), inv_b0);\n}\n\n} } } // END namespace\n# endif\n"
  },
  {
    "path": "include/cppad/local/var_op/asinh_op.hpp",
    "content": "# ifndef CPPAD_LOCAL_VAR_OP_ASINH_OP_HPP\n# define CPPAD_LOCAL_VAR_OP_ASINH_OP_HPP\n\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n\nnamespace CppAD { namespace local { namespace var_op {\n\n\n// See dev documentation: forward_unary_op\ntemplate <class Base>\ninline void asinh_forward_any(\n    size_t        order_low   ,\n    size_t        order_up    ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // p, q\n    size_t p = order_low;\n    size_t q = order_up;\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(AsinhOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(AsinhOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n    CPPAD_ASSERT_UNKNOWN( p <= q );\n\n    // Taylor coefficients corresponding to argument and result\n    Base* x = taylor + i_x * cap_order;\n    Base* z = taylor + i_z * cap_order;\n    Base* b = z      -       cap_order;  // called y in documentation\n\n    size_t k;\n    Base uj;\n    if( p == 0 )\n    {   z[0] = asinh( x[0] );\n        uj   = Base(1.0) + x[0] * x[0];\n        b[0] = sqrt( uj );\n        p++;\n    }\n    for(size_t j = p; j <= q; j++)\n    {   uj = Base(0.0);\n        for(k = 0; k <= j; k++)\n            uj += x[k] * x[j-k];\n        b[j] = Base(0.0);\n        z[j] = Base(0.0);\n        for(k = 1; k < j; k++)\n        {   b[j] -= Base(double(k)) * b[k] * b[j-k];\n            z[j] -= Base(double(k)) * z[k] * b[j-k];\n        }\n        b[j] /= Base(double(j));\n        z[j] /= Base(double(j));\n        //\n        b[j] += uj / Base(2.0);\n        z[j] += x[j];\n        //\n        b[j] /= b[0];\n        z[j] /= b[0];\n    }\n}\n// See dev documentation: forward_unary_op\ntemplate <class Base>\ninline void asinh_forward_dir(\n    size_t        order_up    ,\n    size_t        n_dir       ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // q, r\n    size_t q = order_up;\n    size_t r = n_dir;\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(AcosOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(AcosOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( 0 < q );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n\n    // Taylor coefficients corresponding to argument and result\n    size_t num_taylor_per_var = (cap_order-1) * r + 1;\n    Base* x = taylor + i_x * num_taylor_per_var;\n    Base* z = taylor + i_z * num_taylor_per_var;\n    Base* b = z - num_taylor_per_var;  // called y in documentation\n\n    size_t k, ell;\n    size_t m = (q-1) * r + 1;\n    for(ell = 0; ell < r; ell ++)\n    {   Base uq = 2.0 * x[m + ell] * x[0];\n        for(k = 1; k < q; k++)\n            uq += x[(k-1)*r+1+ell] * x[(q-k-1)*r+1+ell];\n        b[m+ell] = Base(0.0);\n        z[m+ell] = Base(0.0);\n        for(k = 1; k < q; k++)\n        {   b[m+ell] += Base(double(k)) * b[(k-1)*r+1+ell] * b[(q-k-1)*r+1+ell];\n            z[m+ell] += Base(double(k)) * z[(k-1)*r+1+ell] * b[(q-k-1)*r+1+ell];\n        }\n        b[m+ell] = ( uq / Base(2.0) - b[m+ell] / Base(double(q)) ) / b[0];\n        z[m+ell] = ( x[m+ell]     - z[m+ell] / Base(double(q)) ) / b[0];\n    }\n}\n\n// See dev documentation: forward_unary_op\ntemplate <class Base>\ninline void asinh_forward_0(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{   //\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(AsinhOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(AsinhOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( 0 < cap_order );\n\n    // Taylor coefficients corresponding to argument and result\n    Base* x = taylor + i_x * cap_order;\n    Base* z = taylor + i_z * cap_order;\n    Base* b = z      -       cap_order; // called y in documentation\n\n    z[0] = asinh( x[0] );\n    b[0] = sqrt( Base(1.0) + x[0] * x[0] );\n}\n\n// See dev documentation: reverse_unary_op\ntemplate <class Base>\ninline void asinh_reverse(\n    size_t        i_z          ,\n    const addr_t* arg          ,\n    size_t        cap_order    ,\n    const Base*   taylor       ,\n    size_t        n_order      ,\n    Base*         partial      )\n{   // d  //\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    size_t d = n_order - 1;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(AsinhOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(AsinhOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( n_order <= cap_order );\n\n    // Taylor coefficients and partials corresponding to argument\n    const Base* x  = taylor  + i_x * cap_order;\n    Base* px       = partial + i_x * n_order;\n\n    // Taylor coefficients and partials corresponding to first result\n    const Base* z  = taylor  + i_z * cap_order;\n    Base* pz       = partial + i_z * n_order;\n\n    // Taylor coefficients and partials corresponding to auxiliary result\n    const Base* b  = z  - cap_order; // called y in documentation\n    Base* pb       = pz - n_order;\n\n    Base inv_b0 = Base(1.0) / b[0];\n\n    // number of indices to access\n    size_t j = d;\n    size_t k;\n    while(j)\n    {\n        // scale partials w.r.t b[j] by 1 / b[0]\n        pb[j]  = azmul(pb[j], inv_b0);\n\n        // scale partials w.r.t z[j] by 1 / b[0]\n        pz[j]  = azmul(pz[j], inv_b0);\n\n        // update partials w.r.t b^0\n        pb[0] -= azmul(pz[j], z[j]) + azmul(pb[j], b[j]);\n\n        // update partial w.r.t. x^0\n        px[0] += azmul(pb[j], x[j]);\n\n        // update partial w.r.t. x^j\n        px[j] += pz[j] + azmul(pb[j], x[0]);\n\n        // further scale partial w.r.t. z[j] by 1 / j\n        pz[j] /= Base(double(j));\n\n        for(k = 1; k < j; k++)\n        {   // update partials w.r.t b^(j-k)\n            pb[j-k] -= Base(double(k)) * azmul(pz[j], z[k]) + azmul(pb[j], b[k]);\n\n            // update partials w.r.t. x^k\n            px[k]   += azmul(pb[j], x[j-k]);\n\n            // update partials w.r.t. z^k\n            pz[k]   -= Base(double(k)) * azmul(pz[j], b[j-k]);\n        }\n        --j;\n    }\n\n    // j == 0 case\n    px[0] += azmul(pz[0] + azmul(pb[0], x[0]), inv_b0);\n}\n\n} } } // END namespace\n# endif\n"
  },
  {
    "path": "include/cppad/local/var_op/atan_op.hpp",
    "content": "# ifndef CPPAD_LOCAL_VAR_OP_ATAN_OP_HPP\n# define CPPAD_LOCAL_VAR_OP_ATAN_OP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n\nnamespace CppAD { namespace local { namespace var_op {\n\n\n// See dev documentation: forward_unary_op\ntemplate <class Base>\ninline void atan_forward_any(\n    size_t        order_low   ,\n    size_t        order_up    ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // p, q\n    size_t p = order_low;\n    size_t q = order_up;\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(AtanOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(AtanOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n    CPPAD_ASSERT_UNKNOWN( p <= q );\n\n    // Taylor coefficients corresponding to argument and result\n    Base* x = taylor + i_x * cap_order;\n    Base* z = taylor + i_z * cap_order;\n    Base* b = z      -       cap_order;  // called y in documentation\n\n    size_t k;\n    if( p == 0 )\n    {   z[0] = atan( x[0] );\n        b[0] = Base(1.0) + x[0] * x[0];\n        p++;\n    }\n    for(size_t j = p; j <= q; j++)\n    {\n        b[j] = Base(2.0) * x[0] * x[j];\n        z[j] = Base(0.0);\n        for(k = 1; k < j; k++)\n        {   b[j] += x[k] * x[j-k];\n            z[j] -= Base(double(k)) * z[k] * b[j-k];\n        }\n        z[j] /= Base(double(j));\n        z[j] += x[j];\n        z[j] /= b[0];\n    }\n}\n\n// See dev documentation: forward_unary_op\ntemplate <class Base>\ninline void atan_forward_dir(\n    size_t        order_up    ,\n    size_t        n_dir       ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // q, r\n    size_t q = order_up;\n    size_t r = n_dir;\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(AtanOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(AtanOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( 0 < q );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n\n    // Taylor coefficients corresponding to argument and result\n    size_t num_taylor_per_var = (cap_order-1) * r + 1;\n    Base* x = taylor + i_x * num_taylor_per_var;\n    Base* z = taylor + i_z * num_taylor_per_var;\n    Base* b = z      -       num_taylor_per_var; // called y in documentation\n\n    size_t m = (q-1) * r + 1;\n    for(size_t ell = 0; ell < r; ell++)\n    {   b[m+ell] = Base(2.0) * x[m+ell] * x[0];\n        z[m+ell] = Base(double(q)) * x[m+ell];\n        for(size_t k = 1; k < q; k++)\n        {   b[m+ell] += x[(k-1)*r+1+ell] * x[(q-k-1)*r+1+ell];\n            z[m+ell] -= Base(double(k)) * z[(k-1)*r+1+ell] * b[(q-k-1)*r+1+ell];\n        }\n        z[m+ell] /= ( Base(double(q)) * b[0] );\n    }\n}\n\n// See dev documentation: forward_unary_op\ntemplate <class Base>\ninline void atan_forward_0(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{   //\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(AtanOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(AtanOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( 0 < cap_order );\n\n    // Taylor coefficients corresponding to argument and result\n    Base* x = taylor + i_x * cap_order;\n    Base* z = taylor + i_z * cap_order;\n    Base* b = z      -       cap_order; // called y in documentation\n\n    z[0] = atan( x[0] );\n    b[0] = Base(1.0) + x[0] * x[0];\n}\n\n// See dev documentation: reverse_unary_op\ntemplate <class Base>\ninline void atan_reverse(\n    size_t        i_z          ,\n    const addr_t* arg          ,\n    size_t        cap_order    ,\n    const Base*   taylor       ,\n    size_t        n_order      ,\n    Base*         partial      )\n{   // d  //\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    size_t d = n_order - 1;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(AtanOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(AtanOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( n_order <= cap_order );\n\n    // Taylor coefficients and partials corresponding to argument\n    const Base* x  = taylor  + i_x * cap_order;\n    Base* px       = partial + i_x * n_order;\n\n    // Taylor coefficients and partials corresponding to first result\n    const Base* z  = taylor  + i_z * cap_order;\n    Base* pz       = partial + i_z * n_order;\n\n    // Taylor coefficients and partials corresponding to auxiliary result\n    const Base* b  = z  - cap_order; // called y in documentation\n    Base* pb       = pz - n_order;\n\n    Base inv_b0 = Base(1.0) / b[0];\n\n    // number of indices to access\n    size_t j = d;\n    size_t k;\n    while(j)\n    {   // scale partials w.r.t z[j] and b[j]\n        pz[j]  = azmul(pz[j], inv_b0);\n        pb[j] *= Base(2.0);\n\n        pb[0] -= azmul(pz[j], z[j]);\n        px[j] += pz[j] + azmul(pb[j], x[0]);\n        px[0] += azmul(pb[j], x[j]);\n\n        // more scaling of partials w.r.t z[j]\n        pz[j] /= Base(double(j));\n\n        for(k = 1; k < j; k++)\n        {   pb[j-k] -= Base(double(k)) * azmul(pz[j], z[k]);\n            pz[k]   -= Base(double(k)) * azmul(pz[j], b[j-k]);\n            px[k]   += azmul(pb[j], x[j-k]);\n        }\n        --j;\n    }\n    px[0] += azmul(pz[0], inv_b0) + Base(2.0) * azmul(pb[0], x[0]);\n}\n\n} } } // END namespace\n# endif\n"
  },
  {
    "path": "include/cppad/local/var_op/atanh_op.hpp",
    "content": "# ifndef CPPAD_LOCAL_VAR_OP_ATANH_OP_HPP\n# define CPPAD_LOCAL_VAR_OP_ATANH_OP_HPP\n\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n\nnamespace CppAD { namespace local { namespace var_op {\n\n\n// See dev documentation: forward_unary_op\ntemplate <class Base>\ninline void atanh_forward_any(\n    size_t        order_low   ,\n    size_t        order_up    ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // p, q\n    size_t p = order_low;\n    size_t q = order_up;\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(AtanhOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(AtanhOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n    CPPAD_ASSERT_UNKNOWN( p <= q );\n\n    // Taylor coefficients corresponding to argument and result\n    Base* x = taylor + i_x * cap_order;\n    Base* z = taylor + i_z * cap_order;\n    Base* b = z      -       cap_order;  // called y in documentation\n\n    size_t k;\n    if( p == 0 )\n    {   z[0] = atanh( x[0] );\n        b[0] = Base(1.0) - x[0] * x[0];\n        p++;\n    }\n    for(size_t j = p; j <= q; j++)\n    {\n        b[j] = - Base(2.0) * x[0] * x[j];\n        z[j] = Base(0.0);\n        for(k = 1; k < j; k++)\n        {   b[j] -= x[k] * x[j-k];\n            z[j] -= Base(double(k)) * z[k] * b[j-k];\n        }\n        z[j] /= Base(double(j));\n        z[j] += x[j];\n        z[j] /= b[0];\n    }\n}\n\n// See dev documentation: forward_unary_op\ntemplate <class Base>\ninline void atanh_forward_dir(\n    size_t        order_up    ,\n    size_t        n_dir       ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // q, r\n    size_t q = order_up;\n    size_t r = n_dir;\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(AtanhOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(AtanhOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( 0 < q );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n\n    // Taylor coefficients corresponding to argument and result\n    size_t num_taylor_per_var = (cap_order-1) * r + 1;\n    Base* x = taylor + i_x * num_taylor_per_var;\n    Base* z = taylor + i_z * num_taylor_per_var;\n    Base* b = z      -       num_taylor_per_var; // called y in documentation\n\n    size_t m = (q-1) * r + 1;\n    for(size_t ell = 0; ell < r; ell++)\n    {   b[m+ell] = - Base(2.0) * x[m+ell] * x[0];\n        z[m+ell] = Base(double(q)) * x[m+ell];\n        for(size_t k = 1; k < q; k++)\n        {   b[m+ell] -= x[(k-1)*r+1+ell] * x[(q-k-1)*r+1+ell];\n            z[m+ell] -= Base(double(k)) * z[(k-1)*r+1+ell] * b[(q-k-1)*r+1+ell];\n        }\n        z[m+ell] /= ( Base(double(q)) * b[0] );\n    }\n}\n\n// See dev documentation: forward_unary_op\ntemplate <class Base>\ninline void atanh_forward_0(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{   //\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(AtanhOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(AtanhOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( 0 < cap_order );\n\n    // Taylor coefficients corresponding to argument and result\n    Base* x = taylor + i_x * cap_order;\n    Base* z = taylor + i_z * cap_order;\n    Base* b = z      -       cap_order; // called y in documentation\n\n    z[0] = atanh( x[0] );\n    b[0] = Base(1.0) - x[0] * x[0];\n}\n\n// See dev documentation: reverse_unary_op\ntemplate <class Base>\ninline void atanh_reverse(\n    size_t        i_z          ,\n    const addr_t* arg          ,\n    size_t        cap_order    ,\n    const Base*   taylor       ,\n    size_t        n_order      ,\n    Base*         partial      )\n{   // d  //\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    size_t d = n_order - 1;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(AtanhOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(AtanhOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( n_order <= cap_order );\n\n    // Taylor coefficients and partials corresponding to argument\n    const Base* x  = taylor  + i_x * cap_order;\n    Base* px       = partial + i_x * n_order;\n\n    // Taylor coefficients and partials corresponding to first result\n    const Base* z  = taylor  + i_z * cap_order;\n    Base* pz       = partial + i_z * n_order;\n\n    // Taylor coefficients and partials corresponding to auxiliary result\n    const Base* b  = z  - cap_order; // called y in documentation\n    Base* pb       = pz - n_order;\n\n    Base inv_b0 = Base(1.0) / b[0];\n\n    // number of indices to access\n    size_t j = d;\n    size_t k;\n    while(j)\n    {   // scale partials w.r.t z[j] and b[j]\n        pz[j]  = azmul(pz[j], inv_b0);\n        pb[j] *= Base(2.0);\n\n        pb[0] -= azmul(pz[j], z[j]);\n        px[j] += pz[j] - azmul(pb[j], x[0]);\n        px[0] -= azmul(pb[j], x[j]);\n\n        // more scaling of partials w.r.t z[j]\n        pz[j] /= Base(double(j));\n\n        for(k = 1; k < j; k++)\n        {   pb[j-k] -= Base(double(k)) * azmul(pz[j], z[k]);\n            pz[k]   -= Base(double(k)) * azmul(pz[j], b[j-k]);\n            px[k]   -= azmul(pb[j], x[j-k]);\n        }\n        --j;\n    }\n    px[0] += azmul(pz[0], inv_b0) - Base(2.0) * azmul(pb[0], x[0]);\n}\n\n} } } // END namespace\n# endif\n"
  },
  {
    "path": "include/cppad/local/var_op/atomic_op.hpp",
    "content": "# ifndef CPPAD_LOCAL_VAR_OP_ATOMIC_OP_HPP\n# define CPPAD_LOCAL_VAR_OP_ATOMIC_OP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n// BEGIN_CPPAD_LOCAL_VAR_OP_NAMESPACE\nnamespace CppAD { namespace local { namespace var_op {\n\n// sweep_type\nenum sweep_type {\n    forward_op_sweep,\n    forward_dir_sweep,\n    reverse_op_sweep,\n    for_jac_sweep,\n    rev_jac_sweep,\n    for_hes_sweep,\n    rev_hes_sweep\n};\n\n// atomic_op_work\ntemplate <class Base>\nstruct atomic_op_work {\n    // parameter_x, taylor_x, type_x, taylor_y, index_y, variable_y\n    CppAD::vector<Base>           parameter_x;\n    CppAD::vector<ad_type_enum>   type_x;\n    //\n    CppAD::vector<Base>           taylor_x;\n    CppAD::vector<Base>           taylor_y;\n    //\n    CppAD::vector<Base>           partial_x;\n    CppAD::vector<Base>           partial_y;\n    //\n    CppAD::vector<size_t>         index_x;\n    CppAD::vector<size_t>         index_y;\n    //\n    CppAD::vector<bool>           variable_x;\n    CppAD::vector<bool>           variable_y;\n    //\n    // resize\n    void resize(size_t m, size_t n, size_t n_order, sweep_type sweep)\n    {   //\n        // parameter_x, type_x\n        parameter_x.resize(n);\n        type_x.resize(n);\n        //\n        switch( sweep )\n        {\n            default:\n            CPPAD_ASSERT_UNKNOWN(false);\n            break;\n            // ------------------------------------------------------------------\n            // forward_op_sweep\n            case forward_op_sweep:\n            taylor_x.resize(n * n_order);\n            taylor_y.resize(m * n_order);\n            //\n            partial_x.resize(0);\n            partial_y.resize(0);\n            //\n            index_x.resize(0);\n            index_y.resize(m);\n            //\n            variable_x.resize(0);\n            variable_y.resize(m);\n            break;\n            // ------------------------------------------------------------------\n            // forward_dir_sweep\n            case forward_dir_sweep:\n            taylor_x.resize(n * n_order);\n            taylor_y.resize(m * n_order);\n            //\n            partial_x.resize(0);\n            partial_y.resize(0);\n            //\n            index_x.resize(n);\n            index_y.resize(m);\n            //\n            variable_x.resize(0);\n            variable_y.resize(m);\n            break;\n            // ------------------------------------------------------------------\n            // reverse_op_sweep\n            case reverse_op_sweep:\n            taylor_x.resize(n * n_order);\n            taylor_y.resize(m * n_order);\n            //\n            partial_x.resize(n * n_order);\n            partial_y.resize(m * n_order);\n            //\n            index_x.resize(n);\n            index_y.resize(0);\n            //\n            variable_x.resize(n);\n            variable_y.resize(0);\n            break;\n            // ------------------------------------------------------------------\n            // for_jac_sweep, rev_jac_sweep\n            // for_hes_sweep, rev_hes_sweep\n            case for_jac_sweep:\n            case rev_jac_sweep:\n            case for_hes_sweep:\n            case rev_hes_sweep:\n            taylor_x.resize(0);\n            taylor_y.resize(0);\n            //\n            partial_x.resize(0);\n            partial_y.resize(0);\n            //\n            index_x.resize(n);\n            index_y.resize(m);\n            //\n            variable_x.resize(0);\n            variable_y.resize(0);\n            break;\n        }\n    }\n};\n/*\n------------------------------------------------------------------------------\n{xrst_begin_parent var_atomic_op dev}\n{xrst_spell\n    funap\n    funav\n    funrp\n    funrv\n}\n\nAtomic Function Call Operators\n##############################\n\nAFunOp\n******\nThis operator appears at the start and end of every atomic function call.\nIt has four arguments and no results.\n\narg[0]\n======\nThis is the :ref:`atomic_index-name` for this function.\n\narg[1]\n======\nIf this is an atomic_four call,\narg[1] is the corresponding :ref:`atomic_four_call@call_id` .\nIf this is an atomic_one call (which has been deprecated)\narg[1] is corresponding :ref:`atomic_one@id`\n\narg[2], n\n=========\nis the number of arguments to this atomic function call.\nWe use the notation *n* = *arg* [2] .\n\narg[3], m\n=========\nis the number of results returned by this atomic function call.\nWe use the notation *m* = *arg* [3] .\n\nFunapOp, FunavOp\n****************\n#. There are *n* of these operators directly after\n   the AFunOp at the start of a function call,\n   one for each argument to the function call.\n#. Each of these operators has one argument and no result.\n#. If the *j*-th argument in the function call is a parameter (variable)\n   the corresponding operator is FunapOp ( FunavOp ).\n#. The operator argument for FunapOp ( FunavOp )\n   is the parameter index (variable index) for the corresponding\n   argument in the function call.\n\nFunrpOp, FunrvOp\n****************\n#. There are *m* of these operators directly after the\n   FunapOp or FunavOp operators for a function call,\n   one for each result returned by the function call.\n#. If the *i*-th result is a parameter (variable)\n   the corresponding operator is FunrpOp ( FunrvOp ).\n#. The FunrpOp operator has one argument and no result\n   (because the corresponding function result is not a variable).\n   The operator argument is the parameter index for the corresponding\n   result of the function call.\n#. The FunrvOp operator has no arguments and one variable result.\n   The new variable, created by this operator, gets its values from\n   the corresponding result of the function.\n\n{xrst_end var_atomic_op}\n-------------------------------------------------------------------------------\n{xrst_begin var_atomic_forward_any dev}\n\nAny Order Forward Atomic Function Call\n######################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_ATOMIC_FORWARD_ANY\n    // END_ATOMIC_FORWARD_ANY\n}\n\n{xrst_template ;\n    include/cppad/local/var_op/template/atomic_op.xrst\n    headers: n_res, i_z, itr, play, parameter, trace, work\n\n    @mode@ ; forward\n}\n{xrst_template ;\n    include/cppad/local/var_op/template/forward_op.xrst\n    headers: cap_order, order_low, order_up, taylor\n}\n\n{xrst_end var_atomic_forward_any}\n*/\n\n\n// BEGIN_ATOMIC_FORWARD_ANY\ntemplate <class Base, class RecBase>\nvoid atomic_forward_any(\n    play::const_sequential_iterator& itr        ,\n    const player<Base>*              play       ,\n    const Base*                      parameter  ,\n    bool                             trace      ,\n    atomic_op_work<Base>&            work       ,\n    size_t                           cap_order  ,\n    size_t                           order_low  ,\n    size_t                           order_up   ,\n    Base*                            taylor     )\n// END_ATOMIC_FORWARD_ANY\n{  //\n    // vector\n    using CppAD::vector;\n    //\n    // par_is_dyn\n    const pod_vector<bool>& par_is_dyn( play->par_is_dyn() );\n    //\n    // n_order\n    size_t n_order = order_up + 1;\n    //\n    // op_code, i_var, arg\n    op_code_var   op_code;\n    size_t        i_var;\n    const addr_t* arg;\n    itr.op_info(op_code, arg, i_var);\n    CPPAD_ASSERT_UNKNOWN( op_code == AFunOp );\n    CPPAD_ASSERT_NARG_NRES(op_code, 4, 0);\n    //\n    if( trace )\n    {  printOp<Base, RecBase>(\n            std::cout, play, itr.op_index(), i_var, op_code, arg\n        );\n        std::cout << std::endl;\n    }\n    //\n    // atom_index, call_id, m, n\n    size_t atom_index, call_id, m, n;\n    play::atom_op_info<RecBase>(op_code, arg, atom_index, call_id, m, n);\n    //\n    // parameter_x, type_x, taylor_x, taylor_y, index_y, variable_y\n    work.resize(m, n, n_order, forward_op_sweep);\n    vector<Base>&         parameter_x( work.parameter_x );\n    vector<ad_type_enum>& type_x( work.type_x );\n    //\n    vector<Base>&         taylor_x( work.taylor_x );\n    vector<Base>&         taylor_y( work.taylor_y );\n    //\n    vector<size_t>&       index_y( work.index_y );\n    vector<bool>&         variable_y( work.variable_y );\n    //\n    // j\n    for(size_t j = 0; j < n; ++j)\n    {  //\n        // op_code, arg, i_var\n        (++itr).op_info(op_code, arg, i_var);\n        if( trace )\n        {  printOp<Base, RecBase>(\n                std::cout, play, itr.op_index(), i_var, op_code, arg\n            );\n            std::cout << std::endl;\n        }\n        //\n        // type_x, parameter_x, taylor_x\n        switch(op_code)\n        {  //\n            default:\n            CPPAD_ASSERT_UNKNOWN(false);\n            break;\n            //\n            // FunapOp\n            case FunapOp:\n            CPPAD_ASSERT_NARG_NRES(op_code, 1, 0);\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < play->num_par_all() );\n            if( par_is_dyn[ arg[0] ] )\n                type_x[j]    = dynamic_enum;\n            else\n                type_x[j]    = constant_enum;\n            parameter_x[j]             = parameter[ arg[0] ];\n            taylor_x[j * n_order + 0]  = parameter[ arg[0] ];\n            for(size_t k = 1; k < n_order; ++k)\n                taylor_x[j * n_order + k] = Base(0.0);\n            break;\n            //\n            // FunavOp\n            case FunavOp:\n            CPPAD_ASSERT_NARG_NRES(op_code, 1, 0);\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < play->num_var() );\n            type_x[j]       = variable_enum;\n            parameter_x[j]  = CppAD::numeric_limits<Base>::quiet_NaN();\n            for(size_t k = 0; k < n_order; ++k)\n                taylor_x[j * n_order + k] =\n                    taylor[ size_t(arg[0]) * cap_order  + k ];\n            break;\n        }\n    }\n    //\n    // index_y, variable_y\n    for(size_t i = 0; i < m; ++i)\n    {  //\n        // op_code, arg, i_var\n        (++itr).op_info(op_code, arg, i_var);\n        //\n        //\n        switch(op_code)\n        {  //\n            default:\n            CPPAD_ASSERT_UNKNOWN(false);\n            break;\n            //\n            // FunrpOp\n            case FunrpOp:\n            CPPAD_ASSERT_NARG_NRES(op_code, 1, 0);\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < play->num_par_all() );\n            index_y[i]    = std::numeric_limits<size_t>::max();\n            variable_y[i] = false;\n            if( 0 < order_low )\n                taylor_y[i * n_order + 0] = parameter[ arg[0] ];\n            for(size_t k = 1; k < order_low; ++k)\n                taylor_y[i * n_order + k] = Base(0.0);\n            if( trace )\n            {  printOp<Base, RecBase>(\n                    std::cout, play, itr.op_index(), i_var, op_code, arg\n                );\n                std::cout << std::endl;\n            }\n            break;\n            //\n            // FunrvOp\n            case FunrvOp:\n            CPPAD_ASSERT_NARG_NRES(op_code, 0, 1);\n            CPPAD_ASSERT_UNKNOWN( 0 < i_var );\n            index_y[i]    = i_var;\n            variable_y[i] = true;\n            for(size_t k = 0; k < order_low; ++k)\n                taylor_y[i * n_order + k] = taylor[i_var * cap_order + k];\n            break;\n        }\n    }\n    //\n    // op_code\n    (++itr).op_info(op_code, arg, i_var);\n    CPPAD_ASSERT_UNKNOWN( op_code == AFunOp );\n    //\n    // taylor_y\n    size_t need_y = size_t(variable_enum);\n    sweep::call_atomic_forward<Base, RecBase>(\n        parameter_x,\n        type_x,\n        need_y,\n        variable_y,\n        order_low,\n        order_up,\n        atom_index,\n        call_id,\n        taylor_x,\n        taylor_y\n    );\n    //\n    // taylor\n    for(size_t i = 0; i < m; ++i)\n    {  if( variable_y[i] )\n        {  for(size_t k = order_low; k < n_order; ++k)\n                taylor[ index_y[i] * cap_order  + k ] = taylor_y[i * n_order + k];\n            if( trace )\n            {  const addr_t* null_addr = static_cast<addr_t*>( nullptr );\n                printOp<Base, RecBase>(\n                    std::cout, play, itr.op_index(), index_y[i], FunrvOp, null_addr\n                );\n                Base* yi_ptr          = taylor + index_y[i] * cap_order + 0;\n                const Base* null_base = static_cast<Base*>( nullptr );\n                printOpResult<Base>(\n                    std::cout, n_order, yi_ptr, 0, null_base\n                );\n                std::cout << std::endl;\n            }\n        }\n    }\n    //\n    return;\n}\n/*\n-----------------------------------------------------------------------------\n{xrst_begin var_atomic_forward_dir dev}\n\nMultiple Direction Forward Atomic Function Call\n###############################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_ATOMIC_FORWARD_DIR\n    // END_ATOMIC_FORWARD_DIR\n}\n\n{xrst_template ;\n    include/cppad/local/var_op/template/atomic_op.xrst\n    headers: n_res, i_z, itr, play, parameter, trace, work\n\n    @mode@ ; forward\n}\n{xrst_template ;\n    include/cppad/local/var_op/template/forward_dir.xrst\n    headers: n_dir, cap_order, order_up, taylor\n}\n\n\n{xrst_end var_atomic_forward_dir}\n*/\n// BEGIN_ATOMIC_FORWARD_DIR\ntemplate <class Base, class RecBase>\nvoid atomic_forward_dir(\n    play::const_sequential_iterator& itr        ,\n    const player<Base>*              play       ,\n    const Base*                      parameter  ,\n    bool                             trace      ,\n    atomic_op_work<Base>&            work       ,\n    size_t                           cap_order  ,\n    size_t                           order_up   ,\n    size_t                           n_dir      ,\n    Base*                            taylor     )\n// END_ATOMIC_FORWARD_DIR\n{  //\n    // order_low\n    size_t order_low = order_up;\n    //\n    // vector\n    using CppAD::vector;\n    //\n    // taylor_index\n    size_t per_variable = (cap_order - 1) * n_dir + 1;\n    auto taylor_index = [per_variable, n_dir]\n        (size_t variable_index, size_t order, size_t dir)\n    {  size_t index = variable_index * per_variable;\n        if( order > 0 )\n            index += (order - 1) * n_dir + 1 + dir;\n        return index;\n    };\n    //\n    // par_is_dyn\n    const pod_vector<bool>& par_is_dyn( play->par_is_dyn() );\n    //\n    // n_order\n    size_t n_order = order_up + 1;\n    //\n    // op_code, i_var, arg\n    op_code_var   op_code;\n    size_t        i_var;\n    const addr_t* arg;\n    itr.op_info(op_code, arg, i_var);\n    CPPAD_ASSERT_UNKNOWN( op_code == AFunOp );\n    CPPAD_ASSERT_NARG_NRES(op_code, 4, 0);\n    //\n    if( trace )\n    {  printOp<Base, RecBase>(\n            std::cout, play, itr.op_index(), i_var, op_code, arg\n        );\n        std::cout << std::endl;\n    }\n    //\n    // atom_index, call_id, m, n\n    size_t atom_index, call_id, m, n;\n    play::atom_op_info<RecBase>(op_code, arg, atom_index, call_id, m, n);\n    //\n    // parameter_x, type_x, taylor_x, taylor_y, index_x, index_y, variable_y\n    work.resize(m, n, n_order, forward_dir_sweep);\n    vector<Base>&         parameter_x( work.parameter_x );\n    vector<ad_type_enum>& type_x( work.type_x );\n    //\n    vector<Base>&         taylor_x( work.taylor_x );\n    vector<Base>&         taylor_y( work.taylor_y );\n    //\n    vector<size_t>&       index_x( work.index_x );\n    vector<size_t>&       index_y( work.index_y );\n    vector<bool>&         variable_y(work.variable_y );\n\n    //\n    // j\n    for(size_t j = 0; j < n; ++j)\n    {  //\n        // op_code, arg, i_var\n        (++itr).op_info(op_code, arg, i_var);\n        if( trace )\n        {  printOp<Base, RecBase>(\n                std::cout, play, itr.op_index(), i_var, op_code, arg\n            );\n            std::cout << std::endl;\n        }\n        //\n        // index_x, type_x, parameter_x\n        switch(op_code)\n        {  //\n            default:\n            CPPAD_ASSERT_UNKNOWN(false);\n            break;\n            //\n            // FunapOp\n            case FunapOp:\n            CPPAD_ASSERT_NARG_NRES(op_code, 1, 0);\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < play->num_par_all() );\n            index_x[j] = std::numeric_limits<size_t>::max();\n            if( par_is_dyn[ arg[0] ] )\n                type_x[j]    = dynamic_enum;\n            else\n                type_x[j]    = constant_enum;\n            parameter_x[j]  = parameter[ arg[0] ];\n            break;\n            //\n            // FunavOp\n            case FunavOp:\n            CPPAD_ASSERT_NARG_NRES(op_code, 1, 0);\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < play->num_var() );\n            index_x[j]      = size_t( arg[0] );\n            type_x[j]       = variable_enum;\n            parameter_x[j]  = CppAD::numeric_limits<Base>::quiet_NaN();\n            break;\n        }\n    }\n    //\n    // index_y, variable_y\n    for(size_t i = 0; i < m; ++i)\n    {  //\n        // op_code, arg, i_var\n        (++itr).op_info(op_code, arg, i_var);\n        //\n        //\n        switch(op_code)\n        {  //\n            default:\n            CPPAD_ASSERT_UNKNOWN(false);\n            break;\n            //\n            // FunrpOp\n            case FunrpOp:\n            CPPAD_ASSERT_NARG_NRES(op_code, 1, 0);\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < play->num_par_all() );\n            index_y[i]    = size_t( arg[0] );\n            variable_y[i] = false;\n            if( trace )\n            {  printOp<Base, RecBase>(\n                    std::cout, play, itr.op_index(), i_var, op_code, arg\n                );\n                std::cout << std::endl;\n            }\n            break;\n            //\n            // FunrvOp\n            case FunrvOp:\n            CPPAD_ASSERT_NARG_NRES(op_code, 0, 1);\n            CPPAD_ASSERT_UNKNOWN( 0 < i_var );\n            index_y[i]    = i_var;\n            variable_y[i] = true;\n            break;\n        }\n    }\n    //\n    // op_code\n    (++itr).op_info(op_code, arg, i_var);\n    CPPAD_ASSERT_UNKNOWN( op_code == AFunOp );\n    //\n    // dir\n    for(size_t dir = 0; dir < n_dir; ++dir)\n    {\n        //\n        // taylor_x\n        for(size_t j = 0; j < n; ++j)\n        {  if( type_x[j] != variable_enum )\n            {  taylor_x[j * n_order + 0] = parameter_x[j];\n                for(size_t k = 1; k < n_order; ++k)\n                    taylor_x[j * n_order + k] = Base(0.0);\n            }\n            else\n            {  for(size_t k = 0; k < n_order; ++k)\n                {  size_t index              = taylor_index(index_x[j], k, dir);\n                    taylor_x[j * n_order + k] = taylor[index];\n                }\n            }\n        }\n        //\n        // taylor_y\n        for(size_t i = 0; i < m; ++i)\n        {  if( ! variable_y[i] )\n            {  if( 0 < order_low )\n                    taylor_y[i * n_order + 0] = parameter[ index_y[i] ];\n                for(size_t k = 1; k < order_low; ++k)\n                    taylor_y[i * n_order + k] = Base(0.0);\n            }\n            else\n            {  for(size_t k = 0; k < order_low; ++k)\n                {  size_t index              = taylor_index(index_y[i], k, dir);\n                    taylor_y[i * n_order + k] = taylor[index];\n                }\n            }\n        }\n        size_t need_y = size_t(variable_enum);\n        sweep::call_atomic_forward<Base, RecBase>(\n            parameter_x,\n            type_x,\n            need_y,\n            variable_y,\n            order_low,\n            order_up,\n            atom_index,\n            call_id,\n            taylor_x,\n            taylor_y\n        );\n        //\n        // taylor\n        for(size_t i = 0; i < m; ++i) if( variable_y[i] )\n        {  for(size_t k = order_low; k < n_order; ++k)\n            {  size_t index  = taylor_index(index_y[i], k, dir);\n                taylor[index] = taylor_y[i * n_order + k];\n            }\n            if( trace )\n            {  const addr_t* null_addr = static_cast<addr_t*>( nullptr );\n                if( dir == 0 )\n                {  printOp<Base, RecBase>(\n                    std::cout, play, itr.op_index(), index_y[i], FunrvOp, null_addr\n                    );\n                    std::cout << std::endl;\n                }\n                Base* yi_ptr          = taylor_y.data() + i * n_order;\n                const Base* null_base = static_cast<Base*>( nullptr );\n                std::cout << \"     \";\n                printOpResult<Base>(\n                    std::cout, n_order, yi_ptr, 0, null_base\n                );\n                std::cout << std::endl;\n            }\n        }\n    }\n    //\n    return;\n}\n/*\n-------------------------------------------------------------------------------\n{xrst_begin var_atomic_reverse dev}\n{xrst_spell\n    subgraph\n}\n\nReverse Atomic Function Call\n############################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_ATOMIC_REVERSE\n    // END_ATOMIC_REVERSE\n}\n\nIterator\n********\nthis template parameter is either\n``play::subgraph_iterator`` or\n``play::const_sequential_iterator`` .\n\n{xrst_template ;\n    include/cppad/local/var_op/template/atomic_op.xrst\n    headers: n_res, i_z, itr, play, parameter, trace, work\n    headers if @mode@ is reverse: G and H\n\n    @mode@ ; reverse\n}\n\ncap_order\n*********\nsee atomic_forward_any :ref:`var_atomic_forward_any@cap_order`\n\nn_order\n*******\nis the number of Taylor coefficient orders that we are\ncomputing the partial derivatives with respect to.\n\ntaylor\n******\nThe Taylor coefficient for the variable with index j and order k is::\n\n    taylor[ j * cap_order + k ]\n\npartial\n*******\nThe partial derivative with respect to the order *k* Taylor coefficient\nfor the variable with index *j* is::\n\n    partial[ j * n_order + k ]\n\nOn input, *partial* contains the partial derivatives of *G*\nwith respect to the Taylor coefficients of the arguments to *G* .\nOn output, *partial* contains the partial derivatives of *H*\nwith respect to the Taylor coefficients of the arguments to *H* .\nWe only have partials with respect to variables; i.e.,\n*partial* does not included derivatives with respect to\nthe parameters in *x* or *y* .\n~\n\n{xrst_end var_atomic_reverse}\n*/\n// BEGIN_ATOMIC_REVERSE\ntemplate <class Base, class RecBase, class Iterator>\nvoid atomic_reverse(\n    Iterator&                        itr        ,\n    const player<Base>*              play       ,\n    const Base*                      parameter  ,\n    bool                             trace      ,\n    atomic_op_work<Base>&            work       ,\n    size_t                           cap_order  ,\n    size_t                           n_order    ,\n    const Base*                      taylor     ,\n    Base*                            partial    )\n// END_ATOMIC_REVERSE\n{  CPPAD_ASSERT_UNKNOWN( 0 < n_order );\n    //\n    // vector\n    using CppAD::vector;\n    //\n    // par_is_dyn\n    const pod_vector<bool>& par_is_dyn( play->par_is_dyn() );\n    //\n    // n_order\n    size_t order_up = n_order - 1;\n    //\n    // op_code, i_var, arg\n    op_code_var   op_code;\n    size_t        i_var;\n    const addr_t* arg;\n    itr.op_info(op_code, arg, i_var);\n    CPPAD_ASSERT_UNKNOWN( op_code == AFunOp );\n    CPPAD_ASSERT_NARG_NRES(op_code, 4, 0);\n    //\n    if( trace )\n    {  printOp<Base, RecBase>(\n            std::cout, play, itr.op_index(), i_var, op_code, arg\n        );\n        std::cout << std::endl;\n    }\n    //\n    // atom_index, call_id, m, n\n    size_t atom_index, call_id, m, n;\n    play::atom_op_info<RecBase>(op_code, arg, atom_index, call_id, m, n);\n    //\n    // parameter_x, type_x,\n    // taylor_x, taylor_y, partial_x, partial_y, variable_x, index_x\n    work.resize(m, n, n_order, reverse_op_sweep);\n    vector<Base>&         parameter_x( work.parameter_x );\n    vector<ad_type_enum>& type_x( work.type_x );\n    //\n    vector<Base>&         taylor_x( work.taylor_x );\n    vector<Base>&         taylor_y( work.taylor_y );\n    //\n    vector<Base>&         partial_x( work.partial_x );\n    vector<Base>&         partial_y( work.partial_y );\n    //\n    vector<bool>&         variable_x( work.variable_x );\n    vector<size_t>&       index_x( work.index_x );\n    //\n    // i\n    for(size_t ip1 = m; ip1 > 0; --ip1)\n    {  size_t i = ip1 - 1;\n        //\n        // op_code, arg, i_var\n        (--itr).op_info(op_code, arg, i_var);\n        if( trace )\n        {  printOp<Base, RecBase>(\n                std::cout, play, itr.op_index(), i_var, op_code, arg\n            );\n        }\n        //\n        // taylor_y, partial_y\n        switch(op_code)\n        {  //\n            default:\n            CPPAD_ASSERT_UNKNOWN(false);\n            break;\n            //\n            // FunrpOp\n            case FunrpOp:\n            CPPAD_ASSERT_NARG_NRES(op_code, 1, 0);\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < play->num_par_all() );\n            taylor_y[i * n_order + 0]  = parameter[ arg[0] ];\n            partial_y[i * n_order + 0] = Base(0.0);\n            for(size_t k = 1; k < n_order; ++k)\n            {  partial_y[i * n_order + k] = Base(0.0);\n                taylor_y[ i * n_order + k] = Base(0.0);\n            }\n            break;\n            //\n            // FunrvOp\n            case FunrvOp:\n            CPPAD_ASSERT_NARG_NRES(op_code, 0, 1);\n            CPPAD_ASSERT_UNKNOWN( 0 < i_var );\n            for(size_t k = 0; k < n_order; ++k)\n            {  taylor_y[ i * n_order + k] = taylor[i_var * cap_order + k];\n                partial_y[i * n_order + k] = partial[i_var * n_order + k];\n            }\n            if( trace )\n            {  const Base* t_ptr = taylor + i_var * cap_order;\n                const Base* p_ptr = partial + i_var * n_order;\n                printOpResult(\n                    std::cout,\n                    n_order,\n                    t_ptr,\n                    n_order,\n                    p_ptr\n                );\n            }\n            break;\n        }\n        if( trace )\n            std::cout << std::endl;\n    }\n    //\n    // j\n    for(size_t jp1 = n; jp1 > 0; --jp1)\n    {  size_t j = jp1 - 1;\n        //\n        // op_code, arg, i_var\n        (--itr).op_info(op_code, arg, i_var);\n        if( trace )\n        {  printOp<Base, RecBase>(\n                std::cout, play, itr.op_index(), i_var, op_code, arg\n            );\n            std::cout << std::endl;\n        }\n        //\n        // variable_x, type_x\n        switch(op_code)\n        {  //\n            default:\n            CPPAD_ASSERT_UNKNOWN(false);\n            break;\n            //\n            // FunapOp\n            case FunapOp:\n            CPPAD_ASSERT_NARG_NRES(op_code, 1, 0);\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < play->num_par_all() );\n            variable_x[j] = false;\n            index_x[j]    = size_t( arg[0] );\n            if( par_is_dyn[ arg[0] ] )\n                type_x[j]    = dynamic_enum;\n            else\n                type_x[j]    = constant_enum;\n            parameter_x[j]             = parameter[ arg[0] ];\n            taylor_x[j * n_order + 0]  = parameter[ arg[0] ];\n            for(size_t k = 1; k < n_order; ++k)\n                taylor_x[j * n_order + k] = Base(0.0);\n            break;\n            //\n            // FunavOp\n            case FunavOp:\n            CPPAD_ASSERT_NARG_NRES(op_code, 1, 0);\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < play->num_var() );\n            variable_x[j]   = true;\n            index_x[j]      = size_t( arg[0] );\n            type_x[j]       = variable_enum;\n            parameter_x[j]  = CppAD::numeric_limits<Base>::quiet_NaN();\n            for(size_t k = 0; k < n_order; ++k)\n                taylor_x[j * n_order + k] =\n                    taylor[ size_t(arg[0]) * cap_order  + k ];\n            break;\n        }\n    }\n    //\n    // op_code\n    (--itr).op_info(op_code, arg, i_var);\n    CPPAD_ASSERT_UNKNOWN( op_code == AFunOp );\n    //\n    // partial_y\n    sweep::call_atomic_reverse<Base, RecBase>(\n        parameter_x,\n        type_x,\n        variable_x,\n        order_up,\n        atom_index,\n        call_id,\n        taylor_x,\n        taylor_y,\n        partial_x,\n        partial_y\n    );\n    //\n    // taylor\n    for(size_t j = 0; j < n; ++j)\n    {  if( variable_x[j] )\n        {  for(size_t k = 0; k < n_order; ++k)\n            {  size_t index = index_x[j] * n_order + k;\n                partial[index] += partial_x[j * n_order + k];\n            }\n        }\n    }\n    //\n    return;\n}\n/*\n-------------------------------------------------------------------------------\n{xrst_begin var_atomic_for_jac dev}\n\nForward Jacobian Sparsity Atomic Function Call\n##############################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_ATOMIC_FOR_JAC\n    // END_ATOMIC_FOR_JAC\n}\n\n{xrst_template ;\n    include/cppad/local/var_op/template/atomic_op.xrst\n    headers: n_res, i_z, itr, play, parameter, trace, work\n\n    @mode@ ; forward\n}\n\nVector_set\n**********\nis the type used for vectors of sets. It must satisfy the\n:ref:`SetVector-name` concept.\n\nvar_sparsity\n************\n\nInput\n=====\n::\n\n    for j = 0, ..., i_z - n_res\n        The set with index j in var_sparsity\n\nOutput\n======\n::\n\n    for j = i_z , ... , i_z - n_res + 1\n        The set with index j in var_sparsity\n\n{xrst_end var_atomic_for_jac}\n*/\n// BEGIN_ATOMIC_FOR_JAC\ntemplate <class Vector_set, class Base, class RecBase>\ninline void atomic_for_jac(\n    play::const_sequential_iterator& itr          ,\n    const player<Base>*              play         ,\n    const Base*                      parameter    ,\n    bool                             trace        ,\n    atomic_op_work<Base>&            work         ,\n    bool                             dependency   ,\n    Vector_set&                      var_sparsity )\n// END_ATOMIC_FOR_JAC\n{   //\n    //\n    // vector\n    using CppAD::vector;\n    //\n    // par_is_dyn\n    const pod_vector<bool>& par_is_dyn( play->par_is_dyn() );\n    //\n    // op_code, i_var, arg\n    op_code_var   op_code;\n    size_t        i_var;\n    const addr_t* arg;\n    itr.op_info(op_code, arg, i_var);\n    CPPAD_ASSERT_UNKNOWN( op_code == AFunOp );\n    CPPAD_ASSERT_NARG_NRES(op_code, 4, 0);\n    //\n    if( trace )\n    {   printOp<Base, RecBase>(\n            std::cout, play, itr.op_index(), i_var, op_code, arg\n        );\n        std::cout << std::endl;\n    }\n    //\n    // atom_index, call_id, m, n\n    size_t atom_index, call_id, m, n;\n    play::atom_op_info<RecBase>(op_code, arg, atom_index, call_id, m, n);\n    //\n    // parameter_x, type_x, index_x, index_y\n    size_t n_order = 0;\n    work.resize(m, n, n_order, for_jac_sweep);\n    vector<Base>&         parameter_x( work.parameter_x );\n    vector<ad_type_enum>& type_x( work.type_x );\n    vector<size_t>&       index_x( work.index_x );\n    vector<size_t>&       index_y( work.index_y );\n    //\n    // j\n    for(size_t j = 0; j < n; ++j)\n    {   //\n        // op_code, arg, i_var\n        (++itr).op_info(op_code, arg, i_var);\n        if( trace )\n        {   printOp<Base, RecBase>(\n                std::cout, play, itr.op_index(), i_var, op_code, arg\n            );\n            std::cout << std::endl;\n        }\n        //\n        // type_x, parameter_x, index_x\n        switch(op_code)\n        {   //\n            default:\n            CPPAD_ASSERT_UNKNOWN(false);\n            break;\n            //\n            // FunapOp\n            case FunapOp:\n            CPPAD_ASSERT_NARG_NRES(op_code, 1, 0);\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < play->num_par_all() );\n            if( par_is_dyn[ arg[0] ] )\n                type_x[j]    = dynamic_enum;\n            else\n                type_x[j]    = constant_enum;\n            parameter_x[j]  = parameter[ arg[0] ];\n            index_x[j]      = 0; // special variable index used for parameters\n            break;\n            //\n            // FunavOp\n            case FunavOp:\n            CPPAD_ASSERT_NARG_NRES(op_code, 1, 0);\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < play->num_var() );\n            type_x[j]       = variable_enum;\n            parameter_x[j]  = CppAD::numeric_limits<Base>::quiet_NaN();\n            index_x[j]      = size_t(arg[0]);\n            break;\n        }\n    }\n    //\n    // i\n    for(size_t i = 0; i < m; ++i)\n    {   //\n        // op_code, arg, i_var\n        (++itr).op_info(op_code, arg, i_var);\n        //\n        // index_y\n        switch(op_code)\n        {   //\n            default:\n            CPPAD_ASSERT_UNKNOWN(false);\n            break;\n            //\n            // FunrpOp\n            case FunrpOp:\n            CPPAD_ASSERT_NARG_NRES(op_code, 1, 0);\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < play->num_par_all() );\n            index_y[i]       = 0;  // special variable index used for parameters\n            break;\n            //\n            // FunrvOp\n            case FunrvOp:\n            CPPAD_ASSERT_NARG_NRES(op_code, 0, 1);\n            CPPAD_ASSERT_UNKNOWN( 0 < i_var );\n            index_y[i]    = i_var;\n            break;\n        }\n    }\n    //\n    // op_code\n    (++itr).op_info(op_code, arg, i_var);\n    CPPAD_ASSERT_UNKNOWN( op_code == AFunOp );\n    //\n    // varsparsity\n    sweep::call_atomic_for_jac_sparsity<Base,RecBase>(\n        atom_index,\n        call_id,\n        dependency,\n        parameter_x,\n        type_x,\n        index_x,\n        index_y,\n        var_sparsity\n    );\n    //\n    if( trace )\n    {   size_t end = var_sparsity.end();\n        CppAD::vectorBool this_row(end);\n        addr_t*  arg_tmp = { 0 };\n        for(size_t i = 0; i < m; ++i)\n        {   size_t j_var = index_y[i];\n            for(size_t j = 0; j < end; ++j)\n                this_row[j] = false;\n            typename Vector_set::const_iterator itr_sparse(var_sparsity, j_var);\n            size_t j = *itr_sparse;\n            while( j < end )\n            {   this_row[j] = true;\n                j = *(++itr_sparse);\n            }\n            if( 0 < j_var )\n            {   printOp<Base, RecBase>(\n                    std::cout,\n                    play,\n                    itr.op_index() - m + i,\n                    j_var,\n                    FunrvOp,\n                    arg_tmp\n                );\n                printOpResult(\n                    std::cout,\n                    1,\n                    &this_row,\n                    0,\n                    (CppAD::vectorBool *) nullptr\n                );\n                std::cout << std::endl;\n            }\n        }\n    }\n    return;\n}\n/*\n------------------------------------------------------------------------------\n{xrst_begin var_atomic_rev_jac dev}\n\nReverse Jacobian Sparsity Atomic Function Call\n##############################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_ATOMIC_REV_JAC\n    // END_ATOMIC_REV_JAC\n}\n\n{xrst_template ;\n    include/cppad/local/var_op/template/atomic_op.xrst\n    headers: n_res, i_z, itr, play, parameter, trace, work\n    headers if @mode@ is reverse: G and H\n\n    @mode@ ; reverse\n}\n\nVector_set\n**********\nis the type used for vectors of sets. It must satisfy the\n:ref:`SetVector-name` concept.\n\nvar_sparsity\n************\nOn input, *var_sparsity* contains the sparsity pattern for\n:math:`G [ y, x, \\cdots ]` .\nOn output it contains the sparsity pattern for\n:math:`H ( x, \\cdots )` .\n\n{xrst_end var_atomic_rev_jac}\n*/\n// BEGIN_ATOMIC_REV_JAC\ntemplate <class Vector_set, class Base, class RecBase>\ninline void atomic_rev_jac(\n    play::const_sequential_iterator& itr          ,\n    const player<Base>*              play         ,\n    const Base*                      parameter    ,\n    bool                             trace        ,\n    atomic_op_work<Base>&            work         ,\n    bool                             dependency   ,\n    Vector_set&                      var_sparsity )\n// END_ATOMIC_REV_JAC\n{  //\n    //\n    // vector\n    using CppAD::vector;\n    //\n    // par_is_dyn\n    const pod_vector<bool>& par_is_dyn( play->par_is_dyn() );\n    //\n    // op_code, i_var, arg\n    op_code_var   op_code;\n    size_t        i_var;\n    const addr_t* arg;\n    itr.op_info(op_code, arg, i_var);\n    CPPAD_ASSERT_UNKNOWN( op_code == AFunOp );\n    CPPAD_ASSERT_NARG_NRES(op_code, 4, 0);\n    //\n    if( trace )\n    {  printOp<Base, RecBase>(\n            std::cout, play, itr.op_index(), i_var, op_code, arg\n        );\n        std::cout << std::endl;\n    }\n    //\n    // atom_index, call_id, m, n\n    size_t atom_index, call_id, m, n;\n    play::atom_op_info<RecBase>(op_code, arg, atom_index, call_id, m, n);\n    //\n    // parameter_x, type_x, index_x, index_y\n    size_t n_order = 0;\n    work.resize(m, n, n_order, rev_jac_sweep);\n    vector<Base>&         parameter_x( work.parameter_x );\n    vector<ad_type_enum>& type_x( work.type_x );\n    vector<size_t>&       index_x( work.index_x );\n    vector<size_t>&       index_y( work.index_y );\n    //\n    // i\n    for(size_t ip1 = m; ip1 > 0; --ip1)\n    {  size_t i = ip1 - 1;\n        //\n        // op_code, arg, i_var\n        (--itr).op_info(op_code, arg, i_var);\n        //\n        // index_y\n        switch(op_code)\n        {  //\n            default:\n            CPPAD_ASSERT_UNKNOWN(false);\n            break;\n            //\n            // FunrpOp\n            case FunrpOp:\n            CPPAD_ASSERT_NARG_NRES(op_code, 1, 0);\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < play->num_par_all() );\n            index_y[i]       = 0;  // special variable index used for parameters\n            break;\n            //\n            // FunrvOp\n            case FunrvOp:\n            CPPAD_ASSERT_NARG_NRES(op_code, 0, 1);\n            CPPAD_ASSERT_UNKNOWN( 0 < i_var );\n            index_y[i]    = i_var;\n            break;\n        }\n    }\n    if( trace )\n    {  size_t end = var_sparsity.end();\n        CppAD::vectorBool this_row(end);\n        const addr_t* arg_null = static_cast<addr_t*>(nullptr);\n        for(size_t ip1 = m; ip1 > 0; --ip1)\n        {  size_t i = ip1 - 1;\n            if( index_y[i] > 0 )\n            {  for(size_t j = 0; j < end; ++j)\n                    this_row[j] = false;\n                //\n                typedef typename Vector_set::const_iterator itr_sparse_t;\n                itr_sparse_t itr_sparse(var_sparsity, index_y[i]);\n                size_t j = *itr_sparse;\n                while( j < end )\n                {  this_row[j] = true;\n                    j = *(++itr_sparse);\n                }\n                printOp<Base, RecBase>(\n                    std::cout,\n                    play,\n                    itr.op_index() + i,\n                    index_y[i],\n                    FunrvOp,\n                    arg_null\n                );\n                printOpResult(\n                    std::cout,\n                    1,\n                    &this_row,\n                    0,\n                    (CppAD::vectorBool *) nullptr\n                );\n                std::cout << std::endl;\n            }\n        }\n    }\n    //\n    // j\n    for(size_t jp1 = n; jp1 > 0; --jp1)\n    {  size_t j = jp1 - 1;\n        //\n        // op_code, arg, i_var\n        (--itr).op_info(op_code, arg, i_var);\n        if( trace )\n        {  printOp<Base, RecBase>(\n                std::cout, play, itr.op_index(), i_var, op_code, arg\n            );\n            std::cout << std::endl;\n        }\n        //\n        // type_x, parameter_x, index_x\n        switch(op_code)\n        {  //\n            default:\n            CPPAD_ASSERT_UNKNOWN(false);\n            break;\n            //\n            // FunapOp\n            case FunapOp:\n            CPPAD_ASSERT_NARG_NRES(op_code, 1, 0);\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < play->num_par_all() );\n            if( par_is_dyn[ arg[0] ] )\n                type_x[j]    = dynamic_enum;\n            else\n                type_x[j]    = constant_enum;\n            parameter_x[j]  = parameter[ arg[0] ];\n            index_x[j]      = 0; // special variable index used for parameters\n            break;\n            //\n            // FunavOp\n            case FunavOp:\n            CPPAD_ASSERT_NARG_NRES(op_code, 1, 0);\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < play->num_var() );\n            type_x[j]       = variable_enum;\n            parameter_x[j]  = CppAD::numeric_limits<Base>::quiet_NaN();\n            index_x[j]      = size_t(arg[0]);\n            break;\n        }\n    }\n    //\n    // op_code\n    (--itr).op_info(op_code, arg, i_var);\n    CPPAD_ASSERT_UNKNOWN( op_code == AFunOp );\n    //\n    // varsparsity\n    sweep::call_atomic_rev_jac_sparsity<Base,RecBase>(\n        atom_index,\n        call_id,\n        dependency,\n        parameter_x,\n        type_x,\n        index_x,\n        index_y,\n        var_sparsity\n    );\n    return;\n}\n/*\n------------------------------------------------------------------------------\n{xrst_begin var_atomic_rev_hes dev}\n\nReverse Hessian Sparsity Atomic Function Call\n#############################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_ATOMIC_REV_HES\n    // END_ATOMIC_REV_HES\n}\n\n{xrst_template ;\n    include/cppad/local/var_op/template/atomic_op.xrst\n    headers: n_res, i_z, itr, play, parameter, trace, work\n    headers if @mode@ is reverse: G and H\n\n    @mode@ ; reverse\n}\n\nnum_var\n*******\nWe use the notation *num_var* for the number of variables on the tape\n(including the phantom variable at index zero); i.e.::\n``play->num_var()`` .\n\nfor_jac_sparsity\n****************\nThe set with index *j* is the forward Jacobian sparsity\npattern for the variable with index *j*.\n\nrev_jac_include\n***************\nIf the *j* element of this vector is true,\nthe variable with index *j* is included in the Hessian,\nor affects the value of a variable that is included in the Hessian.\n\nInput\n=====\n::\n\n    for j = num_var, ... , i_z + 1\n        rev_jac_include[j] is an input\n\nOutput\n======\n::\n\n    for j = i_z , ... , i_z - n_res + 1\n        rev_jac_include[j] is an output\n\nrev_hes_sparsity\n****************\nOn input (output), this is the sparsity pattern for *G* ( *H* ).\nFor each variable index *j* ,\n*rev_hes_sparsity* [ *j* ] is the set of indices\nthat may have non-zero cross partials with variable index *j* .\n\nExample\n=======\nIf the indices in the sets correspond to the independent variables,\nthen *rev_hes_sparsity* ``.end()`` is the number of independent variables.\nFor *i* a variable index between 1 and the number of independent variables,\n*i* - 1 is the corresponding independent variable index.\n(The index *i* = 0 corresponds to the phantom variable at the beginning\nof the tape. )\n\n{xrst_end var_atomic_rev_hes}\n*/\n// BEGIN_ATOMIC_REV_HES\ntemplate <class Vector_set, class Base, class RecBase>\ninline void atomic_rev_hes(\n    play::const_sequential_iterator& itr               ,\n    const player<Base>*              play              ,\n    const Base*                      parameter         ,\n    bool                             trace             ,\n    atomic_op_work<Base>&            work              ,\n    const Vector_set&                for_jac_sparsity  ,\n    bool*                            rev_jac_include   ,\n    Vector_set&                      rev_hes_sparsity  )\n// END_ATOMIC_REV_HES\n{  //\n    //\n    CPPAD_ASSERT_UNKNOWN( for_jac_sparsity.n_set() == play->num_var() );\n    CPPAD_ASSERT_UNKNOWN( rev_hes_sparsity.n_set() == play->num_var() );\n    CPPAD_ASSERT_UNKNOWN( for_jac_sparsity.end()   == rev_hes_sparsity.end() );\n    //\n    // vector\n    using CppAD::vector;\n    //\n    // par_is_dyn\n    const pod_vector<bool>& par_is_dyn( play->par_is_dyn() );\n    //\n    // op_code, i_var, arg\n    op_code_var   op_code;\n    size_t        i_var;\n    const addr_t* arg;\n    itr.op_info(op_code, arg, i_var);\n    CPPAD_ASSERT_UNKNOWN( op_code == AFunOp );\n    CPPAD_ASSERT_NARG_NRES(op_code, 4, 0);\n    //\n    if( trace )\n    {  printOp<Base, RecBase>(\n            std::cout, play, itr.op_index(), i_var, op_code, arg\n        );\n        std::cout << std::endl;\n    }\n    //\n    // atom_index, call_id, m, n\n    size_t atom_index, call_id, m, n;\n    play::atom_op_info<RecBase>(op_code, arg, atom_index, call_id, m, n);\n    //\n    // parameter_x, type_x, index_x, index_y\n    size_t n_order = 0;\n    work.resize(m, n, n_order, rev_hes_sweep);\n    vector<Base>&         parameter_x( work.parameter_x );\n    vector<ad_type_enum>& type_x( work.type_x );\n    vector<size_t>&       index_x( work.index_x );\n    vector<size_t>&       index_y( work.index_y );\n    //\n    // i\n    for(size_t ip1 = m; ip1 > 0; --ip1)\n    {  size_t i = ip1 - 1;\n        //\n        // op_code, arg, i_var\n        (--itr).op_info(op_code, arg, i_var);\n        //\n        // index_y\n        switch(op_code)\n        {  //\n            default:\n            CPPAD_ASSERT_UNKNOWN(false);\n            break;\n            //\n            // FunrpOp\n            case FunrpOp:\n            CPPAD_ASSERT_NARG_NRES(op_code, 1, 0);\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < play->num_par_all() );\n            index_y[i]       = 0;  // special variable index used for parameters\n            break;\n            //\n            // FunrvOp\n            case FunrvOp:\n            CPPAD_ASSERT_NARG_NRES(op_code, 0, 1);\n            CPPAD_ASSERT_UNKNOWN( 0 < i_var );\n            index_y[i]    = i_var;\n            break;\n        }\n    }\n    //\n    // j\n    for(size_t jp1 = n; jp1 > 0; --jp1)\n    {  size_t j = jp1 - 1;\n        //\n        // op_code, arg, i_var\n        (--itr).op_info(op_code, arg, i_var);\n        if( trace )\n        {  printOp<Base, RecBase>(\n                std::cout, play, itr.op_index(), i_var, op_code, arg\n            );\n            std::cout << std::endl;\n        }\n        //\n        // type_x, parameter_x, index_x\n        switch(op_code)\n        {  //\n            default:\n            CPPAD_ASSERT_UNKNOWN(false);\n            break;\n            //\n            // FunapOp\n            case FunapOp:\n            CPPAD_ASSERT_NARG_NRES(op_code, 1, 0);\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < play->num_par_all() );\n            if( par_is_dyn[ arg[0] ] )\n                type_x[j]    = dynamic_enum;\n            else\n                type_x[j]    = constant_enum;\n            parameter_x[j]  = parameter[ arg[0] ];\n            index_x[j]      = 0; // special variable index used for parameters\n            break;\n            //\n            // FunavOp\n            case FunavOp:\n            CPPAD_ASSERT_NARG_NRES(op_code, 1, 0);\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < play->num_var() );\n            type_x[j]       = variable_enum;\n            parameter_x[j]  = CppAD::numeric_limits<Base>::quiet_NaN();\n            index_x[j]      = size_t(arg[0]);\n            break;\n        }\n    }\n    //\n    // op_code\n    (--itr).op_info(op_code, arg, i_var);\n    CPPAD_ASSERT_UNKNOWN( op_code == AFunOp );\n    //\n    // rev_jac_include, rev_hes_sparsity\n    sweep::call_atomic_rev_hes_sparsity<Base,RecBase>(\n        atom_index,\n        call_id,\n        parameter_x,\n        type_x,\n        index_x,\n        index_y,\n        for_jac_sparsity,\n        rev_jac_include,\n        rev_hes_sparsity\n    );\n    //\n    if( trace )\n    {  typedef typename Vector_set::const_iterator itr_sparse_t;\n        size_t end = rev_hes_sparsity.end();\n        CppAD::vectorBool jac_row(end), hes_row(end);\n        addr_t*  arg_tmp = { 0 };\n        for(size_t i = 0; i < m; ++i)\n        {  size_t j_var = index_y[i];\n            if( 0 < j_var)\n            {\n                for(size_t j = 0; j < end; ++j)\n                {  jac_row[j]  = false;\n                    hes_row[j]  = false;\n                }\n                itr_sparse_t itr_jac(for_jac_sparsity, j_var);\n                size_t j = *itr_jac;\n                while( j < end )\n                {  jac_row[j] = true;\n                    j = *(++itr_jac);\n                }\n                itr_sparse_t itr_hes(rev_hes_sparsity, j_var);\n                j = *itr_hes;\n                while( j < end )\n                {  hes_row[j] = true;\n                    j = *(++itr_hes);\n                }\n                printOp<Base, RecBase>(\n                    std::cout,\n                    play,\n                    itr.op_index() - m + i,\n                    j_var,\n                    FunrvOp,\n                    arg_tmp\n                );\n                printOpResult(\n                    std::cout,\n                    1,\n                    &jac_row,\n                    1,\n                    &hes_row\n                );\n                std::cout << std::endl;\n            }\n        }\n    }\n    return;\n}\n/*\n-------------------------------------------------------------------------------\n{xrst_begin var_atomic_for_hes dev}\n\nForward Hessian Sparsity Atomic Function Call\n#############################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_ATOMIC_FOR_HES\n    // END_ATOMIC_FOR_HES\n}\n\n{xrst_template ;\n    include/cppad/local/var_op/template/atomic_op.xrst\n    headers: n_res, i_z, itr, play, parameter, trace, work\n\n    @mode@ ; forward\n}\n\nVector_set\n**********\nis the type used for vectors of sets. It must satisfy the\n:ref:`SetVector-name` concept.\n\nn_independent_p1\n****************\nis the number of independent variables (in the tape) plus one.\n\nrev_jac_sparsity\n****************\nis the reverse Jacobian sparsity pattern for the scalar valued\nfunction that the Hessian sparsity is being computed for.\nZero is the only possible element in each set;\ni.e.. *ref_jac_sparsity* .end() == 1 .\nIf the set with index *j* is empty,\nthe derivative of the function w.r.t the variable with index *j* is zero.\n\nfor_hes_sparsity\n****************\nOn input, all the linear and nonlinear interactions up to the\narguments to the atomic function have been take into account.\nUpon return, the linear and nonlinear interactions in\nthe atomic function have been take into account.\n\nHessian Sparsity\n================\nFor *j* equal 1 to *n_independent_p1* - 1,\nif *i* is in set with index *j* ,\nthe Hessian may have a non-zero partial with respect to the\nindependent variables with indices ( *i* - 1, *j* - 1 ) .\nNote that the index zero is not used because it corresponds to the\nphantom variable on the tape.\n\nJacobian Sparsity\n=================\nIf *i* is in the set with index *n_independent_p1* + *j* ,\nthe variable with index *j* may have a non-zero partial with resect to the\nindependent variable with index *i* - 1 .\n\n{xrst_end var_atomic_for_hes}\n*/\n// BEGIN_ATOMIC_FOR_HES\ntemplate <class Vector_set, class Base, class RecBase>\ninline void atomic_for_hes(\n    play::const_sequential_iterator& itr              ,\n    const player<Base>*              play             ,\n    const Base*                      parameter        ,\n    bool                             trace            ,\n    atomic_op_work<Base>&            work             ,\n    size_t                           n_independent_p1 ,\n    const Vector_set&                rev_jac_sparsity ,\n    Vector_set&                      for_hes_sparsity )\n// END_ATOMIC_FOR_HES\n{   CPPAD_ASSERT_UNKNOWN( rev_jac_sparsity.end() == 1 );\n    //\n    CPPAD_ASSERT_UNKNOWN( for_hes_sparsity.end() == n_independent_p1 );\n    //\n    // vector\n    using CppAD::vector;\n    //\n    // par_is_dyn\n    const pod_vector<bool>& par_is_dyn( play->par_is_dyn() );\n    //\n    // op_code, i_var, arg\n    op_code_var   op_code;\n    size_t        i_var;\n    const addr_t* arg;\n    itr.op_info(op_code, arg, i_var);\n    CPPAD_ASSERT_UNKNOWN( op_code == AFunOp );\n    CPPAD_ASSERT_NARG_NRES(op_code, 4, 0);\n    //\n    if( trace )\n    {   printOp<Base, RecBase>(\n            std::cout, play, itr.op_index(), i_var, op_code, arg\n        );\n        std::cout << std::endl;\n    }\n    //\n    // atom_index, call_id, m, n\n    size_t atom_index, call_id, m, n;\n    play::atom_op_info<RecBase>(op_code, arg, atom_index, call_id, m, n);\n    //\n    // parameter_x, type_x, index_x, index_y\n    size_t n_order = 0;\n    work.resize(m, n, n_order, for_hes_sweep);\n    vector<Base>&         parameter_x( work.parameter_x );\n    vector<ad_type_enum>& type_x( work.type_x );\n    vector<size_t>&       index_x( work.index_x );\n    vector<size_t>&       index_y( work.index_y );\n    //\n    // j\n    for(size_t j = 0; j < n; ++j)\n    {   //\n        // op_code, arg, i_var\n        (++itr).op_info(op_code, arg, i_var);\n        if( trace )\n        {   printOp<Base, RecBase>(\n                std::cout, play, itr.op_index(), i_var, op_code, arg\n            );\n            std::cout << std::endl;\n        }\n        //\n        // type_x, parameter_x, index_x\n        switch(op_code)\n        {   //\n            default:\n            CPPAD_ASSERT_UNKNOWN(false);\n            break;\n            //\n            // FunapOp\n            case FunapOp:\n            CPPAD_ASSERT_NARG_NRES(op_code, 1, 0);\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < play->num_par_all() );\n            if( par_is_dyn[ arg[0] ] )\n                type_x[j]    = dynamic_enum;\n            else\n                type_x[j]    = constant_enum;\n            parameter_x[j]  = parameter[ arg[0] ];\n            index_x[j]      = 0; // special variable index used for parameters\n            break;\n            //\n            // FunavOp\n            case FunavOp:\n            CPPAD_ASSERT_NARG_NRES(op_code, 1, 0);\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < play->num_var() );\n            type_x[j]       = variable_enum;\n            parameter_x[j]  = CppAD::numeric_limits<Base>::quiet_NaN();\n            index_x[j]      = size_t(arg[0]);\n            break;\n        }\n    }\n    //\n    // i\n    for(size_t i = 0; i < m; ++i)\n    {   //\n        // op_code, arg, i_var\n        (++itr).op_info(op_code, arg, i_var);\n        //\n        // index_y\n        switch(op_code)\n        {   //\n            default:\n            CPPAD_ASSERT_UNKNOWN(false);\n            break;\n            //\n            // FunrpOp\n            case FunrpOp:\n            CPPAD_ASSERT_NARG_NRES(op_code, 1, 0);\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < play->num_par_all() );\n            index_y[i]       = 0;  // special variable index used for parameters\n            break;\n            //\n            // FunrvOp\n            case FunrvOp:\n            CPPAD_ASSERT_NARG_NRES(op_code, 0, 1);\n            CPPAD_ASSERT_UNKNOWN( 0 < i_var );\n            index_y[i]    = i_var;\n            break;\n        }\n    }\n    //\n    // op_code\n    (++itr).op_info(op_code, arg, i_var);\n    CPPAD_ASSERT_UNKNOWN( op_code == AFunOp );\n    //\n    // varsparsity\n    size_t num_var = play->num_var();\n    sweep::call_atomic_for_hes_sparsity<Base,RecBase>(\n        atom_index,\n        call_id,\n        parameter_x,\n        type_x,\n        index_x,\n        index_y,\n        n_independent_p1,\n        num_var,\n        rev_jac_sparsity,\n        for_hes_sparsity\n    );\n    //\n    if( trace )\n    {   typedef typename Vector_set::const_iterator itr_sparse_t;\n        size_t np1 = n_independent_p1;\n        CPPAD_ASSERT_UNKNOWN( np1 == for_hes_sparsity.end() );\n        CppAD::vectorBool jac_row(np1);\n        addr_t*  arg_tmp = { 0 };\n        for(size_t i = 0; i < m; ++i)\n        {   size_t j_var = index_y[i];\n            if( 0 < j_var )\n            {   for(size_t j = 0; j < np1; ++j)\n                    jac_row[j] = false;\n                itr_sparse_t itr_jac(for_hes_sparsity, np1 + j_var);\n                size_t j = *itr_jac;\n                while( j < np1 )\n                {   jac_row[j] = true;\n                    j = *(++itr_jac);\n                }\n                printOp<Base, RecBase>(\n                    std::cout,\n                    play,\n                    itr.op_index() - m + i,\n                    j_var,\n                    FunrvOp,\n                    arg_tmp\n                );\n                printOpResult(\n                    std::cout,\n                    1,\n                    &jac_row,\n                    0,\n                    (CppAD::vectorBool *) nullptr\n                );\n                std::cout << std::endl;\n            }\n        }\n        CppAD::vector< CppAD::vectorBool > hes(np1);\n        for(size_t i = 0; i < np1; ++i)\n        {   hes[i].resize(np1);\n            for(size_t j = 0; j < np1; ++j)\n                hes[i][j] = false;\n            itr_sparse_t itr_hes(for_hes_sparsity, i);\n            size_t j = *itr_hes;\n            while( j < np1 )\n            {   hes[i][j] = true;\n                j = *(++itr_hes);\n            }\n        }\n        printOpResult(\n            std::cout,\n            np1,\n            hes.data(),\n            0,\n            (CppAD::vectorBool *) nullptr\n        );\n        std::cout << std::endl;\n    }\n    return;\n}\n\n\n} } } // END_CPPAD_LOCAL_VAR_OP_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/var_op/binary_op.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin_parent var_binary_op dev}\n{xrst_spell\n    addpv\n    addvv\n    azmul\n    delim\n    divpv\n    divvp\n    divvv\n    mulpv\n    mulvv\n    powpv\n    powvp\n    powvv\n    subpv\n    subvp\n    subvv\n    zmulpv\n    zmulvp\n    zmulvv\n}\n\nBinary Operators\n################\nAll these operators have the same prototype and could be implemented as\nvirtual functions for a binary base case.\nCompilers can not optimize across virtual function calls and testing indicates\nthat a virtual function implementation is significant slower.\n\nUser Syntax\n***********\n| *z* = *fun* ( *x* , *y* )\n| *z* = *x* *Op* *y*\n\nx\n*\nis a parameter or variable and is the first argument for this operator.\n\ny\n*\nis a parameter or variable and is the second argument for this operator.\n\nz\n*\nis the primary result for this operator which is also a variable.\nThe PowvpOp and PowvvOp operators has a two auxiliary results;\nsee :ref:`var_binary_op@n_res` below.\n\nBase\n****\nbase type for the operator; i.e., this operation was recorded\nusing AD<Base> and computations by these operators done using type Base.\n\nFun\n***\n\n.. csv-table::\n    :widths: auto\n    :header-rows: 1\n    :delim: ;\n\n    op_code;      Fun;     fun; Op;         x;         y;  z\n    AddpvOp;    addpv;        ; \\+; parameter;  variable;  *x* + *y*\n    AddvvOp;    addvv;        ; \\+;  variable;  variable;  *x* + *y*\n    DivpvOp;    divpv;        ; \\/; parameter;  variable;  *x* / *y*\n    DivvpOp;    divvp;        ; \\/;  variable; parameter;  *x* / *y*\n    DivvvOp;    divvv;        ; \\/;  variable;  variable;  *x* / *y*\n    MulpvOp;    mulpv;        ; \\*; parameter;  variable;  *x* * *y*\n    MulvvOp;    mulvv;        ; \\*;  variable;  variable;  *x* * *y*\n    SubpvOp;    subpv;        ; \\-; parameter;  variable;  *x* - *y*\n    SubvpOp;    subvp;        ; \\-;  variable; parameter;  *x* - *y*\n    SubvvOp;    subvv;        ; \\-;  variable;  variable;  *x* - *y*\n    PowpvOp;    zmulpv;    pow;   ; parameter;  variable;    pow( *x* , *y* )\n    PowvpOp;    zmulvp;    pow;   ;  variable; parameter;    pow( *x* , *y* )\n    PowvvOp;    zmulvv;    pow;   ;  variable;  variable;    pow( *x* , *y* )\n    ZmulpvOp;   zmulpv;  azmul;   ; parameter;  variable;  azmul( *x* , *y* )\n    ZmulvpOp;   zmulvp;  azmul;   ;  variable; parameter;  azmul( *x* , *y* )\n    ZmulvvOp;   zmulvv;  azmul;   ;  variable;  variable;  azmul( *x* , *y* )\n\ni_z\n***\nis the variable index corresponding to *z* .\n\nn_res\n*****\nis the number of results that are variables.\nThis is 1 for all the binary operators except for PowpvOp and PowvvOp.\nFor the PowpvOp and PowvvOP operators, *n_res* is 3\nand the variable indices of the auxiliary results are *i_z* - 1 and *i_z* - 2.\n\narg\n***\n\narg[0]\n======\nIf *x* is a variable (parameter)\n*arg* [0] is the variable index (parameter index) corresponding to *x* .\n\narg[1]\n======\nIf *y* is a variable (parameter)\n*arg* [1] is the variable index (parameter index) corresponding to *y* .\n\nparameter\n*********\nmaps parameter indices to parameter values.\n\n{xrst_end var_binary_op}\n------------------------------------------------------------------------------\n{xrst_begin var_binary_forward_0 dev}\n\nZero Order Forward Binary Variable Operators\n############################################\n\nx, y, z, n_res\n**************\nsee\n:ref:`var_binary_op@x` ,\n:ref:`var_binary_op@y` ,\n:ref:`var_binary_op@z` ,\n:ref:`var_binary_op@n_res`\n\nPrototype\n*********\n{xrst_code cpp}\ntemplate <class Base>\ninline void Fun_forward_0(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{xrst_code}\n\nBase, Fun, i_z, arg, parameter\n******************************\nsee\n:ref:`var_binary_op@Base` ,\n:ref:`var_binary_op@Fun` ,\n:ref:`var_binary_op@i_z` ,\n:ref:`var_binary_op@arg` ,\n:ref:`var_binary_op@parameter`\n\ncap_order\n*********\nis the maximum number of orders that can fit in *taylor* .\n\ntaylor\n******\nThe Taylor coefficient corresponding to variable *i* and order *k* is\n\n    *taylor* [ *i* * *cap_order* + *k*  ]\n\nInput\n=====\nThe zero order Taylor coefficients\nfor variables with index *i* less than or equal *i_z* - *n_res* .\n\nOutput\n======\nThe zero order Taylor coefficients for variables with index\n*i_z* - *n_res* , .. , *i_z* .\n\n{xrst_end var_binary_forward_0}\n------------------------------------------------------------------------------\n{xrst_begin var_binary_forward_any dev}\n\nAny Order Forward Binary Variable Operators\n###########################################\n\nx, y, z, n_res\n**************\nsee\n:ref:`var_binary_op@x` ,\n:ref:`var_binary_op@y` ,\n:ref:`var_binary_op@z` ,\n:ref:`var_binary_op@n_res`\n\nPrototype\n*********\n{xrst_code cpp}\ntemplate <class Base>\ninline void Fun_forward_any(\n    size_t        order_low   ,\n    size_t        order_up    ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{xrst_code}\n\nBase, Fun, i_z, arg, parameter\n******************************\nsee\n:ref:`var_binary_op@Base` ,\n:ref:`var_binary_op@Fun` ,\n:ref:`var_binary_op@i_z` ,\n:ref:`var_binary_op@arg` ,\n:ref:`var_binary_op@parameter`\n\n{xrst_template ;\n    include/cppad/local/var_op/template/forward_op.xrst\n    headers: cap_order, order_low, order_up, taylor\n}\n\n{xrst_end var_binary_forward_any}\n------------------------------------------------------------------------------\n{xrst_begin var_binary_forward_dir dev}\n\nMultiple Direction Forward Binary Operators\n###########################################\n\nx, y, z, n_res\n**************\nsee\n:ref:`var_binary_op@x` ,\n:ref:`var_binary_op@y` ,\n:ref:`var_binary_op@z` ,\n:ref:`var_binary_op@n_res`\n\nPrototype\n*********\n{xrst_code cpp}\ntemplate <class Base>\ninline void Fun_forward_dir(\n    size_t        order_up    ,\n    size_t        n_dir       ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{xrst_code}\n\nBase, Fun, i_z, arg, parameter\n******************************\nsee\n:ref:`var_binary_op@Base` ,\n:ref:`var_binary_op@Fun` ,\n:ref:`var_binary_op@i_z` ,\n:ref:`var_binary_op@arg` ,\n:ref:`var_binary_op@parameter`\n\n{xrst_template ;\n    include/cppad/local/var_op/template/forward_dir.xrst\n    headers: n_dir, cap_order, order_up, taylor\n}\n\n{xrst_end var_binary_forward_dir}\n------------------------------------------------------------------------------\n{xrst_begin var_binary_reverse dev}\n\nReverse Mode Binary Operators\n#############################\n\nx, y, z, n_res\n**************\nsee\n:ref:`var_binary_op@x` ,\n:ref:`var_binary_op@y` ,\n:ref:`var_binary_op@z` ,\n:ref:`var_binary_op@n_res`\n\nPrototype\n*********\n{xrst_code cpp}\ntemplate <class Base>\ninline void Fun_reverse(\n    size_t        i_z          ,\n    const addr_t* arg          ,\n    const Base*   parameter    ,\n    size_t        cap_order    ,\n    const Base*   taylor       ,\n    size_t        n_order      ,\n    Base*         partial      )\n{xrst_code}\n\nBase, Fun, i_z, arg, parameter\n******************************\nsee\n:ref:`var_binary_op@Base` ,\n:ref:`var_binary_op@Fun` ,\n:ref:`var_binary_op@i_z` ,\n:ref:`var_binary_op@arg` ,\n:ref:`var_binary_op@parameter`\n\ncap_order\n*********\nis the maximum number of orders that can fit in *taylor* .\n\ntaylor\n******\nThe Taylor coefficient corresponding to variable *i* and order *k* is\n\n    *taylor* [ *i* * *cap_order* + *k*  ]\n\n{xrst_template ;\n    include/cppad/local/var_op/template/reverse_op.xrst\n    headers: n_order, partial\n\n    @x, y@ ; x\n}\n\n{xrst_end var_binary_reverse}\n------------------------------------------------------------------------------\n"
  },
  {
    "path": "include/cppad/local/var_op/cexp_op.hpp",
    "content": "# ifndef CPPAD_LOCAL_VAR_OP_CEXP_OP_HPP\n# define CPPAD_LOCAL_VAR_OP_CEXP_OP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\nnamespace CppAD { namespace local { namespace var_op {\n/*\n{xrst_begin_parent var_cexp_op dev}\n\nThe Variable Conditional Expression Operator\n############################################\n\nCExpOp\n******\nis the op code for this operator.\n\nUser Syntax\n***********\n| *z* = ``CondExp`` *Rel* ( *left* , *right* , *if_true* , *if_false* )\n\nRel\n***\nis Lt, Le, Eq, Ge, Gt or Ne .\n\nleft\n****\nis the left operand for the comparison.\n\nright\n*****\nis the right operand for the comparison.\n\nif_true\n*******\nis the value assigned to *z* if the comparison result is true.\n\nif_false\n********\nis the value assigned to *z* if the comparison result is false.\n\nz\n*\nis the variable that results from the comparison.\n\narg\n***\n\narg[0]\n======\nis static cast to addr_t from the enum type\n{xrst_literal\n    include/cppad/local/declare_ad.hpp\n    // BEGIN_COMPARE_OP\n    // END_COMPARE_OP\n}\nThe operator corresponding to Ne does not appear because that case\nis converted to the Eq case by switching *if_true* and *if_false* .\nThus it must hold that::\n\n    arg[0] < addr_t(CompareNe)\n\narg[1]\n======\nThe first four bits of this value are used as flags; see below.\n\narg[2]\n======\nIf arg[1] & 1 is zero (is one) ,\narg[2] is the parameter (variable) index corresponding to *left*\n\narg[3]\n======\nIf arg[1] & 2 is zero (is one) ,\narg[3] is the parameter (variable) index corresponding to *right*\n\narg[4]\n======\nIf arg[1] & 4 is zero (is one) ,\narg[4] is the parameter (variable) index corresponding to *if_true*\n\narg[5]\n======\nIf arg[1] & 8 is zero (is one) ,\narg[5] is the parameter (variable) index corresponding to *if_false*\n\n{xrst_end var_cexp_op}\n------------------------------------------------------------------------------\n{xrst_begin var_cexp_forward_any dev}\n\nAny Order Forward Conditional Expression Variable Operator\n##########################################################\n\nz\n*\nsee\n:ref:`var_cexp_op@z`\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_CEXP_FORWARD_ANY\n    // END_CEXP_FORWARD_ANY\n}\n\narg\n***\nsee\n:ref:`var_cexp_op@arg`\n\nRecBase\n*******\nis the base type use when recording this operator;\ni.e., this operation was recording using AD< *RecBase* > operations.\n\nBase\n****\nis the type used for computations by this operator.\nThis is either *RecBase* or AD< *RecBase* >.\n\ni_z\n***\nis the variable index corresponding to the variable *z* .\n\nnum_par\n*******\nis the total number of values in the *parameter* vector.\n\nparameter\n*********\nmaps parameter indices to parameter values .\n\n{xrst_template ;\n    include/cppad/local/var_op/template/forward_op.xrst\n    headers: cap_order, order_low, order_up, taylor\n}\n\n{xrst_end var_cexp_forward_any}\n*/\n// BEGIN_CEXP_FORWARD_ANY\ntemplate <class Base>\ninline void cexp_forward_any(\n    size_t         order_low   ,\n    size_t         order_up    ,\n    size_t         i_z         ,\n    const addr_t*  arg         ,\n    size_t         num_par     ,\n    const Base*    parameter   ,\n    size_t         cap_order   ,\n    Base*          taylor      )\n// END_CEXP_FORWARD_ANY\n{   Base y_0, y_1, y_2, y_3;\n    size_t p = order_low;\n    size_t q = order_up;\n    //\n    Base zero(0);\n    Base* z = taylor + i_z * cap_order;\n\n    CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < static_cast<size_t> (CompareNe) );\n    CPPAD_ASSERT_UNKNOWN( NumArg(CExpOp) == 6 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(CExpOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( arg[1] != 0 );\n\n    if( arg[1] & 1 )\n    {\n        y_0 = taylor[ size_t(arg[2]) * cap_order + 0 ];\n    }\n    else\n    {   CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) < num_par );\n        y_0 = parameter[ arg[2] ];\n    }\n    if( arg[1] & 2 )\n    {\n        y_1 = taylor[ size_t(arg[3]) * cap_order + 0 ];\n    }\n    else\n    {   CPPAD_ASSERT_UNKNOWN( size_t(arg[3]) < num_par );\n        y_1 = parameter[ arg[3] ];\n    }\n    if( p == 0 )\n    {   if( arg[1] & 4 )\n        {\n            y_2 = taylor[ size_t(arg[4]) * cap_order + 0 ];\n        }\n        else\n        {   CPPAD_ASSERT_UNKNOWN( size_t(arg[4]) < num_par );\n            y_2 = parameter[ arg[4] ];\n        }\n        if( arg[1] & 8 )\n        {\n            y_3 = taylor[ size_t(arg[5]) * cap_order + 0 ];\n        }\n        else\n        {   CPPAD_ASSERT_UNKNOWN( size_t(arg[5]) < num_par );\n            y_3 = parameter[ arg[5] ];\n        }\n        z[0] = CondExpOp(\n            CompareOp( arg[0] ),\n            y_0,\n            y_1,\n            y_2,\n            y_3\n        );\n        p++;\n    }\n    for(size_t d = p; d <= q; d++)\n    {   if( arg[1] & 4 )\n        {\n            y_2 = taylor[ size_t(arg[4]) * cap_order + d];\n        }\n        else\n            y_2 = zero;\n        if( arg[1] & 8 )\n        {\n            y_3 = taylor[ size_t(arg[5]) * cap_order + d];\n        }\n        else\n            y_3 = zero;\n        z[d] = CondExpOp(\n            CompareOp( arg[0] ),\n            y_0,\n            y_1,\n            y_2,\n            y_3\n        );\n    }\n    return;\n}\n\n/*!\nMultiple directions forward mode Taylor coefficients for op = CExpOp.\n\n<!-- replace conditional_exp_op -->\nThe C++ source code corresponding to this operation is\n\\verbatim\n    z = CondExpRel(y_0, y_1, y_2, y_3)\n\\endverbatim\nwhere Rel is one of the following: Lt, Le, Eq, Ge, Gt.\n\n\\tparam Base\nbase type for the operator; i.e., this operation was recorded\nusing AD< Base > and computations by this routine are done using type\n Base.\n\n\\param i_z\nis the AD variable index corresponding to the variable z.\n\n\\param arg\n\\n\n arg[0]\nis static cast to size_t from the enum type\n\\verbatim\n    enum CompareOp {\n        CompareLt,\n        CompareLe,\n        CompareEq,\n        CompareGe,\n        CompareGt,\n        CompareNe\n    }\n\\endverbatim\nfor this operation.\nNote that arg[0] cannot be equal to CompareNe.\n\\n\n\\n\n arg[1] & 1\n\\n\nIf this is zero, y_0 is a parameter. Otherwise it is a variable.\n\\n\n\\n\n arg[1] & 2\n\\n\nIf this is zero, y_1 is a parameter. Otherwise it is a variable.\n\\n\n\\n\n arg[1] & 4\n\\n\nIf this is zero, y_2 is a parameter. Otherwise it is a variable.\n\\n\n\\n\n arg[1] & 8\n\\n\nIf this is zero, y_3 is a parameter. Otherwise it is a variable.\n\\n\n\\n\n arg[2 + j ] for j = 0, 1, 2, 3\n\\n\nis the index corresponding to y_j.\n\n\\param num_par\nis the total number of values in the vector parameter.\n\n\\param parameter\nFor j = 0, 1, 2, 3,\nif y_j is a parameter, parameter [ arg[2 + j] ] is its value.\n\n\\param cap_order\nnumber of columns in the matrix containing the Taylor coefficients.\n\n\\par Checked Assertions\n\\li NumArg(CExpOp) == 6\n\\li NumRes(CExpOp) == 1\n\\li arg[0] < static_cast<size_t> ( CompareNe )\n\\li arg[1] != 0; i.e., not all of y_0, y_1, y_2, y_3 are parameters.\n\\li For j = 0, 1, 2, 3 if y_j is a parameter, arg[2+j] < num_par.\n<!-- end conditional_exp_op -->\n\n\\param q\nis order of the Taylor coefficient of z that we are computing.\n\n\\param r\nis the number of Taylor coefficient directions that we are computing.\n\n\\par tpv\nWe use the notation\n<code>tpv = (cap_order-1) * r + 1</code>\nwhich is the number of Taylor coefficients per variable\n\n\\param taylor\n\\b Input:\nFor j = 0, 1, 2, 3, k = 1, ..., q,\nif y_j is a variable then\n<code>taylor [ arg[2+j] * tpv + 0 ]</code>\nis the zero order Taylor coefficient corresponding to y_j and\n<code>taylor [ arg[2+j] * tpv + (k-1)*r+1+ell</code> is its\nk-th order Taylor coefficient in the ell-th direction.\n\\n\n\\b Input:\nFor j = 0, 1, 2, 3, k = 1, ..., q-1,\n<code>taylor [ i_z * tpv + 0 ]</code>\nis the zero order Taylor coefficient corresponding to z and\n<code>taylor [ i_z * tpv + (k-1)*r+1+ell</code> is its\nk-th order Taylor coefficient in the ell-th direction.\n\\n\n\\b Output: <code>taylor [ i_z * tpv + (q-1)*r+1+ell ]</code>\nis the q-th order Taylor coefficient corresponding to z\nin the ell-th direction.\n*/\ntemplate <class Base>\ninline void cexp_forward_dir(\n    size_t         order_up    ,\n    size_t         n_dir       ,\n    size_t         i_z         ,\n    const addr_t*  arg         ,\n    size_t         num_par     ,\n    const Base*    parameter   ,\n    size_t         cap_order   ,\n    Base*          taylor      )\n{   Base y_0, y_1, y_2, y_3;\n    size_t q = order_up;\n    size_t r = n_dir;\n    //\n    Base zero(0);\n    size_t num_taylor_per_var = (cap_order-1) * r + 1;\n    Base* z = taylor + i_z * num_taylor_per_var;\n\n    CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < static_cast<size_t> (CompareNe) );\n    CPPAD_ASSERT_UNKNOWN( NumArg(CExpOp) == 6 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(CExpOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( arg[1] != 0 );\n    CPPAD_ASSERT_UNKNOWN( 0 < q );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n\n    if( arg[1] & 1 )\n    {\n        y_0 = taylor[ size_t(arg[2]) * num_taylor_per_var + 0 ];\n    }\n    else\n    {   CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) < num_par );\n        y_0 = parameter[ arg[2] ];\n    }\n    if( arg[1] & 2 )\n    {\n        y_1 = taylor[ size_t(arg[3]) * num_taylor_per_var + 0 ];\n    }\n    else\n    {   CPPAD_ASSERT_UNKNOWN( size_t(arg[3]) < num_par );\n        y_1 = parameter[ arg[3] ];\n    }\n    size_t m = (q-1) * r + 1;\n    for(size_t ell = 0; ell < r; ell++)\n    {   if( arg[1] & 4 )\n        {\n            y_2 = taylor[ size_t(arg[4]) * num_taylor_per_var + m + ell];\n        }\n        else\n            y_2 = zero;\n        if( arg[1] & 8 )\n        {\n            y_3 = taylor[ size_t(arg[5]) * num_taylor_per_var + m + ell];\n        }\n        else\n            y_3 = zero;\n        z[m+ell] = CondExpOp(\n            CompareOp( arg[0] ),\n            y_0,\n            y_1,\n            y_2,\n            y_3\n        );\n    }\n    return;\n}\n\n/*!\nCompute zero order forward mode Taylor coefficients for op = CExpOp.\n\n<!-- replace conditional_exp_op -->\nThe C++ source code corresponding to this operation is\n\\verbatim\n    z = CondExpRel(y_0, y_1, y_2, y_3)\n\\endverbatim\nwhere Rel is one of the following: Lt, Le, Eq, Ge, Gt.\n\n\\tparam Base\nbase type for the operator; i.e., this operation was recorded\nusing AD< Base > and computations by this routine are done using type\n Base.\n\n\\param i_z\nis the AD variable index corresponding to the variable z.\n\n\\param arg\n\\n\n arg[0]\nis static cast to size_t from the enum type\n\\verbatim\n    enum CompareOp {\n        CompareLt,\n        CompareLe,\n        CompareEq,\n        CompareGe,\n        CompareGt,\n        CompareNe\n    }\n\\endverbatim\nfor this operation.\nNote that arg[0] cannot be equal to CompareNe.\n\\n\n\\n\n arg[1] & 1\n\\n\nIf this is zero, y_0 is a parameter. Otherwise it is a variable.\n\\n\n\\n\n arg[1] & 2\n\\n\nIf this is zero, y_1 is a parameter. Otherwise it is a variable.\n\\n\n\\n\n arg[1] & 4\n\\n\nIf this is zero, y_2 is a parameter. Otherwise it is a variable.\n\\n\n\\n\n arg[1] & 8\n\\n\nIf this is zero, y_3 is a parameter. Otherwise it is a variable.\n\\n\n\\n\n arg[2 + j ] for j = 0, 1, 2, 3\n\\n\nis the index corresponding to y_j.\n\n\\param num_par\nis the total number of values in the vector parameter.\n\n\\param parameter\nFor j = 0, 1, 2, 3,\nif y_j is a parameter, parameter [ arg[2 + j] ] is its value.\n\n\\param cap_order\nnumber of columns in the matrix containing the Taylor coefficients.\n\n\\par Checked Assertions\n\\li NumArg(CExpOp) == 6\n\\li NumRes(CExpOp) == 1\n\\li arg[0] < static_cast<size_t> ( CompareNe )\n\\li arg[1] != 0; i.e., not all of y_0, y_1, y_2, y_3 are parameters.\n\\li For j = 0, 1, 2, 3 if y_j is a parameter, arg[2+j] < num_par.\n<!-- end conditional_exp_op -->\n\n\\param taylor\n\\b Input:\nFor j = 0, 1, 2, 3,\nif y_j is a variable then\n taylor [ arg[2+j] * cap_order + 0 ]\nis the zero order Taylor coefficient corresponding to y_j.\n\\n\n\\b Output: taylor [ i_z * cap_order + 0 ]\nis the zero order Taylor coefficient corresponding to z.\n*/\ntemplate <class Base>\ninline void cexp_forward_0(\n    size_t         i_z         ,\n    const addr_t*  arg         ,\n    size_t         num_par     ,\n    const Base*    parameter   ,\n    size_t         cap_order   ,\n    Base*          taylor      )\n{   Base y_0, y_1, y_2, y_3;\n    //\n    Base* z;\n\n    CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < static_cast<size_t> (CompareNe) );\n    CPPAD_ASSERT_UNKNOWN( NumArg(CExpOp) == 6 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(CExpOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( arg[1] != 0 );\n\n    if( arg[1] & 1 )\n    {\n        y_0 = taylor[ size_t(arg[2]) * cap_order + 0 ];\n    }\n    else\n    {   CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) < num_par );\n        y_0 = parameter[ arg[2] ];\n    }\n    if( arg[1] & 2 )\n    {\n        y_1 = taylor[ size_t(arg[3]) * cap_order + 0 ];\n    }\n    else\n    {   CPPAD_ASSERT_UNKNOWN( size_t(arg[3]) < num_par );\n        y_1 = parameter[ arg[3] ];\n    }\n    if( arg[1] & 4 )\n    {\n        y_2 = taylor[ size_t(arg[4]) * cap_order + 0 ];\n    }\n    else\n    {   CPPAD_ASSERT_UNKNOWN( size_t(arg[4]) < num_par );\n        y_2 = parameter[ arg[4] ];\n    }\n    if( arg[1] & 8 )\n    {\n        y_3 = taylor[ size_t(arg[5]) * cap_order + 0 ];\n    }\n    else\n    {   CPPAD_ASSERT_UNKNOWN( size_t(arg[5]) < num_par );\n        y_3 = parameter[ arg[5] ];\n    }\n    z = taylor + i_z * cap_order;\n    z[0] = CondExpOp(\n        CompareOp( arg[0] ),\n        y_0,\n        y_1,\n        y_2,\n        y_3\n    );\n    return;\n}\n\n/*!\nCompute reverse mode Taylor coefficients for op = CExpOp.\n\nThis routine is given the partial derivatives of a function\nG( z , y , x , w , ... )\nand it uses them to compute the partial derivatives of\n\\verbatim\n    H( y , x , w , u , ... ) = G[ z(y) , y , x , w , u , ... ]\n\\endverbatim\nwhere y above represents y_0, y_1, y_2, y_3.\n\n<!-- replace conditional_exp_op -->\nThe C++ source code corresponding to this operation is\n\\verbatim\n    z = CondExpRel(y_0, y_1, y_2, y_3)\n\\endverbatim\nwhere Rel is one of the following: Lt, Le, Eq, Ge, Gt.\n\n\\tparam Base\nbase type for the operator; i.e., this operation was recorded\nusing AD< Base > and computations by this routine are done using type\n Base.\n\n\\param i_z\nis the AD variable index corresponding to the variable z.\n\n\\param arg\n\\n\n arg[0]\nis static cast to size_t from the enum type\n\\verbatim\n    enum CompareOp {\n        CompareLt,\n        CompareLe,\n        CompareEq,\n        CompareGe,\n        CompareGt,\n        CompareNe\n    }\n\\endverbatim\nfor this operation.\nNote that arg[0] cannot be equal to CompareNe.\n\\n\n\\n\n arg[1] & 1\n\\n\nIf this is zero, y_0 is a parameter. Otherwise it is a variable.\n\\n\n\\n\n arg[1] & 2\n\\n\nIf this is zero, y_1 is a parameter. Otherwise it is a variable.\n\\n\n\\n\n arg[1] & 4\n\\n\nIf this is zero, y_2 is a parameter. Otherwise it is a variable.\n\\n\n\\n\n arg[1] & 8\n\\n\nIf this is zero, y_3 is a parameter. Otherwise it is a variable.\n\\n\n\\n\n arg[2 + j ] for j = 0, 1, 2, 3\n\\n\nis the index corresponding to y_j.\n\n\\param num_par\nis the total number of values in the vector parameter.\n\n\\param parameter\nFor j = 0, 1, 2, 3,\nif y_j is a parameter, parameter [ arg[2 + j] ] is its value.\n\n\\param cap_order\nnumber of columns in the matrix containing the Taylor coefficients.\n\n\\par Checked Assertions\n\\li NumArg(CExpOp) == 6\n\\li NumRes(CExpOp) == 1\n\\li arg[0] < static_cast<size_t> ( CompareNe )\n\\li arg[1] != 0; i.e., not all of y_0, y_1, y_2, y_3 are parameters.\n\\li For j = 0, 1, 2, 3 if y_j is a parameter, arg[2+j] < num_par.\n<!-- end conditional_exp_op -->\n\n\\param d\nis the order of the Taylor coefficient of z that we are  computing.\n\n\\param taylor\n\\b Input:\nFor j = 0, 1, 2, 3 and k = 0 , ... , d,\nif y_j is a variable then\n taylor [ arg[2+j] * cap_order + k ]\nis the k-th order Taylor coefficient corresponding to y_j.\n\\n\n taylor [ i_z * cap_order + k ]\nfor k = 0 , ... , d\nis the k-th order Taylor coefficient corresponding to z.\n\n\\param n_order\nnumber of columns in the matrix containing the Taylor coefficients.\n\n\\param partial\n\\b Input:\nFor j = 0, 1, 2, 3 and k = 0 , ... , d,\nif y_j is a variable then\n partial [ arg[2+j] * n_order + k ]\nis the partial derivative of G( z , y , x , w , u , ... )\nwith respect to the k-th order Taylor coefficient corresponding to y_j.\n\\n\n\\b Input: partial [ i_z * cap_order + k ]\nfor k = 0 , ... , d\nis the partial derivative of G( z , y , x , w , u , ... )\nwith respect to the k-th order Taylor coefficient corresponding to z.\n\\n\n\\b Output:\nFor j = 0, 1, 2, 3 and k = 0 , ... , d,\nif y_j is a variable then\n partial [ arg[2+j] * n_order + k ]\nis the partial derivative of H( y , x , w , u , ... )\nwith respect to the k-th order Taylor coefficient corresponding to y_j.\n\n*/\ntemplate <class Base>\ninline void cexp_reverse(\n    size_t         i_z         ,\n    const addr_t*  arg         ,\n    size_t         num_par     ,\n    const Base*    parameter   ,\n    size_t         cap_order   ,\n    const Base*    taylor      ,\n    size_t         n_order     ,\n    Base*          partial     )\n{   // d\n    //\n    size_t d = n_order - 1;\n    //\n    Base y_0, y_1;\n    Base zero(0);\n    Base* pz;\n    Base* py_2;\n    Base* py_3;\n\n    CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < static_cast<size_t> (CompareNe) );\n    CPPAD_ASSERT_UNKNOWN( NumArg(CExpOp) == 6 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(CExpOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( arg[1] != 0 );\n\n    pz = partial + i_z * n_order + 0;\n    if( arg[1] & 1 )\n    {\n        y_0 = taylor[ size_t(arg[2]) * cap_order + 0 ];\n    }\n    else\n    {   CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) < num_par );\n        y_0 = parameter[ arg[2] ];\n    }\n    if( arg[1] & 2 )\n    {\n        y_1 = taylor[ size_t(arg[3]) * cap_order + 0 ];\n    }\n    else\n    {   CPPAD_ASSERT_UNKNOWN( size_t(arg[3]) < num_par );\n        y_1 = parameter[ arg[3] ];\n    }\n    if( arg[1] & 4 )\n    {\n        py_2 = partial + size_t(arg[4]) * n_order;\n        size_t j = d + 1;\n        while(j--)\n        {   py_2[j] += CondExpOp(\n                CompareOp( arg[0] ),\n                y_0,\n                y_1,\n                pz[j],\n                zero\n            );\n        }\n    }\n    if( arg[1] & 8 )\n    {\n        py_3 = partial + size_t(arg[5]) * n_order;\n        size_t j = d + 1;\n        while(j--)\n        {   py_3[j] += CondExpOp(\n                CompareOp( arg[0] ),\n                y_0,\n                y_1,\n                zero,\n                pz[j]\n            );\n        }\n    }\n    return;\n}\n\n/*!\nCompute forward Jacobian sparsity patterns for op = CExpOp.\n\n<!-- replace sparse_conditional_exp_op -->\nThe C++ source code corresponding to this operation is\n\\verbatim\n    z = CondExpRel(y_0, y_1, y_2, y_3)\n\\endverbatim\nwhere Rel is one of the following: Lt, Le, Eq, Ge, Gt.\n\n\\tparam Vector_set\nis the type used for vectors of sets. It can be either\nsparse::pack_setvec or sparse::list_setvec.\n\n\\param i_z\nis the AD variable index corresponding to the variable z.\n\n\\param arg\n\\n\n arg[0]\nis static cast to size_t from the enum type\n\\verbatim\n    enum CompareOp {\n        CompareLt,\n        CompareLe,\n        CompareEq,\n        CompareGe,\n        CompareGt,\n        CompareNe\n    }\n\\endverbatim\nfor this operation.\nNote that arg[0] cannot be equal to CompareNe.\n\\n\n\\n\n arg[1] & 1\n\\n\nIf this is zero, y_0 is a parameter. Otherwise it is a variable.\n\\n\n\\n\n arg[1] & 2\n\\n\nIf this is zero, y_1 is a parameter. Otherwise it is a variable.\n\\n\n\\n\n arg[1] & 4\n\\n\nIf this is zero, y_2 is a parameter. Otherwise it is a variable.\n\\n\n\\n\n arg[1] & 8\n\\n\nIf this is zero, y_3 is a parameter. Otherwise it is a variable.\n\\n\n\\n\n arg[2 + j ] for j = 0, 1, 2, 3\n\\n\nis the index corresponding to y_j.\n\n\\param num_par\nis the total number of values in the vector parameter.\n\n\\par Checked Assertions\n\\li NumArg(CExpOp) == 6\n\\li NumRes(CExpOp) == 1\n\\li arg[0] < static_cast<size_t> ( CompareNe )\n\\li arg[1] != 0; i.e., not all of y_0, y_1, y_2, y_3 are parameters.\n\\li For j = 0, 1, 2, 3 if y_j is a parameter, arg[2+j] < num_par.\n<!-- end sparse_conditional_exp_op -->\n\n\\param dependency\nAre the derivatives with respect to left and right of the expression below\nconsidered to be non-zero:\n\\code\n    CondExpRel(left, right, if_true, if_false)\n\\endcode\nThis is used by the optimizer to obtain the correct dependency relations.\n\n\\param sparsity\n\\b Input:\nif y_2 is a variable, the set with index t is\nthe sparsity pattern corresponding to y_2.\nThis identifies which of the independent variables the variable y_2\ndepends on.\n\\n\n\\b Input:\nif y_3 is a variable, the set with index t is\nthe sparsity pattern corresponding to y_3.\nThis identifies which of the independent variables the variable y_3\ndepends on.\n\\n\n\\b Output:\nThe set with index T is\nthe sparsity pattern corresponding to z.\nThis identifies which of the independent variables the variable z\ndepends on.\n*/\ntemplate <class Vector_set>\ninline void cexp_for_jac(\n    bool               dependency    ,\n    size_t             i_z           ,\n    const addr_t*      arg           ,\n    size_t             num_par       ,\n    Vector_set&        sparsity      )\n{   //\n    //\n    CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < static_cast<size_t> (CompareNe) );\n    CPPAD_ASSERT_UNKNOWN( NumArg(CExpOp) == 6 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(CExpOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( arg[1] != 0 );\n# ifndef NDEBUG\n    addr_t k = 1;\n    for( size_t j = 0; j < 4; j++)\n    {   if( ! ( arg[1] & k ) )\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[2+j]) < num_par );\n        k *= 2;\n    }\n# endif\n    sparsity.clear(i_z);\n    if( dependency )\n    {   if( arg[1] & 1 )\n            sparsity.binary_union(i_z, i_z, size_t(arg[2]), sparsity);\n        if( arg[1] & 2 )\n            sparsity.binary_union(i_z, i_z, size_t(arg[3]), sparsity);\n    }\n    if( arg[1] & 4 )\n        sparsity.binary_union(i_z, i_z, size_t(arg[4]), sparsity);\n    if( arg[1] & 8 )\n        sparsity.binary_union(i_z, i_z, size_t(arg[5]), sparsity);\n    return;\n}\n\n/*!\nCompute reverse Jacobian sparsity patterns for op = CExpOp.\n\nThis routine is given the sparsity patterns\nfor a function G(z, y, x, ... )\nand it uses them to compute the sparsity patterns for\n\\verbatim\n    H( y, x, w , u , ... ) = G[ z(x,y) , y , x , w , u , ... ]\n\\endverbatim\nwhere y represents the combination of y_0, y_1, y_2, and y_3.\n\n<!-- replace sparse_conditional_exp_op -->\nThe C++ source code corresponding to this operation is\n\\verbatim\n    z = CondExpRel(y_0, y_1, y_2, y_3)\n\\endverbatim\nwhere Rel is one of the following: Lt, Le, Eq, Ge, Gt.\n\n\\tparam Vector_set\nis the type used for vectors of sets. It can be either\nsparse::pack_setvec or sparse::list_setvec.\n\n\\param i_z\nis the AD variable index corresponding to the variable z.\n\n\\param arg\n\\n\n arg[0]\nis static cast to size_t from the enum type\n\\verbatim\n    enum CompareOp {\n        CompareLt,\n        CompareLe,\n        CompareEq,\n        CompareGe,\n        CompareGt,\n        CompareNe\n    }\n\\endverbatim\nfor this operation.\nNote that arg[0] cannot be equal to CompareNe.\n\\n\n\\n\n arg[1] & 1\n\\n\nIf this is zero, y_0 is a parameter. Otherwise it is a variable.\n\\n\n\\n\n arg[1] & 2\n\\n\nIf this is zero, y_1 is a parameter. Otherwise it is a variable.\n\\n\n\\n\n arg[1] & 4\n\\n\nIf this is zero, y_2 is a parameter. Otherwise it is a variable.\n\\n\n\\n\n arg[1] & 8\n\\n\nIf this is zero, y_3 is a parameter. Otherwise it is a variable.\n\\n\n\\n\n arg[2 + j ] for j = 0, 1, 2, 3\n\\n\nis the index corresponding to y_j.\n\n\\param num_par\nis the total number of values in the vector parameter.\n\n\\par Checked Assertions\n\\li NumArg(CExpOp) == 6\n\\li NumRes(CExpOp) == 1\n\\li arg[0] < static_cast<size_t> ( CompareNe )\n\\li arg[1] != 0; i.e., not all of y_0, y_1, y_2, y_3 are parameters.\n\\li For j = 0, 1, 2, 3 if y_j is a parameter, arg[2+j] < num_par.\n<!-- end sparse_conditional_exp_op -->\n\n\\param dependency\nAre the derivatives with respect to left and right of the expression below\nconsidered to be non-zero:\n\\code\n    CondExpRel(left, right, if_true, if_false)\n\\endcode\nThis is used by the optimizer to obtain the correct dependency relations.\n\n\n\\param sparsity\nif y_2 is a variable, the set with index t is\nthe sparsity pattern corresponding to y_2.\nThis identifies which of the dependent variables depend on the variable y_2.\nOn input, this pattern corresponds to the function G.\nOn output, it corresponds to the function H.\n\\n\n\\n\nif y_3 is a variable, the set with index t is\nthe sparsity pattern corresponding to y_3.\nThis identifies which of the dependent variables depeond on the variable y_3.\nOn input, this pattern corresponds to the function G.\nOn output, it corresponds to the function H.\n\\n\n\\b Output:\nThe set with index T is\nthe sparsity pattern corresponding to z.\nThis identifies which of the dependent variables depend on the variable z.\nOn input and output, this pattern corresponds to the function G.\n*/\ntemplate <class Vector_set>\ninline void cexp_rev_jac(\n    bool                dependency    ,\n    size_t              i_z           ,\n    const addr_t*       arg           ,\n    size_t              num_par       ,\n    Vector_set&         sparsity      )\n{   //\n    //\n    CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < static_cast<size_t> (CompareNe) );\n    CPPAD_ASSERT_UNKNOWN( NumArg(CExpOp) == 6 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(CExpOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( arg[1] != 0 );\n# ifndef NDEBUG\n    addr_t k = 1;\n    for( size_t j = 0; j < 4; j++)\n    {   if( ! ( arg[1] & k ) )\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[2+j]) < num_par );\n        k *= 2;\n    }\n# endif\n    if( dependency )\n    {   if( arg[1] & 1 )\n            sparsity.binary_union( size_t(arg[2]), size_t(arg[2]), i_z, sparsity);\n        if( arg[1] & 2 )\n            sparsity.binary_union( size_t(arg[3]), size_t(arg[3]), i_z, sparsity);\n    }\n    // --------------------------------------------------------------------\n    if( arg[1] & 4 )\n        sparsity.binary_union( size_t(arg[4]), size_t(arg[4]), i_z, sparsity);\n    if( arg[1] & 8 )\n        sparsity.binary_union( size_t(arg[5]), size_t(arg[5]), i_z, sparsity);\n    return;\n}\n\n/*!\nCompute reverse Hessian sparsity patterns for op = CExpOp.\n\nThis routine is given the sparsity patterns\nfor a function G(z, y, x, ... )\nand it uses them to compute the sparsity patterns for\n\\verbatim\n    H( y, x, w , u , ... ) = G[ z(x,y) , y , x , w , u , ... ]\n\\endverbatim\nwhere y represents the combination of y_0, y_1, y_2, and y_3.\n\n<!-- replace sparse_conditional_exp_op -->\nThe C++ source code corresponding to this operation is\n\\verbatim\n    z = CondExpRel(y_0, y_1, y_2, y_3)\n\\endverbatim\nwhere Rel is one of the following: Lt, Le, Eq, Ge, Gt.\n\n\\tparam Vector_set\nis the type used for vectors of sets. It can be either\nsparse::pack_setvec or sparse::list_setvec.\n\n\\param i_z\nis the AD variable index corresponding to the variable z.\n\n\\param arg\n\\n\n arg[0]\nis static cast to size_t from the enum type\n\\verbatim\n    enum CompareOp {\n        CompareLt,\n        CompareLe,\n        CompareEq,\n        CompareGe,\n        CompareGt,\n        CompareNe\n    }\n\\endverbatim\nfor this operation.\nNote that arg[0] cannot be equal to CompareNe.\n\\n\n\\n\n arg[1] & 1\n\\n\nIf this is zero, y_0 is a parameter. Otherwise it is a variable.\n\\n\n\\n\n arg[1] & 2\n\\n\nIf this is zero, y_1 is a parameter. Otherwise it is a variable.\n\\n\n\\n\n arg[1] & 4\n\\n\nIf this is zero, y_2 is a parameter. Otherwise it is a variable.\n\\n\n\\n\n arg[1] & 8\n\\n\nIf this is zero, y_3 is a parameter. Otherwise it is a variable.\n\\n\n\\n\n arg[2 + j ] for j = 0, 1, 2, 3\n\\n\nis the index corresponding to y_j.\n\n\\param num_par\nis the total number of values in the vector parameter.\n\n\\par Checked Assertions\n\\li NumArg(CExpOp) == 6\n\\li NumRes(CExpOp) == 1\n\\li arg[0] < static_cast<size_t> ( CompareNe )\n\\li arg[1] != 0; i.e., not all of y_0, y_1, y_2, y_3 are parameters.\n\\li For j = 0, 1, 2, 3 if y_j is a parameter, arg[2+j] < num_par.\n<!-- end sparse_conditional_exp_op -->\n\n\n\\param jac_reverse\n jac_reverse[i_z]\nis false (true) if the Jacobian of G with respect to z is always zero\n(may be non-zero).\n\\n\n\\n\n jac_reverse[ arg[4] ]\nIf y_2 is a variable,\n jac_reverse[ arg[4] ]\nis false (true) if the Jacobian with respect to y_2 is always zero\n(may be non-zero).\nOn input, it corresponds to the function G,\nand on output it corresponds to the function H.\n\\n\n\\n\n jac_reverse[ arg[5] ]\nIf y_3 is a variable,\n jac_reverse[ arg[5] ]\nis false (true) if the Jacobian with respect to y_3 is always zero\n(may be non-zero).\nOn input, it corresponds to the function G,\nand on output it corresponds to the function H.\n\n\\param hes_sparsity\nThe set with index i_z in hes_sparsity\nis the Hessian sparsity pattern for the function G\nwhere one of the partials is with respect to z.\n\\n\n\\n\nIf y_2 is a variable,\nthe set with index arg[4] in hes_sparsity\nis the Hessian sparsity pattern\nwhere one of the partials is with respect to y_2.\nOn input, this pattern corresponds to the function G.\nOn output, this pattern corresponds to the function H.\n\\n\n\\n\nIf y_3 is a variable,\nthe set with index arg[5] in hes_sparsity\nis the Hessian sparsity pattern\nwhere one of the partials is with respect to y_3.\nOn input, this pattern corresponds to the function G.\nOn output, this pattern corresponds to the function H.\n*/\ntemplate <class Vector_set>\ninline void cexp_rev_hes(\n    size_t               i_z           ,\n    const addr_t*        arg           ,\n    size_t               num_par       ,\n    bool*                jac_reverse   ,\n    Vector_set&          hes_sparsity  )\n{   //\n    //\n\n    CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < static_cast<size_t> (CompareNe) );\n    CPPAD_ASSERT_UNKNOWN( NumArg(CExpOp) == 6 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(CExpOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( arg[1] != 0 );\n# ifndef NDEBUG\n    addr_t k = 1;\n    for( size_t j = 0; j < 4; j++)\n    {   if( ! ( arg[1] & k ) )\n            CPPAD_ASSERT_UNKNOWN( size_t(arg[2+j]) < num_par );\n        k *= 2;\n    }\n# endif\n    if( arg[1] & 4 )\n    {\n        hes_sparsity.binary_union( size_t(arg[4]), size_t(arg[4]), i_z, hes_sparsity);\n        jac_reverse[ arg[4] ] |= jac_reverse[i_z];\n    }\n    if( arg[1] & 8 )\n    {\n        hes_sparsity.binary_union( size_t(arg[5]), size_t(arg[5]), i_z, hes_sparsity);\n        jac_reverse[ arg[5] ] |= jac_reverse[i_z];\n    }\n    return;\n}\n\n} } } // END namespace\n# endif\n"
  },
  {
    "path": "include/cppad/local/var_op/compare_op.hpp",
    "content": "# ifndef CPPAD_LOCAL_VAR_OP_COMPARE_OP_HPP\n# define CPPAD_LOCAL_VAR_OP_COMPARE_OP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ---------------------------------------------------------------------------\n/*\n{xrst_begin_parent var_compare_op dev}\n{xrst_spell\n    eqpp\n    eqpv\n    eqvv\n    lepp\n    lepv\n    levp\n    levv\n    ltpp\n    ltpv\n    ltvp\n    ltvv\n    nepp\n    nepv\n    nevv\n}\n\nComparison Operators\n####################\n\nUser Syntax\n***********\n*z* = *x* *op* *y*\n\nx\n*\nis the left operand for this comparison.\n\ny\n*\nis the right operand for this comparison.\n\nz\n*\nis he result for this operator which is a boolean\n(not a variable or parameter).\n\nop\n**\nis one of the following: ==, <=, <, != .\nThe >= and > comparisons are folded into <= and < by switching *x* and *y* .\n\nop_code\n*******\n\nEqppOp, LeppOp, LtppOp, NeppOp\n==============================\nThese operators implement ==. <=, <, and != for the case where\nboth *x* and *y* are parameters.\n\nEqpvOp, LepvOp, LtpvOp, NepvOp\n==============================\nThese operators implement ==. <=, <, and != for the case where\n*x* is a parameter and *y* is a variable.\n\nLevpOp, LtvpOp\n==============\nThese operators implement <= and < for the case where\n*x* is a variable and *y* is a parameter.\nThe == and != operators are folded into EqpvOp and NepvOp by\nswitching *x* and *y* .\n\nEqvvOp, LevvOp, LtvvOp, NevvOp\n==============================\nThese operators implement ==. <=, <, and != for the case where\nboth *x* and *y* are variables.\n\narg\n***\n\narg[0]\n======\nIf *x* is a variable (parameter)\n*arg* [0] is the variable index (parameter index) corresponding to *x* .\n\narg[1]\n======\nIf *y* is a variable (parameter)\n*arg* [1] is the variable index (parameter index) corresponding to *y* .\n\n{xrst_end var_compare_op}\n\n-------------------------------------------------------------------------------\n{xrst_begin var_compare_forward_any dev}\n\nForward Comparison Operators\n############################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_COMPARE_FORWARD_ANY\n    // END_COMPARE_FORWARD_ANY\n}\n\nRecBase\n*******\nis the base type use when recording this operator;\ni.e., this operation was recording using AD< *RecBase* > operations.\n\nBase\n****\nis the type used for computations by this operator.\nThis is either *RecBase* or AD< *RecBase* >.\ntype *Base* .\n\nop_code, arg\n************\nsee :ref:`var_compare_op@op_code`\n\nparameter\n*********\nmaps parameter indices to parameter values.\n\ncap_order\n*********\nis the maximum number of orders that will fit in *taylor* .\n\ntaylor\n******\nThe Taylor coefficient corresponding to\nvariable index *i* and order zero is\n\n    *taylor* [ *i* * *cap_order* ]\n\nthis_op_index\n*************\nIs the operator index for this compare operation.\n\nchange_count\n************\nis the change_number at which *this_op_index* is returned\nas *change_op_index*.\nIf it is zero, the comparison changes are not counted.\n\nchange_number\n*************\nIf *change_count* is zero, this value is not modified.\nOtherwise, if this operator comparison has changed (is no longer true),\n*change_number* is incremented by one.\n\nchange_op_index\n***************\nIf *change_count* is zero, this value is not modified.\nOtherwise, if this operator comparison has changed (is no longer true), and\nthe new value of *change_number* is equal to *change_count* ,\n*change_op_index* is set equal to *this_op_index* .\n\n{xrst_end var_compare_forward_any}\n*/\n\n# include <cppad/local/op_code_var.hpp>\n# include <cppad/core/cppad_assert.hpp>\n\nnamespace CppAD { namespace local { namespace var_op { // BEGIN namespace\n\n// BEGIN_COMPARE_FORWARD_ANY\ntemplate <class Base> void compare_forward_any(\n    op_code_var   op_code                 ,\n    const addr_t* arg                     ,\n    const Base*   parameter               ,\n    size_t        cap_order               ,\n    const Base*   taylor                  ,\n    size_t        this_op_index           ,\n    size_t        change_count            ,\n    size_t&       change_number           ,\n    size_t&       change_op_index         )\n// END_COMPARE_FORWARD_ANY\n{   //\n    // n_arg, n_res\n    CPPAD_ASSERT_NARG_NRES(op_code, 2, 0);\n    //\n    // special case\n    if( change_count == 0 )\n        return;\n    //\n    // x, y\n    Base x, y;\n    switch(op_code)\n    {   //\n        // pp\n        case EqppOp:\n        case LeppOp:\n        case LtppOp:\n        case NeppOp:\n        x = parameter[ arg[0] ];\n        y = parameter[ arg[1] ];\n        break;\n        //\n        // pv\n        case EqpvOp:\n        case LepvOp:\n        case LtpvOp:\n        case NepvOp:\n        x = parameter[ arg[0] ];\n        y = taylor[ size_t(arg[1]) * cap_order ];\n        break;\n\n        // vp\n        case LevpOp:\n        case LtvpOp:\n        x = taylor[ size_t(arg[0]) * cap_order ];\n        y = parameter[ arg[1] ];\n        break;\n        //\n        // vv\n        case EqvvOp:\n        case LevvOp:\n        case LtvvOp:\n        case NevvOp:\n        x = taylor[ size_t(arg[0]) * cap_order ];\n        y = taylor[ size_t(arg[1]) * cap_order ];\n        break;\n        //\n        default:\n        // assign x and y to avoid compiler warnings\n        CPPAD_ASSERT_UNKNOWN( false );\n        x = CppAD::numeric_limits<Base>::quiet_NaN();\n        y = CppAD::numeric_limits<Base>::quiet_NaN();\n    }\n    bool change;\n    switch(op_code)\n    {   //\n        case EqppOp:\n        case EqpvOp:\n        case EqvvOp:\n        change = x != y;\n        break;\n\n        case LeppOp:\n        case LepvOp:\n        case LevpOp:\n        case LevvOp:\n        change = GreaterThanZero(x - y);\n        break;\n\n        case LtppOp:\n        case LtpvOp:\n        case LtvpOp:\n        case LtvvOp:\n        change = GreaterThanOrZero(x - y);\n        break;\n\n        case NeppOp:\n        case NepvOp:\n        case NevvOp:\n        change = x == y;\n        break;\n\n        default:\n        // assign change to avoid compiler warning\n        CPPAD_ASSERT_UNKNOWN( false );\n        change = true;\n        break;\n    }\n    if( change )\n    {   ++change_number;\n        if( change_number == change_count         )\n            change_op_index = this_op_index;\n    }\n}\n}}} // END namespace\n# endif\n"
  },
  {
    "path": "include/cppad/local/var_op/cos_op.hpp",
    "content": "# ifndef CPPAD_LOCAL_VAR_OP_COS_OP_HPP\n# define CPPAD_LOCAL_VAR_OP_COS_OP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n\nnamespace CppAD { namespace local { namespace var_op {\n\n// See dev documentation: forward_unary_op\ntemplate <class Base>\ninline void cos_forward_any(\n    size_t        order_low   ,\n    size_t        order_up    ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // p, q\n    size_t p = order_low;\n    size_t q = order_up;\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(CosOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(CosOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n    CPPAD_ASSERT_UNKNOWN( p <= q );\n\n    // Taylor coefficients corresponding to argument and result\n    Base* x = taylor + i_x * cap_order;\n    Base* c = taylor + i_z * cap_order;\n    Base* s = c      -       cap_order;\n\n\n    // rest of this routine is identical for the following cases:\n    // forward_sin_op, forward_cos_op, forward_sinh_op, forward_cosh_op.\n    // (except that there is a sign difference for the hyperbolic case).\n    size_t k;\n    if( p == 0 )\n    {   s[0] = sin( x[0] );\n        c[0] = cos( x[0] );\n        p++;\n    }\n    for(size_t j = p; j <= q; j++)\n    {\n        s[j] = Base(0.0);\n        c[j] = Base(0.0);\n        for(k = 1; k <= j; k++)\n        {   s[j] += Base(double(k)) * x[k] * c[j-k];\n            c[j] -= Base(double(k)) * x[k] * s[j-k];\n        }\n        s[j] /= Base(double(j));\n        c[j] /= Base(double(j));\n    }\n}\n// See dev documentation: forward_unary_op\ntemplate <class Base>\ninline void cos_forward_dir(\n    size_t        order_up    ,\n    size_t        n_dir       ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // q, r\n    size_t q = order_up;\n    size_t r = n_dir;\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(CosOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(CosOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( 0 < q );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n\n    // Taylor coefficients corresponding to argument and result\n    size_t num_taylor_per_var = (cap_order-1) * r + 1;\n    Base* x = taylor + i_x * num_taylor_per_var;\n    Base* c = taylor + i_z * num_taylor_per_var;\n    Base* s = c      -       num_taylor_per_var;\n\n\n    // rest of this routine is identical for the following cases:\n    // forward_sin_op, forward_cos_op, forward_sinh_op, forward_cosh_op\n    // (except that there is a sign difference for the hyperbolic case).\n    size_t m = (q-1) * r + 1;\n    for(size_t ell = 0; ell < r; ell++)\n    {   s[m+ell] =   Base(double(q)) * x[m + ell] * c[0];\n        c[m+ell] = - Base(double(q)) * x[m + ell] * s[0];\n        for(size_t k = 1; k < q; k++)\n        {   s[m+ell] += Base(double(k)) * x[(k-1)*r+1+ell] * c[(q-k-1)*r+1+ell];\n            c[m+ell] -= Base(double(k)) * x[(k-1)*r+1+ell] * s[(q-k-1)*r+1+ell];\n        }\n        s[m+ell] /= Base(double(q));\n        c[m+ell] /= Base(double(q));\n    }\n}\n\n// See dev documentation: forward_unary_op\ntemplate <class Base>\ninline void cos_forward_0(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{   //\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(CosOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(CosOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( 0 < cap_order );\n\n    // Taylor coefficients corresponding to argument and result\n    Base* x = taylor + i_x * cap_order;\n    Base* c = taylor + i_z * cap_order;  // called z in documentation\n    Base* s = c      -       cap_order;  // called y in documentation\n\n    c[0] = cos( x[0] );\n    s[0] = sin( x[0] );\n}\n\n// See dev documentation: reverse_unary_op\ntemplate <class Base>\ninline void cos_reverse(\n    size_t        i_z          ,\n    const addr_t* arg          ,\n    size_t        cap_order    ,\n    const Base*   taylor       ,\n    size_t        n_order      ,\n    Base*         partial      )\n{   // d  //\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    size_t d = n_order - 1;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(CosOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(CosOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( n_order <= cap_order );\n\n    // Taylor coefficients and partials corresponding to argument\n    const Base* x  = taylor  + i_x * cap_order;\n    Base* px       = partial + i_x * n_order;\n\n    // Taylor coefficients and partials corresponding to first result\n    const Base* c  = taylor  + i_z * cap_order; // called z in doc\n    Base* pc       = partial + i_z * n_order;\n\n    // Taylor coefficients and partials corresponding to auxiliary result\n    const Base* s  = c  - cap_order; // called y in documentation\n    Base* ps       = pc - n_order;\n\n\n    // rest of this routine is identical for the following cases:\n    // reverse_sin_op, reverse_cos_op, reverse_sinh_op, reverse_cosh_op.\n    size_t j = d;\n    size_t k;\n    while(j)\n    {\n        ps[j]   /= Base(double(j));\n        pc[j]   /= Base(double(j));\n        for(k = 1; k <= j; k++)\n        {\n            px[k]   += Base(double(k)) * azmul(ps[j], c[j-k]);\n            px[k]   -= Base(double(k)) * azmul(pc[j], s[j-k]);\n\n            ps[j-k] -= Base(double(k)) * azmul(pc[j], x[k]);\n            pc[j-k] += Base(double(k)) * azmul(ps[j], x[k]);\n\n        }\n        --j;\n    }\n    px[0] += azmul(ps[0], c[0]);\n    px[0] -= azmul(pc[0], s[0]);\n}\n\n} } } // END namespace\n# endif\n"
  },
  {
    "path": "include/cppad/local/var_op/cosh_op.hpp",
    "content": "# ifndef CPPAD_LOCAL_VAR_OP_COSH_OP_HPP\n# define CPPAD_LOCAL_VAR_OP_COSH_OP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n\nnamespace CppAD { namespace local { namespace var_op {\n\n\n// See dev documentation: forward_unary_op\ntemplate <class Base>\ninline void cosh_forward_any(\n    size_t        order_low   ,\n    size_t        order_up    ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // p, q\n    size_t p = order_low;\n    size_t q = order_up;\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(CoshOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(CoshOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n    CPPAD_ASSERT_UNKNOWN( p <= q );\n\n    // Taylor coefficients corresponding to argument and result\n    Base* x = taylor + i_x * cap_order;\n    Base* c = taylor + i_z * cap_order;\n    Base* s = c      -       cap_order;\n\n    // rest of this routine is identical for the following cases:\n    // forward_sin_op, forward_cos_op, forward_sinh_op, forward_cosh_op.\n    // (except that there is a sign difference for hyperbolic case).\n    size_t k;\n    if( p == 0 )\n    {   s[0] = sinh( x[0] );\n        c[0] = cosh( x[0] );\n        p++;\n    }\n    for(size_t j = p; j <= q; j++)\n    {\n        s[j] = Base(0.0);\n        c[j] = Base(0.0);\n        for(k = 1; k <= j; k++)\n        {   s[j] += Base(double(k)) * x[k] * c[j-k];\n            c[j] += Base(double(k)) * x[k] * s[j-k];\n        }\n        s[j] /= Base(double(j));\n        c[j] /= Base(double(j));\n    }\n}\n// See dev documentation: forward_unary_op\ntemplate <class Base>\ninline void cosh_forward_dir(\n    size_t        order_up    ,\n    size_t        n_dir       ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // q, r\n    size_t q = order_up;\n    size_t r = n_dir;\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(CoshOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(CoshOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( 0 < q );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n\n    // Taylor coefficients corresponding to argument and result\n    size_t num_taylor_per_var = (cap_order-1) * r + 1;\n    Base* x = taylor + i_x * num_taylor_per_var;\n    Base* s = taylor + i_z * num_taylor_per_var;\n    Base* c = s      -       num_taylor_per_var;\n\n\n    // rest of this routine is identical for the following cases:\n    // forward_sin_op, forward_cos_op, forward_sinh_op, forward_cosh_op\n    // (except that there is a sign difference for the hyperbolic case).\n    size_t m = (q-1) * r + 1;\n    for(size_t ell = 0; ell < r; ell++)\n    {   s[m+ell] = Base(double(q)) * x[m + ell] * c[0];\n        c[m+ell] = Base(double(q)) * x[m + ell] * s[0];\n        for(size_t k = 1; k < q; k++)\n        {   s[m+ell] += Base(double(k)) * x[(k-1)*r+1+ell] * c[(q-k-1)*r+1+ell];\n            c[m+ell] += Base(double(k)) * x[(k-1)*r+1+ell] * s[(q-k-1)*r+1+ell];\n        }\n        s[m+ell] /= Base(double(q));\n        c[m+ell] /= Base(double(q));\n    }\n}\n\n// See dev documentation: forward_unary_op\ntemplate <class Base>\ninline void cosh_forward_0(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{   //\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(CoshOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(CoshOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( 0 < cap_order );\n\n    // Taylor coefficients corresponding to argument and result\n    Base* x = taylor + i_x * cap_order;\n    Base* c = taylor + i_z * cap_order;  // called z in documentation\n    Base* s = c      -       cap_order;  // called y in documentation\n\n    c[0] = cosh( x[0] );\n    s[0] = sinh( x[0] );\n}\n\n// See dev documentation: reverse_unary_op\ntemplate <class Base>\ninline void cosh_reverse(\n    size_t        i_z          ,\n    const addr_t* arg          ,\n    size_t        cap_order    ,\n    const Base*   taylor       ,\n    size_t        n_order      ,\n    Base*         partial      )\n{   // d  //\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    size_t d = n_order - 1;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(CoshOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(CoshOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( n_order <= cap_order );\n\n    // Taylor coefficients and partials corresponding to argument\n    const Base* x  = taylor  + i_x * cap_order;\n    Base* px       = partial + i_x * n_order;\n\n    // Taylor coefficients and partials corresponding to first result\n    const Base* c  = taylor  + i_z * cap_order; // called z in doc\n    Base* pc       = partial + i_z * n_order;\n\n    // Taylor coefficients and partials corresponding to auxiliary result\n    const Base* s  = c  - cap_order; // called y in documentation\n    Base* ps       = pc - n_order;\n\n\n    // rest of this routine is identical for the following cases:\n    // reverse_sin_op, reverse_cos_op, reverse_sinh_op, reverse_cosh_op.\n    size_t j = d;\n    size_t k;\n    while(j)\n    {\n        ps[j]   /= Base(double(j));\n        pc[j]   /= Base(double(j));\n        for(k = 1; k <= j; k++)\n        {\n            px[k]   += Base(double(k)) * azmul(ps[j], c[j-k]);\n            px[k]   += Base(double(k)) * azmul(pc[j], s[j-k]);\n\n            ps[j-k] += Base(double(k)) * azmul(pc[j], x[k]);\n            pc[j-k] += Base(double(k)) * azmul(ps[j], x[k]);\n\n        }\n        --j;\n    }\n    px[0] += azmul(ps[0], c[0]);\n    px[0] += azmul(pc[0], s[0]);\n}\n\n} } } // END namespace\n# endif\n"
  },
  {
    "path": "include/cppad/local/var_op/cskip_op.hpp",
    "content": "# ifndef CPPAD_LOCAL_VAR_OP_CSKIP_OP_HPP\n# define CPPAD_LOCAL_VAR_OP_CSKIP_OP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\nnamespace CppAD { namespace local { namespace var_op {\n/*!\n{xrst_begin_parent var_cskip_op dev}\n\nThe Conditional Skip Operator\n#############################\n\nCSkipOp\n*******\nis the op code for this operator.\n\nUser Syntax\n***********\n| *z* = ``CondExp`` *Rel* ( *left* , *right* , *if_true* , *if_false* )\n\nRel\n***\nis Lt, Le, Eq, Ge, or Gt .\n\narg\n***\n\narg[0]\n======\nIs the comparison operator for this conditional skip\nas a static cast from CompareOp to addr_t :\n{xrst_literal\n    include/cppad/local/declare_ad.hpp\n    // BEGIN_COMPARE_OP\n    // END_COMPARE_OP\n}\nNote that arg[0] cannot be equal to CompareNe; i.e.\nthe last enum value CompareNe will not appear.\n\narg[1]\n======\nThe first two bits of this value are used as flags; see below.\n\narg[2]\n======\nIf arg[1] & 1 is zero (is one) ,\narg[2] is the parameter (variable) index corresponding to *left* .\n\narg[3]\n======\nIf arg[1] & 2 is zero (is one) ,\narg[3] is the parameter (variable) index corresponding to *right* .\n\narg[4]\n======\nis the number of operations to skip if the comparison result is true\nand the left and right operands are\n:ref:`base_identical@Identical@IdenticalCon` .\n\narg[5]\n======\nis the number of operations to skip if the comparison result is false\nand the left and right operands are identically constant.\n\narg[6+i]\n========\nFor i = 0 , ... , arg[4] - 1,\narg[6 + i] is the index of an operation to skip if the comparison\nis identically true.\n\narg[6+arg[4]+i]\n===============\nFor i = 0 , ... , arg[5] - 1,\narg[6 + i] is the index of an operation to skip if the comparison\nis identically false.\n\narg[6+arg[4]+arg[5]]\n====================\nThis is equal to 6 + arg[4] + arg[5] + 1,\nwhich is the total number or arguments to this operator.\nHaving this value at the end enables reverse mode to know how far\nto back up to get to the start of this operation.\n\n{xrst_end var_cskip_op}\n------------------------------------------------------------------------------\n{xrst_begin var_cskip_forward_0 dev}\n\nZero Order Forward Conditional Skip Operator\n############################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_CSKIP_FORWARD_0\n    // END_CSKIP_FORWARD_0\n}\n\nRecBase\n*******\nis the base type use when recording this operator;\ni.e., this operation was recording using AD< *RecBase* > operations.\n\nBase\n****\nis the type used for computations by this operator.\nThis is either *RecBase* or AD< *RecBase* >.\n\ni_z\n***\nvariable index corresponding to the result of the previous operation.\nThis is only used for error checking. To be specific,\nif the left and right operand for the conditional expression is a variable,\nits index must be less than or equal this value.\n\nnum_par\n*******\nis the total number of values in the *parameter* vector.\n\nparameter\n*********\nmaps parameter indices to parameter values.\n\ncap_order\n*********\nis the maximum number of orders that can fit in *taylor* .\n\ntaylor\n******\nFor *j* <= *i_z* ,\nthe Taylor coefficient corresponding to variable *j* and order zero is\n\n    *taylor* [ *j* * *cap_order* + 0  ]\n\ncskip_op\n********\nis vector specifying which operations are at this point are know to be\nunnecessary and can be skipped. This is both an input and an output; i.e.,\nthe call may add more true values to *cskip_op* .\n\n{xrst_end var_cskip_forward_0}\n*/\n// BEGIN_CSKIP_FORWARD_0\ntemplate <class Base>\ninline void cskip_forward_0(\n    size_t               i_z            ,\n    const addr_t*        arg            ,\n    size_t               num_par        ,\n    const Base*          parameter      ,\n    size_t               cap_order      ,\n    Base*                taylor         ,\n    bool*                cskip_op       )\n// END_CSKIP_FORWARD_0\n{   //\n    //\n    CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < size_t(CompareNe) );\n    CPPAD_ASSERT_UNKNOWN( arg[1] != 0 );\n    //\n    Base left, right;\n    if( arg[1] & 1 )\n    {   // If variable arg[2] <= i_z, it has already been computed,\n        // but it will be skipped for higher orders.\n        CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) <= i_z );\n        left = taylor[ size_t(arg[2]) * cap_order + 0 ];\n    }\n    else\n    {   CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) < num_par );\n        left = parameter[ arg[2] ];\n    }\n    if( arg[1] & 2 )\n    {   // If variable arg[3] <= i_z, it has already been computed,\n        // but it will be skipped for higher orders.\n        CPPAD_ASSERT_UNKNOWN( size_t(arg[3]) <= i_z );\n        right = taylor[ size_t(arg[3]) * cap_order + 0 ];\n    }\n    else\n    {   CPPAD_ASSERT_UNKNOWN( size_t(arg[3]) < num_par );\n        right = parameter[ arg[3] ];\n    }\n    bool ok_to_skip = IdenticalCon(left) && IdenticalCon(right);\n    if( ! ok_to_skip )\n        return;\n\n    // initialize to avoid compiler warning\n    bool true_case = false;\n    Base diff      = left - right;\n    switch( CompareOp( arg[0] ) )\n    {\n        case CompareLt:\n        true_case = LessThanZero(diff);\n        break;\n\n        case CompareLe:\n        true_case = LessThanOrZero(diff);\n        break;\n\n        case CompareEq:\n        true_case = IdenticalZero(diff);\n        break;\n\n        case CompareGe:\n        true_case = GreaterThanOrZero(diff);\n        break;\n\n        case CompareGt:\n        true_case = GreaterThanZero(diff);\n        break;\n\n        case CompareNe:\n        true_case = ! IdenticalZero(diff);\n        break;\n\n        default:\n        CPPAD_ASSERT_UNKNOWN(false);\n    }\n    if( true_case )\n    {   for(addr_t i = 0; i < arg[4]; i++)\n            cskip_op[ arg[6+i] ] = true;\n    }\n    else\n    {   for(addr_t i = 0; i < arg[5]; i++)\n            cskip_op[ arg[6+arg[4]+i] ] = true;\n    }\n    return;\n}\n} } } // END namespace\n# endif\n"
  },
  {
    "path": "include/cppad/local/var_op/csum_op.hpp",
    "content": "# ifndef CPPAD_LOCAL_VAR_OP_CSUM_OP_HPP\n# define CPPAD_LOCAL_VAR_OP_CSUM_OP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\nnamespace CppAD { namespace local { namespace var_op {\n/*\n{xrst_begin_parent var_csum_op dev}\n\nVariable Cumulative Summation Operator\n######################################\n\nCSumOp\n******\nis the op code for this operator.\n\nUser Syntax\n***********\n::\n\n    z = s\n         + x[0] + ... + x[ n1 - 1 ]\n         - y[0] - ... - y[ n2 - 1 ]\n         + u[0] + ... + u[ n3 - 1 ]\n         - v[0] - ... - v[ n4 - 1 ]\n\ns\n*\nis the constant parameter that initializes the summation.\n\nx\n*\nis the vector of addition variables that appear in the sum.\n\ny\n*\nis the vector of subtraction variables that appear in the sum.\n\nu\n*\nis the vector of addition dynamic parameters that appear in the sum.\n\nv\n*\nis the vector of subtraction dynamic parameters that appear in the sum.\n\nz\n*\nis the result of the summation.\n\nRecBase\n*******\nis the base type use when recording this operator;\ni.e., this operation was recording using AD< *RecBase* > operations.\n\nBase\n****\nis the type used for computations by this operator.\nThis is either *RecBase* or AD< *RecBase* >.\n\ni_z\n***\nis the variable index corresponding to the result for this operation;\ni.e. the row index in taylor corresponding to *z* .\n\narg\n***\n\narg[0]\n======\nis the index of the constant parameter *s* in the parameter vector.\n\narg[1]\n======\nis the index in arg of the end of the addition variables; i.e.,\n*n1* = arg[1] - 5 .\n\narg[2]\n======\nis the index in arg of the end of the subtraction variables; i.e.,\n*n2* = arg[2] - arg[1] .\n\narg[3]\n======\nis the index in arg of the end of the addition dynamic parameters; i.e.,\n*n3* = arg[3] - arg[2] .\n\narg[4]\n======\nis the index in arg of the end of the subtraction dynamic parameters; i.e.,\n*n4* = arg[4] - arg[3] .\n\narg[5+j]\n========\nfor j = 0 , ... , n1 - 1, arg[5 + j]\nis the index corresponding to the variable x[j] .\n\narg[ arg[1]+j ]\n===============\nfor j = 0 , ... , n2 - 1, arg[ arg[1] + j ]\nis the index corresponding to the variable y[j] .\n\narg[ arg[2]+j ]\n===============\nfor j = 0 , ... , n3 - 1, arg[ arg[2] + j ]\nis the index corresponding to the dynamic parameter u[j] .\n\narg[ arg[3]+j ]\n===============\nfor j = 0 , ... , n4 - 1, arg[ arg[3] + j ]\nis the index corresponding to the dynamic parameter v[j] .\n\narg[ arg[4] ]\n=============\nThis is equal to arg[4] + 1\nwhich is the total number or arguments to this operator.\nHaving this value at the end enables reverse mode to know how far\nto back up to get to the start of this operation.\n\n{xrst_end var_csum_op}\n-----------------------------------------------------------------------------\n{xrst_begin var_csum_forward_any dev}\n\nAny Order Forward Cumulative Summation Operation\n################################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_CSUM_FORWARD_ANY\n    // END_CSUM_FORWARD_ANY\n}\n\nx, y, u, v, z\n*************\nsee\n:ref:`var_csum_op@x` ,\n:ref:`var_csum_op@y` ,\n:ref:`var_csum_op@u` ,\n:ref:`var_csum_op@v` ,\n:ref:`var_csum_op@z`\n\ni_z, arg\n********\nsee\n:ref:`var_csum_op@i_z` ,\n:ref:`var_csum_op@arg`\n\n{xrst_template ;\n    include/cppad/local/var_op/template/forward_op.xrst\n    headers: cap_order, order_low, order_up, taylor\n}\n\nnum_par\n*******\nis the number of parameters in parameter.\n\nparameter\n*********\nis the parameter vector for this operation sequence.\n\n{xrst_end var_csum_forward_any}\n*/\n// BEGIN_CSUM_FORWARD_ANY\ntemplate <class Base>\ninline void csum_forward_any(\n    size_t        order_low   ,\n    size_t        order_up    ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        num_par     ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n// END_CSUM_FORWARD_ANY\n{  //\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumRes(CSumOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( order_up < cap_order );\n    CPPAD_ASSERT_UNKNOWN( order_low <= order_up );\n    CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );\n    CPPAD_ASSERT_UNKNOWN( arg[arg[4]] == arg[4] + 1 );\n    //\n    // zero\n    Base zero(0);\n    //\n    // z\n    Base* z = taylor + i_z    * cap_order;\n    for(size_t k = order_low; k <= order_up; k++)\n        z[k] = zero;\n    //\n    if( order_low == 0 )\n    {  // constant parameter\n        z[order_low] = parameter[ arg[0] ];\n        // addition dynamic parameters\n        for(addr_t i = arg[2]; i < arg[3]; ++i)\n            z[order_low] += parameter[ arg[i] ];\n        // subtraction dynamic parameters\n        for(addr_t i = arg[3]; i < arg[4]; ++i)\n            z[order_low] -= parameter[ arg[i] ];\n    }\n    // addition variables\n    for(addr_t i = 5; i < arg[1]; ++i)\n    {  CPPAD_ASSERT_UNKNOWN( size_t(arg[i]) < i_z );\n        Base* x = taylor + size_t(arg[i]) * cap_order;\n        for(size_t k = order_low; k <= order_up; k++)\n            z[k] += x[k];\n    }\n    // subtraction variables\n    for(addr_t i = arg[1]; i < arg[2]; ++i)\n    {  CPPAD_ASSERT_UNKNOWN( size_t(arg[i]) < i_z );\n        Base* x = taylor + size_t(arg[i]) * cap_order;\n        for(size_t k = order_low; k <= order_up; k++)\n            z[k] -= x[k];\n    }\n}\n/*\n{xrst_begin var_csum_forward_dir dev}\n\nMultiple Direction Forward Mode Cumulative Summation Operation\n##############################################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_CSUM_FORWARD_DIR\n    // END_CSUM_FORWARD_DIR\n}\n\nx, y, u, v, z\n*************\nsee\n:ref:`var_csum_op@x` ,\n:ref:`var_csum_op@y` ,\n:ref:`var_csum_op@u` ,\n:ref:`var_csum_op@v` ,\n:ref:`var_csum_op@z`\n\ni_z, arg\n********\nsee\n:ref:`var_csum_op@i_z` ,\n:ref:`var_csum_op@arg`\n\nnum_par\n*******\nis the number of parameters in parameter.\n\nparameter\n*********\nis the parameter vector for this operation sequence.\n\n{xrst_template ;\n    include/cppad/local/var_op/template/forward_dir.xrst\n    headers: n_dir, cap_order, order_up, taylor\n}\n\n{xrst_end var_csum_forward_dir}\n*/\n// BEGIN_CSUM_FORWARD_DIR\ntemplate <class Base>\ninline void csum_forward_dir(\n    size_t        order_up    ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        num_par     ,\n    const Base*   parameter   ,\n    size_t        n_dir       ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n// END_CSUM_FORWARD_DIR\n{  //\n    //\n    CPPAD_ASSERT_UNKNOWN( NumRes(CSumOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( order_up < cap_order );\n    CPPAD_ASSERT_UNKNOWN( 0 < order_up );\n    CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );\n    CPPAD_ASSERT_UNKNOWN( arg[arg[4]] == arg[4] + 1 );\n    //\n    // zero\n    Base zero(0);\n    //\n    // per_variable\n    size_t per_variable = (cap_order-1) * n_dir + 1;\n    //\n    // m\n    size_t m = (order_up - 1) * n_dir + 1;\n    //\n    // z\n    Base* z = taylor + i_z * per_variable + m;\n    for(size_t ell = 0; ell < n_dir; ell++)\n        z[ell] = zero;\n    //\n    // addition variables\n    for(addr_t i = 5; i < arg[1]; ++i)\n    {  CPPAD_ASSERT_UNKNOWN( size_t(arg[i]) < i_z );\n        Base* x = taylor + size_t(arg[i]) * per_variable + m;\n        for(size_t ell = 0; ell < n_dir; ell++)\n            z[ell] += x[ell];\n    }\n    //\n    // subtraction variables\n    for(addr_t i = arg[1]; i < arg[2]; ++i)\n    {  CPPAD_ASSERT_UNKNOWN( size_t(arg[i]) < i_z );\n        Base* x = taylor + size_t(arg[i]) * per_variable + m;\n        for(size_t ell = 0; ell < n_dir; ell++)\n            z[ell] -= x[ell];\n    }\n}\n/*\n---------------------------------------------------------------------------\n{xrst_begin var_csum_reverse dev}\n\nReverse Mode Cumulative Summation Operation\n###########################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_CSUM_REVERSE\n    // END_CSUM_REVERSE\n}\n\nx, y, u, v, z\n*************\nsee\n:ref:`var_csum_op@x` ,\n:ref:`var_csum_op@y` ,\n:ref:`var_csum_op@u` ,\n:ref:`var_csum_op@v` ,\n:ref:`var_csum_op@z`\n\ni_z, arg\n********\nsee\n:ref:`var_csum_op@i_z` ,\n:ref:`var_csum_op@arg`\n\n{xrst_template ;\n    include/cppad/local/var_op/template/reverse_op.xrst\n    headers: n_order, partial\n\n    @x, y@  ; x, y, u, v\n}\n\n{xrst_end var_csum_reverse}\n*/\n// BEGIN_CSUM_REVERSE\ntemplate <class Base>\ninline void csum_reverse(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        n_order     ,\n    Base*         partial     )\n// END_CSUM_REVERSE\n{  // d\n    //\n    size_t d = n_order - 1;\n    //\n    //\n    CPPAD_ASSERT_UNKNOWN( NumRes(CSumOp) == 1 );\n    //\n    // pz, dp1\n    Base* pz = partial + i_z * n_order;\n    size_t dp1 = d + 1;\n    //\n    // addition variables\n    for(addr_t i = 5; i < arg[1]; ++i)\n    {  CPPAD_ASSERT_UNKNOWN( size_t(arg[i]) < i_z );\n        Base* px = partial + size_t(arg[i]) * n_order;\n        size_t k = dp1;\n        while(k--)\n            px[k] += pz[k];\n    }\n    //\n    // subtraction variables\n    for(addr_t i = arg[1]; i < arg[2]; ++i)\n    {  CPPAD_ASSERT_UNKNOWN( size_t(arg[i]) < i_z );\n        Base* px = partial + size_t(arg[i]) * n_order;\n        size_t k = dp1;\n        while(k--)\n            px[k] -= pz[k];\n    }\n}\n/*\n------------------------------------------------------------------------------\n{xrst_begin var_csum_for_jac dev}\n\nForward Jacobian Sparsity for Cumulative Summation\n##################################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_CSUM_FOR_JAC\n    // END_CSUM_FOR_JAC\n}\n\nx, y, u, v, z\n*************\nsee\n:ref:`var_csum_op@x` ,\n:ref:`var_csum_op@y` ,\n:ref:`var_csum_op@u` ,\n:ref:`var_csum_op@v` ,\n:ref:`var_csum_op@z`\n\ni_z, arg\n********\nsee\n:ref:`var_csum_op@i_z` ,\n:ref:`var_csum_op@arg`\n\nVector_set\n**********\nis the type used for vectors of sets.\nIt must satisfy the :ref:`SetVector-name` concept.\n\ni_z\n\nsparsity\n********\n\nInput\n=====\nFor k = 0 , ... , i_z - 1,\nthe set with index k in *sparsity*\nidentifies which independent variables the variable with index k depends on.\n\nOutput\n======\nThe set with index i_z in *sparsity*\nidentifies which independent variables the variable *z* depends on.\n\n{xrst_end var_csum_for_jac}\n*/\n// BEGIN_CSUM_FOR_JAC\ntemplate <class Vector_set>\ninline void csum_for_jac(\n    size_t           i_z         ,\n    const addr_t*    arg         ,\n    Vector_set&      sparsity    )\n// END_CSUM_FOR_JAC\n{  //\n    //\n    // sparsity\n    sparsity.clear(i_z);\n    //\n    // addition and subtraction variables\n    for(addr_t i = 5; i < arg[2]; ++i)\n    {  CPPAD_ASSERT_UNKNOWN( size_t(arg[i]) < i_z );\n        sparsity.binary_union(\n            i_z            , // index in sparsity for result\n            i_z            , // index in sparsity for left operand\n            size_t(arg[i]) , // index for right operand\n            sparsity         // sparsity vector for right operand\n        );\n    }\n}\n/*\n------------------------------------------------------------------------------\n{xrst_begin var_csum_rev_jac dev}\n\nReverse Jacobian Sparsity for Cumulative Summation\n##################################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_CSUM_REV_JAC\n    // END_CSUM_REV_JAC\n}\n\nx, y, u, v, z\n*************\nsee\n:ref:`var_csum_op@x` ,\n:ref:`var_csum_op@y` ,\n:ref:`var_csum_op@u` ,\n:ref:`var_csum_op@v` ,\n:ref:`var_csum_op@z`\n\ni_z, arg\n********\nsee\n:ref:`var_csum_op@i_z` ,\n:ref:`var_csum_op@arg`\n\nVector_set\n**********\nis the type used for vectors of sets.\nIt must satisfy the :ref:`SetVector-name` concept.\n\n\nsparsity\n********\nThe set with index *i_z* is the sparsity pattern for *z* .\nThis sparsity pattern is added th the sparsity pattern for the\nvariables in the vectors *x* and *y* .\n\n{xrst_end var_csum_rev_jac}\n*/\n// BEGIN_CSUM_REV_JAC\ntemplate <class Vector_set>\ninline void csum_rev_jac(\n    size_t           i_z         ,\n    const addr_t*    arg         ,\n    Vector_set&      sparsity    )\n// END_CSUM_REV_JAC\n{  //\n    //\n    // addition and subtraction variables\n    for(addr_t i = 5; i < arg[2]; ++i)\n    {\n        CPPAD_ASSERT_UNKNOWN( size_t(arg[i]) < i_z );\n        sparsity.binary_union(\n            size_t(arg[i]), // index in sparsity for result\n            size_t(arg[i]), // index in sparsity for left operand\n            i_z        , // index for right operand\n            sparsity     // sparsity vector for right operand\n        );\n    }\n}\n/*\n{xrst_begin var_csum_rev_hes dev}\n\nReverse Hessian Sparsity for Cumulative Summation\n#################################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_CSUM_REV_HES\n    // END_CSUM_REV_HES\n}\n\nx, y, u, v, z\n*************\nsee\n:ref:`var_csum_op@x` ,\n:ref:`var_csum_op@y` ,\n:ref:`var_csum_op@u` ,\n:ref:`var_csum_op@v` ,\n:ref:`var_csum_op@z`\n\ni_z, arg\n********\nsee\n:ref:`var_csum_op@i_z` ,\n:ref:`var_csum_op@arg`\n\nG, H\n****\nWe use *G* to denote the scalar function we are computing the\nsparsity pattern for as a function of the variables up to and including *z* .\nWe use *H* for the function with *z* replaced by its operator; i.e.::\n\n    H(x, y, u, v, ...) = G[ z(x, y, u, v) , x, y, u, v, ... ]\n\nVector_set\n**********\nis the type used for vectors of sets.\nIt must satisfy the :ref:`SetVector-name` concept.\n\nrev_jacobian\n************\n#. If rev_jacobian[i_z] is true (false),\n   *G* may depend (does not depend) on *z* .\n\n#. If *j* is the index of an addition variable in the vector *x* or *y* ,\n   and *G* may depend on *z* ,\n   rev_jacobian[j] is set to true.\n\nrev_hes_sparsity\n****************\nOn input, *rev_hes_sparsity*\ncontains the Hessian sparsity pattern for the function *G* .\nOn output, it contains the Hessian sparsity pattern for the function *H* .\n\n{xrst_end var_csum_rev_hes}\n*/\n// BEGIN_CSUM_REV_HES\ntemplate <class Vector_set>\ninline void csum_rev_hes(\n    size_t           i_z                 ,\n    const addr_t*    arg                 ,\n    bool*            rev_jacobian        ,\n    Vector_set&      rev_hes_sparsity    )\n// END_CSUM_REV_HES\n{  //\n    //\n    // addition and subtraction variables\n    for(addr_t i = 5; i < arg[2]; ++i)\n    {\n        CPPAD_ASSERT_UNKNOWN( size_t(arg[i]) < i_z );\n        rev_hes_sparsity.binary_union(\n            size_t(arg[i])     , // index in sparsity for result\n            size_t(arg[i])     , // index in sparsity for left operand\n            i_z                , // index for right operand\n            rev_hes_sparsity     // sparsity vector for right operand\n        );\n        rev_jacobian[arg[i]] |= rev_jacobian[i_z];\n    }\n}\n/*\n------------------------------------------------------------------------------\n{xrst_begin var_csum_for_hes dev}\n\nForward Hessian Sparsity for Cumulative Summation\n#################################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_CSUM_FOR_HES\n    // END_CSUM_FOR_HES\n}\n\nx, y, u, v, z\n*************\nsee\n:ref:`var_csum_op@x` ,\n:ref:`var_csum_op@y` ,\n:ref:`var_csum_op@u` ,\n:ref:`var_csum_op@v` ,\n:ref:`var_csum_op@z`\n\ni_z, arg\n********\nsee\n:ref:`var_csum_op@i_z` ,\n:ref:`var_csum_op@arg`\n\nVector_set\n**********\nis the type used for vectors of sets.\nIt must satisfy the :ref:`SetVector-name` concept.\n\nn\n*\nis the number of independent variables on the tape.\n\nfor_hes_sparse\n**************\nsee :ref:`local_sweep_for_hes@for_hes_sparse` .\n\n{xrst_end var_csum_for_hes}\n*/\n// BEGIN_CSUM_FOR_HES\ntemplate <class Vector_set>\ninline void csum_for_hes(\n    const addr_t*             arg            ,\n    size_t                    i_z            ,\n    size_t                    n              ,\n    Vector_set&               for_hes_sparse )\n// END_CSUM_FOR_HES\n{   //\n    //\n    // np1\n    size_t np1 = n + 1;\n    //\n    // for_hes_sparse\n    for_hes_sparse.clear(np1 + i_z);\n    //\n    // addition and subtraction variables\n    for(addr_t i = 5; i < arg[2]; ++i)\n    {   CPPAD_ASSERT_UNKNOWN( size_t(arg[i]) < i_z );\n        //\n        // linear functions only modify forward Jacobian sparsity\n        for_hes_sparse.binary_union(\n            np1 + i_z            , // index in sparsity for result\n            np1 + i_z            , // index in sparsity for left operand\n            np1 + size_t(arg[i]) , // index for right operand\n            for_hes_sparse         // sparsity vector for right operand\n        );\n    }\n}\n\n} } } // END namespace\n# endif\n"
  },
  {
    "path": "include/cppad/local/var_op/dis_op.hpp",
    "content": "# ifndef CPPAD_LOCAL_VAR_OP_DIS_OP_HPP\n# define CPPAD_LOCAL_VAR_OP_DIS_OP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin_parent var_dis_op dev}\n\nVariable Discrete Operator\n##########################\n\nDisOp\n*****\nis the op code for this operator.\n\nUser Syntax\n***********\n| *z* = *name* ( *x* )\n\nname\n****\nis the :ref:`Discrete@name` of he discrete function.\n\nx\n*\nis the argument for this discrete function.\n\nz\n*\nis the new variable created by this function evaluation.\n(Note that this is called :ref:`Discrete@y` is the user documentation\nfor discrete functions.)\n\narg\n***\n\narg[0]\n======\nis the index that identifies this discrete function.\n\narg[1]\n======\nvariable index corresponding to the argument for this function call.\n\n\n{xrst_end var_dis_op}\n------------------------------------------------------------------------------\n{xrst_begin dis_forward_dir dev}\n{xrst_spell\n    ataylor\n    tpv\n}\n\nForward Mode Result for Discrete Functions\n##########################################\n\nname, x, z, arg\n***************\nsee\n:ref:`var_dis_op@name` ,\n:ref:`var_dis_op@x` ,\n:ref:`var_dis_op@z` ,\n:ref:`var_dis_op@arg`\n\nPrototype\n*********\n\nRecBase\n=======\n{xrst_literal\n    // BEGIN_DIS_FORWARD_ANY\n    // END_DIS_FORWARD_ANY\n}\n\nAD<RecBase>\n===========\n{xrst_literal\n    // BEGIN_AD_DIS_FORWARD_ANY\n    // END_AD_DIS_FORWARD_ANY\n}\n\nRecBase\n*******\nIs the Base type when this function was recorded; i.e.,\n:ref:`Discrete@ax` and :ref:`Discrete@ay` have type ``AD`` < *RecBase* > .\n\norder_low\n*********\nis the lowest order Taylor coefficient that will be calculated.\n\norder_up\n********\nis the highest order Taylor coefficient that will be calculated.\n\nn_dir\n*****\nis the number of directions, for each order,\nthat will be calculated (except for order zero which only has one direction).\n\ni_z\n***\nvariable index corresponding to the result for this operation;\ni.e. the row index in *taylor* or *ataylor* corresponding to *z* .\n\ncap_order\n*********\nis the maximum number of orders that can fit in *taylor* or *ataylor* .\n\ntpv\n***\nWe use the notation\n\n    *tpv* = ( *cap_order* - 1 ) * *n_dir*  + 1\n\nwhich is the number of Taylor coefficients per variable\n\ntaylor\n******\n\nInput\n=====\nThe zero order Taylor coefficient corresponding to x::\n\n    taylor[ arg[1] * tpv + 0 ]\n\nOutput\n======\nIf *order_low* is zero::\n\n    taylor[ i_z * tpv + 0 ]\n\nis the zero order Taylor coefficient corresponding to z.\nFor k = max(order_low, 1), ... , order_up,\n\n    taylor[ i_z * tpv + (k-1)*n_dir + 1 + ell ]\n\nis the k-th order Taylor coefficient corresponding to z (which is zero).\n\nataylor\n*******\nThis has the same description as *taylor* except that its type is\n``AD`` < *RecBase* > instead of *RecBase* .\n\n{xrst_end dis_forward_dir}\n*/\nnamespace CppAD { namespace local { namespace var_op {\n\n// ---------------------------------------------------------------------------\n// BEGIN_DIS_FORWARD_ANY\ntemplate <class RecBase>\ninline void dis_forward_dir(\n    size_t        order_low   ,\n    size_t        order_up    ,\n    size_t        n_dir       ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    RecBase*      taylor      )\n// END_DIS_FORWARD_ANY\n{    // p, q\n    size_t p = order_low;\n    size_t q = order_up;\n    size_t r = n_dir;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(DisOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(DisOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n    CPPAD_ASSERT_UNKNOWN( 0 < r );\n\n    // Taylor coefficients corresponding to argument and result\n    size_t num_taylor_per_var = (cap_order-1) * r + 1;\n    RecBase* x = taylor + size_t(arg[1]) * num_taylor_per_var;\n    RecBase* z = taylor +    i_z * num_taylor_per_var;\n\n    if( p == 0 )\n    {   z[0]  = discrete<RecBase>::eval(size_t(arg[0]), x[0]);\n        p++;\n    }\n    for(size_t ell = 0; ell < r; ell++)\n        for(size_t k = p; k <= q; k++)\n            z[ (k-1) * r + 1 + ell ] = RecBase(0.0);\n}\n// ---------------------------------------------------------------------------\n// BEGIN_AD_DIS_FORWARD_ANY\ntemplate <class RecBase>\ninline void dis_forward_dir(\n    size_t        order_low   ,\n    size_t        order_up    ,\n    size_t        n_dir       ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    AD<RecBase>*  ataylor     )\n// END_AD_DIS_FORWARD_ANY\n{    // p, q\n    size_t p = order_low;\n    size_t q = order_up;\n    size_t r = n_dir;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(DisOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(DisOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n    CPPAD_ASSERT_UNKNOWN( 0 < r );\n\n    // Taylor coefficients corresponding to argument and result\n    size_t num_taylor_per_var = (cap_order-1) * r + 1;\n    AD<RecBase>* ax = ataylor + size_t(arg[1]) * num_taylor_per_var;\n    AD<RecBase>* az = ataylor +    i_z * num_taylor_per_var;\n\n    if( p == 0 )\n    {   az[0]  = discrete<RecBase>::ad_eval(size_t(arg[0]), ax[0]);\n        p++;\n    }\n    for(size_t ell = 0; ell < r; ell++)\n        for(size_t k = p; k <= q; k++)\n            az[ (k-1) * r + 1 + ell ] = AD<RecBase>(0.0);\n}\n\n} } } // END namespace\n# endif\n"
  },
  {
    "path": "include/cppad/local/var_op/div_op.hpp",
    "content": "# ifndef CPPAD_LOCAL_VAR_OP_DIV_OP_HPP\n# define CPPAD_LOCAL_VAR_OP_DIV_OP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\nnamespace CppAD { namespace local { namespace var_op {\n\n// --------------------------- Divvv -----------------------------------------\n\n// See dev documentation: forward_binary_op\ntemplate <class Base>\ninline void divvv_forward_any(\n    size_t        order_low   ,\n    size_t        order_up    ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // p, q\n    size_t p = order_low;\n    size_t q = order_up;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(DivvvOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(DivvvOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n    CPPAD_ASSERT_UNKNOWN( p <= q );\n\n    // Taylor coefficients corresponding to arguments and result\n    Base* x = taylor + size_t(arg[0]) * cap_order;\n    Base* y = taylor + size_t(arg[1]) * cap_order;\n    Base* z = taylor + i_z    * cap_order;\n\n\n    // Using CondExp, it can make sense to divide by zero,\n    // so do not make it an error.\n    size_t k;\n    for(size_t d = p; d <= q; d++)\n    {   z[d] = x[d];\n        for(k = 1; k <= d; k++)\n            z[d] -= z[d-k] * y[k];\n        z[d] /= y[0];\n    }\n}\n\n// See dev documentation: forward_binary_op\ntemplate <class Base>\ninline void divvv_forward_dir(\n    size_t        order_up    ,\n    size_t        n_dir       ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // q, r\n    size_t q = order_up;\n    size_t r = n_dir;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(DivvvOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(DivvvOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( 0 < q );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n\n    // Taylor coefficients corresponding to arguments and result\n    size_t num_taylor_per_var = (cap_order-1) * r + 1;\n    Base* x = taylor + size_t(arg[0]) * num_taylor_per_var;\n    Base* y = taylor + size_t(arg[1]) * num_taylor_per_var;\n    Base* z = taylor + i_z    * num_taylor_per_var;\n\n\n    // Using CondExp, it can make sense to divide by zero,\n    // so do not make it an error.\n    size_t m = (q-1) * r + 1;\n    for(size_t ell = 0; ell < r; ell++)\n    {   z[m+ell] = x[m+ell] - z[0] * y[m+ell];\n        for(size_t k = 1; k < q; k++)\n            z[m+ell] -= z[(q-k-1)*r+1+ell] * y[(k-1)*r+1+ell];\n        z[m+ell] /= y[0];\n    }\n}\n\n\n\n// See dev documentation: forward_binary_op\ntemplate <class Base>\ninline void divvv_forward_0(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{   //\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(DivvvOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(DivvvOp) == 1 );\n\n    // Taylor coefficients corresponding to arguments and result\n    Base* x = taylor + size_t(arg[0]) * cap_order;\n    Base* y = taylor + size_t(arg[1]) * cap_order;\n    Base* z = taylor + i_z    * cap_order;\n\n    z[0] = x[0] / y[0];\n}\n\n\n// See dev documentation: reverse_binary_op\ntemplate <class Base>\ninline void divvv_reverse(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    const Base*   taylor      ,\n    size_t        n_order     ,\n    Base*         partial     )\n{   // d\n    //\n    size_t d = n_order - 1;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(DivvvOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(DivvvOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( n_order <= cap_order );\n\n    // Arguments\n    const Base* y  = taylor + size_t(arg[1]) * cap_order;\n    const Base* z  = taylor + i_z    * cap_order;\n\n    // Partial derivatives corresponding to arguments and result\n    Base* px = partial + size_t(arg[0]) * n_order;\n    Base* py = partial + size_t(arg[1]) * n_order;\n    Base* pz = partial + i_z    * n_order;\n\n    // Using CondExp, it can make sense to divide by zero\n    // so do not make it an error.\n    Base inv_y0 = Base(1.0) / y[0];\n\n    size_t k;\n    // number of indices to access\n    size_t j = d + 1;\n    while(j)\n    {   --j;\n        // scale partial w.r.t. z[j]\n        pz[j] = azmul(pz[j], inv_y0);\n\n        px[j] += pz[j];\n        for(k = 1; k <= j; k++)\n        {   pz[j-k] -= azmul(pz[j], y[k]  );\n            py[k]   -= azmul(pz[j], z[j-k]);\n        }\n        py[0] -= azmul(pz[j], z[j]);\n    }\n}\n\n// --------------------------- Divpv -----------------------------------------\n\n// See dev documentation: forward_binary_op\ntemplate <class Base>\ninline void divpv_forward_any(\n    size_t        order_low   ,\n    size_t        order_up    ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // p, q\n    size_t p = order_low;\n    size_t q = order_up;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(DivpvOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(DivpvOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n    CPPAD_ASSERT_UNKNOWN( p <= q );\n\n    // Taylor coefficients corresponding to arguments and result\n    Base* y = taylor + size_t(arg[1]) * cap_order;\n    Base* z = taylor + i_z    * cap_order;\n\n    // Paraemter value\n    Base x = parameter[ arg[0] ];\n\n    // Using CondExp, it can make sense to divide by zero,\n    // so do not make it an error.\n    size_t k;\n    if( p == 0 )\n    {   z[0] = x / y[0];\n        p++;\n    }\n    for(size_t d = p; d <= q; d++)\n    {   z[d] = Base(0.0);\n        for(k = 1; k <= d; k++)\n            z[d] -= z[d-k] * y[k];\n        z[d] /= y[0];\n    }\n}\n\n// See dev documentation: forward_binary_op\ntemplate <class Base>\ninline void divpv_forward_dir(\n    size_t        order_up    ,\n    size_t        n_dir       ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // q, r\n    size_t q = order_up;\n    size_t r = n_dir;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(DivpvOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(DivpvOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( 0 < q );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n\n    // Taylor coefficients corresponding to arguments and result\n    size_t num_taylor_per_var = (cap_order-1) * r + 1;\n    Base* y = taylor + size_t(arg[1]) * num_taylor_per_var;\n    Base* z = taylor + i_z    * num_taylor_per_var;\n\n    // Using CondExp, it can make sense to divide by zero,\n    // so do not make it an error.\n    size_t m = (q-1) * r + 1;\n    for(size_t ell = 0; ell < r; ell++)\n    {   z[m+ell] = - z[0] * y[m+ell];\n        for(size_t k = 1; k < q; k++)\n            z[m+ell] -= z[(q-k-1)*r+1+ell] * y[(k-1)*r+1+ell];\n        z[m+ell] /= y[0];\n    }\n}\n\n\n// See dev documentation: forward_binary_op\ntemplate <class Base>\ninline void divpv_forward_0(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{   //\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(DivpvOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(DivpvOp) == 1 );\n\n    // Paraemter value\n    Base x = parameter[ arg[0] ];\n\n    // Taylor coefficients corresponding to arguments and result\n    Base* y = taylor + size_t(arg[1]) * cap_order;\n    Base* z = taylor + i_z    * cap_order;\n\n    z[0] = x / y[0];\n}\n\n\n// See dev documentation: reverse_binary_op\ntemplate <class Base>\ninline void divpv_reverse(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    const Base*   taylor      ,\n    size_t        n_order     ,\n    Base*         partial     )\n{   // d\n    //\n    size_t d = n_order - 1;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(DivvvOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(DivvvOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( n_order <= cap_order );\n\n    // Arguments\n    const Base* y = taylor + size_t(arg[1]) * cap_order;\n    const Base* z = taylor + i_z    * cap_order;\n\n    // Partial derivatives corresponding to arguments and result\n    Base* py = partial + size_t(arg[1]) * n_order;\n    Base* pz = partial + i_z    * n_order;\n\n    // Using CondExp, it can make sense to divide by zero so do not\n    // make it an error.\n    Base inv_y0 = Base(1.0) / y[0];\n\n    size_t k;\n    // number of indices to access\n    size_t j = d + 1;\n    while(j)\n    {   --j;\n        // scale partial w.r.t z[j]\n        pz[j] = azmul(pz[j], inv_y0);\n\n        for(k = 1; k <= j; k++)\n        {   pz[j-k] -= azmul(pz[j], y[k]  );\n            py[k]   -= azmul(pz[j], z[j-k] );\n        }\n        py[0] -= azmul(pz[j], z[j]);\n    }\n}\n\n\n// --------------------------- Divvp -----------------------------------------\n\n// See dev documentation: forward_binary_op\ntemplate <class Base>\ninline void divvp_forward_any(\n    size_t        order_low   ,\n    size_t        order_up    ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // p, q\n    size_t p = order_low;\n    size_t q = order_up;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(DivvpOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(DivvpOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n    CPPAD_ASSERT_UNKNOWN( p <= q );\n\n    // Taylor coefficients corresponding to arguments and result\n    Base* x = taylor + size_t(arg[0]) * cap_order;\n    Base* z = taylor + i_z    * cap_order;\n\n    // Parameter value\n    Base y = parameter[ arg[1] ];\n\n    // Using CondExp and multiple levels of AD, it can make sense\n    // to divide by zero so do not make it an error.\n    for(size_t d = p; d <= q; d++)\n        z[d] = x[d] / y;\n}\n\n// See dev documentation: forward_binary_op\ntemplate <class Base>\ninline void divvp_forward_dir(\n    size_t        order_up    ,\n    size_t        n_dir       ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // q, r\n    size_t q = order_up;\n    size_t r = n_dir;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(DivvpOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(DivvpOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n    CPPAD_ASSERT_UNKNOWN( 0 < q  );\n\n    // Taylor coefficients corresponding to arguments and result\n    size_t num_taylor_per_var = (cap_order-1) * r + 1;\n    Base* x = taylor + size_t(arg[0]) * num_taylor_per_var;\n    Base* z = taylor +    i_z * num_taylor_per_var;\n\n    // Parameter value\n    Base y = parameter[ arg[1] ];\n\n    // Using CondExp and multiple levels of AD, it can make sense\n    // to divide by zero so do not make it an error.\n    size_t m = (q-1)*r + 1;\n    for(size_t ell = 0; ell < r; ell++)\n        z[m + ell] = x[m + ell] / y;\n}\n\n\n\n// See dev documentation: forward_binary_op\ntemplate <class Base>\ninline void divvp_forward_0(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{   //\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(DivvpOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(DivvpOp) == 1 );\n\n    // Parameter value\n    Base y = parameter[ arg[1] ];\n\n    // Taylor coefficients corresponding to arguments and result\n    Base* x = taylor + size_t(arg[0]) * cap_order;\n    Base* z = taylor + i_z    * cap_order;\n\n    z[0] = x[0] / y;\n}\n\n\n// See dev documentation: reverse_binary_op\ntemplate <class Base>\ninline void divvp_reverse(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    const Base*   taylor      ,\n    size_t        n_order     ,\n    Base*         partial     )\n{   // d\n    //\n    size_t d = n_order - 1;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(DivvpOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(DivvpOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( n_order <= cap_order );\n\n    // Argument values\n    Base  y = parameter[ arg[1] ];\n\n    // Partial derivatives corresponding to arguments and result\n    Base* px = partial + size_t(arg[0]) * n_order;\n    Base* pz = partial + i_z    * n_order;\n\n    // Using CondExp, it can make sense to divide by zero\n    // so do not make it an error.\n    Base inv_y = Base(1.0) / y;\n\n    // number of indices to access\n    size_t j = d + 1;\n    while(j)\n    {   --j;\n        px[j] += azmul(pz[j], inv_y);\n    }\n}\n\n} } } // END namespace\n# endif\n"
  },
  {
    "path": "include/cppad/local/var_op/erf_op.hpp",
    "content": "# ifndef CPPAD_LOCAL_VAR_OP_ERF_OP_HPP\n# define CPPAD_LOCAL_VAR_OP_ERF_OP_HPP\n\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/local/var_op/mul_op.hpp>\n# include <cppad/local/var_op/sub_op.hpp>\n# include <cppad/local/var_op/exp_op.hpp>\n\n\nnamespace CppAD { namespace local { namespace var_op {\n/*!\n\\file erf_op.hpp\nForward and reverse mode calculations for z = erf(x) or erfc(x).\n*/\n\n/*!\nForward mode Taylor coefficient for result of op = ErfOp or ErfcOp.\n\nThe C++ source code corresponding to this operation is one of\n\\verbatim\n    z = erf(x)\n    z = erfc(x)\n\\endverbatim\n\n\\tparam Base\nbase type for the operator; i.e., this operation was recorded\nusing AD< Base > and computations by this routine are done using type Base.\n\n\\param op\nmust be either ErfOp or ErfcOp and indicates if this is\nz = erf(x) or z = erfc(x).\n\n\\param p\nlowest order of the Taylor coefficients that we are computing.\n\n\\param q\nhighest order of the Taylor coefficients that we are computing.\n\n\\param i_z\nvariable index corresponding to the last (primary) result for this operation;\ni.e. the row index in taylor corresponding to z.\nThe auxiliary results are called y_j have index i_z - j.\n\n\\param arg\narg[0]: is the variable index corresponding to x.\n\\n\narg[1]: is the parameter index corresponding to the value zero.\n\\n\narg[2]: is  the parameter index correspodning to the value 2 / sqrt(pi).\n\n\\param parameter\nparameter[ arg[1] ] is the value zero,\nand parameter[ arg[2] ] is the value 2 / sqrt(pi).\n\n\\param cap_order\nmaximum number of orders that will fit in the taylor array.\n\n\\param taylor\n\\b Input:\ntaylor [ size_t(arg[0]) * cap_order + k ]\nfor k = 0 , ... , q,\nis the k-th order Taylor coefficient corresponding to x.\n\\n\n\\b Input:\ntaylor [ i_z * cap_order + k ]\nfor k = 0 , ... , p - 1,\nis the k-th order Taylor coefficient corresponding to z.\n\\n\n\\b Input:\ntaylor [ ( i_z - j) * cap_order + k ]\nfor k = 0 , ... , p-1,\nand j = 0 , ... , 4,\nis the k-th order Taylor coefficient corresponding to the j-th result for z.\n\\n\n\\b Output:\ntaylor [ (i_z-j) * cap_order + k ],\nfor k = p , ... , q,\nand j = 0 , ... , 4,\nis the k-th order Taylor coefficient corresponding to the j-th result for z.\n\n*/\ntemplate <class Base>\ninline void erf_forward_any(\n    op_code_var   op          ,\n    size_t        order_low   ,\n    size_t        order_up    ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // p, q\n    size_t p = order_low;\n    size_t q = order_up;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( op == ErfOp || op == ErfcOp );\n    CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(op) == 5 );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n    CPPAD_ASSERT_UNKNOWN( p <= q );\n    CPPAD_ASSERT_UNKNOWN(\n        size_t( std::numeric_limits<addr_t>::max() ) >= i_z + 2\n    );\n\n    // array used to pass parameter values for sub-operations\n    addr_t addr[2];\n\n    // convert from final result to first result\n    i_z -= 4; // 4 = NumRes(ErfOp) - 1;\n\n    // z_0 = x * x\n    addr[0] = arg[0]; // x\n    addr[1] = arg[0]; // x\n    mulvv_forward_any(p, q, i_z+0, addr, parameter, cap_order, taylor);\n\n    // z_1 = - x * x\n    addr[0] = arg[1];           // zero\n    addr[1] = addr_t( i_z );    // z_0\n    subpv_forward_any(p, q, i_z+1, addr, parameter, cap_order, taylor);\n\n    // z_2 = exp( - x * x )\n    addr[0] = addr_t(i_z+1);\n    exp_forward_any(p, q, i_z+2, addr, cap_order, taylor);\n\n    // z_3 = (2 / sqrt(pi)) * exp( - x * x )\n    addr[0] = arg[2];            // 2 / sqrt(pi)\n    addr[1] = addr_t( i_z + 2 ); // z_2\n    mulpv_forward_any(p, q, i_z+3, addr, parameter, cap_order, taylor);\n\n    // pointers to taylor coefficients for x , z_3, and z_4\n    Base* x    = taylor + size_t(arg[0]) * cap_order;\n    Base* z_3  = taylor + (i_z+3) * cap_order;\n    Base* z_4  = taylor + (i_z+4) * cap_order;\n\n    // calculate z_4 coefficients\n    if( p == 0 )\n    {   // z4 (t) = erf[x(t)]\n        if( op == ErfOp )\n            z_4[0] = erf(x[0]);\n        else\n            z_4[0] = erfc(x[0]);\n        p++;\n    }\n    // sign\n    Base sign(1.0);\n    if( op == ErfcOp )\n        sign = Base(-1.0);\n    //\n    for(size_t j = p; j <= q; j++)\n    {   // erf:  z_4' (t) =   erf'[x(t)] * x'(t) = z3(t) * x'(t)\n        // erfc: z_4' (t) = - erf'[x(t)] * x'(t) = - z3(t) * x'(t)\n        // z_4[1] + 2 * z_4[2] * t +  ... =\n        // sign * (z_3[0] + z_3[1] * t +  ...) * (x[1] + 2 * x[2] * t +  ...)\n        Base base_j = static_cast<Base>(double(j));\n        z_4[j]      = static_cast<Base>(0);\n        for(size_t k = 1; k <= j; k++)\n            z_4[j] += sign * (Base(double(k)) / base_j) * x[k] * z_3[j-k];\n    }\n}\n\n/*!\nZero order Forward mode Taylor coefficient for result of op = ErfOp or ErfcOp.\n\nThe C++ source code corresponding to this operation one of\n\\verbatim\n    z = erf(x)\n    z = erfc(x)\n\\endverbatim\n\n\\tparam Base\nbase type for the operator; i.e., this operation was recorded\nusing AD< Base > and computations by this routine are done using type Base.\n\n\\param op\nmust be either ErfOp or ErfcOp and indicates if this is\nz = erf(x) or z = erfc(x).\n\n\\param i_z\nvariable index corresponding to the last (primary) result for this operation;\ni.e. the row index in taylor corresponding to z.\nThe auxiliary results are called y_j have index i_z - j.\n\n\\param arg\narg[0]: is the variable index corresponding to x.\n\\n\narg[1]: is the parameter index corresponding to the value zero.\n\\n\narg[2]: is  the parameter index correspodning to the value 2 / sqrt(pi).\n\n\\param parameter\nparameter[ arg[1] ] is the value zero,\nand parameter[ arg[2] ] is the value 2 / sqrt(pi).\n\n\\param cap_order\nmaximum number of orders that will fit in the taylor array.\n\n\\param taylor\n\\b Input:\ntaylor [ size_t(arg[0]) * cap_order + 0 ]\nis the zero order Taylor coefficient corresponding to x.\n\\n\n\\b Input:\ntaylor [ i_z * cap_order + 0 ]\nis the zero order Taylor coefficient corresponding to z.\n\\n\n\\b Output:\ntaylor [ (i_z-j) * cap_order + 0 ],\nfor j = 0 , ... , 4,\nis the zero order Taylor coefficient for j-th result corresponding to z.\n\n*/\ntemplate <class Base>\ninline void erf_forward_0(\n    op_code_var   op          ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{   //\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( op == ErfOp || op == ErfcOp );\n    CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(op) == 5 );\n    CPPAD_ASSERT_UNKNOWN( 0 < cap_order );\n    CPPAD_ASSERT_UNKNOWN(\n        size_t( std::numeric_limits<addr_t>::max() ) >= i_z + 2\n    );\n\n    // array used to pass parameter values for sub-operations\n    addr_t addr[2];\n\n    // convert from final result to first result\n    i_z -= 4; // 4 = NumRes(ErfOp) - 1;\n\n    // z_0 = x * x\n    addr[0] = arg[0]; // x\n    addr[1] = arg[0]; // x\n    mulvv_forward_0(i_z+0, addr, parameter, cap_order, taylor);\n\n    // z_1 = - x * x\n    addr[0] = arg[1];       // zero\n    addr[1] = addr_t(i_z);  // z_0\n    subpv_forward_0(i_z+1, addr, parameter, cap_order, taylor);\n\n    // z_2 = exp( - x * x )\n    addr[0] = addr_t(i_z+1);\n    exp_forward_0(i_z+2, addr, cap_order, taylor);\n\n    // z_3 = (2 / sqrt(pi)) * exp( - x * x )\n    addr[0] = arg[2];          // 2 / sqrt(pi)\n    addr[1] = addr_t(i_z + 2); // z_2\n    mulpv_forward_0(i_z+3, addr, parameter, cap_order, taylor);\n\n    // zero order Taylor coefficient for z_4\n    Base* x    = taylor + size_t(arg[0]) * cap_order;\n    Base* z_4  = taylor + (i_z + 4) * cap_order;\n    if( op == ErfOp )\n        z_4[0] = erf(x[0]);\n    else\n        z_4[0] = erfc(x[0]);\n}\n/*!\nForward mode Taylor coefficient for result of op = ErfOp or ErfcOp.\n\nThe C++ source code corresponding to this operation is one of\n\\verbatim\n    z = erf(x)\n    z = erfc(x)\n\\endverbatim\n\n\\tparam Base\nbase type for the operator; i.e., this operation was recorded\nusing AD< Base > and computations by this routine are done using type Base.\n\n\\param op\nmust be either ErfOp or ErfcOp and indicates if this is\nz = erf(x) or z = erfc(x).\n\n\\param q\norder of the Taylor coefficients that we are computing.\n\n\\param r\nnumber of directions for the Taylor coefficients that we afre computing.\n\n\\param i_z\nvariable index corresponding to the last (primary) result for this operation;\ni.e. the row index in taylor corresponding to z.\nThe auxiliary results have index i_z - j for j = 0 , ... , 4\n(and include z).\n\n\\param arg\narg[0]: is the variable index corresponding to x.\n\\n\narg[1]: is the parameter index corresponding to the value zero.\n\\n\narg[2]: is  the parameter index correspodning to the value 2 / sqrt(pi).\n\n\\param parameter\nparameter[ arg[1] ] is the value zero,\nand parameter[ arg[2] ] is the value 2 / sqrt(pi).\n\n\\param cap_order\nmaximum number of orders that will fit in the taylor array.\n\n\\par tpv\nWe use the notation\n<code>tpv = (cap_order-1) * r + 1</code>\nwhich is the number of Taylor coefficients per variable\n\n\\param taylor\n\\b Input: If x is a variable,\n<code>taylor [ arg[0] * tpv + 0 ]</code>,\nis the zero order Taylor coefficient for all directions and\n<code>taylor [ arg[0] * tpv + (k-1)*r + ell + 1 ]</code>,\nfor k = 1 , ... , q,\nell = 0, ..., r-1,\nis the k-th order Taylor coefficient\ncorresponding to x and the ell-th direction.\n\\n\n\\b Input:\ntaylor [ (i_z - j) * tpv + 0 ]\nis the zero order Taylor coefficient for all directions and the\nj-th result for z.\nfor k = 1 , ... , q-1,\nell = 0, ... , r-1,\n<code>\ntaylor[ (i_z - j) * tpv + (k-1)*r + ell + 1]\n</code>\nis the Taylor coefficient for the k-th order, ell-th direction,\nand j-th auzillary result.\n\\n\n\\b Output:\ntaylor [ (i_z-j) * tpv + (q-1)*r + ell + 1 ],\nfor ell = 0 , ... , r-1,\nis the Taylor coefficient for the q-th order, ell-th direction,\nand j-th auzillary result.\n\n*/\ntemplate <class Base>\ninline void erf_forward_dir(\n    op_code_var   op          ,\n    size_t        order_up    ,\n    size_t        n_dir       ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // q, r\n    size_t q = order_up;\n    size_t r = n_dir;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( op == ErfOp || op == ErfcOp );\n    CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(op) == 5 );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n    CPPAD_ASSERT_UNKNOWN( 0 < q );\n    CPPAD_ASSERT_UNKNOWN(\n        size_t( std::numeric_limits<addr_t>::max() ) >= i_z + 2\n    );\n\n    // array used to pass parameter values for sub-operations\n    addr_t addr[2];\n\n    // convert from final result to first result\n    i_z -= 4; // 4 = NumRes(ErfOp) - 1;\n\n    // z_0 = x * x\n    addr[0] = arg[0]; // x\n    addr[1] = arg[0]; // x\n    mulvv_forward_dir(q, r, i_z+0, addr, parameter, cap_order, taylor);\n\n    // z_1 = - x * x\n    addr[0] = arg[1];         // zero\n    addr[1] = addr_t( i_z );  // z_0\n    subpv_forward_dir(q, r, i_z+1, addr, parameter, cap_order, taylor);\n\n    // z_2 = exp( - x * x )\n    addr[0] = addr_t(i_z+1);\n    exp_forward_dir(q, r, i_z+2, addr, cap_order, taylor);\n\n    // z_3 = (2 / sqrt(pi)) * exp( - x * x )\n    addr[0] = arg[2];            // 2 / sqrt(pi)\n    addr[1] = addr_t( i_z + 2 ); // z_2\n    mulpv_forward_dir(q, r, i_z+3, addr, parameter, cap_order, taylor);\n\n    // pointers to taylor coefficients for x , z_3, and z_4\n    size_t num_taylor_per_var = (cap_order - 1) * r + 1;\n    Base* x    = taylor + size_t(arg[0]) * num_taylor_per_var;\n    Base* z_3  = taylor + (i_z+3) * num_taylor_per_var;\n    Base* z_4  = taylor + (i_z+4) * num_taylor_per_var;\n\n    // sign\n    Base sign(1.0);\n    if( op == ErfcOp )\n        sign = Base(-1.0);\n\n    // erf:  z_4' (t) =   erf'[x(t)] * x'(t) = z3(t) * x'(t)\n    // erfc: z_4' (t) = - erf'[x(t)] * x'(t) = z3(t) * x'(t)\n    // z_4[1] + 2 * z_4[2] * t +  ... =\n    // sign * (z_3[0] + z_3[1] * t +  ...) * (x[1] + 2 * x[2] * t +  ...)\n    Base base_q = static_cast<Base>(double(q));\n    for(size_t ell = 0; ell < r; ell++)\n    {   // index in z_4 and x for q-th order term\n        size_t m = (q-1)*r + ell + 1;\n        // initialize q-th order term summation\n        z_4[m] = sign * z_3[0] * x[m];\n        for(size_t k = 1; k < q; k++)\n        {   size_t x_index  = (k-1)*r + ell + 1;\n            size_t z3_index = (q-k-1)*r + ell + 1;\n            Base bk = Base(double(k));\n            z_4[m] += sign * (bk / base_q) * x[x_index] * z_3[z3_index];\n        }\n    }\n}\n\n/*!\nCompute reverse mode partial derivatives for result of op = ErfOp or ErfcOp.\n\nThe C++ source code corresponding to this operation is one of\n\\verbatim\n    z = erf(x)\n    z = erfc(x)\n\\endverbatim\n\n\\tparam Base\nbase type for the operator; i.e., this operation was recorded\nusing AD< Base > and computations by this routine are done using type Base.\n\n\\param op\nmust be either ErfOp or ErfcOp and indicates if this is\nz = erf(x) or z = erfc(x).\n\n\\param d\nhighest order Taylor of the Taylor coefficients that we are computing\nthe partial derivatives with respect to.\n\n\\param i_z\nvariable index corresponding to the last (primary) result for this operation;\ni.e. the row index in taylor corresponding to z.\nThe auxiliary results are called y_j have index i_z - j.\n\n\\param arg\narg[0]: is the variable index corresponding to x.\n\\n\narg[1]: is the parameter index corresponding to the value zero.\n\\n\narg[2]: is  the parameter index correspodning to the value 2 / sqrt(pi).\n\n\\param parameter\nparameter[ arg[1] ] is the value zero,\nand parameter[ arg[2] ] is the value 2 / sqrt(pi).\n\n\\param cap_order\nmaximum number of orders that will fit in the taylor array.\n\n\\param taylor\n\\b Input:\ntaylor [ size_t(arg[0]) * cap_order + k ]\nfor k = 0 , ... , d,\nis the k-th order Taylor coefficient corresponding to x.\n\\n\ntaylor [ (i_z - j) * cap_order + k ]\nfor k = 0 , ... , d,\nand for j = 0 , ... , 4,\nis the k-th order Taylor coefficient corresponding to the j-th result\nfor this operation.\n\n\\param n_order\nnumber of columns in the matrix containing all the partial derivatives\n\n\\param partial\n\\b Input:\npartial [ size_t(arg[0]) * n_order + k ]\nfor k = 0 , ... , d,\nis the partial derivative of G( z , x , w , u , ... ) with respect to\nthe k-th order Taylor coefficient for x.\n\\n\n\\b Input:\npartial [ (i_z - j) * n_order + k ]\nfor k = 0 , ... , d,\nand for j = 0 , ... , 4,\nis the partial derivative of G( z , x , w , u , ... ) with respect to\nthe k-th order Taylor coefficient for the j-th result of this operation.\n\\n\n\\b Output:\npartial [ size_t(arg[0]) * n_order + k ]\nfor k = 0 , ... , d,\nis the partial derivative of H( x , w , u , ... ) with respect to\nthe k-th order Taylor coefficient for x.\n\\n\n\\b Output:\npartial [ (i_z-j) * n_order + k ]\nfor k = 0 , ... , d,\nand for j = 0 , ... , 4,\nmay be used as work space; i.e., may change in an unspecified manner.\n\n*/\ntemplate <class Base>\ninline void erf_reverse(\n    op_code_var   op          ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    const Base*   taylor      ,\n    size_t        n_order     ,\n    Base*         partial     )\n{   // d\n    //\n    size_t d = n_order - 1;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( op == ErfOp || op == ErfcOp );\n    CPPAD_ASSERT_UNKNOWN( NumArg(op) == 3 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(op) == 5 );\n    CPPAD_ASSERT_UNKNOWN( n_order <= cap_order );\n    CPPAD_ASSERT_UNKNOWN(\n        size_t( std::numeric_limits<addr_t>::max() ) >= i_z + 2\n    );\n\n    // array used to pass parameter values for sub-operations\n    addr_t addr[2];\n\n    // If pz is zero, make sure this operation has no effect\n    // (zero times infinity or nan would be non-zero).\n    Base* pz  = partial + i_z * n_order;\n    bool skip(true);\n    for(size_t i_d = 0; i_d <= d; i_d++)\n        skip &= IdenticalZero(pz[i_d]);\n    if( skip )\n        return;\n\n    // convert from final result to first result\n    i_z -= 4; // 4 = NumRes(ErfOp) - 1;\n\n    // Taylor coefficients and partials corresponding to x\n    const Base* x  = taylor  + size_t(arg[0]) * cap_order;\n    Base* px       = partial + size_t(arg[0]) * n_order;\n\n    // Taylor coefficients and partials corresponding to z_3\n    const Base* z_3  = taylor  + (i_z+3) * cap_order;\n    Base* pz_3       = partial + (i_z+3) * n_order;\n\n    // Taylor coefficients and partials corresponding to z_4\n    Base* pz_4 = partial + (i_z+4) * n_order;\n\n    // sign\n    Base sign(1.0);\n    if( op == ErfcOp )\n        sign = Base(-1.0);\n\n    // Reverse z_4\n    size_t j = d;\n    while(j)\n    {   pz_4[j] /= Base(double(j));\n        for(size_t k = 1; k <= j; k++)\n        {   px[k]     += sign * azmul(pz_4[j], z_3[j-k]) * Base(double(k));\n            pz_3[j-k] += sign * azmul(pz_4[j], x[k]) * Base(double(k));\n        }\n        j--;\n    }\n    px[0] += sign * azmul(pz_4[0], z_3[0]);\n\n    // z_3 = (2 / sqrt(pi)) * exp( - x * x )\n    addr[0] = arg[2];            // 2 / sqrt(pi)\n    addr[1] = addr_t( i_z + 2 ); // z_2\n    mulpv_reverse(\n        i_z+3, addr, parameter, cap_order, taylor, n_order, partial\n    );\n\n    // z_2 = exp( - x * x )\n    addr[0] = addr_t(i_z + 1);\n    exp_reverse(\n        i_z+2, addr, cap_order, taylor, n_order, partial\n    );\n\n    // z_1 = - x * x\n    addr[0] = arg[1];           // zero\n    addr[1] = addr_t( i_z );    // z_0\n    subpv_reverse(\n        i_z+1, addr, parameter, cap_order, taylor, n_order, partial\n    );\n\n    // z_0 = x * x\n    addr[0] = arg[0]; // x\n    addr[1] = arg[0]; // x\n    mulvv_reverse(\n        i_z+0, addr, parameter, cap_order, taylor, n_order, partial\n    );\n\n}\n\n\n} } } // END namespace\n# endif // CPPAD_ERF_OP_INCLUDED\n"
  },
  {
    "path": "include/cppad/local/var_op/exp_op.hpp",
    "content": "# ifndef CPPAD_LOCAL_VAR_OP_EXP_OP_HPP\n# define CPPAD_LOCAL_VAR_OP_EXP_OP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n\nnamespace CppAD { namespace local { namespace var_op {\n\n\n// See dev documentation: forward_unary_op\ntemplate <class Base>\ninline void exp_forward_any(\n    size_t        order_low   ,\n    size_t        order_up    ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // p, q\n    size_t p = order_low;\n    size_t q = order_up;\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(ExpOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(ExpOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n    CPPAD_ASSERT_UNKNOWN( p <= q );\n\n    // Taylor coefficients corresponding to argument and result\n    Base* x = taylor + i_x * cap_order;\n    Base* z = taylor + i_z * cap_order;\n\n    size_t k;\n    if( p == 0 )\n    {   z[0] = exp( x[0] );\n        p++;\n    }\n    for(size_t j = p; j <= q; j++)\n    {\n        z[j] = x[1] * z[j-1];\n        for(k = 2; k <= j; k++)\n            z[j] += Base(double(k)) * x[k] * z[j-k];\n        z[j] /= Base(double(j));\n    }\n}\n\n\n// See dev documentation: forward_unary_op\ntemplate <class Base>\ninline void exp_forward_dir(\n    size_t        order_up    ,\n    size_t        n_dir       ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // q, r\n    size_t q = order_up;\n    size_t r = n_dir;\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(ExpOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(ExpOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n    CPPAD_ASSERT_UNKNOWN( 0 < q );\n\n    // Taylor coefficients corresponding to argument and result\n    size_t num_taylor_per_var = (cap_order-1) * r + 1;\n    Base* x = taylor + i_x * num_taylor_per_var;\n    Base* z = taylor + i_z * num_taylor_per_var;\n\n    size_t m = (q-1)*r + 1;\n    for(size_t ell = 0; ell < r; ell++)\n    {   z[m+ell] = Base(double(q)) * x[m+ell] * z[0];\n        for(size_t k = 1; k < q; k++)\n            z[m+ell] += Base(double(k)) * x[(k-1)*r+ell+1] * z[(q-k-1)*r+ell+1];\n        z[m+ell] /= Base(double(q));\n    }\n}\n\n// See dev documentation: forward_unary_op\ntemplate <class Base>\ninline void exp_forward_0(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{   //\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(ExpOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(ExpOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( 0 < cap_order );\n\n    // Taylor coefficients corresponding to argument and result\n    Base* x = taylor + i_x * cap_order;\n    Base* z = taylor + i_z * cap_order;\n\n    z[0] = exp( x[0] );\n}\n\n// See dev documentation: reverse_unary_op\ntemplate <class Base>\ninline void exp_reverse(\n    size_t        i_z          ,\n    const addr_t* arg          ,\n    size_t        cap_order    ,\n    const Base*   taylor       ,\n    size_t        n_order      ,\n    Base*         partial      )\n{   // d  //\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    size_t d = n_order - 1;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(ExpOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(ExpOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( n_order <= cap_order );\n\n    // Taylor coefficients and partials corresponding to argument\n    const Base* x  = taylor  + i_x * cap_order;\n    Base* px       = partial + i_x * n_order;\n\n    // Taylor coefficients and partials corresponding to result\n    const Base* z  = taylor  + i_z * cap_order;\n    Base* pz       = partial + i_z * n_order;\n\n    // If pz is zero, make sure this operation has no effect\n    // (zero times infinity or nan would be non-zero).\n    bool skip(true);\n    for(size_t i_d = 0; i_d <= d; i_d++)\n        skip &= IdenticalZero(pz[i_d]);\n    if( skip )\n        return;\n\n    // loop through orders in reverse\n    size_t j, k;\n    j = d;\n    while(j)\n    {   // scale partial w.r.t z[j]\n        pz[j] /= Base(double(j));\n\n        for(k = 1; k <= j; k++)\n        {   px[k]   += Base(double(k)) * azmul(pz[j], z[j-k]);\n            pz[j-k] += Base(double(k)) * azmul(pz[j], x[k]);\n        }\n        --j;\n    }\n    px[0] += azmul(pz[0], z[0]);\n}\n\n} } } // END namespace\n# endif\n"
  },
  {
    "path": "include/cppad/local/var_op/expm1_op.hpp",
    "content": "# ifndef CPPAD_LOCAL_VAR_OP_EXPM1_OP_HPP\n# define CPPAD_LOCAL_VAR_OP_EXPM1_OP_HPP\n\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n\nnamespace CppAD { namespace local { namespace var_op {\n\n\ntemplate <class Base>\ninline void expm1_forward_any(\n    size_t        order_low   ,\n    size_t        order_up    ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // p, q\n    size_t p = order_low;\n    size_t q = order_up;\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(Expm1Op) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(Expm1Op) == 1 );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n    CPPAD_ASSERT_UNKNOWN( p <= q );\n\n    // Taylor coefficients corresponding to argument and result\n    Base* x = taylor + i_x * cap_order;\n    Base* z = taylor + i_z * cap_order;\n\n    size_t k;\n    if( p == 0 )\n    {   z[0] = expm1( x[0] );\n        p++;\n    }\n    for(size_t j = p; j <= q; j++)\n    {\n        z[j] = x[1] * z[j-1];\n        for(k = 2; k <= j; k++)\n            z[j] += Base(double(k)) * x[k] * z[j-k];\n        z[j] /= Base(double(j));\n        z[j] += x[j];\n    }\n}\n\n\ntemplate <class Base>\ninline void expm1_forward_dir(\n    size_t        order_up    ,\n    size_t        n_dir       ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // q, r\n    size_t q = order_up;\n    size_t r = n_dir;\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(Expm1Op) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(Expm1Op) == 1 );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n    CPPAD_ASSERT_UNKNOWN( 0 < q );\n\n    // Taylor coefficients corresponding to argument and result\n    size_t num_taylor_per_var = (cap_order-1) * r + 1;\n    Base* x = taylor + i_x * num_taylor_per_var;\n    Base* z = taylor + i_z * num_taylor_per_var;\n\n    size_t m = (q-1)*r + 1;\n    for(size_t ell = 0; ell < r; ell++)\n    {   z[m+ell] = Base(double(q)) * x[m+ell] * z[0];\n        for(size_t k = 1; k < q; k++)\n            z[m+ell] += Base(double(k)) * x[(k-1)*r+ell+1] * z[(q-k-1)*r+ell+1];\n        z[m+ell] /= Base(double(q));\n        z[m+ell] += x[m+ell];\n    }\n}\n\ntemplate <class Base>\ninline void expm1_forward_0(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{   //\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(Expm1Op) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(Expm1Op) == 1 );\n    CPPAD_ASSERT_UNKNOWN( 0 < cap_order );\n\n    // Taylor coefficients corresponding to argument and result\n    Base* x = taylor + i_x * cap_order;\n    Base* z = taylor + i_z * cap_order;\n\n    z[0] = expm1( x[0] );\n}\n\ntemplate <class Base>\ninline void expm1_reverse(\n    size_t        i_z          ,\n    const addr_t* arg          ,\n    size_t        cap_order    ,\n    const Base*   taylor       ,\n    size_t        n_order      ,\n    Base*         partial      )\n{   // d  //\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    size_t d = n_order - 1;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(Expm1Op) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(Expm1Op) == 1 );\n    CPPAD_ASSERT_UNKNOWN( n_order <= cap_order );\n\n    // Taylor coefficients and partials corresponding to argument\n    const Base* x  = taylor  + i_x * cap_order;\n    Base* px       = partial + i_x * n_order;\n\n    // Taylor coefficients and partials corresponding to result\n    const Base* z  = taylor  + i_z * cap_order;\n    Base* pz       = partial + i_z * n_order;\n\n    // If pz is zero, make sure this operation has no effect\n    // (zero times infinity or nan would be non-zero).\n    bool skip(true);\n    for(size_t i_d = 0; i_d <= d; i_d++)\n        skip &= IdenticalZero(pz[i_d]);\n    if( skip )\n        return;\n\n    // loop through orders in reverse\n    size_t j, k;\n    j = d;\n    while(j)\n    {   px[j] += pz[j];\n\n        // scale partial w.r.t z[j]\n        pz[j] /= Base(double(j));\n\n        for(k = 1; k <= j; k++)\n        {   px[k]   += Base(double(k)) * azmul(pz[j], z[j-k]);\n            pz[j-k] += Base(double(k)) * azmul(pz[j], x[k]);\n        }\n        --j;\n    }\n    px[0] += pz[0] + azmul(pz[0], z[0]);\n}\n\n} } } // END namespace\n# endif\n"
  },
  {
    "path": "include/cppad/local/var_op/load_op.hpp",
    "content": "# ifndef CPPAD_LOCAL_VAR_OP_LOAD_OP_HPP\n# define CPPAD_LOCAL_VAR_OP_LOAD_OP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n\nnamespace CppAD { namespace local { namespace var_op {\n/*\n ------------------------------------------------------------------------------\n{xrst_begin_parent var_load_op dev}\n{xrst_spell\n    ldp\n    ldv\n}\n\nAccess an Element in a Variable VecAD Vector\n############################################\n\nLdpOp, LdvOp\n************\nare the op codes for these operators.\n\nUser Syntax\n***********\n| *z* = *v* [ *x* ]\n\n\nv\n*\nis the :ref:`VecAD-name` vector for this load operation.\nIf this vector is a constant before the load,\nthe index *x* is a variable and it is a variable after the load.\n\nx\n*\nis the index for this load.\n\ny\n*\nis the value that was stored in *v* [ *x* ] prior to this load;\nsee :ref:`var_store_op@y` .\n\nz\n*\nis the new variable created by this load.\n(This new variable is like a copy of *y* .)\n\nRecBase\n*******\nis the base type use when recording this operator;\ni.e., this operation was recording using AD< *RecBase* > operations.\n\nBase\n****\nis the type used for computations by this operator.\nThis is either *RecBase* or AD< *RecBase* >.\n\nop_code\n*******\n\n.. csv-table::\n    :widths: auto\n    :header-rows: 1\n\n    op_code, x, z\n    LdpOp, parameter, variable\n    LdvOp, variable, variable\n\ni_z\n***\nis the variable index corresponding to *z* .\n\nnum_vecad_ind\n*************\nis the size of the single array that includes\nall the VecAD vectors together with the size of each vector.\n\narg\n***\n\narg[0]\n======\nthis argument is the offset of the vector *v*\nrelative to the beginning of the single array\nthat contains all VecAD elements and sizes.\nThis offset corresponds to the first element of *v* and not its size\nwhich comes just before the first element.\n\narg[1]\n======\nIf *x* is a parameter (variable), arg[1] is the parameter index\n(variable index) to *x* .\n\narg[2]\n======\nIs the number of this VecAD load instruction that came before this one.\n\n{xrst_end var_load_op}\n-------------------------------------------------------------------------------\n{xrst_begin var_load_forward_0 dev}\n{xrst_spell\n    isvar\n}\n\nZero Order Forward Load an Element of a VecAD Vector\n####################################################\n\nv, x, y, z\n**********\nsee\n:ref:`var_load_op@v` ,\n:ref:`var_load_op@x` ,\n:ref:`var_load_op@y` ,\n:ref:`var_load_op@z`\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_LOAD_FORWARD_0\n    // END_LOAD_FORWARD_0\n}\n\n\nBase, op_code, i_z, num_vecad_ind, arg\n**************************************\nsee\n:ref:`var_load_op@Base` ,\n:ref:`var_load_op@op_code` ,\nref:`var_load_op@i_z` ,\n:ref:`var_load_op@num_vecad_ind` ,\n:ref:`var_load_op@arg` .\n\nnum_var\n*******\nis the number of variables in this recording.\n\nnum_par\n*******\nis the number of parameters in this recording.\n\nparameter\n*********\nThis is the vector of parameters for this recording which has size *num_par* .\n\ncap_order\n*********\nis the maximum number of orders that can fit in *taylor* .\n\ntaylor\n******\nIs the matrix of Taylor coefficients for all the variables.\n\n\nper_variable\n============\nFor each variable there is one Taylor coefficient of order zero\nand *n_dir* coefficients for orders greater than zero.\nThe taylor coefficients capacity per variable is::\n\n    per_variable = (cap_order - 1) * n_dir + 1\n\nInput\n=====\nFor j = 0, ..., i_z - 1,  taylor[ j * per_variable + 0 ] is an input.\n\nOutput\n======\ntaylor[ i_z * per_variable + 0 ] is an output.\n\ni_vec\n*****\nWe use *i_vec* to denote the ``size_t`` value corresponding to\n:ref:`var_load_op@x` .\nIf *x* is a parameter (variable) this is a parameter (variable) index.\n\n\nvec_ad2isvar\n************\nThis vector has size :ref:`var_load_op@num_vecad_ind` .\nIf *y* is a parameter (variable),\n*vec_ad2isvar* [ *arg* [0] + *i_vec*  ] is false (true).\n\nvec_ad2index\n************\nThis vector has size *num_vecad_ind* .\nIf *y* a parameter (variable),\n*vec_ad2index* [ *arg* [0] + *i_vec*  ]\nis the parameter (variable) index\ncorresponding to the value being loaded.\n\n{xrst_end var_load_forward_0}\n*/\n// BEGIN_LOAD_FORWARD_0\ntemplate <class Base>\ninline void load_forward_0(\n    op_code_var                op_code          ,\n    size_t                     i_z              ,\n    size_t                     num_vec_ind      ,\n    const addr_t*              arg              ,\n    size_t                     num_var          ,\n    size_t                     num_par          ,\n    const Base*                parameter        ,\n    size_t                     cap_order        ,\n    Base*                      taylor           ,\n    const pod_vector<bool>&    vec_ad2isvar     ,\n    const pod_vector<size_t>&  vec_ad2index     ,\n    pod_vector<addr_t>&        load_op2var      )\n// END_LOAD_FORWARD_0\n{  CPPAD_ASSERT_NARG_NRES(op_code, 3, 1);\n    //\n    CPPAD_ASSERT_UNKNOWN( 0 < arg[0] );\n    CPPAD_ASSERT_UNKNOWN( vec_ad2isvar.size() == num_vec_ind );\n    CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) < load_op2var.size() );\n    //\n    // i_vec\n    // assign here to avoid compiler warning for default case\n    addr_t i_vec = std::numeric_limits<addr_t>::max();\n    switch(op_code)\n    {  //\n        default:\n        CPPAD_ASSERT_UNKNOWN(false);\n        break;\n        //\n        case LdpOp:\n        CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par );\n        i_vec = addr_t( Integer( parameter[ arg[1] ] ) );\n        break;\n        //\n        case LdvOp:\n        CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_var );\n        i_vec = addr_t(Integer( taylor[ size_t(arg[1]) * cap_order + 0 ] ));\n        break;\n    }\n    //\n    CPPAD_ASSERT_KNOWN(\n        size_t(i_vec) < vec_ad2index[ arg[0] - 1 ] ,\n        \"VecAD: dynamic parameter index out or range during zero order forward\"\n    );\n    CPPAD_ASSERT_UNKNOWN( size_t(arg[0] + i_vec) < num_vec_ind );\n    //\n    // i_y, isvar\n    size_t i_y    = vec_ad2index[ arg[0] + i_vec ];\n    bool   isvar  = vec_ad2isvar[ arg[0] + i_vec ];\n    //\n    // z\n    Base* z       = taylor + i_z * cap_order;\n    //\n    // z, load_op2var\n    if( isvar )\n    {  CPPAD_ASSERT_UNKNOWN( i_y < i_z );\n        load_op2var[ arg[2] ] = addr_t( i_y );\n        Base* y = taylor + i_y * cap_order;\n        z[0]      = y[0];\n    }\n    else\n    {  CPPAD_ASSERT_UNKNOWN( i_y < num_par  );\n        load_op2var[ arg[2] ] = 0;\n        Base y    = parameter[i_y];\n        z[0]      = y;\n    }\n}\n/*\n------------------------------------------------------------------------------\n{xrst_begin var_load_forward_nonzero dev}\n\nNonzero Order Forward Load an Element of a VecAD Vector\n#######################################################\n\nv, x, y, z\n**********\nsee\n:ref:`var_load_op@v` ,\n:ref:`var_load_op@x` ,\n:ref:`var_load_op@y` ,\n:ref:`var_load_op@z`\n\nn_res\n*****\nThe number of results that are variables, *n_res* , is one for\nthis operation.\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_LOAD_FORWARD_NONZERO\n    // END_LOAD_FORWARD_NONZERO\n}\n\n\nBase, op_code, i_z, arg\n***********************\nsee\n:ref:`var_load_op@Base` ,\n:ref:`var_load_op@op_code` ,\n:ref:`var_load_op@i_z` ,\n:ref:`var_load_op@arg` .\n\norder_low\n*********\nis the lowest order Taylor coefficient that we are computing.\n\n{xrst_template ;\n    include/cppad/local/var_op/template/forward_dir.xrst\n    headers: n_dir, cap_order, order_up, taylor\n}\n\n\nload_op2var\n***********\nmaps the load operator index *arg* [2] to the\nindex corresponding to *y* for this load operation.\nIf the case where the index is zero,\n*y* is a parameter; i.e., *y* is not a variable.\n\n{xrst_end var_load_forward_nonzero}\n*/\n// BEGIN_LOAD_FORWARD_NONZERO\ntemplate <class Base>\ninline void load_forward_nonzero(\n    op_code_var                   op_code     ,\n    size_t                        i_z         ,\n    const addr_t*                 arg         ,\n    size_t                        order_low   ,\n    size_t                        order_up    ,\n    size_t                        n_dir       ,\n    size_t                        cap_order   ,\n    const pod_vector<addr_t>&     load_op2var ,\n    Base*                         taylor      )\n// END_LOAD_FORWARD_NONZERO\n{   // p, q\n    size_t p = order_low;\n    size_t q = order_up;\n    size_t r = n_dir;\n    //\n    CPPAD_ASSERT_NARG_NRES(op_code, 3, 1);\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n    CPPAD_ASSERT_UNKNOWN( 0 < r);\n    CPPAD_ASSERT_UNKNOWN( 0 < p);\n    CPPAD_ASSERT_UNKNOWN( p <= q );\n    CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) < load_op2var.size() );\n    //\n    // i_y\n    size_t i_y = size_t( load_op2var[ arg[2] ] );\n    CPPAD_ASSERT_UNKNOWN( i_y < i_z );\n    //\n    // num_taylor_per_var\n    size_t num_taylor_per_var = (cap_order-1) * r + 1;\n    //\n    // z\n    Base* z  = taylor + i_z * num_taylor_per_var;\n    //\n    // z\n    if( i_y > 0 )\n    {  Base* y = taylor + i_y * num_taylor_per_var;\n        for(size_t ell = 0; ell < r; ell++)\n        {  for(size_t k = p; k <= q; k++)\n            {  size_t m = (k-1) * r + 1 + ell;\n                z[m]     = y[m];\n            }\n        }\n    }\n    else\n    {  for(size_t ell = 0; ell < r; ell++)\n        {  for(size_t k = p; k <= q; k++)\n            {  size_t m = (k-1) * r + 1 + ell;\n                z[m]     = Base(0.0);\n            }\n        }\n    }\n}\n/*\n------------------------------------------------------------------------------\n{xrst_begin var_load_reverse dev}\n\nReverse Mode Load an Element of a VecAD Vector\n##############################################\n\nv, x, y, z\n**********\nsee\n:ref:`var_load_op@v` ,\n:ref:`var_load_op@x` ,\n:ref:`var_load_op@y` ,\n:ref:`var_load_op@z`\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_LOAD_REVERSE\n    // END_LOAD_REVERSE\n}\n\nBase, op_code, i_z, arg\n***********************\nsee\n:ref:`var_load_op@Base` ,\n:ref:`var_load_op@op_code` ,\n:ref:`var_load_op@i_z` ,\n:ref:`var_load_op@arg` .\n\ncap_order\n*********\nis the maximum number of orders that can fit in *taylor* .\n\nload_op2var\n***********\nThis vector maps the load instruction index *arg* [2] to the corresponding\n*y* variable index.\nIf this index is zero, *y* is a parameter (not a variable).\n\n{xrst_template ;\n    include/cppad/local/var_op/template/reverse_op.xrst\n    headers: n_order, partial\n\n    @x, y@  ; y\n}\n\nIf *y* is a parameter,\nnothing is modified by this call to ``reverse_load_op`` .\nOtherwise, let *i_y* be the variable index corresponding to *y*; i.e.\n\n| |tab| *i_y* = *load_op2var* [ *arg* [2] ]\n\nFor k = 0 , ... , d the k-th order Taylor coefficient for *z*\nis added to the k-th order Taylor coefficient for *y*; i.e.,\n\n|tab|\n*partial* [ *i_y* * *n_order* + *k* ] +=\n*partial* [ *i_z* * *n_order* + *k* ]\n\n{xrst_end var_load_reverse}\n*/\n// BEGIN_LOAD_REVERSE\ntemplate <class Base>\ninline void load_reverse(\n    op_code_var               op_code     ,\n    size_t                    i_z         ,\n    const addr_t*             arg         ,\n    const pod_vector<addr_t>& load_op2var ,\n    size_t                    cap_order   ,\n    size_t                    n_order     ,\n    Base*                     partial     )\n// END_LOAD_REVERSE\n{  // d\n    //\n    size_t d = n_order - 1;\n    //\n    //\n    CPPAD_ASSERT_NARG_NRES(op_code, 3, 1);\n    CPPAD_ASSERT_UNKNOWN( n_order <= cap_order );\n    // i_y\n    size_t i_y = size_t( load_op2var[ arg[2] ] );\n    CPPAD_ASSERT_UNKNOWN( i_y < i_z );\n    //\n    // py\n    if( i_y > 0 )\n    {\n        Base* pz   = partial + i_z * n_order;\n        Base* py   = partial + i_y * n_order;\n        size_t j = d + 1;\n        while(j--)\n            py[j]   += pz[j];\n    }\n}\n/*\n------------------------------------------------------------------------------\n{xrst_begin var_load_for_jac dev}\n\nForward Jacobian Sparsity for Store a VecAD Element\n###################################################\n\nv, x, y, z\n**********\nsee\n:ref:`var_load_op@v` ,\n:ref:`var_load_op@x` ,\n:ref:`var_load_op@y` ,\n:ref:`var_load_op@z`\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_LOAD_FOR_JAC\n    // END_LOAD_FOR_JAC\n}\n\nop_code, num_vecad_ind, arg\n***************************\nsee :ref:`var_load_op@op_code` ,\n:ref:`var_load_op@num_vecad_ind` ,\n:ref:`var_load_op@arg` .\n\nVector_set\n**********\nis the type used for vectors of sets. It must satisfy the\n:ref:`SetVector-name` concept.\n\ndependency\n**********\nIf true (false) we are including (are not including)\ndependencies that have derivative zero in the sparsity pattern.\nFor example, the :ref:`Discrete-name` functions have derivative zero,\nbut the value depends on its argument.\n\nvecad_ind\n*********\nis a vector with size *num_vec_ind* .\nWe use the notation *i_v* defined by\n\n|tab| *i_v* = vecad_ind[ arg[0] - 1 ]\n\nThis is the index of the VecAD vector and is less than the number of\nVecAD vectors in the recording.\n\nvar_sparsity\n************\nThe sparsity pattern for *z*\nis set equal to the sparsity pattern for *v.\nIf *dependency* is true, and *x* is a variable,\nthe sparsity pattern for *x* is added to the sparsity pattern for *z*.\n\nvecad_sparsity\n**************\nThe set with index *i_v* in *vecad_sparsity\nis the sparsity pattern for the vector *v*.\n\n{xrst_end var_load_for_jac}\n*/\n// BEGIN_LOAD_FOR_JAC\ntemplate <class Vector_set>\ninline void load_for_jac(\n    op_code_var               op_code        ,\n    size_t                    num_vecad_ind  ,\n    size_t                    i_z            ,\n    const addr_t*             arg            ,\n    bool                      dependency     ,\n    const pod_vector<size_t>& vecad_ind      ,\n    Vector_set&               var_sparsity   ,\n    const Vector_set&         vecad_sparsity )\n// END_LOAD_FOR_JAC\n{  //\n    //\n    CPPAD_ASSERT_NARG_NRES(op_code, 3, 1);\n    CPPAD_ASSERT_UNKNOWN( 0 < arg[0] );\n    CPPAD_ASSERT_UNKNOWN( num_vecad_ind == vecad_ind.size() );\n    CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_vecad_ind );\n    //\n    // i_v\n    size_t i_v = vecad_ind[ arg[0] - 1 ];\n    CPPAD_ASSERT_UNKNOWN( i_v < vecad_sparsity.n_set() );\n    //\n    // var_sparsity[i_z]\n    var_sparsity.assignment(i_z, i_v, vecad_sparsity);\n    //\n    // var_sparsity[i_z]\n    if( dependency & (op_code == LdvOp) )\n    {  size_t i_x = size_t( arg[1] );\n        var_sparsity.binary_union(i_z, i_z, i_x, var_sparsity);\n    }\n    return;\n}\n/*\n------------------------------------------------------------------------------\n{xrst_begin var_load_rev_jac dev}\n\nReverse Jacobian Sparsity for Load a VecAD Element\n##################################################\n\nv, x, y, z\n**********\nsee\n:ref:`var_load_op@v` ,\n:ref:`var_load_op@x` ,\n:ref:`var_load_op@y` ,\n:ref:`var_load_op@z`\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_LOAD_REV_JAC\n    // END_LOAD_REV_JAC\n}\n\nop_code, num_vecad_ind, arg\n***************************\nsee :ref:`var_load_op@op_code` ,\n:ref:`var_load_op@num_vecad_ind` ,\n:ref:`var_load_op@arg` .\n\nVector_set\n**********\nis the type used for vectors of sets. It must satisfy the\n:ref:`SetVector-name` concept.\n\ndependency\n**********\nIf true (false) we are including (are not including)\ndependencies that have derivative zero in the sparsity pattern.\nFor example, the :ref:`Discrete-name` functions have derivative zero,\nbut the value depends on its argument.\n\nvecad_ind\n*********\nis a vector with size *num_vec_ind* .\nWe use the notation *i_v* defined by\n\n|tab| *i_v* = vecad_ind[ arg[0] - 1 ]\n\nThis is the index of the VecAD vector and is less than the number of\nVecAD vectors in the recording.\n\nvar_sparsity\n************\nThe set with index *i_z* in *vecad_sparsity\nis the sparsity pattern for the variable *z*.\nIf *dependency* is true and *x* is a variable,\nthe sparsity pattern for *z* is added to the sparsity pattern *x* .\n\nvecad_sparsity\n**************\nThe sparsity pattern for *z* is added to the sparsity pattern\nwith index *i_v* in *vecad_sparsity ( the sparsity pattern for *v* ).\n\n\n{xrst_end var_load_rev_jac}\n*/\n// BEGIN_LOAD_REV_JAC\ntemplate <class Vector_set>\ninline void load_rev_jac(\n    op_code_var               op_code        ,\n    size_t                    num_vecad_ind  ,\n    size_t                    i_z            ,\n    const addr_t*             arg            ,\n    bool                      dependency     ,\n    const pod_vector<size_t>& vecad_ind      ,\n    Vector_set&               var_sparsity   ,\n    Vector_set&               vecad_sparsity )\n// END_LOAD_REV_JAC\n{  //\n    //\n    CPPAD_ASSERT_NARG_NRES(op_code, 3, 1);\n    CPPAD_ASSERT_UNKNOWN( 0 < arg[0] );\n    CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_vecad_ind );\n    //\n    // i_v\n    size_t i_v = vecad_ind[ arg[0] - 1 ];\n    CPPAD_ASSERT_UNKNOWN( i_v < vecad_sparsity.n_set() );\n    //\n    // vecad_sparsity[i_v]\n    vecad_sparsity.binary_union(i_v, i_v, i_z, var_sparsity);\n    if( dependency & (op_code == LdvOp) )\n    {  size_t i_x = size_t( arg[1] );\n        var_sparsity.binary_union(i_x, i_x, i_z, var_sparsity);\n    }\n    return;\n}\n/*\n------------------------------------------------------------------------------\n{xrst_begin var_load_rev_hes dev}\n\nReverse Hessian Sparsity for Load a VecAD Element\n#################################################\n\nv, x, y, z\n**********\nsee\n:ref:`var_load_op@v` ,\n:ref:`var_load_op@x` ,\n:ref:`var_load_op@y` ,\n:ref:`var_load_op@z`\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_LOAD_REV_HES\n    // END_LOAD_REV_HES\n}\n\nop_code, num_vecad_ind, i_z, arg\n********************************\nsee :ref:`var_load_op@op_code` ,\n:ref:`var_load_op@num_vecad_ind` ,\n:ref:`var_load_op@i_z` ,\n:ref:`var_load_op@arg` .\n\nVector_set\n**********\nis the type used for vectors of sets. It must satisfy the\n:ref:`SetVector-name` concept.\n\nvecad_ind\n*********\nis a vector with size *num_vec_ind* .\nWe use the notation *i_v* defined by\n\n|tab| *i_v* = vecad_ind[ arg[0] - 1 ]\n\nThis is the index of the VecAD vector and is less than the number of\nVecAD vectors in the recording.\nIt is also the index of the hessian\nsparsity pattern for *v* in *vecad_sparsity*.\n\nvar_sparsity\n************\nThe set with index *i_z* in *var_sparsity\nis the hessian sparsity pattern for the variable *z*.\n\nvecad_sparsity\n**************\nThe set with index *i_v* in *vecad_sparsity\nis the hessian sparsity pattern for the vector *v*.\nThe sparsity pattern for *z* is added to the sparsity pattern for *v* .\n\nvar_rev_jac\n***********\nIf the scalar function has non-zero partial w.r.t *z* ,\nthe *i_z* component of this vector is true.\n\nvecad_rev_jac\n*************\nIf the scalar function has non-zero partial w.r.t *z* ,\nthe *i_v* component of *vecad_rev_jac* is set to true.\n\n{xrst_end var_load_rev_hes}\n*/\n// BEGIN_LOAD_REV_HES\ntemplate <class Vector_set>\ninline void load_rev_hes(\n    op_code_var               op_code        ,\n    const addr_t*             arg            ,\n    size_t                    num_vecad_ind  ,\n    size_t                    i_z            ,\n    const pod_vector<size_t>& vecad_ind      ,\n    const Vector_set&         var_sparsity   ,\n    Vector_set&               vecad_sparsity ,\n    const bool*               var_rev_jac    ,\n    pod_vector<bool>&         vecad_rev_jac  )\n// END_LOAD_REV_HES\n{  //\n    //\n    CPPAD_ASSERT_NARG_NRES(op_code, 3, 1);\n    CPPAD_ASSERT_UNKNOWN( 0 < arg[0] );\n    CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_vecad_ind );\n    CPPAD_ASSERT_UNKNOWN( vecad_ind.size() == num_vecad_ind );\n    //\n    // i_v\n    size_t i_v = vecad_ind[ arg[0] - 1 ];\n    CPPAD_ASSERT_UNKNOWN( i_v < vecad_sparsity.n_set() );\n    //\n    // vecad_sparsity[i_v]\n    vecad_sparsity.binary_union(i_v, i_v, i_z, var_sparsity);\n    //\n    // vecad_rev_jac[iv]\n    vecad_rev_jac[i_v] |= var_rev_jac[i_z];\n    //\n    return;\n}\n/*\n------------------------------------------------------------------------------\n{xrst_begin var_load_for_hes dev}\n\nForward Hessian Sparsity for Load a VecAD Element\n#################################################\n\nv, x, y, z\n**********\nsee\n:ref:`var_load_op@v` ,\n:ref:`var_load_op@x` ,\n:ref:`var_load_op@y` ,\n:ref:`var_load_op@z`\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_LOAD_FOR_HES\n    // END_LOAD_FOR_HES\n}\n\nop_code, num_vecad_ind, i_z, arg\n********************************\nsee :ref:`var_load_op@op_code` ,\n:ref:`var_load_op@num_vecad_ind` ,\n:ref:`var_load_op@i_z` ,\n:ref:`var_load_op@arg` .\n\nVector_set\n**********\nis the type used for vectors of sets. It must satisfy the\n:ref:`SetVector-name` concept.\n\nn\n*\nis the number of independent variables on the tape.\n\nvecad_ind\n*********\nis a vector with size *num_vec_ind* .\nWe use the notation *i_v* defined by\n\n|tab| *i_v* = vecad_ind[ arg[0] - 1 ]\n\nThis is the index of the VecAD vector and is less than the number of\nVecAD vectors in the recording.\nIt is also the index of the hessian\nsparsity pattern for *v* in *vecad_sparsity*.\n\nvecad_sparsity\n**************\nThe set with index *i_v* in *vecad_sparsity\nis the forward Jacobian sparsity pattern for the vector *v*.\n\nfor_hes_sparse\n**************\nsee :ref:`local_sweep_for_hes@for_hes_sparse` .\n\n{xrst_end var_load_for_hes}\n*/\n// BEGIN_LOAD_FOR_HES\ntemplate <class Vector_set>\ninline void load_for_hes(\n    op_code_var               op_code        ,\n    const addr_t*             arg            ,\n    size_t                    num_vecad_ind  ,\n    size_t                    i_z            ,\n    size_t                    n              ,\n    const pod_vector<size_t>& vecad_ind      ,\n    const Vector_set&         vecad_sparsity ,\n    Vector_set&               for_hes_sparse )\n// END_LOAD_FOR_HES\n{   //\n    //\n    CPPAD_ASSERT_NARG_NRES(op_code, 3, 1);\n    CPPAD_ASSERT_UNKNOWN( 0 < arg[0] );\n    CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_vecad_ind );\n    CPPAD_ASSERT_UNKNOWN( vecad_ind.size() == num_vecad_ind );\n    //\n    // np1\n    size_t np1 = n + 1;\n    CPPAD_ASSERT_UNKNOWN( for_hes_sparse.end() == np1 );\n    //\n    // i_v\n    size_t i_v = vecad_ind[ arg[0] - 1 ];\n    CPPAD_ASSERT_UNKNOWN( i_v < vecad_sparsity.n_set() );\n    //\n    // for_hes_sparse\n    // set Jacobian sparsity for variable with index i_z\n    for_hes_sparse.assignment(np1 + i_z, i_v, vecad_sparsity);\n    //\n    return;\n}\n\n\n} } } // END namespace\n# endif\n"
  },
  {
    "path": "include/cppad/local/var_op/log1p_op.hpp",
    "content": "# ifndef CPPAD_LOCAL_VAR_OP_LOG1P_OP_HPP\n# define CPPAD_LOCAL_VAR_OP_LOG1P_OP_HPP\n\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\nnamespace CppAD { namespace local { namespace var_op {\n\ntemplate <class Base>\ninline void log1p_forward_any(\n    size_t        order_low   ,\n    size_t        order_up    ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // p, q\n    size_t p = order_low;\n    size_t q = order_up;\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    size_t k;\n\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(Log1pOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(Log1pOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n    CPPAD_ASSERT_UNKNOWN( p <= q );\n\n    // Taylor coefficients corresponding to argument and result\n    Base* x = taylor + i_x * cap_order;\n    Base* z = taylor + i_z * cap_order;\n\n    if( p == 0 )\n    {   z[0] = log1p( x[0] );\n        p++;\n        if( q == 0 )\n            return;\n    }\n    if ( p == 1 )\n    {   z[1] = x[1] / (Base(1.0) + x[0]);\n        p++;\n    }\n    for(size_t j = p; j <= q; j++)\n    {\n        z[j] = -z[1] * x[j-1];\n        for(k = 2; k < j; k++)\n            z[j] -= Base(double(k)) * z[k] * x[j-k];\n        z[j] /= Base(double(j));\n        z[j] += x[j];\n        z[j] /= (Base(1.0) + x[0]);\n    }\n}\n\ntemplate <class Base>\ninline void log1p_forward_dir(\n    size_t        order_up    ,\n    size_t        n_dir       ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // q, r\n    size_t q = order_up;\n    size_t r = n_dir;\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(Log1pOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(Log1pOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( 0 < q );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n\n    // Taylor coefficients corresponding to argument and result\n    size_t num_taylor_per_var = (cap_order-1) * r + 1;\n    Base* x = taylor + i_x * num_taylor_per_var;\n    Base* z = taylor + i_z * num_taylor_per_var;\n\n    size_t m = (q-1) * r + 1;\n    for(size_t ell = 0; ell < r; ell++)\n    {   z[m+ell] = Base(double(q)) * x[m+ell];\n        for(size_t k = 1; k < q; k++)\n            z[m+ell] -= Base(double(k)) * z[(k-1)*r+1+ell] * x[(q-k-1)*r+1+ell];\n        z[m+ell] /= (Base(double(q)) + Base(q) * x[0]);\n    }\n}\n\ntemplate <class Base>\ninline void log1p_forward_0(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{   //\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(Log1pOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(Log1pOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( 0 < cap_order );\n\n    // Taylor coefficients corresponding to argument and result\n    Base* x = taylor + i_x * cap_order;\n    Base* z = taylor + i_z * cap_order;\n\n    z[0] = log1p( x[0] );\n}\n\n\ntemplate <class Base>\ninline void log1p_reverse(\n    size_t        i_z          ,\n    const addr_t* arg          ,\n    size_t        cap_order    ,\n    const Base*   taylor       ,\n    size_t        n_order      ,\n    Base*         partial      )\n{   // d  //\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    size_t d = n_order - 1;\n    //\n    size_t j, k;\n\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(Log1pOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(Log1pOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( n_order <= cap_order );\n\n    // Taylor coefficients and partials corresponding to argument\n    const Base* x  = taylor  + i_x * cap_order;\n    Base* px       = partial + i_x * n_order;\n\n    // Taylor coefficients and partials corresponding to result\n    const Base* z  = taylor  + i_z * cap_order;\n    Base* pz       = partial + i_z * n_order;\n\n    Base inv_1px0 = Base(1.0) / (Base(1) + x[0]);\n\n    j = d;\n    while(j)\n    {   // scale partial w.r.t z[j]\n        pz[j]   = azmul(pz[j]   , inv_1px0);\n\n        px[0]   -= azmul(pz[j], z[j]);\n        px[j]   += pz[j];\n\n        // further scale partial w.r.t. z[j]\n        pz[j]   /= Base(double(j));\n\n        for(k = 1; k < j; k++)\n        {   pz[k]   -= Base(double(k)) * azmul(pz[j], x[j-k]);\n            px[j-k] -= Base(double(k)) * azmul(pz[j], z[k]);\n        }\n        --j;\n    }\n    px[0] += azmul(pz[0], inv_1px0);\n}\n\n} } } // END namespace\n# endif\n"
  },
  {
    "path": "include/cppad/local/var_op/log_op.hpp",
    "content": "# ifndef CPPAD_LOCAL_VAR_OP_LOG_OP_HPP\n# define CPPAD_LOCAL_VAR_OP_LOG_OP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\nnamespace CppAD { namespace local { namespace var_op {\n\n// See dev documentation: forward_unary_op\ntemplate <class Base>\ninline void log_forward_any(\n    size_t        order_low   ,\n    size_t        order_up    ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // p, q\n    size_t p = order_low;\n    size_t q = order_up;\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    size_t k;\n\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(LogOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(LogOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n    CPPAD_ASSERT_UNKNOWN( p <= q );\n\n    // Taylor coefficients corresponding to argument and result\n    Base* x = taylor + i_x * cap_order;\n    Base* z = taylor + i_z * cap_order;\n\n    if( p == 0 )\n    {   z[0] = log( x[0] );\n        p++;\n        if( q == 0 )\n            return;\n    }\n    if ( p == 1 )\n    {   z[1] = x[1] / x[0];\n        p++;\n    }\n    for(size_t j = p; j <= q; j++)\n    {\n        z[j] = -z[1] * x[j-1];\n        for(k = 2; k < j; k++)\n            z[j] -= Base(double(k)) * z[k] * x[j-k];\n        z[j] /= Base(double(j));\n        z[j] += x[j];\n        z[j] /= x[0];\n    }\n}\n\n// See dev documentation: forward_unary_op\ntemplate <class Base>\ninline void log_forward_dir(\n    size_t        order_up    ,\n    size_t        n_dir       ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // q, r\n    size_t q = order_up;\n    size_t r = n_dir;\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(LogOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(LogOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( 0 < q );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n\n    // Taylor coefficients corresponding to argument and result\n    size_t num_taylor_per_var = (cap_order-1) * r + 1;\n    Base* x = taylor + i_x * num_taylor_per_var;\n    Base* z = taylor + i_z * num_taylor_per_var;\n\n    size_t m = (q-1) * r + 1;\n    for(size_t ell = 0; ell < r; ell++)\n    {   z[m+ell] = Base(double(q)) * x[m+ell];\n        for(size_t k = 1; k < q; k++)\n            z[m+ell] -= Base(double(k)) * z[(k-1)*r+1+ell] * x[(q-k-1)*r+1+ell];\n        z[m+ell] /= (Base(double(q)) * x[0]);\n    }\n}\n\n// See dev documentation: forward_unary_op\ntemplate <class Base>\ninline void log_forward_0(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{   //\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(LogOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(LogOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( 0 < cap_order );\n\n    // Taylor coefficients corresponding to argument and result\n    Base* x = taylor + i_x * cap_order;\n    Base* z = taylor + i_z * cap_order;\n\n    z[0] = log( x[0] );\n}\n\n\n// See dev documentation: reverse_unary_op\ntemplate <class Base>\ninline void log_reverse(\n    size_t        i_z          ,\n    const addr_t* arg          ,\n    size_t        cap_order    ,\n    const Base*   taylor       ,\n    size_t        n_order      ,\n    Base*         partial      )\n{   // d  //\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    size_t d = n_order - 1;\n    //\n    size_t j, k;\n\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(LogOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(LogOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( n_order <= cap_order );\n\n    // Taylor coefficients and partials corresponding to argument\n    const Base* x  = taylor  + i_x * cap_order;\n    Base* px       = partial + i_x * n_order;\n\n    // Taylor coefficients and partials corresponding to result\n    const Base* z  = taylor  + i_z * cap_order;\n    Base* pz       = partial + i_z * n_order;\n\n    Base inv_x0 = Base(1.0) / x[0];\n\n    j = d;\n    while(j)\n    {   // scale partial w.r.t z[j]\n        pz[j]   = azmul(pz[j]   , inv_x0);\n\n        px[0]   -= azmul(pz[j], z[j]);\n        px[j]   += pz[j];\n\n        // further scale partial w.r.t. z[j]\n        pz[j]   /= Base(double(j));\n\n        for(k = 1; k < j; k++)\n        {   pz[k]   -= Base(double(k)) * azmul(pz[j], x[j-k]);\n            px[j-k] -= Base(double(k)) * azmul(pz[j], z[k]);\n        }\n        --j;\n    }\n    px[0] += azmul(pz[0], inv_x0);\n}\n\n} } } // END namespace\n# endif\n"
  },
  {
    "path": "include/cppad/local/var_op/mul_op.hpp",
    "content": "# ifndef CPPAD_LOCAL_VAR_OP_MUL_OP_HPP\n# define CPPAD_LOCAL_VAR_OP_MUL_OP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\nnamespace CppAD { namespace local { namespace var_op {\n\n// --------------------------- Mulvv -----------------------------------------\n\n// See dev documentation: forward_binary_op\ntemplate <class Base>\ninline void mulvv_forward_any(\n    size_t        order_low   ,\n    size_t        order_up    ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // p, q\n    size_t p = order_low;\n    size_t q = order_up;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(MulvvOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(MulvvOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n    CPPAD_ASSERT_UNKNOWN( p <= q );\n\n    // Taylor coefficients corresponding to arguments and result\n    Base* x = taylor + size_t(arg[0]) * cap_order;\n    Base* y = taylor + size_t(arg[1]) * cap_order;\n    Base* z = taylor + i_z    * cap_order;\n\n    size_t k;\n    for(size_t d = p; d <= q; d++)\n    {   z[d] = Base(0.0);\n        for(k = 0; k <= d; k++)\n            z[d] += x[d-k] * y[k];\n    }\n}\n\n// See dev documentation: forward_binary_op\ntemplate <class Base>\ninline void mulvv_forward_dir(\n    size_t        order_up    ,\n    size_t        n_dir       ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // q, r\n    size_t q = order_up;\n    size_t r = n_dir;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(MulvvOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(MulvvOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( 0 < q );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n\n    // Taylor coefficients corresponding to arguments and result\n    size_t num_taylor_per_var = (cap_order-1) * r + 1;\n    Base* x = taylor + size_t(arg[0]) * num_taylor_per_var;\n    Base* y = taylor + size_t(arg[1]) * num_taylor_per_var;\n    Base* z = taylor +    i_z * num_taylor_per_var;\n\n    size_t k, ell, m;\n    for(ell = 0; ell < r; ell++)\n    {   m = (q-1)*r + ell + 1;\n        z[m] = x[0] * y[m] + x[m] * y[0];\n        for(k = 1; k < q; k++)\n            z[m] += x[(q-k-1)*r + ell + 1] * y[(k-1)*r + ell + 1];\n    }\n}\n\n\n// See dev documentation: forward_binary_op\ntemplate <class Base>\ninline void mulvv_forward_0(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{   //\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(MulvvOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(MulvvOp) == 1 );\n\n    // Taylor coefficients corresponding to arguments and result\n    Base* x = taylor + size_t(arg[0]) * cap_order;\n    Base* y = taylor + size_t(arg[1]) * cap_order;\n    Base* z = taylor + i_z    * cap_order;\n\n    z[0] = x[0] * y[0];\n}\n\n\n// See dev documentation: reverse_binary_op\ntemplate <class Base>\ninline void mulvv_reverse(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    const Base*   taylor      ,\n    size_t        n_order     ,\n    Base*         partial     )\n{   // d\n    //\n    size_t d = n_order - 1;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(MulvvOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(MulvvOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( n_order <= cap_order );\n\n    // Arguments\n    const Base* x  = taylor + size_t(arg[0]) * cap_order;\n    const Base* y  = taylor + size_t(arg[1]) * cap_order;\n\n    // Partial derivatives corresponding to arguments and result\n    Base* px = partial + size_t(arg[0]) * n_order;\n    Base* py = partial + size_t(arg[1]) * n_order;\n    Base* pz = partial + i_z    * n_order;\n\n\n    // number of indices to access\n    size_t j = d + 1;\n    size_t k;\n    while(j)\n    {   --j;\n        for(k = 0; k <= j; k++)\n        {\n            // must use azmul because pz[j] = 0 may mean that this\n            // component of the function was not selected.\n            px[j-k] += azmul(pz[j], y[k]);\n            py[k]   += azmul(pz[j], x[j-k]);\n        }\n    }\n}\n// --------------------------- Mulpv -----------------------------------------\n\n// See dev documentation: forward_binary_op\ntemplate <class Base>\ninline void mulpv_forward_any(\n    size_t        order_low   ,\n    size_t        order_up    ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // p, q\n    size_t p = order_low;\n    size_t q = order_up;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(MulpvOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(MulpvOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n    CPPAD_ASSERT_UNKNOWN( p <= q );\n\n    // Taylor coefficients corresponding to arguments and result\n    Base* y = taylor + size_t(arg[1]) * cap_order;\n    Base* z = taylor + i_z    * cap_order;\n\n    // Paraemter value\n    Base x = parameter[ arg[0] ];\n\n    for(size_t d = p; d <= q; d++)\n        z[d] = x * y[d];\n}\n\n// See dev documentation: forward_binary_op\ntemplate <class Base>\ninline void mulpv_forward_dir(\n    size_t        order_up    ,\n    size_t        n_dir       ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // q, r\n    size_t q = order_up;\n    size_t r = n_dir;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(MulpvOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(MulpvOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( 0 < q );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n\n    // Taylor coefficients corresponding to arguments and result\n    size_t num_taylor_per_var = (cap_order-1) * r + 1;\n    size_t m                  = (q-1) * r + 1;\n    Base* y = taylor + size_t(arg[1]) * num_taylor_per_var + m;\n    Base* z = taylor + i_z    * num_taylor_per_var + m;\n\n    // Paraemter value\n    Base x = parameter[ arg[0] ];\n\n    for(size_t ell = 0; ell < r; ell++)\n        z[ell] = x * y[ell];\n}\n\n// See dev documentation: forward_binary_op\ntemplate <class Base>\ninline void mulpv_forward_0(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{   //\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(MulpvOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(MulpvOp) == 1 );\n\n    // Paraemter value\n    Base x = parameter[ arg[0] ];\n\n    // Taylor coefficients corresponding to arguments and result\n    Base* y = taylor + size_t(arg[1]) * cap_order;\n    Base* z = taylor + i_z    * cap_order;\n\n    z[0] = x * y[0];\n}\n\n\n// See dev documentation: reverse_binary_op\ntemplate <class Base>\ninline void mulpv_reverse(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    const Base*   taylor      ,\n    size_t        n_order     ,\n    Base*         partial     )\n{   // d\n    //\n    size_t d = n_order - 1;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(MulpvOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(MulpvOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( n_order <= cap_order );\n\n    // Arguments\n    Base x  = parameter[ arg[0] ];\n\n    // Partial derivatives corresponding to arguments and result\n    Base* py = partial + size_t(arg[1]) * n_order;\n    Base* pz = partial + i_z    * n_order;\n\n    // number of indices to access\n    size_t j = d + 1;\n    while(j)\n    {   --j;\n        // must use azmul because pz[j] = 0 may mean that this\n        // component of the function was not selected.\n        py[j] += azmul(pz[j], x);\n    }\n}\n\n\n} } } // END namespace\n# endif\n"
  },
  {
    "path": "include/cppad/local/var_op/neg_op.hpp",
    "content": "# ifndef CPPAD_LOCAL_VAR_OP_NEG_OP_HPP\n# define CPPAD_LOCAL_VAR_OP_NEG_OP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\nnamespace CppAD { namespace local { namespace var_op {\ntemplate <class Base>\n\n// See forward_unary1_op in developer documentation\ninline void neg_forward_any(\n    size_t        order_low   ,\n    size_t        order_up    ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // p, q\n    size_t p = order_low;\n    size_t q = order_up;\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    // check assumptions\n    CPPAD_ASSERT_NARG_NRES( NegOp, 1, 1 );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n    CPPAD_ASSERT_UNKNOWN( p <= q );\n\n    // Taylor coefficients corresponding to argument and result\n    Base* x = taylor + i_x * cap_order;\n    Base* z = taylor + i_z * cap_order;\n\n    for(size_t k = p; k <= q; k++)\n        z[k] = - x[k];\n}\n\n// See forward_unary1_op_dir in  developer documentation\n// See dev documentation: forward_unary_op\ntemplate <class Base>\ninline void neg_forward_dir(\n    size_t        order_up    ,\n    size_t        n_dir       ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // q, r\n    size_t q = order_up;\n    size_t r = n_dir;\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n\n    // check assumptions\n    CPPAD_ASSERT_NARG_NRES( NegOp, 1, 1 );\n    CPPAD_ASSERT_UNKNOWN( 0 < q );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n\n    // Taylor coefficients corresponding to argument and result\n    size_t num_taylor_per_var = (cap_order-1) * r + 1;\n    Base* x = taylor + i_x * num_taylor_per_var;\n    Base* z = taylor + i_z * num_taylor_per_var;\n\n    size_t m = (q-1) * r + 1;\n    for(size_t ell = 0; ell < r; ell++)\n        z[m+ell] = - x[m+ell];\n}\n\n// See forward_unary1_op_0 in developer documentation\n// See dev documentation: forward_unary_op\ntemplate <class Base>\ninline void neg_forward_0(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{   //\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n\n    // check assumptions\n    CPPAD_ASSERT_NARG_NRES( NegOp, 1, 1 );\n    CPPAD_ASSERT_UNKNOWN( 0 < cap_order );\n\n    // Taylor coefficients corresponding to argument and result\n    Base* x = taylor + i_x * cap_order;\n    Base* z = taylor + i_z * cap_order;\n\n    z[0] = - x[0];\n}\n\n// See reverse_unary1_op in developer documentation\n// See dev documentation: reverse_unary_op\ntemplate <class Base>\ninline void neg_reverse(\n    size_t        i_z          ,\n    const addr_t* arg          ,\n    size_t        cap_order    ,\n    const Base*   taylor       ,\n    size_t        n_order      ,\n    Base*         partial      )\n{   // d  //\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    size_t d = n_order - 1;\n    //\n    // check assumptions\n    CPPAD_ASSERT_NARG_NRES( NegOp, 1, 1 );\n    CPPAD_ASSERT_UNKNOWN( n_order <= cap_order );\n\n    // Taylor coefficients and partials corresponding to argument\n    Base* px       = partial + i_x * n_order;\n\n    // Taylor coefficients and partials corresponding to result\n    Base* pz       = partial + i_z * n_order;\n\n    Base neg_one   = Base(-1.0);\n    for(size_t k = 0; k <= d; ++k)\n        px[k]  += azmul(pz[k], neg_one);\n\n}\n\n} } } // END namespace\n# endif\n"
  },
  {
    "path": "include/cppad/local/var_op/one_var.hpp",
    "content": "# ifndef CPPAD_LOCAL_VAR_OP_ONE_VAR_HPP\n# define CPPAD_LOCAL_VAR_OP_ONE_VAR_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n// BEGIN_CPPAD_LOCAL_SPARSE_NAMESPACE\nnamespace CppAD { namespace local { namespace var_op {\n\n/*\n{xrst_begin_parent var_one_var dev}\n\nSparsity Calculations for Operators With One Variable\n#####################################################\n\nUnary Operators\n***************\n| *z* = *Fun* ( *x* )\n\nSee :ref:`var_unary_op@Fun` for unary operators\nfor some of the possible values of *Fun* and the corresponding operators.\n\nBinary Operators\n****************\n| *z* = *fun* ( *x* , *y* )\n| *z* = *x*  *Op* *y*\n\n\nSee :ref:`var_binary_op@Fun` for binary operators,\nrestricted to the case where just *x* or just *y* is a variable,\nfor some of the possible values of *Fun* and the corresponding operators.\n\nx\n*\nis the first operand for this operator .\n\ny\n*\nis the second operand for this operator\n\nz\n*\nis the primary result for this operator.\n\nVector_set\n**********\nis the type used for vectors of sets. It must satisfy the\n:ref:`SetVector-name` concept.\n\ni_z\n***\nis the variable index corresponding to *z* .\n\ni_v\n***\nis the variable index corresponding to the argument that is a variable.\n\n{xrst_end var_one_var}\n------------------------------------------------------------------------------\n{xrst_begin var_one_var_for_jac dev}\n\nForward Jacobian Sparsity for One Variable Argument Operators\n#############################################################\n\nx, y, z\n*******\nsee\n:ref:`var_one_var@x` ,\n:ref:`var_one_var@y` ,\n:ref:`var_one_var@z`\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_ONE_VAR_FOR_JAC\n    // END_ONE_VAR_FOR_JAC\n}\n\nVector_set, i_z, i_v\n********************\nsee\n:ref:`var_one_var@Vector_set` ,\n:ref:`var_one_var@i_z` ,\n:ref:`var_one_var@i_v`\n\nsparsity\n********\n\nInput\n=====\nfor *j* < *i_z*  and *j* not an auxiliary result,\nthe set with index *j* in *sparsity* is\nthe Jacobian sparsity for the variable with index *j* .\n\nOutput\n======\nThe set with index *i_z* in *sparsity* is\nthe Jacobian sparsity for the variable *z* .\n\n{xrst_end var_one_var_for_jac}\n*/\n// BEGIN_ONE_VAR_FOR_JAC\ntemplate <class Vector_set>\nvoid one_var_for_jac(\n    size_t            i_z           ,\n    size_t            i_v           ,\n    Vector_set&       sparsity      )\n// END_ONE_VAR_FOR_JAC\n{\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( i_v < i_z );\n\n    sparsity.assignment(i_z, i_v, sparsity);\n}\n/*\n------------------------------------------------------------------------------\n{xrst_begin var_one_var_rev_jac dev}\n\nReverse Jacobian Sparsity for One Variable Argument Operators\n#############################################################\n\nx, y, z\n*******\nsee\n:ref:`var_one_var@x` ,\n:ref:`var_one_var@y` ,\n:ref:`var_one_var@z`\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_ONE_VAR_REV_JAC\n    // END_ONE_VAR_REV_JAC\n}\n\nVector_set, i_z, i_v\n********************\nsee\n:ref:`var_one_var@Vector_set` ,\n:ref:`var_one_var@i_z` ,\n:ref:`var_one_var@i_v`\n\nsparsity\n********\nUse z(v) to denote the variable *z* as a function of the variable *v*\nand define H in terms of G by::\n\n    H( v , u , ... ) = G[ z(v) , u , ... ]\n\nOn input, *sparsity* is a sparsity pattern for the Jacobian of *G* .\nUpon return, *sparsity* is a sparsity pattern for the Jacobian of *H* .\n\n{xrst_end var_one_var_rev_jac}\n*/\n// BEGIN_ONE_VAR_REV_JAC\ntemplate <class Vector_set>\nvoid one_var_rev_jac(\n    size_t            i_z         ,\n    size_t            i_v         ,\n    Vector_set&       sparsity    )\n// END_ONE_VAR_REV_JAC\n{\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( i_v < i_z );\n\n    sparsity.binary_union(i_v, i_v, i_z, sparsity);\n\n    return;\n}\n// ---------------------------------------------------------------------------\n/*\n{xrst_begin var_one_var_rev_hes dev}\n\nReverse Jacobian Sparsity for One Variable Argument Operators\n#############################################################\n\nx, y, z\n*******\nsee\n:ref:`var_one_var@x` ,\n:ref:`var_one_var@y` ,\n:ref:`var_one_var@z`\n\nG and H\n*******\nUse :math:`z(v)` to denote the variable *z* as a function of the variable *v* .\nWe use :math:`G( z, v, \\ldots )` to denote a function of the variables\nup to and including *z* .\nWe define :math:`H(v, \\ldost)` by\n\n.. math::\n\n    H(v, \\cdots ) = G [ z(v) , v , \\cdots ]\n\nnum_var\n*******\nWe use the notation *num_var* for the number of variables on the tape\n(including the phantom variable at index zero).\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_ONE_VAR_REV_HES\n    // END_ONE_VAR_REV_HES\n}\n\nVector_set, i_z, i_v\n********************\nsee\n:ref:`var_one_var@Vector_set` ,\n:ref:`var_one_var@i_z` ,\n:ref:`var_one_var@i_v`\n\nlinear[0]\n*********\nThis value is true (false) if the :math:`z(v)`\nmust have zero second derivative (may have non-zero second derivative).\n\nfor_jac_sparsity\n****************\nThe set with index *j* is the forward Jacobian sparsity\npattern for the variable with index *j*.\n\nrev_jac_include\n***************\nIf the *j* element of this vector is true,\nthe variable with index *j* is included in the Hessian,\nor affects the value of a variable that is included in the Hessian.\n\nInput\n=====\n::\n\n    for j = num_var, ... , i_z + 1\n        rev_jac_include[j] is an input\n\nOutput\n======\nrev_jac_include[i_z] is an output\n\nrev_hes_sparsity\n****************\nOn input (output), this is the sparsity pattern for *G* ( *H* ).\nFor each variable index *j* ,\n*rev_hes_sparsity* [ *j* ] is the set of indices\nthat may have non-zero cross partials with variable index *j* .\n\nExample\n=======\nIf the indices in the sets correspond to the independent variables,\nthen *rev_hes_sparsity* ``.end()`` is the number of independent variables.\nFor *i* a variable index between 1 and the number of independent variables,\n*i* - 1 is the corresponding independent variable index.\n(The index *i* = 0 corresponds to the phantom variable at the beginning\nof the tape. )\n{xrst_end var_one_var_rev_hes}\n*/\n// BEGIN_ONE_VAR_REV_HES\ntemplate <class Vector_set>\nvoid one_var_rev_hes(\n    size_t              i_z               ,\n    size_t              i_v               ,\n    bool*               linear            ,\n    bool*               rev_jacobian      ,\n    const Vector_set&   for_jac_sparsity  ,\n    Vector_set&         rev_hes_sparsity  )\n// END_ONE_VAR_REV_HES\n{\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( i_v < i_z );\n\n    // check for no effect\n    if( ! rev_jacobian[i_z] )\n        return;\n\n    rev_hes_sparsity.binary_union(i_v, i_v, i_z, rev_hes_sparsity);\n    if( ! linear[0] )\n        rev_hes_sparsity.binary_union(i_v, i_v, i_v, for_jac_sparsity);\n\n    rev_jacobian[i_v] = true;\n    return;\n}\n// ---------------------------------------------------------------------------\n/*\n{xrst_begin var_one_var_for_hes dev}\n\nForward Hessian Sparsity for One Variable Argument Operators\n############################################################\n\nx, y, z\n*******\nsee\n:ref:`var_one_var@x` ,\n:ref:`var_one_var@y` ,\n:ref:`var_one_var@z`\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_ONE_VAR_FOR_HES\n    // END_ONE_VAR_FOR_HES\n}\n\nVector_set, i_z, i_v\n********************\nsee\n:ref:`var_one_var@Vector_set` ,\n:ref:`var_one_var@i_z` ,\n:ref:`var_one_var@i_v`\n\n\nlinear[0]\n*********\nThis value is true (false) if the :math:`z(v)`\nmust have zero second derivative (may have non-zero second derivative).\n\n\nn_independent_p1\n****************\nis the number of independent variables (in the tape) plus one.\n\nnum_var\n*******\nThis is the total number of variables in the tape\n(counting the phantom variable at index zero).\n\nfor_sparsity\n************\nOn input, all the linear and nonlinear interactions up to the\narguments to the atomic function have been take into account.\nUpon return, the linear and nonlinear interactions in\nthe atomic function have been take into account.\n\nHessian Sparsity\n================\nFor *j* equal 1 to *n_independent_p1* - 1,\nif *i* is in set with index *j* ,\nthe Hessian may have a non-zero partial with respect to the\nindependent variables with indices ( *i* - 1, *j* - 1 ) .\nNote that the index zero is not used because it corresponds to the\nphantom variable on the tape.\n\nJacobian Sparsity\n=================\nIf *i* is in the set with index *n_independent_p1* + *j* ,\nthe variable with index *j* may have a non-zero partial with resect to the\nindependent variable with index *i* - 1 .\n\n{xrst_end var_one_var_for_hes}\n*/\n// BEGIN_ONE_VAR_FOR_HES\ntemplate <class Vector_set>\nvoid one_var_for_hes(\n    size_t              n_independent_p1 ,\n    size_t              num_var          ,\n    size_t              i_z              ,\n    size_t              i_v              ,\n    bool*               linear           ,\n    Vector_set&         for_sparsity     )\n// END_ONE_VAR_FOR_HES\n{   // np1\n    size_t np1 = n_independent_p1;\n    //\n    CPPAD_ASSERT_UNKNOWN( i_v < i_z );\n    CPPAD_ASSERT_UNKNOWN( i_v < num_var );\n    CPPAD_ASSERT_UNKNOWN( for_sparsity.end() == np1 );\n    CPPAD_ASSERT_UNKNOWN( for_sparsity.n_set() == np1 + num_var );\n    CPPAD_ASSERT_UNKNOWN( for_sparsity.number_elements(np1) == 0 );\n\n    // for_sparsity\n    // set Jacobian sparsity for z\n    for_sparsity.assignment(np1 + i_z, np1 + i_v, for_sparsity);\n\n    //\n    if( ! linear[0] )\n    {   // itr\n        // set of independent variables that v depends on\n        typename Vector_set::const_iterator itr(for_sparsity, i_v + np1);\n        //\n        // i_x\n        // loop over independent variables that v has non-zero partials w.r.t.\n        size_t i_x = *itr;\n        while( i_x < np1 )\n        {   // for_sparsity\n            // union of Hessian sparsity for x and Jacobian sparsity for v\n            for_sparsity.binary_union(i_x, i_x, i_v + np1, for_sparsity);\n            i_x = *(++itr);\n        }\n    }\n    return;\n}\n\n} } } // END_CPPAD_LOCAL_SPARSE_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/local/var_op/par_op.hpp",
    "content": "# ifndef CPPAD_LOCAL_VAR_OP_PAR_OP_HPP\n# define CPPAD_LOCAL_VAR_OP_PAR_OP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\nnamespace CppAD { namespace local { namespace var_op {\n/*\n{xrst_begin_parent var_par_op dev}\n\nCreate a Variable From a Parameter Operator\n###########################################\n\nParOp\n*****\nis the op code for this operator.\n\nPurpose\n*******\nIf one of the :ref:`dependent@y` components in an ADFun object is a parameter,\nit is converted to a variable using this operator.\n\nn_res\n*****\nThis operator has one variable result (the variable that is created).\n\ni_z\n***\nis the variable index corresponding the result of this operator.\n\narg\n***\n\narg[0]\n======\nis the index of the parameter that is converted to a variable\n\n{xrst_end var_par_op}\n------------------------------------------------------------------------------\n{xrst_begin var_par_forward_0 dev}\n\nZero Order Forward Create a Variable From a Parameter\n#####################################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_PAR_FORWARD_0\n    // END_PAR_FORWARD_0\n}\n\ni_z, arg\n********\nsee\nref:`var_par_op@i_z` ,\nref:`var_par_op@arg`\n\nnum_par\n*******\nis the total number of values in the *parameter* vector.\n\nparameter\n*********\nmaps parameter indices to parameter values .\n\ntaylor\n******\nThe Taylor coefficient corresponding to variable *i* and order *k* is\n\n    *taylor* [ *i* * *cap_order* + *k*  ]\n\nInput\n=====\nThe zero order Taylor coefficients\nfor variables with index *i* less than or equal *i_z* .\n\nOutput\n======\nThe zero order Taylor coefficients for variables with index *i_z* ; i.e.,\nthe value of the parameter.\n\n{xrst_end var_par_forward_0}\n*/\n// BEGIN_PAR_FORWARD_0\ntemplate <class Base>\ninline void par_forward_0(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        num_par     ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n// END_PAR_FORWARD_0\n{  //\n    //\n    // check assumptions\n    CPPAD_ASSERT_NARG_NRES(ParOp, 1, 1);\n    CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );\n    CPPAD_ASSERT_UNKNOWN( 0 < cap_order );\n\n    Base* z = taylor + i_z * cap_order;\n\n    z[0]  = parameter[ arg[0] ];\n}\n/*\n------------------------------------------------------------------------------\n{xrst_begin var_par_forward_any dev}\n\nAny Order Forward Create a Variable From a Parameter\n####################################################\n\nn_res\n*****\nsee\n:ref:`var_par_op@n_res` .\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_PAR_FORWARD_ANY\n    // END_PAR_FORWARD_ANY\n}\n\ni_z, arg\n********\nsee\nref:`var_par_op@i_z` ,\nref:`var_par_op@arg`\n\nnum_par\n*******\nis the total number of values in the *parameter* vector.\n\nparameter\n*********\nmaps parameter indices to parameter values .\n\n{xrst_template ;\n    include/cppad/local/var_op/template/forward_op.xrst\n    headers: cap_order, order_low, order_up, taylor\n}\n\n{xrst_end var_par_forward_any}\n*/\n// BEGIN_PAR_FORWARD_ANY\ntemplate <class Base>\ninline void par_forward_any(\n    size_t        order_low   ,\n    size_t        order_up    ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        num_par     ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n// END_PAR_FORWARD_ANY\n{  //\n    //\n    // check assumptions\n    CPPAD_ASSERT_NARG_NRES(ParOp, 1, 1);\n    CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );\n    CPPAD_ASSERT_UNKNOWN( 0 < cap_order );\n    CPPAD_ASSERT_UNKNOWN( order_low <= order_up );\n\n    Base* z = taylor + i_z * cap_order;\n    if( order_low == 0 )\n    {  z[0]  = parameter[ arg[0] ];\n        ++order_low;\n    }\n    for(size_t k = order_low; k <= order_up; ++k)\n        z[k] = Base(0.0);\n}\n/*\n------------------------------------------------------------------------------\n{xrst_begin var_par_forward_dir dev}\n\nMultiple Direction Forward Create a Variable From a Parameter\n#############################################################\n\nn_res\n*****\nsee\n:ref:`var_par_op@n_res` .\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_PAR_FORWARD_DIR\n    // END_PAR_FORWARD_DIR\n}\n\ni_z, arg\n********\nsee\nref:`var_par_op@i_z` ,\nref:`var_par_op@arg`\n\nnum_par\n*******\nis the total number of values in the *parameter* vector.\n\nparameter\n*********\nmaps parameter indices to parameter values .\n\n{xrst_template ;\n    include/cppad/local/var_op/template/forward_dir.xrst\n    headers: n_dir, cap_order, order_up, taylor\n}\n\n{xrst_end var_par_forward_dir}\n*/\n// BEGIN_PAR_FORWARD_DIR\ntemplate <class Base>\ninline void par_forward_dir(\n    size_t        order_up    ,\n    size_t        n_dir       ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        num_par     ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n// END_PAR_FORWARD_DIR\n{   //\n    //\n    // check assumptions\n    CPPAD_ASSERT_NARG_NRES(ParOp, 1, 1);\n    CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par );\n    CPPAD_ASSERT_UNKNOWN( 0 < cap_order );\n    CPPAD_ASSERT_UNKNOWN( 0 < order_up );\n\n    // per_variable\n    size_t per_variable = (cap_order - 1) * n_dir + 1;\n    //\n    // z\n    Base* z  = taylor + i_z * per_variable;\n    //\n    // m\n    size_t m = (order_up - 1) * n_dir + 1;\n    //\n    // taylor\n    for(size_t ell = 0; ell < n_dir; ++ell)\n        z[m + ell]   = Base(0.0);\n}\n\n} } } // END namespace\n# endif\n"
  },
  {
    "path": "include/cppad/local/var_op/pow_op.hpp",
    "content": "# ifndef CPPAD_LOCAL_VAR_OP_POW_OP_HPP\n# define CPPAD_LOCAL_VAR_OP_POW_OP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\nnamespace CppAD { namespace local { namespace var_op {\n/*!\n\\file pow_op.hpp\nForward and reverse mode calculations for z = pow(x, y).\n*/\n\n// --------------------------- Powvv -----------------------------------------\n/*!\nCompute forward mode Taylor coefficients for result of op = PowvvOp.\n\nIn the documentation below,\nthis operations is for the case where both x and y are variables\nand the argument parameter is not used.\n\n\\copydetails CppAD::local::forward_pow_op\n*/\n\ntemplate <class Base>\ninline void powvv_forward_any(\n    size_t        order_low   ,\n    size_t        order_up    ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // p, q\n    size_t p = order_low;\n    size_t q = order_up;\n    //\n    // convert from final result to first result\n    i_z -= 2; // 2 = NumRes(PowvvOp) - 1;\n\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(PowvvOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(PowvvOp) == 3 );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n    CPPAD_ASSERT_UNKNOWN( p <= q );\n    CPPAD_ASSERT_UNKNOWN(\n        size_t( std::numeric_limits<addr_t>::max() ) >= i_z\n    );\n\n    // z_0 = log(x)\n    log_forward_any(p, q, i_z, arg, cap_order, taylor);\n\n    // z_1 = z_0 * y\n    addr_t addr[2];\n    addr[0] = addr_t( i_z );\n    addr[1] = arg[1];\n    mulvv_forward_any(p, q, i_z+1, addr,  parameter, cap_order, taylor);\n\n    // z_2 = exp(z_1)\n    // final result for zero order case is exactly the same as for Base\n    if( p == 0 )\n    {   // Taylor coefficients corresponding to arguments and result\n        Base* x   = taylor + size_t(arg[0]) * cap_order;\n        Base* y   = taylor + size_t(arg[1]) * cap_order;\n        Base* z_2 = taylor + (i_z+2) * cap_order;\n\n        z_2[0] = pow(x[0], y[0]);\n        p++;\n    }\n    if( p <= q )\n    {   addr[0] = addr_t(i_z+1);\n        exp_forward_any(p, q, i_z+2, addr, cap_order, taylor);\n    }\n}\n/*!\nMultiple directions forward mode Taylor coefficients for op = PowvvOp.\n\nThe C++ source code corresponding to this operation is\n\\verbatim\n    z = pow(x, y)\n\\endverbatim\nIn the documentation below,\nthis operations is for the case where x is a variable and y is a parameter.\n\n\\copydetails CppAD::local::forward_pow_op_dir\n*/\n\ntemplate <class Base>\ninline void powvv_forward_dir(\n    size_t        order_up    ,\n    size_t        n_dir       ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // q, r\n    size_t q = order_up;\n    size_t r = n_dir;\n    //\n    // convert from final result to first result\n    i_z -= 2; // 2 = NumRes(PowvvOp) - 1\n\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(PowvvOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(PowvvOp) == 3 );\n    CPPAD_ASSERT_UNKNOWN( 0 < q );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n    CPPAD_ASSERT_UNKNOWN(\n        size_t( std::numeric_limits<addr_t>::max() ) >= i_z\n    );\n\n    // z_0 = log(x)\n    log_forward_dir(q, r, i_z, arg, cap_order, taylor);\n\n    // z_1 = y * z_0\n    addr_t addr[2];\n    addr[0] = addr_t( i_z );\n    addr[1] = arg[1];\n    mulvv_forward_dir(q, r, i_z+1, addr,  parameter, cap_order, taylor);\n\n    // z_2 = exp(z_1)\n    addr[0] = addr_t(i_z+1);\n    exp_forward_dir(q, r, i_z+2, addr, cap_order, taylor);\n}\n/*!\nCompute zero order forward mode Taylor coefficients for result of op = PowvvOp.\n\nThe C++ source code corresponding to this operation is\n\\verbatim\n    z = pow(x, y)\n\\endverbatim\nIn the documentation below,\nthis operations is for the case where both x and y are variables\nand the argument parameter is not used.\n\n\\copydetails CppAD::local::forward_pow_op_0\n*/\n\ntemplate <class Base>\ninline void powvv_forward_0(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{   //\n    //\n    // convert from final result to first result\n    i_z -= 2; // NumRes(PowvvOp) - 1;\n\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(PowvvOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(PowvvOp) == 3 );\n\n    // Taylor coefficients corresponding to arguments and result\n    Base* x   = taylor + size_t(arg[0]) * cap_order;\n    Base* y   = taylor + size_t(arg[1]) * cap_order;\n    Base* z_0 = taylor + i_z    * cap_order;\n    Base* z_1 = z_0    +          cap_order;\n    Base* z_2 = z_1    +          cap_order;\n\n    z_0[0] = log( x[0] );\n    z_1[0] = z_0[0] * y[0];\n    z_2[0] = pow(x[0], y[0]);\n\n}\n\n/*!\nCompute reverse mode partial derivatives for result of op = PowvvOp.\n\nThe C++ source code corresponding to this operation is\n\\verbatim\n    z = pow(x, y)\n\\endverbatim\nIn the documentation below,\nthis operations is for the case where both x and y are variables\nand the argument parameter is not used.\n\n\\copydetails CppAD::local::reverse_pow_op\n*/\n\ntemplate <class Base>\ninline void powvv_reverse(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    const Base*   taylor      ,\n    size_t        n_order     ,\n    Base*         partial     )\n{   //\n    //\n    //\n    // convert from final result to first result\n    i_z -= 2; // NumRes(PowvvOp) - 1;\n\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(PowvvOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(PowvvOp) == 3 );\n    CPPAD_ASSERT_UNKNOWN( n_order <= cap_order );\n    CPPAD_ASSERT_UNKNOWN(\n        size_t( std::numeric_limits<addr_t>::max() ) >= i_z\n    );\n\n    // z_2 = exp(z_1)\n    addr_t addr[2];\n    addr[0] = addr_t(i_z + 1);\n    exp_reverse(\n        i_z+2, addr, cap_order, taylor, n_order, partial\n    );\n\n    // z_1 = z_0 * y\n    addr[0] = addr_t( i_z );\n    addr[1] = arg[1];\n    mulvv_reverse(\n    i_z+1, addr,  parameter, cap_order, taylor, n_order, partial\n    );\n\n    // z_0 = log(x)\n    log_reverse(\n        i_z, arg, cap_order, taylor, n_order, partial\n    );\n}\n\n// --------------------------- Powpv -----------------------------------------\n/*!\nCompute forward mode Taylor coefficients for result of op = PowpvOp.\n\nThe C++ source code corresponding to this operation is\n\\verbatim\n    z = pow(x, y)\n\\endverbatim\nIn the documentation below,\nthis operations is for the case where x is a parameter and y is a variable.\n\n\\copydetails CppAD::local::forward_pow_op\n*/\n\ntemplate <class Base>\ninline void powpv_forward_any(\n    size_t        order_low   ,\n    size_t        order_up    ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // p, q\n    size_t p = order_low;\n    size_t q = order_up;\n    //\n    // convert from final result to first result\n    i_z -= 2; // 2 = NumRes(PowpvOp) - 1;\n\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(PowpvOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(PowpvOp) == 3 );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n    CPPAD_ASSERT_UNKNOWN( p <= q );\n\n    // Taylor coefficients corresponding to arguments and result\n    Base* z_0 = taylor + i_z    * cap_order;\n\n    // z_0 = log(x)\n    Base x    = parameter[ arg[0] ];\n    size_t d;\n    for(d = p; d <= q; d++)\n    {   if( d == 0 )\n            z_0[d] = log(x);\n        else\n            z_0[d] = Base(0.0);\n    }\n\n    // 2DO: remove requirement that i_z * cap_order <= max addr_t value\n    CPPAD_ASSERT_KNOWN(\n        size_t( std::numeric_limits<addr_t>::max() ) >= i_z * cap_order,\n        \"cppad_tape_addr_type maximum value has been exceeded\\n\"\n        \"This is due to a kludge in the pow operation and should be fixed.\"\n    );\n\n    // z_1 = z_0 * y\n    addr_t addr[2];\n    // offset of z_i in taylor (as if it were a parameter); i.e., log(x)\n    addr[0] = addr_t( i_z * cap_order );\n    // offset of y in taylor (as a variable)\n    addr[1] = arg[1];\n\n    // Trick: use taylor both for the parameter vector and variable values\n    mulpv_forward_any(p, q, i_z+1, addr,  taylor, cap_order, taylor);\n\n    // z_2 = exp(z_1)\n    // zero order case exactly same as Base type operation\n    if( p == 0 )\n    {   Base* y   = taylor + size_t(arg[1]) * cap_order;\n        Base* z_2 = taylor + (i_z+2) * cap_order;\n        z_2[0] = pow(x, y[0]);\n        p++;\n    }\n    if( p <= q )\n    {   addr[0] = addr_t(i_z+1);\n        exp_forward_any(p, q, i_z+2, addr, cap_order, taylor);\n    }\n}\n/*!\nMultiple directions forward mode Taylor coefficients for op = PowpvOp.\n\nThe C++ source code corresponding to this operation is\n\\verbatim\n    z = pow(x, y)\n\\endverbatim\nIn the documentation below,\nthis operations is for the case where x is a parameter and y is a variable.\n\n\\copydetails CppAD::local::forward_pow_op_dir\n*/\n\ntemplate <class Base>\ninline void powpv_forward_dir(\n    size_t        order_up    ,\n    size_t        n_dir       ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // q, r\n    size_t q = order_up;\n    size_t r = n_dir;\n    //\n    // convert from final result to first result\n    i_z -= 2; // 2 = NumRes(PowpvOp) - 1;\n\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(PowpvOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(PowpvOp) == 3 );\n    CPPAD_ASSERT_UNKNOWN( 0 < q );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n\n    // Taylor coefficients corresponding to arguments and result\n    size_t num_taylor_per_var = (cap_order-1) * r + 1;\n    Base* z_0 = taylor + i_z * num_taylor_per_var;\n\n    // z_0 = log(x)\n    size_t m  = (q-1) * r + 1;\n    for(size_t ell = 0; ell < r; ell++)\n        z_0[m+ell] = Base(0.0);\n\n    // 2DO: remove requirement i_z * num_taylor_per_var <= max addr_t value\n    CPPAD_ASSERT_KNOWN(\n        size_t( std::numeric_limits<addr_t>::max() ) >= i_z * num_taylor_per_var,\n        \"cppad_tape_addr_type maximum value has been exceeded\\n\"\n        \"This is due to a kludge in the pow operation and should be fixed.\"\n    );\n\n    // z_1 = z_0 * y\n    addr_t addr[2];\n    // offset of z_0 in taylor (as if it were a parameter); i.e., log(x)\n    addr[0] = addr_t( i_z * num_taylor_per_var );\n    // offset of y in taylor (as a variable)\n    addr[1] = arg[1];\n\n    // Trick: use taylor both for the parameter vector and variable values\n    mulpv_forward_dir(q, r, i_z+1, addr,  taylor, cap_order, taylor);\n\n    // z_2 = exp(z_1)\n    addr[0] = addr_t(i_z+1);\n    exp_forward_dir(q, r, i_z+2, addr, cap_order, taylor);\n}\n/*!\nCompute zero order forward mode Taylor coefficient for result of op = PowpvOp.\n\nThe C++ source code corresponding to this operation is\n\\verbatim\n    z = pow(x, y)\n\\endverbatim\nIn the documentation below,\nthis operations is for the case where x is a parameter and y is a variable.\n\n\\copydetails CppAD::local::forward_pow_op_0\n*/\n\ntemplate <class Base>\ninline void powpv_forward_0(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{   //\n    //\n    // convert from final result to first result\n    i_z -= 2; // NumRes(PowpvOp) - 1;\n\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(PowpvOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(PowpvOp) == 3 );\n\n    // Paraemter value\n    Base x = parameter[ arg[0] ];\n\n    // Taylor coefficients corresponding to arguments and result\n    Base* y   = taylor + size_t(arg[1]) * cap_order;\n    Base* z_0 = taylor + i_z    * cap_order;\n    Base* z_1 = z_0    +          cap_order;\n    Base* z_2 = z_1    +          cap_order;\n\n    // z_0 = log(x)\n    z_0[0] = log(x);\n\n    // z_1 = z_0 * y\n    z_1[0] = z_0[0] * y[0];\n\n    // z_2 = exp(z_1)\n    // zero order case exactly same as Base type operation\n    z_2[0] = pow(x, y[0]);\n}\n\n/*!\nCompute reverse mode partial derivative for result of op = PowpvOp.\n\nThe C++ source code corresponding to this operation is\n\\verbatim\n    z = pow(x, y)\n\\endverbatim\nIn the documentation below,\nthis operations is for the case where x is a parameter and y is a variable.\n\n\\copydetails CppAD::local::reverse_pow_op\n*/\n\ntemplate <class Base>\ninline void powpv_reverse(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    const Base*   taylor      ,\n    size_t        n_order     ,\n    Base*         partial     )\n{   //\n    //\n    //\n    // convert from final result to first result\n    i_z -= 2; // NumRes(PowpvOp) - 1;\n\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(PowvvOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(PowvvOp) == 3 );\n    CPPAD_ASSERT_UNKNOWN( n_order <= cap_order );\n\n    // z_2 = exp(z_1)\n    addr_t addr[2];\n    addr[0] = addr_t(i_z + 1);\n    exp_reverse(\n        i_z+2, addr, cap_order, taylor, n_order, partial\n    );\n\n    // 2DO: remove requirement that i_z * cap_order <= max addr_t value\n    CPPAD_ASSERT_KNOWN(\n        size_t( std::numeric_limits<addr_t>::max() ) >= i_z * cap_order,\n        \"cppad_tape_addr_type maximum value has been exceeded\\n\"\n        \"This is due to a kludge in the pow operation and should be fixed.\"\n    );\n\n    // z_1 = z_0 * y\n    addr[0] = addr_t( i_z * cap_order ); // offset of z_0[0] in taylor\n    addr[1] = arg[1];                    // index of y in taylor and partial\n    // use taylor both for parameter and variable values\n    mulpv_reverse(\n        i_z+1, addr,  taylor, cap_order, taylor, n_order, partial\n    );\n\n    // z_0 = log(x)\n    // x is a parameter\n}\n\n// --------------------------- Powvp -----------------------------------------\n/*!\nCompute forward mode Taylor coefficients for result of op = PowvpOp.\n\nThe C++ source code corresponding to this operation is\n\\verbatim\n    z = pow(x, y)\n\\endverbatim\nIn the documentation below,\nthis operations is for the case where x is a variable and y is a parameter.\n\n\\copydetails CppAD::local::forward_pow_op\n*/\n\ntemplate <class Base>\ninline void powvp_forward_any(\n    size_t        order_low   ,\n    size_t        order_up    ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // p, q\n    size_t p = order_low;\n    size_t q = order_up;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(PowvpOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(PowvpOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n    CPPAD_ASSERT_UNKNOWN( p <= q );\n    CPPAD_ASSERT_UNKNOWN(\n        size_t( std::numeric_limits<addr_t>::max() ) >= i_z\n    );\n\n    // Taylor coefficients corresponding to arguments and result\n    Base* x = taylor + size_t(arg[0]) * cap_order;\n    Base* z = taylor + i_z    * cap_order;\n\n    // Paraemter value\n    Base y = parameter[ arg[1] ];\n\n    // Special solution when x[0] is zero\n    Base b0 = Base( 0.0 );\n\n    // special case zero order\n    if( p == 0 )\n    {   z[0] = pow(x[0], y);\n        p++;\n    }\n    for(size_t j = p; j <= q; ++j)\n    {   Base sum = Base(0);\n        for(size_t k = 1; k < j; ++k)\n        {   Base bk = Base( double(k) );\n            sum += bk * (y * x[k] * z[j-k] - z[k] * x[j-k]);\n        }\n        Base bj = Base( double(j) );\n        Base zj = ( y * z[0] * x[j] + sum / bj ) / x[0];\n        z[j] = CondExpEq(x[0], b0, b0, zj);\n    }\n}\n/*!\nMultiple directions forward mode Taylor coefficients for op = PowvpOp.\n\nThe C++ source code corresponding to this operation is\n\\verbatim\n    z = pow(x, y)\n\\endverbatim\nIn the documentation below,\nthis operations is for the case where x is a variable and y is a parameter.\n\n\\copydetails CppAD::local::forward_pow_op_dir\n*/\n\ntemplate <class Base>\ninline void powvp_forward_dir(\n    size_t        order_up    ,\n    size_t        n_dir       ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // q, r\n    size_t q = order_up;\n    size_t r = n_dir;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(PowvpOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(PowvpOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( 0 < q );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n    CPPAD_ASSERT_UNKNOWN(\n        size_t( std::numeric_limits<addr_t>::max() ) >= i_z\n    );\n\n    // Taylor coefficients corresponding to arguments and result\n    size_t num_taylor_per_var = (cap_order-1) * r + 1;\n    Base* x = taylor + size_t(arg[0]) * num_taylor_per_var;\n    Base* z = taylor +    i_z * num_taylor_per_var;\n\n    // Parameter value\n    Base y = parameter[ arg[1] ];\n\n    // special solution when x[0] is zero\n    Base b0 = Base( 0.0 );\n\n    // index in Taylor coefficients where multiple directions start\n    size_t m = (q-1)*r + 1;\n    //\n    // loop over directions\n    for(size_t ell = 0; ell < r; ell++)\n    {   Base sum = Base(0);\n        for(size_t k = 1; k < q; ++k)\n        {   Base xk   = x[(k-1)*r   + ell + 1];\n            Base zk   = z[(k-1)*r   + ell + 1];\n            Base xqk  = x[(q-k-1)*r + ell + 1];\n            Base zqk  = z[(q-k-1)*r + ell + 1];\n            Base bk   = Base( double(k) );\n            sum += bk * (y * xk * zqk - zk * xqk);\n        }\n        Base xq  = x[(q-1)*r + ell + 1];\n        Base bq   = Base( double(q) );\n        Base zell = ( y * z[0] * xq + sum / bq ) / x[0];\n        z[m+ell]  = CondExpEq(x[0], b0, b0, zell);\n    }\n}\n\n/*!\nCompute zero order forward mode Taylor coefficients for result of op = PowvpOp.\n\nThe C++ source code corresponding to this operation is\n\\verbatim\n    z = pow(x, y)\n\\endverbatim\nIn the documentation below,\nthis operations is for the case where x is a variable and y is a parameter.\n\n\\copydetails CppAD::local::forward_pow_op_0\n*/\n\ntemplate <class Base>\ninline void powvp_forward_0(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{   //\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(PowvpOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(PowvpOp) == 1 );\n\n    // Paraemter value\n    Base y = parameter[ arg[1] ];\n\n    // Taylor coefficients corresponding to arguments and result\n    Base* x = taylor + size_t(arg[0]) * cap_order;\n    Base* z = taylor + i_z * cap_order;\n\n    z[0] = pow(x[0], y);\n}\n\n/*!\nCompute reverse mode partial derivative for result of op = PowvpOp.\n\nThe C++ source code corresponding to this operation is\n\\verbatim\n    z = pow(x, y)\n\\endverbatim\nIn the documentation below,\nthis operations is for the case where x is a variable and y is a parameter.\n\n\\copydetails CppAD::local::reverse_pow_op\n*/\n\ntemplate <class Base>\ninline void powvp_reverse(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    const Base*   taylor      ,\n    size_t        n_order     ,\n    Base*         partial     ,\n    CppAD::vector<Base>& work )\n{   //\n    //\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(PowvpOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(PowvpOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( n_order <= cap_order );\n    CPPAD_ASSERT_UNKNOWN(\n        size_t( std::numeric_limits<addr_t>::max() ) >= i_z\n    );\n\n    // Taylor coefficients\n    const Base* x = taylor + size_t( arg[0] ) * cap_order;\n    const Base* z = taylor + i_z * cap_order;\n\n    // parameter value\n    const Base  y = parameter[ arg[1] ];\n\n    // Partial derivatives corresponding to arguments and result\n    Base* px = partial + size_t(arg[0]) * n_order;\n    Base* pz = partial + i_z * n_order;\n\n    // Special solution when x[0] is zero\n    Base b0 = Base( 0.0 );\n\n    // Place to hold px for this operator until conditional assignment at end\n    work.resize(n_order);\n    for(size_t j = 0; j < n_order; ++j)\n        work[j] = px[j];\n\n    // reverse z^j for j = d, ..., 1\n    size_t j = n_order - 1;\n    while(j)\n    {   // j\n        Base bj = Base( double(j) );\n        //\n        // x^j term\n        work[j] += azmul(pz[j], y * z[0] / x[0]);\n        //\n        // x^k terms\n        for(size_t k = 1; k < j; ++k)\n        {   Base bk   = Base( double(k) );\n            Base term = (bk * y - Base(j-k) ) * z[j-k] / (bj * x[0]);\n            work[k] += azmul(pz[j], term);\n        }\n        //\n        // z^k terms\n        for(size_t k = 1; k < j; ++k)\n        {   Base bk   = Base( double(k) );\n            Base term = (Base(j-k) * y - bk) * x[j-k] / (bj * x[0]);\n            pz[k] += azmul(pz[j], term);\n        }\n        //\n        // x^0 term\n        work[0] -= azmul(pz[j], z[j] / x[0]);\n        //\n        // z^0 term\n        pz[0] += azmul(pz[j], y * x[j] / x[0] );\n        //\n        // next j\n        --j;\n    }\n    // reverse z^0\n    work[0] += azmul(pz[0], y * z[0] / x[0]);\n    //\n    for(j = 0; j < n_order; ++j)\n        px[j] = CondExpEq(x[0], b0, b0, work[j]);\n}\n\n} } } // END namespace\n# endif\n"
  },
  {
    "path": "include/cppad/local/var_op/pri_op.hpp",
    "content": "# ifndef CPPAD_LOCAL_VAR_OP_PRI_OP_HPP\n# define CPPAD_LOCAL_VAR_OP_PRI_OP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\nnamespace CppAD { namespace local { namespace var_op {\n/*\n{xrst_begin_parent var_pri_op dev}\n{xrst_spell\n    pos\n}\n\nPrint A Variable or Parameter Operator\n######################################\n\nPriOp\n*****\nis the op code for this operator.\n\nUser Syntax\n***********\n| ``PrintFor`` ( *pos* , *before* , *value* , *after* )\n\npos\n***\nThis value is expected to be positive and\n*value* is printed if *pos* is not positive.\n\nbefore\n******\nis the text printed before the value.\n\nvalue\n*****\nis the value that is printed.\n\nafter\n*****\nis the text printed after the value.\n\nRecBase\n*******\nis the base type use when recording this operator;\ni.e., this operation was recording using AD< *RecBase* > operations.\n\nBase\n****\nis the type used for computations by this operator.\nThis is either *RecBase* or AD< *RecBase* >.\n\narg\n***\n\narg[0]\n******\nThe first two bits of this value are used a flags; see below.\n\narg[1]\n******\nIf arg[0] & 1 is zero (is one), arg[1] is the parameter (variable) index\ncorresponding to *pos* .\n\narg[2]\n******\nis the text index corresponding to *before* .\n\narg[3]\n******\nIf arg[0] & 2 is zero (is one), arg[3] is the parameter (variable) index\ncorresponding to *value* .\n\narg[4]\n******\nis the text index corresponding to *after* .\n\n{xrst_end var_pri_op}\n------------------------------------------------------------------------------\n{xrst_begin var_pri_forward_0 dev}\n\nZero Order Forward Print A Variable or Parameter\n################################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_PRI_FORWARD_0\n    // END_PRI_FORWARD_0\n}\n\ns_out\n*****\nthe results are printed on this output stream.\n\nnum_text\n********\nis the total number of text characters on the tape\n(only used for error checking).\n\ntext\n****\nis the tape text vector.\nThe value *before* ( *after* ) is stored in this vector\nas a null terminated string start at index arg[2] ( arg[4] ).\n\nnum_par\n*******\nis the total number of values in the parameter vector .\n\nparameter\n*********\nmaps parameter indices to parameter values.\n\ncap_order\n*********\nis the maximum number of orders that can fit in taylor .\n\ntaylor\n******\nThe zero order Taylor coefficient corresponding to the variable with\nindex j* is taylor[ j * cap_order + 0] .\n\n{xrst_end var_pri_forward_0}\n*/\n// BEGIN_PRI_FORWARD_0\ntemplate <class Base>\ninline void pri_forward_0(\n    std::ostream& s_out       ,\n    const addr_t* arg         ,\n    size_t        num_text    ,\n    const char*   text        ,\n    size_t        num_par     ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    const Base*   taylor      )\n// END_PRI_FORWARD_0\n{   Base pos, value;\n    //\n    const char* before;\n    const char* after;\n    CPPAD_ASSERT_NARG_NRES(PriOp, 5, 0);\n\n    // pos\n    if( arg[0] & 1 )\n    {   pos = taylor[ size_t(arg[1]) * cap_order + 0 ];\n    }\n    else\n    {   CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < num_par );\n        pos = parameter[ arg[1] ];\n    }\n\n    // before\n    CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) < num_text );\n    before = text + arg[2];\n\n    // value\n    if( arg[0] & 2 )\n    {   value = taylor[ size_t(arg[3]) * cap_order + 0 ];\n    }\n    else\n    {   CPPAD_ASSERT_UNKNOWN( size_t(arg[3]) < num_par );\n        value = parameter[ arg[3] ];\n    }\n\n    // after\n    CPPAD_ASSERT_UNKNOWN( size_t(arg[4]) < num_text );\n    after = text + arg[4];\n\n    if( ! GreaterThanZero( pos ) )\n        s_out << before << value << after;\n}\n\n} } } // END namespace\n# endif\n"
  },
  {
    "path": "include/cppad/local/var_op/prototype_op.hpp",
    "content": "# ifndef CPPAD_LOCAL_VAR_OP_PROTOTYPE_OP_HPP\n# define CPPAD_LOCAL_VAR_OP_PROTOTYPE_OP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n\nnamespace CppAD { namespace local { namespace var_op {\n/*!\n\\file prototype_op.hpp\nDocumentation for generic cases (these generic cases are never used).\n*/\n\n// ==================== Unary operators with one result ====================\n\n\n/*!\nPrototype for forward mode unary operator with one result (not used).\n\n\\tparam Base\nbase type for the operator; i.e., this operation was recorded\nusing AD< Base > and computations by this routine are done using type\n Base.\n\n\\param p\nlowest order of the Taylor coefficient that we are computing.\n\n\\param q\nhighest order of the Taylor coefficient that we are computing.\n\n\\param i_z\nvariable index corresponding to the result for this operation;\ni.e. the row index in taylor corresponding to z.\n\n\\param i_x\nvariable index corresponding to the argument for this operator;\ni.e. the row index in taylor corresponding to x.\n\n\\param cap_order\nmaximum number of orders that will fit in the taylor array.\n\n\\param taylor\n\\b Input: <code>taylor [ i_x * cap_order + k ]</code>,\nfor k = 0 , ... , q,\nis the k-th order Taylor coefficient corresponding to x.\n\\n\n\\b Input: <code>taylor [ i_z * cap_order + k ]</code>,\nfor k = 0 , ... , p-1,\nis the k-th order Taylor coefficient corresponding to z.\n\\n\n\\b Output: <code>taylor [ i_z * cap_order + k ]</code>,\nfor k = p , ... , q,\nis the k-th order Taylor coefficient corresponding to z.\n\n\\par Checked Assertions\n\\li NumArg(op) == 1\n\\li NumRes(op) == 1\n\\li q < cap_order\n\\li p <= q\n*/\ntemplate <class Base>\ninline void unary1_forward_any(\n    size_t        order_low   ,\n    size_t        order_up    ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // p, q\n    size_t p = order_low;\n    size_t q = order_up;\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    // This routine is only for documentation, it should not be used\n    CPPAD_ASSERT_UNKNOWN( false );\n}\n\n/*!\nPrototype for multiple direction forward mode unary operator with one result\n(not used).\n\n\\tparam Base\nbase type for the operator; i.e., this operation was recorded\nusing AD< Base > and computations by this routine are done using type\n Base.\n\n\\param q\norder of the Taylor coefficients that we are computing.\n\n\\param r\nnumber of directions for Taylor coefficients that we are computing.\n\n\\param i_z\nvariable index corresponding to the last (primary) result for this operation;\ni.e. the row index in taylor corresponding to z.\n\n\\param i_x\nvariable index corresponding to the argument for this operator;\ni.e. the row index in taylor corresponding to x.\n\n\\param cap_order\nmaximum number of orders that will fit in the taylor array.\n\n\\par tpv\nWe use the notation\n<code>tpv = (cap_order-1) * r + 1</code>\nwhich is the number of Taylor coefficients per variable\n\n\\param taylor\n\\b Input: If x is a variable,\n<code>taylor [ arg[0] * tpv + 0 ]</code>,\nis the zero order Taylor coefficient for all directions and\n<code>taylor [ arg[0] * tpv + (k-1)*r + ell + 1 ]</code>,\nfor k = 1 , ... , q,\nell = 0, ..., r-1,\nis the k-th order Taylor coefficient\ncorresponding to x and the ell-th direction.\n\\n\n\\b Input: <code>taylor [ i_z * tpv + 0 ]</code>,\nis the zero order Taylor coefficient for all directions and\n<code>taylor [ i_z * tpv + (k-1)*r + ell + 1 ]</code>,\nfor k = 1 , ... , q-1,\nell = 0, ..., r-1,\nis the k-th order Taylor coefficient\ncorresponding to z and the ell-th direction.\n\\n\n\\b Output:\n<code>taylor [ i_z * tpv + (q-1)*r + ell + 1]</code>,\nell = 0, ..., r-1,\nis the q-th order Taylor coefficient\ncorresponding to z and the ell-th direction.\n\n\\par Checked Assertions\n\\li NumArg(op) == 1\n\\li NumRes(op) == 2\n\\li i_x < i_z\n\\li 0 < q\n\\li q < cap_order\n*/\ntemplate <class Base>\ninline void unary1_forward_dir(\n    size_t        order_up    ,\n    size_t        n_dir       ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // q, r\n    size_t q = order_up;\n    size_t r = n_dir;\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    // This routine is only for documentation, it should not be used\n    CPPAD_ASSERT_UNKNOWN( false );\n}\n\n/*!\nPrototype for zero order forward mode unary operator with one result (not used).\n\\tparam Base\nbase type for the operator; i.e., this operation was recorded\nusing AD< Base > and computations by this routine are done using type\n Base .\n\n\\param i_z\nvariable index corresponding to the result for this operation;\ni.e. the row index in taylor corresponding to z.\n\n\\param i_x\nvariable index corresponding to the argument for this operator;\ni.e. the row index in taylor corresponding to x.\n\n\\param cap_order\nmaximum number of orders that will fit in the taylor array.\n\n\\param taylor\n\\b Input: taylor [ i_x * cap_order + 0 ]\nis the zero order Taylor coefficient corresponding to x.\n\\n\n\\b Output: taylor [ i_z * cap_order + 0 ]\nis the zero order Taylor coefficient corresponding to z.\n\n\\par Checked Assertions\n\\li NumArg(op) == 1\n\\li NumRes(op) == 1\n\\li i_x < i_z\n\\li 0 < cap_order\n*/\ntemplate <class Base>\ninline void unary1_forward_0(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{   //\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    // This routine is only for documentation, it should not be used\n    CPPAD_ASSERT_UNKNOWN( false );\n}\n\n/*!\nPrototype for reverse mode unary operator with one result (not used).\n\nThis routine is given the partial derivatives of a function\nG(z , x , w, u ... )\nand it uses them to compute the partial derivatives of\n\\verbatim\n    H( x , w , u , ... ) = G[ z(x) , x , w , u , ... ]\n\\endverbatim\n\n\\tparam Base\nbase type for the operator; i.e., this operation was recorded\nusing AD< Base > and computations by this routine are done using type\n Base .\n\n\\param d\nhighest order Taylor coefficient that\nwe are computing the partial derivatives with respect to.\n\n\\param i_z\nvariable index corresponding to the result for this operation;\ni.e. the row index in taylor to z.\n\n\\param i_x\nvariable index corresponding to the argument for this operation;\ni.e. the row index in taylor corresponding to x.\n\n\\param cap_order\nmaximum number of orders that will fit in the taylor array.\n\n\\param taylor\n taylor [ i_x * cap_order + k ]\nfor k = 0 , ... , d\nis the k-th order Taylor coefficient corresponding to x.\n\\n\n taylor [ i_z * cap_order + k ]\nfor k = 0 , ... , d\nis the k-th order Taylor coefficient corresponding to z.\n\n\\param n_order\nnumber of columns in the matrix containing all the partial derivatives.\n\n\\param partial\n\\b Input: partial [ i_x * n_order + k ]\nfor k = 0 , ... , d\nis the partial derivative of G( z , x , w , u , ... ) with respect to\nthe k-th order Taylor coefficient for x.\n\\n\n\\b Input: partial [ i_z * n_order + k ]\nfor k = 0 , ... , d\nis the partial derivative of G( z , x , w , u , ... ) with respect to\nthe k-th order Taylor coefficient for z.\n\\n\n\\b Output: partial [ i_x * n_order + k ]\nfor k = 0 , ... , d\nis the partial derivative of H( x , w , u , ... ) with respect to\nthe k-th order Taylor coefficient for x.\n\\n\n\\b Output: partial [ i_z * n_order + k ]\nfor k = 0 , ... , d\nmay be used as work space; i.e., may change in an unspecified manner.\n\n\n\\par Checked Assumptions\n\\li NumArg(op) == 1\n\\li NumRes(op) == 1\n\\li i_x < i_z\n\\li d < cap_order\n\\li d < n_order\n*/\ntemplate <class Base>\ninline void unary1_reverse(\n    size_t        i_z          ,\n    const addr_t* arg          ,\n    size_t        cap_order    ,\n    const Base*   taylor       ,\n    size_t        n_order      ,\n    Base*         partial      )\n{   // d  //\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    size_t d = n_order - 1;\n    //\n    // This routine is only for documentation, it should not be used\n    CPPAD_ASSERT_UNKNOWN( false );\n}\n\n// ==================== Unary operators with two results ====================\n\n/*!\nPrototype for forward mode unary operator with two results (not used).\n\n\\tparam Base\nbase type for the operator; i.e., this operation was recorded\nusing AD< Base > and computations by this routine are done using type\n Base.\n\n\\param p\nlowest order of the Taylor coefficients that we are computing.\n\n\\param q\nhighest order of the Taylor coefficients that we are computing.\n\n\\param i_z\nvariable index corresponding to the last (primary) result for this operation;\ni.e. the row index in taylor corresponding to z.\nThe auxiliary result is called y has index i_z - 1.\n\n\\param i_x\nvariable index corresponding to the argument for this operator;\ni.e. the row index in taylor corresponding to x.\n\n\\param cap_order\nmaximum number of orders that will fit in the taylor array.\n\n\\param taylor\n\\b Input: <code>taylor [ i_x * cap_order + k ]</code>\nfor k = 0 , ... , q,\nis the k-th order Taylor coefficient corresponding to x.\n\\n\n\\b Input: <code>taylor [ i_z * cap_order + k ]</code>\nfor k = 0 , ... , p - 1,\nis the k-th order Taylor coefficient corresponding to z.\n\\n\n\\b Input: <code>taylor [ ( i_z - 1) * cap_order + k ]</code>\nfor k = 0 , ... , p-1,\nis the k-th order Taylor coefficient corresponding to the auxiliary result y.\n\\n\n\\b Output: <code>taylor [ i_z * cap_order + k ]</code>,\nfor k = p , ... , q,\nis the k-th order Taylor coefficient corresponding to z.\n\\n\n\\b Output: <code>taylor [ ( i_z - 1 ) * cap_order + k ]</code>,\nfor k = p , ... , q,\nis the k-th order Taylor coefficient corresponding to\nthe autillary result y.\n\n\\par Checked Assertions\n\\li NumArg(op) == 1\n\\li NumRes(op) == 2\n\\li i_x + 1 < i_z\n\\li q < cap_order\n\\li p <= q\n*/\ntemplate <class Base>\ninline void unary2_forward_any(\n    size_t        order_low   ,\n    size_t        order_up    ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // p, q\n    size_t p = order_low;\n    size_t q = order_up;\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    // This routine is only for documentation, it should not be used\n    CPPAD_ASSERT_UNKNOWN( false );\n}\n\n/*!\nPrototype for multiple direction forward mode unary operator with two results\n(not used).\n\n\\tparam Base\nbase type for the operator; i.e., this operation was recorded\nusing AD< Base > and computations by this routine are done using type\n Base.\n\n\\param q\norder of the Taylor coefficients that we are computing.\n\n\\param r\nnumber of directions for Taylor coefficients that we are computing.\n\n\\param i_z\nvariable index corresponding to the last (primary) result for this operation;\ni.e. the row index in taylor corresponding to z.\nThe auxiliary result is called y has index i_z - 1.\n\n\\param i_x\nvariable index corresponding to the argument for this operator;\ni.e. the row index in taylor corresponding to x.\n\n\\param cap_order\nmaximum number of orders that will fit in the taylor array.\n\n\\par tpv\nWe use the notation\n<code>tpv = (cap_order-1) * r + 1</code>\nwhich is the number of Taylor coefficients per variable\n\n\\param taylor\n\\b Input: <code>taylor [ i_x * tpv + 0 ]</code>\nis the zero order Taylor coefficient for all directions and\n<code>taylor [ i_x * tpv + (k-1)*r + ell + 1</code>\nfor k = 1 , ... , q,\nell = 0 , ..., r-1,\nis the k-th order Taylor coefficient\ncorresponding to x and the ell-th direction.\n\\n\n\\b Input: <code>taylor [ i_z * tpv + 0 ]</code>,\nis the zero order Taylor coefficient for all directions and\n<code>taylor [ i_z * tpv + (k-1)*r + ell + 1 ]</code>,\nfor k = 1 , ... , q-1,\nell = 0, ..., r-1,\nis the k-th order Taylor coefficient\ncorresponding to z and the ell-th direction.\n\\n\n\\b Input: <code>taylor [ (i_z-1) * tpv + 0 ]</code>,\nis the zero order Taylor coefficient for all directions and\n<code>taylor [ (i_z-1) * tpv + (k-1)*r + ell + 1 ]</code>,\nfor k = 1 , ... , q-1,\nell = 0, ..., r-1,\nis the k-th order Taylor coefficient\ncorresponding to the auxiliary result y and the ell-th direction.\n\\n\n\\b Output:\n<code>taylor [ i_z * tpv + (q-1)*r + ell + 1]</code>,\nell = 0, ..., r-1,\nis the q-th order Taylor coefficient\ncorresponding to z and the ell-th direction.\n\n\\par Checked Assertions\n\\li NumArg(op) == 1\n\\li NumRes(op) == 2\n\\li i_x + 1 < i_z\n\\li 0 < q\n\\li q < cap_order\n*/\ntemplate <class Base>\ninline void unary2_forward_dir(\n    size_t        order_up    ,\n    size_t        n_dir       ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // q, r\n    size_t q = order_up;\n    size_t r = n_dir;\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    // This routine is only for documentation, it should not be used\n    CPPAD_ASSERT_UNKNOWN( false );\n}\n\n/*!\nPrototype for zero order forward mode unary operator with two results (not used).\n\\tparam Base\nbase type for the operator; i.e., this operation was recorded\nusing AD< Base > and computations by this routine are done using type\n Base .\n\n\\param i_z\nvariable index corresponding to the last (primary) result for this operation;\ni.e. the row index in taylor corresponding to z.\nThe auxiliary result is called y and has index i_z - 1.\n\n\\param i_x\nvariable index corresponding to the argument for this operator;\ni.e. the row index in taylor corresponding to x.\n\n\\param cap_order\nmaximum number of orders that will fit in the taylor array.\n\n\\param taylor\n\\b Input: taylor [ i_x * cap_order + 0 ]\nis the zero order Taylor coefficient corresponding to x.\n\\n\n\\b Output: taylor [ i_z * cap_order + 0 ]\nis the zero order Taylor coefficient corresponding to z.\n\\n\n\\b Output: taylor [ ( i_z - 1 ) * cap_order + j ]\nis the j-th order Taylor coefficient corresponding to\nthe autillary result y.\n\n\\par Checked Assertions\n\\li NumArg(op) == 1\n\\li NumRes(op) == 2\n\\li i_x + 1 < i_z\n\\li j < cap_order\n*/\ntemplate <class Base>\ninline void unary2_forward_0(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{   //\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    // This routine is only for documentation, it should not be used\n    CPPAD_ASSERT_UNKNOWN( false );\n}\n\n/*!\nPrototype for reverse mode unary operator with two results (not used).\n\nThis routine is given the partial derivatives of a function\nG( z , y , x , w , ... )\nand it uses them to compute the partial derivatives of\n\\verbatim\n    H( x , w , u , ... ) = G[ z(x) , y(x), x , w , u , ... ]\n\\endverbatim\n\n\\tparam Base\nbase type for the operator; i.e., this operation was recorded\nusing AD< Base > and computations by this routine are done using type\n Base .\n\n\\param d\nhighest order Taylor coefficient that\nwe are computing the partial derivatives with respect to.\n\n\\param i_z\nvariable index corresponding to the last (primary) result for this operation;\ni.e. the row index in taylor to z.\nThe auxiliary result is called y and has index i_z - 1.\n\n\\param i_x\nvariable index corresponding to the argument for this operation;\ni.e. the row index in taylor corresponding to x.\n\n\\param cap_order\nmaximum number of orders that will fit in the taylor array.\n\n\\param taylor\n taylor [ i_x * cap_order + k ]\nfor k = 0 , ... , d\nis the k-th order Taylor coefficient corresponding to x.\n\\n\n taylor [ i_z * cap_order + k ]\nfor k = 0 , ... , d\nis the k-th order Taylor coefficient corresponding to z.\n\\n\n taylor [ ( i_z - 1) * cap_order + k ]\nfor k = 0 , ... , d\nis the k-th order Taylor coefficient corresponding to\nthe auxiliary variable y.\n\n\\param n_order\nnumber of columns in the matrix containing all the partial derivatives.\n\n\\param partial\n\\b Input: partial [ i_x * n_order + k ]\nfor k = 0 , ... , d\nis the partial derivative of\nG( z , y , x , w , u , ... )\nwith respect to the k-th order Taylor coefficient for x.\n\\n\n\\b Input: partial [ i_z * n_order + k ]\nfor k = 0 , ... , d\nis the partial derivative of G( z , y , x , w , u , ... ) with respect to\nthe k-th order Taylor coefficient for z.\n\\n\n\\b Input: partial [ ( i_z - 1) * n_order + k ]\nfor k = 0 , ... , d\nis the partial derivative of G( z , x , w , u , ... ) with respect to\nthe k-th order Taylor coefficient for the auxiliary variable y.\n\\n\n\\b Output: partial [ i_x * n_order + k ]\nfor k = 0 , ... , d\nis the partial derivative of H( x , w , u , ... ) with respect to\nthe k-th order Taylor coefficient for x.\n\\n\n\\b Output: partial [ ( i_z - j ) * n_order + k ]\nfor j = 0 , 1 , and for k = 0 , ... , d\nmay be used as work space; i.e., may change in an unspecified manner.\n\n\n\\par Checked Assumptions\n\\li NumArg(op) == 1\n\\li NumRes(op) == 2\n\\li i_x + 1 < i_z\n\\li d < cap_order\n\\li d < n_order\n*/\ntemplate <class Base>\ninline void unary2_reverse(\n    size_t        i_z          ,\n    const addr_t* arg          ,\n    size_t        cap_order    ,\n    const Base*   taylor       ,\n    size_t        n_order      ,\n    Base*         partial      )\n{   // d  //\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    size_t d = n_order - 1;\n    //\n    // This routine is only for documentation, it should not be used\n    CPPAD_ASSERT_UNKNOWN( false );\n}\n// =================== Binary operators with one result ====================\n\n/*!\nPrototype forward mode x op y (not used)\n\n\\tparam Base\nbase type for the operator; i.e., this operation was recorded\nusing AD< Base > and computations by this routine are done using type\n Base.\n\n\\param p\nlowest order of the Taylor coefficient that we are computing.\n\n\\param q\nhighest order of the Taylor coefficient that we are computing.\n\n\\param i_z\nvariable index corresponding to the result for this operation;\ni.e. the row index in taylor corresponding to z.\n\n\\param arg\n arg[0]\nindex corresponding to the left operand for this operator;\ni.e. the index corresponding to x.\n\\n\n arg[1]\nindex corresponding to the right operand for this operator;\ni.e. the index corresponding to y.\n\n\\param parameter\nIf x is a parameter, parameter [ arg[0] ]\nis the value corresponding to x.\n\\n\nIf y is a parameter, parameter [ arg[1] ]\nis the value corresponding to y.\n\n\\param cap_order\nmaximum number of orders that will fit in the taylor array.\n\n\\param taylor\n\\b Input: If x is a variable,\n<code>taylor [ size_t(arg[0]) * cap_order + k ]</code>,\nfor k = 0 , ... , q,\nis the k-th order Taylor coefficient corresponding to x.\n\\n\n\\b Input: If y is a variable,\n<code>taylor [ size_t(arg[1]) * cap_order + k ]</code>,\nfor k = 0 , ... , q,\nis the k-th order Taylor coefficient corresponding to y.\n\\n\n\\b Input: <code>taylor [ i_z * cap_order + k ]</code>,\nfor k = 0 , ... , p-1,\nis the k-th order Taylor coefficient corresponding to z.\n\\n\n\\b Output: <code>taylor [ i_z * cap_order + k ]</code>,\nfor k = p, ... , q,\nis the k-th order Taylor coefficient corresponding to z.\n\n\\par Checked Assertions\n\\li NumArg(op) == 2\n\\li NumRes(op) == 1\n\\li q <  cap_order\n\\li p <=  q\n*/\ntemplate <class Base>\ninline void binary_forward_any(\n    size_t        order_low  ,\n    size_t        order_up   ,\n    size_t        i_z        ,\n    const addr_t* arg        ,\n    const Base*   parameter  ,\n    size_t        cap_order  ,\n    Base*         taylor     )\n{    // p, q\n    size_t p = order_low;\n    size_t q = order_up;\n    //\n    // This routine is only for documentation, it should not be used\n    CPPAD_ASSERT_UNKNOWN( false );\n}\n\n/*!\nPrototype multiple direction forward mode x op y (not used)\n\n\\tparam Base\nbase type for the operator; i.e., this operation was recorded\nusing AD< Base > and computations by this routine are done using type\n Base.\n\n\\param q\nis the order of the Taylor coefficients that we are computing.\n\n\\param r\nnumber of directions for Taylor coefficients that we are computing\n\n\\param i_z\nvariable index corresponding to the result for this operation;\ni.e. the row index in taylor corresponding to z.\n\n\\param arg\n arg[0]\nindex corresponding to the left operand for this operator;\ni.e. the index corresponding to x.\n\\n\n arg[1]\nindex corresponding to the right operand for this operator;\ni.e. the index corresponding to y.\n\n\\param parameter\nIf x is a parameter, parameter [ arg[0] ]\nis the value corresponding to x.\n\\n\nIf y is a parameter, parameter [ arg[1] ]\nis the value corresponding to y.\n\n\\param cap_order\nmaximum number of orders that will fit in the taylor array.\n\n\\par tpv\nWe use the notation\n<code>tpv = (cap_order-1) * r + 1</code>\nwhich is the number of Taylor coefficients per variable\n\n\\param taylor\n\\b Input: If x is a variable,\n<code>taylor [ arg[0] * tpv + 0 ]</code>,\nis the zero order Taylor coefficient for all directions and\n<code>taylor [ arg[0] * tpv + (k-1)*r + ell + 1 ]</code>,\nfor k = 1 , ... , q,\nell = 0, ..., r-1,\nis the k-th order Taylor coefficient\ncorresponding to x and the ell-th direction.\n\\n\n\\b Input: If y is a variable,\n<code>taylor [ arg[1] * tpv + 0 ]</code>,\nis the zero order Taylor coefficient for all directions and\n<code>taylor [ arg[1] * tpv + (k-1)*r + ell + 1 ]</code>,\nfor k = 1 , ... , q,\nell = 0, ..., r-1,\nis the k-th order Taylor coefficient\ncorresponding to y and the ell-th direction.\n\\n\n\\b Input: <code>taylor [ i_z * tpv + 0 ]</code>,\nis the zero order Taylor coefficient for all directions and\n<code>taylor [ i_z * tpv + (k-1)*r + ell + 1 ]</code>,\nfor k = 1 , ... , q-1,\nell = 0, ..., r-1,\nis the k-th order Taylor coefficient\ncorresponding to z and the ell-th direction.\n\\n\n\\b Output:\n<code>taylor [ i_z * tpv + (q-1)*r + ell + 1]</code>,\nell = 0, ..., r-1,\nis the q-th order Taylor coefficient\ncorresponding to z and the ell-th direction.\n\n\\par Checked Assertions\n\\li NumArg(op) == 2\n\\li NumRes(op) == 1\n\\li 0 < q <  cap_order\n*/\ntemplate <class Base>\ninline void binary_forward_dir(\n    size_t        order_up   ,\n    size_t        n_dir      ,\n    size_t        i_z        ,\n    const addr_t* arg        ,\n    const Base*   parameter  ,\n    size_t        cap_order  ,\n    Base*         taylor     )\n{    // q, r\n    size_t q = order_up;\n    size_t r = n_dir;\n    //\n    // This routine is only for documentation, it should not be used\n    CPPAD_ASSERT_UNKNOWN( false );\n}\n\n\n/*!\nPrototype zero order forward mode x op y (not used)\n\n\\tparam Base\nbase type for the operator; i.e., this operation was recorded\nusing AD< Base > and computations by this routine are done using type\n Base.\n\n\\param i_z\nvariable index corresponding to the result for this operation;\ni.e. the row index in taylor corresponding to z.\n\n\\param arg\n arg[0]\nindex corresponding to the left operand for this operator;\ni.e. the index corresponding to x.\n\\n\n arg[1]\nindex corresponding to the right operand for this operator;\ni.e. the index corresponding to y.\n\n\\param parameter\nIf x is a parameter, parameter [ arg[0] ]\nis the value corresponding to x.\n\\n\nIf y is a parameter, parameter [ arg[1] ]\nis the value corresponding to y.\n\n\\param cap_order\nmaximum number of orders that will fit in the taylor array.\n\n\\param taylor\n\\b Input: If x is a variable, taylor [ arg[0] * cap_order + 0 ]\nis the zero order Taylor coefficient corresponding to x.\n\\n\n\\b Input: If y is a variable, taylor [ arg[1] * cap_order + 0 ]\nis the zero order Taylor coefficient corresponding to y.\n\\n\n\\b Output: taylor [ i_z * cap_order + 0 ]\nis the zero order Taylor coefficient corresponding to z.\n\n\\par Checked Assertions\n\\li NumArg(op) == 2\n\\li NumRes(op) == 1\n*/\ntemplate <class Base>\ninline void binary_forward_0(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{   //\n    //\n    // This routine is only for documentation, it should not be used\n    CPPAD_ASSERT_UNKNOWN( false );\n}\n\n/*!\nPrototype for reverse mode binary operator x op y (not used).\n\nThis routine is given the partial derivatives of a function\nG( z , y , x , w , ... )\nand it uses them to compute the partial derivatives of\n\\verbatim\n    H( y , x , w , u , ... ) = G[ z(x , y) , y , x , w , u , ... ]\n\\endverbatim\n\n\\tparam Base\nbase type for the operator; i.e., this operation was recorded\nusing AD< Base > and computations by this routine are done using type\n Base .\n\n\\param d\nhighest order Taylor coefficient that\nwe are computing the partial derivatives with respect to.\n\n\\param i_z\nvariable index corresponding to the result for this operation;\ni.e. the row index in taylor corresponding to z.\n\n\\param arg\n arg[0]\nindex corresponding to the left operand for this operator;\ni.e. the index corresponding to x.\n\\n\n arg[1]\nindex corresponding to the right operand for this operator;\ni.e. the index corresponding to y.\n\n\\param parameter\nIf x is a parameter, parameter [ arg[0] ]\nis the value corresponding to x.\n\\n\nIf y is a parameter, parameter [ arg[1] ]\nis the value corresponding to y.\n\n\\param cap_order\nmaximum number of orders that will fit in the taylor array.\n\n\\param taylor\n taylor [ i_z * cap_order + k ]\nfor k = 0 , ... , d\nis the k-th order Taylor coefficient corresponding to z.\n\\n\nIf x is a variable, taylor [ arg[0] * cap_order + k ]\nfor k = 0 , ... , d\nis the k-th order Taylor coefficient corresponding to x.\n\\n\nIf y is a variable, taylor [ arg[1] * cap_order + k ]\nfor k = 0 , ... , d\nis the k-th order Taylor coefficient corresponding to y.\n\n\\param n_order\nnumber of columns in the matrix containing all the partial derivatives.\n\n\\param partial\n\\b Input: partial [ i_z * n_order + k ]\nfor k = 0 , ... , d\nis the partial derivative of\nG( z , y , x , w , u , ... )\nwith respect to the k-th order Taylor coefficient for z.\n\\n\n\\b Input: If x is a variable, partial [ arg[0] * n_order + k ]\nfor k = 0 , ... , d\nis the partial derivative of G( z , y , x , w , u , ... ) with respect to\nthe k-th order Taylor coefficient for x.\n\\n\n\\b Input: If y is a variable, partial [ arg[1] * n_order + k ]\nfor k = 0 , ... , d\nis the partial derivative of G( z , x , w , u , ... ) with respect to\nthe k-th order Taylor coefficient for the auxiliary variable y.\n\\n\n\\b Output: If x is a variable, partial [ arg[0] * n_order + k ]\nfor k = 0 , ... , d\nis the partial derivative of H( y , x , w , u , ... ) with respect to\nthe k-th order Taylor coefficient for x.\n\\n\n\\b Output: If y is a variable, partial [ arg[1] * n_order + k ]\nfor k = 0 , ... , d\nis the partial derivative of H( y , x , w , u , ... ) with respect to\nthe k-th order Taylor coefficient for y.\n\\n\n\\b Output: partial [ i_z * n_order + k ]\nfor k = 0 , ... , d\nmay be used as work space; i.e., may change in an unspecified manner.\n\n\\par Checked Assumptions\n\\li NumArg(op) == 2\n\\li NumRes(op) == 1\n\\li If x is a variable, arg[0] < i_z\n\\li If y is a variable, arg[1] < i_z\n\\li d < cap_order\n\\li d < n_order\n*/\ntemplate <class Base>\ninline void binary_reverse(\n    size_t      i_z          ,\n    addr_t*     arg          ,\n    const Base* parameter    ,\n    size_t      cap_order    ,\n    const Base* taylor       ,\n    size_t      n_order      ,\n    Base*       partial      )\n{   // d\n    //\n    size_t d = n_order - 1;\n    //\n    // This routine is only for documentation, it should not be used\n    CPPAD_ASSERT_UNKNOWN( false );\n}\n// ======================= Pow Function ===================================\n/*!\nPrototype for forward mode z = pow(x, y) (not used).\n\n\\tparam Base\nbase type for the operator; i.e., this operation was recorded\nusing AD< Base > and computations by this routine are done using type\n Base.\n\n\\param p\nlowest order of the Taylor coefficient that we are computing.\n\n\\param q\nhighest order of the Taylor coefficient that we are computing.\n\n\\param i_z\nvariable index corresponding to the last (primary) result for this operation;\ni.e. the row index in taylor corresponding to z.\nNote that there are three results for this operation,\nbelow they are referred to as z_0, z_1, z_2 and correspond to\n\\verbatim\n    z_0 = log(x)\n    z_1 = z0 * y\n    z_2 = exp(z1)\n\\endverbatim\nIt follows that the final result is equal to z; i.e., z = z_2 = pow(x, y).\n\n\\param arg\n arg[0]\nindex corresponding to the left operand for this operator;\ni.e. the index corresponding to x.\n\\n\n arg[1]\nindex corresponding to the right operand for this operator;\ni.e. the index corresponding to y.\n\n\\param parameter\nIf x is a parameter, parameter [ arg[0] ]\nis the value corresponding to x.\n\\n\nIf y is a parameter, parameter [ arg[1] ]\nis the value corresponding to y.\n\n\\param cap_order\nmaximum number of orders that will fit in the taylor array.\n\n\\param taylor\n\\b Input: If x is a variable,\n<code>taylor [ size_t(arg[0]) * cap_order + k ]</code>\nfor k = 0 , ... , q,\nis the k-th order Taylor coefficient corresponding to x.\n\\n\n\\b Input: If y is a variable,\n<code>taylor [ size_t(arg[1]) * cap_order + k ]</code>\nfor k = 0 , ... , q\nis the k-th order Taylor coefficient corresponding to y.\n\\n\n\\b Input: <code>taylor [ (i_z-2+j) * cap_order + k ]</code>,\nfor j = 0, 1, 2 , for k = 0 , ... , p-1,\nis the k-th order Taylor coefficient corresponding to z_j.\n\\n\n\\b Output: <code>taylor [ (i_z-2+j) * cap_order + k ]</code>,\nis the k-th order Taylor coefficient corresponding to z_j.\n\n\\par Checked Assertions\n\\li NumArg(op) == 2\n\\li NumRes(op) == 3\n\\li If x is a variable, arg[0] < i_z - 2\n\\li If y is a variable, arg[1] < i_z - 2\n\\li q < cap_order\n\\li p <= q\n*/\ntemplate <class Base>\ninline void pow_forward_any(\n    size_t        order_low  ,\n    size_t        order_up   ,\n    size_t        i_z        ,\n    const addr_t* arg        ,\n    const Base*   parameter  ,\n    size_t        cap_order  ,\n    Base*         taylor     )\n{    // p, q\n    size_t p = order_low;\n    size_t q = order_up;\n    //\n    // This routine is only for documentation, it should not be used\n    CPPAD_ASSERT_UNKNOWN( false );\n}\n/*!\nPrototype for multiple direction forward mode z = pow(x, y) (not used).\n\n\\tparam Base\nbase type for the operator; i.e., this operation was recorded\nusing AD< Base > and computations by this routine are done using type\n Base.\n\n\\param q\norder of the Taylor coefficient that we are computing.\n\n\\param r\nis the number of Taylor coefficient directions that we are computing\n\n\\param i_z\nvariable index corresponding to the last (primary) result for this operation;\ni.e. the row index in taylor corresponding to z.\nNote that there are three results for this operation,\nbelow they are referred to as z_0, z_1, z_2 and correspond to\n\\verbatim\n    z_0 = log(x)\n    z_1 = z0 * y\n    z_2 = exp(z1)\n\\endverbatim\nIt follows that the final result is equal to z; i.e., z = z_2 = pow(x, y).\n\n\\param arg\n arg[0]\nindex corresponding to the left operand for this operator;\ni.e. the index corresponding to x.\n\\n\n arg[1]\nindex corresponding to the right operand for this operator;\ni.e. the index corresponding to y.\n\n\\param parameter\nIf x is a parameter, parameter [ arg[0] ]\nis the value corresponding to x.\n\\n\nIf y is a parameter, parameter [ arg[1] ]\nis the value corresponding to y.\n\n\\param cap_order\nmaximum number of orders that will fit in the taylor array.\n\n\\par tpv\nWe use the notation\n<code>tpv = (cap_order-1) * r + 1</code>\nwhich is the number of Taylor coefficients per variable\n\n\\param taylor\n\\b Input: If x is a variable,\n<code>taylor [ arg[0] * tpv + 0 ]</code>\nis the zero order coefficient corresponding to x and\n<code>taylor [ arg[0] * tpv + (k-1)*r+1+ell ]</code>\nfor k = 1 , ... , q,\nell = 0 , ... , r-1,\nis the k-th order Taylor coefficient corresponding to x\nfor the ell-th direction.\n\\n\n\\n\n\\b Input: If y is a variable,\n<code>taylor [ arg[1] * tpv + 0 ]</code>\nis the zero order coefficient corresponding to y and\n<code>taylor [ arg[1] * tpv + (k-1)*r+1+ell ]</code>\nfor k = 1 , ... , q,\nell = 0 , ... , r-1,\nis the k-th order Taylor coefficient corresponding to y\nfor the ell-th direction.\n\\n\n\\n\n\\b Input:\n<code>taylor [ (i_z-2+j) * tpv + 0 ]</code>,\nis the zero order coefficient corresponding to z_j and\n<code>taylor [ (i_z-2+j) * tpv + (k-1)*r+1+ell ]</code>,\nfor j = 0, 1, 2 , k = 0 , ... , q-1, ell = 0, ... , r-1,\nis the k-th order Taylor coefficient corresponding to z_j\nfor the ell-th direction.\n\\n\n\\n\n\\b Output:\n<code>taylor [ (i_z-2+j) * tpv + (q-1)*r+1+ell ]</code>,\nfor j = 0, 1, 2 , ell = 0, ... , r-1,\nis the q-th order Taylor coefficient corresponding to z_j\nfor the ell-th direction.\n\n\\par Checked Assertions\n\\li NumArg(op) == 2\n\\li NumRes(op) == 3\n\\li If x is a variable, arg[0] < i_z - 2\n\\li If y is a variable, arg[1] < i_z - 2\n\\li 0 < q\n\\li q < cap_order\n*/\ntemplate <class Base>\ninline void pow_forward_dir(\n    size_t        order_up   ,\n    size_t        n_dir      ,\n    size_t        i_z        ,\n    const addr_t* arg        ,\n    const Base*   parameter  ,\n    size_t        cap_order  ,\n    Base*         taylor     )\n{    // q, r\n    size_t q = order_up;\n    size_t r = n_dir;\n    //\n    // This routine is only for documentation, it should not be used\n    CPPAD_ASSERT_UNKNOWN( false );\n}\n/*!\nPrototype for zero order forward mode z = pow(x, y) (not used).\n\n\\tparam Base\nbase type for the operator; i.e., this operation was recorded\nusing AD< Base > and computations by this routine are done using type\n Base.\n\n\\param i_z\nvariable index corresponding to the last (primary) result for this operation;\ni.e. the row index in taylor corresponding to z.\nNote that there are three results for this operation,\nbelow they are referred to as z_0, z_1, z_2 and correspond to\n\\verbatim\n    z_0 = log(x)\n    z_1 = z0 * y\n    z_2 = exp(z1)\n\\endverbatim\nIt follows that the final result is equal to z; i.e., z = z_2 = pow(x, y).\n\n\\param arg\n arg[0]\nindex corresponding to the left operand for this operator;\ni.e. the index corresponding to x.\n\\n\n arg[1]\nindex corresponding to the right operand for this operator;\ni.e. the index corresponding to y.\n\n\\param parameter\nIf x is a parameter, parameter [ arg[0] ]\nis the value corresponding to x.\n\\n\nIf y is a parameter, parameter [ arg[1] ]\nis the value corresponding to y.\n\n\\param cap_order\nmaximum number of orders that will fit in the taylor array.\n\n\\param taylor\n\\b Input: If x is a variable, taylor [ arg[0] * cap_order + 0 ]\nis the zero order Taylor coefficient corresponding to x.\n\\n\n\\b Input: If y is a variable, taylor [ arg[1] * cap_order + 0 ]\nis the k-th order Taylor coefficient corresponding to y.\n\\n\n\\b Output: taylor [ (i_z - 2 + j) * cap_order + 0 ]\nis the zero order Taylor coefficient corresponding to z_j.\n\n\\par Checked Assertions\n\\li NumArg(op) == 2\n\\li NumRes(op) == 3\n\\li If x is a variable, arg[0] < i_z - 2\n\\li If y is a variable, arg[1] < i_z - 2\n*/\ntemplate <class Base>\ninline void pow_forward_0(\n    size_t        i_z        ,\n    const addr_t* arg        ,\n    const Base*   parameter  ,\n    size_t        cap_order  ,\n    Base*         taylor     )\n{   //\n    //\n    // This routine is only for documentation, it should not be used\n    CPPAD_ASSERT_UNKNOWN( false );\n}\n/*!\nPrototype for reverse mode z = pow(x, y) (not used).\n\nThis routine is given the partial derivatives of a function\nG( z , y , x , w , ... )\nand it uses them to compute the partial derivatives of\n\\verbatim\n    H( y , x , w , u , ... ) = G[ pow(x , y) , y , x , w , u , ... ]\n\\endverbatim\n\n\\tparam Base\nbase type for the operator; i.e., this operation was recorded\nusing AD< Base > and computations by this routine are done using type\n Base .\n\n\\param d\nhighest order Taylor coefficient that\nwe are computing the partial derivatives with respect to.\n\n\\param i_z\nvariable index corresponding to the last (primary) result for this operation;\ni.e. the row index in taylor corresponding to z.\nNote that there are three results for this operation,\nbelow they are referred to as z_0, z_1, z_2 and correspond to\n\\verbatim\n    z_0 = log(x)\n    z_1 = z0 * y\n    z_2 = exp(z1)\n\\endverbatim\nIt follows that the final result is equal to z; i.e., z = z_2 = pow(x, y).\n\n\\param arg\n arg[0]\nindex corresponding to the left operand for this operator;\ni.e. the index corresponding to x.\n\\n\n arg[1]\nindex corresponding to the right operand for this operator;\ni.e. the index corresponding to y.\n\n\\param parameter\nIf x is a parameter, parameter [ arg[0] ]\nis the value corresponding to x.\n\\n\nIf y is a parameter, parameter [ arg[1] ]\nis the value corresponding to y.\n\n\\param cap_order\nmaximum number of orders that will fit in the taylor array.\n\n\\param taylor\n taylor [ (i_z - 2 + j) * cap_order + k ]\nfor j = 0, 1, 2 and k = 0 , ... , d\nis the k-th order Taylor coefficient corresponding to z_j.\n\\n\nIf x is a variable, taylor [ arg[0] * cap_order + k ]\nfor k = 0 , ... , d\nis the k-th order Taylor coefficient corresponding to x.\n\\n\nIf y is a variable, taylor [ arg[1] * cap_order + k ]\nfor k = 0 , ... , d\nis the k-th order Taylor coefficient corresponding to y.\n\n\\param n_order\nnumber of columns in the matrix containing all the partial derivatives.\n\n\\param partial\n\\b Input: partial [ (i_z - 2 + j) * n_order + k ]\nfor j = 0, 1, 2, and k = 0 , ... , d\nis the partial derivative of\nG( z , y , x , w , u , ... )\nwith respect to the k-th order Taylor coefficient for z_j.\n\\n\n\\b Input: If x is a variable, partial [ arg[0] * n_order + k ]\nfor k = 0 , ... , d\nis the partial derivative of G( z , y , x , w , u , ... ) with respect to\nthe k-th order Taylor coefficient for x.\n\\n\n\\b Input: If y is a variable, partial [ arg[1] * n_order + k ]\nfor k = 0 , ... , d\nis the partial derivative of G( z , x , w , u , ... ) with respect to\nthe k-th order Taylor coefficient for the auxiliary variable y.\n\\n\n\\b Output: If x is a variable, partial [ arg[0] * n_order + k ]\nfor k = 0 , ... , d\nis the partial derivative of H( y , x , w , u , ... ) with respect to\nthe k-th order Taylor coefficient for x.\n\\n\n\\b Output: If y is a variable, partial [ arg[1] * n_order + k ]\nfor k = 0 , ... , d\nis the partial derivative of H( y , x , w , u , ... ) with respect to\nthe k-th order Taylor coefficient for y.\n\\n\n\\b Output: partial [ ( i_z - j ) * n_order + k ]\nfor j = 0 , 1 , 2 and for k = 0 , ... , d\nmay be used as work space; i.e., may change in an unspecified manner.\n\n\\par Checked Assumptions\n\\li NumArg(op) == 2\n\\li NumRes(op) == 3\n\\li If x is a variable, arg[0] < i_z - 2\n\\li If y is a variable, arg[1] < i_z - 2\n\\li d < cap_order\n\\li d < n_order\n*/\ntemplate <class Base>\ninline void pow_reverse(\n    size_t      i_z          ,\n    addr_t*     arg          ,\n    const Base* parameter    ,\n    size_t      cap_order    ,\n    const Base* taylor       ,\n    size_t      n_order      ,\n    Base*       partial      )\n{   // d\n    //\n    size_t d = n_order - 1;\n    //\n    // This routine is only for documentation, it should not be used\n    CPPAD_ASSERT_UNKNOWN( false );\n}\n\n// ==================== Sparsity Calculations ==============================\n/*!\nPrototype for reverse mode Hessian sparsity unary operators.\n\nThis routine is given the forward mode Jacobian sparsity patterns for x.\nIt is also given the reverse mode dependence of G on z.\nIn addition, it is given the reverse mode Hessian sparsity\nfor the quantity of interest G(z , y , ... )\nand it uses them to compute the sparsity patterns for\n\\verbatim\n    H( x , w , u , ... ) = G[ z(x) , x , w , u , ... ]\n\\endverbatim\n\n\\tparam Vector_set\nis the type used for vectors of sets. It can be either\nsparse::pack_setvec or sparse::list_setvec.\n\n\\param i_z\nvariable index corresponding to the result for this operation;\ni.e. the row index in sparsity corresponding to z.\n\n\\param i_x\nvariable index corresponding to the argument for this operator;\ni.e. the row index in sparsity corresponding to x.\n\n\\param rev_jacobian\n rev_jacobian[i_z]\nis all false (true) if the Jacobian of G with respect to z must be zero\n(may be non-zero).\n\\n\n\\n\n rev_jacobian[i_x]\nis all false (true) if the Jacobian with respect to x must be zero\n(may be non-zero).\nOn input, it corresponds to the function G,\nand on output it corresponds to the function H.\n\n\\param for_jac_sparsity\nThe set with index i_x in for_jac_sparsity\nis the forward mode Jacobian sparsity pattern for the variable x.\n\n\\param rev_hes_sparsity\nThe set with index i_z in in rev_hes_sparsity\nis the Hessian sparsity pattern for the function G\nwhere one of the partials derivative is with respect to z.\n\\n\n\\n\nThe set with index i_x in rev_hes_sparsity\nis the Hessian sparsity pattern\nwhere one of the partials derivative is with respect to x.\nOn input, it corresponds to the function G,\nand on output it corresponds to the function H.\n\n\\par Checked Assertions:\n\\li i_x < i_z\n*/\n\ntemplate <class Vector_set>\ninline void reverse_sparse_hessian_unary_op(\n    size_t              i_z               ,\n    size_t              i_x               ,\n    bool*               rev_jacobian      ,\n    Vector_set&         for_jac_sparsity  ,\n    Vector_set&         rev_hes_sparsity  )\n{   //\n    //\n    // This routine is only for documentation, it should not be used\n    CPPAD_ASSERT_UNKNOWN( false );\n}\n\n/*!\nPrototype for reverse mode Hessian sparsity binary operators.\n\nThis routine is given the sparsity patterns the Hessian\nof a function G(z, y, x, ... )\nand it uses them to compute the sparsity patterns for the Hessian of\n\\verbatim\n    H( y, x, w , u , ... ) = G[ z(x,y) , y , x , w , u , ... ]\n\\endverbatim\n\n\\tparam Vector_set\nis the type used for vectors of sets. It can be either\nsparse::pack_setvec or sparse::list_setvec.\n\n\\param i_z\nvariable index corresponding to the result for this operation;\ni.e. the row index in sparsity corresponding to z.\n\n\\param arg\n arg[0]\nvariable index corresponding to the left operand for this operator;\ni.e. the set with index arg[0] in var_sparsity\nis the spasity pattern corresponding to x.\n\\n\n\\n arg[1]\nvariable index corresponding to the right operand for this operator;\ni.e. the row index in sparsity patterns corresponding to y.\n\n\\param jac_reverse\n jac_reverse[i_z]\nis false (true) if the Jacobian of G with respect to z is always zero\n(may be non-zero).\n\\n\n\\n\n jac_reverse[ arg[0] ]\nis false (true) if the Jacobian with respect to x is always zero\n(may be non-zero).\nOn input, it corresponds to the function G,\nand on output it corresponds to the function H.\n\\n\n\\n\n jac_reverse[ arg[1] ]\nis false (true) if the Jacobian with respect to y is always zero\n(may be non-zero).\nOn input, it corresponds to the function G,\nand on output it corresponds to the function H.\n\n\\param for_jac_sparsity\nThe set with index arg[0] in for_jac_sparsity for the\nis the forward Jacobian sparsity pattern for x.\n\\n\n\\n\nThe set with index arg[1] in for_jac_sparsity\nis the forward sparsity pattern for y.\n\n\\param rev_hes_sparsity\nThe set with index i_x in rev_hes_sparsity\nis the Hessian sparsity pattern for the function G\nwhere one of the partial derivatives is with respect to z.\n\\n\n\\n\nThe set with index arg[0] in  rev_hes_sparsity\nis the Hessian sparsity pattern where one of the\npartial derivatives is with respect to x.\nOn input, it corresponds to the function G,\nand on output it correspondst to H.\n\\n\n\\n\nThe set with index arg[1] in rev_hes_sparsity\nis the Hessian sparsity pattern where one of the\npartial derivatives is with respect to y.\nOn input, it corresponds to the function G,\nand on output it correspondst to H.\n\n\\par Checked Assertions:\n\\li arg[0] < i_z\n\\li arg[1] < i_z\n*/\ntemplate <class Vector_set>\ninline void reverse_sparse_hessian_binary_op(\n    size_t            i_z                ,\n    const addr_t*     arg                ,\n    bool*             jac_reverse        ,\n    Vector_set&       for_jac_sparsity   ,\n    Vector_set&       rev_hes_sparsity   )\n{   //\n    //\n    // This routine is only for documentation, it should not be used\n    CPPAD_ASSERT_UNKNOWN( false );\n}\n\n\n} } } // END namespace\n# endif\n"
  },
  {
    "path": "include/cppad/local/var_op/sign_op.hpp",
    "content": "# ifndef CPPAD_LOCAL_VAR_OP_SIGN_OP_HPP\n# define CPPAD_LOCAL_VAR_OP_SIGN_OP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n\nnamespace CppAD { namespace local { namespace var_op {\n\n// See dev documentation: forward_unary_op\ntemplate <class Base>\ninline void sign_forward_any(\n    size_t        order_low   ,\n    size_t        order_up    ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // p, q\n    size_t p = order_low;\n    size_t q = order_up;\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(SignOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(SignOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n    CPPAD_ASSERT_UNKNOWN( p <= q );\n\n    // Taylor coefficients corresponding to argument and result\n    Base* x = taylor + i_x * cap_order;\n    Base* z = taylor + i_z * cap_order;\n\n    if( p == 0 )\n    {   z[0] = sign(x[0]);\n        p++;\n    }\n    for(size_t j = p; j <= q; j++)\n        z[j] = Base(0.);\n}\n// See dev documentation: forward_unary_op\ntemplate <class Base>\ninline void sign_forward_dir(\n    size_t        order_up    ,\n    size_t        n_dir       ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // q, r\n    size_t q = order_up;\n    size_t r = n_dir;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(SignOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(SignOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( 0 < q );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n\n    // Taylor coefficients corresponding to argument and result\n    size_t num_taylor_per_var = (cap_order-1) * r + 1;\n    size_t m = (q - 1) * r + 1;\n    Base* z = taylor + i_z * num_taylor_per_var;\n\n    for(size_t ell = 0; ell < r; ell++)\n        z[m+ell] = Base(0.);\n}\n\n// See dev documentation: forward_unary_op\ntemplate <class Base>\ninline void sign_forward_0(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{   //\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(SignOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(SignOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( 0 < cap_order );\n\n    // Taylor coefficients corresponding to argument and result\n    Base x0 = *(taylor + i_x * cap_order);\n    Base* z = taylor + i_z * cap_order;\n\n    z[0] = sign(x0);\n}\n\n// See dev documentation: reverse_unary_op\ntemplate <class Base>\ninline void sign_reverse(\n    size_t        i_z          ,\n    const addr_t* arg          ,\n    size_t        cap_order    ,\n    const Base*   taylor       ,\n    size_t        n_order      ,\n    Base*         partial      )\n{   //\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(SignOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(SignOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( n_order <= cap_order );\n\n    // nothing to do because partials of sign are zero\n    return;\n}\n\n} } } // END namespace\n# endif\n"
  },
  {
    "path": "include/cppad/local/var_op/sin_op.hpp",
    "content": "# ifndef CPPAD_LOCAL_VAR_OP_SIN_OP_HPP\n# define CPPAD_LOCAL_VAR_OP_SIN_OP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n\nnamespace CppAD { namespace local { namespace var_op {\n\n\n// See dev documentation: forward_unary_op\ntemplate <class Base>\ninline void sin_forward_any(\n    size_t        order_low   ,\n    size_t        order_up    ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // p, q\n    size_t p = order_low;\n    size_t q = order_up;\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(SinOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(SinOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n    CPPAD_ASSERT_UNKNOWN( p <= q );\n\n    // Taylor coefficients corresponding to argument and result\n    Base* x = taylor + i_x * cap_order;\n    Base* s = taylor + i_z * cap_order;\n    Base* c = s      -       cap_order;\n\n    // rest of this routine is identical for the following cases:\n    // forward_sin_op, forward_cos_op, forward_sinh_op, forward_cosh_op.\n    // (except that there is a sign difference for the hyperbolic case).\n    size_t k;\n    if( p == 0 )\n    {   s[0] = sin( x[0] );\n        c[0] = cos( x[0] );\n        p++;\n    }\n    for(size_t j = p; j <= q; j++)\n    {\n        s[j] = Base(0.0);\n        c[j] = Base(0.0);\n        for(k = 1; k <= j; k++)\n        {   s[j] += Base(double(k)) * x[k] * c[j-k];\n            c[j] -= Base(double(k)) * x[k] * s[j-k];\n        }\n        s[j] /= Base(double(j));\n        c[j] /= Base(double(j));\n    }\n}\n// See dev documentation: forward_unary_op\ntemplate <class Base>\ninline void sin_forward_dir(\n    size_t        order_up    ,\n    size_t        n_dir       ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // q, r\n    size_t q = order_up;\n    size_t r = n_dir;\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(SinOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(SinOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( 0 < q );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n\n    // Taylor coefficients corresponding to argument and result\n    size_t num_taylor_per_var = (cap_order-1) * r + 1;\n    Base* x = taylor + i_x * num_taylor_per_var;\n    Base* s = taylor + i_z * num_taylor_per_var;\n    Base* c = s      -       num_taylor_per_var;\n\n\n    // rest of this routine is identical for the following cases:\n    // forward_sin_op, forward_cos_op, forward_sinh_op, forward_cosh_op\n    // (except that there is a sign difference for the hyperbolic case).\n    size_t m = (q-1) * r + 1;\n    for(size_t ell = 0; ell < r; ell++)\n    {   s[m+ell] =   Base(double(q)) * x[m + ell] * c[0];\n        c[m+ell] = - Base(double(q)) * x[m + ell] * s[0];\n        for(size_t k = 1; k < q; k++)\n        {   s[m+ell] += Base(double(k)) * x[(k-1)*r+1+ell] * c[(q-k-1)*r+1+ell];\n            c[m+ell] -= Base(double(k)) * x[(k-1)*r+1+ell] * s[(q-k-1)*r+1+ell];\n        }\n        s[m+ell] /= Base(double(q));\n        c[m+ell] /= Base(double(q));\n    }\n}\n\n\n// See dev documentation: forward_unary_op\ntemplate <class Base>\ninline void sin_forward_0(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{   //\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(SinOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(SinOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( 0 < cap_order );\n\n    // Taylor coefficients corresponding to argument and result\n    Base* x = taylor + i_x * cap_order;\n    Base* s = taylor + i_z * cap_order;  // called z in documentation\n    Base* c = s      -       cap_order;  // called y in documentation\n\n    s[0] = sin( x[0] );\n    c[0] = cos( x[0] );\n}\n\n\n// See dev documentation: reverse_unary_op\ntemplate <class Base>\ninline void sin_reverse(\n    size_t        i_z          ,\n    const addr_t* arg          ,\n    size_t        cap_order    ,\n    const Base*   taylor       ,\n    size_t        n_order      ,\n    Base*         partial      )\n{   // d  //\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    size_t d = n_order - 1;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(SinOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(SinOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( n_order <= cap_order );\n\n    // Taylor coefficients and partials corresponding to argument\n    const Base* x  = taylor  + i_x * cap_order;\n    Base* px       = partial + i_x * n_order;\n\n    // Taylor coefficients and partials corresponding to first result\n    const Base* s  = taylor  + i_z * cap_order; // called z in doc\n    Base* ps       = partial + i_z * n_order;\n\n    // Taylor coefficients and partials corresponding to auxiliary result\n    const Base* c  = s  - cap_order; // called y in documentation\n    Base* pc       = ps - n_order;\n\n\n    // rest of this routine is identical for the following cases:\n    // reverse_sin_op, reverse_cos_op, reverse_sinh_op, reverse_cosh_op.\n    size_t j = d;\n    size_t k;\n    while(j)\n    {\n        ps[j]   /= Base(double(j));\n        pc[j]   /= Base(double(j));\n        for(k = 1; k <= j; k++)\n        {\n            px[k]   += Base(double(k)) * azmul(ps[j], c[j-k]);\n            px[k]   -= Base(double(k)) * azmul(pc[j], s[j-k]);\n\n            ps[j-k] -= Base(double(k)) * azmul(pc[j], x[k]);\n            pc[j-k] += Base(double(k)) * azmul(ps[j], x[k]);\n\n        }\n        --j;\n    }\n    px[0] += azmul(ps[0], c[0]);\n    px[0] -= azmul(pc[0], s[0]);\n}\n\n} } } // END namespace\n# endif\n"
  },
  {
    "path": "include/cppad/local/var_op/sinh_op.hpp",
    "content": "# ifndef CPPAD_LOCAL_VAR_OP_SINH_OP_HPP\n# define CPPAD_LOCAL_VAR_OP_SINH_OP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n\nnamespace CppAD { namespace local { namespace var_op {\n\n\n// See dev documentation: forward_unary_op\ntemplate <class Base>\ninline void sinh_forward_any(\n    size_t        order_low   ,\n    size_t        order_up    ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // p, q\n    size_t p = order_low;\n    size_t q = order_up;\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(SinhOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(SinhOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n    CPPAD_ASSERT_UNKNOWN( p <= q );\n\n    // Taylor coefficients corresponding to argument and result\n    Base* x = taylor + i_x * cap_order;\n    Base* s = taylor + i_z * cap_order;\n    Base* c = s      -       cap_order;\n\n\n    // rest of this routine is identical for the following cases:\n    // forward_sin_op, forward_cos_op, forward_sinh_op, forward_cosh_op\n    // (except that there is a sign difference for hyperbolic case).\n    size_t k;\n    if( p == 0 )\n    {   s[0] = sinh( x[0] );\n        c[0] = cosh( x[0] );\n        p++;\n    }\n    for(size_t j = p; j <= q; j++)\n    {\n        s[j] = Base(0.0);\n        c[j] = Base(0.0);\n        for(k = 1; k <= j; k++)\n        {   s[j] += Base(double(k)) * x[k] * c[j-k];\n            c[j] += Base(double(k)) * x[k] * s[j-k];\n        }\n        s[j] /= Base(double(j));\n        c[j] /= Base(double(j));\n    }\n}\n// See dev documentation: forward_unary_op\ntemplate <class Base>\ninline void sinh_forward_dir(\n    size_t        order_up    ,\n    size_t        n_dir       ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // q, r\n    size_t q = order_up;\n    size_t r = n_dir;\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(SinhOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(SinhOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( 0 < q );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n\n    // Taylor coefficients corresponding to argument and result\n    size_t num_taylor_per_var = (cap_order-1) * r + 1;\n    Base* x = taylor + i_x * num_taylor_per_var;\n    Base* s = taylor + i_z * num_taylor_per_var;\n    Base* c = s      -       num_taylor_per_var;\n\n\n    // rest of this routine is identical for the following cases:\n    // forward_sin_op, forward_cos_op, forward_sinh_op, forward_cosh_op\n    // (except that there is a sign difference for the hyperbolic case).\n    size_t m = (q-1) * r + 1;\n    for(size_t ell = 0; ell < r; ell++)\n    {   s[m+ell] = Base(double(q)) * x[m + ell] * c[0];\n        c[m+ell] = Base(double(q)) * x[m + ell] * s[0];\n        for(size_t k = 1; k < q; k++)\n        {   s[m+ell] += Base(double(k)) * x[(k-1)*r+1+ell] * c[(q-k-1)*r+1+ell];\n            c[m+ell] += Base(double(k)) * x[(k-1)*r+1+ell] * s[(q-k-1)*r+1+ell];\n        }\n        s[m+ell] /= Base(double(q));\n        c[m+ell] /= Base(double(q));\n    }\n}\n\n// See dev documentation: forward_unary_op\ntemplate <class Base>\ninline void sinh_forward_0(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{   //\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(SinhOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(SinhOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( 0 < cap_order );\n\n    // Taylor coefficients corresponding to argument and result\n    Base* x = taylor + i_x * cap_order;\n    Base* s = taylor + i_z * cap_order;  // called z in documentation\n    Base* c = s      -       cap_order;  // called y in documentation\n\n    s[0] = sinh( x[0] );\n    c[0] = cosh( x[0] );\n}\n\n// See dev documentation: reverse_unary_op\ntemplate <class Base>\ninline void sinh_reverse(\n    size_t        i_z          ,\n    const addr_t* arg          ,\n    size_t        cap_order    ,\n    const Base*   taylor       ,\n    size_t        n_order      ,\n    Base*         partial      )\n{   // d  //\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    size_t d = n_order - 1;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(SinhOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(SinhOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( n_order <= cap_order );\n\n    // Taylor coefficients and partials corresponding to argument\n    const Base* x  = taylor  + i_x * cap_order;\n    Base* px       = partial + i_x * n_order;\n\n    // Taylor coefficients and partials corresponding to first result\n    const Base* s  = taylor  + i_z * cap_order; // called z in doc\n    Base* ps       = partial + i_z * n_order;\n\n    // Taylor coefficients and partials corresponding to auxiliary result\n    const Base* c  = s  - cap_order; // called y in documentation\n    Base* pc       = ps - n_order;\n\n\n    // rest of this routine is identical for the following cases:\n    // reverse_sin_op, reverse_cos_op, reverse_sinh_op, reverse_cosh_op.\n    size_t j = d;\n    size_t k;\n    while(j)\n    {\n        ps[j]   /= Base(double(j));\n        pc[j]   /= Base(double(j));\n        for(k = 1; k <= j; k++)\n        {\n            px[k]   += Base(double(k)) * azmul(ps[j], c[j-k]);\n            px[k]   += Base(double(k)) * azmul(pc[j], s[j-k]);\n\n            ps[j-k] += Base(double(k)) * azmul(pc[j], x[k]);\n            pc[j-k] += Base(double(k)) * azmul(ps[j], x[k]);\n\n        }\n        --j;\n    }\n    px[0] += azmul(ps[0], c[0]);\n    px[0] += azmul(pc[0], s[0]);\n}\n\n} } } // END namespace\n# endif\n"
  },
  {
    "path": "include/cppad/local/var_op/sqrt_op.hpp",
    "content": "# ifndef CPPAD_LOCAL_VAR_OP_SQRT_OP_HPP\n# define CPPAD_LOCAL_VAR_OP_SQRT_OP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n\nnamespace CppAD { namespace local { namespace var_op {\n\n\n// See dev documentation: forward_unary_op\ntemplate <class Base>\ninline void sqrt_forward_any(\n    size_t        order_low   ,\n    size_t        order_up    ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // p, q\n    size_t p = order_low;\n    size_t q = order_up;\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(SqrtOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(SqrtOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n    CPPAD_ASSERT_UNKNOWN( p <= q );\n\n    // Taylor coefficients corresponding to argument and result\n    Base* x = taylor + i_x * cap_order;\n    Base* z = taylor + i_z * cap_order;\n\n    size_t k;\n    if( p == 0 )\n    {   z[0] = sqrt( x[0] );\n        p++;\n    }\n    for(size_t j = p; j <= q; j++)\n    {\n        z[j] = Base(0.0);\n        for(k = 1; k < j; k++)\n            z[j] -= Base(double(k)) * z[k] * z[j-k];\n        z[j] /= Base(double(j));\n        z[j] += x[j] / Base(2.0);\n        z[j] /= z[0];\n    }\n}\n\n// See dev documentation: forward_unary_op\ntemplate <class Base>\ninline void sqrt_forward_dir(\n    size_t        order_up    ,\n    size_t        n_dir       ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // q, r\n    size_t q = order_up;\n    size_t r = n_dir;\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(SqrtOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(SqrtOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( 0 < q );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n\n    // Taylor coefficients corresponding to argument and result\n    size_t num_taylor_per_var = (cap_order-1) * r + 1;\n    Base* z = taylor + i_z * num_taylor_per_var;\n    Base* x = taylor + i_x * num_taylor_per_var;\n\n    size_t m = (q-1) * r + 1;\n    for(size_t ell = 0; ell < r; ell++)\n    {   z[m+ell] = Base(0.0);\n        for(size_t k = 1; k < q; k++)\n            z[m+ell] -= Base(double(k)) * z[(k-1)*r+1+ell] * z[(q-k-1)*r+1+ell];\n        z[m+ell] /= Base(double(q));\n        z[m+ell] += x[m+ell] / Base(2.0);\n        z[m+ell] /= z[0];\n    }\n}\n\n// See dev documentation: forward_unary_op\ntemplate <class Base>\ninline void sqrt_forward_0(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{   //\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(SqrtOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(SqrtOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( 0 < cap_order );\n\n    // Taylor coefficients corresponding to argument and result\n    Base* x = taylor + i_x * cap_order;\n    Base* z = taylor + i_z * cap_order;\n\n    z[0] = sqrt( x[0] );\n}\n\n// See dev documentation: reverse_unary_op\ntemplate <class Base>\ninline void sqrt_reverse(\n    size_t        i_z          ,\n    const addr_t* arg          ,\n    size_t        cap_order    ,\n    const Base*   taylor       ,\n    size_t        n_order      ,\n    Base*         partial      )\n{   // d  //\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    size_t d = n_order - 1;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(SqrtOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(SqrtOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( n_order <= cap_order );\n\n    // Taylor coefficients and partials corresponding to argument\n    Base* px       = partial + i_x * n_order;\n\n    // Taylor coefficients and partials corresponding to result\n    const Base* z  = taylor  + i_z * cap_order;\n    Base* pz       = partial + i_z * n_order;\n\n\n    Base inv_z0 = Base(1.0) / z[0];\n\n    // number of indices to access\n    size_t j = d;\n    size_t k;\n    while(j)\n    {\n\n        // scale partial w.r.t. z[j]\n        pz[j]    = azmul(pz[j], inv_z0);\n\n        pz[0]   -= azmul(pz[j], z[j]);\n        px[j]   += pz[j] / Base(2.0);\n        for(k = 1; k < j; k++)\n            pz[k]   -= azmul(pz[j], z[j-k]);\n        --j;\n    }\n    px[0] += azmul(pz[0], inv_z0) / Base(2.0);\n}\n\n} } } // END namespace\n# endif\n"
  },
  {
    "path": "include/cppad/local/var_op/store_op.hpp",
    "content": "# ifndef CPPAD_LOCAL_VAR_OP_STORE_OP_HPP\n# define CPPAD_LOCAL_VAR_OP_STORE_OP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\nnamespace CppAD { namespace local { namespace var_op {\n/*\n{xrst_begin_parent var_store_op dev}\n{xrst_spell\n    stpp\n    stpv\n    stvp\n    stvv\n}\n\nStore an Element of a Variable VecAD Vector\n###########################################\n\nStppOp, StpvOp, StvpOp, StvvOp\n******************************\nare the op codes for these operators.\n\nUser Syntax\n***********\n| *v* [ *x* ] = *y*\n\nv\n*\nis the :ref:`VecAD-name` vector for this store operation.\nThis vector is a variable after the store.\nif this is a StppOp operation, *v* is a variable before the store.\n\nx\n*\nis the index for this store.\n\ny\n*\nis the value being stored.\n\nRecBase\n*******\nis the base type use when recording this operator;\ni.e., this operation was recording using AD< *RecBase* > operations.\n\nBase\n****\nis the type used for computations by this operator.\nThis is either *RecBase* or AD< *RecBase* >.\n\nop_code\n*******\n\n.. csv-table::\n    :widths: auto\n    :header-rows: 1\n\n    op_code, x, y\n    StppOp, parameter, parameter\n    StpvOp, parameter, variable\n    StvpOp, variable,  parameter\n    StvvOp, variable,  variable\n\nnum_vecad_ind\n*************\nis the size of the single array that includes\nall the VecAD vectors together with the size of each vector.\n\narg\n***\n\narg[0]\n======\nthis argument is the offset of the vector *v*\nrelative to the beginning of the single array\nthat contains all VecAD elements and sizes.\nThis offset corresponds to the first element of *v* and not its size\nwhich comes just before the first element.\n\narg[1]\n======\nIf *x* is a parameter (variable), arg[1] is the parameter index\n(variable index) to *x* .\n\narg[2]\n======\nIf *y* is a parameter (variable), arg[2] is the parameter index\n(variable index) to *y* .\n\n{xrst_end var_store_op}\n------------------------------------------------------------------------------\n{xrst_begin var_store_forward_0 dev}\n{xrst_spell\n    isvar\n}\n\nZero Order Forward Store an Element of a VecAD Vector\n#####################################################\n\nv, x, y\n*******\nsee\n:ref:`var_store_op@v` ,\n:ref:`var_store_op@x` ,\n:ref:`var_store_op@y`\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_STORE_FORWARD_0\n    // END_STORE_FORWARD_0\n}\n\nBase, op_code, num_vecad_ind, arg\n*********************************\nsee\n:ref:`var_store_op@Base` ,\n:ref:`var_store_op@op_code` ,\n:ref:`var_store_op@num_vecad_ind` ,\n:ref:`var_store_op@arg` .\n\nnum_var\n*******\nis the number of variables in this recording.\n\nnum_par\n*******\nis the number of parameters in this recording.\n\nparameter\n*********\nThis is the vector of parameters for this recording which has size *num_par* .\n\ncap_order\n*********\nis the maximum number of orders that can fit in *taylor* .\n\ntaylor\n******\nIs the matrix of Taylor coefficients for all the variables.\n\ni_vec\n*****\nWe use *i_vec* to denote the ``size_t`` value corresponding to\n:ref:`var_store_op@x` .\nIf *x* is a parameter (variable) this is a parameter (variable) index.\n\nvec_ad2isvar\n************\nThis vector has size :ref:`var_store_op@num_vecad_ind` .\nThe input values of its elements does not matter.\nIf the value being stored is a parameter (variable),\n*vec_ad2isvar* [ *arg* [0] + *i_vec*  ] is set to false (true).\n\nvec_ad2index\n************\nThis vector has size *num_vecad_ind* .\nThe input value of its elements does not matter.\nIf the value being stored is a parameter (variable),\n*vec_ad2index* [ *arg* [0] + *i_vec*  ]\nis set to the parameter (variable) index\ncorresponding to the value being stored.\n\n{xrst_end var_store_forward_0}\n*/\n// BEGIN_STORE_FORWARD_0\ntemplate <class Base>\ninline void store_forward_0(\n    op_code_var          op_code        ,\n    const addr_t*        arg            ,\n    size_t               num_var        ,\n    size_t               num_par        ,\n    const Base*          parameter      ,\n    size_t               cap_order      ,\n    const Base*          taylor         ,\n    pod_vector<bool>&    vec_ad2isvar   ,\n    pod_vector<size_t>&  vec_ad2index   )\n// END_STORE_FORWARD_0\n{  //\n    //\n    CPPAD_ASSERT_NARG_NRES(op_code, 3, 0);\n    CPPAD_ASSERT_UNKNOWN( 0 < arg[0] );\n    CPPAD_ASSERT_UNKNOWN( vec_ad2isvar.size() == vec_ad2index.size() )\n    //\n    // i_y\n    size_t i_y = size_t( arg[2] );\n    //\n    // i_vec, isvar\n    // assign here to avoid compiler warning for default case\n    addr_t i_vec = std::numeric_limits<addr_t>::max();\n    bool   isvar = false;\n    switch(op_code)\n    {  //\n        default:\n        CPPAD_ASSERT_UNKNOWN(false);\n        break;\n        //\n        case StppOp:\n        i_vec = addr_t( Integer( parameter[ arg[1] ] ) );\n        isvar = false;\n        CPPAD_ASSERT_UNKNOWN( i_y < num_par );\n        break;\n        //\n        case StpvOp:\n        i_vec = addr_t( Integer( parameter[ arg[1] ] ) );\n        isvar = true;\n        CPPAD_ASSERT_UNKNOWN( i_y < num_var );\n        break;\n        //\n        case StvpOp:\n        i_vec = addr_t(Integer( taylor[ size_t(arg[1]) * cap_order + 0 ] ));\n        isvar = false;\n        CPPAD_ASSERT_UNKNOWN( i_y < num_par );\n        break;\n        //\n        case StvvOp:\n        i_vec = addr_t(Integer( taylor[ size_t(arg[1]) * cap_order + 0 ] ));\n        isvar = true;\n        CPPAD_ASSERT_UNKNOWN( i_y < num_var );\n        break;\n    }\n    //\n    CPPAD_ASSERT_KNOWN(\n        size_t(i_vec) < vec_ad2index[ arg[0] - 1 ] ,\n        \"VecAD: zero order forward index out of range\"\n    );\n    //\n    // vec_ad2isvar, vec_ad2index\n    vec_ad2isvar[ arg[0] + i_vec ]  = isvar;\n    vec_ad2index[ arg[0] + i_vec ]  = i_y;\n}\n/*\n------------------------------------------------------------------------------\n{xrst_begin var_store_for_jac dev}\n\nForward Jacobian Sparsity for Store a VecAD Element\n###################################################\n\nv, x, y\n*******\nsee\n:ref:`var_store_op@v` ,\n:ref:`var_store_op@x` ,\n:ref:`var_store_op@y`\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_STORE_FOR_JAC\n    // END_STORE_FOR_JAC\n}\n\nop_code, num_vecad_ind, arg\n***************************\nsee :ref:`var_store_op@op_code` ,\n:ref:`var_store_op@num_vecad_ind` ,\n:ref:`var_store_op@arg` .\n\nVector_set\n**********\nis the type used for vectors of sets. It must satisfy the\n:ref:`SetVector-name` concept.\n\ndependency\n**********\nIf true (false) we are including (are not including)\ndependencies that have derivative zero in the sparsity pattern.\nFor example, the :ref:`Discrete-name` functions have derivative zero,\nbut the value depends on its argument.\n\nvecad_ind\n*********\nis a vector with size *num_vec_ind* .\nWe use the notation *i_v* defined by\n\n|tab| *i_v* = vecad_ind[ arg[0] - 1 ]\n\nThis is the index of the VecAD vector and is less than the number of\nVecAD vectors in the recording.\n\nvar_sparsity\n************\nIf :ref:`var_store_op@y` is a variable,\nthe sets with index arg[2] in *var_sparsity* is the sparsity pattern for *y* .\nOtherwise, *y* is a parameter and its sparsity pattern for *y* is empty\n\n\nvecad_sparsity\n**************\nThe set with index *i_v* in *vecad_sparsity\nis the sparsity pattern for the vector *v*.\nThe sparsity pattern for *y* is added\nto the sparsity pattern for *v* .\nIf *dependency* is true and *x* is a variable,\nthe sparsity pattern for *x* is also added to the sparsity pattern for *v*.\n\n{xrst_end var_store_for_jac}\n*/\n// BEGIN_STORE_FOR_JAC\ntemplate <class Vector_set>\ninline void store_for_jac(\n    op_code_var               op_code        ,\n    size_t                    num_vecad_ind  ,\n    const addr_t*             arg            ,\n    bool                      dependency     ,\n    const pod_vector<size_t>& vecad_ind      ,\n    const Vector_set&         var_sparsity   ,\n    Vector_set&               vecad_sparsity )\n// END_STORE_FOR_JAC\n{  //\n    //\n    CPPAD_ASSERT_NARG_NRES(op_code, 3, 0);\n    CPPAD_ASSERT_UNKNOWN( 0 < arg[0] );\n    CPPAD_ASSERT_UNKNOWN( num_vecad_ind == vecad_ind.size() );\n    CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_vecad_ind );\n    //\n    // i_v\n    size_t i_v = vecad_ind[ arg[0] - 1 ];\n    CPPAD_ASSERT_UNKNOWN( i_v < vecad_sparsity.n_set() );\n    //\n    // i_x, i_y\n    size_t i_x = size_t( arg[1] );\n    size_t i_y = size_t( arg[2] );\n    //\n    switch(op_code)\n    {  //\n        default:\n        CPPAD_ASSERT_UNKNOWN(false);\n        break;\n        //\n        case StppOp:\n        break;\n        //\n        case StpvOp:\n        vecad_sparsity.binary_union(i_v, i_v, i_y, var_sparsity);\n        break;\n        //\n        case StvpOp:\n        if( dependency )\n            vecad_sparsity.binary_union(i_v, i_v, i_x, var_sparsity);\n        break;\n        //\n        case StvvOp:\n        if( dependency )\n            vecad_sparsity.binary_union(i_v, i_v, i_x, var_sparsity);\n        vecad_sparsity.binary_union(i_v, i_v, i_y, var_sparsity);\n        break;\n    }\n    return;\n}\n/*\n------------------------------------------------------------------------------\n{xrst_begin var_store_rev_jac dev}\n\nReverse Jacobian Sparsity for Store a VecAD Element\n###################################################\n\nv, x, y\n*******\nsee\n:ref:`var_store_op@v` ,\n:ref:`var_store_op@x` ,\n:ref:`var_store_op@y`\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_STORE_REV_JAC\n    // END_STORE_REV_JAC\n}\n\nop_code, num_vecad_ind, arg\n***************************\nsee :ref:`var_store_op@op_code` ,\n:ref:`var_store_op@num_vecad_ind` ,\n:ref:`var_store_op@arg` .\n\nVector_set\n**********\nis the type used for vectors of sets. It must satisfy the\n:ref:`SetVector-name` concept.\n\ndependency\n**********\nIf true (false) we are including (are not including)\ndependencies that have derivative zero in the sparsity pattern.\nFor example, the :ref:`Discrete-name` functions have derivative zero,\nbut the value depends on its argument.\n\nvecad_ind\n*********\nis a vector with size *num_vec_ind* .\nWe use the notation *i_v* defined by\n\n|tab| *i_v* = vecad_ind[ arg[0] - 1 ]\n\nThis is the index of the VecAD vector and is less than the number of\nVecAD vectors in the recording.\n\nvar_sparsity\n************\nIf :ref:`var_store_op@y` is a variable,\nthe sparsity pattern for *v* is added to the sparsity pattern for *y*.\nIf *dependency* is true and *x* is a variable,\nthe sparsity pattern for *v* is also added to the sparsity pattern for *x*.\n\nvecad_sparsity\n**************\nThe set with index *i_v* in *vecad_sparsity\nis the sparsity pattern for the vector *v*.\n\n{xrst_end var_store_rev_jac}\n*/\n// BEGIN_STORE_REV_JAC\ntemplate <class Vector_set>\ninline void store_rev_jac(\n    op_code_var               op_code        ,\n    size_t                    num_vecad_ind  ,\n    const addr_t*             arg            ,\n    bool                      dependency     ,\n    const pod_vector<size_t>& vecad_ind      ,\n    Vector_set&               var_sparsity   ,\n    const Vector_set&         vecad_sparsity )\n// END_STORE_REV_JAC\n{  //\n    //\n    CPPAD_ASSERT_NARG_NRES(op_code, 3, 0);\n    CPPAD_ASSERT_UNKNOWN( 0 < arg[0] );\n    CPPAD_ASSERT_UNKNOWN( num_vecad_ind == vecad_ind.size() );\n    CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_vecad_ind );\n    //\n    // i_v\n    size_t i_v = vecad_ind[ arg[0] - 1 ];\n    CPPAD_ASSERT_UNKNOWN( i_v < vecad_sparsity.n_set() );\n    //\n    // i_x, i_y\n    size_t i_x = size_t( arg[1] );\n    size_t i_y = size_t( arg[2] );\n    //\n    switch(op_code)\n    {  //\n        default:\n        CPPAD_ASSERT_UNKNOWN(false);\n        break;\n        //\n        case StppOp:\n        break;\n        //\n        case StpvOp:\n        var_sparsity.binary_union(i_y, i_y, i_v, vecad_sparsity);\n        break;\n        //\n        case StvpOp:\n        if( dependency )\n            var_sparsity.binary_union(i_x, i_x, i_v, vecad_sparsity);\n        break;\n        //\n        case StvvOp:\n        if( dependency )\n            var_sparsity.binary_union(i_x, i_x, i_v, vecad_sparsity);\n        var_sparsity.binary_union(i_y, i_y, i_v, vecad_sparsity);\n        break;\n    }\n    return;\n}\n/*\n------------------------------------------------------------------------------\n{xrst_begin var_store_rev_hes dev}\n\nReverse Hessian Sparsity for Store a VecAD Element\n##################################################\n\nv, x, y\n*******\nsee\n:ref:`var_store_op@v` ,\n:ref:`var_store_op@x` ,\n:ref:`var_store_op@y`\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_STORE_REV_HES\n    // END_STORE_REV_HES\n}\n\nop_code, num_vecad_ind, arg\n***************************\nsee :ref:`var_store_op@op_code` ,\n:ref:`var_store_op@num_vecad_ind` ,\n:ref:`var_store_op@arg` .\n\nVector_set\n**********\nis the type used for vectors of sets. It must satisfy the\n:ref:`SetVector-name` concept.\n\nvecad_ind\n*********\nis a vector with size *num_vec_ind* .\nWe use the notation *i_v* defined by\n\n|tab| *i_v* = vecad_ind[ arg[0] - 1 ]\n\nThis is the index of the VecAD vector and is less than the number of\nVecAD vectors in the recording.\nIt is also the index of the hessian\nsparsity pattern for *v* in *vecad_sparsity*.\n\nvar_sparsity\n************\nIf :ref:`var_store_op@y` is a variable,\nthe hessian sparsity pattern for *v* is added to the\nhessian sparsity pattern for *y*.\n\nvecad_sparsity\n**************\nThe set with index *i_v* in *vecad_sparsity\nis the hessian sparsity pattern for the vector *v*.\n\nvar_rev_jac\n***********\nIf the scalar function we are computing the Hessian sparsity of\nhas a non-zero partial w.r.t. *v*,\nand *y* is a variable, *var_rev_jac* [ *i_y* ] is set to true.\nThis is because the scalar function has non-zero partial w.r.t. *y* .\n\nvecad_rev_jac\n*************\nthe *i_v* component of this vector is true ,\nif the scalar function has non-zero partial w.r.t *v*.\n\n{xrst_end var_store_rev_hes}\n*/\n// BEGIN_STORE_REV_HES\ntemplate <class Vector_set>\ninline void store_rev_hes(\n    op_code_var               op_code        ,\n    const addr_t*             arg            ,\n    size_t                    num_vecad_ind  ,\n    const pod_vector<size_t>& vecad_ind      ,\n    Vector_set&               var_sparsity   ,\n    const Vector_set&         vecad_sparsity ,\n    bool*                     var_rev_jac    ,\n    const pod_vector<bool>&   vecad_rev_jac  )\n// END_STORE_REV_HES\n{  //\n    //\n    CPPAD_ASSERT_NARG_NRES(op_code, 3, 0);\n    CPPAD_ASSERT_UNKNOWN( 0 < arg[0] );\n    CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_vecad_ind );\n    CPPAD_ASSERT_UNKNOWN( vecad_ind.size() == num_vecad_ind );\n    //\n    // i_v\n    size_t i_v = vecad_ind[ arg[0] - 1 ];\n    CPPAD_ASSERT_UNKNOWN( i_v < vecad_sparsity.n_set() );\n    //\n    // i_y\n    size_t i_y = size_t( arg[2] );\n    //\n    switch(op_code)\n    {  //\n        default:\n        CPPAD_ASSERT_UNKNOWN(false);\n        break;\n        //\n        case StpvOp:\n        case StvvOp:\n        var_sparsity.binary_union(i_y, i_y, i_v, vecad_sparsity);\n        var_rev_jac[i_y] |= vecad_rev_jac[i_v];\n        break;\n        //\n        case StppOp:\n        case StvpOp:\n        break;\n    }\n    //\n    return;\n}\n/*\n------------------------------------------------------------------------------\n{xrst_begin var_store_for_hes dev}\n\nForward Hessian Sparsity for Store a VecAD Element\n##################################################\n\nv, x, y\n*******\nsee\n:ref:`var_store_op@v` ,\n:ref:`var_store_op@x` ,\n:ref:`var_store_op@y`\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_STORE_FOR_HES\n    // END_STORE_FOR_HES\n}\n\nop_code, num_vecad_ind, arg\n***************************\nsee :ref:`var_store_op@op_code` ,\n:ref:`var_store_op@num_vecad_ind` ,\n:ref:`var_store_op@arg` .\n\nVector_set\n**********\nis the type used for vectors of sets. It must satisfy the\n:ref:`SetVector-name` concept.\n\nvecad_ind\n*********\nis a vector with size *num_vec_ind* .\nWe use the notation *i_v* defined by\n\n|tab| *i_v* = vecad_ind[ arg[0] - 1 ]\n\nThis is the index of the VecAD vector and is less than the number of\nVecAD vectors in the recording.\nIt is also the index of the hessian\nsparsity pattern for *v* in *vecad_sparsity*.\n\nvar_sparsity\n************\nIf :ref:`var_store_op@y` is a variable,\nthe hessian sparsity pattern for *v* is added to the\nhessian sparsity pattern for *y*.\n\nvecad_sparsity\n**************\nThe set with index *i_v* in *vecad_sparsity\nis the hessian sparsity pattern for the vector *v*.\n\nvar_rev_jac\n***********\nIf the scalar function we are computing the Hessian sparsity of\nhas a non-zero partial w.r.t. *v*,\nand *y* is a variable, *var_rev_jac* [ *i_y* ] is set to true.\nThis is because the scalar function has non-zero partial w.r.t. *y* .\n\nvecad_rev_jac\n*************\nthe *i_v* component of this vector is true ,\nif the scalar function has non-zero partial w.r.t *v*.\n\n{xrst_end var_store_for_hes}\n*/\n// BEGIN_STORE_FOR_HES\ntemplate <class Vector_set>\ninline void store_for_hes(\n    op_code_var               op_code        ,\n    const addr_t*             arg            ,\n    size_t                    num_vecad_ind  ,\n    size_t                    n              ,\n    const pod_vector<size_t>& vecad_ind      ,\n    Vector_set&               vecad_sparsity ,\n    const Vector_set&         for_hes_sparse )\n// END_STORE_FOR_HES\n{   //\n    //\n    CPPAD_ASSERT_NARG_NRES(op_code, 3, 0);\n    CPPAD_ASSERT_UNKNOWN( 0 < arg[0] );\n    CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_vecad_ind );\n    CPPAD_ASSERT_UNKNOWN( vecad_ind.size() == num_vecad_ind );\n    //\n    // np1\n    size_t np1 = n + 1;\n    CPPAD_ASSERT_UNKNOWN( for_hes_sparse.end() == np1 );\n    //\n    // i_v\n    size_t i_v = vecad_ind[ arg[0] - 1 ];\n    CPPAD_ASSERT_UNKNOWN( i_v < vecad_sparsity.n_set() );\n    //\n    // i_y\n    size_t i_y = size_t( arg[2] );\n    //\n    switch(op_code)\n    {   //\n        default:\n        CPPAD_ASSERT_UNKNOWN(false);\n        break;\n        //\n        // vecad_sparsity\n        // set Jacobian sparsity for vector with index i_v\n        case StpvOp:\n        case StvvOp:\n        vecad_sparsity.binary_union(i_v, i_v, np1 + i_y, for_hes_sparse);\n        break;\n        //\n        case StppOp:\n        case StvpOp:\n        break;\n    }\n    //\n    return;\n}\n\n} } } // END namespace\n# endif\n"
  },
  {
    "path": "include/cppad/local/var_op/sub_op.hpp",
    "content": "# ifndef CPPAD_LOCAL_VAR_OP_SUB_OP_HPP\n# define CPPAD_LOCAL_VAR_OP_SUB_OP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\nnamespace CppAD { namespace local { namespace var_op {\n\n// --------------------------- Subvv -----------------------------------------\n\n// See dev documentation: forward_binary_op\ntemplate <class Base>\ninline void subvv_forward_any(\n    size_t        order_low   ,\n    size_t        order_up    ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // p, q\n    size_t p = order_low;\n    size_t q = order_up;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(SubvvOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(SubvvOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n    CPPAD_ASSERT_UNKNOWN( p <= q );\n\n    // Taylor coefficients corresponding to arguments and result\n    Base* x = taylor + size_t(arg[0]) * cap_order;\n    Base* y = taylor + size_t(arg[1]) * cap_order;\n    Base* z = taylor + i_z    * cap_order;\n\n    for(size_t d = p; d <= q; d++)\n        z[d] = x[d] - y[d];\n}\n\n// See dev documentation: forward_binary_op\ntemplate <class Base>\ninline void subvv_forward_dir(\n    size_t        order_up    ,\n    size_t        n_dir       ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // q, r\n    size_t q = order_up;\n    size_t r = n_dir;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(SubvvOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(SubvvOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( 0 < q );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n\n    // Taylor coefficients corresponding to arguments and result\n    size_t num_taylor_per_var = (cap_order-1) * r + 1;\n    size_t m                  = (q-1) * r + 1;\n    Base* x = taylor + size_t(arg[0]) * num_taylor_per_var + m;\n    Base* y = taylor + size_t(arg[1]) * num_taylor_per_var + m;\n    Base* z = taylor + i_z    * num_taylor_per_var + m;\n\n    for(size_t ell = 0; ell < r; ell++)\n        z[ell] = x[ell] - y[ell];\n}\n\n\n// See dev documentation: forward_binary_op\ntemplate <class Base>\ninline void subvv_forward_0(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{   //\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(SubvvOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(SubvvOp) == 1 );\n\n    // Taylor coefficients corresponding to arguments and result\n    Base* x = taylor + size_t(arg[0]) * cap_order;\n    Base* y = taylor + size_t(arg[1]) * cap_order;\n    Base* z = taylor + i_z    * cap_order;\n\n    z[0] = x[0] - y[0];\n}\n\n\n// See dev documentation: reverse_binary_op\ntemplate <class Base>\ninline void subvv_reverse(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    const Base*   taylor      ,\n    size_t        n_order     ,\n    Base*         partial     )\n{   // d\n    //\n    size_t d = n_order - 1;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(SubvvOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(SubvvOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( n_order <= cap_order );\n\n    // Partial derivatives corresponding to arguments and result\n    Base* px = partial + size_t(arg[0]) * n_order;\n    Base* py = partial + size_t(arg[1]) * n_order;\n    Base* pz = partial + i_z    * n_order;\n\n    // number of indices to access\n    size_t i = d + 1;\n    while(i)\n    {   --i;\n        px[i] += pz[i];\n        py[i] -= pz[i];\n    }\n}\n\n// --------------------------- Subpv -----------------------------------------\n\n// See dev documentation: forward_binary_op\ntemplate <class Base>\ninline void subpv_forward_any(\n    size_t        order_low   ,\n    size_t        order_up    ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // p, q\n    size_t p = order_low;\n    size_t q = order_up;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(SubpvOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(SubpvOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n    CPPAD_ASSERT_UNKNOWN( p <= q );\n\n    // Taylor coefficients corresponding to arguments and result\n    Base* y = taylor + size_t(arg[1]) * cap_order;\n    Base* z = taylor + i_z    * cap_order;\n\n    // Paraemter value\n    Base x = parameter[ arg[0] ];\n    if( p == 0 )\n    {   z[0] = x - y[0];\n        p++;\n    }\n    for(size_t d = p; d <= q; d++)\n        z[d] = - y[d];\n}\n\n// See dev documentation: forward_binary_op\ntemplate <class Base>\ninline void subpv_forward_dir(\n    size_t        order_up    ,\n    size_t        n_dir       ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // q, r\n    size_t q = order_up;\n    size_t r = n_dir;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(SubpvOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(SubpvOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( 0 < q );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n\n    // Taylor coefficients corresponding to arguments and result\n    size_t num_taylor_per_var = (cap_order-1) * r + 1;\n    size_t m                  = (q-1) * r + 1;\n    Base* y = taylor + size_t(arg[1]) * num_taylor_per_var + m;\n    Base* z = taylor + i_z    * num_taylor_per_var + m;\n\n    // Paraemter value\n    for(size_t ell = 0; ell < r; ell++)\n        z[ell] = - y[ell];\n}\n\n// See dev documentation: forward_binary_op\ntemplate <class Base>\ninline void subpv_forward_0(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{   //\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(SubpvOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(SubpvOp) == 1 );\n\n    // Paraemter value\n    Base x = parameter[ arg[0] ];\n\n    // Taylor coefficients corresponding to arguments and result\n    Base* y = taylor + size_t(arg[1]) * cap_order;\n    Base* z = taylor + i_z    * cap_order;\n\n    z[0] = x - y[0];\n}\n\n\n// See dev documentation: reverse_binary_op\ntemplate <class Base>\ninline void subpv_reverse(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    const Base*   taylor      ,\n    size_t        n_order     ,\n    Base*         partial     )\n{   // d\n    //\n    size_t d = n_order - 1;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(SubvvOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(SubvvOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( n_order <= cap_order );\n\n    // Partial derivatives corresponding to arguments and result\n    Base* py = partial + size_t(arg[1]) * n_order;\n    Base* pz = partial + i_z    * n_order;\n\n    // number of indices to access\n    size_t i = d + 1;\n    while(i)\n    {   --i;\n        py[i] -= pz[i];\n    }\n}\n\n// --------------------------- Subvp -----------------------------------------\n\n// See dev documentation: forward_binary_op\ntemplate <class Base>\ninline void subvp_forward_any(\n    size_t        order_low   ,\n    size_t        order_up    ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // p, q\n    size_t p = order_low;\n    size_t q = order_up;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(SubvpOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(SubvpOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n    CPPAD_ASSERT_UNKNOWN( p <= q );\n\n    // Taylor coefficients corresponding to arguments and result\n    Base* x = taylor + size_t(arg[0]) * cap_order;\n    Base* z = taylor + i_z    * cap_order;\n\n    // Parameter value\n    Base y = parameter[ arg[1] ];\n    if( p == 0 )\n    {   z[0] = x[0] - y;\n        p++;\n    }\n    for(size_t d = p; d <= q; d++)\n        z[d] = x[d];\n}\n\n// See dev documentation: forward_binary_op\ntemplate <class Base>\ninline void subvp_forward_dir(\n    size_t        order_up    ,\n    size_t        n_dir       ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // q, r\n    size_t q = order_up;\n    size_t r = n_dir;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(SubvpOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(SubvpOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( 0 < q );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n\n    // Taylor coefficients corresponding to arguments and result\n    size_t num_taylor_per_var = (cap_order-1) * r + 1;\n    Base* x = taylor + size_t(arg[0]) * num_taylor_per_var;\n    Base* z = taylor + i_z    * num_taylor_per_var;\n\n    // Parameter value\n    size_t m = (q-1) * r + 1;\n    for(size_t ell = 0; ell < r; ell++)\n        z[m+ell] = x[m+ell];\n}\n\n\n// See dev documentation: forward_binary_op\ntemplate <class Base>\ninline void subvp_forward_0(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{   //\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(SubvpOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(SubvpOp) == 1 );\n\n    // Parameter value\n    Base y = parameter[ arg[1] ];\n\n    // Taylor coefficients corresponding to arguments and result\n    Base* x = taylor + size_t(arg[0]) * cap_order;\n    Base* z = taylor + i_z    * cap_order;\n\n    z[0] = x[0] - y;\n}\n\n\n// See dev documentation: reverse_binary_op\ntemplate <class Base>\ninline void subvp_reverse(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    const Base*   taylor      ,\n    size_t        n_order     ,\n    Base*         partial     )\n{   // d\n    //\n    size_t d = n_order - 1;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(SubvpOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(SubvpOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( n_order <= cap_order );\n\n    // Partial derivatives corresponding to arguments and result\n    Base* px = partial + size_t(arg[0]) * n_order;\n    Base* pz = partial + i_z    * n_order;\n\n    // number of indices to access\n    size_t i = d + 1;\n    while(i)\n    {   --i;\n        px[i] += pz[i];\n    }\n}\n\n} } } // END namespace\n# endif\n"
  },
  {
    "path": "include/cppad/local/var_op/tan_op.hpp",
    "content": "# ifndef CPPAD_LOCAL_VAR_OP_TAN_OP_HPP\n# define CPPAD_LOCAL_VAR_OP_TAN_OP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n\nnamespace CppAD { namespace local { namespace var_op {\n\n\n// See dev documentation: forward_unary_op\ntemplate <class Base>\ninline void tan_forward_any(\n    size_t        order_low   ,\n    size_t        order_up    ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // p, q\n    size_t p = order_low;\n    size_t q = order_up;\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(TanOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(TanOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n    CPPAD_ASSERT_UNKNOWN( p <= q );\n\n    // Taylor coefficients corresponding to argument and result\n    Base* x = taylor + i_x * cap_order;\n    Base* z = taylor + i_z * cap_order;\n    Base* y = z      -       cap_order;\n\n    size_t k;\n    if( p == 0 )\n    {   z[0] = tan( x[0] );\n        y[0] = z[0] * z[0];\n        p++;\n    }\n    for(size_t j = p; j <= q; j++)\n    {   Base base_j = static_cast<Base>(double(j));\n\n        z[j] = x[j];\n        for(k = 1; k <= j; k++)\n            z[j] += Base(double(k)) * x[k] * y[j-k] / base_j;\n\n        y[j] = z[0] * z[j];\n        for(k = 1; k <= j; k++)\n            y[j] += z[k] * z[j-k];\n    }\n}\n\n// See dev documentation: forward_unary_op\ntemplate <class Base>\ninline void tan_forward_dir(\n    size_t        order_up    ,\n    size_t        n_dir       ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // q, r\n    size_t q = order_up;\n    size_t r = n_dir;\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(TanOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(TanOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( 0 < q );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n\n    // Taylor coefficients corresponding to argument and result\n    size_t num_taylor_per_var = (cap_order-1) * r + 1;\n    Base* x = taylor + i_x * num_taylor_per_var;\n    Base* z = taylor + i_z * num_taylor_per_var;\n    Base* y = z      -       num_taylor_per_var;\n\n    size_t k;\n    size_t m = (q-1) * r + 1;\n    for(size_t ell = 0; ell < r; ell++)\n    {   z[m+ell] = Base(double(q)) * ( x[m+ell] + x[m+ell] * y[0]);\n        for(k = 1; k < q; k++)\n            z[m+ell] +=  Base(double(k)) * x[(k-1)*r+1+ell] * y[(q-k-1)*r+1+ell];\n        z[m+ell] /= Base(double(q));\n        //\n        y[m+ell] = Base(2.0) * z[m+ell] * z[0];\n        for(k = 1; k < q; k++)\n            y[m+ell] += z[(k-1)*r+1+ell] * z[(q-k-1)*r+1+ell];\n    }\n}\n\n\n// See dev documentation: forward_unary_op\ntemplate <class Base>\ninline void tan_forward_0(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{   //\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(TanOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(TanOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( 0 < cap_order );\n\n    // Taylor coefficients corresponding to argument and result\n    Base* x = taylor + i_x * cap_order;\n    Base* z = taylor + i_z * cap_order;  // called z in documentation\n    Base* y = z      -       cap_order;  // called y in documentation\n\n    z[0] = tan( x[0] );\n    y[0] = z[0] * z[0];\n}\n\n\n// See dev documentation: reverse_unary_op\ntemplate <class Base>\ninline void tan_reverse(\n    size_t        i_z          ,\n    const addr_t* arg          ,\n    size_t        cap_order    ,\n    const Base*   taylor       ,\n    size_t        n_order      ,\n    Base*         partial      )\n{   // d  //\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    size_t d = n_order - 1;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(TanOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(TanOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( n_order <= cap_order );\n\n    // Taylor coefficients and partials corresponding to argument\n    const Base* x  = taylor  + i_x * cap_order;\n    Base* px       = partial + i_x * n_order;\n\n    // Taylor coefficients and partials corresponding to first result\n    const Base* z  = taylor  + i_z * cap_order; // called z in doc\n    Base* pz       = partial + i_z * n_order;\n\n    // Taylor coefficients and partials corresponding to auxiliary result\n    const Base* y  = z  - cap_order; // called y in documentation\n    Base* py       = pz - n_order;\n\n\n    size_t j = d;\n    size_t k;\n    Base base_two(2);\n    while(j)\n    {\n        px[j]   += pz[j];\n        pz[j]   /= Base(double(j));\n        for(k = 1; k <= j; k++)\n        {   px[k]   += azmul(pz[j], y[j-k]) * Base(double(k));\n            py[j-k] += azmul(pz[j], x[k]) * Base(double(k));\n        }\n        for(k = 0; k < j; k++)\n            pz[k] += azmul(py[j-1], z[j-k-1]) * base_two;\n\n        --j;\n    }\n    px[0] += azmul(pz[0], Base(1.0) + y[0]);\n}\n\n} } } // END namespace\n# endif\n"
  },
  {
    "path": "include/cppad/local/var_op/tanh_op.hpp",
    "content": "# ifndef CPPAD_LOCAL_VAR_OP_TANH_OP_HPP\n# define CPPAD_LOCAL_VAR_OP_TANH_OP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n\nnamespace CppAD { namespace local { namespace var_op {\n\n\n// See dev documentation: forward_unary_op\ntemplate <class Base>\ninline void tanh_forward_any(\n    size_t        order_low   ,\n    size_t        order_up    ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // p, q\n    size_t p = order_low;\n    size_t q = order_up;\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(TanOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(TanOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n    CPPAD_ASSERT_UNKNOWN( p <= q );\n\n    // Taylor coefficients corresponding to argument and result\n    Base* x = taylor + i_x * cap_order;\n    Base* z = taylor + i_z * cap_order;\n    Base* y = z      -       cap_order;\n\n    size_t k;\n    if( p == 0 )\n    {   z[0] = tanh( x[0] );\n        y[0] = z[0] * z[0];\n        p++;\n    }\n    for(size_t j = p; j <= q; j++)\n    {   Base base_j = static_cast<Base>(double(j));\n\n        z[j] = x[j];\n        for(k = 1; k <= j; k++)\n            z[j] -= Base(double(k)) * x[k] * y[j-k] / base_j;\n\n        y[j] = z[0] * z[j];\n        for(k = 1; k <= j; k++)\n            y[j] += z[k] * z[j-k];\n    }\n}\n\n// See dev documentation: forward_unary_op\ntemplate <class Base>\ninline void tanh_forward_dir(\n    size_t        order_up    ,\n    size_t        n_dir       ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // q, r\n    size_t q = order_up;\n    size_t r = n_dir;\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(TanOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(TanOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( 0 < q );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n\n    // Taylor coefficients corresponding to argument and result\n    size_t num_taylor_per_var = (cap_order-1) * r + 1;\n    Base* x = taylor + i_x * num_taylor_per_var;\n    Base* z = taylor + i_z * num_taylor_per_var;\n    Base* y = z      -       num_taylor_per_var;\n\n    size_t k;\n    size_t m = (q-1) * r + 1;\n    for(size_t ell = 0; ell < r; ell++)\n    {   z[m+ell] = Base(double(q)) * ( x[m+ell] - x[m+ell] * y[0] );\n        for(k = 1; k < q; k++)\n            z[m+ell] -= Base(double(k)) * x[(k-1)*r+1+ell] * y[(q-k-1)*r+1+ell];\n        z[m+ell] /= Base(double(q));\n        //\n        y[m+ell] = Base(2.0) * z[m+ell] * z[0];\n        for(k = 1; k < q; k++)\n            y[m+ell] += z[(k-1)*r+1+ell] * z[(q-k-1)*r+1+ell];\n    }\n}\n\n// See dev documentation: forward_unary_op\ntemplate <class Base>\ninline void tanh_forward_0(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{   //\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(TanOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(TanOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( 0 < cap_order );\n\n    // Taylor coefficients corresponding to argument and result\n    Base* x = taylor + i_x * cap_order;\n    Base* z = taylor + i_z * cap_order;  // called z in documentation\n    Base* y = z      -       cap_order;  // called y in documentation\n\n    z[0] = tanh( x[0] );\n    y[0] = z[0] * z[0];\n}\n\n\n// See dev documentation: reverse_unary_op\ntemplate <class Base>\ninline void tanh_reverse(\n    size_t        i_z          ,\n    const addr_t* arg          ,\n    size_t        cap_order    ,\n    const Base*   taylor       ,\n    size_t        n_order      ,\n    Base*         partial      )\n{   // d  //\n    //\n    // i_x\n    size_t i_x = size_t(arg[0]);\n    //\n    size_t d = n_order - 1;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(TanOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(TanOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( n_order <= cap_order );\n\n    // Taylor coefficients and partials corresponding to argument\n    const Base* x  = taylor  + i_x * cap_order;\n    Base* px       = partial + i_x * n_order;\n\n    // Taylor coefficients and partials corresponding to first result\n    const Base* z  = taylor  + i_z * cap_order; // called z in doc\n    Base* pz       = partial + i_z * n_order;\n\n    // Taylor coefficients and partials corresponding to auxiliary result\n    const Base* y  = z  - cap_order; // called y in documentation\n    Base* py       = pz - n_order;\n\n\n    size_t j = d;\n    size_t k;\n    Base base_two(2);\n    while(j)\n    {\n        px[j]   += pz[j];\n        pz[j]   /= Base(double(j));\n        for(k = 1; k <= j; k++)\n        {   px[k]   -= azmul(pz[j], y[j-k]) * Base(double(k));\n            py[j-k] -= azmul(pz[j], x[k]) * Base(double(k));\n        }\n        for(k = 0; k < j; k++)\n            pz[k] += azmul(py[j-1], z[j-k-1]) * base_two;\n\n        --j;\n    }\n    px[0] += azmul(pz[0], Base(1.0) - y[0]);\n}\n\n} } } // END namespace\n# endif\n"
  },
  {
    "path": "include/cppad/local/var_op/template/atomic_op.xrst",
    "content": "{xrst_comment\nSPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\nSPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\nSPDX-FileContributor: 2024 Bradley M. Bell\n\nThis file is intended to help document of all the atomic_op routines.\n\nIt has the following xrst template comments:\n    headers: n_res, i_z, itr, play, parameter, trace, work\n    headers if @mode@ is reverse: G and H\n\nIt has the following xrst template replacements:\n    @mode@ : Must be either forward or reverse.\n}\n\nNotation\n********\n\nn_res\n=====\nWe use *n_res* to denote the number of variables created by this function call.\nWhich is also equal to the number of\n{xrst_spell_off}\n``FunrvOp``\n{xrst_spell_on}\noperators in function call.\n\ni_z\n===\nWe use *i_z* to denote the index of the last variable\ncreated by this function call.\n\n{xrst_suspend @mode@ != reverse}\nG and H\n=======\nWe use :math:`y(x)` to denote the atomic function call\nas a mapping from the vector *x* to the vector *y* .\nWe use :math:`G( y, x, \\ldots )` to denote a scalar valued function\nof the taylor coefficients of the variables with index less than or\nequal *i_z* ; i.e., the last variable in the vector *y* .\nWe define :math:`H(x, \\ldots )` by\n\n.. math::\n\n    H(x, \\cdots ) = G [ y(x), x, \\cdots ]\n\n{xrst_resume}\n\nitr\n***\nis an iterator for the recording in *play* .\n{xrst_suspend @mode@ != forward}\nOn input (output), the operator corresponding to *itr* is the first (second)\n:ref:`var_atomic_op@AfunOp` for this function call.\n{xrst_resume}\n{xrst_suspend @mode@ != reverse}\nOn input (output), the operator corresponding to *itr* is the second (first)\n:ref:`var_atomic_op@AfunOp` for this function call.\n{xrst_resume}\n\nplay\n****\nis a player for the recording that contains the operation sequence\nthat contains this atomic function call.\n\nparameter\n*********\nis the parameter vector for this operation sequence.\n\ntrace\n*****\nif *trace* is true (false) a trace of the evaluation of this\natomic function call is (is not) printed.\n\nwork\n****\nis unspecified work space.\nIt passed as an argument to reduce memory allocations.\n"
  },
  {
    "path": "include/cppad/local/var_op/template/forward_dir.xrst",
    "content": "{xrst_comment\nSPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\nSPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\nSPDX-FileContributor: 2024 Bradley M. Bell\n\nThis file is intended to help document multiple direction forward Taylor\ncomputation for all operators.\n\nIt has the following xrst template comments:\n    headers: n_dir, cap_order, order_up, taylor\n\nIt does not have any xrst template replacements:\n}\n\nn_dir\n*****\nnumber of directions that we are computing the Taylor coefficient for.\n\ncap_order\n*********\nis the maximum number of orders that can fit in *taylor* .\n\norder_up\n********\nis the order of the Taylor coefficients that are computed by this call.\n\ntaylor\n******\n\nper_variable\n============\nFor each variable there is one Taylor coefficient of order zero\nand *n_dir* coefficients for orders greater than zero.\nThe taylor coefficients capacity per variable is::\n\n    per_variable = (cap_order - 1) * n_dir + 1\n\n(j, k, ell)\n===========\nFor variable index j, order k, and direction index ell::\n\n    if k == 0\n        (j, k, ell) = j * per_variable\n    else\n        (j, k, ell) = j * per_variable + (k-1) * n_dir + 1 + ell\n\nThe value taylor[ (j, k, ell) ] is the\nTaylor coefficient corresponding to\nthe variable with index j, the order k, and the direction with index ell.\n\nn_dir = 1\n=========\nIf *n_dir* is equal to one then *ell* is zero and::\n\n    (j, k, ell) = j * cap_order + k\n\nn_res\n=====\nis the number of results (that are variables) for this operator.\n\nInput\n=====\n::\n\n    for j = 0, ..., i_z - n_res,\n        for k = 0 , ... , order_up\n            for ell = 0 , ... , n_dir - 1\n                taylor [ (j, k, ell) ] is an input\n\n    for j = i_z - n_res + 1, ..., i_z\n        for k = 0 , ... , order_up - 1\n            for ell = 0 , ... , n_dir - 1\n                taylor [ (j, k, ell) ] is an input\n\nOutput\n======\n::\n\n    for j = i_z - n_res + 1, ..., i_z\n        for ell = 0 , ... , n_dir - 1\n            taylor [ (j, order_up, ell) ] is an output\n"
  },
  {
    "path": "include/cppad/local/var_op/template/forward_op.xrst",
    "content": "{xrst_comment\nSPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\nSPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\nSPDX-FileContributor: 2024 Bradley M. Bell\n\nThis file is intended to help document the multiple order forward Taylor\ncomputation for all operators.\n\nIt has the following xrst template comments:\n    headers: cap_order, order_low, order_up, taylor\n\nIt does not have any xrst template replacements:\n}\n\ncap_order\n*********\nis the maximum number of orders that can fit in *taylor* .\n\norder_low\n*********\nis the lowest order Taylor coefficient that we are computing.\n\norder_up\n********\nis the highest order Taylor coefficient that we are computing.\n\ntaylor\n******\nThe Taylor coefficient corresponding to variable *j* and order *k* is\n\n    *taylor* [ *j* * *cap_order* + *k*  ]\n\n\nn_res\n=====\nis the number of results (that are variables) for this operator.\n\nInput\n=====\n::\n\n    for j = 0, ..., i_z - n_res\n        for k = 0 , ... , order_up\n            taylor [ j * cap_order + k ] is an input\n\n    for j = i_z - n_res + 1 , ... , i_z\n        for  k = 0 , ... , order_up - 1\n            taylor [ j * cap_order + k ] is an input\n\nOutput\n======\n::\n\n    for j = i_z - n_res + 1 , ... , i_z\n        for k = order_low , ... , order_up\n            taylor [ i_z * cap_order + k ] is an output\n"
  },
  {
    "path": "include/cppad/local/var_op/template/reverse_op.xrst",
    "content": "{xrst_comment\nSPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\nSPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\nSPDX-FileContributor: 2024 Bradley M. Bell\n\nThis file is intended to help document reverse computation of\nTaylor partials for all operators.\n\nIt has the following xrst template comments:\n    headers: n_order, partial\n\nIt has the following xrst template replacements:\n@x, y@   : The arguments, without parenthesis, in function for this operator;\n              e.g., if @x, y@ is replaced by 'x , y', the function is 'z(x, y)' .\n}\n\nn_order\n*******\nis the number of Taylor coefficient orders that we are\ncomputing the partial derivatives with respect to.\n\npartial\n*******\nThe partial derivative with respect to the order *k* Taylor coefficient\nfor the variable with index *j* is::\n\n    partial[ j * n_order + k ]\n\nWe use :math:`G( z, @x, y@, \\ldots )` to denote a scalar valued function\nof the taylor coefficients of the variables with index less than or\nequal the variable index for *z* .\nWe define :math:`H( @x, y@, \\ldots )` by\n\n.. math::\n\n    H( @x, y@, \\cdots ) = G [ z(@x, y@), @x, y@, \\cdots ]\n\nOn input, *partial* contains the partial derivatives of *G*\nwith respect to the Taylor coefficients of the arguments to *G* .\nOn output, *partial* contains the partial derivatives of *H*\nwith respect to the Taylor coefficients of the arguments to *H* .\nWe only compute partials with respect to variables; i.e.,\nno partials are computed with respect to the parameters in @x, y@ .\n"
  },
  {
    "path": "include/cppad/local/var_op/two_var.hpp",
    "content": "# ifndef CPPAD_LOCAL_VAR_OP_TWO_VAR_HPP\n# define CPPAD_LOCAL_VAR_OP_TWO_VAR_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n// BEGIN_CPPAD_LOCAL_SPARSE_NAMESPACE\nnamespace CppAD { namespace local { namespace var_op {\n// END_DECLARE_NAMESPACE\n\n/*\n{xrst_begin_parent var_two_var dev}\n\nSparsity Calculations for Operators With Two Variables\n######################################################\n\nBinary Operators\n****************\n| *z* = *fun* ( *x* , *y* )\n| *z* = *x*  *Op* *y*\n\nSee :ref:`var_binary_op@Fun` for binary operators,\nrestricted to the case where both *x* and *y* are variables,\nfor some of the possible values of *Fun* and the corresponding operators.\n\nx\n*\nis the first operand for this operator .\n\ny\n*\nis the second operand for this operator\n\nz\n*\nis the primary result for this operator.\n\nVector_set\n**********\nis the type used for vectors of sets. It must satisfy the\n:ref:`SetVector-name` concept.\n\ni_z\n***\nis the variable index corresponding to *z* .\n\narg\n***\n\narg[0]\n======\nis the variable index corresponding to x.\n\narg[1]\n======\nis the variable index corresponding to y.\n\n{xrst_end var_two_var}\n------------------------------------------------------------------------------\n{xrst_begin var_two_var_for_jac dev}\n\nForward Jacobian Sparsity for Two Variable Argument Operators\n#############################################################\n\nx, y, z\n*******\nsee\n:ref:`var_two_var@x` ,\n:ref:`var_two_var@y` ,\n:ref:`var_two_var@z`\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_TWO_VAR_FOR_JAC\n    // END_TWO_VAR_FOR_JAC\n}\n\nVector_set, i_z, arg\n********************\nsee\n:ref:`var_two_var@Vector_set` ,\n:ref:`var_two_var@i_z` ,\n:ref:`var_two_var@arg`\n\nsparsity\n********\n\nInput\n=====\nfor *j* < *i_z*  and *j* not an auxiliary result,\nthe set with index *j* in *sparsity* is\nthe Jacobian sparsity for the variable with index *j* .\n\nOutput\n======\nThe set with index *i_z* in *sparsity* is\nthe Jacobian sparsity for the variable *z* .\n\n{xrst_end var_two_var_for_jac}\n*/\n// BEGIN_TWO_VAR_FOR_JAC\ntemplate <class Vector_set>\nvoid two_var_for_jac(\n    size_t            i_z           ,\n    const addr_t*     arg           ,\n    Vector_set&       sparsity      )\n// END_TWO_VAR_FOR_JAC\n{\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < i_z );\n    CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < i_z );\n\n    sparsity.binary_union(i_z, size_t(arg[0]), size_t(arg[1]), sparsity);\n\n    return;\n}\n/*\n------------------------------------------------------------------------------\n{xrst_begin var_two_var_rev_jac dev}\n\nReverse Jacobian Sparsity for Two Variable Argument Operators\n#############################################################\n\nx, y, z\n*******\nsee\n:ref:`var_two_var@x` ,\n:ref:`var_two_var@y` ,\n:ref:`var_two_var@z`\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_TWO_VAR_REV_JAC\n    // END_TWO_VAR_REV_JAC\n}\n\nVector_set, i_z, arg\n********************\nsee\n:ref:`var_two_var@Vector_set` ,\n:ref:`var_two_var@i_z` ,\n:ref:`var_two_var@arg`\n\nsparsity\n********\nUse z(x, y) to denote the variable *z* as a function of the variables\n*x* , *y* , and define H in terms of G by::\n\n    H( x, y, ... ) = G[ z(x, y) , x, y, ... ]\n\nOn input, *sparsity* is a sparsity pattern for the Jacobian of *G* .\nUpon return, *sparsity* is a sparsity pattern for the Jacobian of *H* .\n\n{xrst_end var_two_var_rev_jac}\n*/\n// BEGIN_TWO_VAR_REV_JAC\ntemplate <class Vector_set>\nvoid two_var_rev_jac(\n    size_t              i_z           ,\n    const addr_t*       arg           ,\n    Vector_set&         sparsity      )\n// END_TWO_VAR_REV_JAC\n{\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < i_z );\n    CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < i_z );\n\n    sparsity.binary_union( size_t(arg[0]), size_t(arg[0]), i_z, sparsity);\n    sparsity.binary_union( size_t(arg[1]), size_t(arg[1]), i_z, sparsity);\n\n    return;\n}\n// ---------------------------------------------------------------------------\n/*\n{xrst_begin var_two_var_for_hes dev}\n\nForward Hessian Sparsity for Two Variable Argument Operators\n############################################################\n\nx, y, z\n*******\nsee\n:ref:`var_two_var@x` ,\n:ref:`var_two_var@y` ,\n:ref:`var_two_var@z`\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_TWO_VAR_FOR_HES\n    // END_TWO_VAR_FOR_HES\n}\n\nVector_set, i_z, arg\n********************\nsee\n:ref:`var_two_var@Vector_set` ,\n:ref:`var_two_var@i_z` ,\n:ref:`var_two_var@arg`\n\n\nlinear\n******\n\nlinear[0]\n=========\nThis value is true (false) if the :math:`z(x, y)`\nmust have zero second partial derivative with respect to *x*\n(may have non-zero second partial).\n\nlinear[1]\n=========\nThis value is true (false) if the :math:`z(x, y)`\nmust have zero second partial derivative with respect to *y*\n(may have non-zero second partial).\n\nlinear[2]\n=========\nThis value is true (false) if the :math:`z(x, y)`\nmust have zero cross partial derivative\n(may have non-zero cross partial).\n\nn_independent_p1\n****************\nis the number of independent variables (in the tape) plus one.\n\nnum_var\n*******\nThis is the total number of variables in the tape\n(counting the phantom variable at index zero).\n\nfor_sparsity\n************\nOn input, all the linear and nonlinear interactions up to the\narguments to the atomic function have been take into account.\nUpon return, the linear and nonlinear interactions in\nthe atomic function have been take into account.\n\nHessian Sparsity\n================\nFor *j* equal 1 to *n_independent_p1* - 1,\nif *i* is in set with index *j* ,\nthe Hessian may have a non-zero partial with respect to the\nindependent variables with indices ( *i* - 1, *j* - 1 ) .\nNote that the index zero is not used because it corresponds to the\nphantom variable on the tape.\n\nJacobian Sparsity\n=================\nIf *i* is in the set with index *n_independent_p1* + *j* ,\nthe variable with index *j* may have a non-zero partial with resect to the\nindependent variable with index *i* - 1 .\n\n{xrst_end var_two_var_for_hes}\n*/\n// BEGIN_TWO_VAR_FOR_HES\ntemplate <class Vector_set>\nvoid two_var_for_hes(\n    size_t        n_independent_p1    ,\n    size_t        num_var             ,\n    size_t        i_z                 ,\n    const addr_t* arg                 ,\n    bool*         linear              ,\n    Vector_set&   for_sparsity        )\n// END_TWO_VAR_FOR_HES\n{  //\n    // np1, i_x, i_y, linear_x, linear_y, linear_xy\n    size_t np1 = n_independent_p1;\n    size_t i_x = size_t( arg[0] );\n    size_t i_y = size_t( arg[1] );\n    bool linear_x  = linear[0];\n    bool linear_y  = linear[1];\n    bool linear_xy = linear[2];\n    //\n    CPPAD_ASSERT_UNKNOWN( i_x < i_z  && i_y < i_z );\n    CPPAD_ASSERT_UNKNOWN( i_z < num_var );\n    CPPAD_ASSERT_UNKNOWN( for_sparsity.end() == np1 );\n    CPPAD_ASSERT_UNKNOWN( for_sparsity.n_set() == np1 + num_var );\n    CPPAD_ASSERT_UNKNOWN( for_sparsity.number_elements(np1) == 0 );\n    //\n    //\n    // for_sparsity\n    // Jacobian sparsity for z\n    for_sparsity.binary_union(np1 + i_z, np1 + i_x, np1 + i_y, for_sparsity);\n    //\n    //\n    if( ! linear_x )\n    {  //\n        // itr_x, i_u\n        typename Vector_set::const_iterator itr_x(for_sparsity, i_x + np1);\n        size_t i_u = *itr_x;\n        while( i_u < np1 )\n        {  // x depends on the independent variable u\n            //\n            // for_sparsity\n            // update Hessian term with one partial w.r.t u\n            if( ! linear_xy )\n            {  // other independent variables that z depends on\n                for_sparsity.binary_union(i_u, i_u, i_z + np1, for_sparsity);\n            }\n            else\n            {  // other independent variables that x depends on\n                for_sparsity.binary_union(i_u, i_u, i_x + np1, for_sparsity);\n            }\n            //\n            // i_u\n            i_u = *(++itr_x);\n        }\n    }\n    if( ! linear_y )\n    {  //\n        // itr_y, i_u\n        typename Vector_set::const_iterator itr_y(for_sparsity, i_y + np1);\n        size_t i_u = *itr_y;\n        while( i_u < np1 )\n        {  // y depends on the independent variable u\n            //\n            // for_sparsity\n            // update Hessian term with one partial w.r.t u\n            if( ! linear_xy )\n            {  // other independent variables that z depends on\n                for_sparsity.binary_union(i_u, i_u, i_z + np1, for_sparsity);\n            }\n            else\n            {  // other independent variables that y depends on\n                for_sparsity.binary_union(i_u, i_u, i_y + np1, for_sparsity);\n            }\n            //\n            // i_u\n            i_u = *(++itr_y);\n        }\n    }\n    if( (! linear_xy) && linear_x )\n    {  //\n        // itr_x, i_u\n        typename Vector_set::const_iterator itr_x(for_sparsity, i_x + np1);\n        size_t i_u = *itr_x;\n        while( i_u < np1 )\n        {  // x depends on the independent variable u\n            //\n            // for_sparsity\n            // update Hessian term with one partial w.r.t u other w.r.t\n            // independent variables that y depends on\n            for_sparsity.binary_union(i_u, i_u, i_y + np1, for_sparsity);\n            //\n            // i_u\n            i_u = *(++itr_x);\n        }\n    }\n    if( (! linear_xy) && linear_y )\n    {  //\n        // itr_y, i_u\n        typename Vector_set::const_iterator itr_y(for_sparsity, i_y + np1);\n        size_t i_u = *itr_y;\n        while( i_u < np1 )\n        {  // y depends on the independent variable u\n            //\n            // for_sparsity\n            // update Hessian term with one partial w.r.t u other w.r.t\n            // independent variables that x depends on\n            for_sparsity.binary_union(i_u, i_u, i_x + np1, for_sparsity);\n            //\n            // i_u\n            i_u = *(++itr_y);\n        }\n    }\n}\n// ---------------------------------------------------------------------------\n/*\n{xrst_begin var_two_var_rev_hes dev}\n\nReverse Jacobian Sparsity for Two Variable Argument Operators\n#############################################################\n\nx, y, z\n*******\nsee\n:ref:`var_two_var@x` ,\n:ref:`var_two_var@y` ,\n:ref:`var_two_var@z`\n\nG and H\n*******\nUse z(x, y) to denote the variable *z* as a function of the variables\n*x* , *y* , and define H in terms of G by::\n\n    H( x, y, ... ) = G[ z(x, y) , x, y, ... ]\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_TWO_VAR_REV_HES\n    // END_TWO_VAR_REV_HES\n}\n\nVector_set, i_z, arg\n********************\nsee\n:ref:`var_two_var@Vector_set` ,\n:ref:`var_two_var@i_z` ,\n:ref:`var_two_var@arg`\n\nlinear\n******\n\nlinear[0]\n=========\nThis value is true (false) if the :math:`z(x, y)`\nmust have zero second partial derivative with respect to *x*\n(may have non-zero second partial).\n\nlinear[1]\n=========\nThis value is true (false) if the :math:`z(x, y)`\nmust have zero second partial derivative with respect to *y*\n(may have non-zero second partial).\n\nlinear[2]\n=========\nThis value is true (false) if the :math:`z(x, y)`\nmust have zero cross partial derivative\n(may have non-zero cross partial).\n\nn_independent_p1\n****************\nis the number of independent variables (in the tape) plus one.\n\nnum_var\n*******\nThis is the total number of variables in the tape\n(counting the phantom variable at index zero).\n\nfor_jac_sparsity\n****************\nThe set with index *j* is the forward Jacobian sparsity\npattern for the variable with index *j*.\n\nrev_jac_include\n***************\nIf the *j* element of this vector is true,\nthe variable with index *j* is included in the Hessian,\nor affects the value of a variable that is included in the Hessian.\n\nInput\n=====\n::\n\n    for j = num_var, ... , i_z + 1\n        rev_jac_include[j] is an input\n\nOutput\n======\nrev_jac_include[i_z] is an output\n\nrev_hes_sparsity\n****************\nOn input (output), this is the sparsity pattern for *G* ( *H* ).\nFor each variable index *j* ,\n*rev_hes_sparsity* [ *j* ] is the set of indices\nthat may have non-zero cross partials with variable index *j* .\n\nExample\n=======\nIf the indices in the sets correspond to the independent variables,\nthen *rev_hes_sparsity* ``.end()`` is the number of independent variables.\nFor *i* a variable index between 1 and the number of independent variables,\n*i* - 1 is the corresponding independent variable index.\n(The index *i* = 0 corresponds to the phantom variable at the beginning\nof the tape. )\n{xrst_end var_two_var_rev_hes}\n*/\n// BEGIN_TWO_VAR_REV_HES\ntemplate <class Vector_set>\nvoid two_var_rev_hes(\n    size_t              i_z               ,\n    const addr_t*       arg               ,\n    bool*               linear            ,\n    bool*               rev_jacobian      ,\n    const Vector_set&   for_jac_sparsity  ,\n    Vector_set&         rev_hes_sparsity  )\n// END_TWO_VAR_REV_HES\n{   //\n    // check for nothing to do\n    if( ! rev_jacobian[i_z] )\n        return;\n    //\n    // i_x, i_y, linear_x, linear_y, linear_xy\n    size_t i_x = size_t( arg[0] );\n    size_t i_y = size_t( arg[1] );\n    bool linear_x  = linear[0];\n    bool linear_y  = linear[1];\n    bool linear_xy = linear[2];\n    //\n    CPPAD_ASSERT_UNKNOWN( i_x < i_z );\n    CPPAD_ASSERT_UNKNOWN( i_y < i_z );\n    //\n    // rev_hes_sparsity\n    // propagate form z to x and y\n    rev_hes_sparsity.binary_union(i_x, i_x, i_z, rev_hes_sparsity);\n    rev_hes_sparsity.binary_union(i_y, i_y, i_z, rev_hes_sparsity);\n    //\n    if( ! linear_x )\n    {   rev_hes_sparsity.binary_union(i_x, i_x, i_x, for_jac_sparsity);\n        rev_hes_sparsity.binary_union(i_y, i_y, i_x, for_jac_sparsity);\n    }\n    if( ! linear_y )\n    {   rev_hes_sparsity.binary_union(i_x, i_x, i_y, for_jac_sparsity);\n        rev_hes_sparsity.binary_union(i_y, i_y, i_y, for_jac_sparsity);\n    }\n    if( ! linear_xy )\n    {   rev_hes_sparsity.binary_union(i_x, i_x, i_y, for_jac_sparsity);\n        rev_hes_sparsity.binary_union(i_y, i_y, i_x, for_jac_sparsity);\n    }\n    //\n    // rev_jacobian\n    rev_jacobian[i_x] = true;\n    rev_jacobian[i_y] = true;\n}\n// ---------------------------------------------------------------------------\n} } } // END_CPPAD_LOCAL_SPARSE_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/local/var_op/unary_op.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin_parent var_unary_op dev}\n{xrst_spell\n    acosh\n    asinh\n    erfc\n    expm\n    neg\n}\n\nUnary Variable Operators\n########################\nAll these operators have the same prototype and could be implemented as\nvirtual functions for a unary base case.\nCompilers can not optimize across virtual function calls and testing indicates\nthat a virtual function implementation is significant slower.\n\nUser Syntax\n***********\n| *z* = *Fun* ( *x* )\n\nx\n*\nis the argument to this operator which must be a variable.\n\nz\n*\nis the primary result for this operator which is also a variable.\nSome unary operators have an auxiliary result;\nsee :ref:`var_unary_op@n_res` below.\n\nBase\n****\nbase type for the operator; i.e., this operation was recorded\nusing AD<Base> and computations by these operators done using type Base.\n\nFun\n***\n\n.. csv-table::\n    :widths: auto\n    :header-rows: 1\n\n    op_code,    Fun,      z\n    AbsOp,     fabs,      absolute value of *x*\n    AcosOp,    acos,      inverse cosine of *x*\n    AcoshOp,   acosh,     inverse hyperbolic cosine of *x*\n    AsinOp,    asin,      inverse sine of *x*\n    AsinhOp,   asinh,     inverse hyperbolic sine of *x*\n    AtanOp,    atan,      inverse tangent  of *x*\n    AtanhOp,   atanh,     inverse hyperbolic tangent of *x*\n    CosOp,     cos,       cosine of *x*\n    CoshOp,    cosh,      hyperbolic cosine of *x*\n    ErfOp,     erf,       error function of *x*\n    ErfcOp,    erfc,      complementary error function of *x*\n    ExpOp,     exp,       exponential of *x*\n    Expm1Op,   expm1,     exponential of *x* minus one\n    Log1pOp,   log1p,     logarithm of 1 + *x*\n    LogOp,     log,       logarithm of *x*\n    NegOp,     -,         minus *x*\n    SignOp,    sign,      sign of *x*\n    SinOp,     sin,       sine of *x*\n    SinhOp,    sinh,      hyperbolic sine of *x*\n    SqrtOp,    sqrt,      square root of *x*\n    TanOp,     tan,       tangent of *x*\n    TanhOp,    tanh,      hyperbolic tangent of *x*\n\ni_z\n***\nis the variable index corresponding to *z* .\n\nn_res\n*****\nis the number of results that are variables.\nThis is 2 (1) for unary operators that have (do not have) an auxiliary result.\nIf an operator has an auxiliary result, the variable index for the\nauxiliary result is *i_z* - 1 .\n\narg\n***\n*arg* [0] is the variable index corresponding to *x* .\n\n{xrst_end var_unary_op}\n------------------------------------------------------------------------------\n{xrst_begin var_unary_forward_0 dev}\n\nZero Order Forward Unary Variable Operators\n###########################################\n\nx, z, n_res\n***********\nsee\n:ref:`var_unary_op@x` ,\n:ref:`var_unary_op@z` ,\n:ref:`var_unary_op@n_res`\n\nPrototype\n*********\n{xrst_code cpp}\ntemplate <class Base>\ninline void Fun_forward_0(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{xrst_code}\n\nBase, Fun, i_z, arg\n*******************\nsee\n:ref:`var_unary_op@Base` ,\n:ref:`var_unary_op@Fun` ,\n:ref:`var_unary_op@i_z` ,\n:ref:`var_unary_op@arg`\n\ncap_order\n*********\nis the maximum number of orders that can fit in *taylor* .\n\ntaylor\n******\nThe Taylor coefficient corresponding to variable *i* and order *k* is\n\n    *taylor* [ *i* * *cap_order* + *k*  ]\n\nInput\n=====\nThe zero order Taylor coefficients\nfor variables with index *i* less than or equal *i_z* - *n_res* .\n\nOutput\n======\nThe zero order Taylor coefficients for variables with index\n*i_z* and *i_z* - *n_res* + 1.\n\n{xrst_end var_unary_forward_0}\n------------------------------------------------------------------------------\n{xrst_begin var_unary_forward_any dev}\n\nAny Order Forward Unary Variable Operators\n##########################################\n\nx, z, n_res\n***********\nsee\n:ref:`var_unary_op@x` ,\n:ref:`var_unary_op@z` ,\n:ref:`var_unary_op@n_res`\n\nPrototype\n*********\n{xrst_code cpp}\ntemplate <class Base>\ninline void Fun_forward_any(\n    size_t        order_low   ,\n    size_t        order_up    ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{xrst_code}\n\nBase, Fun, i_z, arg\n*******************\nsee\n:ref:`var_unary_op@Base` ,\n:ref:`var_unary_op@Fun` ,\n:ref:`var_unary_op@i_z` ,\n:ref:`var_unary_op@arg`\n\n{xrst_template ;\n    include/cppad/local/var_op/template/forward_op.xrst\n    headers: cap_order, order_low, order_up, taylor\n}\n\n\n{xrst_end var_unary_forward_any}\n------------------------------------------------------------------------------\n{xrst_begin var_unary_forward_dir dev}\n\nMultiple Direction Forward Unary Operators\n##########################################\n\nx, z, n_res\n***********\nsee\n:ref:`var_unary_op@x` ,\n:ref:`var_unary_op@z` ,\n:ref:`var_unary_op@n_res`\n\nPrototype\n*********\n{xrst_code cpp}\ntemplate <class Base>\ninline void Fun_forward_dir(\n    size_t        order_up    ,\n    size_t        n_dir       ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{xrst_code}\n\nBase, Fun, i_z, arg\n*******************\nsee\n:ref:`var_unary_op@Base` ,\n:ref:`var_unary_op@Fun` ,\n:ref:`var_unary_op@i_z` ,\n:ref:`var_unary_op@arg`\n\n{xrst_template ;\n    include/cppad/local/var_op/template/forward_dir.xrst\n    headers: n_dir, cap_order, order_up, taylor\n}\n\n{xrst_end var_unary_forward_dir}\n------------------------------------------------------------------------------\n{xrst_begin var_unary_reverse dev}\n\nReverse Mode Unary Operators\n############################\n\nx, z, n_res\n***********\nsee\n:ref:`var_unary_op@x` ,\n:ref:`var_unary_op@z` ,\n:ref:`var_unary_op@n_res`\n\nPrototype\n*********\n{xrst_code cpp}\ntemplate <class Base>\ninline void Fun_reverse(\n    size_t        i_z          ,\n    const addr_t* arg          ,\n    size_t        cap_order    ,\n    const Base*   taylor       ,\n    size_t        n_order      ,\n    Base*         partial      )\n{xrst_code}\n\nBase, Fun, i_z, arg\n*******************\nsee\n:ref:`var_unary_op@Base` ,\n:ref:`var_unary_op@Fun` ,\n:ref:`var_unary_op@i_z` ,\n:ref:`var_unary_op@arg`\n\ncap_order\n*********\nis the maximum number of orders that can fit in *taylor* .\n\ntaylor\n******\nThe Taylor coefficient corresponding to variable *i* and order *k* is\n\n    *taylor* [ *i* * *cap_order* + *k*  ]\n\n{xrst_template ;\n    include/cppad/local/var_op/template/reverse_op.xrst\n    headers: n_order, partial\n\n    @x, y@ ; x\n}\n\n{xrst_end var_unary_reverse}\n------------------------------------------------------------------------------\n"
  },
  {
    "path": "include/cppad/local/var_op/var_op.hpp",
    "content": "# ifndef CPPAD_LOCAL_VAR_OP_VAR_OP_HPP\n# define CPPAD_LOCAL_VAR_OP_VAR_OP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n// used by the sparse operators\n# include <cppad/local/sparse/internal.hpp>\n\n// operations\n# include <cppad/core/std_math_11.hpp>\n# include <cppad/local/var_op/abs_op.hpp>\n# include <cppad/local/var_op/add_op.hpp>\n# include <cppad/local/var_op/acos_op.hpp>\n# include <cppad/local/var_op/acosh_op.hpp>\n# include <cppad/local/var_op/asin_op.hpp>\n# include <cppad/local/var_op/asinh_op.hpp>\n# include <cppad/local/var_op/atan_op.hpp>\n# include <cppad/local/var_op/atanh_op.hpp>\n# include <cppad/local/var_op/cexp_op.hpp>\n# include <cppad/local/var_op/cos_op.hpp>\n# include <cppad/local/var_op/cosh_op.hpp>\n# include <cppad/local/var_op/cskip_op.hpp>\n# include <cppad/local/var_op/csum_op.hpp>\n# include <cppad/local/var_op/dis_op.hpp>\n# include <cppad/local/var_op/div_op.hpp>\n# include <cppad/local/var_op/erf_op.hpp>\n# include <cppad/local/var_op/exp_op.hpp>\n# include <cppad/local/var_op/expm1_op.hpp>\n# include <cppad/local/var_op/load_op.hpp>\n# include <cppad/local/var_op/log_op.hpp>\n# include <cppad/local/var_op/log1p_op.hpp>\n# include <cppad/local/var_op/mul_op.hpp>\n# include <cppad/local/var_op/neg_op.hpp>\n# include <cppad/local/var_op/par_op.hpp>\n# include <cppad/local/var_op/pow_op.hpp>\n# include <cppad/local/var_op/pri_op.hpp>\n# include <cppad/local/var_op/sign_op.hpp>\n# include <cppad/local/var_op/sin_op.hpp>\n# include <cppad/local/var_op/sinh_op.hpp>\n# include <cppad/local/var_op/sqrt_op.hpp>\n# include <cppad/local/var_op/sub_op.hpp>\n# include <cppad/local/var_op/two_var.hpp>\n# include <cppad/local/var_op/one_var.hpp>\n# include <cppad/local/var_op/store_op.hpp>\n# include <cppad/local/var_op/tan_op.hpp>\n# include <cppad/local/var_op/tanh_op.hpp>\n# include <cppad/local/var_op/zmul_op.hpp>\n\n\n# endif\n"
  },
  {
    "path": "include/cppad/local/var_op/zmul_op.hpp",
    "content": "# ifndef CPPAD_LOCAL_VAR_OP_ZMUL_OP_HPP\n# define CPPAD_LOCAL_VAR_OP_ZMUL_OP_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\nnamespace CppAD { namespace local { namespace var_op {\n\n// --------------------------- Zmulvv -----------------------------------------\n\n// See dev documentation: forward_binary_op\ntemplate <class Base>\ninline void zmulvv_forward_any(\n    size_t        order_low   ,\n    size_t        order_up    ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // p, q\n    size_t p = order_low;\n    size_t q = order_up;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(ZmulvvOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(ZmulvvOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n    CPPAD_ASSERT_UNKNOWN( p <= q );\n\n    // Taylor coefficients corresponding to arguments and result\n    Base* x = taylor + size_t(arg[0]) * cap_order;\n    Base* y = taylor + size_t(arg[1]) * cap_order;\n    Base* z = taylor + i_z    * cap_order;\n\n    size_t k;\n    for(size_t d = p; d <= q; d++)\n    {   z[d] = Base(0.0);\n        for(k = 0; k <= d; k++)\n            z[d] += azmul(x[d-k], y[k]);\n    }\n}\n\n// See dev documentation: forward_binary_op\ntemplate <class Base>\ninline void zmulvv_forward_dir(\n    size_t        order_up    ,\n    size_t        n_dir       ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // q, r\n    size_t q = order_up;\n    size_t r = n_dir;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(ZmulvvOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(ZmulvvOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( 0 < q );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n\n    // Taylor coefficients corresponding to arguments and result\n    size_t num_taylor_per_var = (cap_order-1) * r + 1;\n    Base* x = taylor + size_t(arg[0]) * num_taylor_per_var;\n    Base* y = taylor + size_t(arg[1]) * num_taylor_per_var;\n    Base* z = taylor +    i_z * num_taylor_per_var;\n\n    size_t k, ell, m;\n    for(ell = 0; ell < r; ell++)\n    {   m = (q-1)*r + ell + 1;\n        z[m] = azmul(x[0], y[m]) + azmul(x[m],  y[0]);\n        for(k = 1; k < q; k++)\n            z[m] += azmul(x[(q-k-1)*r + ell + 1], y[(k-1)*r + ell + 1]);\n    }\n}\n\n\n// See dev documentation: forward_binary_op\ntemplate <class Base>\ninline void zmulvv_forward_0(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{   //\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(ZmulvvOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(ZmulvvOp) == 1 );\n\n    // Taylor coefficients corresponding to arguments and result\n    Base* x = taylor + size_t(arg[0]) * cap_order;\n    Base* y = taylor + size_t(arg[1]) * cap_order;\n    Base* z = taylor + i_z    * cap_order;\n\n    z[0] = azmul(x[0], y[0]);\n}\n\n\n// See dev documentation: reverse_binary_op\ntemplate <class Base>\ninline void zmulvv_reverse(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    const Base*   taylor      ,\n    size_t        n_order     ,\n    Base*         partial     )\n{   // d\n    //\n    size_t d = n_order - 1;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(ZmulvvOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(ZmulvvOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( n_order <= cap_order );\n\n    // Arguments\n    const Base* x  = taylor + size_t(arg[0]) * cap_order;\n    const Base* y  = taylor + size_t(arg[1]) * cap_order;\n\n    // Partial derivatives corresponding to arguments and result\n    Base* px = partial + size_t(arg[0]) * n_order;\n    Base* py = partial + size_t(arg[1]) * n_order;\n    Base* pz = partial + i_z    * n_order;\n\n    // number of indices to access\n    size_t j = d + 1;\n    size_t k;\n    while(j)\n    {   --j;\n        for(k = 0; k <= j; k++)\n        {\n            px[j-k] += azmul(pz[j], y[k]);\n            py[k]   += azmul(pz[j], x[j-k]);\n        }\n    }\n}\n// --------------------------- Zmulpv -----------------------------------------\n\n// See dev documentation: forward_binary_op\ntemplate <class Base>\ninline void zmulpv_forward_any(\n    size_t        order_low   ,\n    size_t        order_up    ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // p, q\n    size_t p = order_low;\n    size_t q = order_up;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(ZmulpvOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(ZmulpvOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n    CPPAD_ASSERT_UNKNOWN( p <= q );\n\n    // Taylor coefficients corresponding to arguments and result\n    Base* y = taylor + size_t(arg[1]) * cap_order;\n    Base* z = taylor + i_z    * cap_order;\n\n    // Paraemter value\n    Base x = parameter[ arg[0] ];\n\n    for(size_t d = p; d <= q; d++)\n        z[d] = azmul(x, y[d]);\n}\n\n// See dev documentation: forward_binary_op\ntemplate <class Base>\ninline void zmulpv_forward_dir(\n    size_t        order_up    ,\n    size_t        n_dir       ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // q, r\n    size_t q = order_up;\n    size_t r = n_dir;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(ZmulpvOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(ZmulpvOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( 0 < q );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n\n    // Taylor coefficients corresponding to arguments and result\n    size_t num_taylor_per_var = (cap_order-1) * r + 1;\n    size_t m                  = (q-1) * r + 1;\n    Base* y = taylor + size_t(arg[1]) * num_taylor_per_var + m;\n    Base* z = taylor + i_z    * num_taylor_per_var + m;\n\n    // Paraemter value\n    Base x = parameter[ arg[0] ];\n\n    for(size_t ell = 0; ell < r; ell++)\n        z[ell] = azmul(x, y[ell]);\n}\n\n// See dev documentation: forward_binary_op\ntemplate <class Base>\ninline void zmulpv_forward_0(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{   //\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(ZmulpvOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(ZmulpvOp) == 1 );\n\n    // Paraemter value\n    Base x = parameter[ arg[0] ];\n\n    // Taylor coefficients corresponding to arguments and result\n    Base* y = taylor + size_t(arg[1]) * cap_order;\n    Base* z = taylor + i_z    * cap_order;\n\n    z[0] = azmul(x, y[0]);\n}\n\n\n// See dev documentation: reverse_binary_op\ntemplate <class Base>\ninline void zmulpv_reverse(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    const Base*   taylor      ,\n    size_t        n_order     ,\n    Base*         partial     )\n{   // d\n    //\n    size_t d = n_order - 1;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(ZmulpvOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(ZmulpvOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( n_order <= cap_order );\n\n    // Arguments\n    Base x  = parameter[ arg[0] ];\n\n    // Partial derivatives corresponding to arguments and result\n    Base* py = partial + size_t(arg[1]) * n_order;\n    Base* pz = partial + i_z    * n_order;\n\n    // number of indices to access\n    size_t j = d + 1;\n    while(j)\n    {   --j;\n        py[j] += azmul(pz[j], x);\n    }\n}\n// --------------------------- Zmulvp -----------------------------------------\n\n// See dev documentation: forward_binary_op\ntemplate <class Base>\ninline void zmulvp_forward_any(\n    size_t        order_low   ,\n    size_t        order_up    ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // p, q\n    size_t p = order_low;\n    size_t q = order_up;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(ZmulvpOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(ZmulvpOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n    CPPAD_ASSERT_UNKNOWN( p <= q );\n\n    // Taylor coefficients corresponding to arguments and result\n    Base* x = taylor + size_t(arg[0]) * cap_order;\n    Base* z = taylor + i_z    * cap_order;\n\n    // Paraemter value\n    Base y = parameter[ arg[1] ];\n\n    for(size_t d = p; d <= q; d++)\n        z[d] = azmul(x[d], y);\n}\n\n// See dev documentation: forward_binary_op\ntemplate <class Base>\ninline void zmulvp_forward_dir(\n    size_t        order_up    ,\n    size_t        n_dir       ,\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{    // q, r\n    size_t q = order_up;\n    size_t r = n_dir;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(ZmulvpOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(ZmulvpOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( 0 < q );\n    CPPAD_ASSERT_UNKNOWN( q < cap_order );\n\n    // Taylor coefficients corresponding to arguments and result\n    size_t num_taylor_per_var = (cap_order-1) * r + 1;\n    size_t m                  = (q-1) * r + 1;\n    Base* x = taylor + size_t(arg[0]) * num_taylor_per_var + m;\n    Base* z = taylor + i_z    * num_taylor_per_var + m;\n\n    // Paraemter value\n    Base y = parameter[ arg[1] ];\n\n    for(size_t ell = 0; ell < r; ell++)\n        z[ell] = azmul(x[ell], y);\n}\n\n// See dev documentation: forward_binary_op\ntemplate <class Base>\ninline void zmulvp_forward_0(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    Base*         taylor      )\n{   //\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(ZmulvpOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(ZmulvpOp) == 1 );\n\n    // Paraemter value\n    Base y = parameter[ arg[1] ];\n\n    // Taylor coefficients corresponding to arguments and result\n    Base* x = taylor + size_t(arg[0]) * cap_order;\n    Base* z = taylor + i_z    * cap_order;\n\n    z[0] = azmul(x[0], y);\n}\n\n\n// See dev documentation: reverse_binary_op\ntemplate <class Base>\ninline void zmulvp_reverse(\n    size_t        i_z         ,\n    const addr_t* arg         ,\n    const Base*   parameter   ,\n    size_t        cap_order   ,\n    const Base*   taylor      ,\n    size_t        n_order     ,\n    Base*         partial     )\n{   // d\n    //\n    size_t d = n_order - 1;\n    //\n    // check assumptions\n    CPPAD_ASSERT_UNKNOWN( NumArg(ZmulvpOp) == 2 );\n    CPPAD_ASSERT_UNKNOWN( NumRes(ZmulvpOp) == 1 );\n    CPPAD_ASSERT_UNKNOWN( n_order <= cap_order );\n\n    // Arguments\n    Base y  = parameter[ arg[1] ];\n\n    // Partial derivatives corresponding to arguments and result\n    Base* px = partial + size_t(arg[0]) * n_order;\n    Base* pz = partial + i_z    * n_order;\n\n    // number of indices to access\n    size_t j = d + 1;\n    while(j)\n    {   --j;\n        px[j] += azmul(pz[j], y);\n    }\n}\n\n} } } // END namespace\n# endif\n"
  },
  {
    "path": "include/cppad/speed/det_33.hpp",
    "content": "# ifndef CPPAD_SPEED_DET_33_HPP\n# define CPPAD_SPEED_DET_33_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin det_33}\n\nCheck Determinant of 3 by 3 matrix\n##################################\n\nSyntax\n******\n| # ``include <cppad/speed/det_33.hpp>``\n| *ok* = ``det_33`` ( *x* , *d* )\n\nPurpose\n*******\nThis routine can be used to check a method for computing\nthe determinant of a matrix.\n\nInclusion\n*********\nThe template function ``det_33`` is defined in the ``CppAD``\nnamespace by including\nthe file ``cppad/speed/det_33.hpp``\n(relative to the CppAD distribution directory).\n\nx\n*\nThe argument *x* has prototype\n\n    ``const`` *Vector* & *x*\n\n.\nIt contains the elements of the matrix :math:`X` in row major order; i.e.,\n\n.. math::\n\n    X_{i,j} = x [ i * 3 + j ]\n\nd\n*\nThe argument *d* has prototype\n\n    ``const`` *Vector* & *d*\n\n.\nIt is tested to see if *d* [0] it is equal to :math:`\\det ( X )`.\n\nVector\n******\nIf *y* is a *Vector* object,\nit must support the syntax\n\n    *y* [ *i* ]\n\nwhere *i* has type ``size_t`` with value less than 9.\nThis must return a ``double`` value corresponding to the *i*-th\nelement of the vector *y* .\nThis is the only requirement of the type *Vector* .\n(Note that only the first element of the vector *d* is used.)\n\nok\n**\nThe return value *ok* has prototype\n\n    ``bool`` *ok*\n\nIt is true, if the determinant *d* [0]\npasses the test and false otherwise.\n{xrst_toc_hidden\n    xrst/det_33_hpp.xrst\n}\n\nSource Code\n***********\nThe file\n:ref:`det_33.hpp-name`\ncontains the source code for this template function.\n\n{xrst_end det_33}\n------------------------------------------------------------------------------\n*/\n// BEGIN C++\n# include <cppad/utility/near_equal.hpp>\nnamespace CppAD {\ntemplate <class Vector>\n    bool det_33(const Vector &x, const Vector &d)\n    {   bool ok = true;\n        double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n        // use expansion by minors to compute the determinant by hand\n        double check = 0.;\n        check += x[0] * ( x[4] * x[8] - x[5] * x[7] );\n        check -= x[1] * ( x[3] * x[8] - x[5] * x[6] );\n        check += x[2] * ( x[3] * x[7] - x[4] * x[6] );\n\n        ok &= CppAD::NearEqual(check, d[0], eps99, eps99);\n\n        return ok;\n    }\n}\n// END C++\n# endif\n"
  },
  {
    "path": "include/cppad/speed/det_by_lu.hpp",
    "content": "# ifndef CPPAD_SPEED_DET_BY_LU_HPP\n# define CPPAD_SPEED_DET_BY_LU_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin det_by_lu}\n\nDeterminant Using Expansion by Lu Factorization\n###############################################\n\nSyntax\n******\n| # ``include <cppad/speed/det_by_lu.hpp>``\n| ``det_by_lu`` < *Scalar* > *det* ( *n* )\n| *d* = *det* ( *a* )\n\nInclusion\n*********\nThe template class ``det_by_lu`` is defined in the ``CppAD``\nnamespace by including\nthe file ``cppad/speed/det_by_lu.hpp``\n(relative to the CppAD distribution directory).\n\nConstructor\n***********\nThe syntax\n\n    ``det_by_lu`` < *Scalar* > *det* ( *n* )\n\nconstructs the object *det* which can be used for\nevaluating the determinant of *n* by *n* matrices\nusing LU factorization.\n\nScalar\n******\nThe type *Scalar* can be any\n:ref:`NumericType-name`\n\nn\n*\nThe argument *n* has prototype\n\n    ``size_t`` *n*\n\ndet\n***\nThe syntax\n\n    *d* = *det* ( *a* )\n\nreturns the determinant of the matrix :math:`A` using LU factorization.\n\na\n=\nThe argument *a* has prototype\n\n    ``const`` *Vector* & *a*\n\nIt must be a *Vector* with length :math:`n * n` and with\nIt must be a *Vector* with length :math:`n * n` and with\nelements of type *Scalar* .\nThe elements of the :math:`n \\times n` matrix :math:`A` are defined,\nfor :math:`i = 0 , \\ldots , n-1` and :math:`j = 0 , \\ldots , n-1`, by\n\n.. math::\n\n    A_{i,j} = a[ i * m + j]\n\nd\n=\nThe return value *d* has prototype\n\n    *Scalar* *d*\n\nVector\n******\nIf *y* is a *Vector* object,\nit must support the syntax\n\n    *y* [ *i* ]\n\nwhere *i* has type ``size_t`` with value less than :math:`n * n`.\nThis must return a *Scalar* value corresponding to the *i*-th\nelement of the vector *y* .\nThis is the only requirement of the type *Vector* .\n{xrst_toc_hidden\n    speed/example/det_by_lu.cpp\n    xrst/det_by_lu_hpp.xrst\n}\n\nExample\n*******\nThe file\n:ref:`det_by_lu.cpp-name`\ncontains an example and test of ``det_by_lu.hpp`` .\n\nSource Code\n***********\nThe file\n:ref:`det_by_lu.hpp-name`\ncontains the source for this template function.\n\n{xrst_end det_by_lu}\n---------------------------------------------------------------------------\n*/\n// BEGIN C++\n# include <cppad/utility/vector.hpp>\n# include <cppad/utility/lu_solve.hpp>\n\n// BEGIN CppAD namespace\nnamespace CppAD {\n\ntemplate <class Scalar>\nclass det_by_lu {\nprivate:\n    const size_t m_;\n    const size_t n_;\n    CppAD::vector<Scalar> A_;\n    CppAD::vector<Scalar> B_;\n    CppAD::vector<Scalar> X_;\npublic:\n    det_by_lu(size_t n) : m_(0), n_(n), A_(n * n)\n    {   }\n\n    template <class Vector>\n    Scalar operator()(const Vector &x)\n    {\n\n        Scalar       logdet;\n        Scalar       det;\n        int          signdet;\n        size_t       i;\n\n        // copy matrix so it is not overwritten\n        for(i = 0; i < n_ * n_; i++)\n            A_[i] = x[i];\n\n        // compute log determinant\n        signdet = CppAD::LuSolve(\n            n_, m_, A_, B_, X_, logdet);\n\n/*\n        // Do not do this for speed test because it makes floating\n        // point operation sequence very simple.\n        if( signdet == 0 )\n            det = 0;\n        else\n            det =  Scalar( signdet ) * exp( logdet );\n*/\n\n        // convert to determinant\n        det     = Scalar( signdet ) * exp( logdet );\n\n# ifdef FADBAD\n        // Fadbad requires temporaries to be set to constants\n        for(i = 0; i < n_ * n_; i++)\n            A_[i] = 0;\n# endif\n\n        return det;\n    }\n};\n} // END CppAD namespace\n// END C++\n# endif\n"
  },
  {
    "path": "include/cppad/speed/det_by_minor.hpp",
    "content": "# ifndef CPPAD_SPEED_DET_BY_MINOR_HPP\n# define CPPAD_SPEED_DET_BY_MINOR_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin det_by_minor}\n\nDeterminant Using Expansion by Minors\n#####################################\n\nSyntax\n******\n| ``# include <cppad/speed/det_by_minor.hpp>``\n| ``det_by_minor`` < *Scalar* > *det* ( *n* )\n| *d* = *det* ( *a* )\n\nInclusion\n*********\nThe template class ``det_by_minor`` is defined in the ``CppAD``\nnamespace by including the file ``cppad/speed/det_by_minor.hpp`` .\n\nConstructor\n***********\nThe syntax\n\n    ``det_by_minor`` < *Scalar* > *det* ( *n* )\n\nconstructs the object *det* which can be used for\nevaluating the determinant of *n* by *n* matrices\nusing expansion by minors.\n\nScalar\n******\nThe type *Scalar* must satisfy the same conditions\nas in the function :ref:`det_of_minor<det_of_minor@Scalar>` .\n\nn\n*\nThe argument *n* has prototype\n\n    ``size_t`` *n*\n\ndet\n***\nThe syntax\n\n    *d* = *det* ( *a* )\n\nreturns the determinant of the matrix *A* using expansion by minors.\n\na\n=\nThe argument *a* has prototype\n\n    ``const`` *Vector* & *a*\n\nIt must be a *Vector* with length :math:`n * n` and with\nelements of type *Scalar* .\nThe elements of the :math:`n \\times n` matrix :math:`A` are defined,\nfor :math:`i = 0 , \\ldots , n-1` and :math:`j = 0 , \\ldots , n-1`, by\n\n.. math::\n\n    A_{i,j} = a[ i * m + j]\n\nd\n=\nThe return value *d* has prototype\n\n    *Scalar* *d*\n\nIt is equal to the determinant of :math:`A`.\n\nVector\n******\nIf *y* is a *Vector* object,\nit must support the syntax\n\n    *y* [ *i* ]\n\nwhere *i* has type ``size_t`` with value less than :math:`n * n`.\nThis must return a *Scalar* value corresponding to the *i*-th\nelement of the vector *y* .\nThis is the only requirement of the type *Vector* .\n{xrst_toc_hidden\n    speed/example/det_by_minor.cpp\n    xrst/det_by_minor_hpp.xrst\n}\n\nExample\n*******\nThe file\n:ref:`det_by_minor.cpp-name`\ncontains an example and test of ``det_by_minor.hpp`` .\n\nSource Code\n***********\nThe file\n:ref:`det_by_minor.hpp-name`\ncontains the source for this template function.\n\n{xrst_end det_by_minor}\n---------------------------------------------------------------------------\n*/\n// BEGIN C++\n# include <cppad/speed/det_of_minor.hpp>\n# include <vector>\n\n// BEGIN CppAD namespace\nnamespace CppAD {\n\ntemplate <class Scalar>\nclass det_by_minor {\nprivate:\n    //\n    // m_\n    // size for the matrix\n    const size_t        m_;\n    //\n    // r_, c_\n    // row and column indices so that minor is entire matrix.\n    std::vector<size_t> r_;\n    std::vector<size_t> c_;\n    //\n    // a_\n    // temporary vector declared here to avoid reallocation for each use\n    std::vector<Scalar> a_;\npublic:\n    det_by_minor(size_t m) : m_(m) , r_(m + 1) , c_(m + 1), a_(m * m)\n    {   //\n        // r_, c_\n        // values that correspond to entire matrix\n        for(size_t i = 0; i < m; i++)\n        {   r_[i] = i+1;\n            c_[i] = i+1;\n        }\n        r_[m] = 0;\n        c_[m] = 0;\n    }\n    //\n    // operator()\n    template <class Vector>\n    Scalar operator()(const Vector &x)\n    {   //\n        // a_\n        // copy from type Vector to std::vector<Scalar>\n        for(size_t i = 0; i < m_ * m_; ++i)\n            a_[i] = x[i];\n        //\n        // det\n        // compute determinant of entire matrix\n        Scalar det = det_of_minor(a_, m_, m_, r_, c_);\n        //\n# ifndef NDEBUG\n        // r_, c_\n        // values that correspond to entire matrix\n        // (not const because det_of_minor uses r_, c_ for work space)\n        for(size_t i = 0; i < m_; ++i)\n        {   assert( r_[i] == i + 1 );\n            assert( c_[i] == i + 1 );\n        }\n        assert( r_[m_] == 0 );\n        assert( c_[m_] == 0 );\n# endif\n        return det;\n    }\n\n};\n\n} // END CppAD namespace\n// END C++\n# endif\n"
  },
  {
    "path": "include/cppad/speed/det_grad_33.hpp",
    "content": "# ifndef CPPAD_SPEED_DET_GRAD_33_HPP\n# define CPPAD_SPEED_DET_GRAD_33_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin det_grad_33}\n\nCheck Gradient of Determinant of 3 by 3 matrix\n##############################################\n\nSyntax\n******\n| # ``include <cppad/speed/det_grad_33.hpp>``\n| *ok* = ``det_grad_33`` ( *x* , *g* )\n\nPurpose\n*******\nThis routine can be used to check a method for computing the\ngradient of the determinant of a matrix.\n\nInclusion\n*********\nThe template function ``det_grad_33`` is defined in the ``CppAD``\nnamespace by including\nthe file ``cppad/speed/det_grad_33.hpp``\n(relative to the CppAD distribution directory).\n\nx\n*\nThe argument *x* has prototype\n\n    ``const`` *Vector* & *x*\n\n.\nIt contains the elements of the matrix :math:`X` in row major order; i.e.,\n\n.. math::\n\n    X_{i,j} = x [ i * 3 + j ]\n\ng\n*\nThe argument *g* has prototype\n\n    ``const`` *Vector* & *g*\n\n.\nIt contains the elements of the gradient of\n:math:`\\det ( X )` in row major order; i.e.,\n\n.. math::\n\n    \\D{\\det (X)}{X(i,j)} = g [ i * 3 + j ]\n\nVector\n******\nIf *y* is a *Vector* object,\nit must support the syntax\n\n    *y* [ *i* ]\n\nwhere *i* has type ``size_t`` with value less than 9.\nThis must return a ``double`` value corresponding to the *i*-th\nelement of the vector *y* .\nThis is the only requirement of the type *Vector* .\n\nok\n**\nThe return value *ok* has prototype\n\n    ``bool`` *ok*\n\nIt is true, if the gradient *g*\npasses the test and false otherwise.\n{xrst_toc_hidden\n    xrst/det_grad_33_hpp.xrst\n}\n\nSource Code\n***********\nThe file\n:ref:`det_grad_33.hpp-name`\ncontains the source code for this template function.\n\n{xrst_end det_grad_33}\n------------------------------------------------------------------------------\n*/\n// BEGIN C++\n# include <limits>\n# include <cppad/utility/near_equal.hpp>\nnamespace CppAD {\ntemplate <class Vector>\n    bool det_grad_33(const Vector &x, const Vector &g)\n    {   bool ok = true;\n        typedef typename Vector::value_type Float;\n        Float eps = 10. * Float( std::numeric_limits<double>::epsilon() );\n\n        // use expansion by minors to compute the derivative by hand\n        double check[9];\n        check[0] = + ( x[4] * x[8] - x[5] * x[7] );\n        check[1] = - ( x[3] * x[8] - x[5] * x[6] );\n        check[2] = + ( x[3] * x[7] - x[4] * x[6] );\n        //\n        check[3] = - ( x[1] * x[8] - x[2] * x[7] );\n        check[4] = + ( x[0] * x[8] - x[2] * x[6] );\n        check[5] = - ( x[0] * x[7] - x[1] * x[6] );\n        //\n        check[6] = + ( x[1] * x[5] - x[2] * x[4] );\n        check[7] = - ( x[0] * x[5] - x[2] * x[3] );\n        check[8] = + ( x[0] * x[4] - x[1] * x[3] );\n        //\n        for(size_t i = 0; i < 3 * 3; i++)\n            ok &= CppAD::NearEqual(check[i], g[i], eps, eps);\n\n        return ok;\n    }\n}\n// END C++\n# endif\n"
  },
  {
    "path": "include/cppad/speed/det_of_minor.hpp",
    "content": "# ifndef CPPAD_SPEED_DET_OF_MINOR_HPP\n# define CPPAD_SPEED_DET_OF_MINOR_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin det_of_minor}\n\nDeterminant of a Minor\n######################\n\nSyntax\n******\n| ``# include <cppad/speed/det_of_minor.hpp>``\n| *d* = ``det_of_minor`` ( *a* , *m* , *n* , *r* , *c* )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_DET_OF_MINOR\n    // END_DET_OF_MINOR\n}\n\nInclusion\n*********\nThe template function ``det_of_minor`` is defined in the ``CppAD``\nnamespace by including the file ``cppad/speed/det_of_minor.hpp`` .\n\nPurpose\n*******\nThis template function\nreturns the determinant of a minor of the matrix :math:`A`\nusing expansion by minors.\nThis template function\nis for example and testing purposes only.\nExpansion by minors is chosen as an example because it uses\na lot of floating point operations yet does not require much source code\n(on the order of *m* factorial floating point operations and\nabout 100 lines of source code including comments).\nThis is not an efficient method for computing a determinant;\nfor example, using an LU factorization would be faster.\n\nMinor\n*****\nThe elements of the :math:`n \\times n` minor :math:`M`\nof the matrix :math:`A` are defined,\nfor :math:`i = 0 , \\ldots , n-1` and :math:`j = 0 , \\ldots , n-1`, by\n\n.. math::\n\n    M_{i,j} = A_{R(i), C(j)}\n\nwhere the functions\n:math:`R(i)` is defined by the :ref:`argument r<det_of_minor@r>` and\n:math:`C(j)` is defined by the :ref:`argument c<det_of_minor@c>` .\n\n\nDeterminant of A\n****************\nIf the following conditions hold, the minor is the\nentire matrix :math:`A` and hence ``det_of_minor``\nwill return the determinant of :math:`A`:\n\n#. :math:`n = m`.\n#. for :math:`i = 0 , \\ldots , m-1`, :math:`r[i] = i+1`,\n   and :math:`r[m] = 0`.\n#. for :math:`j = 0 , \\ldots , m-1`, :math:`c[j] = j+1`,\n   and :math:`c[m] = 0`.\n\nScalar\n******\nThis is the type of the elements of *a* .\nIf *x* and *y* are *Scalar* objects,\nthe type *Scalar* must support the following operations:\n\n.. csv-table::\n    :widths: auto\n\n    **Syntax**,**Description**,**Result Type**\n    *Scalar* (0),constructor for *Scalar* object equal to zero,*Scalar*\n    *x* = *y*,set value of *x* to current value of *y*\n    *x* + *y*,value of *x* plus *y*,*Scalar*\n    *x* ``-`` *y*,value of *x* minus *y*,*Scalar*\n    *x* * *y*,value of *x* times value of *y*,*Scalar*\n\na\n*\nThe elements of the :math:`m \\times m` matrix :math:`A` are defined,\nfor :math:`i = 0 , \\ldots , m-1` and :math:`j = 0 , \\ldots , m-1`, by\n\n.. math::\n\n    A_{i,j} = a[ i * m + j]\n\nm\n*\nThis is the number of rows (and columns) in the square matrix :math:`A`.\n\nn\n*\nThis is the number of rows (and columns) in the square minor :math:`M`.\n\nr\n*\nThis defines the function :math:`R(i)`\nwhich specifies the rows of the minor :math:`M`.\nTo be specific, the function :math:`R(i)`\nfor :math:`i = 1, \\ldots , n-1` is defined by\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        R(0)   & = & r[m]\n        \\\\\n        R(i) & = & r[ R(i-1) ]\n    \\end{eqnarray}\n\nAll the elements of *r* have value less than or equal *m* ;\n:math:`R(i) < m` and :math:`r[ R(n-1) ] = m` .\nThe elements of vector *r* are modified during the computation,\nand restored to their original value before the return from ``det_of_minor`` .\n\nc\n*\nThis defines the function :math:`C(i)`\nwhich specifies the columns of the minor :math:`M`.\nTo be specific, the function :math:`C(i)`\nfor :math:`j = 1, \\ldots , n-1` is defined by\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        C(0)   & = & c[m]\n        \\\\\n        C(j) & = & c[ C(j-1) ]\n    \\end{eqnarray}\n\nAll the elements of *c* must have value less than or equal *m* ;\n:math:`C(j) < m` and :math:`c[ C(n-1) ] = m` .\nThe elements of vector *c* are modified during the computation,\nand restored to their original value before the return from ``det_of_minor`` .\n\nd\n*\nThe return value *d* is equal to the determinant of the minor :math:`M`.\n\n{xrst_toc_hidden\n    speed/example/det_of_minor.cpp\n    xrst/det_of_minor_hpp.xrst\n}\n\nExample\n*******\nThe file\n:ref:`det_of_minor.cpp-name`\ncontains an example and test of ``det_of_minor.hpp`` .\n\nSource Code\n***********\nThe file\n:ref:`det_of_minor.hpp-name`\ncontains the source for this template function.\n\n{xrst_end det_of_minor}\n---------------------------------------------------------------------------\n*/\n// BEGIN C++\n# include <vector>\n# include <cassert>\n# include <cstddef>\n\nnamespace CppAD { // BEGIN CppAD namespace\n\n// BEGIN_DET_OF_MINOR\ntemplate <class Scalar>\nScalar det_of_minor(\n    const std::vector<Scalar>&      a  ,\n    size_t                          m  ,\n    size_t                          n  ,\n    std::vector<size_t>&            r  ,\n    std::vector<size_t>&            c  )\n{   assert( a.size() == m * m );\n    assert( r.size() == m + 1 );\n    assert( c.size() == m + 1 );\n    // END_DET_OF_MINOR\n    //\n    // R0 = R(0)\n    size_t R0 = r[m];\n    assert( R0 < m );\n    //\n    // Cj = C(0)\n    size_t Cj = c[m];\n    assert( Cj < m );\n    //\n    //\n    // check if this is a 1 by 1 minor\n    if( n == 1 ) return a[ R0 * m + Cj ];\n    //\n    // detM\n    // initialize determinant of the minor M\n    Scalar detM(0);\n    //\n    // sign\n    // initialize sign of factor for next sub-minor\n    int sign = 1;\n    //\n    // r\n    // remove row with index 0 in M from all the sub-minors of M\n    r[m] = r[R0];\n    //\n    // C(j-1)\n    // initial index in c for previous column of the minor M\n    size_t Cj1 = m;\n    //\n    // for each column of M\n    for(size_t j = 0; j < n; j++)\n    {\n        // M[0,j] = A[ R0, Cj ]\n        // element with index (0, j) in the minor M\n        assert( Cj < m );\n        Scalar M0j = a[ R0 * m + Cj ];\n        //\n        // remove column with index j in M to form next sub-minor S of M\n        c[Cj1] = c[Cj];\n        //\n        // detS\n        // compute determinant of S, the sub-minor of M with\n        // row R(0) and column C(j) removed.\n        Scalar detS = det_of_minor(a, m, n - 1, r, c);\n        //\n        // restore column with index j in representation of M as a minor of A\n        c[Cj1] = Cj;\n        //\n        // detM\n        // include this sub-minor term in the summation\n        if( sign > 0 )\n            detM = detM + M0j * detS;\n        else\n            detM = detM - M0j * detS;\n        //\n        // advance to next column of M\n        Cj1  = Cj;\n        Cj   = c[Cj];\n        sign = - sign;\n    }\n    //\n    // r\n    // restore row zero to the minor representation for M\n    r[m] = R0;\n    //\n    // return the determinant of the minor M\n    return detM;\n}\n\n} // END CppAD namespace\n// END C++\n# endif\n"
  },
  {
    "path": "include/cppad/speed/mat_sum_sq.hpp",
    "content": "# ifndef CPPAD_SPEED_MAT_SUM_SQ_HPP\n# define CPPAD_SPEED_MAT_SUM_SQ_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin mat_sum_sq}\n\nSum Elements of a Matrix Times Itself\n#####################################\n\nSyntax\n******\n| # ``include <cppad/speed/mat_sum_sq.hpp>``\n| *mat_sum_sq* ( ``n`` , ``x`` , ``y`` , ``z`` )\n\nPurpose\n*******\nThis routine is intended for use with the matrix multiply speed tests;\nto be specific, it computes\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        y_{i,j} & = & \\sum_{k=0}^{n-1} x_{i,k} x_{k,j}\n        \\\\\n        z_0     & = & \\sum_{i=0}^{n-1} \\sum_{j=0}^{n-1} y_{i,j}\n    \\end{eqnarray}\n\nsee :ref:`link_mat_mul-name` .\n\nInclusion\n*********\nThe template function ``mat_sum_sq`` is defined in the ``CppAD``\nnamespace by including\nthe file ``cppad/speed/mat_sum_sq.hpp``\n(relative to the CppAD distribution directory).\n\nn\n*\nThis argument has prototype\n\n    ``size_t`` *n*\n\nIt specifies the size of the matrices.\n\nx\n*\nThe argument *x* has prototype\n\n    ``const`` *Vector* & *x*\n\nand *x* . ``size`` () == *n* * *n* .\nIt contains the elements of :math:`x` in row major order; i.e.,\n\n.. math::\n\n    x_{i,j} = x [ i * n + j ]\n\ny\n*\nThe argument *y* has prototype\n\n    *Vector* & *y*\n\nand *y* . ``size`` () == *n* * *n* .\nThe input value of its elements does not matter.\nUpon return,\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        y_{i,j}        & = & \\sum_{k=0}^{n-1} x_{i,k} x_{k,j}\n        \\\\\n        y[ i * n + j ] & = & y_{i,j}\n    \\end{eqnarray}\n\nz\n*\nThe argument *d* has prototype\n\n    *Vector* & *z*\n\n.\nThe input value of its element does not matter.\nUpon return\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        z_0 & = & \\sum_{i=0}^{n-1} \\sum_{j=0}^n y_{i,j}\n        \\\\\n        z[0] & = & z_0\n    \\end{eqnarray}\n\nVector\n******\nThe type *Vector* is any\n:ref:`SimpleVector-name` , or it can be a raw pointer to the vector elements.\nThe element type must support\naddition, multiplication, and assignment to both its own type\nand to a double value.\n{xrst_toc_hidden\n    speed/example/mat_sum_sq.cpp\n    xrst/mat_sum_sq_hpp.xrst\n}\n\nExample\n*******\nThe file\n:ref:`mat_sum_sq.cpp-name`\ncontains an example and test of ``mat_sum_sq.hpp`` .\n\nSource Code\n***********\nThe file\n:ref:`mat_sum_sq.hpp-name`\ncontains the source for this template function.\n\n{xrst_end mat_sum_sq}\n------------------------------------------------------------------------------\n*/\n// BEGIN C++\n# include <cstddef>\n//\nnamespace CppAD {\n    template <class Vector>\n    void mat_sum_sq(size_t n, Vector& x , Vector& y , Vector& z)\n    {   size_t i, j, k;\n        // Very simple computation of y = x * x for speed comparison\n        for(i = 0; i < n; i++)\n        {   for(j = 0; j < n; j++)\n            {   y[i * n + j] = 0.;\n                for(k = 0; k < n; k++)\n                    y[i * n + j] += x[i * n + k] * x[k * n + j];\n            }\n        }\n        z[0] = 0.;\n        for(i = 0; i < n; i++)\n        {   for(j = 0; j < n; j++)\n                z[0] += y[i * n + j];\n        }\n        return;\n    }\n\n}\n// END C++\n# endif\n"
  },
  {
    "path": "include/cppad/speed/ode_evaluate.hpp",
    "content": "# ifndef CPPAD_SPEED_ODE_EVALUATE_HPP\n# define CPPAD_SPEED_ODE_EVALUATE_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin ode_evaluate}\n{xrst_spell\n    fp\n    retaped\n    runge\n}\n\nEvaluate a Function Defined in Terms of an ODE\n##############################################\n\nSyntax\n******\n| # ``include <cppad/speed/ode_evaluate.hpp>``\n| ``ode_evaluate`` ( *x* , *p* , *fp* )\n\nPurpose\n*******\nThis routine evaluates a function :math:`f : \\B{R}^n \\rightarrow \\B{R}^n`\ndefined by\n\n.. math::\n\n    f(x) = y(x, 1)\n\nwhere :math:`y(x, t)` solves the ordinary differential equation\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        y(x, 0)              & = & x\n        \\\\\n        \\partial_t y (x, t ) & = & g[ y(x,t) , t ]\n    \\end{eqnarray}\n\nwhere :math:`g : \\B{R}^n \\times \\B{R} \\rightarrow \\B{R}^n`\nis an unspecified function.\n\nInclusion\n*********\nThe template function ``ode_evaluate``\nis defined in the ``CppAD`` namespace by including\nthe file ``cppad/speed/ode_evaluate.hpp``\n(relative to the CppAD distribution directory).\n\nFloat\n*****\n\nOperation Sequence\n==================\nThe type *Float* must be a :ref:`NumericType-name` .\nThe *Float*\n:ref:`operation sequence<glossary@Operation@Sequence>`\nfor this routine does not depend on the value of the argument *x* ,\nhence it does not need to be retaped for each value of :math:`x`.\n\nfabs\n====\nIf *y* and *z* are *Float* objects, the syntax\n\n    *y* = ``fabs`` ( *z* )\n\nmust be supported. Note that it does not matter if the operation\nsequence for ``fabs`` depends on *z* because the\ncorresponding results are not actually used by ``ode_evaluate`` ;\nsee ``fabs`` in :ref:`Runge45<Runge45@Scalar@fabs>` .\n\nx\n*\nThe argument *x* has prototype\n\n    ``const CppAD::vector<`` *Float* >& *x*\n\nIt contains he argument value for which the function,\nor its derivative, is being evaluated.\nThe value :math:`n` is determined by the size of the vector *x* .\n\np\n*\nThe argument *p* has prototype\n\n    ``size_t`` *p*\n\np == 0\n======\nIn this case a numerical method is used to solve the ode\nand obtain an accurate approximation for :math:`y(x, 1)`.\nThis numerical method has a fixed\nthat does not depend on *x* .\n\np = 1\n=====\nIn this case an analytic solution for the partial derivative\n:math:`\\partial_x y(x, 1)` is returned.\n\nfp\n**\nThe argument *fp* has prototype\n\n    ``CppAD::vector<`` *Float* >& *fp*\n\nThe input value of the elements of *fp* does not matter.\n\nFunction\n========\nIf *p* is zero, *fp* has size equal to :math:`n`\nand contains the value of :math:`y(x, 1)`.\n\nGradient\n========\nIf *p* is one, *fp* has size equal to *n^2*\nand for :math:`i = 0 , \\ldots 1`, :math:`j = 0 , \\ldots , n-1`\n\n.. math::\n\n    \\D{y[i]}{x[j]} (x, 1) = fp [ i \\cdot n + j ]\n\n{xrst_toc_hidden\n    speed/example/ode_evaluate.cpp\n    xrst/ode_evaluate.xrst\n}\n\nExample\n*******\nThe file\n:ref:`ode_evaluate.cpp-name`\ncontains an example and test  of ``ode_evaluate.hpp`` .\n\nSource Code\n***********\nThe file\n:ref:`ode_evaluate.hpp-name`\ncontains the source code for this template function.\n\n{xrst_end ode_evaluate}\n*/\n// BEGIN C++\n# include <cppad/utility/vector.hpp>\n# include <cppad/utility/ode_err_control.hpp>\n# include <cppad/utility/runge_45.hpp>\n\nnamespace CppAD {\n\n    template <class Float>\n    class ode_evaluate_fun {\n    public:\n        // Given that y_i (0) = x_i,\n        // the following y_i (t) satisfy the ODE below:\n        // y_0 (t) = x[0]\n        // y_1 (t) = x[1] + x[0] * t\n        // y_2 (t) = x[2] + x[1] * t + x[0] * t^2/2\n        // y_3 (t) = x[3] + x[2] * t + x[1] * t^2/2 + x[0] * t^3 / 3!\n        // ...\n        void Ode(\n            const Float&                    t,\n            const CppAD::vector<Float>&     y,\n            CppAD::vector<Float>&           f)\n        {   size_t n  = y.size();\n            f[0]      = 0.;\n            for(size_t k = 1; k < n; k++)\n                f[k] = y[k-1];\n        }\n    };\n    //\n    template <class Float>\n    void ode_evaluate(\n        const CppAD::vector<Float>& x  ,\n        size_t                      p  ,\n        CppAD::vector<Float>&       fp )\n    {   using CppAD::vector;\n        typedef vector<Float> FloatVector;\n\n        size_t n = x.size();\n        CPPAD_ASSERT_KNOWN( p == 0 || p == 1,\n            \"ode_evaluate: p is not zero or one\"\n        );\n        CPPAD_ASSERT_KNOWN(\n            ((p==0) && (fp.size()==n)) || ((p==1) && (fp.size()==n*n)),\n            \"ode_evaluate: the size of fp is not correct\"\n        );\n        if( p == 0 )\n        {   // function that defines the ode\n            ode_evaluate_fun<Float> F;\n\n            // number of Runge45 steps to use\n            size_t M = 10;\n\n            // initial and final time\n            Float ti = 0.0;\n            Float tf = 1.0;\n\n            // initial value for y(x, t); i.e. y(x, 0)\n            // (is a reference to x)\n            const FloatVector& yi = x;\n\n            // final value for y(x, t); i.e., y(x, 1)\n            // (is a reference to fp)\n            FloatVector& yf = fp;\n\n            // Use fourth order Runge-Kutta to solve ODE\n            yf = CppAD::Runge45(F, M, ti, tf, yi);\n\n            return;\n        }\n        /* Compute derivaitve of y(x, 1) w.r.t x\n        y_0 (x, t) = x[0]\n        y_1 (x, t) = x[1] + x[0] * t\n        y_2 (x, t) = x[2] + x[1] * t + x[0] * t^2/2\n        y_3 (x, t) = x[3] + x[2] * t + x[1] * t^2/2 + x[0] * t^3 / 3!\n        ...\n        */\n        size_t i, j, k;\n        for(i = 0; i < n; i++)\n        {   for(j = 0; j < n; j++)\n                fp[ i * n + j ] = 0.0;\n        }\n        size_t factorial = 1;\n        for(k = 0; k < n; k++)\n        {   if( k > 1 )\n                factorial *= k;\n            for(i = k; i < n; i++)\n            {   // partial w.r.t x[i-k] of x[i-k] * t^k / k!\n                j = i - k;\n                fp[ i * n + j ] += 1.0 / Float(factorial);\n            }\n        }\n    }\n}\n// END C++\n\n# endif\n"
  },
  {
    "path": "include/cppad/speed/sparse_hes_fun.hpp",
    "content": "# ifndef CPPAD_SPEED_SPARSE_HES_FUN_HPP\n# define CPPAD_SPEED_SPARSE_HES_FUN_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin sparse_hes_fun}\n{xrst_spell\n    fp\n}\n\nEvaluate a Function That Has a Sparse Hessian\n#############################################\n\nSyntax\n******\n| # ``include <cppad/speed/sparse_hes_fun.hpp>``\n| ``sparse_hes_fun`` ( *n* , *x* , *row* , *col* , *p* , *fp* )\n\nPurpose\n*******\nThis routine evaluates\n:math:`f(x)`, :math:`f^{(1)} (x)`, or :math:`f^{(2)} (x)`\nwhere the Hessian :math:`f^{(2)} (x)` is sparse.\nThe function :math:`f : \\B{R}^n \\rightarrow \\B{R}` only depends on the\nsize and contents of the index vectors *row* and *col* .\nThe non-zero entries in the Hessian of this function have\none of the following forms:\n\n.. math::\n\n    \\DD{f}{x[row[k]]}{x[row[k]]}\n    \\; , \\;\n    \\DD{f}{x[row[k]]}{x[col[k]]}\n    \\; , \\;\n    \\DD{f}{x[col[k]]}{x[row[k]]}\n    \\; , \\;\n    \\DD{f}{x[col[k]]}{x[col[k]]}\n\nfor some :math:`k` between zero and :math:`K-1`.\nAll the other terms of the Hessian are zero.\n\nInclusion\n*********\nThe template function ``sparse_hes_fun``\nis defined in the ``CppAD`` namespace by including\nthe file ``cppad/speed/sparse_hes_fun.hpp``\n(relative to the CppAD distribution directory).\n\nFloat\n*****\nThe type *Float* must be a :ref:`NumericType-name` .\nIn addition, if *y* and *z* are *Float* objects,\n\n    *y* = ``exp`` ( *z* )\n\nmust set the *y* equal the exponential of *z* , i.e.,\nthe derivative of *y* with respect to *z* is equal to *y* .\n\nFloatVector\n***********\nThe type *FloatVector* is any\n:ref:`SimpleVector-name` , or it can be a raw pointer,\nwith elements of type *Float* .\n\nn\n*\nThe argument *n* has prototype\n\n    ``size_t`` *n*\n\nIt specifies the dimension for the domain space for :math:`f(x)`.\n\nx\n*\nThe argument *x* has prototype\n\n    ``const`` *FloatVector* & *x*\n\nIt contains the argument value for which the function,\nor its derivative, is being evaluated.\nWe use :math:`n` to denote the size of the vector *x* .\n\nrow\n***\nThe argument *row* has prototype\n\n    ``const CppAD::vector<size_t>&`` *row*\n\nIt specifies one of the first\nindex of :math:`x` for each non-zero Hessian term\n(see :ref:`sparse_hes_fun@Purpose` above).\nAll the elements of *row* must be between zero and *n* ``-1`` .\nThe value :math:`K` is defined by *K* = *row* . ``size`` () .\n\ncol\n***\nThe argument *col* has prototype\n\n    ``const CppAD::vector<size_t>&`` *col*\n\nand its size must be :math:`K`; i.e., the same as for *col* .\nIt specifies the second\nindex of :math:`x` for the non-zero Hessian terms.\nAll the elements of *col* must be between zero and *n* ``-1`` .\nThere are no duplicated entries requested, to be specific,\nif *k1* != *k2* then\n\n    ( *row* [ *k1* ] , *col* [ *k1* ] ) != ( *row* [ *k2* ] , *col* [ *k2* ] )\n\np\n*\nThe argument *p* has prototype\n\n    ``size_t`` *p*\n\nIt is either zero or two and\nspecifies the order of the derivative of :math:`f`\nthat is being evaluated, i.e., :math:`f^{(p)} (x)` is evaluated.\n\nfp\n**\nThe argument *fp* has prototype\n\n    *FloatVector* & *fp*\n\nThe input value of the elements of *fp* does not matter.\n\nFunction\n========\nIf *p* is zero, *fp* has size one and\n*fp* [0] is the value of :math:`f(x)`.\n\nHessian\n=======\nIf *p* is two, *fp* has size *K* and\nfor :math:`k = 0 , \\ldots , K-1`,\n\n.. math::\n\n    \\DD{f}{ x[ \\R{row}[k] ] }{ x[ \\R{col}[k] ]} = fp [k]\n\n{xrst_toc_hidden\n    speed/example/sparse_hes_fun.cpp\n    xrst/sparse_hes_fun.xrst\n}\n\nExample\n*******\nThe file\n:ref:`sparse_hes_fun.cpp-name`\ncontains an example and test  of ``sparse_hes_fun.hpp`` .\n\nSource Code\n***********\nThe file\n:ref:`sparse_hes_fun.hpp-name`\ncontains the source code for this template function.\n\n{xrst_end sparse_hes_fun}\n------------------------------------------------------------------------------\n*/\n// BEGIN C++\n# include <cppad/core/cppad_assert.hpp>\n# include <cppad/utility/check_numeric_type.hpp>\n# include <cppad/utility/vector.hpp>\n\n// following needed by gcc under fedora 17 so that exp(double) is defined\n# include <cppad/base_require.hpp>\n\nnamespace CppAD {\n    template <class Float, class FloatVector>\n    void sparse_hes_fun(\n        size_t                       n    ,\n        const FloatVector&           x    ,\n        const CppAD::vector<size_t>& row  ,\n        const CppAD::vector<size_t>& col  ,\n        size_t                       p    ,\n        FloatVector&                fp    )\n    {\n        // check numeric type specifications\n        CheckNumericType<Float>();\n\n        // check value of p\n        CPPAD_ASSERT_KNOWN(\n            p == 0 || p == 2,\n            \"sparse_hes_fun: p != 0 and p != 2\"\n        );\n\n        size_t K = row.size();\n        size_t i, j, k;\n        if( p == 0 )\n            fp[0] = Float(0);\n        else\n        {   for(k = 0; k < K; k++)\n                fp[k] = Float(0);\n        }\n\n        // determine which diagonal entries are present in row[k], col[k]\n        CppAD::vector<size_t> diagonal(n);\n        for(i = 0; i < n; i++)\n            diagonal[i] = K;   // no diagonal entry for this row\n        for(k = 0; k < K; k++)\n        {   if( row[k] == col[k] )\n            {   CPPAD_ASSERT_UNKNOWN( diagonal[row[k]] == K );\n                // index of the diagonal entry\n                diagonal[ row[k] ] = k;\n            }\n        }\n\n        // determine which entries must be multiplied by a factor of two\n        CppAD::vector<Float> factor(K);\n        for(k = 0; k < K; k++)\n        {   factor[k] = Float(1);\n            for(size_t k1 = 0; k1 < K; k1++)\n            {   bool reflected = true;\n                reflected &= k != k1;\n                reflected &= row[k] != col[k];\n                reflected &= row[k] == col[k1];\n                reflected &= col[k] == row[k1];\n                if( reflected )\n                    factor[k] = Float(2);\n            }\n        }\n\n        Float t;\n        for(k = 0; k < K; k++)\n        {   i    = row[k];\n            j    = col[k];\n            t    = exp( x[i] * x[j] );\n            switch(p)\n            {\n                case 0:\n                fp[0] += t;\n                break;\n\n                case 2:\n                if( i == j )\n                {   // second partial of t w.r.t. x[i], x[i]\n                    fp[k] += ( Float(2) + Float(4) * x[i] * x[i] ) * t;\n                }\n                else // (i != j)\n                {   //\n                    // second partial of t w.r.t x[i], x[j]\n                    fp[k] += factor[k] * ( Float(1) + x[i] * x[j] ) * t;\n                    if( diagonal[i] != K )\n                    {   // second partial of t w.r.t x[i], x[i]\n                        size_t ki = diagonal[i];\n                        fp[ki] += x[j] * x[j] * t;\n                    }\n                    if( diagonal[j] != K )\n                    {   // second partial of t w.r.t x[j], x[j]\n                        size_t kj = diagonal[j];\n                        fp[kj] += x[i] * x[i] * t;\n                    }\n                }\n                break;\n            }\n        }\n\n    }\n}\n// END C++\n# endif\n"
  },
  {
    "path": "include/cppad/speed/sparse_jac_fun.hpp",
    "content": "# ifndef CPPAD_SPEED_SPARSE_JAC_FUN_HPP\n# define CPPAD_SPEED_SPARSE_JAC_FUN_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin sparse_jac_fun}\n{xrst_spell\n    fp\n}\n\nEvaluate a Function That Has a Sparse Jacobian\n##############################################\n\nSyntax\n******\n| # ``include <cppad/speed/sparse_jac_fun.hpp>``\n| ``sparse_jac_fun`` ( *m* , *n* , *x* , *row* , *col* , *p* , *fp* )\n\nPurpose\n*******\nThis routine evaluates\n:math:`f(x)` and :math:`f^{(1)} (x)`\nwhere the Jacobian :math:`f^{(1)} (x)` is sparse.\nThe function :math:`f : \\B{R}^n \\rightarrow \\B{R}^m` only depends on the\nsize and contents of the index vectors *row* and *col* .\nThe non-zero entries in the Jacobian of this function have\none of the following forms:\n\n.. math::\n\n    \\D{ f[row[k]]}{x[col[k]]}\n\nfor some :math:`k` between zero and :math:`K-1`.\nAll the other terms of the Jacobian are zero.\n\nInclusion\n*********\nThe template function ``sparse_jac_fun``\nis defined in the ``CppAD`` namespace by including\nthe file ``cppad/speed/sparse_jac_fun.hpp``\n(relative to the CppAD distribution directory).\n\nFloat\n*****\nThe type *Float* must be a :ref:`NumericType-name` .\nIn addition, if *y* and *z* are *Float* objects,\n\n    *y* = ``exp`` ( *z* )\n\nmust set the *y* equal the exponential of *z* , i.e.,\nthe derivative of *y* with respect to *z* is equal to *y* .\n\nFloatVector\n***********\nThe type *FloatVector* is any\n:ref:`SimpleVector-name` , or it can be a raw pointer,\nwith elements of type *Float* .\n\nn\n*\nThe argument *n* has prototype\n\n    ``size_t`` *n*\n\nIt specifies the dimension for the domain space for :math:`f(x)`.\n\nm\n*\nThe argument *m* has prototype\n\n    ``size_t`` *m*\n\nIt specifies the dimension for the range space for :math:`f(x)`.\n\nx\n*\nThe argument *x* has prototype\n\n    ``const`` *FloatVector* & *x*\n\nIt contains the argument value for which the function,\nor its derivative, is being evaluated.\nWe use :math:`n` to denote the size of the vector *x* .\n\nrow\n***\nThe argument *row* has prototype\n\n    ``const CppAD::vector<size_t>&`` *row*\n\nIt specifies indices in the range of :math:`f(x)` for non-zero components\nof the Jacobian\n(see :ref:`sparse_hes_fun@Purpose` above).\nThe value :math:`K` is defined by *K* = *row* . ``size`` () .\nAll the elements of *row* must be between zero and *m* ``-1`` .\n\ncol\n***\nThe argument *col* has prototype\n\n    ``const CppAD::vector<size_t>&`` *col*\n\nand its size must be :math:`K`; i.e., the same as *row* .\nIt specifies the component of :math:`x` for\nthe non-zero Jacobian terms.\nAll the elements of *col* must be between zero and *n* ``-1`` .\n\np\n*\nThe argument *p* has prototype\n\n    ``size_t`` *p*\n\nIt is either zero or one and\nspecifies the order of the derivative of :math:`f`\nthat is being evaluated, i.e., :math:`f^{(p)} (x)` is evaluated.\n\nfp\n**\nThe argument *fp* has prototype\n\n    *FloatVector* & *fp*\n\nIf *p*  = 0 , it size is *m*\notherwise its size is *K* .\nThe input value of the elements of *fp* does not matter.\n\nFunction\n========\nIf *p* is zero, *fp* has size :math:`m` and\n( *fp* [0], ... , ``fp`` [ ``m`` *-1* ]) is the value of :math:`f(x)`.\n\nJacobian\n========\nIf *p* is one, *fp* has size *K* and\nfor :math:`k = 0 , \\ldots , K-1`,\n\n.. math::\n\n    \\D{f[ \\R{row}[i] ]}{x[ \\R{col}[j] ]} = fp [k]\n\n{xrst_toc_hidden\n    speed/example/sparse_jac_fun.cpp\n    xrst/sparse_jac_fun.xrst\n}\n\nExample\n*******\nThe file\n:ref:`sparse_jac_fun.cpp-name`\ncontains an example and test  of ``sparse_jac_fun.hpp`` .\n\nSource Code\n***********\nThe file\n:ref:`sparse_jac_fun.hpp-name`\ncontains the source code for this template function.\n\n{xrst_end sparse_jac_fun}\n------------------------------------------------------------------------------\n*/\n// BEGIN C++\n# include <cppad/core/cppad_assert.hpp>\n# include <cppad/utility/check_numeric_type.hpp>\n# include <cppad/utility/vector.hpp>\n\n// following needed by gcc under fedora 17 so that exp(double) is defined\n# include <cppad/base_require.hpp>\n\nnamespace CppAD {\n    template <class Float, class FloatVector>\n    void sparse_jac_fun(\n        size_t                       m    ,\n        size_t                       n    ,\n        const FloatVector&           x    ,\n        const CppAD::vector<size_t>& row  ,\n        const CppAD::vector<size_t>& col  ,\n        size_t                       p    ,\n        FloatVector&                 fp   )\n    {\n        // check numeric type specifications\n        CheckNumericType<Float>();\n        // check value of p\n        CPPAD_ASSERT_KNOWN(\n            p == 0 || p == 1,\n            \"sparse_jac_fun: p != 0 and p != 1\"\n        );\n        size_t K = row.size();\n        CPPAD_ASSERT_KNOWN(\n            K >= m,\n            \"sparse_jac_fun: row.size() < m\"\n        );\n        size_t i, j, k;\n\n        if( p == 0 )\n            for(i = 0; i < m; i++)\n                fp[i] = Float(0);\n\n        Float t;\n        for(k = 0; k < K; k++)\n        {   i    = row[k];\n            j    = col[k];\n            t    = exp( x[j] * x[j] / 2.0 );\n            switch(p)\n            {\n                case 0:\n                fp[i] += t;\n                break;\n\n                case 1:\n                fp[k] = t * x[j];\n                break;\n            }\n        }\n    }\n}\n// END C++\n# endif\n"
  },
  {
    "path": "include/cppad/speed/uniform_01.hpp",
    "content": "# ifndef CPPAD_SPEED_UNIFORM_01_HPP\n# define CPPAD_SPEED_UNIFORM_01_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin uniform_01}\n\nSimulate a [0,1] Uniform Random Variate\n#######################################\n\nSyntax\n******\n| # ``include <cppad/speed/uniform_01.hpp>``\n| ``uniform_01`` ( *seed* )\n| ``uniform_01`` ( *n* , *x* )\n\nPurpose\n*******\nThis routine is used to create random values for speed testing purposes.\n\nInclusion\n*********\nThe template function ``uniform_01`` is defined in the ``CppAD``\nnamespace by including\nthe file ``cppad/speed/uniform_01.hpp``\n(relative to the CppAD distribution directory).\n\nseed\n****\nThe argument *seed* has prototype\n\n    ``size_t`` *seed*\n\nIt specifies a seed\nfor the uniform random number generator.\n\nn\n*\nThe argument *n* has prototype\n\n    ``size_t`` *n*\n\nIt specifies the number of elements in the random vector *x* .\n\nx\n*\nThe argument *x* has prototype\n\n    *Vector* & *x*\n\n.\nThe input value of the elements of *x* does not matter.\nUpon return, the elements of *x* are set to values\nrandomly sampled over the interval [0,1].\n\nVector\n******\nIf *y* is a ``double`` value,\nthe object *x* must support the syntax\n\n    *x* [ *i* ] = *y*\n\nwhere *i* has type ``size_t`` with value less than\nor equal :math:`n-1`.\nThis is the only requirement of the type *Vector* .\n{xrst_toc_hidden\n    xrst/uniform_01_hpp.xrst\n}\n\nSource Code\n***********\nThe file\n:ref:`uniform_01.hpp-name`\nconstraints the source code for this template function.\n\n{xrst_end uniform_01}\n------------------------------------------------------------------------------\n*/\n// BEGIN C++\n# include <cstdlib>\n\nnamespace CppAD {\n    inline void uniform_01(size_t seed)\n    {   std::srand( (unsigned int) seed); }\n\n    template <class Vector>\n    void uniform_01(size_t n, Vector &x)\n    {   static double factor = 1. / double(RAND_MAX);\n        while(n--)\n            x[n] = std::rand() * factor;\n    }\n}\n// END C++\n# endif\n"
  },
  {
    "path": "include/cppad/utility/check_numeric_type.hpp",
    "content": "# ifndef CPPAD_UTILITY_CHECK_NUMERIC_TYPE_HPP\n# define CPPAD_UTILITY_CHECK_NUMERIC_TYPE_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin CheckNumericType}\n\nCheck NumericType Class Concept\n###############################\n\nSyntax\n******\n| # ``include <cppad/utility/check_numeric_type.hpp>``\n| ``CheckNumericType`` < *NumericType* >()\n\nPurpose\n*******\nThe syntax\n\n    ``CheckNumericType`` < *NumericType* >()\n\npreforms compile and run time checks that the type specified\nby *NumericType* satisfies all the requirements for\na :ref:`NumericType-name` class.\nIf a requirement is not satisfied,\na an error message makes it clear what condition is not satisfied.\n\nInclude\n*******\nThe file ``cppad/utility/check_numeric_type.hpp``\nis included by ``cppad/cppad.hpp``\nbut it can also be included separately with out the rest\nif the CppAD include files.\n\nParallel Mode\n*************\nThe routine :ref:`thread_alloc::parallel_setup<ta_parallel_setup-name>`\nmust be called before it\ncan be used in :ref:`parallel<ta_in_parallel-name>` mode.\n\nExample\n*******\n{xrst_toc_hidden\n    example/utility/check_numeric_type.cpp\n}\nThe file :ref:`check_numeric_type.cpp-name`\ncontains an example and test of this function.\nThe comments in this example suggest a way to change the example\nso an error message occurs.\n\n{xrst_end CheckNumericType}\n---------------------------------------------------------------------------\n*/\n\n# include <cstddef>\n# include <cppad/utility/thread_alloc.hpp>\n\nnamespace CppAD {\n\n# ifdef NDEBUG\n    template <class NumericType>\n    void CheckNumericType(void)\n    { }\n# else\n    template <class NumericType>\n    NumericType CheckNumericType(void)\n    {   // Section 3.6.2 of ISO/IEC 14882:1998(E) states: \"The storage for\n        // objects with static storage duration (3.7.1) shall be zero-\n        // initialized (8.5) before any other initialization takes place.\"\n        static size_t count[CPPAD_MAX_NUM_THREADS];\n        size_t thread = thread_alloc::thread_num();\n        if( count[thread] > 0  )\n            return NumericType(0);\n        count[thread]++;\n        /*\n        constructors\n        */\n        NumericType check_NumericType_default_constructor;\n        NumericType check_NumericType_constructor_from_int(1);\n\n        const NumericType x(1);\n\n        NumericType check_NumericType_copy_constructor(x);\n\n        // assignment\n        NumericType check_NumericType_assignment;\n        check_NumericType_assignment = x;\n\n        /*\n        unary operators\n        */\n        const NumericType check_NumericType_unary_plus(1);\n        NumericType check_NumericType_unary_plus_result =\n            + check_NumericType_unary_plus;\n\n        const NumericType check_NumericType_unary_minus(1);\n        NumericType check_NumericType_unary_minus_result =\n            - check_NumericType_unary_minus;\n\n        /*\n        binary operators\n        */\n        const NumericType check_NumericType_binary_addition(1);\n        NumericType check_NumericType_binary_addition_result =\n            check_NumericType_binary_addition + x;\n\n        const NumericType check_NumericType_binary_subtraction(1);\n        NumericType check_NumericType_binary_subtraction_result =\n            check_NumericType_binary_subtraction - x;\n\n        const NumericType check_NumericType_binary_multiplication(1);\n        NumericType check_NumericType_binary_multiplication_result =\n            check_NumericType_binary_multiplication * x;\n\n        const NumericType check_NumericType_binary_division(1);\n        NumericType check_NumericType_binary_division_result =\n            check_NumericType_binary_division / x;\n\n        /*\n        compound assignment operators\n        */\n        NumericType\n        check_NumericType_computed_assignment_addition(1);\n        check_NumericType_computed_assignment_addition += x;\n\n        NumericType\n        check_NumericType_computed_assignment_subtraction(1);\n        check_NumericType_computed_assignment_subtraction -= x;\n\n        NumericType\n        check_NumericType_computed_assignment_multiplication(1);\n        check_NumericType_computed_assignment_multiplication *= x;\n\n        NumericType\n        check_NumericType_computed_assignment_division(1);\n        check_NumericType_computed_assignment_division /= x;\n\n        /*\n        use all values so as to avoid warnings\n        */\n        check_NumericType_default_constructor = x;\n        return\n            + check_NumericType_default_constructor\n            + check_NumericType_constructor_from_int\n            + check_NumericType_copy_constructor\n            + check_NumericType_assignment\n            + check_NumericType_unary_plus_result\n            + check_NumericType_unary_minus_result\n            + check_NumericType_binary_addition_result\n            + check_NumericType_binary_subtraction_result\n            + check_NumericType_binary_multiplication_result\n            + check_NumericType_binary_division_result\n            + check_NumericType_computed_assignment_addition\n            + check_NumericType_computed_assignment_subtraction\n            + check_NumericType_computed_assignment_multiplication\n            + check_NumericType_computed_assignment_division\n        ;\n    }\n# endif\n\n} // end namespace CppAD\n\n# endif\n"
  },
  {
    "path": "include/cppad/utility/check_simple_vector.hpp",
    "content": "# ifndef CPPAD_UTILITY_CHECK_SIMPLE_VECTOR_HPP\n# define CPPAD_UTILITY_CHECK_SIMPLE_VECTOR_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin CheckSimpleVector}\n\nCheck Simple Vector Concept\n###########################\n\nSyntax\n******\n| # ``include <cppad/utility/check_simple_vector.hpp>``\n| ``CheckSimpleVector`` < *Scalar* , *Vector* >()\n| ``CheckSimpleVector`` < *Scalar* , *Vector* >( *x* , *y* )\n\nPurpose\n*******\nPreforms compile and run time checks that the type specified\nby *Vector* satisfies all the requirements for\na :ref:`SimpleVector-name` class with\n:ref:`elements of type<SimpleVector@Elements of Specified Type>`\n*Scalar* .\nIf a requirement is not satisfied,\na an error message makes it clear what condition is not satisfied.\n\nVector\n******\nis the vector type we are checking.\n\nScalar\n******\nis the type corresponding to the elements of an *Vector* .\n\nx, y\n****\nIf the arguments *x* and *y* are present,\nthey have prototype\n\n| |tab| ``const`` *Scalar* & *x*\n| |tab| ``const`` *Scalar* & *y*\n\nIn addition, the check\n\n    *x* == *x*\n\nwill return the boolean value ``true`` , and\n\n    *x* == *y*\n\nwill return ``false`` .\n\nRestrictions\n************\nIf the arguments *x* and *y* are not present,\nthe following extra assumption is made by ``CheckSimpleVector`` :\nIf *x* is a *Scalar* object\n\n| |tab| *x*  = 0\n| |tab| *y*  = 1\n\nassigns values to the objects *x* and *y* .\nIn addition,\n*x* == *x* would return the boolean value ``true`` and\n*x* == *y* would return ``false`` .\n\nInclude\n*******\nThe file ``cppad/utility/check_simple_vector.hpp``\nis included by ``cppad/cppad.hpp``\nbut it can also be included separately with out the rest\nif the CppAD include files.\n\nParallel Mode\n*************\nThis routine must be called before entering parallel mode\nbecause it has static variables that must be initialized.\nIf it's first call is not in  parallel mode, and NDEBUG is not defined,\nyou will get an assertion. Running in the debugger and going to the\nstack frame where CheckSimpleVector is called may help you determine\nwhat the value of *Scalar* and *Vector* need to be initialized.\n\nExample\n*******\n{xrst_toc_hidden\n    example/utility/check_simple_vector.cpp\n}\nThe file :ref:`check_simple_vector.cpp-name`\ncontains an example and test of this function where *S*\nis the same as *T* .\nThe comments in this example suggest a way to change the example\nso *S* is not the same as *T* .\n\n{xrst_end CheckSimpleVector}\n---------------------------------------------------------------------------\n*/\n\n# include <cstddef>\n# include <cppad/core/cppad_assert.hpp>\n# include <cppad/local/define.hpp>\n# include <cppad/utility/thread_alloc.hpp>\n\n// CPPAD_CHECK_SIMPLE_VECTOR\n# ifndef NDEBUG\n# define CPPAD_CHECK_SIMPLE_VECTOR 1\n# elif CPPAD_DEBUG_AND_RELEASE\n# define CPPAD_CHECK_SIMPLE_VECTOR 1\n# else\n# define CPPAD_CHECK_SIMPLE_VECTOR 0\n# endif\n\nnamespace CppAD {\n\n# if ! CPPAD_CHECK_SIMPLE_VECTOR\n    template <class Scalar, class Vector>\n    inline void CheckSimpleVector(const Scalar& x, const Scalar& y)\n    { }\n    template <class Scalar, class Vector>\n    inline void CheckSimpleVector(void)\n    { }\n# else\n    template <class S, class T>\n    struct ok_if_S_same_as_T { };\n\n    template <class T>\n    struct ok_if_S_same_as_T<T,T> { T value; };\n\n    template <class Scalar, class Vector>\n    inline void CheckSimpleVector(const Scalar& x, const Scalar& y)\n    {   //\n        // count\n        static size_t count = 0;\n        if( count > 0  )\n            return;\n        CPPAD_ASSERT_KNOWN(\n            ! CppAD::thread_alloc::in_parallel() ,\n            \"In parallel mode and CheckSimpleVector was not previously called\\n\"\n            \"with this Scalar and Vector type; see the heading\\n\"\n            \"Parallel Mode in the CheckSimpleVector documentation.\"\n        );\n        count++;\n\n        // value_type must be type of elements of Vector\n        typedef typename Vector::value_type value_type;\n\n        // check that elements of Vector have type Scalar\n        struct ok_if_S_same_as_T<Scalar, value_type> x_copy;\n        x_copy.value = x;\n\n        // check default constructor\n        Vector d;\n\n        // size member function\n        CPPAD_ASSERT_KNOWN(\n            d.size() == 0,\n            \"default constructor result does not have size zero\"\n        );\n\n        // resize to same size as other vectors in test\n        d.resize(1);\n\n        // check sizing constructor\n        Vector s(1);\n\n        // check element assignment\n        s[0] = y;\n        CPPAD_ASSERT_KNOWN(\n            s[0] == y,\n            \"element assignment failed\"\n        );\n\n        // check copy constructor\n        s[0] = x_copy.value;\n        const Vector c(s);\n        s[0] = y;\n        CPPAD_ASSERT_KNOWN(\n            c[0] == x,\n            \"copy constructor is shallow\"\n        );\n\n        // vector assignment operator\n        d[0] = x;\n        s    = d;\n        s[0] = y;\n        CPPAD_ASSERT_KNOWN(\n            d[0] == x,\n            \"assignment operator is shallow\"\n        );\n\n        // element access, right side const\n        // element assignment, left side not const\n        d[0] = c[0];\n        CPPAD_ASSERT_KNOWN(\n            d[0] == x,\n            \"element assignment from const failed\"\n        );\n    }\n    template <class Scalar, class Vector>\n    void CheckSimpleVector(void)\n    {   Scalar x;\n        Scalar y;\n\n        // use assignment and not constructor\n        x = Scalar(0);\n        y = Scalar(1);\n\n        CheckSimpleVector<Scalar, Vector>(x, y);\n    }\n\n# endif\n\n} // end namespace CppAD\n\n# undef CPPAD_CHECK_SIMPLE_VECTOR\n# endif\n"
  },
  {
    "path": "include/cppad/utility/create_dll_lib.hpp",
    "content": "# ifndef CPPAD_UTILITY_CREATE_DLL_LIB_HPP\n# define CPPAD_UTILITY_CREATE_DLL_LIB_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin create_dll_lib}\n{xrst_spell\n    cmd\n    csrc\n    hc\n    hs\n    msg\n}\n\nCreate a Dynamic Link Library\n#############################\n\nSyntax\n******\n| # ``include <cppad/utility/create_dll_lib.hpp>``\n| *err_msg* = ``create_dll_lib`` ( *dll_file* , *csrc_files* , *options* )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_CREATE_DLL_LIB\n    // END_CREATE_DLL_LIB\n}\n\ninclude\n*******\nAs with all the CppAD utilities, ``create_dll_lib.hpp`` is included\nby ``<cppad/cppad.hpp>`` , and can also be included separately.\n\ndll_file\n********\nThis is the file where the dynamic link library file named *dll_file* .\nThis file name must have the proper extension for a dynamic link library\n(``.so`` on unix and ``.dll`` on windows).\n\nStringVector\n************\nThe type *StringVector* is a simple vector with elements\nof type ``std::string`` .\n\ncsrc_files\n**********\nThe vector *csrc_files* contains the names of the C source\nfiles that are compiled and linked to the library.\nThese files do not have to have a specific extension.\n\noptions\n*******\nThe possible keys in this map are documented below.\nThe default value for each key is used when the key\ndoes not appear in *options* .\n\ncompile\n=======\nThis is an abbreviated version of the compile command.\nIt does not include the output file flag or output file name.\nIf :ref:`cmake-name` detects that this is the MSVC compiler,\nthe default value for this option is\n\n    `cl /EHs /EHc /c /TC``\n\nIf cmake detects that this is the Clang or GNU compiler,\nthe default value for this option is\n\n    *cppad_c_compiler_cmd* ``-c -fPIC``\n\nHere and below *cppad_c_compiler_cmd* is the command used to run\nthe C compiler (which is determined by cmake) .\n\n\nlink\n====\nThis is an abbreviated version of the link command.\nIt does not include the output file flag or output file name.\nIn the MSVC case, the default for this option is\n\n    ``link /DLL``\n\nIn the Clang or GNU case, the default for this option is\n\n    *cppad_c_compiler_cmd* ``-shared`` .\n\n\nerr_msg\n*******\nIf this string is empty, no error occurred.\nOtherwise the processing aborted and *err_msg* is the corresponding\nerror message.\n\nExample\n*******\nThe file :ref:`dll_lib.cpp-name` contains an example and test of\n``create_dll_lib`` .\n\n{xrst_end create_dll_lib}\n*/\n# include <map>\n# include <cppad/local/temp_file.hpp>\n# include <cppad/configure.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n//\n// create\n// BEGIN_CREATE_DLL_LIB\ntemplate <class StringVector>\nstd::string create_dll_lib(\n    const std::string&                        dll_file   ,\n    const StringVector&                       csrc_files ,\n    const std::map<std::string, std::string>& options    )\n// END_CREATE_DLL_LIB\n{   using std::string;\n    //\n    // err_msg\n    string err_msg = \"\";\n    //\n    // compile, link\n    string compile = \"\";\n    string  link   = \"\";\n# if CPPAD_C_COMPILER_MSVC_FLAGS\n    compile = CPPAD_C_COMPILER_CMD \" /EHs /EHc /c /TC\";\n    link    = \"link /DLL\";\n# endif\n# if CPPAD_C_COMPILER_GNU_FLAGS\n    compile = CPPAD_C_COMPILER_CMD \" -c -fPIC\";\n    link    = CPPAD_C_COMPILER_CMD \" -shared\";\n# endif\n    for( const auto& pair : options )\n    {   const string& key = pair.first;\n        if( key == \"compile\" )\n            compile = pair.second;\n        else if( key == \"link\" )\n            link = pair.second;\n        else\n        {   err_msg = \"options contains following invalid key: \" + key;\n            return err_msg;\n        }\n    }\n    //\n    // check if we know how to create a dll with this compiler\n    if( compile == \"\" )\n    {   err_msg  = \"Do not know how to create a dll using this C compiler\\n\";\n        err_msg += CPPAD_C_COMPILER_CMD;\n        return err_msg;\n    }\n    //\n    // check the std::system function exists\n    int flag = std::system(nullptr);\n    if( flag == 0 )\n    {   err_msg = \"C++ std::system function not available\\n\";\n        return err_msg;\n    }\n    //\n    // check the file extensions\n# ifdef _WIN32\n    string dll_ext = \".dll\";\n# else\n    string dll_ext = \".so\";\n# endif\n    size_t last_match = dll_file.rfind(dll_ext);\n    size_t expected   = dll_file.size() - dll_ext.size();\n    if( last_match != expected )\n    {   err_msg += \"dll_file = \" + dll_file + \"\\ndoes not end with \" + dll_ext;\n        return err_msg;\n    }\n    //\n    // o_file_list, o_file_vec;\n    string       o_file_list;\n    StringVector o_file_vec( csrc_files.size() );\n    //\n    // i_csrc\n    for(size_t i_csrc = 0; i_csrc < csrc_files.size(); ++i_csrc)\n    {   //\n        // c_file\n        string c_file = csrc_files[i_csrc];\n        //\n        // o_file\n        string o_file = local::temp_file();\n        //\n        // cmd\n        string cmd = compile + \" \" + c_file;\n# ifdef _MSC_VER\n        cmd += \" /Fo\\\"\" + o_file + \"\\\" 1> nul 2> nul\";\n# else\n        cmd += \" -o \" + o_file;\n# endif\n        //\n        // o_file\n        // compile c_file and put result in o_file\n        flag = std::system( cmd.c_str() );\n        if(  flag != 0 )\n        {   err_msg = \"create_dll_lib: following system command failed\\n\";\n            err_msg += cmd;\n            return err_msg;\n        }\n        //\n        // o_file_list\n        o_file_list += \" \" + o_file;\n        //\n        // o_file_vec\n        o_file_vec[i_csrc] = o_file;\n    }\n    string cmd = link + \" \" + o_file_list;\n# ifdef _MSC_VER\n    cmd += \" /OUT:\" + dll_file + \" 1> nul 2> nul\";\n# else\n    cmd += \" -o \"   + dll_file;;\n# endif\n    flag = std::system( cmd.c_str() );\n    if(  flag != 0 )\n    {   err_msg = \"create_dll_lib: following system command failed\\n\";\n        err_msg += cmd;\n        return err_msg;\n    }\n    //\n    // remove o_file\n    for(size_t i = 0; i < o_file_vec.size(); ++i)\n    {   flag = std::remove( o_file_vec[i].c_str() );\n        if(  flag != 0 )\n        {   err_msg = \"create_dll_lib: following system command failed\\n\";\n            err_msg += cmd;\n            return err_msg;\n        }\n    }\n    return err_msg;\n}\n\n} // END_CPPAD_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/utility/elapsed_seconds.hpp",
    "content": "# ifndef CPPAD_UTILITY_ELAPSED_SECONDS_HPP\n# define CPPAD_UTILITY_ELAPSED_SECONDS_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin elapsed_seconds}\n{xrst_spell\n    chrono\n}\n\nReturns Elapsed Number of Seconds\n#################################\n\nSyntax\n******\n| # ``include <cppad/utility/elapsed_seconds.hpp>``\n| *s* = ``elapsed_seconds`` ()\n\nAccuracy\n********\nThis routine uses ``std::chrono::steady_clock`` to do its timing.\n\ns\n*\nis a ``double`` equal to the\nnumber of seconds since the first call to ``elapsed_seconds`` .\n{xrst_toc_hidden\n    speed/example/elapsed_seconds.cpp\n}\nExample\n*******\nThe routine :ref:`elapsed_seconds.cpp-name` is\nan example and test of this routine.\n\n{xrst_end elapsed_seconds}\n-----------------------------------------------------------------------\n*/\n\n# include <cppad/core/cppad_assert.hpp>\n\n// needed before one can use CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL\n# include <cppad/utility/thread_alloc.hpp>\n\n// c++11 time function\n# include <chrono>\n\n\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n\ninline double elapsed_seconds(void)\n// --------------------------------------------------------------------------\n{   CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL;\n    static bool first_ = true;\n    static std::chrono::time_point<std::chrono::steady_clock> start_;\n    if( first_ )\n    {   start_ = std::chrono::steady_clock::now();\n        first_ = false;\n        return 0.0;\n    }\n    std::chrono::time_point<std::chrono::steady_clock> now;\n    now   = std::chrono::steady_clock::now();\n    std::chrono::duration<double> difference = now - start_;\n    return difference.count();\n}\n// --------------------------------------------------------------------------\n} // END_CPPAD_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/utility/error_handler.hpp",
    "content": "# ifndef CPPAD_UTILITY_ERROR_HANDLER_HPP\n# define CPPAD_UTILITY_ERROR_HANDLER_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin ErrorHandler}\n{xrst_spell\n    msg\n    test test\n}\n\nReplacing the CppAD Error Handler\n#################################\n\nSyntax\n******\n| # ``include <cppad/utility/error_handler.hpp>``\n| ``ErrorHandler`` *info* ( *handler* )\n| ``ErrorHandler::Call`` ( *known* , *line* , *file* , *exp* , *msg* )\n\nConstructor\n***********\nWhen you construct a ``ErrorHandler`` object,\nthe current CppAD error handler is replaced by *handler* .\nWhen the object is destructed, the previous CppAD error handler is restored.\n\nParallel Mode\n=============\nThe ``ErrorHandler`` constructor and destructor cannot be called in\n:ref:`parallel<ta_in_parallel-name>` execution mode.\nIf this rule is not abided by, a raw C++ ``assert`` ,\ninstead of one that uses this error handler, will be generated.\n\nCall\n****\nWhen ``ErrorHandler::Call`` is called,\nthe current CppAD error handler is used to report an error.\nThis starts out as a default error handler and can be replaced\nusing the ``ErrorHandler`` constructor.\n\ninfo\n****\nThe object *info* is used to store information\nthat is necessary to restore the previous CppAD error handler.\nThis restoration is done when the destructor for *info* is called.\n\nhandler\n*******\nThe argument *handler* has prototype\n\n| |tab| ``void`` (* *handler* )\n| |tab| |tab| ( ``bool`` , ``int`` , ``const char`` * , ``const char`` * , ``const char`` * );\n\nWhen an error is detected,\nit is called with the syntax\n\n    *handler* ( *known* , *line* , *file* , *exp* , *msg* )\n\nThis routine should not return; i.e., upon detection of the error,\nthe routine calling *handler* does not know how to proceed.\n\nknown\n*****\nThe *handler* argument *known* has prototype\n\n    ``bool`` *known*\n\nIf it is true, the error being reported is from a know problem.\n\nline\n****\nThe *handler* argument *line* has prototype\n\n    ``int`` *line*\n\nIt reports the source code line number where the error is detected.\n\nfile\n****\nThe *handler* argument *file* has prototype\n\n    ``const char`` * *file*\n\nand is a ``'\\0'`` terminated character vector.\nIt reports the source code file where the error is detected.\n\nexp\n***\nThe *handler* argument *exp* has prototype\n\n    ``const char`` * *exp*\n\nand is a ``'\\0'`` terminated character vector.\nIt is a source code boolean expression that should have been true,\nbut is false,\nand thereby causes this call to *handler* .\n\nmsg\n***\nThe *handler* argument *msg* has prototype\n\n    ``const char`` * *msg*\n\nand is a ``'\\0'`` terminated character vector.\nIt reports the meaning of the error from the C++ programmers point of view.\n{xrst_toc_hidden\n    example/utility/error_handler.cpp\n    include/cppad/core/cppad_assert.hpp\n}\nExample\n*******\nThe file\n:ref:`error_handler.cpp-name`\ncontains an example and test a test of using this routine.\n\n{xrst_end ErrorHandler}\n---------------------------------------------------------------------------\n*/\n\n# include <iostream>\n\n# include <cppad/configure.hpp>\n# include <cppad/local/set_get_in_parallel.hpp>\n# include <cassert>\n# include <cstdlib>\n\nnamespace CppAD { // BEGIN CppAD namespace\n\nclass ErrorHandler {\n    template <class Base>\n    friend void parallel_ad(void);\npublic:\n    typedef void (*Handler)\n        (bool, int, const char *, const char *, const char *);\n\n    // construct a new handler\n    ErrorHandler(Handler handler) : previous( Current() )\n    {   if( local::set_get_in_parallel() )\n        {   bool known       = true;\n            int  line        = __LINE__;\n            const char* file = __FILE__;\n            const char* exp  = \"! local::set_get_in_parallel()\";\n            const char* msg  =\n                \"Using ErrorHandler constructor in parallel mode.\";\n            Call(known, line, file, exp, msg);\n        }\n        Current() = handler;\n    }\n\n    // destructor for an error handler\n    ~ErrorHandler(void)\n    {   if( local::set_get_in_parallel() )\n        {   bool known       = true;\n            int  line        = __LINE__;\n            const char* file = __FILE__;\n            const char* exp  = \"! local::set_get_in_parallel()\";\n            const char* msg  =\n                \"Using ErrorHandler destructor in parallel mode.\";\n            Call(known, line, file, exp, msg);\n        }\n        Current() = previous;\n    }\n\n    // report an error\n    static void Call(\n        bool        known,\n        int         line ,\n        const char *file ,\n        const char *exp  ,\n        const char *msg  )\n    {   Handler handler = Current();\n        handler(known, line, file, exp, msg);\n    }\n\nprivate:\n    const Handler previous;\n\n    // The default error handler\n    static void Default(\n        bool        known,\n        int         line ,\n        const char *file ,\n        const char *exp  ,\n        const char *msg  )\n    {   using std::cerr;\n        using std::endl;\n\n        cerr << CPPAD_PACKAGE_STRING;\n        if( known )\n            cerr << \" error from a known source:\" << endl;\n        else\n            cerr << \" error from unknown source\"  << endl;\n        if( msg[0] != '\\0' )\n            cerr << msg << endl;\n        cerr << \"Error detected by false result for\"  << endl;\n        cerr << \"    \"     << exp                     << endl;\n        cerr << \"at line \" << line << \" in the file \" << endl;\n        cerr << \"    \"     << file                    << endl;\n\n        // terminate program execution\n        assert(false);\n\n        // termination when NDEBUG is defined\n        std::exit(1);\n    }\n\n    // current error handler\n    static Handler &Current(void)\n    {   static bool first_call = true;\n        static Handler current = Default;\n        // CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL\n        // code below is like macro above but works when NDEBUG defined\n        if( first_call )\n        {   if( local::set_get_in_parallel() )\n            {   bool known       = false;\n                int  line        = __LINE__;\n                const char* file = __FILE__;\n                const char* exp  = \"\";\n                const char* msg  = \"\";\n                Call(known, line, file, exp, msg);\n            }\n            first_call = false;\n        }\n        return current;\n    }\n};\n\n} // END CppAD namespace\n\n\n\n# endif\n"
  },
  {
    "path": "include/cppad/utility/index_sort.hpp",
    "content": "# ifndef CPPAD_UTILITY_INDEX_SORT_HPP\n# define CPPAD_UTILITY_INDEX_SORT_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin index_sort}\n\nReturns Indices that Sort a Vector\n##################################\n\nSyntax\n******\n| # ``include <cppad/utility/index_sort.hpp>``\n| ``index_sort`` ( *keys* , *ind* )\n\nkeys\n****\nThe argument *keys* has prototype\n\n    ``const`` *KeyVector* & *keys*\n\nwhere *KeyVector* is\na :ref:`SimpleVector-name` class with elements that support the ``<``\noperation.\n\nind\n***\nThe argument *ind* has prototype\n\n    *SizeVector* & *ind*\n\nwhere *SizeVector* is\na :ref:`SimpleVector-name` class with elements of type *Size_t* ,\nwhere *Size_t* is an integral type.\nThe routine :ref:`CheckSimpleVector-name` will generate an error message\nif this is not the case.\n\nInput\n=====\nThe size of *ind* must be the same as the size of *keys*\nand the value of its input elements does not matter.\n\nReturn\n======\nUpon return, *ind* is a permutation of the set of indices\nthat yields increasing order for *keys* .\nIn other words, for all *i* != *j* ,\n\n    *ind* [ *i* ] != *ind* [ *j* ]\n\nand for *i* = 0 , ... , *size* ``-2`` ,\n\n    ( *keys* [ *ind* [ *i* +1] ] < *keys* [ *ind* [ *i* ] ] ) == ``false``\n\nExample\n*******\n{xrst_toc_hidden\n    example/utility/index_sort.cpp\n}\nThe file :ref:`index_sort.cpp-name` contains an example\nand test of this routine.\nIt return true if it succeeds and false otherwise.\n\n{xrst_end index_sort}\n*/\n# include <algorithm>\n# include <cppad/utility/thread_alloc.hpp>\n# include <cppad/utility/check_simple_vector.hpp>\n# include <cppad/local/define.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\n\\file index_sort.hpp\nFile used to implement the CppAD index sort utility\n*/\n\n/*!\nHelper class used by index_sort\n*/\ntemplate <class Compare, class Size_t>\nclass index_sort_element {\nprivate:\n    /// key used to determine position of this element\n    Compare key_;\n    /// index value corresponding to this key\n    Size_t  index_;\npublic:\n    /// operator required by std::sort\n    bool operator<(const index_sort_element& other) const\n    {   return key_ < other.key_; }\n    /// set the key for this element\n    void set_key(const Compare& value)\n    {   key_ = value; }\n    /// set the index for this element\n    void set_index(const Size_t& index)\n    {   index_ = index; }\n    /// get the key for this element\n    Compare get_key(void) const\n    {   return key_; }\n    /// get the index for this element\n    Size_t get_index(void) const\n    {   return index_; }\n};\n\n/*!\nCompute the indices that sort a vector of keys\n\n\\tparam KeyVector\nSimple vector type that deterimene the sorting order by < operator\non its elements.\n\n\\tparam SizeVector\nSimple vector type with elements of size_t\nthat is used to return index values.\n\n\\param keys [in]\nvalues that determine the sorting order.\n\n\\param ind [out]\nmust have the same size as keys.\nThe input value of its elements does not matter.\nThe output value of its elements satisfy\n\\code\n( keys[ ind[i] ] < keys[ ind[i+1] ] ) == false\n\\endcode\n*/\ntemplate <class KeyVector, class SizeVector>\nvoid index_sort(const KeyVector& keys, SizeVector& ind)\n{   typedef typename KeyVector::value_type      Compare;\n    typedef typename SizeVector::value_type     Size_t;\n    typedef index_sort_element<Compare, Size_t> Element;\n    //\n    CheckSimpleVector<Size_t, SizeVector>();\n    //\n    CPPAD_ASSERT_KNOWN(\n        keys.size() == ind.size(),\n        \"index_sort: vector sizes do not match\"\n    );\n\n    size_t size_work = keys.size();\n    size_t size_out;\n    Element* work =\n        thread_alloc::create_array<Element>(size_work, size_out);\n\n    // copy initial order into work\n    size_t i;\n    for(i = 0; i < size_work; i++)\n    {   work[i].set_key( keys[i] );\n        work[i].set_index( Size_t(i) );\n    }\n\n    // sort the work array\n    std::sort(work, work+size_work);\n\n    // copy the indices to the output vector\n    for(i = 0; i < size_work; i++)\n        ind[i] = work[i].get_index();\n\n    // we are done with this work array\n    thread_alloc::delete_array(work);\n\n    return;\n}\n\n} // END_CPPAD_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/utility/link_dll_lib.hpp",
    "content": "# ifndef CPPAD_UTILITY_LINK_DLL_LIB_HPP\n# define CPPAD_UTILITY_LINK_DLL_LIB_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin link_dll_lib}\n{xrst_spell\n    msg\n}\n\nLink a Dynamic Link Library\n###########################\n\nSyntax\n******\n| # ``include <cppad/utility/link_dll_lib.hpp>``\n| ``link_dll_lib`` *dll_linker* ( *dll_file* , *err_msg* )\n| *fun_ptr* = *dll_linker* ( *function_name* , *err_msg* )\n|\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_PROTOTYPE\n    // END_PROTOTYPE\n}\n\ndll_linker\n**********\nIs the dynamic link object that holds an in memory version of the library,\n\nerr_msg\n*******\nIf *err_msg* is non-empty, it contains an error message\nfor the corresponding operation.\n\ndll_file\n********\nIs the file containing the dynamic link library.\n\nfunction_name\n*************\nIs the name of an external entry point in the dll.\n\nfun_ptr\n*******\nIs a ``void*`` version of a pointer the function corresponding to\n*function_name* .\n\nWarning !!\n==========\n*fun_ptr* becomes invalid when the *dll_linker* destructor is called.\n\n{xrst_toc_hidden\n    example/utility/dll_lib.cpp\n}\nExample\n*******\nThe file :ref:`dll_lib.cpp-name` contains an example and test of\n``link_dll_lib`` .\n\n{xrst_end link_dll_lib}\n*/\n\n# include <string>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n\nclass link_dll_lib {\nprivate:\n    // pointer to the dll object\n    void* handle_;\n    //\n    // error message during constructor\n    std::string ctor_err_msg_;\n    //\n# ifdef _WIN32\n    static void*       dlopen(const char *filename, int flag);\n    static void*       dlsym(void* handle, const char* symbol);\n    static int         dlclose(void* handle);\n    static const char* dlerror(void);\n# endif\n    //\npublic:\n    // BEGIN_PROTOTYPE\n    link_dll_lib(const std::string& dll_file, std::string& err_msg);\n    ~link_dll_lib(void);\n    void* operator()\n    (const std::string& function_name, std::string& err_msg) const;\n    // END_PROTOTYPE\n};\n\n} // END_CPPAD_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/utility/lu_factor.hpp",
    "content": "# ifndef CPPAD_UTILITY_LU_FACTOR_HPP\n# define CPPAD_UTILITY_LU_FACTOR_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin LuFactor}\n{xrst_spell\n    geq\n    ip\n    jp\n}\n\nLU Factorization of A Square Matrix\n###################################\n\nSyntax\n******\n| # ``include <cppad/utility/lu_factor.hpp>``\n| *sign* = ``LuFactor`` ( *ip* , *jp* , *LU* )\n\nDescription\n***********\nComputes an LU factorization of the matrix *A*\nwhere *A* is a square matrix.\n\nInclude\n*******\nThe file ``cppad/utility/lu_factor.hpp``\nis included by ``cppad/cppad.hpp``\nbut it can also be included separately with out the rest of\nthe ``CppAD`` routines.\n\nMatrix Storage\n**************\nAll matrices are stored in row major order.\nTo be specific, if :math:`Y` is a vector\nthat contains a :math:`p` by :math:`q` matrix,\nthe size of :math:`Y` must be equal to :math:`p * q` and for\n:math:`i = 0 , \\ldots , p-1`,\n:math:`j = 0 , \\ldots , q-1`,\n\n.. math::\n\n    Y_{i,j} = Y[ i * q + j ]\n\nsign\n****\nThe return value *sign* has prototype\n\n    ``int`` *sign*\n\nIf *A* is invertible, *sign* is plus or minus one\nand is the sign of the permutation corresponding to the row ordering\n*ip* and column ordering *jp* .\nIf *A* is not invertible, *sign* is zero.\n\nip\n**\nThe argument *ip* has prototype\n\n    *SizeVector* & *ip*\n\n(see description of :ref:`LuFactor@SizeVector` below).\nThe size of *ip* is referred to as *n* in the\nspecifications below.\nThe input value of the elements of *ip* does not matter.\nThe output value of the elements of *ip* determine\nthe order of the rows in the permuted matrix.\n\njp\n**\nThe argument *jp* has prototype\n\n    *SizeVector* & *jp*\n\n(see description of :ref:`LuFactor@SizeVector` below).\nThe size of *jp* must be equal to *n* .\nThe input value of the elements of *jp* does not matter.\nThe output value of the elements of *jp* determine\nthe order of the columns in the permuted matrix.\n\nLU\n**\nThe argument *LU* has the prototype\n\n    *FloatVector* & *LU*\n\nand the size of *LU* must equal :math:`n * n`\n(see description of :ref:`LuFactor@FloatVector` below).\n\nA\n=\nWe define *A* as the matrix corresponding to the input\nvalue of *LU* .\n\nP\n=\nWe define the permuted matrix *P* in terms of *A* by\n\n    *P* ( *i* , *j* ) = *A* [ *ip* [ *i* ] * *n* + *jp* [ *j* ] ]\n\nL\n=\nWe define the lower triangular matrix *L* in terms of the\noutput value of *LU* .\nThe matrix *L* is zero above the diagonal\nand the rest of the elements are defined by\n\n    *L* ( *i* , *j* ) = *LU* [ *ip* [ *i* ] * *n* + *jp* [ *j* ] ]\n\nfor :math:`i = 0 , \\ldots , n-1` and :math:`j = 0 , \\ldots , i`.\n\nU\n=\nWe define the upper triangular matrix *U* in terms of the\noutput value of *LU* .\nThe matrix *U* is zero below the diagonal,\none on the diagonal,\nand the rest of the elements are defined by\n\n    *U* ( *i* , *j* ) = *LU* [ *ip* [ *i* ] * *n* + *jp* [ *j* ] ]\n\nfor :math:`i = 0 , \\ldots , n-2` and :math:`j = i+1 , \\ldots , n-1`.\n\nFactor\n======\nIf the return value *sign* is non-zero,\n\n    *L* * *U* = *P*\n\nIf the return value of *sign* is zero,\nthe contents of *L* and *U* are not defined.\n\nDeterminant\n===========\nIf the return value *sign* is zero,\nthe determinant of *A* is zero.\nIf *sign* is non-zero,\nusing the output value of *LU*\nthe determinant of the matrix *A* is equal to\n\n    *sign* * *LU* [ *ip* [0], *jp* [0]] * ... * *LU* [ *ip* [ *n* ``-1`` ], *jp* [ *n* ``-1`` ]]\n\nSizeVector\n**********\nThe type *SizeVector* must be a :ref:`SimpleVector-name` class with\n:ref:`elements of type size_t<SimpleVector@Elements of Specified Type>` .\nThe routine :ref:`CheckSimpleVector-name` will generate an error message\nif this is not the case.\n\nFloatVector\n***********\nThe type *FloatVector* must be a\n:ref:`simple vector class<SimpleVector-name>` .\nThe routine :ref:`CheckSimpleVector-name` will generate an error message\nif this is not the case.\n\nFloat\n*****\nThis notation is used to denote the type corresponding\nto the elements of a *FloatVector* .\nThe type *Float* must satisfy the conditions\nfor a :ref:`NumericType-name` .\nThe routine :ref:`CheckNumericType-name` will generate an error message\nif this is not the case.\nIn addition, the following operations must be defined for any pair\nof *Float* objects *x* and *y* :\n\n.. list-table::\n    :widths: auto\n\n    * - **Operation**\n      - **Description**\n    * - ``log`` ( *x* )\n      - returns the logarithm of *x* as a *Float* object\n\nAbsGeq\n******\nIncluding the file ``lu_factor.hpp`` defines the template function\n\n| |tab| ``template <class`` *Float* >\n| |tab| ``bool AbsGeq`` < *Float* >( ``const`` *Float* & *x* , ``const`` *Float* & *y* )\n\nin the ``CppAD`` namespace.\nThis function returns true if the absolute value of\n*x* is greater than or equal the absolute value of *y* .\nIt is used by ``LuFactor`` to choose the pivot elements.\nThis template function definition uses the operator\n``<=`` to obtain the absolute value for *Float* objects.\nIf this operator is not defined for your use of *Float* ,\nyou will need to specialize this template so that it works for your\nuse of ``LuFactor`` .\n\nComplex numbers do not have the operation ``<=`` defined.\nThe specializations\n\n| ``bool AbsGeq< std::complex<float> >``\n| |tab| ( ``const std::complex<float> &`` *x* , ``const std::complex<float> &`` *y* )\n| ``bool AbsGeq< std::complex<double> >``\n| |tab| ( ``const std::complex<double> &`` *x* , ``const std::complex<double> &`` *y* )\n\nare define by including ``lu_factor.hpp``\nThese return true if the sum of the square of the real and imaginary parts\nof *x* is greater than or equal the\nsum of the square of the real and imaginary parts of *y* .\n{xrst_toc_hidden\n    example/utility/lu_factor.cpp\n    xrst/lu_factor_hpp.xrst\n}\nExample\n*******\nThe file\n:ref:`lu_factor.cpp-name`\ncontains an example and test of using ``LuFactor`` by itself.\n\nThe file :ref:`lu_solve.hpp-name` provides a useful example usage of\n``LuFactor`` with ``LuInvert`` .\n\nSource\n******\nThe file :ref:`lu_factor.hpp-name` contains the\ncurrent source code that implements these specifications.\n\n{xrst_end LuFactor}\n--------------------------------------------------------------------------\n*/\n// BEGIN C++\n\n# include <complex>\n# include <vector>\n\n# include <cppad/core/cppad_assert.hpp>\n# include <cppad/utility/check_simple_vector.hpp>\n# include <cppad/utility/check_numeric_type.hpp>\n\nnamespace CppAD { // BEGIN CppAD namespace\n\n// AbsGeq\ntemplate <class Float>\nbool AbsGeq(const Float &x, const Float &y)\n{   Float xabs = x;\n    if( xabs <= Float(0) )\n        xabs = - xabs;\n    Float yabs = y;\n    if( yabs <= Float(0) )\n        yabs = - yabs;\n    return xabs >= yabs;\n}\ninline bool AbsGeq(\n    const std::complex<double> &x,\n    const std::complex<double> &y)\n{   double xsq = x.real() * x.real() + x.imag() * x.imag();\n    double ysq = y.real() * y.real() + y.imag() * y.imag();\n\n    return xsq >= ysq;\n}\ninline bool AbsGeq(\n    const std::complex<float> &x,\n    const std::complex<float> &y)\n{   float xsq = x.real() * x.real() + x.imag() * x.imag();\n    float ysq = y.real() * y.real() + y.imag() * y.imag();\n\n    return xsq >= ysq;\n}\n\n// Lines that are different from code in cppad/core/lu_ratio.hpp end with //\ntemplate <class SizeVector, class FloatVector>                          //\nint LuFactor(SizeVector &ip, SizeVector &jp, FloatVector &LU)           //\n{\n    // type of the elements of LU                                   //\n    typedef typename FloatVector::value_type Float;                 //\n\n    // check numeric type specifications\n    CheckNumericType<Float>();\n\n    // check simple vector class specifications\n    CheckSimpleVector<Float, FloatVector>();\n    CheckSimpleVector<size_t, SizeVector>();\n\n    size_t  i, j;          // some temporary indices\n    const Float zero( 0 ); // the value zero as a Float object\n    size_t  imax;          // row index of maximum element\n    size_t  jmax;          // column index of maximum element\n    Float    emax;         // maximum absolute value\n    size_t  p;             // count pivots\n    int     sign;          // sign of the permutation\n    Float   etmp;          // temporary element\n    Float   pivot;         // pivot element\n\n    // -------------------------------------------------------\n    size_t n = ip.size();\n    CPPAD_ASSERT_KNOWN(\n        size_t(jp.size()) == n,\n        \"Error in LuFactor: jp must have size equal to n\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t(LU.size()) == n * n,\n        \"Error in LuFactor: LU must have size equal to n * m\"\n    );\n    // -------------------------------------------------------\n\n    // initialize row and column order in matrix not yet pivoted\n    for(i = 0; i < n; i++)\n    {   ip[i] = i;\n        jp[i] = i;\n    }\n    // initialize the sign of the permutation\n    sign = 1;\n    // ---------------------------------------------------------\n\n    // Reduce the matrix P to L * U using n pivots\n    for(p = 0; p < n; p++)\n    {   // determine row and column corresponding to element of\n        // maximum absolute value in remaining part of P\n        imax = jmax = n;\n        emax = zero;\n        for(i = p; i < n; i++)\n        {   for(j = p; j < n; j++)\n            {   CPPAD_ASSERT_UNKNOWN(\n                    (ip[i] < n) && (jp[j] < n)\n                );\n                etmp = LU[ ip[i] * n + jp[j] ];\n\n                // check if maximum absolute value so far\n                if( AbsGeq (etmp, emax) )\n                {   imax = i;\n                    jmax = j;\n                    emax = etmp;\n                }\n            }\n        }\n        CPPAD_ASSERT_KNOWN(\n        (imax < n) && (jmax < n) ,\n        \"LuFactor can't determine an element with \"\n        \"maximum absolute value.\\n\"\n        \"Perhaps original matrix contains not a number or infinity.\\n\"\n        \"Perhaps your specialization of AbsGeq is not correct.\"\n        );\n        if( imax != p )\n        {   // switch rows so max absolute element is in row p\n            i        = ip[p];\n            ip[p]    = ip[imax];\n            ip[imax] = i;\n            sign     = -sign;\n        }\n        if( jmax != p )\n        {   // switch columns so max absolute element is in column p\n            j        = jp[p];\n            jp[p]    = jp[jmax];\n            jp[jmax] = j;\n            sign     = -sign;\n        }\n        // pivot using the max absolute element\n        pivot   = LU[ ip[p] * n + jp[p] ];\n\n        // check for determinant equal to zero\n        if( pivot == zero )\n        {   // abort the mission\n            return   0;\n        }\n\n        // Reduce U by the elementary transformations that maps\n        // LU( ip[p], jp[p] ) to one.  Only need transform elements\n        // above the diagonal in U and LU( ip[p] , jp[p] ) is\n        // corresponding value below diagonal in L.\n        for(j = p+1; j < n; j++)\n            LU[ ip[p] * n + jp[j] ] /= pivot;\n\n        // Reduce U by the elementary transformations that maps\n        // LU( ip[i], jp[p] ) to zero. Only need transform elements\n        // above the diagonal in U and LU( ip[i], jp[p] ) is\n        // corresponding value below diagonal in L.\n        for(i = p+1; i < n; i++ )\n        {   etmp = LU[ ip[i] * n + jp[p] ];\n            for(j = p+1; j < n; j++)\n            {   LU[ ip[i] * n + jp[j] ] -=\n                    etmp * LU[ ip[p] * n + jp[j] ];\n            }\n        }\n    }\n    return sign;\n}\n} // END CppAD namespace\n// END C++\n# endif\n"
  },
  {
    "path": "include/cppad/utility/lu_invert.hpp",
    "content": "# ifndef CPPAD_UTILITY_LU_INVERT_HPP\n# define CPPAD_UTILITY_LU_INVERT_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin LuInvert}\n{xrst_spell\n    ip\n    jp\n}\n\nInvert an LU Factored Equation\n##############################\n\nSyntax\n******\n| # ``include <cppad/utility/lu_invert.hpp>``\n| ``LuInvert`` ( *ip* , *jp* , *LU* , *X* )\n\nDescription\n***********\nSolves the matrix equation *A* * *X* = *B*\nusing an LU factorization computed by :ref:`LuFactor-name` .\n\nInclude\n*******\nThe file ``cppad/utility/lu_invert.hpp``\nis included by ``cppad/cppad.hpp``\nbut it can also be included separately with out the rest of\nthe ``CppAD`` routines.\n\nMatrix Storage\n**************\nAll matrices are stored in row major order.\nTo be specific, if :math:`Y` is a vector\nthat contains a :math:`p` by :math:`q` matrix,\nthe size of :math:`Y` must be equal to :math:`p * q` and for\n:math:`i = 0 , \\ldots , p-1`,\n:math:`j = 0 , \\ldots , q-1`,\n\n.. math::\n\n    Y_{i,j} = Y[ i * q + j ]\n\nip\n**\nThe argument *ip* has prototype\n\n    ``const`` *SizeVector* & *ip*\n\n(see description for *SizeVector* in\n:ref:`LuFactor<LuFactor@SizeVector>` specifications).\nThe size of *ip* is referred to as *n* in the\nspecifications below.\nThe elements of *ip* determine\nthe order of the rows in the permuted matrix.\n\njp\n**\nThe argument *jp* has prototype\n\n    ``const`` *SizeVector* & *jp*\n\n(see description for *SizeVector* in\n:ref:`LuFactor<LuFactor@SizeVector>` specifications).\nThe size of *jp* must be equal to *n* .\nThe elements of *jp* determine\nthe order of the columns in the permuted matrix.\n\nLU\n**\nThe argument *LU* has the prototype\n\n    ``const`` *FloatVector* & *LU*\n\nand the size of *LU* must equal :math:`n * n`\n(see description for *FloatVector* in\n:ref:`LuFactor<LuFactor@FloatVector>` specifications).\n\nL\n=\nWe define the lower triangular matrix *L* in terms of *LU* .\nThe matrix *L* is zero above the diagonal\nand the rest of the elements are defined by\n\n    *L* ( *i* , *j* ) = *LU* [ *ip* [ *i* ] * *n* + *jp* [ *j* ] ]\n\nfor :math:`i = 0 , \\ldots , n-1` and :math:`j = 0 , \\ldots , i`.\n\nU\n=\nWe define the upper triangular matrix *U* in terms of *LU* .\nThe matrix *U* is zero below the diagonal,\none on the diagonal,\nand the rest of the elements are defined by\n\n    *U* ( *i* , *j* ) = *LU* [ *ip* [ *i* ] * *n* + *jp* [ *j* ] ]\n\nfor :math:`i = 0 , \\ldots , n-2` and :math:`j = i+1 , \\ldots , n-1`.\n\nP\n=\nWe define the permuted matrix *P* in terms of\nthe matrix *L* and the matrix *U*\nby *P* = *L* * *U* .\n\nA\n=\nThe matrix *A* ,\nwhich defines the linear equations that we are solving, is given by\n\n    *P* ( *i* , *j* ) = *A* [ *ip* [ *i* ] * *n* + *jp* [ *j* ] ]\n\n(Hence\n*LU* contains a permuted factorization of the matrix *A* .)\n\nX\n*\nThe argument *X* has prototype\n\n    *FloatVector* & *X*\n\n(see description for *FloatVector* in\n:ref:`LuFactor<LuFactor@FloatVector>` specifications).\nThe matrix *X*\nmust have the same number of rows as the matrix *A* .\nThe input value of *X* is the matrix *B* and the\noutput value solves the matrix equation *A* * *X* = *B* .\n{xrst_toc_hidden\n    example/utility/lu_invert.cpp\n    xrst/lu_invert_hpp.xrst\n}\nExample\n*******\nThe file :ref:`lu_solve.hpp-name` is a good example usage of\n``LuFactor`` with ``LuInvert`` .\nThe file\n:ref:`lu_invert.cpp-name`\ncontains an example and test of using ``LuInvert`` by itself.\n\nSource\n******\nThe file :ref:`lu_invert.hpp-name` contains the\ncurrent source code that implements these specifications.\n\n{xrst_end LuInvert}\n--------------------------------------------------------------------------\n*/\n// BEGIN C++\n# include <cppad/core/cppad_assert.hpp>\n# include <cppad/utility/check_simple_vector.hpp>\n# include <cppad/utility/check_numeric_type.hpp>\n\nnamespace CppAD { // BEGIN CppAD namespace\n\n// LuInvert\ntemplate <class SizeVector, class FloatVector>\nvoid LuInvert(\n    const SizeVector  &ip,\n    const SizeVector  &jp,\n    const FloatVector &LU,\n    FloatVector       &B )\n{   size_t k; // column index in X\n    size_t p; // index along diagonal in LU\n    size_t i; // row index in LU and X\n\n    typedef typename FloatVector::value_type Float;\n\n    // check numeric type specifications\n    CheckNumericType<Float>();\n\n    // check simple vector class specifications\n    CheckSimpleVector<Float, FloatVector>();\n    CheckSimpleVector<size_t, SizeVector>();\n\n    Float etmp;\n\n    size_t n = ip.size();\n    CPPAD_ASSERT_KNOWN(\n        size_t(jp.size()) == n,\n        \"Error in LuInvert: jp must have size equal to n * n\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t(LU.size()) == n * n,\n        \"Error in LuInvert: Lu must have size equal to n * m\"\n    );\n    size_t m = size_t(B.size()) / n;\n    CPPAD_ASSERT_KNOWN(\n        size_t(B.size()) == n * m,\n        \"Error in LuSolve: B must have size equal to a multiple of n\"\n    );\n\n    // temporary storage for reordered solution\n    FloatVector x(n);\n\n    // loop over equations\n    for(k = 0; k < m; k++)\n    {   // invert the equation c = L * b\n        for(p = 0; p < n; p++)\n        {   // solve for c[p]\n            etmp = B[ ip[p] * m + k ] / LU[ ip[p] * n + jp[p] ];\n            B[ ip[p] * m + k ] = etmp;\n            // subtract off effect on other variables\n            for(i = p+1; i < n; i++)\n                B[ ip[i] * m + k ] -=\n                    etmp * LU[ ip[i] * n + jp[p] ];\n        }\n\n        // invert the equation x = U * c\n        p = n;\n        while( p > 0 )\n        {   --p;\n            etmp       = B[ ip[p] * m + k ];\n            x[ jp[p] ] = etmp;\n            for(i = 0; i < p; i++ )\n                B[ ip[i] * m + k ] -=\n                    etmp * LU[ ip[i] * n + jp[p] ];\n        }\n\n        // copy reordered solution into B\n        for(i = 0; i < n; i++)\n            B[i * m + k] = x[i];\n    }\n    return;\n}\n} // END CppAD namespace\n// END C++\n# endif\n"
  },
  {
    "path": "include/cppad/utility/lu_solve.hpp",
    "content": "# ifndef CPPAD_UTILITY_LU_SOLVE_HPP\n# define CPPAD_UTILITY_LU_SOLVE_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin LuSolve}\n{xrst_spell\n    geq\n    leq\n    logdet\n    signdet\n}\n\nCompute Determinant and Solve Linear Equations\n##############################################\n\nSyntax\n******\n| # ``include <cppad/utility/lu_solve.hpp>``\n| *signdet* = ``LuSolve`` ( *n* , *m* , *A* , *B* , *X* , *logdet* )\n\nDescription\n***********\nUse an LU factorization of the matrix *A* to\ncompute its determinant\nand solve for *X* in the linear of equation\n\n.. math::\n\n    A * X = B\n\nwhere *A* is an\n*n* by *n* matrix,\n*X* is an\n*n* by *m* matrix, and\n*B* is an :math:`n x m` matrix.\n\nInclude\n*******\nThe file ``cppad/utility/lu_solve.hpp``\nis included by ``cppad/cppad.hpp``\nbut it can also be included separately with out the rest of\nthe ``CppAD`` routines.\n\nFactor and Invert\n*****************\nThis routine is an easy to user interface to\n:ref:`LuFactor-name` and :ref:`LuInvert-name` for computing determinants and\nsolutions of linear equations.\nThese separate routines should be used if\none right hand side *B*\ndepends on the solution corresponding to another\nright hand side (with the same value of *A* ).\nIn this case only one call to ``LuFactor`` is required\nbut there will be multiple calls to ``LuInvert`` .\n\nMatrix Storage\n**************\nAll matrices are stored in row major order.\nTo be specific, if :math:`Y` is a vector\nthat contains a :math:`p` by :math:`q` matrix,\nthe size of :math:`Y` must be equal to :math:`p * q` and for\n:math:`i = 0 , \\ldots , p-1`,\n:math:`j = 0 , \\ldots , q-1`,\n\n.. math::\n\n    Y_{i,j} = Y[ i * q + j ]\n\nsigndet\n*******\nThe return value *signdet* is a ``int`` value\nthat specifies the sign factor for the determinant of *A* .\nThis determinant of *A* is zero if and only if *signdet*\nis zero.\n\nn\n*\nThe argument *n* has type ``size_t``\nand specifies the number of rows in the matrices\n*A* ,\n*X* ,\nand *B* .\nThe number of columns in *A* is also equal to *n* .\n\nm\n*\nThe argument *m* has type ``size_t``\nand specifies the number of columns in the matrices\n*X*\nand *B* .\nIf *m* is zero,\nonly the determinant of *A* is computed and\nthe matrices *X* and *B* are not used.\n\nA\n*\nThe argument *A* has the prototype\n\n    ``const`` *FloatVector* & *A*\n\nand the size of *A* must equal :math:`n * n`\n(see description of :ref:`LuSolve@FloatVector` below).\nThis is the :math:`n` by *n* matrix that\nwe are computing the determinant of\nand that defines the linear equation.\n\nB\n*\nThe argument *B* has the prototype\n\n    ``const`` *FloatVector* & *B*\n\nand the size of *B* must equal :math:`n * m`\n(see description of :ref:`LuSolve@FloatVector` below).\nThis is the :math:`n` by *m* matrix that\ndefines the right hand side of the linear equations.\nIf *m* is zero, *B* is not used.\n\nX\n*\nThe argument *X* has the prototype\n\n    *FloatVector* & *X*\n\nand the size of *X* must equal :math:`n * m`\n(see description of :ref:`LuSolve@FloatVector` below).\nThe input value of *X* does not matter.\nOn output, the elements of *X* contain the solution\nof the equation we wish to solve\n(unless *signdet* is equal to zero).\nIf *m* is zero, *X* is not used.\n\nlogdet\n******\nThe argument *logdet* has prototype\n\n    *Float* & *logdet*\n\nOn input, the value of *logdet* does not matter.\nOn output, it has been set to the\nlog of the determinant of *A*\n(but not quite).\nTo be more specific,\nthe determinant of *A* is given by the formula\n\n    *det* = *signdet* * ``exp`` ( *logdet*  )\n\nThis enables ``LuSolve`` to use logs of absolute values\nin the case where *Float* corresponds to a real number.\n\nFloat\n*****\nThe type *Float* must satisfy the conditions\nfor a :ref:`NumericType-name` .\nThe routine :ref:`CheckNumericType-name` will generate an error message\nif this is not the case.\nIn addition, the following operations must be defined for any pair\nof *Float* objects *x* and *y* :\n\n.. list-table::\n    :widths: auto\n\n    * - **Operation**\n      - **Description**\n    * - ``log`` ( *x* )\n      - returns the logarithm of *x* as a *Float* object\n\nFloatVector\n***********\nThe type *FloatVector* must be a :ref:`SimpleVector-name` class with\n:ref:`elements of type Float<SimpleVector@Elements of Specified Type>` .\nThe routine :ref:`CheckSimpleVector-name` will generate an error message\nif this is not the case.\n\nLeqZero\n*******\nIncluding the file ``lu_solve.hpp`` defines the template function\n\n| |tab| ``template <class`` *Float* >\n| |tab| ``bool LeqZero`` < *Float* >( ``const`` *Float* & *x* )\n\nin the ``CppAD`` namespace.\nThis function returns true if *x* is less than or equal to zero\nand false otherwise.\nIt is used by ``LuSolve`` to avoid taking the log of\nzero (or a negative number if *Float* corresponds to real numbers).\nThis template function definition assumes that the operator\n``<=`` is defined for *Float* objects.\nIf this operator is not defined for your use of *Float* ,\nyou will need to specialize this template so that it works for your\nuse of ``LuSolve`` .\n\nComplex numbers do not have the operation or ``<=`` defined.\nIn addition, in the complex case,\none can take the log of a negative number.\nThe specializations\n\n| |tab| ``bool LeqZero< std::complex<float> >`` ( ``const std::complex<float> &`` *x* )\n| |tab| ``bool LeqZero< std::complex<double> >`` ( ``const std::complex<double> &`` *x* )\n\nare defined by including ``lu_solve.hpp`` .\nThese return true if *x* is zero and false otherwise.\n\nAbsGeq\n******\nIncluding the file ``lu_solve.hpp`` defines the template function\n\n| |tab| ``template <class`` *Float* >\n| |tab| ``bool AbsGeq`` < *Float* >( ``const`` *Float* & *x* , ``const`` *Float* & *y* )\n\nIf the type *Float* does not support the ``<=`` operation\nand it is not ``std::complex<float>`` or ``std::complex<double>`` ,\nsee the documentation for ``AbsGeq`` in :ref:`LuFactor<LuFactor@AbsGeq>` .\n{xrst_toc_hidden\n    example/utility/lu_solve.cpp\n    xrst/lu_solve_hpp.xrst\n}\nExample\n*******\nThe file\n:ref:`lu_solve.cpp-name`\ncontains an example and test of using this routine.\n\nSource\n******\nThe file :ref:`lu_solve.hpp-name` contains the\ncurrent source code that implements these specifications.\n\n{xrst_end LuSolve}\n--------------------------------------------------------------------------\n*/\n// BEGIN C++\n# include <complex>\n# include <vector>\n\n// link exp for float and double cases\n# include <cppad/base_require.hpp>\n\n# include <cppad/core/cppad_assert.hpp>\n# include <cppad/utility/check_simple_vector.hpp>\n# include <cppad/utility/check_numeric_type.hpp>\n# include <cppad/utility/lu_factor.hpp>\n# include <cppad/utility/lu_invert.hpp>\n\nnamespace CppAD { // BEGIN CppAD namespace\n\n// LeqZero\ntemplate <class Float>\nbool LeqZero(const Float &x)\n{   return x <= Float(0); }\ninline bool LeqZero( const std::complex<double> &x )\n{   return x == std::complex<double>(0); }\ninline bool LeqZero( const std::complex<float> &x )\n{   return x == std::complex<float>(0); }\n\n// LuSolve\ntemplate <class Float, class FloatVector>\nint LuSolve(\n    size_t             n      ,\n    size_t             m      ,\n    const FloatVector &A      ,\n    const FloatVector &B      ,\n    FloatVector       &X      ,\n    Float        &logdet      )\n{\n    // check numeric type specifications\n    CheckNumericType<Float>();\n\n    // check simple vector class specifications\n    CheckSimpleVector<Float, FloatVector>();\n\n    size_t        p;       // index of pivot element (diagonal of L)\n    int     signdet;       // sign of the determinant\n    Float     pivot;       // pivot element\n\n    // the value zero\n    const Float zero(0);\n\n    // pivot row and column order in the matrix\n    std::vector<size_t> ip(n);\n    std::vector<size_t> jp(n);\n\n    // -------------------------------------------------------\n    CPPAD_ASSERT_KNOWN(\n        size_t(A.size()) == n * n,\n        \"Error in LuSolve: A must have size equal to n * n\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t(B.size()) == n * m,\n        \"Error in LuSolve: B must have size equal to n * m\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t(X.size()) == n * m,\n        \"Error in LuSolve: X must have size equal to n * m\"\n    );\n    // -------------------------------------------------------\n\n    // copy A so that it does not change\n    FloatVector Lu(A);\n\n    // copy B so that it does not change\n    X = B;\n\n    // Lu factor the matrix A\n    signdet = LuFactor(ip, jp, Lu);\n\n    // compute the log of the determinant\n    logdet  = Float(0);\n    for(p = 0; p < n; p++)\n    {   // pivot using the max absolute element\n        pivot   = Lu[ ip[p] * n + jp[p] ];\n\n        // check for determinant equal to zero\n        if( pivot == zero )\n        {   // abort the mission\n            logdet = Float(0);\n            return   0;\n        }\n\n        // update the determinant\n        if( LeqZero ( pivot ) )\n        {   logdet += log( - pivot );\n            signdet = - signdet;\n        }\n        else\n            logdet += log( pivot );\n\n    }\n\n    // solve the linear equations\n    LuInvert(ip, jp, Lu, X);\n\n    // return the sign factor for the determinant\n    return signdet;\n}\n} // END CppAD namespace\n// END C++\n# endif\n"
  },
  {
    "path": "include/cppad/utility/memory_leak.hpp",
    "content": "# ifndef CPPAD_UTILITY_MEMORY_LEAK_HPP\n# define CPPAD_UTILITY_MEMORY_LEAK_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin memory_leak app}\n\nMemory Leak Detection\n#####################\n\nDeprecated 2012-04-06\n*********************\nThis routine has been deprecated.\nYou should instead use the routine :ref:`ta_free_all-name` .\n\nSyntax\n******\n| # ``include <cppad/utility/memory_leak.hpp>``\n| ``flag`` = ``memory_leak`` ()\n| *flag* = *memory_leak* ( *add_static* )\n\nPurpose\n*******\nThis routine checks that the are no memory leaks\ncaused by improper use of :ref:`thread_alloc-name` memory allocator.\nThe deprecated memory allocator :ref:`track_new_del-name` is also checked.\nMemory errors in the deprecated :ref:`omp_alloc-name` allocator are\nreported as being in ``thread_alloc`` .\n\nthread\n******\nIt is assumed that :ref:`in_parallel()<ta_in_parallel-name>` is false\nand :ref:`thread_num<ta_thread_num-name>` is zero when\n``memory_leak`` is called.\n\nadd_static\n**********\nThis argument has prototype\n\n    ``size_t`` *add_static*\n\nand its default value is zero.\nStatic variables hold onto memory forever.\nIf the argument *add_static* is present (and non-zero),\n``memory_leak`` adds this amount of memory to the\n:ref:`inuse<ta_inuse-name>` sum that corresponds to\nstatic variables in the program.\nA call with *add_static* should be make after\na routine that has static variables which\nuse :ref:`get_memory<ta_get_memory-name>` to allocate memory.\nThe value of *add_static* should be the difference of\n\n    ``thread_alloc::inuse`` (0)\n\nbefore and after the call.\nSince multiple statics may be allocated in different places in the program,\nit is expected that there will be multiple calls\nthat use this option.\n\nflag\n****\nThe return value *flag* has prototype\n\n    ``bool`` *flag*\n\nIf *add_static* is non-zero,\nthe return value for ``memory_leak`` is false.\nOtherwise, the return value for ``memory_leak`` should be false\n(indicating that the only allocated memory corresponds to static variables).\n\ninuse\n*****\nIt is assumed that, when ``memory_leak`` is called,\nthere should not be any memory\n:ref:`inuse<ta_inuse-name>` or :ref:`omp_inuse-name` for any thread\n(except for inuse memory corresponding to static variables).\nIf there is, a message is printed and ``memory_leak`` returns false.\n\navailable\n*********\nIt is assumed that, when ``memory_leak`` is called,\nthere should not be any memory\n:ref:`available<ta_available-name>` or :ref:`omp_available-name` for any thread;\ni.e., it all has been returned to the system.\nIf there is memory still available for any thread,\n``memory_leak`` returns false.\n\nTRACK_COUNT\n***********\nIt is assumed that, when ``memory_leak`` is called,\n:ref:`track_new_del@TrackCount` will return a zero value.\nIf it returns a non-zero value,\n``memory_leak`` returns false.\n\nError Message\n*************\nIf this is the first call to ``memory_leak`` , no message is printed.\nOtherwise, if it returns true, an error message is printed\nto standard output describing the memory leak that was detected.\n\n{xrst_end memory_leak}\n*/\n# include <iostream>\n# include <cppad/local/define.hpp>\n# include <cppad/utility/omp_alloc.hpp>\n# include <cppad/utility/thread_alloc.hpp>\n# include <cppad/utility/track_new_del.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\n\\file memory_leak.hpp\nFile that implements a memory check at end of a CppAD program\n*/\n\n/*!\nFunction that checks\nallocator thread_alloc for misuse that results in memory leaks.\nDeprecated routines in track_new_del.hpp and omp_alloc.hpp are also checked.\n\n\\param add_static [in]\nThe amount specified by add_static is added to the amount\nof memory that is expected to be used by thread zero for static variables.\n\n\\return\nIf add_static is non-zero, the return value is false.\nOtherwise, if one of the following errors is detected,\nthe return value is true:\n\n\\li\nThread zero does not have the expected amount of inuse memory\n(for static variables).\n\\li\nA thread, other than thread zero, has any inuse memory.\n\\li\nAny thread has available memory.\n\n\\par\nIf an error is detected, diagnostic information is printed to standard\noutput.\n*/\ninline bool memory_leak(size_t add_static = 0)\n{   // CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL not necessary given asserts below\n    static size_t thread_zero_static_inuse     = 0;\n    using std::cout;\n    using std::endl;\n    using CppAD::thread_alloc;\n    using CppAD::omp_alloc;\n    // --------------------------------------------------------------------\n    CPPAD_ASSERT_KNOWN(\n        ! thread_alloc::in_parallel(),\n        \"memory_leak: in_parallel() is true.\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        thread_alloc::thread_num() == 0,\n        \"memory_leak: thread_num() is not zero.\"\n    );\n    if( add_static != 0 )\n    {   thread_zero_static_inuse += add_static;\n        return false;\n    }\n    bool leak                 = false;\n    size_t thread             = 0;\n\n    // check that memory in use for thread zero corresponds to statics\n    size_t num_bytes = thread_alloc::inuse(thread);\n    if( num_bytes != thread_zero_static_inuse )\n    {   leak = true;\n        cout << \"thread zero: static inuse = \" << thread_zero_static_inuse;\n        cout << \", current inuse(0)= \" << num_bytes << endl;\n    }\n    // check that no memory is currently available for this thread\n    num_bytes = thread_alloc::available(thread);\n    if( num_bytes != 0 )\n    {   leak = true;\n        cout << \"thread zero: available    = \";\n        cout << num_bytes << endl;\n    }\n    for(thread = 1; thread < CPPAD_MAX_NUM_THREADS; thread++)\n    {\n        // check that no memory is currently in use for this thread\n        num_bytes = thread_alloc::inuse(thread);\n        if( num_bytes != 0 )\n        {   leak = true;\n            cout << \"thread \" << thread << \": inuse(thread) = \";\n            cout << num_bytes << endl;\n        }\n        // check that no memory is currently available for this thread\n        num_bytes = thread_alloc::available(thread);\n        if( num_bytes != 0 )\n        {   leak = true;\n            cout << \"thread \" << thread << \": available(thread) = \";\n            cout << num_bytes << endl;\n        }\n    }\n    // ----------------------------------------------------------------------\n    // check track_new_del\n    if( CPPAD_TRACK_COUNT() != 0 )\n    {   leak = true;\n        CppAD::TrackElement::Print();\n    }\n    return leak;\n}\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/utility/nan.hpp",
    "content": "# ifndef CPPAD_UTILITY_NAN_HPP\n# define CPPAD_UTILITY_NAN_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin nan}\n{xrst_spell\n    hasnan\n    isnan\n}\n\nObtain Nan or Determine if a Value is Nan\n#########################################\n\nSyntax\n******\n| # ``include <cppad/utility/nan.hpp>``\n| *b* = ``CppAD::isnan`` ( *s* )\n| *b* = ``hasnan`` ( *v* )\n\nPurpose\n*******\nCheck for the value not a number ``nan`` .\nThe IEEE standard specifies that a floating point value *a*\nis ``nan`` if and only if the following returns true\n\n    *a* != *a*\n\nstd::isnan\n**********\nSome compilers; e.g. Visual Studio, result in an ambiguous error\nbetween ``CppAD::isnan`` and ``std::isnan`` unless you include the ``CppAD``\nbefore ``isnan`` (even when inside the CppAD namespace).\n\nInclude\n*******\nThe file ``cppad/utility/nan.hpp``\nis included by ``cppad/cppad.hpp``\nbut it can also be included separately with out the rest of\nthe ``CppAD`` routines.\n\nMacros\n======\nSome C++ compilers use preprocessor symbols called ``nan``\nand ``isnan`` .\nThese preprocessor symbols will no longer be defined after\nthis file is included.\n\nisnan\n*****\nThis routine determines if a scalar value is ``nan`` .\n\ns\n=\nThe argument *s* has prototype\n\n    ``const`` *Scalar* *s*\n\nb\n=\nThe return value *b* has prototype\n\n    ``bool`` *b*\n\nIt is true if the value *s* is ``nan`` .\n\nhasnan\n******\nThis routine determines if a\n:ref:`SimpleVector-name` has an element that is ``nan`` .\n\nv\n=\nThe argument *v* has prototype\n\n    ``const`` *Vector* & *v*\n\n(see :ref:`nan@Vector` for the definition of *Vector* ).\n\nb\n=\nThe return value *b* has prototype\n\n    ``bool`` *b*\n\nIt is true if the vector *v* has a ``nan`` .\n\nnan(zero)\n*********\n\nDeprecated 2015-10-04\n=====================\nThis routine has been deprecated, use CppAD numeric limits\n:ref:`numeric_limits@quiet_NaN` in its place.\n\nSyntax\n======\n\n    *s* = ``nan`` ( *z* )\n\nz\n=\nThe argument *z* has prototype\n\n    ``const`` *Scalar* & *z*\n\nand its value is zero\n(see :ref:`nan@Scalar` for the definition of *Scalar* ).\n\ns\n=\nThe return value *s* has prototype\n\n    *Scalar* *s*\n\nIt is the value ``nan`` for this floating point type.\n\nScalar\n******\nThe type *Scalar* must support the following operations;\n\n.. list-table::\n    :widths: auto\n\n    * - **Operation**\n      - **Description**\n    * - *a* / *b*\n      - division operator (returns a *Scalar* object)\n    * - *a* == *b*\n      - equality operator (returns a ``bool`` object)\n    * - *a* != *b*\n      - not equality operator (returns a ``bool`` object)\n\nNote that the division operator will be used with *a* and *b*\nequal to zero. For some types (e.g. ``int`` ) this may generate\nan exception. No attempt is made to catch any such exception.\n\nVector\n******\nThe type *Vector* must be a :ref:`SimpleVector-name` class with\nelements of type *Scalar* .\n{xrst_toc_hidden\n    example/utility/nan.cpp\n}\nExample\n*******\nThe file :ref:`nan.cpp-name`\ncontains an example and test of this routine.\n\n{xrst_end nan}\n*/\n\n# include <cstddef>\n# include <cppad/core/cppad_assert.hpp>\n\n/*\n# define nan There must be a define for every CppAD undef\n*/\n# ifdef nan\n# undef nan\n# endif\n\n/*\n# define isnan There must be a define for every CppAD undef\n*/\n# ifdef isnan\n# undef isnan\n# endif\n\nnamespace CppAD { // BEGIN CppAD namespace\n\ntemplate <class Scalar>\nbool isnan(const Scalar &s)\n{   return (s != s);\n}\n\ntemplate <class Vector>\nbool hasnan(const Vector &v)\n{\n    bool found_nan;\n    size_t i;\n    i   = v.size();\n    found_nan = false;\n    // on MS Visual Studio 2012, CppAD required in front of isnan ?\n    while(i--)\n        found_nan |= CppAD::isnan(v[i]);\n    return found_nan;\n}\n\ntemplate <class Scalar>\nScalar nan(const Scalar &zero)\n{   return zero / zero;\n}\n\n} // End CppAD namespace\n\n# endif\n"
  },
  {
    "path": "include/cppad/utility/near_equal.hpp",
    "content": "# ifndef CPPAD_UTILITY_NEAR_EQUAL_HPP\n# define CPPAD_UTILITY_NEAR_EQUAL_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin NearEqual}\n{xrst_spell\n    cout\n    endl\n}\n\nDetermine if Two Values Are Nearly Equal\n########################################\n\nSyntax\n******\n| # ``include <cppad/utility/near_equal.hpp>``\n| *b* = ``NearEqual`` ( *x* , *y* , *r* , *a* )\n\nPurpose\n*******\nReturns true,\nif *x* and *y* are nearly equal,\nand false otherwise.\n\nx\n*\nThe argument *x*\nhas one of the following possible prototypes\n\n| |tab| ``const`` *Type* & *x* ,\n| |tab| ``const std::complex<`` *Type* > & *x* ,\n\ny\n*\nThe argument *y*\nhas one of the following possible prototypes\n\n| |tab| ``const`` *Type* & *y* ,\n| |tab| ``const std::complex<`` *Type* > & *y* ,\n\nr\n*\nThe relative error criteria *r* has prototype\n\n    ``const`` *Type* & *r*\n\nIt must be greater than or equal to zero.\nThe relative error condition is defined as:\n\n.. math::\n\n    | x - y | \\leq r ( |x| + |y| )\n\na\n*\nThe absolute error criteria *a* has prototype\n\n    ``const`` *Type* & *a*\n\nIt must be greater than or equal to zero.\nThe absolute error condition is defined as:\n\n.. math::\n\n    | x - y | \\leq a\n\nb\n*\nThe return value *b* has prototype\n\n    ``bool`` *b*\n\nIf either *x* or *y* is infinite or not a number,\nthe return value is false.\nOtherwise, if either the relative or absolute error\ncondition (defined above) is satisfied, the return value is true.\nOtherwise, the return value is false.\n\nType\n****\nThe type *Type* must be a\n:ref:`NumericType-name` .\nThe routine :ref:`CheckNumericType-name` will generate\nan error message if this is not the case.\nIn addition, the following operations must be defined objects\n*a* and *b* of type *Type* :\n\n.. list-table::\n    :widths: auto\n\n    * - **Operation**\n      - **Description**\n    * - *a* <= *b*\n      - less that or equal operator (returns a ``bool`` object)\n\nInclude Files\n*************\nThe file ``cppad/utility/near_equal.hpp``\nis included by ``cppad/cppad.hpp``\nbut it can also be included separately with out the rest of\nthe ``CppAD`` routines.\n\nExample\n*******\n{xrst_toc_hidden\n    example/utility/near_equal.cpp\n}\nThe file :ref:`near_equal.cpp-name` contains an example\nand test of ``NearEqual`` .\nIt return true if it succeeds and false otherwise.\n\nExercise\n********\nCreate and run a program that contains the following code:\n::\n\n    using std::complex;\n    using std::cout;\n    using std::endl;\n\n    complex<double> one(1., 0), i(0., 1);\n    complex<double> x = one / i;\n    complex<double> y = - i;\n    double          r = 1e-12;\n    double          a = 0;\n    bool           ok = CppAD::NearEqual(x, y, r, a);\n    if( ok )\n    cout << \"Ok\"    << endl;\n    else\n    cout << \"Error\" << endl;\n\n{xrst_end NearEqual}\n\n*/\n\n# include <limits>\n# include <complex>\n# include <cppad/core/cppad_assert.hpp>\n# include <cppad/utility/check_numeric_type.hpp>\n\nnamespace CppAD { // Begin CppAD namespace\n\n// determine if both x and y are finite values\ntemplate <class Type>\nbool near_equal_isfinite(const Type &x , const Type &y)\n{   Type infinity = Type( std::numeric_limits<double>::infinity() );\n\n    // handle bug where some compilers return true for nan == nan\n    bool xNan = x != x;\n    bool yNan = y != y;\n\n    // infinite cases\n    bool xInf = (x == infinity   || x == - infinity);\n    bool yInf = (x == infinity   || x == - infinity);\n\n    return ! (xNan | yNan | xInf | yInf);\n}\n\ntemplate <class Type>\nbool NearEqual(const Type &x, const Type &y, const Type &r, const Type &a)\n{\n    CheckNumericType<Type>();\n    Type zero(0);\n\n    CPPAD_ASSERT_KNOWN(\n        zero <= r,\n        \"Error in NearEqual: relative error is less than zero\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        zero <= a,\n        \"Error in NearEqual: absolute error is less than zero\"\n    );\n\n    // check for special cases\n    if( ! CppAD::near_equal_isfinite(x, y) )\n        return false;\n\n    Type ax = x;\n    if( ax <= zero )\n        ax = - ax;\n\n    Type ay = y;\n    if( ay <= zero )\n        ay = - ay;\n\n    Type ad = x - y;\n    if( ad <= zero )\n        ad = - ad;\n\n    if( ad <= a )\n        return true;\n\n    if( ad <= r * (ax + ay) )\n        return true;\n\n    return false;\n}\n\ntemplate <class Type>\nbool NearEqual(\n    const std::complex<Type> &x ,\n    const std::complex<Type> &y ,\n    const              Type  &r ,\n    const              Type  & a )\n{\n    CheckNumericType<Type>();\n# ifndef NDEBUG\n    Type zero(0);\n# endif\n\n    CPPAD_ASSERT_KNOWN(\n        zero <= r,\n        \"Error in NearEqual: relative error is less than zero\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        zero <= a,\n        \"Error in NearEqual: absolute error is less than zero\"\n    );\n\n    // check for special cases\n    if( ! CppAD::near_equal_isfinite(x.real(), x.imag()) )\n        return false;\n    if( ! CppAD::near_equal_isfinite(y.real(), y.imag()) )\n        return false;\n\n    std::complex<Type> d = x - y;\n\n    Type ad = std::abs(d);\n    if( ad <= a )\n        return true;\n\n    Type ax = std::abs(x);\n    Type ay = std::abs(y);\n    if( ad <= r * (ax + ay) )\n        return true;\n\n    return false;\n}\n\ntemplate <class Type>\nbool NearEqual(\n    const std::complex<Type> &x ,\n    const              Type  &y ,\n    const              Type  &r ,\n    const              Type  & a )\n{\n    return NearEqual(x, std::complex<Type>(y, Type(0)), r, a);\n}\n\ntemplate <class Type>\nbool NearEqual(\n    const              Type  &x ,\n    const std::complex<Type> &y ,\n    const              Type  &r ,\n    const              Type  & a )\n{\n    return NearEqual(std::complex<Type>(x, Type(0)), y, r, a);\n}\n\n} // END CppAD namespace\n\n# endif\n"
  },
  {
    "path": "include/cppad/utility/ode_err_control.hpp",
    "content": "# ifndef CPPAD_UTILITY_ODE_ERR_CONTROL_HPP\n# define CPPAD_UTILITY_ODE_ERR_CONTROL_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin OdeErrControl}\n{xrst_spell\n    eabs\n    eb\n    ef\n    erel\n    nstep\n    scur\n    smax\n    smin\n    tf\n    xa\n    xb\n    xf\n}\n\nAn Error Controller for ODE Solvers\n###################################\n\nSyntax\n******\n| # ``include <cppad/utility/ode_err_control.hpp>``\n| *xf* = ``OdeErrControl`` ( *method* , *ti* , *tf* , *xi* ,\n| |tab| ``smin`` , ``smax`` , ``scur`` , ``eabs`` , ``erel`` , ``ef`` , ``maxabs`` , ``nstep``  )\n\nDescription\n***********\nLet :math:`\\B{R}` denote the real numbers\nand let :math:`F : \\B{R} \\times \\B{R}^n \\rightarrow \\B{R}^n` be a smooth function.\nWe define :math:`X : [ti , tf] \\rightarrow \\B{R}^n` by\nthe following initial value problem:\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        X(ti)  & = & xi    \\\\\n        X'(t)  & = & F[t , X(t)]\n    \\end{eqnarray}\n\nThe routine ``OdeErrControl`` can be used to adjust the step size\nused an arbitrary integration methods in order to be as fast as possible\nand still with in a requested error bound.\n\nInclude\n*******\nThe file ``cppad/utility/ode_err_control.hpp`` is included by\n``cppad/cppad.hpp``\nbut it can also be included separately with out the rest of\nthe ``CppAD`` routines.\n\nNotation\n********\nThe template parameter types :ref:`OdeErrControl@Scalar` and\n:ref:`OdeErrControl@Vector` are documented below.\n\nxf\n**\nThe return value *xf* has the prototype\n\n    *Vector* *xf*\n\n(see description of :ref:`OdeErrControl@Vector` below).\nand the size of *xf* is equal to *n* .\nIf *xf* contains not a number :ref:`nan-name` ,\nsee the discussion of :ref:`step<OdeErrControl@Method@Nan>` .\n\nMethod\n******\nThe class *Method*\nand the object *method* satisfy the following syntax\n\n    *Method* & *method*\n\nThe object *method* must support ``step`` and\n``order`` member functions defined below:\n\nstep\n====\nThe syntax\n\n    *method* . ``step`` ( *ta* , *tb* , *xa* , *xb* , *eb* )\n\nexecutes one step of the integration method.\n\n    *ta*\n\nThe argument *ta* has prototype\n\n    ``const`` *Scalar* & *ta*\n\nIt specifies the initial time for this step in the\nODE integration.\n(see description of :ref:`OdeErrControl@Scalar` below).\n\n    *tb*\n\nThe argument *tb* has prototype\n\n    ``const`` *Scalar* & *tb*\n\nIt specifies the final time for this step in the\nODE integration.\n\n    *xa*\n\nThe argument *xa* has prototype\n\n    ``const`` *Vector* & *xa*\n\nand size *n* .\nIt specifies the value of :math:`X(ta)`.\n(see description of :ref:`OdeErrControl@Vector` below).\n\n    *xb*\n\nThe argument value *xb* has prototype\n\n    *Vector* & *xb*\n\nand size *n* .\nThe input value of its elements does not matter.\nOn output,\nit contains the approximation for :math:`X(tb)` that the method obtains.\n\n    *eb*\n\nThe argument value *eb* has prototype\n\n    *Vector* & *eb*\n\nand size *n* .\nThe input value of its elements does not matter.\nOn output,\nit contains an estimate for the error in the approximation *xb* .\nIt is assumed (locally) that the error bound in this approximation\nnearly equal to :math:`K (tb - ta)^m`\nwhere *K* is a fixed constant and *m*\nis the corresponding argument to ``CodeControl`` .\n\nNan\n===\nIf any element of the vector *eb* or *xb* are\nnot a number ``nan`` ,\nthe current step is considered to large.\nIf this happens with the current step size equal to *smin* ,\n``OdeErrControl`` returns with *xf* and *ef* as vectors\nof ``nan`` .\n\norder\n=====\nIf *m* is ``size_t`` ,\nthe object *method* must also support the following syntax\n\n    *m* = *method* . ``order`` ()\n\nThe return value *m* is the order of the error estimate;\ni.e., there is a constant K such that if :math:`ti \\leq ta \\leq tb \\leq tf`,\n\n.. math::\n\n    | eb(tb) | \\leq K | tb - ta |^m\n\nwhere *ta* , *tb* , and *eb* are as in\n*method* . ``step`` ( *ta* , *tb* , *xa* , *xb* , *eb* )\n\nti\n**\nThe argument *ti* has prototype\n\n    ``const`` *Scalar* & *ti*\n\nIt specifies the initial time for the integration of\nthe differential equation.\n\ntf\n**\nThe argument *tf* has prototype\n\n    ``const`` *Scalar* & *tf*\n\nIt specifies the final time for the integration of\nthe differential equation.\n\nxi\n**\nThe argument *xi* has prototype\n\n    ``const`` *Vector* & *xi*\n\nand size *n* .\nIt specifies value of :math:`X(ti)`.\n\nsmin\n****\nThe argument *smin* has prototype\n\n    ``const`` *Scalar* & *smin*\n\nThe step size during a call to *method* is defined as\nthe corresponding value of :math:`tb - ta`.\nIf :math:`tf - ti \\leq smin`,\nthe integration will be done in one step of size *tf - ti* .\nOtherwise,\nthe minimum value of *tb - ta* will be :math:`smin`\nexcept for the last two calls to *method* where it may be\nas small as :math:`smin / 2`.\n\nsmax\n****\nThe argument *smax* has prototype\n\n    ``const`` *Scalar* & *smax*\n\nIt specifies the maximum step size to use during the integration;\ni.e., the maximum value for :math:`tb - ta` in a call to *method* .\nThe value of *smax* must be greater than or equal *smin* .\n\nscur\n****\nThe argument *scur* has prototype\n\n    *Scalar* & *scur*\n\nThe value of *scur* is the suggested next step size,\nbased on error criteria, to try in the next call to *method* .\nOn input it corresponds to the first call to *method* ,\nin this call to ``OdeErrControl`` (where :math:`ta = ti`).\nOn output it corresponds to the next call to *method* ,\nin a subsequent call to ``OdeErrControl`` (where *ta* = *tf* ).\n\neabs\n****\nThe argument *eabs* has prototype\n\n    ``const`` *Vector* & *eabs*\n\nand size *n* .\nEach of the elements of *eabs* must be\ngreater than or equal zero.\nIt specifies a bound for the absolute\nerror in the return value *xf* as an approximation for :math:`X(tf)`.\n(see the\n:ref:`OdeErrControl@Error Criteria Discussion`\nbelow).\n\nerel\n****\nThe argument *erel* has prototype\n\n    ``const`` *Scalar* & *erel*\n\nand is greater than or equal zero.\nIt specifies a bound for the relative\nerror in the return value *xf* as an approximation for :math:`X(tf)`\n(see the\n:ref:`OdeErrControl@Error Criteria Discussion`\nbelow).\n\nef\n**\nThe argument value *ef* has prototype\n\n    *Vector* & *ef*\n\nand size *n* .\nThe input value of its elements does not matter.\nOn output,\nit contains an estimated bound for the\nabsolute error in the approximation *xf* ; i.e.,\n\n.. math::\n\n    ef_i > | X( tf )_i - xf_i |\n\nIf on output *ef* contains not a number ``nan`` ,\nsee the discussion of :ref:`step<OdeErrControl@Method@Nan>` .\n\nmaxabs\n******\nThe argument *maxabs* is optional in the call to ``OdeErrControl`` .\nIf it is present, it has the prototype\n\n    *Vector* & *maxabs*\n\nand size *n* .\nThe input value of its elements does not matter.\nOn output,\nit contains an estimate for the\nmaximum absolute value of :math:`X(t)`; i.e.,\n\n.. math::\n\n    maxabs[i] \\approx \\max \\left\\{\n        | X( t )_i | \\; : \\;  t \\in [ti, tf]\n    \\right\\}\n\nnstep\n*****\nThe argument *nstep* is optional in the call to ``OdeErrControl`` .\nIf it is present, it has the prototype\n\n    *size_t* & *nstep*\n\nIts input value does not matter and its output value\nis the number of calls to *method* . ``step``\nused by ``OdeErrControl`` .\n\nError Criteria Discussion\n*************************\nThe relative error criteria *erel* and\nabsolute error criteria *eabs* are enforced during each step of the\nintegration of the ordinary differential equations.\nIn addition, they are inversely scaled by the step size so that\nthe total error bound is less than the sum of the error bounds.\nTo be specific, if :math:`\\tilde{X} (t)` is the approximate solution\nat time :math:`t`,\n*ta* is the initial step time,\nand *tb* is the final step time,\n\n.. math::\n\n    \\left| \\tilde{X} (tb)_j  - X (tb)_j \\right|\n    \\leq\n    \\frac{tf - ti}{tb - ta}\n    \\left[ eabs[j] + erel \\;  | \\tilde{X} (tb)_j | \\right]\n\nIf :math:`X(tb)_j` is near zero for some :math:`tb \\in [ti , tf]`,\nand one uses an absolute error criteria :math:`eabs[j]` of zero,\nthe error criteria above will force ``OdeErrControl``\nto use step sizes equal to\n:ref:`OdeErrControl@smin`\nfor steps ending near :math:`tb`.\nIn this case, the error relative to *maxabs* can be judged after\n``OdeErrControl`` returns.\nIf *ef* is to large relative to *maxabs* ,\n``OdeErrControl`` can be called again\nwith a smaller value of *smin* .\n\nScalar\n******\nThe type *Scalar* must satisfy the conditions\nfor a :ref:`NumericType-name` .\nThe routine :ref:`CheckNumericType-name` will generate an error message\nif this is not the case.\nIn addition, the following operations must be defined for\n*Scalar* objects *a* and *b* :\n\n.. list-table::\n    :widths: auto\n\n    * - **Operation**\n      - **Description**\n    * - *a* <= *b*\n      - returns true (false) if *a* is less than or equal\n         (greater than) *b* .\n    * - *a* == *b*\n      - returns true (false) if *a* is equal to *b* .\n    * - ``log`` ( *a* )\n      - returns a *Scalar* equal to the logarithm of *a*\n    * - ``exp`` ( *a* )\n      - returns a *Scalar* equal to the exponential of *a*\n\nVector\n******\nThe type *Vector* must be a :ref:`SimpleVector-name` class with\n:ref:`elements of type Scalar<SimpleVector@Elements of Specified Type>` .\nThe routine :ref:`CheckSimpleVector-name` will generate an error message\nif this is not the case.\n\nExample\n*******\n{xrst_toc_hidden\n    example/utility/ode_err_control.cpp\n    example/utility/ode_err_maxabs.cpp\n}\nThe files\n:ref:`ode_err_control.cpp-name`\nand\n:ref:`ode_err_maxabs.cpp-name`\ncontain examples and tests of using this routine.\nThey return true if they succeed and false otherwise.\n\nTheory\n******\nLet :math:`e(s)` be the error as a function of the\nstep size :math:`s` and suppose that there is a constant\n:math:`K` such that :math:`e(s) = K s^m`.\nLet :math:`a` be our error bound.\nGiven the value of :math:`e(s)`, a step of size :math:`\\lambda s`\nwould be ok provided that\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        a  & \\geq & e( \\lambda s ) (tf - ti) / ( \\lambda s ) \\\\\n        a  & \\geq & K \\lambda^m s^m (tf - ti) / ( \\lambda s ) \\\\\n        a  & \\geq & \\lambda^{m-1} s^{m-1} (tf - ti) e(s) / s^m \\\\\n        a  & \\geq & \\lambda^{m-1} (tf - ti) e(s) / s           \\\\\n        \\lambda^{m-1} & \\leq & \\frac{a}{e(s)} \\frac{s}{tf - ti}\n    \\end{eqnarray}\n\nThus if the right hand side of the last inequality is greater\nthan or equal to one, the step of size :math:`s` is ok.\n\nSource Code\n***********\nThe source code for this routine is in the file\n``cppad/ode_err_control.hpp`` .\n\n{xrst_end OdeErrControl}\n--------------------------------------------------------------------------\n*/\n\n// link exp and log for float and double\n# include <cppad/base_require.hpp>\n\n# include <cppad/core/cppad_assert.hpp>\n# include <cppad/utility/check_simple_vector.hpp>\n# include <cppad/utility/nan.hpp>\n\nnamespace CppAD { // Begin CppAD namespace\n\ntemplate <class Scalar, class Vector, class Method>\nVector OdeErrControl(\n    Method          &method,\n    const Scalar    &ti    ,\n    const Scalar    &tf    ,\n    const Vector    &xi    ,\n    const Scalar    &smin  ,\n    const Scalar    &smax  ,\n    Scalar          &scur  ,\n    const Vector    &eabs  ,\n    const Scalar    &erel  ,\n    Vector          &ef    ,\n    Vector          &maxabs,\n    size_t          &nstep )\n{\n    // check simple vector class specifications\n    CheckSimpleVector<Scalar, Vector>();\n\n    size_t n = size_t(xi.size());\n\n    CPPAD_ASSERT_KNOWN(\n        smin <= smax,\n        \"Error in OdeErrControl: smin > smax\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t(eabs.size()) == n,\n        \"Error in OdeErrControl: size of eabs is not equal to n\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t(maxabs.size()) == n,\n        \"Error in OdeErrControl: size of maxabs is not equal to n\"\n    );\n    size_t m = method.order();\n    CPPAD_ASSERT_KNOWN(\n        m > 1,\n        \"Error in OdeErrControl: m is less than or equal one\"\n    );\n\n    bool    ok;\n    bool    minimum_step;\n    size_t  i;\n    Vector xa(n), xb(n), eb(n), nan_vec(n);\n\n    // initialization\n    Scalar zero(0.0);\n    Scalar one(1.0);\n    Scalar two(2.0);\n    Scalar three(3.0);\n    Scalar m1(double(m-1));\n    Scalar ta = ti;\n    for(i = 0; i < n; i++)\n    {   nan_vec[i] = nan(zero);\n        ef[i]      = zero;\n        xa[i]      = xi[i];\n        if( zero <= xi[i] )\n            maxabs[i] = xi[i];\n        else\n            maxabs[i] = - xi[i];\n\n    }\n    nstep = 0;\n\n    Scalar tb, step, lambda, axbi, a, r, root;\n    while( ! (ta == tf) )\n    {   // start with value suggested by error criteria\n        step = scur;\n\n        // check maximum\n        if( smax <= step )\n            step = smax;\n\n        // check minimum\n        minimum_step = step <= smin;\n        if( minimum_step )\n            step = smin;\n\n        // check if near the end\n        if( tf <= ta + step * three / two )\n            tb = tf;\n        else\n            tb = ta + step;\n\n        // try using this step size\n        nstep++;\n        method.step(ta, tb, xa, xb, eb);\n        step = tb - ta;\n\n        // check if this steps error estimate is ok\n        ok = ! (hasnan(xb) || hasnan(eb));\n        if( (! ok) && minimum_step )\n        {   ef = nan_vec;\n            return nan_vec;\n        }\n\n        // compute value of lambda for this step\n        lambda = Scalar(10) * scur / step;\n        for(i = 0; i < n; i++)\n        {   if( zero <= xb[i] )\n                axbi = xb[i];\n            else\n                axbi = - xb[i];\n            a    = eabs[i] + erel * axbi;\n            if( ! (eb[i] == zero) )\n            {   r = ( a / eb[i] ) * step / (tf - ti);\n                root = exp( log(r) / m1 );\n                if( root <= lambda )\n                    lambda = root;\n            }\n        }\n        if( ok && ( one <= lambda || step <= smin * three / two) )\n        {   // this step is within error limits or\n            // close to the minimum size\n            ta = tb;\n            for(i = 0; i < n; i++)\n            {   xa[i] = xb[i];\n                ef[i] = ef[i] + eb[i];\n                if( zero <= xb[i] )\n                    axbi = xb[i];\n                else\n                    axbi = - xb[i];\n                if( axbi > maxabs[i] )\n                    maxabs[i] = axbi;\n            }\n        }\n        if( ! ok )\n        {   // decrease step an see if method will work this time\n            scur = step / two;\n        }\n        else if( ! (ta == tf) )\n        {   // step suggested by the error criteria is not used\n            // on the last step because it may be very small.\n            scur = lambda * step / two;\n        }\n    }\n    return xa;\n}\n\ntemplate <class Scalar, class Vector, class Method>\nVector OdeErrControl(\n    Method          &method,\n    const Scalar    &ti    ,\n    const Scalar    &tf    ,\n    const Vector    &xi    ,\n    const Scalar    &smin  ,\n    const Scalar    &smax  ,\n    Scalar          &scur  ,\n    const Vector    &eabs  ,\n    const Scalar    &erel  ,\n    Vector          &ef    )\n{   Vector maxabs(xi.size());\n    size_t nstep;\n    return OdeErrControl(\n    method, ti, tf, xi, smin, smax, scur, eabs, erel, ef, maxabs, nstep\n    );\n}\n\ntemplate <class Scalar, class Vector, class Method>\nVector OdeErrControl(\n    Method          &method,\n    const Scalar    &ti    ,\n    const Scalar    &tf    ,\n    const Vector    &xi    ,\n    const Scalar    &smin  ,\n    const Scalar    &smax  ,\n    Scalar          &scur  ,\n    const Vector    &eabs  ,\n    const Scalar    &erel  ,\n    Vector          &ef    ,\n    Vector          &maxabs)\n{   size_t nstep;\n    return OdeErrControl(\n    method, ti, tf, xi, smin, smax, scur, eabs, erel, ef, maxabs, nstep\n    );\n}\n\n} // End CppAD namespace\n\n# endif\n"
  },
  {
    "path": "include/cppad/utility/ode_gear.hpp",
    "content": "# ifndef CPPAD_UTILITY_ODE_GEAR_HPP\n# define CPPAD_UTILITY_ODE_GEAR_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin OdeGear}\n{xrst_spell\n    dep\n    pp\n    test test\n    vol\n}\n\nAn Arbitrary Order Gear Method\n##############################\n\nSyntax\n******\n| # ``include <cppad/utility/ode_gear.hpp>``\n| ``OdeGear`` ( *F* , *m* , *n* , *T* , *X* , *e* )\n\nPurpose\n*******\nThis routine applies\n:ref:`OdeGear@Gear's Method`\nto solve an explicit set of ordinary differential equations.\nWe are given\n:math:`f : \\B{R} \\times \\B{R}^n \\rightarrow \\B{R}^n` be a smooth function.\nThis routine solves the following initial value problem\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        x( t_{m-1} )  & = & x^0    \\\\\n        x^\\prime (t)  & = & f[t , x(t)]\n    \\end{eqnarray}\n\nfor the value of :math:`x( t_m )`.\nIf your set of  ordinary differential equations are not stiff\nan explicit method may be better (perhaps :ref:`Runge45-name` .)\n\nInclude\n*******\nThe file ``cppad/utility/ode_gear.hpp``\nis included by ``cppad/cppad.hpp``\nbut it can also be included separately with out the rest of\nthe ``CppAD`` routines.\n\nFun\n***\nThe class *Fun*\nand the object *F* satisfy the prototype\n\n    *Fun* & *F*\n\nThis must support the following set of calls\n\n| |tab| *F* . ``Ode`` ( *t* , *x* , *f* )\n| |tab| *F* . ``Ode_dep`` ( *t* , *x* , *f_x* )\n\nt\n=\nThe argument *t* has prototype\n\n    ``const`` *Scalar* & *t*\n\n(see description of :ref:`OdeGear@Scalar` below).\n\nx\n=\nThe argument *x* has prototype\n\n    ``const`` *Vector* & *x*\n\nand has size *n*\n(see description of :ref:`OdeGear@Vector` below).\n\nf\n=\nThe argument *f* to *F* . ``Ode`` has prototype\n\n    *Vector* & *f*\n\nOn input and output, *f* is a vector of size *n*\nand the input values of the elements of *f* do not matter.\nOn output,\n*f* is set equal to :math:`f(t, x)`\n(see *f* ( *t* , *x* ) in :ref:`OdeGear@Purpose` ).\n\nf_x\n===\nThe argument *f_x* has prototype\n\n    *Vector* & *f_x*\n\nOn input and output, *f_x* is a vector of size :math:`n * n`\nand the input values of the elements of *f_x* do not matter.\nOn output,\n\n.. math::\n\n    f\\_x [i * n + j] = \\partial_{x(j)} f_i ( t , x )\n\nWarning\n=======\nThe arguments *f* , and *f_x*\nmust have a call by reference in their prototypes; i.e.,\ndo not forget the ``&`` in the prototype for\n*f* and *f_x* .\n\nm\n*\nThe argument *m* has prototype\n\n    ``size_t`` *m*\n\nIt specifies the order (highest power of :math:`t`)\nused to represent the function :math:`x(t)` in the multi-step method.\nUpon return from ``OdeGear`` ,\nthe *i*-th component of the polynomial is defined by\n\n.. math::\n\n    p_i ( t_j ) = X[ j * n + i ]\n\nfor :math:`j = 0 , \\ldots , m` (where :math:`0 \\leq i < n`).\nThe value of :math:`m` must be greater than or equal one.\n\nn\n*\nThe argument *n* has prototype\n\n    ``size_t`` *n*\n\nIt specifies the range space dimension of the\nvector valued function :math:`x(t)`.\n\nT\n*\nThe argument *T* has prototype\n\n    ``const`` *Vector* & *T*\n\nand size greater than or equal to :math:`m+1`.\nFor :math:`j = 0 , \\ldots m`, :math:`T[j]` is the time\ncorresponding to time corresponding\nto a previous point in the multi-step method.\nThe value :math:`T[m]` is the time\nof the next point in the multi-step method.\nThe array :math:`T` must be monotone increasing; i.e.,\n:math:`T[j] < T[j+1]`.\nAbove and below we often use the shorthand :math:`t_j` for :math:`T[j]`.\n\nX\n*\nThe argument *X* has the prototype\n\n    *Vector* & *X*\n\nand size greater than or equal to :math:`(m+1) * n`.\nOn input to ``OdeGear`` ,\nfor :math:`j = 0 , \\ldots , m-1`, and\n:math:`i = 0 , \\ldots , n-1`\n\n.. math::\n\n    X[ j * n + i ] = x_i ( t_j )\n\nUpon return from ``OdeGear`` ,\nfor :math:`i = 0 , \\ldots , n-1`\n\n.. math::\n\n    X[ m * n + i ] \\approx x_i ( t_m )\n\ne\n*\nThe vector *e* is an approximate error bound for the result; i.e.,\n\n.. math::\n\n    e[i] \\geq | X[ m * n + i ] - x_i ( t_m ) |\n\nThe order of this approximation is one less than the order of\nthe solution; i.e.,\n\n.. math::\n\n    e = O ( h^m )\n\nwhere :math:`h` is the maximum of :math:`t_{j+1} - t_j`.\n\nScalar\n******\nThe type *Scalar* must satisfy the conditions\nfor a :ref:`NumericType-name` .\nThe routine :ref:`CheckNumericType-name` will generate an error message\nif this is not the case.\nIn addition, the following operations must be defined for\n*Scalar* objects *a* and *b* :\n\n.. list-table::\n    :widths: auto\n\n    * - **Operation**\n      - **Description**\n    * - *a* < *b*\n      - less than operator (returns a ``bool`` object)\n\nVector\n******\nThe type *Vector* must be a :ref:`SimpleVector-name` class with\n:ref:`elements of type Scalar<SimpleVector@Elements of Specified Type>` .\nThe routine :ref:`CheckSimpleVector-name` will generate an error message\nif this is not the case.\n\nExample\n*******\n{xrst_toc_hidden\n    example/utility/ode_gear.cpp\n}\nThe file\n:ref:`ode_gear.cpp-name`\ncontains an example and test a test of using this routine.\n\nSource Code\n***********\nThe source code for this routine is in the file\n``cppad/ode_gear.hpp`` .\n\nTheory\n******\nFor this discussion we use the shorthand :math:`x_j`\nfor the value :math:`x ( t_j ) \\in \\B{R}^n` which is not to be confused\nwith :math:`x_i (t) \\in \\B{R}` in the notation above.\nThe interpolating polynomial :math:`p(t)` is given by\n\n.. math::\n\n    p(t) =\n    \\sum_{j=0}^m\n    x_j\n    \\frac{\n        \\prod_{i \\neq j} ( t - t_i )\n    }{\n        \\prod_{i \\neq j} ( t_j - t_i )\n    }\n\nThe derivative :math:`p^\\prime (t)` is given by\n\n.. math::\n\n    p^\\prime (t) =\n    \\sum_{j=0}^m\n    x_j\n    \\frac{\n        \\sum_{i \\neq j} \\prod_{k \\neq i,j} ( t - t_k )\n    }{\n        \\prod_{k \\neq j} ( t_j - t_k )\n    }\n\nEvaluating the derivative at the point :math:`t_\\ell` we have\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    p^\\prime ( t_\\ell ) & = &\n    x_\\ell\n    \\frac{\n        \\sum_{i \\neq \\ell} \\prod_{k \\neq i,\\ell} ( t_\\ell - t_k )\n    }{\n        \\prod_{k \\neq \\ell} ( t_\\ell - t_k )\n    }\n    +\n    \\sum_{j \\neq \\ell}\n    x_j\n    \\frac{\n        \\sum_{i \\neq j} \\prod_{k \\neq i,j} ( t_\\ell - t_k )\n    }{\n        \\prod_{k \\neq j} ( t_j - t_k )\n    }\n    \\\\\n    & = &\n    x_\\ell\n    \\sum_{i \\neq \\ell}\n    \\frac{ 1 }{ t_\\ell - t_i }\n    +\n    \\sum_{j \\neq \\ell}\n    x_j\n    \\frac{\n        \\prod_{k \\neq \\ell,j} ( t_\\ell - t_k )\n    }{\n        \\prod_{k \\neq j} ( t_j - t_k )\n    }\n    \\\\\n    & = &\n    x_\\ell\n    \\sum_{k \\neq \\ell} ( t_\\ell - t_k )^{-1}\n    +\n    \\sum_{j \\neq \\ell}\n    x_j\n    ( t_j - t_\\ell )^{-1}\n    \\prod_{k \\neq \\ell ,j} ( t_\\ell - t_k ) / ( t_j - t_k )\n    \\end{eqnarray}\n\nWe define the vector :math:`\\alpha \\in \\B{R}^{m+1}` by\n\n.. math::\n\n    \\alpha_j = \\left\\{ \\begin{array}{ll}\n    \\sum_{k \\neq m} ( t_m - t_k )^{-1}\n        & {\\rm if} \\; j = m\n    \\\\\n    ( t_j - t_m )^{-1}\n    \\prod_{k \\neq m,j} ( t_m - t_k ) / ( t_j - t_k )\n        & {\\rm otherwise}\n    \\end{array} \\right.\n\nIt follows that\n\n.. math::\n\n    p^\\prime ( t_m ) = \\alpha_0 x_0 + \\cdots + \\alpha_m x_m\n\nGear's method determines :math:`x_m` by solving the following\nnonlinear equation\n\n.. math::\n\n    f( t_m , x_m ) = \\alpha_0 x_0 + \\cdots + \\alpha_m x_m\n\nNewton's method for solving this equation determines iterates,\nwhich we denote by :math:`x_m^k`, by solving the following affine\napproximation of the equation above\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    f( t_m , x_m^{k-1} ) + \\partial_x f( t_m , x_m^{k-1} ) ( x_m^k - x_m^{k-1} )\n    & = &\n    \\alpha_0 x_0^k + \\alpha_1 x_1 + \\cdots + \\alpha_m x_m\n    \\\\\n    \\left[ \\alpha_m I - \\partial_x f( t_m , x_m^{k-1} ) \\right]  x_m\n    & = &\n    \\left[\n    f( t_m , x_m^{k-1} ) - \\partial_x f( t_m , x_m^{k-1} ) x_m^{k-1}\n    - \\alpha_0 x_0 - \\cdots - \\alpha_{m-1} x_{m-1}\n    \\right]\n    \\end{eqnarray}\n\nIn order to initialize Newton's method; i.e. choose :math:`x_m^0`\nwe define the vector :math:`\\beta \\in \\B{R}^{m+1}` by\n\n.. math::\n\n    \\beta_j = \\left\\{ \\begin{array}{ll}\n    \\sum_{k \\neq m-1} ( t_{m-1} - t_k )^{-1}\n        & {\\rm if} \\; j = m-1\n    \\\\\n    ( t_j - t_{m-1} )^{-1}\n    \\prod_{k \\neq m-1,j} ( t_{m-1} - t_k ) / ( t_j - t_k )\n        & {\\rm otherwise}\n    \\end{array} \\right.\n\nIt follows that\n\n.. math::\n\n    p^\\prime ( t_{m-1} ) = \\beta_0 x_0 + \\cdots + \\beta_m x_m\n\nWe solve the following approximation of the equation above to determine\n:math:`x_m^0`:\n\n.. math::\n\n    f( t_{m-1} , x_{m-1} ) =\n    \\beta_0 x_0 + \\cdots + \\beta_{m-1} x_{m-1} + \\beta_m x_m^0\n\nGear's Method\n*************\nC. W. Gear,\n*Simultaneous Numerical Solution of Differential-Algebraic Equations* ,\nIEEE Transactions on Circuit Theory,\nvol. 18, no. 1, pp. 89-95, Jan. 1971.\n\n{xrst_end OdeGear}\n--------------------------------------------------------------------------\n*/\n\n# include <cstddef>\n# include <cppad/core/cppad_assert.hpp>\n# include <cppad/utility/check_simple_vector.hpp>\n# include <cppad/utility/check_numeric_type.hpp>\n# include <cppad/utility/vector.hpp>\n# include <cppad/utility/lu_factor.hpp>\n# include <cppad/utility/lu_invert.hpp>\n\nnamespace CppAD { // BEGIN CppAD namespace\n\ntemplate <class Vector, class Fun>\nvoid OdeGear(\n    Fun          &F  ,\n    size_t        m  ,\n    size_t        n  ,\n    const Vector &T  ,\n    Vector       &X  ,\n    Vector       &e  )\n{\n    // temporary indices\n    size_t i, j, k;\n\n    typedef typename Vector::value_type Scalar;\n\n    // check numeric type specifications\n    CheckNumericType<Scalar>();\n\n    // check simple vector class specifications\n    CheckSimpleVector<Scalar, Vector>();\n\n    CPPAD_ASSERT_KNOWN(\n        m >= 1,\n        \"OdeGear: m is less than one\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        n > 0,\n        \"OdeGear: n is equal to zero\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t(T.size()) >= (m+1),\n        \"OdeGear: size of T is not greater than or equal (m+1)\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t(X.size()) >= (m+1) * n,\n        \"OdeGear: size of X is not greater than or equal (m+1) * n\"\n    );\n    for(j = 0; j < m; j++) CPPAD_ASSERT_KNOWN(\n        T[j] < T[j+1],\n        \"OdeGear: the array T is not monotone increasing\"\n    );\n\n    // some constants\n    Scalar zero(0);\n    Scalar one(1);\n\n    // vectors required by method\n    Vector alpha(m + 1);\n    Vector beta(m + 1);\n    Vector f(n);\n    Vector f_x(n * n);\n    Vector x_m0(n);\n    Vector x_m(n);\n    Vector b(n);\n    Vector A(n * n);\n\n    // compute alpha[m]\n    alpha[m] = zero;\n    for(k = 0; k < m; k++)\n        alpha[m] += one / (T[m] - T[k]);\n\n    // compute beta[m-1]\n    beta[m-1] = one / (T[m-1] - T[m]);\n    for(k = 0; k < m-1; k++)\n        beta[m-1] += one / (T[m-1] - T[k]);\n\n\n    // compute other components of alpha\n    for(j = 0; j < m; j++)\n    {   // compute alpha[j]\n        alpha[j] = one / (T[j] - T[m]);\n        for(k = 0; k < m; k++)\n        {   if( k != j )\n            {   alpha[j] *= (T[m] - T[k]);\n                alpha[j] /= (T[j] - T[k]);\n            }\n        }\n    }\n\n    // compute other components of beta\n    for(j = 0; j <= m; j++)\n    {   if( j != m-1 )\n        {   // compute beta[j]\n            beta[j] = one / (T[j] - T[m-1]);\n            for(k = 0; k <= m; k++)\n            {   if( k != j && k != m-1 )\n                {   beta[j] *= (T[m-1] - T[k]);\n                    beta[j] /= (T[j] - T[k]);\n                }\n            }\n        }\n    }\n\n    // evaluate f(T[m-1], x_{m-1} )\n    for(i = 0; i < n; i++)\n        x_m[i] = X[(m-1) * n + i];\n    F.Ode(T[m-1], x_m, f);\n\n    // solve for x_m^0\n    for(i = 0; i < n; i++)\n    {   x_m[i] =  f[i];\n        for(j = 0; j < m; j++)\n            x_m[i] -= beta[j] * X[j * n + i];\n        x_m[i] /= beta[m];\n    }\n    x_m0 = x_m;\n\n    // evaluate partial w.r.t x of f(T[m], x_m^0)\n    F.Ode_dep(T[m], x_m, f_x);\n\n    // compute the matrix A = ( alpha[m] * I - f_x )\n    for(i = 0; i < n; i++)\n    {   for(j = 0; j < n; j++)\n            A[i * n + j]  = - f_x[i * n + j];\n        A[i * n + i] += alpha[m];\n    }\n\n    // LU factor (and overwrite) the matrix A\n    CppAD::vector<size_t> ip(n) , jp(n);\n# ifndef NDEBUG\n    int sign =\n# endif\n    LuFactor(ip, jp, A);\n    CPPAD_ASSERT_KNOWN(\n        sign != 0,\n        \"OdeGear: step size is to large\"\n    );\n\n    // Iterations of Newton's method\n    for(k = 0; k < 3; k++)\n    {\n        // only evaluate f( T[m] , x_m ) keep f_x during iteration\n        F.Ode(T[m], x_m, f);\n\n        // b = f + f_x x_m - alpha[0] x_0 - ... - alpha[m-1] x_{m-1}\n        for(i = 0; i < n; i++)\n        {   b[i]         = f[i];\n            for(j = 0; j < n; j++)\n                b[i]         -= f_x[i * n + j] * x_m[j];\n            for(j = 0; j < m; j++)\n                b[i] -= alpha[j] * X[ j * n + i ];\n        }\n        LuInvert(ip, jp, A, b);\n        x_m = b;\n    }\n\n    // return estimate for x( t[k] ) and the estimated error bound\n    for(i = 0; i < n; i++)\n    {   X[m * n + i] = x_m[i];\n        e[i]         = x_m[i] - x_m0[i];\n        if( e[i] < zero )\n            e[i] = - e[i];\n    }\n}\n\n} // End CppAD namespace\n\n# endif\n"
  },
  {
    "path": "include/cppad/utility/ode_gear_control.hpp",
    "content": "# ifndef CPPAD_UTILITY_ODE_GEAR_CONTROL_HPP\n# define CPPAD_UTILITY_ODE_GEAR_CONTROL_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin OdeGearControl}\n{xrst_spell\n    dep\n    eabs\n    ef\n    erel\n    maxabs\n    nstep\n    sini\n    smax\n    smin\n    test test\n    tf\n    xf\n}\n\nAn Error Controller for Gear's Ode Solvers\n##########################################\n\nSyntax\n******\n| # ``include <cppad/utility/ode_gear_control.hpp>``\n| *xf* = ``OdeGearControl`` ( *F* , *M* , *ti* , *tf* , *xi* ,\n| |tab| ``smin`` , ``smax`` , ``sini`` , ``eabs`` , ``erel`` , ``ef`` , ``maxabs`` , ``nstep``  )\n\nPurpose\n*******\nLet :math:`\\B{R}` denote the real numbers\nand let :math:`f : \\B{R} \\times \\B{R}^n \\rightarrow \\B{R}^n` be a smooth function.\nWe define :math:`X : [ti , tf] \\rightarrow \\B{R}^n` by\nthe following initial value problem:\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        X(ti)  & = & xi    \\\\\n        X'(t)  & = & f[t , X(t)]\n    \\end{eqnarray}\n\nThe routine :ref:`OdeGear-name` is a stiff multi-step method that\ncan be used to approximate the solution to this equation.\nThe routine ``OdeGearControl`` sets up this multi-step method\nand controls the error during such an approximation.\n\nInclude\n*******\nThe file ``cppad/utility/ode_gear_control.hpp``\nis included by ``cppad/cppad.hpp``\nbut it can also be included separately with out the rest of\nthe ``CppAD`` routines.\n\nNotation\n********\nThe template parameter types :ref:`OdeGearControl@Scalar` and\n:ref:`OdeGearControl@Vector` are documented below.\n\nxf\n**\nThe return value *xf* has the prototype\n\n    *Vector* *xf*\n\nand the size of *xf* is equal to *n*\n(see description of :ref:`OdeGear@Vector` below).\nIt is the approximation for :math:`X(tf)`.\n\nFun\n***\nThe class *Fun*\nand the object *F* satisfy the prototype\n\n    *Fun* & *F*\n\nThis must support the following set of calls\n\n| |tab| *F* . ``Ode`` ( *t* , *x* , *f* )\n| |tab| *F* . ``Ode_dep`` ( *t* , *x* , *f_x* )\n\nt\n=\nThe argument *t* has prototype\n\n    ``const`` *Scalar* & *t*\n\n(see description of :ref:`OdeGear@Scalar` below).\n\nx\n=\nThe argument *x* has prototype\n\n    ``const`` *Vector* & *x*\n\nand has size *N*\n(see description of :ref:`OdeGear@Vector` below).\n\nf\n=\nThe argument *f* to *F* . ``Ode`` has prototype\n\n    *Vector* & *f*\n\nOn input and output, *f* is a vector of size *N*\nand the input values of the elements of *f* do not matter.\nOn output,\n*f* is set equal to :math:`f(t, x)`\n(see *f* ( *t* , *x* ) in :ref:`OdeGear@Purpose` ).\n\nf_x\n===\nThe argument *f_x* has prototype\n\n    *Vector* & *f_x*\n\nOn input and output, *f_x* is a vector of size :math:`N * N`\nand the input values of the elements of *f_x* do not matter.\nOn output,\n\n.. math::\n\n    f\\_x [i * n + j] = \\partial_{x(j)} f_i ( t , x )\n\nWarning\n=======\nThe arguments *f* , and *f_x*\nmust have a call by reference in their prototypes; i.e.,\ndo not forget the ``&`` in the prototype for\n*f* and *f_x* .\n\nM\n*\nThe argument *M* has prototype\n\n    ``size_t`` *M*\n\nIt specifies the order of the multi-step method; i.e.,\nthe order of the approximating polynomial\n(after the initialization process).\nThe argument *M* must greater than or equal one.\n\nti\n**\nThe argument *ti* has prototype\n\n    ``const`` *Scalar* & *ti*\n\nIt specifies the initial time for the integration of\nthe differential equation.\n\ntf\n**\nThe argument *tf* has prototype\n\n    ``const`` *Scalar* & *tf*\n\nIt specifies the final time for the integration of\nthe differential equation.\n\nxi\n**\nThe argument *xi* has prototype\n\n    ``const`` *Vector* & *xi*\n\nand size *n* .\nIt specifies value of :math:`X(ti)`.\n\nsmin\n****\nThe argument *smin* has prototype\n\n    ``const`` *Scalar* & *smin*\n\nThe minimum value of :math:`T[M] -  T[M-1]` in a call to ``OdeGear``\nwill be :math:`smin` except for the last two calls where it may be\nas small as :math:`smin / 2`.\nThe value of *smin* must be less than or equal *smax* .\n\nsmax\n****\nThe argument *smax* has prototype\n\n    ``const`` *Scalar* & *smax*\n\nIt specifies the maximum step size to use during the integration;\ni.e., the maximum value for :math:`T[M] - T[M-1]`\nin a call to ``OdeGear`` .\n\nsini\n****\nThe argument *sini* has prototype\n\n    *Scalar* & *sini*\n\nThe value of *sini* is the minimum\nstep size to use during initialization of the multi-step method; i.e.,\nfor calls to ``OdeGear`` where :math:`m < M`.\nThe value of *sini* must be less than or equal *smax*\n(and can also be less than *smin* ).\n\neabs\n****\nThe argument *eabs* has prototype\n\n    ``const`` *Vector* & *eabs*\n\nand size *n* .\nEach of the elements of *eabs* must be\ngreater than or equal zero.\nIt specifies a bound for the absolute\nerror in the return value *xf* as an approximation for :math:`X(tf)`.\n(see the\n:ref:`OdeGearControl@Error Criteria Discussion`\nbelow).\n\nerel\n****\nThe argument *erel* has prototype\n\n    ``const`` *Scalar* & *erel*\n\nand is greater than or equal zero.\nIt specifies a bound for the relative\nerror in the return value *xf* as an approximation for :math:`X(tf)`\n(see the\n:ref:`OdeGearControl@Error Criteria Discussion`\nbelow).\n\nef\n**\nThe argument value *ef* has prototype\n\n    *Vector* & *ef*\n\nand size *n* .\nThe input value of its elements does not matter.\nOn output,\nit contains an estimated bound for the\nabsolute error in the approximation *xf* ; i.e.,\n\n.. math::\n\n    ef_i > | X( tf )_i - xf_i |\n\nmaxabs\n******\nThe argument *maxabs* is optional in the call to ``OdeGearControl`` .\nIf it is present, it has the prototype\n\n    *Vector* & *maxabs*\n\nand size *n* .\nThe input value of its elements does not matter.\nOn output,\nit contains an estimate for the\nmaximum absolute value of :math:`X(t)`; i.e.,\n\n.. math::\n\n    maxabs[i] \\approx \\max \\left\\{\n        | X( t )_i | \\; : \\;  t \\in [ti, tf]\n    \\right\\}\n\nnstep\n*****\nThe argument *nstep* has the prototype\n\n    *size_t* & *nstep*\n\nIts input value does not matter and its output value\nis the number of calls to :ref:`OdeGear-name`\nused by ``OdeGearControl`` .\n\nError Criteria Discussion\n*************************\nThe relative error criteria *erel* and\nabsolute error criteria *eabs* are enforced during each step of the\nintegration of the ordinary differential equations.\nIn addition, they are inversely scaled by the step size so that\nthe total error bound is less than the sum of the error bounds.\nTo be specific, if :math:`\\tilde{X} (t)` is the approximate solution\nat time :math:`t`,\n*ta* is the initial step time,\nand *tb* is the final step time,\n\n.. math::\n\n    \\left| \\tilde{X} (tb)_j  - X (tb)_j \\right|\n    \\leq\n    \\frac{tf - ti}{tb - ta}\n    \\left[ eabs[j] + erel \\;  | \\tilde{X} (tb)_j | \\right]\n\nIf :math:`X(tb)_j` is near zero for some :math:`tb \\in [ti , tf]`,\nand one uses an absolute error criteria :math:`eabs[j]` of zero,\nthe error criteria above will force ``OdeGearControl``\nto use step sizes equal to\n:ref:`OdeGearControl@smin`\nfor steps ending near :math:`tb`.\nIn this case, the error relative to *maxabs* can be judged after\n``OdeGearControl`` returns.\nIf *ef* is to large relative to *maxabs* ,\n``OdeGearControl`` can be called again\nwith a smaller value of *smin* .\n\nScalar\n******\nThe type *Scalar* must satisfy the conditions\nfor a :ref:`NumericType-name` .\nThe routine :ref:`CheckNumericType-name` will generate an error message\nif this is not the case.\nIn addition, the following operations must be defined for\n*Scalar* objects *a* and *b* :\n\n.. list-table::\n    :widths: auto\n\n    * - **Operation**\n      - **Description**\n    * - *a* <= *b*\n      - returns true (false) if *a* is less than or equal\n         (greater than) *b* .\n    * - *a* == *b*\n      - returns true (false) if *a* is equal to *b* .\n    * - ``log`` ( *a* )\n      - returns a *Scalar* equal to the logarithm of *a*\n    * - ``exp`` ( *a* )\n      - returns a *Scalar* equal to the exponential of *a*\n\nVector\n******\nThe type *Vector* must be a :ref:`SimpleVector-name` class with\n:ref:`elements of type Scalar<SimpleVector@Elements of Specified Type>` .\nThe routine :ref:`CheckSimpleVector-name` will generate an error message\nif this is not the case.\n\nExample\n*******\n{xrst_toc_hidden\n    example/utility/ode_gear_control.cpp\n}\nThe file\n:ref:`ode_gear_control.cpp-name`\ncontains an example and test a test of using this routine.\n\nTheory\n******\nLet :math:`e(s)` be the error as a function of the\nstep size :math:`s` and suppose that there is a constant\n:math:`K` such that :math:`e(s) = K s^m`.\nLet :math:`a` be our error bound.\nGiven the value of :math:`e(s)`, a step of size :math:`\\lambda s`\nwould be ok provided that\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        a  & \\geq & e( \\lambda s ) (tf - ti) / ( \\lambda s ) \\\\\n        a  & \\geq & K \\lambda^m s^m (tf - ti) / ( \\lambda s ) \\\\\n        a  & \\geq & \\lambda^{m-1} s^{m-1} (tf - ti) e(s) / s^m \\\\\n        a  & \\geq & \\lambda^{m-1} (tf - ti) e(s) / s           \\\\\n        \\lambda^{m-1} & \\leq & \\frac{a}{e(s)} \\frac{s}{tf - ti}\n    \\end{eqnarray}\n\nThus if the right hand side of the last inequality is greater\nthan or equal to one, the step of size :math:`s` is ok.\n\nSource Code\n***********\nThe source code for this routine is in the file\n``cppad/ode_gear_control.hpp`` .\n\n{xrst_end OdeGearControl}\n--------------------------------------------------------------------------\n*/\n\n// link exp and log for float and double\n# include <cppad/base_require.hpp>\n\n# include <cppad/utility/ode_gear.hpp>\n\nnamespace CppAD { // Begin CppAD namespace\n\ntemplate <class Scalar, class Vector, class Fun>\nVector OdeGearControl(\n    Fun             &F     ,\n    size_t           M     ,\n    const Scalar    &ti    ,\n    const Scalar    &tf    ,\n    const Vector    &xi    ,\n    const Scalar    &smin  ,\n    const Scalar    &smax  ,\n    Scalar          &sini  ,\n    const Vector    &eabs  ,\n    const Scalar    &erel  ,\n    Vector          &ef    ,\n    Vector          &maxabs,\n    size_t          &nstep )\n{\n    // check simple vector class specifications\n    CheckSimpleVector<Scalar, Vector>();\n\n    // dimension of the state space\n    size_t n = size_t(xi.size());\n\n    CPPAD_ASSERT_KNOWN(\n        M >= 1,\n        \"Error in OdeGearControl: M is less than one\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        smin <= smax,\n        \"Error in OdeGearControl: smin is greater than smax\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        sini <= smax,\n        \"Error in OdeGearControl: sini is greater than smax\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t(eabs.size()) == n,\n        \"Error in OdeGearControl: size of eabs is not equal to n\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        size_t(maxabs.size()) == n,\n        \"Error in OdeGearControl: size of maxabs is not equal to n\"\n    );\n\n    // some constants\n    const Scalar zero(0);\n    const Scalar one(1);\n    const Scalar one_plus( Scalar(3) / Scalar(2) );\n    const Scalar two(2);\n    const Scalar ten(10);\n\n    // temporary indices\n    size_t i, k;\n\n    // temporary Scalars\n    Scalar step, sprevious, lambda, axi, a, root, r;\n\n    // vectors of Scalars\n    Vector T  (M + 1);\n    Vector X( (M + 1) * n );\n    Vector e(n);\n    Vector xf(n);\n\n    // initial integer values\n    size_t m = 1;\n    nstep    = 0;\n\n    // initialize T\n    T[0] = ti;\n\n    // initialize X, ef, maxabs\n    for(i = 0; i < n; i++)\n    for(i = 0; i < n; i++)\n    {   X[i] = xi[i];\n        ef[i] = zero;\n        X[i]  = xi[i];\n        if( zero <= xi[i] )\n            maxabs[i] = xi[i];\n        else\n            maxabs[i] = - xi[i];\n\n    }\n\n    // initial step size\n    step = smin;\n\n    while( T[m-1] < tf )\n    {   sprevious = step;\n\n        // check maximum\n        if( smax <= step )\n            step = smax;\n\n        // check minimum\n        if( m < M )\n        {   if( step <= sini )\n                step = sini;\n        }\n        else\n            if( step <= smin )\n                step = smin;\n\n        // check if near the end\n        if( tf <= T[m-1] + one_plus * step )\n            T[m] = tf;\n        else\n            T[m] = T[m-1] + step;\n\n        // try using this step size\n        nstep++;\n        OdeGear(F, m, n, T, X, e);\n        step = T[m] - T[m-1];\n\n        // compute value of lambda for this step\n        lambda = Scalar(10) *  sprevious / step;\n        for(i = 0; i < n; i++)\n        {   axi = X[m * n + i];\n            if( axi <= zero )\n                axi = - axi;\n            a  = eabs[i] + erel * axi;\n            if( e[i] > zero )\n            {   if( m == 1 )\n                    root = (a / e[i]) / ten;\n                else\n                {   r = ( a / e[i] ) * step / (tf - ti);\n                    root = exp( log(r) / Scalar(m-1) );\n                }\n                if( root <= lambda )\n                    lambda = root;\n            }\n        }\n\n        bool advance;\n        if( m == M )\n            advance = one <= lambda || step <= one_plus * smin;\n        else\n            advance = one <= lambda || step <= one_plus * sini;\n\n\n        if( advance )\n        {   // accept the results of this time step\n            CPPAD_ASSERT_UNKNOWN( m <= M );\n            if( m == M )\n            {   // shift for next step\n                for(k = 0; k < m; k++)\n                {   T[k] = T[k+1];\n                    for(i = 0; i < n; i++)\n                        X[k*n + i] = X[(k+1)*n + i];\n                }\n            }\n            // update ef and maxabs\n            for(i = 0; i < n; i++)\n            {   ef[i] = ef[i] + e[i];\n                axi = X[m * n + i];\n                if( axi <= zero )\n                    axi = - axi;\n                if( axi > maxabs[i] )\n                    maxabs[i] = axi;\n            }\n            if( m != M )\n                m++;  // all we need do in this case\n        }\n\n        // new step suggested by error criteria\n        step = std::min(lambda , ten) * step / two;\n    }\n    for(i = 0; i < n; i++)\n        xf[i] = X[(m-1) * n + i];\n\n    return xf;\n}\n\n} // End CppAD namespace\n\n# endif\n"
  },
  {
    "path": "include/cppad/utility/omp_alloc.hpp",
    "content": "# ifndef CPPAD_UTILITY_OMP_ALLOC_HPP\n# define CPPAD_UTILITY_OMP_ALLOC_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/utility/thread_alloc.hpp>\n# ifdef _OPENMP\n# include <omp.h>\n# endif\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\nclass omp_alloc{\n// ============================================================================\npublic:\n/*\n{xrst_begin omp_max_num_threads app}\nSet and Get Maximum Number of Threads for omp_alloc Allocator\n#############################################################\n\nDeprecated 2011-08-31\n*********************\nUse the functions :ref:`thread_alloc::parallel_setup<ta_parallel_setup-name>`\nand :ref:`thread_alloc:num_threads<ta_num_threads-name>` instead.\n\nSyntax\n******\n| # ``include <cppad/utility/omp_alloc.hpp>``\n| ``omp_alloc::set_max_num_threads`` ( *number* )\n| *number* = ``omp_alloc::get_max_num_threads`` ()\n\nPurpose\n*******\nBy default there is only one thread and all execution is in sequential mode\n(not :ref:`parallel<omp_in_parallel-name>` ).\n\nnumber\n******\nThe argument and return value *number* has prototype\n\n    ``size_t`` *number*\n\nand must be greater than zero.\n\nset_max_num_threads\n*******************\nInforms :ref:`omp_alloc-name` of the maximum number of OpenMP threads.\n\nget_max_num_threads\n*******************\nReturns the valued used in the previous call to ``set_max_num_threads`` .\nIf there was no such previous call, the value one is returned\n(and only thread number zero can use :ref:`omp_alloc-name` ).\n\nRestrictions\n************\nThe function ``set_max_num_threads`` must be called before\nthe program enters :ref:`parallel<omp_in_parallel-name>` execution mode.\nIn addition, this function cannot be called while in parallel mode.\n\n{xrst_end omp_max_num_threads}\n*/\n    /*!\n    Inform omp_alloc of the maximum number of OpenMP threads and enable\n    parallel execution mode by initializing all statics in this file.\n\n    \\param number [in]\n    maximum number of OpenMP threads.\n    */\n    static void set_max_num_threads(size_t number)\n    {   thread_alloc::parallel_setup(\n            number, omp_alloc::in_parallel, omp_alloc::get_thread_num\n        );\n        thread_alloc::hold_memory(number > 1);\n    }\n    /*!\n    Get the current maximum number of OpenMP threads that omp_alloc can use.\n\n    \\return\n    maximum number of OpenMP threads.\n    */\n    static size_t get_max_num_threads(void)\n    {   return thread_alloc::num_threads(); }\n\n/* -----------------------------------------------------------------------\n{xrst_begin omp_in_parallel app}\n\nIs The Current Execution in OpenMP Parallel Mode\n################################################\n\nDeprecated 2011-08-31\n*********************\nUse the function :ref:`thread_alloc::in_parallel<ta_in_parallel-name>` instead.\n\nSyntax\n******\n\n    # ``include <cppad/utility/omp_alloc.hpp>``\n\n*flag* = ``omp_alloc::in_parallel`` ()\n\nPurpose\n*******\nSome of the :ref:`omp_alloc-name` allocation routines have different\nspecifications for parallel (not sequential) execution mode.\nThis routine enables you to determine if the current execution mode\nis sequential or parallel.\n\nflag\n****\nThe return value has prototype\n\n    ``bool`` *flag*\n\nIt is true if the current execution is in parallel mode\n(possibly multi-threaded) and false otherwise (sequential mode).\n\n{xrst_end omp_in_parallel}\n*/\n    /// Are we in a parallel execution state; i.e., is it possible that\n    /// other threads are currently executing.\n    static bool in_parallel(void)\n    {\n# ifdef _OPENMP\n        return omp_in_parallel() != 0;\n# else\n        return false;\n# endif\n    }\n\n/* -----------------------------------------------------------------------\n{xrst_begin omp_get_thread_num app}\n\nGet the Current OpenMP Thread Number\n####################################\n\nDeprecated 2011-08-31\n*********************\nUse the function :ref:`thread_alloc::thread_num<ta_thread_num-name>` instead.\n\nSyntax\n******\n\n    # ``include <cppad/utility/omp_alloc.hpp>``\n\n*thread* = ``omp_alloc::get_thread_num`` ()\n\nPurpose\n*******\nSome of the :ref:`omp_alloc-name` allocation routines have a thread number.\nThis routine enables you to determine the current thread.\n\nthread\n******\nThe return value *thread* has prototype\n\n    ``size_t`` *thread*\n\nand is the currently executing thread number.\nIf ``_OPENMP`` is not defined, *thread* is zero.\n\n{xrst_end omp_get_thread_num}\n*/\n    /// Get current OpenMP thread number (zero if _OpenMP not defined).\n    static size_t get_thread_num(void)\n    {\n# ifdef _OPENMP\n        size_t thread = static_cast<size_t>( omp_get_thread_num() );\n        return thread;\n# else\n        return 0;\n# endif\n    }\n/* -----------------------------------------------------------------------\n{xrst_begin omp_get_memory app}\n\nGet At Least A Specified Amount of Memory\n#########################################\n\nDeprecated 2011-08-31\n*********************\nUse the function :ref:`thread_alloc::get_memory<ta_get_memory-name>` instead.\n\nSyntax\n******\n\n    # ``include <cppad/utility/omp_alloc.hpp>``\n\n*v_ptr* = ``omp_alloc::get_memory`` ( *min_bytes* , *cap_bytes* )\n\nPurpose\n*******\nUse :ref:`omp_alloc-name` to obtain a minimum number of bytes of memory\n(for use by the :ref:`current thread<omp_get_thread_num-name>` ).\n\nmin_bytes\n*********\nThis argument has prototype\n\n    ``size_t`` *min_bytes*\n\nIt specifies the minimum number of bytes to allocate.\n\ncap_bytes\n*********\nThis argument has prototype\n\n    ``size_t&`` *cap_bytes*\n\nIt's input value does not matter.\nUpon return, it is the actual number of bytes (capacity)\nthat have been allocated for use,\n\n    *min_bytes* <= *cap_bytes*\n\nv_ptr\n*****\nThe return value *v_ptr* has prototype\n\n    ``void`` * *v_ptr*\n\nIt is the location where the *cap_bytes* of memory\nthat have been allocated for use begins.\n\nAllocation Speed\n****************\nThis allocation should be faster if the following conditions hold:\n\n#. The memory allocated by a previous call to ``get_memory``\n   is currently available for use.\n#. The current *min_bytes* is between\n   the previous *min_bytes* and previous *cap_bytes* .\n\n{xrst_end omp_get_memory}\n*/\n    /*!\n    Use omp_alloc to get a specified amount of memory.\n\n    If the memory allocated by a previous call to get_memory is now\n    available, and min_bytes is between its previous value\n    and the previous cap_bytes, this memory allocation will have\n    optimal speed. Otherwise, the memory allocation is more complicated and\n    may have to wait for other threads to complete an allocation.\n\n    \\param min_bytes [in]\n    The minimum number of bytes of memory to be obtained for use.\n\n    \\param cap_bytes [out]\n    The actual number of bytes of memory obtained for use.\n\n    \\return\n    pointer to the beginning of the memory allocated for use.\n    */\n    static void* get_memory(size_t min_bytes, size_t& cap_bytes)\n    {   return thread_alloc::get_memory(min_bytes, cap_bytes); }\n\n/* -----------------------------------------------------------------------\n{xrst_begin omp_return_memory app}\n\nReturn Memory to omp_alloc\n##########################\n\nDeprecated 2011-08-31\n*********************\nUse the function :ref:`thread_alloc::return_memory<ta_return_memory-name>` instead.\n\nSyntax\n******\n\n    # ``include <cppad/utility/omp_alloc.hpp>``\n\n``omp_alloc::return_memory`` ( *v_ptr* )\n\nPurpose\n*******\nIf :ref:`omp_max_num_threads-name` is one,\nthe memory is returned to the system.\nOtherwise, the memory is retained by :ref:`omp_alloc-name` for quick future use\nby the thread that allocated to memory.\n\nv_ptr\n*****\nThis argument has prototype\n\n    ``void`` * *v_ptr*\n\n.\nIt must be a pointer to memory that is currently in use; i.e.\nobtained by a previous call to :ref:`omp_get_memory-name` and not yet returned.\n\nThread\n******\nEither the :ref:`current thread<omp_get_thread_num-name>` must be the same as during\nthe corresponding call to :ref:`omp_get_memory-name` ,\nor the current execution mode must be sequential\n(not :ref:`parallel<omp_in_parallel-name>` ).\n\nNDEBUG\n******\nIf ``NDEBUG`` is defined, *v_ptr* is not checked (this is faster).\nOtherwise, a list of in use pointers is searched to make sure\nthat *v_ptr* is in the list.\n\n{xrst_end omp_return_memory}\n*/\n    /*!\n    Return memory that was obtained by get_memory.\n    If  <code>max_num_threads(0) == 1</code>,\n    the memory is returned to the system.\n    Otherwise, it is retained by omp_alloc and available for use by\n    get_memory for this thread.\n\n    \\param v_ptr [in]\n    Value of the pointer returned by get_memory and still in use.\n    After this call, this pointer will available (and not in use).\n\n    \\par\n    We must either be in sequential (not parallel) execution mode,\n    or the current thread must be the same as for the corresponding call\n    to get_memory.\n    */\n    static void return_memory(void* v_ptr)\n    {   thread_alloc::return_memory(v_ptr); }\n/* -----------------------------------------------------------------------\n{xrst_begin omp_free_available app}\n\nFree Memory Currently Available for Quick Use by a Thread\n#########################################################\n\nDeprecated 2011-08-31\n*********************\nUse the function :ref:`thread_alloc::free_available<ta_free_available-name>`\ninstead.\n\nSyntax\n******\n\n    # ``include <cppad/utility/omp_alloc.hpp>``\n\n``omp_alloc::free_available`` ( *thread* )\n\nPurpose\n*******\nFree memory, currently available for quick use by a specific thread,\nfor general future use.\n\nthread\n******\nThis argument has prototype\n\n    ``size_t`` *thread*\n\nEither :ref:`omp_get_thread_num-name` must be the same as *thread* ,\nor the current execution mode must be sequential\n(not :ref:`parallel<omp_in_parallel-name>` ).\n\n{xrst_end omp_free_available}\n*/\n    /*!\n    Return all the memory being held as available for a thread to the system.\n\n    \\param thread [in]\n    this thread that will no longer have any available memory after this call.\n    This must either be the thread currently executing, or we must be\n    in sequential (not parallel) execution mode.\n    */\n    static void free_available(size_t thread)\n    {   thread_alloc::free_available(thread); }\n/* -----------------------------------------------------------------------\n{xrst_begin omp_inuse app}\n\nAmount of Memory a Thread is Currently Using\n############################################\n\nDeprecated 2011-08-31\n*********************\n\nSyntax\n******\n\n    # ``include <cppad/utility/omp_alloc.hpp>``\n\n*num_bytes* = ``omp_alloc::inuse`` ( *thread* )\nUse the function :ref:`thread_alloc::inuse<ta_inuse-name>` instead.\n\nPurpose\n*******\nMemory being managed by :ref:`omp_alloc-name` has two states,\ncurrently in use by the specified thread,\nand quickly available for future use by the specified thread.\nThis function informs the program how much memory is in use.\n\nthread\n******\nThis argument has prototype\n\n    ``size_t`` *thread*\n\nEither :ref:`omp_get_thread_num-name` must be the same as *thread* ,\nor the current execution mode must be sequential\n(not :ref:`parallel<omp_in_parallel-name>` ).\n\nnum_bytes\n*********\nThe return value has prototype\n\n    ``size_t`` *num_bytes*\n\nIt is the number of bytes currently in use by the specified thread.\n\n{xrst_end omp_inuse}\n*/\n    /*!\n    Determine the amount of memory that is currently inuse.\n\n    \\param thread [in]\n    Thread for which we are determining the amount of memory\n    (must be < CPPAD_MAX_NUM_THREADS).\n    During parallel execution, this must be the thread\n    that is currently executing.\n\n    \\return\n    The amount of memory in bytes.\n    */\n    static size_t inuse(size_t thread)\n    {   return thread_alloc::inuse(thread); }\n/* -----------------------------------------------------------------------\n{xrst_begin omp_available app}\n\nAmount of Memory Available for Quick Use by a Thread\n####################################################\n\nDeprecated 2011-08-31\n*********************\nUse the function :ref:`thread_alloc::available<ta_available-name>` instead.\n\nSyntax\n******\n\n    # ``include <cppad/utility/omp_alloc.hpp>``\n\n*num_bytes* = ``omp_alloc::available`` ( *thread* )\n\nPurpose\n*******\nMemory being managed by :ref:`omp_alloc-name` has two states,\ncurrently in use by the specified thread,\nand quickly available for future use by the specified thread.\nThis function informs the program how much memory is available.\n\nthread\n******\nThis argument has prototype\n\n    ``size_t`` *thread*\n\nEither :ref:`omp_get_thread_num-name` must be the same as *thread* ,\nor the current execution mode must be sequential\n(not :ref:`parallel<omp_in_parallel-name>` ).\n\nnum_bytes\n*********\nThe return value has prototype\n\n    ``size_t`` *num_bytes*\n\nIt is the number of bytes currently available for use by the specified thread.\n\n{xrst_end omp_available}\n*/\n    /*!\n    Determine the amount of memory that is currently available for use.\n\n    \\copydetails inuse\n    */\n    static size_t available(size_t thread)\n    {   return thread_alloc::available(thread); }\n/* -----------------------------------------------------------------------\n{xrst_begin omp_create_array app}\n\nAllocate Memory and Create A Raw Array\n######################################\n\nDeprecated 2011-08-31\n*********************\nUse the function :ref:`thread_alloc::create_array<ta_create_array-name>` instead.\n\nSyntax\n******\n\n    # ``include <cppad/utility/omp_alloc.hpp>``\n\n*array* = ``omp_alloc::create_array<`` *Type* >( *size_min* , *size_out* ) .\n\nPurpose\n*******\nCreate a new raw array using :ref:`omp_alloc-name` a fast memory allocator\nthat works well in a multi-threading OpenMP environment.\n\nType\n****\nThe type of the elements of the array.\n\nsize_min\n********\nThis argument has prototype\n\n    ``size_t`` *size_min*\n\nThis is the minimum number of elements that there can be\nin the resulting *array* .\n\nsize_out\n********\nThis argument has prototype\n\n    ``size_t&`` *size_out*\n\nThe input value of this argument does not matter.\nUpon return, it is the actual number of elements\nin *array*\n( *size_min* <= *size_out* ).\n\narray\n*****\nThe return value *array* has prototype\n\n    *Type* * *array*\n\nIt is array with *size_out* elements.\nThe default constructor for *Type* is used to initialize the\nelements of *array* .\nNote that :ref:`omp_delete_array-name`\nshould be used to destroy the array when it is no longer needed.\n\nDelta\n*****\nThe amount of memory :ref:`omp_inuse-name` by the current thread,\nwill increase *delta* where\n\n    ``sizeof`` ( *Type* ) * ( *size_out* + 1) > *delta* >= ``sizeof`` ( *Type* ) * *size_out*\n\nThe :ref:`omp_available-name` memory will decrease by *delta* ,\n(and the allocation will be faster)\nif a previous allocation with *size_min* between its current value\nand *size_out* is available.\n\n{xrst_end omp_create_array}\n*/\n    /*!\n    Use omp_alloc to Create a Raw Array.\n\n    \\tparam Type\n    The type of the elements of the array.\n\n    \\param size_min [in]\n    The minimum number of elements in the array.\n\n    \\param size_out [out]\n    The actual number of elements in the array.\n\n    \\return\n    pointer to the first element of the array.\n    The default constructor is used to initialize\n    all the elements of the array.\n\n    \\par\n    The extra_ field, in the omp_alloc node before the return value,\n    is set to size_out.\n    */\n    template <class Type>\n    static Type* create_array(size_t size_min, size_t& size_out)\n    {   return thread_alloc::create_array<Type>(size_min, size_out); }\n/* -----------------------------------------------------------------------\n{xrst_begin omp_delete_array app}\n\nReturn A Raw Array to The Available Memory for a Thread\n#######################################################\n\nDeprecated 2011-08-31\n*********************\nUse the function :ref:`thread_alloc::delete_array<ta_delete_array-name>` instead.\n\nSyntax\n******\n\n    # ``include <cppad/utility/omp_alloc.hpp>``\n\n``omp_alloc::delete_array`` ( *array* ) .\n\nPurpose\n*******\nReturns memory corresponding to a raw array\n(create by :ref:`omp_create_array-name` ) to the\n:ref:`omp_available-name` memory pool for the current thread.\n\nType\n****\nThe type of the elements of the array.\n\narray\n*****\nThe argument *array* has prototype\n\n    *Type* * *array*\n\nIt is a value returned by :ref:`omp_create_array-name` and not yet deleted.\nThe *Type* destructor is called for each element in the array.\n\nThread\n******\nThe :ref:`current thread<omp_get_thread_num-name>` must be the\nsame as when :ref:`omp_create_array-name` returned the value *array* .\nThere is an exception to this rule:\nwhen the current execution mode is sequential\n(not :ref:`parallel<omp_in_parallel-name>` ) the current thread number does not matter.\n\nDelta\n*****\nThe amount of memory :ref:`omp_inuse-name` will decrease by *delta* ,\nand the :ref:`omp_available-name` memory will increase by *delta* ,\nwhere :ref:`omp_create_array@Delta`\nis the same as for the corresponding call to ``create_array`` .\n\n{xrst_end omp_delete_array}\n*/\n    /*!\n    Return Memory Used for a Raw Array to the Available Pool.\n\n    \\tparam Type\n    The type of the elements of the array.\n\n    \\param array [in]\n    A value returned by create_array that has not yet been deleted.\n    The Type destructor is used to destroy each of the elements\n    of the array.\n\n    \\par\n    During parallel execution, the current thread must be the same\n    as during the corresponding call to create_array.\n    */\n    template <class Type>\n    static void delete_array(Type* array)\n    {   thread_alloc::delete_array(array); }\n};\n/* --------------------------------------------------------------------------\n{xrst_begin omp_efficient app}\n\nCheck If A Memory Allocation is Efficient for Another Use\n#########################################################\n\nRemoved\n*******\nThis function has been removed because speed tests seem to indicate\nit is just as fast, or faster, to free and then reallocate the memory.\n\nSyntax\n******\n\n    # ``include <cppad/utility/omp_alloc.hpp>``\n\n*flag* = ``omp_alloc::efficient`` ( *v_ptr* , *num_bytes* )\n\nPurpose\n*******\nCheck if memory that is currently in use is an efficient\nallocation for a specified number of bytes.\n\nv_ptr\n*****\nThis argument has prototype\n\n    ``const void`` * *v_ptr*\n\n.\nIt must be a pointer to memory that is currently in use; i.e.\nobtained by a previous call to :ref:`omp_get_memory-name` and not yet returned.\n\nnum_bytes\n*********\nThis argument has prototype\n\n    ``size_t`` *num_bytes*\n\nIt specifies the number of bytes of the memory allocated by *v_ptr*\nthat we want to use.\n\nflag\n****\nThe return value has prototype\n\n    ``bool`` *flag*\n\nIt is true,\na call to ``get_memory`` with\n:ref:`omp_get_memory@min_bytes`\nequal to *num_bytes* would result in a value for\n:ref:`omp_get_memory@cap_bytes` that is the same as when ``v_ptr``\nwas returned by ``get_memory`` ; i.e.,\n*v_ptr* is an efficient memory block for *num_bytes*\nbytes of information.\n\nThread\n******\nEither the :ref:`current thread<omp_get_thread_num-name>` must be the same as during\nthe corresponding call to :ref:`omp_get_memory-name` ,\nor the current execution mode must be sequential\n(not :ref:`parallel<omp_in_parallel-name>` ).\n\nNDEBUG\n******\nIf ``NDEBUG`` is defined, *v_ptr* is not checked (this is faster).\nOtherwise, a list of in use pointers is searched to make sure\nthat *v_ptr* is in the list.\n\n{xrst_end omp_efficient}\n---------------------------------------------------------------------------\n{xrst_begin old_max_num_threads app}\nSet Maximum Number of Threads for omp_alloc Allocator\n#####################################################\n\nRemoved\n*******\nThis function has been removed from the CppAD API.\nUse the function :ref:`thread_alloc::parallel_setup<ta_parallel_setup-name>`\nin its place.\n\nSyntax\n******\n\n    # ``include <cppad/utility/omp_alloc.hpp>``\n\n``omp_alloc::max_num_threads`` ( *number* )\n\nPurpose\n*******\nBy default there is only one thread and all execution is in sequential mode\n(not :ref:`parallel<omp_in_parallel-name>` ).\n\nnumber\n******\nThe argument *number* has prototype\n\n    ``size_t`` *number*\n\nIt must be greater than zero and specifies the maximum number of\nOpenMP threads that will be active at one time.\n\nRestrictions\n************\nThis function must be called before the program enters\n:ref:`parallel<omp_in_parallel-name>` execution mode.\n\n{xrst_end old_max_num_threads}\n-------------------------------------------------------------------------------\n*/\n} // END_CPPAD_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/utility/poly.hpp",
    "content": "# ifndef CPPAD_UTILITY_POLY_HPP\n# define CPPAD_UTILITY_POLY_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin Poly}\n\nEvaluate a Polynomial or its Derivative\n#######################################\n\nSyntax\n******\n| # ``include <cppad/utility/poly.hpp>``\n| *p* = ``Poly`` ( *k* , *a* , *z* )\n\nDescription\n***********\nComputes the *k*-th derivative of the polynomial\n\n.. math::\n\n    P(z) = a_0 + a_1 z^1 + \\cdots + a_d z^d\n\nIf *k* is equal to zero, the return value is :math:`P(z)`.\n\nInclude\n*******\nThe file ``cppad/utility/poly.hpp``\nis included by ``cppad/cppad.hpp``\nbut it can also be included separately with out the rest of\nthe ``CppAD`` routines.\nIncluding this file defines\n``Poly`` within the ``CppAD`` namespace.\n\nk\n*\nThe argument *k* has prototype\n\n    ``size_t`` *k*\n\nIt specifies the order of the derivative to calculate.\n\na\n*\nThe argument *a* has prototype\n\n    ``const`` *Vector* & *a*\n\n(see :ref:`Poly@Vector` below).\nIt specifies the vector corresponding to the polynomial :math:`P(z)`.\n\nz\n*\nThe argument *z* has prototype\n\n    ``const`` *Type* & *z*\n\n(see *Type* below).\nIt specifies the point at which to evaluate the polynomial\n\np\n*\nThe result *p*  has prototype\n\n    *Type* *p*\n\n(see :ref:`Poly@Type` below)\nand it is equal to the *k*-th derivative of :math:`P(z)`; i.e.,\n\n.. math::\n\n    p = \\frac{k !}{0 !} a_k\n      + \\frac{(k+1) !}{1 !} a_{k+1} z^1\n      + \\ldots\n      + \\frac{d !}{(d - k) !} a_d z^{d - k}\n\nIf :math:`k > d`, *p* = *Type* (0) .\n\nType\n****\nThe type *Type* is determined by the argument *z* .\nIt is assumed that\nmultiplication and addition of *Type* objects\nare commutative.\n\nOperations\n==========\nThe following operations must be supported where\n*x* and *y* are objects of type *Type*\nand *i* is an ``int`` :\n\n.. list-table::\n    :widths: auto\n\n    * - *x* = *i*\n      - assignment\n    * - *x* = *y*\n      - assignment\n    * - *x* \\\\* = *y*\n      - multiplication compound assignment\n    * - *x* += *y*\n      - addition compound assignment\n\nVector\n******\nThe type *Vector* must be a :ref:`SimpleVector-name` class with\n:ref:`elements of type<SimpleVector@Elements of Specified Type>`\n*Type* .\nThe routine :ref:`CheckSimpleVector-name` will generate an error message\nif this is not the case.\n\nOperation Sequence\n******************\nThe *Type* operation sequence used to calculate *p* is\n:ref:`glossary@Operation@Independent`\nof *z* and the elements of *a*\n(it does depend on the size of the vector *a* ).\n{xrst_toc_hidden\n    example/utility/poly.cpp\n    xrst/poly_hpp.xrst\n}\n\nExample\n*******\nThe file\n:ref:`poly.cpp-name`\ncontains an example and test of this routine.\n\nSource\n******\nThe file :ref:`poly.hpp-name` contains the\ncurrent source code that implements these specifications.\n\n{xrst_end Poly}\n------------------------------------------------------------------------------\n*/\n// BEGIN C++\n# include <cstddef>  // used to defined size_t\n# include <cppad/utility/check_simple_vector.hpp>\n\nnamespace CppAD {    // BEGIN CppAD namespace\n\ntemplate <class Type, class Vector>\nType Poly(size_t k, const Vector &a, const Type &z)\n{   size_t i;\n    size_t d = a.size() - 1;\n\n    Type tmp;\n\n    // check Vector is Simple Vector class with Type elements\n    CheckSimpleVector<Type, Vector>();\n\n    // case where derivative order greater than degree of polynomial\n    if( k > d )\n    {   tmp = 0;\n        return tmp;\n    }\n    // case where we are evaluating a derivative\n    if( k > 0 )\n    {   // initialize factor as (k-1) !\n        size_t factor = 1;\n        for(i = 2; i < k; i++)\n            factor *= i;\n\n        // set b to coefficient vector corresponding to derivative\n        Vector b(d - k + 1);\n        for(i = k; i <= d; i++)\n        {   factor   *= i;\n            tmp       = double( factor );\n            b[i - k]  = a[i] * tmp;\n            factor   /= (i - k + 1);\n        }\n        // value of derivative polynomial\n        return Poly(0, b, z);\n    }\n    // case where we are evaluating the original polynomial\n    Type sum = a[d];\n    i        = d;\n    while(i > 0)\n    {   sum *= z;\n        sum += a[--i];\n    }\n    return sum;\n}\n} // END CppAD namespace\n// END C++\n# endif\n"
  },
  {
    "path": "include/cppad/utility/pow_int.hpp",
    "content": "# ifndef CPPAD_UTILITY_POW_INT_HPP\n# define CPPAD_UTILITY_POW_INT_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n-------------------------------------------------------------------------------\n{xrst_begin pow_int}\n\nThe Integer Power Function\n##########################\n\nSyntax\n******\n| # ``include <cppad/utility/pow_int.hpp>``\n| *z* = ``pow`` ( *x* , *y* )\n\nSee Also\n********\n:ref:`pow-name`\n\nPurpose\n*******\nDetermines the value of the power function\n\n.. math::\n\n    {\\rm pow} (x, y) = x^y\n\nfor integer exponents *n*\nusing multiplication and possibly division to compute the value.\nThe other CppAD :ref:`pow-name` function may use logarithms and exponentiation\nto compute derivatives of the same value\n(which will not work if *x* is less than or equal zero).\n\nInclude\n*******\nThe file ``cppad/utility/pow_int.hpp``\nis included by ``cppad/cppad.hpp``\nbut it can also be included separately with out the rest of\nthe ``CppAD`` routines.\nIncluding this file defines\nthis version of the ``pow`` within the ``CppAD`` namespace.\n\nx\n*\nThe argument *x* has prototype\n\n    ``const`` *Type* & *x*\n\ny\n*\nThe argument *y* has prototype\n\n    ``const int&`` *y*\n\nz\n*\nThe result *z* has prototype\n\n    *Type* *z*\n\nType\n****\nThe type *Type* must support the following operations\nwhere *a* and *b* are *Type* objects\nand *i* is an ``int`` :\n\n.. csv-table::\n    :widths: auto\n\n    **Operation**,**Description**,**Result Type**\n    *Type* *a* ( *i* ),construction of a *Type* object from an ``int``,*Type*\n    *a* * *b*,binary multiplication of *Type* objects,*Type*\n    *a* / *b*,binary division of *Type* objects,*Type*\n\nOperation Sequence\n******************\nThe *Type* operation sequence used to calculate *z* is\n:ref:`glossary@Operation@Independent`\nof *x* .\n\nExample\n*******\n{xrst_toc_hidden\n    example/utility/pow_int.cpp\n}\nThe file :ref:`pow_int.cpp-name`\nis an example and test of this function.\n\n{xrst_end pow_int}\n-------------------------------------------------------------------------------\n*/\n\nnamespace CppAD {\n\n    template <class Type>\n    inline Type pow (const Type& x, const int& n)\n    {\n        Type p(1);\n        int n2 = n / 2;\n\n        if( n == 0 )\n            return p;\n        if( n < 0 )\n            return p / pow(x, -n);\n        if( n == 1 )\n            return x;\n\n        // p = (x^2)^(n/2)\n        p = pow( x * x , n2 );\n\n        // n is even case\n        if( n % 2 == 0 )\n            return p;\n\n        // n is odd case\n        return p * x;\n    }\n\n}\n\n# endif\n"
  },
  {
    "path": "include/cppad/utility/romberg_mul.hpp",
    "content": "# ifndef CPPAD_UTILITY_ROMBERG_MUL_HPP\n# define CPPAD_UTILITY_ROMBERG_MUL_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin RombergMul}\n{xrst_spell\n    test test\n}\n\nMulti-dimensional Romberg Integration\n#####################################\n\nSyntax\n******\n| # ``include <cppad/utility/romberg_mul.hpp>``\n| ``RombergMul`` < *Fun* , *SizeVector* , *FloatVector* , *m* > *R*\n| *r* = *R* ( *F* , *a* , *b* , *n* , *p* , *e* )\n\nDescription\n***********\nReturns the Romberg integration estimate\n:math:`r` for the multi-dimensional integral\n\n.. math::\n\n    r =\n    \\int_{a[0]}^{b[0]} \\cdots \\int_{a[m-1]}^{b[m-1]}\n    \\; F(x) \\;\n    {\\bf d} x_0 \\cdots {\\bf d} x_{m-1}\n    \\; + \\;\n    \\sum_{i=0}^{m-1}\n    O \\left[ ( b[i] - a[i] ) / 2^{n[i]-1} \\right]^{2(p[i]+1)}\n\nInclude\n*******\nThe file ``cppad/utility/romberg_mul.hpp``\nis included by ``cppad/cppad.hpp``\nbut it can also be included separately with out the rest of\nthe ``CppAD`` routines.\n\nm\n*\nThe template parameter *m* must be convertible to a ``size_t``\nobject with a value that can be determined at compile time; for example\n``2`` .\nIt determines the dimension of the domain space for the integration.\n\nr\n*\nThe return value *r* has prototype\n\n    *Float* *r*\n\nIt is the estimate computed by ``RombergMul`` for the integral above\n(see description of :ref:`RombergMul@Float` below).\n\nF\n*\nThe object *F* has the prototype\n\n    *Fun* & *F*\n\nIt must support the operation\n\n    *F* ( *x* )\n\nThe argument *x* to *F* has prototype\n\n    ``const`` *Float* & *x*\n\nThe return value of *F* is a *Float* object\n\na\n*\nThe argument *a* has prototype\n\n    ``const`` *FloatVector* & *a*\n\nIt specifies the lower limit for the integration\n(see description of :ref:`RombergMul@FloatVector` below).\n\nb\n*\nThe argument *b* has prototype\n\n    ``const`` *FloatVector* & *b*\n\nIt specifies the upper limit for the integration.\n\nn\n*\nThe argument *n* has prototype\n\n    ``const`` *SizeVector* & *n*\n\nA total number of :math:`2^{n[i]-1} + 1`\nevaluations of *F* ( *x* ) are used to estimate the integral\nwith respect to :math:`{\\bf d} x_i`.\n\np\n*\nThe argument *p* has prototype\n\n    ``const`` *SizeVector* & *p*\n\nFor :math:`i = 0 , \\ldots , m-1`,\n:math:`n[i]` determines the accuracy order in the\napproximation for the integral\nthat is returned by ``RombergMul`` .\nThe values in *p* must be less than or equal *n* ; i.e.,\n*p* [ *i* ] <= *n* [ *i* ] .\n\ne\n*\nThe argument *e* has prototype\n\n    *Float* & *e*\n\nThe input value of *e* does not matter\nand its output value is an approximation for the absolute error in\nthe integral estimate.\n\nFloat\n*****\nThe type *Float* is defined as the type of the elements of\n:ref:`RombergMul@FloatVector` .\nThe type *Float* must satisfy the conditions\nfor a :ref:`NumericType-name` .\nThe routine :ref:`CheckNumericType-name` will generate an error message\nif this is not the case.\nIn addition, if *x* and *y* are *Float* objects,\n\n    *x* < *y*\n\nreturns the ``bool`` value true if *x* is less than\n*y* and false otherwise.\n\nFloatVector\n***********\nThe type *FloatVector* must be a :ref:`SimpleVector-name` class.\nThe routine :ref:`CheckSimpleVector-name` will generate an error message\nif this is not the case.\n{xrst_toc_hidden\n    example/utility/romberg_mul.cpp\n}\nExample\n*******\nThe file :ref:`romberg_mul.cpp-name`\ncontains an example and test a test of using this routine.\n\nSource Code\n***********\nThe source code for this routine is in the file\n``cppad/romberg_mul.hpp`` .\n\n{xrst_end RombergMul}\n*/\n\n# include <cppad/utility/romberg_one.hpp>\n# include <cppad/utility/check_numeric_type.hpp>\n# include <cppad/utility/check_simple_vector.hpp>\n\nnamespace CppAD { // BEGIN CppAD namespace\n\ntemplate <class Fun, class FloatVector>\nclass SliceLast {\n    typedef typename FloatVector::value_type Float;\nprivate:\n    Fun        *F;\n    size_t      last;\n    FloatVector x;\npublic:\n    SliceLast( Fun *F_, size_t last_, const FloatVector &x_ )\n    : F(F_) , last(last_), x(last + 1)\n    {   size_t i;\n        for(i = 0; i < last; i++)\n            x[i] = x_[i];\n    }\n    double operator()(const Float &xlast)\n    {   x[last] = xlast;\n        return (*F)(x);\n    }\n};\n\ntemplate <class Fun, class SizeVector, class FloatVector, class Float>\nclass IntegrateLast {\nprivate:\n    Fun                 *F;\n    const size_t        last;\n    const FloatVector   a;\n    const FloatVector   b;\n    const SizeVector    n;\n    const SizeVector    p;\n    Float               esum;\n    size_t              ecount;\n\npublic:\n    IntegrateLast(\n        Fun                *F_    ,\n        size_t              last_ ,\n        const FloatVector  &a_    ,\n        const FloatVector  &b_    ,\n        const SizeVector   &n_    ,\n        const SizeVector   &p_    )\n    : F(F_) , last(last_), a(a_) , b(b_) , n(n_) , p(p_)\n    { }\n    Float operator()(const FloatVector           &x)\n    {   Float r, e;\n        SliceLast<Fun, FloatVector           > S(F, last, x);\n        r     = CppAD::RombergOne(\n            S, a[last], b[last], n[last], p[last], e\n        );\n        esum = esum + e;\n        ecount++;\n        return r;\n    }\n    void ClearEsum(void)\n    {   esum   = 0.; }\n    Float GetEsum(void)\n    {   return esum; }\n\n    void ClearEcount(void)\n    {   ecount   = 0; }\n    size_t GetEcount(void)\n    {   return ecount; }\n};\n\ntemplate <class Fun, class SizeVector, class FloatVector, size_t m>\nclass RombergMul {\n    typedef typename FloatVector::value_type Float;\npublic:\n    RombergMul(void)\n    {   }\n    Float operator() (\n        Fun                 &F  ,\n        const FloatVector   &a  ,\n        const FloatVector   &b  ,\n        const SizeVector    &n  ,\n        const SizeVector    &p  ,\n        Float               &e  )\n    {   Float r;\n\n        typedef IntegrateLast<\n            Fun         ,\n            SizeVector  ,\n            FloatVector ,\n            Float       > IntegrateOne;\n\n        IntegrateOne Fm1(&F, m-1, a, b, n, p);\n        RombergMul<\n            IntegrateOne,\n            SizeVector  ,\n            FloatVector ,\n            m-1         > RombergMulM1;\n\n        Fm1.ClearEsum();\n        Fm1.ClearEcount();\n\n        r  = RombergMulM1(Fm1, a, b, n, p, e);\n\n        Float prod = 1;\n        for(size_t i = 0; i < m-1; i++)\n            prod *= (b[i] - a[i]);\n\n# ifndef NDEBUG\n        size_t pow2 = 1;\n        for(size_t i = 0; i < m-1; i++)\n            for(size_t j = 0; j < (n[i] - 1); j++)\n                pow2 *= 2;\n        assert( Fm1.GetEcount() == (pow2+1) );\n# endif\n\n        e = e + Fm1.GetEsum() * prod / Float( double(Fm1.GetEcount()) );\n\n        return r;\n    }\n};\n\ntemplate <class Fun, class SizeVector, class FloatVector>\nclass RombergMul <Fun, SizeVector, FloatVector, 1> {\n    typedef typename FloatVector::value_type Float;\npublic:\n    Float operator() (\n        Fun                 &F  ,\n        const FloatVector   &a  ,\n        const FloatVector   &b  ,\n        const SizeVector    &n  ,\n        const SizeVector    &p  ,\n        Float               &e  )\n    {   Float r;\n        typedef IntegrateLast<\n            Fun         ,\n            SizeVector  ,\n            FloatVector ,\n            Float       > IntegrateOne;\n\n        // check simple vector class specifications\n        CheckSimpleVector<Float, FloatVector>();\n\n        // check numeric type specifications\n        CheckNumericType<Float>();\n\n        IntegrateOne F0(&F, 0, a, b, n, p);\n\n        F0.ClearEsum();\n        F0.ClearEcount();\n\n        r  = F0(a);\n\n        assert( F0.GetEcount() == 1 );\n        e = F0.GetEsum();\n\n        return r;\n    }\n};\n\n} // END CppAD namespace\n\n# endif\n"
  },
  {
    "path": "include/cppad/utility/romberg_one.hpp",
    "content": "# ifndef CPPAD_UTILITY_ROMBERG_ONE_HPP\n# define CPPAD_UTILITY_ROMBERG_ONE_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin RombergOne}\n{xrst_spell\n    test test\n}\n\nOne DimensionalRomberg Integration\n##################################\n\nSyntax\n******\n| # ``include <cppad/utility/romberg_one.hpp>``\n| *r* = ``RombergOne`` ( *F* , *a* , *b* , *n* , *e* )\n\nDescription\n***********\nReturns the Romberg integration estimate\n:math:`r` for a one dimensional integral\n\n.. math::\n\n    r = \\int_a^b F(x) {\\bf d} x + O \\left[ (b - a) / 2^{n-1} \\right]^{2(p+1)}\n\nInclude\n*******\nThe file ``cppad/utility/romberg_one.hpp``\nis included by ``cppad/cppad.hpp``\nbut it can also be included separately with out the rest of\nthe ``CppAD`` routines.\n\nr\n*\nThe return value *r* has prototype\n\n    *Float* *r*\n\nIt is the estimate computed by ``RombergOne`` for the integral above.\n\nF\n*\nThe object *F* can be of any type, but it must support\nthe operation\n\n    *F* ( *x* )\n\nThe argument *x* to *F* has prototype\n\n    ``const`` *Float* & *x*\n\nThe return value of *F* is a *Float* object\n(see description of :ref:`RombergOne@Float` below).\n\na\n*\nThe argument *a* has prototype\n\n    ``const`` *Float* & *a*\n\nIt specifies the lower limit for the integration.\n\nb\n*\nThe argument *b* has prototype\n\n    ``const`` *Float* & *b*\n\nIt specifies the upper limit for the integration.\n\nn\n*\nThe argument *n* has prototype\n\n    ``size_t`` *n*\n\nA total number of :math:`2^{n-1} + 1` evaluations of *F* ( *x* )\nare used to estimate the integral.\n\np\n*\nThe argument *p* has prototype\n\n    ``size_t`` *p*\n\nIt must be less than or equal :math:`n`\nand determines the accuracy order in the approximation for the integral\nthat is returned by ``RombergOne`` .\nTo be specific\n\n.. math::\n\n    r = \\int_a^b F(x) {\\bf d} x + O \\left[ (b - a) / 2^{n-1} \\right]^{2(p+1)}\n\ne\n*\nThe argument *e* has prototype\n\n    *Float* & *e*\n\nThe input value of *e* does not matter\nand its output value is an approximation for the error in\nthe integral estimates; i.e.,\n\n.. math::\n\n    e \\approx \\left| r - \\int_a^b F(x) {\\bf d} x \\right|\n\nFloat\n*****\nThe type *Float* must satisfy the conditions\nfor a :ref:`NumericType-name` .\nThe routine :ref:`CheckNumericType-name` will generate an error message\nif this is not the case.\nIn addition, if *x* and *y* are *Float* objects,\n\n    *x* < *y*\n\nreturns the ``bool`` value true if *x* is less than\n*y* and false otherwise.\n{xrst_toc_hidden\n    example/utility/romberg_one.cpp\n}\nExample\n*******\nThe file\n:ref:`romberg_one.cpp-name`\ncontains an example and test a test of using this routine.\n\nSource Code\n***********\nThe source code for this routine is in the file\n``cppad/romberg_one.hpp`` .\n\n{xrst_end RombergOne}\n*/\n\n# include <cppad/utility/check_numeric_type.hpp>\n# include <cppad/core/cppad_assert.hpp>\n# include <cppad/utility/vector.hpp>\n\nnamespace CppAD { // BEGIN CppAD namespace\n\ntemplate <class Fun, class Float>\nFloat RombergOne(\n    Fun           &F ,\n    const Float   &a ,\n    const Float   &b ,\n    size_t         n ,\n    size_t         p ,\n    Float         &e )\n{\n    size_t ipow2 = 1;\n    size_t k, i;\n    Float pow2, sum, x;\n\n    Float  zero  = Float(0);\n    Float  two   = Float(2);\n\n    // check specifications for a NumericType\n    CheckNumericType<Float>();\n\n    CPPAD_ASSERT_KNOWN(\n        n >= 2,\n        \"RombergOne: n must be greater than or equal 2\"\n    );\n    CppAD::vector<Float> r(n);\n\n    //  set r[i] = trapazoidal rule with 2^i intervals in [a, b]\n    r[0]  = ( F(a) + F(b) ) * (b - a) / two;\n    for(i = 1; i < n; i++)\n    {   ipow2 *= 2;\n        // there must be a conversion from int to any numeric type\n        pow2   = Float(int(ipow2));\n        sum    = zero;\n        for(k = 1; k < ipow2; k += 2)\n        {   // start = a + (b-a)/pow2, increment = 2*(b-a)/pow2\n            x    = ( (pow2 - Float(double(k))) * a + double(k) * b ) / pow2;\n            sum  = sum + F(x);\n        }\n        // combine function evaluations in sum with those in T[i-1]\n        r[i] = r[i-1] / two + sum * (b - a) / pow2;\n    }\n\n    // now compute the higher order estimates\n    size_t ipow4    = 1;   // order of accuract for previous estimate\n    Float pow4, pow4minus;\n    for(i = 0; i < p; i++)\n    {   // compute estimate accurate to O[ step^(2*(i+1)) ]\n        // put results in r[n-1], r[n-2], ... , r[n-i+1]\n        ipow4    *= 4;\n        pow4      = Float(int(ipow4));\n        pow4minus = Float(ipow4-1);\n        for(k = n-1; k > i; k--)\n            r[k] = ( pow4 * r[k] - r[k-1] ) / pow4minus;\n    }\n\n    // error estimate for r[n]\n    e = r[n-1] - r[n-2];\n    if( e < zero )\n        e = - e;\n    return r[n-1];\n}\n\n} // END CppAD namespace\n\n# endif\n"
  },
  {
    "path": "include/cppad/utility/rosen_34.hpp",
    "content": "# ifndef CPPAD_UTILITY_ROSEN_34_HPP\n# define CPPAD_UTILITY_ROSEN_34_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin Rosen34}\n{xrst_spell\n    dep\n    rosenbrock\n    test test\n    tf\n    xf\n}\n\nA 3rd and 4th Order Rosenbrock ODE Solver\n#########################################\n\nSyntax\n******\n| # ``include <cppad/utility/rosen_34.hpp>``\n| *xf* = ``Rosen34`` ( *F* , *M* , *ti* , *tf* , *xi* )\n| *xf* = ``Rosen34`` ( *F* , *M* , *ti* , *tf* , *xi* , *e* )\n\nDescription\n***********\nThis is an embedded 3rd and 4th order Rosenbrock ODE solver\n(see Section 16.6 of :ref:`Bib@Numerical Recipes`\nfor a description of Rosenbrock ODE solvers).\nIn particular, we use the formulas taken from page 100 of\n:ref:`Bib@Shampine, L.F.`\n(except that the fraction 98/108 has been correction to be 97/108).\n\nWe use :math:`n` for the size of the vector *xi* .\nLet :math:`\\B{R}` denote the real numbers\nand let :math:`F : \\B{R} \\times \\B{R}^n \\rightarrow \\B{R}^n` be a smooth function.\nThe return value *xf* contains a 5th order\napproximation for the value :math:`X(tf)` where\n:math:`X : [ti , tf] \\rightarrow \\B{R}^n` is defined by\nthe following initial value problem:\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        X(ti)  & = & xi    \\\\\n        X'(t)  & = & F[t , X(t)]\n    \\end{eqnarray}\n\nIf your set of  ordinary differential equations are not stiff\nan explicit method may be better (perhaps :ref:`Runge45-name` .)\n\nInclude\n*******\nThe file ``cppad/utility/rosen_34.hpp``\nis included by ``cppad/cppad.hpp``\nbut it can also be included separately with out the rest of\nthe ``CppAD`` routines.\n\nxf\n**\nThe return value *xf* has the prototype\n\n    *Vector* *xf*\n\nand the size of *xf* is equal to *n*\n(see description of :ref:`Rosen34@Vector` below).\n\n.. math::\n\n    X(tf) = xf + O( h^5 )\n\nwhere :math:`h = (tf - ti) / M` is the step size.\nIf *xf* contains not a number :ref:`nan-name` ,\nsee the discussion of :ref:`f<Rosen34@Fun@Nan>` .\n\nFun\n***\nThe class *Fun*\nand the object *F* satisfy the prototype\n\n    *Fun* & *F*\n\nThis must support the following set of calls\n\n| |tab| *F* . ``Ode`` ( *t* , *x* , *f* )\n| |tab| *F* . ``Ode_ind`` ( *t* , *x* , *f_t* )\n| |tab| *F* . ``Ode_dep`` ( *t* , *x* , *f_x* )\n\nt\n=\nIn all three cases,\nthe argument *t* has prototype\n\n    ``const`` *Scalar* & *t*\n\n(see description of :ref:`Rosen34@Scalar` below).\n\nx\n=\nIn all three cases,\nthe argument *x* has prototype\n\n    ``const`` *Vector* & *x*\n\nand has size *n*\n(see description of :ref:`Rosen34@Vector` below).\n\nf\n=\nThe argument *f* to *F* . ``Ode`` has prototype\n\n    *Vector* & *f*\n\nOn input and output, *f* is a vector of size *n*\nand the input values of the elements of *f* do not matter.\nOn output,\n*f* is set equal to :math:`F(t, x)`\n(see *F* ( *t* , *x* ) in :ref:`Rosen34@Description` ).\n\nf_t\n===\nThe argument *f_t* to *F* . ``Ode_ind`` has prototype\n\n    *Vector* & *f_t*\n\nOn input and output, *f_t* is a vector of size *n*\nand the input values of the elements of *f_t* do not matter.\nOn output, the *i*-th element of\n*f_t* is set equal to :math:`\\partial_t F_i (t, x)`\n(see *F* ( *t* , *x* ) in :ref:`Rosen34@Description` ).\n\nf_x\n===\nThe argument *f_x* to *F* . ``Ode_dep`` has prototype\n\n    *Vector* & *f_x*\n\nOn input and output, *f_x* is a vector of size *n* * *n*\nand the input values of the elements of *f_x* do not matter.\nOn output, the [ *i* * *n* + *j* ] element of\n*f_x* is set equal to :math:`\\partial_{x(j)} F_i (t, x)`\n(see *F* ( *t* , *x* ) in :ref:`Rosen34@Description` ).\n\nNan\n===\nIf any of the elements of *f* , *f_t* , or *f_x*\nhave the value not a number ``nan`` ,\nthe routine ``Rosen34`` returns with all the\nelements of *xf* and *e* equal to ``nan`` .\n\nWarning\n=======\nThe arguments *f* , *f_t* , and *f_x*\nmust have a call by reference in their prototypes; i.e.,\ndo not forget the ``&`` in the prototype for\n*f* , *f_t* and *f_x* .\n\nOptimization\n============\nEvery call of the form\n\n    *F* . ``Ode_ind`` ( *t* , *x* , *f_t* )\n\nis directly followed by a call of the form\n\n    *F* . ``Ode_dep`` ( *t* , *x* , *f_x* )\n\nwhere the arguments *t* and *x* have not changed between calls.\nIn many cases it is faster to compute the values of *f_t*\nand *f_x* together and then pass them back one at a time.\n\nM\n*\nThe argument *M* has prototype\n\n    ``size_t`` *M*\n\nIt specifies the number of steps\nto use when solving the differential equation.\nThis must be greater than or equal one.\nThe step size is given by :math:`h = (tf - ti) / M`, thus\nthe larger *M* , the more accurate the\nreturn value *xf* is as an approximation\nfor :math:`X(tf)`.\n\nti\n**\nThe argument *ti* has prototype\n\n    ``const`` *Scalar* & *ti*\n\n(see description of :ref:`Rosen34@Scalar` below).\nIt specifies the initial time for *t* in the\ndifferential equation; i.e.,\nthe time corresponding to the value *xi* .\n\ntf\n**\nThe argument *tf* has prototype\n\n    ``const`` *Scalar* & *tf*\n\nIt specifies the final time for *t* in the\ndifferential equation; i.e.,\nthe time corresponding to the value *xf* .\n\nxi\n**\nThe argument *xi* has the prototype\n\n    ``const`` *Vector* & *xi*\n\nand the size of *xi* is equal to *n* .\nIt specifies the value of :math:`X(ti)`\n\ne\n*\nThe argument *e* is optional and has the prototype\n\n    *Vector* & *e*\n\nIf *e* is present,\nthe size of *e* must be equal to *n* .\nThe input value of the elements of *e* does not matter.\nOn output\nit contains an element by element\nestimated bound for the absolute value of the error in *xf*\n\n.. math::\n\n    e = O( h^4 )\n\nwhere :math:`h = (tf - ti) / M` is the step size.\n\nScalar\n******\nThe type *Scalar* must satisfy the conditions\nfor a :ref:`NumericType-name` .\nThe routine :ref:`CheckNumericType-name` will generate an error message\nif this is not the case.\nIn addition, the following operations must be defined for\n*Scalar* objects *a* and *b* :\n\n.. list-table::\n    :widths: auto\n\n    * - **Operation**\n      - **Description**\n    * - *a* < *b*\n      - less than operator (returns a ``bool`` object)\n\nVector\n******\nThe type *Vector* must be a :ref:`SimpleVector-name` class with\n:ref:`elements of type Scalar<SimpleVector@Elements of Specified Type>` .\nThe routine :ref:`CheckSimpleVector-name` will generate an error message\nif this is not the case.\n\nParallel Mode\n*************\nFor each set of types\n:ref:`Rosen34@Scalar` ,\n:ref:`Rosen34@Vector` , and\n:ref:`Rosen34@Fun` ,\nthe first call to ``Rosen34``\nmust not be :ref:`parallel<ta_in_parallel-name>` execution mode.\n\nExample\n*******\n{xrst_toc_hidden\n    example/utility/rosen_34.cpp\n}\nThe file\n:ref:`rosen_34.cpp-name`\ncontains an example and test a test of using this routine.\n\nSource Code\n***********\nThe source code for this routine is in the file\n``cppad/rosen_34.hpp`` .\n\n{xrst_end Rosen34}\n--------------------------------------------------------------------------\n*/\n\n# include <cstddef>\n# include <cppad/core/cppad_assert.hpp>\n# include <cppad/utility/check_simple_vector.hpp>\n# include <cppad/utility/check_numeric_type.hpp>\n# include <cppad/utility/vector.hpp>\n# include <cppad/utility/lu_factor.hpp>\n# include <cppad/utility/lu_invert.hpp>\n\n// needed before one can use CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL\n# include <cppad/utility/thread_alloc.hpp>\n\nnamespace CppAD { // BEGIN CppAD namespace\n\ntemplate <class Scalar, class Vector, class Fun>\nVector Rosen34(\n    Fun           &F ,\n    size_t         M ,\n    const Scalar &ti ,\n    const Scalar &tf ,\n    const Vector &xi )\n{   Vector e( xi.size() );\n    return Rosen34(F, M, ti, tf, xi, e);\n}\n\ntemplate <class Scalar, class Vector, class Fun>\nVector Rosen34(\n    Fun           &F ,\n    size_t         M ,\n    const Scalar &ti ,\n    const Scalar &tf ,\n    const Vector &xi ,\n    Vector       &e )\n{\n    CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL;\n\n    // check numeric type specifications\n    CheckNumericType<Scalar>();\n\n    // check simple vector class specifications\n    CheckSimpleVector<Scalar, Vector>();\n\n    // Parameters for Shampine's Rosenbrock method\n    // are static to avoid recalculation on each call and\n    // do not use Vector to avoid possible memory leak\n    static Scalar a[3] = {\n        Scalar(0),\n        Scalar(1),\n        Scalar(3)   / Scalar(5)\n    };\n    static Scalar b[2 * 2] = {\n        Scalar(1),\n        Scalar(0),\n        Scalar(24)  / Scalar(25),\n        Scalar(3)   / Scalar(25)\n    };\n    static Scalar ct[4] = {\n        Scalar(1)   / Scalar(2),\n        - Scalar(3) / Scalar(2),\n        Scalar(121) / Scalar(50),\n        Scalar(29)  / Scalar(250)\n    };\n    static Scalar cg[3 * 3] = {\n        - Scalar(4),\n        Scalar(0),\n        Scalar(0),\n        Scalar(186) / Scalar(25),\n        Scalar(6)   / Scalar(5),\n        Scalar(0),\n        - Scalar(56) / Scalar(125),\n        - Scalar(27) / Scalar(125),\n        - Scalar(1)  / Scalar(5)\n    };\n    static Scalar d3[3] = {\n        Scalar(97) / Scalar(108),\n        Scalar(11) / Scalar(72),\n        Scalar(25) / Scalar(216)\n    };\n    static Scalar d4[4] = {\n        Scalar(19)  / Scalar(18),\n        Scalar(1)   / Scalar(4),\n        Scalar(25)  / Scalar(216),\n        Scalar(125) / Scalar(216)\n    };\n    CPPAD_ASSERT_KNOWN(\n        M >= 1,\n        \"Error in Rosen34: the number of steps is less than one\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        e.size() == xi.size(),\n        \"Error in Rosen34: size of e not equal to size of xi\"\n    );\n    size_t i, j, k, l, m;             // indices\n\n    size_t  n    = xi.size();         // number of components in X(t)\n    Scalar  ns   = Scalar(double(M)); // number of steps as Scalar object\n    Scalar  h    = (tf - ti) / ns;    // step size\n    Scalar  zero = Scalar(0);         // some constants\n    Scalar  one  = Scalar(1);\n    Scalar  two  = Scalar(2);\n\n    // permutation vectors needed for LU factorization routine\n    CppAD::vector<size_t> ip(n), jp(n);\n\n    // vectors used to store values returned by F\n    Vector E(n * n), Eg(n), f_t(n);\n    Vector g(n * 3), x3(n), x4(n), xf(n), ftmp(n), xtmp(n), nan_vec(n);\n\n    // initialize e = 0, nan_vec = nan\n    for(i = 0; i < n; i++)\n    {   e[i]       = zero;\n        nan_vec[i] = nan(zero);\n    }\n\n    xf = xi;           // initialize solution\n    for(m = 0; m < M; m++)\n    {   // time at beginning of this interval\n        Scalar t = ti * (Scalar(int(M - m)) / ns)\n                      + tf * (Scalar(int(m)) / ns);\n\n        // value of x at beginning of this interval\n        x3 = x4 = xf;\n\n        // evaluate partial derivatives at beginning of this interval\n        F.Ode_ind(t, xf, f_t);\n        F.Ode_dep(t, xf, E);    // E = f_x\n        if( hasnan(f_t) || hasnan(E) )\n        {   e = nan_vec;\n            return nan_vec;\n        }\n\n        // E = I - f_x * h / 2\n        for(i = 0; i < n; i++)\n        {   for(j = 0; j < n; j++)\n                E[i * n + j] = - E[i * n + j] * h / two;\n            E[i * n + i] += one;\n        }\n\n        // LU factor the matrix E\n# ifndef NDEBUG\n        int sign = LuFactor(ip, jp, E);\n# else\n        LuFactor(ip, jp, E);\n# endif\n        CPPAD_ASSERT_KNOWN(\n            sign != 0,\n            \"Error in Rosen34: I - f_x * h / 2 not invertible\"\n        );\n\n        // loop over integration steps\n        for(k = 0; k < 3; k++)\n        {   // set location for next function evaluation\n            xtmp = xf;\n            for(l = 0; l < k; l++)\n            {   // loop over previous function evaluations\n                Scalar bkl = b[(k-1)*2 + l];\n                for(i = 0; i < n; i++)\n                {   // loop over elements of x\n                    xtmp[i] += bkl * g[i*3 + l] * h;\n                }\n            }\n            // ftmp = F(t + a[k] * h, xtmp)\n            F.Ode(t + a[k] * h, xtmp, ftmp);\n            if( hasnan(ftmp) )\n            {   e = nan_vec;\n                return nan_vec;\n            }\n\n            // Form Eg for this integration step\n            for(i = 0; i < n; i++)\n                Eg[i] = ftmp[i] + ct[k] * f_t[i] * h;\n            for(l = 0; l < k; l++)\n            {   for(i = 0; i < n; i++)\n                    Eg[i] += cg[(k-1)*3 + l] * g[i*3 + l];\n            }\n\n            // Solve the equation E * g = Eg\n            LuInvert(ip, jp, E, Eg);\n\n            // save solution and advance x3, x4\n            for(i = 0; i < n; i++)\n            {   g[i*3 + k]  = Eg[i];\n                x3[i]      += h * d3[k] * Eg[i];\n                x4[i]      += h * d4[k] * Eg[i];\n            }\n        }\n        // Form Eg for last update to x4 only\n        for(i = 0; i < n; i++)\n            Eg[i] = ftmp[i] + ct[3] * f_t[i] * h;\n        for(l = 0; l < 3; l++)\n        {   for(i = 0; i < n; i++)\n                Eg[i] += cg[2*3 + l] * g[i*3 + l];\n        }\n\n        // Solve the equation E * g = Eg\n        LuInvert(ip, jp, E, Eg);\n\n        // advance x4 and accumulate error bound\n        for(i = 0; i < n; i++)\n        {   x4[i] += h * d4[3] * Eg[i];\n\n            // cant use abs because cppad.hpp may not be included\n            Scalar diff = x4[i] - x3[i];\n            if( diff < zero )\n                e[i] -= diff;\n            else\n                e[i] += diff;\n        }\n\n        // advance xf for this step using x4\n        xf = x4;\n    }\n    return xf;\n}\n\n} // End CppAD namespace\n\n# endif\n"
  },
  {
    "path": "include/cppad/utility/runge_45.hpp",
    "content": "# ifndef CPPAD_UTILITY_RUNGE_45_HPP\n# define CPPAD_UTILITY_RUNGE_45_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin Runge45}\n{xrst_spell\n    karp\n    kutta\n    tf\n    xf\n}\n\nAn Embedded 4th and 5th Order Runge-Kutta ODE Solver\n####################################################\n\nSyntax\n******\n| # ``include <cppad/utility/runge_45.hpp>``\n| *xf* = ``Runge45`` ( *F* , *M* , *ti* , *tf* , *xi* )\n| *xf* = ``Runge45`` ( *F* , *M* , *ti* , *tf* , *xi* , *e* )\n\nPurpose\n*******\nThis is an implementation of the\nCash-Karp embedded 4th and 5th order Runge-Kutta ODE solver\ndescribed in Section 16.2 of :ref:`Bib@Numerical Recipes` .\nWe use :math:`n` for the size of the vector *xi* .\nLet :math:`\\B{R}` denote the real numbers\nand let :math:`F : \\B{R} \\times \\B{R}^n \\rightarrow \\B{R}^n`\nbe a smooth function.\nThe return value *xf* contains a 5th order\napproximation for the value :math:`X(tf)` where\n:math:`X : [ti , tf] \\rightarrow \\B{R}^n` is defined by\nthe following initial value problem:\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        X(ti)  & = & xi    \\\\\n        X'(t)  & = & F[t , X(t)]\n    \\end{eqnarray}\n\nIf your set of ordinary differential equations\nare stiff, an implicit method may be better\n(perhaps :ref:`Rosen34-name` .)\n\nOperation Sequence\n******************\nThe :ref:`operation sequence<glossary@Operation@Sequence>` for *Runge*\ndoes not depend on any of its *Scalar* input values provided that\nthe operation sequence for\n\n    *F* . ``Ode`` ( *t* , *x* , *f* )\n\ndoes not on any of its *Scalar* inputs (see below).\n\nInclude\n*******\nThe file ``cppad/utility/runge_45.hpp``\nis included by ``cppad/cppad.hpp``\nbut it can also be included separately with out the rest of\nthe ``CppAD`` routines.\n\nxf\n**\nThe return value *xf* has the prototype\n\n    *Vector* *xf*\n\nand the size of *xf* is equal to *n*\n(see description of :ref:`Runge45@Vector` below).\n\n.. math::\n\n    X(tf) = xf + O( h^6 )\n\nwhere :math:`h = (tf - ti) / M` is the step size.\nIf *xf* contains not a number :ref:`nan-name` ,\nsee the discussion for :ref:`Runge45@Fun@f` .\n\nFun\n***\nThe class *Fun*\nand the object *F* satisfy the prototype\n\n    *Fun* & *F*\n\nThe object *F* (and the class *Fun* )\nmust have a member function named ``Ode``\nthat supports the syntax\n\n    *F* . ``Ode`` ( *t* , *x* , *f* )\n\nt\n=\nThe argument *t* to *F* . ``Ode`` has prototype\n\n    ``const`` *Scalar* & *t*\n\n(see description of :ref:`Runge45@Scalar` below).\n\nx\n=\nThe argument *x* to *F* . ``Ode`` has prototype\n\n    ``const`` *Vector* & *x*\n\nand has size *n*\n(see description of :ref:`Runge45@Vector` below).\n\nf\n=\nThe argument *f* to *F* . ``Ode`` has prototype\n\n    *Vector* & *f*\n\nOn input and output, *f* is a vector of size *n*\nand the input values of the elements of *f* do not matter.\nOn output,\n*f* is set equal to :math:`F(t, x)` in the differential equation.\nIf any of the elements of *f* have the value not a number ``nan``\nthe routine ``Runge45`` returns with all the\nelements of *xf* and *e* equal to ``nan`` .\n\nWarning\n=======\nThe argument *f* to *F* . ``Ode``\nmust have a call by reference in its prototype; i.e.,\ndo not forget the ``&`` in the prototype for *f* .\n\nM\n*\nThe argument *M* has prototype\n\n    ``size_t`` *M*\n\nIt specifies the number of steps\nto use when solving the differential equation.\nThis must be greater than or equal one.\nThe step size is given by :math:`h = (tf - ti) / M`, thus\nthe larger *M* , the more accurate the\nreturn value *xf* is as an approximation\nfor :math:`X(tf)`.\n\nti\n**\nThe argument *ti* has prototype\n\n    ``const`` *Scalar* & *ti*\n\n(see description of :ref:`Runge45@Scalar` below).\nIt specifies the initial time for *t* in the\ndifferential equation; i.e.,\nthe time corresponding to the value *xi* .\n\ntf\n**\nThe argument *tf* has prototype\n\n    ``const`` *Scalar* & *tf*\n\nIt specifies the final time for *t* in the\ndifferential equation; i.e.,\nthe time corresponding to the value *xf* .\n\nxi\n**\nThe argument *xi* has the prototype\n\n    ``const`` *Vector* & *xi*\n\nand the size of *xi* is equal to *n* .\nIt specifies the value of :math:`X(ti)`\n\ne\n*\nThe argument *e* is optional and has the prototype\n\n    *Vector* & *e*\n\nIf *e* is present,\nthe size of *e* must be equal to *n* .\nThe input value of the elements of *e* does not matter.\nOn output\nit contains an element by element\nestimated bound for the absolute value of the error in *xf*\n\n.. math::\n\n    e = O( h^5 )\n\nwhere :math:`h = (tf - ti) / M` is the step size.\nIf on output, *e* contains not a number ``nan`` ,\nsee the discussion for :ref:`Runge45@Fun@f` .\n\nScalar\n******\nThe type *Scalar* must satisfy the conditions\nfor a :ref:`NumericType-name` .\nThe routine :ref:`CheckNumericType-name` will generate an error message\nif this is not the case.\n\nfabs\n====\nIn addition, the following function must be defined for\n*Scalar* objects *a* and *b*\n\n    *a* = ``fabs`` ( *b* )\n\nNote that this operation is only used for computing *e* ; hence\nthe operation sequence for *xf* can still be independent of\nthe arguments to ``Runge45`` even if\n\n    ``fabs`` ( *b* ) = ``std::max`` ( ``-`` *b* , *b* )\n\n.\n\nVector\n******\nThe type *Vector* must be a :ref:`SimpleVector-name` class with\n:ref:`elements of type Scalar<SimpleVector@Elements of Specified Type>` .\nThe routine :ref:`CheckSimpleVector-name` will generate an error message\nif this is not the case.\n\nParallel Mode\n*************\nFor each set of types\n:ref:`Runge45@Scalar` ,\n:ref:`Runge45@Vector` , and\n:ref:`Runge45@Fun` ,\nthe first call to ``Runge45``\nmust not be :ref:`parallel<ta_in_parallel-name>` execution mode.\n\nExample\n*******\n{xrst_toc_hidden\n    example/utility/runge45_1.cpp\n    example/utility/runge_45.cpp\n}\nThe file\n:ref:`runge45_1.cpp-name`\ncontains a simple example and test of ``Runge45`` .\n\nThe file\n:ref:`runge_45.cpp-name` contains an example using ``Runge45``\nin the context of algorithmic differentiation.\nIt also returns true if it succeeds and false otherwise.\n\nSource Code\n***********\nThe source code for this routine is in the file\n``cppad/runge_45.hpp`` .\n\n{xrst_end Runge45}\n--------------------------------------------------------------------------\n*/\n# include <cstddef>\n# include <cppad/core/cppad_assert.hpp>\n# include <cppad/utility/check_simple_vector.hpp>\n# include <cppad/utility/check_numeric_type.hpp>\n# include <cppad/utility/nan.hpp>\n\n// needed before one can use CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL\n# include <cppad/utility/thread_alloc.hpp>\n\nnamespace CppAD { // BEGIN CppAD namespace\n\ntemplate <class Scalar, class Vector, class Fun>\nVector Runge45(\n    Fun           &F ,\n    size_t         M ,\n    const Scalar &ti ,\n    const Scalar &tf ,\n    const Vector &xi )\n{   Vector e( xi.size() );\n    return Runge45(F, M, ti, tf, xi, e);\n}\n\ntemplate <class Scalar, class Vector, class Fun>\nVector Runge45(\n    Fun           &F ,\n    size_t         M ,\n    const Scalar &ti ,\n    const Scalar &tf ,\n    const Vector &xi ,\n    Vector       &e )\n{\n    CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL;\n\n    // check numeric type specifications\n    CheckNumericType<Scalar>();\n\n    // check simple vector class specifications\n    CheckSimpleVector<Scalar, Vector>();\n\n    // Cash-Karp parameters for embedded Runge-Kutta method\n    // are static to avoid recalculation on each call and\n    // do not use Vector to avoid possible memory leak\n    static Scalar a[6] = {\n        Scalar(0),\n        Scalar(1) / Scalar(5),\n        Scalar(3) / Scalar(10),\n        Scalar(3) / Scalar(5),\n        Scalar(1),\n        Scalar(7) / Scalar(8)\n    };\n    static Scalar b[5 * 5] = {\n        Scalar(1) / Scalar(5),\n        Scalar(0),\n        Scalar(0),\n        Scalar(0),\n        Scalar(0),\n\n        Scalar(3) / Scalar(40),\n        Scalar(9) / Scalar(40),\n        Scalar(0),\n        Scalar(0),\n        Scalar(0),\n\n        Scalar(3) / Scalar(10),\n        -Scalar(9) / Scalar(10),\n        Scalar(6) / Scalar(5),\n        Scalar(0),\n        Scalar(0),\n\n        -Scalar(11) / Scalar(54),\n        Scalar(5) / Scalar(2),\n        -Scalar(70) / Scalar(27),\n        Scalar(35) / Scalar(27),\n        Scalar(0),\n\n        Scalar(1631) / Scalar(55296),\n        Scalar(175) / Scalar(512),\n        Scalar(575) / Scalar(13824),\n        Scalar(44275) / Scalar(110592),\n        Scalar(253) / Scalar(4096)\n    };\n    static Scalar c4[6] = {\n        Scalar(2825) / Scalar(27648),\n        Scalar(0),\n        Scalar(18575) / Scalar(48384),\n        Scalar(13525) / Scalar(55296),\n        Scalar(277) / Scalar(14336),\n        Scalar(1) / Scalar(4),\n    };\n    static Scalar c5[6] = {\n        Scalar(37) / Scalar(378),\n        Scalar(0),\n        Scalar(250) / Scalar(621),\n        Scalar(125) / Scalar(594),\n        Scalar(0),\n        Scalar(512) / Scalar(1771)\n    };\n\n    CPPAD_ASSERT_KNOWN(\n        M >= 1,\n        \"Error in Runge45: the number of steps is less than one\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        e.size() == xi.size(),\n        \"Error in Runge45: size of e not equal to size of xi\"\n    );\n    size_t i, j, k, m;              // indices\n\n    size_t  n = xi.size();           // number of components in X(t)\n    Scalar  ns = Scalar(int(M));     // number of steps as Scalar object\n    Scalar  h = (tf - ti) / ns;      // step size\n    Scalar  zero_or_nan = Scalar(0); // zero (nan if Ode returns has a nan)\n    for(i = 0; i < n; i++)           // initialize e = 0\n        e[i] = zero_or_nan;\n\n    // vectors used to store values returned by F\n    Vector fh(6 * n), xtmp(n), ftmp(n), x4(n), x5(n), xf(n);\n\n    xf = xi;           // initialize solution\n    for(m = 0; m < M; m++)\n    {   // time at beginning of this interval\n        // (convert to int to avoid MS compiler warning)\n        Scalar t = ti * (Scalar(int(M - m)) / ns)\n                      + tf * (Scalar(int(m)) / ns);\n\n        // loop over integration steps\n        x4 = x5 = xf;   // start x4 and x5 at same point for each step\n        for(j = 0; j < 6; j++)\n        {   // loop over function evaluations for this step\n            xtmp = xf;  // location for next function evaluation\n            for(k = 0; k < j; k++)\n            {   // loop over previous function evaluations\n                Scalar bjk = b[ (j-1) * 5 + k ];\n                for(i = 0; i < n; i++)\n                {   // loop over elements of x\n                    xtmp[i] += bjk * fh[i * 6 + k];\n                }\n            }\n            // ftmp = F(t + a[j] * h, xtmp)\n            F.Ode(t + a[j] * h, xtmp, ftmp);\n\n            // if ftmp has a nan, set zero_or_nan to nan\n            for(i = 0; i < n; i++)\n                zero_or_nan *= ftmp[i];\n\n            for(i = 0; i < n; i++)\n            {   // loop over elements of x\n                Scalar fhi    = ftmp[i] * h;\n                fh[i * 6 + j] = fhi;\n                x4[i]        += c4[j] * fhi;\n                x5[i]        += c5[j] * fhi;\n                x5[i]        += zero_or_nan;\n            }\n        }\n        // accumulate error bound\n        for(i = 0; i < n; i++)\n        {   // cant use abs because cppad.hpp may not be included\n            Scalar diff = x5[i] - x4[i];\n            e[i] += fabs(diff);\n            e[i] += zero_or_nan;\n        }\n\n        // advance xf for this step using x5\n        xf = x5;\n    }\n    return xf;\n}\n\n} // End CppAD namespace\n\n# endif\n"
  },
  {
    "path": "include/cppad/utility/set_union.hpp",
    "content": "# ifndef CPPAD_UTILITY_SET_UNION_HPP\n# define CPPAD_UTILITY_SET_UNION_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin set_union}\n\nUnion of Standard Sets\n######################\n\nSyntax\n******\n| # ``include <cppad/utility/set_union.hpp>``\n| *result* = ``set_union`` ( *left* , *right* )\n\nPurpose\n*******\nThis is a simplified (and restricted) interface to\nthe ``std::union`` operation.\n\nElement\n*******\nThis is the type of the elements of the sets.\n\nleft\n****\nThis argument has prototype\n\n    ``const std::set<`` *Element* >& *left*\n\nright\n*****\nThis argument has prototype\n\n    ``const std::set<`` *Element* >& *right*\n\nresult\n******\nThe return value has prototype\n\n    ``std::set<`` *Element* >& *result*\n\nIt contains the union of *left* and *right* .\nNote that C++11 detects that the return value is a temporary\nand uses it for the result instead of making a separate copy.\n{xrst_toc_hidden\n    example/utility/set_union.cpp\n}\nExample\n*******\nThe file :ref:`set_union.cpp-name` contains an example and test of this\n\n{xrst_end set_union}\n*/\n\n# include <set>\n# include <algorithm>\n# include <iterator>\n\nnamespace CppAD {\n    template <class Element>\n    std::set<Element> set_union(\n        const std::set<Element>&     left   ,\n        const std::set<Element>&     right  )\n    {   std::set<Element> result;\n        std::set_union(\n            left.begin()              ,\n            left.end()                ,\n            right.begin()             ,\n            right.end()               ,\n            std::inserter(result, result.begin())\n        );\n        return result;\n    }\n}\n\n# endif\n"
  },
  {
    "path": "include/cppad/utility/sparse2eigen.hpp",
    "content": "# ifndef CPPAD_UTILITY_SPARSE2EIGEN_HPP\n# define CPPAD_UTILITY_SPARSE2EIGEN_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin sparse2eigen}\n{xrst_spell\n    nnz\n}\n\nConvert A CppAD Sparse Matrix to an Eigen Sparse Matrix\n#######################################################\n\nSyntax\n******\n| # ``include <cppad/utility/sparse2eigen.hpp>``\n| ``sparse2eigen`` ( *source* , *destination* )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_PROTOTYPE\n    // END_PROTOTYPE\n}\n\nInclude\n*******\nIf :ref:`cmake@Eigen` is found (and c++14 is supported),\nthe file ``cppad/utility/sparse2eigen.hpp``\nis included by ``cppad/cppad.hpp`` .\nIn any case,\nit can also be included separately with out the rest of\nthe ``CppAD`` routines.\nIncluding this file defines\nthis version of the ``sparse2eigen`` within the ``CppAD`` namespace.\n\nSizeVector\n**********\nWe use :ref:`sparse_rc@SizeVector` to denote a\n:ref:`SimpleVector-name` class with elements of ``size_t`` .\n\nValueVector\n***********\nWe use *ValueVector* to denote a\n:ref:`SimpleVector-name` class with elements of type *value_type* .\n\nOptions\n*******\nWe use *Options* to denote either\n``Eigen::RowMajor`` of ``Eigen::ColMajor`` .\n\nvalue_type\n**********\nThe type of elements of elements in *source* and *destination*\nmust be the same. We use *value_type* to denote this type.\n\nsource\n******\nThis is the CppAD sparse matrix that is being converted to eigen format.\n\ndestination\n***********\nThis is the Eigen sparse matrix that is the result of the conversion.\n\nCompressed\n**********\nThe result matrix *destination*\nis in compressed format. For example, let\n\n| |tab| ``size_t`` *nnz* = *source* . ``nnz`` ();\n| |tab| ``const`` *s_vector* & *s_value* = *source* . ``val`` ();\n| |tab| ``const`` *value_type* * *d_value* = *destination* . ``valuePtr`` ();\n| |tab| ``const`` *s_vector* & *row_major* = *source* . ``row_major`` ();\n| |tab| ``const`` *s_vector* & *col_major* = *source* . ``col_major`` ();\n\nIt follows that, for *k* = 0 , ..., *nnz* :\nIf *Options* is ``Eigen::RowMajor`` ,\n\n    *d_value* [ *k* ] == *s_value* [ *row_major* [ *k* ] ]\n\nIf *Options* is ``Eigen::ColMajor`` ,\n\n    *d_value* [ *k* ] == *s_value* [ *col_major* [ *k* ] ]\n\n{xrst_toc_hidden\n    example/sparse/sparse2eigen.cpp\n}\n\nExample\n*******\nThe file :ref:`sparse2eigen.cpp-name` contains an example and test\nof ``sparse2eigen.cpp`` It return true if the test passes\nand false otherwise.\n\n{xrst_end sparse2eigen}\n*/\n# include <cppad/configure.hpp>\n# include <Eigen/Sparse>\n# include <cppad/utility/sparse_rcv.hpp>\n# include <cppad/utility/vector.hpp>\n\nnamespace CppAD { // BEGIN CPPAD_NAMESPACE\n\n// BEGIN_PROTOTYPE\ntemplate <class SizeVector, class ValueVector, int Options>\nvoid sparse2eigen(\nconst CppAD::sparse_rcv<SizeVector, ValueVector>&               source       ,\nEigen::SparseMatrix<typename ValueVector::value_type, Options>& destination  )\n// END_PROTOTYPE\n{   using Eigen::Index;\n    typedef typename ValueVector::value_type value_type;\n    typedef Eigen::Triplet<value_type>       triplet;\n    std::vector<triplet> vec( source.nnz() );\n    //\n    const SizeVector&  row = source.row();\n    const SizeVector&  col = source.col();\n    const ValueVector& val = source.val();\n    //\n    for(size_t k = 0; k < source.nnz(); k++)\n        vec[k] = triplet( int(row[k]), int(col[k]), val[k] );\n    //\n    size_t nr = source.nr();\n    size_t nc = source.nc();\n    destination.resize( Index(nr), Index(nc) );\n    destination.setFromTriplets(vec.begin(), vec.end());\n    //\n    CPPAD_ASSERT_UNKNOWN( destination.isCompressed() );\n    //\n    return;\n}\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/utility/sparse_rc.hpp",
    "content": "# ifndef CPPAD_UTILITY_SPARSE_RC_HPP\n# define CPPAD_UTILITY_SPARSE_RC_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin sparse_rc}\n{xrst_spell\n    nnz\n    nr\n    ostream\n}\nRow and Column Index Sparsity Patterns\n######################################\n\nSyntax\n******\n\ninclude\n=======\n\n    # ``include <cppad/utility/sparse_rc.hpp>``\n\nConstructor\n===========\n\n| ``sparse_rc`` < *SizeVector* > *empty*\n| ``sparse_rc`` < *SizeVector* > *pattern* ( *nr* , *nc* , *nnz* )\n| ``sparse_rc`` < *SizeVector* > *pattern* ( *other* )\n\nAssignment\n==========\n\n| *pattern* = *other*\n| *pattern* . ``swap`` ( *other* )\n\nEquality\n========\n\n    *equal* = *pattern* == *other*\n\n.\n\nSetting\n=======\n\n| *resize* ( *nr* , *nc* , *nnz* )\n| *pattern* . ``set`` ( *k* , *r* , *c* )\n| *pattern* . ``push_back`` ( *r* , *c* )\n| *pattern* . ``set_row_major`` ()\n| *pattern* . ``set_col_major`` ()\n\nScalars\n=======\n\n| *pattern* . ``nr`` ()\n| *pattern* . ``nc`` ()\n| *pattern* . ``nnz`` ()\n\nVectors\n=======\n\n| ``const`` *SizeVector* & *row* ( *pattern* . ``row`` () )\n| ``const`` *SizeVector* & *col* ( *pattern* . ``col`` () )\n| ``const`` *SizeVector* & *row_major* ( *pattern* . ``get_row_major`` () )\n| ``const`` *SizeVector* & *col_major* ( *pattern* . ``get_col_major`` () )\n| *row_major* = *pattern* . ``row_major`` ()\n| *col_major* = *pattern* . ``col_major`` ()\n\nOutput\n======\n\n    *os* << *pattern*\n\nSizeVector\n**********\nWe use *SizeVector* to denote :ref:`SimpleVector-name` class\n:ref:`with elements of type<SimpleVector@Elements of Specified Type>`\n``size_t`` .\nIn addition, *SimpleVector* must support the ``swap`` operation\nbetween two of its vectors.\n\nempty\n*****\nThis is an empty sparsity pattern. To be specific,\nthe corresponding number of rows *nr* ,\nnumber of columns *nc* ,\nand number of possibly non-zero values *nnz* ,\nare all zero.\n\npattern\n*******\nThis object is used to hold a sparsity pattern for a matrix.\nThe sparsity *pattern* is ``const``\nexcept during its constructor, ``resize`` , and ``set`` .\n\nother\n*****\n\nAssignment and Constructor\n==========================\nIn the assignment and constructor, *other* has prototype\n\n    ``const sparse_rc`` < *SizeVector* >& *other*\n\nAfter the assignment and constructor, *pattern* is an independent copy\nof *other* ; i.e. it has all the same values as *other*\nand changes to *pattern* do not affect *other* .\n\nMove Semantics Assignment and Constructor\n=========================================\nIn the assignment and constructor, if *other* has prototype\n\n    ``sparse_rc`` < *SizeVector* >&& *other*\n\nA move semantics version of the assignment or constructor is used; e.g.,\nwhen *other* is a function return value.\n\nswap\n====\nIn the swap operation, *other* has prototype\n\n    ``sparse_rc`` < *SizeVector* >& *other*\n\nAfter the swap operation *other* ( *pattern* ) is equivalent\nto *pattern* ( *other* ) before the operation.\n\nEquality\n========\nIn the equality operation, *other* has prototype\n\n    ``const sparse_rc`` < *SizeVector* >& *other*\n\nThe two sparsity patterns are equal if the following conditions hold:\n\n#. The number of rows\n   *pattern* . ``nr`` () and *other* . ``nr`` () are equal.\n#. The number of columns\n   *pattern* . ``nc`` () and *other* . ``nc`` () are equal.\n#. The number of non-zero values\n   *pattern* . ``nnz`` () and *other* . ``nnz`` () are equal.\n#. The set of (row, column) pairs corresponding to\n   *pattern* and *other* , are equal.\n\nDetermining equality requires sorting both patterns\n\nnr\n**\nThis argument has prototype\n\n    ``size_t`` *nr*\n\nIt specifies the number of rows in the sparsity pattern.\nThe function call ``nr()`` returns the value of *nr* .\n\nnc\n**\nThis argument has prototype\n\n    ``size_t`` *nc*\n\nIt specifies the number of columns in the sparsity pattern.\nThe function call ``nc()`` returns the value of *nc* .\n\nnnz\n***\nThis argument has prototype\n\n    ``size_t`` *nnz*\n\nIt specifies the number of possibly non-zero\nindex pairs in the sparsity pattern.\nThe function call ``nnz()`` returns the value of *nnz* .\n\nresize\n******\nThe current sparsity pattern is lost and a new one is started\nwith the specified parameters. The elements in the *row*\nand *col* vectors should be assigned using ``set`` .\n\nset\n***\nThis function sets the values\n\n| |tab| *row* [ *k* ] = *r*\n| |tab| *col* [ *k* ] = *c*\n\npush_back\n*********\nThis function  the value *r* to the back of *row* ,\nthe value *c* to the back of *col* ,\nand increases *nnz* by one.\nThis operation requires *SizeVector* to support the\n``push_back`` operation\n(which is not part of the SimpleVector requirements).\n\nk\n=\nThis argument has type\n\n    ``size_t`` *k*\n\nand must be less than *nnz* .\n\nr\n=\nThis argument has type\n\n    ``size_t`` *r*\n\nIt specifies the value assigned to *row* [ *k* ] and must\nbe less than *nr* .\n\nc\n=\nThis argument has type\n\n    ``size_t`` *c*\n\nIt specifies the value assigned to *col* [ *k* ] and must\nbe less than *nc* .\n\nrow\n***\nThis vector has size *nnz* and\n*row* [ *k* ]\nis the row index of the *k*-th possibly non-zero\nindex pair in the sparsity pattern.\n\ncol\n***\nThis vector has size *nnz* and\n*col* [ *k* ] is the column index of the *k*-th possibly non-zero\nindex pair in the sparsity pattern.\n\nrow_major\n*********\nThis vector has prototype\n\n    *SizeVector* *row_major*\n\nand its size *nnz* .\nIt sorts the sparsity pattern in row-major order.\nTo be specific,\n\n    *col* [ *row_major* [ *k* ] ] <= *col* [ *row_major* [ *k* +1] ]\n\nand if *col* [ *row_major* [ *k* ] ] == *col* [ *row_major* [ *k* +1] ] ,\n\n    *row* [ *row_major* [ *k* ] ] < *row* [ *row_major* [ *k* +1] ]\n\nThis routine generates an assert if there are two entries with the same\nrow and column values (if ``NDEBUG`` is not defined).\n\nset_row_major\n*************\nStore the current row major order in *pattern* .\nThis can be used by the row_major function and the equality function\nto avoid re-sorting the pattern each time.\n\nget_row_major\n*************\nRetrieve the row major order stored in *pattern*\nby the previous ``set_row_major`` .\nIf this order is no longer valid, the return value\n*row_major* has size zero.\n\ncol_major\n*********\nThis vector has prototype\n\n    *SizeVector* *col_major*\n\nand its size *nnz* .\nIt sorts the sparsity pattern in column-major order.\nTo be specific,\n\n    *row* [ *col_major* [ *k* ] ] <= *row* [ *col_major* [ *k* +1] ]\n\nand if *row* [ *col_major* [ *k* ] ] == *row* [ *col_major* [ *k* +1] ] ,\n\n    *col* [ *col_major* [ *k* ] ] < *col* [ *col_major* [ *k* +1] ]\n\nThis routine generates an assert if there are two entries with the same\nrow and column values (if ``NDEBUG`` is not defined).\n\nset_col_major\n*************\nStore the current row major order in *pattern* .\nThis can be used by the col_major function and the equality function\nto avoid re-sorting the pattern each time.\n\nget_col_major\n*************\nRetrieve the row major order stored in *pattern*\nby the previous ``set_col_major`` .\nIf this order is no longer valid, the return value\n*col_major* has size zero.\n{xrst_toc_hidden\n    example/utility/sparse_rc.cpp\n}\nExample\n*******\nThe file :ref:`sparse_rc.cpp-name`\ncontains an example and test of this class.\n\nos\n**\nIf *os* is an ``std::ostream`` , the operation\n\n    *os* << *pattern*\n\noutputs *pattern* to the *os* stream.\nThe output begins with a left brace ``{``\nand ends with a right brace ``}`` .\nThe output is in row major order and has one line for each row.\nThe row index is output at the beginning of a line\nand the column indices follow.\n\n{xrst_end sparse_rc}\n*/\n# include <cstddef> // for size_t\n# include <cppad/core/cppad_assert.hpp>  // for CPPAD_ASSERT\n# include <cppad/utility/index_sort.hpp> // for row and column major ordering\n\nnamespace CppAD { // BEGIN CPPAD_NAMESPACE\n\n// sparsity pattern for a matrix with indices of type size_t\ntemplate <class SizeVector>\nclass sparse_rc {\nprivate:\n    // number of rows in the sparsity pattern\n    size_t nr_;\n    //\n    // number of columns in the sparsity pattern\n    size_t nc_;\n    //\n    // number of possibly non-zero index pairs\n    size_t nnz_;\n    //\n    // row_[k] is the row index for the k-th possibly non-zero entry\n    SizeVector row_;\n    //\n    // col_[k] is the column index for the k-th possibly non-zero entry\n    SizeVector col_;\n    //\n    // if row_major_.size() != 0, row_major_[k] is index of k-th non-zero\n    // entry in row major order.\n    SizeVector row_major_;\n    //\n    // if col_major_.size() != 0, col_major_[k] is index of k-th non-zero\n    // entry in column major order.\n    SizeVector col_major_;\n    //\n    // simple_vector_assign\n    static void simple_vector_assign(\n        SizeVector& destination, const SizeVector& source\n    )\n    {   // resize to zero first so do not copy any values\n        destination.resize(0);\n        // size agreement required for simple vector\n        destination.resize( source.size() );\n        // assignment\n        destination = source;\n    }\npublic:\n    // default constructor\n    // Eigen vector is ambiguous for row_(0), col_(0) so use default ctor\n    sparse_rc(void)\n    : nr_(0), nc_(0), nnz_(0)\n    { }\n    //\n    // move semantics constructor\n    // (none of the default constructor values are used by destructor)\n    sparse_rc(sparse_rc&& other)\n    {   swap(other); }\n    //\n    // destructor\n    ~sparse_rc(void)\n    { }\n    //\n    // sizing constructor\n    // Eigen vector is ambiguous for row_(0), col_(0) so use default ctor\n    sparse_rc(size_t nr, size_t nc, size_t nnz)\n    : nr_(nr), nc_(nc), nnz_(nnz)\n    {   row_.resize(nnz);\n        col_.resize(nnz);\n    }\n    //\n    // copy constructor\n    sparse_rc(const sparse_rc& other)\n    :\n    nr_(other.nr_)   ,\n    nc_(other.nc_)   ,\n    nnz_(other.nnz_) ,\n    row_(other.row_) ,\n    col_(other.col_) ,\n    row_major_(other.row_major_) ,\n    col_major_(other.col_major_)\n    { }\n    //\n    // assignment\n    void operator=(const sparse_rc& other)\n    {   nr_  = other.nr_;\n        nc_  = other.nc_;\n        nnz_ = other.nnz_;\n        //\n        simple_vector_assign(row_, other.row_);\n        simple_vector_assign(col_, other.col_);\n        simple_vector_assign(row_major_, other.row_major_);\n        simple_vector_assign(col_major_, other.col_major_);\n    }\n    //\n    // swap\n    void swap(sparse_rc& other)\n    {   std::swap( nr_ , other.nr_ );\n        std::swap( nc_ , other.nc_ );\n        std::swap( nnz_ , other.nnz_ );\n        //\n        row_.swap( other.row_ );\n        col_.swap( other.col_ );\n        row_major_.swap( other.row_major_ );\n        col_major_.swap( other.col_major_ );\n    }\n    //\n    // move semantics assignment\n    void operator=(sparse_rc&& other)\n    {   swap(other); }\n    //\n    // equality\n    bool operator==(const sparse_rc& other) const\n    {   // result\n        bool result = true;\n        result &= nr_  == other.nr_;\n        result &= nc_  == other.nc_;\n        result &= nnz_ == other.nnz_;\n        if( ! result )\n            return result;\n        //\n        // this_order, other_order, this_order_ptr, other_order_ptr\n        SizeVector        this_order;\n        SizeVector        other_order;\n        const SizeVector* this_order_ptr = &this_order;\n        const SizeVector* other_order_ptr = &other_order;\n        bool this_row_ok  = row_major_.size() > 0;\n        bool this_col_ok  = col_major_.size() > 0;\n        bool other_row_ok = other.row_major_.size() > 0;\n        bool other_col_ok = other.col_major_.size() > 0;\n        if( this_row_ok && this_row_ok )\n        {   this_order_ptr  = &row_major_;\n            other_order_ptr = &(other.row_major_);\n        }\n        else if( this_col_ok && this_col_ok )\n        {   this_order_ptr  = &col_major_;\n            other_order_ptr = &(other.col_major_);\n        }\n        else if( this_row_ok )\n        {   this_order_ptr = &row_major_;\n            other_order    = other.row_major();\n        }\n        else if( this_col_ok )\n        {   this_order_ptr = &col_major_;\n            other_order    = other.col_major();\n        }\n        else if( other_row_ok )\n        {   other_order_ptr = &(other.row_major_);\n            this_order      = row_major();\n        }\n        else if( other_col_ok )\n        {   other_order_ptr = &(other.col_major_);\n            this_order      = col_major();\n        }\n        else\n        {   this_order  = row_major();\n            other_order = other.row_major();\n        }\n        //\n        // result\n        for(size_t k = 0; k < nnz_; ++k)\n        {   size_t this_k  = (*this_order_ptr)[k];\n            size_t other_k = (*other_order_ptr)[k];\n            result &= row_[this_k] == other.row_[other_k];\n            result &= col_[this_k] == other.col_[other_k];\n        }\n        return result;\n    }\n    //\n    // resize\n    void resize(size_t nr, size_t nc, size_t nnz)\n    {   nr_ = nr;\n        nc_ = nc;\n        nnz_ = nnz;\n        row_.resize(nnz);\n        col_.resize(nnz);\n        row_major_.resize(0);\n        col_major_.resize(0);\n    }\n    //\n    // set row and column for a possibly non-zero element\n    void set(size_t k, size_t r, size_t c)\n    {   CPPAD_ASSERT_KNOWN(\n            k < nnz_,\n            \"The index k is not less than nnz in sparse_rc::set\"\n        );\n        CPPAD_ASSERT_KNOWN(\n            r < nr_,\n            \"The index r is not less than nr in sparse_rc::set\"\n        );\n        CPPAD_ASSERT_KNOWN(\n            c < nc_,\n            \"The index c is to not less than nc in sparse_rc::set\"\n        );\n        row_[k] = r;\n        col_[k] = c;\n        //\n        row_major_.resize(0);\n        col_major_.resize(0);\n    }\n    //\n    // push_back\n    void push_back(size_t r, size_t c)\n    {   CPPAD_ASSERT_KNOWN(\n            r < nr_,\n            \"The index r is not less than nr in sparse_rc::push_back\"\n        );\n        CPPAD_ASSERT_KNOWN(\n            c < nc_,\n            \"The index c is to not less than nc in sparse_rc::push_back\"\n        );\n        row_.push_back(r);\n        col_.push_back(c);\n        ++nnz_;\n        CPPAD_ASSERT_UNKNOWN( row_.size() == nnz_ );\n        CPPAD_ASSERT_UNKNOWN( col_.size() == nnz_ );\n        //\n        row_major_.resize(0);\n        col_major_.resize(0);\n    }\n    //\n    // number of rows in matrix\n    size_t nr(void) const\n    {   return nr_; }\n    //\n    // number of columns in matrix\n    size_t nc(void) const\n    {   return nc_; }\n    //\n    // number of possibly non-zero elements in matrix\n    size_t nnz(void) const\n    {   return nnz_; }\n    //\n    // row indices\n    const SizeVector& row(void) const\n    {   return row_; }\n    //\n    // column indices\n    const SizeVector& col(void) const\n    {   return col_; }\n    //\n    // row-major order\n    SizeVector row_major(void) const\n    {   if( row_major_.size() > 0 )\n            return row_major_;\n        //\n        SizeVector keys(nnz_), row_major(nnz_);\n        for(size_t k = 0; k < nnz_; k++)\n        {   CPPAD_ASSERT_UNKNOWN( row_[k] < nr_ );\n            keys[k] = row_[k] * nc_ + col_[k];\n        }\n        index_sort(keys, row_major);\n# ifndef NDEBUG\n        for(size_t ell = 0; ell + 1 < nnz_; ell++)\n        {   size_t k  = row_major[ ell ];\n            size_t kp = row_major[ ell + 1 ];\n            CPPAD_ASSERT_KNOWN(\n                row_[k] != row_[kp] || col_[k] != col_[kp],\n                \"sparse_rc: row_major: duplicate entry in this pattern\"\n            );\n            CPPAD_ASSERT_UNKNOWN(\n                row_[k]<row_[kp] || (row_[k]==row_[kp] && col_[k]<col_[kp])\n            );\n        }\n# endif\n        return row_major;\n    }\n    //\n    // column-major indices\n    SizeVector col_major(void) const\n    {   if( col_major_.size() > 0 )\n            return col_major_;\n        SizeVector keys(nnz_), col_major(nnz_);\n        for(size_t k = 0; k < nnz_; k++)\n        {   CPPAD_ASSERT_UNKNOWN( col_[k] < nc_ );\n            keys[k] = col_[k] * nr_ + row_[k];\n        }\n        index_sort(keys, col_major);\n# ifndef NDEBUG\n        for(size_t ell = 0; ell + 1 < nnz_; ell++)\n        {   size_t k  = col_major[ ell ];\n            size_t kp = col_major[ ell + 1 ];\n            CPPAD_ASSERT_KNOWN(\n                col_[k] != col_[kp] || row_[k] != row_[kp],\n                \"sparse_rc: col_major: duplicate entry in this pattern\"\n            );\n            CPPAD_ASSERT_UNKNOWN(\n                col_[k]<col_[kp] || (col_[k]==col_[kp] && row_[k]<row_[kp])\n            );\n        }\n# endif\n        return col_major;\n    }\n    //\n    void set_row_major(void)\n    {   row_major_ = row_major();\n    }\n    const SizeVector& get_row_major(void) const\n    {   return row_major_;\n    }\n    //\n    void set_col_major(void)\n    {   col_major_ = col_major();\n    }\n    const SizeVector& get_col_major(void) const\n    {   return col_major_;\n    }\n};\n//\n// output\ntemplate <class SizeVector>\nstd::ostream& operator << (\n    std::ostream&                       os      ,\n    const CppAD::sparse_rc<SizeVector>& pattern )\n{   size_t nnz = pattern.nnz();\n    if( nnz == 0 )\n    {   os << \"{ }\";\n        return os;\n    }\n    const SizeVector& row       = pattern.row();\n    const SizeVector& col       = pattern.col();\n    SizeVector        row_major = pattern.row_major();\n    //\n    // k, r, c\n    size_t k = 0;\n    size_t r = row[ row_major[k] ];\n    size_t c = col[ row_major[k] ];\n    //\n    // os\n    os << \"{\\nrow = \" << r << \", col = \" << c;\n    while(++k < nnz )\n    {   bool new_row = r != row[ row_major[k] ];\n        r = row[ row_major[k] ];\n        c = col[ row_major[k] ];\n        if( new_row )\n            os << \"\\nrow = \" << r << \", col = \" << c;\n        else\n            os << \", \" << c;\n    }\n    os << \"\\n}\";\n    //\n    return os;\n}\n} // END_CPPAD_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/utility/sparse_rcv.hpp",
    "content": "# ifndef CPPAD_UTILITY_SPARSE_RCV_HPP\n# define CPPAD_UTILITY_SPARSE_RCV_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n------------------------------------------------------------------------------\n{xrst_begin sparse_rcv}\n{xrst_spell\n    nnz\n    nr\n    rc\n}\nSparse Matrix Row, Column, Value Representation\n###############################################\n\nSyntax\n******\n| # ``include <cppad/utility/sparse_rcv.hpp>``\n| ``sparse_rcv`` < *SizeVector* , *ValueVector* > *empty*\n| ``sparse_rcv`` < *SizeVector* , *ValueVector* > *matrix* ( *pattern* )\n| *matrix* = *other*\n| *matrix* . ``swap`` ( *other*  )\n| *matrix* . ``set`` ( *k* , *v* )\n| *nr* = *matrix* . ``nr`` ()\n| *nc* = *matrix* . ``nc`` ()\n| *nnz* = *matrix* . ``nnz`` ()\n| ``const`` *SizeVector* & *row* ( *matrix* . ``row`` () )\n| ``const`` *SizeVector* & *col* ( *matrix* . ``col`` () )\n| ``const`` *ValueVector* & *val* ( *matrix* . ``val`` () )\n| ``const sparse_rc`` < *SizeVector* >& *pat* ( *matrix* . ``pat`` () )\n| *row_major* = *matrix* . ``row_major`` ()\n| *col_major* = *matrix* . ``col_major`` ()\n\nSizeVector\n**********\nWe use :ref:`sparse_rc@SizeVector` to denote the\n:ref:`SimpleVector-name` class corresponding to *pattern* .\n\nValueVector\n***********\nWe use *ValueVector* to denote the\n:ref:`SimpleVector-name` class corresponding to *val* .\n\nempty\n*****\nThis is an empty sparse matrix object. To be specific,\nthe corresponding number of rows *nr* ,\nnumber of columns *nc* ,\nand number of possibly non-zero values *nnz* ,\nare all zero.\n\npattern\n*******\nThis constructor argument has prototype\n\n    ``const sparse_rc`` < *SizeVector* >& *pattern*\n\nIt specifies the number of rows, number of columns and\nthe possibly non-zero entries in the *matrix* .\n\nmatrix\n******\nThis is a sparse matrix object with the sparsity specified by *pattern* .\nOnly the *val* vector can be changed. All other values returned by\n*matrix* are fixed during the constructor and constant there after.\nThe *val* vector is only changed by the constructor\nand the ``set`` function.\nThere are two exceptions to this rule, where *other* appears in the\nassignment and swap syntax.\n\nother\n*****\n\nAssignment and Constructor\n==========================\nIn the assignment and constructor, *other* has prototype\n\n    ``const sparse_rcv`` < *SizeVector* , *ValueVector* >& *other*\n\nAfter this assignment and constructor, *other* is an independent copy\nof *matrix* ; i.e. it has all the same values as *matrix*\nand changes to *matrix* do not affect *other* .\n\nMove Semantics Assignment and Constructor\n=========================================\nIn the assignment and constructor, if *other* has prototype\n\n    ``sparse_rcv`` < *SizeVector* , *ValueVector* >&& *other*\n\nA move semantics version of the assignment operator is used; e.g.,\nwhen *other* is a function return value;\n\nswap\n====\nAfter the swap operation *other* ( *matrix* ) is equivalent\nto *matrix* ( *other* ) before the operation.\n\nnr\n**\nThis return value has prototype\n\n    ``size_t`` *nr*\n\nand is the number of rows in *matrix* .\n\nnc\n**\nThis argument and return value has prototype\n\n    ``size_t`` *nc*\n\nand is the number of columns in *matrix* .\n\nnnz\n***\nWe use the notation *nnz* to denote the number of\npossibly non-zero entries in *matrix* .\n\nset\n***\nThis function sets the value\n\n    *val* [ *k* ] = *v*\n\nk\n=\nThis argument has type\n\n    ``size_t`` *k*\n\nand must be less than *nnz* .\n\nv\n=\nThis argument has type\n\n    ``const`` *ValueVector* :: ``value_type&`` *v*\n\nIt specifies the value assigned to *val* [ *k* ] .\n\nrow\n***\nThis vector has size *nnz* and\n*row* [ *k* ]\nis the row index of the *k*-th possibly non-zero\nelement in *matrix* .\n\ncol\n***\nThis vector has size *nnz* and\n*col* [ ``k`` ] is the column index of the *k*-th possibly non-zero\nelement in *matrix*\n\nval\n***\nThis vector has size *nnz* and\n*val* [ ``k`` ] is value of the *k*-th possibly non-zero entry\nin the sparse matrix (the value may be zero).\n\npat\n***\nThis is equal to the sparsity pattern; i.e.,\n*pattern* in the constructor.\n\nrow_major\n*********\nThis vector has prototype\n\n    *SizeVector* *row_major*\n\nand its size *nnz* .\nIt sorts the sparsity pattern in row-major order.\nTo be specific,\n\n    *col* [ *row_major* [ *k* ] ] <= *col* [ *row_major* [ *k* +1] ]\n\nand if *col* [ *row_major* [ *k* ] ] == *col* [ *row_major* [ *k* +1] ] ,\n\n    *row* [ *row_major* [ *k* ] ] < *row* [ *row_major* [ *k* +1] ]\n\nThis routine generates an assert if there are two entries with the same\nrow and column values (if ``NDEBUG`` is not defined).\n\ncol_major\n*********\nThis vector has prototype\n\n    *SizeVector* *col_major*\n\nand its size *nnz* .\nIt sorts the sparsity pattern in column-major order.\nTo be specific,\n\n    *row* [ *col_major* [ *k* ] ] <= *row* [ *col_major* [ *k* +1] ]\n\nand if *row* [ *col_major* [ *k* ] ] == *row* [ *col_major* [ *k* +1] ] ,\n\n    *col* [ *col_major* [ *k* ] ] < *col* [ *col_major* [ *k* +1] ]\n\nThis routine generates an assert if there are two entries with the same\nrow and column values (if ``NDEBUG`` is not defined).\n\nEigen Matrix\n************\nIf you have the :ref:`eigen package<eigen-name>` in your include path,\nyou can use :ref:`sparse2eigen-name` to convert a sparse matrix to eigen format.\n{xrst_toc_hidden\n    example/utility/sparse_rcv.cpp\n}\nExample\n*******\nThe file :ref:`sparse_rcv.cpp-name`\ncontains an example and test of this class.\n\n{xrst_end sparse_rcv}\n*/\n/*!\n\\file sparse_rcv.hpp\nA sparse matrix class.\n*/\n# include <cppad/utility/sparse_rc.hpp>\n\nnamespace CppAD { // BEGIN CPPAD_NAMESPACE\n\n/// Sparse matrices with elements of type Scalar\ntemplate <class SizeVector, class ValueVector>\nclass sparse_rcv {\nprivate:\n    /// sparsity pattern\n    sparse_rc<SizeVector> pattern_;\n    /// value_type\n    typedef typename ValueVector::value_type value_type;\n    /// val_[k] is the value for the k-th possibly non-zero entry in the matrix\n    ValueVector    val_;\npublic:\n    // ------------------------------------------------------------------------\n    /// default constructor\n    sparse_rcv(void)\n    : pattern_(0, 0, 0)\n    { }\n    /// copy constructor\n    sparse_rcv(const sparse_rcv& other)\n    :\n    pattern_( other.pat() ) ,\n    val_( other.val() )\n    { }\n    /// move semantics constructor\n    /// (none of the default constructor values are used by destructor)\n    sparse_rcv(sparse_rcv&& other)\n    {   swap(other); }\n    /// destructor\n    ~sparse_rcv(void)\n    { }\n    /// constructor\n    sparse_rcv(const sparse_rc<SizeVector>& pattern )\n    :\n    pattern_(pattern)    ,\n    val_(pattern_.nnz())\n    { }\n    /// assignment\n    void operator=(const sparse_rcv& other)\n    {   pattern_ = other.pattern_;\n        // simple vector assignment requires vectors to have same size\n        val_.resize( other.nnz() );\n        val_ = other.val();\n    }\n    /// swap\n    void swap(sparse_rcv& other)\n    {   pattern_.swap( other.pattern_ );\n        val_.swap( other.val_ );\n    }\n    /// move semantics assignment\n    void operator=(sparse_rcv&& other)\n    {   swap(other); }\n    // ------------------------------------------------------------------------\n    void set(size_t k, const value_type& v)\n    {   CPPAD_ASSERT_KNOWN(\n            pattern_.nnz(),\n            \"The index k is not less than nnz in sparse_rcv::set\"\n        );\n        val_[k] = v;\n    }\n    /// number of rows in matrix\n    size_t nr(void) const\n    {   return pattern_.nr(); }\n    /// number of columns in matrix\n    size_t nc(void) const\n    {   return pattern_.nc(); }\n    /// number of possibly non-zero elements in matrix\n    size_t nnz(void) const\n    {   return pattern_.nnz(); }\n    /// row indices\n    const SizeVector& row(void) const\n    {   return pattern_.row(); }\n    /// column indices\n    const SizeVector& col(void) const\n    {   return pattern_.col(); }\n    /// value for possibly non-zero elements\n    const ValueVector& val(void) const\n    {   return val_; }\n    /// sparsity pattern\n    const sparse_rc<SizeVector>& pat(void) const\n    {   return pattern_; }\n    /// row-major order\n    SizeVector row_major(void) const\n    {   return pattern_.row_major(); }\n    /// column-major indices\n    SizeVector col_major(void) const\n    {   return pattern_.col_major(); }\n};\n\n} // END_CPPAD_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/utility/speed_test.hpp",
    "content": "# ifndef CPPAD_UTILITY_SPEED_TEST_HPP\n# define CPPAD_UTILITY_SPEED_TEST_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin speed_test}\n{xrst_spell\n    ctime\n    gettimeofday\n}\n\nRun One Speed Test and Return Results\n#####################################\n\nSyntax\n******\n| # ``include <cppad/utility/speed_test.hpp>``\n| *rate_vec* = ``speed_test`` ( *test* , *size_vec* , *time_min* )\n\nSee Also\n********\n:ref:`time_test-name`\n\nPurpose\n*******\nThe ``speed_test`` function executes a speed test\nfor various sized problems\nand reports the rate of execution.\n\nMotivation\n**********\nIt is important to separate small calculation units\nand test them individually.\nThis way individual changes can be tested in the context of the\nroutine that they are in.\nOn many machines, accurate timing of a very short execution\nsequences is not possible.\nIn addition,\nthere may be set up and tear down time for a test that\nwe do not really want included in the timing.\nFor this reason ``speed_test``\nautomatically determines how many times to\nrepeat the section of the test that we wish to time.\n\nInclude\n*******\nThe file ``cppad/utility/speed_test.hpp`` defines the\n``speed_test`` function.\nThis file is included by ``cppad/cppad.hpp``\nand it can also be included separately with out the rest of\nthe ``CppAD`` routines.\n\nVector\n******\nWe use *Vector* to denote a\n:ref:`simple vector class<SimpleVector-name>` with elements\nof type ``size_t`` .\n\ntest\n****\nThe ``speed_test`` argument *test* is a function with the syntax\n\n    *test* ( *size* , *repeat* )\n\nand its return value is ``void`` .\n\nsize\n====\nThe *test* argument *size* has prototype\n\n    ``size_t`` *size*\n\nIt specifies the size for this test.\n\nrepeat\n======\nThe *test* argument *repeat* has prototype\n\n    ``size_t`` *repeat*\n\nIt specifies the number of times to repeat the test.\n\nsize_vec\n********\nThe ``speed_test`` argument *size_vec* has prototype\n\n    ``const`` *Vector* & *size_vec*\n\nThis vector determines the size for each of the tests problems.\n\ntime_min\n********\nThe argument *time_min* has prototype\n\n    ``double`` *time_min*\n\nIt specifies the minimum amount of time in seconds\nthat the *test* routine should take.\nThe *repeat* argument to *test* is increased\nuntil this amount of execution time is reached.\n\nrate_vec\n********\nThe return value *rate_vec* has prototype\n\n    *Vector* & *rate_vec*\n\nWe use :math:`n` to denote its size which is the same as\nthe vector *size_vec* .\nFor :math:`i = 0 , \\ldots , n-1`,\n\n    *rate_vec* [ *i* ]\n\nis the ratio of *repeat* divided by time in seconds\nfor the problem with size *size_vec* [ *i* ] .\n\nTiming\n******\nIf your system supports the unix ``gettimeofday`` function,\nit will be used to measure time.\nOtherwise,\ntime is measured by the difference in\n::\n\n    (double) clock() / (double) CLOCKS_PER_SEC\n\nin the context of the standard ``<ctime>`` definitions.\n{xrst_toc_hidden\n    speed/example/speed_test.cpp\n}\nExample\n*******\nThe routine :ref:`speed_test.cpp-name` is an example and test\nof ``speed_test`` .\n\n{xrst_end speed_test}\n-----------------------------------------------------------------------\n*/\n\n# include <cstddef>\n# include <cmath>\n\n# include <cppad/utility/check_simple_vector.hpp>\n# include <cppad/utility/elapsed_seconds.hpp>\n\n\nnamespace CppAD { // BEGIN CppAD namespace\n\n// implemented as an inline so that can include in multiple link modules\n// with this same file\ntemplate <class Vector>\nVector speed_test(\n    void test(size_t size, size_t repeat),\n    const Vector& size_vec               ,\n    double time_min                      )\n{\n    // check that size_vec is a simple vector with size_t elements\n    CheckSimpleVector<size_t, Vector>();\n\n    size_t   n = size_vec.size();\n    Vector rate_vec(n);\n    size_t i;\n    for(i = 0; i < n; i++)\n    {   size_t size   = size_vec[i];\n        size_t repeat = 1;\n        double s0     = elapsed_seconds();\n        double s1     = elapsed_seconds();\n        while( s1 - s0 < time_min )\n        {   if( 2 * repeat < repeat )\n            {   // Can't use an assert here because this happens\n                // in release mode first.\n                std::cerr << \"speed_test: test function is too fast to time\\n\";\n                std::exit(1);\n            }\n            repeat = 2 * repeat;\n            s0     = elapsed_seconds();\n            test(size, repeat);\n            s1     = elapsed_seconds();\n        }\n        double rate = .5 + double(repeat) / (s1 - s0);\n        // first convert to float to avoid warning with g++ -Wconversion\n        rate_vec[i] = static_cast<size_t>( static_cast<float>(rate) );\n    }\n    return rate_vec;\n}\n\n} // END CppAD namespace\n\n/*\n{xrst_begin SpeedTest}\n{xrst_spell\n    cout\n    ctime\n}\n\nRun One Speed Test and Print Results\n####################################\n\nSyntax\n******\n\n    # ``include <cppad/utility/speed_test.hpp>``\n\n``SpeedTest`` ( *Test* , *first* , *inc* , *last* )\n\nSee Also\n********\n:ref:`time_test-name`\n\nPurpose\n*******\nThe ``SpeedTest`` function executes a speed test\nfor various sized problems\nand reports the results on standard output; i.e. ``std::cout`` .\nThe size of each test problem is included in its report\n(unless *first* is equal to *last* ).\n\nMotivation\n**********\nIt is important to separate small calculation units\nand test them individually.\nThis way individual changes can be tested in the context of the\nroutine that they are in.\nOn many machines, accurate timing of a very short execution\nsequences is not possible.\nIn addition,\nthere may be set up time for a test that\nwe do not really want included in the timing.\nFor this reason ``SpeedTest``\nautomatically determines how many times to\nrepeat the section of the test that we wish to time.\n\nInclude\n*******\nThe file ``speed_test.hpp`` contains the\n``SpeedTest`` function.\nThis file is included by ``cppad/utility/cppad.hpp``\nbut it can also be included separately with out the rest of\nthe ``CppAD`` routines.\n\nTest\n****\nThe ``SpeedTest`` argument *Test* is a function with the syntax\n\n    *name* = *Test* ( *size* , *repeat* )\n\nsize\n====\nThe *Test* argument *size* has prototype\n\n    ``size_t`` *size*\n\nIt specifies the size for this test.\n\nrepeat\n======\nThe *Test* argument *repeat* has prototype\n\n    ``size_t`` *repeat*\n\nIt specifies the number of times to repeat the test.\n\nname\n====\nThe *Test* result *name* has prototype\n\n    ``std::string`` *name*\n\nThe results for this test are reported on ``std::cout``\nwith *name* as an identifier for the test.\nIt is assumed that,\nfor the duration of this call to ``SpeedTest`` ,\n*Test* will always return\nthe same value for *name* .\nIf *name* is the empty string,\nno test name is reported by ``SpeedTest`` .\n\nfirst\n*****\nThe ``SpeedTest`` argument *first* has prototype\n\n    ``size_t`` *first*\n\nIt specifies the size of the first test problem reported by this call to\n``SpeedTest`` .\n\nlast\n****\nThe ``SpeedTest`` argument *last* has prototype\n\n    ``size_t`` *last*\n\nIt specifies the size of the last test problem reported by this call to\n``SpeedTest`` .\n\ninc\n***\nThe ``SpeedTest`` argument *inc* has prototype\n\n    ``int`` *inc*\n\nIt specifies the increment between problem sizes; i.e.,\nall values of *size* in calls to *Test* are given by\n\n    *size* = *first* + *j* * *inc*\n\nwhere *j* is a positive integer.\nThe increment can be positive or negative but it cannot be zero.\nThe values *first* , *last* and *inc* must\nsatisfy the relation\n\n.. math::\n\n    inc * ( last - first ) \\geq 0\n\nrate\n****\nThe value displayed in the ``rate`` column on ``std::cout``\nis defined as the value of *repeat* divided by the\ncorresponding elapsed execution time in seconds.\nThe elapsed execution time is measured by the difference in\n::\n\n    (double) clock() / (double) CLOCKS_PER_SEC\n\nin the context of the standard ``<ctime>`` definitions.\n\nErrors\n******\nIf one of the restrictions above is violated,\nthe CppAD error handler is used to report the error.\nYou can redefine this action using the instructions in\n:ref:`ErrorHandler-name`\n\nExample\n*******\n{xrst_toc_hidden\n    speed/example/speed_program.cpp\n}\nThe program :ref:`speed_program.cpp-name` is an example usage\nof ``SpeedTest`` .\n\n{xrst_end SpeedTest}\n-----------------------------------------------------------------------\n*/\n// BEGIN C++\n\n\n# include <string>\n# include <iostream>\n# include <iomanip>\n# include <cppad/core/cppad_assert.hpp>\n\nnamespace CppAD { // BEGIN CppAD namespace\n\ninline void SpeedTestNdigit(size_t value, size_t &ndigit, size_t &pow10)\n{   pow10 = 10;\n    ndigit       = 1;\n    while( pow10 <= value )\n    {   pow10  *= 10;\n        ndigit += 1;\n    }\n}\n\n// implemented as an inline so that can include in multiple link modules\n// with this same file\ninline void SpeedTest(\n    std::string Test(size_t size, size_t repeat),\n    size_t first,\n    int    inc,\n    size_t last\n)\n{\n\n    using std::cout;\n    using std::endl;\n\n    size_t    size;\n    size_t    repeat;\n    size_t    rate;\n    size_t    digit;\n    size_t    ndigit;\n    size_t    pow10;\n    size_t    maxSize;\n    size_t    maxSizeDigit;\n\n    double    s0;\n    double    s1;\n\n    std::string name;\n\n    CPPAD_ASSERT_KNOWN(\n        inc != 0 && first != 0 && last != 0,\n        \"inc, first, or last is zero in call to SpeedTest\"\n    );\n    CPPAD_ASSERT_KNOWN(\n        (inc > 0 && first <= last) || (inc < 0 && first >= last),\n        \"SpeedTest: increment is positive and first > last or \"\n        \"increment is negative and first < last\"\n    );\n\n    // compute maxSize\n    maxSize = size = first;\n    while(  (inc > 0 && size <= last) || (inc < 0 && size >= last) )\n    {\n        if( size > maxSize )\n            maxSize = size;\n\n        // next size\n        if( int(size) + inc > 0 )\n            size = size_t( int(size) + inc );\n        else\n            size  = 0;\n    }\n    SpeedTestNdigit(maxSize, maxSizeDigit, pow10);\n\n    size = first;\n    while(  (inc > 0 && size <= last) || (inc < 0 && size >= last) )\n    {\n        repeat = 1;\n        s0     = elapsed_seconds();\n        s1     = elapsed_seconds();\n        while( s1 - s0 < 1. )\n        {   if( 2 * repeat < repeat )\n            {   // Can't use an assert here because this happens\n                // in release mode first.\n                std::cerr << \"SpeedTest: test function is too fast to time\\n\";\n                std::exit(1);\n            }\n            repeat = 2 * repeat;\n            s0     = elapsed_seconds();\n            name   = Test(size, repeat);\n            s1     = elapsed_seconds();\n        }\n        double r = .5 + double(repeat) / (s1 - s0);\n        // first convert to float to avoid warning with g++ -Wconversion\n        rate     = static_cast<size_t>( static_cast<float>( r ) );\n\n        if( size == first && name != \"\" )\n            cout << name << endl;\n\n        if( first != last )\n        {\n            // convert int(size_t) to avoid warning on _MSC_VER sys\n            std::cout << \"size = \"  << int(size);\n\n            SpeedTestNdigit(size, ndigit, pow10);\n            while( ndigit < maxSizeDigit )\n            {   cout << \" \";\n                ndigit++;\n            }\n            cout << \" \";\n        }\n\n        cout << \"rate = \";\n        SpeedTestNdigit(rate, ndigit, pow10);\n        while( ndigit > 0 )\n        {\n            pow10 /= 10;\n            digit  = rate / pow10;\n\n            // convert int(size_t) to avoid warning on _MSC_VER sys\n            std::cout << int(digit);\n\n            rate    = rate % pow10;\n            ndigit -= 1;\n\n            if( (ndigit > 0) && (ndigit % 3 == 0) )\n                cout << \",\";\n        }\n        cout << endl;\n\n        // next size\n        if( int(size) + inc > 0 )\n            size = size_t( int(size) + inc );\n        else\n            size  = 0;\n    }\n    return;\n}\n\n} // END CppAD namespace\n\n// END C++\n# endif\n"
  },
  {
    "path": "include/cppad/utility/test_boolofvoid.hpp",
    "content": "# ifndef CPPAD_UTILITY_TEST_BOOLOFVOID_HPP\n# define CPPAD_UTILITY_TEST_BOOLOFVOID_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin test_boolofvoid}\n{xrst_spell\n    ipopt\n}\n\nObject that Runs a Group of Tests\n#################################\n\nSyntax\n******\n| # ``include <cppad/utility/test_boolofvoid.hpp>``\n| ``test_boolofvoid`` *Run* ( *group* , *width* )\n| *Run* ( *test* , *name* )\n| *ok* = *Run* . ``summary`` ( *memory_ok* )\n\nPurpose\n*******\nThe object *Run* is used to run a group of tests functions\nand report the results on standard output.\n\ngroup\n*****\nThe argument has prototype\n\n    ``const std::string&`` *group*\n\nIt is the name for this group of tests.\n\nwidth\n*****\nThe argument has prototype\n\n    ``size_t`` *width*\n\nIt is the number of columns used to display the name of each test.\nIt must be greater than the maximum number of characters in a test name.\n\ntest\n****\nThe argument has prototype\n\n    ``bool`` *test* ( ``void`` )\n\nIt is a function that returns true (when the test passes) and false\notherwise.\n\nname\n****\nThe argument has prototype\n\n    ``const std::string&`` *name*\n\nIt is the name for the corresponding *test* .\n\nmemory_ok\n*********\nThe argument has prototype\n\n    ``bool`` *memory_ok*\n\nIt is false if a memory leak is detected (and true otherwise).\n\nok\n**\nThis is true if all of the tests pass (including the memory leak test),\notherwise it is false.\n\nExample\n*******\nSee any of the main programs in the example directory; e.g.,\n``example/ipopt_solve.cpp`` .\n\n{xrst_end test_boolofvoid}\n*/\n\n# include <cppad/core/cppad_assert.hpp>\n# include <string>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n\n/// One class object is used to run a group of tests\nclass test_boolofvoid {\nprivate:\n    /// name for the group of test this object will run\n    const std::string group_;\n    /// number of characters used to display the name for each individual test\n    /// (must be larger than the number of characters in name for each test)\n    const size_t      width_;\n    /// number of tests that have passed\n    size_t            n_ok_;\n    /// number of tests that have failed\n    size_t            n_error_;\n\npublic:\n    /// ctor\n    test_boolofvoid(const std::string& group, size_t width) :\n    group_(group) ,\n    width_(width) ,\n    n_ok_(0)      ,\n    n_error_(0)\n    {   std::cout << \"Begin test group \" << group_ << std::endl; }\n    /// destructor\n    ~test_boolofvoid(void)\n    {   std::cout << \"End test group \" << group_ << std::endl; }\n    /// run one test\n    bool operator()(bool test(void), const std::string& name)\n    {   CPPAD_ASSERT_KNOWN(\n            name.size() < width_ ,\n            \"test_boolofvoid: name does not have less characters than width\"\n        );\n        std::cout.width( int(width_) );\n        std::cout.setf( std::ios_base::left );\n        std::cout << name;\n        //\n        bool ok = test();\n        if( ok )\n        {   std::cout << \"OK\" << std::endl;\n            n_ok_++;\n        }\n        else\n        {   std::cout << \"Error\" << std::endl;\n            n_error_++;\n        }\n        return ok;\n    }\n    /// number of tests that passed\n    size_t n_ok(void) const\n    {   return n_ok_; }\n    /// number of tests that failed\n    size_t n_error(void) const\n    {   return n_error_; }\n    /// summary\n    bool summary(bool memory_ok )\n    {\n        std::cout.width( int(width_) );\n        std::cout.setf( std::ios_base::left );\n        std::cout << \"memory_leak\";\n        //\n        if( memory_ok  )\n        {   std::cout << \"OK\" << std::endl;\n            n_ok_++;\n        }\n        else\n        {   std::cout << \"Error\" << std::endl;\n            n_error_++;\n        }\n        if( n_error_ == 0 )\n            std::cout << \"All \" << n_ok_ << \" tests passed.\" << std::endl;\n        else\n            std::cout << n_error_ << \" tests failed.\" << std::endl;\n        //\n        return n_error_ == 0;\n    }\n};\n\n} // END_CPPAD_NAMESPACE\n\n# endif\n"
  },
  {
    "path": "include/cppad/utility/thread_alloc.hpp",
    "content": "# ifndef CPPAD_UTILITY_THREAD_ALLOC_HPP\n# define CPPAD_UTILITY_THREAD_ALLOC_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <sstream>\n# include <limits>\n# include <memory>\n# include <cstdint>\n\n\n# ifdef _MSC_VER\n// Suppress warning that Microsoft compiler changed its behavior and is now\n// doing the correct thing at the statement:\n//            new(array + i) Type();\n# pragma warning(disable:4345)\n# endif\n\n# include <cppad/core/cppad_assert.hpp>\n# include <cppad/local/define.hpp>\n# include <cppad/local/set_get_in_parallel.hpp>\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\n\\file thread_alloc.hpp\nFile used to define the CppAD multi-threading allocator class\n*/\n\n/*!\n\\def CPPAD_MAX_NUM_CAPACITY\nMaximum number of different capacities the allocator will attempt.\nThis must be larger than the log base two of numeric_limit<size_t>::max().\n*/\n# define CPPAD_MAX_NUM_CAPACITY 100\n\n/*!\n\\def CPPAD_MIN_DOUBLE_CAPACITY\nMinimum number of double values that will fit in an allocation.\n*/\n# define CPPAD_MIN_DOUBLE_CAPACITY 16\n\n/*!\n\\def CPPAD_TRACE_CAPACITY\nIf NDEBUG is not defined, print all calls to get_memory and return_memory\nthat correspond to this capacity and thread CPPAD_TRACE_THREAD.\n(Note that if CPPAD_TRACE_CAPACITY is zero, or any other value not in the list\nof capacities, no tracing will be done.)\n*/\n# define CPPAD_TRACE_CAPACITY 0\n\n/*!\n\\def CPPAD_TRACE_THREAD\nIf NDEBUG is not defined, print all calls to get_memory and return_memory\nthat correspond to this thead and capacity CPPAD_TRACE_CAPACITY.\n*/\n# define CPPAD_TRACE_THREAD 0\n\n/*\nNote that Section 3.6.2 of ISO/IEC 14882:1998(E) states: \"The storage for\nobjects with static storage duration (3.7.1) shall be zero-initialized\n(8.5) before any other initialization takes place.\"\n*/\n\n/*!\nCapacity vector for memory allocation block sizes.\n\nOnly one of these objects should be created and used as a\nstatic variable inside of the thread_alloc::capacity_info function.\n*/\n\n/*!\nAllocator class that works well with an multi-threading environment.\n*/\nclass thread_alloc{\n// ============================================================================\nprivate:\n\n    class capacity_t {\n    public:\n        /// number of capacity values actually used\n        size_t number;\n        /// the different capacity values\n        size_t value[CPPAD_MAX_NUM_CAPACITY];\n        /// ctor\n        capacity_t(void)\n        {   // Cannot figure out how to call thread_alloc::in_parallel here.\n            // CPPAD_ASSERT_UNKNOWN(\n            //    ! thread_alloc::in_parallel() , \"thread_alloc: \"\n            //    \"parallel mode and parallel_setup not yet called.\"\n            // );\n            number           = 0;\n            size_t capacity  = CPPAD_MIN_DOUBLE_CAPACITY * sizeof(double);\n            while( capacity < std::numeric_limits<size_t>::max() / 2 )\n            {   CPPAD_ASSERT_UNKNOWN( number < CPPAD_MAX_NUM_CAPACITY );\n                value[number++] = capacity;\n                // next capactiy is 3/2 times the current one\n                capacity        = 3 * ( (capacity + 1) / 2 );\n            }\n            CPPAD_ASSERT_UNKNOWN( number > 0 );\n        }\n    };\n\n    class block_t {\n    public:\n        /// extra information (currently used by create and delete array)\n        size_t             extra_;\n        /// an index that uniquely identifies both thread and capacity\n        size_t             tc_index_;\n        /// pointer to the next memory allocation with the same tc_index_\n        void*              next_;\n        ///\n        /// Calculated by include/cppad/CMakeLists.txt\n        CPPAD_PADDING_BLOCK_T\n        // -----------------------------------------------------------------\n        /// make default constructor private. It is only used by constructor\n        /// for `root arrays below.\n        block_t(void) : extra_(0), tc_index_(0), next_(nullptr)\n        { }\n    };\n\n    // ---------------------------------------------------------------------\n    /// Vector of fixed capacity values for this allocator\n    static const capacity_t* capacity_info(void)\n    {   CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL;\n        static const capacity_t capacity;\n        return &capacity;\n    }\n    // ---------------------------------------------------------------------\n    /// Structure of information for each thread\n    struct thread_alloc_info {\n        /// count of available bytes for this thread\n        size_t  count_inuse_;\n        /// count of inuse bytes for this thread\n        size_t  count_available_;\n        /// root of available list for this thread and each capacity\n        block_t root_available_[CPPAD_MAX_NUM_CAPACITY];\n        /*!\n        root of inuse list for this thread and each capacity\n        If NDEBUG is defined or CPPAD_DEBUG_AND_RELEASE is true,\n        this memory is not used, but it still helps to separate\n        this structure from the structure for the next thread.\n        */\n        block_t root_inuse_[CPPAD_MAX_NUM_CAPACITY];\n    };\n    // ---------------------------------------------------------------------\n    /*!\n    Set and Get hold available memory flag.\n\n    \\param set [in]\n    if true, the value returned by this return is changed.\n\n    \\param new_value [in]\n    if set is true, this is the new value returned by this routine.\n    Otherwise, new_value is ignored.\n\n    \\return\n    the current setting for this routine (which is initially false).\n    */\n    static bool set_get_hold_memory(bool set, bool new_value = false)\n    {   static bool value = false;\n        if( set )\n            value = new_value;\n        return value;\n    }\n    // ---------------------------------------------------------------------\n    /*!\n    Get pointer to the information for this thread.\n\n    \\param thread [in]\n    Is the thread number for this information pointer.\n\n    \\param clear\n    If clear is true, then the information pointer for this thread\n    is deleted and the nullptr pointer is returned.\n    There must be no memory currently in either the inuse or available\n    lists when this routine is called.\n\n    \\return\n    is the current information pointer for this thread.\n    If clear is false, and the current pointer is nullptr,\n    a new information record is allocated and its pointer returned.\n    In this case, if info is the returned pointer,\n    <code>info->count_inuse == 0</code> and\n    <code>info->count_available == 0</code>.\n    In addition,\n    for <code>c = 0 , ... , CPPAD_MAX_NUM_CAPACITY-1</code>\n    <code>info->root_inuse_[c].next_ == nullptr</code> and\n    <code>info->root_available_[c].next_ == nullptr</code>.\n    */\n    static thread_alloc_info* thread_info(\n        size_t             thread          ,\n        bool               clear = false   )\n    {   static thread_alloc_info* all_info[CPPAD_MAX_NUM_THREADS];\n        static thread_alloc_info  zero_info;\n\n        CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL;\n\n        CPPAD_ASSERT_UNKNOWN( thread < CPPAD_MAX_NUM_THREADS );\n\n        thread_alloc_info* info = all_info[thread];\n        if( clear )\n        {   if( info != nullptr )\n            {\n# ifndef NDEBUG\n                CPPAD_ASSERT_UNKNOWN(\n                    info->count_inuse_     == 0 &&\n                    info->count_available_ == 0\n                );\n                for(size_t c = 0; c < CPPAD_MAX_NUM_CAPACITY; c++)\n                {   CPPAD_ASSERT_UNKNOWN(\n                        info->root_inuse_[c].next_     == nullptr &&\n                        info->root_available_[c].next_ == nullptr\n                    );\n                }\n# endif\n                if( thread != 0 )\n                    ::operator delete( reinterpret_cast<void*>(info) );\n                info             = nullptr;\n                all_info[thread] = info;\n            }\n        }\n        else if( info == nullptr )\n        {   if( thread == 0 )\n                info = &zero_info;\n            else\n            {   size_t size = sizeof(thread_alloc_info);\n                void* v_ptr = ::operator new(size);\n                info        = reinterpret_cast<thread_alloc_info*>(v_ptr);\n            }\n            all_info[thread] = info;\n\n            // initialize the information record\n            for(size_t c = 0; c < CPPAD_MAX_NUM_CAPACITY; c++)\n            {   info->root_inuse_[c].next_       = nullptr;\n                info->root_available_[c].next_   = nullptr;\n            }\n            info->count_inuse_     = 0;\n            info->count_available_ = 0;\n        }\n        return info;\n    }\n    // -----------------------------------------------------------------------\n    /*!\n    Increase the number of bytes of memory that are currently in use; i.e.,\n    that been obtained with get_memory and not yet returned.\n\n    \\param inc [in]\n    amount to increase memory in use.\n\n    \\param thread [in]\n    Thread for which we are increasing the number of bytes in use\n    (must be less than num_threads).\n    During parallel execution, this must be the thread\n    that is currently executing.\n    */\n    static void inc_inuse(size_t inc, size_t thread)\n    {\n        CPPAD_ASSERT_UNKNOWN( thread < num_threads() );\n        CPPAD_ASSERT_UNKNOWN(\n            thread == thread_num() || (! in_parallel())\n        );\n        thread_alloc_info* info = thread_info(thread);\n\n        // do the addition\n        size_t result = info->count_inuse_ + inc;\n        CPPAD_ASSERT_UNKNOWN( result >= info->count_inuse_ );\n\n        info->count_inuse_ = result;\n    }\n    // -----------------------------------------------------------------------\n    /*!\n    Increase the number of bytes of memory that are currently available; i.e.,\n    have been obtained obtained from the system and are being held future use.\n\n    \\copydetails inc_inuse\n    */\n    static void inc_available(size_t inc, size_t thread)\n    {\n        CPPAD_ASSERT_UNKNOWN( thread < CPPAD_MAX_NUM_THREADS);\n        CPPAD_ASSERT_UNKNOWN(\n            thread == thread_num() || (! in_parallel())\n        );\n        thread_alloc_info* info = thread_info(thread);\n        // do the addition\n        size_t result = info->count_available_ + inc;\n        CPPAD_ASSERT_UNKNOWN( result >= info->count_available_ );\n\n        info->count_available_ = result;\n    }\n    // -----------------------------------------------------------------------\n    /*!\n    Decrease the number of bytes of memory that are currently in use; i.e.,\n    that been obtained with get_memory and not yet returned.\n\n    \\param dec [in]\n    amount to decrease number of bytes in use.\n\n    \\param thread [in]\n    Thread for which we are decreasing the number of bytes in use\n    (must be less than num_threads).\n    During parallel execution, this must be the thread\n    that is currently executing.\n    */\n    static void dec_inuse(size_t dec, size_t thread)\n    {\n        CPPAD_ASSERT_UNKNOWN(\n            thread < num_threads() || (! in_parallel())\n        );\n        CPPAD_ASSERT_UNKNOWN(\n            thread == thread_num() || (! in_parallel())\n        );\n        thread_alloc_info* info = thread_info(thread);\n\n        // do the subtraction\n        CPPAD_ASSERT_UNKNOWN( info->count_inuse_ >= dec );\n        info->count_inuse_ = info->count_inuse_ - dec;\n    }\n    // -----------------------------------------------------------------------\n    /*!\n    Decrease the number of bytes of memory that are currently available; i.e.,\n    have been obtained obtained from the system and are being held future use.\n\n    \\copydetails dec_inuse\n    */\n    static void dec_available(size_t dec, size_t thread)\n    {\n        CPPAD_ASSERT_UNKNOWN( thread < CPPAD_MAX_NUM_THREADS);\n        CPPAD_ASSERT_UNKNOWN(\n            thread == thread_num() || (! in_parallel())\n        );\n        thread_alloc_info* info = thread_info(thread);\n        // do the subtraction\n        CPPAD_ASSERT_UNKNOWN( info->count_available_ >= dec );\n        info->count_available_ =  info->count_available_ - dec;\n    }\n\n    // ----------------------------------------------------------------------\n    /*!\n    Set and get the number of threads that are sharing memory.\n\n    \\param number_new\n    If number is zero, we are only retrieving the current maximum\n    number of threads. Otherwise, we are setting and retrieving\n    maximum number of threads.\n\n    \\return\n    the number of threads that are sharing memory.\n    If number_new is non-zero, the return value is equal to\n    number_new.\n    */\n    static size_t set_get_num_threads(size_t number_new)\n    {   static size_t number_user = 1;\n\n        CPPAD_ASSERT_UNKNOWN( number_new <= CPPAD_MAX_NUM_THREADS );\n        CPPAD_ASSERT_UNKNOWN( ! in_parallel() || (number_new == 0) );\n\n        // case where we are changing the number of threads\n        if( number_new != 0 )\n            number_user = number_new;\n\n        return number_user;\n    }\n    /*!\n    Set and call the routine that determine the current thread number.\n\n    \\return\n    returns value for the most recent setting for thread_num_new.\n    If set is true,\n    or the most recent setting is nullptr (its initial value),\n    the return value is zero.\n    Otherwise the routine corresponding to the most recent setting\n    is called and its value returned by set_get_thread_num.\n\n    \\param thread_num_new [in]\n    If set is false, thread_num_new it is not used.\n    Otherwise, the current value of thread_num_new becomes the\n    most recent setting for thread_num.\n\n    \\param set\n    If set is true, then thread_num_new is becomes the most\n    recent setting for this set_get_thread_num.\n    */\n    static size_t set_get_thread_num(\n        size_t (*thread_num_new)(void)  ,\n        bool set = false                )\n    {   static size_t (*thread_num_user)(void) = nullptr;\n\n        if( set )\n        {   thread_num_user = thread_num_new;\n            return 0;\n        }\n\n        if( thread_num_user == nullptr )\n            return 0;\n\n        size_t thread = thread_num_user();\n        CPPAD_ASSERT_KNOWN(\n            thread < set_get_num_threads(0) ,\n            \"parallel_setup: thread_num() >= num_threads\"\n        );\n        return thread;\n    }\n// ============================================================================\npublic:\n/*\n{xrst_begin ta_parallel_setup}\nSetup thread_alloc For Use in Multi-Threading Environment\n#########################################################\n\nSyntax\n******\n| ``thread_alloc::parallel_setup`` ( *num_threads* , *in_parallel* , *thread_num* )\n\nPurpose\n*******\nBy default there is only one thread and all execution is in sequential mode,\ni.e., multiple threads are not sharing the same memory; i.e.\nnot in parallel mode.\n\nSpeed\n*****\nIt should be faster, even when *num_thread* is equal to one,\nfor ``thread_alloc`` to hold onto memory.\nThis can be accomplished using the function call\n\n    ``thread_alloc::hold_memory`` ( ``true`` )\n\nsee :ref:`hold_memory<ta_hold_memory-name>` .\n\nnum_threads\n***********\nThis argument has prototype\n\n    ``size_t`` *num_threads*\n\nand must be greater than zero.\nIt specifies the number of threads that are sharing memory.\nThe case *num_threads*  == 1 is a special case that is\nused to terminate a multi-threading environment.\n\nin_parallel\n***********\nThis function has prototype\n\n    ``bool`` *in_parallel* ( ``void`` )\n\nIt must return ``true`` if there is more than one thread\ncurrently executing.\nOtherwise it can return false.\n\nIn the special case where *num_threads*  == 1 ,\nthe routine *in_parallel* is not used.\n\nthread_num\n**********\nThis function has prototype\n\n    ``size_t`` *thread_num* ( ``void`` )\n\nIt must return a thread number that uniquely identifies the\ncurrently executing thread.\nFurthermore\n\n    0 <= *thread_num* () < *num_threads*\n\n.\nIn the special case where *num_threads*  == 1 ,\nthe routine *thread_num* is not used.\n\nNote that this function is called by other routines so,\nas soon as a new thread is executing,\none must be certain that *thread_num* () will\nwork for that thread.\n\nRestrictions\n************\nThe function ``parallel_setup`` must be called before\nthe program enters :ref:`parallel<ta_in_parallel-name>` execution mode.\nIn addition, this function cannot be called while in parallel mode.\n\nExample\n*******\nThe files\n:ref:`openmp_get_started.cpp-name` ,\n:ref:`bthread_get_started.cpp-name` , and\n:ref:`pthread_get_started.cpp-name` ,\ncontain examples and tests that use this function.\n\n{xrst_end ta_parallel_setup}\n*/\n    /*!\n    Set thread_alloc up for parallel mode usage.\n\n    \\param num_threads [in]\n    Is the number of thread that may be executing at the same time.\n\n    \\param in_parallel [in]\n    Is the routine that determines if we are in parallel mode or not.\n\n    \\param thread_num [in]\n    Is the routine that determines the current thread number\n    (between zero and num_threads minus one).\n    */\n    static void parallel_setup(\n        size_t num_threads         ,\n        bool (*in_parallel)(void)  ,\n        size_t (*thread_num)(void) )\n    {\n        // Special case where we go back to single thread mode right away\n        // (previous settings may no longer be valid)\n        if( num_threads == 1 )\n        {   bool set = true;\n            set_get_num_threads(num_threads);\n            // emphasize that this routine is outside thread_alloc class\n            CppAD::local::set_get_in_parallel(set, nullptr);\n            set_get_thread_num(nullptr, set);\n            return;\n        }\n\n        CPPAD_ASSERT_KNOWN(\n            num_threads <= CPPAD_MAX_NUM_THREADS ,\n            \"parallel_setup: num_threads is too large\"\n        );\n        CPPAD_ASSERT_KNOWN(\n            num_threads != 0 ,\n            \"parallel_setup: num_threads == zero\"\n        );\n        CPPAD_ASSERT_KNOWN(\n            in_parallel != nullptr ,\n            \"parallel_setup: num_threads != 1 and in_parallel == nullptr\"\n        );\n        CPPAD_ASSERT_KNOWN(\n            thread_num != nullptr ,\n            \"parallel_setup: num_threads != 1 and thread_num == nullptr\"\n        );\n\n        // Make sure that constructors for all static variables in this file\n        // are called in sequential mode.\n        for(size_t thread = 0; thread < num_threads; thread++)\n            thread_info(thread);\n        capacity_info();\n        size_t cap_bytes;\n        void* v_ptr = get_memory(0, cap_bytes);\n\n        // free memory allocated by call to get_memory above\n        return_memory(v_ptr);\n        free_available( set_get_thread_num(nullptr) );\n\n        // delay this so thread_num() call above is in previous mode\n        // (current settings may not yet be valid)\n        if( num_threads > 1 )\n        {   bool set = true;\n            set_get_num_threads(num_threads);\n            // emphasize that this routine is outside thread_alloc class\n            CppAD::local::set_get_in_parallel(set, in_parallel);\n            set_get_thread_num(thread_num, set);\n        }\n    }\n/*\n{xrst_begin ta_num_threads}\nGet Number of Threads\n#####################\n\nSyntax\n******\n*number* = ``thread_alloc::num_threads`` ()\n\nPurpose\n*******\nDetermine the number of threads as set during :ref:`parallel_setup<ta_parallel_setup-name>` .\n\nnumber\n******\nThe return value *number* has prototype\n\n    ``size_t`` *number*\n\nand is equal to the value of\n:ref:`ta_parallel_setup@num_threads`\nin the previous call to *parallel_setup* .\nIf there was no such previous call, the value one is returned.\n\nExample\n*******\nThe example and test :ref:`thread_alloc.cpp-name` uses this routine.\n\n{xrst_end ta_num_threads}\n*/\n    /*!\n    Get the current number of threads that thread_alloc can use.\n    */\n    static size_t num_threads(void)\n    {  return set_get_num_threads(0); }\n/* -----------------------------------------------------------------------\n{xrst_begin ta_in_parallel}\n\nIs The Current Execution in Parallel Mode\n#########################################\n\nSyntax\n******\n*flag* = ``thread_alloc::in_parallel`` ()\n\nPurpose\n*******\nSome of the :ref:`thread_alloc-name` allocation routines have different\nspecifications for parallel (not sequential) execution mode.\nThis routine enables you to determine if the current execution mode\nis sequential or parallel.\n\nflag\n****\nThe return value has prototype\n\n    ``bool`` *flag*\n\nIt is true if the current execution is in parallel mode\n(possibly multi-threaded) and false otherwise (sequential mode).\n\nExample\n*******\n:ref:`thread_alloc.cpp-name`\n\n{xrst_end ta_in_parallel}\n*/\n    /// Are we in a parallel execution state; i.e., is it possible that\n    /// other threads are currently executing.\n    static bool in_parallel(void)\n    {  // emphasize that this routine is outside thread_alloc class\n        return CppAD::local::set_get_in_parallel();\n    }\n/* -----------------------------------------------------------------------\n{xrst_begin ta_thread_num}\n\nGet the Current Thread Number\n#############################\n\nSyntax\n******\n*thread* = ``thread_alloc::thread_num`` ()\n\nPurpose\n*******\nSome of the :ref:`thread_alloc-name` allocation routines have a thread number.\nThis routine enables you to determine the current thread.\n\nthread\n******\nThe return value *thread* has prototype\n\n    ``size_t`` *thread*\n\nand is the currently executing thread number.\n\nExample\n*******\n:ref:`thread_alloc.cpp-name`\n\n{xrst_end ta_thread_num}\n*/\n    /// Get current thread number\n    static size_t thread_num(void)\n    {  return set_get_thread_num(nullptr); }\n/* -----------------------------------------------------------------------\n{xrst_begin ta_get_memory}\n\nGet At Least A Specified Amount of Memory\n#########################################\n\nSyntax\n******\n*v_ptr* = ``thread_alloc::get_memory`` ( *min_bytes* , *cap_bytes* )\n\nPurpose\n*******\nUse :ref:`thread_alloc-name` to obtain a minimum number of bytes of memory\n(for use by the :ref:`current thread<ta_thread_num-name>` ).\n\nmin_bytes\n*********\nThis argument has prototype\n\n    ``size_t`` *min_bytes*\n\nIt specifies the minimum number of bytes to allocate.\nThis value must be less than\n::\n\n    std::numeric_limits<size_t>::max() / 2\n\ncap_bytes\n*********\nThis argument has prototype\n\n    ``size_t&`` *cap_bytes*\n\nIt's input value does not matter.\nUpon return, it is the actual number of bytes (capacity)\nthat have been allocated for use,\n\n    *min_bytes* <= *cap_bytes*\n\nv_ptr\n*****\nThe return value *v_ptr* has prototype\n\n    ``void`` * *v_ptr*\n\nIt is the location where the *cap_bytes* of memory\nthat have been allocated for use begins.\n\nAllocation Speed\n****************\nThis allocation should be faster if the following conditions hold:\n\n#. The memory allocated by a previous call to ``get_memory``\n   is currently available for use.\n#. The current *min_bytes* is between\n   the previous *min_bytes* and previous *cap_bytes* .\n\nAlignment\n*********\nWe call a memory allocation aligned if the address is a multiple\nof the number of bytes in a ``size_t`` value.\nIf the system ``new`` allocator is aligned, then *v_ptr*\npointer is also aligned.\n\nExample\n*******\n:ref:`thread_alloc.cpp-name`\n\n{xrst_end ta_get_memory}\n*/\n    /*!\n    Use thread_alloc to get a specified amount of memory.\n\n    If the memory allocated by a previous call to get_memory is now\n    available, and min_bytes is between its previous value\n    and the previous cap_bytes, this memory allocation will have\n    optimal speed. Otherwise, the memory allocation is more complicated and\n    may have to wait for other threads to complete an allocation.\n\n    \\param min_bytes [in]\n    The minimum number of bytes of memory to be obtained for use.\n\n    \\param cap_bytes [out]\n    The actual number of bytes of memory obtained for use.\n\n    \\return\n    pointer to the beginning of the memory allocated for use.\n    */\n    static void* get_memory(size_t min_bytes, size_t& cap_bytes)\n    {   // see first_trace below\n        CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL;\n\n        // check that number of requested bytes is not to large\n        CPPAD_ASSERT_KNOWN(\n            min_bytes < std::numeric_limits<size_t>::max() / 2 ,\n            \"get_memory(min_bytes, cap_bytes): min_bytes is too large\"\n        );\n\n        size_t num_cap = capacity_info()->number;\n        using std::cout;\n        using std::endl;\n\n        // determine the capacity for this request\n        size_t c_index   = 0;\n        const size_t* capacity_vec = capacity_info()->value;\n        while( capacity_vec[c_index] < min_bytes )\n        {   ++c_index;\n            CPPAD_ASSERT_UNKNOWN(c_index < num_cap );\n        }\n        cap_bytes = capacity_vec[c_index];\n\n        // determine the thread, capacity, and info for this thread\n        size_t thread            = thread_num();\n        size_t tc_index          = thread * num_cap + c_index;\n        thread_alloc_info* info  = thread_info(thread);\n\n# ifndef NDEBUG\n        // trace allocation\n        static bool first_trace = true;\n        if( cap_bytes == CPPAD_TRACE_CAPACITY &&\n                 thread    ==  CPPAD_TRACE_THREAD  && first_trace )\n        {   cout << endl;\n            cout << \"thread_alloc: Trace for Thread = \" << thread;\n            cout << \" and capacity = \" << cap_bytes << endl;\n            if( first_trace )\n                first_trace = false;\n        }\n\n# if ! CPPAD_DEBUG_AND_RELEASE\n        // Root nodes for both lists. Note these are different for different\n        // threads because tc_index is different for different threads.\n        block_t* inuse_root     = info->root_inuse_ + c_index;\n# endif\n# endif\n        block_t* available_root = info->root_available_ + c_index;\n\n        // check if we already have a node we can use\n        void* v_node              = available_root->next_;\n        block_t* node             = reinterpret_cast<block_t*>(v_node);\n        if( node != nullptr )\n        {   CPPAD_ASSERT_UNKNOWN( node->tc_index_ == tc_index );\n\n            // remove node from available list\n            available_root->next_ = node->next_;\n\n            // return value for get_memory\n            void* v_ptr = reinterpret_cast<void*>(node + 1);\n# ifndef NDEBUG\n# if ! CPPAD_DEBUG_AND_RELEASE\n            // add node to inuse list\n            node->next_           = inuse_root->next_;\n            inuse_root->next_     = v_node;\n# endif\n\n            // trace allocation\n            if( cap_bytes == CPPAD_TRACE_CAPACITY &&\n                      thread    ==  CPPAD_TRACE_THREAD   )\n            {   cout << \"get_memory:    v_ptr = \" << v_ptr << endl; }\n# endif\n\n            // adjust counts\n            inc_inuse(cap_bytes, thread);\n            dec_available(cap_bytes, thread);\n\n# ifndef NDEBUG\n            // check that pointers and doubles are aligned\n            std::uintptr_t i_ptr = reinterpret_cast<std::uintptr_t>(v_ptr);\n            CPPAD_ASSERT_UNKNOWN( i_ptr % sizeof(v_ptr) == 0 );\n            CPPAD_ASSERT_UNKNOWN( i_ptr % sizeof(double) == 0 );\n# endif\n            // return pointer to memory, do not include block_t at beginning\n            return v_ptr;\n        }\n\n        // Create a new node with thread_alloc information at front.\n        // This uses the system allocator, which is thread safe, but slower,\n        // because the thread might wait for a lock on the allocator.\n        v_node          = ::operator new(sizeof(block_t) + cap_bytes);\n        CPPAD_ASSERT_UNKNOWN( v_node != nullptr );\n        node            = reinterpret_cast<block_t*>(v_node);\n        node->tc_index_ = tc_index;\n        void* v_ptr     = reinterpret_cast<void*>(node + 1);\n\n# ifndef NDEBUG\n# if ! CPPAD_DEBUG_AND_RELEASE\n        // add node to inuse list\n        node->next_       = inuse_root->next_;\n        inuse_root->next_ = v_node;\n# endif\n\n        // trace allocation\n        if( cap_bytes == CPPAD_TRACE_CAPACITY &&\n            thread    == CPPAD_TRACE_THREAD    )\n        {   cout << \"get_memory:    v_ptr = \" << v_ptr << endl; }\n# endif\n\n        // adjust counts\n        inc_inuse(cap_bytes, thread);\n\n        return v_ptr;\n    }\n\n/* -----------------------------------------------------------------------\n{xrst_begin ta_return_memory}\n\nReturn Memory to thread_alloc\n#############################\n\nSyntax\n******\n``thread_alloc::return_memory`` ( *v_ptr* )\n\nPurpose\n*******\nIf :ref:`hold_memory<ta_hold_memory-name>` is false,\nthe memory is returned to the system.\nOtherwise, the memory is retained by :ref:`thread_alloc-name` for quick future use\nby the thread that allocated to memory.\n\nv_ptr\n*****\nThis argument has prototype\n\n    ``void`` * *v_ptr*\n\n.\nIt must be a pointer to memory that is currently in use; i.e.\nobtained by a previous call to\n:ref:`get_memory<ta_get_memory-name>` and not yet returned.\n\nThread\n******\nEither the :ref:`current thread<ta_thread_num-name>` must be the same as during\nthe corresponding call to :ref:`get_memory<ta_get_memory-name>` ,\nor the current execution mode must be sequential\n(not :ref:`parallel<ta_in_parallel-name>` ).\n\nNDEBUG\n******\nIf ``NDEBUG`` is defined, *v_ptr* is not checked (this is faster).\nOtherwise, a list of in use pointers is searched to make sure\nthat *v_ptr* is in the list.\n\nExample\n*******\n:ref:`thread_alloc.cpp-name`\n\n{xrst_end ta_return_memory}\n*/\n    /*!\n    Return memory that was obtained by get_memory.\n    If  <code>num_threads() == 1</code>,\n    the memory is returned to the system.\n    Otherwise, it is retained by thread_alloc and available for use by\n    get_memory for this thread.\n\n    \\param v_ptr [in]\n    Value of the pointer returned by get_memory and still in use.\n    After this call, this pointer will available (and not in use).\n\n    \\par\n    We must either be in sequential (not parallel) execution mode,\n    or the current thread must be the same as for the corresponding call\n    to get_memory.\n    */\n    static void return_memory(void* v_ptr)\n    {   size_t num_cap   = capacity_info()->number;\n\n        block_t* node    = reinterpret_cast<block_t*>(v_ptr) - 1;\n        size_t tc_index  = node->tc_index_;\n        size_t thread    = tc_index / num_cap;\n        size_t c_index   = tc_index % num_cap;\n        size_t capacity  = capacity_info()->value[c_index];\n\n        CPPAD_ASSERT_UNKNOWN( thread < CPPAD_MAX_NUM_THREADS );\n        CPPAD_ASSERT_KNOWN(\n            thread == thread_num() || (! in_parallel()),\n            \"Attempt to return memory for a different thread \"\n            \"while in parallel mode\"\n        );\n\n        thread_alloc_info* info = thread_info(thread);\n# ifndef NDEBUG\n# if ! CPPAD_DEBUG_AND_RELEASE\n        // remove node from inuse list\n        void* v_node         = reinterpret_cast<void*>(node);\n        block_t* inuse_root  = info->root_inuse_ + c_index;\n        block_t* previous    = inuse_root;\n        while( (previous->next_ != nullptr) && (previous->next_ != v_node) )\n            previous = reinterpret_cast<block_t*>(previous->next_);\n\n        // check that v_ptr is valid\n        if( previous->next_ != v_node )\n        {   using std::endl;\n            std::ostringstream oss;\n            oss << \"return_memory: attempt to return memory not in use\";\n            oss << endl;\n            oss << \"v_ptr    = \" << v_ptr    << endl;\n            oss << \"thread   = \" << thread   << endl;\n            oss << \"capacity = \" << capacity << endl;\n            oss << \"See CPPAD_TRACE_THREAD & CPPAD_TRACE_CAPACITY in\";\n            oss << endl << \"# include <cppad/utility/thread_alloc.hpp>\" << endl;\n            // oss.str() returns a string object with a copy of the current\n            // contents in the stream buffer.\n            std::string msg_str       = oss.str();\n            // msg_str.c_str() returns a pointer to the c-string\n            // representation of the string object's value.\n            const char* msg_char_star = msg_str.c_str();\n            CPPAD_ASSERT_KNOWN(false, msg_char_star );\n        }\n        // remove v_ptr from inuse list\n        previous->next_  = node->next_;\n# endif\n        // trace option\n        if( capacity==CPPAD_TRACE_CAPACITY && thread==CPPAD_TRACE_THREAD )\n        {   std::cout << \"return_memory: v_ptr = \" << v_ptr << std::endl; }\n\n# endif\n        // capacity bytes are removed from the inuse pool\n        dec_inuse(capacity, thread);\n\n        // check for case where we just return the memory to the system\n        if( ! set_get_hold_memory(false) )\n        {   ::operator delete( reinterpret_cast<void*>(node) );\n            return;\n        }\n\n        // add this node to available list for this thread and capacity\n        block_t* available_root = info->root_available_ + c_index;\n        node->next_             = available_root->next_;\n        available_root->next_   = reinterpret_cast<void*>(node);\n\n        // capacity bytes are added to the available pool\n        inc_available(capacity, thread);\n    }\n/* -----------------------------------------------------------------------\n{xrst_begin ta_free_available}\n{xrst_spell\n    inuse\n}\n\nFree Memory Currently Available for Quick Use by a Thread\n#########################################################\n\nSyntax\n******\n``thread_alloc::free_available`` ( *thread* )\n\nPurpose\n*******\nReturn to the system all the memory that is currently being\n:ref:`held<ta_hold_memory-name>` for quick use by the specified thread.\n\nExtra Memory\n============\nIn the case where *thread*  > 0 ,\nsome extra memory is used to track allocations by the specified thread.\nIf\n\n    ``thread_alloc::inuse`` ( *thread* ) == 0\n\nthe extra memory is also returned to the system.\n\nthread\n******\nThis argument has prototype\n\n    ``size_t`` *thread*\n\nEither :ref:`thread_num<ta_thread_num-name>` must be the same as *thread* ,\nor the current execution mode must be sequential\n(not :ref:`parallel<ta_in_parallel-name>` ).\n\nExample\n*******\n:ref:`thread_alloc.cpp-name`\n\n{xrst_end ta_free_available}\n*/\n    /*!\n    Return all the memory being held as available for a thread to the system.\n\n    \\param thread [in]\n    this thread that will no longer have any available memory after this call.\n    This must either be the thread currently executing, or we must be\n    in sequential (not parallel) execution mode.\n    */\n    static void free_available(size_t thread)\n    {   CPPAD_ASSERT_KNOWN(\n            thread < CPPAD_MAX_NUM_THREADS,\n            \"Attempt to free memory for a thread >= CPPAD_MAX_NUM_THREADS\"\n        );\n        CPPAD_ASSERT_KNOWN(\n            thread == thread_num() || (! in_parallel()),\n            \"Attempt to free memory for a different thread \"\n            \"while in parallel mode\"\n        );\n\n        size_t num_cap = capacity_info()->number;\n        if( num_cap == 0 )\n            return;\n        const size_t*     capacity_vec  = capacity_info()->value;\n        size_t c_index;\n        thread_alloc_info* info = thread_info(thread);\n        for(c_index = 0; c_index < num_cap; c_index++)\n        {   size_t capacity = capacity_vec[c_index];\n            block_t* available_root = info->root_available_ + c_index;\n            void* v_ptr             = available_root->next_;\n            while( v_ptr != nullptr )\n            {   block_t* node = reinterpret_cast<block_t*>(v_ptr);\n                void* next    = node->next_;\n                ::operator delete(v_ptr);\n                v_ptr         = next;\n\n                dec_available(capacity, thread);\n            }\n            available_root->next_ = nullptr;\n        }\n        CPPAD_ASSERT_UNKNOWN( available(thread) == 0 );\n        if( inuse(thread) == 0 )\n        {   // clear the information for this thread\n            thread_info(thread, true);\n        }\n    }\n/* -----------------------------------------------------------------------\n{xrst_begin ta_hold_memory}\n\nControl When Thread Alloc Retains Memory For Future Use\n#######################################################\n\nSyntax\n******\n``thread_alloc::hold_memory`` ( *value* )\n\nPurpose\n*******\nIt should be faster, even when *num_thread* is equal to one,\nfor ``thread_alloc`` to hold onto memory.\nCalling *hold_memory* with *value* equal to true,\ninstructs ``thread_alloc`` to hold onto memory,\nand put it in the :ref:`available<ta_available-name>` pool,\nafter each call to :ref:`return_memory<ta_return_memory-name>` .\n\nvalue\n*****\nIf *value* is true,\n``thread_alloc`` with hold onto memory for future quick use.\nIf it is false, future calls to :ref:`return_memory<ta_return_memory-name>`\nwill return the corresponding memory to the system.\nBy default (when ``hold_memory`` has not been called)\n``thread_alloc`` does not hold onto memory.\n\nfree_available\n**************\nMemory that is being held by ``thread_alloc`` can be returned\nto the system using :ref:`free_available<ta_free_available-name>` .\n\n{xrst_end ta_hold_memory}\n*/\n    /*!\n    Change the thread_alloc hold memory setting.\n\n    \\param value [in]\n    New value for the thread_alloc hold memory setting.\n    */\n    static void hold_memory(bool value)\n    {   bool set = true;\n        set_get_hold_memory(set, value);\n    }\n\n/* -----------------------------------------------------------------------\n{xrst_begin ta_inuse}\n\nAmount of Memory a Thread is Currently Using\n############################################\n\nSyntax\n******\n*num_bytes* = ``thread_alloc::inuse`` ( *thread* )\n\nPurpose\n*******\nMemory being managed by :ref:`thread_alloc-name` has two states,\ncurrently in use by the specified thread,\nand quickly available for future use by the specified thread.\nThis function informs the program how much memory is in use.\n\nthread\n******\nThis argument has prototype\n\n    ``size_t`` *thread*\n\nEither :ref:`thread_num<ta_thread_num-name>` must be the same as *thread* ,\nor the current execution mode must be sequential\n(not :ref:`parallel<ta_in_parallel-name>` ).\n\nnum_bytes\n*********\nThe return value has prototype\n\n    ``size_t`` *num_bytes*\n\nIt is the number of bytes currently in use by the specified thread.\n\nExample\n*******\n:ref:`thread_alloc.cpp-name`\n\n{xrst_end ta_inuse}\n*/\n    /*!\n    Determine the amount of memory that is currently inuse.\n\n    \\param thread [in]\n    Thread for which we are determining the amount of memory\n    (must be < CPPAD_MAX_NUM_THREADS).\n    During parallel execution, this must be the thread\n    that is currently executing.\n\n    \\return\n    The amount of memory in bytes.\n    */\n    static size_t inuse(size_t thread)\n    {\n        CPPAD_ASSERT_UNKNOWN( thread < CPPAD_MAX_NUM_THREADS);\n        CPPAD_ASSERT_UNKNOWN(\n            thread == thread_num() || (! in_parallel())\n        );\n        thread_alloc_info* info = thread_info(thread);\n        return info->count_inuse_;\n    }\n/* -----------------------------------------------------------------------\n{xrst_begin ta_available}\n\nAmount of Memory Available for Quick Use by a Thread\n####################################################\n\nSyntax\n******\n*num_bytes* = ``thread_alloc::available`` ( *thread* )\n\nPurpose\n*******\nMemory being managed by :ref:`thread_alloc-name` has two states,\ncurrently in use by the specified thread,\nand quickly available for future use by the specified thread.\nThis function informs the program how much memory is available.\n\nthread\n******\nThis argument has prototype\n\n    ``size_t`` *thread*\n\nEither :ref:`thread_num<ta_thread_num-name>` must be the same as *thread* ,\nor the current execution mode must be sequential\n(not :ref:`parallel<ta_in_parallel-name>` ).\n\nnum_bytes\n*********\nThe return value has prototype\n\n    ``size_t`` *num_bytes*\n\nIt is the number of bytes currently available for use by the specified thread.\n\nExample\n*******\n:ref:`thread_alloc.cpp-name`\n\n{xrst_end ta_available}\n*/\n    /*!\n    Determine the amount of memory that is currently available for use.\n\n    \\copydetails inuse\n    */\n    static size_t available(size_t thread)\n    {\n        CPPAD_ASSERT_UNKNOWN( thread < CPPAD_MAX_NUM_THREADS);\n        CPPAD_ASSERT_UNKNOWN(\n            thread == thread_num() || (! in_parallel())\n        );\n        thread_alloc_info* info = thread_info(thread);\n        return info->count_available_;\n    }\n/* -----------------------------------------------------------------------\n{xrst_begin ta_create_array}\n\nAllocate An Array and Call Default Constructor for its Elements\n###############################################################\n\nSyntax\n******\n*array* = ``thread_alloc::create_array<`` *Type* >( *size_min* , *size_out* ) .\n\nPurpose\n*******\nCreate a new raw array using :ref:`thread_alloc-name` memory allocator\n(works well in a multi-threading environment)\nand call default constructor for each element.\n\nType\n****\nThe type of the elements of the array.\n\nsize_min\n********\nThis argument has prototype\n\n    ``size_t`` *size_min*\n\nThis is the minimum number of elements that there can be\nin the resulting *array* .\n\nsize_out\n********\nThis argument has prototype\n\n    ``size_t&`` *size_out*\n\nThe input value of this argument does not matter.\nUpon return, it is the actual number of elements\nin *array*\n( *size_min* <= *size_out* ).\n\narray\n*****\nThe return value *array* has prototype\n\n    *Type* * *array*\n\nIt is array with *size_out* elements.\nThe default constructor for *Type* is used to initialize the\nelements of *array* .\nNote that :ref:`delete_array<ta_delete_array-name>`\nshould be used to destroy the array when it is no longer needed.\n\nDelta\n*****\nThe amount of memory :ref:`inuse<ta_inuse-name>` by the current thread,\nwill increase *delta* where\n\n    ``sizeof`` ( *Type* ) * ( *size_out* + 1) > *delta* >= ``sizeof`` ( *Type* ) * *size_out*\n\nThe :ref:`available<ta_available-name>` memory will decrease by *delta* ,\n(and the allocation will be faster)\nif a previous allocation with *size_min* between its current value\nand *size_out* is available.\n\nAlignment\n*********\nWe call a memory allocation aligned if the address is a multiple\nof the number of bytes in a ``size_t`` value.\nIf the system ``new`` allocator is aligned, then *array*\npointer is also aligned.\n\nExample\n*******\n:ref:`thread_alloc.cpp-name`\n\n{xrst_end ta_create_array}\n*/\n    /*!\n    Use thread_alloc to allocate an array, then call default constructor\n    for each element.\n\n    \\tparam Type\n    The type of the elements of the array.\n\n    \\param size_min [in]\n    The minimum number of elements in the array.\n\n    \\param size_out [out]\n    The actual number of elements in the array.\n\n    \\return\n    pointer to the first element of the array.\n    The default constructor is used to initialize\n    all the elements of the array.\n\n    \\par\n    The extra_ field, in the thread_alloc node before the return value,\n    is set to size_out.\n    */\n    template <class Type>\n    static Type* create_array(size_t size_min, size_t& size_out)\n    {   // minimum number of bytes to allocate\n        size_t min_bytes = size_min * sizeof(Type);\n        // do the allocation\n        size_t num_bytes;\n        void*  v_ptr     = get_memory(min_bytes, num_bytes);\n        // This is where the array starts\n        Type*  array     = reinterpret_cast<Type*>(v_ptr);\n        // number of Type values in the allocation\n        size_out         = num_bytes / sizeof(Type);\n        // store this number in the extra field\n        block_t* node    = reinterpret_cast<block_t*>(v_ptr) - 1;\n        node->extra_     = size_out;\n\n        // call default constructor for each element\n        size_t i;\n        for(i = 0; i < size_out; i++)\n            new(array + i) Type();\n\n        return array;\n    }\n/* -----------------------------------------------------------------------\n{xrst_begin ta_delete_array}\n{xrst_spell\n    deallocate\n}\n\nDeallocate An Array and Call Destructor for its Elements\n########################################################\n\nSyntax\n******\n``thread_alloc::delete_array`` ( *array* ) .\n\nPurpose\n*******\nReturns memory corresponding to an array created by\n(create by :ref:`create_array<ta_create_array-name>` ) to the\n:ref:`available<ta_available-name>` memory pool for the current thread.\n\nType\n****\nThe type of the elements of the array.\n\narray\n*****\nThe argument *array* has prototype\n\n    *Type* * *array*\n\nIt is a value returned by :ref:`create_array<ta_create_array-name>` and not yet deleted.\nThe *Type* destructor is called for each element in the array.\n\nThread\n******\nThe :ref:`current thread<ta_thread_num-name>` must be the\nsame as when :ref:`create_array<ta_create_array-name>` returned the value *array* .\nThere is an exception to this rule:\nwhen the current execution mode is sequential\n(not :ref:`parallel<ta_in_parallel-name>` ) the current thread number does not matter.\n\nDelta\n*****\nThe amount of memory :ref:`inuse<ta_inuse-name>` will decrease by *delta* ,\nand the :ref:`available<ta_available-name>` memory will increase by *delta* ,\nwhere :ref:`ta_create_array@Delta`\nis the same as for the corresponding call to ``create_array`` .\n\nExample\n*******\n:ref:`thread_alloc.cpp-name`\n\n{xrst_end ta_delete_array}\n*/\n    /*!\n    Return Memory Used for an Array to the Available Pool\n    (include destructor call for each element).\n\n    \\tparam Type\n    The type of the elements of the array.\n\n    \\param array [in]\n    A value returned by create_array that has not yet been deleted.\n    The Type destructor is used to destroy each of the elements\n    of the array.\n\n    \\par\n    During parallel execution, the current thread must be the same\n    as during the corresponding call to create_array.\n    */\n    template <class Type>\n    static void delete_array(Type* array)\n    {   // determine the number of values in the array\n        block_t* node = reinterpret_cast<block_t*>(array) - 1;\n        size_t size     = node->extra_;\n\n        // call destructor for each element\n        size_t i;\n        for(i = 0; i < size; i++)\n            (array + i)->~Type();\n\n        // return the memory to the available pool for this thread\n        thread_alloc::return_memory( reinterpret_cast<void*>(array) );\n    }\n/* -----------------------------------------------------------------------\n{xrst_begin ta_free_all}\n\nFree All Memory That Was Allocated for Use by thread_alloc\n##########################################################\n\nSyntax\n******\n*ok* = ``thread_alloc::free_all`` () .\n\nPurpose\n*******\nReturns all memory that was used by ``thread_alloc`` to the system.\n\nok\n**\nThe return value *ok* has prototype\n\n    ``bool`` *ok*\n\nIts value will be ``true`` if all the memory can be freed.\nThis requires that for all *thread* indices, there is no memory\n:ref:`inuse<ta_inuse-name>` ; i.e.,\n\n    0 == ``thread_alloc::inuse`` ( *thread* )\n\nOtherwise, the return value will be false.\n\nRestrictions\n************\nThis function cannot be called while in parallel mode.\n\nExample\n*******\n:ref:`thread_alloc.cpp-name`\n\n{xrst_end ta_free_all}\n*/\n    /*!\n    Return to the system all thread_alloc memory that is not currently inuse.\n\n    \\return\n    If no thread_alloc memory is currently inuse,\n    all memory is returned to the system and the return value is true.\n    Otherwise the return value is false.\n    */\n    static bool free_all(void)\n    {   CPPAD_ASSERT_KNOWN(\n            ! in_parallel(),\n            \"free_all cannot be used while in parallel execution\"\n        );\n        bool ok = true;\n        size_t thread = CPPAD_MAX_NUM_THREADS;\n        while(thread--)\n        {   ok &= inuse(thread) == 0;\n            free_available(thread);\n        }\n        return ok;\n    }\n};\n\n\n} // END_CPPAD_NAMESPACE\n\n// preprocessor symbols local to this file\n# undef CPPAD_MAX_NUM_CAPACITY\n# undef CPPAD_MIN_DOUBLE_CAPACITY\n# undef CPPAD_TRACE_CAPACITY\n# undef CPPAD_TRACE_THREAD\n# endif\n"
  },
  {
    "path": "include/cppad/utility/time_test.hpp",
    "content": "# ifndef CPPAD_UTILITY_TIME_TEST_HPP\n# define CPPAD_UTILITY_TIME_TEST_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin time_test}\n\nDetermine Amount of Time to Execute a Test\n##########################################\n\nSyntax\n******\n| # ``include <cppad/utility/time_test.hpp>``\n| *time* = ``time_test`` ( *test_fun* , *time_min* )\n| *time* = ``time_test`` ( *test_fun* , *time_min* , *test_size* )\n| *time* = ``time_test`` ( *test_fun* , *time_min* , *test_size* , *repeat_out* )\n\nPurpose\n*******\nThe ``time_test`` function executes a timing test\nand reports the amount of wall clock time for execution.\n\nMotivation\n**********\nIt is important to separate small calculation units\nand test them individually.\nThis way individual changes can be tested in the context of the\nroutine that they are in.\nOn many machines, accurate timing of a very short execution\nsequences is not possible.\nIn addition,\nthere may be set up and tear down time for a test that\nwe do not really want included in the timing.\nFor this reason ``time_test``\nautomatically determines how many times to\nrepeat the section of the test that we wish to time.\n\nInclude\n*******\nThe file ``cppad/utility/time_test.hpp`` defines the\n``time_test`` function.\nThis file is included by ``cppad/cppad.hpp``\nand it can also be included separately with out the rest of\nthe ``CppAD`` routines.\n\ntest_fun\n********\nThe ``time_test`` argument *test_fun* is a function,\nor function object.\nIn the case where *test_size* is not present,\n*test_fun* supports the syntax\n\n    *test_fun* ( *repeat* )\n\nIn the case where *test_size* is present,\n*test_fun* supports the syntax\n\n    *test_fun* ( *size* , *repeat* )\n\nIn either case, the return value for *test_fun* is ``void`` .\n\nsize\n====\nIf the argument *size* is present,\nit has prototype\n\n    ``size_t`` *size*\n\nand is equal to the *test_size* argument to ``time_test`` .\n\nrepeat\n======\nThe *test_fun* argument *repeat* has prototype\n\n    ``size_t`` *repeat*\n\nIt specifies the number of times to repeat the test.\n\ntime_min\n********\nThe argument *time_min* has prototype\n\n    ``double`` *time_min*\n\nIt specifies the minimum amount of time in seconds\nthat the repeats of *test_fun* routine should take.\nThe *repeat* argument to *test_fun* is increased\nuntil this amount of execution time (or more) is reached.\n\ntest_size\n*********\nIf this argument is present, it argument has prototype\n\n    ``size_t`` *test_size*\n\nIn this case *test_size* will be present, and have the same value,\nin each call to *test_fun* .\n\nrepeat_out\n**********\nIf this argument is present, it has prototype\n\n    ``size_t&`` *repeat_out*\n\nThis input value of this argument does not matter.\nUpon return, it is the value of :ref:`time_test@test_fun@repeat`\nthat corresponds to the return value *time* ; i.e.,\nthe total time for the repeats of the test is\n\n    *total_time* = *repeat_out* * *time*\n\ntime\n****\nThe return value *time* has prototype\n\n    ``double`` *time*\n\nand is the number of wall clock seconds that it took\nto execute the repeats of *test_fun*\ndivided by the value used for *repeat* .\n\nTiming\n******\nThe routine :ref:`elapsed_seconds-name` will be used to determine the\namount of time it took to execute the test.\n{xrst_toc_hidden\n    include/cppad/utility/elapsed_seconds.hpp\n    speed/example/time_test.cpp\n}\nExample\n*******\nThe routine :ref:`time_test.cpp-name` is an example and test\nof ``time_test`` .\n\n{xrst_end time_test}\n-----------------------------------------------------------------------\n*/\n\n# include <algorithm>\n# include <cstddef>\n# include <cmath>\n# include <cppad/utility/elapsed_seconds.hpp>\n# include <cppad/local/define.hpp>\n\n# define CPPAD_EXTRA_RUN_BEFORE_TIMING 0\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n/*!\n\\file time_test.hpp\n\\brief Function that preforms one timing test (for speed of execution).\n*/\n\n/*!\nPreform one wall clock execution timing test.\n\n\\tparam Test\nEither the type void (*)(size_t)\nor a function object type that supports the same syntax.\n\n\\param test\nThe function, or function object, that supports the operation\ntest(repeat) where repeat is the number of times\nto repeat the tests operation that is being timed.\n\n\\param time_min\nis the minimum amount of time that test should take to preform\nthe repetitions of the operation being timed.\n\n\\return\nis the time for each execution of the test.\n*/\ntemplate <class Test>\ndouble time_test(Test test, double time_min )\n{\n# if CPPAD_EXTRA_RUN_BEFORE_TIMING\n    test(1);\n# endif\n    size_t repeat = 0;\n    double s0     = elapsed_seconds();\n    double s1     = s0;\n    while( s1 - s0 < time_min )\n    {   repeat = std::max(size_t(1), 2 * repeat);\n        s0     = elapsed_seconds();\n        test(repeat);\n        s1     = elapsed_seconds();\n    }\n    double time = (s1 - s0) / double(repeat);\n    return time;\n}\n/*!\nPreform one wall clock execution timing test.\n\n\\tparam Test\nEither the type void (*)(size_t, size_t)\nor a function object type that supports the same syntax.\n\n\\param test\nThe function, or function object, that supports the operation\ntest(size, repeat) where size\nis the size for this test and repeat is the number of times\nto repeat the tests operation that is being timed.\n\n\\param time_min\nis the minimum amount of time that test should take to preform\nthe repetitions of the operation being timed.\n\n\\param test_size\nwill be used for the value of size in the call to test.\n\n\\return\nis the time for each execution of the test.\n*/\ntemplate <class Test>\ndouble time_test(Test test, double time_min, size_t test_size)\n{\n# if CPPAD_EXTRA_RUN_BEFORE_TIMING\n    test(test_size, 1);\n# endif\n    size_t repeat = 0;\n    double s0     = elapsed_seconds();\n    double s1     = s0;\n    while( s1 - s0 < time_min )\n    {   repeat = std::max(size_t(1), 2 * repeat);\n        s0     = elapsed_seconds();\n        test(test_size, repeat);\n        s1     = elapsed_seconds();\n    }\n    double time = (s1 - s0) / double(repeat);\n    return time;\n}\n/*!\nPreform one wall clock execution timing test.\n\n\\tparam Test\nEither the type void (*)(size_t, size_t)\nor a function object type that supports the same syntax.\n\n\\param test\nThe function, or function object, that supports the operation\ntest(size, repeat) where size\nis the size for this test and repeat is the number of times\nto repeat the tests operation that is being timed.\n\n\\param time_min\nis the minimum amount of time that test should take to preform\nthe repetitions of the operation being timed.\n\n\\param test_size\nwill be used for the value of size in the call to test.\n\n\\param repeat_out\nthe return value is the number of times the test was repeated;\ni.e., the return value is the total time divided by repeat.\n\n\\return\nis the time for each execution of the test.\n*/\ntemplate <class Test>\ndouble time_test(\n    Test test, double time_min, size_t test_size, size_t& repeat_out\n)\n{\n# if CPPAD_EXTRA_RUN_BEFORE_TIMING\n    test(test_size, 1);\n# endif\n    repeat_out    = 0;\n    double s0     = elapsed_seconds();\n    double s1     = s0;\n    while( s1 - s0 < time_min )\n    {   repeat_out = std::max(size_t(1), 2 * repeat_out);\n        s0         = elapsed_seconds();\n        test(test_size, repeat_out);\n        s1         = elapsed_seconds();\n    }\n    double time = (s1 - s0) / double(repeat_out);\n    return time;\n}\n\n} // END_CPPAD_NAMESPACE\n\n# undef CPPAD_EXTRA_RUN_BEFORE_TIMING\n// END PROGRAM\n# endif\n"
  },
  {
    "path": "include/cppad/utility/to_string.hpp",
    "content": "# ifndef CPPAD_UTILITY_TO_STRING_HPP\n# define CPPAD_UTILITY_TO_STRING_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin to_string}\n{xrst_spell\n    long long\n    ostringstream\n}\n\nConvert Certain Types to a String\n#################################\n\nSyntax\n******\n| # ``include <cppad/utility/to_string.hpp>``\n| *s* = ``to_string`` ( *value* ) .\n\nSee Also\n********\n:ref:`base_to_string-name` , :ref:`ad_to_string-name`\n\nPurpose\n*******\nThis routine is similar to the C++11 routine ``std::to_string``\nwith the following differences:\n\n#. It works with C++98.\n#. It has been extended to the fundamental floating point types.\n#. It has specifications for extending to an arbitrary type; see\n   :ref:`base_to_string-name` .\n#. If ``<cppad/cppad.hpp>`` is included,\n   and it has been extended to a *Base* type,\n   it automatically extends to the\n   :ref:`AD types above Base<glossary@AD Type Above Base>` .\n#. For integer types, conversion to a string is exact.\n   For floating point types, conversion to a string yields a value\n   that has relative error within machine epsilon.\n\nvalue\n*****\n\nInteger\n=======\nThe argument *value* can have the following prototype\n\n    ``const`` *Integer* & *value*\n\nwhere *Integer* is any of the fundamental integer types; e.g.,\n``short int`` and ``unsigned long`` .\nNote that if C++11 is supported by this compilation,\n``unsigned long long`` is also a fundamental integer type.\n\nFloat\n=====\nThe argument *value* can have the following prototype\n\n    ``const`` *Float* & *value*\n\nwhere *Float* is any of the fundamental floating point types; i.e.,\n``float`` , ``double`` , and ``long double`` .\n\ns\n*\nThe return value has prototype\n\n    ``std::string`` *s*\n\nand contains a representation of the specified *value* .\n\nInteger\n=======\nIf *value* is an ``Integer`` ,\nthe representation is equivalent to ``os`` << ``value``\nwhere *os* is an ``std::ostringstream`` .\n\nFloat\n=====\nIf *value* is a ``Float`` ,\nenough digits are used in the representation so that\nthe result is accurate to within round off error.\n{xrst_toc_hidden\n    example/utility/to_string.cpp\n}\nExample\n*******\nThe file :ref:`to_string.cpp-name`\ncontains an example and test of this routine.\n\n{xrst_end to_string}\n*/\n# include <limits>\n# include <cmath>\n# include <iomanip>\n# include <sstream>\n# include <cppad/core/cppad_assert.hpp>\n\n# define CPPAD_SPECIALIZE_TO_STRING_INTEGER(Type) \\\ntemplate <> struct to_string_struct<Type>\\\n{   std::string operator()(const Type& value) \\\n    {   std::stringstream os;\\\n        os << value;\\\n        return os.str();\\\n    }\\\n};\n\n# define CPPAD_SPECIALIZE_TO_STRING_FLOAT(Float) \\\ntemplate <> struct to_string_struct<Float>\\\n{   std::string operator()(const Float& value) \\\n    {   std::stringstream os;\\\n        int n_digits = 1 + std::numeric_limits<Float>::digits10;\\\n        os << std::setprecision(n_digits);\\\n        os << value;\\\n        return os.str();\\\n    }\\\n};\n\nnamespace CppAD {\n\n    // Default implementation,\n    // each type must define its own specialization.\n    template <class Type>\n    struct to_string_struct\n    {   std::string operator()(const Type& value)\n        {   CPPAD_ASSERT_KNOWN(\n                false,\n                \"to_string is not implemented for this type\"\n            );\n            // return empty string\n            return std::string(\"\");\n        }\n    };\n\n    // specialization for the fundamental integer types\n    CPPAD_SPECIALIZE_TO_STRING_INTEGER(signed short)\n    CPPAD_SPECIALIZE_TO_STRING_INTEGER(unsigned short)\n    //\n    CPPAD_SPECIALIZE_TO_STRING_INTEGER(signed int)\n    CPPAD_SPECIALIZE_TO_STRING_INTEGER(unsigned int)\n    //\n    CPPAD_SPECIALIZE_TO_STRING_INTEGER(signed long)\n    CPPAD_SPECIALIZE_TO_STRING_INTEGER(unsigned long)\n    //\n    CPPAD_SPECIALIZE_TO_STRING_INTEGER(signed long long)\n    CPPAD_SPECIALIZE_TO_STRING_INTEGER(unsigned long long)\n\n    // specialization for the fundamental floating point types\n    CPPAD_SPECIALIZE_TO_STRING_FLOAT(float)\n    CPPAD_SPECIALIZE_TO_STRING_FLOAT(double)\n    CPPAD_SPECIALIZE_TO_STRING_FLOAT(long double)\n\n    // link from function to function object in structure\n    template<class Type>\n    std::string to_string(const Type& value)\n    {   to_string_struct<Type> to_str;\n        return to_str(value);\n    }\n}\n\n# undef CPPAD_SPECIALIZE_TO_STRING_FLOAT\n# undef CPPAD_SPECIALIZE_TO_STRING_INTEGER\n# endif\n"
  },
  {
    "path": "include/cppad/utility/track_new_del.hpp",
    "content": "# ifndef CPPAD_UTILITY_TRACK_NEW_DEL_HPP\n# define CPPAD_UTILITY_TRACK_NEW_DEL_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin track_new_del app}\n{xrst_spell\n    ncopy\n    newlen\n    newptr\n    oldptr\n}\n\nRoutines That Track Use of New and Delete\n#########################################\n\nDeprecated 2007-07-23\n*********************\nAll these routines have been deprecated.\nYou should use the :ref:`thread_alloc-name` memory allocator instead\n(which works better in both a single thread and\nproperly in multi-threading environment).\n\nSyntax\n******\n| # ``include <cppad/utility/track_new_del.hpp>``\n| *newptr* = ``TrackNewVec`` ( *file* , *line* , *newlen* , *oldptr* )\n| ``TrackDelVec`` ( *file* , *line* , *oldptr* )\n| *newptr* = ``TrackExtend`` ( *file* , *line* , *newlen* , *ncopy* , *oldptr* )\n| *count* = ``TrackCount`` ( *file* , *line* )\n\nPurpose\n*******\nThese routines\naid in the use of ``new[]`` and  ``delete[]``\nduring the execution of a C++ program.\n\nInclude\n*******\nThe file ``cppad/utility/track_new_del.hpp`` is included by\n``cppad/cppad.hpp``\nbut it can also be included separately with out the rest of the\nCppAD include files.\n\nfile\n****\nThe argument *file* has prototype\n\n    ``const char`` * *file*\n\nIt should be the source code file name\nwhere the call to ``TrackNew`` is located.\nThe best way to accomplish this is the use the preprocessor symbol\n``__FILE__`` for this argument.\n\nline\n****\nThe argument *line* has prototype\n\n    ``int`` *line*\n\nIt should be the source code file line number\nwhere the call to ``TrackNew`` is located.\nThe best way to accomplish this is the use the preprocessor symbol\n``__LINE__`` for this argument.\n\noldptr\n******\nThe argument *oldptr* has prototype\n\n    *Type* * *oldptr*\n\nThis argument is used to identify the type *Type* .\n\nnewlen\n******\nThe argument *newlen* has prototype\n\n    ``size_t`` *newlen*\n\nhead newptr\n***********\nThe return value *newptr* has prototype\n\n    *Type* * *newptr*\n\nIt points to the newly allocated vector of objects\nthat were allocated using\n\n    ``new Type`` [ *newlen* ]\n\nncopy\n*****\nThe argument *ncopy* has prototype\n\n    ``size_t`` *ncopy*\n\nThis specifies the number of elements that are copied from\nthe old array to the new array.\nThe value of *ncopy*\nmust be less than or equal *newlen* .\n\nTrackNewVec\n***********\nIf ``NDEBUG`` is defined, this routine only sets\n\n    *newptr* = *Type* ``new`` [ *newlen* ]\n\nThe value of *oldptr* does not matter\n(except that it is used to identify *Type* ).\nIf ``NDEBUG`` is not defined, ``TrackNewVec`` also\ntracks the this memory allocation.\nIn this case, if memory cannot be allocated\n:ref:`ErrorHandler-name` is used to generate a message\nstating that there was not sufficient memory.\n\nMacro\n=====\nThe preprocessor macro call\n\n    ``CPPAD_TRACK_NEW_VEC`` ( *newlen* , *oldptr* )\n\nexpands to\n\n    ``CppAD::TrackNewVec`` (__ ``FILE__`` , __ ``LINE__`` , *newlen* , *oldptr* )\n\nPreviously Deprecated\n=====================\nThe preprocessor macro ``CppADTrackNewVec`` is the\nsame as ``CPPAD_TRACK_NEW_VEC`` and was previously deprecated.\n\nTrackDelVec\n***********\nThis routine is used to a vector of objects\nthat have been allocated using ``TrackNew`` or ``TrackExtend`` .\nIf ``NDEBUG`` is defined, this routine only frees memory with\n\n    ``delete`` [] *oldptr*\n\nIf ``NDEBUG`` is not defined, ``TrackDelete`` also checks that\n*oldptr* was allocated by ``TrackNew`` or ``TrackExtend``\nand has not yet been freed.\nIf this is not the case,\n:ref:`ErrorHandler-name` is used to generate an error message.\n\nMacro\n=====\nThe preprocessor macro call\n\n    ``CPPAD_TRACK_DEL_VEC`` ( *oldptr* )\n\nexpands to\n\n    ``CppAD::TrackDelVec`` (__ ``FILE__`` , __ ``LINE__`` , *oldptr* )\n\nPreviously Deprecated\n=====================\nThe preprocessor macro ``CppADTrackDelVec`` is the\nsame as ``CPPAD_TRACK_DEL_VEC`` was previously deprecated.\n\nTrackExtend\n***********\nThis routine is used to\nallocate a new vector (using ``TrackNewVec`` ),\ncopy *ncopy* elements from the old vector to the new vector.\nIf *ncopy* is greater than zero, *oldptr*\nmust have been allocated using ``TrackNewVec`` or ``TrackExtend`` .\nIn this case, the vector pointed to by *oldptr*\nmust be have at least *ncopy* elements\nand it will be deleted (using ``TrackDelVec`` ).\nNote that the dependence of ``TrackExtend`` on ``NDEBUG``\nis indirectly through the routines ``TrackNewVec`` and\n``TrackDelVec`` .\n\nMacro\n=====\nThe preprocessor macro call\n\n    ``CPPAD_TRACK_EXTEND`` ( *newlen* , *ncopy* , *oldptr* )\n\nexpands to\n\n    ``CppAD::TrackExtend`` (__ ``FILE__`` , __ ``LINE__`` , *newlen* , *ncopy* , *oldptr* )\n\nPreviously Deprecated\n=====================\nThe preprocessor macro ``CppADTrackExtend`` is the\nsame as ``CPPAD_TRACK_EXTEND`` and was previously deprecated.\n\nTrackCount\n**********\nThe return value *count* has prototype\n\n    ``size_t`` *count*\n\nIf ``NDEBUG`` is defined, *count* will be zero.\nOtherwise, it will be\nthe number of vectors that\nhave been allocated\n(by ``TrackNewVec`` or ``TrackExtend`` )\nand not yet freed\n(by ``TrackDelete`` ).\n\nMacro\n=====\nThe preprocessor macro call\n\n    ``CPPAD_TRACK_COUNT`` ()\n\nexpands to\n\n    ``CppAD::TrackCount`` (__ ``FILE__`` , __ ``LINE__`` )\n\nPreviously Deprecated\n=====================\nThe preprocessor macro ``CppADTrackCount`` is the\nsame as ``CPPAD_TRACK_COUNT`` and was previously deprecated.\n\nMulti-Threading\n***************\nThese routines cannot be used :ref:`in_parallel<ta_in_parallel-name>`\nexecution mode.\nUse the :ref:`thread_alloc-name` routines instead.\n\n{xrst_end track_new_del}\n------------------------------------------------------------------------------\n*/\n# include <cppad/local/define.hpp>\n# include <cppad/core/cppad_assert.hpp>\n# include <cppad/utility/thread_alloc.hpp>\n# include <sstream>\n# include <string>\n\n# ifndef CPPAD_TRACK_DEBUG\n# define CPPAD_TRACK_DEBUG 0\n# endif\n\n// -------------------------------------------------------------------------\n# define CPPAD_TRACK_NEW_VEC(newlen, oldptr) \\\n    CppAD::TrackNewVec(__FILE__, __LINE__, newlen, oldptr)\n\n# define CPPAD_TRACK_DEL_VEC(oldptr) \\\n    CppAD::TrackDelVec(__FILE__, __LINE__, oldptr)\n\n# define CPPAD_TRACK_EXTEND(newlen, ncopy, oldptr) \\\n    CppAD::TrackExtend(__FILE__, __LINE__, newlen, ncopy, oldptr)\n\n# define CPPAD_TRACK_COUNT() \\\n    CppAD::TrackCount(__FILE__, __LINE__)\n// -------------------------------------------------------------------------\n# define CppADTrackNewVec CPPAD_TRACK_NEW_VEC\n# define CppADTrackDelVec CPPAD_TRACK_DEL_VEC\n# define CppADTrackExtend CPPAD_TRACK_EXTEND\n# define CppADTrackCount  CPPAD_TRACK_COUNT\n// -------------------------------------------------------------------------\nnamespace CppAD { // Begin CppAD namespace\n\n// TrackElement ------------------------------------------------------------\nclass TrackElement {\n\npublic:\n    std::string   file;   // corresponding file name\n    int           line;   // corresponding line number\n    void          *ptr;   // value returned by TrackNew\n    TrackElement *next;   // next element in linked list\n\n    // default constructor (used to initialize root)\n    TrackElement(void)\n    : file(\"\"), line(0), ptr(nullptr), next(nullptr)\n    { }\n\n    TrackElement(const char *f, int l, void *p)\n    : file(f), line(l), ptr(p), next(nullptr)\n    {   CPPAD_ASSERT_UNKNOWN( p != nullptr);\n    }\n\n    // There is only one tracking list and it starts it here\n    static TrackElement *Root(void)\n    {   CPPAD_ASSERT_UNKNOWN( ! thread_alloc::in_parallel() );\n        static TrackElement root;\n        return &root;\n    }\n\n    // Print one tracking element\n    static void Print(TrackElement* E)\n    {\n        CPPAD_ASSERT_UNKNOWN( ! thread_alloc::in_parallel() );\n        using std::cout;\n        cout << \"E = \"         << E;\n        cout << \", E->next = \" << E->next;\n        cout << \", E->ptr  = \" << E->ptr;\n        cout << \", E->line = \" << E->line;\n        cout << \", E->file = \" << E->file;\n        cout << std::endl;\n    }\n\n    // Print the linked list for a thread\n    static void Print(void)\n    {\n        CPPAD_ASSERT_UNKNOWN( ! thread_alloc::in_parallel() );\n        using std::cout;\n        using std::endl;\n        TrackElement *E = Root();\n        // convert int(size_t) to avoid warning on _MSC_VER systems\n        cout << \"Begin Track List\" << endl;\n        while( E->next != nullptr )\n        {   E = E->next;\n            Print(E);\n        }\n        cout << \"End Track List:\" << endl;\n        cout << endl;\n    }\n};\n\n\n// TrackError ----------------------------------------------------------------\ninline void TrackError(\n    const char *routine,\n    const char *file,\n    int         line,\n    const char *msg )\n{\n    CPPAD_ASSERT_UNKNOWN( ! thread_alloc::in_parallel() );\n    std::ostringstream buf;\n    buf << routine\n        << \": at line \"\n        << line\n        << \" in file \"\n        << file\n        << std::endl\n        << msg;\n    std::string str = buf.str();\n    size_t      n   = str.size();\n    size_t i;\n    char *message = new char[n + 1];\n    for(i = 0; i < n; i++)\n        message[i] = str[i];\n    message[n] = '\\0';\n    CPPAD_ASSERT_KNOWN( false , message);\n}\n\n// TrackNewVec ---------------------------------------------------------------\n# ifdef NDEBUG\ntemplate <class Type>\nType *TrackNewVec(\n    const char *file, int line, size_t len, Type * /* oldptr */ )\n{\n# if CPPAD_TRACK_DEBUG\n    static bool first = true;\n    if( first )\n    {   std::cout << \"NDEBUG is defined for TrackNewVec\" << std::endl;\n        first = false;\n    }\n# endif\n    return (new Type[len]);\n}\n\n# else\n\ntemplate <class Type>\nType *TrackNewVec(\n    const char *file          ,\n    int         line          ,\n    size_t      len           ,\n    Type       * /* oldptr */ )\n{\n    CPPAD_ASSERT_KNOWN(\n        ! thread_alloc::in_parallel() ,\n        \"attempt to use TrackNewVec in parallel execution mode.\"\n    );\n    // try to allocate the new memrory\n    Type *newptr = nullptr;\n    try\n    {   newptr = new Type[len];\n    }\n    catch(...)\n    {   TrackError(\"TrackNewVec\", file, line,\n            \"Cannot allocate sufficient memory\"\n        );\n    }\n    // create tracking element\n    void *vptr = static_cast<void *>(newptr);\n    TrackElement *E = new TrackElement(file, line, vptr);\n\n    // get the root\n    TrackElement *root = TrackElement::Root();\n\n    // put this element at the front of linked list\n    E->next    = root->next;\n    root->next = E;\n\n# if CPPAD_TRACK_DEBUG\n    std::cout << \"TrackNewVec: \";\n    TrackElement::Print(E);\n# endif\n\n    return newptr;\n}\n\n# endif\n\n// TrackDelVec --------------------------------------------------------------\n# ifdef NDEBUG\ntemplate <class Type>\nvoid TrackDelVec(const char *file, int line, Type *oldptr)\n{\n# if CPPAD_TRACK_DEBUG\n    static bool first = true;\n    if( first )\n    {   std::cout << \"NDEBUG is defined in TrackDelVec\" << std::endl;\n        first = false;\n    }\n# endif\n      delete [] oldptr;\n}\n\n# else\n\ntemplate <class Type>\nvoid TrackDelVec(\n    const char *file    ,\n    int         line    ,\n    Type       *oldptr  )\n{\n    CPPAD_ASSERT_KNOWN(\n        ! thread_alloc::in_parallel() ,\n        \"attempt to use TrackDelVec in parallel execution mode.\"\n    );\n    TrackElement        *P;\n    TrackElement        *E;\n\n    // search list for pointer\n    P          = TrackElement::Root();\n    E          = P->next;\n    void *vptr = static_cast<void *>(oldptr);\n    while(E != nullptr && E->ptr != vptr)\n    {   P = E;\n        E = E->next;\n    }\n\n    // check if pointer was not in list\n    if( E == nullptr || E->ptr != vptr ) TrackError(\n        \"TrackDelVec\", file, line,\n        \"Invalid value for the argument oldptr.\\n\"\n        \"Possible linking of debug and NDEBUG compilations of CppAD.\"\n    );\n\n# if CPPAD_TRACK_DEBUG\n    std::cout << \"TrackDelVec: \";\n    TrackElement::Print(E);\n# endif\n\n    // remove tracking element from list\n    P->next = E->next;\n\n    // delete allocated pointer\n    delete [] oldptr;\n\n    // delete tracking element\n    delete E;\n\n    return;\n}\n\n# endif\n\n// TrackExtend --------------------------------------------------------------\ntemplate <class Type>\nType *TrackExtend(\n    const char *file    ,\n    int         line    ,\n    size_t      newlen  ,\n    size_t      ncopy   ,\n    Type       *oldptr  )\n{\n    CPPAD_ASSERT_KNOWN(\n        ! thread_alloc::in_parallel() ,\n        \"attempt to use TrackExtend in parallel execution mode.\"\n    );\n\n# if CPPAD_TRACK_DEBUG\n    using std::cout;\n    cout << \"TrackExtend: file = \" << file;\n    cout << \", line = \" << line;\n    cout << \", newlen = \" << newlen;\n    cout << \", ncopy = \" << ncopy;\n    cout << \", oldptr = \" << oldptr;\n    cout << std::endl;\n# endif\n    CPPAD_ASSERT_KNOWN(\n        ncopy <= newlen,\n        \"TrackExtend: ncopy is greater than newlen.\"\n    );\n\n    // allocate the new memrory\n    Type *newptr = TrackNewVec(file, line, newlen, oldptr);\n\n    // copy the data\n    size_t i;\n    for(i = 0; i < ncopy; i++)\n        newptr[i] = oldptr[i];\n\n    // delete the old vector\n    if( ncopy > 0 )\n        TrackDelVec(file, line, oldptr);\n\n    return newptr;\n}\n\n// TrackCount --------------------------------------------------------------\ninline size_t TrackCount(const char *file, int line)\n{\n    CPPAD_ASSERT_KNOWN(\n        ! thread_alloc::in_parallel() ,\n        \"attempt to use TrackCount in parallel execution mode.\"\n    );\n    size_t count = 0;\n    TrackElement *E = TrackElement::Root();\n    while( E->next != nullptr )\n    {   ++count;\n        E = E->next;\n    }\n    return count;\n}\n// ---------------------------------------------------------------------------\n\n} // End CppAD namespace\n\n// preprocessor symbols local to this file\n# undef CPPAD_TRACK_DEBUG\n\n# endif\n"
  },
  {
    "path": "include/cppad/utility/vector.hpp",
    "content": "# ifndef CPPAD_UTILITY_VECTOR_HPP\n# define CPPAD_UTILITY_VECTOR_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n\n# include <cstddef>\n# include <iostream>\n# include <cppad/core/cppad_assert.hpp>\n# include <cppad/utility/check_simple_vector.hpp>\n# include <cppad/utility/thread_alloc.hpp>\n\n// Note that CPPAD_CONST is undefined by cppad_vector_itr.hpp\n# define CPPAD_CONST 0\n# include <cppad/local/utility/cppad_vector_itr.hpp>\n# undef  CPPAD_LOCAL_UTILITY_CPPAD_VECTOR_ITR_HPP\n# define CPPAD_CONST 1\n# include <cppad/local/utility/cppad_vector_itr.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n\n// ==========================================================================\ntemplate <class Type> class vector {\n// ==========================================================================\n/*\n{xrst_begin cppad_vector_member dev}\n\nVector Class: Member Data\n#########################\n\nSyntax\n******\n| *vec* . ``capacity`` ()\n| *vec* . ``size`` ()\n| *vec* . ``data`` ()\n\nType\n****\nis the type of the elements in the array.\n\ncapacity\\_\n**********\nNumber of *Type* elements in ``data_`` that have been allocated\n(and constructor has been called).\n\nlength\\_\n********\nNumber of *Type* elements currently in this vector.\n\ndata\\_\n******\nPointer to the first element of the vector\n(not defined and should not be used when ``capacity_`` is  0).\n\nSource\n******\n{xrst_spell_off}\n{xrst_code hpp} */\nprivate:\n    size_t capacity_;\n    size_t length_;\n    Type*  data_;\npublic:\n    size_t capacity(void) const noexcept\n    {  return capacity_; }\n    size_t size(void) const noexcept\n    {  return length_; }\n    const Type* data(void) const noexcept\n    {  return data_; }\n    Type* data(void) noexcept\n    {  return data_; }\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end cppad_vector_member}\n-----------------------------------------------------------------------------\n{xrst_begin cppad_vector_typedef dev}\n\nVector Class: Type Definitions\n##############################\n\nvalue_type\n**********\ntype corresponding to an element of a vector.\n\niterator\n********\ntype corresponding to an iterator for a vector.\n\nconst_iterator\n**************\ntype corresponding to an iterator for a vector when\nthe vector is ``const`` .\n\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    typedef Type                                         value_type;\n    typedef local::utility::cppad_vector_itr<Type>       iterator;\n    typedef local::utility::const_cppad_vector_itr<Type> const_iterator;\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end cppad_vector_typedef}\n-----------------------------------------------------------------------------\n{xrst_begin cppad_vector_ctor dev}\n{xrst_spell\n    initializer\n}\n\nVector Class: Constructors and Destructor\n#########################################\n\nDefault\n*******\n\n    ``vector`` < *Type* > *vec*\n\ncreates an empty vector no elements and capacity zero.\n\nSizing\n******\n\n|  ``vector`` < *Type* > *vec* ( *n* )\n|  ``vector`` < *Type* > *vec* ( *n* , *value* )\n\nwhere *n* is a ``size_t`` , ``unsigned int`` , or ``int`` .\nThis creates the vector *vec* with *n* elements and capacity\ngreater than or equal *n* .\n\nValue\n=====\nIf *value* is present, it is a *Type* object and all of the\nelements of the vector are given this value.\n\nInitializer List\n****************\n\n    ``vector`` < *Type > *vec* ( { *e_1* , ... , *e_n* } )\n\nCopy\n****\n\n    ``vector`` < *Type* > *vec* ( *other* )\n\nwhere *other* is a ``vector`` < *Type* > ,\ncreates the vector *vec*\nwith *n* = *other* . ``size`` () elements and capacity\ngreater than or equal *n* .\n\nMove Semantics\n**************\nA move semantics version of the copy operator\nis implemented using ``swap`` .\n\nDestructor\n**********\nIf ``capacity_`` is non-zero, call the destructor\nfor all the corresponding elements and then frees the corresponding memory.\n\ndelete_data\n***********\nCall destructor and free all the allocated elements\n(there are ``capacity_`` such elements).\n\nSource\n******\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    // default\n    vector(void) noexcept\n    : capacity_(0), length_(0), data_(nullptr)\n    { }\n    //\n    // sizing\n    vector(size_t n) : capacity_(0), length_(0), data_(nullptr)\n    {  resize(n); }\n# if ! CPPAD_IS_SAME_UNSIGNED_INT_SIZE_T\n    vector(unsigned int n) : capacity_(0), length_(0), data_(nullptr)\n    {  resize(n); }\n# endif\n    vector(int n) : capacity_(0), length_(0), data_(nullptr)\n    {  resize(n); }\n    //\n    // sizing with value\n    vector(size_t n, const Type& value)\n    : capacity_(0), length_(0), data_(nullptr)\n    {  resize(n);\n        for(size_t i = 0; i < length_; ++i)\n            data_[i] = value;\n    }\n# if ! CPPAD_IS_SAME_UNSIGNED_INT_SIZE_T\n    vector(unsigned int n, const Type& value)\n    : capacity_(0), length_(0), data_(nullptr)\n    {  resize(n);\n        for(size_t i = 0; i < length_; ++i)\n            data_[i] = value;\n    }\n# endif\n    vector(int n, const Type& value)\n    : capacity_(0), length_(0), data_(nullptr)\n    {  resize(n);\n        for(size_t i = 0; i < length_; ++i)\n            data_[i] = value;\n    }\n    //\n    // initializer list\n    vector(std::initializer_list<Type> list) :\n    capacity_(0), length_(0), data_(nullptr)\n    {  for(auto itr = list.begin(); itr != list.end(); ++itr)\n            this->push_back(*itr);\n    }\n    //\n    // copy\n    vector(const vector& other) : capacity_(0), length_(0), data_(nullptr)\n    {  resize(other.length_);\n        for(size_t i = 0; i < length_; i++)\n            data_[i] = other.data_[i];\n    }\n    // capacity_ is only value required to make destructor work for other\n    // after this move semantics constructor\n    vector(vector&& other) : capacity_(0), length_(0), data_(nullptr)\n    {  swap(other); }\n    ~vector(void)\n    {  if( capacity_ > 0 ) delete_data(data_); }\nprivate:\n    void delete_data(Type* data_ptr)\n    {  thread_alloc::delete_array(data_ptr); }\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end cppad_vector_ctor}\n-----------------------------------------------------------------------------\n{xrst_begin cppad_vector_size dev}\n\nVector Class: Change Size\n#########################\n\nSyntax\n******\n\n| |tab|  *vec* . ``resize`` ( *n* )\n| |tab| *vec* . ``clear`` ()\n\nn\n*\nis a ``size_t`` , ``unsigned int`` , or ``int`` specifying\nthe number of elements in the new version of the vector.\n\nresize\n******\nIf *n* is less than or equal the input value of\n*vec* . ``capacity_`` ,\nthe only change is that *vec* . ``length_`` is set to *n* .\nOtherwise, new memory is allocated for the vector and\n*vec* . ``length_`` elements are copied from the old vector\nto the new one. I you do not need the old elements, you can first resize\nto zero and then the *n* to avoid copying the elements.\n\nclear\n*****\nThe destructor is called for all the elements of *vec*\nand then *vec.length_* and *vec* . ``capacity_`` are set to zero.\n\n{xrst_end cppad_vector_size}\n------------------------------------------------------------------------------\n*/\npublic:\n# if ! CPPAD_IS_SAME_UNSIGNED_INT_SIZE_T\n    void resize(unsigned int n)\n    {  resize( size_t(n) ); }\n# endif\n    void resize(int n)\n    {  CPPAD_ASSERT_KNOWN(\n            n >= 0,\n            \"CppAD::vector: attempt to create a vector with a negative size.\"\n        );\n        resize( size_t(n) );\n    }\n    void resize(size_t n)\n    {  if( capacity_ < n )\n        {  if( capacity_ == 0 )\n            {  // get new memory and set capacity\n                data_ = thread_alloc::create_array<Type>(n, capacity_);\n            }\n            else\n            {  // save old information\n                Type*  old_data     = data_;\n\n                // get new memory and set capacity\n                data_ = thread_alloc::create_array<Type>(n, capacity_);\n\n                // copy old data\n                for(size_t i = 0; i < length_; ++i)\n                    data_[i] = old_data[i];\n\n                // free old memory\n                thread_alloc::delete_array(old_data);\n            }\n        }\n        length_ = n;\n    }\n    void clear(void)\n    {  length_ = 0;\n        // check if there is old memory to be freed\n        if( capacity_ > 0 )\n            delete_data(data_);\n        capacity_ = 0;\n    }\n/*\n-------------------------------------------------------------------------------\n{xrst_begin cppad_vector_assign dev}\n\nVector Class: Assignment Operators\n##################################\n\nSyntax\n******\n\n    *vec* . ``swap`` ( *other* )\n\n*vec* = *other*\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_SWAP\n    // END_SWAP\n}\n{xrst_literal\n    // BEGIN_MOVE_ASSIGN\n    // END_MOVE_ASSIGN\n}\n{xrst_literal\n    // BEGIN_ASSIGN\n    // END_ASSIGN\n}\n\nswap\n****\nSwaps ``length_`` , ``capacity_`` and ``data_``\nbetween *vec* and *other* .\n\nAssignment\n**********\nsee :ref:`user API assignment<CppAD_vector@Assignment>`\n\nMove Semantics\n**************\nThe move semantics version of the assignment operator\nis implemented using ``swap`` .\n\n{xrst_end cppad_vector_assign}\n-------------------------------------------------------------------------------\n*/\n// BEGIN_SWAP\npublic:\n    // swap does not do any allocation and hence is declared noexcept\n    void swap(vector& other) noexcept\n// END_SWAP\n    {  // special case where vec and other are the same vector\n         if( this == &other )\n            return;\n        //\n        std::swap(length_,   other.length_   );\n        std::swap(capacity_, other.capacity_ );\n        std::swap(data_,     other.data_     );\n        return;\n    }\n\n// BEGIN_MOVE_ASSIGN\n    // move assignment does not doe any allocation and hence is declared noexcept\n    vector& operator=(vector&& other) noexcept\n// END_MOVE_ASSIGN\n    {  swap(other);\n        return *this;\n    }\n\n// BEGIN_ASSIGN\n    vector& operator=(const vector& other)\n// END_ASSIGN\n    {  // avoid copying old elements\n        resize(0);\n        // new size for this vector\n        resize( other.length_ );\n        // copy elements from other\n        for(size_t i = 0; i < length_; i++)\n            data_[i] = other.data_[i];\n        return *this;\n    }\n/*\n-------------------------------------------------------------------------------\n{xrst_begin cppad_vector_compare dev}\n{xrst_spell\n}\n\nVector Class: Comparison Operators\n##################################\n\nSyntax\n******\n\n|  *result* = *vec* *op* *other*\n\nwhere *op* is one of the following: == , != , < , <= , > , >= .\n\nPrototype\n*********\n{xrst_literal ,\n    // BEGIN_EQUAL, // END_EQUAL\n    // BEGIN_NOT_EQUAL, // END_NOT_EQUAL\n    // BEGIN_LESS_THAN, // END_LESS_THAN\n    // BEGIN_LESS_OR_EQUAL, // END_LESS_OR_EQUAL\n    // BEGIN_GREATER_THAN, // END_GREATER_THAN\n    // BEGIN_GREATER_OR_EQUAL, // END_GREATER_OR_EQUAL\n}\n\nvec\n***\nis the left side for the comparison operation.\n\nother\n*****\nis the right side for the comparison operation.\nThis vector must have the same size as *vec* .\n\nresult\n******\nThe *result* is true if the comparison\n\n|  *vec* [ *i* ] *op* *other [ *i* ]\n\ntrue for all valid indices *i* .  Otherwise, the *result* is false\n\n{xrst_end cppad_vector_compare}\n-------------------------------------------------------------------------------\n*/\n// BEGIN_EQUAL\npublic:\n    bool operator==(const vector& other) const\n// END_EQUAL\n    {  bool result = true;\n        CPPAD_ASSERT_KNOWN(\n            length_ == other.length_ ,\n            \"CppAD::vector: vec == other: size of vectors is different\"\n        );\n        for(size_t i = 0; i < length_; ++i)\n            result &= data_[i] == other.data_[i];\n        return result;\n    }\n// BEGIN_NOT_EQUAL\n    bool operator!=(const vector& other) const\n// END_NOT_EQUAL\n    {  bool result = true;\n        CPPAD_ASSERT_KNOWN(\n            length_ == other.length_ ,\n            \"CppAD::vector: vec == other: size of vectors is different\"\n        );\n        for(size_t i = 0; i < length_; ++i)\n            result &= data_[i] != other.data_[i];\n        return result;\n    }\n// BEGIN_LESS_THAN\n    bool operator<(const vector& other) const\n// END_LESS_THAN\n    {  bool result = true;\n        CPPAD_ASSERT_KNOWN(\n            length_ == other.length_ ,\n            \"CppAD::vector: vec == other: size of vectors is different\"\n        );\n        for(size_t i = 0; i < length_; ++i)\n            result &= data_[i] < other.data_[i];\n        return result;\n    }\n// BEGIN_LESS_OR_EQUAL\n    bool operator<=(const vector& other) const\n// END_LESS_OR_EQUAL\n    {  bool result = true;\n        CPPAD_ASSERT_KNOWN(\n            length_ == other.length_ ,\n            \"CppAD::vector: vec == other: size of vectors is different\"\n        );\n        for(size_t i = 0; i < length_; ++i)\n            result &= data_[i] <= other.data_[i];\n        return result;\n    }\n// BEGIN_GREATER_THAN\n    bool operator>(const vector& other) const\n// END_GREATER_THAN\n    {  bool result = true;\n        CPPAD_ASSERT_KNOWN(\n            length_ == other.length_ ,\n            \"CppAD::vector: vec == other: size of vectors is different\"\n        );\n        for(size_t i = 0; i < length_; ++i)\n            result &= data_[i] > other.data_[i];\n        return result;\n    }\n// BEGIN_GREATER_OR_EQUAL\n    bool operator>=(const vector& other) const\n// END_GREATER_OR_EQUAL\n    {  bool result = true;\n        CPPAD_ASSERT_KNOWN(\n            length_ == other.length_ ,\n            \"CppAD::vector: vec == other: size of vectors is different\"\n        );\n        for(size_t i = 0; i < length_; ++i)\n            result &= data_[i] >= other.data_[i];\n        return result;\n    }\n/*\n-------------------------------------------------------------------------------\n{xrst_begin cppad_vector_subscript dev}\n\nVector Class: Subscript Operator\n################################\n\nSyntax\n******\n\n| *element* = *vec* [ *i* ]\n| *vec* [ *i* ] = *element*\n\nSource\n******\n{xrst_spell_off}\n{xrst_code hpp} */\n    const Type& operator[]( size_t i) const\n    {  CPPAD_ASSERT_KNOWN( i < length_,\n            \"vector: index greater than or equal vector size\"\n        );\n        return data_[i];\n    }\n    Type& operator[](size_t i)\n    {  CPPAD_ASSERT_KNOWN(i < length_,\n            \"vector: index greater than or equal vector size\"\n        );\n        return data_[i];\n    }\n    template <class Index> const Type& operator[]( Index i) const\n    {  return (*this)[size_t(i)]; }\n    template <class Index> Type& operator[](Index i)\n    {  return (*this)[size_t(i)]; }\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end cppad_vector_subscript}\n-------------------------------------------------------------------------------\n{xrst_begin cppad_vector_push_back dev}\n\nVector Class: push_back\n#######################\n\nSyntax\n******\n*vec* . ``push_back`` ( *element* )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_PUSH_BACK\n    // END_PUSH_BACK\n}\n\nDocumentation\n*************\nsee :ref:`use API push_back<cppad_vector_push_back-name>`\n\n{xrst_end cppad_vector_push_back}\n*/\n// BEGIN_PUSH_BACK\n    void push_back(const Type& element)\n// END_PUSH_BACK\n    {  // case where no allocation is necessary\n        if( length_ < capacity_ )\n        {  data_[length_++] = element;\n            return;\n        }\n        CPPAD_ASSERT_UNKNOWN( length_ == capacity_ );\n\n        // create new vector with required size\n        vector vec(length_ + 1);\n\n        // copy old data values\n        for(size_t i = 0; i < length_; ++i)\n            vec.data_[i] = data_[i];\n\n        // put the new element in the new vector\n        CPPAD_ASSERT_UNKNOWN( vec.length_ == length_ + 1);\n        vec.data_[length_] = element;\n\n        // swap old and new vectors\n        swap(vec);\n    }\n/* %$$\n-------------------------------------------------------------------------------\n{xrst_begin cppad_vector_push_vector dev}\n\nVector Class: push_vector\n#########################\n\nSyntax\n******\n*vec* . ``push_vector`` ( *other* )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_PUSH_VECTOR\n    // END_PUSH_VECTOR\n}\n\nDocumentation\n*************\nsee :ref:`use API push_vector<cppad_vector_push_vector-name>`\n\n{xrst_end cppad_vector_push_vector}\n*/\n// BEGIN_PUSH_VECTOR\n    template <class Vector> void push_vector(const Vector& other)\n// END_PUSH_VECTOR\n    {  // can not use push_back because MS V++ 7.1 did not resolve\n        // to non-template member function when scalar is used.\n        //\n        CheckSimpleVector<Type, Vector>();\n        size_t m = other.size();\n\n        // case where no allocation is necessary\n        if( length_ + m <= capacity_ )\n        {  for(size_t i = 0; i < m; i++)\n                data_[length_++] = other[i];\n            return;\n        }\n\n        // create new vector with required size\n        vector vec(length_ + m);\n\n        // copy old data values\n        for(size_t i = 0; i < length_; ++i)\n            vec.data_[i] = data_[i];\n\n        // put the new elements in the new vector\n        CPPAD_ASSERT_UNKNOWN( vec.length_ == length_ + m );\n        for(size_t i = 0; i < m; i++)\n            vec.data_[length_ + i] = other[i];\n\n        // swap old and new vectors\n        swap(vec);\n    }\n/*\n------------------------------------------------------------------------------\n{xrst_begin cppad_vector_itr_fun dev}\n\nVector Class: Iterator Functions\n################################\n\nSyntax\n******\n\n| ``os`` *vec* . ``begin`` ()\n| *os* ``vec`` . *end* ()\n\nSource\n******\n{xrst_spell_off}\n{xrst_code hpp} */\n    const_iterator begin(void) const noexcept\n    {    return const_iterator(&data_, &length_, 0); }\n    const_iterator end(void) const noexcept\n    {  typedef typename const_iterator::difference_type difference_type;\n        difference_type index = static_cast<difference_type>(length_);\n        return const_iterator(&data_, &length_, index);\n    }\n    //\n    iterator begin(void) noexcept\n    {    return iterator(&data_, &length_, 0); }\n    iterator end(void) noexcept\n    {  typedef typename iterator::difference_type difference_type;\n        difference_type index = static_cast<difference_type>(length_);\n        return iterator(&data_, &length_, index);\n    }\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end cppad_vector_itr_fun}\n*/\n\n// =========================================================================\n};  // END_TEMPLATE_CLASS_VECTOR\n// =========================================================================\n\n/*\n{xrst_begin cppad_vector_output dev}\n\nVector Class: Output\n####################\n\nSyntax\n******\n*os* << ``vec``\n\nSource\n******\n{xrst_spell_off}\n{xrst_code hpp} */\ntemplate <class Type>\nstd::ostream& operator << (std::ostream&  os , const CppAD::vector<Type>& vec )\n{  os << \"{ \";\n    for(size_t i = 0; i < vec.size(); ++i)\n    {  os << vec[i];\n        if( i + 1 < vec.size() )\n            os << \", \";\n    }\n    os << \" }\";\n    return os;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end cppad_vector_output}\n*/\n\n} // END_CPPAD_NAMESPACE\n\n// user API specifies that vector_bool.hpp is included by vector.hpp\n# include <cppad/utility/vector_bool.hpp>\n\n# endif\n"
  },
  {
    "path": "include/cppad/utility/vector_bool.hpp",
    "content": "# ifndef CPPAD_UTILITY_VECTOR_BOOL_HPP\n# define CPPAD_UTILITY_VECTOR_BOOL_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n\n# include <cstddef>\n# include <iostream>\n# include <limits>\n# include <cppad/core/cppad_assert.hpp>\n# include <cppad/utility/check_simple_vector.hpp>\n# include <cppad/utility/thread_alloc.hpp>\n# include <cppad/local/utility/vector_bool.hpp>\n\nnamespace CppAD { // BEGIN_CPPAD_NAMESPACE\n\n// ============================================================================\nclass vectorBool {\n// ============================================================================\n/*\n{xrst_begin vector_bool_member dev}\n\nvectorBool: Member Data\n#######################\n\nSyntax\n******\n| *vec* . ``unit_min`` ()\n| *vec* . ``bit_per_unit`` ()\n\nunit_t\n******\nType used to pack multiple boolean (bit) values into one unit.\nLogical operations are preformed one unit at a time.\n\nbit_per_unit\\_\n**************\nnumber of bits packed into each unit value in ``data_`` .\n\nn_unit\\_\n********\nNumber of unit values in ``data_`` .\n\nlength\\_\n********\nnumber of bits currently stored in this vector.\n\ndata\\_\n******\npointer to where the bits are stored.\n\nunit_min\n********\nminimum number of ``unit_t`` values that can store ``length_`` bits.\nNote that this is really a function of ``length_`` .\n\nsize\n****\nis the number of boolean elements in the vector.\n\ncapacity\n********\nis the maximum number of boolean elements that will fit in the\ncurrent allocation for ``data_`` .\n\nSource\n******\n{xrst_spell_off}\n{xrst_code hpp} */\nprivate:\n    typedef size_t unit_t;\n    static const size_t bit_per_unit_ = std::numeric_limits<unit_t>::digits;\n    size_t    n_unit_;\n    size_t    length_;\n    unit_t    *data_;\n    //\n    size_t unit_min(void) const\n    {  if( length_ == 0 )\n            return 0;\n        return (length_ - 1) / bit_per_unit_ + 1;\n    }\npublic:\n    static size_t bit_per_unit(void)\n    {  return bit_per_unit_; }\n    size_t size(void) const\n    {  return length_; }\n    size_t capacity(void) const\n    {  return n_unit_ * bit_per_unit_; }\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end vector_bool_member}\n-------------------------------------------------------------------------------\n{xrst_begin vector_bool_typedef dev}\n\nvectorBool Type Definitions\n###########################\n\nvalue_type\n**********\ntype corresponding to the elements of this vector\n(note that non-const elements actually use\n:ref:`vectorBoolElement<vector_bool_element-name>` ).\n\nSource\n******\n{xrst_spell_off}\n{xrst_code hpp} */\npublic:\n    typedef bool value_type;\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end vector_bool_typedef}\n----------------------------------------------------------------------------\n{xrst_begin vector_bool_ctor dev}\n{xrst_spell\n    initializer\n}\nvectorBool: Constructors and Destructor\n#######################################\n\nDefault\n*******\n\n    ``vectorBool`` *vec*\n\ncreates an empty vector with no elements and ``n_unit_`` zero.\n\nSizing\n******\n\n    ``vectorBool`` *vec* ( *n* )\n\nwhere *n* is a ``size_t`` ,\ncreates the vector *vec* with *n* elements and ``n_unit_``\ngreater than or equal ``unit_min()`` .\n\nInitializer\n***********\n\n    ``vectorBool`` *vec* ( { *b_1* , ... , *b_n* } )\n\n\nCopy\n****\n\n    ``vector`` < *Type* > *vec* ( *other* )\n\nwhere *other* is a ``vector`` < *Type* > ,\ncreates the vector *vec*\nwith *n* = *other* . ``size`` () elements and ``n_unit_``\ngreater than or equal ``unit_min()`` .\n\nDestructor\n**********\nIf ``n_unit_`` is non-zero, the memory corresponding to ``data_``\nis returned to thread_alloc.\n\nSource\n******\n{xrst_spell_off}\n{xrst_code hpp}:\n*/\n    // default\n    vectorBool(void) : n_unit_(0), length_(0), data_(nullptr)\n    { }\n    //\n    // sizing\n    vectorBool(size_t n) : n_unit_(0), length_(0), data_(nullptr)\n    {  resize(n); }\n    vectorBool(int n) : n_unit_(0), length_(0), data_(nullptr)\n    {  resize( size_t(n) ); }\n# if ! CPPAD_IS_SAME_UNSIGNED_INT_SIZE_T\n    vectorBool(unsigned int n) : n_unit_(0), length_(0), data_(nullptr)\n    {  resize( size_t(n) ); }\n# endif\n    //\n    // copy\n    vectorBool(const vectorBool& other)\n    : n_unit_(0), length_(0), data_(nullptr)\n    {  resize(other.length_);\n        size_t n_used = unit_min();\n        CPPAD_ASSERT_UNKNOWN( n_used <= n_unit_ );\n        for(size_t i = 0; i < n_used; ++i)\n            data_[i] = other.data_[i];\n    }\n    vectorBool(std::initializer_list<bool> list)\n    : n_unit_(0), length_(0), data_(nullptr)\n    {  for(auto itr = list.begin(); itr != list.end(); ++itr)\n            this->push_back(*itr);\n    }\n    // n_unit_ is the only value necessary to make destructor work\n    // for other after this move semantics constructor\n    vectorBool(vectorBool&& other)\n    : n_unit_(0), length_(0), data_(nullptr)\n    {  swap(other); }\n    ~vectorBool(void)\n    {  clear(); }\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end vector_bool_ctor}\n-----------------------------------------------------------------------------\n{xrst_begin vector_bool_size dev}\n\nvectorBool: Change Size\n#######################\n\nSyntax\n******\n\n| |tab| *vec* . ``resize`` ( *n* )\n| |tab| *vec* . ``clear`` ()\n\nn\n*\nis a ``size_t`` or ``int`` specifying\nthe number of elements in the new version of the vector.\n\nresize\n******\nIf *n* is less than or equal the input value of\n*vec* . ``n_unit_`` times *vec* . ``bit_per_unit_`` ,\nthe only change is that *vec* . ``length_`` is set to *n* .\nOtherwise the old elements are freed and a new vector is created\nwith *vec* . ``length_`` equal to *n* .\n\nclear\n*****\nthe memory allocated for this vector is freed and\n*vec.length_* and *vec* . ``n_unit_`` are set to zero.\n\n{xrst_end vector_bool_size}\n------------------------------------------------------------------------------\n*/\n// BEGIN_RESIZE\npublic:\n# if ! CPPAD_IS_SAME_UNSIGNED_INT_SIZE_T\n    void resize(unsigned int n)\n    {  resize( size_t(n) );\n    }\n# endif\n    void resize(int n)\n    {  CPPAD_ASSERT_KNOWN(\n            n >= 0,\n            \"CppAD::vector: attempt to create a vector with a negative size.\"\n        );\n        resize( size_t(n) );\n    }\n    void resize(size_t n)\n// END_RESIZE\n    {  length_ = n;\n        // check if we can use the current memory\n        size_t min_unit = unit_min();\n        if( n_unit_ >= min_unit )\n            return;\n        // check if there is old memory to be freed\n        if( n_unit_ > 0 )\n        {  void* v_ptr = reinterpret_cast<void*>(data_);\n            thread_alloc::return_memory(v_ptr);\n        }\n        // get new memory and set n_unit\n        size_t min_bytes = min_unit * sizeof(unit_t);\n        size_t cap_bytes;\n        void* v_ptr = thread_alloc::get_memory(min_bytes, cap_bytes);\n        data_       = reinterpret_cast<unit_t*>(v_ptr);\n        n_unit_     = cap_bytes / sizeof(unit_t);\n        CPPAD_ASSERT_UNKNOWN( n_unit_ >= min_unit );\n    }\n// BEGIN_CLEAR\n    void clear(void)\n// END_CLEAR\n    {\n        // check if there is old memory to be freed\n        if( n_unit_ > 0 )\n        {  void* v_ptr = reinterpret_cast<void*>(data_);\n            thread_alloc::return_memory(v_ptr);\n        }\n        length_ = 0;\n        n_unit_ = 0;\n    }\n/*\n-------------------------------------------------------------------------------\n{xrst_begin vector_bool_assign dev}\n\nvectorBool: Assignment Operators\n################################\n\nSyntax\n******\n\n| |tab| *vec* . ``swap`` ( *other* )\n| |tab| *vec* = *other*\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_SWAP\n    // END_SWAP\n}\n{xrst_literal\n    // BEGIN_ASSIGN\n    // END_ASSIGN\n}\n{xrst_literal\n    // BEGIN_MOVE_SEMANTICS\n    // END_MOVE_SEMANTICS\n}\n\nswap\n****\nSwaps ``n_unit_`` , ``length_`` and ``data_``\nbetween *vec* and *other* .\n\nAssignment\n**********\nIf the input value of *vec* . ``length_`` is zero,\n:ref:`vector_bool_size@resize` is used to change its size to\nbe the same as other.\nThe size of *vec* and *other* are then compared and if\ndifferent, an assert with a know cause is generated.\nThe elements of *vec* are then individually assigned\nto have the value of the corresponding elements of *other* .\n\nMove Semantics\n**************\nA move semantics version of the assignment operator, implemented using\n``swap`` , is defined.\n\n{xrst_end vector_bool_assign}\n-------------------------------------------------------------------------------\n*/\n// BEGIN_SWAP\n    void swap(vectorBool& other)\n// END_SWAP\n    {  // swap with self case\n         if( this == &other )\n            return;\n        std::swap(n_unit_,   other.n_unit_   );\n        std::swap(length_,   other.length_   );\n        std::swap(data_,     other.data_     );\n        return;\n    }\n// BEGIN_ASSIGN\n    vectorBool& operator=(const vectorBool& other)\n// END_ASSIGN\n    {  // If original length is zero, then resize it to other.\n        // Otherwise a length mismatch is an error.\n        if( length_ == 0 )\n            resize( other.length_ );\n        CPPAD_ASSERT_KNOWN(\n            length_ == other.length_ ,\n            \"vectorBool: size miss match in assignment operation\"\n        );\n        size_t n_used = unit_min();\n        CPPAD_ASSERT_UNKNOWN( n_used <= n_unit_ );\n        for(size_t i = 0; i < n_used; i++)\n            data_[i] = other.data_[i];\n        return *this;\n    }\n// BEGIN_MOVE_SEMANTICS\n    vectorBool& operator=(vectorBool&& other)\n// END_MOVE_SEMANTICS\n    {  CPPAD_ASSERT_KNOWN(\n            length_ == other.length_ || (length_ == 0),\n            \"vectorBool: size miss match in assignment operation\"\n        );\n        swap(other);\n        return *this;\n    }\n/*\n-------------------------------------------------------------------------------\n{xrst_begin vector_bool_subscript dev}\n\nvectorBool: Subscript Operator\n##############################\n\nSyntax\n******\n\n| *target* = *vec* [ *i* ]\n| *vec* [ *i* ] = *source*\n\ntarget\n******\nIn this syntax *vec* is ``const``\nand the value *vec* [ *i* ] is a ``bool`` .\n\nsource\n******\nIn this syntax *vec* is not ``const``\nand the value *vec* [ *i* ] is a\n:ref:`vectorBoolElement<vector_bool_element-name>` .\n\nSource Code\n***********\n{xrst_spell_off}\n{xrst_code hpp} */\n    bool operator[](size_t i) const\n    {  CPPAD_ASSERT_KNOWN( i < length_,\n            \"vectorBool: index greater than or equal vector size\"\n        );\n        size_t unit_index   = i / bit_per_unit_;\n        size_t bit_index    = i - unit_index * bit_per_unit_;\n        unit_t unit         = data_[unit_index];\n        unit_t mask         = unit_t(1) << bit_index;\n        return (unit & mask) != 0;\n    }\n    local::utility::vectorBoolElement operator[](size_t i)\n    {  CPPAD_ASSERT_KNOWN( i < length_,\n            \"vectorBool: index greater than or equal vector size\"\n        );\n        size_t unit_index   = i / bit_per_unit_;\n        size_t bit_index    = i - unit_index * bit_per_unit_;\n        unit_t mask         = unit_t(1) << bit_index;\n        return local::utility::vectorBoolElement(data_ + unit_index , mask);\n    }\n    template <class Index> bool operator[]( Index i) const\n    {  return (*this)[size_t(i)]; }\n    template <class Index>\n    local::utility::vectorBoolElement operator[](Index i)\n    {  return (*this)[size_t(i)]; }\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end vector_bool_subscript}\n-------------------------------------------------------------------------------\n{xrst_begin vector_bool_push_back dev}\n\nvectorBool: push_back\n#####################\n\nSyntax\n******\n*vec* . ``push_back`` ( *element* )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_PUSH_BACK\n    // END_PUSH_BACK\n}\n\nDocumentation\n*************\nsee :ref:`use API push_back<cppad_vector_push_back-name>`\n\n{xrst_end vector_bool_push_back}\n*/\n// BEGIN_PUSH_BACK\n    void push_back(bool element)\n// END_PUSH_BACK\n    {  CPPAD_ASSERT_UNKNOWN( unit_min() <= n_unit_ );\n        size_t old_length = length_;\n        if( length_ + 1 > n_unit_ * bit_per_unit_ )\n        {  CPPAD_ASSERT_UNKNOWN( unit_min() == n_unit_ );\n\n            // create new vector with requuired size\n            vectorBool vec(length_ + 1);\n\n            // copy old data values\n            size_t n_used = unit_min();\n            CPPAD_ASSERT_UNKNOWN( n_used <= n_unit_ );\n            for(size_t i = 0; i < n_used; ++i)\n                vec.data_[i] = data_[i];\n\n            // swap old and new vectors\n            swap(vec);\n        }\n        else\n            ++length_;\n        CPPAD_ASSERT_UNKNOWN( length_ <= n_unit_ * bit_per_unit_ )\n        size_t   unit_index = old_length / bit_per_unit_;\n        size_t   bit_index  = old_length - unit_index * bit_per_unit_;\n        unit_t mask         = unit_t(1) << bit_index;\n        if( element )\n            data_[unit_index] |= mask;\n        else\n            data_[unit_index] &= ~mask;\n    }\n/* %$$\n-------------------------------------------------------------------------------\n{xrst_begin vector_bool_push_vector dev}\n\nvectorBool: push_vector\n#######################\n\nSyntax\n******\n*vec* . ``push_vector`` ( *other* )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_PUSH_VECTOR\n    // END_PUSH_VECTOR\n}\n\nDocumentation\n*************\nsee :ref:`use API push_vector<cppad_vector_push_vector-name>`\n\n{xrst_end vector_bool_push_vector}\n*/\n// BEGIN_PUSH_VECTOR\n    template <class Vector> void push_vector(const Vector& other)\n// END_PUSH_VECTOR\n    {  CPPAD_ASSERT_UNKNOWN( unit_min() <= n_unit_ );\n        CheckSimpleVector<bool, Vector>();\n        size_t old_length = length_;\n        size_t m           = other.size();\n        if( length_ + m > n_unit_ * bit_per_unit_ )\n        {\n            // create new vector with requuired size\n            vectorBool vec(length_ + m);\n\n            // copy old data values\n            size_t n_used = unit_min();\n            CPPAD_ASSERT_UNKNOWN( n_used <= n_unit_ );\n            for(size_t i = 0; i < n_used; ++i)\n                vec.data_[i] = data_[i];\n\n            // swap old and new vectors\n            swap(vec);\n        }\n        else\n            length_ += m;\n        //\n        // put the new elements in this vector\n        CPPAD_ASSERT_UNKNOWN( length_ <= n_unit_ * bit_per_unit_ )\n        for(size_t k = 0; k < m; k++)\n        {  size_t unit_index = (old_length + k) / bit_per_unit_;\n            size_t bit_index  = (old_length + k) - unit_index * bit_per_unit_;\n            unit_t mask       = unit_t(1) << bit_index;\n            if( other[k] )\n                data_[unit_index] |= mask;\n            else\n                data_[unit_index] &= ~mask;\n        }\n    }\n};\n\n/*\n{xrst_begin vector_bool_output dev}\n\nvectorBool: Output\n##################\n\nSyntax\n******\n*os* << ``vec``\n\nSource\n******\n{xrst_spell_off}\n{xrst_code hpp} */\ninline std::ostream& operator << (std::ostream&  os , const vectorBool& vec )\n{  for(size_t i = 0; i < vec.size(); ++i)\n        os << vec[i];\n    return os;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end vector_bool_output}\n*/\n\n} // END_CPPAD_NAMESPACE\n# endif\n"
  },
  {
    "path": "include/cppad/utility/xrst/cppad_vector.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin CppAD_vector}\n{xrst_spell\n    citr\n    cout\n    dereference\n    endl\n    initializer\n    ostream\n    rvalues\n    typename\n}\n\nThe CppAD::vector Template Class\n################################\n\nSyntax\n******\n| # ``include <cppad/utility/vector.hpp>``\n| # ``include <cppad/utility/vector_bool.hpp>``\n| ``CppAD::vector<`` *Scalar* > *vec* , *other*\n\nDescription\n***********\nThe include file ``cppad/vector.hpp`` defines the\nvector template class ``CppAD::vector`` .\nThis is a :ref:`SimpleVector-name` template class and in addition\nit has the features listed below.\nThe purposes for this template vector class are as follows:\n\n#. If ``NDEBUG`` is not defined, it checks for all\n   memory accesses to make sure the corresponding index is valid.\n   This includes when using its\n   :ref:`CppAD_vector@Iterators`\n#. It has a simple set of private member variables that make it\n   easy to understand when viewing its values in a C++ debugger.\n#. It uses the :ref:`thread_alloc-name` memory allocator which makes it fast\n   in a multi-threading environment; see\n   :ref:`CppAD_vector@Memory and Parallel Mode` .\n#. The operations it has are like the corresponding ``std::vector``\n   operation so it is easy to use.\n\nInclude\n*******\nThe files\n``cppad/utility/vector.hpp`` and ``cppad/utility/vector_bool.hpp`` are\nincluded by ``cppad/cppad.hpp`` .\nThey can also be included separately with out the rest of the\nCppAD include files.\n\nDeprecated 2019-08-19\n=====================\nThe file ``cppad/utility/vector.hpp``\nincludes the ``cppad/utility/vector_bool.hpp``\nbecause they used to be one file.\nIf you want :ref:`CppAD_vector@vectorBool` ,\nand not the rest of CppAD, you should include\n``cppad/utility/vector_bool.hpp`` .\n\nSize Constructor\n****************\nThe size *n* in the constructor syntax below can be an\n``int`` or ``unsigned int``\n(all simple vectors support ``size_t`` ):\n\n    ``CppAD::vector<`` *Scalar* > *vec* ( *n* )\n\nValue\n=====\nThe size constructor can specify a *value* to assign\nto all of the vector elements:\n\n    ``CppAD::vector<`` *Scalar* > *vec* ( *n* , *value* )\n\nwhere *value* is a *Scalar* object.\n\n\nInitializer Constructor\n***********************\nIf *e_1* , ... , *e_n* are values of type *Scalar*,\nthe syntax below constructs a vector with the corresponding element values.\n\n    ``CppAD::vector`` < *Scalar* > *vec* ( { *e_1* , ... , *e_n* )\n\n\ncapacity\n********\nIf *cap* is a ``size_t`` object,\n\n    *cap* = *vec* . ``capacity`` ()\n\nset *cap* to the number of *Scalar* objects that\ncould fit in the memory currently allocated for *vec* .\nNote that\n\n    *vec* . ``size`` () <= *vec* . ``capacity`` ()\n\nswap\n****\n\n    *vec* . ``swap`` ( *other* )\n\nexchanges the contents of *vec* and *other* .\nFor example :ref:`vec.data()<CppAD_vector@data>` after the ``swap``\nis equal to *other* . ``data`` () before ``swap`` .\n\nAssignment\n**********\n\n    *vec* = *other*\n\nhas all the properties listed for a\n:ref:`simple vector assignment<SimpleVector@Assignment>`\nplus the following:\n\nCheck Size\n==========\nIt is no longer necessary for *vec* to have the\nsame size as *other* .\nThis makes ``CppAD::vector`` more like ``std::vector`` .\n\nReturn Reference\n================\nA reference to the vector *vec* is returned.\nAn example use of this reference is in multiple assignments of the form\n\n    *vec* = *other* = *another*\n\nwhere *another* is a ``CppAD::vector<`` *Scalar* > object.\n\nMove Semantics\n==============\nIf the C++ compiler supports move semantic rvalues using the ``&&``\nsyntax, then it will be used during the vector assignment statement.\nThis means that return values and other temporaries are not be copied,\nbut rather pointers are transferred.\n\nComparison\n**********\nIf *op* is == , != , < , <= , > , >= and\n*result* is a ``bool`` , and\n\n    *result* = *vec* *op* *other*\n\n*result* is true if the comparison\n\n    *vec* [ *i* ] *op* *other [ *i* ]\n\nis true for all valid indices *i* .\nOtherwise, the *result* is false\n\nElement Access\n**************\nIf *i* has type ``size_t`` ,\n\n    *vec* [ *i* ]\n\nhas all the properties listed for a\n:ref:`simple vector element access<SimpleVector@Element Access>`\nplus the following:\n\ni\n=\nThis operation is defined for any *i*\nthat has a conversion to ``size_t`` .\nThe object *vec* [ *i* ] has type *Scalar*\n(is not possibly a different type that can be converted to *Scalar* ).\n\nError Checking\n==============\nIf *i* is not less than the size of the *vec* ,\nand ``NDEBUUG`` is not defined,\n``CppAD::vector`` will use\n:ref:`ErrorHandler-name`\nto generate an appropriate error report.\n\npush_back\n*********\nIf *vec* has size *n* and\n*scalar* has type *Scalar* ,\n\n    *vec* . ``push_back`` ( *scalar* )\n\nextends the vector so that its new size is *n* +1\nand *vec* [ *n* ] is equal to *s*\n(equal in the sense of the *Scalar* assignment operator).\n\npush_vector\n***********\nIf *vec* has size *n* and\n*simple_vec* is a :ref:`simple vector<SimpleVector-name>`\nwith elements of type *Scalar* and size *m* ,\n\n    *vec* . ``push_vector`` ( *simple_vec* )\n\nextends the vector *vec* so that its new size is *n* + *m*\nand *vec* [ *n* + *i* ] is equal to *simple_vec* [ *i* ]\nfor *i* = 1 , ... , *m-1*\n(equal in the sense of the *Scalar* assignment operator).\n\nOutput\n******\nIf *os* is an ``std::ostream`` , the operation\n\n    *os* << *vec*\n\nwill output *vec* to the standard output stream *os* .\nThe elements of *vec* are enclosed at the beginning by a\n``{`` character,\nthey are separated by ``,`` characters,\nand they are enclosed at the end by ``}`` character.\nIt is assumed by this operation that if *scalar*\nis an object with type *Scalar* ,\n\n    *os* << *scalar*\n\nwill output the value *scalar* to *os* .\n\nresize\n******\nIf *n* is a ``size_t`` or ``int`` ,\n\n    *vec* . ``resize`` ( *n* )\n\nsets the size of *vec* equal to *n* .\n\ndata\n====\nThe elements in *vec* before the resize operation are preserved.\n\nmemory\n======\nIf before the resize, *n* <= *vec* . ``capacity`` () ,\nno memory is freed or allocated and\nthe capacity of *vec* does not change.\nOtherwise, new memory is allocated and the elements before the resize\nare copied to the new memory.\nIf you do not need to the elements previously in the vector,\nyou can resize to zero and then to the new size to avoid the copy.\n\nclear\n*****\n\n    *vec* . ``clear`` ()\n\nfrees all memory allocated for *vec*\nand both its size and capacity are set to zero.\nThis can be useful when using very large vectors\nand when checking for memory leaks (and there are global vectors)\nsee the :ref:`memory<CppAD_vector@Memory and Parallel Mode>` discussion.\n\ndata\n****\n\n    *vec* . ``data`` ()\n\nreturns a pointer to a *Scalar* object such that for\n0 <= *i* < *vec* . ``size`` () ,\n*vec* [ *i* ] and *vec* . ``data`` ()[ *i* ]\nare the same *Scalar* object.\nIf *vec* is ``const`` , the pointer is ``const`` .\nIf *vec* . ``capacity`` () is zero, the value of the pointer is not defined.\nThe pointer may no longer be valid after the following operations on\n*vec* :\nits destructor,\n``clear`` ,\n``resize`` ,\n``push_back`` ,\n``push_vector`` ,\nassignment to another vector when original size of *vec* is zero.\n\nIterators\n*********\n\nSyntax\n======\n\n| ``typename CppAD::vector<`` *Scalar* >:: ``iterator`` *itr*\n| ``typename CppAD::vector<`` *Scalar* >:: ``const_iterator`` *citr*\n| *vec* . ``begin`` ()\n| *vec* . ``end`` ()\n\nitr\n===\nis a random access iterator type for non ``const`` objects.\n\ncitr\n====\nis a random access iterator type for a ``const`` objects.\nAn ``iterator`` can be converted to a ``const_iterator`` ,\nbut not the other way around.\n\nbegin\n=====\nis an iterator corresponding to the first element of the vector.\nIt is a ``const_iterator`` (``iterator`` )\ndepending on if *vec* is ``const`` (not ``const`` )\n\nend\n===\nis an iterator corresponding to just beyond the last element of the vector.\nIt is a ``const_iterator`` (``iterator`` )\ndepending on if *vec* is ``const`` (not ``const`` )\n\noperator[]\n==========\nThe syntax *itr* [ *i* ]\nand *citr* [ *i* ] is extended\n(from a normal random access iterator) to include the case where\n*i* is ``size_t`` object.\n\nError Checking\n==============\nEach element access (dereference of the iterator)\ndoes an error check similar to the element access\n:ref:`CppAD_vector@Element Access@Error Checking` above.\nThe error handler will also be called,\nif ``NDEBUG`` is not defined and\na comparison operator (e.g. ``>`` ) is used between\ntwo iterators that correspond to different vectors.\n\nvectorBool\n**********\nThe file ``<cppad/utility/vector_bool.hpp>`` defines the class\n``CppAD::vectorBool`` .\nThis has the same specifications as ``CppAD::vector<bool>``\nwith the following exceptions:\n\nMemory\n======\nThe class ``vectorBool`` conserves on memory,\non the other hand, ``CppAD::vector<bool>`` is expected to be faster\nthan ``vectorBool`` .\n\nbit_per_unit\n============\nThe static function call\n\n    *size* = ``vectorBool::bit_per_unit`` ()\n\nreturns the ``size_t`` value *s*\nwhich is equal to the number of boolean values (bits) that are\npacked into one operation unit.\nBits are accessed using a mask with the size of an operation unit.\n\ndata\n====\nThe :ref:`CppAD_vector@data` function is not supported by\n``vectorBool`` .\n\nIterators\n=========\nThe :ref:`CppAD_vector@Iterators` are not supported by\n``vectorBool`` .\n\nOutput\n======\nThe ``CppAD::vectorBool`` output operator\nprints each boolean value as\na ``0`` for false,\na ``1`` for true,\nand does not print any other output; i.e.,\nthe vector is written a long sequence of zeros and ones with no\nsurrounding ``{`` , ``}`` and with no separating commas or spaces.\n\nElement Type\n============\nIf *vec_bool* has type ``vectorBool``\nand *i* has type ``size_t`` ,\nthe element access value *vec_bool* [ *i* ] has an unspecified type,\nreferred to here as *element_t* , that supports the following\noperations:\n\n#. *element_t* can be converted to ``bool`` ; e.g.\n   the following syntax is supported:\n\n        ``static_cast<bool>`` ( *vec_bool* [ *i* ] )\n\n#. *element_t* supports the assignment operator ``=`` where the\n   right hand side is a ``bool`` or an *element_t* object; e.g.,\n   if *flag* has type ``bool`` , the following syntax is supported:\n\n        *vec_bool* [ *i* ] = *flag*\n\n#. The result of an assignment to an *element_t*\n   also has type *element_t* .\n   For example, if *other_flag* has type ``bool`` ,\n   the following syntax is supported:\n\n        *other_flag* = *vec_bool* [ *i* ] = *flag*\n\nMemory and Parallel Mode\n************************\nThese vectors use the multi-threaded fast memory allocator\n:ref:`thread_alloc-name` :\n\n#. The :ref:`hold_memory<ta_hold_memory-name>` routine can be used\n   to make memory allocation faster.\n#. The routine :ref:`parallel_setup<ta_parallel_setup-name>` must\n   be called before these vectors can be used\n   :ref:`in parallel<ta_in_parallel-name>` .\n#. Using these vectors affects the amount of memory\n   :ref:`in_use<ta_inuse-name>` and :ref:`available<ta_available-name>` .\n#. Calling :ref:`CppAD_vector@clear` ,\n   makes the corresponding memory available (though ``thread_alloc`` )\n   to the current thread.\n#. Available memory\n   can then be completely freed using :ref:`free_available<ta_free_available-name>` .\n\nExample\n*******\n{xrst_toc_hidden\n    example/utility/cppad_vector.cpp\n    example/utility/vector_bool.cpp\n}\nThe files\n:ref:`cppad_vector.cpp-name` and\n:ref:`vector_bool.cpp-name` each\ncontain an example and test of this template class.\nThey return true if they succeed and false otherwise.\n\nExercise\n********\nCreate and run a program that contains the following code:\n::\n\n    CppAD::vector<double> x(3);\n    size_t i;\n    for(i = 0; i < 3; i++)\n    x[i] = 4. - i;\n    std::cout << \"x = \" << x << std::endl;\n\n{xrst_end CppAD_vector}\n"
  },
  {
    "path": "include/cppad/utility/xrst/dev_cppad_vector.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin dev_cppad_vector dev}\n\nThe CppAD Vector Template Class Developer Documentation\n#######################################################\n\nUser API\n********\n:ref:`cppad_vector-name`\n\nContents\n********\n{xrst_toc_table\n    include/cppad/local/utility/cppad_vector_itr.hpp\n    include/cppad/utility/vector.hpp\n}\n\n{xrst_end dev_cppad_vector}\n"
  },
  {
    "path": "include/cppad/utility/xrst/dev_utility.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin dev_utility dev}\n\nGeneral Purpose Utilities Developer Documentation\n#################################################\n\nContents\n********\n{xrst_toc_table\n    include/cppad/utility/xrst/dev_cppad_vector.xrst\n    include/cppad/utility/xrst/dev_vector_bool.xrst\n}\n\n{xrst_end dev_utility}\n"
  },
  {
    "path": "include/cppad/utility/xrst/dev_vector_bool.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin dev_vector_bool dev}\n\nvectorBool Developer Documentation\n##################################\n\nUser API\n********\n:ref:`CppAD_vector@vectorBool`\n\nContents\n********\n{xrst_toc_table\n    include/cppad/local/utility/vector_bool.hpp\n    include/cppad/utility/vector_bool.hpp\n}\n\n{xrst_end dev_vector_bool}\n"
  },
  {
    "path": "include/cppad/utility/xrst/utility.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin utility}\n{xrst_spell\n    boolofvoid\n    dll\n    rc\n    rcv\n    rosen\n    runge\n}\n\nSome General Purpose Utilities\n##############################\nThese routines can be included individually; for example,\n::\n\n    # include <cppad/utility/vector.hpp>\n\nonly includes the definitions necessary for the ``CppAD::vector`` class.\nThey can also be included as a group, separate from the rest of CppAD, using\n::\n\n    # include <cppad/utility.hpp>\n\nThey will also be included, along with the rest of CppAD, using\n::\n\n    # include <cppad/cppad.hpp>\n\n{xrst_comment BEGIN_SORT_THIS_LINE_PLUS_2}\n{xrst_toc_hidden\n    include/cppad/utility/check_numeric_type.hpp\n    include/cppad/utility/check_simple_vector.hpp\n    include/cppad/utility/create_dll_lib.hpp\n    include/cppad/utility/error_handler.hpp\n    include/cppad/utility/index_sort.hpp\n    include/cppad/utility/link_dll_lib.hpp\n    include/cppad/utility/nan.hpp\n    include/cppad/utility/near_equal.hpp\n    include/cppad/utility/ode_err_control.hpp\n    include/cppad/utility/ode_gear.hpp\n    include/cppad/utility/ode_gear_control.hpp\n    include/cppad/utility/poly.hpp\n    include/cppad/utility/pow_int.hpp\n    include/cppad/utility/romberg_mul.hpp\n    include/cppad/utility/romberg_one.hpp\n    include/cppad/utility/rosen_34.hpp\n    include/cppad/utility/runge_45.hpp\n    include/cppad/utility/set_union.hpp\n    include/cppad/utility/sparse2eigen.hpp\n    include/cppad/utility/sparse_rc.hpp\n    include/cppad/utility/sparse_rcv.hpp\n    include/cppad/utility/speed_test.hpp\n    include/cppad/utility/test_boolofvoid.hpp\n    include/cppad/utility/time_test.hpp\n    include/cppad/utility/to_string.hpp\n    include/cppad/utility/xrst/cppad_vector.xrst\n    xrst/lu_det_and_solve.xrst\n    xrst/numeric_type.xrst\n    xrst/simple_vector.xrst\n    xrst/thread_alloc.xrst\n}\n{xrst_comment END_SORT_THIS_LINE_MINUS_2}\n\nTesting\n*******\nThe routines listed below support numerical correctness and speed testing:\n\n.. csv-table::\n    :widths: auto\n\n    NearEqual,:ref:`NearEqual-title`\n    time_test,:ref:`time_test-title`\n    speed_test,:ref:`speed_test-title`\n    SpeedTest,:ref:`SpeedTest-title`\n    test_boolofvoid,:ref:`test_boolofvoid-title`\n\nC++ Concepts\n************\nWe refer to a the set of classes that satisfy certain conditions\nas a C++ concept.\nThe following concepts are used by the CppAD Template library:\n\n.. csv-table::\n    :widths: auto\n\n    NumericType,:ref:`NumericType-title`\n    CheckNumericType,:ref:`CheckNumericType-title`\n    SimpleVector,:ref:`SimpleVector-title`\n    CheckSimpleVector,:ref:`CheckSimpleVector-title`\n\nGeneral Numerical Routines\n**************************\nThe routines listed below are general purpose numerical routines\nwritten with the floating point type a C++ template parameter.\nThis enables them to be used with algorithmic differentiation types,\nas well as for other purposes.\n\n.. csv-table::\n    :widths: auto\n\n    nan,:ref:`nan-title`\n    pow_int,:ref:`pow_int-title`\n    Poly,:ref:`Poly-title`\n    lu_det_and_solve,:ref:`lu_det_and_solve-title`\n    RombergOne,:ref:`RombergOne-title`\n    RombergMul,:ref:`RombergMul-title`\n    Runge45,:ref:`Runge45-title`\n    Rosen34,:ref:`Rosen34-title`\n    OdeErrControl,:ref:`OdeErrControl-title`\n    OdeGear,:ref:`OdeGear-title`\n    OdeGearControl,:ref:`OdeGearControl-title`\n\nMiscellaneous\n*************\n\nError Handler\n=============\nAll of the routines in the CppAD namespace use the following\ngeneral purpose error handler:\n\n.. csv-table::\n    :widths: auto\n\n    ErrorHandler,:ref:`ErrorHandler-title`\n\nThe CppAD Vector Template Class\n===============================\nThis is a simple implementation of a template vector class\n(that is easy to view in a C++ debugger):\n\n.. csv-table::\n    :widths: auto\n\n    CppAD_vector,:ref:`CppAD_vector-title`\n\nMulti-Threading Memory Allocation\n=================================\n\n.. csv-table::\n    :widths: auto\n\n    thread_alloc,:ref:`thread_alloc-title`\n\nSorting Indices\n===============\n\n.. csv-table::\n    :widths: auto\n\n    index_sort,:ref:`index_sort-title`\n\nto_string\n=========\n\n.. csv-table::\n    :widths: auto\n\n    to_string,:ref:`to_string-title`\n\nset_union\n=========\n\n.. csv-table::\n    :widths: auto\n\n    set_union,:ref:`set_union-title`\n\nSparse Matrices\n===============\n\n.. csv-table::\n    :widths: auto\n\n    sparse_rc,:ref:`sparse_rc-title`\n    sparse_rcv,:ref:`sparse_rcv-title`\n    sparse2eigen,:ref:`sparse2eigen-title`\n\nDynamic Libraries\n=================\n\n.. csv-table::\n    :widths: auto\n\n    create_dll_lib,:ref:`create_dll_lib-title`\n    link_dll_lib,:ref:`link_dll_lib-title`\n\n{xrst_end utility}\n"
  },
  {
    "path": "include/cppad/utility.hpp",
    "content": "# ifndef CPPAD_UTILITY_HPP\n# define CPPAD_UTILITY_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n// BEGIN_SORT_THIS_LINE_PLUS_1\n# include <cppad/utility/check_numeric_type.hpp>\n# include <cppad/utility/check_simple_vector.hpp>\n# include <cppad/utility/create_dll_lib.hpp>\n# include <cppad/utility/elapsed_seconds.hpp>\n# include <cppad/utility/error_handler.hpp>\n# include <cppad/utility/index_sort.hpp>\n# include <cppad/utility/link_dll_lib.hpp>\n# include <cppad/utility/lu_factor.hpp>\n# include <cppad/utility/lu_invert.hpp>\n# include <cppad/utility/lu_solve.hpp>\n# include <cppad/utility/memory_leak.hpp>\n# include <cppad/utility/nan.hpp>\n# include <cppad/utility/near_equal.hpp>\n# include <cppad/utility/ode_err_control.hpp>\n# include <cppad/utility/ode_gear.hpp>\n# include <cppad/utility/ode_gear_control.hpp>\n# include <cppad/utility/omp_alloc.hpp>\n# include <cppad/utility/poly.hpp>\n# include <cppad/utility/pow_int.hpp>\n# include <cppad/utility/romberg_mul.hpp>\n# include <cppad/utility/romberg_one.hpp>\n# include <cppad/utility/rosen_34.hpp>\n# include <cppad/utility/runge_45.hpp>\n# include <cppad/utility/set_union.hpp>\n# include <cppad/utility/sparse_rc.hpp>\n# include <cppad/utility/sparse_rcv.hpp>\n# include <cppad/utility/speed_test.hpp>\n# include <cppad/utility/test_boolofvoid.hpp>\n# include <cppad/utility/thread_alloc.hpp>\n# include <cppad/utility/time_test.hpp>\n# include <cppad/utility/to_string.hpp>\n# include <cppad/utility/track_new_del.hpp>\n# include <cppad/utility/vector.hpp>\n// END_SORT_THIS_LINE_MINUS_1\n\n# if CPPAD_HAS_EIGEN\n# include <cppad/utility/sparse2eigen.hpp>\n# endif\n\n# endif\n"
  },
  {
    "path": "include/cppad/wno_conversion.hpp",
    "content": "# ifndef CPPAD_WNO_CONVERSION_HPP\n# define CPPAD_WNO_CONVERSION_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin wno_conversion}\n\nSuppress Suspect Implicit Conversion Warnings\n#############################################\n\nSyntax\n******\n| # ``include <cppad/wno_conversion.hpp>``\n\nPurpose\n*******\nIn many cases it is good to have warnings for implicit conversions\nthat may loose range or precision.\nThe include command above, before any other includes, suppresses\nthese warning for a particular compilation unit (which usually corresponds\nto a * . ``cpp`` file).\n\n{xrst_end wno_conversion}\n*/\n\n# include <cppad/configure.hpp>\n# if CPPAD_COMPILER_HAS_CONVERSION_WARN\n# pragma GCC diagnostic ignored \"-Wfloat-conversion\"\n# pragma GCC diagnostic ignored \"-Wconversion\"\n# endif\n\n# endif\n"
  },
  {
    "path": "introduction/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# Build the introduction/exp_apx directory tests\n\n# BEGIN_SORT_THIS_LINE_PLUS_2\nSET(source_list\n    exp_2.cpp\n    exp_2.hpp\n    exp_2_cppad.cpp\n    exp_2_for0.cpp\n    exp_2_for1.cpp\n    exp_2_for2.cpp\n    exp_2_rev1.cpp\n    exp_2_rev2.cpp\n    exp_eps.cpp\n    exp_eps.hpp\n    exp_eps_cppad.cpp\n    exp_eps_for0.cpp\n    exp_eps_for1.cpp\n    exp_eps_for2.cpp\n    exp_eps_rev1.cpp\n    exp_eps_rev2.cpp\n    introduction.cpp\n)\n# END_SORT_THIS_LINE_MINUS_2\n\nset_compile_flags( introduction \"${cppad_debug_which}\" \"${source_list}\" )\n#\nADD_EXECUTABLE( introduction EXCLUDE_FROM_ALL ${source_list} )\n#\nTARGET_LINK_LIBRARIES(introduction ${cppad_lib} ${colpack_libs})\n#\n# check_introduction\nadd_check_executable(check introduction)\n"
  },
  {
    "path": "introduction/exp_2.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n// BEGIN C++\n# include <cmath>           // define fabs function\n# include \"exp_2.hpp\"       // definition of exp_2 algorithm\nbool exp_2(void)\n{   double x     = .5;\n    double check = 1 + x + x * x / 2.;\n    bool   ok    = std::fabs( exp_2(x) - check ) <= 1e-10;\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "introduction/exp_2.hpp",
    "content": "# ifndef CPPAD_INTRODUCTION_EXP_2_HPP\n# define CPPAD_INTRODUCTION_EXP_2_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin exp_2}\n{xrst_spell\n    apx\n    yyyymmdd\n}\n\nSecond Order Exponential Approximation\n######################################\n\nSyntax\n******\n| # ``include`` ``\"exp_2.hpp\"``\n| *y* = ``exp_2`` ( *x* )\n\nPurpose\n*******\nThis is a simple example algorithm that is used to demonstrate\nAlgorithmic Differentiation\n(see :ref:`exp_eps-name` for a more complex example).\n\nMathematical Form\n*****************\nThe exponential function can be defined by\n\n.. math::\n\n    \\exp (x) = 1 + x^1 / 1 ! + x^2 / 2 ! + \\cdots\n\nThe second order approximation for the exponential function is\n\n.. math::\n\n    {\\rm exp\\_2} (x) =  1 + x + x^2 / 2\n\ninclude\n*******\nThe include command in the syntax is relative to\n\n    ``cppad-`` *yyyymmdd* / ``introduction/exp_apx``\n\nwhere ``cppad-`` *yyyymmdd* is the distribution directory\ncreated during the beginning steps of the\n:ref:`installation<Install-name>` of CppAD.\n\nx\n*\nThe argument *x* has prototype\n\n    ``const`` *Type* & *x*\n\n(see *Type* below).\nIt specifies the point at which to evaluate the\napproximation for the second order exponential approximation.\n\ny\n*\nThe result *y* has prototype\n\n    *Type* *y*\n\nIt is the value of the exponential function\napproximation defined above.\n\nType\n****\nIf *u* and *v* are *Type* objects and *i*\nis an ``int`` :\n\n.. csv-table::\n    :widths: auto\n\n    **Operation**,**Result Type**,**Description**\n    *Type* ( *i* ),*Type*,construct object with value equal to *i*\n    *Type u* = *v*,*Type*,construct *u* with value equal to *v*\n    *u* * *v*,*Type*,result is value of :math:`u * v`\n    *u* / *v*,*Type*,result is value of :math:`u / v`\n    *u* + *v*,*Type*,result is value of :math:`u + v`\n\nContents\n********\n{xrst_toc_table\n    introduction/exp_2.xrst\n    introduction/exp_2_cppad.cpp\n}\n\nImplementation\n**************\nThe file :ref:`exp_2.hpp-name`\ncontains a C++ implementation of this function.\n\nTest\n****\nThe file :ref:`exp_2.cpp-name`\ncontains a test of this implementation.\n\nExercises\n*********\n\n#. Suppose that we make the call\n   ::\n\n        double x = .1;\n        double y = exp_2(x);\n\n    What is the value assigned to\n    ``v1`` , ``v2`` , ... ,``v5`` in :ref:`exp_2.hpp-name` ?\n#. Extend the routine ``exp_2.hpp`` to\n   a routine ``exp_3.hpp`` that computes\n\n    .. math::\n\n        1 + x^2 / 2 ! + x^3 / 3 !\n\n    Do this in a way that only assigns one value to each variable\n    (as ``exp_2`` does).\n#. Suppose that we make the call\n   ::\n\n        double x = .5;\n        double y = exp_3(x);\n\n    using ``exp_3`` created in the previous problem.\n    What is the value assigned to the new variables in ``exp_3``\n    (variables that are in ``exp_3`` and not in ``exp_2`` ) ?\n\n{xrst_end exp_2}\n------------------------------------------------------------------------------\n*/\n// BEGIN C++\ntemplate <class Type>\nType exp_2(const Type &x)\n{        Type v1  = x;                // v1 = x\n        Type v2  = Type(1) + v1;     // v2 = 1 + x\n        Type v3  = v1 * v1;          // v3 = x^2\n        Type v4  = v3 / Type(2);     // v4 = x^2 / 2\n        Type v5  = v2 + v4;          // v5 = 1 + x + x^2 / 2\n        return v5;                   // exp_2(x) = 1 + x + x^2 / 2\n}\n// END C++\n\n# endif\n"
  },
  {
    "path": "introduction/exp_2.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin exp_2.hpp}\n\nexp_2: Implementation\n#####################\n\n{xrst_literal\n    introduction/exp_2.hpp\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end exp_2.hpp}\n-----------------------------------------------------------------------------\n{xrst_begin exp_2.cpp}\n\nexp_2: Test\n###########\n\n{xrst_literal\n    introduction/exp_2.cpp\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end exp_2.cpp}\n-----------------------------------------------------------------------------\n{xrst_begin exp_2_for0}\n\nexp_2: Operation Sequence and Zero Order Forward Mode\n#####################################################\n\nMathematical Form\n*****************\nThe operation sequence (see below) corresponding to\nthe algorithm :ref:`exp_2.hpp-name` is the same for all values of *x* .\nThe mathematical form for the corresponding function is\n\n.. math::\n\n    f(x) = 1 + x + x^2 / 2\n\nAn algorithmic differentiation package\ndoes not operate on the mathematical function :math:`f(x)`\nbut rather on the particular algorithm used to compute the function\n(in this case :ref:`exp_2.hpp-name` ).\n\nZero Order Expansion\n********************\nIn general, a zero order forward sweep is given a vector\n:math:`x^{(0)} \\in \\B{R}^n` and it returns the corresponding vector\n:math:`y^{(0)} \\in \\B{R}^m` given by\n\n.. math::\n\n    y^{(0)} = f( x^{(0)} )\n\nThe superscript :math:`(0)` denotes zero order derivative;\ni.e., it is equal to the value\nof the corresponding variable.\nFor the example we are considering here,\nboth :math:`n` and :math:`m` are equal to one.\n\nOperation Sequence\n******************\nAn atomic *Type* operation is an operation\nthat has a *Type* result and is not made up of\nother more basic operations.\nA sequence of atomic *Type* operations is called a\n*Type* operation sequence.\nGiven an C++ algorithm and its inputs,\nthere is a corresponding *Type* operation sequence for each type.\nIf *Type* is clear from the context,\nwe drop it and just refer to the operation sequence.\n\nWe consider the case where :ref:`exp_2.hpp-name` is executed with\n:math:`x^{(0)} = .5`.\nThe table below contains the corresponding operation sequence\nand the results of a zero order sweep.\n\nIndex\n=====\nThe Index column contains the index in the operation sequence\nof the corresponding atomic operation and variable.\nA Forward sweep starts with the first operation\nand ends with the last.\n\nCode\n====\nThe Code column contains the C++ source code corresponding\nto the corresponding atomic operation in the sequence.\n\nOperation\n=========\nThe Operation column contains the\nmathematical function corresponding to each atomic operation in the sequence.\n\nZero Order\n==========\nThe Zero Order column contains the zero order derivative for\nthe corresponding variable in the operation sequence.\nForward mode refers to the fact that\nthese coefficients are computed in the same order as the original algorithm;\ni.e, in order of increasing index in the operation sequence.\n\nSweep\n=====\n\n.. csv-table::\n    :widths: auto\n\n    **Index**,,**Code**,,**Operation**,,**Zero Order**\n    1,,``Type v1  = x;``,,:math:`v_1 = x`,,:math:`v_1^{(0)} = 0.5`\n    2,,``Type v2  = Type(1) + v1;``,,:math:`v_2 = 1 + v_1`,,:math:`v_2^{(0)} = 1.5`\n    3,,``Type v3  = v1 * v1;``,,:math:`v_3 = v_1 * v_1`,,:math:`v_3^{(0)} = 0.25`\n    4,,``Type v4  = v3 / Type(2);``,,:math:`v_4 = v_3 / 2`,,:math:`v_4^{(0)} = 0.125`\n    5,,``Type v5  = v2 + v4;``,,:math:`v_5 = v_2 + v_4`,,:math:`v_5^{(0)} = 1.625`\n\nReturn Value\n************\nThe return value for this case is\n\n.. math::\n\n    1.625 =\n    v_5^{(0)} =\n    f( x^{(0)} )\n\n{xrst_toc_hidden\n    introduction/exp_2_for0.cpp\n}\n\nVerification\n************\nThe file :ref:`exp_2_for0.cpp-name` contains a routine\nthat verifies the values computed above.\n\nExercises\n*********\n\n#. Suppose that :math:`x^{(0)} = .2`,\n   what is the result of a zero order forward sweep for\n   the operation sequence above;\n   i.e., what are the corresponding values for\n\n    .. math::\n\n        v_1^{(0)} , v_2^{(0)} , \\cdots , v_5^{(0)}\n\n#. Create a modified version of\n   :ref:`exp_2_for0.cpp-name` that verifies the values you obtained\n   for the previous exercise.\n#. Create and run a main program that reports the result of calling\n   the modified version\n   of :ref:`exp_2_for0.cpp-name` in the previous exercise.\n\n{xrst_end exp_2_for0}\n------------------------------------------------------------------------------\n{xrst_begin exp_2_for1}\n\nexp_2: First Order Forward Mode\n###############################\n\nFirst Order Expansion\n*********************\nWe define :math:`x(t)` near :math:`t = 0` by the first order expansion\n\n.. math::\n\n    x(t) = x^{(0)} + x^{(1)} * t\n\nit follows that :math:`x^{(0)}` is the zero,\nand :math:`x^{(1)}` the first,\norder derivative of :math:`x(t)`\nat :math:`t = 0`.\n\nPurpose\n*******\nIn general, a first order forward sweep is given the\n:ref:`zero order derivative<exp_2_for0@Zero Order Expansion>`\nfor all of the variables in an operation sequence,\nand the first order derivatives for the independent variables.\nIt uses these to compute the first order derivatives,\nand thereby obtain the first order expansion,\nfor all the other variables in the operation sequence.\n\nMathematical Form\n*****************\nSuppose that we use the algorithm :ref:`exp_2.hpp-name` to compute\n\n.. math::\n\n    f(x) = 1 + x + x^2 / 2\n\nThe corresponding derivative function is\n\n.. math::\n\n    \\partial_x f (x) =   1 + x\n\nAn algorithmic differentiation package\ndoes not operate on the mathematical form of the function,\nor its derivative,\nbut rather on the\n:ref:`exp_2_for0@Operation Sequence`\nfor the for the algorithm that is used to evaluate the function.\n\nOperation Sequence\n******************\nWe consider the case where :ref:`exp_2.hpp-name` is executed with\n:math:`x = .5`.\nThe corresponding operation sequence and\nzero order forward mode values\n(see :ref:`zero order sweep<exp_2_for0@Operation Sequence@Sweep>` )\nare inputs and are used by a first order forward sweep.\n\nIndex\n=====\nThe Index column contains the index in the operation sequence\nof the corresponding atomic operation.\nA Forward sweep starts with the first operation\nand ends with the last.\n\nOperation\n=========\nThe Operation column contains the\nmathematical function corresponding to each atomic operation in the sequence.\n\nZero Order\n==========\nThe Zero Order column contains the zero order derivatives\nfor the corresponding variable in the operation sequence\n(see :ref:`zero order sweep<exp_2_for0@Operation Sequence@Sweep>` ).\n\nDerivative\n==========\nThe Derivative column contains the\nmathematical function corresponding to the derivative\nwith respect to :math:`t`,\nat :math:`t = 0`, for each variable in the sequence.\n\nFirst Order\n===========\nThe First Order column contains the first order derivatives\nfor the corresponding variable in the operation sequence; i.e.,\n\n.. math::\n\n    v_j (t) = v_j^{(0)} + v_j^{(1)} t\n\nWe use :math:`x^{(1)} = 1` so that differentiation\nwith respect to :math:`t`,\nat :math:`t = 0`, is the same as partial differentiation\nwith respect to :math:`x` at :math:`x = x^{(0)}`.\n\nSweep\n=====\n\n.. csv-table::\n    :widths: auto\n\n    **Index**,,**Operation**,,**Zero Order**,,**Derivative**,,**First Order**\n    1,,:math:`v_1 = x`,,0.5,,:math:`v_1^{(1)} = x^{(1)}`,,:math:`v_1^{(1)} = 1`\n    2,,:math:`v_2 = 1 + v_1`,,1.5,,:math:`v_2^{(1)} = v_1^{(1)}`,,:math:`v_2^{(1)} = 1`\n    3,,:math:`v_3 = v_1 * v_1`,,0.25,,:math:`v_3^{(1)} = 2 * v_1^{(0)} * v_1^{(1)}`,,:math:`v_3^{(1)} = 1`\n    4,,:math:`v_4 = v_3 / 2`,,0.125,,:math:`v_4^{(1)} = v_3^{(1)} / 2`,,:math:`v_4^{(1)} = 0.5`\n    5,,:math:`v_5 = v_2 + v_4`,,1.625,,:math:`v_5^{(1)} = v_2^{(1)} + v_4^{(1)}`,,:math:`v_5^{(1)} = 1.5`\n\nReturn Value\n************\nThe derivative of the return value for this case is\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        1.5\n        & = &\n        v_5^{(1)} =\n        \\left[ \\D{v_5}{t} \\right]_{t=0} =\n        \\left[ \\D{}{t} f ( x^{(0)} + x^{(1)} t ) \\right]_{t=0}\n        \\\\\n        & = &\n        f^{(1)} ( x^{(0)} ) * x^{(1)} =\n        f^{(1)} ( x^{(0)} )\n    \\end{eqnarray}\n\n(We have used the fact that :math:`x^{(1)} = 1`.)\n{xrst_toc_hidden\n    introduction/exp_2_for1.cpp\n}\nVerification\n************\nThe file :ref:`exp_2_for1.cpp-name` contains a routine\nwhich verifies the values computed above.\n\nExercises\n*********\n\n#. Which statement in the routine defined by :ref:`exp_2_for1.cpp-name` uses\n   the values that are calculated by the routine\n   defined by :ref:`exp_2_for0.cpp-name` ?\n#. Suppose that :math:`x = .1`,\n   what are the results of a zero and first order forward sweep for\n   the operation sequence above;\n   i.e., what are the corresponding values for\n   :math:`v_1^{(0)}, v_2^{(0)}, \\cdots , v_5^{(0)}` and\n   :math:`v_1^{(1)}, v_2^{(1)}, \\cdots , v_5^{(1)}` ?\n#. Create a modified version of :ref:`exp_2_for1.cpp-name` that verifies\n   the derivative values from the previous exercise.\n   Also create and run a main program that reports the result\n   of calling the modified version of\n   :ref:`exp_2_for1.cpp-name` .\n\n{xrst_end exp_2_for1}\n------------------------------------------------------------------------------\n{xrst_begin exp_2_rev1}\n{xrst_spell\n    rcll\n}\n\nexp_2: First Order Reverse Mode\n###############################\n\nPurpose\n*******\nFirst order reverse mode uses the\n:ref:`exp_2_for0@Operation Sequence` ,\nand zero order forward sweep values,\nto compute the first order derivative\nof one dependent variable with respect to all the independent variables.\nThe computations are done in reverse\nof the order of the computations in the original algorithm.\n\nMathematical Form\n*****************\nSuppose that we use the algorithm :ref:`exp_2.hpp-name` to compute\n\n.. math::\n\n    f(x) = 1 + x + x^2 / 2\n\nThe corresponding derivative function is\n\n.. math::\n\n    \\partial_x f (x) =   1 + x\n\nf_5\n***\nFor our example, we chose to compute the derivative\nof the value returned by :ref:`exp_2.hpp-name`\nwhich is equal to the symbol :math:`v_5` in the\n:ref:`exp_2 operation sequence<exp_2_for0@Operation Sequence>` .\nWe begin with the function :math:`f_5` where :math:`v_5`\nis both an argument and the value of the function; i.e.,\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    f_5 ( v_1 , v_2 , v_3 , v_4 , v_5 ) & = & v_5\n    \\\\\n    \\D{f_5}{v_5} & = & 1\n    \\end{eqnarray}\n\nAll the other partial derivatives of :math:`f_5` are zero.\n\nIndex 5: f_4\n************\nReverse mode starts with the last operation in the sequence.\nFor the case in question, this is the operation with index 5,\n\n.. math::\n\n    v_5 = v_2 + v_4\n\nWe define the function\n:math:`f_4 ( v_1 , v_2 , v_3 , v_4 )`\nas equal to :math:`f_5`\nexcept that :math:`v_5` is eliminated using\nthis operation; i.e.\n\n.. math::\n\n    f_4  =\n    f_5 [  v_1 , v_2 , v_3 , v_4 , v_5 ( v_2 , v_4 ) ]\n\nIt follows that\n\n.. math::\n\n    \\begin{array}{rcll}\n    \\D{f_4}{v_2}\n    & = & \\D{f_5}{v_2} +\n        \\D{f_5}{v_5} * \\D{v_5}{v_2}\n    & = 1\n    \\\\\n    \\D{f_4}{v_4}\n    & = & \\D{f_5}{v_4} +\n        \\D{f_5}{v_5} * \\D{v_5}{v_4}\n    & = 1\n    \\end{array}\n\nAll the other partial derivatives of :math:`f_4` are zero.\n\nIndex 4: f_3\n************\nThe next operation has index 4,\n\n.. math::\n\n    v_4 = v_3 / 2\n\nWe define the function\n:math:`f_3 (  v_1 , v_2 , v_3 )`\nas equal to :math:`f_4`\nexcept that :math:`v_4` is eliminated using this operation; i.e.,\n\n.. math::\n\n    f_3 =\n    f_4 [ v_1 , v_2 , v_3 , v_4 ( v_3 ) ]\n\nIt follows that\n\n.. math::\n\n    \\begin{array}{rcll}\n    \\D{f_3}{v_1}\n    & = & \\D{f_4}{v_1}\n    & = 0\n    \\\\\n    \\D{f_3}{v_2}\n    & = & \\D{f_4}{v_2}\n    & = 1\n    \\\\\n    \\D{f_3}{v_3}\n    & = & \\D{f_4}{v_3} +\n        \\D{f_4}{v_4} * \\D{v_4}{v_3}\n    & = 0.5\n    \\end{array}\n\nIndex 3: f_2\n************\nThe next operation has index 3,\n\n.. math::\n\n    v_3 = v_1 * v_1\n\nWe define the function\n:math:`f_2 ( v_1 , v_2 )`\nas equal to :math:`f_3`\nexcept that :math:`v_3` is eliminated using this operation; i.e.,\n\n.. math::\n\n    f_2 =\n    f_3 [ v_1 , v_2 , v_3 ( v_1 ) ]\n\nNote that the value of :math:`v_1` is equal to :math:`x`\nwhich is .5 for this evaluation.\nIt follows that\n\n.. math::\n\n    \\begin{array}{rcll}\n    \\D{f_2}{v_1}\n    & = & \\D{f_3}{v_1} +\n        \\D{f_3}{v_3} * \\D{v_3}{v_1}\n    & = 0.5\n    \\\\\n    \\D{f_2}{v_2}\n    & = & \\D{f_3}{v_2}\n    & = 1\n    \\end{array}\n\nIndex 2: f_1\n************\nThe next operation has index 2,\n\n.. math::\n\n    v_2 = 1 + v_1\n\nWe define the function\n:math:`f_1 ( v_1 )`\nas equal to :math:`f_2`\nexcept that :math:`v_2` is eliminated using this operation; i.e.,\n\n.. math::\n\n    f_1 =\n    f_2 [ v_1 , v_2 ( v_1 ) ]\n\nIt follows that\n\n.. math::\n\n    \\begin{array}{rcll}\n    \\D{f_1}{v_1}\n    & = & \\D{f_2}{v_1} +\n        \\D{f_2}{v_2} * \\D{v_2}{v_1}\n    & = 1.5\n    \\end{array}\n\nNote that :math:`v_1` is equal to :math:`x`,\nso the derivative of this is the derivative of\nthe function defined by :ref:`exp_2.hpp-name` at :math:`x = .5`.\n{xrst_toc_hidden\n    introduction/exp_2_rev1.cpp\n}\nVerification\n************\nThe file :ref:`exp_2_rev1.cpp-name` contains a routine\nwhich verifies the values computed above.\nIt only tests the partial derivatives of\n:math:`f_j` that might not be equal to the corresponding\npartials of :math:`f_{j+1}`; i.e., the\nother partials of :math:`f_j` must be equal to the corresponding\npartials of :math:`f_{j+1}`.\n\nExercises\n*********\n\n#. Which statement in the routine defined by :ref:`exp_2_rev1.cpp-name` uses\n   the values that are calculated by the routine\n   defined by :ref:`exp_2_for0.cpp-name` ?\n#. Consider the case where :math:`x = .1`\n   and we first preform a zero order forward sweep\n   for the operation sequence used above.\n   What are the results of a\n   first order reverse sweep; i.e.,\n   what are the corresponding derivatives of\n   :math:`f_5 , f_4 , \\ldots , f_1`.\n#. Create a modified version of\n   :ref:`exp_2_rev1.cpp-name`\n   that verifies the values you obtained for the previous exercise.\n   Also create and run a main program that reports the result\n   of calling the modified version of\n   :ref:`exp_2_rev1.cpp-name` .\n\n{xrst_end exp_2_rev1}\n------------------------------------------------------------------------------\n{xrst_begin exp_2_for2}\n\nexp_2: Second Order Forward Mode\n################################\n\nSecond Order Expansion\n**********************\nWe define :math:`x(t)` near :math:`t = 0` by the second order expansion\n\n.. math::\n\n    x(t) = x^{(0)} + x^{(1)} * t + x^{(2)} * t^2 / 2\n\nIt follows that for :math:`k = 0 , 1 , 2`,\n\n.. math::\n\n    x^{(k)} = \\dpow{k}{t} x (0)\n\nPurpose\n*******\nIn general, a second order forward sweep is given the\n:ref:`exp_2_for1@First Order Expansion`\nfor all of the variables in an operation sequence,\nand the second order derivatives for the independent variables.\nIt uses these to compute the second order derivative,\nand thereby obtain the second order expansion,\nfor all the variables in the operation sequence.\n\nMathematical Form\n*****************\nSuppose that we use the algorithm :ref:`exp_2.hpp-name` to compute\n\n.. math::\n\n    f(x) = 1 + x + x^2 / 2\n\nThe corresponding second derivative function is\n\n.. math::\n\n    \\Dpow{2}{x} f (x) =   1\n\nOperation Sequence\n******************\nWe consider the case where :ref:`exp_2.hpp-name` is executed with\n:math:`x = .5`.\nThe corresponding operation sequence,\nzero order forward sweep values,\nand first order forward sweep values\nare inputs and are used by a second order forward sweep.\n\nIndex\n=====\nThe Index column contains the index in the operation sequence\nof the corresponding atomic operation.\nA Forward sweep starts with the first operation\nand ends with the last.\n\nZero\n====\nThe Zero column contains the zero order sweep results\nfor the corresponding variable in the operation sequence\n(see :ref:`zero order sweep<exp_2_for0@Operation Sequence@Sweep>` ).\n\nOperation\n=========\nThe Operation column contains the\nfirst order sweep operation for this variable.\n\nFirst\n=====\nThe First column contains the first order sweep results\nfor the corresponding variable in the operation sequence\n(see :ref:`first order sweep<exp_2_for1@Operation Sequence@Sweep>` ).\n\nDerivative\n==========\nThe Derivative column contains the\nmathematical function corresponding to the second derivative\nwith respect to :math:`t`,\nat :math:`t = 0`, for each variable in the sequence.\n\nSecond\n======\nThe Second column contains the second order derivatives\nfor the corresponding variable in the operation sequence; i.e.,\nthe second order expansion for the *i*-th variable is given by\n\n.. math::\n\n    v_i (t) = v_i^{(0)} + v_i^{(1)} * t +  v_i^{(2)} * t^2 / 2\n\nWe use :math:`x^{(0)} = 1`, and :math:`x^{(2)} = 0`\nso that second order differentiation\nwith respect to :math:`t`, at :math:`t = 0`,\nis the same as the second partial differentiation\nwith respect to :math:`x` at :math:`x = x^{(0)}`.\n\nSweep\n=====\n\n.. csv-table::\n    :widths: auto\n\n    **Index**,,**Zero**,,**Operation**,,**First**,,**Derivative**,,**Second**\n    1,,0.5,,:math:`v_1^{(1)} = x^{(1)}`,,1,,:math:`v_1^{(2)} = x^{(2)}`,,:math:`v_1^{(2)} = 0`\n    2,,1.5,,:math:`v_2^{(1)} = v_1^{(1)}`,,1,,:math:`v_2^{(2)} = v_1^{(2)}`,,:math:`v_2^{(2)} = 0`\n    3,,0.25,,:math:`v_3^{(1)} = 2 * v_1^{(0)} * v_1^{(1)}`,,1,,:math:`v_3^{(2)} = 2 * (v_1^{(1)} * v_1^{(1)} + v_1^{(0)} * v_1^{(2)} )`,,:math:`v_3^{(2)} = 2`\n    4,,0.125,,:math:`v_4^{(1)} = v_3^{(1)} / 2`,,.5,,:math:`v_4^{(2)} = v_3^{(2)} / 2`,,:math:`v_4^{(2)} = 1`\n    5,,1.625,,:math:`v_5^{(1)} = v_2^{(1)} + v_4^{(1)}`,,1.5,,:math:`v_5^{(2)} = v_2^{(2)} + v_4^{(2)}`,,:math:`v_5^{(2)} = 1`\n\nReturn Value\n************\nThe second derivative of the return value for this case is\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        1\n        & = &\n        v_5^{(2)} =\n        \\left[ \\Dpow{2}{t} v_5 \\right]_{t=0} =\n        \\left[ \\Dpow{2}{t} f( x^{(0)} + x^{(1)} * t ) \\right]_{t=0}\n        \\\\\n        & = &\n        x^{(1)} * \\Dpow{2}{x} f ( x^{(0)} ) * x^{(1)} =\n        \\Dpow{2}{x} f ( x^{(0)} )\n    \\end{eqnarray}\n\n(We have used the fact that\n:math:`x^{(1)} = 1` and :math:`x^{(2)} = 0`.)\n{xrst_toc_hidden\n    introduction/exp_2_for2.cpp\n}\nVerification\n************\nThe file :ref:`exp_2_for2.cpp-name` contains a routine\nwhich verifies the values computed above.\n\nExercises\n*********\n\n#. Which statement in the routine defined by :ref:`exp_2_for2.cpp-name` uses\n   the values that are calculated by the routine\n   defined by :ref:`exp_2_for1.cpp-name` ?\n#. Suppose that :math:`x = .1`,\n   what are the results of a zero, first, and second order forward sweep for\n   the operation sequence above;\n   i.e., what are the corresponding values for\n   :math:`v_i^{(k)}` for :math:`i = 1, \\ldots , 5` and :math:`k = 0, 1, 2`.\n#. Create a modified version of :ref:`exp_2_for2.cpp-name` that verifies\n   the derivative values from the previous exercise.\n   Also create and run a main program that reports the result\n   of calling the modified version of\n   :ref:`exp_2_for2.cpp-name` .\n\n{xrst_end exp_2_for2}\n------------------------------------------------------------------------------\n{xrst_begin exp_2_rev2}\n{xrst_spell\n    rcll\n}\n\nexp_2: Second Order Reverse Mode\n################################\n\nPurpose\n*******\nIn general, a second order reverse sweep is given the\n:ref:`exp_2_for1@First Order Expansion`\nfor all of the variables in an operation sequence.\nGiven a choice of a particular variable,\nit computes the derivative,\nof that variables first order expansion coefficient,\nwith respect to all of the independent variables.\n\nMathematical Form\n*****************\nSuppose that we use the algorithm :ref:`exp_2.hpp-name` to compute\n\n.. math::\n\n    f(x) = 1 + x + x^2 / 2\n\nThe corresponding second derivative is\n\n.. math::\n\n    \\Dpow{2}{x} f (x) =   1\n\nf_5\n***\nFor our example, we chose to compute the derivative of :math:`v_5^{(1)}`\nwith respect to all the independent variable.\nFor the case computed for the\n:ref:`first order sweep<exp_2_for1@Operation Sequence@Sweep>` ,\n:math:`v_5^{(1)}` is the derivative\nof the value returned by :ref:`exp_2.hpp-name` .\nThis the value computed will be the second derivative of\nthe value returned by  :ref:`exp_2.hpp-name` .\nWe begin with the function :math:`f_5` where :math:`v_5^{(1)}`\nis both an argument and the value of the function; i.e.,\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    f_5 \\left(\n        v_1^{(0)}, v_1^{(1)} , \\ldots  , v_5^{(0)} , v_5^{(1)}\n    \\right)\n    & = & v_5^{(1)}\n    \\\\\n    \\D{f_5}{v_5^{(1)}} & = & 1\n    \\end{eqnarray}\n\nAll the other partial derivatives of :math:`f_5` are zero.\n\nIndex 5: f_4\n************\nSecond order reverse mode starts with the last operation in the sequence.\nFor the case in question, this is the operation with index 5.\nThe zero and first order sweep representations of this operation are\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        v_5^{(0)} & = & v_2^{(0)} + v_4^{(0)}\n        \\\\\n        v_5^{(1)} & = & v_2^{(1)} + v_4^{(1)}\n    \\end{eqnarray}\n\nWe define the function\n:math:`f_4 \\left( v_1^{(0)} , \\ldots , v_4^{(1)} \\right)`\nas equal to :math:`f_5`\nexcept that :math:`v_5^{(0)}` and :math:`v_5^{(1)}` are eliminated using\nthis operation; i.e.\n\n.. math::\n\n    f_4  =\n    f_5 \\left[   v_1^{(0)} , \\ldots , v_4^{(1)} ,\n        v_5^{(0)} \\left( v_2^{(0)} , v_4^{(0)} \\right) ,\n        v_5^{(1)} \\left( v_2^{(1)} , v_4^{(1)} \\right)\n    \\right]\n\nIt follows that\n\n.. math::\n\n    \\begin{array}{rcll}\n    \\D{f_4}{v_2^{(1)}}\n    & = & \\D{f_5}{v_2^{(1)}} +\n        \\D{f_5}{v_5^{(1)}} * \\D{v_5^{(1)}}{v_2^{(1)}}\n    & = 1\n    \\\\\n    \\D{f_4}{v_4^{(1)}}\n    & = & \\D{f_5}{v_4^{(1)}} +\n        \\D{f_5}{v_5^{(1)}} * \\D{v_5}{v_4^{(1)}}\n    & = 1\n    \\end{array}\n\nAll the other partial derivatives of :math:`f_4` are zero.\n\nIndex 4: f_3\n************\nThe next operation has index 4,\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        v_4^{(0)} & = & v_3^{(0)} / 2\n        \\\\\n        v_4^{(1)} & = & v_3^{(1)} / 2\n    \\end{eqnarray}\n\nWe define the function\n:math:`f_3 \\left(  v_1^{(0)} , \\ldots , v_3^{(1)} \\right)`\nas equal to :math:`f_4`\nexcept that :math:`v_4^{(0)}` and :math:`v_4^{(1)}`\nare eliminated using this operation; i.e.,\n\n.. math::\n\n    f_3 =\n    f_4 \\left[ v_1^{(0)} , \\ldots , v_3^{(1)} ,\n        v_4^{(0)} \\left( v_3^{(0)} \\right) ,\n        v_4^{(1)} \\left( v_3^{(1)} \\right)\n    \\right]\n\nIt follows that\n\n.. math::\n\n    \\begin{array}{rcll}\n    \\D{f_3}{v_2^{(1)}}\n    & = & \\D{f_4}{v_2^{(1)}}\n    & = 1\n    \\\\\n    \\D{f_3}{v_3^{(1)}}\n    & = & \\D{f_4}{v_3^{(1)}} +\n        \\D{f_4}{v_4^{(1)}} * \\D{v_4^{(1)}}{v_3^{(1)}}\n    & = 0.5\n    \\end{array}\n\nAll the other partial derivatives of :math:`f_3` are zero.\n\nIndex 3: f_2\n************\nThe next operation has index 3,\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        v_3^{(0)} & = & v_1^{(0)} * v_1^{(0)}\n        \\\\\n        v_3^{(1)} & = & 2 * v_1^{(0)} * v_1^{(1)}\n    \\end{eqnarray}\n\nWe define the function\n:math:`f_2 \\left(  v_1^{(0)} , \\ldots , v_2^{(1)} \\right)`\nas equal to :math:`f_3`\nexcept that :math:`v_3^{(0)}` and :math:`v_3^{(1)}` are\neliminated using this operation; i.e.,\n\n.. math::\n\n    f_2 =\n    f_3 \\left[ v_1^{(0)} , \\ldots , v_2^{(1)} ,\n        v_3^{(0)} ( v_1^{(0)} ) ,\n        v_3^{(1)} ( v_1^{(0)} , v_1^{(1)} )\n    \\right]\n\nNote that, from the\n:ref:`first order forward sweep<exp_2_for1@Operation Sequence@Sweep>` ,\nthe value of :math:`v_1^{(0)}` is equal to :math:`.5`\nand  :math:`v_1^{(1)}` is equal 1.\nIt follows that\n\n.. math::\n\n    \\begin{array}{rcll}\n    \\D{f_2}{v_1^{(0)}}\n    & = &\n    \\D{f_3}{v_1^{(0)}} +\n        \\D{f_3}{v_3^{(0)}} * \\D{v_3^{(0)}}{v_1^{(0)}}  +\n        \\D{f_3}{v_3^{(1)}} * \\D{v_3^{(1)}}{v_1^{(0)}}\n    & = 1\n    \\\\\n    \\D{f_2}{v_1^{(1)}}\n    & = &\n    \\D{f_3}{v_1^{(1)}} +\n        \\D{f_3}{v_3^{(1)}} * \\D{v_3^{(1)}}{v_1^{(1)}}\n    & = 0.5\n    \\\\\n    \\D{f_2}{v_2^{(0)}}\n    & = & \\D{f_3}{v_2^{(0)}}\n    & = 0\n    \\\\\n    \\D{f_2}{v_2^{(1)}}\n    & = & \\D{f_3}{v_2^{(1)}}\n    & = 1\n    \\end{array}\n\nIndex 2: f_1\n************\nThe next operation has index 2,\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        v_2^{(0)} & = & 1 + v_1^{(0)}\n        \\\\\n        v_2^{(1)} & = & v_1^{(1)}\n    \\end{eqnarray}\n\nWe define the function\n:math:`f_1 ( v_1^{(0)} , v_1^{(1)} )`\nas equal to :math:`f_2`\nexcept that :math:`v_2^{(0)}` and  :math:`v_2^{(1)}`\nare eliminated using this operation; i.e.,\n\n.. math::\n\n    f_1 =\n    f_2 \\left[ v_1^{(0)} , v_1^{(1)} ,\n        v_2^{(0)} ( v_1^{(0)} )  ,\n        v_2^{(1)} ( v_1^{(1)} )\n    \\right]\n\nIt follows that\n\n.. math::\n\n    \\begin{array}{rcll}\n    \\D{f_1}{v_1^{(0)}}\n    & = & \\D{f_2}{v_1^{(0)}} +\n        \\D{f_2}{v_2^{(0)}} * \\D{v_2^{(0)}}{v_1^{(0)}}\n    & = 1\n    \\\\\n    \\D{f_1}{v_1^{(1)}}\n    & = & \\D{f_2}{v_1^{(1)}} +\n        \\D{f_2}{v_2^{(1)}} * \\D{v_2^{(1)}}{v_1^{(1)}}\n    & = 1.5\n    \\end{array}\n\nNote that :math:`v_1` is equal to :math:`x`,\nso the second derivative of\nthe function defined by :ref:`exp_2.hpp-name` at :math:`x = .5`\nis given by\n\n.. math::\n\n    \\Dpow{2}{x} v_5^{(0)}\n    =\n    \\D{ v_5^{(1)} }{x}\n    =\n    \\D{ v_5^{(1)} }{v_1^{(0)}}\n    =\n    \\D{f_1}{v_1^{(0)}} = 1\n\nThere is a theorem about Algorithmic Differentiation that explains why\nthe other partial of :math:`f_1` is equal to the\nfirst derivative of\nthe function defined by :ref:`exp_2.hpp-name` at :math:`x = .5`.\n{xrst_toc_hidden\n    introduction/exp_2_rev2.cpp\n}\nVerification\n************\nThe file :ref:`exp_2_rev2.cpp-name` contains a routine\nwhich verifies the values computed above.\nIt only tests the partial derivatives of\n:math:`f_j` that might not be equal to the corresponding\npartials of :math:`f_{j+1}`; i.e., the\nother partials of :math:`f_j` must be equal to the corresponding\npartials of :math:`f_{j+1}`.\n\nExercises\n*********\n\n#. Which statement in the routine defined by :ref:`exp_2_rev2.cpp-name` uses\n   the values that are calculated by the routine\n   defined by :ref:`exp_2_for0.cpp-name` ?\n   Which statements use values that are calculate by the routine\n   defined in :ref:`exp_2_for1.cpp-name` ?\n#. Consider the case where :math:`x = .1`\n   and we first preform a zero order forward sweep,\n   then a first order sweep,\n   for the operation sequence used above.\n   What are the results of a\n   second order reverse sweep; i.e.,\n   what are the corresponding derivatives of\n   :math:`f_5 , f_4 , \\ldots , f_1`.\n#. Create a modified version of\n   :ref:`exp_2_rev2.cpp-name`\n   that verifies the values you obtained for the previous exercise.\n   Also create and run a main program that reports the result\n   of calling the modified version of\n   :ref:`exp_2_rev2.cpp-name` .\n\n{xrst_end exp_2_rev2}\n------------------------------------------------------------------------------\n"
  },
  {
    "path": "introduction/exp_2_cppad.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin exp_2_cppad}\n\nexp_2: CppAD Forward and Reverse Sweeps\n#######################################\n\nPurpose\n*******\nUse CppAD forward and reverse modes to compute the\npartial derivative with respect to :math:`x`,\nat the point :math:`x = .5`,\nof the function\n\n    ``exp_2`` ( *x* )\n\nas defined by the :ref:`exp_2.hpp-name` include file.\n\nExercises\n*********\n\n#. Create and test a modified version of the routine below that computes\n   the same order derivatives with respect to :math:`x`,\n   at the point :math:`x = .1`\n   of the function\n\n        ``exp_2`` ( *x* )\n\n#. Create a routine called\n\n        ``exp_3`` ( *x* )\n\n    that evaluates the function\n\n    .. math::\n\n        f(x) = 1 + x^2 / 2 + x^3 / 6\n\n    Test a modified version of the routine below that computes\n    the derivative of :math:`f(x)`\n    at the point :math:`x = .5`.\n\n{xrst_spell_off}\n{xrst_code cpp} */\n\n# include <cppad/cppad.hpp>  // https://www.coin-or.org/CppAD/\n# include \"exp_2.hpp\"        // second order exponential approximation\nbool exp_2_cppad(void)\n{  bool ok = true;\n    using CppAD::AD;\n    using CppAD::vector;    // can use any simple vector template class\n    using CppAD::NearEqual; // checks if values are nearly equal\n\n    // domain space vector\n    size_t n = 1; // dimension of the domain space\n    vector< AD<double> > X(n);\n    X[0] = .5;    // value of x for this operation sequence\n\n    // declare independent variables and start recording operation sequence\n    CppAD::Independent(X);\n\n    // evaluate our exponential approximation\n    AD<double> x   = X[0];\n    AD<double> apx = exp_2(x);\n\n    // range space vector\n    size_t m = 1;  // dimension of the range space\n    vector< AD<double> > Y(m);\n    Y[0] = apx;    // variable that represents only range space component\n\n    // Create f: X -> Y corresponding to this operation sequence\n    // and stop recording. This also executes a zero order forward\n    // sweep using values in X for x.\n    CppAD::ADFun<double> f(X, Y);\n\n    // first order forward sweep that computes\n    // partial of exp_2(x) with respect to x\n    vector<double> dx(n);  // differential in domain space\n    vector<double> dy(m);  // differential in range space\n    dx[0] = 1.;            // direction for partial derivative\n    dy    = f.Forward(1, dx);\n    double check = 1.5;\n    ok   &= NearEqual(dy[0], check, 1e-10, 1e-10);\n\n    // first order reverse sweep that computes the derivative\n    vector<double>  w(m);   // weights for components of the range\n    vector<double> dw(n);   // derivative of the weighted function\n    w[0] = 1.;              // there is only one weight\n    dw   = f.Reverse(1, w); // derivative of w[0] * exp_2(x)\n    check = 1.5;            // partial of exp_2(x) with respect to x\n    ok   &= NearEqual(dw[0], check, 1e-10, 1e-10);\n\n    // second order forward sweep that computes\n    // second partial of exp_2(x) with respect to x\n    vector<double> x2(n);     // second order Taylor coefficients\n    vector<double> y2(m);\n    x2[0] = 0.;               // evaluate second partial .w.r.t. x\n    y2    = f.Forward(2, x2);\n    check = 0.5 * 1.;         // Taylor coef is 1/2 second derivative\n    ok   &= NearEqual(y2[0], check, 1e-10, 1e-10);\n\n    // second order reverse sweep that computes\n    // derivative of partial of exp_2(x) w.r.t. x\n    dw.resize(2 * n);         // space for first and second derivatives\n    dw    = f.Reverse(2, w);\n    check = 1.;               // result should be second derivative\n    ok   &= NearEqual(dw[0*2+1], check, 1e-10, 1e-10);\n\n    return ok;\n}\n\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end exp_2_cppad}\n*/\n"
  },
  {
    "path": "introduction/exp_2_for0.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin exp_2_for0.cpp}\n\nexp_2: Verify Zero Order Forward Sweep\n######################################\n\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <cmath>            // for fabs function\nbool exp_2_for0(double *v0)  // double v0[6]\n{  bool  ok = true;\n    double x = .5;\n\n    v0[1] = x;                                  // v1 = x\n    ok  &= std::fabs( v0[1] - 0.5) < 1e-10;\n\n    v0[2] = 1. + v0[1];                         // v2 = 1 + v1\n    ok  &= std::fabs( v0[2] - 1.5) < 1e-10;\n\n    v0[3] = v0[1] * v0[1];                      // v3 = v1 * v1\n    ok  &= std::fabs( v0[3] - 0.25) < 1e-10;\n\n    v0[4] = v0[3] / 2.;                         // v4 = v3 / 2\n    ok  &= std::fabs( v0[4] - 0.125) < 1e-10;\n\n    v0[5] = v0[2] + v0[4];                      // v5  = v2 + v4\n    ok  &= std::fabs( v0[5] - 1.625) < 1e-10;\n\n    return ok;\n}\nbool exp_2_for0(void)\n{  double v0[6];\n    return exp_2_for0(v0);\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end exp_2_for0.cpp}\n*/\n"
  },
  {
    "path": "introduction/exp_2_for1.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin exp_2_for1.cpp}\n\nexp_2: Verify First Order Forward Sweep\n#######################################\n\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <cmath>                   // prototype for fabs\nextern bool exp_2_for0(double *v0); // computes zero order forward sweep\nbool exp_2_for1(double *v1)         // double v1[6]\n{  bool ok = true;\n    double v0[6];\n\n    // set the value of v0[j] for j = 1 , ... , 5\n    ok &= exp_2_for0(v0);\n\n    v1[1] = 1.;                                     // v1 = x\n    ok    &= std::fabs( v1[1] - 1. ) <= 1e-10;\n\n    v1[2] = v1[1];                                  // v2 = 1 + v1\n    ok    &= std::fabs( v1[2] - 1. ) <= 1e-10;\n\n    v1[3] = v1[1] * v0[1] + v0[1] * v1[1];          // v3 = v1 * v1\n    ok    &= std::fabs( v1[3] - 1. ) <= 1e-10;\n\n    v1[4] = v1[3] / 2.;                             // v4 = v3 / 2\n    ok    &= std::fabs( v1[4] - 0.5) <= 1e-10;\n\n    v1[5] = v1[2] + v1[4];                          // v5 = v2 + v4\n    ok    &= std::fabs( v1[5] - 1.5) <= 1e-10;\n\n    return ok;\n}\nbool exp_2_for1(void)\n{  double v1[6];\n    return exp_2_for1(v1);\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end exp_2_for1.cpp}\n*/\n"
  },
  {
    "path": "introduction/exp_2_for2.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin exp_2_for2.cpp}\n\nexp_2: Verify Second Order Forward Sweep\n########################################\n\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <cmath>                   // prototype for fabs\nextern bool exp_2_for0(double *v0); // computes zero order forward sweep\nextern bool exp_2_for1(double *v1); // computes first order forward sweep\nbool exp_2_for2(void)\n{  bool ok = true;\n    double v0[6], v1[6], v2[6];\n\n    // set the value of v0[j], v1[j], for j = 1 , ... , 5\n    ok &= exp_2_for0(v0);\n    ok &= exp_2_for1(v1);\n\n    v2[1] = 0.;                                     // v1 = x\n    ok    &= std::fabs( v2[1] - 0. ) <= 1e-10;\n\n    v2[2] = v2[1];                                  // v2 = 1 + v1\n    ok    &= std::fabs( v2[2] - 0. ) <= 1e-10;\n\n    v2[3] = 2.*(v0[1]*v2[1] + v1[1]*v1[1]);         // v3 = v1 * v1\n    ok    &= std::fabs( v2[3] - 2. ) <= 1e-10;\n\n    v2[4] = v2[3] / 2.;                             // v4 = v3 / 2\n    ok    &= std::fabs( v2[4] - 1. ) <= 1e-10;\n\n    v2[5] = v2[2] + v2[4];                          // v5 = v2 + v4\n    ok    &= std::fabs( v2[5] - 1. ) <= 1e-10;\n\n    return ok;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end exp_2_for2.cpp}\n*/\n"
  },
  {
    "path": "introduction/exp_2_rev1.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin exp_2_rev1.cpp}\n\nexp_2: Verify First Order Reverse Sweep\n#######################################\n\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <cstddef>                 // define size_t\n# include <cmath>                   // prototype for fabs\nextern bool exp_2_for0(double *v0); // computes zero order forward sweep\nbool exp_2_rev1(void)\n{  bool ok = true;\n\n    // set the value of v0[j] for j = 1 , ... , 5\n    double v0[6];\n    ok &= exp_2_for0(v0);\n\n    // initial all partial derivatives as zero\n    double f_v[6];\n    size_t j;\n    for(j = 0; j < 6; j++)\n        f_v[j] = 0.;\n\n    // set partial derivative for f5\n    f_v[5] = 1.;\n    ok &= std::fabs( f_v[5] - 1. ) <= 1e-10; // f5_v5\n\n    // f4 = f5( v1 , v2 , v3 , v4 , v2 + v4 )\n    f_v[2] += f_v[5] * 1.;\n    f_v[4] += f_v[5] * 1.;\n    ok &= std::fabs( f_v[2] - 1. ) <= 1e-10; // f4_v2\n    ok &= std::fabs( f_v[4] - 1. ) <= 1e-10; // f4_v4\n\n    // f3 = f4( v1 , v2 , v3 , v3 / 2 )\n    f_v[3] += f_v[4] / 2.;\n    ok &= std::fabs( f_v[3] - 0.5) <= 1e-10; // f3_v3\n\n    // f2 = f3( v1 , v2 , v1 * v1 )\n    f_v[1] += f_v[3] * 2. * v0[1];\n    ok &= std::fabs( f_v[1] - 0.5) <= 1e-10; // f2_v1\n\n    // f1 = f2( v1 , 1 + v1 )\n    f_v[1] += f_v[2] * 1.;\n    ok &= std::fabs( f_v[1] - 1.5) <= 1e-10; // f1_v1\n\n    return ok;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end exp_2_rev1.cpp}\n*/\n"
  },
  {
    "path": "introduction/exp_2_rev2.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin exp_2_rev2.cpp}\n\nexp_2: Verify Second Order Reverse Sweep\n########################################\n\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <cstddef>                 // define size_t\n# include <cmath>                   // prototype for fabs\nextern bool exp_2_for0(double *v0); // computes zero order forward sweep\nextern bool exp_2_for1(double *v1); // computes first order forward sweep\nbool exp_2_rev2(void)\n{  bool ok = true;\n\n    // set the value of v0[j], v1[j] for j = 1 , ... , 5\n    double v0[6], v1[6];\n    ok &= exp_2_for0(v0);\n    ok &= exp_2_for1(v1);\n\n    // initial all partial derivatives as zero\n    double f_v0[6], f_v1[6];\n    size_t j;\n    for(j = 0; j < 6; j++)\n    {  f_v0[j] = 0.;\n        f_v1[j] = 0.;\n    }\n\n    // set partial derivative for f_5\n    f_v1[5] = 1.;\n    ok &= std::fabs( f_v1[5] - 1. ) <= 1e-10; // partial f_5 w.r.t v_5^1\n\n    // f_4 = f_5( v_1^0 , ... , v_4^1 , v_2^0 + v_4^0 , v_2^1 + v_4^1 )\n    f_v0[2] += f_v0[5] * 1.;\n    f_v0[4] += f_v0[5] * 1.;\n    f_v1[2] += f_v1[5] * 1.;\n    f_v1[4] += f_v1[5] * 1.;\n    ok &= std::fabs( f_v0[2] - 0. ) <= 1e-10; // partial f_4 w.r.t. v_2^0\n    ok &= std::fabs( f_v0[4] - 0. ) <= 1e-10; // partial f_4 w.r.t. v_4^0\n    ok &= std::fabs( f_v1[2] - 1. ) <= 1e-10; // partial f_4 w.r.t. v_2^1\n    ok &= std::fabs( f_v1[4] - 1. ) <= 1e-10; // partial f_4 w.r.t. v_4^1\n\n    // f_3 = f_4( v_1^0 , ... , v_3^1, v_3^0 / 2 , v_3^1 / 2 )\n    f_v0[3] += f_v0[4] / 2.;\n    f_v1[3] += f_v1[4] / 2.;\n    ok &= std::fabs( f_v0[3] - 0.  ) <= 1e-10; // partial f_3 w.r.t. v_3^0\n    ok &= std::fabs( f_v1[3] - 0.5 ) <= 1e-10; // partial f_3 w.r.t. v_3^1\n\n    // f_2 = f_3(  v_1^0 , ... , v_2^1, v_1^0 * v_1^0 , 2 * v_1^0 * v_1^1 )\n    f_v0[1] += f_v0[3] * 2. * v0[1];\n    f_v0[1] += f_v1[3] * 2. * v1[1];\n    f_v1[1] += f_v1[3] * 2. * v0[1];\n    ok &= std::fabs( f_v0[1] - 1.  ) <= 1e-10; // partial f_2 w.r.t. v_1^0\n    ok &= std::fabs( f_v1[1] - 0.5 ) <= 1e-10; // partial f_2 w.r.t. v_1^1\n\n    // f_1 = f_2( v_1^0 , v_1^1 , 1 + v_1^0 , v_1^1 )\n    f_v0[1] += f_v0[2] * 1.;\n    f_v1[1] += f_v1[2] * 1.;\n    ok &= std::fabs( f_v0[1] - 1. ) <= 1e-10; // partial f_1 w.r.t. v_1^0\n    ok &= std::fabs( f_v1[1] - 1.5) <= 1e-10; // partial f_1 w.r.t. v_1^1\n\n    return ok;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end exp_2_rev2.cpp}\n*/\n"
  },
  {
    "path": "introduction/exp_eps.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n// BEGIN C++\n# include <cmath>             // for fabs function\n# include \"exp_eps.hpp\"       // definition of exp_eps algorithm\nbool exp_eps(void)\n{   double x       = .5;\n    double epsilon = .2;\n    double check   = 1 + .5 + .125; // include 1 term less than epsilon\n    bool   ok      = std::fabs( exp_eps(x, epsilon) - check ) <= 1e-10;\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "introduction/exp_eps.hpp",
    "content": "# ifndef CPPAD_INTRODUCTION_EXP_EPS_HPP\n# define CPPAD_INTRODUCTION_EXP_EPS_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin exp_eps}\n{xrst_spell\n    apx\n    yyyymmdd\n}\n\nAn Epsilon Accurate Exponential Approximation\n#############################################\n\nSyntax\n******\n| # ``include`` ``\"exp_eps.hpp\"``\n| *y* = ``exp_eps`` ( *x* , *epsilon* )\n\nPurpose\n*******\nThis is a an example algorithm that is used to demonstrate\nhow Algorithmic Differentiation works with loops and\nboolean decision variables\n(see :ref:`exp_2-name` for a simpler example).\n\nMathematical Function\n*********************\nThe exponential function can be defined by\n\n.. math::\n\n    \\exp (x) = 1 + x^1 / 1 ! + x^2 / 2 ! + \\cdots\n\nWe define :math:`k ( x, \\varepsilon )` as the smallest\nnon-negative integer such that :math:`\\varepsilon \\geq x^k / k !`; i.e.,\n\n.. math::\n\n    k( x, \\varepsilon ) =\n        \\min \\{ k \\in {\\rm Z}_+ \\; | \\; \\varepsilon \\geq x^k / k ! \\}\n\nThe mathematical form for our approximation of the exponential function is\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    {\\rm exp\\_eps} (x , \\varepsilon ) & = & \\left\\{\n    \\begin{array}{ll}\n    \\frac{1}{ {\\rm exp\\_eps} (-x , \\varepsilon ) }\n        & {\\rm if} \\; x < 0\n    \\\\\n    1 + x^1 / 1 ! + \\cdots + x^{k( x, \\varepsilon)} / k( x, \\varepsilon ) !\n        & {\\rm otherwise}\n    \\end{array}\n    \\right.\n    \\end{eqnarray}\n\ninclude\n*******\nThe include command in the syntax is relative to\n\n    ``cppad-`` *yyyymmdd* / ``introduction/exp_apx``\n\nwhere ``cppad-`` *yyyymmdd* is the distribution directory\ncreated during the beginning steps of the\n:ref:`installation<Install-name>` of CppAD.\n\nx\n*\nThe argument *x* has prototype\n\n    ``const`` *Type* & *x*\n\n(see *Type* below).\nIt specifies the point at which to evaluate the\napproximation for the exponential function.\n\nepsilon\n*******\nThe argument *epsilon* has prototype\n\n    ``const`` *Type* & *epsilon*\n\nIt specifies the accuracy with which\nto approximate the exponential function value; i.e.,\nit is the value of :math:`\\varepsilon` in the\nexponential function approximation defined above.\n\ny\n*\nThe result *y* has prototype\n\n    *Type* *y*\n\nIt is the value of the exponential function\napproximation defined above.\n\nType\n****\nIf *u* and *v* are *Type* objects and *i*\nis an ``int`` :\n\n.. list-table::\n    :widths: auto\n\n    * - **Operation**\n      - **Result Type**\n      - **Description**\n    * - *Type* ( *i* )\n      - *Type*\n      - object with value equal to *i*\n    * - *Type u* = *v*\n      - *Type*\n      - construct *u* with value equal to *v*\n    * - *u* > *v*\n      - ``bool``\n      - true,\n         if *u* greater than *v* , an false otherwise\n    * - *u* = *v*\n      - *Type*\n      - new *u* (and result) is value of *v*\n    * - *u* * *v*\n      - *Type*\n      - result is value of :math:`u * v`\n    * - *u* / *v*\n      - *Type*\n      - result is value of :math:`u / v`\n    * - *u* + *v*\n      - *Type*\n      - result is value of :math:`u + v`\n    * - ``-`` *u*\n      - *Type*\n      - result is value of :math:`- u`\n\n{xrst_toc_hidden\n    introduction/exp_eps.xrst\n    introduction/exp_eps_cppad.cpp\n}\n\nImplementation\n**************\nThe file :ref:`exp_eps.hpp-name`\ncontains a C++ implementation of this function.\n\nTest\n****\nThe file :ref:`exp_eps.cpp-name`\ncontains a test of this implementation.\n\nExercises\n*********\n\n#. Using the definition of :math:`k( x, \\varepsilon )` above,\n   what is the value of\n   :math:`k(.5, 1)`, :math:`k(.5, .1)`, and :math:`k(.5, .01)` ?\n#. Suppose that we make the following call to ``exp_eps`` :\n   ::\n\n        double x       = 1.;\n        double epsilon = .01;\n        double y = exp_eps(x, epsilon);\n\n    What is the value assigned to\n    ``k`` , ``temp`` , ``term`` , and ``sum``\n    the first time through the ``while`` loop in :ref:`exp_eps.hpp-name` ?\n#. Continuing the previous exercise,\n   what is the value assigned to\n   ``k`` , ``temp`` , ``term`` , and ``sum``\n   the second time through the ``while`` loop in :ref:`exp_eps.hpp-name` ?\n\n{xrst_end exp_eps}\n-----------------------------------------------------------------------------\n*/\n// BEGIN C++\ntemplate <class Type>\nType exp_eps(const Type &x, const Type &epsilon)\n{   // abs_x = |x|\n    Type abs_x = x;\n    if( Type(0) > x )\n        abs_x = - x;\n    // initialize\n    int  k    = 0;          // initial order\n    Type term = 1.;         // term = |x|^k / k !\n    Type sum  = term;       // initial sum\n    while(term > epsilon)\n    {   k         = k + 1;          // order for next term\n        Type temp = term * abs_x;   // term = |x|^k / (k-1)!\n        term      = temp / Type(k); // term = |x|^k / k !\n        sum       = sum + term;     // sum  = 1 + ... + |x|^k / k !\n    }\n    // In the case where x is negative, use exp(x) = 1 / exp(-|x|)\n    if( Type(0) > x )\n        sum = Type(1) / sum;\n    return sum;\n}\n// END C++\n\n# endif\n"
  },
  {
    "path": "introduction/exp_eps.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin exp_eps.hpp}\n\nexp_eps: Implementation\n#######################\n\n{xrst_literal\n    introduction/exp_eps.hpp\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end exp_eps.hpp}\n-----------------------------------------------------------------------------\n{xrst_begin exp_eps.cpp}\n\nexp_eps: Test of exp_eps\n########################\n\n{xrst_literal\n    introduction/exp_eps.cpp\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end exp_eps.cpp}\n-----------------------------------------------------------------------------\n{xrst_begin exp_eps_for0}\n\nexp_eps: Operation Sequence and Zero Order Forward Sweep\n########################################################\n\nMathematical Form\n*****************\nSuppose that we use the algorithm :ref:`exp_eps.hpp-name`\nto compute ``exp_eps`` ( *x* , *epsilon* )\nwith *x* is equal to .5\nand *epsilon* is equal to .2.\nFor this case,\nthe mathematical form for the operation sequence\ncorresponding to the ``exp_eps`` is\n\n.. math::\n\n    f( x , \\varepsilon ) = 1 + x + x^2 / 2\n\nNote that, for these particular values of *x* and *epsilon* ,\nthis is the same as the mathematical form for\n:ref:`exp_2<exp_2_for0@Mathematical Form>` .\n\nOperation Sequence\n******************\nWe consider the\n:ref:`operation sequence<glossary@Operation@Sequence>`\ncorresponding to the algorithm :ref:`exp_eps.hpp-name`\nwith the argument *x* is equal to .5\nand *epsilon* is equal to .2.\n\nVariable\n========\nWe refer to values that depend on the input variables\n*x* and *epsilon* as variables.\n\nParameter\n=========\nWe refer to values that do not depend on the input variables\n*x* or *epsilon* as parameters.\nOperations where the result is a parameter are not included\nin the zero order sweep below.\n\nIndex\n=====\nThe Index column contains the index in the operation sequence\nof the corresponding atomic operation and variable.\nA Forward sweep starts with the first operation\nand ends with the last.\n\nCode\n====\nThe Code column contains the C++ source code corresponding\nto the corresponding atomic operation in the sequence.\n\nOperation\n=========\nThe Operation column contains the\nmathematical function corresponding to each atomic operation in the sequence.\n\nZero Order\n==========\nThe Zero Order column contains the\n:ref:`zero order derivative<exp_2_for0@Zero Order Expansion>`\nfor the corresponding variable in the operation sequence.\nForward mode refers to the fact that\nthese coefficients are computed in the same order as the original algorithm;\ni.e., in order of increasing index.\n\nSweep\n=====\n\n.. csv-table::\n    :widths: auto\n\n    **Index**,,**Code**,,**Operation**,,**Zero Order**\n    1,,``abs_x = x;``,,:math:`v_1 = x`,,:math:`v_1^{(0)} = 0.5`\n    2,,``temp  = term * abs_x;``,,:math:`v_2 = 1 * v_1`,,:math:`v_2^{(0)} = 0.5`\n    3,,``term = temp / Type(k);``,,:math:`v_3 = v_2 / 1`,,:math:`v_3^{(0)} = 0.5`\n    4,,``sum  = sum + term;``,,:math:`v_4 = 1 + v_3`,,:math:`v_4^{(0)} = 1.5`\n    5,,``temp  = term * abs_x;``,,:math:`v_5 = v_3 * v_1`,,:math:`v_5^{(0)} = 0.25`\n    6,,``term = temp / Type(k);``,,:math:`v_6 = v_5 / 2`,,:math:`v_6^{(0)} = 0.125`\n    7,,``sum  = sum + term;``,,:math:`v_7 = v_4 + v_6`,,:math:`v_7^{(0)} = 1.625`\n\nReturn Value\n************\nThe return value for this case is\n\n.. math::\n\n    1.625 =\n    v_7^{(0)} =\n    f ( x^{(0)} , \\varepsilon^{(0)} )\n\nComparisons\n***********\nIf *x* were negative,\nor if *epsilon* were a much smaller or much larger value,\nthe results of the following comparisons could be different:\n::\n\n    if( Type(0) > x )\n    while(term > epsilon)\n\nThis in turn would result in a different operation sequence.\nThus the operation sequence above only corresponds to\n:ref:`exp_eps.hpp-name`\nfor values of *x* and *epsilon* within a certain range.\nNote that there is a neighborhood\nof :math:`x = 0.5` for which the comparisons would have the\nsame result and hence the operation sequence would be the same.\n{xrst_toc_hidden\n    introduction/exp_eps_for0.cpp\n}\n\nVerification\n************\nThe file :ref:`exp_eps_for0.cpp-name` contains a routine\nthat verifies the values computed above.\n\nExercises\n*********\n\n#. Suppose that :math:`x^{(0)} = .1`,\n   what is the result of a zero order forward sweep for\n   the operation sequence above;\n   i.e., what are the corresponding values for\n   :math:`v_1^{(0)} , v_2^{(0)} , \\ldots , v_7^{(0)}`.\n#. Create a modified version of\n   :ref:`exp_eps_for0.cpp-name` that verifies the values you obtained\n   for the previous exercise.\n#. Create and run a main program that reports the result of calling\n   the modified version\n   of :ref:`exp_eps_for0.cpp-name` in the previous exercise.\n\n{xrst_end exp_eps_for0}\n-----------------------------------------------------------------------------\n{xrst_begin exp_eps_for1}\n\nexp_eps: First Order Forward Sweep\n##################################\n\nFirst Order Expansion\n*********************\nWe define :math:`x(t)` and :math:`\\varepsilon(t) ]` near :math:`t = 0`\nby the first order expansions\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        x(t) & = & x^{(0)} + x^{(1)} * t\n        \\\\\n        \\varepsilon(t) & = & \\varepsilon^{(0)} + \\varepsilon^{(1)} * t\n    \\end{eqnarray}\n\nIt follows that :math:`x^{(0)}` (:math:`\\varepsilon^{(0)}`) is the zero,\nand :math:`x^{(1)}`  (:math:`\\varepsilon^{(1)}`) the first,\norder derivative of :math:`x(t)`\nat :math:`t = 0` (:math:`\\varepsilon (t)`)\nat :math:`t = 0`.\n\nMathematical Form\n*****************\nSuppose that we use the algorithm :ref:`exp_eps.hpp-name`\nto compute ``exp_eps`` ( *x* , *epsilon* )\nwith *x* is equal to .5\nand *epsilon* is equal to .2.\nFor this case, the mathematical function for the operation sequence\ncorresponding to ``exp_eps`` is\n\n.. math::\n\n    f ( x , \\varepsilon ) =   1 + x + x^2 / 2\n\nThe corresponding partial derivative with respect to :math:`x`,\nand the value of the derivative, are\n\n.. math::\n\n    \\partial_x f ( x , \\varepsilon ) =   1 + x  = 1.5\n\nOperation Sequence\n******************\n\nIndex\n=====\nThe Index column contains the index in the operation sequence\nof the corresponding atomic operation.\nA Forward sweep starts with the first operation\nand ends with the last.\n\nOperation\n=========\nThe Operation column contains the\nmathematical function corresponding to each atomic operation in the sequence.\n\nZero Order\n==========\nThe Zero Order column contains the zero order derivatives\nfor the corresponding variable in the operation sequence\n(see :ref:`zero order sweep<exp_2_for1@Operation Sequence@Sweep>` ).\n\nDerivative\n==========\nThe Derivative column contains the\nmathematical function corresponding to the derivative\nwith respect to :math:`t`,\nat :math:`t = 0`, for each variable in the sequence.\n\nFirst Order\n===========\nThe First Order column contains the first order derivatives\nfor the corresponding variable in the operation sequence; i.e.,\n\n.. math::\n\n    v_j (t) = v_j^{(0)} + v_j^{(1)} t\n\nWe use :math:`x^{(1)} = 1` and :math:`\\varepsilon^{(1)} = 0`,\nso that differentiation with respect to :math:`t`,\nat :math:`t = 0`,\nis the same partial differentiation with respect to :math:`x`\nat :math:`x = x^{(0)}`.\n\nSweep\n=====\n\n.. csv-table::\n    :widths: auto\n\n    **Index**,,**Operation**,,**Zero Order**,,**Derivative**,,**First Order**\n    1,,:math:`v_1 = x`,,0.5,,:math:`v_1^{(1)} = x^{(1)}`,,:math:`v_1^{(1)} = 1`\n    2,,:math:`v_2 = 1 * v_1`,,0.5,,:math:`v_2^{(1)} = 1 * v_1^{(1)}`,,:math:`v_2^{(1)} = 1`\n    3,,:math:`v_3 = v_2 / 1`,,0.5,,:math:`v_3^{(1)} = v_2^{(1)} / 1`,,:math:`v_3^{(1)} = 1`\n    4,,:math:`v_4 = 1 + v_3`,,1.5,,:math:`v_4^{(1)} = v_3^{(1)}`,,:math:`v_4^{(1)} = 1`\n    5,,:math:`v_5 = v_3 * v_1`,,0.25,,:math:`v_5^{(1)} = v_3^{(1)} * v_1^{(0)} + v_3^{(0)} * v_1^{(1)}`,,:math:`v_5^{(1)} = 1`\n    6,,:math:`v_6 = v_5 / 2`,,0.125,,:math:`v_6^{(1)} = v_5^{(1)} / 2`,,:math:`v_6^{(1)} = 0.5`\n    7,,:math:`v_7 = v_4 + v_6`,,1.625,,:math:`v_7^{(1)} = v_4^{(1)} + v_6^{(1)}`,,:math:`v_7^{(1)} = 1.5`\n\nReturn Value\n************\nThe derivative of the return value for this case is\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    1.5\n    & = &\n    v_7^{(1)} =\n    \\left[ \\D{v_7}{t} \\right]_{t=0} =\n    \\left[ \\D{}{t} f( x^{(0)} + x^{(1)} * t , \\varepsilon^{(0)} ) \\right]_{t=0}\n    \\\\\n    & = &\n    \\partial_x f ( x^{(0)} , \\varepsilon^{(0)} ) * x^{(1)} =\n    \\partial_x f ( x^{(0)} , \\varepsilon^{(0)} )\n    \\end{eqnarray}\n\n(We have used the fact that\n:math:`x^{(1)} = 1` and :math:`\\varepsilon^{(1)} = 0`.)\n{xrst_toc_hidden\n    introduction/exp_eps_for1.cpp\n}\n\nVerification\n************\nThe file :ref:`exp_eps_for1.cpp-name` contains a routine\nthat verifies the values computed above.\n\nExercises\n*********\n\n#. Suppose that :math:`x = .1`,\n   what are the results of a zero and first order forward mode sweep for\n   the operation sequence above;\n   i.e., what are the corresponding values for\n   :math:`v_1^{(0)}, v_2^{(0)}, \\cdots , v_7^{(0)}` and\n   :math:`v_1^{(1)}, v_2^{(1)}, \\cdots , v_7^{(1)}` ?\n#. Create a modified version of :ref:`exp_eps_for1.cpp-name` that verifies\n   the derivative values from the previous exercise.\n   Also create and run a main program that reports the result\n   of calling the modified version of\n   :ref:`exp_eps_for1.cpp-name` .\n#. Suppose that :math:`x = .1` and :math:`\\epsilon = .2`,\n   what is the operation sequence corresponding to\n\n        ``exp_eps`` ( *x* , *epsilon* )\n\n{xrst_end exp_eps_for1}\n-----------------------------------------------------------------------------\n{xrst_begin exp_eps_rev1}\n{xrst_spell\n    rcll\n}\n\nexp_eps: First Order Reverse Sweep\n##################################\n\nPurpose\n*******\nFirst order reverse mode uses the\n:ref:`exp_eps_for0@Operation Sequence` ,\nand zero order forward sweep values,\nto compute the first order derivative\nof one dependent variable with respect to all the independent variables.\nThe computations are done in reverse\nof the order of the computations in the original algorithm.\n\nMathematical Form\n*****************\nSuppose that we use the algorithm :ref:`exp_eps.hpp-name`\nto compute ``exp_eps`` ( *x* , *epsilon* )\nwith *x* is equal to .5\nand *epsilon* is equal to .2.\nFor this case, the mathematical function for the operation sequence\ncorresponding to ``exp_eps`` is\n\n.. math::\n\n    f ( x , \\varepsilon ) =   1 + x + x^2 / 2\n\nThe corresponding partial derivatives,\nand the value of the derivatives, are\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    \\partial_x f ( x , \\varepsilon ) & = &  1 + x  = 1.5\n    \\\\\n    \\partial_\\varepsilon f ( x , \\varepsilon ) & = &  0\n    \\end{eqnarray}\n\nepsilon\n*******\nSince :math:`\\varepsilon` is an independent variable,\nit could included as an argument to all of the\n:math:`f_j` functions below.\nThe result would be that all the partials with respect to\n:math:`\\varepsilon` would be zero and hence we drop it to simplify\nthe presentation.\n\nf_7\n***\nIn reverse mode we choose one dependent variable and\ncompute its derivative with respect to all the independent variables.\nFor our example, we chose the value returned by :ref:`exp_eps.hpp-name`\nwhich is :math:`v_7`.\nWe begin with the function :math:`f_7` where :math:`v_7`\nis both an argument and the value of the function; i.e.,\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    f_7 ( v_1 , v_2 , v_3 , v_4 , v_5 , v_6 , v_7 ) & = & v_7\n    \\\\\n    \\D{f_7}{v_7} & = & 1\n    \\end{eqnarray}\n\nAll the other partial derivatives of :math:`f_7` are zero.\n\nIndex 7: f_6\n************\nThe last operation has index 7,\n\n.. math::\n\n    v_7 =   v_4 + v_6\n\nWe define the function\n:math:`f_6 ( v_1 , v_2 , v_3 , v_4 , v_5 , v_6 )`\nas equal to :math:`f_7`\nexcept that :math:`v_7` is eliminated using\nthis operation; i.e.\n\n.. math::\n\n    f_6  =\n    f_7 [ v_1 , v_2 , v_3 , v_4 , v_5 , v_6 , v_7 ( v_4 , v_6 ) ]\n\nIt follows that\n\n.. math::\n\n    \\begin{array}{rcll}\n    \\D{f_6}{v_4}\n    & = & \\D{f_7}{v_4} +\n        \\D{f_7}{v_7} * \\D{v_7}{v_4}\n    & = 1\n    \\\\\n    \\D{f_6}{v_6}\n    & = & \\D{f_7}{v_6} +\n        \\D{f_7}{v_7} * \\D{v_7}{v_6}\n    & = 1\n    \\end{array}\n\nAll the other partial derivatives of :math:`f_6` are zero.\n\nIndex 6: f_5\n************\nThe previous operation has index 6,\n\n.. math::\n\n    v_6 = v_5 / 2\n\nWe define the function\n:math:`f_5 (  v_1 , v_2 , v_3 , v_4 , v_5 )`\nas equal to :math:`f_6`\nexcept that :math:`v_6` is eliminated using this operation; i.e.,\n\n.. math::\n\n    f_5 =\n    f_6 [  v_1 , v_2 , v_3 , v_4 , v_5 , v_6 ( v_5 ) ]\n\nIt follows that\n\n.. math::\n\n    \\begin{array}{rcll}\n    \\D{f_5}{v_4}\n    & = & \\D{f_6}{v_4}\n    & = 1\n    \\\\\n    \\D{f_5}{v_5}\n    & = & \\D{f_6}{v_5} +\n        \\D{f_6}{v_6} * \\D{v_6}{v_5}\n    & = 0.5\n    \\end{array}\n\nAll the other partial derivatives of :math:`f_5` are zero.\n\nIndex 5: f_4\n************\nThe previous operation has index 5,\n\n.. math::\n\n    v_5 = v_3 * v_1\n\nWe define the function\n:math:`f_4 (  v_1 , v_2 , v_3 , v_4 )`\nas equal to :math:`f_5`\nexcept that :math:`v_5` is eliminated using this operation; i.e.,\n\n.. math::\n\n    f_4 =\n    f_5 [  v_1 , v_2 , v_3 , v_4 , v_5 ( v_3 , v_1 )  ]\n\nGiven the information from the forward sweep, we have\n:math:`v_3 =  0.5` and :math:`v_1 = 0.5`.\nIt follows that\n\n.. math::\n\n    \\begin{array}{rcll}\n    \\D{f_4}{v_1}\n    & = & \\D{f_5}{v_1} +\n        \\D{f_5}{v_5} * \\D{v_5}{v_1}\n    & =  0.25\n    \\\\\n    \\D{f_4}{v_2} & = & \\D{f_5}{v_2}  & = 0\n    \\\\\n    \\D{f_4}{v_3}\n    & = & \\D{f_5}{v_3} +\n        \\D{f_5}{v_5} * \\D{v_5}{v_3}\n    & =  0.25\n    \\\\\n    \\D{f_4}{v_4}\n    & = & \\D{f_5}{v_4}\n    & = 1\n    \\end{array}\n\nIndex 4: f_3\n************\nThe previous operation has index 4,\n\n.. math::\n\n    v_4 = 1 + v_3\n\nWe define the function\n:math:`f_3 (  v_1 , v_2 , v_3 )`\nas equal to :math:`f_4`\nexcept that :math:`v_4` is eliminated using this operation; i.e.,\n\n.. math::\n\n    f_3 =\n    f_4 [  v_1 , v_2 , v_3 , v_4 ( v_3 )  ]\n\nIt follows that\n\n.. math::\n\n    \\begin{array}{rcll}\n    \\D{f_3}{v_1}\n    & = & \\D{f_4}{v_1}\n    & =  0.25\n    \\\\\n    \\D{f_3}{v_2} & = & \\D{f_4}{v_2}  & = 0\n    \\\\\n    \\D{f_3}{v_3}\n    & = & \\D{f_4}{v_3} +\n        \\D{f_4}{v_4} * \\D{v_4}{v_3}\n    & =  1.25\n    \\end{array}\n\nIndex 3: f_2\n************\nThe previous operation has index 3,\n\n.. math::\n\n    v_3 = v_2 / 1\n\nWe define the function\n:math:`f_2 (  v_1 , v_2 )`\nas equal to :math:`f_3`\nexcept that :math:`v_3` is eliminated using this operation; i.e.,\n\n.. math::\n\n    f_2 =\n    f_4 [  v_1 , v_2 , v_3 ( v_2 )  ]\n\nIt follows that\n\n.. math::\n\n    \\begin{array}{rcll}\n    \\D{f_2}{v_1}\n    & = & \\D{f_3}{v_1}\n    & =  0.25\n    \\\\\n    \\D{f_2}{v_2} & = & \\D{f_3}{v_2}  +\n        \\D{f_3}{v_3} * \\D{v_3}{v_2}\n    & = 1.25\n    \\end{array}\n\nIndex 2: f_1\n************\nThe previous operation has index 1,\n\n.. math::\n\n    v_2 = 1 * v_1\n\nWe define the function\n:math:`f_1 (  v_1 )`\nas equal to :math:`f_2`\nexcept that :math:`v_2` is eliminated using this operation; i.e.,\n\n.. math::\n\n    f_1 =\n    f_2 [  v_1 , v_2 ( v_1 )  ]\n\nIt follows that\n\n.. math::\n\n    \\begin{array}{rcll}\n    \\D{f_1}{v_1} & = & \\D{f_2}{v_1}  +\n        \\D{f_2}{v_2} * \\D{v_2}{v_1}\n    & = 1.5\n    \\end{array}\n\nNote that :math:`v_1` is equal to :math:`x`,\nso the derivative of ``exp_eps`` ( *x* , *epsilon* )\nat *x* equal to .5 and *epsilon* equal .2 is\n1.5 in the *x* direction and zero in the *epsilon* direction.\nWe also note that\n:ref:`forward<exp_eps_for1-name>` mode gave the\nsame result for the partial in the *x* direction.\n{xrst_toc_hidden\n    introduction/exp_eps_rev1.cpp\n}\n\nVerification\n************\nThe file :ref:`exp_eps_rev1.cpp-name` contains a routine\nthat verifies the values computed above.\nIt only tests the partial derivatives of\n:math:`f_j` that might not be equal to the corresponding\npartials of :math:`f_{j+1}`; i.e., the\nother partials of :math:`f_j` must be equal to the corresponding\npartials of :math:`f_{j+1}`.\n\nExercises\n*********\n\n#. Consider the case where :math:`x = .1`\n   and we first preform a zero order forward mode sweep\n   for the operation sequence used above (in reverse order).\n   What are the results of a\n   first order reverse mode sweep; i.e.,\n   what are the corresponding values for\n   :math:`\\D{f_j}{v_k}` for all :math:`j, k` such that\n   :math:`\\D{f_j}{v_k} \\neq 0`.\n#. Create a modified version of\n   :ref:`exp_eps_rev1.cpp-name`\n   that verifies the values you obtained for the previous exercise.\n   Also create and run a main program that reports the result\n   of calling the modified version of\n   :ref:`exp_eps_rev1.cpp-name` .\n\n{xrst_end exp_eps_rev1}\n-----------------------------------------------------------------------------\n{xrst_begin exp_eps_for2}\n\nexp_eps: Second Order Forward Mode\n##################################\n\nSecond Order Expansion\n**********************\n\nWe define :math:`x(t)` and :math:`\\varepsilon(t) ]` near :math:`t = 0`\nby the second order expansions\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        x(t) & = & x^{(0)} + x^{(1)} * t  + x^{(2)} * t^2 / 2\n        \\\\\n        \\varepsilon(t) & = & \\varepsilon^{(0)} + \\varepsilon^{(1)} * t\n                                +   \\varepsilon^{(2)} * t^2 / 2\n    \\end{eqnarray}\n\nIt follows that for :math:`k = 0 , 1 , 2`,\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        x^{(k)}  & = & \\dpow{k}{t} x (0)\n        \\\\\n        \\varepsilon^{(k)}  & = & \\dpow{k}{t} \\varepsilon (0)\n    \\end{eqnarray}\n\nPurpose\n*******\nIn general, a second order forward sweep is given the\n:ref:`exp_2_for1@First Order Expansion`\nfor all of the variables in an operation sequence,\nand the second order derivatives for the independent variables.\nIt uses these to compute the second order derivative,\nand thereby obtain the second order expansion,\nfor all the variables in the operation sequence.\n\nMathematical Form\n*****************\nSuppose that we use the algorithm :ref:`exp_eps.hpp-name`\nto compute ``exp_eps`` ( *x* , *epsilon* )\nwith *x* is equal to .5\nand *epsilon* is equal to .2.\nFor this case, the mathematical function for the operation sequence\ncorresponding to ``exp_eps`` is\n\n.. math::\n\n    f ( x , \\varepsilon ) =   1 + x + x^2 / 2\n\nThe corresponding second partial derivative with respect to :math:`x`,\nand the value of the derivative, are\n\n.. math::\n\n    \\Dpow{2}{x} f ( x , \\varepsilon ) =   1.\n\nOperation Sequence\n******************\n\nIndex\n=====\nThe Index column contains the index in the operation sequence\nof the corresponding atomic operation.\nA Forward sweep starts with the first operation\nand ends with the last.\n\nZero\n====\nThe Zero column contains the zero order sweep results\nfor the corresponding variable in the operation sequence\n(see :ref:`zero order sweep<exp_2_for0@Operation Sequence@Sweep>` ).\n\nOperation\n=========\nThe Operation column contains the\nfirst order sweep operation for this variable.\n\nFirst\n=====\nThe First column contains the first order sweep results\nfor the corresponding variable in the operation sequence\n(see :ref:`first order sweep<exp_2_for1@Operation Sequence@Sweep>` ).\n\nDerivative\n==========\nThe Derivative column contains the\nmathematical function corresponding to the second derivative\nwith respect to :math:`t`,\nat :math:`t = 0`, for each variable in the sequence.\n\nSecond\n======\nThe Second column contains the second order derivatives\nfor the corresponding variable in the operation sequence; i.e.,\nthe second order expansion for the *i*-th variable is given by\n\n.. math::\n\n    v_i (t) = v_i^{(0)} + v_i^{(1)} * t +  v_i^{(2)} * t^2 / 2\n\nWe use :math:`x^{(1)} = 1`, :math:`x^{(2)} = 0`,\nuse :math:`\\varepsilon^{(1)} = 1`, and :math:`\\varepsilon^{(2)} = 0`\nso that second order differentiation\nwith respect to :math:`t`, at :math:`t = 0`,\nis the same as the second partial differentiation\nwith respect to :math:`x` at :math:`x = x^{(0)}`.\n\nSweep\n=====\n\n.. list-table::\n    :widths: auto\n\n    * - **Index**\n      -\n      - **Zero**\n      -\n      - **Operation**\n      -\n      - **First**\n      -\n      - **Derivative**\n      -\n      - **Second**\n    * - 1\n      -\n      - 0.5\n      -\n      - :math:`v_1^{(1)} = x^{(1)}`\n      -\n      - 1\n      -\n      - :math:`v_2^{(2)} = x^{(2)}`\n      -\n      - 0\n    * - 2\n      -\n      - 0.5\n      -\n      - :math:`v_2^{(1)} = 1 * v_1^{(1)}`\n      -\n      - 1\n      -\n      - :math:`v_2^{(2)} = 1 * v_1^{(2)}`\n      -\n      - 0\n    * - 3\n      -\n      - 0.5\n      -\n      - :math:`v_3^{(1)} = v_2^{(1)} / 1`\n      -\n      - 1\n      -\n      - :math:`v_3^{(2)} = v_2^{(2)} / 1`\n      -\n      - 0\n    * - 4\n      -\n      - 1.5\n      -\n      - :math:`v_4^{(1)} = v_3^{(1)}`\n      -\n      - 1\n      -\n      - :math:`v_4^{(2)} = v_3^{(2)}`\n      -\n      - 0\n    * - 5\n      -\n      - 0.25\n      -\n      - :math:`v_5^{(1)} = v_3^{(1)} * v_1^{(0)} + v_3^{(0)} * v_1^{(1)}`\n      -\n      - 1\n      -\n      - :math:`v_5^{(2)} = v_3^{(2)} * v_1^{(0)} + 2 * v_3^{(1)} * v_1^{(1)}`\n         :math:`+ v_3^{(0)} * v_1^{(2)}`\n      -\n      - 2\n    * - 6\n      -\n      - 0.125\n      -\n      - :math:`v_6^{(1)} = v_5^{(1)} / 2`\n      -\n      - 0.5\n      -\n      - :math:`v_6^{(2)} = v_5^{(2)} / 2`\n      -\n      - 1\n    * - 7\n      -\n      - 1.625\n      -\n      - :math:`v_7^{(1)} = v_4^{(1)} + v_6^{(1)}`\n      -\n      - 1.5\n      -\n      - :math:`v_7^{(2)} = v_4^{(2)} + v_6^{(2)}`\n      -\n      - 1\n\nReturn Value\n************\nThe second derivative of the return value for this case is\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    1\n    & = &\n    v_7^{(2)} =\n    \\left[ \\Dpow{2}{t} v_7 \\right]_{t=0} =\n    \\left[ \\Dpow{2}{t} f( x^{(0)} + x^{(1)} * t , \\varepsilon^{(0)} ) \\right]_{t=0}\n    \\\\\n    & = &\n    x^{(1)} * \\Dpow{2}{x} f ( x^{(0)} ,  \\varepsilon^{(0)} ) * x^{(1)} =\n    \\Dpow{2}{x} f ( x^{(0)} ,  \\varepsilon^{(0)} )\n    \\end{eqnarray}\n\n(We have used the fact that\n:math:`x^{(1)} = 1`, :math:`x^{(2)} = 0`,\n:math:`\\varepsilon^{(1)} = 1`, and :math:`\\varepsilon^{(2)} = 0`.)\n{xrst_toc_hidden\n    introduction/exp_eps_for2.cpp\n}\nVerification\n************\nThe file :ref:`exp_eps_for2.cpp-name` contains a routine\nwhich verifies the values computed above.\n\nExercises\n*********\n\n#. Which statement in the routine defined by :ref:`exp_eps_for2.cpp-name` uses\n   the values that are calculated by the routine\n   defined by :ref:`exp_eps_for1.cpp-name` ?\n#. Suppose that :math:`x = .1`,\n   what are the results of a zero, first, and second order forward sweep for\n   the operation sequence above;\n   i.e., what are the corresponding values for\n   :math:`v_i^{(k)}` for :math:`i = 1, \\ldots , 7` and :math:`k = 0, 1, 2`.\n#. Create a modified version of :ref:`exp_eps_for2.cpp-name` that verifies\n   the derivative values from the previous exercise.\n   Also create and run a main program that reports the result\n   of calling the modified version of\n   :ref:`exp_eps_for2.cpp-name` .\n\n{xrst_end exp_eps_for2}\n-----------------------------------------------------------------------------\n{xrst_begin exp_eps_rev2}\n{xrst_spell\n    rcll\n}\n\nexp_eps: Second Order Reverse Sweep\n###################################\n\nPurpose\n*******\nIn general, a second order reverse sweep is given the\n:ref:`exp_eps_for1@First Order Expansion`\nfor all of the variables in an operation sequence.\nGiven a choice of a particular variable,\nit computes the derivative,\nof that variables first order expansion coefficient,\nwith respect to all of the independent variables.\n\nMathematical Form\n*****************\nSuppose that we use the algorithm :ref:`exp_eps.hpp-name`\nto compute ``exp_eps`` ( *x* , *epsilon* )\nwith *x* is equal to .5\nand *epsilon* is equal to .2.\nFor this case, the mathematical function for the operation sequence\ncorresponding to ``exp_eps`` is\n\n.. math::\n\n    f ( x , \\varepsilon ) =   1 + x + x^2 / 2\n\nThe corresponding derivative of the\npartial derivative with respect to :math:`x` is\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    \\Dpow{2}{x} f ( x , \\varepsilon ) & = &  1\n    \\\\\n    \\partial_\\varepsilon \\partial_x f ( x , \\varepsilon ) & = &  0\n    \\end{eqnarray}\n\nepsilon\n*******\nSince :math:`\\varepsilon` is an independent variable,\nit could included as an argument to all of the\n:math:`f_j` functions below.\nThe result would be that all the partials with respect to\n:math:`\\varepsilon` would be zero and hence we drop it to simplify\nthe presentation.\n\nf_7\n***\nIn reverse mode we choose one dependent variable and\ncompute its derivative with respect to all the independent variables.\nFor our example, we chose the value returned by :ref:`exp_eps.hpp-name`\nwhich is :math:`v_7`.\nWe begin with the function :math:`f_7` where :math:`v_7`\nis both an argument and the value of the function; i.e.,\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    f_7 \\left(\n        v_1^{(0)} , v_1^{(1)} , \\ldots , v_7^{(0)} , v_7^{(1)}\n    \\right)\n    & = & v_7^{(1)}\n    \\\\\n    \\D{f_7}{v_7^{(1)}} & = & 1\n    \\end{eqnarray}\n\nAll the other partial derivatives of :math:`f_7` are zero.\n\nIndex 7: f_6\n************\nThe last operation has index 7,\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        v_7^{(0)} & = &   v_4^{(0)} + v_6^{(0)}\n        \\\\\n        v_7^{(1)} & = &   v_4^{(1)} + v_6^{(1)}\n    \\end{eqnarray}\n\nWe define the function\n:math:`f_6 \\left( v_1^{(0)} , \\ldots , v_6^{(1)} \\right)`\nas equal to :math:`f_7`\nexcept that :math:`v_7^{(0)}` and :math:`v_7^{(1)}` are eliminated using\nthis operation; i.e.\n\n.. math::\n\n    f_6  =\n    f_7 \\left[ v_1^{(0)} , \\ldots , v_6^{(1)} ,\n        v_7^{(0)} \\left( v_4^{(0)} , v_6^{(0)} \\right)  ,\n        v_7^{(1)} \\left( v_4^{(1)} , v_6^{(1)} \\right)\n    \\right]\n\nIt follows that\n\n.. math::\n\n    \\begin{array}{rcll}\n    \\D{f_6}{v_4^{(1)}}\n    & = & \\D{f_7}{v_4^{(1)}} +\n        \\D{f_7}{v_7^{(1)}} * \\D{v_7^{(1)}}{v_4^{(1)}}\n    & = 1\n    \\\\\n    \\D{f_6}{v_6^{(1)}}\n    & = & \\D{f_7}{v_6^{(1)}} +\n        \\D{f_7}{v_7^{(1)}} * \\D{v_7^{(1)}}{v_6^{(1)}}\n    & = 1\n    \\end{array}\n\nAll the other partial derivatives of :math:`f_6` are zero.\n\nIndex 6: f_5\n************\nThe previous operation has index 6,\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        v_6^{(0)} & = & v_5^{(0)} / 2\n        \\\\\n        v_6^{(1)} & = & v_5^{(1)} / 2\n    \\end{eqnarray}\n\nWe define the function\n:math:`f_5 \\left( v_1^{(0)} , \\ldots , v_5^{(1)} \\right)`\nas equal to :math:`f_6`\nexcept that :math:`v_6^{(0)}` and :math:`v_6^{(1)}` are eliminated using\nthis operation; i.e.\n\n.. math::\n\n    f_5 =\n    f_6 \\left[ v_1^{(0)} , \\ldots , v_5^{(1)} ,\n        v_6^{(0)} \\left( v_5^{(0)} \\right) ,\n        v_6^{(1)} \\left( v_5^{(1)} \\right)\n    \\right]\n\nIt follows that\n\n.. math::\n\n    \\begin{array}{rcll}\n    \\D{f_5}{v_4^{(1)}}\n    & = & \\D{f_6}{v_4^{(1)}}\n    & = 1\n    \\\\\n    \\D{f_5}{v_5^{(1)}}\n    & = & \\D{f_6}{v_5} +\n        \\D{f_6}{v_6^{(1)}} * \\D{v_6^{(1)}}{v_5^{(1)}}\n    & = 0.5\n    \\end{array}\n\nAll the other partial derivatives of :math:`f_5` are zero.\n\nIndex 5: f_4\n************\nThe previous operation has index 5,\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        v_5^{(0)} & = & v_3^{(0)} * v_1^{(0)}\n        \\\\\n        v_5^{(1)} & = & v_3^{(1)} * v_1^{(0)} + v_3^{(0)} * v_1^{(1)}\n    \\end{eqnarray}\n\nWe define the function\n:math:`f_4 \\left( v_1^{(0)} , \\ldots , v_4^{(1)} \\right)`\nas equal to :math:`f_5`\nexcept that :math:`v_5^{(0)}` and :math:`v_5^{(1)}` are eliminated using\nthis operation; i.e.\n\n.. math::\n\n    f_4 =\n    f_5 \\left[  v_1^{(0)} , \\ldots , v_4^{(1)} ,\n        v_5^{(0)} \\left( v_1^{(0)}, v_3^{(0)} \\right) ,\n        v_5^{(1)} \\left( v_1^{(0)}, v_1^{(1)}, v_3^{(0)} , v_3^{(1)} \\right) ,\n    \\right]\n\nGiven the information from the forward sweep, we have\n:math:`v_1^{(0)} =  0.5`,\n:math:`v_3^{(0)} =  0.5`,\n:math:`v_1^{(1)} =  1`,\n:math:`v_3^{(1)} =  1`,\nand the fact that the partial of :math:`f_5` with respect to\n:math:`v_5^{(0)}` is zero, we have\n\n.. math::\n\n    \\begin{array}{rcll}\n    \\D{f_4}{v_1^{(0)}}\n    & = & \\D{f_5}{v_1^{(0)}}\n      +   \\D{f_5}{v_5^{(1)}} * \\D{v_5^{(1)}}{v_1^{(0)}}\n    & = 0.5\n    \\\\\n    \\D{f_4}{v_1^{(1)}}\n    & = & \\D{f_5}{v_1^{(1)}}\n      +   \\D{f_5}{v_5^{(1)}} * \\D{v_5^{(1)}}{v_1^{(1)}}\n    & = 0.25\n    \\\\\n    \\D{f_4}{v_3^{(0)}}\n    & = & \\D{f_5}{v_3^{(0)}}\n      +   \\D{f_5}{v_5^{(1)}} * \\D{v_5^{(1)}}{v_3^{(0)}}\n    & = 0.5\n    \\\\\n    \\D{f_4}{v_3^{(1)}}\n    & = & \\D{f_3}{v_1^{(1)}}\n      +   \\D{f_5}{v_5^{(1)}} * \\D{v_5^{(1)}}{v_3^{(1)}}\n    & = 0.25\n    \\\\\n    \\D{f_4}{v_4^{(1)}}\n    & = & \\D{f_5}{v_4^{(1)}}\n    & = 1\n    \\end{array}\n\nAll the other partial derivatives of :math:`f_5` are zero.\n\nIndex 4: f_3\n************\nThe previous operation has index 4,\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        v_4^{(0)} = 1 + v_3^{(0)}\n        \\\\\n        v_4^{(1)} = v_3^{(1)}\n    \\end{eqnarray}\n\nWe define the function\n:math:`f_3 \\left( v_1^{(0)} , \\ldots , v_3^{(1)} \\right)`\nas equal to :math:`f_4`\nexcept that :math:`v_4^{(0)}` and :math:`v_4^{(1)}` are eliminated using\nthis operation; i.e.\n\n.. math::\n\n    f_3 =\n    f_4 \\left[ v_1^{(0)} , \\ldots , v_3^{(1)} ,\n        v_4^{(0)} \\left( v_3^{(0)} \\right) ,\n        v_4^{(1)} \\left( v_3^{(1)} \\right)\n    \\right]\n\nIt follows that\n\n.. math::\n\n    \\begin{array}{rcll}\n    \\D{f_3}{v_1^{(0)}}\n    & = & \\D{f_4}{v_1^{(0)}}\n    & =  0.5\n    \\\\\n    \\D{f_3}{v_1^{(1)}}\n    & = & \\D{f_4}{v_1^{(1)}}\n    & =  0.25\n    \\\\\n    \\D{f_3}{v_2^{(0)}}\n    & = & \\D{f_4}{v_2^{(0)}}\n    & = 0\n    \\\\\n    \\D{f_3}{v_2^{(1)}}\n    & = & \\D{f_4}{v_2^{(1)}}\n    & = 0\n    \\\\\n    \\D{f_3}{v_3^{(0)}}\n    & = & \\D{f_4}{v_3^{(0)}}\n      +   \\D{f_4}{v_4^{(0)}} * \\D{v_4^{(0)}}{v_3^{(0)}}\n    & = 0.5\n    \\\\\n    \\D{f_3}{v_3^{(1)}}\n    & = & \\D{f_4}{v_3^{(1)}}\n      +   \\D{f_4}{v_4^{(1)}} * \\D{v_4^{(1)}}{v_3^{(1)}}\n    & = 1.25\n    \\end{array}\n\nIndex 3: f_2\n************\nThe previous operation has index 3,\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        v_3^{(0)} & = & v_2^{(0)} / 1\n        \\\\\n        v_3^{(1)} & = & v_2^{(1)} / 1\n    \\end{eqnarray}\n\nWe define the function\n:math:`f_2 \\left( v_1^{(0)} , \\ldots , v_2^{(1)} \\right)`\nas equal to :math:`f_3`\nexcept that :math:`v_3^{(0)}` and :math:`v_3^{(1)}` are eliminated using\nthis operation; i.e.\n\n.. math::\n\n    f_2 =\n    f_3 \\left[ v_1^{(0)} , \\ldots , v_2^{(1)} ,\n        v_3^{(0)} \\left( v_2^{(0)} \\right) ,\n        v_3^{(1)} \\left( v_2^{(1)} \\right)\n    \\right]\n\nIt follows that\n\n.. math::\n\n    \\begin{array}{rcll}\n    \\D{f_2}{v_1^{(0)}}\n    & = & \\D{f_3}{v_1^{(0)}}\n    & =  0.5\n    \\\\\n    \\D{f_2}{v_1^{(1)}}\n    & = & \\D{f_3}{v_1^{(1)}}\n    & =  0.25\n    \\\\\n    \\D{f_2}{v_2^{(0)}}\n    & = & \\D{f_3}{v_2^{(0)}}\n      +   \\D{f_3}{v_3^{(0)}} * \\D{v_3^{(0)}}{v_2^{(0)}}\n    & = 0.5\n    \\\\\n    \\D{f_2}{v_2^{(1)}}\n    & = & \\D{f_3}{v_2^{(1)}}\n      +   \\D{f_3}{v_3^{(1)}} * \\D{v_3^{(1)}}{v_2^{(0)}}\n    & = 1.25\n    \\end{array}\n\nIndex 2: f_1\n************\nThe previous operation has index 1,\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        v_2^{(0)} & = & 1 * v_1^{(0)}\n        \\\\\n        v_2^{(1)} & = & 1 * v_1^{(1)}\n    \\end{eqnarray}\n\nWe define the function\n:math:`f_1 \\left( v_1^{(0)} , v_1^{(1)} \\right)`\nas equal to :math:`f_2`\nexcept that :math:`v_2^{(0)}` and :math:`v_2^{(1)}` are eliminated using\nthis operation; i.e.\n\n.. math::\n\n    f_1 =\n    f_2 \\left[  v_1^{(0)} , v_1^{(1)} ,\n        v_2^{(0)} \\left( v_1^{(0)} \\right)  ,\n        v_2^{(1)} \\left( v_1^{(1)} \\right)\n    \\right]\n\nIt follows that\n\n.. math::\n\n    \\begin{array}{rcll}\n    \\D{f_1}{v_1^{(0)}}\n    & = & \\D{f_2}{v_1^{(0)}}\n      +   \\D{f_2}{v_2^{(0)}} * \\D{v_2^{(0)}}{v_1^{(0)}}\n    & =  1\n    \\\\\n    \\D{f_1}{v_1^{(1)}}\n    & = & \\D{f_2}{v_1^{(1)}}\n      +   \\D{f_2}{v_2^{(1)}} * \\D{v_2^{(1)}}{v_1^{(1)}}\n    & = 1.5\n    \\end{array}\n\nNote that :math:`v_1` is equal to :math:`x`,\nso the second partial derivative of\n``exp_eps`` ( *x* , *epsilon* )\nat *x* equal to .5 and *epsilon* equal .2 is\n\n.. math::\n\n    \\Dpow{2}{x} v_7^{(0)}\n    = \\D{v_7^{(1)}}{x}\n    = \\D{f_1}{v_1^{(0)}}\n    = 1\n\nThere is a theorem about algorithmic differentiation that explains why\nthe other partial of :math:`f_1` is equal to the first partial of\n``exp_eps`` ( *x* , *epsilon* )\nwith respect to :math:`x`.\n{xrst_toc_hidden\n    introduction/exp_eps_rev2.cpp\n}\n\nVerification\n************\nThe file :ref:`exp_eps_rev2.cpp-name` contains a routine\nthat verifies the values computed above.\nIt only tests the partial derivatives of\n:math:`f_j` that might not be equal to the corresponding\npartials of :math:`f_{j+1}`; i.e., the\nother partials of :math:`f_j` must be equal to the corresponding\npartials of :math:`f_{j+1}`.\n\nExercises\n*********\n\n#. Consider the case where :math:`x = .1`\n   and we first preform a zero order forward mode sweep\n   for the operation sequence used above (in reverse order).\n   What are the results of a\n   first order reverse mode sweep; i.e.,\n   what are the corresponding values for\n   :math:`\\D{f_j}{v_k}` for all :math:`j, k` such that\n   :math:`\\D{f_j}{v_k} \\neq 0`.\n#. Create a modified version of\n   :ref:`exp_eps_rev2.cpp-name`\n   that verifies the values you obtained for the previous exercise.\n   Also create and run a main program that reports the result\n   of calling the modified version of\n   :ref:`exp_eps_rev2.cpp-name` .\n\n{xrst_end exp_eps_rev2}\n-----------------------------------------------------------------------------\n"
  },
  {
    "path": "introduction/exp_eps_cppad.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin exp_eps_cppad}\n\nexp_eps: CppAD Forward and Reverse Sweeps\n#########################################\n\nPurpose\n*******\nUse CppAD forward and reverse modes to compute the\npartial derivative with respect to :math:`x`,\nat the point :math:`x = .5` and :math:`\\varepsilon = .2`,\nof the function\n\n    ``exp_eps`` ( *x* , *epsilon* )\n\nas defined by the :ref:`exp_eps.hpp-name` include file.\n\nExercises\n*********\n\n#. Create and test a modified version of the routine below that computes\n   the same order derivatives with respect to :math:`x`,\n   at the point :math:`x = .1` and :math:`\\varepsilon = .2`,\n   of the function\n\n        ``exp_eps`` ( *x* , *epsilon* )\n\n#. Create and test a modified version of the routine below that computes\n   partial derivative with respect to :math:`x`,\n   at the point :math:`x = .1` and :math:`\\varepsilon = .2`,\n   of the function corresponding to the operation sequence\n   for :math:`x = .5` and :math:`\\varepsilon = .2`.\n   Hint: you could define a vector u with two components and use\n\n        *f* . ``Forward`` (0, *u* )\n\n    to run zero order forward mode at a point different\n    form the point where the operation sequence corresponding to\n    *f* was recorded.\n\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <cppad/cppad.hpp>  // https://www.coin-or.org/CppAD/\n# include \"exp_eps.hpp\"      // our example exponential function approximation\nbool exp_eps_cppad(void)\n{  bool ok = true;\n    using CppAD::AD;\n    using CppAD::vector;    // can use any simple vector template class\n    using CppAD::NearEqual; // checks if values are nearly equal\n\n    // domain space vector\n    size_t n = 2; // dimension of the domain space\n    vector< AD<double> > U(n);\n    U[0] = .5;    // value of x for this operation sequence\n    U[1] = .2;    // value of e for this operation sequence\n\n    // declare independent variables and start recording operation sequence\n    CppAD::Independent(U);\n\n    // evaluate our exponential approximation\n    AD<double> x       = U[0];\n    AD<double> epsilon = U[1];\n    AD<double> apx = exp_eps(x, epsilon);\n\n    // range space vector\n    size_t m = 1;  // dimension of the range space\n    vector< AD<double> > Y(m);\n    Y[0] = apx;    // variable that represents only range space component\n\n    // Create f: U -> Y corresponding to this operation sequence\n    // and stop recording. This also executes a zero order forward\n    // mode sweep using values in U for x and e.\n    CppAD::ADFun<double> f(U, Y);\n\n    // first order forward mode sweep that computes partial w.r.t x\n    vector<double> du(n);      // differential in domain space\n    vector<double> dy(m);      // differential in range space\n    du[0] = 1.;                // x direction in domain space\n    du[1] = 0.;\n    dy    = f.Forward(1, du);  // partial w.r.t. x\n    double check = 1.5;\n    ok   &= NearEqual(dy[0], check, 1e-10, 1e-10);\n\n    // first order reverse mode sweep that computes the derivative\n    vector<double>  w(m);     // weights for components of the range\n    vector<double> dw(n);     // derivative of the weighted function\n    w[0] = 1.;                // there is only one weight\n    dw   = f.Reverse(1, w);   // derivative of w[0] * exp_eps(x, epsilon)\n    check = 1.5;              // partial w.r.t. x\n    ok   &= NearEqual(dw[0], check, 1e-10, 1e-10);\n    check = 0.;               // partial w.r.t. epsilon\n    ok   &= NearEqual(dw[1], check, 1e-10, 1e-10);\n\n    // second order forward sweep that computes\n    // second partial of exp_eps(x, epsilon) w.r.t. x\n    vector<double> x2(n);     // second order Taylor coefficients\n    vector<double> y2(m);\n    x2[0] = 0.;               // evaluate partial w.r.t x\n    x2[1] = 0.;\n    y2    = f.Forward(2, x2);\n    check = 0.5 * 1.;         // Taylor coef is 1/2 second derivative\n    ok   &= NearEqual(y2[0], check, 1e-10, 1e-10);\n\n    // second order reverse sweep that computes\n    // derivative of partial of exp_eps(x, epsilon) w.r.t. x\n    dw.resize(2 * n);         // space for first and second derivative\n    dw    = f.Reverse(2, w);\n    check = 1.;               // result should be second derivative\n    ok   &= NearEqual(dw[0*2+1], check, 1e-10, 1e-10);\n\n    return ok;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end exp_eps_cppad}\n*/\n"
  },
  {
    "path": "introduction/exp_eps_for0.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin exp_eps_for0.cpp}\n\nexp_eps: Verify Zero Order Forward Sweep\n########################################\n\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <cmath>                // for fabs function\nbool exp_eps_for0(double *v0)    // double v0[8]\n{  bool  ok = true;\n    double x = .5;\n\n    v0[1] = x;                                  // abs_x = x;\n    ok  &= std::fabs( v0[1] - 0.5) < 1e-10;\n\n    v0[2] = 1. * v0[1];                         // temp = term * abs_x;\n    ok  &= std::fabs( v0[2] - 0.5) < 1e-10;\n\n    v0[3] = v0[2] / 1.;                         // term = temp / Type(k);\n    ok  &= std::fabs( v0[3] - 0.5) < 1e-10;\n\n    v0[4] = 1. + v0[3];                         // sum = sum + term;\n    ok  &= std::fabs( v0[4] - 1.5) < 1e-10;\n\n    v0[5] = v0[3] * v0[1];                      // temp = term * abs_x;\n    ok  &= std::fabs( v0[5] - 0.25) < 1e-10;\n\n    v0[6] = v0[5] / 2.;                         // term = temp / Type(k);\n    ok  &= std::fabs( v0[6] - 0.125) < 1e-10;\n\n    v0[7] = v0[4] + v0[6];                      // sum = sum + term;\n    ok  &= std::fabs( v0[7] - 1.625) < 1e-10;\n\n    return ok;\n}\nbool exp_eps_for0(void)\n{  double v0[8];\n    return exp_eps_for0(v0);\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end exp_eps_for0.cpp}\n*/\n"
  },
  {
    "path": "introduction/exp_eps_for1.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin exp_eps_for1.cpp}\n\nexp_eps: Verify First Order Forward Sweep\n#########################################\n\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <cmath>                     // for fabs function\nextern bool exp_eps_for0(double *v0); // computes zero order forward sweep\nbool exp_eps_for1(double *v1)         // double v[8]\n{  bool ok = true;\n    double v0[8];\n\n    // set the value of v0[j] for j = 1 , ... , 7\n    ok &= exp_eps_for0(v0);\n\n    v1[1] = 1.;                                      // v1 = x\n    ok    &= std::fabs( v1[1] - 1. ) <= 1e-10;\n\n    v1[2] = 1. * v1[1];                              // v2 = 1 * v1\n    ok    &= std::fabs( v1[2] - 1. ) <= 1e-10;\n\n    v1[3] = v1[2] / 1.;                              // v3 = v2 / 1\n    ok    &= std::fabs( v1[3] - 1. ) <= 1e-10;\n\n    v1[4] = v1[3];                                   // v4 = 1 + v3\n    ok    &= std::fabs( v1[4] - 1. ) <= 1e-10;\n\n    v1[5] = v1[3] * v0[1] + v0[3] * v1[1];           // v5 = v3 * v1\n    ok    &= std::fabs( v1[5] - 1. ) <= 1e-10;\n\n    v1[6] = v1[5] / 2.;                              // v6 = v5 / 2\n    ok    &= std::fabs( v1[6] - 0.5 ) <= 1e-10;\n\n    v1[7] = v1[4] + v1[6];                           // v7 = v4 + v6\n    ok    &= std::fabs( v1[7] - 1.5 ) <= 1e-10;\n\n    return ok;\n}\nbool exp_eps_for1(void)\n{  double v1[8];\n    return exp_eps_for1(v1);\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end exp_eps_for1.cpp}\n*/\n"
  },
  {
    "path": "introduction/exp_eps_for2.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin exp_eps_for2.cpp}\n\nexp_eps: Verify Second Order Forward Sweep\n##########################################\n\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <cmath>                     // for fabs function\nextern bool exp_eps_for0(double *v0); // computes zero order forward sweep\nextern bool exp_eps_for1(double *v1); // computes first order forward sweep\nbool exp_eps_for2(void)\n{  bool ok = true;\n    double v0[8], v1[8], v2[8];\n\n    // set the value of v0[j], v1[j] for j = 1 , ... , 7\n    ok &= exp_eps_for0(v0);\n    ok &= exp_eps_for1(v1);\n\n    v2[1] = 0.;                                      // v1 = x\n    ok    &= std::fabs( v2[1] - 0. ) <= 1e-10;\n\n    v2[2] = 1. * v2[1];                              // v2 = 1 * v1\n    ok    &= std::fabs( v2[2] - 0. ) <= 1e-10;\n\n    v2[3] = v2[2] / 1.;                              // v3 = v2 / 1\n    ok    &= std::fabs( v2[3] - 0. ) <= 1e-10;\n\n    v2[4] = v2[3];                                   // v4 = 1 + v3\n    ok    &= std::fabs( v2[4] - 0. ) <= 1e-10;\n\n    v2[5] = v2[3] * v0[1] + 2. * v1[3] * v1[1]       // v5 = v3 * v1\n             + v0[3] * v2[1];\n    ok    &= std::fabs( v2[5] - 2. ) <= 1e-10;\n\n    v2[6] = v2[5] / 2.;                              // v6 = v5 / 2\n    ok    &= std::fabs( v2[6] - 1. ) <= 1e-10;\n\n    v2[7] = v2[4] + v2[6];                           // v7 = v4 + v6\n    ok    &= std::fabs( v2[7] - 1. ) <= 1e-10;\n\n    return ok;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end exp_eps_for2.cpp}\n*/\n"
  },
  {
    "path": "introduction/exp_eps_rev1.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin exp_eps_rev1.cpp}\n\nexp_eps: Verify First Order Reverse Sweep\n#########################################\n\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <cstddef>                     // define size_t\n# include <cmath>                       // for fabs function\nextern bool exp_eps_for0(double *v0);   // computes zero order forward sweep\nbool exp_eps_rev1(void)\n{  bool ok = true;\n\n    // set the value of v0[j] for j = 1 , ... , 7\n    double v0[8];\n    ok &= exp_eps_for0(v0);\n\n    // initial all partial derivatives as zero\n    double f_v[8];\n    size_t j;\n    for(j = 0; j < 8; j++)\n        f_v[j] = 0.;\n\n    // set partial derivative for f7\n    f_v[7] = 1.;\n    ok    &= std::fabs( f_v[7] - 1. ) <= 1e-10;     // f7_v7\n\n    // f6( v1 , v2 , v3 , v4 , v5 , v6 )\n    f_v[4] += f_v[7] * 1.;\n    f_v[6] += f_v[7] * 1.;\n    ok     &= std::fabs( f_v[4] - 1.  ) <= 1e-10;   // f6_v4\n    ok     &= std::fabs( f_v[6] - 1.  ) <= 1e-10;   // f6_v6\n\n    // f5( v1 , v2 , v3 , v4 , v5 )\n    f_v[5] += f_v[6] / 2.;\n    ok     &= std::fabs( f_v[5] - 0.5 ) <= 1e-10;   // f5_v5\n\n    // f4( v1 , v2 , v3 , v4 )\n    f_v[1] += f_v[5] * v0[3];\n    f_v[3] += f_v[5] * v0[1];\n    ok     &= std::fabs( f_v[1] - 0.25) <= 1e-10;   // f4_v1\n    ok     &= std::fabs( f_v[3] - 0.25) <= 1e-10;   // f4_v3\n\n    // f3( v1 , v2 , v3 )\n    f_v[3] += f_v[4] * 1.;\n    ok     &= std::fabs( f_v[3] - 1.25) <= 1e-10;   // f3_v3\n\n    // f2( v1 , v2 )\n    f_v[2] += f_v[3] / 1.;\n    ok     &= std::fabs( f_v[2] - 1.25) <= 1e-10;   // f2_v2\n\n    // f1( v1 )\n    f_v[1] += f_v[2] * 1.;\n    ok     &= std::fabs( f_v[1] - 1.5 ) <= 1e-10;   // f1_v2\n\n    return ok;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end exp_eps_rev1.cpp}\n*/\n"
  },
  {
    "path": "introduction/exp_eps_rev2.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin exp_eps_rev2.cpp}\n\nexp_eps: Verify Second Order Reverse Sweep\n##########################################\n\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <cstddef>                     // define size_t\n# include <cmath>                       // for fabs function\nextern bool exp_eps_for0(double *v0);   // computes zero order forward sweep\nextern bool exp_eps_for1(double *v1);   // computes first order forward sweep\nbool exp_eps_rev2(void)\n{  bool ok = true;\n\n    // set the value of v0[j], v1[j] for j = 1 , ... , 7\n    double v0[8], v1[8];\n    ok &= exp_eps_for0(v0);\n    ok &= exp_eps_for1(v1);\n\n    // initial all partial derivatives as zero\n    double f_v0[8], f_v1[8];\n    size_t j;\n    for(j = 0; j < 8; j++)\n    {  f_v0[j] = 0.;\n        f_v1[j] = 0.;\n    }\n\n    // set partial derivative for f_7\n    f_v1[7] = 1.;\n    ok &= std::fabs( f_v1[7] - 1.  ) <= 1e-10; // partial f_7 w.r.t. v_7^1\n\n    // f_6 = f_7( v_1^0 , ... , v_6^1 , v_4^0 + v_6^0, v_4^1 , v_6^1 )\n    f_v0[4] += f_v0[7];\n    f_v0[6] += f_v0[7];\n    f_v1[4] += f_v1[7];\n    f_v1[6] += f_v1[7];\n    ok &= std::fabs( f_v0[4] - 0.  ) <= 1e-10; // partial f_6 w.r.t. v_4^0\n    ok &= std::fabs( f_v0[6] - 0.  ) <= 1e-10; // partial f_6 w.r.t. v_6^0\n    ok &= std::fabs( f_v1[4] - 1.  ) <= 1e-10; // partial f_6 w.r.t. v_4^1\n    ok &= std::fabs( f_v1[6] - 1.  ) <= 1e-10; // partial f_6 w.r.t. v_6^1\n\n    // f_5 = f_6( v_1^0 , ... , v_5^1 , v_5^0 / 2 , v_5^1 / 2 )\n    f_v0[5] += f_v0[6] / 2.;\n    f_v1[5] += f_v1[6] / 2.;\n    ok &= std::fabs( f_v0[5] - 0.  ) <= 1e-10; // partial f_5 w.r.t. v_5^0\n    ok &= std::fabs( f_v1[5] - 0.5 ) <= 1e-10; // partial f_5 w.r.t. v_5^1\n\n    // f_4 = f_5( v_1^0 , ... , v_4^1 , v_3^0 * v_1^0 ,\n    //            v_3^1 * v_1^0 + v_3^0 * v_1^1 )\n    f_v0[1] += f_v0[5] * v0[3] + f_v1[5] * v1[3];\n    f_v0[3] += f_v0[5] * v0[1] + f_v1[5] * v1[1];\n    f_v1[1] += f_v1[5] * v0[3];\n    f_v1[3] += f_v1[5] * v0[1];\n    ok &= std::fabs( f_v0[1] - 0.5  ) <= 1e-10; // partial f_4 w.r.t. v_1^0\n    ok &= std::fabs( f_v0[3] - 0.5  ) <= 1e-10; // partial f_4 w.r.t. v_3^0\n    ok &= std::fabs( f_v1[1] - 0.25 ) <= 1e-10; // partial f_4 w.r.t. v_1^1\n    ok &= std::fabs( f_v1[3] - 0.25 ) <= 1e-10; // partial f_4 w.r.t. v_3^1\n\n    // f_3 = f_4(  v_1^0 , ... , v_3^1 , 1 + v_3^0 , v_3^1 )\n    f_v0[3] += f_v0[4];\n    f_v1[3] += f_v1[4];\n    ok &= std::fabs( f_v0[3] - 0.5 ) <= 1e-10;  // partial f_3 w.r.t. v_3^0\n    ok &= std::fabs( f_v1[3] - 1.25) <= 1e-10;  // partial f_3 w.r.t. v_3^1\n\n    // f_2 = f_3( v_1^0 , ... , v_2^1 , v_2^0 , v_2^1 )\n    f_v0[2] += f_v0[3];\n    f_v1[2] += f_v1[3];\n    ok &= std::fabs( f_v0[2] - 0.5 ) <= 1e-10;  // partial f_2 w.r.t. v_2^0\n    ok &= std::fabs( f_v1[2] - 1.25) <= 1e-10;  // partial f_2 w.r.t. v_2^1\n\n    // f_1 = f_2 ( v_1^0 , v_2^0 , v_1^0 , v_2^0 )\n    f_v0[1] += f_v0[2];\n    f_v1[1] += f_v1[2];\n    ok &= std::fabs( f_v0[1] - 1.  ) <= 1e-10;  // partial f_1 w.r.t. v_1^0\n    ok &= std::fabs( f_v1[1] - 1.5 ) <= 1e-10;  // partial f_1 w.r.t. v_1^1\n\n    return ok;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end exp_eps_rev2.cpp}\n*/\n"
  },
  {
    "path": "introduction/introduction.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin exp_apx.cpp}\n\nCorrectness Tests For Exponential Approximation in Introduction\n###############################################################\n\nRunning Tests\n*************\nTo build this program and run its correctness tests see :ref:`cmake_check-name` .\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end exp_apx.cpp}\n*/\n// BEGIN C++\n\n// system include files used for I/O\n# include <iostream>\n\n// memory allocation routine\n# include <cppad/utility/thread_alloc.hpp>\n\n// test runner\n# include <cppad/utility/test_boolofvoid.hpp>\n\n// external complied tests\nextern bool exp_2(void);\nextern bool exp_2_cppad(void);\nextern bool exp_2_for1(void);\nextern bool exp_2_for2(void);\nextern bool exp_2_rev1(void);\nextern bool exp_2_rev2(void);\nextern bool exp_2_for0(void);\nextern bool exp_eps(void);\nextern bool exp_eps_cppad(void);\nextern bool exp_eps_for1(void);\nextern bool exp_eps_for2(void);\nextern bool exp_eps_for0(void);\nextern bool exp_eps_rev1(void);\nextern bool exp_eps_rev2(void);\n\n// main program that runs all the tests\nint main(void)\n{   std::string group = \"introduction\";\n    size_t      width = 20;\n    CppAD::test_boolofvoid Run(group, width);\n\n    // This comment is used by OneTest\n\n    // external compiled tests\n    Run( exp_2,           \"exp_2\"          );\n    Run( exp_2_cppad,     \"exp_2_cppad\"    );\n    Run( exp_2_for0,      \"exp_2_for0\"     );\n    Run( exp_2_for1,      \"exp_2_for1\"     );\n    Run( exp_2_for2,      \"exp_2_for2\"     );\n    Run( exp_2_rev1,      \"exp_2_rev1\"     );\n    Run( exp_2_rev2,      \"exp_2_rev2\"     );\n    Run( exp_eps,         \"exp_eps\"        );\n    Run( exp_eps_cppad,   \"exp_eps_cppad\"  );\n    Run( exp_eps_for0,    \"exp_eps_for0\"   );\n    Run( exp_eps_for1,    \"exp_eps_for1\"   );\n    Run( exp_eps_for2,    \"exp_eps_for2\"   );\n    Run( exp_eps_rev1,    \"exp_eps_rev1\"   );\n    Run( exp_eps_rev2,    \"exp_eps_rev2\"   );\n    //\n    // check for memory leak\n    bool memory_ok = CppAD::thread_alloc::free_all();\n    // print summary at end\n    bool ok = Run.summary(memory_ok);\n    //\n    return static_cast<int>( ! ok );\n}\n// END C++\n"
  },
  {
    "path": "pkgconfig/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# Construct cppad.pc from cppad.pc.in; see\n# http://people.freedesktop.org/~dbn/pkg-config-guide.html\n# -----------------------------------------------------------------------------\n# {xrst_begin pkgconfig}\n# {xrst_spell\n#     builddir\n#     cflags\n#     datadir\n#     includedir\n#     libdir\n#     libs\n# }\n# {xrst_comment_ch #}\n#\n# CppAD pkg-config Files\n# ######################\n#\n# Purpose\n# *******\n# The ``pkg-config`` program helps with the used if installed libraries\n# and include files; see its\n# `guide <https://people.freedesktop.org/~dbn/pkg-config-guide.html>`_\n# for more information on writing an using pkg-config files.\n#\n# cppad.pc\n# ********\n#\n# PKG_CONFIG_PATH\n# ===============\n# The ``cppad.pc`` file is installed in the following two directories:\n#\n# | |tab| *prefix* / *libdir* / ``pkgconfig``\n# | |tab| *prefix* / *datadir* / ``pkgconfig``\n#\n# where *prefix* is :ref:`cmake@cppad_prefix` ,\n# *libdir* is the first entry in\n# :ref:`cmake@cmake_install_libdirs` ,\n# and # *datadir* is\n# :ref:`cmake@cmake_install_datadir` .\n# In order to use ``pkg-config`` ,\n# one of these directories must your ``PKG_CONFIG_PATH`` .\n#\n# Compile Flags\n# =============\n# The necessary flags for compiling code that includes CppAD can\n# be obtained with the command\n# ::\n#\n#     pkg-config --cflags cppad\n#\n# Link Flags\n# ==========\n# The flags for linking can be obtains with the command\n# ::\n#\n#     pkg-config --libs cppad\n#\n# Extra Definitions\n# =================\n# The ``cppad.pc`` file contains the text:\n#\n# | |tab| ``prefix`` = *prefix*\n# | |tab| ``exec_prefix`` = *exec_prefix*\n# | |tab| ``includedir`` = *includedir*\n# | |tab| ``libdir`` = *libdir*\n#\n# where *prefix* , *exec_prefix* , *includedir* , and\n# *libdir* are the\n# `gnu installation variables <https://www.gnu.org/prep/standards/html_node/Directory-Variables.html>`_.\n#\n# cppad-uninstalled.pc\n# ********************\n#\n# PKG_CONFIG_PATH\n# ===============\n# The ``cppad-uninstalled.pc`` file is located in the following directory:\n#\n#     *builddir* / ``pkgconfig``\n#\n# where *builddir* is the directory where the :ref:`cmake-name` command\n# is executed.\n#\n# Compile Flags\n# =============\n# The necessary flags for compiling code that includes CppAD,\n# before CppAD is installed, can be obtained with the command\n# ::\n#\n#     pkg-config --cflags cppad-uninstalled\n#\n# Link Flags\n# ==========\n# The flags for linking can be obtains with the command\n# ::\n#\n#     pkg-config --libs cppad-uninstalled\n#\n# Extra Definitions\n# =================\n# The ``cppad-uninstalled.pc`` file has the same extra variables\n# as the ``cppad.pc`` file.\n#\n# {xrst_end pkgconfig}\n# ----------------------------------------------------------------------------\n#\n# The following variables are used by cppad.pc.in\n# and set in the top source CMakeLists.txt:\n#  cppad_prefix,\n#  cppad_description,\n#  cppad_version,\n#  cppad_url,\n#  cppad_lib\n# The other variables used by cppad.pc.in are set below\n# Note that cppad_SOURCE_DIR is used by cppad-uninstalled.pc\n# and is set by cmake to the top source directory.\n#\n# cppad_includedir\nLIST(GET cmake_install_includedirs 0 cppad_includedir)\n#\n# cppad_libdir\nLIST(GET cmake_install_libdirs 0 cppad_libdir)\n#\n# add_to_set\nMACRO(add_to_set variable_name element)\n    IF( \"${${variable_name}}\" STREQUAL \"\" )\n        SET(${variable_name} ${element} )\n    ELSE( \"${${variable_name}}\" STREQUAL \"\" )\n        LIST(FIND ${variable_name} ${element} index)\n        IF( index EQUAL -1 )\n            SET(${variable_name} \"${${variable_name}} ${element}\")\n        ENDIF( index EQUAL -1 )\n    ENDIF( \"${${variable_name}}\" STREQUAL \"\" )\nENDMACRO(add_to_set variable_name element)\n# -----------------------------------------------------------------------------\n# initialize\nSET(cppad_libdir_list \"-L${cppad_prefix}/${cppad_libdir}\")\nSET(cppad_lib_list    \"-l${cppad_lib}\")\nSET(cppad_requires         \"\")\nSET(cppad_libs_private     \"\")\nSET(cppad_requires_private \"\")\n#\n# Colpack does not have a pkgconfig file.\nSET(colpack_libdir     NOTFOUND)\nIF( cppad_has_colpack )\n    FOREACH(dir ${cmake_install_libdirs})\n        FILE(GLOB file_list \"${colpack_prefix}/${dir}/libColPack.*\" )\n        IF( file_list )\n            SET(colpack_libdir \"${colpack_prefix}/${dir}\")\n        ENDIF( file_list )\n    ENDFOREACH(dir ${cmake_install_libdirs})\n    IF( NOT colpack_libdir )\n        MESSAGE(FATAL_ERROR \"Cannit find libColPack.* below ${colpack_prefix}\")\n    ENDIF( NOT colpack_libdir )\n    add_to_set(cppad_libdir_list \"-L${colpack_libdir}\")\n    add_to_set(cppad_lib_list    \"-lColPack\")\nENDIF( cppad_has_colpack )\n#\n# Ipopt and eigen have pkgconfig files.\nIF( cppad_has_eigen )\n    SET(cppad_requires         \"${cppad_requires} eigen3\")\nENDIF( cppad_has_eigen )\nIF( cppad_has_ipopt )\n    SET(cppad_requires         \"${cppad_requires} ipopt\")\n    add_to_set(cppad_lib_list  \"-lcppad_ipopt\" )\nENDIF( cppad_has_ipopt )\n# -----------------------------------------------------------------------------\n# cppad.pc\nCONFIGURE_FILE(\n    ${CMAKE_CURRENT_SOURCE_DIR}/cppad.pc.in\n    ${CMAKE_CURRENT_BINARY_DIR}/cppad.pc\n    @ONLY\n)\n# cppad-uninstalled.pc\nCONFIGURE_FILE(\n    ${CMAKE_CURRENT_SOURCE_DIR}/cppad-uninstalled.pc.in\n    ${CMAKE_CURRENT_BINARY_DIR}/cppad-uninstalled.pc\n    @ONLY\n)\n# During install copy cppad.pc to datadir\nINSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/cppad.pc\n    DESTINATION ${cppad_abs_datadir}/pkgconfig\n)\n# During install also copy cppad.pc to libdir\nINSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/cppad.pc\n    DESTINATION ${cppad_abs_libdir}/pkgconfig\n)\n"
  },
  {
    "path": "pkgconfig/cppad-uninstalled.pc.in",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# The settings in this file file are the same as in cppad.pc except for the\n# following line:\n# includedir=@cppad_SOURCE_DIR@/include\n#\nprefix=@cppad_prefix@\nexec_prefix=${prefix}\nincludedir=@cppad_SOURCE_DIR@/include\nlibdir=${exec_prefix}/@cppad_libdir@\n#\nName:                  cppad\nDescription:           @cppad_description@\nVersion:               @cppad_version@\nURL:                   @cppad_url@\n#\nCflags:                -I${includedir}\nLibs:                  @cppad_libdir_list@ @cppad_lib_list@\nRequires:              @cppad_requires@\nLibs.private:          @cppad_libs_private@\nRequires.private:      @cppad_requires_private@\n"
  },
  {
    "path": "pkgconfig/cppad.pc.in",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n#\n# The following variable settings seem to by required by the vcpkg packager,\n# see https://www.gnu.org/prep/standards/html_node/Directory-Variables.html\n# for the meaning of these variables.\n#\nprefix=@cppad_prefix@\nexec_prefix=${prefix}\nincludedir=${prefix}/@cppad_includedir@\nlibdir=${exec_prefix}/@cppad_libdir@\n#\n# See https://people.freedesktop.org/~dbn/pkg-config-guide.html\n# for the meaning of the settings below:\n#\nName:                  cppad\nDescription:           @cppad_description@\nVersion:               @cppad_version@\nURL:                   @cppad_url@\n#\nCflags:                -I${includedir}\nLibs:                  @cppad_libdir_list@ @cppad_lib_list@\nRequires:              @cppad_requires@\nLibs.private:          @cppad_libs_private@\nRequires.private:      @cppad_requires_private@\n"
  },
  {
    "path": "readme.md",
    "content": "# CppAD: A Package for Differentiation of C++ Algorithms\n\n## Documentation\n[users guide](https://cppad.readthedocs.io/latest/user_guide.html)\n\n## License\nSPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n\n## Install\n\n- The preferred method to test and\n  [install](https://cppad.readthedocs.io/latest/Install.html)\n  CppAD uses [cmake](https://cmake.org).\n\n- A deprecated\n  [autotools](https://cppad.readthedocs.io/latest/cmake.html#autotools)\n  procedure can be used for this purpose, but it will eventually be removed.\n\n## Getting Started\n  [get_started](https://cppad.readthedocs.io/latest/get_started.cpp.html)\n  demonstrates using CppAD by computing the derivative of a simple example function.\n"
  },
  {
    "path": "speed/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-25 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n# Initialize list of tests as empty\nSET(check_speed_depends \"\")\n\n# The CMakeLists.txt file in the specified source directory is processed\n# before the current input file continues beyond this command.\n# add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])\nADD_SUBDIRECTORY(src)\nADD_SUBDIRECTORY(cppad)\nADD_SUBDIRECTORY(double)\nADD_SUBDIRECTORY(example)\nADD_SUBDIRECTORY(xpackage)\nIF ( cppad_profile_flag )\n    ADD_SUBDIRECTORY(profile)\nENDIF ( cppad_profile_flag )\n#\nIF( cppad_has_adolc )\n    ADD_SUBDIRECTORY(adolc)\nENDIF( cppad_has_adolc )\nIF( cppad_has_fadbad )\n    ADD_SUBDIRECTORY(fadbad)\nENDIF( cppad_has_fadbad )\nIF( cppad_has_cppadcg )\n    ADD_SUBDIRECTORY(cppadcg)\nENDIF( cppad_has_cppadcg )\nIF( cppad_has_sacado )\n    ADD_SUBDIRECTORY(sacado)\nENDIF( cppad_has_sacado )\nIF( NOT cppad_link_flags_has_m32 )\n    ADD_SUBDIRECTORY(cppad_jit)\nENDIF( NOT cppad_link_flags_has_m32 )\n\n# check_speed\nADD_CUSTOM_TARGET(check_speed DEPENDS ${check_speed_depends} )\nMESSAGE(STATUS \"make check_speed: available\")\n\n# Change check depends in parent environment\nadd_to_list(check_depends check_speed)\nSET(check_depends \"${check_depends}\" PARENT_SCOPE)\n"
  },
  {
    "path": "speed/add_test.sh",
    "content": "#! /bin/bash -e\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# Use this shell script when a new test is added to initially create\n# the source code files */test_name.cpp which return false (for not available).\n#\necho \"Change this script so that it automates the omhelp commands\"\necho \"at the beginning of the created files.\"\necho exit 1\n#\nif [ \"$1\" == \"\" ]\nthen\n    echo \"usage: new_test.sh test_name\"\n    echo \"where test_name is the name of the new test being added\"\n    exit 1\nfi\ntest_name=\"$1\"\nif [ ! -e \"link_$test_name.cpp\" ]\nthen\n    echo \"The file ./link_$test_name.cpp does not yet exist.\"\n    echo \"It must first be created before executing this script.\"\n    exit 1\nfi\nif ! grep \"speed\\/link_$test_name.cpp\" main.cpp\nthen\n    echo \"link_$test_name.cpp has not yet been added to main.cpp\"\n    exit 1\nfi\nlist=\"\n    adolc\n    cppad\n    double\n    fadbad\n    sacado\n\"\nfor dir in profile $list\ndo\n    if grep \"link_$test_name.cpp\" $dir/makefile.am\n    then\n        echo \"$test_name.cpp is already in $dir/makefile.am\"\n        exit 1\n    fi\n    if [ -e $dir/$test_name.cpp ]\n    then\n        echo \"The file $dir/$test_name.cpp already exists.\"\n        exit 1\n    fi\ndone\n#\nsed -i main.cpp -e \"s/speed\\/link[^%]*\\$/&%\\n\\tspeed\\/link_$test_name.cpp/\"\n#\ncopy=`sed -n ../COPYING -e '/^\\/\\*/,/\\*\\/$/p'`\nlink=`sed -n link_$test_name.cpp -e \"/^ *extern *bool *link_$test_name/,/^);/p\"`\nfun=`echo \"$link\" | sed -e 's/extern */\\n/' -e 's/^);/)\\n{\\n\\treturn false;\\n}/'`\nfor dir in $list\ndo\n    echo \"$copy$fun\" > $dir/$test_name.cpp\n    sed -i $dir/makefile.am \\\n        -e \"s/\\/main.cpp.*/&\\n\\t..\\/link_$test_name.cpp \\\\\\\\/\" \\\n        -e \"s/\\/link_$test_name.cpp.*/&\\n\\t$test_name.cpp \\\\\\\\/\"\ndone\nsed -i profile/makefile.am \\\n    -e \"s/\\/main.cpp.*/&\\n\\t..\\/link_$test_name.cpp \\\\\\\\/\" \\\n    -e \"s/\\/link_$test_name.cpp.*/&\\n\\t..\\/cppad\\/$test_name.cpp \\\\\\\\/\"\n"
  },
  {
    "path": "speed/adolc/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-23 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# Build the speed/adolc directory tests\n# Inherit build type from ../CMakeList.txt\n\n# assert include_adolc is true\nassert(include_adolc )\n\n\n# Adds flags to the compiler command line for sources in the current directory\n# and below. This command can be used to add any flags, but it was originally\n# intended to add preprocessor definitions.\nADD_DEFINITIONS(\"-DCPPAD_ADOLC_SPEED\")\n\n# Local include directories to search (not in package_prefix/includdir)\nINCLUDE_DIRECTORIES( ${CMAKE_CURRENT_SOURCE_DIR}/../src )\n\n# add_executable(<name> [WIN32] [MACOSX_BUNDLE] [EXCLUDE_FROM_ALL]\n#                 source1 source2 ... sourceN\n# )\nSET(source_list ../main.cpp alloc_mat.cpp\n    det_lu.cpp\n    det_minor.cpp\n    mat_mul.cpp\n    ode.cpp\n    poly.cpp\n    sparse_hessian.cpp\n    sparse_jacobian.cpp\n)\nset_compile_flags( speed_adolc \"${cppad_debug_which}\" \"${source_list}\" )\n#\nADD_EXECUTABLE( speed_adolc EXCLUDE_FROM_ALL ${source_list} )\n\n# List of libraries to be linked into the specified target\nTARGET_LINK_LIBRARIES(speed_adolc\n    speed_src\n    ${cppad_lib}\n    ${adolc_LINK_LIBRARIES}\n    ${colpack_libs}\n)\n\n# check_speed_adolc\nadd_check_executable(check_speed adolc \"correct 54321 colpack\")\n"
  },
  {
    "path": "speed/adolc/adolc_alloc_mat.hpp",
    "content": "# ifndef CPPAD_SPEED_ADOLC_ADOLC_ALLOC_MAT_HPP\n# define CPPAD_SPEED_ADOLC_ADOLC_ALLOC_MAT_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\ndouble** adolc_alloc_mat(size_t m, size_t n);\nvoid adolc_free_mat(double** mat);\n\n# endif\n"
  },
  {
    "path": "speed/adolc/adolc_usrparms.sh",
    "content": "#! /bin/bash -e\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n#! /bin/bash\n#\nmessage=\"\nusage: adolc_usrparms.sh <dir>\n         adolc_usrparms.sh <dir> <bufsize> <tbufsize> show\n         adolc_usrparms.sh <dir> <bufsize> <tbufsize> modify\n\nThe first usage prints the value of BUFSIZE and TBUFSIZE.\nThe second usage show how the usrparms.h file would be modified.\nThe third usage actually modifies the file.\n\n<dir>:\nThe distribution directory corresponding to adolc; e.g., adolc-1.10.2.\nThe file where the buffer sizes are specified is <dir>/adolc/usrparms.h.\n\nBUFSIZE:\nBuffer size for tapes.\n\nTBUFSIZE:\nBuffer size for temporary Taylor store.\n\n<bufsize>:\nthe value we are changing the Adolc BUFSIZE parameter to.\n\n<tbufsize>:\nthe value we are changing the Adolc TBUFSIZE parameter to.\n\"\nif [ \"$1\" == \"\" ]\nthen\n    echo \"$message\"\n    exit 1\nfi\nfile=\"$1/adolc/usrparms.h\"\nif [ ! -e $file ]\nthen\n    echo \"adolc_usrparms.sh: cannot find the file $file\"\n    exit 1\nfi\n#\n# case where we print the value of BUFSIZE and  TBUFSIZE\nif [ \"$2\" == \"\" ]\nthen\n    grep \"^#define T*BUFSIZE\" < $file\n    exit 0\nfi\nsame=\"/* Previous: \\1\\2 */ \\3\\n#define\"\ncmd_one=\"s|^\\(#define BUFSIZE *\\)\\([0-9]*\\)\\(.*\\)|$same BUFSIZE    $2|\"\ncmd_two=\"s|^\\(#define TBUFSIZE *\\)\\([0-9]*\\)\\(.*\\)|$same TBUFSIZE   $3|\"\nif [ \"$4\" == \"show\" ]\nthen\n    sed < $file > adolc_usrparms.tmp \\\n        -e \"$cmd_one\" -e \"$cmd_two\"\n    diff $file adolc_usrparms.tmp\n    exit 0\nfi\nif [ \"$4\" == \"modify\" ]\nthen\n    sed < $file > adolc_usrparms.tmp \\\n        -e \"$cmd_one\" -e \"$cmd_two\"\n    diff $file adolc_usrparms.tmp\n    mv adolc_usrparms.tmp $file\n    echo \"Execute the following commands for the change to take effect:\"\n    echo \"cd $1\"\n    echo \"make\"\n    echo \"make install\"\n    exit 0\nfi\necho \"$message\"\nexit 1\n"
  },
  {
    "path": "speed/adolc/alloc_mat.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin adolc_alloc_mat}\n\nAdolc Test Utility: Allocate and Free Memory For a Matrix\n#########################################################\n\nSyntax\n******\n| *mat* = ``adolc_alloc_mat`` ( *m* , *n* )\n| *adolc_free_mat* ( ``mat`` )\n\nPurpose\n*******\nUse the :ref:`thread_alloc-name` memory allocator to allocate and free\nmemory that can be used as a matrix with the Adolc package.\n\nm\n*\nIs the number of rows in the matrix.\n\nn\n*\nIs the number of columns in the matrix.\n\nmat\n***\nIs the matrix.\nTo be specific,\nbetween a call to ``adolc_alloc_mat`` ,\nand the corresponding call to ``adolc_free_mat`` ,\nfor *i* = 0 , ... , *m* ``-1``\nand *j* = 0 , ... , *n* ``-1`` ,\n*mat* [ *i* ][ *j* ] is the element in row *i*\nand column *j* .\n\n{xrst_end adolc_alloc_mat}\n*/\n# include <cppad/utility/thread_alloc.hpp>\n\ndouble** adolc_alloc_mat(size_t m, size_t n)\n{   using CppAD::thread_alloc;\n    size_t size_min = size_t(m * n), size_out;\n    double*  vec = thread_alloc::create_array<double>(size_min, size_out);\n    double** mat = thread_alloc::create_array<double*>(size_min, size_out);\n\n    for(size_t i = 0; i < m; i++)\n        mat[i] = vec + i * n;\n\n    return mat;\n}\nvoid adolc_free_mat(double** mat)\n{   using CppAD::thread_alloc;\n    thread_alloc::delete_array(mat[0]);\n    thread_alloc::delete_array(mat);\n    return;\n}\n"
  },
  {
    "path": "speed/adolc/det_lu.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin adolc_det_lu.cpp}\n\nAdolc Speed: Gradient of Determinant Using Lu Factorization\n###########################################################\n\nSpecifications\n**************\nSee :ref:`link_det_lu-name` .\n\nImplementation\n**************\n{xrst_spell_off}\n{xrst_code cpp} */\n// suppress conversion warnings before other includes\n# include <cppad/wno_conversion.hpp>\n//\n# include <adolc/adolc.h>\n\n# include <cppad/speed/det_by_lu.hpp>\n# include <cppad/speed/uniform_01.hpp>\n# include <cppad/utility/track_new_del.hpp>\n\n// list of possible options\n# include <map>\nextern std::map<std::string, bool> global_option;\n\nbool link_det_lu(\n    size_t                     size     ,\n    size_t                     repeat   ,\n    CppAD::vector<double>     &matrix   ,\n    CppAD::vector<double>     &gradient )\n{\n    // speed test global option values\n    if( global_option[\"onetape\"] || global_option[\"atomic\"] )\n        return false;\n    if( global_option[\"memory\"] || global_option[\"optimize\"] )\n        return false;\n    // -----------------------------------------------------\n    // setup\n    short tag  = 0;                // tape identifier\n    int   keep = 1;                // keep forward mode results in buffer\n    int   m    = 1;                // number of dependent variables\n    int   n    = int(size * size); // number of independent variables\n    double f;                      // function value\n    int j;                         // temporary index\n\n    // set up for thread_alloc memory allocator (fast and checks for leaks)\n    using CppAD::thread_alloc; // the allocator\n    size_t size_min;           // requested number of elements\n    size_t size_out;           // capacity of an allocation\n\n    // object for computing determinant\n    typedef adouble            ADScalar;\n    typedef ADScalar*          ADVector;\n    CppAD::det_by_lu<ADScalar> Det(size);\n\n    // AD value of determinant\n    ADScalar   detA;\n\n    // AD version of matrix\n    size_min    = size_t(n);\n    ADVector A  = thread_alloc::create_array<ADScalar>(size_min, size_out);\n\n    // vectors of reverse mode weights\n    size_min    = size_t(m);\n    double* u   = thread_alloc::create_array<double>(size_min, size_out);\n    u[0] = 1.;\n\n    // vector with matrix value\n    size_min     = size_t(n);\n    double* mat  = thread_alloc::create_array<double>(size_min, size_out);\n\n    // vector to receive gradient result\n    size_min     = size_t(n);\n    double* grad = thread_alloc::create_array<double>(size_min, size_out);\n    // ------------------------------------------------------\n    while(repeat--)\n    {  // get the next matrix\n        CppAD::uniform_01( size_t(n), mat);\n\n        // declare independent variables\n        trace_on(tag, keep);\n        for(j = 0; j < n; j++)\n            A[j] <<= mat[j];\n\n        // AD computation of the determinant\n        detA = Det(A);\n\n        // create function object f : A -> detA\n        detA >>= f;\n        trace_off();\n\n        // evaluate and return gradient using reverse mode\n        fos_reverse(tag, m, n, u, grad);\n    }\n    // ------------------------------------------------------\n\n    // return matrix and gradient\n    for(j = 0; j < n; j++)\n    {  matrix[j] = mat[j];\n        gradient[j] = grad[j];\n    }\n    // tear down\n    thread_alloc::delete_array(grad);\n    thread_alloc::delete_array(mat);\n    thread_alloc::delete_array(u);\n    thread_alloc::delete_array(A);\n\n    return true;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end adolc_det_lu.cpp}\n*/\n"
  },
  {
    "path": "speed/adolc/det_minor.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin adolc_det_minor.cpp}\n\nAdolc Speed: Gradient of Determinant by Minor Expansion\n#######################################################\n\nSpecifications\n**************\nSee :ref:`link_det_minor-name` .\n\nImplementation\n**************\n{xrst_spell_off}\n{xrst_code cpp} */\n// suppress conversion warnings before other includes\n# include <cppad/wno_conversion.hpp>\n//\n# include <adolc/adolc.h>\n# include <cppad/utility/vector.hpp>\n# include <cppad/speed/det_by_minor.hpp>\n# include <cppad/speed/uniform_01.hpp>\n\n// list of possible options\n# include <map>\nextern std::map<std::string, bool> global_option;\n\nnamespace {\n    void setup(short tag, size_t size, const CppAD::vector<double>& matrix)\n    {  // number of independent variables\n        int n = int(size * size);\n\n        // object for computing determinant\n        CppAD::det_by_minor<adouble> a_det(size);\n\n        // declare independent variables\n        int keep = 1; // keep forward mode results\n        trace_on(tag, keep);\n        CppAD::vector<adouble> a_A(n);\n        for(int j = 0; j < n; ++j)\n            a_A[j] <<= matrix[j];\n\n        // AD computation of the determinant\n        adouble a_detA = a_det(a_A);\n\n        // create function object f : A -> detA\n        double f;\n        a_detA >>= f;\n        trace_off();\n    }\n}\n\nbool link_det_minor(\n    const std::string&         job      ,\n    size_t                     size     ,\n    size_t                     repeat   ,\n    CppAD::vector<double>     &matrix   ,\n    CppAD::vector<double>     &gradient )\n{\n    // --------------------------------------------------------------------\n    // check global options\n    // Allow colpack true even though it is not used below because it is\n    // true durng the adolc correctness tests.\n    const char* valid[] = { \"onetape\", \"optimize\", \"colpack\"};\n    size_t n_valid = sizeof(valid) / sizeof(valid[0]);\n    typedef std::map<std::string, bool>::iterator iterator;\n    //\n    for(iterator itr=global_option.begin(); itr!=global_option.end(); ++itr)\n    {  if( itr->second )\n        {  bool ok = false;\n            for(size_t i = 0; i < n_valid; i++)\n                ok |= itr->first == valid[i];\n            if( ! ok )\n                return false;\n        }\n    }\n    // -----------------------------------------------------\n    // size corresponding to current tape\n    static size_t static_size = 0;\n    //\n    // number of independent variables\n    int n = int(size * size);\n    //\n    // tape identifier\n    short tag = 0;\n    //\n    bool onetape = global_option[\"onetape\"];\n    // ----------------------------------------------------------------------\n    if( job == \"setup\" )\n    {  if( onetape )\n        {  // get a matrix\n            CppAD::uniform_01(size_t(n), matrix);\n            //\n            // record the tape\n            setup(tag, size, matrix);\n            static_size = size;\n        }\n        else\n        {  static_size = 0;\n        }\n        return true;\n    }\n    if( job == \"teardown\" )\n    {  // 2DO: How does one free an adolc tape ?\n        return true;\n    }\n    // ----------------------------------------------------------------------\n    CPPAD_ASSERT_UNKNOWN( job == \"run\" );\n    //\n    // number of dependent variables\n    int   m    = 1;\n    //\n    // vectors of reverse mode weights\n    CppAD::vector<double> u(m);\n    u[0] = 1.;\n    //\n    if( onetape ) while(repeat--)\n    {  if( size != static_size )\n        {  CPPAD_ASSERT_UNKNOWN( size == static_size );\n        }\n\n        // choose a matrix\n        CppAD::uniform_01( size_t(n), matrix);\n\n        // evaluate the determinant at the new matrix value\n        int keep = 1; // keep this forward mode result\n        double f;     // function result\n        zos_forward(tag, m, n, keep, matrix.data(), &f);\n\n        // evaluate and return gradient using reverse mode\n        fos_reverse(tag, m, n, u.data(), gradient.data());\n    }\n    else while(repeat--)\n    {\n        // choose a matrix\n        CppAD::uniform_01( size_t(n), matrix);\n\n        // record the tape\n        setup(tag, size, matrix);\n\n        // evaluate and return gradient using reverse mode\n        fos_reverse(tag, m, n, u.data(), gradient.data());\n    }\n    // --------------------------------------------------------------------\n    return true;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end adolc_det_minor.cpp}\n*/\n"
  },
  {
    "path": "speed/adolc/mat_mul.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin adolc_mat_mul.cpp}\n\nAdolc Speed: Matrix Multiplication\n##################################\n\nSpecifications\n**************\nSee :ref:`link_mat_mul-name` .\n\nImplementation\n**************\n\n{xrst_spell_off}\n{xrst_code cpp} */\n// suppress conversion warnings before other includes\n# include <cppad/wno_conversion.hpp>\n//\n# include <adolc/adolc.h>\n# include <cppad/utility/vector.hpp>\n# include <cppad/speed/mat_sum_sq.hpp>\n# include <cppad/speed/uniform_01.hpp>\n# include <cppad/utility/vector.hpp>\n\n// list of possible options\n# include <map>\nextern std::map<std::string, bool> global_option;\n\nbool link_mat_mul(\n    size_t                           size     ,\n    size_t                           repeat   ,\n    CppAD::vector<double>&           x        ,\n    CppAD::vector<double>&           z        ,\n    CppAD::vector<double>&           dz       )\n{\n    // speed test global option values\n    if( global_option[\"memory\"] || global_option[\"atomic\"] || global_option[\"optimize\"] )\n        return false;\n    // -----------------------------------------------------\n    // setup\n    typedef adouble    ADScalar;\n    typedef ADScalar*  ADVector;\n\n    short tag  = 0;                // tape identifier\n    int   m    = 1;                // number of dependent variables\n    int   n    = int(size * size); // number of independent variables\n    double f;                      // function value\n    int j;                         // temporary index\n\n    // set up for thread_alloc memory allocator (fast and checks for leaks)\n    using CppAD::thread_alloc; // the allocator\n    size_t capacity;           // capacity of an allocation\n\n    // AD domain space vector\n    ADVector X = thread_alloc::create_array<ADScalar>(size_t(n), capacity);\n\n    // Product matrix\n    ADVector Y = thread_alloc::create_array<ADScalar>(size_t(n), capacity);\n\n    // AD range space vector\n    ADVector Z = thread_alloc::create_array<ADScalar>(size_t(m), capacity);\n\n    // vector with matrix value\n    double* mat = thread_alloc::create_array<double>(size_t(n), capacity);\n\n    // vector of reverse mode weights\n    double* u  = thread_alloc::create_array<double>(size_t(m), capacity);\n    u[0] = 1.;\n\n    // gradient\n    double* grad = thread_alloc::create_array<double>(size_t(n), capacity);\n\n    // ----------------------------------------------------------------------\n    if( ! global_option[\"onetape\"] ) while(repeat--)\n    {  // choose a matrix\n        CppAD::uniform_01( size_t(n), mat);\n\n        // declare independent variables\n        int keep = 1; // keep forward mode results\n        trace_on(tag, keep);\n        for(j = 0; j < n; j++)\n            X[j] <<= mat[j];\n\n        // do computations\n        CppAD::mat_sum_sq(size, X, Y, Z);\n\n        // create function object f : X -> Z\n        Z[0] >>= f;\n        trace_off();\n\n        // evaluate and return gradient using reverse mode\n        fos_reverse(tag, m, n, u, grad);\n    }\n    else\n    {  // choose a matrix\n        CppAD::uniform_01( size_t(n), mat);\n\n        // declare independent variables\n        int keep = 0; // do not keep forward mode results\n        trace_on(tag, keep);\n        for(j = 0; j < n; j++)\n            X[j] <<= mat[j];\n\n        // do computations\n        CppAD::mat_sum_sq(size, X, Y, Z);\n\n        // create function object f : X -> Z\n        Z[0] >>= f;\n        trace_off();\n\n        while(repeat--)\n        {  // choose a matrix\n            CppAD::uniform_01( size_t(n), mat);\n\n            // evaluate the determinant at the new matrix value\n            keep = 1; // keep this forward mode result\n            zos_forward(tag, m, n, keep, mat, &f);\n\n            // evaluate and return gradient using reverse mode\n            fos_reverse(tag, m, n, u, grad);\n        }\n    }\n    // return function, matrix, and gradient\n    z[0] = f;\n    for(j = 0; j < n; j++)\n    {  x[j]  = mat[j];\n        dz[j] = grad[j];\n    }\n\n    // tear down\n    thread_alloc::delete_array(X);\n    thread_alloc::delete_array(Y);\n    thread_alloc::delete_array(Z);\n    thread_alloc::delete_array(mat);\n    thread_alloc::delete_array(u);\n    thread_alloc::delete_array(grad);\n\n    return true;\n}\n\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end adolc_mat_mul.cpp}\n*/\n"
  },
  {
    "path": "speed/adolc/ode.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin adolc_ode.cpp}\n\nAdolc Speed: Ode\n################\n\nSpecifications\n**************\nSee :ref:`link_ode-name` .\n\nImplementation\n**************\n\n{xrst_spell_off}\n{xrst_code cpp} */\n// suppress conversion warnings before other includes\n# include <cppad/wno_conversion.hpp>\n//\n# include <adolc/adolc.h>\n\n# include <cppad/utility/vector.hpp>\n# include <cppad/speed/ode_evaluate.hpp>\n# include <cppad/speed/uniform_01.hpp>\n\n// list of possible options\n# include <map>\nextern std::map<std::string, bool> global_option;\n\nbool link_ode(\n    size_t                     size       ,\n    size_t                     repeat     ,\n    CppAD::vector<double>      &x         ,\n    CppAD::vector<double>      &jac\n)\n{\n    // speed test global option values\n    if( global_option[\"atomic\"] )\n        return false;\n    if( global_option[\"memory\"] || global_option[\"optimize\"] )\n        return false;\n    // -------------------------------------------------------------\n    // setup\n    assert( x.size() == size );\n    assert( jac.size() == size * size );\n\n    typedef CppAD::vector<adouble> ADVector;\n    typedef CppAD::vector<double>  DblVector;\n\n    size_t i, j;\n    short  tag    = 0;       // tape identifier\n    int    keep   = 0;       // do not keep forward mode results\n    size_t p      = 0;       // use ode to calculate function values\n    size_t n      = size;    // number of independent variables\n    size_t m      = n;       // number of dependent variables\n    ADVector  X(n), Y(m); // independent and dependent variables\n    DblVector f(m);       // function value\n\n    // set up for thread_alloc memory allocator (fast and checks for leaks)\n    using CppAD::thread_alloc; // the allocator\n    size_t size_min;           // requested number of elements\n    size_t size_out;           // capacity of an allocation\n\n    // raw memory for use with adolc\n    size_min = size_t(n);\n    double *x_raw   = thread_alloc::create_array<double>(size_min, size_out);\n    size_min = size_t(m * n);\n    double *jac_raw = thread_alloc::create_array<double>(size_min, size_out);\n    size_min = size_t(m);\n    double **jac_ptr = thread_alloc::create_array<double*>(size_min, size_out);\n    for(i = 0; i < m; i++)\n        jac_ptr[i] = jac_raw + i * n;\n\n    // -------------------------------------------------------------\n    if( ! global_option[\"onetape\"] ) while(repeat--)\n    {  // choose next x value\n        uniform_01( size_t(n), x);\n\n        // declare independent variables\n        trace_on(tag, keep);\n        for(j = 0; j < n; j++)\n            X[j] <<= x[j];\n\n        // evaluate function\n        CppAD::ode_evaluate(X, p, Y);\n\n        // create function object f : X -> Y\n        for(i = 0; i < m; i++)\n            Y[i] >>= f[i];\n        trace_off();\n\n        // evaluate the Jacobian\n        for(j = 0; j < n; j++)\n            x_raw[j] = x[j];\n        jacobian(tag, int(m), int(n), x_raw, jac_ptr);\n    }\n    else\n    {  // choose next x value\n        uniform_01( size_t(n), x);\n\n        // declare independent variables\n        trace_on(tag, keep);\n        for(j = 0; j < n; j++)\n            X[j] <<= x[j];\n\n        // evaluate function\n        CppAD::ode_evaluate(X, p, Y);\n\n        // create function object f : X -> Y\n        for(i = 0; i < m; i++)\n            Y[i] >>= f[i];\n        trace_off();\n\n        while(repeat--)\n        {  // get next argument value\n            uniform_01( size_t(n), x);\n            for(j = 0; j < n; j++)\n                x_raw[j] = x[j];\n\n            // evaluate jacobian\n            jacobian(tag, int(m), int(n), x_raw, jac_ptr);\n        }\n    }\n    // convert return value to a simple vector\n    for(i = 0; i < m; i++)\n    {  for(j = 0; j < n; j++)\n            jac[i * n + j] = jac_ptr[i][j];\n    }\n    // ----------------------------------------------------------------------\n    // tear down\n    thread_alloc::delete_array(x_raw);\n    thread_alloc::delete_array(jac_raw);\n    thread_alloc::delete_array(jac_ptr);\n\n    return true;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end adolc_ode.cpp}\n*/\n"
  },
  {
    "path": "speed/adolc/poly.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin adolc_poly.cpp}\n\nAdolc Speed: Second Derivative of a Polynomial\n##############################################\n\nSpecifications\n**************\nSee :ref:`link_poly-name` .\n\nImplementation\n**************\n\n{xrst_spell_off}\n{xrst_code cpp} */\n// suppress conversion warnings before other includes\n# include <cppad/wno_conversion.hpp>\n//\n# include <vector>\n# include <adolc/adolc.h>\n\n# include <cppad/speed/uniform_01.hpp>\n# include <cppad/utility/poly.hpp>\n# include <cppad/utility/vector.hpp>\n# include <cppad/utility/thread_alloc.hpp>\n# include \"adolc_alloc_mat.hpp\"\n\n// list of possible options\n# include <map>\nextern std::map<std::string, bool> global_option;\n\nbool link_poly(\n    size_t                     size     ,\n    size_t                     repeat   ,\n    CppAD::vector<double>     &a        ,  // coefficients of polynomial\n    CppAD::vector<double>     &z        ,  // polynomial argument value\n    CppAD::vector<double>     &ddp      )  // second derivative w.r.t z\n{\n    if( global_option[\"atomic\"] )\n        return false;\n    if( global_option[\"memory\"] || global_option[\"optimize\"] )\n        return false;\n    // -----------------------------------------------------\n    // setup\n    size_t i;\n    short tag  = 0;  // tape identifier\n    int   keep = 0;  // do not keep forward mode results in buffer\n    int   m    = 1;  // number of dependent variables\n    int   n    = 1;  // number of independent variables\n    int   d    = 2;  // highest derivative degree\n    double f;        // function value\n\n    // set up for thread_alloc memory allocator (fast and checks for leaks)\n    using CppAD::thread_alloc; // the allocator\n    size_t capacity;           // capacity of an allocation\n\n    // choose a vector of polynomial coefficients\n    CppAD::uniform_01(size, a);\n\n    // AD copy of the polynomial coefficients\n    std::vector<adouble> A(size);\n    for(i = 0; i < size; i++)\n        A[i] = a[i];\n\n    // domain and range space AD values\n    adouble Z, P;\n\n    // allocate arguments to hos_forward\n    double* x0 = thread_alloc::create_array<double>(size_t(n), capacity);\n    double* y0 = thread_alloc::create_array<double>(size_t(m), capacity);\n    double** x = adolc_alloc_mat(size_t(n), size_t(d));\n    double** y = adolc_alloc_mat(size_t(m), size_t(d));\n\n    // Taylor coefficient for argument\n    x[0][0] = 1.;  // first order\n    x[0][1] = 0.;  // second order\n\n    // ----------------------------------------------------------------------\n    if( ! global_option[\"onetape\"] ) while(repeat--)\n    {  // choose an argument value\n        CppAD::uniform_01(1, z);\n\n        // declare independent variables\n        trace_on(tag, keep);\n        Z <<= z[0];\n\n        // AD computation of the function value\n        P = CppAD::Poly(0, A, Z);\n\n        // create function object f : Z -> P\n        P >>= f;\n        trace_off();\n\n        // set the argument value\n        x0[0] = z[0];\n\n        // evaluate the polynomial at the new argument value\n        hos_forward(tag, m, n, d, keep, x0, x, y0, y);\n\n        // second derivative is twice second order Taylor coef\n        ddp[0] = 2. * y[0][1];\n    }\n    else\n    {\n        // choose an argument value\n        CppAD::uniform_01(1, z);\n\n        // declare independent variables\n        trace_on(tag, keep);\n        Z <<= z[0];\n\n        // AD computation of the function value\n        P = CppAD::Poly(0, A, Z);\n\n        // create function object f : Z -> P\n        P >>= f;\n        trace_off();\n\n        while(repeat--)\n        {  // get the next argument value\n            CppAD::uniform_01(1, z);\n            x0[0] = z[0];\n\n            // evaluate the polynomial at the new argument value\n            hos_forward(tag, m, n, d, keep, x0, x, y0, y);\n\n            // second derivative is twice second order Taylor coef\n            ddp[0] = 2. * y[0][1];\n        }\n    }\n    // ------------------------------------------------------\n    // tear down\n    adolc_free_mat(x);\n    adolc_free_mat(y);\n    thread_alloc::delete_array(x0);\n    thread_alloc::delete_array(y0);\n\n    return true;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end adolc_poly.cpp}\n*/\n"
  },
  {
    "path": "speed/adolc/sparse_hessian.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin adolc_sparse_hessian.cpp}\n\nAdolc Speed: Sparse Hessian\n###########################\n\nSpecifications\n**************\nSee :ref:`link_sparse_hessian-name` .\n\nImplementation\n**************\n\n{xrst_spell_off}\n{xrst_code cpp} */\n// suppress conversion warnings before other includes\n# include <cppad/wno_conversion.hpp>\n//\n# include <adolc/adolc.h>\n# include <adolc/adolc_sparse.h>\n# include <cppad/utility/vector.hpp>\n# include <cppad/utility/index_sort.hpp>\n# include <cppad/speed/uniform_01.hpp>\n# include <cppad/utility/thread_alloc.hpp>\n# include <cppad/speed/sparse_hes_fun.hpp>\n\n// list of possible options\n# include <map>\nextern std::map<std::string, bool> global_option;\n\nbool link_sparse_hessian(\n    size_t                           size     ,\n    size_t                           repeat   ,\n    const CppAD::vector<size_t>&     row      ,\n    const CppAD::vector<size_t>&     col      ,\n    CppAD::vector<double>&           x_return ,\n    CppAD::vector<double>&           hessian  ,\n    size_t&                          n_color )\n{\n    if( global_option[\"atomic\"] || (! global_option[\"colpack\"]) )\n        return false;\n    if( global_option[\"memory\"] || global_option[\"optimize\"] || global_option[\"boolsparsity\"] )\n        return false;\n    // -----------------------------------------------------\n    // setup\n    typedef unsigned int*    IntVector;\n    typedef double*          DblVector;\n    typedef adouble          ADScalar;\n    typedef ADScalar*        ADVector;\n\n    size_t order = 0;    // derivative order corresponding to function\n    size_t m = 1;        // number of dependent variables\n    size_t n = size;     // number of independent variables\n\n    // setup for thread_alloc memory allocator (fast and checks for leaks)\n    using CppAD::thread_alloc; // the allocator\n    size_t capacity;           // capacity of an allocation\n\n    // tape identifier\n    short tag  = 0;\n    // AD domain space vector\n    ADVector a_x = thread_alloc::create_array<ADScalar>(n, capacity);\n    // AD range space vector\n    ADVector a_y = thread_alloc::create_array<ADScalar>(m, capacity);\n    // double argument value\n    DblVector x = thread_alloc::create_array<double>(n, capacity);\n    // double function value\n    double f;\n\n    // options that control sparse_hess\n    int        options[2];\n    options[0] = 0; // safe mode\n    options[1] = 0; // indirect recovery\n\n    // structure that holds some of the work done by sparse_hess\n    int       nnz;                   // number of non-zero values\n    IntVector rind   = nullptr;   // row indices\n    IntVector cind   = nullptr;   // column indices\n    DblVector values = nullptr;   // Hessian values\n\n    // ----------------------------------------------------------------------\n    if( ! global_option[\"onetape\"] ) while(repeat--)\n    {  // choose a value for x\n        CppAD::uniform_01( size_t(n), x);\n\n        // declare independent variables\n        int keep = 0; // keep forward mode results\n        trace_on(tag, keep);\n        for(size_t j = 0; j < n; j++)\n            a_x[j] <<= x[j];\n\n        // AD computation of f (x)\n        CppAD::sparse_hes_fun<ADScalar>(n, a_x, row, col, order, a_y);\n\n        // create function object f : x -> y\n        a_y[0] >>= f;\n        trace_off();\n\n        // is this a repeat call with the same sparsity pattern\n        int same_pattern = 0;\n\n        // calculate the hessian at this x\n        rind   = nullptr;\n        cind   = nullptr;\n        values = nullptr;\n        sparse_hess(tag, int(n),\n            same_pattern, x, &nnz, &rind, &cind, &values, options\n        );\n\n        // free raw memory allocated by sparse_hess\n        // (keep on last repeat for correctness testing)\n        if( repeat != 0 )\n        {  free(rind);\n            free(cind);\n            free(values);\n        }\n    }\n    else\n    {  // choose a value for x\n        CppAD::uniform_01( size_t(n), x);\n\n        // declare independent variables\n        int keep = 0; // keep forward mode results\n        trace_on(tag, keep);\n        for(size_t j = 0; j < n; j++)\n            a_x[j] <<= x[j];\n\n        // AD computation of f (x)\n        CppAD::sparse_hes_fun<ADScalar>(n, a_x, row, col, order, a_y);\n\n        // create function object f : x -> y\n        a_y[0] >>= f;\n        trace_off();\n\n        // is this a repeat call at the same argument\n        int same_pattern = 0;\n\n        while(repeat--)\n        {  // choose a value for x\n            CppAD::uniform_01( size_t(n), x);\n\n            // calculate the hessian at this x\n            sparse_hess(tag, int(n),\n                same_pattern, x, &nnz, &rind, &cind, &values, options\n            );\n            same_pattern = 1;\n        }\n    }\n    // Adolc returns upper triangle in row major order while row, col are\n    // lower triangle in row major order.\n    CppAD::vector<size_t> keys(nnz), ind(nnz);\n    for(int ell = 0; ell < nnz; ++ell)\n    {  // transpose to get lower triangle\n        size_t i = size_t( cind[ell] );\n        size_t j = size_t( rind[ell] );\n        keys[ell] = i * n + j; // row major order for lower triangle\n    }\n    CppAD::index_sort(keys, ind);\n    size_t k = 0;     // initialize index in row, col\n    size_t r = row[k];\n    size_t c = col[k];\n    for(int ell = 0; ell < nnz; ++ell)\n    {  // Adolc version of lower triangle of Hessian in row major order\n        size_t ind_ell  = ind[ell];\n        size_t i        = size_t( cind[ind_ell] );\n        size_t j        = size_t( rind[ind_ell] );\n        while( (r < i) || ( (r == i) && (c < j) ) )\n        {  // (r, c) not in Adolc sparsity pattern\n            hessian[k++] = 0.0;\n            if( k < row.size() )\n            {  r = row[k];\n                c = col[k];\n            }\n            else\n            {  r = n;\n                c = n;\n            }\n        }\n        if( (r == i) && (c == j) )\n        {  // adolc value for (r, c)\n            hessian[k++] = values[ind_ell];\n            if( k < row.size() )\n            {  r = row[k];\n                c = col[k];\n            }\n            else\n            {  r = n;\n                c = n;\n            }\n        }\n        else\n        {  // Hessian at (i, j) must be zero (but Adolc does not know this)\n            assert( values[ind_ell] == 0.0 );\n        }\n    }\n    // free raw memory allocated by sparse_hessian\n    free(rind);\n    free(cind);\n    free(values);\n    //\n    // return argument\n    for(size_t j = 0; j < n; j++)\n        x_return[j] = x[j];\n\n    // do not know how to return number of sweeps used\n    n_color = 0;\n\n    // tear down\n    thread_alloc::delete_array(a_x);\n    thread_alloc::delete_array(a_y);\n    thread_alloc::delete_array(x);\n    return true;\n\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end adolc_sparse_hessian.cpp}\n*/\n"
  },
  {
    "path": "speed/adolc/sparse_jacobian.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cstring>\n# include <cppad/utility/vector.hpp>\n\n/*\n{xrst_begin adolc_sparse_jacobian.cpp}\n\nAdolc Speed: Sparse Jacobian\n############################\n\nSpecifications\n**************\nSee :ref:`link_sparse_jacobian-name` .\n\nImplementation\n**************\n\n{xrst_spell_off}\n{xrst_code cpp} */\n// suppress conversion warnings before other includes\n# include <cppad/wno_conversion.hpp>\n//\n# include <adolc/adolc.h>\n# include <adolc/adolc_sparse.h>\n# include <cppad/utility/vector.hpp>\n# include <cppad/speed/uniform_01.hpp>\n# include <cppad/speed/sparse_jac_fun.hpp>\n\n// list of possible options\n# include <map>\nextern std::map<std::string, bool> global_option;\n\nnamespace {\n    using CppAD::vector;\n    typedef vector<size_t>    s_vector;\n    typedef vector<double>    d_vector;\n    typedef vector<adouble>   a_vector;\n    void setup(\n        // inputs\n        short           tag     ,\n        size_t          size    ,\n        size_t          m       ,\n        const s_vector& row     ,\n        const s_vector& col     ,\n        const d_vector& x       ,\n        int*            options , // const but adolc want non-const arg\n        // outputs\n        size_t&         n_color ,\n        int&            nnz     ,\n        unsigned int*&  rind    ,\n        unsigned int*&  cind    ,\n        double*&        values  )\n    {  // independent variables\n        CPPAD_ASSERT_UNKNOWN( size = x.size() );\n        int keep = 0; // keep forward mode results\n        trace_on(tag, keep);\n        size_t n = size;\n        a_vector a_x(n);\n        for(size_t j = 0; j < n; ++j)\n            a_x[j] <<= x[j];\n        //\n        // dependent variables\n        a_vector a_y(m);\n        //\n        // AD computation of f(x)\n        size_t order = 0;\n        CppAD::sparse_jac_fun<adouble>(m, n, a_x, row, col, order, a_y);\n        //\n        // create function object f : x -> y\n        double yi;\n        for(size_t i = 0; i < m; i++)\n            a_y[i] >>= yi;\n        trace_off();\n        //\n        // null pointers for recalculation of sparsity pattern\n        free(rind);\n        free(cind);\n        free(values);\n        rind   = nullptr;\n        cind   = nullptr;\n        values = nullptr;\n        //\n        // Retrieve n_color using undocumented feature of sparsedrivers.cpp\n        int same_pattern = 0;\n        n_color = size_t( sparse_jac(tag, int(m), int(n),\n            same_pattern, x.data(), &nnz, &rind, &cind, &values, options\n        ) );\n    }\n\n}\n\nbool link_sparse_jacobian(\n    const std::string&               job      ,\n    size_t                           size     ,\n    size_t                           repeat   ,\n    size_t                           m        ,\n    const CppAD::vector<size_t>&     row      ,\n    const CppAD::vector<size_t>&     col      ,\n             CppAD::vector<double>&     x_return ,\n             CppAD::vector<double>&     jacobian ,\n             size_t&                    n_color  )\n{\n    // --------------------------------------------------------------------\n    // check global options\n    // Allow colpack true even though it is not used below because it is\n    // true durng the adolc correctness tests.\n    const char* valid[] = { \"onetape\", \"optimize\", \"colpack\"};\n    size_t n_valid = sizeof(valid) / sizeof(valid[0]);\n    typedef std::map<std::string, bool>::iterator iterator;\n    //\n    for(iterator itr=global_option.begin(); itr!=global_option.end(); ++itr)\n    {  if( itr->second )\n        {  bool ok = false;\n            for(size_t i = 0; i < n_valid; i++)\n                ok |= itr->first == valid[i];\n            if( ! ok )\n                return false;\n        }\n    }\n    // -----------------------------------------------------\n    static size_t  static_size     = 0;\n    static int     static_nnz      = 0;\n    unsigned int*  static_rind     = nullptr;\n    unsigned int*  static_cind     = nullptr;\n    double*        static_values   = nullptr;\n    // -----------------------------------------------------\n    short tag  = 0;\n    //\n    // options that control sparse_jac\n    int        options[4];\n    if( global_option[\"boolsparsity\"] )\n        options[0] = 1;  // sparsity by propagation of bit pattern\n    else\n        options[0] = 0;  // sparsity pattern by index domains\n    options[1] = 0;  // 0 = safe mode, 1 = tight mode\n    options[2] = 0;  // 0 = autodetect, 1 = forward, 2 = reverse\n    options[3] = 0;  // 0 = column compression, 1 = row compression\n    //\n    // independent variiables\n    size_t n = size;\n    d_vector x(n);\n    //\n    // default value for n_color\n    n_color = 0;\n    //\n    bool onetape = global_option[\"onetape\"];\n    // -----------------------------------------------------\n    if( job == \"setup\" )\n    {  // get a value for x\n        CppAD::uniform_01( size_t(n), x);\n        //\n        // record the tape and run coloring problem\n        options[2] = -1;\n        setup(tag, size, m, row, col, x, options,\n            n_color, static_nnz, static_rind, static_cind, static_values\n        );\n        static_size = size;\n        //\n        return true;\n    }\n    if( job == \"teardown\" )\n    {  free(static_rind);\n        free(static_cind);\n        free(static_values);\n        static_rind   = nullptr;\n        static_cind   = nullptr;\n        static_values = nullptr;\n        return true;\n    }\n    // -----------------------------------------------------\n    CPPAD_ASSERT_UNKNOWN( job == \"run\" );\n    //\n    while (repeat--)\n    {  // choose a value for x\n        CppAD::uniform_01( size_t(n), x);\n        //\n        if ( ! onetape )\n        {  // retape and calculate jacobian\n            options[2] = -1; // stop at sparsity pattern, return n_color\n            setup(tag, size, m, row, col, x, options,\n                n_color, static_nnz, static_rind, static_cind, static_values\n            );\n            options[2] = 0;\n        }\n        else\n        {  if( size != static_size )\n                CPPAD_ASSERT_UNKNOWN( size == static_size );\n        }\n        // calculate the jacobian at this x\n        int same_pattern = 1;\n        sparse_jac(\n            tag, int(m), int(n), same_pattern, x.data(),\n            &static_nnz, &static_rind, &static_cind, &static_values,\n            options\n        );\n    }\n    // --------------------------------------------------------------------\n    // jacobian\n    CPPAD_ASSERT_UNKNOWN( size_t(static_nnz) == row.size() );\n    for(int ell = 0; ell < static_nnz; ell++)\n    {  CPPAD_ASSERT_UNKNOWN( row[ell] == size_t(static_rind[ell]) );\n        CPPAD_ASSERT_UNKNOWN( col[ell] == size_t(static_cind[ell]) );\n        jacobian[ell] = static_values[ell];\n    }\n    // x_return\n    for(size_t j = 0; j < n; j++)\n        x_return[j] = x[j];\n    //\n    return true;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end adolc_sparse_jacobian.cpp}\n*/\n"
  },
  {
    "path": "speed/adolc/speed_adolc.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin speed_adolc}\n\nSpeed Test of Derivatives Using Adolc\n#####################################\n\nPurpose\n*******\nCppAD has a set of speed tests that are used to compare\nAdolc with other AD packages.\nThis section links to the source code the Adolc speed tests\n(any suggestions to make the Adolc results faster are welcome).\n\ninclude_adolc\n*************\nTo run these tests\nyou must specify :ref:`cmake@include_adolc`\non your cmake command line.\n\nRunning Tests\n*************\nTo build these speed tests, and run their correctness tests,\nexecute the following commands starting in the\n:ref:`cmake@Build Directory` :\n\n| |tab| ``cd speed/adolc``\n| |tab| ``make check_speed_adolc VERBOSE`` =1\n\nYou can then run the corresponding speed tests\nwith the following command\n\n    ./ ``speed_adolc speed`` *seed*\n\nwhere *seed* is a positive integer.\nSee :ref:`speed_main-name` for more options.\n\nContents\n********\n{xrst_toc_list\n    speed/adolc/det_minor.cpp\n    speed/adolc/det_lu.cpp\n    speed/adolc/mat_mul.cpp\n    speed/adolc/ode.cpp\n    speed/adolc/poly.cpp\n    speed/adolc/sparse_hessian.cpp\n    speed/adolc/sparse_jacobian.cpp\n    speed/adolc/alloc_mat.cpp\n}\n\n{xrst_end speed_adolc}\n"
  },
  {
    "path": "speed/cppad/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# Build the speed/cppad directory tests\n# Inherit build type environment from ../CMakeList.txt\n\n# Adds flags to the compiler command line for sources in the current directory\n# and below. This command can be used to add any flags, but it was originally\n# intended to add preprocessor definitions.\nADD_DEFINITIONS(\"-DCPPAD_CPPAD_SPEED\")\n\n# Local include directories to search (not in package_prefix/includdir)\nINCLUDE_DIRECTORIES( ${CMAKE_CURRENT_SOURCE_DIR}/../src )\n\n# add_executable(<name> [WIN32] [MACOSX_BUNDLE] [EXCLUDE_FROM_ALL]\n#                 source1 source2 ... sourceN\n# )\nSET(source_list ../main.cpp\n    det_lu.cpp\n    det_minor.cpp\n    mat_mul.cpp\n    ode.cpp\n    poly.cpp\n    sparse_hessian.cpp\n    sparse_jacobian.cpp\n)\n# 2DO: fix problem with the test\n#  ./speed_cppad sparse_hessian 123 colpack\n# when speed_cppad is compiled for debugging.\nset_compile_flags( speed_cppad \"${cppad_debug_which}\" \"${source_list}\" )\n#\nADD_EXECUTABLE( speed_cppad EXCLUDE_FROM_ALL ${source_list} )\n#\n# List of libraries to be linked into the specified target\nTARGET_LINK_LIBRARIES(speed_cppad\n    ${cppad_lib}\n    ${colpack_libs}\n)\n# List of libraries to be linked into the specified target\nTARGET_LINK_LIBRARIES(speed_cppad\n    speed_src\n    ${cppad_lib}\n    ${colpack_libs}\n)\n\n# check_speed_cppad\nadd_check_executable(check_speed cppad \"correct 54321\")\n"
  },
  {
    "path": "speed/cppad/det_lu.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-23 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin cppad_det_lu.cpp}\n\nCppad Speed: Gradient of Determinant Using Lu Factorization\n###########################################################\n\nSpecifications\n**************\nSee :ref:`link_det_lu-name` .\n\nImplementation\n**************\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <cppad/speed/det_by_lu.hpp>\n# include <cppad/speed/uniform_01.hpp>\n# include <cppad/cppad.hpp>\n\n// Note that CppAD uses global_option[\"memory\"] at the main program level\n# include <map>\nextern std::map<std::string, bool> global_option;\n// see comments in main program for this external\nextern size_t global_cppad_thread_alloc_inuse;\n\nbool link_det_lu(\n    size_t                           size     ,\n    size_t                           repeat   ,\n    CppAD::vector<double>           &matrix   ,\n    CppAD::vector<double>           &gradient )\n{  global_cppad_thread_alloc_inuse = 0;\n\n    // --------------------------------------------------------------------\n    // check global options\n    const char* valid[] = { \"memory\", \"optimize\", \"val_graph\"};\n    size_t n_valid = sizeof(valid) / sizeof(valid[0]);\n    typedef std::map<std::string, bool>::iterator iterator;\n    //\n    for(iterator itr=global_option.begin(); itr!=global_option.end(); ++itr)\n    {  if( itr->second )\n        {  bool ok = false;\n            for(size_t i = 0; i < n_valid; i++)\n                ok |= itr->first == valid[i];\n            if( ! ok )\n                return false;\n        }\n    }\n    // --------------------------------------------------------------------\n    // optimization options:\n    std::string optimize_options =\n        \"no_conditional_skip no_compare_op no_print_for_op\";\n    if( global_option[\"val_graph\"] )\n        optimize_options += \" val_graph\";\n    // -----------------------------------------------------\n    // setup\n    typedef CppAD::AD<double>           ADScalar;\n    typedef CppAD::vector<ADScalar>     ADVector;\n    CppAD::det_by_lu<ADScalar>          Det(size);\n\n    size_t i;               // temporary index\n    size_t m = 1;           // number of dependent variables\n    size_t n = size * size; // number of independent variables\n    ADVector   A(n);        // AD domain space vector\n    ADVector   detA(m);     // AD range space vector\n    CppAD::ADFun<double> f; // AD function object\n\n    // vectors of reverse mode weights\n    CppAD::vector<double> w(1);\n    w[0] = 1.;\n\n    // do not even record comparison operators\n    size_t abort_op_index = 0;\n    bool record_compare   = false;\n\n    // ------------------------------------------------------\n    while(repeat--)\n    {  // get the next matrix\n        CppAD::uniform_01(n, matrix);\n        for( i = 0; i < n; i++)\n            A[i] = matrix[i];\n\n        // declare independent variables\n        Independent(A, abort_op_index, record_compare);\n\n        // AD computation of the determinant\n        detA[0] = Det(A);\n\n        // create function object f : A -> detA\n        f.Dependent(A, detA);\n        if( global_option[\"optimize\"] )\n            f.optimize(optimize_options);\n\n        // evaluate and return gradient using reverse mode\n        f.Forward(0, matrix);\n        gradient = f.Reverse(1, w);\n    }\n    size_t thread                   = CppAD::thread_alloc::thread_num();\n    global_cppad_thread_alloc_inuse = CppAD::thread_alloc::inuse(thread);\n    return true;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end cppad_det_lu.cpp}\n*/\n"
  },
  {
    "path": "speed/cppad/det_minor.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-23 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin cppad_det_minor.cpp}\n\nCppad Speed: Gradient of Determinant by Minor Expansion\n#######################################################\n\nSpecifications\n**************\nSee :ref:`link_det_minor-name` .\n\nImplementation\n**************\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <cppad/cppad.hpp>\n# include <cppad/speed/det_by_minor.hpp>\n# include <cppad/speed/uniform_01.hpp>\n\n// Note that CppAD uses global_option[\"memory\"] at the main program level\n# include <map>\nextern std::map<std::string, bool> global_option;\n// see comments in main program for this external\nextern size_t global_cppad_thread_alloc_inuse;\n\nnamespace {\n    // typedefs\n    typedef CppAD::AD<double>       a_double;\n    typedef CppAD::vector<a_double> a_vector;\n    //\n    // setup\n    void setup(\n        // inputs\n        size_t size             ,\n        // outputs\n        CppAD::ADFun<double>& f )\n    {\n        // object for computing determinant\n        CppAD::det_by_minor<a_double>   a_det(size);\n        //\n        // number of independent variables\n        size_t nx = size * size;\n        //\n        // choose a matrix\n        CppAD::vector<double> matrix(nx);\n        CppAD::uniform_01(nx, matrix);\n        //\n        // copy to independent variables\n        a_vector   a_A(nx);\n        for(size_t j = 0; j < nx; ++j)\n            a_A[j] = matrix[j];\n        //\n        // declare independent variables for function computation\n        bool record_compare   = false;\n        size_t abort_op_index = 0;\n        CppAD::Independent(a_A, abort_op_index, record_compare);\n        //\n        // AD computation of the determinant\n        a_vector a_detA(1);\n        a_detA[0] = a_det(a_A);\n        //\n        // f : A -> detA\n        f.Dependent(a_A, a_detA);\n        //\n        // optimize\n        std::string optimize_options =\n        \"no_conditional_skip no_compare_op no_print_for_op no_cumulative_sum_op\";\n        if( global_option[\"val_graph\"] )\n            optimize_options += \" val_graph\";\n        if( global_option[\"optimize\"] )\n            f.optimize(optimize_options);\n    }\n\n}\n\nbool link_det_minor(\n    const std::string&         job      ,\n    size_t                     size     ,\n    size_t                     repeat   ,\n    CppAD::vector<double>     &matrix   ,\n    CppAD::vector<double>     &gradient )\n{  global_cppad_thread_alloc_inuse = 0;\n\n    // --------------------------------------------------------------------\n    // check global options\n    const char* valid[] = { \"memory\", \"onetape\", \"optimize\", \"val_graph\"};\n    size_t n_valid = sizeof(valid) / sizeof(valid[0]);\n    typedef std::map<std::string, bool>::iterator iterator;\n    //\n    for(iterator itr=global_option.begin(); itr!=global_option.end(); ++itr)\n    {  if( itr->second )\n        {  bool ok = false;\n            for(size_t i = 0; i < n_valid; i++)\n                ok |= itr->first == valid[i];\n            if( ! ok )\n                return false;\n        }\n    }\n    // ---------------------------------------------------------------------\n    //\n    // AD function mapping matrix to determinant\n    static CppAD::ADFun<double> static_f;\n    //\n    // size corresponding to static_f\n    static size_t static_size = 0;\n    //\n    // number of independent variables\n    size_t nx = size * size;\n    //\n    // vectors of reverse mode weights\n    CppAD::vector<double> w(1);\n    w[0] = 1.;\n    //\n    // onetape\n    bool onetape = global_option[\"onetape\"];\n    // -----------------------------------------------------------------------\n    if( job == \"setup\" )\n    {  if( onetape )\n        {  setup(size, static_f);\n            static_size = size;\n        }\n        else\n        {  static_size = 0;\n        }\n        return true;\n    }\n    if( job ==  \"teardown\" )\n    {  static_f = CppAD::ADFun<double>();\n        return true;\n    }\n    // -----------------------------------------------------------------------\n    CPPAD_ASSERT_UNKNOWN( job == \"run\" );\n    while(repeat--)\n    {  if( onetape )\n        {  // use if before assert to avoid warning\n            if( size != static_size )\n            {  CPPAD_ASSERT_UNKNOWN( size == static_size );\n            }\n        }\n        else\n        {  setup(size, static_f);\n        }\n        // get next matrix\n        CppAD::uniform_01(nx, matrix);\n\n        // evaluate the gradient\n        static_f.Forward(0, matrix);\n        gradient = static_f.Reverse(1, w);\n    }\n    size_t thread                   = CppAD::thread_alloc::thread_num();\n    global_cppad_thread_alloc_inuse = CppAD::thread_alloc::inuse(thread);\n    return true;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end cppad_det_minor.cpp}\n*/\n"
  },
  {
    "path": "speed/cppad/mat_mul.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-23 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin cppad_mat_mul.cpp}\n\nCppAD Speed, Matrix Multiplication\n##################################\n\nSpecifications\n**************\nSee :ref:`link_mat_mul-name` .\n\nImplementation\n**************\n\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <cppad/cppad.hpp>\n# include <cppad/speed/mat_sum_sq.hpp>\n# include <cppad/speed/uniform_01.hpp>\n# include <cppad/example/atomic_four/mat_mul/mat_mul.hpp>\n\n// Note that CppAD uses global_option[\"memory\"] at the main program level\n# include <map>\nextern std::map<std::string, bool> global_option;\n// see comments in main program for this external\nextern size_t global_cppad_thread_alloc_inuse;\n\nbool link_mat_mul(\n    size_t                           size     ,\n    size_t                           repeat   ,\n    CppAD::vector<double>&           x        ,\n    CppAD::vector<double>&           z        ,\n    CppAD::vector<double>&           dz\n)\n{  global_cppad_thread_alloc_inuse = 0;\n\n    // --------------------------------------------------------------------\n    // check global options\n    const char* valid[] = {\n        \"memory\", \"onetape\", \"optimize\", \"atomic\", \"val_graph\"\n    };\n    size_t n_valid = sizeof(valid) / sizeof(valid[0]);\n    typedef std::map<std::string, bool>::iterator iterator;\n    //\n    for(iterator itr=global_option.begin(); itr!=global_option.end(); ++itr)\n    {  if( itr->second )\n        {  bool ok = false;\n            for(size_t i = 0; i < n_valid; i++)\n                ok |= itr->first == valid[i];\n            if( ! ok )\n                return false;\n        }\n    }\n    // --------------------------------------------------------------------\n    // optimization options: no conditional skips or compare operators\n    std::string optimize_options =\n        \"no_conditional_skip no_compare_op no_print_for_op\";\n    if( global_option[\"val_graph\"] )\n        optimize_options += \" val_graph\";\n    // -----------------------------------------------------\n    // setup\n    typedef CppAD::AD<double>           ADScalar;\n    typedef CppAD::vector<ADScalar>     ADVector;\n\n    size_t j;               // temporary index\n    size_t m = 1;           // number of dependent variables\n    size_t n = size * size; // number of independent variables\n    ADVector   X(n);        // AD domain space vector\n    ADVector   Y(n);        // Store product matrix\n    ADVector   Z(m);        // AD range space vector\n    CppAD::ADFun<double> f; // AD function object\n\n    // vectors of reverse mode weights\n    CppAD::vector<double> w(1);\n    w[0] = 1.;\n\n    // atomic function information\n    CppAD::vector<ADScalar> ax(2 * n), ay(n);\n    CppAD::atomic_mat_mul<double> atom_mul(\"atom_mul\");\n    //\n    // do not even record comparison operators\n    size_t abort_op_index = 0;\n    bool record_compare   = false;\n\n    // ------------------------------------------------------\n    if( ! global_option[\"onetape\"] ) while(repeat--)\n    {  // get the next matrix\n        CppAD::uniform_01(n, x);\n        for( j = 0; j < n; j++)\n            X[j] = x[j];\n\n        // declare independent variables\n        Independent(X, abort_op_index, record_compare);\n\n        // do computations\n        if( ! global_option[\"atomic\"] )\n            mat_sum_sq(size, X, Y, Z);\n        else\n        {  for(j = 0; j < n; j++)\n            {  ax[j]     = X[j];\n                ax[n + j] = X[j];\n            }\n            // Y = X * X\n            size_t call_id = atom_mul.set(size, size, size);\n            atom_mul(call_id, ax, ay);\n            Z[0] = 0.;\n            for(j = 0; j < n; j++)\n                Z[0] += ay[j];\n        }\n        // create function object f : X -> Z\n        f.Dependent(X, Z);\n\n        if( global_option[\"optimize\"] )\n            f.optimize(optimize_options);\n\n        // skip comparison operators\n        f.compare_change_count(0);\n\n        // evaluate and return gradient using reverse mode\n        z  = f.Forward(0, x);\n        dz = f.Reverse(1, w);\n    }\n    else\n    {  // get a next matrix\n        CppAD::uniform_01(n, x);\n        for(j = 0; j < n; j++)\n            X[j] = x[j];\n\n        // declare independent variables\n        Independent(X, abort_op_index, record_compare);\n\n        // do computations\n        if( ! global_option[\"atomic\"] )\n            mat_sum_sq(size, X, Y, Z);\n        else\n        {  for(j = 0; j < n; j++)\n            {  ax[j]   = X[j];\n                ax[j+n] = X[j];\n            }\n            // Y = X * X\n            atom_mul(ax, ay);\n            Z[0] = 0.;\n            for(j = 0; j < n; j++)\n                Z[0] += ay[j];\n        }\n\n        // create function object f : X -> Z\n        f.Dependent(X, Z);\n\n        if( global_option[\"optimize\"] )\n            f.optimize(optimize_options);\n\n        // skip comparison operators\n        f.compare_change_count(0);\n\n        while(repeat--)\n        {  // get a next matrix\n            CppAD::uniform_01(n, x);\n\n            // evaluate and return gradient using reverse mode\n            z  = f.Forward(0, x);\n            dz = f.Reverse(1, w);\n        }\n    }\n    size_t thread                   = CppAD::thread_alloc::thread_num();\n    global_cppad_thread_alloc_inuse = CppAD::thread_alloc::inuse(thread);\n    // --------------------------------------------------------------------\n    // Free temporary work space (any future atomic_mat_mul constructors\n    // would create new temporary work space.)\n    CppAD::user_atomic<double>::clear();\n    // --------------------------------------------------------------------\n\n    return true;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end cppad_mat_mul.cpp}\n*/\n"
  },
  {
    "path": "speed/cppad/ode.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-23 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin cppad_ode.cpp}\n\nCppad Speed: Gradient of Ode Solution\n#####################################\n\nSpecifications\n**************\nSee :ref:`link_ode-name` .\n\nImplementation\n**************\n\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <cppad/cppad.hpp>\n# include <cppad/speed/ode_evaluate.hpp>\n# include <cppad/speed/uniform_01.hpp>\n# include <cassert>\n\n// Note that CppAD uses global_option[\"memory\"] at the main program level\n# include <map>\nextern std::map<std::string, bool> global_option;\n// see comments in main program for this external\nextern size_t global_cppad_thread_alloc_inuse;\n\nbool link_ode(\n    size_t                     size       ,\n    size_t                     repeat     ,\n    CppAD::vector<double>      &x         ,\n    CppAD::vector<double>      &jacobian\n)\n{  global_cppad_thread_alloc_inuse = 0;\n\n    // --------------------------------------------------------------------\n    // check global options\n    const char* valid[] = { \"memory\", \"onetape\", \"optimize\", \"val_graph\"};\n    size_t n_valid = sizeof(valid) / sizeof(valid[0]);\n    typedef std::map<std::string, bool>::iterator iterator;\n    //\n    for(iterator itr=global_option.begin(); itr!=global_option.end(); ++itr)\n    {  if( itr->second )\n        {  bool ok = false;\n            for(size_t i = 0; i < n_valid; i++)\n                ok |= itr->first == valid[i];\n            if( ! ok )\n                return false;\n        }\n    }\n    // --------------------------------------------------------------------\n    // optimization options: no conditional skips or compare operators\n    std::string optimize_options =\n        \"no_conditional_skip no_compare_op no_print_for_op\";\n    if( global_option[\"val_graph\"] )\n        optimize_options += \" val_graph\";\n    // --------------------------------------------------------------------\n    // setup\n    assert( x.size() == size );\n    assert( jacobian.size() == size * size );\n\n    typedef CppAD::AD<double>       ADScalar;\n    typedef CppAD::vector<ADScalar> ADVector;\n\n    size_t j;\n    size_t p = 0;              // use ode to calculate function values\n    size_t n = size;           // number of independent variables\n    size_t m = n;              // number of dependent variables\n    ADVector  X(n), Y(m);      // independent and dependent variables\n    CppAD::ADFun<double>  f;   // AD function\n\n    // do not even record comparison operators\n    size_t abort_op_index = 0;\n    bool record_compare   = false;\n\n    // -------------------------------------------------------------\n    if( ! global_option[\"onetape\"] ) while(repeat--)\n    {  // choose next x value\n        uniform_01(n, x);\n        for(j = 0; j < n; j++)\n            X[j] = x[j];\n\n        // declare independent variables\n        Independent(X, abort_op_index, record_compare);\n\n        // evaluate function\n        CppAD::ode_evaluate(X, p, Y);\n\n        // create function object f : X -> Y\n        f.Dependent(X, Y);\n\n        if( global_option[\"optimize\"] )\n            f.optimize(optimize_options);\n\n        // skip comparison operators\n        f.compare_change_count(0);\n\n        jacobian = f.Jacobian(x);\n    }\n    else\n    {  // an x value\n        uniform_01(n, x);\n        for(j = 0; j < n; j++)\n            X[j] = x[j];\n\n        // declare the independent variable vector\n        Independent(X, abort_op_index, record_compare);\n\n        // evaluate function\n        CppAD::ode_evaluate(X, p, Y);\n\n        // create function object f : X -> Y\n        f.Dependent(X, Y);\n\n        if( global_option[\"optimize\"] )\n            f.optimize(optimize_options);\n\n        // skip comparison operators\n        f.compare_change_count(0);\n\n        while(repeat--)\n        {  // get next argument value\n            uniform_01(n, x);\n\n            // evaluate jacobian\n            jacobian = f.Jacobian(x);\n        }\n    }\n    size_t thread                   = CppAD::thread_alloc::thread_num();\n    global_cppad_thread_alloc_inuse = CppAD::thread_alloc::inuse(thread);\n    return true;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end cppad_ode.cpp}\n*/\n"
  },
  {
    "path": "speed/cppad/poly.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-23 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin cppad_poly.cpp}\n\nCppad Speed: Second Derivative of a Polynomial\n##############################################\n\nSpecifications\n**************\nSee :ref:`link_poly-name` .\n\nImplementation\n**************\n\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <cppad/cppad.hpp>\n# include <cppad/speed/uniform_01.hpp>\n\n// Note that CppAD uses global_option[\"memory\"] at the main program level\n# include <map>\nextern std::map<std::string, bool> global_option;\n// see comments in main program for this external\nextern size_t global_cppad_thread_alloc_inuse;\n\nbool link_poly(\n    size_t                     size     ,\n    size_t                     repeat   ,\n    CppAD::vector<double>     &a        ,  // coefficients of polynomial\n    CppAD::vector<double>     &z        ,  // polynomial argument value\n    CppAD::vector<double>     &ddp      )  // second derivative w.r.t z\n{  global_cppad_thread_alloc_inuse = 0;\n\n    // --------------------------------------------------------------------\n    // check global options\n    const char* valid[] = { \"memory\", \"onetape\", \"optimize\", \"val_graph\"};\n    size_t n_valid = sizeof(valid) / sizeof(valid[0]);\n    typedef std::map<std::string, bool>::iterator iterator;\n    //\n    for(iterator itr=global_option.begin(); itr!=global_option.end(); ++itr)\n    {  if( itr->second )\n        {  bool ok = false;\n            for(size_t i = 0; i < n_valid; i++)\n                ok |= itr->first == valid[i];\n            if( ! ok )\n                return false;\n        }\n    }\n    // --------------------------------------------------------------------\n    // optimization options: no conditional skips or compare operators\n    std::string optimize_options =\n        \"no_conditional_skip no_compare_op no_print_for_op\";\n    if( global_option[\"val_graph\"] )\n        optimize_options += \" val_graph\";\n    // -----------------------------------------------------\n    // setup\n    typedef CppAD::AD<double>     ADScalar;\n    typedef CppAD::vector<ADScalar> ADVector;\n\n    size_t i;      // temporary index\n    size_t m = 1;  // number of dependent variables\n    size_t n = 1;  // number of independent variables\n    ADVector Z(n); // AD domain space vector\n    ADVector P(m); // AD range space vector\n\n    // choose the polynomial coefficients\n    CppAD::uniform_01(size, a);\n\n    // AD copy of the polynomial coefficients\n    ADVector A(size);\n    for(i = 0; i < size; i++)\n        A[i] = a[i];\n\n    // forward mode first and second differentials\n    CppAD::vector<double> p(1), dp(1), dz(1), ddz(1);\n    dz[0]  = 1.;\n    ddz[0] = 0.;\n\n    // AD function object\n    CppAD::ADFun<double> f;\n\n    // do not even record comparison operators\n    size_t abort_op_index = 0;\n    bool record_compare   = false;\n\n    // --------------------------------------------------------------------\n    if( ! global_option[\"onetape\"] ) while(repeat--)\n    {\n        // choose an argument value\n        CppAD::uniform_01(1, z);\n        Z[0] = z[0];\n\n        // declare independent variables\n        Independent(Z, abort_op_index, record_compare);\n\n        // AD computation of the function value\n        P[0] = CppAD::Poly(0, A, Z[0]);\n\n        // create function object f : A -> detA\n        f.Dependent(Z, P);\n\n        if( global_option[\"optimize\"] )\n            f.optimize(optimize_options);\n\n        // skip comparison operators\n        f.compare_change_count(0);\n\n        // pre-allocate memory for three forward mode calculations\n        f.capacity_order(3);\n\n        // evaluate the polynomial\n        p = f.Forward(0, z);\n\n        // evaluate first order Taylor coefficient\n        dp = f.Forward(1, dz);\n\n        // second derivative is twice second order Taylor coef\n        ddp     = f.Forward(2, ddz);\n        ddp[0] *= 2.;\n    }\n    else\n    {\n        // choose an argument value\n        CppAD::uniform_01(1, z);\n        Z[0] = z[0];\n\n        // declare independent variables\n        Independent(Z, abort_op_index, record_compare);\n\n        // AD computation of the function value\n        P[0] = CppAD::Poly(0, A, Z[0]);\n\n        // create function object f : A -> detA\n        f.Dependent(Z, P);\n\n        if( global_option[\"optimize\"] )\n            f.optimize(optimize_options);\n\n        // skip comparison operators\n        f.compare_change_count(0);\n\n        while(repeat--)\n        {  // sufficient memory is allocated by second repetition\n\n            // get the next argument value\n            CppAD::uniform_01(1, z);\n\n            // evaluate the polynomial at the new argument value\n            p = f.Forward(0, z);\n\n            // evaluate first order Taylor coefficient\n            dp = f.Forward(1, dz);\n\n            // second derivative is twice second order Taylor coef\n            ddp     = f.Forward(2, ddz);\n            ddp[0] *= 2.;\n        }\n    }\n    size_t thread                   = CppAD::thread_alloc::thread_num();\n    global_cppad_thread_alloc_inuse = CppAD::thread_alloc::inuse(thread);\n    return true;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end cppad_poly.cpp}\n*/\n"
  },
  {
    "path": "speed/cppad/sparse_hessian.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-23 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin cppad_sparse_hessian.cpp}\n\nCppad Speed: Sparse Hessian\n###########################\n\nSpecifications\n**************\nSee :ref:`link_sparse_hessian-name` .\n\nImplementation\n**************\n\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <cppad/cppad.hpp>\n# include <cppad/speed/uniform_01.hpp>\n# include <cppad/speed/sparse_hes_fun.hpp>\n\n// Note that CppAD uses global_option[\"memory\"] at the main program level\n# include <map>\nextern std::map<std::string, bool> global_option;\n// see comments in main program for this external\nextern size_t global_cppad_thread_alloc_inuse;\n\nnamespace {\n    // typedefs\n    using CppAD::vector;\n    typedef CppAD::AD<double>                     a1double;\n    typedef CppAD::AD<a1double>                   a2double;\n    typedef vector<bool>                          b_vector;\n    typedef vector<size_t>                        s_vector;\n    typedef vector<double>                        d_vector;\n    typedef vector<a1double>                      a1vector;\n    typedef vector<a2double>                      a2vector;\n    typedef CppAD::sparse_rc<s_vector>            sparsity_pattern;\n    typedef CppAD::sparse_rcv<s_vector, d_vector> sparse_matrix;\n    // ------------------------------------------------------------------------\n    void create_fun(\n        const d_vector&             x        ,\n        const s_vector&             row      ,\n        const s_vector&             col      ,\n        CppAD::ADFun<double>&       fun      )\n    {\n        // initialize a1double version of independent variables\n        size_t n = x.size();\n        a1vector a1x(n);\n        for(size_t j = 0; j < n; j++)\n            a1x[j] = x[j];\n        //\n        // optimization options\n        std::string optimize_options =\n            \"no_conditional_skip no_compare_op no_print_for_op\";\n        if( global_option[\"val_graph\"] )\n            optimize_options += \" val_graph\";\n        //\n        // order of derivative in sparse_hes_fun\n        size_t order = 0;\n        //\n        // do not even record comparison operators\n        size_t abort_op_index = 0;\n        bool record_compare   = false;\n        //\n        if( ! global_option[\"hes2jac\"] )\n        {\n            // declare independent variables\n            Independent(a1x, abort_op_index, record_compare);\n            //\n            // AD computation of y\n            a1vector a1y(1);\n            CppAD::sparse_hes_fun<a1double>(n, a1x, row, col, order, a1y);\n            //\n            // create function object f : X -> Y\n            fun.Dependent(a1x, a1y);\n            //\n            if( global_option[\"optimize\"] )\n                fun.optimize(optimize_options);\n            //\n            // skip comparison operators\n            fun.compare_change_count(0);\n            //\n            // fun corresponds to f(x)\n            return;\n        }\n        // declare independent variables for f(x)\n        a2vector a2x(n);\n        for(size_t j = 0; j < n; j++)\n            a2x[j] = a1x[j];\n        Independent(a2x, abort_op_index, record_compare);\n        //\n        // a2double computation of y\n        a2vector a2y(1);\n        CppAD::sparse_hes_fun<a2double>(n, a2x, row, col, order, a2y);\n        //\n        // create function object corresponding to y = f(x)\n        CppAD::ADFun<a1double> a1f;\n        a1f.Dependent(a2x, a2y);\n        //\n        // declare independent variables for g(x)\n        Independent(a1x, abort_op_index, record_compare);\n        //\n        // a1double computation of z\n        a1vector a1w(1), a1z(n);\n        a1w[0] = 1.0;\n        a1f.Forward(0, a1x);\n        a1z = a1f.Reverse(1, a1w);\n        //\n        // create function object z = g(x) = f'(x)\n        fun.Dependent(a1x, a1z);\n        //\n        if( global_option[\"optimize\"] )\n            fun.optimize(optimize_options);\n        //\n        // skip comparison operators\n        fun.compare_change_count(0);\n        //\n        // fun corresponds to g(x)\n        return;\n    }\n    // ------------------------------------------------------------------------\n    void calc_sparsity(\n        sparsity_pattern&      sparsity ,\n        CppAD::ADFun<double>&  fun      )\n    {\n        size_t n = fun.Domain();\n        size_t m = fun.Range();\n        //\n        bool transpose     = false;\n        //\n        if( global_option[\"subsparsity\"] )\n        {  CPPAD_ASSERT_UNKNOWN( global_option[\"hes2jac\"] )\n            CPPAD_ASSERT_UNKNOWN( n == m );\n            b_vector select_domain(n), select_range(m);\n            for(size_t j = 0; j < n; ++j)\n                select_domain[j] = true;\n            for(size_t i = 0; i < m; ++i)\n                select_range[i] = true;\n            //\n            // fun corresponds to g(x)\n            fun.subgraph_sparsity(\n                select_domain, select_range, transpose, sparsity\n            );\n            return;\n        }\n        bool dependency    = false;\n        bool reverse       = global_option[\"revsparsity\"];\n        bool internal_bool = global_option[\"boolsparsity\"];\n        //\n        if( ! global_option[\"hes2jac\"] )\n        {  // fun corresponds to f(x)\n            //\n            CPPAD_ASSERT_UNKNOWN( m == 1 );\n            //\n            b_vector select_range(m);\n            select_range[0] = true;\n            //\n            if( reverse )\n            {  sparsity_pattern identity;\n                identity.resize(n, n, n);\n                for(size_t k = 0; k < n; k++)\n                    identity.set(k, k, k);\n                fun.for_jac_sparsity(\n                    identity, transpose, dependency, internal_bool, sparsity\n                );\n                fun.rev_hes_sparsity(\n                    select_range, transpose, internal_bool, sparsity\n                );\n            }\n            else\n            {  b_vector select_domain(n);\n                for(size_t j = 0; j < n; j++)\n                    select_domain[j] = true;\n                fun.for_hes_sparsity(\n                    select_domain, select_range, internal_bool, sparsity\n                );\n            }\n            return;\n        }\n        // fun corresponds to g(x)\n        CPPAD_ASSERT_UNKNOWN( m == n );\n        //\n        // sparsity pattern for identity matrix\n        sparsity_pattern eye;\n        eye.resize(n, n, n);\n        for(size_t k = 0; k < n; k++)\n            eye.set(k, k, k);\n        //\n        if( reverse )\n        {  fun.rev_jac_sparsity(\n                eye, transpose, dependency, internal_bool, sparsity\n            );\n        }\n        else\n        {  fun.for_jac_sparsity(\n                eye, transpose, dependency, internal_bool, sparsity\n            );\n        }\n        return;\n    }\n    // ------------------------------------------------------------------------\n    size_t calc_hessian(\n        d_vector&               hessian  ,\n        const d_vector&         x        ,\n        sparse_matrix&          subset   ,\n        const sparsity_pattern& sparsity ,\n        CppAD::sparse_jac_work& jac_work ,\n        CppAD::sparse_hes_work& hes_work ,\n        CppAD::ADFun<double>&   fun      )\n    {  size_t n_color;\n        //\n        if( ! global_option[\"hes2jac\"] )\n        {  // fun corresponds to f(x)\n            //\n            // coloring method\n            std::string coloring = \"cppad\";\n            if( global_option[\"colpack\"] )\n                coloring = \"colpack\";\n            if( global_option[\"symmetric\"] )\n                coloring += \".symmetric\";\n            else\n                coloring += \".general\";\n            //\n            // only one function component\n            d_vector w(1);\n            w[0] = 1.0;\n            //\n            // compute hessian\n            n_color = fun.sparse_hes(\n                x, w, subset, sparsity, coloring, hes_work\n            );\n        }\n        else\n        {  // fun corresponds to g(x)\n            //\n            if( global_option[\"subgraph\"] )\n            {  fun.subgraph_jac_rev(x, subset);\n                n_color = 0;\n            }\n            else\n            {\n                //\n                // coloring method\n                std::string coloring = \"cppad\";\n# if CPPAD_HAS_COLPACK\n                if( global_option[\"colpack\"] )\n                    coloring = \"colpack\";\n# endif\n                size_t group_max = 1;\n                n_color = fun.sparse_jac_for(\n                    group_max, x, subset, sparsity, coloring, jac_work\n                );\n            }\n        }\n        // return result\n        const d_vector& val( subset.val() );\n        size_t nnz = subset.nnz();\n        for(size_t k = 0; k < nnz; k++)\n            hessian[k] = val[k];\n        //\n        return n_color;\n    }\n}\n\nbool link_sparse_hessian(\n    size_t                           size     ,\n    size_t                           repeat   ,\n    const CppAD::vector<size_t>&     row      ,\n    const CppAD::vector<size_t>&     col      ,\n    CppAD::vector<double>&           x        ,\n    CppAD::vector<double>&           hessian  ,\n    size_t&                          n_color  )\n{  global_cppad_thread_alloc_inuse = 0;\n\n    // --------------------------------------------------------------------\n    // check global options\n    const char* valid[] = {\n        \"memory\", \"onetape\", \"optimize\", \"hes2jac\", \"subgraph\",\n        \"boolsparsity\", \"revsparsity\", \"symmetric\", \"val_graph\"\n# if CPPAD_HAS_COLPACK\n        , \"colpack\"\n# else\n        , \"subsparsity\"\n# endif\n    };\n    size_t n_valid = sizeof(valid) / sizeof(valid[0]);\n    typedef std::map<std::string, bool>::iterator iterator;\n    //\n    for(iterator itr=global_option.begin(); itr!=global_option.end(); ++itr)\n    {  if( itr->second )\n        {  bool ok = false;\n            for(size_t i = 0; i < n_valid; i++)\n                ok |= itr->first == valid[i];\n            if( ! ok )\n                return false;\n        }\n    }\n    if( global_option[\"subsparsity\"] )\n    {  if( global_option[\"boolsparsity\"] || global_option[\"revsparsity\"] )\n            return false;\n        if( ! global_option[\"hes2jac\"] )\n            return false;\n    }\n    if( global_option[\"subgraph\"] )\n    {  if( ! global_option[\"hes2jac\"] )\n            return false;\n    }\n# if ! CPPAD_HAS_COLPACK\n    if( global_option[\"colpack\"] )\n        return false;\n# endif\n    // -----------------------------------------------------------------------\n    // setup\n    size_t n = size;          // number of independent variables\n    CppAD::ADFun<double> fun; // AD function object used to calculate Hessian\n    //\n    // declare sparsity pattern\n    sparsity_pattern sparsity;\n    //\n    // declare subset where Hessian is evaluated\n    sparsity_pattern subset_pattern;\n    size_t nr  = n;\n    size_t nc  = n;\n    size_t nnz = row.size();\n    subset_pattern.resize(nr, nc, nnz);\n    for(size_t k = 0; k < nnz; k++)\n        subset_pattern.set(k, row[k], col[k]);\n    sparse_matrix subset( subset_pattern );\n    //\n    // structures that holds some of the work done by sparse_jac, sparse_hes\n    CppAD::sparse_jac_work jac_work;\n    CppAD::sparse_hes_work hes_work;\n\n    // -----------------------------------------------------------------------\n    if( ! global_option[\"onetape\"] ) while(repeat--)\n    {  // choose a value for x\n        CppAD::uniform_01(n, x);\n        //\n        // create f(x)\n        create_fun(x, row, col, fun);\n        //\n        // calculate the sparsity pattern for Hessian of f(x)\n        calc_sparsity(sparsity, fun);\n        //\n        // calculate the Hessian at this x\n        jac_work.clear(); // without work from previous calculation\n        hes_work.clear();\n        n_color = calc_hessian(\n            hessian, x, subset, sparsity, jac_work, hes_work, fun\n        );\n    }\n    else\n    {  // choose a value for x\n        CppAD::uniform_01(n, x);\n        //\n        // create f(x)\n        create_fun(x, row, col, fun);\n        //\n        // calculate the sparsity pattern for Hessian of f(x)\n        calc_sparsity(sparsity, fun);\n        //\n        while(repeat--)\n        {  // choose a value for x\n            CppAD::uniform_01(n, x);\n            //\n            // calculate this Hessian at this x\n            n_color = calc_hessian(\n                hessian, x, subset, sparsity, jac_work, hes_work, fun\n            );\n        }\n    }\n    size_t thread                   = CppAD::thread_alloc::thread_num();\n    global_cppad_thread_alloc_inuse = CppAD::thread_alloc::inuse(thread);\n    return true;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end cppad_sparse_hessian.cpp}\n*/\n"
  },
  {
    "path": "speed/cppad/sparse_jacobian.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-23 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin cppad_sparse_jacobian.cpp}\n\nCppad Speed: Sparse Jacobian\n############################\n\nSpecifications\n**************\nSee :ref:`link_sparse_jacobian-name` .\n\nImplementation\n**************\n\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <cppad/cppad.hpp>\n# include <cppad/speed/uniform_01.hpp>\n# include <cppad/speed/sparse_jac_fun.hpp>\n\n// Note that CppAD uses global_option[\"memory\"] at the main program level\n# include <map>\nextern std::map<std::string, bool> global_option;\n// see comments in main program for this external\nextern size_t global_cppad_thread_alloc_inuse;\n\nnamespace {\n    using CppAD::vector;\n    typedef CppAD::AD<double>                     a_double;\n    typedef vector<size_t>                        s_vector;\n    typedef vector<bool>                          b_vector;\n    typedef vector<double>                        d_vector;\n    typedef vector<a_double>                      a_vector;\n    typedef CppAD::sparse_rc<s_vector>            sparsity;\n    typedef CppAD::sparse_rcv<s_vector, d_vector> sparse_matrix;\n\n    void calc_sparsity(\n        CppAD::sparse_rc<s_vector>& pattern ,\n        CppAD::ADFun<double>&       f        )\n    {  bool reverse       = global_option[\"revsparsity\"];\n        bool transpose     = false;\n        bool internal_bool = global_option[\"boolsparsity\"];\n        bool dependency    = false;\n        bool subgraph      = global_option[\"subsparsity\"];\n        size_t n = f.Domain();\n        size_t m = f.Range();\n        if( subgraph )\n        {  b_vector select_domain(n), select_range(m);\n            for(size_t j = 0; j < n; ++j)\n                select_domain[j] = true;\n            for(size_t i = 0; i < m; ++i)\n                select_range[i] = true;\n            f.subgraph_sparsity(\n                select_domain, select_range, transpose, pattern\n            );\n        }\n        else\n        {  size_t q = n;\n            if( reverse )\n                q = m;\n            //\n            CppAD::sparse_rc<s_vector> identity;\n            identity.resize(q, q, q);\n            for(size_t k = 0; k < q; k++)\n                identity.set(k, k, k);\n            //\n            if( reverse )\n            {  f.rev_jac_sparsity(\n                    identity, transpose, dependency, internal_bool, pattern\n                );\n            }\n            else\n            {  f.for_jac_sparsity(\n                    identity, transpose, dependency, internal_bool, pattern\n                );\n            }\n        }\n    }\n    // --------------------------------------------------------------------\n    void setup(\n        // inputs\n        size_t                  size    ,\n        size_t                  m       ,\n        const s_vector&         row     ,\n        const s_vector&         col     ,\n        // outputs\n        size_t&                 n_color ,\n        CppAD::ADFun<double>&   f       ,\n        sparse_matrix&          subset  ,\n        CppAD::sparse_jac_work& work    )\n    {  // optimization options\n        std::string optimize_options =\n            \"no_conditional_skip no_compare_op no_print_for_op\";\n        if( global_option[\"val_graph\"] )\n            optimize_options += \" val_graph\";\n        //\n        // default value for n_color\n        n_color = 0;\n        //\n        // independent variable vector\n        size_t nc = size;\n        a_vector a_x(nc);\n        d_vector x(nc);\n        //\n        // dependent variable vector\n        size_t nr = m;\n        a_vector a_y(nr);\n        //\n        // choose a value for independent variable vector\n        CppAD::uniform_01(nc, x);\n        for(size_t j = 0; j < nc; j++)\n            a_x[j] = x[j];\n        //\n        // declare independent variables\n        size_t abort_op_index = 0;\n        bool record_compare   = false;\n        CppAD::Independent(a_x, abort_op_index, record_compare);\n        //\n        // AD computation of f(x)\n        size_t order = 0;\n        CppAD::sparse_jac_fun<a_double>(nr, nc, a_x, row, col, order, a_y);\n        //\n        // create function object f : x -> y\n        f.Dependent(a_x, a_y);\n        //\n        if( global_option[\"optimize\"] )\n            f.optimize(optimize_options);\n        //\n        // coloring method\n        std::string coloring = \"cppad\";\n# if CPPAD_HAS_COLPACK\n        if( global_option[\"colpack\"] )\n            coloring = \"colpack\";\n# else\n        CPPAD_ASSERT_UNKNOWN( ! global_option[\"colpack\"] );\n# endif\n        //\n        // sparsity pattern for subset of Jacobian that is evaluated\n        size_t nnz = row.size();\n        sparsity subset_pattern(nr, nc, nnz);\n        for(size_t k = 0; k < nnz; ++k)\n            subset_pattern.set(k, row[k], col[k]);\n        //\n        // sparse matrix for subset of Jacobian that is evaluated\n        subset = sparse_matrix( subset_pattern );\n        //\n        // maximum number of colors at once\n        size_t group_max = 25;\n        //\n        if( global_option[\"subgraph\"] )\n        {  // This would cache some information in f,  but would it enough ?\n            // The time it takes to compute derivatives that are not used\n            // slows down the test when onetape is false.\n            // f.subgraph_jac_rev(x, ac_subset);\n        }\n        else\n        {  // need full sparsity pattern\n            // (could use subset_sparsity, but pretend we do not know that)\n            sparsity pattern;\n            calc_sparsity(pattern, f);\n            //\n            // Use forward mode to compute the Jacobian\n            // (this caches information in work),\n            work.clear();\n            n_color = f.sparse_jac_for(\n                group_max, x, subset, pattern, coloring, work\n            );\n        }\n    }\n}\n\nbool link_sparse_jacobian(\n    const std::string&               job      ,\n    size_t                           size     ,\n    size_t                           repeat   ,\n    size_t                           m        ,\n    const CppAD::vector<size_t>&     row      ,\n    const CppAD::vector<size_t>&     col      ,\n             CppAD::vector<double>&     x        ,\n             CppAD::vector<double>&     jacobian ,\n             size_t&                    n_color  )\n{  global_cppad_thread_alloc_inuse = 0;\n\n    // --------------------------------------------------------------------\n    // check global options\n    const char* valid[] = {\n        \"memory\", \"onetape\", \"optimize\", \"subgraph\",\n        \"boolsparsity\", \"revsparsity\", \"subsparsity\", \"val_graph\"\n# if CPPAD_HAS_COLPACK\n        , \"colpack\"\n# endif\n    };\n    size_t n_valid = sizeof(valid) / sizeof(valid[0]);\n    typedef std::map<std::string, bool>::iterator iterator;\n    //\n    for(iterator itr=global_option.begin(); itr!=global_option.end(); ++itr)\n    {  if( itr->second )\n        {  bool ok = false;\n            for(size_t i = 0; i < n_valid; i++)\n                ok |= itr->first == valid[i];\n            if( ! ok )\n                return false;\n        }\n    }\n    if( global_option[\"subsparsity\"] )\n    {  if( global_option[\"boolsparisty\"]\n        ||  global_option[\"revsparsity\"]\n        ||  global_option[\"colpack\"]  )\n            return false;\n    }\n    // -----------------------------------------------------\n    // size corresponding to static_f\n    static size_t static_size = 0;\n    //\n    // function object corresponding to f(x)\n    static CppAD::ADFun<double> static_f;\n    //\n    // subset of Jacobian that we are using\n    static sparse_matrix static_subset;\n    //\n    // information used by for_sparse_jac_for\n    static CppAD::sparse_jac_work static_work;\n    //\n    // sparsity pattern not used because work is non-empty\n    sparsity empty_pattern;\n    // -----------------------------------------------------------------------\n    //\n    // default value for n_color\n    n_color = 0;\n    //\n    bool onetape = global_option[\"onetape\"];\n    //\n    if( job == \"setup\" )\n    {  if( onetape )\n        {  setup(size, m, row, col,\n                n_color, static_f, static_subset, static_work\n            );\n            static_size = size;\n        }\n        else\n        {  static_size = 0;\n        }\n        return true;\n    }\n    if( job == \"teardown\" )\n    {  static_f      = CppAD::ADFun<double>();\n        sparse_matrix empty_matrix;\n        static_subset.swap( empty_matrix );\n        static_work.clear();\n        static_size = 0;\n        return true;\n    }\n    // ------------------------------------------------------------------------\n    CPPAD_ASSERT_UNKNOWN( job == \"run\" );\n    //\n    // number of independent variables\n    static size_t n = size;\n    //\n    // maximum number of colors at once\n    size_t group_max = 25;\n    //\n    // coloring method\n    std::string coloring = \"cppad\";\n    if( global_option[\"colpack\"] )\n        coloring = \"colpack\";\n    // ------------------------------------------------------\n    while(repeat--)\n    {  if( onetape )\n        {  if( size != static_size )\n                CPPAD_ASSERT_UNKNOWN( size == static_size );\n        }\n        else\n        {  setup(size, m, row, col,\n                n_color, static_f, static_subset, static_work\n            );\n        }\n        // choose a value for x\n        CppAD::uniform_01(n, x);\n\n        if( global_option[\"subgraph\"] )\n        {  // user reverse mode because forward not yet implemented\n            static_f.subgraph_jac_rev(x, static_subset);\n        }\n        else\n        {  // Use forward mode because m > n (is this sufficient reason ?)\n            n_color = static_f.sparse_jac_for(group_max, x,\n                static_subset, empty_pattern, coloring, static_work\n            );\n        }\n        jacobian = static_subset.val();\n    }\n    size_t thread                   = CppAD::thread_alloc::thread_num();\n    global_cppad_thread_alloc_inuse = CppAD::thread_alloc::inuse(thread);\n    return true;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end cppad_sparse_jacobian.cpp}\n*/\n"
  },
  {
    "path": "speed/cppad/speed_cppad.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin speed_cppad}\n\nSpeed Test Derivatives Using CppAD\n##################################\n\nPurpose\n*******\nCppAD has a set of speed tests that are used to determine if\ncertain changes improve its execution speed\n(and to compare CppAD with other AD packages).\nThis section links to the source code the CppAD speed tests\n(any suggestions to make the CppAD results faster are welcome).\n\nRunning Tests\n*************\nTo build these speed tests, and run their correctness tests,\nexecute the following commands starting in the\n:ref:`cmake@Build Directory` :\n\n| |tab| ``cd speed/cppad``\n| |tab| ``make check_speed_cppad VERBOSE`` =1\n\nYou can then run the corresponding speed tests\nwith the following command\n\n    ./ ``speed_cppad speed`` *seed*\n\nwhere *seed* is a positive integer.\nSee :ref:`speed_main-name` for more options.\n\nContents\n********\n{xrst_toc_list\n    speed/cppad/det_minor.cpp\n    speed/cppad/det_lu.cpp\n    speed/cppad/mat_mul.cpp\n    speed/cppad/ode.cpp\n    speed/cppad/poly.cpp\n    speed/cppad/sparse_hessian.cpp\n    speed/cppad/sparse_jacobian.cpp\n}\n\n{xrst_end speed_cppad}\n"
  },
  {
    "path": "speed/cppad_jit/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-23 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# Build the speed/cppad_jit directory tests\n# Inherit build type from ../CMakeList.txt\n\n# Adds flags to the compiler command line for sources in the current directory\n# and below. This command can be used to add any flags, but it was originally\n# intended to add preprocessor definitions.\nADD_DEFINITIONS(\"-DCPPAD_CPPAD_JIT_SPEED\")\n\n# Local include directories to search (not in package_prefix/includdir)\nINCLUDE_DIRECTORIES(\n    ${CMAKE_CURRENT_SOURCE_DIR}/../src\n)\n\n# add_executable(<name> [WIN32] [MACOSX_BUNDLE] [EXCLUDE_FROM_ALL]\n#                 source1 source2 ... sourceN\n# )\nSET(source_list ../main.cpp\n    det_lu.cpp\n    det_minor.cpp\n    mat_mul.cpp\n    ode.cpp\n    poly.cpp\n    sparse_hessian.cpp\n    sparse_jacobian.cpp\n)\nset_compile_flags( speed_cppad_jit \"${cppad_debug_which}\" \"${source_list}\" )\n#\nADD_EXECUTABLE( speed_cppad_jit EXCLUDE_FROM_ALL ${source_list} )\n#\n# List of libraries to be linked into the specified target\nTARGET_LINK_LIBRARIES(speed_cppad_jit\n    ${cppad_lib}\n    ${colpack_libs}\n)\n# cppad_jit is an include file only library\nTARGET_LINK_LIBRARIES(speed_cppad_jit speed_src )\n\n# check_speed_cppad_jit\nadd_check_executable(check_speed cppad_jit \"correct 54321\")\n"
  },
  {
    "path": "speed/cppad_jit/det_lu.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin cppad_jit_det_lu.cpp}\n\ncppad_jit Speed: Gradient of Determinant Using Lu Factorization\n###############################################################\n\nSpecifications\n**************\n:ref:`link_det_lu-name`\n\nImplementation\n**************\nA cppad_jit version of this test is not yet implemented\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <map>\n# include <cppad/utility/vector.hpp>\n\n// list of possible options\nextern std::map<std::string, bool> global_option;\n\nbool link_det_lu(\n    size_t                     size     ,\n    size_t                     repeat   ,\n    CppAD::vector<double>     &matrix   ,\n    CppAD::vector<double>     &gradient )\n{  return false; }\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end cppad_jit_det_lu.cpp}\n*/\n"
  },
  {
    "path": "speed/cppad_jit/det_minor.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin cppad_jit_det_minor.cpp}\n\ncppad_jit Speed: Gradient of Determinant by Minor Expansion\n###########################################################\n\nSpecifications\n**************\nSee :ref:`link_det_minor-name` .\n\nImplementation\n**************\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <map>\n# include <cppad/cppad.hpp>\n# include <cppad/speed/det_by_minor.hpp>\n# include <cppad/speed/uniform_01.hpp>\nextern std::map<std::string, bool> global_option;\n\n# ifdef _WIN32\n# define DLL_EXT \".dll\"\n# else\n# define DLL_EXT \".so\"\n# endif\n\n# if ! (CPPAD_C_COMPILER_GNU_FLAGS || CPPAD_C_COMPILER_MSVC_FLAGS )\nbool link_det_minor(\n    const std::string&         job      ,\n    size_t                     size     ,\n    size_t                     repeat   ,\n    CppAD::vector<double>     &matrix   ,\n    CppAD::vector<double>     &gradient )\n{  return false; }\n# else\nnamespace {\n    //\n    // using\n    using std::string;\n    //\n    // typedefs\n    typedef CppAD::AD<double>        a_double;\n    typedef CppAD::vector<double>    d_vector;\n    typedef CppAD::vector<a_double>  ad_vector;\n    //\n    // get_function_ptr\n    CppAD::jit_double get_function_ptr(\n        CppAD::link_dll_lib* dll_linker )\n    {  std::string function_name = \"cppad_jit_gradient_det\";\n        string err_msg;\n        void* void_ptr = (*dll_linker)(function_name, err_msg);\n        if( err_msg != \"\" )\n        {  std::cerr << \"link_det_minor: err_msg = \" << err_msg << \"\\n\";\n            return nullptr;\n        }\n        CppAD::jit_double function_ptr =\n                reinterpret_cast<CppAD::jit_double>(void_ptr);\n        return function_ptr;\n    }\n    //\n    // setup\n    CppAD::link_dll_lib* setup(size_t size)\n    {  // optimization options\n        string optimize_options =\n            \"no_conditional_skip no_compare_op no_print_for_op\";\n        //\n        // adet\n        // object for computing determinant\n        CppAD::det_by_minor<a_double>   adet(size);\n        //\n        // nx\n        // number of independent variables\n        size_t nx = size * size;\n        //\n        // matrix\n        CppAD::vector<double> matrix(nx);\n        CppAD::uniform_01(nx, matrix);\n        //\n        // aA\n        ad_vector   aA(nx);\n        for(size_t j = 0; j < nx; ++j)\n            aA[j] = matrix[j];\n        //\n        // Independent\n        // declare independent variables for function computation\n        bool record_compare   = false;\n        size_t abort_op_index = 0;\n        CppAD::Independent(aA, abort_op_index, record_compare);\n        //\n        // adet_A\n        // AD computation of the determinant\n        ad_vector adet_A(1);\n        adet_A[0] = adet(aA);\n        //\n        // f\n        // f( matrix ) = det(matrix)\n        CppAD::ADFun<double>  f;\n        f.Dependent(aA, adet_A);\n        if( global_option[\"optimize\"] )\n            f.optimize(optimize_options);\n        //\n        // af\n        CppAD::ADFun<a_double, double> af;\n        af = f.base2ad();\n        //\n        // Independent\n        // declare independent variables for gradient computation\n        CppAD::Independent(aA, abort_op_index, record_compare);\n        //\n        // aw\n        // vectors of reverse mode weights\n        CppAD::vector<a_double> aw(1);\n        aw[0] = a_double(1.0);\n        //\n        // agradient\n        ad_vector agradient(nx);\n        af.Forward(0, aA);\n        agradient = af.Reverse(1, aw);\n        //\n        // g\n        // function objects for g : A -> det'( detA  )\n        CppAD::ADFun<double> g;\n        g.Dependent(aA, agradient);\n        if( global_option[\"optimize\"] )\n            g.optimize(optimize_options);\n        g.function_name_set(\"gradient_det\");\n        //\n        // csrc_file\n        string type      = \"double\";\n        string csrc_file = \"gradient_det.c\";\n        std::ofstream ofs;\n        ofs.open(csrc_file, std::ofstream::out);\n        g.to_csrc(ofs, type);\n        ofs.close();\n        //\n        // dll_file\n        string dll_file = \"gradient_det\" DLL_EXT;\n        CppAD::vector< string > csrc_files(1);\n        csrc_files[0] = csrc_file;\n        std::map< string, string > dll_options;\n# if CPPAD_C_COMPILER_MSVC_FLAGS\n        dll_options[\"compile\"] = CPPAD_C_COMPILER_CMD \" /EHs /EHc /c /TC /O2\";\n# endif\n# if CPPAD_C_COMPILER_GNU_FLAGS\n        dll_options[\"compile\"] = \"gcc -c -fPIC -O2\";\n# endif\n        string err_msg =\n            CppAD::create_dll_lib(dll_file, csrc_files, dll_options);\n        if( err_msg != \"\" )\n        {  std::cerr << \"link_det_minor: err_msg = \" << err_msg << \"\\n\";\n            return nullptr;\n        }\n        //\n        // dll_linker_ptr\n        CppAD::link_dll_lib* dll_linker_ptr =\n            new CppAD::link_dll_lib(dll_file, err_msg);\n        if( err_msg != \"\" )\n        {  std::cerr << \"link_det_minor: err_msg = \" << err_msg << \"\\n\";\n            delete dll_linker_ptr;\n            return nullptr;\n        }\n        return dll_linker_ptr;\n    }\n}\n\nbool link_det_minor(\n    const std::string&         job      ,\n    size_t                     size     ,\n    size_t                     repeat   ,\n    CppAD::vector<double>     &matrix   ,\n    CppAD::vector<double>     &gradient )\n{  CPPAD_ASSERT_UNKNOWN( matrix.size() == size * size );\n    CPPAD_ASSERT_UNKNOWN( gradient.size() == size * size );\n    // --------------------------------------------------------------------\n    // check global options\n    const char* valid[] = { \"onetape\", \"optimize\"};\n    size_t n_valid = sizeof(valid) / sizeof(valid[0]);\n    typedef std::map<string, bool>::iterator iterator;\n    //\n    for(iterator itr=global_option.begin(); itr!=global_option.end(); ++itr)\n    {  if( itr->second )\n        {  bool ok = false;\n            for(size_t i = 0; i < n_valid; i++)\n                ok |= itr->first == valid[i];\n            if( ! ok )\n                return false;\n        }\n    }\n    // --------------------------------------------------------------------\n    // pointer to dll linker\n    static CppAD::link_dll_lib* static_dll_linker = nullptr;\n    //\n    // pointer to gradient_det function\n    static CppAD::jit_double static_gradient_det;\n    //\n    // size corresponding static_fun\n    static size_t static_size = 0;\n    //\n    // number of independent variables\n    size_t nx = size * size;\n    //\n    // onetape\n    bool onetape = global_option[\"onetape\"];\n    // ----------------------------------------------------------------------\n    if( job == \"setup\" )\n    {  if( onetape )\n        {  if( static_dll_linker != nullptr )\n                delete static_dll_linker;\n            static_dll_linker = setup(size);\n            //\n            static_gradient_det = get_function_ptr(static_dll_linker);\n            static_size         = size;\n            if( static_gradient_det == nullptr )\n                return false;\n        }\n        else\n        {  static_gradient_det = nullptr;\n            static_size         = 0;\n        }\n        return true;\n    }\n    if( job ==  \"teardown\" )\n    {  if( static_dll_linker != nullptr )\n        {  delete static_dll_linker;\n            static_dll_linker = nullptr;\n        }\n        return true;\n    }\n    // -----------------------------------------------------------------------\n    CPPAD_ASSERT_UNKNOWN( job == \"run\" );\n    if( onetape ) while(repeat--)\n    {  // use if before assert to avoid warning that static_size is not used\n        if( size != static_size )\n        {  CPPAD_ASSERT_UNKNOWN( size == static_size );\n        }\n\n        // get next matrix\n        CppAD::uniform_01(nx, matrix);\n\n        // evaluate the gradient\n        size_t compare_change = 0;\n        static_gradient_det(\n            nx, matrix.data(), nx, gradient.data(), &compare_change\n        );\n    }\n    else while(repeat--)\n    {  if( static_dll_linker != nullptr )\n            delete static_dll_linker;\n        static_dll_linker = setup(size);\n        //\n        static_gradient_det = get_function_ptr(static_dll_linker);\n        static_size         = size;\n        if( static_gradient_det == nullptr )\n            return false;\n        //\n        // get next matrix\n        CppAD::uniform_01(nx, matrix);\n\n        // evaluate the gradient\n        size_t compare_change = 0;\n        static_gradient_det(\n            nx, matrix.data(), nx, gradient.data(), &compare_change\n        );\n    }\n    return true;\n}\n# endif // CPPAD_C_COMPILER_GNU_FLAGS || CPPAD_C_COMPILER_MSVC_FLAGS\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end cppad_jit_det_minor.cpp}\n*/\n"
  },
  {
    "path": "speed/cppad_jit/mat_mul.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin cppad_jit_mat_mul.cpp}\n\ncppad_jit Speed: Matrix Multiplication\n######################################\n\nSpecifications\n**************\n:ref:`link_mat_mul-name`\n\nImplementation\n**************\n// a cppad_jit version of this test is not yet implemented\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <map>\n# include <cppad/utility/vector.hpp>\n\n// list of possible options\nextern std::map<std::string, bool> global_option;\n\nbool link_mat_mul(\n    size_t                           size     ,\n    size_t                           repeat   ,\n    CppAD::vector<double>&           x        ,\n    CppAD::vector<double>&           z        ,\n    CppAD::vector<double>&           dz       )\n{  return false; }\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end cppad_jit_mat_mul.cpp}\n*/\n"
  },
  {
    "path": "speed/cppad_jit/ode.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin cppad_jit_ode.cpp}\n\ncppad_jit Speed: Ode\n####################\n\nSpecifications\n**************\n:ref:`link_ode-name`\n\nImplementation\n**************\n// a cppad_jit version of this test is not yet implemented\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <map>\n# include <cppad/utility/vector.hpp>\n\n// list of possible options\nextern std::map<std::string, bool> global_option;\n\nbool link_ode(\n    size_t                     size       ,\n    size_t                     repeat     ,\n    CppAD::vector<double>      &x         ,\n    CppAD::vector<double>      &jacobian  )\n{  return false; }\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end cppad_jit_ode.cpp}\n*/\n"
  },
  {
    "path": "speed/cppad_jit/poly.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin cppad_jit_poly.cpp}\n\ncppad_jit Speed: Second Derivative of a Polynomial\n##################################################\n\nSpecifications\n**************\n:ref:`link_poly-name`\n\nImplementation\n**************\n// a cppad_jit version of this test is not yet implemented\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <map>\n# include <cppad/utility/vector.hpp>\n\n// list of possible options\nextern std::map<std::string, bool> global_option;\n\nbool link_poly(\n    size_t                     size     ,\n    size_t                     repeat   ,\n    CppAD::vector<double>     &a        ,  // coefficients of polynomial\n    CppAD::vector<double>     &z        ,  // polynomial argument value\n    CppAD::vector<double>     &ddp      )  // second derivative w.r.t z\n{  return false; }\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end cppad_jit_poly.cpp}\n*/\n"
  },
  {
    "path": "speed/cppad_jit/sparse_hessian.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/utility/vector.hpp>\n\n/*\n{xrst_begin cppad_jit_sparse_hessian.cpp}\n\ncppad_jit Speed: Sparse Hessian\n###############################\n\nSpecifications\n**************\n:ref:`link_sparse_hessian-name`\n\n{xrst_spell_off}\n{xrst_code cpp} */\n// A cppad_jit version of this test is not yet available\nbool link_sparse_hessian(\n    size_t                            size      ,\n    size_t                            repeat    ,\n    const CppAD::vector<size_t>&      row       ,\n    const CppAD::vector<size_t>&      col       ,\n    CppAD::vector<double>&            x         ,\n    CppAD::vector<double>&            hessian   ,\n    size_t&                           n_color\n)\n{  return false; }\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end cppad_jit_sparse_hessian.cpp}\n*/\n"
  },
  {
    "path": "speed/cppad_jit/sparse_jacobian.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cstring>\n# include <cppad/utility/vector.hpp>\n\n/*\n{xrst_begin cppad_jit_sparse_jacobian.cpp}\n\ncppad_jit Speed: sparse_jacobian\n################################\n\nSpecifications\n**************\n:ref:`link_sparse_jacobian-name`\n\n{xrst_spell_off}\n{xrst_code cpp} */\n// A cppad_jit version of this test is not yet available\nbool link_sparse_jacobian(\n    const std::string&               job      ,\n    size_t                           size     ,\n    size_t                           repeat   ,\n    size_t                           m        ,\n    const CppAD::vector<size_t>&     row      ,\n    const CppAD::vector<size_t>&     col      ,\n    CppAD::vector<double>&           x        ,\n    CppAD::vector<double>&           jacobian ,\n    size_t&                          n_color  )\n{\n    return false;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end cppad_jit_sparse_jacobian.cpp}\n*/\n"
  },
  {
    "path": "speed/cppad_jit/speed_cppad_jit.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin speed_cppad_jit}\n\nSpeed Test Derivatives Using cppad_jit\n######################################\n\nPurpose\n*******\nCppAD has a set of speed tests that are used to compare\ncppad_jit with other AD packages.\nThis section links to the source code the cppad_jit speed tests\n(any suggestions to make the cppad_jit results faster are welcome).\n\nRunning Tests\n*************\nTo build these speed tests, and run their correctness tests,\nexecute the following commands starting in the\n:ref:`cmake@Build Directory` :\n\n| |tab| ``cd speed/cppad_jit``\n| |tab| ``make check_speed_cppad_jit VERBOSE`` =1\n\nYou can then run the corresponding speed tests\nwith the following command\n\n    ./ ``speed_cppad_jit speed`` *seed*\n\nwhere *seed* is a positive integer.\nSee :ref:`speed_main-name` for more options.\n\nContents\n********\n{xrst_toc_list\n    speed/cppad_jit/det_minor.cpp\n    speed/cppad_jit/det_lu.cpp\n    speed/cppad_jit/mat_mul.cpp\n    speed/cppad_jit/ode.cpp\n    speed/cppad_jit/poly.cpp\n    speed/cppad_jit/sparse_hessian.cpp\n    speed/cppad_jit/sparse_jacobian.cpp\n}\n\n{xrst_end speed_cppad_jit}\n"
  },
  {
    "path": "speed/cppadcg/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# Build the speed/cppadcg directory tests\n# Inherit build type from ../CMakeList.txt\n#\nassert ( include_cppadcg )\n#\n# Adds flags to the compiler command line for sources in the current directory\n# and below. This command can be used to add any flags, but it was originally\n# intended to add preprocessor definitions.\nADD_DEFINITIONS(\"-DCPPAD_CPPADCG_SPEED\")\n\n# Local include directories to search (not in package_prefix/includdir)\nINCLUDE_DIRECTORIES( ${CMAKE_CURRENT_SOURCE_DIR}/../src )\n\nSET(source_list ../main.cpp\n    det_lu.cpp\n    det_minor.cpp\n    mat_mul.cpp\n    ode.cpp\n    poly.cpp\n    sparse_hessian.cpp\n    sparse_jacobian.cpp\n)\nset_compile_flags( speed_cppadcg \"${cppad_debug_which}\" \"${source_list}\" )\n#\nADD_EXECUTABLE(speed_cppadcg EXCLUDE_FROM_ALL ${source_list} )\n#\n# List of libraries to be linked into the specified target\nTARGET_LINK_LIBRARIES(speed_cppadcg\n    ${cppad_lib}\n    ${colpack_libs}\n)\n# cppadcg is an include file only library\nTARGET_LINK_LIBRARIES(speed_cppadcg\n    speed_src\n    ${cppad_lib}\n    ${colpack_libs}\n)\n\n\n# check_speed_cppadcg\nSET(random_seed 54321)\nadd_check_executable(check_speed cppadcg \"correct ${random_seed} onetape\")\n"
  },
  {
    "path": "speed/cppadcg/det_lu.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin cppadcg_det_lu.cpp}\n\nCppadcg Speed: Gradient of Determinant Using Lu Factorization\n#############################################################\n\nSpecifications\n**************\n:ref:`link_det_lu-name`\n\nImplementation\n**************\nA cppadcg version of this test is not yet implemented\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <map>\n# include <cppad/utility/vector.hpp>\n\n// list of possible options\nextern std::map<std::string, bool> global_option;\n\nbool link_det_lu(\n    size_t                     size     ,\n    size_t                     repeat   ,\n    CppAD::vector<double>     &matrix   ,\n    CppAD::vector<double>     &gradient )\n{  return false; }\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end cppadcg_det_lu.cpp}\n*/\n"
  },
  {
    "path": "speed/cppadcg/det_minor.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin cppadcg_det_minor.cpp}\n\ncppadcg Speed: Gradient of Determinant by Minor Expansion\n#########################################################\n\nSpecifications\n**************\nSee :ref:`link_det_minor-name` .\n\nPASS_JACOBIAN_TO_CODE_GEN\n*************************\nIf this is one, the Jacobian of the determinant is the function passed\nto CppADCodeGen.  In this case,  the ``code_gen_fun``\n:ref:`code_gen_fun@Syntax@function` is used to calculate\nthe Jacobian of the determinant.\nOtherwise, this flag is zero and the determinant function is passed\nto CppADCodeGen. In this case, the ``code_gen_fun``\n:ref:`code_gen_fun@Syntax@jacobian` is used to calculate\nthe Jacobian of the determinant.\n{xrst_spell_off}\n{xrst_code cpp} */\n# define PASS_JACOBIAN_TO_CODE_GEN 1\n/* {xrst_code}\n{xrst_spell_on}\n\nImplementation\n**************\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <cppad/speed/det_by_minor.hpp>\n# include <cppad/speed/uniform_01.hpp>\n# include <cppad/utility/vector.hpp>\n# include <cppad/example/code_gen_fun.hpp>\n\n# include <map>\nextern std::map<std::string, bool> global_option;\n\nnamespace {\n    //\n    // typedefs\n    typedef CppAD::cg::CG<double>     c_double;\n    typedef CppAD::AD<c_double>      ac_double;\n    typedef CppAD::vector<double>     d_vector;\n    typedef CppAD::vector<ac_double> ac_vector;\n    //\n    // setup\n    void setup(\n        // inputs\n        size_t size     ,\n        // outputs\n        code_gen_fun& fun )\n    {  // optimization options\n        std::string optimize_options =\n            \"no_conditional_skip no_compare_op no_print_for_op\";\n        //\n        // object for computing determinant\n        CppAD::det_by_minor<ac_double>   ac_det(size);\n        //\n        // number of independent variables\n        size_t nx = size * size;\n        //\n        // choose a matrix\n        CppAD::vector<double> matrix(nx);\n        CppAD::uniform_01(nx, matrix);\n        //\n        // copy to independent variables\n        ac_vector   ac_A(nx);\n        for(size_t j = 0; j < nx; ++j)\n            ac_A[j] = matrix[j];\n        //\n        // declare independent variables for function computation\n        bool record_compare   = false;\n        size_t abort_op_index = 0;\n        CppAD::Independent(ac_A, abort_op_index, record_compare);\n        //\n        // AD computation of the determinant\n        ac_vector ac_detA(1);\n        ac_detA[0] = ac_det(ac_A);\n        //\n        // create function objects for f : A -> detA\n        CppAD::ADFun<c_double>            c_f;\n        c_f.Dependent(ac_A, ac_detA);\n        if( global_option[\"optimize\"] )\n            c_f.optimize(optimize_options);\n# if ! PASS_JACOBIAN_TO_CODE_GEN\n        // f(x) is the determinant function\n        code_gen_fun::evaluation_enum eval_jac = code_gen_fun::dense_enum;\n        code_gen_fun f_tmp(\"det_minor\", c_f, eval_jac);\n        fun.swap(f_tmp);\n# else\n        CppAD::ADFun<ac_double, c_double> ac_f;\n        ac_f = c_f.base2ad();\n        //\n        // declare independent variables for gradient computation\n        CppAD::Independent(ac_A, abort_op_index, record_compare);\n        //\n        // vectors of reverse mode weights\n        CppAD::vector<ac_double> ac_w(1);\n        ac_w[0] = ac_double(1.0);\n        //\n        // AD computation of the gradient\n        ac_vector ac_gradient(nx);\n        ac_f.Forward(0, ac_A);\n        ac_gradient = ac_f.Reverse(1, ac_w);\n        //\n        // create function objects for g : A -> det'( detA  )\n        CppAD::ADFun<c_double> c_g;\n        c_g.Dependent(ac_A, ac_gradient);\n        if( global_option[\"optimize\"] )\n            c_g.optimize(optimize_options);\n        // g(x) is the Jacobian of the determinant\n        code_gen_fun g_tmp(\"det_minor\", c_g);\n        fun.swap(g_tmp);\n# endif\n    }\n}\n\nbool link_det_minor(\n    const std::string&         job      ,\n    size_t                     size     ,\n    size_t                     repeat   ,\n    CppAD::vector<double>     &matrix   ,\n    CppAD::vector<double>     &gradient )\n{  CPPAD_ASSERT_UNKNOWN( matrix.size() == size * size );\n    CPPAD_ASSERT_UNKNOWN( gradient.size() == size * size );\n    // --------------------------------------------------------------------\n    // check global options\n    const char* valid[] = { \"onetape\", \"optimize\"};\n    size_t n_valid = sizeof(valid) / sizeof(valid[0]);\n    typedef std::map<std::string, bool>::iterator iterator;\n    //\n    for(iterator itr=global_option.begin(); itr!=global_option.end(); ++itr)\n    {  if( itr->second )\n        {  bool ok = false;\n            for(size_t i = 0; i < n_valid; i++)\n                ok |= itr->first == valid[i];\n            if( ! ok )\n                return false;\n        }\n    }\n    // --------------------------------------------------------------------\n    //\n    // function object mapping matrix to gradient of determinant\n    static code_gen_fun static_fun;\n    //\n    // size corresponding static_fun\n    static size_t static_size = 0;\n    //\n    // number of independent variables\n    size_t nx = size * size;\n    //\n    // onetape\n    bool onetape = global_option[\"onetape\"];\n    // ----------------------------------------------------------------------\n    if( job == \"setup\" )\n    {  if( onetape )\n        {  setup(size, static_fun);\n            static_size = size;\n        }\n        else\n        {  static_size = 0;\n        }\n        return true;\n    }\n    if( job ==  \"teardown\" )\n    {  code_gen_fun fun;\n        static_fun.swap(fun);\n        return true;\n    }\n    // -----------------------------------------------------------------------\n    CPPAD_ASSERT_UNKNOWN( job == \"run\" );\n    if( onetape ) while(repeat--)\n    {  // use if before assert to avoid warning that static_size is not used\n        if( size != static_size )\n        {  CPPAD_ASSERT_UNKNOWN( size == static_size );\n        }\n\n        // get next matrix\n        CppAD::uniform_01(nx, matrix);\n\n        // evaluate the gradient\n# if PASS_JACOBIAN_TO_CODE_GEN\n        gradient = static_fun(matrix);\n# else\n        gradient = static_fun.jacobian(matrix);\n# endif\n    }\n    else while(repeat--)\n    {  setup(size, static_fun);\n        static_size = size;\n\n        // get next matrix\n        CppAD::uniform_01(nx, matrix);\n\n        // evaluate the gradient\n# if PASS_JACOBIAN_TO_CODE_GEN\n        gradient = static_fun(matrix);\n# else\n        gradient = static_fun.jacobian(matrix);\n# endif\n    }\n    return true;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end cppadcg_det_minor.cpp}\n*/\n"
  },
  {
    "path": "speed/cppadcg/mat_mul.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin cppadcg_mat_mul.cpp}\n\nCppadcg Speed: Matrix Multiplication\n####################################\n\nSpecifications\n**************\n:ref:`link_mat_mul-name`\n\nImplementation\n**************\n// a cppadcg version of this test is not yet implemented\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <map>\n# include <cppad/utility/vector.hpp>\n\n// list of possible options\nextern std::map<std::string, bool> global_option;\n\nbool link_mat_mul(\n    size_t                           size     ,\n    size_t                           repeat   ,\n    CppAD::vector<double>&           x        ,\n    CppAD::vector<double>&           z        ,\n    CppAD::vector<double>&           dz       )\n{  return false; }\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end cppadcg_mat_mul.cpp}\n*/\n"
  },
  {
    "path": "speed/cppadcg/ode.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin cppadcg_ode.cpp}\n\nCppadcg Speed: Ode\n##################\n\nSpecifications\n**************\n:ref:`link_ode-name`\n\nImplementation\n**************\n// a cppadcg version of this test is not yet implemented\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <map>\n# include <cppad/utility/vector.hpp>\n\n// list of possible options\nextern std::map<std::string, bool> global_option;\n\nbool link_ode(\n    size_t                     size       ,\n    size_t                     repeat     ,\n    CppAD::vector<double>      &x         ,\n    CppAD::vector<double>      &jacobian  )\n{  return false; }\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end cppadcg_ode.cpp}\n*/\n"
  },
  {
    "path": "speed/cppadcg/poly.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin cppadcg_poly.cpp}\n\nCppadcg Speed: Second Derivative of a Polynomial\n################################################\n\nSpecifications\n**************\n:ref:`link_poly-name`\n\nImplementation\n**************\n// a cppadcg version of this test is not yet implemented\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <map>\n# include <cppad/utility/vector.hpp>\n\n// list of possible options\nextern std::map<std::string, bool> global_option;\n\nbool link_poly(\n    size_t                     size     ,\n    size_t                     repeat   ,\n    CppAD::vector<double>     &a        ,  // coefficients of polynomial\n    CppAD::vector<double>     &z        ,  // polynomial argument value\n    CppAD::vector<double>     &ddp      )  // second derivative w.r.t z\n{  return false; }\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end cppadcg_poly.cpp}\n*/\n"
  },
  {
    "path": "speed/cppadcg/sparse_hessian.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/utility/vector.hpp>\n\n/*\n{xrst_begin cppadcg_sparse_hessian.cpp}\n\nCppadcg Speed: Sparse Hessian\n#############################\n\nSpecifications\n**************\n:ref:`link_sparse_hessian-name`\n\n{xrst_spell_off}\n{xrst_code cpp} */\n// A cppadcg version of this test is not yet available\nbool link_sparse_hessian(\n    size_t                            size      ,\n    size_t                            repeat    ,\n    const CppAD::vector<size_t>&      row       ,\n    const CppAD::vector<size_t>&      col       ,\n    CppAD::vector<double>&            x         ,\n    CppAD::vector<double>&            hessian   ,\n    size_t&                           n_color\n)\n{  return false; }\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end cppadcg_sparse_hessian.cpp}\n*/\n"
  },
  {
    "path": "speed/cppadcg/sparse_jacobian.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin cppadcg_sparse_jacobian.cpp}\n\nCppadcg Speed: Sparse Jacobian\n##############################\n\nSpecifications\n**************\nSee :ref:`link_sparse_jacobian-name` .\n\nPASS_SPARSE_JACOBIAN_TO_CODE_GEN\n********************************\nIf this is one, the sparse Jacobian is the is the function passed\nto CppADCodeGen, In this case, the ``code_gen_fun``\n:ref:`code_gen_fun@Syntax@function` is used to calculate\nthe sparse Jacobian.\nOtherwise, this flag is zero and the original function passed\nto CppADCodeGen. In this case, the ``code_gen_fun``\n:ref:`code_gen_fun@Syntax@sparse_jacobian`\nis used to calculate the sparse Jacobian.\n{xrst_spell_off}\n{xrst_code cpp} */\n# define PASS_SPARSE_JACOBIAN_TO_CODE_GEN 1\n/* {xrst_code}\n{xrst_spell_on}\n\nImplementation\n**************\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <cppad/speed/uniform_01.hpp>\n# include <cppad/utility/vector.hpp>\n# include <cppad/speed/sparse_jac_fun.hpp>\n# include <cppad/example/code_gen_fun.hpp>\n\n# include <map>\nextern std::map<std::string, bool> global_option;\n\nnamespace {\n    // -----------------------------------------------------------------------\n    // typedefs\n    typedef CppAD::cg::CG<double>       c_double;\n    typedef CppAD::AD<c_double>        ac_double;\n    typedef CppAD::vector<bool>         b_vector;\n    typedef CppAD::vector<size_t>       s_vector;\n    typedef CppAD::vector<double>       d_vector;\n    typedef CppAD::vector<ac_double>   ac_vector;\n    typedef CppAD::sparse_rc<s_vector> sparsity;\n    // ------------------------------------------------------------------------\n# if PASS_SPARSE_JACOBIAN_TO_CODE_GEN\n    // calc_sparsity\n    void calc_sparsity(\n        CppAD::sparse_rc<s_vector>& pattern ,\n        CppAD::ADFun<c_double>&     f       )\n    {  bool reverse       = global_option[\"revsparsity\"];\n        bool transpose     = false;\n        bool internal_bool = global_option[\"boolsparsity\"];\n        bool dependency    = false;\n        bool subgraph      = global_option[\"subsparsity\"];\n        size_t n = f.Domain();\n        size_t m = f.Range();\n        if( subgraph )\n        {  b_vector select_domain(n), select_range(m);\n            for(size_t j = 0; j < n; ++j)\n                select_domain[j] = true;\n            for(size_t i = 0; i < m; ++i)\n                select_range[i] = true;\n            f.subgraph_sparsity(\n                select_domain, select_range, transpose, pattern\n            );\n        }\n        else\n        {  size_t q = n;\n            if( reverse )\n                q = m;\n            //\n            CppAD::sparse_rc<s_vector> identity;\n            identity.resize(q, q, q);\n            for(size_t k = 0; k < q; k++)\n                identity.set(k, k, k);\n            //\n            if( reverse )\n            {  f.rev_jac_sparsity(\n                    identity, transpose, dependency, internal_bool, pattern\n                );\n            }\n            else\n            {  f.for_jac_sparsity(\n                    identity, transpose, dependency, internal_bool, pattern\n                );\n            }\n        }\n    }\n# endif // PASS_SPARSE_JACOBIAN_TO_CODE_GEN\n    // -------------------------------------------------------------------------\n    // setup\n    void setup(\n            // inputs\n            size_t          size     ,\n            const s_vector& row      ,\n            const s_vector& col      ,\n            // outputs\n            size_t&         n_color  ,\n            code_gen_fun&   fun      ,\n            s_vector&  row_major     )\n    {  // optimization options\n        std::string optimize_options =\n            \"no_conditional_skip no_compare_op no_print_for_op\";\n        //\n        // independent variable vector\n        size_t nc = size;\n        ac_vector ac_x(nc);\n        //\n        // dependent variable vector\n        size_t nr = 2 * nc;\n        ac_vector ac_y(nr);\n        //\n        // values of independent variables do not matter\n        for(size_t j = 0; j < nc; j++)\n            ac_x[j] = ac_double( double(j) / double(nc) );\n        //\n        // declare independent variables\n        size_t abort_op_index = 0;\n        bool record_compare   = false;\n        CppAD::Independent(ac_x, abort_op_index, record_compare);\n        //\n        // AD computation of f(x) (order zero derivative is function value)\n        size_t order = 0;\n        CppAD::sparse_jac_fun<ac_double>(nr, nc, ac_x, row, col, order, ac_y);\n        //\n        // create function object f : x -> y\n        CppAD::ADFun<c_double>            c_f;\n        CppAD::ADFun<ac_double, c_double> ac_f;\n        c_f.Dependent(ac_x, ac_y);\n        if( global_option[\"optimize\"] )\n            c_f.optimize(optimize_options);\n        //\n        // number of non-zeros in sparsity pattern for Jacobian\n# if ! PASS_SPARSE_JACOBIAN_TO_CODE_GEN\n        // set fun\n        code_gen_fun::evaluation_enum eval_jac = code_gen_fun::sparse_enum;\n        code_gen_fun f_tmp(\"sparse_jacobian\", c_f, eval_jac);\n        fun.swap(f_tmp);\n        //\n        // set row_major\n        d_vector x(nc);\n        CppAD::uniform_01(nc, x);\n        CppAD::sparse_rcv<s_vector, d_vector> Jrcv = fun.sparse_jacobian(x);\n        row_major = Jrcv.row_major();\n# ifndef NDEBUG\n        size_t nnz = row.size();\n        CPPAD_ASSERT_UNKNOWN( row_major.size() == nnz );\n        for(size_t k = 0; k < nnz; ++k)\n        {  size_t ell = row_major[k];\n            CPPAD_ASSERT_UNKNOWN(\n                Jrcv.row()[ell] == row[k] && Jrcv.col()[ell] == col[k]\n            );\n        }\n# endif\n        //\n# else  // PASS_SPARSE_JACOBIAN_TO_CODE_GEN\n        //\n        // sparsity pattern  for subset of Jacobian pattern that is evaluated\n        size_t nnz = row.size();\n        sparsity subset_pattern(nr, nc, nnz);\n        for(size_t k = 0; k < nnz; ++k)\n            subset_pattern.set(k, row[k], col[k]);\n        //\n        // spoarse matrix for subset of Jacobian that is evaluated\n        CppAD::sparse_rcv<s_vector, ac_vector> ac_subset( subset_pattern );\n        //\n        // coloring method\n        std::string coloring = \"cppad\";\n# if CPPAD_HAS_COLPACK\n        if( global_option[\"colpack\"] )\n            coloring = \"colpack\";\n# endif\n        //\n        // maximum number of colors at once\n        size_t group_max = 1;\n        ac_f = c_f.base2ad();\n        //\n        // declare independent variables for jacobian computation\n        CppAD::Independent(ac_x, abort_op_index, record_compare);\n        //\n        if( global_option[\"subgraph\"] )\n        {  // use reverse mode because forward not yet implemented\n            ac_f.subgraph_jac_rev(ac_x, ac_subset);\n            n_color = 0;\n        }\n        else\n        {  // calculate the Jacobian sparsity pattern for this function\n            sparsity pattern;\n            calc_sparsity(pattern, c_f);\n            //\n              // use forward mode to compute Jacobian\n            CppAD::sparse_jac_work work;\n            n_color = ac_f.sparse_jac_for(\n                group_max, ac_x, ac_subset, pattern, coloring, work\n            );\n        }\n        const ac_vector ac_val ( ac_subset.val() );\n        //\n        // create function g : x -> f'(x)\n        CppAD::ADFun<c_double> c_g;\n        c_g.Dependent(ac_x, ac_val);\n        if( global_option[\"optimize\"] )\n            c_g.optimize(optimize_options);\n        code_gen_fun g_tmp(\"sparse_jacobian\", c_g);\n        //\n        // set return value\n        fun.swap(g_tmp);\n# endif // PASS_SPARSE_JACOBIAN_TO_CODE_GEN\n        return;\n    }\n}\n\nbool link_sparse_jacobian(\n    const std::string&               job      ,\n    size_t                           size     ,\n    size_t                           repeat   ,\n    size_t                           m        ,\n    const CppAD::vector<size_t>&     row      ,\n    const CppAD::vector<size_t>&     col      ,\n    CppAD::vector<double>&           x        ,\n    CppAD::vector<double>&           jacobian ,\n    size_t&                          n_color  )\n{  assert( x.size() == size );\n    assert( jacobian.size() == row.size() );\n    // --------------------------------------------------------------------\n    // check global options\n    const char* valid[] = {\n        \"memory\", \"onetape\", \"optimize\", \"subgraph\",\n        \"boolsparsity\", \"revsparsity\", \"subsparsity\"\n# if CPPAD_HAS_COLPACK\n        , \"colpack\"\n# endif\n    };\n    size_t n_valid = sizeof(valid) / sizeof(valid[0]);\n    typedef std::map<std::string, bool>::iterator iterator;\n    //\n    for(iterator itr=global_option.begin(); itr!=global_option.end(); ++itr)\n    {  if( itr->second )\n        {  bool ok = false;\n            for(size_t i = 0; i < n_valid; i++)\n                ok |= itr->first == valid[i];\n            if( ! ok )\n                return false;\n        }\n    }\n    if( global_option[\"subsparsity\"] )\n    {  if( global_option[\"boolsparisty\"]\n        ||  global_option[\"revsparsity\"]\n        ||  global_option[\"colpack\"]  )\n            return false;\n    }\n    // -----------------------------------------------------\n    // size corresponding to static_fun\n    static size_t static_size = 0;\n    //\n    // function object mapping x to f'(x)\n    static code_gen_fun static_fun;\n    //\n    // row_major order for Jrcv\n    static s_vector static_row_major;\n    //\n# if ! PASS_SPARSE_JACOBIAN_TO_CODE_GEN\n    // code gen value for sparse jacobian\n    CppAD::sparse_rcv<s_vector, d_vector> Jrcv;\n# endif\n    //\n    // number of independent variables\n    size_t nx = size;\n    //\n    bool onetape = global_option[\"onetape\"];\n    //\n    // default return value\n    n_color = 0;\n    // -----------------------------------------------------\n    if( job == \"setup\" )\n    {  if( onetape )\n        {  // sets n_color when ontape is true\n            setup(size, row, col, n_color, static_fun, static_row_major);\n            static_size = size;\n        }\n        else\n        {  static_size = 0;\n        }\n        return true;\n    }\n    if( job == \"teardown\" )\n    {  code_gen_fun f_tmp;\n        static_fun.swap(f_tmp);\n        static_row_major.clear();\n        //\n        static_size    = 0;\n        return true;\n    }\n    // -----------------------------------------------------\n    CPPAD_ASSERT_UNKNOWN( job == \"run\" )\n    if( onetape ) while(repeat--)\n    {  // use if before assert to avoid warning that static_size is not used\n        if( size != static_size )\n        {  CPPAD_ASSERT_UNKNOWN( size == static_size );\n        }\n\n        // get next x\n        CppAD::uniform_01(nx, x);\n\n        // evaluate the jacobian\n# if PASS_SPARSE_JACOBIAN_TO_CODE_GEN\n        jacobian = static_fun(x);\n# else\n        Jrcv = static_fun.sparse_jacobian(x);\n        CPPAD_ASSERT_UNKNOWN( Jrcv.nnz() == jacobian.size() );\n        for(size_t k = 0; k < row.size(); ++k)\n            jacobian[k] = Jrcv.val()[ static_row_major[k] ];\n# endif\n    }\n    else while(repeat--)\n    {  // sets n_color when ontape is false\n        setup(size, row, col, n_color, static_fun, static_row_major);\n        static_size = size;\n\n        // get next x\n        CppAD::uniform_01(nx, x);\n\n        // evaluate the jacobian\n# if PASS_SPARSE_JACOBIAN_TO_CODE_GEN\n        jacobian = static_fun(x);\n# else\n        Jrcv = static_fun.sparse_jacobian(x);\n        CPPAD_ASSERT_UNKNOWN( Jrcv.nnz() == jacobian.size() );\n        for(size_t k = 0; k < row.size(); ++k)\n            jacobian[k] = Jrcv.val()[ static_row_major[k] ];\n# endif\n    }\n    return true;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end cppadcg_sparse_jacobian.cpp}\n*/\n"
  },
  {
    "path": "speed/cppadcg/speed_cppadcg.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin speed_cppadcg}\n{xrst_spell\n    onetape\n}\n\nSpeed Test Derivatives Using Cppadcg\n####################################\n\nPurpose\n*******\nCppAD has a set of speed tests that are used to compare\nCppadcg with other AD packages.\nThis section links to the source code the Cppadcg speed tests\n(any suggestions to make the Cppadcg results faster are welcome).\n\nBuilding Tests\n**************\nStarting in the\n:ref:`cmake@Build Directory` ,\nexecute the following commands\n\n| |tab| ``cd build/speed/cppadcg``\n| |tab| ./ ``speed_cppadcg`` *test* *seed* *option_list*\n\nA message saying that the sizes are incorrect will be printed.\nIn addition, it will say that source code with the correct sizes\nhas been created.\nIf you then execute\n\n    ``make check_speed_cppadcg VERBOSE`` =1\n\nIt will build ``speed_cppadcg`` with the proper sizes and\nrun its correctness tests.\n\nRunning Tests\n*************\nYou can then run the corresponding speed tests\nwith the either of the following commands:\n\n| |tab| ./ ``speed_cppadcg speed`` *seed* ``onetape``\n| |tab| ./ ``speed_cppadcg speed`` *seed* ``onetape optimize``\n\nwhere *seed* is a positive integer.\nSee :ref:`speed_main-name` for more options.\n\nContents\n********\n{xrst_toc_list\n    speed/cppadcg/det_minor.cpp\n    speed/cppadcg/det_lu.cpp\n    speed/cppadcg/mat_mul.cpp\n    speed/cppadcg/ode.cpp\n    speed/cppadcg/poly.cpp\n    speed/cppadcg/sparse_hessian.cpp\n    speed/cppadcg/sparse_jacobian.cpp\n}\n\n{xrst_end speed_cppadcg}\n"
  },
  {
    "path": "speed/dev_speed.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin dev_speed dev}\n\nSpeed Testing Developer Documentation\n#####################################\n\nContents\n********\n{xrst_toc_table\n    speed/src/dev_link.xrst\n    speed/src/dev_sparse_hessian.xrst\n    speed/src/link_sparse_jacobian.cpp\n}\n\n{xrst_end dev_speed}\n"
  },
  {
    "path": "speed/double/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# Build the speed/double directory tests\n# Inherit build type environment from ../CMakeList.txt\n\n# Adds flags to the compiler command line for sources in the current directory\n# and below. This command can be used to add any flags, but it was originally\n# intended to add preprocessor definitions.\nADD_DEFINITIONS(\"-DCPPAD_DOUBLE_SPEED\")\n\n# Local include directories to search (not in package_prefix/includdir)\nINCLUDE_DIRECTORIES( ${CMAKE_CURRENT_SOURCE_DIR}/../src )\n\n# add_executable(<name> [WIN32] [MACOSX_BUNDLE] [EXCLUDE_FROM_ALL]\n#                 source1 source2 ... sourceN\n# )\nSET(source_list ../main.cpp\n    det_lu.cpp\n    det_minor.cpp\n    mat_mul.cpp\n    ode.cpp\n    poly.cpp\n    sparse_hessian.cpp\n    sparse_jacobian.cpp\n)\nset_compile_flags( speed_double \"${cppad_debug_which}\" \"${source_list}\" )\n#\nADD_EXECUTABLE( speed_double EXCLUDE_FROM_ALL ${source_list} )\n#\n# List of libraries to be linked into the specified target\nTARGET_LINK_LIBRARIES(speed_double\n    ${cppad_lib}\n    ${colpack_libs}\n)\n# double does not use any external library\nTARGET_LINK_LIBRARIES(speed_double speed_src )\n\n\n# check_speed_double\nadd_check_executable(check_speed double \"correct 54321\")\n"
  },
  {
    "path": "speed/double/det_lu.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin double_det_lu.cpp}\n\nDouble Speed: Determinant Using Lu Factorization\n################################################\n\nSpecifications\n**************\nSee :ref:`link_det_lu-name` .\n\nImplementation\n**************\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <cppad/utility/vector.hpp>\n# include <cppad/speed/det_by_lu.hpp>\n# include <cppad/speed/uniform_01.hpp>\n\n// Note that CppAD uses global_option[\"memory\"] at the main program level\n# include <map>\nextern std::map<std::string, bool> global_option;\n\nbool link_det_lu(\n    size_t                           size     ,\n    size_t                           repeat   ,\n    CppAD::vector<double>           &matrix   ,\n    CppAD::vector<double>           &det      )\n{\n    if(global_option[\"onetape\"]||global_option[\"atomic\"]||global_option[\"optimize\"])\n        return false;\n    // -----------------------------------------------------\n    // setup\n    CppAD::det_by_lu<double>  Det(size);\n    size_t n = size * size; // number of independent variables\n\n    // ------------------------------------------------------\n\n    while(repeat--)\n    {  // get the next matrix\n        CppAD::uniform_01(n, matrix);\n\n        // computation of the determinant\n        det[0] = Det(matrix);\n    }\n    return true;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end double_det_lu.cpp}\n*/\n"
  },
  {
    "path": "speed/double/det_minor.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin double_det_minor.cpp}\n\nDouble Speed: Determinant by Minor Expansion\n############################################\n\nSpecifications\n**************\nSee :ref:`link_det_minor-name` .\n\nImplementation\n**************\n\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <cppad/utility/vector.hpp>\n# include <cppad/speed/det_by_minor.hpp>\n# include <cppad/speed/uniform_01.hpp>\n\n// Note that CppAD uses global_option[\"memory\"] at the main program level\n# include <map>\nextern std::map<std::string, bool> global_option;\n\nbool link_det_minor(\n    const std::string&         job      ,\n    size_t                     size     ,\n    size_t                     repeat   ,\n    CppAD::vector<double>     &matrix   ,\n    CppAD::vector<double>     &det      )\n{  // --------------------------------------------------------------------------\n    // ignore global_option\n    // --------------------------------------------------------------------------\n    if( job == \"setup\" || job == \"teardown\" )\n        return true;\n    CPPAD_ASSERT_UNKNOWN( job == \"run\" );\n    //\n    // setup\n    CppAD::det_by_minor<double>   Det(size);\n    //\n    // number of independent variables\n    size_t n = size * size;\n    // -------------------------------------------------------------------------\n    while(repeat--)\n    {  // get the next matrix\n        CppAD::uniform_01(n, matrix);\n\n        // computation of the determinant\n        det[0] = Det(matrix);\n    }\n    return true;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end double_det_minor.cpp}\n*/\n"
  },
  {
    "path": "speed/double/mat_mul.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin double_mat_mul.cpp}\n\nDouble Speed: Matrix Multiplication\n###################################\n\nSpecifications\n**************\nSee :ref:`link_mat_mul-name` .\n\nImplementation\n**************\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <cppad/cppad.hpp>\n# include <cppad/speed/mat_sum_sq.hpp>\n# include <cppad/speed/uniform_01.hpp>\n\n// Note that CppAD uses global_option[\"memory\"] at the main program level\n# include <map>\nextern std::map<std::string, bool> global_option;\n\nbool link_mat_mul(\n    size_t                           size     ,\n    size_t                           repeat   ,\n    CppAD::vector<double>&           x        ,\n    CppAD::vector<double>&           z        ,\n    CppAD::vector<double>&           dz\n)\n{\n    if(global_option[\"onetape\"]||global_option[\"atomic\"]||global_option[\"optimize\"])\n        return false;\n    // -----------------------------------------------------\n    size_t n = size * size; // number of independent variables\n    CppAD::vector<double> y(n);\n\n    while(repeat--)\n    {  // get the next matrix\n        CppAD::uniform_01(n, x);\n\n        // do computation\n        mat_sum_sq(size, x, y, z);\n\n    }\n    return true;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end double_mat_mul.cpp}\n*/\n"
  },
  {
    "path": "speed/double/ode.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin double_ode.cpp}\n\nDouble Speed: Ode Solution\n##########################\n\nSpecifications\n**************\nSee :ref:`link_ode-name` .\n\nImplementation\n**************\n\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <cstring>\n# include <cppad/utility/vector.hpp>\n# include <cppad/speed/ode_evaluate.hpp>\n# include <cppad/speed/uniform_01.hpp>\n\n// Note that CppAD uses global_option[\"memory\"] at the main program level\n# include <map>\nextern std::map<std::string, bool> global_option;\n\nbool link_ode(\n    size_t                     size       ,\n    size_t                     repeat     ,\n    CppAD::vector<double>      &x         ,\n    CppAD::vector<double>      &jacobian\n)\n{\n    if(global_option[\"onetape\"]||global_option[\"atomic\"]||global_option[\"optimize\"])\n        return false;\n    // -------------------------------------------------------------\n    // setup\n    assert( x.size() == size );\n\n    size_t n = size;\n\n    size_t m = 0;\n    CppAD::vector<double> f(n);\n\n    while(repeat--)\n    {  // choose next x value\n        uniform_01(n, x);\n\n        // evaluate function\n        CppAD::ode_evaluate(x, m, f);\n\n    }\n    size_t i;\n    for(i = 0; i < n; i++)\n        jacobian[i] = f[i];\n    return true;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end double_ode.cpp}\n*/\n"
  },
  {
    "path": "speed/double/poly.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin double_poly.cpp}\n\nDouble Speed: Evaluate a Polynomial\n###################################\n\nSpecifications\n**************\nSee :ref:`link_poly-name` .\n\nImplementation\n**************\n\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <cppad/cppad.hpp>\n# include <cppad/speed/uniform_01.hpp>\n\n// Note that CppAD uses global_option[\"memory\"] at the main program level\n# include <map>\nextern std::map<std::string, bool> global_option;\n\nbool link_poly(\n    size_t                     size     ,\n    size_t                     repeat   ,\n    CppAD::vector<double>     &a        ,  // coefficients of polynomial\n    CppAD::vector<double>     &z        ,  // polynomial argument value\n    CppAD::vector<double>     &p        )  // second derivative w.r.t z\n{\n    if(global_option[\"onetape\"]||global_option[\"atomic\"]||global_option[\"optimize\"])\n        return false;\n    // -----------------------------------------------------\n    // setup\n\n    // ------------------------------------------------------\n    while(repeat--)\n    {  // get the next argument value\n        CppAD::uniform_01(1, z);\n\n        // evaluate the polynomial at the new argument value\n        p[0] = CppAD::Poly(0, a, z[0]);\n    }\n    return true;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end double_poly.cpp}\n*/\n"
  },
  {
    "path": "speed/double/sparse_hessian.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin double_sparse_hessian.cpp}\n\nDouble Speed: Sparse Hessian\n############################\n\nSpecifications\n**************\nSee :ref:`link_sparse_hessian-name` .\n\nImplementation\n**************\n\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <cppad/utility/vector.hpp>\n# include <cppad/speed/uniform_01.hpp>\n# include <cppad/speed/sparse_hes_fun.hpp>\n\n// Note that CppAD uses global_option[\"memory\"] at the main program level\n# include <map>\nextern std::map<std::string, bool> global_option;\n\nbool link_sparse_hessian(\n    size_t                           size     ,\n    size_t                           repeat   ,\n    const CppAD::vector<size_t>&     row      ,\n    const CppAD::vector<size_t>&     col      ,\n    CppAD::vector<double>&           x        ,\n    CppAD::vector<double>&           hessian  ,\n    size_t&                          n_color  )\n{\n    if(global_option[\"onetape\"]||global_option[\"atomic\"]||global_option[\"optimize\"]||global_option[\"boolsparsity\"])\n        return false;\n    // -----------------------------------------------------\n    // setup\n    using CppAD::vector;\n    size_t order = 0;          // derivative order corresponding to function\n    size_t n     = size;       // argument space dimension\n    size_t m     = 1;          // range space dimension\n    vector<double> y(m);       // function value\n\n    // choose a value for x\n    CppAD::uniform_01(n, x);\n\n    // ------------------------------------------------------\n\n    while(repeat--)\n    {\n        // computation of the function\n        CppAD::sparse_hes_fun<double>(n, x, row, col, order, y);\n    }\n    hessian[0] = y[0];\n\n    return true;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end double_sparse_hessian.cpp}\n*/\n"
  },
  {
    "path": "speed/double/sparse_jacobian.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin double_sparse_jacobian.cpp}\n\nDouble Speed: Sparse Jacobian\n#############################\n\nSpecifications\n**************\nSee :ref:`link_sparse_jacobian-name` .\n\nImplementation\n**************\n\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <cppad/utility/vector.hpp>\n# include <cppad/speed/uniform_01.hpp>\n# include <cppad/speed/sparse_jac_fun.hpp>\n\n// Note that CppAD uses global_option[\"memory\"] at the main program level\n# include <map>\nextern std::map<std::string, bool> global_option;\n\nbool link_sparse_jacobian(\n    const std::string&               job      ,\n    size_t                           size     ,\n    size_t                           repeat   ,\n    size_t                           m        ,\n    const CppAD::vector<size_t>&     row      ,\n    const CppAD::vector<size_t>&     col      ,\n             CppAD::vector<double>&     x        ,\n             CppAD::vector<double>&     jacobian ,\n             size_t&                    n_color  )\n{\n    if(global_option[\"onetape\"]||global_option[\"atomic\"]||global_option[\"optimize\"]||global_option[\"boolsparsity\"])\n        return false;\n    // -----------------------------------------------------\n    // setup\n    using CppAD::vector;\n    size_t i;\n    size_t order = 0;          // order for computing function value\n    size_t n     = size;       // argument space dimension\n    vector<double> yp(m);      // function value yp = f(x)\n\n    // ------------------------------------------------------\n    while(repeat--)\n    {  // choose a value for x\n        CppAD::uniform_01(n, x);\n\n        // computation of the function\n        CppAD::sparse_jac_fun<double>(m, n, x, row, col, order, yp);\n    }\n    for(i = 0; i < m; i++)\n        jacobian[i] = yp[i];\n\n    return true;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end double_sparse_jacobian.cpp}\n*/\n"
  },
  {
    "path": "speed/double/speed_double.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin speed_double}\n\nSpeed Test of Functions in Double\n#################################\n\nPurpose\n*******\nCppAD has a set of speed tests for just calculating functions\n(in double precision instead of an AD type).\nThis section links to the source code the function value speed tests.\n\nRunning Tests\n*************\nTo build these speed tests, and run their correctness tests,\nexecute the following commands starting in the\n:ref:`cmake@Build Directory` :\n\n| |tab| ``cd speed/double``\n| |tab| ``make check_speed_double VERBOSE`` =1\n\nYou can then run the corresponding speed tests\nwith the following command\n\n    ./ ``speed_double speed`` *seed*\n\nwhere *seed* is a positive integer.\nSee :ref:`speed_main-name` for more options.\n\nContents\n********\n{xrst_toc_list\n    speed/double/det_minor.cpp\n    speed/double/det_lu.cpp\n    speed/double/mat_mul.cpp\n    speed/double/ode.cpp\n    speed/double/poly.cpp\n    speed/double/sparse_hessian.cpp\n    speed/double/sparse_jacobian.cpp\n}\n\n{xrst_end speed_double}\n"
  },
  {
    "path": "speed/example/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# Build the speed/cppad directory tests\n# Inherit build type from ../CMakeList.txt\n#\n# source_list\nSET(source_list example.cpp\n    det_by_lu.cpp\n    det_by_minor.cpp\n    det_of_minor.cpp\n    elapsed_seconds.cpp\n    mat_sum_sq.cpp\n    ode_evaluate.cpp\n    sparse_hes_fun.cpp\n    sparse_jac_fun.cpp\n    speed_test.cpp\n    time_test.cpp\n)\nset_compile_flags( speed_example \"${cppad_debug_which}\" \"${source_list}\" )\n#\n# speed_example\nADD_EXECUTABLE( speed_example EXCLUDE_FROM_ALL ${source_list} )\nTARGET_LINK_LIBRARIES(speed_example\n    ${cppad_lib}\n    ${colpack_libs}\n)\n# check_speed_example\nadd_check_executable(check_speed example)\n#\n# seed_program\nset_compile_flags( speed_program \"${cppad_debug_which}\" speed_program.cpp )\nADD_EXECUTABLE( speed_program EXCLUDE_FROM_ALL speed_program.cpp )\nTARGET_LINK_LIBRARIES(speed_program\n    ${cppad_lib}\n    ${colpack_libs}\n)\n# check_speed_program\nadd_check_executable(check_speed program)\n"
  },
  {
    "path": "speed/example/det_by_lu.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin det_by_lu.cpp}\n\nDeterminant Using Lu Factorization: Example and Test\n####################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end det_by_lu.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n# include <cppad/speed/det_by_lu.hpp>\n\nbool det_by_lu()\n{   bool ok = true;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // dimension of the matrix\n    size_t n = 3;\n\n    // construct the determinat object\n    CppAD::det_by_lu<double> Det(n);\n\n    double  a[] = {\n        1., 2., 3.,  // a[0] a[1] a[2]\n        3., 2., 1.,  // a[3] a[4] a[5]\n        2., 1., 2.   // a[6] a[7] a[8]\n    };\n    CPPAD_TESTVECTOR(double) A(9);\n    size_t i;\n    for(i = 0; i < 9; i++)\n        A[i] = a[i];\n\n\n    // evaluate the determinant\n    double det = Det(A);\n\n    double check;\n    check = a[0]*(a[4]*a[8] - a[5]*a[7])\n             - a[1]*(a[3]*a[8] - a[5]*a[6])\n             + a[2]*(a[3]*a[7] - a[4]*a[6]);\n\n    ok = CppAD::NearEqual(det, check, eps99, eps99);\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "speed/example/det_by_minor.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin det_by_minor.cpp}\n\nDeterminant Using Expansion by Minors: Example and Test\n#######################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end det_by_minor.cpp}\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n# include <cppad/speed/det_by_minor.hpp>\n\nbool det_by_minor()\n{   bool ok = true;\n\n    // dimension of the matrix\n    size_t n = 3;\n\n    // construct the determinat object\n    CppAD::det_by_minor<double> Det(n);\n\n    double  a[] = {\n        1., 2., 3.,  // a[0] a[1] a[2]\n        3., 2., 1.,  // a[3] a[4] a[5]\n        2., 1., 2.   // a[6] a[7] a[8]\n    };\n    CPPAD_TESTVECTOR(double) A(9);\n    size_t i;\n    for(i = 0; i < 9; i++)\n        A[i] = a[i];\n\n\n    // evaluate the determinant\n    double det = Det(A);\n\n    double check;\n    check = a[0]*(a[4]*a[8] - a[5]*a[7])\n             - a[1]*(a[3]*a[8] - a[5]*a[6])\n             + a[2]*(a[3]*a[7] - a[4]*a[6]);\n\n    ok = det == check;\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "speed/example/det_of_minor.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-23 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin det_of_minor.cpp}\n\nDeterminant of a Minor: Example and Test\n########################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end det_of_minor.cpp}\n*/\n// BEGIN C++\n# include <vector>\n# include <cstddef>\n# include <cppad/speed/det_of_minor.hpp>\n\nbool det_of_minor()\n{   bool   ok = true;\n    //\n    // a\n    // values in the matrix A in row major order\n    std::vector<double> a = {\n        1., 2., 3.,\n        4., 5., 6.,\n        7., 8., 10.\n    };\n    //\n    // m\n    // dimension of the matrix A\n    size_t m = 3;\n    assert( m * m == a.size() );\n    //\n    // r, c\n    // index vectors set so minor is the entire matrix A\n    std::vector<size_t> r(m + 1);\n    std::vector<size_t> c(m + 1);\n    for(size_t i= 0; i < m; i++)\n    {   r[i] = i+1;\n        c[i] = i+1;\n    }\n    r[m] = 0;\n    c[m] = 0;\n    //\n    // n\n    // size of minor that is the entire matrix A\n    size_t n = m;\n    //\n    // det\n    // evaluate the determinant of A\n    double det = CppAD::det_of_minor(a, m, n, r, c);\n    //\n    // ok\n    // check the value of the determinant of A\n    ok &= (det == (double) (1*(5*10-6*8) - 2*(4*10-6*7) + 3*(4*8-5*7)) );\n    //\n    // M\n    // minor where row 0 and column 1 are removed\n    r[m] = 1;     // skip row index 0 by starting at row index 1\n    c[0] = 2;     // skip column index 1 by pointing from index 0 to index 2\n    n    = m - 1; // dimension of the minor M\n    //\n    // det\n    // evaluate determinant of the minor\n    det = CppAD::det_of_minor(a, m, m-1, r, c);\n    //\n    // ok\n    // check the value of the determinant of the minor\n    ok &= (det == (double) (4*10-6*7) );\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "speed/example/elapsed_seconds.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin elapsed_seconds.cpp}\n\nElapsed Seconds: Example and Test\n#################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end elapsed_seconds.cpp}\n*/\n// BEGIN C++\n# include <cppad/utility/elapsed_seconds.hpp>\n\n# include <iostream>\n# include <algorithm>\n# include <cmath>\n\n# define CPPAD_DEBUG_ELAPSED_SECONDS 0\n\nbool elapsed_seconds(void)\n{   bool ok = true;\n\n    double max_diff = 0.;\n    double s0 = CppAD::elapsed_seconds();\n    double s1 = CppAD::elapsed_seconds();\n    double s2 = CppAD::elapsed_seconds();\n    while(s2 - s0 < 1.)\n    {   max_diff = std::max(s2 - s1, max_diff);\n        s1 = s2;\n        s2 = CppAD::elapsed_seconds();\n\n    }\n# if CPPAD_DEBUG_ELAPSED_SECONDS\n    std::cout << \"max_diff = \" << max_diff << std::endl;\n# endif\n    ok &= 0. < max_diff && max_diff < .04;\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "speed/example/example.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin speed_example.cpp}\n\nSpeed Examples and Tests Driver\n###############################\n\nRunning These Tests\n*******************\nAfter executing the :ref:`cmake-name` command\nform the :ref:`download@Distribution Directory`,\nyou can build and run these tests with the commands::\n\n    cd build\n    make check_speed_example\n\nNote that your choice of :ref:`cmake@generator` may require using\nan different version of make; e.g., ``ninja`` .\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end speed_example.cpp}\n-------------------------------------------------------------------------------\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n\n// various example routines\nextern bool det_of_minor(void);\nextern bool det_by_lu(void);\nextern bool det_by_minor(void);\nextern bool elapsed_seconds(void);\nextern bool mat_sum_sq(void);\nextern bool ode_evaluate(void);\nextern bool sparse_hes_fun(void);\nextern bool sparse_jac_fun(void);\nextern bool speed_test(void);\nextern bool time_test(void);\n\nnamespace {\n    // function that runs one test\n    size_t Run_ok_count    = 0;\n    size_t Run_error_count = 0;\n    const char* exception_list[] = {\n        \"elapsed_seconds\",\n        \"speed_test\",\n        \"time_test\"\n    };\n    size_t n_exception = sizeof(exception_list) / sizeof(exception_list[0]);\n    bool Run(bool TestOk(void), std::string name)\n    {   bool ok               = true;\n        std::streamsize width =  20;\n        std::cout.width( width );\n        std::cout.setf( std::ios_base::left );\n        std::cout << name;\n        bool exception = false;\n        for(size_t i = 0; i < n_exception; i++)\n            exception |= exception_list[i] == name;\n        //\n        ok &= name.size() < size_t(width);\n        ok &= TestOk();\n        if( ok )\n        {   std::cout << \"OK\" << std::endl;\n            Run_ok_count++;\n        }\n        else if ( exception )\n        {   std::cout << \"Error: perhaps too many other programs running\";\n            std::cout << std::endl;\n            // no change to Run_ok_count\n            ok = true;\n        }\n        else\n        {   std::cout << \"Error\" << std::endl;\n            Run_error_count++;\n        }\n        return ok;\n    }\n}\n\n// main program that runs all the tests\nint main(void)\n{   bool ok = true;\n    using std::cout;\n    using std::endl;\n\n    // This line used by test_one.sh\n\n    ok &= Run(det_of_minor,          \"det_of_minor\"   );\n    ok &= Run(det_by_minor,         \"det_by_minor\"    );\n    ok &= Run(det_by_lu,               \"det_by_lu\"    );\n    ok &= Run(elapsed_seconds,   \"elapsed_seconds\"    );\n    ok &= Run(mat_sum_sq,             \"mat_sum_sq\"    );\n    ok &= Run(ode_evaluate,         \"ode_evaluate\"    );\n    ok &= Run(sparse_hes_fun,    \"sparse_hes_fun\"     );\n    ok &= Run(sparse_jac_fun,    \"sparse_jac_fun\"     );\n    ok &= Run(speed_test,             \"speed_test\"    );\n    ok &= Run(time_test,               \"time_test\"    );\n    assert( ok || (Run_error_count > 0) );\n\n    // check for memory leak in previous calculations\n    if( ! CppAD::thread_alloc::free_all() )\n    {   ok = false;\n        cout << \"Error: memory leak detected\" << endl;\n    }\n\n    if( ok )\n    {   cout << \"Check above to see if all \" << int(Run_ok_count)\n        << \" tests passed.\\n\";\n        cout << \"possible exceptions are: \" << exception_list[0];\n        for(size_t i = 1; i < n_exception; ++i)\n            cout << \", \" << exception_list[i];\n        cout << endl;\n    }\n    else\n        cout << int(Run_error_count) << \" tests failed.\";\n    cout << endl;\n\n    if(ok)\n        return EXIT_SUCCESS;\n    else\n        return EXIT_FAILURE;\n}\n\n// END C++\n"
  },
  {
    "path": "speed/example/mat_sum_sq.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n{xrst_begin mat_sum_sq.cpp}\n\nSum of the Elements of the Square of a Matrix: Example and Test\n###############################################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end mat_sum_sq.cpp}\n*/\n// BEGIN C++\n# include <vector>\n# include <cstddef>\n# include <cppad/utility/vector.hpp>\n# include <cppad/speed/mat_sum_sq.hpp>\n\nbool mat_sum_sq()\n{   bool   ok = true;\n    double x_00, x_01, x_10, x_11, check;\n\n    // dimension of the matrices x, y, and the result z\n    size_t n = 2;\n    CppAD::vector<double> x(n * n), y(n * n), z(1);\n\n    // x = [ 1 2 ; 3 4 ]\n    x[0] = x_00 = 1.;\n    x[1] = x_01 = 2.;\n    x[2] = x_10 = 3.;\n    x[3] = x_11 = 4.;\n\n    // compute y = x * x and z = sum of elements in y\n    CppAD::mat_sum_sq(n, x, y, z);\n\n    // check y_00\n    check = x_00 * x_00 + x_01 * x_10;\n    ok   &= (check == y[0]);\n\n    // check y_01\n    check = x_00 * x_01 + x_01 * x_11;\n    ok   &= (check == y[1]);\n\n    // check y_10\n    check = x_10 * x_00 + x_11 * x_10;\n    ok   &= (check == y[2]);\n\n    // check y_11\n    check = x_10 * x_01 + x_11 * x_11;\n    ok   &= (check == y[3]);\n\n    // check z\n    check = y[0] + y[1] + y[2] + y[3];\n    ok   &= (check == z[0]);\n\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "speed/example/ode_evaluate.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin ode_evaluate.cpp}\n\node_evaluate: Example and test\n##############################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end ode_evaluate.cpp}\n*/\n// BEGIN C++\n# include <cppad/speed/ode_evaluate.hpp>\n# include <cppad/speed/uniform_01.hpp>\n# include <cppad/cppad.hpp>\n\nbool ode_evaluate(void)\n{   using CppAD::NearEqual;\n    using CppAD::AD;\n\n    bool ok = true;\n\n    size_t n = 3;\n    CppAD::vector<double>       x(n);\n    CppAD::vector<double>       ym(n * n);\n    CppAD::vector< AD<double> > X(n);\n    CppAD::vector< AD<double> > Ym(n);\n\n    // choose x\n    size_t j;\n    for(j = 0; j < n; j++)\n    {   x[j] = double(j + 1);\n        X[j] = x[j];\n    }\n\n    // declare independent variables\n    Independent(X);\n\n    // evaluate function\n    size_t m = 0;\n    CppAD::ode_evaluate(X, m, Ym);\n\n    // evaluate derivative\n    m = 1;\n    CppAD::ode_evaluate(x, m, ym);\n\n    // use AD to evaluate derivative\n    CppAD::ADFun<double>   F(X, Ym);\n    CppAD::vector<double>  dy(n * n);\n    dy = F.Jacobian(x);\n\n    size_t k;\n    for(k = 0; k < n * n; k++)\n        ok &= NearEqual(ym[k], dy[k] , 1e-7, 1e-7);\n\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "speed/example/sparse_hes_fun.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin sparse_hes_fun.cpp}\n\nsparse_hes_fun: Example and test\n################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end sparse_hes_fun.cpp}\n*/\n// BEGIN C++\n# include <cppad/speed/sparse_hes_fun.hpp>\n# include <cppad/speed/uniform_01.hpp>\n# include <cppad/cppad.hpp>\n\nbool sparse_hes_fun(void)\n{   using CppAD::NearEqual;\n    bool ok = true;\n\n    typedef CppAD::AD<double> ADScalar;\n\n    size_t j, k;\n    double eps = 10. * CppAD::numeric_limits<double>::epsilon();\n    size_t n   = 5;\n    size_t m   = 1;\n    size_t K   = 2 * n;\n    CppAD::vector<size_t>       row(K),  col(K);\n    CppAD::vector<double>       x(n),    ypp(K);\n    CppAD::vector<ADScalar>     a_x(n),  a_y(m);\n\n    // choose x\n    for(j = 0; j < n; j++)\n        a_x[j] = x[j] = double(j + 1);\n\n    // choose row, col\n    for(k = 0; k < K; k++)\n    {   row[k] = k % 3;\n        col[k] = k / 3;\n    }\n    for(k = 0; k < K; k++)\n    {   for(size_t k1 = 0; k1 < K; k1++)\n            assert( k == k1 || row[k] != row[k1] || col[k] != col[k1] );\n    }\n\n    // declare independent variables\n    Independent(a_x);\n\n    // evaluate function\n    size_t order = 0;\n    CppAD::sparse_hes_fun<ADScalar>(n, a_x, row, col, order, a_y);\n\n    // evaluate Hessian\n    order = 2;\n    CppAD::sparse_hes_fun<double>(n, x, row, col, order, ypp);\n\n    // use AD to evaluate Hessian\n    CppAD::ADFun<double>   f(a_x, a_y);\n    CppAD::vector<double>  hes(n * n);\n    // compoute Hessian of f_0 (x)\n    hes = f.Hessian(x, 0);\n\n    for(k = 0; k < K; k++)\n    {   size_t index = row[k] * n + col[k];\n        ok &= NearEqual(hes[index], ypp[k] , eps, eps);\n    }\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "speed/example/sparse_jac_fun.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin sparse_jac_fun.cpp}\n\nsparse_jac_fun: Example and test\n################################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end sparse_jac_fun.cpp}\n*/\n// BEGIN C++\n# include <cppad/speed/sparse_jac_fun.hpp>\n# include <cppad/speed/uniform_01.hpp>\n# include <cppad/cppad.hpp>\n\nbool sparse_jac_fun(void)\n{   using CppAD::NearEqual;\n    using CppAD::AD;\n\n    bool ok = true;\n\n    size_t j, k;\n    double eps = CppAD::numeric_limits<double>::epsilon();\n    size_t n   = 3;\n    size_t m   = 4;\n    size_t K   = 5;\n    CppAD::vector<size_t>       row(K), col(K);\n    CppAD::vector<double>       x(n),   yp(K);\n    CppAD::vector< AD<double> > a_x(n), a_y(m);\n\n    // choose x\n    for(j = 0; j < n; j++)\n        a_x[j] = x[j] = double(j + 1);\n\n    // choose row, col\n    for(k = 0; k < K; k++)\n    {   row[k] = k % m;\n        col[k] = (K - k) % n;\n    }\n\n    // declare independent variables\n    Independent(a_x);\n\n    // evaluate function\n    size_t order = 0;\n    CppAD::sparse_jac_fun< AD<double> >(m, n, a_x, row, col, order, a_y);\n\n    // evaluate derivative\n    order = 1;\n    CppAD::sparse_jac_fun<double>(m, n, x, row, col, order, yp);\n\n    // use AD to evaluate derivative\n    CppAD::ADFun<double>   f(a_x, a_y);\n    CppAD::vector<double>  jac(m * n);\n    jac = f.Jacobian(x);\n\n    for(k = 0; k < K; k++)\n    {   size_t index = row[k] * n + col[k];\n        ok &= NearEqual(jac[index], yp[k] , eps, eps);\n    }\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "speed/example/speed_program.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin speed_program.cpp}\n\nExample Use of SpeedTest\n########################\n\nProgram\n*******\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <cppad/utility/speed_test.hpp>\n\n// Some compilers have gotten smarter and do not calculate something that is not used\n// so make the result a global.\ndouble global_result = 0.0;\n\nstd::string Test(size_t size, size_t repeat)\n{  // setup\n    double *a = new double[size];\n    double *b = new double[size];\n    size_t i  = size;;\n    while(i)\n    {  --i;\n        a[i] = double(i);\n        b[i] = double(2 * i);\n    }\n    // operations we are timing\n    while(repeat--)\n    {  i = size;;\n        while(i)\n        {  --i;\n            global_result += a[i] * b[i];\n        }\n    }\n    // teardown\n    delete [] a;\n    delete [] b;\n\n    // return a test name that is valid for all sizes and repeats\n    return \"double: result = sum_i a[i] * b[i]\";\n}\nint main(void)\n{\n    CppAD::SpeedTest(Test, 20, 20, 100);\n    return 0;\n}\n\n/* {xrst_code}\n{xrst_spell_on}\n\nOutput\n******\nExecuting of the program above generated the following output\n(the rates will be different for each particular system):\n::\n\n    double: c[*] = a[*] + b[*]\n    size = 20  rate = 7,157,515\n    size = 40  rate = 3,887,214\n    size = 60  rate = 2,685,214\n    size = 80  rate = 2,032,124\n    size = 100 rate = 1,657,828\n\n{xrst_end speed_program.cpp}\n*/\n"
  },
  {
    "path": "speed/example/speed_test.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin speed_test.cpp}\n\nspeed_test: Example and test\n############################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end speed_test.cpp}\n*/\n// BEGIN C++\n# include <cppad/utility/speed_test.hpp>\n# include <cppad/utility/vector.hpp>\n\nnamespace { // empty namespace\n    using CppAD::vector;\n    vector<double> a, b, c;\n    void test(size_t size, size_t repeat)\n    {   // setup\n        a.resize(size);\n        b.resize(size);\n        c.resize(size);\n        size_t i  = size;;\n        while(i)\n        {   --i;\n            a[i] = double(i);\n            b[i] = double(2 * i);\n            c[i] = 0.0;\n        }\n        // operations we are timing\n        while(repeat--)\n        {   i = size;;\n            while(i)\n            {   --i;\n                c[i] += std::sqrt(a[i] * a[i] + b[i] * b[i]);\n            }\n        }\n    }\n}\nbool speed_test(void)\n{   bool ok = true;\n\n    // size of the test cases\n    vector<size_t> size_vec(2);\n    size_vec[0] = 40;\n    size_vec[1] = 80;\n\n    // minimum amount of time to run test\n    double time_min = 0.5;\n\n    // run the test cases\n    vector<size_t> rate_vec(2);\n    rate_vec = CppAD::speed_test(test, size_vec, time_min);\n\n    // time per repeat loop (note counting setup or teardown)\n    double time_0 = 1. / double(rate_vec[0]);\n    double time_1 = 1. / double(rate_vec[1]);\n\n    // for this case, time should be linear w.r.t size\n    double check    = double(size_vec[1]) * time_0 / double(size_vec[0]);\n    double rel_diff = (check - time_1) / time_1;\n    ok             &= (std::fabs(rel_diff) <= .1);\n    if( ! ok )\n        std::cout << std::endl << \"rel_diff = \" << rel_diff << std::endl;\n\n    a.clear();\n    b.clear();\n    c.clear();\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "speed/example/time_test.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin time_test.cpp}\n\ntime_test: Example and test\n###########################\n\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n{xrst_end time_test.cpp}\n*/\n// BEGIN C++\n# include <cppad/utility/time_test.hpp>\n# include <cppad/utility/vector.hpp>\n\nnamespace { // empty namespace\n    using CppAD::vector;\n\n    // used to check size\n    size_t size_;\n\n    // used to check repeat\n    size_t repeat_;\n\n    vector<double> a, b, c;\n    void test(size_t size, size_t repeat)\n    {   // used for check\n        size_   = size;\n        repeat_ = repeat;\n\n        // setup\n        a.resize(size);\n        b.resize(size);\n        c.resize(size);\n        size_t i  = size;;\n        while(i)\n        {   --i;\n            a[i] = float(i);\n            b[i] = float(2 * i);\n            c[i] = 0.0;\n        }\n        // operations we are timing\n        while(repeat--)\n        {   i = size;;\n            while(i)\n            {   --i;\n                c[i] += std::sqrt(a[i] * a[i] + b[i] * b[i]);\n            }\n        }\n    }\n\n}\nbool time_test(void)\n{   bool ok = true;\n    using CppAD::time_test;\n\n    // minimum amount of time to run test\n    double time_min = 0.5;\n\n    // size of first test case\n    size_t test_size = 20;\n\n    // run the first test case\n    size_t repeat_first;\n    double time_first = time_test(test, time_min, test_size, repeat_first);\n    ok &= size_   == test_size;\n    ok &= repeat_ == repeat_first;\n    ok &= time_min <= double(repeat_first)  * time_first;\n\n    // size of second test case is twice as large\n    test_size = 2 * test_size;\n\n    // run the second test case\n    size_t repeat_second;\n    double time_second = time_test(test, time_min, test_size, repeat_second);\n    ok &= size_   == test_size;\n    ok &= repeat_ == repeat_second;\n    ok &= time_min <= double(repeat_second) * time_second;\n\n    // test above should hold without exception, one below might not\n    assert( ok );\n\n    // for this case, time should be linear w.r.t size\n    double rel_diff = 1. - 2. * time_first / time_second;\n    ok             &= (std::fabs(rel_diff) <= .1);\n    if( ! ok )\n        std::cout << std::endl << \"rel_diff = \" << rel_diff  << std::endl;\n\n    a.clear();\n    b.clear();\n    c.clear();\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "speed/fadbad/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# Build the speed/fadbad directory tests\n# Inherit build type from ../CMakeList.txt\n\n# assert fadbad_prefix is defined\nassert ( fadbad_prefix )\n\n# Adds flags to the compiler command line for sources in the current directory\n# and below. This command can be used to add any flags, but it was originally\n# intended to add preprocessor definitions.\nADD_DEFINITIONS(\"-DCPPAD_FADBAD_SPEED\")\n\n# Local include directories to search (not in package_prefix/includdir)\nINCLUDE_DIRECTORIES( ${CMAKE_CURRENT_SOURCE_DIR}/../src )\n\n# add_executable(<name> [WIN32] [MACOSX_BUNDLE] [EXCLUDE_FROM_ALL]\n#                 source1 source2 ... sourceN\n# )\nSET(source_list ../main.cpp\n    det_lu.cpp\n    det_minor.cpp\n    mat_mul.cpp\n    ode.cpp\n    poly.cpp\n    sparse_hessian.cpp\n    sparse_jacobian.cpp\n)\nset_compile_flags( speed_fadbad \"${cppad_debug_which}\" \"${source_list}\" )\n#\nADD_EXECUTABLE( speed_fadbad EXCLUDE_FROM_ALL ${source_list} )\n#\n# List of libraries to be linked into the specified target\nTARGET_LINK_LIBRARIES(speed_fadbad\n    ${cppad_lib}\n    ${colpack_libs}\n)\n# fadbad is an include file only library\nTARGET_LINK_LIBRARIES(speed_fadbad speed_src )\n\n# check_speed_fadbad\nadd_check_executable(check_speed fadbad \"correct 54321\")\n"
  },
  {
    "path": "speed/fadbad/det_lu.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin fadbad_det_lu.cpp}\n\nFadbad Speed: Gradient of Determinant Using Lu Factorization\n############################################################\n\nSpecifications\n**************\nSee :ref:`link_det_lu-name` .\n\nImplementation\n**************\n{xrst_spell_off}\n{xrst_code cpp} */\n// suppress conversion warnings before other includes\n# include <cppad/wno_conversion.hpp>\n//\n# include <FADBAD++/badiff.h>\n# include <cppad/speed/det_by_lu.hpp>\n# include <cppad/speed/uniform_01.hpp>\n# include <cppad/utility/vector.hpp>\n\n// list of possible options\n# include <map>\nextern std::map<std::string, bool> global_option;\n\nbool link_det_lu(\n    size_t                     size     ,\n    size_t                     repeat   ,\n    CppAD::vector<double>     &matrix   ,\n    CppAD::vector<double>     &gradient )\n{\n    // speed test global option values\n    if( global_option[\"onetape\"] || global_option[\"atomic\"] )\n        return false;\n    if( global_option[\"memory\"] || global_option[\"optimize\"] )\n        return false;\n    // -----------------------------------------------------\n    // setup\n    //\n    // object for computing determinant\n    typedef fadbad::B<double>       ADScalar;\n    typedef CppAD::vector<ADScalar> ADVector;\n    CppAD::det_by_lu<ADScalar>      Det(size);\n\n    size_t i;                // temporary index\n    size_t m = 1;            // number of dependent variables\n    size_t n = size * size;  // number of independent variables\n    ADScalar   detA;         // AD value of the determinant\n    ADVector   A(n);         // AD version of matrix\n\n    // ------------------------------------------------------\n    while(repeat--)\n    {  // get the next matrix\n        CppAD::uniform_01(n, matrix);\n\n        // set independent variable values\n        for(i = 0; i < n; i++)\n            A[i] = matrix[i];\n\n        // compute the determinant\n        detA = Det(A);\n\n        // create function object f : A -> detA\n        detA.diff(0, (unsigned int) m);  // index 0 of m dependent variables\n\n        // evaluate and return gradient using reverse mode\n        for(i =0; i < n; i++)\n            gradient[i] = A[i].d(0); // partial detA w.r.t A[i]\n    }\n    // ---------------------------------------------------------\n    return true;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end fadbad_det_lu.cpp}\n*/\n"
  },
  {
    "path": "speed/fadbad/det_minor.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin fadbad_det_minor.cpp}\n\nFadbad Speed: Gradient of Determinant by Minor Expansion\n########################################################\n\nSpecifications\n**************\nSee :ref:`link_det_minor-name` .\n\nImplementation\n**************\n\n{xrst_spell_off}\n{xrst_code cpp} */\n// suppress conversion warnings before other includes\n# include <cppad/wno_conversion.hpp>\n//\n# include <FADBAD++/badiff.h>\n# include <cppad/speed/det_by_minor.hpp>\n# include <cppad/speed/uniform_01.hpp>\n# include <cppad/utility/vector.hpp>\n\n// list of possible options\n# include <map>\nextern std::map<std::string, bool> global_option;\n\nbool link_det_minor(\n    const std::string&         job      ,\n    size_t                     size     ,\n    size_t                     repeat   ,\n    CppAD::vector<double>     &matrix   ,\n    CppAD::vector<double>     &gradient )\n{\n    // --------------------------------------------------------------------\n    // check not global options\n    typedef std::map<std::string, bool>::iterator iterator;\n    for(iterator itr=global_option.begin(); itr!=global_option.end(); ++itr)\n    {  if( itr->second )\n            return false;\n    }\n    // -----------------------------------------------------\n\n    // AD types\n    typedef fadbad::B<double>       b_double;\n    typedef CppAD::vector<b_double> b_vector;\n\n    // object that computes the determinant\n    CppAD::det_by_minor<b_double>   b_det(size);\n\n    // number of dependent variables\n    unsigned int m = 1;\n\n    // number of independent variables\n    size_t n = size * size;\n\n    // independent variable vector\n    b_vector   b_A(n);\n\n    // AD value of the determinant\n    b_double  b_detA;\n\n    // ------------------------------------------------------\n    while(repeat--)\n    {  // get the next matrix\n        CppAD::uniform_01(n, matrix);\n\n        // set independent variable values\n        for(size_t j = 0; j < n; j++)\n            b_A[j] = matrix[j];\n\n        // compute the determinant\n        b_detA = b_det(b_A);\n\n        // create function object f : A -> detA\n        b_detA.diff(0, m);  // index 0 of m dependent variables\n\n        // evaluate and return gradient using reverse mode\n        for(size_t j = 0; j < n; j++)\n            gradient[j] = b_A[j].d(0); // partial detA w.r.t A[i]\n    }\n    // ---------------------------------------------------------\n    return true;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end fadbad_det_minor.cpp}\n*/\n"
  },
  {
    "path": "speed/fadbad/mat_mul.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin fadbad_mat_mul.cpp}\n\nFadbad Speed: Matrix Multiplication\n###################################\n\nSpecifications\n**************\nSee :ref:`link_mat_mul-name` .\n\nImplementation\n**************\n\n{xrst_spell_off}\n{xrst_code cpp} */\n// suppress conversion warnings before other includes\n# include <cppad/wno_conversion.hpp>\n//\n# include <FADBAD++/badiff.h>\n# include <cppad/speed/mat_sum_sq.hpp>\n# include <cppad/speed/uniform_01.hpp>\n# include <cppad/utility/vector.hpp>\n\n// list of possible options\n# include <map>\nextern std::map<std::string, bool> global_option;\n\nbool link_mat_mul(\n    size_t                           size     ,\n    size_t                           repeat   ,\n    CppAD::vector<double>&           x        ,\n    CppAD::vector<double>&           z        ,\n    CppAD::vector<double>&           dz       )\n{\n    // speed test global option values\n    if( global_option[\"memory\"] || global_option[\"onetape\"] || global_option[\"atomic\"] || global_option[\"optimize\"] )\n        return false;\n    // The correctness check for this test is failing, so abort (for now).\n    return false;\n\n    // -----------------------------------------------------\n    // setup\n\n    // object for computing determinant\n    typedef fadbad::B<double>       ADScalar;\n    typedef CppAD::vector<ADScalar> ADVector;\n\n    size_t j;                // temporary index\n    size_t m = 1;            // number of dependent variables\n    size_t n = size * size;  // number of independent variables\n    ADVector   X(n);         // AD domain space vector\n    ADVector   Y(n);         // Store product matrix\n    ADVector   Z(m);         // AD range space vector\n\n    // ------------------------------------------------------\n    while(repeat--)\n    {  // get the next matrix\n        CppAD::uniform_01(n, x);\n\n        // set independent variable values\n        for(j = 0; j < n; j++)\n            X[j] = x[j];\n\n        // do the computation\n        mat_sum_sq(size, X, Y, Z);\n\n        // create function object f : X -> Z\n        Z[0].diff(0, m);  // index 0 of m dependent variables\n\n        // evaluate and return gradient using reverse mode\n        for(j = 0; j < n; j++)\n            dz[j] = X[j].d(0); // partial Z[0] w.r.t X[j]\n    }\n    // return function value\n    z[0] = Z[0].x();\n\n    // ---------------------------------------------------------\n    return true;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end fadbad_mat_mul.cpp}\n*/\n"
  },
  {
    "path": "speed/fadbad/ode.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin fadbad_ode.cpp}\n\nFadbad Speed: Ode\n#################\n\nSpecifications\n**************\nSee :ref:`link_ode-name` .\n\nImplementation\n**************\n\n{xrst_spell_off}\n{xrst_code cpp} */\n// suppress conversion warnings before other includes\n# include <cppad/wno_conversion.hpp>\n//\n# include <FADBAD++/fadiff.h>\n# include <algorithm>\n# include <cassert>\n# include <cppad/utility/vector.hpp>\n# include <cppad/speed/uniform_01.hpp>\n# include <cppad/speed/ode_evaluate.hpp>\n\n// list of possible options\n# include <map>\nextern std::map<std::string, bool> global_option;\n\nnamespace fadbad {\n    // define fabs for use by ode_evaluate\n    fadbad::F<double> fabs(const fadbad::F<double>& x)\n    {  return std::max(-x, x); }\n}\n\nbool link_ode(\n    size_t                     size       ,\n    size_t                     repeat     ,\n    CppAD::vector<double>      &x         ,\n    CppAD::vector<double>      &jacobian\n)\n{\n    // speed test global option values\n    if( global_option[\"atomic\"] )\n        return false;\n    if( global_option[\"memory\"] || global_option[\"onetape\"] || global_option[\"optimize\"] )\n        return false;\n    // -------------------------------------------------------------\n    // setup\n    assert( x.size() == size );\n    assert( jacobian.size() == size * size );\n\n    typedef fadbad::F<double>       ADScalar;\n    typedef CppAD::vector<ADScalar> ADVector;\n\n    size_t i, j;\n    size_t p = 0;          // use ode to calculate function values\n    size_t n = size;       // number of independent variables\n    size_t m = n;          // number of dependent variables\n    ADVector X(n), Y(m);   // independent and dependent variables\n\n    // -------------------------------------------------------------\n    while(repeat--)\n    {  // choose next x value\n        CppAD::uniform_01(n, x);\n        for(j = 0; j < n; j++)\n        {  // set value of x[j]\n            X[j] = x[j];\n            // set up for X as the independent variable vector\n            X[j].diff((unsigned int) j, (unsigned int) n);\n        }\n\n        // evaluate function\n        CppAD::ode_evaluate(X, p, Y);\n\n        // return values with Y as the dependent variable vector\n        for(i = 0; i < m; i++)\n        {  for(j = 0; j < n; j++)\n                jacobian[ i * n + j ] = Y[i].d((unsigned int) j);\n        }\n    }\n    return true;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end fadbad_ode.cpp}\n*/\n"
  },
  {
    "path": "speed/fadbad/poly.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin fadbad_poly.cpp}\n\nFadbad Speed: Second Derivative of a Polynomial\n###############################################\n\nSpecifications\n**************\nSee :ref:`link_poly-name` .\n\nImplementation\n**************\n\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <cppad/utility/vector.hpp>\n# include <cppad/utility/poly.hpp>\n# include <cppad/speed/uniform_01.hpp>\n# include <FADBAD++/tadiff.h>\n\n// list of possible options\n# include <map>\nextern std::map<std::string, bool> global_option;\n\nbool link_poly(\n    size_t                     size     ,\n    size_t                     repeat   ,\n    CppAD::vector<double>     &a        ,  // coefficients of polynomial\n    CppAD::vector<double>     &z        ,  // polynomial argument value\n    CppAD::vector<double>     &ddp      )  // second derivative w.r.t z\n{\n    if( global_option[\"atomic\"] )\n        return false;\n    if( global_option[\"memory\"] || global_option[\"onetape\"] || global_option[\"optimize\"] )\n        return false;\n    // -----------------------------------------------------\n    // setup\n    size_t i;             // temporary index\n    fadbad::T<double>  Z; // domain space AD value\n    fadbad::T<double>  P; // range space AD value\n\n    // choose the polynomial coefficients\n    CppAD::uniform_01(size, a);\n\n    // AD copy of the polynomial coefficients\n    CppAD::vector< fadbad::T<double> > A(size);\n    for(i = 0; i < size; i++)\n        A[i] = a[i];\n\n    // ------------------------------------------------------\n    while(repeat--)\n    {  // get the next argument value\n        CppAD::uniform_01(1, z);\n\n        // independent variable value\n        Z    = z[0]; // argument value\n        Z[1] = 1;    // argument first order Taylor coefficient\n\n        // AD computation of the dependent variable\n        P = CppAD::Poly(0, A, Z);\n\n        // Taylor-expand P to degree one\n        P.eval(2);\n\n        // second derivative is twice second order Taylor coefficient\n        ddp[0] = 2. * P[2];\n\n        // Free DAG corresponding to P does not seem to improve speed.\n        // Probably because it gets freed the next time P is assigned.\n        // P.reset();\n    }\n    // ------------------------------------------------------\n    return true;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end fadbad_poly.cpp}\n*/\n"
  },
  {
    "path": "speed/fadbad/sparse_hessian.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/utility/vector.hpp>\n\n/*\n{xrst_begin fadbad_sparse_hessian.cpp}\n\nFadbad Speed: Sparse Hessian\n############################\n\n{xrst_spell_off}\n{xrst_code cpp} */\n// A fadbad version of this test is not yet available\nbool link_sparse_hessian(\n    size_t                            size      ,\n    size_t                            repeat    ,\n    const CppAD::vector<size_t>&      row       ,\n    const CppAD::vector<size_t>&      col       ,\n    CppAD::vector<double>&            x         ,\n    CppAD::vector<double>&            hessian   ,\n    size_t&                           n_color\n)\n{\n    return false;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end fadbad_sparse_hessian.cpp}\n*/\n"
  },
  {
    "path": "speed/fadbad/sparse_jacobian.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cstring>\n# include <cppad/utility/vector.hpp>\n\n/*\n{xrst_begin fadbad_sparse_jacobian.cpp}\n\nFadbad Speed: sparse_jacobian\n#############################\n\n{xrst_spell_off}\n{xrst_code cpp} */\n// A fadbad version of this test is not yet available\nbool link_sparse_jacobian(\n    const std::string&               job      ,\n    size_t                           size     ,\n    size_t                           repeat   ,\n    size_t                           m        ,\n    const CppAD::vector<size_t>&     row      ,\n    const CppAD::vector<size_t>&     col      ,\n    CppAD::vector<double>&           x        ,\n    CppAD::vector<double>&           jacobian ,\n    size_t&                          n_color  )\n{\n    return false;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end fadbad_sparse_jacobian.cpp}\n*/\n"
  },
  {
    "path": "speed/fadbad/speed_fadbad.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin speed_fadbad}\n\nSpeed Test Derivatives Using Fadbad\n###################################\n\nPurpose\n*******\nCppAD has a set of speed tests that are used to compare\nFadbad with other AD packages.\nThis section links to the source code the Fadbad speed tests\n(any suggestions to make the Fadbad results faster are welcome).\n\nfadbad_prefix\n*************\nTo run these tests,\nyou must include the :ref:`fadbad_prefix-name`\nin you :ref:`cmake@CMake Command` .\n\nRunning Tests\n*************\nTo build these speed tests, and run their correctness tests,\nexecute the following commands starting in the\n:ref:`cmake@Build Directory` :\n\n| |tab| ``cd speed/fadbad``\n| |tab| ``make check_speed_fadbad VERBOSE`` =1\n\nYou can then run the corresponding speed tests\nwith the following command\n\n    ./ ``speed_fadbad speed`` *seed*\n\nwhere *seed* is a positive integer.\nSee :ref:`speed_main-name` for more options.\n\nContents\n********\n{xrst_toc_list\n    speed/fadbad/det_minor.cpp\n    speed/fadbad/det_lu.cpp\n    speed/fadbad/mat_mul.cpp\n    speed/fadbad/ode.cpp\n    speed/fadbad/poly.cpp\n    speed/fadbad/sparse_hessian.cpp\n    speed/fadbad/sparse_jacobian.cpp\n}\n\n{xrst_end speed_fadbad}\n"
  },
  {
    "path": "speed/main.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cstring>\n# include <cstdlib>\n# include <cassert>\n# include <cstddef>\n# include <iostream>\n# include <iomanip>\n# include <map>\n# include <cppad/utility/vector.hpp>\n# include <cppad/speed/det_grad_33.hpp>\n# include <cppad/speed/det_33.hpp>\n# include <cppad/speed/uniform_01.hpp>\n# include <cppad/utility/poly.hpp>\n# include <cppad/utility/track_new_del.hpp>\n# include <cppad/utility/thread_alloc.hpp>\n\n# ifdef CPPAD_ADOLC_SPEED\n# define AD_PACKAGE \"adolc\"\n# endif\n# ifdef CPPAD_CPPAD_SPEED\n# define AD_PACKAGE \"cppad\"\n# endif\n# ifdef CPPAD_DOUBLE_SPEED\n# define AD_PACKAGE \"double\"\n# endif\n# ifdef CPPAD_FADBAD_SPEED\n# define AD_PACKAGE \"fadbad\"\n# endif\n# ifdef CPPAD_PROFILE_SPEED\n# define AD_PACKAGE \"profile\"\n# endif\n# ifdef CPPAD_SACADO_SPEED\n# define AD_PACKAGE \"sacado\"\n# endif\n# ifdef CPPAD_CPPADCG_SPEED\n# define AD_PACKAGE \"cppadcg\"\n# endif\n# ifdef CPPAD_CPPAD_JIT_SPEED\n# define AD_PACKAGE \"cppad_jit\"\n# endif\n# ifdef CPPAD_XPACKAGE_SPEED\n# define AD_PACKAGE \"xpackage\"\n# endif\n\n/*\n{xrst_begin speed_main}\n{xrst_spell\n    boolsparsity\n    onetape\n    optionlist\n    retaped\n    revsparsity\n    subgraphs\n    subsparsity\n    underbar\n}\n\nRunning the Speed Test Program\n##############################\n\nSyntax\n******\n| ``speed/`` *package* / ``speed_`` *package* *test* *seed* *option_list*\n\nPurpose\n*******\nA version of this program runs the correctness tests\nor the speed tests for one AD package identified by *package* .\n\npackage\n*******\n\nAD Package\n==========\nThe command line argument\n*package* specifies one of the AD package.\nThe CppAD distribution comes with support for the following packages:\n:ref:`adolc<speed_adolc-name>` ,\n:ref:`cppad<speed_cppad-name>` ,\n:ref:`fadbad<speed_fadbad-name>` ,\n:ref:`sacado<speed_sacado-name>` ,\n:ref:`cppadcg<speed_cppadcg-name>` .\nYou can extend this program to include other package;\nsee :ref:`speed_xpackage-name` .\n\ndouble\n======\nThe value\n*package* can be ``double`` in which case\nthe function values (instead of derivatives) are computed\nusing double precision operations.\nThis enables one to compare the speed of computing function\nvalues in ``double`` to the speed of the derivative computations.\n(It is often useful to divide the speed of the derivative computation by\nthe speed of the function evaluation in ``double`` .)\n\nprofile\n=======\nIn the special case where *package* is ``profile`` ,\nthe CppAD package is compiled and run with profiling to aid in determining\nwhere it is spending most of its time.\n\ntest\n****\nThe argument *test* specifies which test to run\nand has the following possible values:\n:ref:`speed_main@test@correct` ,\n:ref:`speed_main@test@speed` ,\n:ref:`det_minor<link_det_minor-name>` ,\n:ref:`det_lu<link_det_lu-name>` ,\n:ref:`mat_mul<link_mat_mul-name>` ,\n:ref:`ode<link_ode-name>` ,\n:ref:`poly<link_poly-name>` ,\n:ref:`sparse_hessian<link_sparse_hessian-name>` ,\n:ref:`sparse_jacobian<link_sparse_jacobian-name>` .\nYou can experiment with changing the implementation of a\nparticular test for a particular package.\n\ncorrect\n=======\nIf *test* is equal to ``correct`` ,\nall of the correctness tests are run.\n\nspeed\n=====\nIf *test* is equal to ``speed`` ,\nall of the speed tests are run.\n\nseed\n****\nThe command line argument *seed* is an unsigned integer\n(all its characters are between 0 and 9).\nThe random number simulator :ref:`uniform_01-name` is initialized with\nthe call\n\n    ``uniform_01`` ( *seed* )\n\nbefore any of the testing routines (listed above) are called.\n\nGlobal Options\n**************\nThis global variable has prototype\n{xrst_spell_off}\n{xrst_code cpp}\n    extern std::map<std::string, bool> global_option;\n{xrst_code}\n{xrst_spell_on}\nThe syntax\n\n    ``global_option`` [\" *option* \"]\n\nhas the value true, if *option* is present,\nand false otherwise.\nThis is true for each option that follows *seed* .\nThe order of the options does not matter and the list can be empty.\nEach option, is be a separate command line argument to the main program.\nThe documentation below specifics how the\n:ref:`speed_cppad-name` program uses these options.\nIt is the intention that other packages use each option in a similar\nway or make it invalid.\nThe implementation of each test should check that the option\nsetting are valid for that test and if not it should return false;\nfor example, see the source code for :ref:`adolc_sparse_hessian.cpp-name` .\n\nonetape\n=======\nIf this option is present,\n:ref:`speed_cppad-name` will use one taping of the operation\nsequence for all the repetitions of that speed test.\nOtherwise, the\n:ref:`operation sequence<glossary@Operation@Sequence>`\nwill be retaped for each test repetition.\n\nAll of the tests, except :ref:`det_lu<link_det_lu-name>` ,\nhave the same operation sequence for each repetition.\nThe operation sequence for ``det_lu``\nmay be different because it depends on the matrix for which the determinant\nis being calculated.\nFor this reason, :ref:`cppad_det_lu.cpp-name` returns false,\nto indicate that the test not implemented,\nwhen ``global_onetape`` is true.\n\nmemory\n======\nThis option is special because individual CppAD speed tests need not do\nanything different if this option is true or false.\nIf the ``memory`` option is present, the CppAD\n:ref:`hold_memory<ta_hold_memory-name>` routine will be called by\nthe speed test main program before any of the tests are executed\nThis should make the CppAD ``thread_alloc`` allocator faster.\nIf it is not present, CppAD will used standard memory allocation.\nAnother package might use this option for a different\nmemory allocation method.\n\noptimize\n========\nIf this option is present,\nCppAD will :ref:`optimize-name`\nthe operation sequence before doing computations.\nIf it is false, this optimization will not be done.\nNote that this option is usually slower unless it is combined with the\n``onetape`` option.\n\nval_graph\n=========\nIf this option and optimize are present,\nCppAD will add the :code:`optimize@options@val_graph` option to\nthe optimization of the operation sequence.\n\natomic\n======\nIf this option is present,\nCppAD will use a user defined\n:ref:`atomic<atomic_two-name>` operation is used for the test.\nSo far, CppAD has only implemented\nthe :ref:`mat_mul<link_mat_mul-name>` test as an atomic operation.\n\nhes2jac\n=======\nIf this option is present,\n:ref:`speed_cppad-name` will compute hessians as the Jacobian\nof the gradient.\nThis is accomplished using\n:ref:`multiple levels<mul_level-name>` of AD.\nSo far, CppAD has only implemented\nthe :ref:`sparse_hessian<link_sparse_hessian-name>`\ntest in this manner.\n\nsubgraph\n========\nIf this option is present,\n:ref:`speed_cppad-name` will compute sparse Jacobians using subgraphs.\nThe CppAD :ref:`sparse_jacobian<link_sparse_jacobian-name>`\ntest is implemented for this option.\nIn addition, the CppAD :ref:`sparse_hessian<link_sparse_hessian-name>`\ntest is implemented for this option when ``hes2jac`` is present.\n\nSparsity Options\n****************\nThe following options only apply to the\n:ref:`sparse_jacobian<link_sparse_jacobian-name>` and\n:ref:`sparse_hessian<link_sparse_hessian-name>` tests.\nThe other tests return false when any of these options\nare present.\n\nboolsparsity\n============\nIf this option is present, CppAD will use a\n:ref:`vectors of bool<glossary@Sparsity Pattern@Boolean Vector>`\nto compute sparsity patterns.\nOtherwise CppAD will use\n:ref:`vectors of sets<glossary@Sparsity Pattern@Vector of Sets>` .\n\nrevsparsity\n===========\nIf this option is present,\nCppAD will use reverse mode for to compute sparsity patterns.\nOtherwise CppAD will use forward mode.\n\nsubsparsity\n===========\nIf this option is present,\nCppAD will use subgraphs to compute sparsity patterns.\nIf\n``boolsparsity`` , ``revsparsity`` , or ``colpack`` is also present,\nthe CppAD speed tests will return false; i.e., these options are not\nsupported by :ref:`subgraph_sparsity-name` .\n\ncolpack\n=======\nIf this option is present,\nCppAD will use :ref:`colpack<colpack_prefix-name>` to do the coloring.\nOtherwise, it will use it's own coloring algorithm.\n\nsymmetric\n=========\nIf this option is present, CppAD will use a symmetric\n:ref:`coloring method<sparse_hessian@work@color_method>`\nfor computing Hessian sparsity patterns.\nOtherwise, it will use a general coloring method.\nThe CppAD\n:ref:`sparse_hessian<link_sparse_hessian-name>` test\nis implemented for this option.\n\nCorrectness Results\n*******************\nOne, but not both, of the following two output lines\n\n| |tab| *package* _ *test* _ *optionlist* _ ``available`` = ``false``\n| |tab| *package* _ *test* _ *optionlist* _ ``ok`` = *flag*\n\nis generated for each correctness test where\n*package* and *test* are as above,\n*optionlist* are the options (in *option_list* )\nseparated by the underbar ``_`` character\n(whereas they are separated by spaces in *option_list* ),\nand *flag* is ``true`` or ``false`` .\n\nSpeed Results\n*************\nFor each speed test, corresponds to three lines of the\nfollowing form are generated:\n\n| |tab| *package* _ *test* _ *optionlist* _ ``ok`` = *flag*\n| |tab| *test* _ ``size`` = [ *size_1* , ..., *size_n*  ]\n| |tab| *package* _ *test* _ ``rate`` = [ *rate_1* , ..., *rate_n*  ]\n\nThe values *package* , *test* , *optionlist* ,\nand *flag* are as in the correctness results above.\nThe values *size_1* , ..., *size_n* are the\nsize arguments used for the corresponding tests.\nThe values *rate_1* , ..., *rate_n* are the number of times\nper second that the corresponding size problem executed.\n\nn_color\n=======\nThe :ref:`sparse_jacobian<link_sparse_jacobian-name>`\nand :ref:`sparse_hessian<link_sparse_hessian-name>` tests has an extra output\nline with the following form\n\n    *package* _ ``sparse_`` *test* _ ``n_color`` = [ *n_color_1* , ..., *n_color_n*  ]\n\nwere *test* is ``jacobian`` (``hessian`` ).\nThe values *n_color_1* , ..., *n_color_n* are the number of\ncolors used for each sparse Jacobian (Hessian) calculation; see\n*n_color* for\n:ref:`sparse_jac<sparse_jac@n_color>` and *n_sweep* for\n:ref:`sparse_hessian<sparse_hessian@n_sweep>` .\n{xrst_toc_hidden\n    speed/src/link.xrst\n}\nLink Routines\n*************\nEach :ref:`speed_main@package`\ndefines it's own version of one of the\n:ref:`link_routines-name` listed below.\nEach of these routines links this main program to the corresponding test:\n\n.. csv-table::\n    :widths: auto\n\n    link_det_lu,:ref:`link_det_lu-title`\n    link_det_minor,:ref:`link_det_minor-title`\n    link_mat_mul,:ref:`link_mat_mul-title`\n    link_ode,:ref:`link_ode-title`\n    link_poly,:ref:`link_poly-title`\n    link_sparse_hessian,:ref:`link_sparse_hessian-title`\n    link_sparse_jacobian,:ref:`link_sparse_jacobian-title`\n\n{xrst_end speed_main}\n-----------------------------------------------------------------------------\n*/\n// external routines\n\n# define CPPAD_DECLARE_TIME(name)                         \\\n    extern bool available_##name(void);                   \\\n    extern bool correct_##name(bool is_package_double);   \\\n    extern double time_##name(double time_min, size_t size)\n\nCPPAD_DECLARE_TIME(det_lu);\nCPPAD_DECLARE_TIME(det_minor);\nCPPAD_DECLARE_TIME(mat_mul);\nCPPAD_DECLARE_TIME(ode);\nCPPAD_DECLARE_TIME(poly);\nCPPAD_DECLARE_TIME(sparse_hessian);\nCPPAD_DECLARE_TIME(sparse_jacobian);\n//\n// some routines defined in src subdirectory\nextern void info_sparse_jacobian(\n    CppAD::vector<size_t>& size_vec    ,\n    CppAD::vector<size_t>& n_color_vec\n);\nextern void info_sparse_hessian(size_t size, size_t& n_color);\n//\n// --------------------------------------------------------------------------\nstd::map<std::string, bool> global_option;\n//\n// If return value for the previous CppAD speed test was false, this is zero.\n// Otherwise it is value returned by CppAD::thread_alloc::inuse for the\n// current thread at end of the test.\nsize_t global_cppad_thread_alloc_inuse = 0;\n//\n// This is the value of seed in the main program command line.\n// It can be used by the sparse matrix routines to reset the random generator\n// so same sparsity pattern is obtained during source generation and usage.\nsize_t global_seed= 0;\n//\n// --------------------------------------------------------------------------\nnamespace {\n    using std::cout;\n    using std::cerr;\n    using std::endl;\n    const char* option_list[] = {\n        \"memory\",\n        \"onetape\",\n        \"optimize\",\n        \"atomic\",\n        \"hes2jac\",\n        \"subgraph\",\n        \"boolsparsity\",\n        \"revsparsity\",\n        \"subsparsity\",\n        \"colpack\",\n        \"symmetric\",\n        \"val_graph\"\n    };\n    size_t num_option = sizeof(option_list) / sizeof( option_list[0] );\n    // ----------------------------------------------------------------\n    // not available test message\n    void not_available_message(const char* test_name)\n    {   cout << AD_PACKAGE << \": \" << test_name;\n        cout << \" is not available with \" << endl;\n        int max_len = 0;\n        for(size_t i = 0; i < num_option; i++)\n        {   int len = int( std::strlen( option_list[i] ) );\n            max_len = std::max( max_len, len);\n        }\n        for(size_t i = 0; i < num_option; i++)\n        {   std::string option = option_list[i];\n            if( global_option[option] )\n                cout << std::setw(max_len + 1) << option << \" = true\\n\";\n            else\n                cout << std::setw(max_len + 1) << option << \" = false\\n\";\n        }\n    }\n    // ------------------------------------------------------\n    // output vector in form readable by octave or matlab\n    // convert size_t to int to avoid warning by MS compiler\n    void output(const CppAD::vector<size_t> &v)\n    {   size_t i= 0, n = v.size();\n        cout << \"[ \";\n        while(i < n)\n        {   cout << int(v[i++]);\n            if( i < n )\n                cout << \", \";\n        }\n        cout << \" ]\";\n    }\n\n    // ----------------------------------------------------------------\n    // function that runs one correctness case\n    static size_t Run_ok_count    = 0;\n    static size_t Run_error_count = 0;\n    bool run_correct(\n        bool available_case(void) ,\n        bool correct_case(bool)   ,\n        const char *case_name     )\n    {   bool available = available_case();\n        bool ok        = true;\n        if( available )\n        {\n# ifdef CPPAD_DOUBLE_SPEED\n            bool is_package_double = true;\n# else\n            bool is_package_double = false;\n# endif\n            ok = correct_case(is_package_double);\n        }\n        cout << AD_PACKAGE << \"_\" << case_name;\n        for(size_t i = 0; i < num_option; i++)\n        {   std::string option = option_list[i];\n            if( global_option[option]  )\n                cout << \"_\" << option;\n        }\n        if( ! available )\n        {   cout << \"_available = false\" << endl;\n            return ok;\n        }\n        cout << \"_correct = \";\n        if( ok )\n        {   cout << \" true\" << endl;\n            Run_ok_count++;\n        }\n        else\n        {   cout << \" false\" << endl;\n            Run_error_count++;\n        }\n        return ok;\n    }\n    // ----------------------------------------------------------------\n    // function that runs one speed case\n    void run_speed(\n        double time_case(double time_min,  size_t size)  ,\n        const CppAD::vector<size_t>&        size_vec     ,\n        const std::string&                  case_name    )\n    {   double time_min = 1.;\n        cout << case_name << \"_size = \";\n        output(size_vec);\n        cout << endl;\n        cout << AD_PACKAGE << \"_\" << case_name << \"_rate = \";\n        cout << std::fixed;\n        for(size_t i = 0; i < size_vec.size(); i++)\n        {   if( i == 0 )\n                cout << \"[ \";\n            else\n                cout << \", \";\n            cout << std::flush;\n            size_t size = size_vec[i];\n            double time = time_case(time_min, size);\n            double rate = 1. / time;\n            if( rate >= 1000 )\n                cout << std::setprecision(0) << rate;\n            else if( rate >= 10 )\n                cout << std::setprecision(2) << rate;\n            else\n                cout << std::setprecision(4) << rate;\n        }\n        cout << \" ]\" << endl;\n        //\n        return;\n    }\n}\n\n// main program that runs all the tests\nint main(int argc, char *argv[])\n{   bool ok = true;\n    enum test_enum {\n        test_correct,\n        test_speed,\n        test_det_lu,\n        test_det_minor,\n        test_mat_mul,\n        test_ode,\n        test_poly,\n        test_sparse_hessian,\n        test_sparse_jacobian,\n        test_error\n    };\n    struct test_struct {\n        const char       *name;\n        const test_enum  index;\n    };\n    const test_struct test_list[]= {\n        { \"correct\",            test_correct         },\n        { \"speed\",              test_speed           },\n        { \"det_lu\",             test_det_lu          },\n        { \"det_minor\",          test_det_minor       },\n        { \"mat_mul\",            test_mat_mul         },\n        { \"ode\",                test_ode             },\n        { \"poly\",               test_poly            },\n        { \"sparse_hessian\",     test_sparse_hessian  },\n        { \"sparse_jacobian\",    test_sparse_jacobian }\n    };\n    const size_t n_test  = sizeof(test_list) / sizeof(test_list[0]);\n    //\n    test_enum match = test_error;\n    int    iseed = 0;\n    bool   error = argc < 3;\n    if( ! error )\n    {   for(size_t i = 0; i < n_test; i++)\n            if( strcmp(test_list[i].name, argv[1]) == 0 )\n                match = test_list[i].index;\n        error = match == test_error;\n        for(size_t i = 0; *(argv[2] + i) != '\\0'; ++i)\n        {   error |= *(argv[2] + i) < '0';\n            error |= '9' < *(argv[2] + i);\n        }\n        iseed = std::atoi( argv[2] );\n        error |= iseed < 0;\n        for(size_t i = 0; i < num_option; i++)\n            global_option[ option_list[i] ] = false;\n        for(size_t i = 3; i < size_t(argc); i++)\n        {   bool found = false;\n            for(size_t j = 0; j < num_option; j++)\n            {   if( strcmp(argv[i], option_list[j]) == 0 )\n                {   global_option[ option_list[j] ] = true;\n                    found = true;\n                }\n            }\n            error |= ! found;\n        }\n    }\n    if( error )\n    {   cout << \"usage: ./speed_\"\n                 << AD_PACKAGE << \" test seed option_list\" << endl;\n        cout << \"test choices:\";\n        for(size_t i = 0; i < n_test; i++)\n        {   if( i % 5 == 0 )\n                std::cout << \"\\n\\t\";\n            else\n                std::cout << \", \";\n            cout << test_list[i].name;\n        }\n        cout << \"\\n\\nseed: is a positive integer used as a random seed.\";\n        cout << \"\\n\\noption_list: zero or more of the following:\";\n        for(size_t i = 0; i < num_option; i++)\n        {   if( i % 5 == 0 )\n                std::cout << \"\\n\\t\";\n            else\n                std::cout << \", \";\n            cout << option_list[i];\n        }\n        cout << endl << endl;\n        return 1;\n    }\n    if( global_option[\"memory\"] )\n        CppAD::thread_alloc::hold_memory(true);\n\n    // initialize the random number simulator\n    // (may be re-initialized by sparse jacobain test)\n    global_seed = size_t(iseed);\n    CppAD::uniform_01(global_seed);\n\n    // arguments needed for speed tests\n    size_t n_size   = 5;\n    CppAD::vector<size_t> size_det_lu(n_size);\n    CppAD::vector<size_t> size_det_minor(n_size);\n    CppAD::vector<size_t> size_mat_mul(n_size);\n    CppAD::vector<size_t> size_ode(n_size);\n    CppAD::vector<size_t> size_poly(n_size);\n    CppAD::vector<size_t> size_sparse_hessian(n_size);\n    CppAD::vector<size_t> size_sparse_jacobian(n_size);\n    for(size_t i = 0; i < n_size; i++)\n    {   size_det_minor[i]   =  i + 4;\n        size_det_lu[i]      = 20 * i + 1;\n        size_mat_mul[i]     = 20 * i + 1;\n        size_ode[i]         = 20 * i + 1;\n        size_poly[i]        = 20 * i + 1;\n        size_sparse_hessian[i]  = 250 * (i + 1) * (i + 1);\n        size_sparse_jacobian[i] = 250 * (i + 1) * (i + 1);\n    }\n    switch(match)\n    {\n        // run all the correctness tests\n        case test_correct:\n        ok &= run_correct( available_det_lu, correct_det_lu, \"det_lu\"\n        );\n        ok &= run_correct(\n            available_det_minor, correct_det_minor, \"det_minor\"\n        );\n        ok &= run_correct(\n            available_mat_mul, correct_mat_mul, \"mat_mul\"\n        );\n        ok &= run_correct(\n            available_ode, correct_ode, \"ode\"\n        );\n        ok &= run_correct( available_poly, correct_poly, \"poly\"\n        );\n        ok &= run_correct(\n            available_sparse_hessian,\n            correct_sparse_hessian,\n            \"sparse_hessian\"\n        );\n        ok &= run_correct(\n            available_sparse_jacobian,\n            correct_sparse_jacobian,\n            \"sparse_jacobian\"\n        );\n        // summarize results\n        assert( ok || (Run_error_count > 0) );\n        if( ok )\n        {   cout << \"All \" << int(Run_ok_count)\n                      << \" correctness tests passed.\" << endl;\n        }\n        else\n        {   cout << int(Run_error_count)\n                      << \" correctness tests failed.\" << endl;\n        }\n        break;\n        // ---------------------------------------------------------\n        // run all the speed tests\n        case test_speed:\n        if( available_det_lu() ) run_speed(\n            time_det_lu,          size_det_lu,          \"det_lu\"\n        );\n        if( available_det_minor() ) run_speed(\n            time_det_minor,       size_det_minor,       \"det_minor\"\n        );\n        if( available_mat_mul() ) run_speed(\n            time_mat_mul,           size_mat_mul,       \"mat_mul\"\n        );\n        if( available_ode() ) run_speed(\n            time_ode,             size_ode,             \"ode\"\n        );\n        if( available_poly() ) run_speed(\n            time_poly,            size_poly,            \"poly\"\n        );\n        if( available_sparse_hessian() ) run_speed(\n            time_sparse_hessian,  size_sparse_hessian,  \"sparse_hessian\"\n        );\n        if( available_sparse_jacobian() ) run_speed(\n        time_sparse_jacobian, size_sparse_jacobian, \"sparse_jacobian\"\n        );\n        ok = true;\n        break;\n        // ---------------------------------------------------------\n\n        case test_det_lu:\n        if( ! available_det_lu() )\n        {   not_available_message( argv[1] );\n            exit(1);\n        }\n        ok &= run_correct(\n            available_det_lu, correct_det_lu, \"det_lu\")\n        ;\n        run_speed(time_det_lu,    size_det_lu,     \"det_lu\");\n        break;\n        // ---------------------------------------------------------\n\n        case test_det_minor:\n        if( ! available_det_minor() )\n        {   not_available_message( argv[1] );\n            exit(1);\n        }\n        ok &= run_correct(\n            available_det_minor, correct_det_minor, \"det_minor\"\n        );\n        run_speed(time_det_minor, size_det_minor, \"det_minor\");\n        break;\n        // ---------------------------------------------------------\n\n        case test_mat_mul:\n        if( ! available_mat_mul() )\n        {   not_available_message( argv[1] );\n            exit(1);\n        }\n        ok &= run_correct(\n            available_mat_mul, correct_mat_mul, \"mat_mul\"\n        );\n        run_speed(time_mat_mul, size_mat_mul, \"mat_mul\");\n        break;\n        // ---------------------------------------------------------\n\n        case test_ode:\n        if( ! available_ode() )\n        {   not_available_message( argv[1] );\n            exit(1);\n        }\n        ok &= run_correct(\n            available_ode, correct_ode, \"ode\"\n        );\n        run_speed(time_ode,      size_ode,      \"ode\");\n        break;\n        // ---------------------------------------------------------\n\n        case test_poly:\n        if( ! available_poly() )\n        {   not_available_message( argv[1] );\n            exit(1);\n        }\n        ok &= run_correct(\n            available_poly, correct_poly, \"poly\"\n        );\n        run_speed(time_poly,      size_poly,      \"poly\");\n        break;\n        // ---------------------------------------------------------\n\n        case test_sparse_hessian:\n        if( ! available_sparse_hessian() )\n        {   not_available_message( argv[1] );\n            exit(1);\n        }\n        ok &= run_correct(\n            available_sparse_hessian,\n            correct_sparse_hessian,\n            \"sparse_hessian\"\n        );\n        run_speed(\n            time_sparse_hessian, size_sparse_hessian,  \"sparse_hessian\"\n        );\n        cout << AD_PACKAGE << \"_sparse_hessian_n_color = \";\n        for(size_t i = 0; i < size_sparse_hessian.size(); i++)\n        {   if( i == 0 )\n                cout << \"[ \";\n            else\n                cout << \", \";\n            size_t n_color;\n            info_sparse_hessian(size_sparse_hessian[i], n_color);\n            cout << n_color;\n        }\n        cout << \" ]\" << endl;\n        break;\n        // ---------------------------------------------------------\n\n        case test_sparse_jacobian:\n        if( ! available_sparse_jacobian() )\n        {   not_available_message( argv[1] );\n            exit(1);\n        }\n        ok &= run_correct(\n            available_sparse_jacobian,\n            correct_sparse_jacobian,\n            \"sparse_jacobian\"\n        );\n        run_speed(\n            time_sparse_jacobian, size_sparse_jacobian, \"sparse_jacobian\"\n        );\n        {   // output values of n_color\n            CppAD::vector<size_t> size_vec, n_color_vec;\n            info_sparse_jacobian(size_vec, n_color_vec);\n            assert( size_sparse_jacobian.size() == size_vec.size() );\n            cout << AD_PACKAGE << \"_sparse_jacobian_n_color = \";\n            for(size_t i = 0; i < size_vec.size(); i++)\n            {   assert( size_vec[i] == size_sparse_jacobian[i] );\n                if( i == 0 )\n                    cout << \"[ \";\n                else\n                    cout << \", \";\n                cout << n_color_vec[i];\n            }\n        }\n        cout << \" ]\" << endl;\n        break;\n        // ---------------------------------------------------------\n\n        default:\n        assert(0);\n    }\n# ifndef NDEBUG\n    // return memory for vectors that are still in scope\n    size_det_lu.clear();\n    size_det_minor.clear();\n    size_mat_mul.clear();\n    size_ode.clear();\n    size_poly.clear();\n    size_sparse_hessian.clear();\n    size_sparse_jacobian.clear();\n    // check for memory leak\n    if( CppAD::thread_alloc::free_all() )\n    {   Run_ok_count++;\n        cout << \"No memory leak detected\" << endl;\n    }\n    else\n    {   ok = false;\n        Run_error_count++;\n        cout << \"Memory leak detected\" << endl;\n    }\n# endif\n    if( global_cppad_thread_alloc_inuse != 0 )\n    {   cout << \"memory allocated at end of last cppad speed test = \";\n        cout << global_cppad_thread_alloc_inuse << std::endl;\n    }\n    if( ! ok )\n    {   cout << \"speed main: Error\\n\";\n        exit(1);\n    }\n    std::cout << \"speed main: OK\\n\";\n    return 0;\n}\n"
  },
  {
    "path": "speed/profile/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-25 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# Build the speed/profile directory tests\n# Inherit build type from ../CMakeList.txt\n\n# Adds flags to the compiler command line for sources in the current directory\n# and below. This command can be used to add any flags, but it was originally\n# intended to add preprocessor definitions.\nADD_DEFINITIONS(\"-DCPPAD_PROFILE_SPEED ${cppad_profile_flag}\")\n\n# Extra flags used by the linker when creating an executable.\nSET(CMAKE_EXE_LINKER_FLAGS ${cppad_profile_flag} ${cppad_link_flags})\n\n# Local include directories to search (not in package_prefix/includdir)\nINCLUDE_DIRECTORIES( ${CMAKE_CURRENT_SOURCE_DIR}/../src )\n\n# add_executable(<name> [WIN32] [MACOSX_BUNDLE] [EXCLUDE_FROM_ALL]\n#                 source1 source2 ... sourceN\n# )\nSET(source_list ../main.cpp\n    ../cppad/det_lu.cpp\n    ../cppad/det_minor.cpp\n    ../cppad/mat_mul.cpp\n    ../cppad/ode.cpp\n    ../cppad/poly.cpp\n    ../cppad/sparse_hessian.cpp\n    ../cppad/sparse_jacobian.cpp\n)\nset_compile_flags( speed_profile \"${cppad_debug_which}\" \"${source_list}\" )\n#\nADD_EXECUTABLE( speed_profile EXCLUDE_FROM_ALL ${source_list} )\n#\n# List of libraries to be linked into the specified target\nTARGET_LINK_LIBRARIES(speed_profile\n    ${cppad_lib}\n    ${colpack_libs}\n)\n# profile builds it own copy of src/speed library (see ADD_EXECUTABLE above)\n# TARGET_LINK_LIBRARIES(speed_profile speed_src )\nTARGET_LINK_LIBRARIES(speed_profile\n    speed_src\n    ${cppad_lib}\n    ${colpack_libs}\n)\n\n# check_speed_profile\nadd_check_executable(check_speed profile \"correct 54321\")\n\n# Sed script to make gprof output more readable, use:\n#  ./speed_profile speed 54321\n#  gprof speed_profile gmon.out | sed -f 'gprof.sed' > gprof.out\n#\n# configure_file(InputFile OutputFile [COPYONLY] [ESCAPE_QUOTES] [@ONLY])\nCONFIGURE_FILE(\n    ${CMAKE_CURRENT_SOURCE_DIR}/gprof.sed.in\n    ${CMAKE_CURRENT_BINARY_DIR}/gprof.sed\n    COPYONLY\n)\n"
  },
  {
    "path": "speed/profile/gprof.sed.in",
    "content": "#! /bin/bash -e\n# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# remove template information\ns/<[^<>]*>//g\ns/<[^<>]*>//g\ns/<[^<>]*>//g\ns/<[^<>]*>//g\ns/<[^<>]*>//g\n# remove argument information\ns/([^()]*)//g\ns/([^()]*)//g\n# remove names space information\ns/[a-zA-Z0-9_]*:://g\ns/[a-zA-Z0-9_]*:://g\ns/[a-zA-Z0-9_]*:://g\ns/[a-zA-Z0-9_]*:://g\n"
  },
  {
    "path": "speed/sacado/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-23 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# Build the speed/sacado directory tests\n# Inherit build type from ../CMakeList.txt\n\n# assert sacado_prefix is defined\nassert( sacado_prefix )\n\n# Avoid the following warning:\n# The installed Kokkos configuration does not support CXX extensions.\nSET(CMAKE_CXX_EXTENSIONS Off)\n\n# Adds flags to the compiler command line for sources in the current directory\n# and below. This command can be used to add any flags, but it was originally\n# intended to add preprocessor definitions.\nADD_DEFINITIONS(\"-DCPPAD_SACADO_SPEED -DRAD_AUTO_AD_Const\")\n\n# Local include directories to search (not in package_prefix/includdir)\nINCLUDE_DIRECTORIES( ${CMAKE_CURRENT_SOURCE_DIR}/../src )\n\n# add_executable(<name> [WIN32] [MACOSX_BUNDLE] [EXCLUDE_FROM_ALL]\n#                 source1 source2 ... sourceN\n# )\nSET(source_list ../main.cpp\n    det_lu.cpp\n    det_minor.cpp\n    mat_mul.cpp\n    ode.cpp\n    poly.cpp\n    sparse_hessian.cpp\n    sparse_jacobian.cpp\n)\nset_compile_flags( speed_sacado \"${cppad_debug_which}\" \"${source_list}\" )\n#\nADD_EXECUTABLE( speed_sacado EXCLUDE_FROM_ALL ${source_list} )\n#\n# List of libraries to be linked into the specified target\nTARGET_LINK_LIBRARIES(speed_sacado\n    ${cppad_lib}\n    ${colpack_libs}\n)\n# determine libraries necessary to link Sacado\nFOREACH(dir ${cmake_install_libdirs})\n    IF( IS_DIRECTORY ${sacado_prefix}/${dir}/cmake/Trilinos )\n        SET(Trilinos_DIR \"${sacado_prefix}/${dir}/cmake/Trilinos\" )\n    ENDIF( IS_DIRECTORY ${sacado_prefix}/${dir}/cmake/Trilinos )\nENDFOREACH( dir )\nFIND_PACKAGE(Trilinos CONFIG)\nprint_variable(Sacado_LIBRARIES)\n#\n# include the dl library if it is in the system path\nCHECK_LIBRARY_EXISTS( dl dlopen \"${CMAKE_SYSTEM_LIBRARY_PATH}\" dl_found )\nIF( dl_found )\n    TARGET_LINK_LIBRARIES( speed_sacado speed_src ${Sacado_LIBRARIES} dl )\nELSE( dl_found )\n    TARGET_LINK_LIBRARIES( speed_sacado speed_src ${Sacado_LIBRARIES} )\nENDIF( dl_found )\n#\n# the check_speed_sacado\nadd_check_executable(check_speed sacado \"correct 54321\")\n"
  },
  {
    "path": "speed/sacado/det_lu.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin sacado_det_lu.cpp}\n\nSacado Speed: Gradient of Determinant Using Lu Factorization\n############################################################\n\nSpecifications\n**************\nSee :ref:`link_det_lu-name` .\n\nImplementation\n**************\n{xrst_spell_off}\n{xrst_code cpp} */\n// suppress conversion warnings before other includes\n# include <cppad/wno_conversion.hpp>\n//\n\n# include <Sacado.hpp>\n# include <cppad/speed/det_by_lu.hpp>\n# include <cppad/speed/uniform_01.hpp>\n# include <cppad/utility/vector.hpp>\n\n// list of possible options\n# include <map>\nextern std::map<std::string, bool> global_option;\n\nbool link_det_lu(\n    size_t                     size     ,\n    size_t                     repeat   ,\n    CppAD::vector<double>     &matrix   ,\n    CppAD::vector<double>     &gradient )\n{\n    // speed test global option values\n    if( global_option[\"onetape\"] || global_option[\"atomic\"] )\n        return false;\n    if( global_option[\"memory\"] || global_option[\"optimize\"] )\n        return false;\n    // -----------------------------------------------------\n    // setup\n    //\n    // object for computing determinant\n    typedef Sacado::Rad::ADvar<double>   ADScalar;\n    typedef CppAD::vector<ADScalar>      ADVector;\n    CppAD::det_by_lu<ADScalar>           Det(size);\n\n    size_t i;                // temporary index\n    size_t n = size * size;  // number of independent variables\n    ADScalar   detA;         // AD value of the determinant\n    ADVector   A(n);         // AD version of matrix\n\n    // ------------------------------------------------------\n    while(repeat--)\n    {  // get the next matrix\n        CppAD::uniform_01(n, matrix);\n\n        // set independent variable values\n        for(i = 0; i < n; i++)\n            A[i] = matrix[i];\n\n        // compute the determinant\n        detA = Det(A);\n\n        // compute the gradient of detA\n        ADScalar::Gradcomp();\n\n        // evaluate and return gradient using reverse mode\n        for(i =0; i < n; i++)\n            gradient[i] = A[i].adj(); // partial detA w.r.t A[i]\n    }\n    // ---------------------------------------------------------\n    return true;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end sacado_det_lu.cpp}\n*/\n"
  },
  {
    "path": "speed/sacado/det_minor.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin sacado_det_minor.cpp}\n\nSacado Speed: Gradient of Determinant by Minor Expansion\n########################################################\n\nSpecifications\n**************\nSee :ref:`link_det_minor-name` .\n\nImplementation\n**************\n\n{xrst_spell_off}\n{xrst_code cpp} */\n// suppress conversion warnings before other includes\n# include <cppad/wno_conversion.hpp>\n//\n# include <Sacado.hpp>\n# include <cppad/speed/det_by_minor.hpp>\n# include <cppad/speed/uniform_01.hpp>\n# include <cppad/utility/vector.hpp>\n\n// list of possible options\n# include <map>\nextern std::map<std::string, bool> global_option;\n\nbool link_det_minor(\n    const std::string&         job      ,\n    size_t                     size     ,\n    size_t                     repeat   ,\n    CppAD::vector<double>     &matrix   ,\n    CppAD::vector<double>     &gradient )\n{\n    // --------------------------------------------------------------------\n    // check none of the global options is true\n    typedef std::map<std::string, bool>::iterator iterator;\n    for(iterator itr=global_option.begin(); itr!=global_option.end(); ++itr)\n    {  if( itr->second )\n            return false;\n    }\n    // -----------------------------------------------------\n    // not using job\n    // -----------------------------------------------------\n\n    // AD types\n    typedef Sacado::Rad::ADvar<double>    r_double;\n    typedef CppAD::vector<r_double>       r_vector;\n\n    // object for computing deterinant\n    CppAD::det_by_minor<r_double>         r_det(size);\n\n    // number of independent variables\n    size_t n = size * size;\n\n    // independent variable vector\n    r_vector   r_A(n);\n\n    // AD value of the determinant\n    r_double   r_detA;\n\n    // ------------------------------------------------------\n    while(repeat--)\n    {  // get the next matrix\n        CppAD::uniform_01(n, matrix);\n\n        // set independent variable values\n        for(size_t j = 0; j < n; ++j)\n            r_A[j] = matrix[j];\n\n        // compute the determinant\n        r_detA = r_det(r_A);\n\n        // reverse mode compute gradient of last computed value; i.e., detA\n        r_double::Gradcomp();\n\n        // return gradient\n        for(size_t j =0; j < n; ++j)\n            gradient[j] = r_A[j].adj(); // partial detA w.r.t A[j]\n    }\n    // ---------------------------------------------------------\n    return true;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end sacado_det_minor.cpp}\n*/\n"
  },
  {
    "path": "speed/sacado/mat_mul.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin sacado_mat_mul.cpp}\n\nSacado Speed: Matrix Multiplication\n###################################\n\nSpecifications\n**************\nSee :ref:`link_mat_mul-name` .\n\nImplementation\n**************\n\n{xrst_spell_off}\n{xrst_code cpp} */\n// suppress conversion warnings before other includes\n# include <cppad/wno_conversion.hpp>\n//\n# include <Sacado.hpp>\n# include <cppad/utility/vector.hpp>\n# include <cppad/speed/mat_sum_sq.hpp>\n# include <cppad/speed/uniform_01.hpp>\n\n// list of possible options\n# include <map>\nextern std::map<std::string, bool> global_option;\n\nbool link_mat_mul(\n    size_t                           size     ,\n    size_t                           repeat   ,\n    CppAD::vector<double>&           x        ,\n    CppAD::vector<double>&           z        ,\n    CppAD::vector<double>&           dz       )\n{\n    // speed test global option values\n    if( global_option[\"memory\"] || global_option[\"onetape\"] || global_option[\"atomic\"] || global_option[\"optimize\"] )\n        return false;\n    // -----------------------------------------------------\n    // setup\n\n    // object for computing determinant\n    typedef Sacado::Rad::ADvar<double>    ADScalar;\n    typedef CppAD::vector<ADScalar>       ADVector;\n\n    size_t j;                // temporary index\n    size_t m = 1;            // number of dependent variables\n    size_t n = size * size;  // number of independent variables\n    ADVector   X(n);         // AD domain space vector\n    ADVector   Y(n);         // Store product matrix\n    ADVector   Z(m);         // AD range space vector\n    ADScalar   f;\n\n    // ------------------------------------------------------\n    while(repeat--)\n    {  // get the next matrix\n        CppAD::uniform_01(n, x);\n\n        // set independent variable values\n        for(j = 0; j < n; j++)\n            X[j] = x[j];\n\n        // do the computation\n        mat_sum_sq(size, X, Y, Z);\n\n        // create function object f : X -> Z\n        f = Z[0];\n\n        // reverse mode gradient of last ADvar computed value; i.e., f\n        ADScalar::Gradcomp();\n\n        // return gradient\n        for(j = 0; j < n; j++)\n            dz[j] = X[j].adj(); // partial f w.r.t X[j]\n    }\n    // return function value\n    z[0] = f.val();\n\n    // ---------------------------------------------------------\n    return true;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end sacado_mat_mul.cpp}\n*/\n"
  },
  {
    "path": "speed/sacado/ode.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin sacado_ode.cpp}\n\nSacado Speed: Gradient of Ode Solution\n######################################\n\nSpecifications\n**************\nSee :ref:`link_ode-name` .\n\nImplementation\n**************\n\n{xrst_spell_off}\n{xrst_code cpp} */\n// suppress conversion warnings before other includes\n# include <cppad/wno_conversion.hpp>\n//\n# include <Sacado.hpp>\n# include <cassert>\n# include <cppad/utility/vector.hpp>\n# include <cppad/speed/uniform_01.hpp>\n# include <cppad/speed/ode_evaluate.hpp>\n\n// list of possible options\n# include <map>\nextern std::map<std::string, bool> global_option;\n\nbool link_ode(\n    size_t                     size       ,\n    size_t                     repeat     ,\n    CppAD::vector<double>      &x         ,\n    CppAD::vector<double>      &jacobian\n)\n{\n    // speed test global option values\n    if( global_option[\"atomic\"] )\n        return false;\n    if( global_option[\"memory\"] || global_option[\"onetape\"] || global_option[\"optimize\"] )\n        return false;\n    // -------------------------------------------------------------\n    // setup\n    assert( x.size() == size );\n    assert( jacobian.size() == size * size );\n\n    typedef Sacado::Fad::DFad<double>  ADScalar;\n    typedef CppAD::vector<ADScalar>    ADVector;\n\n    size_t i, j;\n    size_t p = 0;          // use ode to calculate function values\n    size_t n = size;       // number of independent variables\n    size_t m = n;          // number of dependent variables\n    ADVector X(n), Y(m);   // independent and dependent variables\n\n    // -------------------------------------------------------------\n    while(repeat--)\n    {  // choose next x value\n        CppAD::uniform_01(n, x);\n        for(j = 0; j < n; j++)\n        {  // set up for X as the independent variable vector\n            X[j] = ADScalar(int(n), int(j), x[j]);\n        }\n\n        // evaluate function\n        CppAD::ode_evaluate(X, p, Y);\n\n        // return values with Y as the dependent variable vector\n        for(i = 0; i < m; i++)\n        {  for(j = 0; j < n; j++)\n                jacobian[ i * n + j ] = Y[i].dx( int(j) );\n        }\n    }\n    return true;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end sacado_ode.cpp}\n*/\n"
  },
  {
    "path": "speed/sacado/poly.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin sacado_poly.cpp}\n\nSacado Speed: Second Derivative of a Polynomial\n###############################################\n\nSpecifications\n**************\nSee :ref:`link_poly-name` .\n\nImplementation\n**************\n\n{xrst_spell_off}\n{xrst_code cpp} */\n// suppress conversion warnings before other includes\n# include <cppad/wno_conversion.hpp>\n//\n# include <Sacado.hpp>\n# include <cppad/utility/vector.hpp>\n# include <cppad/utility/poly.hpp>\n# include <cppad/speed/uniform_01.hpp>\n\n// list of possible options\n# include <map>\nextern std::map<std::string, bool> global_option;\n\nbool link_poly(\n    size_t                     size     ,\n    size_t                     repeat   ,\n    CppAD::vector<double>     &a        ,  // coefficients of polynomial\n    CppAD::vector<double>     &z        ,  // polynomial argument value\n    CppAD::vector<double>     &ddp      )  // second derivative w.r.t z\n{\n    if( global_option[\"atomic\"] )\n        return false;\n    if( global_option[\"memory\"] || global_option[\"onetape\"] || global_option[\"optimize\"] )\n        return false;\n    // -----------------------------------------------------\n    // setup\n    typedef Sacado::Tay::Taylor<double>  ADScalar;\n    CppAD::vector<ADScalar>              A(size);\n\n    size_t i;               // temporary index\n    ADScalar   Z;           // domain space AD value\n    ADScalar   P;           // range space AD value\n    int order = 2;          // order of Taylor coefficients\n    Z.resize(order+1, false);\n    P.resize(order+1, false);\n\n    // choose the polynomial coefficients\n    CppAD::uniform_01(size, a);\n\n    // AD copy of the polynomial coefficients\n    for(i = 0; i < size; i++)\n        A[i] = a[i];\n\n    // ------------------------------------------------------\n    while(repeat--)\n    {  // get the next argument value\n        CppAD::uniform_01(1, z);\n\n        // independent variable value\n        Z.fastAccessCoeff(0)   = z[0]; // argument value\n        Z.fastAccessCoeff(1)   = 1.;   // first order coefficient\n        Z.fastAccessCoeff(2)   = 0.;   // second order coefficient\n\n        // AD computation of the dependent variable\n        P = CppAD::Poly(0, A, Z);\n\n        // second derivative is twice second order Taylor coefficient\n        ddp[0] = 2. * P.fastAccessCoeff(2);\n    }\n    // ------------------------------------------------------\n    return true;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end sacado_poly.cpp}\n*/\n"
  },
  {
    "path": "speed/sacado/sparse_hessian.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/utility/vector.hpp>\n\n/*\n{xrst_begin sacado_sparse_hessian.cpp}\n\nSacado Speed: Sparse Hessian\n############################\n\n{xrst_spell_off}\n{xrst_code cpp} */\n// A sacado version of this test is not yet implemented\nextern bool link_sparse_hessian(\n    size_t                            size      ,\n    size_t                            repeat    ,\n    const CppAD::vector<size_t>&      row       ,\n    const CppAD::vector<size_t>&      col       ,\n    CppAD::vector<double>&            x         ,\n    CppAD::vector<double>&            hessian   ,\n    size_t&                           n_color\n)\n{\n    return false;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end sacado_sparse_hessian.cpp}\n*/\n"
  },
  {
    "path": "speed/sacado/sparse_jacobian.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cstring>\n# include <string>\n# include <cppad/utility/vector.hpp>\n\n/*\n{xrst_begin sacado_sparse_jacobian.cpp}\n\nSacado Speed: sparse_jacobian\n#############################\n\n{xrst_spell_off}\n{xrst_code cpp} */\n// A sacado version of this test is not yet available\nbool link_sparse_jacobian(\n    const std::string&               job      ,\n    size_t                           size     ,\n    size_t                           repeat   ,\n    size_t                           m        ,\n    const CppAD::vector<size_t>&     row      ,\n    const CppAD::vector<size_t>&     col      ,\n    CppAD::vector<double>&           x        ,\n    CppAD::vector<double>&           jacobian ,\n    size_t&                          n_color  )\n{\n    return false;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end sacado_sparse_jacobian.cpp}\n*/\n"
  },
  {
    "path": "speed/sacado/speed_sacado.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin speed_sacado}\n\nSpeed Test Derivatives Using Sacado\n###################################\n\nPurpose\n*******\nCppAD has a set of speed tests that are used to compare\nSacado with other AD packages.\nThis section links to the source code the Sacado speed tests\n(any suggestions to make the Sacado results faster are welcome).\n\nsacado_prefix\n*************\nTo run these tests,\nyou must include the :ref:`sacado_prefix-name`\nin you :ref:`cmake@CMake Command` .\n\nRunning Tests\n*************\nTo build these speed tests, and run their correctness tests,\nexecute the following commands starting in the\n:ref:`cmake@Build Directory` :\n\n| |tab| ``cd speed/sacado``\n| |tab| ``make check_speed_sacado VERBOSE`` =1\n\nYou can then run the corresponding speed tests\nwith the following command\n\n    ./ ``speed_sacado speed`` *seed*\n\nwhere *seed* is a positive integer.\nSee :ref:`speed_main-name` for more options.\n\nContents\n********\n{xrst_toc_list\n    speed/sacado/det_minor.cpp\n    speed/sacado/det_lu.cpp\n    speed/sacado/mat_mul.cpp\n    speed/sacado/ode.cpp\n    speed/sacado/poly.cpp\n    speed/sacado/sparse_hessian.cpp\n    speed/sacado/sparse_jacobian.cpp\n}\n\n{xrst_end speed_sacado}\n"
  },
  {
    "path": "speed/speed.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin speed}\n{xrst_spell\n    adolc\n    cppadcg\n    fadbad\n    sacado\n}\n\nSpeed Test an Operator Overloading AD Package\n#############################################\n\nPurpose\n*******\nCppad has a set of speed tests that are used to determine if\nchanges improve its execution speed.\nThese tests can also be used to compare the AD packages\n:ref:`Adolc<adolc@Adolc Home Page>` ,\nCppad,\n:ref:`Fadbad<fadbad_prefix@Fadbad Home Page>` ,\n:ref:`Cppadcg<cppadcg@CppADCodeGen Home Page>` ,\n:ref:`Sacado<sacado_prefix@Sacado Home Page>` .\n\ndebug_which\n***********\nUsually, one wants to compile the speed tests in release mode.\nThis can be done by setting\n:ref:`cmake@cppad_debug_which` to ``debug_none``\nin the cmake command.\nCorrectness tests are included for all the speed tests,\nso it is possible you will want to compile these tests for debugging; i.e.,\nset *cppad_debug_which* to ``debug_all`` .\n\nThe sections below explain how you can run these tests on your computer.\n\nContents\n********\n{xrst_toc_table\n    speed/main.cpp\n    speed/speed_utility.xrst\n    speed/double/speed_double.xrst\n    speed/adolc/speed_adolc.xrst\n    speed/cppad/speed_cppad.xrst\n    speed/fadbad/speed_fadbad.xrst\n    speed/cppad_jit/speed_cppad_jit.xrst\n    speed/cppadcg/speed_cppadcg.xrst\n    speed/sacado/speed_sacado.xrst\n    speed/xpackage/speed_xpackage.xrst\n}\n\n{xrst_end speed}\n"
  },
  {
    "path": "speed/speed_utility.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin speed_utility}\n\nSpeed Testing Utilities\n#######################\n{xrst_toc_hidden\n    include/cppad/speed/det_by_lu.hpp\n    include/cppad/speed/det_of_minor.hpp\n    include/cppad/speed/det_by_minor.hpp\n    include/cppad/speed/det_33.hpp\n    include/cppad/speed/det_grad_33.hpp\n    include/cppad/speed/mat_sum_sq.hpp\n    include/cppad/speed/ode_evaluate.hpp\n    include/cppad/speed/sparse_jac_fun.hpp\n    include/cppad/speed/sparse_hes_fun.hpp\n    include/cppad/speed/uniform_01.hpp\n}\n\nSpeed Main Program\n******************\n\n.. csv-table::\n    :widths: auto\n\n    speed_main,:ref:`speed_main-title`\n\nSpeed Utility Routines\n**********************\n\n.. csv-table::\n    :widths: auto\n\n    det_by_lu,:ref:`det_by_lu-title`\n    det_by_minor,:ref:`det_by_minor-title`\n    det_of_minor,:ref:`det_of_minor-title`\n    det_33,:ref:`det_33-title`\n    det_grad_33,:ref:`det_grad_33-title`\n    mat_sum_sq,:ref:`mat_sum_sq-title`\n    ode_evaluate,:ref:`ode_evaluate-title`\n    sparse_jac_fun,:ref:`sparse_jac_fun-title`\n    sparse_hes_fun,:ref:`sparse_hes_fun-title`\n    uniform_01,:ref:`uniform_01-title`\n\nLibrary Routines\n****************\n\n.. csv-table::\n    :widths: auto\n\n    LuFactor,:ref:`LuFactor-title`\n    LuInvert,:ref:`LuInvert-title`\n    LuSolve,:ref:`LuSolve-title`\n    Poly,:ref:`Poly-title`\n\nSource Code\n***********\n\n.. csv-table::\n    :widths: auto\n\n    det_by_lu.hpp,:ref:`det_by_lu.hpp-title`\n    det_by_minor.hpp,:ref:`det_by_minor.hpp-title`\n    det_grad_33.hpp,:ref:`det_grad_33.hpp-title`\n    det_of_minor.hpp,:ref:`det_of_minor.hpp-title`\n    lu_factor.hpp,:ref:`lu_factor.hpp-title`\n    lu_invert.hpp,:ref:`lu_invert.hpp-title`\n    lu_solve.hpp,:ref:`lu_solve.hpp-title`\n    mat_sum_sq.hpp,:ref:`mat_sum_sq.hpp-title`\n    poly.hpp,:ref:`poly.hpp-title`\n    sparse_jac_fun.hpp,:ref:`sparse_jac_fun.hpp-title`\n    sparse_hes_fun.hpp,:ref:`sparse_hes_fun.hpp-title`\n    uniform_01.hpp,:ref:`uniform_01.hpp-title`\n\n{xrst_end speed_utility}\n"
  },
  {
    "path": "speed/src/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# Build the cppad_ipopt/src library\n# Inherit build type from ../CMakeList.txt\n\n#  add_library(<name> [STATIC | SHARED | MODULE] [EXCLUDE_FROM_ALL]\n#  source1 source2 ... sourceN)\n# )\n# Make libspeed_src a static library because this is just for testing\n# and is not installed (do not have to worry about library search path).\n# BEGIN_SORT_THIS_LINE_PLUS_2\nSET(source_list\n    link_det_lu.cpp\n    link_det_minor.cpp\n    link_mat_mul.cpp\n    link_ode.cpp\n    link_poly.cpp\n    link_sparse_hessian.cpp\n    link_sparse_jacobian.cpp\n)\n# END_SORT_THIS_LINE_MINUS_2\n\n# 2DO: fix problem with the test\n#  ./speed_cppad sparse_hessian 123 colpack\n# when speed_cppad is compiled for debugging.\n#\nset_compile_flags( speed_src \"${cppad_debug_which}\" \"${source_list}\" )\n#\nADD_LIBRARY(speed_src STATIC EXCLUDE_FROM_ALL ${source_list} )\n"
  },
  {
    "path": "speed/src/dev_link.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin speed_available dev}\n{xrst_spell\n    src\n}\n\nIs A Speed Test Available\n#########################\n\nSyntax\n******\n| *available* = ``available_`` *name* ()\n\nname\n****\nThe text *name* in the syntax is\n``det_lu`` ,\n``det_minor`` ,\n``mat_mul`` ,\n``ode`` ,\n``sparse_hessian`` , or\n``sparse_jacobian`` .\n\nNamespace\n*********\nThis function is in the global namespace, not the CppAD namespace.\n\navailable\n*********\nThe ``bool`` return value *available* is true (false)\nif the speed test *name* is (is not) available for this package.\n\nImplementation\n**************\nThis function is implemented in the file\n``speed/src/link_`` *name* . ``cpp`` .\n\n{xrst_end speed_available}\n------------------------------------------------------------------------------\n{xrst_begin speed_correct dev}\n{xrst_spell\n    src\n}\n\nDoes a A Speed Test Return Correct Results\n##########################################\n\nSyntax\n******\n\n    *ok* = ``correct_`` *name* ( *is_package_double* )\n\nname\n****\nThe text *name* in the syntax is\n``det_lu`` ,\n``det_minor`` ,\n``mat_mul`` ,\n``ode`` ,\n``sparse_hessian`` , or\n``sparse_jacobian`` .\n\nNamespace\n*********\nThis function is in the global namespace, not the CppAD namespace.\n\nis_package_double\n*****************\nThe ``bool`` argument *is_package_double* is true (false)\nif we are checking functions values (derivative values).\n\nok\n**\nThe ``bool`` return value *ok* is true (false)\nif the speed test for *name* returns correct (incorrect) values.\n\nImplementation\n**************\nThis function is implemented in the file\n``speed/src/link_`` *name* . ``cpp`` .\n\n{xrst_end speed_correct}\n------------------------------------------------------------------------------\n{xrst_begin speed_time dev}\n{xrst_spell\n    src\n}\n\nMeasure Time It Takes for a A Speed Test to Run\n###############################################\n\nSyntax\n******\n\n    *time* = ``time_`` *name* ( *time_min* , *size* )\n\nname\n****\nThe text *name* in the syntax is\n``det_lu`` ,\n``det_minor`` ,\n``mat_mul`` ,\n``ode`` ,\n``sparse_hessian`` , or\n``sparse_jacobian`` .\n\nNamespace\n*********\nThis function is in the global namespace, not the CppAD namespace.\n\ntime_min\n********\nIs the minimum time, in seconds, for the test.\nCalls to ``link_`` *name* will be repeated enough times so that\nthe total time is at least *time_min* .\n\nsize\n****\nThis ``size_t`` argument the size for this speed test;\nsee *size* in the corresponding ``link_`` *name* documentation.\n\ntime\n****\nThis is the average amount of time for each call; i.e., the total time,\nwhich is greater than or equal *time_min* ,\ndivided by the number of repeats.\n\nImplementation\n**************\nThis function is implemented in the file\n``speed/src/link_`` *name* . ``cpp`` .\n\n{xrst_end speed_time}\n------------------------------------------------------------------------------\n{xrst_begin speed_time_callback dev}\n\nTiming Callback Functions\n#########################\n\nSyntax\n******\n\n    *time* = ``time_`` *name* _ ``callback`` ( *size_t* , *repeat* )\n\nname\n****\nThe text *name* in the syntax is\n``det_lu`` ,\n``det_minor`` ,\n``mat_mul`` ,\n``ode`` ,\n``sparse_hessian`` , or\n``sparse_jacobian`` .\n\nNamespace\n*********\nThese functions are in the empty namespace; i.e., it is only accessed\nby functions in the file where it is defined.\n\nsize\n****\nThis ``size_t`` argument the size for this speed test;\nsee *size* in the corresponding ``link_`` *name* documentation.\n\nrepeat\n******\nThis ``size_t`` value\nis the number of times to repeat a call to the corresponding link routine.\n\njob\n***\nThe :ref:`link_routines@job`\nargument to the corresponding link routine will be ``run`` .\n\n{xrst_end speed_time_callback}\n"
  },
  {
    "path": "speed/src/dev_sparse_hessian.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin dev_sparse_hessian dev}\n\nDeveloper Documentation for Speed Testing Sparse Hessian\n########################################################\n\nContents\n********\n{xrst_toc_table\n    speed/src/link_sparse_hessian.cpp\n}\n\n{xrst_end dev_sparse_hessian}\n"
  },
  {
    "path": "speed/src/link.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin link_routines}\n{xrst_spell\n    teardown\n}\n\nPackage Specific Speed Test Linking Routines\n############################################\n\nSyntax\n******\n| *available* = *link_name* ( *job* , *size* , *repeat* , *other_arguments*  )\n\nPurpose\n*******\nEach :ref:`speed_main@package`\ndefines a version of each *link_name* listed below.\nThis is used by the :ref:`speed_main-name` program\nto run the corresponding speed and correctness tests.\n\nThread Save\n***********\nThe *link_name* routines may use static memory for setup and teardown\nand hence may not be thread safe.\n\nlink_name\n*********\nThe routine *link_name* in the syntax is one of the following:\n\nContents\n********\n{xrst_toc_table\n    speed/src/link_det_lu.cpp\n    speed/src/link_det_minor.cpp\n    speed/src/link_mat_mul.cpp\n    speed/src/link_ode.cpp\n    speed/src/link_poly.cpp\n    speed/src/link_sparse_hessian.hpp\n    speed/src/link_sparse_jacobian.hpp\n}\n\nNamespace\n*********\nThese routines are in the global namespace, not the CppAD namespace.\n\navailable\n*********\nThe ``bool`` return value *available* is true (false)\nif the speed test *name* is (is not) available for this package.\n\njob\n***\nThis argument can be used to cache information that does not\ndepend on the function argument value without having the corresponding time\nincluded in the test results.\nThis is expected to be important when the global option\n:ref:`speed_main@Global Options@onetape` is true.\nThe ``const std::string&`` argument *job*\nhas one of the following values:\n\nsetup\n=====\nThis is the first call with a new value for *size*\nand will not be used for timing.\nIt can be used to setup information that should not be included in timing\nhow long this routine takes.\n\nrun\n===\nThis call will be used for timing how long this routine takes.\nThe previous call *job* was either ``setup`` or ``run``\nand had the same value of *size* .\n\nteardown\n========\nThis is the last call with this value of *size*\nand will not be used for timing.\nIt should be used to take down the setup; e.g., fee any memory that\nwas allocated.\n\nsize\n****\nThe ``size_t`` argument *size* this is the size parameter for this\ntest.  Larger sizes correspond to more computation per call.\n\nrepeat\n******\nIf *job* is ``run`` ,\nthe *size_t* argument *repeat* is the number of\nrandomly chosen argument values that the test derivatives should be\nevaluated for.\nThe value of *repeat* is always greater than or equal one\nand all the ``link_`` *name* output values are always calculated.\n\nother_arguments\n***************\nEach link function routine has specific specifications\nfor *size* and their other arguments.\n\n{xrst_end link_routines}\n"
  },
  {
    "path": "speed/src/link_det_lu.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/utility/vector.hpp>\n# include <cppad/speed/det_grad_33.hpp>\n# include <cppad/speed/det_33.hpp>\n# include <cppad/utility/time_test.hpp>\n\n// BEGIN PROTOTYPE\nextern bool link_det_lu(\n    size_t                     size      ,\n    size_t                     repeat    ,\n    CppAD::vector<double>&     matrix    ,\n    CppAD::vector<double>&     gradient\n);\n// END PROTOTYPE\n/*\n-------------------------------------------------------------------------------\n{xrst_begin link_det_lu}\n\nSpeed Testing Gradient of Determinant Using Lu Factorization\n############################################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN PROTOTYPE\n    // END PROTOTYPE\n}\n\nPurpose\n*******\nEach :ref:`speed_main@package`\nmust define a version of this routine as specified below.\nThis is used by the :ref:`speed_main-name` program\nto run the corresponding speed and correctness tests.\n\nMethod\n******\nThe same template routine :ref:`det_by_lu-name` is used\nby the different AD packages.\n\nReturn Value\n************\nIf this speed test is not yet\nsupported by a particular *package* ,\nthe corresponding return value for ``link_det_lu``\nshould be ``false`` .\n\nsize\n****\nThe argument *size*\nis the number of rows and columns in the matrix.\n\nrepeat\n******\nThe argument *repeat* is the number of different matrices\nthat the gradient (or determinant) is computed for.\n\nmatrix\n******\nThe argument *matrix* is a vector with *size* * *size* elements.\nThe input value of its elements does not matter.\nThe output value of its elements is the last matrix that the\ngradient (or determinant) is computed for.\n\ngradient\n********\nThe argument *gradient* is a vector with *size* * *size* elements.\nThe input value of its elements does not matter.\nThe output value of its elements is the gradient of the\ndeterminant of *matrix* with respect to its elements.\n\ndouble\n======\nIn the case where *package* is ``double`` ,\nonly the first element of *gradient* is used and it is actually\nthe determinant value (the gradient value is not computed).\n\n{xrst_end link_det_lu}\n-----------------------------------------------------------------------------\n*/\n// ---------------------------------------------------------------------------\n// The routines below are documented in dev_link.omh\n// ---------------------------------------------------------------------------\nnamespace {\n    void time_det_lu_callback(size_t size, size_t repeat)\n    {   // free statically allocated memory\n        if( size == 0 && repeat == 0 )\n            return;\n        //\n        CppAD::vector<double> matrix(size * size);\n        CppAD::vector<double> gradient(size * size);\n\n        link_det_lu(size, repeat, matrix, gradient);\n        return;\n    }\n}\n// ---------------------------------------------------------------------------\nbool available_det_lu(void)\n{   size_t size   = 3;\n    size_t repeat = 1;\n    CppAD::vector<double> matrix(size * size);\n    CppAD::vector<double> gradient(size * size);\n\n    return link_det_lu(size, repeat, matrix, gradient);\n}\n// ---------------------------------------------------------------------------\nbool correct_det_lu(bool is_package_double)\n{   size_t size   = 3;\n    size_t repeat = 1;\n    CppAD::vector<double> matrix(size * size);\n    CppAD::vector<double> gradient(size * size);\n\n    link_det_lu(size, repeat, matrix, gradient);\n    bool ok;\n    if( is_package_double )\n        ok = CppAD::det_33(matrix, gradient);\n    else\n        ok = CppAD::det_grad_33(matrix, gradient);\n    return ok;\n}\n// ---------------------------------------------------------------------------\ndouble time_det_lu(double time_min, size_t size)\n{   return CppAD::time_test(time_det_lu_callback, time_min, size);\n}\n"
  },
  {
    "path": "speed/src/link_det_minor.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/utility/vector.hpp>\n# include <cppad/speed/det_grad_33.hpp>\n# include <cppad/speed/det_33.hpp>\n# include <cppad/utility/time_test.hpp>\n// BEGIN PROTOTYPE\nextern bool link_det_minor(\n    const std::string&         job       ,\n    size_t                     size      ,\n    size_t                     repeat    ,\n    CppAD::vector<double>&     matrix    ,\n    CppAD::vector<double>&     gradient\n);\n// END PROTOTYPE\n/*\n-------------------------------------------------------------------------------\n{xrst_begin link_det_minor}\n\nSpeed Testing Gradient of Determinant by Minor Expansion\n########################################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN PROTOTYPE\n    // END PROTOTYPE\n}\n\nMethod\n******\nThe same template class :ref:`det_by_minor-name`\nis used by the different AD packages.\n\njob\n***\nSee the standard link specifications for :ref:`link_routines@job` .\n\nsize\n****\nSee the standard link specifications for :ref:`link_routines@size`\nIn addition, *size* is the number of rows and columns in\n*matrix* .\n\nrepeat\n******\nSee the standard link specifications for :ref:`link_routines@repeat` .\n\nmatrix\n******\nThe argument *matrix* is a vector with\n*size* * *size* elements.\nThe input value of its elements does not matter.\nThe output value of its elements is the last matrix that the\ngradient (or determinant) is computed for.\n\ngradient\n********\nThe argument *gradient* is a vector with\n*size* * *size* elements.\nThe input value of its elements does not matter.\nThe output value of its elements is the gradient of the\ndeterminant of *matrix* with respect to its elements.\n\ndouble\n======\nIn the case where *package* is ``double`` ,\nonly the first element of *gradient* is used and it is actually\nthe determinant value (the gradient value is not computed).\n\n{xrst_end link_det_minor}\n-----------------------------------------------------------------------------\n*/\n// ---------------------------------------------------------------------------\n// The routines below are documented in dev_link.omh\n// ---------------------------------------------------------------------------\nnamespace {\n    void time_det_minor_callback(size_t size, size_t repeat)\n    {   std::string           job(\"run\");\n        CppAD::vector<double> matrix(size * size);\n        CppAD::vector<double> gradient(size * size);\n        //\n        link_det_minor(job, size, repeat, matrix, gradient);\n        return;\n    }\n}\n// ---------------------------------------------------------------------------\nbool available_det_minor(void)\n{\n    size_t size   = 3;\n    size_t repeat = 0;\n    CppAD::vector<double> matrix(size * size);\n    CppAD::vector<double> gradient(size * size);\n    //\n    std::string job = \"setup\";\n    bool result = link_det_minor(job, size, repeat, matrix, gradient);\n    //\n    job = \"teardown\";\n    link_det_minor(job, size, repeat, matrix, gradient);\n    //\n    return result;\n}\n// ---------------------------------------------------------------------------\nbool correct_det_minor(bool is_package_double)\n{\n    size_t  size   = 3;\n    size_t  repeat = 1;\n    CppAD::vector<double> matrix(size * size);\n    CppAD::vector<double> gradient(size * size);\n    //\n    std::string job = \"setup\";\n    link_det_minor(job, size, repeat, matrix, gradient);\n    //\n    job = \"run\";\n    link_det_minor(job, size, repeat, matrix, gradient);\n    //\n    bool ok = CppAD::det_grad_33(matrix, gradient);\n    if( is_package_double )\n        ok = CppAD::det_33(matrix, gradient);\n    else\n        ok = CppAD::det_grad_33(matrix, gradient);\n    //\n    job = \"teardown\";\n    link_det_minor(job, size, repeat, matrix, gradient);\n    //\n    return ok;\n}\ndouble time_det_minor(double time_min, size_t size)\n{   CPPAD_ASSERT_UNKNOWN( size != 0 );\n    //\n    CppAD::vector<double> matrix(size * size);\n    CppAD::vector<double> gradient(size * size);\n    //\n    std::string job    = \"setup\";\n    size_t      repeat = 0;\n    link_det_minor(job, size, repeat, matrix, gradient);\n    //\n    // job is run in time_det_minor_callback\n    double time = CppAD::time_test(time_det_minor_callback, time_min, size);\n    //\n    job = \"teardown\";\n    link_det_minor(job, size, repeat, matrix, gradient);\n    //\n    return time;\n}\n// ---------------------------------------------------------------------------\n"
  },
  {
    "path": "speed/src/link_mat_mul.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/utility/vector.hpp>\n# include <cppad/utility/near_equal.hpp>\n# include <cppad/utility/time_test.hpp>\n// BEGIN PROTOTYPE\nextern bool link_mat_mul(\n    size_t                     size     ,\n    size_t                     repeat   ,\n    CppAD::vector<double>&     x        ,\n    CppAD::vector<double>&     z        ,\n    CppAD::vector<double>&     dz\n);\n// END PROTOTYPE\n/*\n-------------------------------------------------------------------------------\n{xrst_begin link_mat_mul}\n{xrst_spell\n    dz\n}\n\nSpeed Testing Derivative of Matrix Multiply\n###########################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN PROTOTYPE\n    // END PROTOTYPE\n}\n\nPurpose\n*******\nEach :ref:`speed_main@package`\nmust define a version of this routine as specified below.\nThis is used by the :ref:`speed_main-name` program\nto run the corresponding speed and correctness tests.\n\nReturn Value\n************\nIf this speed test is not yet\nsupported by a particular *package* ,\nthe corresponding return value for ``link_mat_mul``\nshould be ``false`` .\n\nn\n*\nThe argument *n* is the number of rows and columns\nin the square matrix *x* .\n\nrepeat\n******\nThe argument *repeat* is the number of different argument values\nthat the derivative of *z* (or just the value of *z* )\nwill be computed.\n\nx\n*\nThe argument *x* is a vector with\n*x* . ``size`` () = *size* * *size* elements.\nThe input value of its elements does not matter.\nThe output value of its elements is the last random matrix\nthat is multiplied and then summed to form *z* ;\n\n.. math::\n\n    x_{i,j} = x[ i * s + j ]\n\nwhere *s* = *size* .\n\nz\n*\nThe argument *z* is a vector with one element.\nThe input value of the element does not matter.\nThe output of its element the sum of the elements of\n*y* = *x* * *x* ; i.e.,\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        y_{i,j} & = & \\sum_{k=0}^{s-1} x_{i,k} x_{k, j}\n        \\\\\n        z       & = & \\sum_{i=0}^{s-1} \\sum_{j=0}^{s-1} y_{i,j}\n    \\end{eqnarray}\n\ndz\n**\nThe argument *dz* is a vector with\n*dz* . ``size`` () = *size* * *size* .\nThe input values of its elements do not matter.\nThe output value of its elements form the\nderivative of *z* with respect to *x* .\n\n{xrst_end link_mat_mul}\n-----------------------------------------------------------------------------\n*/\n// ---------------------------------------------------------------------------\n// The routines below are documented in dev_link.omh\n// ---------------------------------------------------------------------------\nnamespace {\n    void time_mat_mul_callback(size_t size, size_t repeat)\n    {   // free statically allocated memory\n        if( size == 0 && repeat == 0 )\n            return;\n        //\n        CppAD::vector<double>  x(size * size), z(1), dz(size * size);\n\n        link_mat_mul(size, repeat, x, z, dz);\n        return;\n    }\n}\n// ---------------------------------------------------------------------------\nbool available_mat_mul(void)\n{   size_t size   = 3;\n    size_t repeat = 1;\n    CppAD::vector<double>  x(size * size), z(1), dz(size * size);\n\n    return link_mat_mul(size, repeat, x, z, dz);\n}\n// --------------------------------------------------------------------------\nbool correct_mat_mul(bool is_package_double)\n{   size_t size   = 2;\n    size_t repeat = 1;\n    CppAD::vector<double>  x(size * size), z(1), dz(size * size);\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    link_mat_mul(size, repeat, x, z, dz);\n\n    double x00 = x[0 * size + 0];\n    double x01 = x[0 * size + 1];\n    double x10 = x[1 * size + 0];\n    double x11 = x[1 * size + 1];\n    bool ok = true;\n    double check;\n    if( is_package_double )\n    {   check  = 0;\n        check += x00 * x00 + x01 * x10; // y00\n        check += x00 * x01 + x01 * x11; // y01\n        check += x10 * x00 + x11 * x10; // y10\n        check += x10 * x01 + x11 * x11; // y11\n        ok &= CppAD::NearEqual(check, z[0], eps99, eps99);\n        return ok;\n    }\n    // partial w.r.t. x00\n    check = x00 + x00 + x01 + x10;\n    ok   &= CppAD::NearEqual(check, dz[0 * size + 0], eps99, eps99);\n    // partial w.r.t. x01\n    check = x10 + x00 + x11 + x10;\n    ok   &= CppAD::NearEqual(check, dz[0 * size + 1], eps99, eps99);\n    // partial w.r.t. x10\n    check = x01 + x00 + x11 + x01;\n    ok   &= CppAD::NearEqual(check, dz[1 * size + 0], eps99, eps99);\n    // partial w.r.t. x11\n    check = x01 + x10 + x11 + x11;\n    ok   &= CppAD::NearEqual(check, dz[1 * size + 1], eps99, eps99);\n\n    return ok;\n}\ndouble time_mat_mul(double time_min, size_t size)\n{   return CppAD::time_test(time_mat_mul_callback, time_min, size);\n}\n// --------------------------------------------------------------------------\n"
  },
  {
    "path": "speed/src/link_ode.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/utility/vector.hpp>\n# include <cppad/speed/ode_evaluate.hpp>\n# include <cppad/utility/near_equal.hpp>\n# include <cppad/utility/near_equal.hpp>\n# include <cppad/utility/time_test.hpp>\n// BEGIN PROTOTYPE\nextern bool link_ode(\n    size_t                     size       ,\n    size_t                     repeat     ,\n    CppAD::vector<double>&     x          ,\n    CppAD::vector<double>&     jacobian\n);\n// END PROTOTYPE\n/*\n-------------------------------------------------------------------------------\n{xrst_begin link_ode}\n{xrst_spell\n    fp\n}\n\nSpeed Testing the Jacobian of Ode Solution\n##########################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN PROTOTYPE\n    // END PROTOTYPE\n}\n\nPurpose\n*******\nEach :ref:`speed_main@package`\nmust define a version of this routine as specified below.\nThis is used by the :ref:`speed_main-name` program\nto run the corresponding speed and correctness tests.\n\nMethod\n******\nThe same template routine :ref:`ode_evaluate-name` is used\nby th different AD packages.\n\nf\n*\nThe function\n:math:`f : \\B{R}^n \\rightarrow \\B{R}^n` that is defined and computed by\nevaluating :ref:`ode_evaluate-name` with a call of the form\n\n    ``ode_evaluate`` ( *x* , *p* , *fp* )\n\nwith *p* equal to zero.\nCalls with the value *p* equal to one are used to check\nthe derivative values.\n\nReturn Value\n************\nIf this speed test is not yet\nsupported by a particular *package* ,\nthe corresponding return value for ``link_ode``\nshould be ``false`` .\n\nsize\n****\nThe argument *size*\nis the number of variables in the ordinary differential equations\nwhich is also equal to :math:`n`.\n\nrepeat\n******\nThe argument *repeat* is the number of times the\nJacobian is computed.\n\nx\n*\nThe argument *x* is a vector with :math:`n` elements.\nThe input value of the elements of *x* does not matter.\nOn output, it has been set to the\nargument value for which the function,\nor its derivative, is being evaluated.\nThe value of this vector must change with each repetition.\n\njacobian\n********\nThe argument *jacobian* is a vector with :math:`n^2` elements.\nThe input value of its elements does not matter.\nThe output value of its elements is the Jacobian of the function :math:`f(x)`\nthat corresponds to output value of *x* .\nTo be more specific, for\n:math:`i = 0 , \\ldots , n-1` and :math:`j = 0 , \\ldots , n-1`,\n\n.. math::\n\n    \\D{f[i]}{x[j]} (x) = jacobian [ i \\cdot n + j ]\n\ndouble\n======\nIn the case where *package* is ``double`` ,\nonly the first :math:`n` element of *jacobian*\nare modified and they are to the function value\n:math:`f(x)` corresponding to the output value of *x* .\n\n{xrst_end link_ode}\n-----------------------------------------------------------------------------\n*/\n// ---------------------------------------------------------------------------\n// The routines below are documented in dev_link.omh\n// ---------------------------------------------------------------------------\nnamespace {\n    void time_ode_callback(size_t n, size_t repeat)\n    {   // free statically allocated memory\n        if( n == 0 && repeat == 0 )\n            return;\n        //\n        CppAD::vector<double> x(n);\n        CppAD::vector<double> jacobian(n * n);\n        link_ode(n, repeat, x, jacobian);\n        return;\n    }\n}\n// ---------------------------------------------------------------------------\nbool available_ode(void)\n{   size_t n      = 1;\n    size_t repeat = 1;\n    CppAD::vector<double> x(n);\n    CppAD::vector<double> jacobian(n * n);\n\n    return link_ode(n, repeat, x, jacobian);\n}\n// ----------------------------------------------------------------------------\nbool correct_ode(bool is_package_double)\n{   bool ok       = true;\n\n    size_t n      = 5;\n    size_t repeat = 1;\n    CppAD::vector<double> x(n);\n    CppAD::vector<double> jacobian(n * n);\n\n    link_ode(n, repeat, x, jacobian);\n\n    size_t size = n * n;\n    size_t p = 1;\n    if( is_package_double )\n    {   p    = 0;  // check function value\n        size = n;\n    }\n    CppAD::vector<double> check(size);\n    CppAD::ode_evaluate(x, p, check);\n    size_t k;\n    for(k = 0; k < size; k++)\n        ok &= CppAD::NearEqual(check[k], jacobian[k], 1e-6, 1e-6);\n\n    return ok;\n}\ndouble time_ode(double time_min, size_t size)\n{   return CppAD::time_test(time_ode_callback, time_min, size);\n}\n// ----------------------------------------------------------------------------\n"
  },
  {
    "path": "speed/src/link_poly.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/utility/vector.hpp>\n# include <cppad/utility/poly.hpp>\n# include <cppad/utility/near_equal.hpp>\n# include <cppad/utility/time_test.hpp>\n// BEGIN PROTOTYPE\nextern bool link_poly(\n    size_t                     size     ,\n    size_t                     repeat   ,\n    CppAD::vector<double>&     a        ,\n    CppAD::vector<double>&     z        ,\n    CppAD::vector<double>&     ddp\n);\n// END PROTOTYPE\n/*\n-------------------------------------------------------------------------------\n{xrst_begin link_poly}\n{xrst_spell\n    ddp\n}\n\nSpeed Testing Second Derivative of a Polynomial\n###############################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN PROTOTYPE\n    // END PROTOTYPE\n}\n\nPurpose\n*******\nEach :ref:`speed_main@package`\nmust define a version of this routine as specified below.\nThis is used by the :ref:`speed_main-name` program\nto run the corresponding speed and correctness tests.\n\nMethod\n******\nThe same template routine :ref:`Poly-name` is used\nby the different AD packages.\n\nReturn Value\n************\nIf this speed test is not yet\nsupported by a particular *package* ,\nthe corresponding return value for ``link_poly``\nshould be ``false`` .\n\nsize\n****\nThe argument *size* is the order of the polynomial\n(the number of coefficients in the polynomial).\n\nrepeat\n******\nThe argument *repeat* is the number of different argument values\nthat the second derivative (or just the polynomial) will be computed at.\n\na\n*\nThe argument *a* is a vector with *size* elements.\nThe input value of its elements does not matter.\nThe output value of its elements is the coefficients of the\npolynomial that is differentiated\n(*i*-th element is coefficient of order *i* ).\n\nz\n*\nThe argument *z* is a vector with one element.\nThe input value of the element does not matter.\nThe output of its element is the polynomial argument value\nwere the last second derivative (or polynomial value) was computed.\n\nddp\n***\nThe argument *ddp* is a vector with one element.\nThe input value of its element does not matter.\nThe output value of its element is the\nsecond derivative of the polynomial with respect to it's argument value.\n\ndouble\n======\nIn the case where *package* is ``double`` ,\nthe output value of the element of *ddp*\nis the polynomial value (the second derivative is not computed).\n\n{xrst_end link_poly}\n-----------------------------------------------------------------------------\n*/\n// ---------------------------------------------------------------------------\n// The routines below are documented in dev_link.omh\n// ---------------------------------------------------------------------------\nnamespace {\nvoid time_poly_callback(size_t size, size_t repeat)\n    {   // free statically allocated memory\n        if( size == 0 && repeat == 0 )\n            return;\n        //\n        CppAD::vector<double>  a(size), z(1), ddp(1);\n\n        link_poly(size, repeat, a, z, ddp);\n        return;\n    }\n}\n// ---------------------------------------------------------------------------\nbool available_poly(void)\n{   size_t size   = 10;\n    size_t repeat = 1;\n    CppAD::vector<double>  a(size), z(1), ddp(1);\n\n    return link_poly(size, repeat, a, z, ddp);\n}\n// ---------------------------------------------------------------------------\nbool correct_poly(bool is_package_double)\n{   size_t size   = 10;\n    size_t repeat = 1;\n    CppAD::vector<double>  a(size), z(1), ddp(1);\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    link_poly(size, repeat, a, z, ddp);\n\n    size_t k;\n    double check;\n    if( is_package_double )\n        k = 0;\n    else\n        k = 2;\n    check = CppAD::Poly(k, a, z[0]);\n\n    bool ok = CppAD::NearEqual(check, ddp[0], eps99, eps99);\n    return ok;\n}\n// ---------------------------------------------------------------------------\ndouble time_poly(double time_min, size_t size)\n{   return CppAD::time_test(time_poly_callback, time_min, size);\n}\n// ---------------------------------------------------------------------------\n"
  },
  {
    "path": "speed/src/link_sparse_hessian.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/utility/near_equal.hpp>\n# include <cppad/speed/sparse_hes_fun.hpp>\n# include <cppad/speed/uniform_01.hpp>\n# include <cppad/utility/index_sort.hpp>\n# include <cppad/utility/time_test.hpp>\n\n# include \"link_sparse_hessian.hpp\"\n\nnamespace { // BEGIN_EMPTY_NAMESPACE\n\nusing CppAD::vector;\n\n/*\n------------------------------------------------------------------------------\n{xrst_begin sparse_hessian_choose_row_col dev}\n\nRandomly choose Hessian row and column indices\n##############################################\n\nNamespace\n*********\nThis function is in the empty namespace; i.e., it is only accessed\nby functions in this file.\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_choose_row_col\n    // END_choose_row_col\n}\n\nn\n*\nis number of rows and columns in the Hessian.\n\nrow\n***\nThe input size and elements of row do not matter.\nUpon return it is the chosen row indices.\n\ncol\n***\nThe input size and elements of col do not matter.\nUpon return it is the chosen column indices.\n\nOrder\n*****\nThe return row and column values are in row major order.\n\nDiagonal\n********\nThe diagonal is included in the result; i.e., for each *i*\nbetween zero and *n* ``-1`` , there is a *k* such that\n\n    *row* [ *k* ] == *col* [ *k* ] == *i*\n\n.\n\n{xrst_end sparse_hessian_choose_row_col}\n*/\n// BEGIN_choose_row_col\nvoid choose_row_col(\n    size_t                 n   ,\n    CppAD::vector<size_t>& row ,\n    CppAD::vector<size_t>& col )\n// END_choose_row_col\n{  using CppAD::vector;\n\n    // maximum number of entries per row\n    size_t max_per_row = 5;\n\n    // random choices for each row, and correspond sort order\n    vector<double> random_01(max_per_row);\n    vector<size_t> random_index(max_per_row), order(max_per_row);\n\n    // generate the row and column indices\n    row.resize(0);\n    col.resize(0);\n    for(size_t i = 0; i < n; i++)\n    {  // generate max_per_row random values between 0 and 1\n        CppAD::uniform_01(max_per_row, random_01);\n\n        // make sure the diagonal is in the result because\n        // sparse_hes_fun requires it\n        random_index[0] = i;\n\n        // convert to column indices between 0 and i\n        for(size_t k = 1; k < max_per_row; ++k)\n        {  random_index[k] = size_t( random_01[k] * double(i) );\n            random_index[k] = std::min(random_index[k], i);\n        }\n\n        // determine the sort order for the indices\n        CppAD::index_sort(random_index, order);\n\n        // set the indices for this row\n        for(size_t k = 0; k < max_per_row; k++)\n        {  size_t j = random_index[ order[k] ];\n            bool ok = k == 0;\n            if( ! ok )\n                ok = random_index[ order[k-1] ] < j;\n            if( ok )\n            {  row.push_back(i);\n                col.push_back(j);\n            }\n        }\n    }\n}\n} // END_EMPTY_NAMESPACE\n/*\n------------------------------------------------------------------------------\n{xrst_begin info_sparse_hessian dev}\n\nSparse Hessian Speed Test Information\n#####################################\n\nNamespace\n*********\nThis function is in the global namespace, not the CppAD namespace.\n\nSyntax\n******\n| ``info_spares_hessian`` ( *size* , *n_color* )\n\nsize\n****\nThis ``size_t`` value is equal to\n:ref:`speed_time_callback@size`\nin the corresponding call to ``time_sparse_hessian_callback`` .\n\nn_color\n*******\nThe input value of this *size_t* does not matter.\nUpon return, it is the value :ref:`link_sparse_hessian@n_color`\nreturned by the corresponding call to ``link_sparse_hessian`` .\n\n{xrst_end info_sparse_hessian}\n*/\nvoid info_sparse_hessian(size_t size, size_t& n_color)\n{   size_t n      = size;\n    size_t repeat = 1;\n    vector<size_t> row, col;\n    choose_row_col(n, row, col);\n\n    // note that cppad/speed/sparse_hessian.cpp assumes that x.size()\n    // is the size corresponding to this test\n    vector<double> x(n);\n    size_t K = row.size();\n    vector<double> hessian(K);\n    link_sparse_hessian(n, repeat, row, col, x, hessian, n_color);\n    return;\n}\n// ---------------------------------------------------------------------------\n// The routines below are documented in dev_link.omh\n// ---------------------------------------------------------------------------\nnamespace {\n    void time_sparse_hessian_callback(size_t size, size_t repeat)\n    {\n        static size_t previous_size = 0;\n        static vector<size_t> row, col;\n        //\n        // free statically allocated memory\n        if( size == 0 && repeat == 0 )\n        {   row.clear();\n            col.clear();\n            previous_size = size;\n            return;\n        }\n\n        size_t n = size;\n        vector<double> x(n);\n        if( size != previous_size )\n        {   choose_row_col(n, row, col);\n            previous_size = size;\n        }\n        size_t K = row.size();\n        vector<double> hessian(K);\n# ifndef NDEBUG\n        for(size_t k = 0; k < K; k++)\n            CPPAD_ASSERT_UNKNOWN( col[k] <= row[k] );\n# endif\n\n        // note that cppad/sparse_hessian.cpp assumes that x.size() == size\n        size_t n_color;\n        link_sparse_hessian(n, repeat, row, col, x, hessian, n_color);\n        return;\n    }\n}\n// ---------------------------------------------------------------------------\nbool available_sparse_hessian(void)\n{\n    size_t n      = 2;\n    size_t repeat = 1;\n    vector<double> x(n);\n    vector<size_t> row, col;\n    choose_row_col(n, row, col);\n    size_t K = row.size();\n    vector<double> hessian(K);\n\n    size_t n_color;\n    return link_sparse_hessian(n, repeat, row, col, x, hessian, n_color);\n}\n// ---------------------------------------------------------------------------\nbool correct_sparse_hessian(bool is_package_double)\n{\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    size_t n      = 10;\n    size_t repeat = 1;\n    vector<double> x(n);\n    vector<size_t> row, col;\n    choose_row_col(n, row, col);\n    size_t K = row.size();\n    vector<double> hessian(K);\n# ifndef NDEBUG\n    for(size_t k = 0; k < K; k++)\n        CPPAD_ASSERT_UNKNOWN( col[k] <= row[k] );\n# endif\n\n    // The double package assumes hessian.size() >= 1\n    CPPAD_ASSERT_UNKNOWN( K >= 1 );\n    size_t n_color;\n    link_sparse_hessian(n, repeat, row, col, x, hessian, n_color);\n\n    size_t order, size;\n    if( is_package_double)\n    {   order = 0;  // check function value\n        size  = 1;\n    }\n    else\n    {   order = 2;     // check hessian value\n        size  = K;\n    }\n    CppAD::vector<double> check(size);\n    CppAD::sparse_hes_fun<double>(n, x, row, col, order, check);\n    bool ok = true;\n    size_t k;\n    for(k = 0; k < size; k++)\n        ok &= CppAD::NearEqual(check[k], hessian[k], eps99, eps99);\n\n    return ok;\n}\n// ---------------------------------------------------------------------------\ndouble time_sparse_hessian(double time_min, size_t size)\n{   double time = CppAD::time_test(\n        time_sparse_hessian_callback, time_min, size\n    );\n    time_sparse_hessian_callback(0, 0);\n    return time;\n}\n"
  },
  {
    "path": "speed/src/link_sparse_hessian.hpp",
    "content": "# ifndef CPPAD_SPEED_SRC_LINK_SPARSE_HESSIAN_HPP\n# define CPPAD_SPEED_SRC_LINK_SPARSE_HESSIAN_HPP\n\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/utility/vector.hpp>\n// BEGIN PROTOTYPE\nextern bool link_sparse_hessian(\n    size_t                           size      ,\n    size_t                           repeat    ,\n    const CppAD::vector<size_t>&     row       ,\n    const CppAD::vector<size_t>&     col       ,\n    CppAD::vector<double>&           x         ,\n    CppAD::vector<double>&           hessian   ,\n    size_t&                          n_color\n);\n// END PROTOTYPE\n/*\n-------------------------------------------------------------------------------\n{xrst_begin link_sparse_hessian}\n\nLink to Speed Test Sparse Hessian\n#################################\n\nSyntax\n******\n| *ok* = ``link_sparse_hessian`` (\n| |tab| |tab| *size* , *repeat* , *row* , *col* , *x* , *hessian* , *n_color*\n| )\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN PROTOTYPE\n    // END PROTOTYPE\n}\n\nNamespace\n*********\nThe function ``link_sparse_hessian`` is in the global namespace,\nnot the ``CppAD`` namespace.\n\nMethod\n******\nGiven a row index vector :math:`row`\nand a second column vector :math:`col`,\nthe corresponding function\n:math:`f : \\B{R}^n \\rightarrow \\B{R}`\nis defined by :ref:`sparse_hes_fun-name` .\nThe non-zero entries in the Hessian of this function have\none of the following forms:\n\n.. math::\n\n    \\DD{f}{x[row[k]]}{x[row[k]]}\n    \\; , \\;\n    \\DD{f}{x[row[k]]}{x[col[k]]}\n    \\; , \\;\n    \\DD{f}{x[col[k]]}{x[row[k]]}\n    \\; , \\;\n    \\DD{f}{x[col[k]]}{x[col[k]]}\n\nfor some :math:`k` between zero and :math:`K-1`.\nAll the other terms of the Hessian are zero.\n\nSparsity Pattern\n****************\nThe combination of *row* and *col* determine\nthe sparsity pattern for the Hessian that is computed.\nThe calculation of this sparsity pattern,\nif necessary to compute the Hessian,\nis intended to be part of the timing for this test.\n\nsize\n****\nThe argument *size* , referred to as :math:`n` below,\nis the dimension of the domain space for :math:`f(x)`.\n\nrepeat\n******\nThe argument *repeat* is the number of times\nto repeat the test\n(with a different value for *x* corresponding to\neach repetition).\n\nx\n*\nThe size of *x* is :math:`n`; i.e., *x* . ``size`` () == *size* .\nThe input value of the elements of *x* does not matter.\nOn output, it has been set to the\nargument value for which the function,\nor its derivative, is being evaluated.\nThe value of this vector need not change with each repetition.\n\nrow\n***\nThe size of the vector *row* defines the value :math:`K`.\nThe input value of its elements does not matter.\nOn output,\nall the elements of *row* are between zero and :math:`n-1`.\n\ncol\n***\nThe argument *col* is a vector with size :math:`K`.\nThe input value of its elements does not matter.\nOn output,\nall the elements of *col* are between zero and :math:`n-1`.\n\nRow Major\n*********\nThe indices *row* and *col* are in row major order; i.e.,\nfor each *k* < *row* . ``size`` () ``-2``\n\n    *row* [ *k* ] <= *row* [ *k* +1]\n\nand if *row* [ *k* ] == *row* [ *k* +1] then\n\n    *col* [ *k* ] < *col* [ *k* +1]\n\nLower Triangular\n****************\nOnly the lower triangle of the Hessian is included.\n\n    *col* [ *k* ] <= *row* [ *k* ]\n\n.\n\nhessian\n*******\nThe size of *hessian* is *K* .\nThe input value of its elements does not matter.\nThe output value of its elements is the Hessian of the function :math:`f(x)`.\nTo be more specific, for\n:math:`k = 0 , \\ldots , K-1`,\n\n.. math::\n\n    \\DD{f}{ x[ \\R{row}[k] ] }{ x[ \\R{col}[k] ]} = \\R{hessian} [k]\n\nn_color\n*******\nThe input value of *n_color* does not matter. On output,\nit is the value :ref:`sparse_hessian@n_sweep` corresponding\nto the evaluation of *hessian* .\nThis is also the number of colors corresponding to the\n:ref:`coloring method<sparse_hessian@work@color_method>` ,\nwhich can be set to :ref:`speed_main@Sparsity Options@colpack` ,\nand is otherwise ``cppad`` .\n\ndouble\n======\nIn the case where *package* is ``double`` ,\nonly the first element of *hessian* is used and it is actually\nthe value of :math:`f(x)` (derivatives are not computed).\n\n{xrst_end link_sparse_hessian}\n-----------------------------------------------------------------------------\n*/\n\n# endif\n"
  },
  {
    "path": "speed/src/link_sparse_jacobian.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/utility/near_equal.hpp>\n# include <cppad/speed/sparse_jac_fun.hpp>\n# include <cppad/speed/uniform_01.hpp>\n# include <cppad/utility/index_sort.hpp>\n# include <cppad/utility/time_test.hpp>\n\n# include \"link_sparse_jacobian.hpp\"\n\nnamespace { // BEGIN_EMPTY_NAMESPACE\n    static CppAD::vector<size_t> info_size_vec_;\n    static CppAD::vector<size_t> info_n_color_vec_;\n    //\n    static size_t                callback_size_    = 0;\n    static size_t                callback_n_color_ = 0;\n    static CppAD::vector<size_t> callback_row_;\n    static CppAD::vector<size_t> callback_col_;\n/*\n------------------------------------------------------------------------------\n{xrst_begin sparse_jacobian_choose_row_col dev}\nRandomly Choose Row and Column Indices for Sparse Jacobian\n##########################################################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_CHOOSE_ROW_COL\n    // END_CHOOSE_ROW_COL\n}\n\nn\n*\nis the dimension of the domain space for the function f(x).\n\nm\n*\nis the dimension of the range space for the function f(x).\n\nrow\n***\nThe input size and elements of *row* do not matter.\nUpon return it is the chosen row indices.\n\ncol\n***\nThe input size and elements of *col* do not matter.\nUpon return it is the chosen column indices.\n\nRow Major\n*********\nThe result is in row major order.\n\n{xrst_end sparse_jacobian_choose_row_col}\n*/\n// BEGIN_CHOOSE_ROW_COL\nvoid choose_row_col(\n    size_t                 n    ,\n    size_t                 m    ,\n    CppAD::vector<size_t>& row  ,\n    CppAD::vector<size_t>& col  )\n// END_CHOOSE_ROW_COL\n{  using CppAD::vector;\n    //\n    // get random numbers for row and column indices\n    size_t K = 5 * std::max(m, n);\n    vector<double>  random(2 * K);\n    CppAD::uniform_01(2 * K, random);\n    //\n    // sort the temporary row and column choices\n    vector<size_t> key(K);\n    vector<size_t> ind(K);\n    for(size_t k = 0; k < K; k++)\n    {  // convert from [0,1] to row index\n        // avoid warning when converting double to size_t\n        size_t r = size_t( float( double(m) * random[k] ) );\n        r        = std::min(m-1, r);\n        // convert from [0,1] to column index\n        size_t c = size_t( float( double(n) * random[k + K] ) );\n        c        = std::min(n-1, c);\n        //\n        // key in row major order\n        key[k] = c + n * r;\n    }\n    CppAD::index_sort(key, ind);\n    //\n    // remove duplicates and set row, col in row major order\n    row.resize(0);\n    col.resize(0);\n    size_t k          = ind[0];\n    size_t c_previous = key[k] % n;\n    size_t r_previous = key[k] / n;\n    CPPAD_ASSERT_UNKNOWN( r_previous < m && c_previous < n );\n    CPPAD_ASSERT_UNKNOWN( key[k] == c_previous + n * r_previous );\n    row.push_back(r_previous);\n    col.push_back(c_previous);\n    for(size_t ell = 1; ell < K; ell++)\n    {  k        = ind[ell];\n        size_t c = key[k] % n;\n        size_t r = key[k] / n;\n        CPPAD_ASSERT_UNKNOWN( key[k] == c + n * r );\n        CPPAD_ASSERT_UNKNOWN( r < m && c < n );\n        if( r != r_previous || c != c_previous)\n        {  row.push_back(r);\n            col.push_back(c);\n        }\n        r_previous = r;\n        c_previous = c;\n    }\n# ifndef NDEBUG\n    size_t nnz = row.size();\n    CPPAD_ASSERT_UNKNOWN( nnz > 0 );\n    r_previous    = row[0];\n    c_previous    = col[0];\n    for(k = 1; k < nnz; ++k)\n    {  CPPAD_ASSERT_UNKNOWN( r_previous <= row[k] );\n        if( r_previous == row[k] )\n            CPPAD_ASSERT_UNKNOWN( c_previous <= col[k] );\n        r_previous = row[k];\n        c_previous = col[k];\n    }\n# endif\n}\n} // END_EMPTY_NAMESPACE\n/*\n------------------------------------------------------------------------------\n{xrst_begin info_sparse_jacobian dev}\n\nSparse Jacobian Speed Test Information\n######################################\n\nNamespace\n*********\nThis function is in the global namespace, not the CppAD namespace.\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN_INFO_SPARSE_JACOBIAN\n    // END_INFO_SPARSE_JACOBIAN\n}\n\nsize_vec\n********\nThe input value of *size_vec* does not matter.\nUpon return, it contains the values (in order) of\n:ref:`speed_time@size` in the previous call to\n``time_sparse_jacobian`` .\nOnly calls since the previous call to ``info_sparse_jacobian``\nare included.\n\nn_color\n*******\nThe input value of *n_color_vec* does not matter.\nUpon return, it has the same size as *size_vec* .\nThe value *n_color* [ *j* ] is the value of\n:ref:`link_sparse_jacobian@n_color`\nreturned by a call to ``link_sparse_jacobian``\nwith size equal to *size_vec* [ *j* ] .\n\n{xrst_end info_sparse_jacobian}\n*/\n// BEGIN_INFO_SPARSE_JACOBIAN\nvoid info_sparse_jacobian(\n    CppAD::vector<size_t>& size_vec    ,\n    CppAD::vector<size_t>& n_color_vec )\n// END_INFO_SPARSE_JACOBIAN\n{   using CppAD::vector;\n    //\n    size_vec.clear();\n    n_color_vec.clear();\n    //\n    size_vec.swap( info_size_vec_ );\n    n_color_vec.swap( info_n_color_vec_ );\n    //\n    return;\n}\n// ---------------------------------------------------------------------------\n// The routines below are documented in dev_link.omh\n// ---------------------------------------------------------------------------\nnamespace {\n    void time_sparse_jacobian_callback(size_t size, size_t repeat)\n    {   using CppAD::vector;\n        CPPAD_ASSERT_UNKNOWN( callback_size_ == size );\n        //\n        size_t          n = size;\n        size_t          m = 2 * n;\n        vector<double>  x(n);\n        size_t          nnz = callback_row_.size();\n        vector<double>  jacobian(nnz);\n        //\n        std::string    job = \"run\";\n        link_sparse_jacobian(\n            job,\n            n,\n            repeat,\n            m,\n            callback_row_,\n            callback_col_,\n            x,\n            jacobian,\n            callback_n_color_\n        );\n        return;\n    }\n}\n// ---------------------------------------------------------------------------\nbool available_sparse_jacobian(void)\n{   using CppAD::vector;\n    //\n    size_t n      = 3;\n    size_t m      = 2 * n;\n    vector<size_t> row, col;\n    choose_row_col(n, m, row, col);\n    //\n    size_t          repeat = 1;\n    vector<double>  x(n);\n    size_t          nnz = row.size();\n    vector<double>  jacobian(nnz);\n    size_t          n_color;\n    //\n    std::string job = \"setup\";\n    bool result = link_sparse_jacobian(\n        job, n, repeat, m, row, col, x, jacobian, n_color\n    );\n    //\n    job = \"teardown\";\n    link_sparse_jacobian(\n        job, n, repeat, m, row, col, x, jacobian, n_color\n    );\n    //\n    return result;\n}\n// ----------------------------------------------------------------------------\nbool correct_sparse_jacobian(bool is_package_double)\n{   using CppAD::vector;\n    bool ok       = true;\n    double eps    = 10. * CppAD::numeric_limits<double>::epsilon();\n    //\n    size_t n      = 10;\n    size_t m      = 2 * n;\n    vector<size_t> row, col;\n    choose_row_col(n, m, row, col);\n    //\n    // The double package assumes jacobian.size() >= m\n    size_t nnz = row.size();\n    CPPAD_ASSERT_UNKNOWN( nnz >= m );\n    //\n    size_t         repeat  = 1;\n    vector<double> x(n);\n    vector<double> jacobian(nnz);\n    size_t         n_color;\n    // ----------------------------------------------------------------------\n    // compute jacobian\n    std::string job = \"setup\";\n    link_sparse_jacobian(\n            job, n, repeat, m, row, col, x, jacobian, n_color\n    );\n    //\n    job = \"run\";\n    link_sparse_jacobian(\n            job, n, repeat, m, row, col, x, jacobian, n_color\n    );\n    // ----------------------------------------------------------------------\n    // check result\n    if( is_package_double)\n    {   // check f(x)\n        size_t order = 0;\n        vector<double> check(m);\n        CppAD::sparse_jac_fun<double>(m, n, x, row, col, order, check);\n        for(size_t i = 0; i < m; i++)\n            ok &= CppAD::NearEqual(check[i], jacobian[i], eps, eps);\n\n    }\n    else\n    {   // check f'(x)\n        size_t order = 1;\n        vector<double> check(nnz);\n        CppAD::sparse_jac_fun<double>(m, n, x, row, col, order, check);\n        for(size_t k = 0; k < nnz; k++)\n            ok &= CppAD::NearEqual(check[k], jacobian[k], eps, eps);\n    }\n    // -----------------------------------------------------------------------\n    job = \"teardown\";\n    link_sparse_jacobian(\n            job, n, repeat, m, row, col, x, jacobian, n_color\n    );\n    return ok;\n}\n// ----------------------------------------------------------------------------\ndouble time_sparse_jacobian(double time_min, size_t size)\n{   CPPAD_ASSERT_UNKNOWN( size != 0 );\n    using CppAD::vector;\n    //\n    // set callback_row_, callback_col_, callback_size_\n    callback_size_   = size;\n    size_t n         = size;\n    size_t m         = 2 * n;\n    choose_row_col(n, m, callback_row_, callback_col_);\n    //\n    size_t          repeat = 1;\n    vector<double>  x(n);\n    size_t          nnz = callback_row_.size();\n    vector<double>  jacobian(nnz);\n    size_t          n_color;\n    //\n    std::string  job = \"setup\";\n    link_sparse_jacobian(\n        job, n, repeat, m, callback_row_, callback_col_, x, jacobian, n_color\n    );\n    //\n    // job is run in time_sparse_jacoabian_callback\n    double time = CppAD::time_test(\n        time_sparse_jacobian_callback, time_min, size\n    );\n    if( callback_n_color_ == 0 )\n        callback_n_color_ = n_color;\n\n    job = \"teardown\";\n    link_sparse_jacobian(\n        job, n, repeat, m, callback_row_, callback_col_, x, jacobian, n_color\n    );\n    if( callback_n_color_ == 0 )\n        callback_n_color_ = n_color;\n    //\n    // memory allocated for callback_row_, callback_col_\n    callback_size_ = 0;\n    callback_row_.clear();\n    callback_col_.clear();\n    //\n    info_size_vec_.push_back(size);\n    info_n_color_vec_.push_back(callback_n_color_);\n    callback_n_color_ = 0;\n    //\n    return time;\n}\n"
  },
  {
    "path": "speed/src/link_sparse_jacobian.hpp",
    "content": "# ifndef CPPAD_SPEED_SRC_LINK_SPARSE_JACOBIAN_HPP\n# define CPPAD_SPEED_SRC_LINK_SPARSE_JACOBIAN_HPP\n\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/utility/vector.hpp>\n// BEGIN PROTOTYPE\nextern bool link_sparse_jacobian(\n    const std::string&                job       ,\n    size_t                            size      ,\n    size_t                            repeat    ,\n    size_t                            m         ,\n    const CppAD::vector<size_t>&      row       ,\n    const CppAD::vector<size_t>&      col       ,\n             CppAD::vector<double>&      x         ,\n             CppAD::vector<double>&      jacobian  ,\n             size_t&                     n_color\n);\n// END PROTOTYPE\n/*\n------------------------------------------------------------------------------\n{xrst_begin link_sparse_jacobian}\n\nSpeed Testing Sparse Jacobians\n##############################\n\nPrototype\n*********\n{xrst_literal\n    // BEGIN PROTOTYPE\n    // END PROTOTYPE\n}\n\nMethod\n******\nGiven a range space dimension *m*\nthe row index vector :math:`row`, and column index vector :math:`col`,\na corresponding function :math:`f : \\B{R}^n \\rightarrow \\B{R}^m`\nis defined by :ref:`sparse_jac_fun-name` .\nThe non-zero entries in the Jacobian of this function have the form\n\n.. math::\n\n    \\D{f[row[k]]}{x[col[k]]]}\n\nfor some :math:`k` between zero and *K* = *row* . ``size`` () ``-1`` .\nAll the other terms of the Jacobian are zero.\n\nSparsity Pattern\n****************\nThe combination of *row* and *col* determine\nthe sparsity pattern for the Jacobian that is differentiated.\nThe calculation of this sparsity pattern,\nif necessary to compute the Jacobian,\nis intended to be part of the timing for this test.\n\njob\n***\nSee the standard link specifications for :ref:`link_routines@job` .\n\nsize\n****\nSee the standard link specifications for :ref:`link_routines@size` .\nIn addition, *size* is referred to as :math:`n` below,\nis the dimension of the domain space for :math:`f(x)`.\n\nrepeat\n******\nSee the standard link specifications for :ref:`link_routines@repeat` .\n\nm\n*\nIs the dimension of the range space for the function :math:`f(x)`.\n\nrow\n***\nThe size of the vector *row* defines the value :math:`K`.\nThe input value of its elements does not matter.\nOn output,\nall the elements of *row* are between zero and :math:`m-1`.\n\ncol\n***\nThe argument *col* is a vector with size :math:`K`.\nThe input value of its elements does not matter.\nOn output,\nall the elements of *col* are between zero and :math:`n-1`.\n\nRow Major\n*********\nThe indices *row* and *col* are in row major order; i.e.,\nfor each *k* < *row* . ``size`` () ``-2``\n\n    *row* [ *k* ] <= *row* [ *k* +1]\n\nand if *row* [ *k* ] == *row* [ *k* +1] then\n\n    *col* [ *k* ] < *col* [ *k* +1]\n\nx\n*\nThe argument *x* has prototype\n\n    ``CppAD::vector<double>&`` *x*\n\nand its size is :math:`n`; i.e., *x* . ``size`` () == *size* .\nThe input value of the elements of *x* does not matter.\nOn output, it has been set to the\nargument value for which the function,\nor its derivative, is being evaluated and placed in *jacobian* .\nThe value of this vector need not change with each repetition.\n\njacobian\n********\nThe argument *jacobian* has prototype\n\n    ``CppAD::vector<double>&`` *jacobian*\n\nand its size is *K* .\nThe input value of its elements does not matter.\nThe output value of its elements is the Jacobian of the function :math:`f(x)`.\nTo be more specific, for\n:math:`k = 0 , \\ldots , K - 1`,\n\n.. math::\n\n    \\D{f[ \\R{row}[k] ]}{x[ \\R{col}[k] ]} (x) = \\R{jacobian} [k]\n\nn_color\n*******\nThe input value of *n_color* does not matter. On output,\nit has value zero or :ref:`sparse_jacobian@n_sweep` corresponding\nto the evaluation of *jacobian* .\nThis is also the number of colors corresponding to the\n:ref:`coloring method<sparse_jacobian@work@color_method>` ,\nwhich can be set to :ref:`speed_main@Sparsity Options@colpack` ,\nand is otherwise ``cppad`` .\nIf this routine returns an non-zero *n_color* for\nany *job* value, the non-zero value will be reported for this test.\n\ndouble\n======\nIn the case where *package* is ``double`` ,\nonly the first :math:`m`\nelements of *jacobian* are used and they are set to\nthe value of :math:`f(x)`.\n\n{xrst_end link_sparse_jacobian}\n-----------------------------------------------------------------------------\n*/\n# endif\n"
  },
  {
    "path": "speed/xpackage/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# Build the speed/xpackage directory tests\n# Inherit build type from ../CMakeList.txt\n\n# Set the install prefix for this package\nSET(xpackage_prefix \"/usr\")\n\n# Adds flags to the compiler command line for sources in the current directory\n# and below. This command can be used to add any flags, but it was originally\n# intended to add preprocessor definitions.\nADD_DEFINITIONS(\"-DCPPAD_XPACKAGE_SPEED\")\n\n# Local include directories to search (not in package_prefix/includdir)\nINCLUDE_DIRECTORIES(\n    ${CMAKE_CURRENT_SOURCE_DIR}/../src\n    ${xpackage_prefix}/include\n)\n\n# add_executable(<name> [WIN32] [MACOSX_BUNDLE] [EXCLUDE_FROM_ALL]\n#                 source1 source2 ... sourceN\n# )\nSET(source_list ../main.cpp\n    det_lu.cpp\n    det_minor.cpp\n    mat_mul.cpp\n    ode.cpp\n    poly.cpp\n    sparse_hessian.cpp\n    sparse_jacobian.cpp\n)\nset_compile_flags( speed_xpackage \"${cppad_debug_which}\" \"${source_list}\" )\n#\nADD_EXECUTABLE( speed_xpackage EXCLUDE_FROM_ALL ${source_list} )\n#\n# List of libraries to be linked into the specified target\nTARGET_LINK_LIBRARIES(speed_xpackage\n    ${cppad_lib}\n    ${colpack_libs}\n)\n# xpackage is an include file only library\nTARGET_LINK_LIBRARIES(speed_xpackage speed_src )\n\n# check_speed_xpackage\nadd_check_executable(check_speed xpackage \"correct 54321\")\n"
  },
  {
    "path": "speed/xpackage/det_lu.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin xpackage_det_lu.cpp}\n\nXpackage Speed: Gradient of Determinant Using Lu Factorization\n##############################################################\n\nSpecifications\n**************\n:ref:`link_det_lu-name`\n\nImplementation\n**************\nA xpackage version of this test is not yet implemented\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <map>\n# include <cppad/utility/vector.hpp>\n\n// list of possible options\nextern std::map<std::string, bool> global_option;\n\nbool link_det_lu(\n    size_t                     size     ,\n    size_t                     repeat   ,\n    CppAD::vector<double>     &matrix   ,\n    CppAD::vector<double>     &gradient )\n{  return false; }\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end xpackage_det_lu.cpp}\n*/\n"
  },
  {
    "path": "speed/xpackage/det_minor.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin xpackage_det_minor.cpp}\n\nXpackage Speed: Gradient of Determinant by Minor Expansion\n##########################################################\n\nSpecifications\n**************\n:ref:`link_det_minor-name`\n\nImplementation\n**************\n// a xpackage version of this test is not yet implemented\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <map>\n# include <cppad/utility/vector.hpp>\n\n// list of possible options\nextern std::map<std::string, bool> global_option;\n\nbool link_det_minor(\n    const std::string&         job      ,\n    size_t                     size     ,\n    size_t                     repeat   ,\n    CppAD::vector<double>     &matrix   ,\n    CppAD::vector<double>     &gradient )\n{  return false; }\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end xpackage_det_minor.cpp}\n*/\n"
  },
  {
    "path": "speed/xpackage/mat_mul.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin xpackage_mat_mul.cpp}\n\nXpackage Speed: Matrix Multiplication\n#####################################\n\nSpecifications\n**************\n:ref:`link_mat_mul-name`\n\nImplementation\n**************\n// a xpackage version of this test is not yet implemented\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <map>\n# include <cppad/utility/vector.hpp>\n\n// list of possible options\nextern std::map<std::string, bool> global_option;\n\nbool link_mat_mul(\n    size_t                           size     ,\n    size_t                           repeat   ,\n    CppAD::vector<double>&           x        ,\n    CppAD::vector<double>&           z        ,\n    CppAD::vector<double>&           dz       )\n{  return false; }\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end xpackage_mat_mul.cpp}\n*/\n"
  },
  {
    "path": "speed/xpackage/ode.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin xpackage_ode.cpp}\n\nXpackage Speed: Ode\n###################\n\nSpecifications\n**************\n:ref:`link_ode-name`\n\nImplementation\n**************\n// a xpackage version of this test is not yet implemented\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <map>\n# include <cppad/utility/vector.hpp>\n\n// list of possible options\nextern std::map<std::string, bool> global_option;\n\nbool link_ode(\n    size_t                     size       ,\n    size_t                     repeat     ,\n    CppAD::vector<double>      &x         ,\n    CppAD::vector<double>      &jacobian  )\n{  return false; }\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end xpackage_ode.cpp}\n*/\n"
  },
  {
    "path": "speed/xpackage/poly.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n{xrst_begin xpackage_poly.cpp}\n\nXpackage Speed: Second Derivative of a Polynomial\n#################################################\n\nSpecifications\n**************\n:ref:`link_poly-name`\n\nImplementation\n**************\n// a xpackage version of this test is not yet implemented\n{xrst_spell_off}\n{xrst_code cpp} */\n# include <map>\n# include <cppad/utility/vector.hpp>\n\n// list of possible options\nextern std::map<std::string, bool> global_option;\n\nbool link_poly(\n    size_t                     size     ,\n    size_t                     repeat   ,\n    CppAD::vector<double>     &a        ,  // coefficients of polynomial\n    CppAD::vector<double>     &z        ,  // polynomial argument value\n    CppAD::vector<double>     &ddp      )  // second derivative w.r.t z\n{  return false; }\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end xpackage_poly.cpp}\n*/\n"
  },
  {
    "path": "speed/xpackage/sparse_hessian.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/utility/vector.hpp>\n\n/*\n{xrst_begin xpackage_sparse_hessian.cpp}\n\nXpackage Speed: Sparse Hessian\n##############################\n\nSpecifications\n**************\n:ref:`link_sparse_hessian-name`\n\n{xrst_spell_off}\n{xrst_code cpp} */\n// A xpackage version of this test is not yet available\nbool link_sparse_hessian(\n    size_t                            size      ,\n    size_t                            repeat    ,\n    const CppAD::vector<size_t>&      row       ,\n    const CppAD::vector<size_t>&      col       ,\n    CppAD::vector<double>&            x         ,\n    CppAD::vector<double>&            hessian   ,\n    size_t&                           n_color\n)\n{  return false; }\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end xpackage_sparse_hessian.cpp}\n*/\n"
  },
  {
    "path": "speed/xpackage/sparse_jacobian.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cstring>\n# include <cppad/utility/vector.hpp>\n\n/*\n{xrst_begin xpackage_sparse_jacobian.cpp}\n\nXpackage Speed: sparse_jacobian\n###############################\n\nSpecifications\n**************\n:ref:`link_sparse_jacobian-name`\n\n{xrst_spell_off}\n{xrst_code cpp} */\n// A xpackage version of this test is not yet available\nbool link_sparse_jacobian(\n    const std::string&               job      ,\n    size_t                           size     ,\n    size_t                           repeat   ,\n    size_t                           m        ,\n    const CppAD::vector<size_t>&     row      ,\n    const CppAD::vector<size_t>&     col      ,\n    CppAD::vector<double>&           x        ,\n    CppAD::vector<double>&           jacobian ,\n    size_t&                          n_color  )\n{\n    return false;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end xpackage_sparse_jacobian.cpp}\n*/\n"
  },
  {
    "path": "speed/xpackage/speed_xpackage.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin speed_xpackage}\n{xrst_spell\n    cp\n    grep\n    ifdef\n    sed\n    txt\n}\n\nSpeed Test Example and Template for a New Package\n#################################################\n\nPurpose\n*******\nCppAD has a set of speed tests that are used to compare\nAD packages.\nThis section can be used as a starting point for linking a new package\nto he CppAD speed tests.\n\nFiles\n*****\nUse the following command, in the\n:ref:`download@Distribution Directory` ,\nto see which files link the example package ``xpackage``\nto the speed tests:\n\n    ``git grep -l xpackage``\n\nTemplate\n********\nSuppose *your_package* is the name of a package you\nwant to add to the speed tests.\nIf you are using a Unix system,\nexecuting the following commands in the distribution directory\nwill use ``xpackage`` as a template for your package:\n\n| |tab| ``cp -r speed/xpackage speed/`` *your_package*\n| |tab| ``for file in`` ` ``ls speed/`` *your_package* `\n| |tab| ``do``\n| |tab| |tab| ``sed -i speed/`` *your_package* / ``$file`` \\\\\n| |tab| |tab| |tab| ``-e`` ' ``s/xpackage/`` *your_package* /' \\\\\n| |tab| |tab| |tab| ``-e`` ' ``s/Xpackage/`` *Your_package* /' \\\\\n| |tab| |tab| |tab| ``-e`` ' ``s/CPPAD_XPACKAGE_SPEED/`` *YOUR_PACKAGE* /'\n| |tab| ``done``\n| |tab| ``git checkout speed/CMakeLists.txt``\n| |tab| ``sed -i speed/CMakeLists.txt`` \\\\\n| |tab| |tab| ``-e`` ' ``s/^.`` * ( ``xpackage`` )/ ``ADD_SUBDIRECTORY`` ( *your_package* )\\\\ ``n&/`` '\n| |tab| ``git checkout speed/main.cpp``\n| |tab| ``line1`` ='# ``ifdef CPPAD_`` *YOUR_PACKAGE* _ ``SPEED`` '\n| |tab| ``line2`` ='# ``define AD_PACKAGE`` \" *your_package* \"'\n| |tab| ``line3`` ='# ``endif`` '\n| |tab| ``sed -i speed/main.cpp`` \\\\\n| |tab| |tab| ``-e`` \"/ ``CPPAD_XPACKAGE_SPEED/s/^/$line1\\n$line2\\n$line3\\n/`` \"\n\nwhere *your_package* has been replaced by the name of the new package\n*Your_package* is a capitalized version of the name, and\n*YOUR_PACKAGE* is an all caps version of the name.\n\nRunning Tests\n*************\nStarting in the distribution directory,\nthe following commands will build the new package version of the tests:\n\n| |tab| ``bin/run_cmake.sh --no_optional``\n| |tab| ``cd build/speed/`` *your_package*\n| |tab| ``make check_speed_`` *your_package* ``VERBOSE`` =1\n\nThis should result in the following output:\n\n| |tab| ...\n| |tab| *your_package* _ ``det_lu_available`` = ``false``\n| |tab| *your_package* _ ``det_minor_available`` = ``false``\n| |tab| *your_package* _ ``mat_mul_available`` = ``false``\n| |tab| *your_package* _ ``ode_available`` = ``false``\n| |tab| *your_package* _ ``poly_available`` = ``false``\n| |tab| *your_package* _ ``sparse_hessian_available`` = ``false``\n| |tab| *your_package* _ ``sparse_jacobian_available`` = ``false``\n| |tab| ``All 0 correctness tests passed.``\n| |tab| ``No memory leak detected``\n| |tab| ``speed main: OK``\n| |tab| [100%] ``Built target check_speed_`` *your_package*\n\nYou can not edit one or more of the * . ``cpp`` files in the\n*your_package* directory so that the corresponding speed test\nis available and then run the corresponding test using the\n:ref:`speed_main-name` instructions.\nSee :ref:`speed_cppad-name` for examples of how to do this for each\nof the speed tests.\n\nContents\n********\n{xrst_toc_list\n    speed/xpackage/det_minor.cpp\n    speed/xpackage/det_lu.cpp\n    speed/xpackage/mat_mul.cpp\n    speed/xpackage/ode.cpp\n    speed/xpackage/poly.cpp\n    speed/xpackage/sparse_hessian.cpp\n    speed/xpackage/sparse_jacobian.cpp\n}\n\n{xrst_end speed_xpackage}\n"
  },
  {
    "path": "test_more/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# Build the test_more directory tests\n\n# initialize check_depends\nSET(check_test_more_depends \"\")\n\n# deprecated tests\nADD_SUBDIRECTORY(deprecated)\n\n# compare_c tests\n# clange-cl.exe seems to be confused about C files and gives an error message\n# saying that C++ forbids macroizing the keywords bool, true, and false.\nSTRING(REGEX MATCH \".*[/\\]clang-cl.exe\" match \"${CMAKE_C_COMPILER}\" )\nIF( NOT \"${match}\" STREQUAL \"${CMAKE_C_COMPILER}\" )\n    ADD_SUBDIRECTORY(compare_c)\nENDIF( )\n#\n# debug_rel tests\nIF( NOT \"${CMAKE_GENERATOR}\" STREQUAL \"NMake Makefiles\" )\n    # Visual studio rejects mixing debug and release flags\n    ADD_SUBDIRECTORY(debug_rel)\nENDIF( NOT \"${CMAKE_GENERATOR}\" STREQUAL \"NMake Makefiles\" )\n#\n# cppad_for_tmb tests\nIF( OpenMP_CXX_FOUND )\n    ADD_SUBDIRECTORY(cppad_for_tmb)\nENDIF( OpenMP_CXX_FOUND )\n\n# general tests\nADD_SUBDIRECTORY(general)\n\n# Add the check_example target\nADD_CUSTOM_TARGET(check_test_more \"\" DEPENDS ${check_test_more_depends})\nMESSAGE(STATUS \"make check_test_more: available\")\n\n# Change check depends in parent environment\nadd_to_list(check_depends check_test_more)\nSET(check_depends \"${check_depends}\" PARENT_SCOPE)\n"
  },
  {
    "path": "test_more/compare_c/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# {xrst_begin compare_c app}\n# {xrst_comment_ch #}\n#\n# Compare Speed of C and C++\n# ##########################\n#\n# Syntax\n# ******\n#\n#     ``test_more/compare_c/det_by_minor_c``\n#\n# ``test_more/compare_c/det_by_minor_cpp``\n#\n# Purpose\n# *******\n# Compares the speed of the exact same source code compiled\n# using C versus C++.\n#\n# Contents\n# ********\n# {xrst_toc_table\n#    test_more/compare_c/det_by_minor.c\n# }\n#\n# {xrst_end compare_c}\n# -----------------------------------------------------------------------------\n#\n# use cppad_debug_which to determine build type\nIF( \"${cppad_debug_which}\" STREQUAL debug_all )\n    SET(CMAKE_BUILD_TYPE DEBUG)\n    SET(all_cxx_flags \"${cppad_cxx_flags} ${CMAKE_CXX_FLAGSS_DEBUG}\")\nELSEIF( \"${cppad_debug_which}\" STREQUAL debug_odd )\n    SET(CMAKE_BUILD_TYPE DEBUG)\n    SET(all_cxx_flags \"${cppad_cxx_flags} ${CMAKE_CXX_FLAGSS_DEBUG}\")\nELSE( \"${cppad_debug_which}\" STREQUAL debug_odd )\n    SET(CMAKE_BUILD_TYPE RELEASE)\n    SET(all_cxx_flags \"${cppad_cxx_flags} ${CMAKE_CXX_FLAGSS_RELEASE}\")\nENDIF( \"${cppad_debug_which}\" STREQUAL debug_all )\n#\n# initialize check_test_more_compare_c\nSET(check_test_more_compare_c_depends \"\")\n#\n# Microsofts C compiler does not seem to work as part of a C++ project\nSTRING(FIND \"${CMAKE_C_COMPILER_ID}\" \"MSVC\" index)\nIF( \"${index}\" EQUAL \"-1\" )\n    ADD_SUBDIRECTORY(c)\nENDIF( )\nADD_SUBDIRECTORY(cpp)\n#\n# check_test_more_compare_c target\nADD_CUSTOM_TARGET( check_test_more_compare_c\n    DEPENDS ${check_test_more_compare_c_depends}\n)\nMESSAGE(STATUS \"make check_test_more_compare_c: available\")\n\n# Add check_test_more_compare_c to check depends in parent environment\nadd_to_list(check_test_more_depends check_test_more_compare_c)\nSET(check_test_more_depends \"${check_test_more_depends}\" PARENT_SCOPE)\n"
  },
  {
    "path": "test_more/compare_c/c/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-25 Bradley M. Bell\n# ----------------------------------------------------------------------------\n#\n# CMAKE_C_FLAGS\nIF( ${cppad_link_flags_has_m32} )\n    SET(CMAKE_C_FLAGS \"${CMAKE_C_FLAGS} -m32\")\nENDIF( )\n#\nADD_EXECUTABLE(test_more_compare_c_c EXCLUDE_FROM_ALL ../det_by_minor.c)\n#\n# List of libraries to be linked into the specified target\nTARGET_LINK_LIBRARIES(test_more_compare_c_c\n    ${cppad_lib}\n    ${colpack_libs}\n)\nSET_TARGET_PROPERTIES(test_more_compare_c_c PROPERTIES\n    LINK_OPTIONS \"${cppad_link_flags}\"\n)\n#\n# check_test_more_compare_c_c\nadd_check_executable(check_test_more_compare_c c)\n"
  },
  {
    "path": "test_more/compare_c/cpp/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-25 Bradley M. Bell\n# ----------------------------------------------------------------------------\n#\n# det_by_minor.cpp\nCONFIGURE_FILE(\n    ${CMAKE_CURRENT_SOURCE_DIR}/../det_by_minor.c\n    ${CMAKE_CURRENT_BINARY_DIR}/det_by_minor.cpp\n    COPYONLY\n)\nADD_EXECUTABLE(test_more_compare_c_cpp EXCLUDE_FROM_ALL det_by_minor.cpp)\n#\nSET_TARGET_PROPERTIES(\n    test_more_compare_c_cpp PROPERTIES COMPILE_FLAGS \"${all_cxx_flags}\"\n)\n#\n# List of libraries to be linked into the specified target\nTARGET_LINK_LIBRARIES(test_more_compare_c_cpp\n    ${cppad_lib}\n    ${colpack_libs}\n)\nSET_TARGET_PROPERTIES(test_more_compare_c_cpp PROPERTIES\n    LINK_OPTIONS \"${cppad_link_flags}\"\n)\n#\n# check_test_more_compare_c_cpp\nadd_check_executable(check_test_more_compare_c cpp)\n"
  },
  {
    "path": "test_more/compare_c/det_by_minor.c",
    "content": "/* $Id: */\n\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <assert.h>\n# include <stdlib.h>\n# include <math.h>\n# include <stdio.h>\n# include <stddef.h>\n# include <float.h>\n\n// In the case of plain C, we defined the type bool together with true, false\n# ifndef __cplusplus\n# define bool int\n# define true 1\n# define false 0\n# endif\n\n/*\n-------------------------------------------------------------------------------\n{xrst_begin det_of_minor_c app}\n\nDeterminant of a Minor\n######################\n\nSyntax\n******\n| *d* = ``det_of_minor`` ( *a* , *m* , *n* , *r* , *c* )\n\nPurpose\n*******\nreturns the determinant of a minor of the matrix :math:`A`\nusing expansion by minors.\nThe elements of the :math:`n \\times n` minor :math:`M`\nof the matrix :math:`A` are defined,\nfor :math:`i = 0 , \\ldots , n-1` and :math:`j = 0 , \\ldots , n-1`, by\n\n.. math::\n\n    M_{i,j} = A_{R(i), C(j)}\n\nwhere the functions\n:math:`R(i)` is defined by the :ref:`argument r<det_of_minor@r>` and\n:math:`C(j)` is defined by the :ref:`argument c<det_of_minor@c>` .\n\nThis function\nis for example and testing purposes only.\nExpansion by minors is chosen as an example because it uses\na lot of floating point operations yet does not require much source code\n(on the order of *m* factorial floating point operations and\nabout 70 lines of source code including comments).\nThis is not an efficient method for computing a determinant;\nfor example, using an LU factorization would be better.\n\nDeterminant of A\n****************\nIf the following conditions hold, the minor is the\nentire matrix :math:`A` and hence ``det_of_minor``\nwill return the determinant of :math:`A`:\n\n#. :math:`n = m`.\n#. for :math:`i = 0 , \\ldots , m-1`, :math:`r[i] = i+1`,\n   and :math:`r[m] = 0`.\n#. for :math:`j = 0 , \\ldots , m-1`, :math:`c[j] = j+1`,\n   and :math:`c[m] = 0`.\n\na\n*\nThe argument *a* has prototype\n\n    ``const double`` * *a*\n\nand is a vector with size :math:`m * m`.\nThe elements of the :math:`m \\times m` matrix :math:`A` are defined,\nfor :math:`i = 0 , \\ldots , m-1` and :math:`j = 0 , \\ldots , m-1`, by\n\n.. math::\n\n    A_{i,j} = a[ i * m + j]\n\nm\n*\nThe argument *m* has prototype\n\n    ``size_t`` *m*\n\nand is the size of the square matrix :math:`A`.\n\nn\n*\nThe argument *n* has prototype\n\n    ``size_t`` *n*\n\nand is the size of the square minor :math:`M`.\n\nr\n*\nThe argument *r* has prototype\n\n    ``size_t`` * *r*\n\nand is a vector with :math:`m + 1` elements.\nThis vector defines the function :math:`R(i)`\nwhich specifies the rows of the minor :math:`M`.\nTo be specific, the function :math:`R(i)`\nfor :math:`i = 0, \\ldots , n-1` is defined by\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        R(0)   & = & r[m]\n        \\\\\n        R(i+1) & = & r[ R(i) ]\n    \\end{eqnarray}\n\nAll the elements of *r* must have value\nless than or equal *m* .\nThe elements of vector *r* are modified during the computation,\nand restored to their original value before the return from\n``det_of_minor`` .\n\nc\n*\nThe argument *c* has prototype\n\n    ``size_t`` * *c*\n\nand is a vector with :math:`m + 1` elements\nThis vector defines the function :math:`C(i)`\nwhich specifies the rows of the minor :math:`M`.\nTo be specific, the function :math:`C(i)`\nfor :math:`j = 0, \\ldots , n-1` is defined by\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        C(0)   & = & c[m]\n        \\\\\n        C(j+1) & = & c[ C(j) ]\n    \\end{eqnarray}\n\nAll the elements of *c* must have value\nless than or equal *m* .\nThe elements of vector *c* are modified during the computation,\nand restored to their original value before the return from\n``det_of_minor`` .\n\nd\n*\nThe result *d* has prototype\n\n    ``double`` *d*\n\nand is equal to the determinant of the minor :math:`M`.\n\nSource Code\n***********\n{xrst_spell_off}\n{xrst_code cpp} */\ndouble det_of_minor(\n    const double*        a  ,\n    size_t               m  ,\n    size_t               n  ,\n    size_t*              r  ,\n    size_t*              c  )\n{  size_t R0, Cj, Cj1, j;\n    double detM, M0j, detS;\n    int s;\n\n    R0 = r[m]; /* R(0) */\n    Cj = c[m]; /* C(j)    (case j = 0) */\n    Cj1 = m;   /* C(j-1)  (case j = 0) */\n\n    /* check for 1 by 1 case */\n    if( n == 1 ) return a[ R0 * m + Cj ];\n\n    /* initialize determinant of the minor M */\n    detM = 0.;\n\n    /* initialize sign of factor for neat sub-minor */\n    s = 1;\n\n    /* remove row with index 0 in M from all the sub-minors of M */\n    r[m] = r[R0];\n\n    /* for each column of M */\n    for(j = 0; j < n; j++)\n    {  /* element with index (0,j) in the minor M */\n        M0j = a[ R0 * m + Cj ];\n\n        /* remove column with index j in M to form next sub-minor S of M */\n        c[Cj1] = c[Cj];\n\n        /* compute determinant of the current sub-minor S */\n        detS = det_of_minor(a, m, n - 1, r, c);\n\n        /* restore column Cj to representation of M as a minor of A */\n        c[Cj1] = Cj;\n\n        /* include this sub-minor term in the summation */\n        if( s > 0 )\n            detM = detM + M0j * detS;\n        else\n            detM = detM - M0j * detS;\n\n        /* advance to neat column of M */\n        Cj1 = Cj;\n        Cj  = c[Cj];\n        s   = - s;\n    }\n\n    /* restore row zero to the minor representation for M */\n    r[m] = R0;\n\n    /* return the determinant of the minor M */\n    return detM;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end det_of_minor_c}\n-------------------------------------------------------------------------------\n{xrst_begin det_by_minor_c app}\n\nCompute Determinant using Expansion by Minors\n#############################################\n\nSyntax\n******\n*d* = ``det_by_minor`` ( *a* , *n* )\n\nPurpose\n*******\nreturns the determinant of the matrix :math:`A`\nusing expansion by minors.\nThe elements of the :math:`n \\times n` minor :math:`M`\nof the matrix :math:`A` are defined,\nfor :math:`i = 0 , \\ldots , n-1` and :math:`j = 0 , \\ldots , n-1`, by\n\n.. math::\n\n    M_{i,j} = A_{i, j}\n\na\n*\nThe argument *a* has prototype\n\n    ``const double`` * *a*\n\nand is a vector with size :math:`m * m`.\nThe elements of the :math:`m \\times m` matrix :math:`A` are defined,\nfor :math:`i = 0 , \\ldots , m-1` and :math:`j = 0 , \\ldots , m-1`, by\n\n.. math::\n\n    A_{i,j} = a[ i * m + j]\n\nm\n*\nThe argument *m* has prototype\n\n    ``size_t`` *m*\n\nand is the number of rows (and columns) in the square matrix :math:`A`.\n\nSource Code\n***********\n{xrst_spell_off}\n{xrst_code cpp} */\ndouble det_by_minor(double* a, size_t m)\n{  size_t *r, *c, i;\n    double value;\n\n    r = (size_t*) malloc( (m+1) * sizeof(size_t) );\n    c = (size_t*) malloc( (m+1) * sizeof(size_t) );\n\n    assert(m <= 100);\n    for(i = 0; i < m; i++)\n    {  r[i] = i+1;\n        c[i] = i+1;\n    }\n    r[m] = 0;\n    c[m] = 0;\n\n    value = det_of_minor(a, m, m, r, c);\n\n    free(r);\n    free(c);\n    return value;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end det_by_minor_c}\n--------------------------------------------------------------------------\n{xrst_begin uniform_01_c app}\n\nSimulate a [0,1] Uniform Random Variate\n#######################################\n\nSyntax\n******\n\n    ``random_seed`` ( *seed* )\n\n``uniform_01`` ( *n* , *a* )\n\nPurpose\n*******\nThis routine is used to create random values for speed testing purposes.\n\nseed\n****\nThe argument *seed* has prototype\n\n    ``size_t`` *seed*\n\nIt specifies a seed\nfor the uniform random number generator.\n\nn\n*\nThe argument *n* has prototype\n\n    ``size_t`` *n*\n\nIt specifies the number of elements in the random vector *a* .\n\na\n*\nThe argument *a* has prototype\n\n    ``double`` * *a*\n\n.\nThe input value of the elements of *a* does not matter.\nUpon return, the elements of *a* are set to values\nrandomly sampled over the interval [0,1].\n\nSource Code\n***********\n{xrst_spell_off}\n{xrst_code cpp} */\nvoid random_seed(size_t seed)\n{  srand( (unsigned int) seed );\n}\nvoid uniform_01(size_t n, double* a)\n{  static double factor = 1. / (double) RAND_MAX;\n    while(n--)\n        a[n] = rand() * factor;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end uniform_01_c}\n------------------------------------------------------------------------------\n{xrst_begin correct_det_by_minor_c app}\n\nCorrectness Test of det_by_minor Routine\n########################################\n\nSyntax\n******\n*flag* = ``correct_det_by_minor`` ()\n\nflag\n****\nThe return value has prototype\n\n    ``bool`` *flag*\n\nIt value is ``1`` if the test passes and ``0`` otherwise.\n\nSource Code\n***********\n{xrst_spell_off}\n{xrst_code cpp} */\nbool correct_det_by_minor(void)\n{  double a[9], det, check;\n    double eps99 = 99.0 * DBL_EPSILON;\n\n    random_seed(123);\n    uniform_01(9, a);\n\n    /* compute determinant using expansion by minors */\n    det = det_by_minor(a, 3);\n\n    /* use expansion by minors to hand code the determinant  */\n    check = 0.;\n    check += a[0] * ( a[4] * a[8] - a[5] * a[7] );\n    check -= a[1] * ( a[3] * a[8] - a[5] * a[6] );\n    check += a[2] * ( a[3] * a[7] - a[4] * a[6] );\n\n    if( fabs(det / check - 1.0) < eps99 )\n        return true;\n    return false;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end correct_det_by_minor_c}\n------------------------------------------------------------------------------\n{xrst_begin repeat_det_by_minor_c app}\n\nRepeat det_by_minor Routine A Specified Number of Times\n#######################################################\n\nSyntax\n******\n``repeat_det_by_minor`` ( *repeat* , *size* )\n\nrepeat\n******\nThe argument has prototype\n\n    ``size_t`` *repeat*\n\nIt specifies the number of times to repeat the calculation.\n\nsize\n****\nThe argument has prototype\n\n    ``size_t`` *size*\n\nIt specifies the number of rows (and columns) in the square\nmatrix we are computing the determinant of.\n\nSource Code\n***********\n{xrst_spell_off}\n{xrst_code cpp} */\nvoid repeat_det_by_minor(size_t repeat, size_t size)\n{  double *a;\n    a = (double*) malloc( (size * size) * sizeof(double) );\n\n    while(repeat--)\n    {  uniform_01(size * size, a);\n        det_by_minor(a, size);\n    }\n\n    free(a);\n    return;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end repeat_det_by_minor_c}\n------------------------------------------------------------------------------\n{xrst_begin elapsed_seconds_c app}\n\nReturns Elapsed Number of Seconds\n#################################\n\nSyntax\n******\n*s* = ``elapsed_seconds`` ()\n\nPurpose\n*******\nThis routine is accurate to within .02 seconds\nIt does not necessary work for time intervals that are greater than a day.\n\ns\n*\nis a ``double`` equal to the\nnumber of seconds since the first call to ``elapsed_seconds`` .\n\nSource Code\n***********\n{xrst_spell_off}\n{xrst_code cpp} */\n# if _MSC_VER\n// ---------------------------------------------------------------------------\n// Microsoft version of timer\n# ifndef NOMINMAX\n# define NOMINMAX  // so windows.h does not define min and max as macros\n# endif\n# include <windows.h>\n# include <cassert>\ndouble elapsed_seconds(void)\n{  static bool       first_  = true;\n    static SYSTEMTIME st_;\n    double hour, minute, second, milli, diff;\n    SYSTEMTIME st;\n\n    if( first_ )\n    {  GetSystemTime(&st_);\n        first_ = false;\n        return 0.;\n    }\n    GetSystemTime(&st);\n\n    hour   = (double) st.wHour         - (double) st_.wHour;\n    minute = (double) st.wMinute       - (double) st_.wMinute;\n    second = (double) st.wSecond       - (double) st_.wSecond;\n    milli  = (double) st.wMilliseconds - (double) st_.wMilliseconds;\n\n    diff   = 1e-3*milli + second + 60.*minute + 3600.*hour;\n    if( diff < 0. )\n        diff += 3600.*24.;\n    assert( 0 <= diff && diff < 3600.*24. );\n\n    return diff;\n}\n# else\n// ---------------------------------------------------------------------------\n// Unix version of timer\n# include <sys/time.h>\ndouble elapsed_seconds(void)\n{  double sec, usec, diff;\n\n    static bool first_ = true;\n    static struct timeval tv_first;\n    struct timeval        tv;\n    if( first_ )\n    {  gettimeofday(&tv_first, NULL);\n        first_ = false;\n        return 0.;\n    }\n    gettimeofday(&tv, NULL);\n    assert( tv.tv_sec >= tv_first.tv_sec );\n\n    sec  = (double)(tv.tv_sec -  tv_first.tv_sec);\n    usec = (double)tv.tv_usec - (double)tv_first.tv_usec;\n    diff = sec + 1e-6*usec;\n\n    return diff;\n}\n# endif\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end elapsed_seconds_c}\n-----------------------------------------------------------------------------\n{xrst_begin time_det_by_minor_c app}\n\nDetermine Amount of Time to Execute det_by_minor\n################################################\n\nSyntax\n******\n*time* = ``time_test`` ( *size* , *time_min* )\n\nPurpose\n*******\nreports the amount of wall clock time for ``det_by_minor``\nto compute the determinant of a square matrix.\n\nThe *size* has prototype\n\n    ``size_t`` *size*\n\nIt specifies the number of rows (and columns) in the square matrix\nthat the determinant is being calculated for.\n\ntime_min\n********\nThe argument *time_min* has prototype\n\n    ``double`` *time_min*\n\nIt specifies the minimum amount of time in seconds\nthat the *test* routine should take.\nThe calculations is repeated the necessary number of times so that\nthis amount of execution time (or more) is reached.\n\ntime\n****\nThe return value *time* has prototype\n\n    ``double`` *time*\n\nand is the number of wall clock seconds that it took for\n``det_by_minor`` to compute its determinant\n(plus overhead which includes choosing a random matrix).\n\nSource Code\n***********\n{xrst_spell_off}\n{xrst_code cpp} */\ndouble time_det_by_minor(size_t size, double time_min)\n{  size_t repeat;\n    double s0, s1, time;\n    repeat = 0;\n    s0     = elapsed_seconds();\n    s1     = s0;\n    while( s1 - s0 < time_min )\n    {  if( repeat == 0 )\n            repeat = 1;\n        else\n            repeat = 2 * repeat;\n        s0     = elapsed_seconds();\n        repeat_det_by_minor(repeat, size);\n        s1     = elapsed_seconds();\n    }\n    time = (s1 - s0) / (double) repeat;\n    return time;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end time_det_by_minor_c}\n------------------------------------------------------------------------------\n{xrst_begin main_compare_c app}\n\nMain Program For Comparing C and C++ Speed\n##########################################\n\nSource Code\n***********\n{xrst_spell_off}\n{xrst_code cpp} */\nint main(void)\n{  bool flag;\n    size_t i;\n\n    random_seed(123);\n\n    printf(\"correct_det_by_minor: \");\n    flag = correct_det_by_minor();\n    if( flag )\n        printf(\"OK\\n\");\n    else\n        printf(\"Error\\n\");\n\n    for(i = 0; i < 5; i++)\n    {  double time_min = 1.0;\n        size_t size     = 2 + i * 2;\n        int   i_size    = (int) size;\n        printf(\"time_det_minor for %d x %d matrix = \", i_size, i_size);\n        printf(\"%g\\n\", time_det_by_minor(size, time_min) );\n    }\n\n    if( flag )\n        return 0;\n    return 1;\n}\n/* {xrst_code}\n{xrst_spell_on}\n\n{xrst_end main_compare_c}\n*/\n"
  },
  {
    "path": "test_more/cppad_for_tmb/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-25 Bradley M. Bell\n# ----------------------------------------------------------------------------\n#\n# Name for this text\nSET(name cppad_for_tmb)\n#\n# Add extra compiler flags to cppad_cxx_flags so set_compile_flags uses them.\n# This change only affects the cppad_for_tmb tests (NO PARENT_SCOPE).\nSET(cppad_cxx_flags \"${cppad_cxx_flags} ${OpenMP_CXX_FLAGS} -DCPPAD_FOR_TMB\")\n#\n# BEGIN_SORT_THIS_LINE_PLUS_2\nSET(source_list\n    ${name}.cpp\n    implicit_ctor.cpp\n    multi_atomic_three.cpp\n    multi_atomic_two.cpp\n    multi_chkpoint_one.cpp\n    multi_chkpoint_two.cpp\n    prefer_reverse.cpp\n)\n# END_SORT_THIS_LINE_MINUS_2\n\nset_compile_flags(\n    test_more_${name} \"${cppad_debug_which}\" \"${source_list}\"\n)\n#\n# now that we have the properties, add the executable\nADD_EXECUTABLE( test_more_${name} EXCLUDE_FROM_ALL ${source_list} )\nTARGET_LINK_LIBRARIES(test_more_${name} PRIVATE\n    ${cppad_lib}\n    ${colpack_libs}\n    ${OpenMP_CXX_LIBRARIES}\n)\n#\n# Extra flags used by linker for openmp support\nSET(CMAKE_EXE_LINKER_FLAGS ${OpenMP_CXX_FLAGS} ${cppad_link_flags} )\n#\n# check_test_more_${name}\nadd_check_executable(check_test_more ${name})\n"
  },
  {
    "path": "test_more/cppad_for_tmb/cppad_for_tmb.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/cppad.hpp>\n# include <omp.h>\n\nextern bool implicit_ctor(void);\nextern bool prefer_reverse(void);\nextern bool multi_atomic_two(void);\nextern bool multi_atomic_three(void);\nextern bool multi_chkpoint_one(void);\nextern bool multi_chkpoint_two(void);\n\nint main(void)\n{   std::string group = \"test_more/cppad_for_tmb\";\n    size_t      width = 30;\n    CppAD::test_boolofvoid Run(group, width);\n\n    // This line is used by test_one.sh\n\n    Run( implicit_ctor,            \"implicit_ctor\"          );\n    Run( prefer_reverse,           \"prefer_reverse\"         );\n    Run( multi_atomic_two,         \"multi_atomic_two\"       );\n    Run( multi_atomic_three,       \"multi_atomic_three\"     );\n    Run( multi_chkpoint_one,       \"multi_chkpoint_one\"     );\n    Run( multi_chkpoint_two,       \"multi_chkpoint_two\"     );\n\n    // check for memory leak\n    bool memory_ok = CppAD::thread_alloc::free_all();\n    // print summary at end\n    bool ok  = Run.summary(memory_ok);\n    //\n    return static_cast<int>( ! ok );\n}\n"
  },
  {
    "path": "test_more/cppad_for_tmb/implicit_ctor.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/cppad.hpp>\n\n// implicit constructor from double\nbool implicit_ctor(void)\n{   using CppAD::AD;\n    bool ok = true;\n    //\n    AD< AD<double> > x = 5.0;\n    ok &= Value(x) == 5.0;\n    //\n    return ok;\n}\n"
  },
  {
    "path": "test_more/cppad_for_tmb/multi_atomic_three.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/cppad.hpp>\n# include <omp.h>\n\nnamespace {\n    using CppAD::vector;\n    typedef CPPAD_TESTVECTOR(double)               d_vector;\n    typedef CPPAD_TESTVECTOR( CppAD::AD<double> ) ad_vector;\n    typedef CppAD::ad_type_enum                   ad_type_enum;\n\n\n    // --------------------------------------------------------------------\n    class long_sum_atomic : public CppAD::atomic_three<double> {\n    private:\n        const size_t length_of_sum_;\n    public:\n        // constructor\n        long_sum_atomic(const std::string& name, size_t length_of_sum)\n        :\n        CppAD::atomic_three<double>(name) ,\n        length_of_sum_(length_of_sum)\n        { }\n        // for_type\n        virtual bool for_type(\n            const vector<double>&       parameter_x ,\n            const vector<ad_type_enum>& type_x      ,\n            vector<ad_type_enum>&       type_y      )\n        {   bool ok = parameter_x.size() == 1;\n            ok     &= type_x.size() == 1;\n            ok     &= type_y.size() == 1;\n            if( ! ok )\n                return false;\n            type_y[0] = type_x[0];\n            return true;\n        }\n        // forward\n        virtual bool forward(\n            const vector<double>&       parameter_x ,\n            const vector<ad_type_enum>& type_x      ,\n            size_t                      need_y      ,\n            size_t                      order_low   ,\n            size_t                      order_up    ,\n            const vector<double>&       taylor_x    ,\n            vector<double>&             taylor_y    )\n        {\n            // check for errors in usage\n            bool ok = order_low == 0 && order_up == 0;\n            ok     &= taylor_x.size() == 1;\n            ok     &= taylor_y.size() == 1;\n            ok     &= type_x.size() <= 1;\n            if( ! ok )\n                return false;\n\n            // value information\n            taylor_y[0] = 0.0;\n            for(size_t i = 0; i < length_of_sum_; ++i)\n                taylor_y[0] += taylor_x[0];\n\n            return true;\n        }\n    };\n    // --------------------------------------------------------------------\n\n    // inform CppAD if we are in parallel mode\n    bool in_parallel(void)\n    {   return omp_in_parallel() != 0; }\n    //\n    // inform CppAD of the current thread number\n    size_t thread_num(void)\n    {   return static_cast<size_t>( omp_get_thread_num() ); }\n\n}\n\n// multi_thread_checkpoint\nbool multi_atomic_three(void)\n{   bool ok = true;\n\n    // OpenMP setup\n    size_t num_threads = 4;      // number of threads\n    omp_set_dynamic(0);          // turn off dynamic thread adjustment\n    omp_set_num_threads( int(num_threads) );  // set number of OMP threads\n\n    // check that multi-threading is possible on this machine\n    if( omp_get_max_threads() < 2 )\n    {   std::cout << \"This machine does not support multi-threading: \";\n    }\n\n    // create checkpoint version of algorithm\n    size_t n(1), m(1);\n    ad_vector ax(n), ay(m);\n    ax[0] = 2.0;\n    size_t length_of_sum = 5000;\n    long_sum_atomic atom_fun(\"long_sum\", length_of_sum);\n\n    // setup for using CppAD in parallel mode\n    CppAD::thread_alloc::parallel_setup(num_threads, in_parallel, thread_num);\n    CppAD::thread_alloc::hold_memory(true);\n    CppAD::parallel_ad<double>();\n\n    // place to hold result for each thread\n    d_vector y(num_threads);\n    for(size_t thread = 0; thread < num_threads; thread++)\n        y[thread] = 0.0;\n\n    # pragma omp parallel for\n    for(int thread = 0; thread < int(num_threads); thread++)\n    {   ad_vector au(n), av(m);\n        au[0] = 1.0;\n        CppAD::Independent(au);\n        atom_fun(au, av);\n        CppAD::ADFun<double> f(au, av);\n        //\n        d_vector x(n), v(m);\n        x[0]      = double( thread + 1 );\n        v         = f.Forward(0, x);\n        //\n        // this assignment has false sharing; i.e., will case cache resets\n        // (conversion avoids boost vector conversion warning)\n        y[size_t(thread)] = v[0];\n    }\n\n    // check the results\n    for(size_t thread = 0; thread < num_threads; thread++)\n    {   double check = double( length_of_sum * (thread + 1) );\n        ok          &= check == y[thread];\n    }\n    return ok;\n}\n"
  },
  {
    "path": "test_more/cppad_for_tmb/multi_atomic_two.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/cppad.hpp>\n# include <omp.h>\n\nnamespace {\n\n    using CppAD::vector;\n    typedef CPPAD_TESTVECTOR(double)               d_vector;\n    typedef CPPAD_TESTVECTOR( CppAD::AD<double> ) ad_vector;\n\n\n    // --------------------------------------------------------------------\n    class long_sum_atomic : public CppAD::atomic_base<double> {\n    private:\n        const size_t length_of_sum_;\n    public:\n        // constructor\n        long_sum_atomic(const std::string& name, size_t length_of_sum)\n        :\n        CppAD::atomic_base<double>(name) ,\n        length_of_sum_(length_of_sum)\n        { }\n        // forward (only implement zero order)\n        virtual bool forward(\n            size_t                p  ,\n            size_t                q  ,\n            const vector<bool>&   vx ,\n            vector<bool>&         vy ,\n            const vector<double>& tx ,\n            vector<double>&       ty )\n        {\n            // check for errors in usage\n            bool ok = p == 0 && q == 0;\n            ok     &= tx.size() == 1;\n            ok     &= ty.size() == 1;\n            ok     &= vx.size() <= 1;\n            if( ! ok )\n                return false;\n\n            // variable information\n            if( vx.size() > 0 )\n                vy[0] = vx[0];\n\n            // value information\n            ty[0] = 0.0;\n            for(size_t i = 0; i < length_of_sum_; ++i)\n                ty[0] += tx[0];\n\n            return ok;\n        }\n    };\n    // --------------------------------------------------------------------\n\n    // inform CppAD if we are in parallel mode\n    bool in_parallel(void)\n    {   return omp_in_parallel() != 0; }\n    //\n    // inform CppAD of the current thread number\n    size_t thread_num(void)\n    {   return static_cast<size_t>( omp_get_thread_num() ); }\n\n}\n\n// multi_thread_checkpoint\nbool multi_atomic_two(void)\n{   bool ok = true;\n\n    // OpenMP setup\n    size_t num_threads = 4;      // number of threads\n    omp_set_dynamic(0);          // turn off dynamic thread adjustment\n    omp_set_num_threads( int(num_threads) );  // set number of OMP threads\n\n    // check that multi-threading is possible on this machine\n    if( omp_get_max_threads() < 2 )\n    {   std::cout << \"This machine does not support multi-threading: \";\n    }\n\n    // create checkpoint version of algorithm\n    size_t n(1), m(1);\n    ad_vector ax(n), ay(m);\n    ax[0] = 2.0;\n    size_t length_of_sum = 5000;\n    long_sum_atomic atom_fun(\"long_sum\", length_of_sum);\n\n    // setup for using CppAD in parallel mode\n    CppAD::thread_alloc::parallel_setup(num_threads, in_parallel, thread_num);\n    CppAD::thread_alloc::hold_memory(true);\n    CppAD::parallel_ad<double>();\n\n    // place to hold result for each thread\n    d_vector y(num_threads);\n    for(size_t thread = 0; thread < num_threads; thread++)\n        y[thread] = 0.0;\n\n    # pragma omp parallel for\n    for(int thread = 0; thread < int(num_threads); thread++)\n    {   ad_vector au(n), av(m);\n        au[0] = 1.0;\n        CppAD::Independent(au);\n        atom_fun(au, av);\n        CppAD::ADFun<double> f(au, av);\n        //\n        d_vector x(n), v(m);\n        x[0]      = double( thread + 1 );\n        v         = f.Forward(0, x);\n        //\n        // this assignment has false sharing; i.e., will case cache resets\n        // (conversion avoids boost vector conversion warning)\n        y[size_t(thread)] = v[0];\n    }\n\n    // check the results\n    for(size_t thread = 0; thread < num_threads; thread++)\n    {   double check = double( length_of_sum * (thread + 1) );\n        ok          &= check == y[thread];\n    }\n    return ok;\n}\n"
  },
  {
    "path": "test_more/cppad_for_tmb/multi_chkpoint_one.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/cppad.hpp>\n# include <omp.h>\n\nnamespace {\n\n    typedef CPPAD_TESTVECTOR(double)               d_vector;\n    typedef CPPAD_TESTVECTOR( CppAD::AD<double> ) ad_vector;\n\n\n    // algorithm that we are checkpoingint\n    const size_t length_of_sum_ = 5000;\n    void long_sum_algo(const ad_vector& ax, ad_vector& ay)\n    {   ay[0] = 0.0;\n        for(size_t i = 0; i < length_of_sum_; ++i)\n            ay[0] += ax[0];\n        return;\n    }\n    // inform CppAD if we are in parallel mode\n    bool in_parallel(void)\n    {   return omp_in_parallel() != 0; }\n    //\n    // inform CppAD of the current thread number\n    size_t thread_num(void)\n    {   return static_cast<size_t>( omp_get_thread_num() ); }\n\n}\n\n// multi_thread_checkpoint\nbool multi_chkpoint_one(void)\n{   bool ok = true;\n\n    // OpenMP setup\n    size_t num_threads = 4;      // number of threads\n    omp_set_dynamic(0);          // turn off dynamic thread adjustment\n    omp_set_num_threads( int(num_threads) );  // set number of OMP threads\n\n    // check that multi-threading is possible on this machine\n    if( omp_get_max_threads() < 2 )\n    {   std::cout << \"This machine does not support multi-threading: \";\n    }\n\n    // create checkpoint version of algorithm\n    size_t n(1), m(1);\n    ad_vector ax(n), ay(m);\n    ax[0] = 2.0;\n    CppAD::atomic_base<double>::option_enum sparsity =\n        CppAD::atomic_base<double>::set_sparsity_enum;\n    bool optimize = false;\n    CppAD::checkpoint<double> atom_fun(\n        \"long_sum\", long_sum_algo, ax, ay, sparsity, optimize\n    );\n\n    // setup for using CppAD in parallel mode\n    CppAD::thread_alloc::parallel_setup(num_threads, in_parallel, thread_num);\n    CppAD::thread_alloc::hold_memory(true);\n    CppAD::parallel_ad<double>();\n\n    // place to hold result for each thread\n    d_vector y(num_threads);\n    for(size_t thread = 0; thread < num_threads; thread++)\n        y[thread] = 0.0;\n\n    # pragma omp parallel for\n    for(int thread = 0; thread < int(num_threads); thread++)\n    {   ad_vector au(n), av(m);\n        au[0] = 1.0;\n        CppAD::Independent(au);\n        atom_fun(au, av);\n        CppAD::ADFun<double> f(au, av);\n        //\n        d_vector x(n), v(m);\n        x[0]      = double( thread + 1 );\n        v         = f.Forward(0, x);\n        //\n        // this assignment has false sharing; i.e., will case cache resets\n        // (conversion avoids boost vector conversion warning)\n        y[size_t(thread)] = v[0];\n    }\n\n    // check the results\n    for(size_t thread = 0; thread < num_threads; thread++)\n    {   double check = double( length_of_sum_ * (thread + 1) );\n        ok          &= check == y[thread];\n    }\n    return ok;\n}\n"
  },
  {
    "path": "test_more/cppad_for_tmb/multi_chkpoint_two.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/cppad.hpp>\n# include <omp.h>\n\nnamespace {\n\n    typedef CPPAD_TESTVECTOR(double)               d_vector;\n    typedef CPPAD_TESTVECTOR( CppAD::AD<double> ) ad_vector;\n\n\n    // algorithm that we are checkpoingint\n    const size_t length_of_sum_ = 5000;\n    void long_sum_algo(const ad_vector& ax, ad_vector& ay)\n    {   ay[0] = 0.0;\n        for(size_t i = 0; i < length_of_sum_; ++i)\n            ay[0] += ax[0];\n        return;\n    }\n    // inform CppAD if we are in parallel mode\n    bool in_parallel(void)\n    {   return omp_in_parallel() != 0; }\n    //\n    // inform CppAD of the current thread number\n    size_t thread_num(void)\n    {   return static_cast<size_t>( omp_get_thread_num() ); }\n\n}\n\n// multi_thread_chkpoint_two\nbool multi_chkpoint_two(void)\n{   bool ok = true;\n\n    // OpenMP setup\n    size_t num_threads = 4;      // number of threads\n    omp_set_dynamic(0);          // turn off dynamic thread adjustment\n    omp_set_num_threads( int(num_threads) );  // set number of OMP threads\n\n    // check that multi-threading is possible on this machine\n    if( omp_get_max_threads() < 2 )\n    {   std::cout << \"This machine does not support multi-threading: \";\n    }\n\n    // create ADFun corresponding to long_sum_algo\n    size_t n(1), m(1);\n    ad_vector ax(n), ay(m);\n    ax[0] = 2.0;\n    CppAD::Independent(ax);\n    long_sum_algo(ax, ay);\n    CppAD::ADFun<double> fun(ax, ay);\n\n    // create chkpoint_two version of algorithm\n    const char* name      = \"long_sum\";\n    bool internal_bool    = false;\n    bool use_hes_sparsity = false;\n    bool use_base2ad      = false;\n    bool use_in_parallel  = true;\n    CppAD::chkpoint_two<double> chk_fun( fun, name,\n        internal_bool, use_hes_sparsity, use_base2ad, use_in_parallel\n    );\n    // setup for using CppAD in parallel mode\n    CppAD::thread_alloc::parallel_setup(num_threads, in_parallel, thread_num);\n    CppAD::thread_alloc::hold_memory(true);\n    CppAD::parallel_ad<double>();\n\n    // place to hold result for each thread\n    d_vector y(num_threads);\n    for(size_t thread = 0; thread < num_threads; thread++)\n        y[thread] = 0.0;\n\n    # pragma omp parallel for\n    for(int thread = 0; thread < int(num_threads); thread++)\n    {   ad_vector au(n), av(m);\n        au[0] = 1.0;\n        CppAD::Independent(au);\n        chk_fun(au, av);\n        CppAD::ADFun<double> f(au, av);\n        //\n        d_vector x(n), v(m);\n        x[0]      = double( thread + 1 );\n        v         = f.Forward(0, x);\n        //\n        // this assignment has false sharing; i.e., will case cache resets\n        // (conversion avoids boost vector conversion warning)\n        y[size_t(thread)] = v[0];\n    }\n\n    // check the results\n    for(size_t thread = 0; thread < num_threads; thread++)\n    {   double check = double( length_of_sum_ * (thread + 1) );\n        ok          &= check == y[thread];\n    }\n    return ok;\n}\n"
  },
  {
    "path": "test_more/cppad_for_tmb/prefer_reverse.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/cppad.hpp>\n# include <omp.h>\n\nnamespace { // BEGIN_EMPTY_NAMESPACE\n\nusing CppAD::vector;\n\n// ----------------------------------------------------------------------------\n// prefer reverse mode during computation of Jacobians\n\n// example_tmb_atomic\nclass example_tmb_atomic : public CppAD::atomic_base<double> {\npublic:\n    // constructor\n    example_tmb_atomic(const std::string& name)\n    : CppAD::atomic_base<double>(name)\n    { }\n    // forward (only implement zero order)\n    virtual bool forward(\n        size_t                p  ,\n        size_t                q  ,\n        const vector<bool>&   vx ,\n        vector<bool>&         vy ,\n        const vector<double>& tx ,\n        vector<double>&       ty )\n    {\n        // check for errors in usage\n        bool ok = p == 0 && q == 0;\n        ok     &= tx.size() == 1;\n        ok     &= ty.size() == 1;\n        ok     &= vx.size() <= 1;\n        if( ! ok )\n            return false;\n\n        // variable information\n        if( vx.size() > 0 )\n            vy[0] = vx[0];\n\n        // y = 1 / x\n        ty[0] = 1.0 / tx[0];\n\n        return ok;\n    }\n    // reverse (implement first order)\n    virtual bool reverse(\n        size_t                q  ,\n        const vector<double>& tx ,\n        const vector<double>& ty ,\n        vector<double>&       px ,\n        const vector<double>& py )\n    {\n        // check for errors in usage\n        bool ok = q == 0;\n        ok     &= tx.size() == 1;\n        ok     &= ty.size() == 1;\n        ok     &= px.size() == 1;\n        ok     &= py.size() == 1;\n        if( ! ok )\n            return false;\n\n        // y = 1 / x\n        // dy/dx = - 1 / (x * x)\n        double dy_dx = -1.0 / ( tx[0] * tx[0] );\n        px[0]        = py[0] * dy_dx;\n\n        return ok;\n    }\n};\n\n} // END_EMPTY_NAMESPACE\n\nbool prefer_reverse(void)\n{   bool ok = true;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // Create atomic functions\n    example_tmb_atomic afun(\"reciprocal\");\n\n    // Declare independent variables\n    size_t n = 1;\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) ax(n);\n    ax[0] = 5.0;\n    CppAD::Independent(ax);\n\n    // Compute dependent variables\n    size_t m = 1;\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) ay(m);\n    afun(ax, ay);\n\n    // Create f(x) = 1 / x\n    CppAD::ADFun<double> f(ax, ay);\n\n    // Use Jacobian to compute f'(x) = - 1 / (x * x).\n    // This would fail with the normal CppAD distribution because it would use\n    // first order forward mode for the  calculation.\n    CPPAD_TESTVECTOR(double) x(n), dy_dx(m);\n    x[0]   = 2.0;\n    dy_dx  = f.Jacobian(x);\n\n    // check the result\n    double check = -1.0 / (x[0] * x[0]);\n    ok &= CppAD::NearEqual(dy_dx[0], check, eps99, eps99);\n\n    return ok;\n}\n"
  },
  {
    "path": "test_more/debug_rel/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# Build the test_more/general tests\n\n# set compiler flags for debug_rel.cpp and debug.cpp\nIF( \"${cppad_debug_which}\" STREQUAL \"debug_all\" )\n    SET(debug_flags    \"${cppad_cxx_flags} ${CMAKE_CXX_FLAGS_DEBUG}\")\n    SET(release_flags  \"${cppad_cxx_flags} ${CMAKE_CXX_FLAGS_DEBUG}\")\nELSEIF( \"${cppad_debug_which}\" STREQUAL \"debug_none\" )\n    SET(debug_flags    \"${cppad_cxx_flags} ${CMAKE_CXX_FLAGS_RELEASE}\")\n    SET(release_flags  \"${cppad_cxx_flags} ${CMAKE_CXX_FLAGS_RELEASE}\")\nELSE( \"${cppad_debug_which}\" )\n    SET(debug_flags    \"${cppad_cxx_flags} ${CMAKE_CXX_FLAGS_DEBUG}\")\n    SET(release_flags  \"${cppad_cxx_flags} ${CMAKE_CXX_FLAGS_RELEASE}\")\nENDIF( \"${cppad_debug_which}\" STREQUAL \"debug_all\" )\n#\nSET_SOURCE_FILES_PROPERTIES(\n    debug_rel.cpp debug.cpp PROPERTIES COMPILE_FLAGS \"${debug_flags}\"\n)\n#\nSET_SOURCE_FILES_PROPERTIES(\n    release.cpp PROPERTIES COMPILE_FLAGS \"${release_flags}\"\n)\n\n# now that we have the properties, add the executable\nADD_EXECUTABLE(test_more_debug_rel EXCLUDE_FROM_ALL\n    debug_rel.cpp\n    debug.cpp\n    release.cpp\n)\n# debug_rel does not use cppad_lib\n\n# check_test_more_debug_rel\nadd_check_executable(check_test_more debug_rel)\n"
  },
  {
    "path": "test_more/debug_rel/debug.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/cppad.hpp>\n\n// checks that d_ptr points to a double with value 5.0 and then\n// frees the double using thread_alloc::return_memory\nbool debug_thread_alloc(double *d_ptr)\n{   bool ok = true;\n    ok &= ( *d_ptr == 5.0);\n    void* v_ptr = reinterpret_cast<void*>(d_ptr);\n    CppAD::thread_alloc::return_memory(v_ptr);\n    return ok;\n}\n\n// just use ADFun<double> constructor\nvoid debug_adfun_ctor(void)\n{\n    CppAD::vector< CppAD::AD<double> > ax(1), ay(1);\n    ax[0] = 0.;\n    CppAD::Independent(ax);\n    ay[0] = fabs(ax[0]);\n    CppAD::ADFun<double> f(ax, ay);\n    return;\n}\n"
  },
  {
    "path": "test_more/debug_rel/debug_rel.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n// system include files used for I/O\n# include <iostream>\n\n// for free_all\n# include <cppad/utility/thread_alloc.hpp>\n\nnamespace {\n    size_t n_ok    = 0;\n    size_t n_error = 0;\n    void print_test(bool ok, const char* name)\n    {\n        std::cout.width(20);\n        std::cout.setf( std::ios_base::left );\n        std::cout << name;\n        //\n        if( ok )\n        {   std::cout << \"OK\\n\";\n            n_ok++;\n        }\n        else\n        {   std::cout << \"Error\\n\";\n            n_error++;\n        }\n    }\n}\n\n// thread_alloc\ndouble *release_thread_alloc(void);\nbool      debug_thread_alloc(double* d_ptr);\n\n// adfun_ctor\nvoid debug_adfun_ctor(void);\nvoid release_adfun_ctor(void);\n\n// main program that runs all the tests\nint main(void)\n{   using std::cout;\n    cout << \"Begin test_more/debug_rel\\n\";\n    //\n    // thread_alloc\n    {   double* d_ptr = release_thread_alloc();\n        bool ok       = debug_thread_alloc(d_ptr);\n        print_test(ok, \"thead_alloc\");\n    }\n    // adfun_ctor\n    {   // this test would fail with an assert during release_adfun_ctor\n        release_adfun_ctor();\n        debug_adfun_ctor();\n        bool ok = true;\n        print_test(ok, \"adfun_ctor\");\n    }\n    // memory\n    {   bool ok = CppAD::thread_alloc::free_all();\n        print_test(ok, \"memory\");\n    }\n    if( n_error == 0 )\n        std::cout << \"All \" << n_ok << \" tests passed.\" << std::endl;\n    else\n        std::cout << n_error << \" tests failed.\" << std::endl;\n    //\n    if( n_error == 0 )\n        return 0;\n    return 1;\n}\n"
  },
  {
    "path": "test_more/debug_rel/release.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/cppad.hpp>\n\n// Returns a pointer to a double that has value 5.0\n// and must be freed using thread_alloc::return_memory.\ndouble *release_thread_alloc(void)\n{   size_t min_bytes = sizeof(double);\n    size_t cap_bytes;\n    void*   v_ptr = CppAD::thread_alloc::get_memory(min_bytes, cap_bytes);\n    double* d_ptr = reinterpret_cast<double*>(v_ptr);\n    *d_ptr        = 5.0;\n    return d_ptr;\n}\n\n// just use ADFun<double> constructor\nvoid release_adfun_ctor(void)\n{\n    CppAD::vector< CppAD::AD<double> > ax(1), ay(1);\n    ax[0] = 0.;\n    CppAD::Independent(ax);\n    ay[0] = fabs(ax[0]);\n    CppAD::ADFun<double> f(ax, ay);\n    return;\n}\n"
  },
  {
    "path": "test_more/deprecated/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# Build the test_more/deprecated tests\n#\n# initialize check_test_more_deprecated\n# This directory has both an executable and sub-directories\nSET(check_test_more_deprecated_depends \"\")\n#\nADD_SUBDIRECTORY(atomic_two)\nADD_SUBDIRECTORY(chkpoint_one)\n#\n# BEGIN_SORT_THIS_LINE_PLUS_2\nSET(source_list\n    deprecated.cpp\n    old_mat_mul.cpp\n    old_reciprocal.cpp\n    old_tan.cpp\n    old_usead_1.cpp\n    old_usead_2.cpp\n    omp_alloc.cpp\n    track_new_del.cpp\n    zdouble.cpp\n)\n# END_SORT_THIS_LINE_MINUS_2\n#\nset_compile_flags(\n    test_more_deprecated \"${cppad_debug_which}\" \"${source_list}\" )\n#\nADD_EXECUTABLE(test_more_deprecated EXCLUDE_FROM_ALL ${source_list})\n#\n# List of libraries to be linked into the specified target\nTARGET_LINK_LIBRARIES(test_more_deprecated\n    ${cppad_lib}\n    ${colpack_libs}\n)\n#\n# check_test_more_deprecated\nadd_check_executable(check_test_more deprecated)\n"
  },
  {
    "path": "test_more/deprecated/atomic_two/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n#\n# eigen_sources and CPPAD_HAS_EIGEN\nIF( cppad_has_eigen )\nELSE( cppad_has_eigen )\n    SET(eigen_sources \"\")\nENDIF( cppad_has_eigen )\n#\n# BEGIN_SORT_THIS_LINE_PLUS_2\nSET(source_list\n    atomic_sparsity.cpp\n    atomic_two.cpp\n    base2ad.cpp\n    for_sparse_hes.cpp\n    for_sparse_jac.cpp\n    forward.cpp\n    get_started.cpp\n    mat_mul.cpp\n    norm_sq.cpp\n    reciprocal.cpp\n    rev_sparse_hes.cpp\n    rev_sparse_jac.cpp\n    reverse.cpp\n    set_sparsity.cpp\n    tangent.cpp\n)\n# END_SORT_THIS_LINE_MINUS_2\n\nset_compile_flags(test_more_deprecated_atomic_two\n    \"${cppad_debug_which}\" \"${source_list}\"\n)\n#\nADD_EXECUTABLE(test_more_deprecated_atomic_two\n    EXCLUDE_FROM_ALL ${source_list}\n)\n#\n# List of libraries to be linked into the specified target\nTARGET_LINK_LIBRARIES(test_more_deprecated_atomic_two\n    ${cppad_lib}\n    ${colpack_libs}\n)\n#\n# check_test_more_deprecated_atomic_two\nadd_check_executable(check_test_more_deprecated atomic_two)\n"
  },
  {
    "path": "test_more/deprecated/atomic_two/atomic_sparsity.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\nAtomic function\ng( x ) = [ x_2, x_0 * x_1 ]\n\\] $$\n*/\n# include <cppad/cppad.hpp>\nnamespace {   // isolate items below to this file\nusing   CppAD::vector;                          // vector\ntypedef vector< std::set<size_t> > set_vector;  // atomic_sparsity\n//\n// a utility to compute the union of two sets.\nusing CppAD::set_union;\n//\nclass atomic_set_sparsity : public CppAD::atomic_base<double> {\npublic:\n    // constructor\n    atomic_set_sparsity(const std::string& name) :\n    // this example only uses set sparsity patterns\n    CppAD::atomic_base<double>(name, set_sparsity_enum )\n    { }\nprivate:\n    // forward\n    virtual bool forward(\n        size_t                    p ,\n        size_t                    q ,\n        const vector<bool>&      vx ,\n        vector<bool>&            vy ,\n        const vector<double>&    tx ,\n        vector<double>&          ty\n    )\n    {\n        size_t n = tx.size() / (q + 1);\n# ifndef NDEBUG\n        size_t m = ty.size() / (q + 1);\n# endif\n        assert( n == 3 );\n        assert( m == 2 );\n\n        // only order zero\n        bool ok = q == 0;\n        if( ! ok )\n            return ok;\n\n        // check for defining variable information\n        if( vx.size() > 0 )\n        {   ok   &= vx.size() == n;\n            vy[0] = vx[2];\n            vy[1] = vx[0] || vx[1];\n        }\n\n        // Order zero forward mode.\n        // y[0] = x[2], y[1] = x[0] * x[1]\n        if( p <= 0 )\n        {   ty[0] = tx[2];\n            ty[1] = tx[0] * tx[1];\n        }\n        return ok;\n    }\n    // for_sparse_jac\n    virtual bool for_sparse_jac(\n        size_t                          p ,\n        const set_vector&               r ,\n        set_vector&                     s ,\n        const vector<double>&           x )\n    {   // This function needed if using f.ForSparseJac\n# ifndef NDEBUG\n        size_t n = r.size();\n        size_t m = s.size();\n# endif\n        assert( n == x.size() );\n        assert( n == 3 );\n        assert( m == 2 );\n\n        // sparsity for S(x) = f'(x) * R  = [ 0,   0, 1 ] * R\n        s[0] = r[2];\n        // s[1] = union(r[0], r[1])\n        s[1] = set_union(r[0], r[1]);\n        //\n        return true;\n    }\n    virtual bool rev_sparse_jac(\n        size_t                                p  ,\n        const set_vector&                     rt ,\n        set_vector&                           st ,\n        const vector<double>&                 x  )\n    {   // This function needed if using RevSparseJac or optimize\n# ifndef NDEBUG\n        size_t n = st.size();\n        size_t m = rt.size();\n# endif\n        assert( n == x.size() );\n        assert( n == 3 );\n        assert( m == 2 );\n\n        //                                       [ 0, x1 ]\n        // sparsity for S(x)^T = f'(x)^T * R^T = [ 0, x0 ] * R^T\n        //                                       [ 1, 0  ]\n        st[0] = rt[1];\n        st[1] = rt[1];\n        st[2] = rt[0];\n        return true;\n    }\n    virtual bool for_sparse_hes(\n        const vector<bool>&                   vx,\n        const vector<bool>&                   r ,\n        const vector<bool>&                   s ,\n        set_vector&                           h ,\n        const vector<double>&                 x )\n    {\n        size_t n = r.size();\n# ifndef NDEBUG\n        size_t m = s.size();\n# endif\n        assert( x.size() == n );\n        assert( h.size() == n );\n        assert( n == 3 );\n        assert( m == 2 );\n\n        // initialize h as empty\n        for(size_t i = 0; i < n; i++)\n            h[i].clear();\n\n        // only f_1 has a non-zero hessian\n        if( ! s[1] )\n            return true;\n\n        // only the cross term between x[0] and x[1] is non-zero\n        if( ! ( r[0] && r[1] ) )\n            return true;\n\n        // set the possibly non-zero terms in the hessian\n        h[0].insert(1);\n        h[1].insert(0);\n\n        return true;\n    }\n    virtual bool rev_sparse_hes(\n        const vector<bool>&                   vx,\n        const vector<bool>&                   s ,\n        vector<bool>&                         t ,\n        size_t                                p ,\n        const set_vector&                     r ,\n        const set_vector&                     u ,\n        set_vector&                           v ,\n        const vector<double>&                 x )\n    {   // This function needed if using RevSparseHes\n# ifndef NDEBUG\n        size_t m = s.size();\n        size_t n = t.size();\n# endif\n        assert( x.size() == n );\n        assert( r.size() == n );\n        assert( u.size() == m );\n        assert( v.size() == n );\n        assert( n == 3 );\n        assert( m == 2 );\n\n        // sparsity for T(x) = S(x) * f'(x) = S(x) * [  0,  0,  1 ]\n        //                                           [ x1, x0,  0 ]\n        t[0] = s[1];\n        t[1] = s[1];\n        t[2] = s[0];\n\n        // V(x) = f'(x)^T * g''(y) * f'(x) * R  +  g'(y) * f''(x) * R\n        // U(x) = g''(y) * f'(x) * R\n        // S(x) = g'(y)\n\n        //                                      [ 0, x1 ]\n        // sparsity for W(x) = f'(x)^T * U(x) = [ 0, x0 ] * U(x)\n        //                                      [ 1, 0  ]\n        v[0] = u[1];\n        v[1] = u[1];\n        v[2] = u[0];\n        //\n        //                                      [ 0, 1, 0 ]\n        // sparsity for V(x) = W(x) + S_1 (x) * [ 1, 0, 0 ] * R\n        //                                      [ 0, 0, 0 ]\n        if( s[1] )\n        {   // v[0] = union( v[0], r[1] )\n            v[0] = set_union(v[0], r[1]);\n            // v[1] = union( v[1], r[0] )\n            v[1] = set_union(v[1], r[0]);\n        }\n        return true;\n    }\n}; // End of atomic_set_sparsity class\n\n\n// f(u) = g( u_0 + u_1 , u_0 + u_1 , u_2 )\n//      = [ u_2 , (u_0 + u_1)^2 ]\nbool test_one(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps = 10. * std::numeric_limits<double>::epsilon();\n    // Create the atomic get_started object\n    atomic_set_sparsity afun(\"atomic_set_sparsity\");\n    size_t n = 3;\n    size_t m = 2;\n    vector< AD<double> > au(n), ay(m);\n    for(size_t j = 0; j < n; j++)\n        au[j] = double(j + 1);\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(au);\n\n    // ax\n    vector< AD<double> > ax(n);\n    ax[0] = au[0] + au[1];\n    ax[1] = au[0] + au[1];\n    ax[2] = au[2];\n\n    // call atomic function\n    afun(ax, ay);\n\n    // create f: u -> y and stop tape recording\n    CppAD::ADFun<double> f(au, ay);\n\n    // check function value\n    ok &= NearEqual(ay[0] , au[2],  eps, eps);\n    ok &= NearEqual(ay[1] , (au[0] + au[1]) * (au[0] + au[1]),  eps, eps);\n\n    // correct Jacobian result\n    set_vector check_s(m);\n    check_s[0].insert(2);\n    check_s[1].insert(0);\n    check_s[1].insert(1);\n    // compute and test forward mode\n    {   set_vector r(n), s(m);\n        for(size_t i = 0; i < n; i++)\n            r[i].insert(i);\n        s = f.ForSparseJac(n, r);\n        for(size_t i = 0; i < m; i++)\n            ok &= s[i] == check_s[i];\n    }\n    // compute and test reverse mode\n    {   set_vector r(m), s(m);\n        for(size_t i = 0; i < m; i++)\n            r[i].insert(i);\n        s = f.RevSparseJac(m, r);\n        for(size_t i = 0; i < m; i++)\n            ok &= s[i] == check_s[i];\n    }\n    // correct Hessian result for w_0 * f_0 (u) + w_1 * f_1(u)\n    set_vector check_h(n);\n    check_h[0].insert(0);\n    check_h[0].insert(1);\n    check_h[1].insert(0);\n    check_h[1].insert(1);\n    // compute and test forward mode\n    {   set_vector r(1), s(1), h(n);\n        for(size_t i = 0; i < m; i++)\n            s[0].insert(i);\n        for(size_t j = 0; j < n; j++)\n            r[0].insert(j);\n        h = f.ForSparseHes(r, s);\n        for(size_t i = 0; i < n; i++)\n            ok &= h[i] == check_h[i];\n    }\n    // compute and test reverse mode\n    {   set_vector s(1), h(n);\n        for(size_t i = 0; i < m; i++)\n            s[0].insert(i);\n        h = f.RevSparseHes(n, s);\n        for(size_t i = 0; i < n; i++)\n            ok &= h[i] == check_h[i];\n    }\n    return ok;\n}\n\n// f(u) = g( u_0 + u_1 , u_1 + u_2 , u_2 + u_0 )\n//      = [ u_2 + u_0 , (u_0 + u_1)*(u_1 + u_2) ]\nbool test_two(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps = 10. * std::numeric_limits<double>::epsilon();\n    // Create the atomic get_started object\n    atomic_set_sparsity afun(\"atomic_set_sparsity\");\n    size_t n = 3;\n    size_t m = 2;\n    vector< AD<double> > au(n), ay(m);\n    for(size_t j = 0; j < n; j++)\n        au[j] = double(j + 1);\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(au);\n\n    // ax\n    vector< AD<double> > ax(n);\n    ax[0] = au[0] + au[1];\n    ax[1] = au[1] + au[2];\n    ax[2] = au[2] + au[0];\n\n    // call atomic function\n    afun(ax, ay);\n\n    // create f: u -> y and stop tape recording\n    CppAD::ADFun<double> f(au, ay);\n\n    // check function value\n    ok &= NearEqual(ay[0] , au[2] + au[0],  eps, eps);\n    ok &= NearEqual(ay[1] , (au[0] + au[1]) * (au[1] + au[2]),  eps, eps);\n\n    // correct Jacobian result\n    set_vector check_s(m);\n    check_s[0].insert(2);\n    check_s[0].insert(0);\n    check_s[1].insert(0);\n    check_s[1].insert(1);\n    check_s[1].insert(2);\n    // compute and test forward mode\n    {   set_vector r(n), s(m);\n        for(size_t i = 0; i < n; i++)\n            r[i].insert(i);\n        s = f.ForSparseJac(n, r);\n        for(size_t i = 0; i < m; i++)\n            ok &= s[i] == check_s[i];\n    }\n    // compute and test reverse mode\n    {   set_vector r(m), s(m);\n        for(size_t i = 0; i < m; i++)\n            r[i].insert(i);\n        s = f.RevSparseJac(m, r);\n        for(size_t i = 0; i < m; i++)\n            ok &= s[i] == check_s[i];\n    }\n    // ----------------------------------------------------------------------\n    // correct Hessian result for f_0 (u)\n    set_vector check_h(n), s(1);\n    s[0].insert(0);\n    // compute and test forward mode\n    {   set_vector r(1), h(n);\n        for(size_t j = 0; j < n; j++)\n            r[0].insert(j);\n        h = f.ForSparseHes(r, s);\n        for(size_t i = 0; i < n; i++)\n            ok &= h[i] == check_h[i];\n    }\n    // compute and test reverse mode\n    {   set_vector h(n);\n        h = f.RevSparseHes(n, s);\n        for(size_t i = 0; i < n; i++)\n            ok &= h[i] == check_h[i];\n    }\n    // ----------------------------------------------------------------------\n    // correct Hessian result for f_1 (u)\n    s[0].clear();\n    s[0].insert(1);\n    check_h[0].insert(1);\n    check_h[0].insert(2);\n    check_h[1].insert(0);\n    check_h[1].insert(1);\n    check_h[1].insert(2);\n    check_h[2].insert(0);\n    check_h[2].insert(1);\n    // compute and test forward mode\n    {   set_vector r(1), h(n);\n        for(size_t j = 0; j < n; j++)\n            r[0].insert(j);\n        h = f.ForSparseHes(r, s);\n        for(size_t i = 0; i < n; i++)\n            ok &= h[i] == check_h[i];\n    }\n    // compute and test reverse mode\n    {   set_vector h(n);\n        h = f.RevSparseHes(n, s);\n        for(size_t i = 0; i < n; i++)\n            ok &= h[i] == check_h[i];\n    }\n    return ok;\n}\n\n}  // End empty namespace\n\nbool atomic_sparsity(void)\n{   bool ok = true;\n    ok     &= test_one();\n    ok     &= test_two();\n    return ok;\n}\n"
  },
  {
    "path": "test_more/deprecated/atomic_two/atomic_two.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n// CPPAD_HAS_* defines\n# include <cppad/configure.hpp>\n\n// system include files used for I/O\n# include <iostream>\n\n// C style asserts\n# include <cassert>\n\n// for thread_alloc\n# include <cppad/utility/thread_alloc.hpp>\n\n// test runner\n# include <cppad/utility/test_boolofvoid.hpp>\n\n// external compiled tests\nextern bool atomic_sparsity(void);\nextern bool mat_mul(void);\nextern bool base2ad(void);\nextern bool for_sparse_hes(void);\nextern bool for_sparse_jac(void);\nextern bool forward(void);\nextern bool get_started(void);\nextern bool norm_sq(void);\nextern bool reciprocal(void);\nextern bool rev_sparse_hes(void);\nextern bool rev_sparse_jac(void);\nextern bool reverse(void);\nextern bool set_sparsity(void);\nextern bool tangent(void);\n\n// main program that runs all the tests\nint main(void)\n{   std::string group = \"test_more/deprecated/atomic_two\";\n    size_t      width = 20;\n    CppAD::test_boolofvoid Run(group, width);\n\n    // This line is used by test_one.sh\n\n    // external compiled tests\n    Run( atomic_sparsity,     \"atomic_sparsity\");\n    Run( mat_mul,             \"mat_mul\"        );\n    Run( base2ad,             \"base2ad\"        );\n    Run( for_sparse_hes,      \"for_sparse_hes\" );\n    Run( for_sparse_jac,      \"for_sparse_jac\" );\n    Run( forward,             \"forward\"        );\n    Run( get_started,         \"get_started\"    );\n    Run( norm_sq,             \"norm_sq\"        );\n    Run( reciprocal,          \"reciprocal\"     );\n    Run( rev_sparse_hes,      \"rev_sparse_hes\" );\n    Run( rev_sparse_jac,      \"rev_sparse_jac\" );\n    Run( reverse,             \"reverse\"        );\n    Run( set_sparsity,        \"set_sparsity\"   );\n    Run( tangent,             \"tangent\"        );\n# if CPPAD_HAS_EIGEN\n# endif\n    // check for memory leak\n    bool memory_ok = CppAD::thread_alloc::free_all();\n    // print summary at end\n    bool ok = Run.summary(memory_ok);\n    //\n    return static_cast<int>( ! ok );\n}\n"
  },
  {
    "path": "test_more/deprecated/atomic_two/base2ad.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n@begin atomic_two_base2ad.cpp@@\n\n$section base2ad with Atomic Operations: Example and Test$$\n\n$head Source Code$$\n$srcthisfile%0%// BEGIN C++%// END C++%1%$$\n\n$end\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\nnamespace {          // isolate items below to this file\n//\n// abbreviations\nusing CppAD::AD;\nusing CppAD::vector;\n//\nclass atomic_base2ad : public CppAD::atomic_base<double> {\n//\npublic:\n    // constructor (could use const char* for name)\n    atomic_base2ad(const std::string& name) :\n    // this example does not use any sparsity patterns\n    CppAD::atomic_base<double>(name)\n    { }\nprivate:\n    // ----------------------------------------------------------------------\n    // forward mode\n    // ----------------------------------------------------------------------\n    template <class Scalar>\n    bool template_forward(\n        size_t                    p ,\n        size_t                    q ,\n        const vector<bool>&      vx ,\n                  vector<bool>&      vy ,\n        const vector<Scalar>&    tx ,\n                  vector<Scalar>&    ty\n    )\n    {\n# ifndef NDEBUG\n        size_t n = tx.size() / (q + 1);\n        size_t m = ty.size() / (q + 1);\n# endif\n        assert( n == 1 );\n        assert( m == 1 );\n\n        // return flag\n        bool ok = q == 0;\n        if( ! ok )\n            return ok;\n\n        // check for defining variable information\n        // This case must always be implemented\n        if( vx.size() > 0 )\n            vy[0] = vx[0];\n\n        // Order zero forward mode.\n        // This case must always be implemented\n        // y^0 = f( x^0 ) = 1 / x^0\n        Scalar f = 1. / tx[0];\n        if( p <= 0 )\n            ty[0] = f;\n        return ok;\n    }\n    // forward mode routines called by ADFun<Base> objects\n    virtual bool forward(\n        size_t                    p ,\n        size_t                    q ,\n        const vector<bool>&      vx ,\n                  vector<bool>&      vy ,\n        const vector<double>&    tx ,\n                  vector<double>&    ty\n    )\n    {   return template_forward(p, q, vx, vy, tx, ty);\n    }\n    // forward mode routines called by ADFun< AD<Base> , Base> objects\n    virtual bool forward(\n        size_t                          p ,\n        size_t                          q ,\n        const vector<bool>&            vx ,\n                  vector<bool>&            vy ,\n        const vector< AD<double> >&    atx ,\n                  vector< AD<double> >&    aty\n    )\n    {   return template_forward(p, q, vx, vy, atx, aty);\n    }\n    // ----------------------------------------------------------------------\n    // reverse mode\n    // ----------------------------------------------------------------------\n    template <class Scalar>\n    bool template_reverse(\n        size_t                    q ,\n        const vector<Scalar>&    tx ,\n        const vector<Scalar>&    ty ,\n                  vector<Scalar>&    px ,\n        const vector<Scalar>&    py\n    )\n    {\n# ifndef NDEBUG\n        size_t n = tx.size() / (q + 1);\n        size_t m = ty.size() / (q + 1);\n# endif\n        assert( n == 1 );\n        assert( m == 1 );\n\n        // return flag\n        bool ok = q == 0;\n        if( ! ok )\n            return ok;\n\n        // Order zero reverse mode.\n        // y^0 = f( x^0 ) = 1 / x^0\n        // y^1 = f'( x^0 ) * x^1 = - x^1 / (x^0 * x^0)\n        px[0] = - py[0] / ( tx[0] * tx[0] );\n        return ok;\n    }\n    // reverse mode routines called by ADFun<Base> objects\n    virtual bool reverse(\n        size_t                    q ,\n        const vector<double>&    tx ,\n        const vector<double>&    ty ,\n                  vector<double>&    px ,\n        const vector<double>&    py\n    )\n    {   return template_reverse(q, tx, ty, px, py);\n    }\n    // reverse mode routines called by ADFun<Base> objects\n    virtual bool reverse(\n        size_t                         q ,\n        const vector< AD<double> >&    atx ,\n        const vector< AD<double> >&    aty ,\n                  vector< AD<double> >&    apx ,\n        const vector< AD<double> >&    apy\n    )\n    {   return template_reverse(q, atx, aty, apx, apy);\n    }\n}; // End of atomic_base2ad class\n}  // End empty namespace\n\nbool base2ad(void)\n{   bool ok = true;\n    using CppAD::NearEqual;\n    double eps = 10. * CppAD::numeric_limits<double>::epsilon();\n    //\n    // Create the atomic base2ad object\n    atomic_base2ad afun(\"atomic_base2ad\");\n    //\n    // Create the function f(x)\n    //\n    size_t n  = 1;\n    double  x0 = 0.5;\n    vector< AD<double> > ax(n);\n    ax[0]     = x0;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(ax);\n\n    // range space vector\n    size_t m = 1;\n    vector< AD<double> > ay(m);\n\n    // call atomic function and store base2ad(x) in au[0]\n    vector< AD<double> > au(m);\n    afun(ax, au);        // u = 1 / x\n\n    // now use AD division to invert to invert the operation\n    ay[0] = 1.0 / au[0]; // y = 1 / u = x\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f;\n    f.Dependent (ax, ay);  // f(x) = x\n\n    // check function value\n    double check = x0;\n    ok &= NearEqual( Value(ay[0]) , check,  eps, eps);\n\n    // check zero order forward mode\n    size_t q;\n    vector<double> x_q(n), y_q(m);\n    q      = 0;\n    x_q[0] = x0;\n    y_q    = f.Forward(q, x_q);\n    ok &= NearEqual(y_q[0] , check,  eps, eps);\n\n    // check first order reverse\n    vector<double> dw(n), w(m);\n    w[0]  = 1.0;\n    dw    = f.Reverse(q+1, w);\n    check = 1.0;\n    ok &= NearEqual(dw[0] , check,  eps, eps);\n\n    // create af : x -> y\n    CppAD::ADFun< AD<double> , double > af( f.base2ad() );\n\n    // check zero order forward mode\n    vector< AD<double> > ax_q(n), ay_q(m);\n    q      = 0;\n    ax_q[0] = x0;\n    ay_q    = af.Forward(q, ax_q);\n    check   = x0;\n    ok &= NearEqual( Value(ay_q[0]) , check,  eps, eps);\n\n    // check first order reverse\n    vector< AD<double> > adw(n), aw(m);\n    aw[0]  = 1.0;\n    adw    = af.Reverse(q+1, aw);\n    check = 1.0;\n    ok &= NearEqual( Value(adw[0]) , check,  eps, eps);\n\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "test_more/deprecated/atomic_two/for_sparse_hes.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n@begin atomic_two_for_sparse_hes.cpp@@\n\n$section Atomic Forward Hessian Sparsity: Example and Test$$\n\n$head Purpose$$\nThis example demonstrates calculation of the forward Hessian sparsity pattern\nfor an atomic operation.\n\n$head function$$\nFor this example, the atomic function\n$latex f : \\B{R}^3 \\rightarrow \\B{R}^2$$ is defined by\n$latex \\[\nf( x ) = \\left( \\begin{array}{c}\n    x_2 * x_2 \\\\\n    x_0 * x_1\n\\end{array} \\right)\n\\] $$\nThe Hessians of the component functions are\n$latex \\[\nf_0^{(2)} ( x ) = \\left( \\begin{array}{ccc}\n    0 & 0 & 0  \\\\\n    0 & 0 & 0  \\\\\n    0 & 0 & 2\n\\end{array} \\right)\n\\W{,}\nf_1^{(2)} ( x ) = \\left( \\begin{array}{ccc}\n    0 & 1 & 0 \\\\\n    1 & 0 & 0 \\\\\n    0 & 0 & 0\n\\end{array} \\right)\n\\] $$\n\n$head Start  Class Definition$$\n$srccode%cpp% */\n# include <cppad/cppad.hpp>\nnamespace {          // isolate items below to this file\nusing CppAD::vector; // abbreviate as vector\n//\nclass atomic_for_sparse_hes : public CppAD::atomic_base<double> {\n/* %$$\n$head Constructor $$\n$srccode%cpp% */\npublic:\n    // constructor (could use const char* for name)\n    atomic_for_sparse_hes(const std::string& name) :\n    // this example only uses pack sparsity patterns\n    CppAD::atomic_base<double>(name, pack_sparsity_enum)\n    { }\nprivate:\n/* %$$\n$head forward$$\n$srccode%cpp% */\n    // forward mode routine called by CppAD\n    virtual bool forward(\n        size_t                    p ,\n        size_t                    q ,\n        const vector<bool>&      vx ,\n        vector<bool>&            vy ,\n        const vector<double>&    tx ,\n        vector<double>&          ty\n    )\n    {\n# ifndef NDEBUG\n        size_t n = tx.size() / (q + 1);\n        size_t m = ty.size() / (q + 1);\n# endif\n        assert( n == 3 );\n        assert( m == 2 );\n\n        // return flag\n        bool ok = q == 0;\n        if( ! ok )\n            return ok;\n\n        // check for defining variable information\n        // This case must always be implemented\n        if( vx.size() > 0 )\n        {   vy[0] = vx[0];\n            vy[1] = vx[0] || vy[0];\n        }\n\n        // Order zero forward mode.\n        // This case must always be implemented\n        // f(x) = [ x_0 * x_0 ]\n        //        [ x_0 * x_1 ]\n        assert( p <= 0 );\n        if( p <= 0 )\n        {   ty[0] = tx[2] * tx[2];\n            ty[1] = tx[0] * tx[1];\n        }\n        return ok;\n    }\n/* %$$\n$head for_sparse_jac$$\n$srccode%cpp% */\n    // forward Jacobian sparsity routine called by CppAD\n    virtual bool for_sparse_jac(\n        size_t                     q ,\n        const CppAD::vectorBool&   r ,\n        CppAD::vectorBool&         s ,\n        const vector<double>&      x )\n    {   // This function needed because we are using ForSparseHes\n        // with afun.option( CppAD::atomic_base<double>::pack_sparsity_enum )\n# ifndef NDEBUG\n        size_t n = r.size() / q;\n        size_t m = s.size() / q;\n# endif\n        assert( x.size() == n );\n        assert( n == 3 );\n        assert( m == 2 );\n\n\n        // f'(x) = [   0,   0, 2 x_2 ]\n        //         [ x_1, x_0,     0 ]\n\n        // sparsity for first row of S(x) = f'(x) * R\n        size_t i = 0;\n        for(size_t j = 0; j < q; j++)\n            s[ i * q + j ] = r[ 2 * q + j ];\n\n        // sparsity for second row of S(x) = f'(x) * R\n        i = 1;\n        for(size_t j = 0; j < q; j++)\n            s[ i * q + j ] = r[ 0 * q + j ] || r[ 1 * q + j];\n\n        return true;\n    }\n/* %$$\n$head rev_sparse_jac$$\n$srccode%cpp% */\n    // reverse Jacobian sparsity routine called by CppAD\n    virtual bool rev_sparse_jac(\n        size_t                     q  ,\n        const CppAD::vectorBool&   rt ,\n        CppAD::vectorBool&         st ,\n        const vector<double>&      x  )\n    {   // This function needed because we are using ForSparseHes\n        // with afun.option( CppAD::atomic_base<double>::pack_sparsity_enum )\n# ifndef NDEBUG\n        size_t m = rt.size() / q;\n        size_t n = st.size() / q;\n# endif\n        assert( x.size() == n );\n        assert( n == 3 );\n        assert( m == 2 );\n\n        //           [     0,  x_1 ]\n        // f'(x)^T = [     0,  x_0 ]\n        //           [ 2 x_2,    0 ]\n\n        // sparsity for first row of S(x)^T = f'(x)^T * R^T\n        size_t i = 0;\n        for(size_t j = 0; j < q; j++)\n            st[ i * q + j ] = rt[ 1 * q + j ];\n\n        // sparsity for second row of S(x)^T = f'(x)^T * R^T\n        i = 1;\n        for(size_t j = 0; j < q; j++)\n            st[ i * q + j ] = rt[ 1 * q + j ];\n\n        // sparsity for third row of S(x)^T = f'(x)^T * R^T\n        i = 2;\n        for(size_t j = 0; j < q; j++)\n            st[ i * q + j ] = rt[ 0 * q + j ];\n\n        return true;\n    }\n/* %$$\n$head for_sparse_hes$$\n$srccode%cpp% */\n    // forward Hessian sparsity routine called by CppAD\n    virtual bool for_sparse_hes(\n        const vector<bool>&   vx,\n        const vector<bool>&   r ,\n        const vector<bool>&   s ,\n        CppAD::vectorBool&    h ,\n        const vector<double>& x )\n    {   // This function needed because we are using RevSparseHes\n        // with afun.option( CppAD::atomic_base<double>::pack_sparsity_enum )\n        size_t n = r.size();\n# ifndef NDEBUG\n        size_t m = s.size();\n# endif\n        assert( x.size() == n );\n        assert( n == 3 );\n        assert( m == 2 );\n        assert( h.size() == n * n );\n\n        //            [ 0 , 0 , 0 ]                  [ 0 , 1 , 0 ]\n        // f_0''(x) = [ 0 , 0 , 0 ]  f_1^{(2)} (x) = [ 1 , 0 , 0 ]\n        //            [ 0 , 0 , 2 ]                  [ 0 , 0 , 0 ]\n\n        // initial entire matrix as false\n        for(size_t i = 0; i < n * n; i++)\n            h[i] = false;\n\n        // component (2, 2)\n        h[ 2 * n + 2 ] = s[0] && r[2];\n\n        // components (1, 0) and (0, 1)\n        h[ 1 * n + 0 ] = s[1] && r[0] && r[1];\n        h[ 0 * n + 1 ] = s[1] && r[0] && r[1];\n\n        return true;\n    }\n}; // End of atomic_for_sparse_hes class\n\n/* %$$\n$head Use Atomic Function$$\n$srccode%cpp% */\nbool use_atomic_for_sparse_hes(bool x_1_variable)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps = 10. * CppAD::numeric_limits<double>::epsilon();\n    //\n    // Create the atomic for_sparse_hes object\n    atomic_for_sparse_hes afun(\"atomic_for_sparse_hes\");\n    //\n    // Create the function f(u)\n    //\n    // domain space vector\n    size_t n  = 3;\n    double x_0 = 1.00;\n    double x_1 = 2.00;\n    double x_2 = 3.00;\n    vector< AD<double> > au(n);\n    au[0] = x_0;\n    au[1] = x_1;\n    au[2] = x_2;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(au);\n\n    // range space vector\n    size_t m = 2;\n    vector< AD<double> > ay(m);\n\n    // call atomic function\n    vector< AD<double> > ax(n);\n    ax[0] = au[0];\n    ax[2] = au[2];\n    if( x_1_variable )\n        ax[1] = au[1];\n    else\n        ax[1] = x_1;\n    afun(ax, ay);          // y = [ x_2 * x_2 ,  x_0 * x_1 ]^T\n\n    // create f: u -> y and stop tape recording\n    CppAD::ADFun<double> f;\n    f.Dependent (au, ay);  // f(u) = y\n    //\n    // check function value\n    double check = x_2 * x_2;\n    ok &= NearEqual( Value(ay[0]) , check,  eps, eps);\n    check = x_0 * x_1;\n    ok &= NearEqual( Value(ay[1]) , check,  eps, eps);\n\n    // check zero order forward mode\n    size_t q;\n    vector<double> xq(n), yq(m);\n    q     = 0;\n    xq[0] = x_0;\n    xq[1] = x_1;\n    xq[2] = x_2;\n    yq    = f.Forward(q, xq);\n    check = x_2 * x_2;\n    ok &= NearEqual(yq[0] , check,  eps, eps);\n    check = x_0 * x_1;\n    ok &= NearEqual(yq[1] , check,  eps, eps);\n\n    // forward sparse Hessian\n    CppAD::vectorBool r(n), s(m), h(n * n);\n    for(size_t j = 0; j < n; j++)\n        r[j] = true;\n    for(size_t i = 0; i < m; i++)\n        s[i] = true;\n    h = f.ForSparseHes(r, s);\n\n    // check result\n    CppAD::vectorBool check_h(n * n);\n    for(size_t i = 0; i < n * n; i++)\n        check_h[i] = false;\n    check_h[ 2 * n + 2 ] = true;\n    if( x_1_variable )\n    {   check_h[0 * n + 1] = true;\n        check_h[1 * n + 0] = true;\n    }\n    for(size_t i = 0; i < n * n; i++)\n        ok &= h[ i ] == check_h[ i ];\n    //\n    return ok;\n}\n}  // End empty namespace\n/* %$$\n$head Test with x_1 Both a Variable and a Parameter$$\n$srccode%cpp% */\nbool for_sparse_hes(void)\n{   bool ok = true;\n    // test with x_1 a variable\n    ok     &= use_atomic_for_sparse_hes(true);\n    // test with x_1 a parameter\n    ok     &= use_atomic_for_sparse_hes(false);\n    return ok;\n}\n/* %$$\n$end\n*/\n"
  },
  {
    "path": "test_more/deprecated/atomic_two/for_sparse_jac.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n@begin atomic_two_for_sparse_jac.cpp@@\n$spell\n    Jacobian\n$$\n\n$section Atomic Forward Jacobian Sparsity: Example and Test$$\n\n$head Purpose$$\nThis example demonstrates calculation of the forward Jacobian sparsity pattern\nfor an atomic operation.\n\n$head function$$\nFor this example, the atomic function\n$latex f : \\B{R}^3 \\rightarrow \\B{R}^2$$ is defined by\n$latex \\[\nf(x) = \\left( \\begin{array}{c}\n    x_2 * x_2 \\\\\n    x_0 * x_1\n\\end{array} \\right)\n\\] $$\nThe corresponding Jacobian is\n$latex \\[\nf^{(1)} (x) = \\left( \\begin{array}{ccc}\n  0  &   0 & 2 x_2 \\\\\nx_1  & x_0 & 0\n\\end{array} \\right)\n\\] $$\n\n$head Start  Class Definition$$\n$srccode%cpp% */\n# include <cppad/cppad.hpp>\nnamespace {          // isolate items below to this file\nusing CppAD::vector; // abbreviate as vector\n//\nclass atomic_for_sparse_jac : public CppAD::atomic_base<double> {\n/* %$$\n$head Constructor $$\n$srccode%cpp% */\npublic:\n    // constructor (could use const char* for name)\n    atomic_for_sparse_jac(const std::string& name) :\n    // this example only uses pack sparsty patterns\n    CppAD::atomic_base<double>(name, pack_sparsity_enum)\n    { }\nprivate:\n/* %$$\n$head forward$$\n$srccode%cpp% */\n    // forward mode routine called by CppAD\n    virtual bool forward(\n        size_t                    p ,\n        size_t                    q ,\n        const vector<bool>&      vx ,\n        vector<bool>&            vy ,\n        const vector<double>&    tx ,\n        vector<double>&          ty\n    )\n    {\n# ifndef NDEBUG\n        size_t n = tx.size() / (q + 1);\n        size_t m = ty.size() / (q + 1);\n# endif\n        assert( n == 3 );\n        assert( m == 2 );\n\n        // return flag\n        bool ok = q == 0;\n        if( ! ok )\n            return ok;\n\n        // check for defining variable information\n        // This case must always be implemented\n        if( vx.size() > 0 )\n        {   vy[0] = vx[2];\n            vy[1] = vx[0] || vx[1];\n        }\n\n        // Order zero forward mode.\n        // This case must always be implemented\n        // f(x) = [ x_2 * x_2 ]\n        //        [ x_0 * x_1 ]\n        assert( p <= 0 );\n        if( p <= 0 )\n        {   ty[0] = tx[2] * tx[2];\n            ty[1] = tx[0] * tx[1];\n        }\n        return ok;\n    }\n/* %$$\n$head for_sparse_jac$$\n$srccode%cpp% */\n    // forward Jacobian sparsity routine called by CppAD\n    virtual bool for_sparse_jac(\n        size_t                     q ,\n        const CppAD::vectorBool&   r ,\n        CppAD::vectorBool&         s ,\n        const vector<double>&      x )\n    {   // This function needed because we are using ForSparseJac\n        // with afun.option( CppAD::atomic_base<double>::pack_sparsity_enum )\n# ifndef NDEBUG\n        size_t n = r.size() / q;\n        size_t m = s.size() / q;\n# endif\n        assert( x.size() == n );\n        assert( n == 3 );\n        assert( m == 2 );\n\n        // f'(x) = [   0,   0, 2 x_2 ]\n        //         [ x_1, x_0,     0 ]\n\n        // sparsity for first row of S(x) = f'(x) * R\n        size_t i = 0;\n        for(size_t j = 0; j < q; j++)\n            s[ i * q + j ] = r[ 2 * q + j ];\n\n        // sparsity for second row of S(x) = f'(x) * R\n        i = 1;\n        for(size_t j = 0; j < q; j++)\n            s[ i * q + j ] = r[ 0 * q + j ] || r[ 1 * q + j];\n\n        return true;\n    }\n}; // End of atomic_for_sparse_jac class\n\n/* %$$\n$head Use Atomic Function$$\n$srccode%cpp% */\nbool use_atomic_for_sparse_jac(bool x_1_variable)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps = 10. * CppAD::numeric_limits<double>::epsilon();\n    //\n    // Create the atomic for_sparse_jac object\n    atomic_for_sparse_jac afun(\"atomic_for_sparse_jac\");\n    //\n    // Create the function f(u)\n    //\n    // domain space vector\n    size_t n  = 3;\n    double x_0 = 1.00;\n    double x_1 = 2.00;\n    double x_2 = 3.00;\n    vector< AD<double> > au(n);\n    au[0] = x_0;\n    au[1] = x_1;\n    au[2] = x_2;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(au);\n\n    // range space vector\n    size_t m = 2;\n    vector< AD<double> > ay(m);\n\n    // call atomic function\n    vector< AD<double> > ax(n);\n    ax[0] = au[0];\n    ax[2] = au[2];\n    if( x_1_variable )\n        ax[1] = au[1];\n    else\n        ax[1] = x_1;\n    afun(ax, ay);          // y = [ x_2 * x_2 ,  x_0 * x_1 ]^T\n\n    // create f: u -> y and stop tape recording\n    CppAD::ADFun<double> f;\n    f.Dependent (au, ay);  // f(u) = y\n    //\n    // check function value\n    double check = x_2 * x_2;\n    ok &= NearEqual( Value(ay[0]) , check,  eps, eps);\n    check = x_0 * x_1;\n    ok &= NearEqual( Value(ay[1]) , check,  eps, eps);\n\n    // check zero order forward mode\n    size_t q;\n    vector<double> xq(n), yq(m);\n    q     = 0;\n    xq[0] = x_0;\n    xq[1] = x_1;\n    xq[2] = x_2;\n    yq    = f.Forward(q, xq);\n    check = x_2 * x_2;\n    ok &= NearEqual(yq[0] , check,  eps, eps);\n    check = x_0 * x_1;\n    ok &= NearEqual(yq[1] , check,  eps, eps);\n\n    // forward sparse Jacobian\n    CppAD::vectorBool r(n * n), s(m * n);\n    // r = identity matrix\n    for(size_t i = 0; i < n; i++)\n        for(size_t j = 0; j < n; j++)\n            r[ i * n + j] = i == j;\n    s = f.ForSparseJac(n, r);\n\n    // check result\n    CppAD::vectorBool check_s(m * n);\n    check_s[ 0 * n + 0 ] = false;\n    check_s[ 0 * n + 1 ] = false;\n    check_s[ 0 * n + 2 ] = true;\n    check_s[ 1 * n + 0 ] = true;\n    check_s[ 1 * n + 1 ] = x_1_variable;\n    check_s[ 1 * n + 2 ] = false;\n    //\n    for(size_t i = 0; i < m * n; i++)\n        ok &= s[ i ] == check_s[ i ];\n    //\n    return ok;\n}\n}  // End empty namespace\n/* %$$\n$head Test with x_1 Both a Variable and a Parameter$$\n$srccode%cpp% */\nbool for_sparse_jac(void)\n{   bool ok = true;\n    // test with x_1 a variable\n    ok     &= use_atomic_for_sparse_jac(true);\n    // test with x_1 a parameter\n    ok     &= use_atomic_for_sparse_jac(false);\n    return ok;\n}\n/* %$$\n$end\n*/\n"
  },
  {
    "path": "test_more/deprecated/atomic_two/forward.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n@begin atomic_two_forward.cpp@@\n$spell\n    Jacobian\n$$\n\n$section Atomic Forward: Example and Test$$\n\n$head Purpose$$\nThis example demonstrates forward mode derivative calculation\nusing an atomic operation.\n\n$head function$$\nFor this example, the atomic function\n$latex f : \\B{R}^3 \\rightarrow \\B{R}^2$$ is defined by\n$latex \\[\nf(x) = \\left( \\begin{array}{c}\n    x_2 * x_2 \\\\\n    x_0 * x_1\n\\end{array} \\right)\n\\] $$\nThe corresponding Jacobian is\n$latex \\[\nf^{(1)} (x) = \\left( \\begin{array}{ccc}\n  0  &   0 & 2 x_2 \\\\\nx_1  & x_0 & 0\n\\end{array} \\right)\n\\] $$\nThe Hessians of the component functions are\n$latex \\[\nf_0^{(2)} ( x ) = \\left( \\begin{array}{ccc}\n    0 & 0 & 0  \\\\\n    0 & 0 & 0  \\\\\n    0 & 0 & 2\n\\end{array} \\right)\n\\W{,}\nf_1^{(2)} ( x ) = \\left( \\begin{array}{ccc}\n    0 & 1 & 0 \\\\\n    1 & 0 & 0 \\\\\n    0 & 0 & 0\n\\end{array} \\right)\n\\] $$\n\n$head Start  Class Definition$$\n$srccode%cpp% */\n# include <cppad/cppad.hpp>\nnamespace {          // isolate items below to this file\nusing CppAD::vector; // abbreviate as vector\n//\nclass atomic_forward : public CppAD::atomic_base<double> {\n/* %$$\n$head Constructor $$\n$srccode%cpp% */\npublic:\n    // constructor (could use const char* for name)\n    atomic_forward(const std::string& name) :\n    // this example does not use sparsity patterns\n    CppAD::atomic_base<double>(name)\n    { }\nprivate:\n/* %$$\n$head forward$$\n$srccode%cpp% */\n    // forward mode routine called by CppAD\n    virtual bool forward(\n        size_t                    p ,\n        size_t                    q ,\n        const vector<bool>&      vx ,\n        vector<bool>&            vy ,\n        const vector<double>&    tx ,\n        vector<double>&          ty\n    )\n    {\n        size_t q1 = q + 1;\n# ifndef NDEBUG\n        size_t n = tx.size() / q1;\n        size_t m = ty.size() / q1;\n# endif\n        assert( n == 3 );\n        assert( m == 2 );\n        assert( p <= q );\n\n        // this example only implements up to second order forward mode\n        bool ok = q <= 2;\n        if( ! ok )\n            return ok;\n\n        // check for defining variable information\n        // This case must always be implemented\n        if( vx.size() > 0 )\n        {   vy[0] = vx[2];\n            vy[1] = vx[0] || vx[1];\n        }\n        // ------------------------------------------------------------------\n        // Zero forward mode.\n        // This case must always be implemented\n        // f(x) = [ x_2 * x_2 ]\n        //        [ x_0 * x_1 ]\n        // y^0  = f( x^0 )\n        if( p <= 0 )\n        {   // y_0^0 = x_2^0 * x_2^0\n            ty[0 * q1 + 0] = tx[2 * q1 + 0] * tx[2 * q1 + 0];\n            // y_1^0 = x_0^0 * x_1^0\n            ty[1 * q1 + 0] = tx[0 * q1 + 0] * tx[1 * q1 + 0];\n        }\n        if( q <= 0 )\n            return ok;\n        // ------------------------------------------------------------------\n        // First order one forward mode.\n        // This case is needed if first order forward mode is used.\n        // f'(x) = [   0,   0, 2 * x_2 ]\n        //         [ x_1, x_0,       0 ]\n        // y^1 =  f'(x^0) * x^1\n        if( p <= 1 )\n        {   // y_0^1 = 2 * x_2^0 * x_2^1\n            ty[0 * q1 + 1] = 2.0 * tx[2 * q1 + 0] * tx[2 * q1 + 1];\n            // y_1^1 = x_1^0 * x_0^1 + x_0^0 * x_1^1\n            ty[1 * q1 + 1]  = tx[1 * q1 + 0] * tx[0 * q1 + 1];\n            ty[1 * q1 + 1] += tx[0 * q1 + 0] * tx[1 * q1 + 1];\n        }\n        if( q <= 1 )\n            return ok;\n        // ------------------------------------------------------------------\n        // Second order forward mode.\n        // This case is needed if second order forward mode is used.\n        // f'(x) = [   0,   0, 2 x_2 ]\n        //         [ x_1, x_0,     0 ]\n        //\n        //            [ 0 , 0 , 0 ]                  [ 0 , 1 , 0 ]\n        // f_0''(x) = [ 0 , 0 , 0 ]  f_1^{(2)} (x) = [ 1 , 0 , 0 ]\n        //            [ 0 , 0 , 2 ]                  [ 0 , 0 , 0 ]\n        //\n        //  y_0^2 = x^1 * f_0''( x^0 ) x^1 / 2! + f_0'( x^0 ) x^2\n        //        = ( x_2^1 * 2.0 * x_2^1 ) / 2!\n        //        + 2.0 * x_2^0 * x_2^2\n        ty[0 * q1 + 2]  = tx[2 * q1 + 1] * tx[2 * q1 + 1];\n        ty[0 * q1 + 2] += 2.0 * tx[2 * q1 + 0] * tx[2 * q1 + 2];\n        //\n        //  y_1^2 = x^1 * f_1''( x^0 ) x^1 / 2! + f_1'( x^0 ) x^2\n        //        = ( x_1^1 * x_0^1 + x_0^1 * x_1^1) / 2\n        //        + x_1^0 * x_0^2 + x_0^0 + x_1^2\n        ty[1 * q1 + 2]  = tx[1 * q1 + 1] * tx[0 * q1 + 1];\n        ty[1 * q1 + 2] += tx[1 * q1 + 0] * tx[0 * q1 + 2];\n        ty[1 * q1 + 2] += tx[0 * q1 + 0] * tx[1 * q1 + 2];\n        // ------------------------------------------------------------------\n        return ok;\n    }\n};\n}  // End empty namespace\n/* %$$\n$head Use Atomic Function$$\n$srccode%cpp% */\nbool forward(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps = 10. * CppAD::numeric_limits<double>::epsilon();\n    //\n    // Create the atomic_forward object\n    atomic_forward afun(\"atomic_forward\");\n    //\n    // Create the function f(u)\n    //\n    // domain space vector\n    size_t n  = 3;\n    double x_0 = 1.00;\n    double x_1 = 2.00;\n    double x_2 = 3.00;\n    vector< AD<double> > au(n);\n    au[0] = x_0;\n    au[1] = x_1;\n    au[2] = x_2;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(au);\n\n    // range space vector\n    size_t m = 2;\n    vector< AD<double> > ay(m);\n\n    // call atomic function\n    vector< AD<double> > ax = au;\n    afun(ax, ay);\n\n    // create f: u -> y and stop tape recording\n    CppAD::ADFun<double> f;\n    f.Dependent (au, ay);  // y = f(u)\n    //\n    // check function value\n    double check = x_2 * x_2;\n    ok &= NearEqual( Value(ay[0]) , check,  eps, eps);\n    check = x_0 * x_1;\n    ok &= NearEqual( Value(ay[1]) , check,  eps, eps);\n\n    // --------------------------------------------------------------------\n    // zero order forward\n    //\n    vector<double> x0(n), y0(m);\n    x0[0] = x_0;\n    x0[1] = x_1;\n    x0[2] = x_2;\n    y0   = f.Forward(0, x0);\n    check = x_2 * x_2;\n    ok &= NearEqual(y0[0] , check,  eps, eps);\n    check = x_0 * x_1;\n    ok &= NearEqual(y0[1] , check,  eps, eps);\n    // --------------------------------------------------------------------\n    // first order forward\n    //\n    // value of Jacobian of f\n    double check_jac[] = {\n        0.0, 0.0, 2.0 * x_2,\n        x_1, x_0,       0.0\n    };\n    vector<double> x1(n), y1(m);\n    // check first order forward mode\n    for(size_t j = 0; j < n; j++)\n        x1[j] = 0.0;\n    for(size_t j = 0; j < n; j++)\n    {   // compute partial in j-th component direction\n        x1[j] = 1.0;\n        y1    = f.Forward(1, x1);\n        x1[j] = 0.0;\n        // check this direction\n        for(size_t i = 0; i < m; i++)\n            ok &= NearEqual(y1[i], check_jac[i * n + j], eps, eps);\n    }\n    // --------------------------------------------------------------------\n    // second order forward\n    //\n    // value of Hessian of f_0\n    double check_hes_0[] = {\n        0.0, 0.0, 0.0,\n        0.0, 0.0, 0.0,\n        0.0, 0.0, 2.0\n    };\n    //\n    // value of Hessian of f_1\n    double check_hes_1[] = {\n        0.0, 1.0, 0.0,\n        1.0, 0.0, 0.0,\n        0.0, 0.0, 0.0\n    };\n    vector<double> x2(n), y2(m);\n    for(size_t j = 0; j < n; j++)\n        x2[j] = 0.0;\n    // compute diagonal elements of the Hessian\n    for(size_t j = 0; j < n; j++)\n    {   // first order forward in j-th direction\n        x1[j] = 1.0;\n        f.Forward(1, x1);\n        y2 = f.Forward(2, x2);\n        // check this element of Hessian diagonal\n        ok &= NearEqual(y2[0], check_hes_0[j * n + j] / 2.0, eps, eps);\n        ok &= NearEqual(y2[1], check_hes_1[j * n + j] / 2.0, eps, eps);\n        //\n        for(size_t k = 0; k < n; k++) if( k != j )\n        {   x1[k] = 1.0;\n            f.Forward(1, x1);\n            y2 = f.Forward(2, x2);\n            //\n            // y2 = (H_jj + H_kk + H_jk + H_kj) / 2.0\n            // y2 = (H_jj + H_kk) / 2.0 + H_jk\n            //\n            double H_jj = check_hes_0[j * n + j];\n            double H_kk = check_hes_0[k * n + k];\n            double H_jk = y2[0] - (H_kk + H_jj) / 2.0;\n            ok &= NearEqual(H_jk, check_hes_0[j * n + k], eps, eps);\n            //\n            H_jj = check_hes_1[j * n + j];\n            H_kk = check_hes_1[k * n + k];\n            H_jk = y2[1] - (H_kk + H_jj) / 2.0;\n            ok &= NearEqual(H_jk, check_hes_1[j * n + k], eps, eps);\n            //\n            x1[k] = 0.0;\n        }\n        x1[j] = 0.0;\n    }\n    // --------------------------------------------------------------------\n    return ok;\n}\n/* %$$\n$end\n*/\n"
  },
  {
    "path": "test_more/deprecated/atomic_two/get_started.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n@begin atomic_two_get_started.cpp@@\n\n$section Getting Started with Atomic Operations: Example and Test$$\n\n$head Purpose$$\nThis example demonstrates the minimal amount of information\nnecessary for a $cref atomic_two$$ operation.\n\n$head Start Class Definition$$\n$srccode%cpp% */\n# include <cppad/cppad.hpp>\nnamespace {          // isolate items below to this file\nusing CppAD::vector; // abbreviate as vector\nclass atomic_get_started : public CppAD::atomic_base<double> {\n/* %$$\n\n$head Constructor$$\n$srccode%cpp% */\npublic:\n    // constructor (could use const char* for name)\n    atomic_get_started(const std::string& name) :\n    // this example does not use any sparsity patterns\n    CppAD::atomic_base<double>(name)\n    { }\nprivate:\n/* %$$\n$head forward$$\n$srccode%cpp% */\n    // forward mode routine called by CppAD\n    virtual bool forward(\n        size_t                    p ,\n        size_t                    q ,\n        const vector<bool>&      vx ,\n                  vector<bool>&      vy ,\n        const vector<double>&    tx ,\n                  vector<double>&    ty\n    )\n    {\n# ifndef NDEBUG\n        size_t n = tx.size() / (q + 1);\n        size_t m = ty.size() / (q + 1);\n# endif\n        assert( n == 1 );\n        assert( m == 1 );\n\n        // return flag\n        bool ok = q == 0;\n        if( ! ok )\n            return ok;\n\n        // check for defining variable information\n        // This case must always be implemented\n        if( vx.size() > 0 )\n            vy[0] = vx[0];\n\n        // Order zero forward mode.\n        // This case must always be implemented\n        // y^0 = f( x^0 ) = 1 / x^0\n        double f = 1. / tx[0];\n        if( p <= 0 )\n            ty[0] = f;\n        return ok;\n    }\n/* %$$\n$head End Class Definition$$\n$srccode%cpp% */\n}; // End of atomic_get_started class\n}  // End empty namespace\n\n/* %$$\n$head Use Atomic Function$$\n$srccode%cpp% */\nbool get_started(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps = 10. * CppAD::numeric_limits<double>::epsilon();\n/* %$$\n$subhead Constructor$$\n$srccode%cpp% */\n    // Create the atomic get_started object\n    atomic_get_started afun(\"atomic_get_started\");\n/* %$$\n$subhead Recording$$\n$srccode%cpp% */\n    // Create the function f(x)\n    //\n    // domain space vector\n    size_t n  = 1;\n    double  x0 = 0.5;\n    vector< AD<double> > ax(n);\n    ax[0]     = x0;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(ax);\n\n    // range space vector\n    size_t m = 1;\n    vector< AD<double> > ay(m);\n\n    // call atomic function and store get_started(x) in au[0]\n    vector< AD<double> > au(m);\n    afun(ax, au);        // u = 1 / x\n\n    // now use AD division to invert to invert the operation\n    ay[0] = 1.0 / au[0]; // y = 1 / u = x\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f;\n    f.Dependent (ax, ay);  // f(x) = x\n/* %$$\n$subhead forward$$\n$srccode%cpp% */\n    // check function value\n    double check = x0;\n    ok &= NearEqual( Value(ay[0]) , check,  eps, eps);\n\n    // check zero order forward mode\n    size_t q;\n    vector<double> x_q(n), y_q(m);\n    q      = 0;\n    x_q[0] = x0;\n    y_q    = f.Forward(q, x_q);\n    ok &= NearEqual(y_q[0] , check,  eps, eps);\n\n    return ok;\n}\n/* %$$\n$end\n*/\n"
  },
  {
    "path": "test_more/deprecated/atomic_two/mat_mul.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n@begin atomic_two_mat_mul.cpp@@\n$spell\n    mul\n$$\n\n$section User Atomic Matrix Multiply: Example and Test$$\n\n$head See Also$$\n$cref atomic_two_eigen_mat_mul.cpp$$\n\n$children%\n    include/cppad/example/atomic_three/mat_mul.hpp\n%$$\n\n$head Class Definition$$\nThis example uses the file $cref atomic_three_mat_mul.hpp$$\nwhich defines matrix multiply as a $cref atomic_two$$ operation.\n\n$head Use Atomic Function$$\n$srccode%cpp% */\n# include <cppad/cppad.hpp>\n# include \"mat_mul.hpp\"\n\nbool mat_mul(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::vector;\n    size_t i, j;\n/* %$$\n$subhead Constructor$$\n$srccode%cpp% */\n    // -------------------------------------------------------------------\n    // object that multiplies  2 x 2  matrices\n    atomic_mat_mul afun;\n/* %$$\n$subhead Recording$$\n$srccode%cpp% */\n    // start recording with four independent variables\n    size_t n = 4;\n    vector<double> x(n);\n    vector< AD<double> > ax(n);\n    for(j = 0; j < n; j++)\n        ax[j] = x[j] = double(j + 1);\n    CppAD::Independent(ax);\n\n    // ------------------------------------------------------------------\n    size_t nr_left = 2;\n    size_t n_middle  = 2;\n    size_t nc_right = 2;\n    vector< AD<double> > atom_x(3 + (nr_left + nc_right) * n_middle );\n\n    // matrix dimensions\n    atom_x[0] = AD<double>( nr_left );\n    atom_x[1] = AD<double>( n_middle );\n    atom_x[2] = AD<double>( nc_right );\n\n    // left matrix\n    atom_x[3] = ax[0];  // left[0, 0] = x0\n    atom_x[4] = ax[1];  // left[0, 1] = x1\n    atom_x[5] = 5.;     // left[1, 0] = 5\n    atom_x[6] = 6.;     // left[1, 1] = 6\n\n    // right matrix\n    atom_x[7] = ax[2];  // right[0, 0] = x2\n    atom_x[8] = 7.;     // right[0, 1] = 7\n    atom_x[9] = ax[3];  // right[1, 0] = x3\n    atom_x[10] = 8.;     // right[1, 1] = 8\n    // ------------------------------------------------------------------\n    /*\n    [ x0 , x1 ] * [ x2 , 7 ] = [ x0*x2 + x1*x3 , x0*7 + x1*8 ]\n    [ 5  , 6  ]   [ x3 , 8 ]   [  5*x2 +  6*x3 ,  5*7 +  6*8 ]\n    */\n    vector< AD<double> > atom_y(nr_left * nc_right);\n    afun(atom_x, atom_y);\n\n    ok &= (atom_y[0] == x[0]*x[2] + x[1]*x[3]) && Variable(atom_y[0]);\n    ok &= (atom_y[1] == x[0]*7.   + x[1]*8.  ) && Variable(atom_y[1]);\n    ok &= (atom_y[2] ==   5.*x[2] +   6.*x[3]) && Variable(atom_y[2]);\n    ok &= (atom_y[3] ==   5.*7.   +   6.*8.  ) && Parameter(atom_y[3]);\n\n    // ------------------------------------------------------------------\n    // define the function g : x -> atom_y\n    // g(x) = [ x0*x2 + x1*x3 , x0*7 + x1*8 , 5*x2  + 6*x3  , 5*7 + 6*8 ]^T\n    CppAD::ADFun<double> g(ax, atom_y);\n/* %$$\n$subhead forward$$\n$srccode%cpp% */\n    // Test zero order forward mode evaluation of g(x)\n    size_t m = atom_y.size();\n    vector<double> y(m);\n    for(j = 0; j <  n; j++)\n        x[j] = double(j + 2);\n    y = g.Forward(0, x);\n    ok &= y[0] == x[0] * x[2] + x[1] * x[3];\n    ok &= y[1] == x[0] * 7.   + x[1] * 8.;\n    ok &= y[2] == 5. * x[2]   + 6. * x[3];\n    ok &= y[3] == 5. * 7.     + 6. * 8.;\n\n    //----------------------------------------------------------------------\n    // Test first order forward mode evaluation of g'(x) * [1, 2, 3, 4]^T\n    // g'(x) = [ x2, x3, x0, x1 ]\n    //         [ 7 ,  8,  0, 0  ]\n    //         [ 0 ,  0,  5, 6  ]\n    //         [ 0 ,  0,  0, 0  ]\n    CppAD::vector<double> dx(n), dy(m);\n    for(j = 0; j <  n; j++)\n        dx[j] = double(j + 1);\n    dy = g.Forward(1, dx);\n    ok &= dy[0] == 1. * x[2] + 2. * x[3] + 3. * x[0] + 4. * x[1];\n    ok &= dy[1] == 1. * 7.   + 2. * 8.   + 3. * 0.   + 4. * 0.;\n    ok &= dy[2] == 1. * 0.   + 2. * 0.   + 3. * 5.   + 4. * 6.;\n    ok &= dy[3] == 1. * 0.   + 2. * 0.   + 3. * 0.   + 4. * 0.;\n\n    //----------------------------------------------------------------------\n    // Test second order forward mode\n    // g_0^2 (x) = [ 0, 0, 1, 0 ], g_0^2 (x) * [1] = [3]\n    //             [ 0, 0, 0, 1 ]              [2]   [4]\n    //             [ 1, 0, 0, 0 ]              [3]   [1]\n    //             [ 0, 1, 0, 0 ]              [4]   [2]\n    CppAD::vector<double> ddx(n), ddy(m);\n    for(j = 0; j <  n; j++)\n        ddx[j] = 0.;\n    ddy = g.Forward(2, ddx);\n\n    // [1, 2, 3, 4] * g_0^2 (x) * [1, 2, 3, 4]^T = 1*3 + 2*4 + 3*1 + 4*2\n    ok &= 2. * ddy[0] == 1. * 3. + 2. * 4. + 3. * 1. + 4. * 2.;\n\n    // for i > 0, [1, 2, 3, 4] * g_i^2 (x) * [1, 2, 3, 4]^T = 0\n    ok &= ddy[1] == 0.;\n    ok &= ddy[2] == 0.;\n    ok &= ddy[3] == 0.;\n/* %$$\n$subhead reverse$$\n$srccode%cpp% */\n    // Test second order reverse mode\n    CppAD::vector<double> w(m), dw(2 * n);\n    for(i = 0; i < m; i++)\n        w[i] = 0.;\n    w[0] = 1.;\n    dw = g.Reverse(2, w);\n\n    // g_0'(x) = [ x2, x3, x0, x1 ]\n    ok &= dw[0*2 + 0] == x[2];\n    ok &= dw[1*2 + 0] == x[3];\n    ok &= dw[2*2 + 0] == x[0];\n    ok &= dw[3*2 + 0] == x[1];\n\n    // g_0'(x)   * [1, 2, 3, 4]  = 1 * x2 + 2 * x3 + 3 * x0 + 4 * x1\n    // g_0^2 (x) * [1, 2, 3, 4]  = [3, 4, 1, 2]\n    ok &= dw[0*2 + 1] == 3.;\n    ok &= dw[1*2 + 1] == 4.;\n    ok &= dw[2*2 + 1] == 1.;\n    ok &= dw[3*2 + 1] == 2.;\n/* %$$\n$subhead option$$\n$srccode%cpp% */\n    //----------------------------------------------------------------------\n    // Test both the boolean and set sparsity at the atomic level\n    for(size_t sparse_index = 0; sparse_index < 2; sparse_index++)\n    {   if( sparse_index == 0 )\n            afun.option( CppAD::atomic_base<double>::bool_sparsity_enum );\n        else\n            afun.option( CppAD::atomic_base<double>::set_sparsity_enum );\n/* %$$\n$subhead for_sparse_jac$$\n$srccode%cpp% */\n    // Test forward Jacobian sparsity pattern\n    /*\n    g(x) = [ x0*x2 + x1*x3 , x0*7 + x1*8 , 5*x2  + 6*x3  , 5*7 + 6*8 ]^T\n    so the sparsity pattern should be\n    s[0] = {0, 1, 2, 3}\n    s[1] = {0, 1}\n    s[2] = {2, 3}\n    s[3] = {}\n    */\n    CppAD::vector< std::set<size_t> > r(n), s(m);\n    for(j = 0; j <  n; j++)\n    {   assert( r[j].empty() );\n        r[j].insert(j);\n    }\n    s = g.ForSparseJac(n, r);\n    for(j = 0; j <  n; j++)\n    {   // s[0] = {0, 1, 2, 3}\n        ok &= s[0].find(j) != s[0].end();\n        // s[1] = {0, 1}\n        if( j == 0 || j == 1 )\n            ok &= s[1].find(j) != s[1].end();\n        else\n            ok &= s[1].find(j) == s[1].end();\n        // s[2] = {2, 3}\n        if( j == 2 || j == 3 )\n            ok &= s[2].find(j) != s[2].end();\n        else\n            ok &= s[2].find(j) == s[2].end();\n    }\n    // s[3] == {}\n    ok &= s[3].empty();\n/* %$$\n$subhead rev_sparse_jac$$\n$srccode%cpp% */\n    // Test reverse Jacobian sparsity pattern\n    for(i = 0; i <  m; i++)\n    {   s[i].clear();\n        s[i].insert(i);\n    }\n    r = g.RevSparseJac(m, s);\n    for(j = 0; j <  n ; j++)\n    {   // r[0] = {0, 1, 2, 3}\n        ok &= r[0].find(j) != r[0].end();\n        // r[1] = {0, 1}\n        if( j == 0 || j == 1 )\n            ok &= r[1].find(j) != r[1].end();\n        else\n            ok &= r[1].find(j) == r[1].end();\n        // r[2] = {2, 3}\n        if( j == 2 || j == 3 )\n            ok &= r[2].find(j) != r[2].end();\n        else\n            ok &= r[2].find(j) == r[2].end();\n    }\n    // r[3] == {}\n    ok &= r[3].empty();\n/* %$$\n$subhead rev_sparse_hes$$\n$srccode%cpp% */\n    /* Test reverse Hessian sparsity pattern\n    g_0^2 (x) = [ 0, 0, 1, 0 ] and for i > 0, g_i^2 = 0\n                [ 0, 0, 0, 1 ]\n                [ 1, 0, 0, 0 ]\n                [ 0, 1, 0, 0 ]\n    so for the sparsity pattern for the first component of g is\n    h[0] = {2}\n    h[1] = {3}\n    h[2] = {0}\n    h[3] = {1}\n    */\n    CppAD::vector< std::set<size_t> > h(n), t(1);\n    t[0].clear();\n    t[0].insert(0);\n    h = g.RevSparseHes(n, t);\n    size_t check[] = {2, 3, 0, 1};\n    for(j = 0; j <  n; j++)\n    {   // h[j] = { check[j] }\n        for(i = 0; i < n; i++)\n        {   if( i == check[j] )\n                ok &= h[j].find(i) != h[j].end();\n            else\n                ok &= h[j].find(i) == h[j].end();\n        }\n    }\n    t[0].clear();\n    for( j = 1; j < n; j++)\n            t[0].insert(j);\n    h = g.RevSparseHes(n, t);\n    for(j = 0; j <  n; j++)\n    {   // h[j] = { }\n        for(i = 0; i < n; i++)\n            ok &= h[j].find(i) == h[j].end();\n    }\n\n    //-----------------------------------------------------------------\n    } // end for(size_t sparse_index  ...\n    //-----------------------------------------------------------------\n\n    return ok;\n}\n/* %$$\n$end\n*/\n"
  },
  {
    "path": "test_more/deprecated/atomic_two/mat_mul.hpp",
    "content": "# ifndef CPPAD_TEST_MORE_DEPRECATED_ATOMIC_TWO_MAT_MUL_HPP\n# define CPPAD_TEST_MORE_DEPRECATED_ATOMIC_TWO_MAT_MUL_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n@begin atomic_three_mat_mul.hpp@@\n$spell\n    Taylor\n    ty\n    px\n    CppAD\n    jac\n    hes\n    nr\n    nc\n$$\n\n$section Matrix Multiply as an Atomic Operation$$\n\n$head See Also$$\n$cref atomic_two_eigen_mat_mul.hpp$$\n\n$head Matrix Dimensions$$\nThis example puts the matrix dimensions in the atomic function arguments,\ninstead of the $cref/constructor/atomic_two_ctor/$$, so that they can\nbe different for different calls to the atomic function.\nThese dimensions are:\n$table\n$icode nr_left$$ $cnext number of rows in the left matrix $rend\n$icode n_middle$$ $cnext rows in the left matrix and columns in right $rend\n$icode nc_right$$ $cnext number of columns in the right matrix\n$tend\n\n$head Start Class Definition$$\n$srccode%cpp% */\n# include <cppad/cppad.hpp>\nnamespace { // Begin empty namespace\nusing CppAD::vector;\n//\nusing CppAD::set_union;\n//\n// matrix result = left * right\nclass atomic_mat_mul : public CppAD::atomic_base<double> {\n/* %$$\n$head Constructor$$\n$srccode%cpp% */\npublic:\n    // ---------------------------------------------------------------------\n    // constructor\n    atomic_mat_mul(void) : CppAD::atomic_base<double>(\"mat_mul\")\n    { }\nprivate:\n/* %$$\n$head Left Operand Element Index$$\nIndex in the Taylor coefficient matrix $icode tx$$ of a left matrix element.\n$srccode%cpp% */\n    size_t left(\n        size_t i        , // left matrix row index\n        size_t j        , // left matrix column index\n        size_t k        , // Taylor coeffocient order\n        size_t nk       , // number of Taylor coefficients in tx\n        size_t nr_left  , // rows in left matrix\n        size_t n_middle , // rows in left and columns in right\n        size_t nc_right ) // columns in right matrix\n    {   assert( i < nr_left );\n        assert( j < n_middle );\n        return (3 + i * n_middle + j) * nk + k;\n    }\n/* %$$\n$head Right Operand Element Index$$\nIndex in the Taylor coefficient matrix $icode tx$$ of a right matrix element.\n$srccode%cpp% */\n    size_t right(\n        size_t i        , // right matrix row index\n        size_t j        , // right matrix column index\n        size_t k        , // Taylor coeffocient order\n        size_t nk       , // number of Taylor coefficients in tx\n        size_t nr_left  , // rows in left matrix\n        size_t n_middle , // rows in left and columns in right\n        size_t nc_right ) // columns in right matrix\n    {   assert( i < n_middle );\n        assert( j < nc_right );\n        size_t offset = 3 + nr_left * n_middle;\n        return (offset + i * nc_right + j) * nk + k;\n    }\n/* %$$\n$head Result Element Index$$\nIndex in the Taylor coefficient matrix $icode ty$$ of a result matrix element.\n$srccode%cpp% */\n    size_t result(\n        size_t i        , // result matrix row index\n        size_t j        , // result matrix column index\n        size_t k        , // Taylor coeffocient order\n        size_t nk       , // number of Taylor coefficients in ty\n        size_t nr_left  , // rows in left matrix\n        size_t n_middle , // rows in left and columns in right\n        size_t nc_right ) // columns in right matrix\n    {   assert( i < nr_left  );\n        assert( j < nc_right );\n        return (i * nc_right + j) * nk + k;\n    }\n/* %$$\n$head Forward Matrix Multiply$$\nForward mode multiply Taylor coefficients in $icode tx$$ and sum into\n$icode ty$$ (for one pair of left and right orders)\n$srccode%cpp% */\n    void forward_multiply(\n        size_t                 k_left   , // order for left coefficients\n        size_t                 k_right  , // order for right coefficients\n        const vector<double>&  tx       , // domain space Taylor coefficients\n                  vector<double>&  ty       , // range space Taylor coefficients\n        size_t                 nr_left  , // rows in left matrix\n        size_t                 n_middle , // rows in left and columns in right\n        size_t                 nc_right ) // columns in right matrix\n    {\n        size_t nx       = 3 + (nr_left + nc_right) * n_middle;\n        size_t nk       = tx.size() / nx;\n# ifndef NDEBUG\n        size_t ny       = nr_left * nc_right;\n        assert( nk == ty.size() / ny );\n# endif\n        //\n        size_t k_result = k_left + k_right;\n        assert( k_result < nk );\n        //\n        for(size_t i = 0; i < nr_left; i++)\n        {   for(size_t j = 0; j < nc_right; j++)\n            {   double sum = 0.0;\n                for(size_t ell = 0; ell < n_middle; ell++)\n                {   size_t i_left  = left(\n                        i, ell, k_left, nk, nr_left, n_middle, nc_right\n                    );\n                    size_t i_right = right(\n                        ell, j,  k_right, nk, nr_left, n_middle, nc_right\n                    );\n                    sum           += tx[i_left] * tx[i_right];\n                }\n                size_t i_result = result(\n                    i, j, k_result, nk, nr_left, n_middle, nc_right\n                );\n                ty[i_result]   += sum;\n            }\n        }\n    }\n/* %$$\n$head Reverse Matrix Multiply$$\nReverse mode partials of Taylor coefficients and sum into $icode px$$\n(for one pair of left and right orders)\n$srccode%cpp% */\n    void reverse_multiply(\n        size_t                 k_left  , // order for left coefficients\n        size_t                 k_right , // order for right coefficients\n        const vector<double>&  tx      , // domain space Taylor coefficients\n        const vector<double>&  ty      , // range space Taylor coefficients\n                  vector<double>&  px      , // partials w.r.t. tx\n        const vector<double>&  py      , // partials w.r.t. ty\n        size_t                 nr_left  , // rows in left matrix\n        size_t                 n_middle , // rows in left and columns in right\n        size_t                 nc_right ) // columns in right matrix\n    {\n        size_t nx       = 3 + (nr_left + nc_right) * n_middle;\n        size_t nk       = tx.size() / nx;\n# ifndef NDEBUG\n        size_t ny       = nr_left * nc_right;\n        assert( nk == ty.size() / ny );\n# endif\n        assert( tx.size() == px.size() );\n        assert( ty.size() == py.size() );\n        //\n        size_t k_result = k_left + k_right;\n        assert( k_result < nk );\n        //\n        for(size_t i = 0; i < nr_left; i++)\n        {   for(size_t j = 0; j < nc_right; j++)\n            {   size_t i_result = result(\n                    i, j, k_result, nk, nr_left, n_middle, nc_right\n                );\n                for(size_t ell = 0; ell < n_middle; ell++)\n                {   size_t i_left  = left(\n                        i, ell, k_left, nk, nr_left, n_middle, nc_right\n                    );\n                    size_t i_right = right(\n                        ell, j,  k_right, nk, nr_left, n_middle, nc_right\n                    );\n                    // sum        += tx[i_left] * tx[i_right];\n                    px[i_left]    += tx[i_right] * py[i_result];\n                    px[i_right]   += tx[i_left]  * py[i_result];\n                }\n            }\n        }\n        return;\n    }\n/* %$$\n$head forward$$\nRoutine called by CppAD during $cref Forward$$ mode.\n$srccode%cpp% */\n    virtual bool forward(\n        size_t                    q ,\n        size_t                    p ,\n        const vector<bool>&      vx ,\n                  vector<bool>&      vy ,\n        const vector<double>&    tx ,\n                  vector<double>&    ty\n    )\n    {   size_t n_order  = p + 1;\n        size_t nr_left  = size_t( tx[ 0 * n_order + 0 ] );\n        size_t n_middle = size_t( tx[ 1 * n_order + 0 ] );\n        size_t nc_right = size_t( tx[ 2 * n_order + 0 ] );\n# ifndef NDEBUG\n        size_t nx       = 3 + (nr_left + nc_right) * n_middle;\n        size_t ny       = nr_left * nc_right;\n# endif\n        assert( vx.size() == 0 || nx == vx.size() );\n        assert( vx.size() == 0 || ny == vy.size() );\n        assert( nx * n_order == tx.size() );\n        assert( ny * n_order == ty.size() );\n        size_t i, j, ell;\n\n        // check if we are computing vy information\n        if( vx.size() > 0 )\n        {   size_t nk = 1;\n            size_t k  = 0;\n            for(i = 0; i < nr_left; i++)\n            {   for(j = 0; j < nc_right; j++)\n                {   bool var = false;\n                    for(ell = 0; ell < n_middle; ell++)\n                    {   size_t i_left  = left(\n                            i, ell, k, nk, nr_left, n_middle, nc_right\n                        );\n                        size_t i_right = right(\n                            ell, j, k, nk, nr_left, n_middle, nc_right\n                        );\n                        bool   nz_left = vx[i_left] || (tx[i_left]  != 0.);\n                        bool  nz_right = vx[i_right] || (tx[i_right] != 0.);\n                        // if not multiplying by the constant zero\n                        if( nz_left & nz_right )\n                                var |= bool(vx[i_left]) || bool(vx[i_right]);\n                    }\n                    size_t i_result = result(\n                        i, j, k, nk, nr_left, n_middle, nc_right\n                    );\n                    vy[i_result] = var;\n                }\n            }\n        }\n\n        // initialize result as zero\n        size_t k;\n        for(i = 0; i < nr_left; i++)\n        {   for(j = 0; j < nc_right; j++)\n            {   for(k = q; k <= p; k++)\n                {   size_t i_result = result(\n                        i, j, k, n_order, nr_left, n_middle, nc_right\n                    );\n                    ty[i_result] = 0.0;\n                }\n            }\n        }\n        for(k = q; k <= p; k++)\n        {   // sum the produces that result in order k\n            for(ell = 0; ell <= k; ell++)\n                forward_multiply(\n                    ell, k - ell, tx, ty, nr_left, n_middle, nc_right\n                );\n        }\n\n        // all orders are implemented, so always return true\n        return true;\n    }\n/* %$$\n$head reverse$$\nRoutine called by CppAD during $cref Reverse$$ mode.\n$srccode%cpp% */\n    virtual bool reverse(\n        size_t                     p ,\n        const vector<double>&     tx ,\n        const vector<double>&     ty ,\n                  vector<double>&     px ,\n        const vector<double>&     py\n    )\n    {   size_t n_order  = p + 1;\n        size_t nr_left  = size_t( tx[ 0 * n_order + 0 ] );\n        size_t n_middle = size_t( tx[ 1 * n_order + 0 ] );\n        size_t nc_right = size_t( tx[ 2 * n_order + 0 ] );\n# ifndef NDEBUG\n        size_t nx       = 3 + (nr_left + nc_right) * n_middle;\n        size_t ny       = nr_left * nc_right;\n# endif\n        assert( nx * n_order == tx.size() );\n        assert( ny * n_order == ty.size() );\n        assert( px.size() == tx.size() );\n        assert( py.size() == ty.size() );\n\n        // initialize summation\n        for(size_t i = 0; i < px.size(); i++)\n            px[i] = 0.0;\n\n        // number of orders to differentiate\n        size_t k = n_order;\n        while(k--)\n        {   // differentiate the produces that result in order k\n            for(size_t ell = 0; ell <= k; ell++)\n                reverse_multiply(\n                    ell, k - ell, tx, ty, px, py, nr_left, n_middle, nc_right\n                );\n        }\n\n        // all orders are implemented, so always return true\n        return true;\n    }\n/* %$$\n$head for_sparse_jac$$\nRoutines called by CppAD during $cref ForSparseJac$$.\n$srccode%cpp% */\n    // boolean sparsity patterns\n    virtual bool for_sparse_jac(\n        size_t                                q ,\n        const vector<bool>&                   r ,\n                  vector<bool>&                   s ,\n        const vector<double>&                 x )\n    {\n        size_t nr_left  = size_t( CppAD::Integer( x[0] ) );\n        size_t n_middle = size_t( CppAD::Integer( x[1] ) );\n        size_t nc_right = size_t( CppAD::Integer( x[2] ) );\n# ifndef NDEBUG\n        size_t  nx      = 3 + (nr_left + nc_right) * n_middle;\n        size_t  ny      = nr_left * nc_right;\n# endif\n        assert( nx     == x.size() );\n        assert( nx * q == r.size() );\n        assert( ny * q == s.size() );\n        size_t p;\n\n        // sparsity for S(x) = f'(x) * R\n        size_t nk = 1;\n        size_t k  = 0;\n        for(size_t i = 0; i < nr_left; i++)\n        {   for(size_t j = 0; j < nc_right; j++)\n            {   size_t i_result = result(\n                    i, j, k, nk, nr_left, n_middle, nc_right\n                );\n                for(p = 0; p < q; p++)\n                    s[i_result * q + p] = false;\n                for(size_t ell = 0; ell < n_middle; ell++)\n                {   size_t i_left  = left(\n                        i, ell, k, nk, nr_left, n_middle, nc_right\n                    );\n                    size_t i_right = right(\n                        ell, j, k, nk, nr_left, n_middle, nc_right\n                    );\n                    for(p = 0; p < q; p++)\n                    {   // cast avoids Microsoft warning (should not be needed)\n                        s[i_result * q + p] |= bool( r[i_left * q + p ] );\n                        s[i_result * q + p] |= bool( r[i_right * q + p ] );\n                    }\n                }\n            }\n        }\n        return true;\n    }\n    // set sparsity patterns\n    virtual bool for_sparse_jac(\n        size_t                                q ,\n        const vector< std::set<size_t> >&     r ,\n                  vector< std::set<size_t> >&     s ,\n        const vector<double>&                 x )\n    {\n        size_t nr_left  = size_t( CppAD::Integer( x[0] ) );\n        size_t n_middle = size_t( CppAD::Integer( x[1] ) );\n        size_t nc_right = size_t( CppAD::Integer( x[2] ) );\n# ifndef NDEBUG\n        size_t  nx      = 3 + (nr_left + nc_right) * n_middle;\n        size_t  ny      = nr_left * nc_right;\n# endif\n        assert( nx == x.size() );\n        assert( nx == r.size() );\n        assert( ny == s.size() );\n\n        // sparsity for S(x) = f'(x) * R\n        size_t nk = 1;\n        size_t k  = 0;\n        for(size_t i = 0; i < nr_left; i++)\n        {   for(size_t j = 0; j < nc_right; j++)\n            {   size_t i_result = result(\n                    i, j, k, nk, nr_left, n_middle, nc_right\n                );\n                s[i_result].clear();\n                for(size_t ell = 0; ell < n_middle; ell++)\n                {   size_t i_left  = left(\n                        i, ell, k, nk, nr_left, n_middle, nc_right\n                    );\n                    size_t i_right = right(\n                        ell, j, k, nk, nr_left, n_middle, nc_right\n                    );\n                    //\n                    s[i_result] = set_union(s[i_result], r[i_left] );\n                    s[i_result] = set_union(s[i_result], r[i_right] );\n                }\n            }\n        }\n        return true;\n    }\n/* %$$\n$head rev_sparse_jac$$\nRoutines called by CppAD during $cref RevSparseJac$$.\n$srccode%cpp% */\n    // boolean sparsity patterns\n    virtual bool rev_sparse_jac(\n        size_t                                q ,\n        const vector<bool>&                  rt ,\n                  vector<bool>&                  st ,\n        const vector<double>&                 x )\n    {\n        size_t nr_left  = size_t( CppAD::Integer( x[0] ) );\n        size_t n_middle = size_t( CppAD::Integer( x[1] ) );\n        size_t nc_right = size_t( CppAD::Integer( x[2] ) );\n        size_t  nx      = 3 + (nr_left + nc_right) * n_middle;\n# ifndef NDEBUG\n        size_t  ny      = nr_left * nc_right;\n# endif\n        assert( nx     == x.size() );\n        assert( nx * q == st.size() );\n        assert( ny * q == rt.size() );\n        size_t i, j, p;\n\n        // initialize\n        for(i = 0; i < nx; i++)\n        {   for(p = 0; p < q; p++)\n                st[ i * q + p ] = false;\n        }\n\n        // sparsity for S(x)^T = f'(x)^T * R^T\n        size_t nk = 1;\n        size_t k  = 0;\n        for(i = 0; i < nr_left; i++)\n        {   for(j = 0; j < nc_right; j++)\n            {   size_t i_result = result(\n                    i, j, k, nk, nr_left, n_middle, nc_right\n                );\n                for(size_t ell = 0; ell < n_middle; ell++)\n                {   size_t i_left  = left(\n                        i, ell, k, nk, nr_left, n_middle, nc_right\n                    );\n                    size_t i_right = right(\n                        ell, j, k, nk, nr_left, n_middle, nc_right\n                    );\n                    for(p = 0; p < q; p++)\n                    {   st[i_left * q + p] |= bool( rt[i_result * q + p] );\n                        st[i_right* q + p] |= bool( rt[i_result * q + p] );\n                    }\n                }\n            }\n        }\n        return true;\n    }\n    // set sparsity patterns\n    virtual bool rev_sparse_jac(\n        size_t                                q ,\n        const vector< std::set<size_t> >&    rt ,\n                  vector< std::set<size_t> >&    st ,\n        const vector<double>&                 x )\n    {\n        size_t nr_left  = size_t( CppAD::Integer( x[0] ) );\n        size_t n_middle = size_t( CppAD::Integer( x[1] ) );\n        size_t nc_right = size_t( CppAD::Integer( x[2] ) );\n        size_t  nx      = 3 + (nr_left + nc_right) * n_middle;\n# ifndef NDEBUG\n        size_t  ny        = nr_left * nc_right;\n# endif\n        assert( nx == x.size() );\n        assert( nx == st.size() );\n        assert( ny == rt.size() );\n        size_t i, j;\n\n        // initialize\n        for(i = 0; i < nx; i++)\n            st[i].clear();\n\n        // sparsity for S(x)^T = f'(x)^T * R^T\n        size_t nk = 1;\n        size_t k  = 0;\n        for(i = 0; i < nr_left; i++)\n        {   for(j = 0; j < nc_right; j++)\n            {   size_t i_result = result(\n                    i, j, k, nk, nr_left, n_middle, nc_right\n                );\n                for(size_t ell = 0; ell < n_middle; ell++)\n                {   size_t i_left  = left(\n                        i, ell, k, nk, nr_left, n_middle, nc_right\n                    );\n                    size_t i_right = right(\n                        ell, j, k, nk, nr_left, n_middle, nc_right\n                    );\n                    //\n                    st[i_left]  = set_union(st[i_left],  rt[i_result]);\n                    st[i_right] = set_union(st[i_right], rt[i_result]);\n                }\n            }\n        }\n        return true;\n    }\n/* %$$\n$head rev_sparse_hes$$\nRoutines called by $cref RevSparseHes$$.\n$srccode%cpp% */\n    // set sparsity patterns\n    virtual bool rev_sparse_hes(\n        const vector<bool>&                   vx,\n        const vector<bool>&                   s ,\n                  vector<bool>&                   t ,\n        size_t                                q ,\n        const vector< std::set<size_t> >&     r ,\n        const vector< std::set<size_t> >&     u ,\n                  vector< std::set<size_t> >&     v ,\n        const vector<double>&                 x )\n    {\n        size_t nr_left  = size_t( CppAD::Integer( x[0] ) );\n        size_t n_middle = size_t( CppAD::Integer( x[1] ) );\n        size_t nc_right = size_t( CppAD::Integer( x[2] ) );\n        size_t  nx        = 3 + (nr_left + nc_right) * n_middle;\n# ifndef NDEBUG\n        size_t  ny        = nr_left * nc_right;\n# endif\n        assert( x.size()  == nx );\n        assert( vx.size() == nx );\n        assert( t.size()  == nx );\n        assert( r.size()  == nx );\n        assert( v.size()  == nx );\n        assert( s.size()  == ny );\n        assert( u.size()  == ny );\n        //\n        size_t i, j;\n        //\n        // initialize sparsity patterns as false\n        for(j = 0; j < nx; j++)\n        {   t[j] = false;\n            v[j].clear();\n        }\n        size_t nk = 1;\n        size_t k  = 0;\n        for(i = 0; i < nr_left; i++)\n        {   for(j = 0; j < nc_right; j++)\n            {   size_t i_result = result(\n                    i, j, k, nk, nr_left, n_middle, nc_right\n                );\n                for(size_t ell = 0; ell < n_middle; ell++)\n                {   size_t i_left  = left(\n                        i, ell, k, nk, nr_left, n_middle, nc_right\n                    );\n                    size_t i_right = right(\n                        ell, j, k, nk, nr_left, n_middle, nc_right\n                    );\n                    //\n                    // Compute sparsity for T(x) = S(x) * f'(x).\n                    // We need not use vx with f'(x) back propagation.\n                    t[i_left]  |= bool( s[i_result] );\n                    t[i_right] |= bool( s[i_result] );\n\n                    // V(x) = f'(x)^T * U(x) +  S(x) * f''(x) * R\n                    // U(x) = g''(y) * f'(x) * R\n                    // S(x) = g'(y)\n\n                    // back propagate f'(x)^T * U(x)\n                    // (no need to use vx with f'(x) propagation)\n                    v[i_left]  = set_union(v[i_left],  u[i_result] );\n                    v[i_right] = set_union(v[i_right], u[i_result] );\n\n                    // back propagate S(x) * f''(x) * R\n                    // (here is where we must check for cross terms)\n                    if( s[i_result] && vx[i_left] && vx[i_right] )\n                    {   v[i_left]  = set_union(v[i_left],  r[i_right] );\n                        v[i_right] = set_union(v[i_right], r[i_left]  );\n                    }\n                }\n            }\n        }\n        return true;\n    }\n    // bool sparsity\n    virtual bool rev_sparse_hes(\n        const vector<bool>&                   vx,\n        const vector<bool>&                   s ,\n                  vector<bool>&                   t ,\n        size_t                                q ,\n        const vector<bool>&                   r ,\n        const vector<bool>&                   u ,\n                  vector<bool>&                   v ,\n        const vector<double>&                 x )\n    {\n        size_t nr_left  = size_t( CppAD::Integer( x[0] ) );\n        size_t n_middle = size_t( CppAD::Integer( x[1] ) );\n        size_t nc_right = size_t( CppAD::Integer( x[2] ) );\n        size_t  nx        = 3 + (nr_left + nc_right) * n_middle;\n# ifndef NDEBUG\n        size_t  ny        = nr_left * nc_right;\n# endif\n        assert( x.size()  == nx );\n        assert( vx.size() == nx );\n        assert( t.size()  == nx );\n        assert( r.size()  == nx * q );\n        assert( v.size()  == nx * q );\n        assert( s.size()  == ny );\n        assert( u.size()  == ny * q );\n        size_t i, j, p;\n        //\n        // initialize sparsity patterns as false\n        for(j = 0; j < nx; j++)\n        {   t[j] = false;\n            for(p = 0; p < q; p++)\n                v[j * q + p] = false;\n        }\n        size_t nk = 1;\n        size_t k  = 0;\n        for(i = 0; i < nr_left; i++)\n        {   for(j = 0; j < nc_right; j++)\n            {   size_t i_result = result(\n                    i, j, k, nk, nr_left, n_middle, nc_right\n                );\n                for(size_t ell = 0; ell < n_middle; ell++)\n                {   size_t i_left  = left(\n                        i, ell, k, nk, nr_left, n_middle, nc_right\n                    );\n                    size_t i_right = right(\n                        ell, j, k, nk, nr_left, n_middle, nc_right\n                    );\n                    //\n                    // Compute sparsity for T(x) = S(x) * f'(x).\n                    // We so not need to use vx with f'(x) propagation.\n                    t[i_left]  |= bool( s[i_result] );\n                    t[i_right] |= bool( s[i_result] );\n\n                    // V(x) = f'(x)^T * U(x) +  S(x) * f''(x) * R\n                    // U(x) = g''(y) * f'(x) * R\n                    // S(x) = g'(y)\n\n                    // back propagate f'(x)^T * U(x)\n                    // (no need to use vx with f'(x) propagation)\n                    for(p = 0; p < q; p++)\n                    {   v[ i_left  * q + p] |= bool( u[ i_result * q + p] );\n                        v[ i_right * q + p] |= bool( u[ i_result * q + p] );\n                    }\n\n                    // back propagate S(x) * f''(x) * R\n                    // (here is where we must check for cross terms)\n                    if( s[i_result] && vx[i_left] && vx[i_right] )\n                    {   for(p = 0; p < q; p++)\n                        {   v[i_left * q + p]  |= bool( r[i_right * q + p] );\n                            v[i_right * q + p] |= bool( r[i_left * q + p] );\n                        }\n                    }\n                }\n            }\n        }\n        return true;\n    }\n/* %$$\n$head End Class Definition$$\n$srccode%cpp% */\n}; // End of mat_mul class\n}  // End empty namespace\n/* %$$\n$end\n*/\n\n\n# endif\n"
  },
  {
    "path": "test_more/deprecated/atomic_two/norm_sq.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n@begin atomic_two_norm_sq.cpp@@\n$spell\n    sq\n    bool\n    enum\n$$\n\n$section Atomic Euclidean Norm Squared: Example and Test$$\n\n$head Theory$$\nThis example demonstrates using $cref atomic_two$$\nto define the operation\n$latex f : \\B{R}^n \\rightarrow \\B{R}^m$$ where\n$latex n = 2$$, $latex m = 1$$, where\n$latex \\[\n    f(x) =  x_0^2 + x_1^2\n\\] $$\n\n$head sparsity$$\nThis example only uses bool sparsity patterns.\n\n$head Start Class Definition$$\n$srccode%cpp% */\n# include <cppad/cppad.hpp>\nnamespace {           // isolate items below to this file\nusing CppAD::vector;  // abbreviate as vector\n//\nclass atomic_norm_sq : public CppAD::atomic_base<double> {\n/* %$$\n$head Constructor $$\n$srccode%cpp% */\npublic:\n    // constructor (could use const char* for name)\n    atomic_norm_sq(const std::string& name) :\n    // this example only uses boolean sparsity patterns\n    CppAD::atomic_base<double>(name, atomic_base<double>::bool_sparsity_enum)\n    { }\nprivate:\n/* %$$\n$head forward$$\n$srccode%cpp% */\n    // forward mode routine called by CppAD\n    virtual bool forward(\n        size_t                    p ,\n        size_t                    q ,\n        const vector<bool>&      vx ,\n                  vector<bool>&      vy ,\n        const vector<double>&    tx ,\n                  vector<double>&    ty\n    )\n    {\n# ifndef NDEBUG\n        size_t n = tx.size() / (q+1);\n        size_t m = ty.size() / (q+1);\n# endif\n        assert( n == 2 );\n        assert( m == 1 );\n        assert( p <= q );\n\n        // return flag\n        bool ok = q <= 1;\n\n        // Variable information must always be implemented.\n        // y_0 is a variable if and only if x_0 or x_1 is a variable.\n        if( vx.size() > 0 )\n            vy[0] = vx[0] || vx[1];\n\n        // Order zero forward mode must always be implemented.\n        // y^0 = f( x^0 )\n        double x_00 = tx[ 0*(q+1) + 0];        // x_0^0\n        double x_10 = tx[ 1*(q+1) + 0];        // x_10\n        double f = x_00 * x_00 + x_10 * x_10;  // f( x^0 )\n        if( p <= 0 )\n            ty[0] = f;   // y_0^0\n        if( q <= 0 )\n            return ok;\n        assert( vx.size() == 0 );\n\n        // Order one forward mode.\n        // This case needed if first order forward mode is used.\n        // y^1 = f'( x^0 ) x^1\n        double x_01 = tx[ 0*(q+1) + 1];   // x_0^1\n        double x_11 = tx[ 1*(q+1) + 1];   // x_1^1\n        double fp_0 = 2.0 * x_00;         // partial f w.r.t x_0^0\n        double fp_1 = 2.0 * x_10;         // partial f w.r.t x_1^0\n        if( p <= 1 )\n            ty[1] = fp_0 * x_01 + fp_1 * x_11; // f'( x^0 ) * x^1\n        if( q <= 1 )\n            return ok;\n\n        // Assume we are not using forward mode with order > 1\n        assert( ! ok );\n        return ok;\n    }\n/* %$$\n$head reverse$$\n$srccode%cpp% */\n    // reverse mode routine called by CppAD\n    virtual bool reverse(\n        size_t                    q ,\n        const vector<double>&    tx ,\n        const vector<double>&    ty ,\n                  vector<double>&    px ,\n        const vector<double>&    py\n    )\n    {\n# ifndef NDEBUG\n        size_t n = tx.size() / (q+1);\n        size_t m = ty.size() / (q+1);\n# endif\n        assert( px.size() == n * (q+1) );\n        assert( py.size() == m * (q+1) );\n        assert( n == 2 );\n        assert( m == 1 );\n        bool ok = q <= 1;\n\n        double fp_0, fp_1;\n        switch(q)\n        {   case 0:\n            // This case needed if first order reverse mode is used\n            // F ( {x} ) = f( x^0 ) = y^0\n            fp_0  =  2.0 * tx[0];  // partial F w.r.t. x_0^0\n            fp_1  =  2.0 * tx[1];  // partial F w.r.t. x_0^1\n            px[0] = py[0] * fp_0;; // partial G w.r.t. x_0^0\n            px[1] = py[0] * fp_1;; // partial G w.r.t. x_0^1\n            assert(ok);\n            break;\n\n            default:\n            // Assume we are not using reverse with order > 1 (q > 0)\n            assert(!ok);\n        }\n        return ok;\n    }\n/* %$$\n$head for_sparse_jac$$\n$srccode%cpp% */\n    // forward Jacobian bool sparsity routine called by CppAD\n    virtual bool for_sparse_jac(\n        size_t                                p ,\n        const vector<bool>&                   r ,\n                  vector<bool>&                   s ,\n        const vector<double>&                 x )\n    {   // This function needed if using f.ForSparseJac\n        size_t n = r.size() / p;\n# ifndef NDEBUG\n        size_t m = s.size() / p;\n# endif\n        assert( n == x.size() );\n        assert( n == 2 );\n        assert( m == 1 );\n\n        // sparsity for S(x) = f'(x) * R\n        // where f'(x) = 2 * [ x_0, x_1 ]\n        for(size_t j = 0; j < p; j++)\n        {   s[j] = false;\n            for(size_t i = 0; i < n; i++)\n            {   // Visual Studio 2013 generates warning without bool below\n                s[j] |= bool( r[i * p + j] );\n            }\n        }\n        return true;\n    }\n/* %$$\n$head rev_sparse_jac$$\n$srccode%cpp% */\n    // reverse Jacobian bool sparsity routine called by CppAD\n    virtual bool rev_sparse_jac(\n        size_t                                p  ,\n        const vector<bool>&                   rt ,\n                  vector<bool>&                   st ,\n        const vector<double>&                 x  )\n    {   // This function needed if using RevSparseJac or optimize\n        size_t n = st.size() / p;\n# ifndef NDEBUG\n        size_t m = rt.size() / p;\n# endif\n        assert( n == x.size() );\n        assert( n == 2 );\n        assert( m == 1 );\n\n        // sparsity for S(x)^T = f'(x)^T * R^T\n        // where f'(x)^T = 2 * [ x_0, x_1]^T\n        for(size_t j = 0; j < p; j++)\n            for(size_t i = 0; i < n; i++)\n                st[i * p + j] = rt[j];\n\n        return true;\n    }\n/* %$$\n$head rev_sparse_hes$$\n$srccode%cpp% */\n    // reverse Hessian bool sparsity routine called by CppAD\n    virtual bool rev_sparse_hes(\n        const vector<bool>&                   vx,\n        const vector<bool>&                   s ,\n                  vector<bool>&                   t ,\n        size_t                                p ,\n        const vector<bool>&                   r ,\n        const vector<bool>&                   u ,\n                  vector<bool>&                   v ,\n        const vector<double>&                 x )\n    {   // This function needed if using RevSparseHes\n# ifndef NDEBUG\n        size_t m = s.size();\n# endif\n        size_t n = t.size();\n        assert( x.size() == n );\n        assert( r.size() == n * p );\n        assert( u.size() == m * p );\n        assert( v.size() == n * p );\n        assert( n == 2 );\n        assert( m == 1 );\n\n        // There are no cross term second derivatives for this case,\n        // so it is not necessary to use vx.\n\n        // sparsity for T(x) = S(x) * f'(x)\n        t[0] = s[0];\n        t[1] = s[0];\n\n        // V(x) = f'(x)^T * g''(y) * f'(x) * R  +  g'(y) * f''(x) * R\n        // U(x) = g''(y) * f'(x) * R\n        // S(x) = g'(y)\n\n        // back propagate the sparsity for U\n        size_t j;\n        for(j = 0; j < p; j++)\n            for(size_t i = 0; i < n; i++)\n                v[ i * p + j] = u[j];\n\n        // include forward Jacobian sparsity in Hessian sparsity\n        // sparsity for g'(y) * f''(x) * R  (Note f''(x) has same sparsity\n        // as the identity matrix)\n        if( s[0] )\n        {   for(j = 0; j < p; j++)\n                for(size_t i = 0; i < n; i++)\n                {   // Visual Studio 2013 generates warning without bool below\n                    v[ i * p + j] |= bool( r[ i * p + j] );\n                }\n        }\n\n        return true;\n    }\n/* %$$\n$head End Class Definition$$\n$srccode%cpp% */\n}; // End of atomic_norm_sq class\n}  // End empty namespace\n\n/* %$$\n$head Use Atomic Function$$\n$srccode%cpp% */\nbool norm_sq(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps = 10. * CppAD::numeric_limits<double>::epsilon();\n/* %$$\n$subhead Constructor$$\n$srccode%cpp% */\n    // --------------------------------------------------------------------\n    // Create the atomic reciprocal object\n    atomic_norm_sq afun(\"atomic_norm_sq\");\n/* %$$\n$subhead Recording$$\n$srccode%cpp% */\n    // Create the function f(x)\n    //\n    // domain space vector\n    size_t  n  = 2;\n    double  x0 = 0.25;\n    double  x1 = 0.75;\n    vector< AD<double> > ax(n);\n    ax[0]      = x0;\n    ax[1]      = x1;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(ax);\n\n    // range space vector\n    size_t m = 1;\n    vector< AD<double> > ay(m);\n\n    // call atomic function and store norm_sq(x) in au[0]\n    afun(ax, ay);        // y_0 = x_0 * x_0 + x_1 * x_1\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f;\n    f.Dependent (ax, ay);\n/* %$$\n$subhead forward$$\n$srccode%cpp% */\n    // check function value\n    double check = x0 * x0 + x1 * x1;\n    ok &= NearEqual( Value(ay[0]) , check,  eps, eps);\n\n    // check zero order forward mode\n    size_t q;\n    vector<double> x_q(n), y_q(m);\n    q      = 0;\n    x_q[0] = x0;\n    x_q[1] = x1;\n    y_q    = f.Forward(q, x_q);\n    ok &= NearEqual(y_q[0] , check,  eps, eps);\n\n    // check first order forward mode\n    q      = 1;\n    x_q[0] = 0.3;\n    x_q[1] = 0.7;\n    y_q    = f.Forward(q, x_q);\n    check  = 2.0 * x0 * x_q[0] + 2.0 * x1 * x_q[1];\n    ok &= NearEqual(y_q[0] , check,  eps, eps);\n\n/* %$$\n$subhead reverse$$\n$srccode%cpp% */\n    // first order reverse mode\n    q     = 1;\n    vector<double> w(m), dw(n * q);\n    w[0]  = 1.;\n    dw    = f.Reverse(q, w);\n    check = 2.0 * x0;\n    ok &= NearEqual(dw[0] , check,  eps, eps);\n    check = 2.0 * x1;\n    ok &= NearEqual(dw[1] , check,  eps, eps);\n/* %$$\n$subhead for_sparse_jac$$\n$srccode%cpp% */\n    // forward mode sparstiy pattern\n    size_t p = n;\n    CppAD::vectorBool r1(n * p), s1(m * p);\n    r1[0] = true;  r1[1] = false; // sparsity pattern identity\n    r1[2] = false; r1[3] = true;\n    //\n    s1    = f.ForSparseJac(p, r1);\n    ok  &= s1[0] == true;  // f[0] depends on x[0]\n    ok  &= s1[1] == true;  // f[0] depends on x[1]\n/* %$$\n$subhead rev_sparse_jac$$\n$srccode%cpp% */\n    // reverse mode sparstiy pattern\n    q = m;\n    CppAD::vectorBool s2(q * m), r2(q * n);\n    s2[0] = true;          // compute sparsity pattern for f[0]\n    //\n    r2    = f.RevSparseJac(q, s2);\n    ok  &= r2[0] == true;  // f[0] depends on x[0]\n    ok  &= r2[1] == true;  // f[0] depends on x[1]\n/* %$$\n$subhead rev_sparse_hes$$\n$srccode%cpp% */\n    // Hessian sparsity (using previous ForSparseJac call)\n    CppAD::vectorBool s3(m), h(p * n);\n    s3[0] = true;        // compute sparsity pattern for f[0]\n    //\n    h     = f.RevSparseHes(p, s3);\n    ok  &= h[0] == true;  // partial of f[0] w.r.t. x[0],x[0] is non-zero\n    ok  &= h[1] == false; // partial of f[0] w.r.t. x[0],x[1] is zero\n    ok  &= h[2] == false; // partial of f[0] w.r.t. x[1],x[0] is zero\n    ok  &= h[3] == true;  // partial of f[0] w.r.t. x[1],x[1] is non-zero\n    //\n    return ok;\n}\n/* %$$\n$end\n*/\n"
  },
  {
    "path": "test_more/deprecated/atomic_two/reciprocal.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n@begin atomic_two_reciprocal.cpp@@\n$spell\n    enum\n$$\n\n$section Reciprocal as an Atomic Operation: Example and Test$$\n\n$head Theory$$\nThis example demonstrates using $cref atomic_two$$\nto define the operation\n$latex f : \\B{R}^n \\rightarrow \\B{R}^m$$ where\n$latex n = 1$$, $latex m = 1$$, and $latex f(x) = 1 / x$$.\n\n$head sparsity$$\nThis example only uses set sparsity patterns.\n\n$head Start Class Definition$$\n$srccode%cpp% */\n# include <cppad/cppad.hpp>\nnamespace {           // isolate items below to this file\nusing CppAD::vector;  // abbreviate as vector\n//\n// a utility to compute the union of two sets.\nusing CppAD::set_union;\n//\nclass atomic_reciprocal : public CppAD::atomic_base<double> {\n/* %$$\n$head Constructor $$\n$srccode%cpp% */\npublic:\n    // constructor (could use const char* for name)\n    atomic_reciprocal(const std::string& name) :\n    // this example only uses set sparsity patterns\n    CppAD::atomic_base<double>(name, atomic_base<double>::set_sparsity_enum)\n    { }\nprivate:\n/* %$$\n$head forward$$\n$srccode%cpp% */\n    // forward mode routine called by CppAD\n    virtual bool forward(\n        size_t                    p ,\n        size_t                    q ,\n        const vector<bool>&      vx ,\n                  vector<bool>&      vy ,\n        const vector<double>&    tx ,\n                  vector<double>&    ty\n    )\n    {\n# ifndef NDEBUG\n        size_t n = tx.size() / (q + 1);\n        size_t m = ty.size() / (q + 1);\n# endif\n        assert( n == 1 );\n        assert( m == 1 );\n        assert( p <= q );\n\n        // return flag\n        bool ok = q <= 2;\n\n        // check for defining variable information\n        // This case must always be implemented\n        if( vx.size() > 0 )\n            vy[0] = vx[0];\n\n        // Order zero forward mode.\n        // This case must always be implemented\n        // y^0 = f( x^0 ) = 1 / x^0\n        double f = 1. / tx[0];\n        if( p <= 0 )\n            ty[0] = f;\n        if( q <= 0 )\n            return ok;\n        assert( vx.size() == 0 );\n\n        // Order one forward mode.\n        // This case needed if first order forward mode is used.\n        // y^1 = f'( x^0 ) x^1\n        double fp = - f / tx[0];\n        if( p <= 1 )\n            ty[1] = fp * tx[1];\n        if( q <= 1 )\n            return ok;\n\n        // Order two forward mode.\n        // This case needed if second order forward mode is used.\n        // Y''(t) = X'(t)^\\R{T} f''[X(t)] X'(t) + f'[X(t)] X''(t)\n        // 2 y^2  = x^1 * f''( x^0 ) x^1 + 2 f'( x^0 ) x^2\n        double fpp  = - 2.0 * fp / tx[0];\n        ty[2] = tx[1] * fpp * tx[1] / 2.0 + fp * tx[2];\n        if( q <= 2 )\n            return ok;\n\n        // Assume we are not using forward mode with order > 2\n        assert( ! ok );\n        return ok;\n    }\n/* %$$\n$head reverse$$\n$srccode%cpp% */\n    // reverse mode routine called by CppAD\n    virtual bool reverse(\n        size_t                    q ,\n        const vector<double>&    tx ,\n        const vector<double>&    ty ,\n                  vector<double>&    px ,\n        const vector<double>&    py\n    )\n    {\n# ifndef NDEBUG\n        size_t n = tx.size() / (q + 1);\n        size_t m = ty.size() / (q + 1);\n# endif\n        assert( px.size() == n * (q + 1) );\n        assert( py.size() == m * (q + 1) );\n        assert( n == 1 );\n        assert( m == 1 );\n        bool ok = q <= 2;\n\n        double f, fp, fpp, fppp;\n        switch(q)\n        {   case 0:\n            // This case needed if first order reverse mode is used\n            // reverse: F^0 ( tx ) = y^0 = f( x^0 )\n            f     = ty[0];\n            fp    = - f / tx[0];\n            px[0] = py[0] * fp;;\n            assert(ok);\n            break;\n\n            case 1:\n            // This case needed if second order reverse mode is used\n            // reverse: F^1 ( tx ) = y^1 = f'( x^0 ) x^1\n            f      = ty[0];\n            fp     = - f / tx[0];\n            fpp    = - 2.0 * fp / tx[0];\n            px[1]  = py[1] * fp;\n            px[0]  = py[1] * fpp * tx[1];\n            // reverse: F^0 ( tx ) = y^0 = f( x^0 );\n            px[0] += py[0] * fp;\n            assert(ok);\n            break;\n\n            case 2:\n            // This needed if third order reverse mode is used\n            // reverse: F^2 ( tx ) = y^2 =\n            //          = x^1 * f''( x^0 ) x^1 / 2 + f'( x^0 ) x^2\n            f      = ty[0];\n            fp     = - f / tx[0];\n            fpp    = - 2.0 * fp / tx[0];\n            fppp   = - 3.0 * fpp / tx[0];\n            px[2]  = py[2] * fp;\n            px[1]  = py[2] * fpp * tx[1];\n            px[0]  = py[2] * tx[1] * fppp * tx[1] / 2.0 + fpp * tx[2];\n            // reverse: F^1 ( tx ) = y^1 = f'( x^0 ) x^1\n            px[1] += py[1] * fp;\n            px[0] += py[1] * fpp * tx[1];\n            // reverse: F^0 ( tx ) = y^0 = f( x^0 );\n            px[0] += py[0] * fp;\n            assert(ok);\n            break;\n\n            default:\n            assert(!ok);\n        }\n        return ok;\n    }\n/* %$$\n$head for_sparse_jac$$\n$srccode%cpp% */\n    // forward Jacobian set sparsity routine called by CppAD\n    virtual bool for_sparse_jac(\n        size_t                                p ,\n        const vector< std::set<size_t> >&     r ,\n                  vector< std::set<size_t> >&     s ,\n        const vector<double>&                 x )\n    {   // This function needed if using f.ForSparseJac\n# ifndef NDEBUG\n        size_t n = r.size();\n        size_t m = s.size();\n# endif\n        assert( n == x.size() );\n        assert( n == 1 );\n        assert( m == 1 );\n\n        // sparsity for S(x) = f'(x) * R is same as sparsity for R\n        s[0] = r[0];\n\n        return true;\n    }\n/* %$$\n$head rev_sparse_jac$$\n$srccode%cpp% */\n    // reverse Jacobian set sparsity routine called by CppAD\n    virtual bool rev_sparse_jac(\n        size_t                                p  ,\n        const vector< std::set<size_t> >&     rt ,\n                  vector< std::set<size_t> >&     st ,\n        const vector<double>&                 x  )\n    {   // This function needed if using RevSparseJac or optimize\n# ifndef NDEBUG\n        size_t n = st.size();\n        size_t m = rt.size();\n# endif\n        assert( n == x.size() );\n        assert( n == 1 );\n        assert( m == 1 );\n\n        // sparsity for S(x)^T = f'(x)^T * R^T is same as sparsity for R^T\n        st[0] = rt[0];\n\n        return true;\n    }\n/* %$$\n$head rev_sparse_hes$$\n$srccode%cpp% */\n    // reverse Hessian set sparsity routine called by CppAD\n    virtual bool rev_sparse_hes(\n        const vector<bool>&                   vx,\n        const vector<bool>&                   s ,\n                  vector<bool>&                   t ,\n        size_t                                p ,\n        const vector< std::set<size_t> >&     r ,\n        const vector< std::set<size_t> >&     u ,\n                  vector< std::set<size_t> >&     v ,\n        const vector<double>&                 x )\n    {   // This function needed if using RevSparseHes\n# ifndef NDEBUG\n        size_t n = vx.size();\n        size_t m = s.size();\n# endif\n        assert( x.size() == n );\n        assert( t.size() == n );\n        assert( r.size() == n );\n        assert( u.size() == m );\n        assert( v.size() == n );\n        assert( n == 1 );\n        assert( m == 1 );\n\n        // There are no cross term second derivatives for this case,\n        // so it is not necessary to vx.\n\n        // sparsity for T(x) = S(x) * f'(x) is same as sparsity for S\n        t[0] = s[0];\n\n        // V(x) = f'(x)^T * g''(y) * f'(x) * R  +  g'(y) * f''(x) * R\n        // U(x) = g''(y) * f'(x) * R\n        // S(x) = g'(y)\n\n        // back propagate the sparsity for U, note f'(x) may be non-zero;\n        v[0] = u[0];\n\n        // include forward Jacobian sparsity in Hessian sparsity\n        // (note sparsty for f''(x) * R same as for R)\n        if( s[0] )\n            v[0] = set_union(v[0], r[0] );\n\n        return true;\n    }\n/* %$$\n$head End Class Definition$$\n$srccode%cpp% */\n}; // End of atomic_reciprocal class\n}  // End empty namespace\n\n/* %$$\n$head Use Atomic Function$$\n$srccode%cpp% */\nbool reciprocal(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps = 10. * CppAD::numeric_limits<double>::epsilon();\n/* %$$\n$subhead Constructor$$\n$srccode%cpp% */\n    // --------------------------------------------------------------------\n    // Create the atomic reciprocal object\n    atomic_reciprocal afun(\"atomic_reciprocal\");\n/* %$$\n$subhead Recording$$\n$srccode%cpp% */\n    // Create the function f(x)\n    //\n    // domain space vector\n    size_t n  = 1;\n    double  x0 = 0.5;\n    vector< AD<double> > ax(n);\n    ax[0]     = x0;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(ax);\n\n    // range space vector\n    size_t m = 1;\n    vector< AD<double> > ay(m);\n\n    // call atomic function and store reciprocal(x) in au[0]\n    vector< AD<double> > au(m);\n    afun(ax, au);        // u = 1 / x\n\n    // now use AD division to invert to invert the operation\n    ay[0] = 1.0 / au[0]; // y = 1 / u = x\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f;\n    f.Dependent (ax, ay);  // f(x) = x\n/* %$$\n$subhead forward$$\n$srccode%cpp% */\n    // check function value\n    double check = x0;\n    ok &= NearEqual( Value(ay[0]) , check,  eps, eps);\n\n    // check zero order forward mode\n    size_t q;\n    vector<double> x_q(n), y_q(m);\n    q      = 0;\n    x_q[0] = x0;\n    y_q    = f.Forward(q, x_q);\n    ok &= NearEqual(y_q[0] , check,  eps, eps);\n\n    // check first order forward mode\n    q      = 1;\n    x_q[0] = 1;\n    y_q    = f.Forward(q, x_q);\n    check  = 1.;\n    ok &= NearEqual(y_q[0] , check,  eps, eps);\n\n    // check second order forward mode\n    q      = 2;\n    x_q[0] = 0;\n    y_q    = f.Forward(q, x_q);\n    check  = 0.;\n    ok &= NearEqual(y_q[0] , check,  eps, eps);\n/* %$$\n$subhead reverse$$\n$srccode%cpp% */\n    // third order reverse mode\n    q     = 3;\n    vector<double> w(m), dw(n * q);\n    w[0]  = 1.;\n    dw    = f.Reverse(q, w);\n    check = 1.;\n    ok &= NearEqual(dw[0] , check,  eps, eps);\n    check = 0.;\n    ok &= NearEqual(dw[1] , check,  eps, eps);\n    ok &= NearEqual(dw[2] , check,  eps, eps);\n/* %$$\n$subhead for_sparse_jac$$\n$srccode%cpp% */\n    // forward mode sparstiy pattern\n    size_t p = n;\n    CppAD::vectorBool r1(n * p), s1(m * p);\n    r1[0] = true;          // compute sparsity pattern for x[0]\n    //\n    s1    = f.ForSparseJac(p, r1);\n    ok  &= s1[0] == true;  // f[0] depends on x[0]\n/* %$$\n$subhead rev_sparse_jac$$\n$srccode%cpp% */\n    // reverse mode sparstiy pattern\n    q = m;\n    CppAD::vectorBool s2(q * m), r2(q * n);\n    s2[0] = true;          // compute sparsity pattern for f[0]\n    //\n    r2    = f.RevSparseJac(q, s2);\n    ok  &= r2[0] == true;  // f[0] depends on x[0]\n/* %$$\n$subhead rev_sparse_hes$$\n$srccode%cpp% */\n    // Hessian sparsity (using previous ForSparseJac call)\n    CppAD::vectorBool s3(m), h(p * n);\n    s3[0] = true;        // compute sparsity pattern for f[0]\n    //\n    h     = f.RevSparseHes(p, s3);\n    ok  &= h[0] == true; // second partial of f[0] w.r.t. x[0] may be non-zero\n    //\n    return ok;\n}\n/* %$$\n$end\n*/\n"
  },
  {
    "path": "test_more/deprecated/atomic_two/rev_sparse_hes.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n@begin atomic_two_rev_sparse_hes.cpp@@\n\n$section Atomic Reverse Hessian Sparsity: Example and Test$$\n\n$head Purpose$$\nThis example demonstrates calculation of the reverse Hessian sparsity pattern\nfor an atomic operation.\n\n$head function$$\nFor this example, the atomic function\n$latex f : \\B{R}^3 \\rightarrow \\B{R}^2$$ is defined by\n$latex \\[\nf( x ) = \\left( \\begin{array}{c}\n    x_2 * x_2 \\\\\n    x_0 * x_1\n\\end{array} \\right)\n\\] $$\nThe Hessians of the component functions are\n$latex \\[\nf_0^{(2)} ( x ) = \\left( \\begin{array}{ccc}\n    0 & 0 & 0  \\\\\n    0 & 0 & 0  \\\\\n    0 & 0 & 2\n\\end{array} \\right)\n\\W{,}\nf_1^{(2)} ( x ) = \\left( \\begin{array}{ccc}\n    0 & 1 & 0 \\\\\n    1 & 0 & 0 \\\\\n    0 & 0 & 0\n\\end{array} \\right)\n\\] $$\n\n$head Start  Class Definition$$\n$srccode%cpp% */\n# include <cppad/cppad.hpp>\nnamespace {          // isolate items below to this file\nusing CppAD::vector; // abbreviate as vector\n//\nclass atomic_rev_sparse_hes : public CppAD::atomic_base<double> {\n/* %$$\n$head Constructor $$\n$srccode%cpp% */\npublic:\n    // constructor (could use const char* for name)\n    atomic_rev_sparse_hes(const std::string& name) :\n    // this example only uses pack sparsity patterns\n    CppAD::atomic_base<double>(name, pack_sparsity_enum)\n    { }\nprivate:\n/* %$$\n$head forward$$\n$srccode%cpp% */\n    // forward mode routine called by CppAD\n    virtual bool forward(\n        size_t                    p ,\n        size_t                    q ,\n        const vector<bool>&      vx ,\n        vector<bool>&            vy ,\n        const vector<double>&    tx ,\n        vector<double>&          ty\n    )\n    {\n# ifndef NDEBUG\n        size_t n = tx.size() / (q + 1);\n        size_t m = ty.size() / (q + 1);\n# endif\n        assert( n == 3 );\n        assert( m == 2 );\n\n        // return flag\n        bool ok = q == 0;\n        if( ! ok )\n            return ok;\n\n        // check for defining variable information\n        // This case must always be implemented\n        if( vx.size() > 0 )\n        {   vy[0] = vx[0];\n            vy[1] = vx[0] || vy[0];\n        }\n\n        // Order zero forward mode.\n        // This case must always be implemented\n        // f(x) = [ x_0 * x_0 ]\n        //        [ x_0 * x_1 ]\n        assert( p <= 0 );\n        if( p <= 0 )\n        {   ty[0] = tx[2] * tx[2];\n            ty[1] = tx[0] * tx[1];\n        }\n        return ok;\n    }\n/* %$$\n$head for_sparse_jac$$\n$srccode%cpp% */\n    // forward Jacobian sparsity routine called by CppAD\n    virtual bool for_sparse_jac(\n        size_t                     q ,\n        const CppAD::vectorBool&   r ,\n        CppAD::vectorBool&         s ,\n        const vector<double>&      x )\n    {   // This function needed because we are using ForSparseHes\n        // with afun.option( CppAD::atomic_base<double>::pack_sparsity_enum )\n# ifndef NDEBUG\n        size_t n = r.size() / q;\n        size_t m = s.size() / q;\n# endif\n        assert( n == x.size() );\n        assert( n == 3 );\n        assert( m == 2 );\n\n\n        // f'(x) = [   0,   0, 2 x_2 ]\n        //         [ x_1, x_0,     0 ]\n\n        // sparsity for first row of S(x) = f'(x) * R\n        size_t i = 0;\n        for(size_t j = 0; j < q; j++)\n            s[ i * q + j ] = r[ 2 * q + j ];\n\n        // sparsity for second row of S(x) = f'(x) * R\n        i = 1;\n        for(size_t j = 0; j < q; j++)\n            s[ i * q + j ] = r[ 0 * q + j ] || r[ 1 * q + j];\n\n        return true;\n    }\n/* %$$\n$head rev_sparse_jac$$\n$srccode%cpp% */\n    // reverse Jacobian sparsity routine called by CppAD\n    virtual bool rev_sparse_jac(\n        size_t                     q  ,\n        const CppAD::vectorBool&   rt ,\n        CppAD::vectorBool&         st ,\n        const vector<double>&      x  )\n    {   // This function needed because we are using ForSparseHes\n        // with afun.option( CppAD::atomic_base<double>::pack_sparsity_enum )\n# ifndef NDEBUG\n        size_t m = rt.size() / q;\n        size_t n = st.size() / q;\n# endif\n        assert( n == x.size() );\n        assert( n == 3 );\n        assert( m == 2 );\n\n        //           [     0,  x_1 ]\n        // f'(x)^T = [     0,  x_0 ]\n        //           [ 2 x_2,    0 ]\n\n        // sparsity for first row of S(x)^T = f'(x)^T * R^T\n        size_t i = 0;\n        for(size_t j = 0; j < q; j++)\n            st[ i * q + j ] = rt[ 1 * q + j ];\n\n        // sparsity for second row of S(x)^T = f'(x)^T * R^T\n        i = 1;\n        for(size_t j = 0; j < q; j++)\n            st[ i * q + j ] = rt[ 1 * q + j ];\n\n        // sparsity for third row of S(x)^T = f'(x)^T * R^T\n        i = 2;\n        for(size_t j = 0; j < q; j++)\n            st[ i * q + j ] = rt[ 0 * q + j ];\n\n        return true;\n    }\n/* %$$\n$head rev_sparse_hes$$\n$srccode%cpp% */\n    // reverse Hessian sparsity routine called by CppAD\n    virtual bool rev_sparse_hes(\n        const vector<bool>&                   vx,\n        const vector<bool>&                   s ,\n        vector<bool>&                         t ,\n        size_t                                q ,\n        const CppAD::vectorBool&              r ,\n        const CppAD::vectorBool&              u ,\n        CppAD::vectorBool&                    v ,\n        const vector<double>&                 x )\n    {   // This function needed because we are using RevSparseHes\n        // with afun.option( CppAD::atomic_base<double>::pack_sparsity_enum )\n# ifndef NDEBUG\n        size_t m = s.size();\n        size_t n = t.size();\n# endif\n        assert( x.size() == n );\n        assert( r.size() == n * q );\n        assert( u.size() == m * q );\n        assert( v.size() == n * q );\n        assert( n == 3 );\n        assert( m == 2 );\n        //\n        // f'(x) = [   0,   0, 2 x_2 ]\n        //         [ x_1, x_0,     0 ]\n        //\n        //            [ 0 , 0 , 0 ]                  [ 0 , 1 , 0 ]\n        // f_0''(x) = [ 0 , 0 , 0 ]  f_1^{(2)} (x) = [ 1 , 0 , 0 ]\n        //            [ 0 , 0 , 2 ]                  [ 0 , 0 , 0 ]\n        // ------------------------------------------------------------------\n        // sparsity pattern for row vector T(x) = S(x) * f'(x)\n        t[0] = s[1];\n        t[1] = s[1];\n        t[2] = s[0];\n        // ------------------------------------------------------------------\n        // sparsity pattern for W(x) = f'(x)^T * U(x)\n        for(size_t j = 0; j < q; j++)\n        {   v[ 0 * q + j ] = u[ 1 * q + j ];\n            v[ 1 * q + j ] = u[ 1 * q + j ];\n            v[ 2 * q + j ] = u[ 0 * q + j ];\n        }\n        // ------------------------------------------------------------------\n        // sparsity pattern for Q(x) = W(x) + S_0 (x) * f_0^{(2)} (x) * R\n        if( s[0] )\n        {   for(size_t j = 0; j < q; j++)\n            {   // cannot use |= with vectorBool\n                v[ 2 * q + j ] = bool(v[ 2 * q + j ]) || bool(r[ 2 * q + j ]);\n            }\n        }\n        // ------------------------------------------------------------------\n        // sparsity pattern for V(x) = Q(x) + S_1 (x) * f_1^{(2)} (x) * R\n        if( s[1] )\n        {   for(size_t j = 0; j < q; j++)\n            {   // cannot use |= with vectorBool\n                v[ 0 * q + j ] = bool(v[ 0 * q + j ]) || bool(r[ 1 * q + j ]);\n                v[ 1 * q + j ] = bool(v[ 1 * q + j ]) || bool(r[ 0 * q + j ]);\n            }\n        }\n        return true;\n    }\n}; // End of atomic_rev_sparse_hes class\n\n/* %$$\n$head Use Atomic Function$$\n$srccode%cpp% */\nbool use_atomic_rev_sparse_hes(bool x_1_variable)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps = 10. * CppAD::numeric_limits<double>::epsilon();\n    //\n    // Create the atomic rev_sparse_hes object\n    atomic_rev_sparse_hes afun(\"atomic_rev_sparse_hes\");\n    //\n    // Create the function f(u)\n    //\n    // domain space vector\n    size_t n  = 3;\n    double x_0 = 1.00;\n    double x_1 = 2.00;\n    double x_2 = 3.00;\n    vector< AD<double> > au(n);\n    au[0] = x_0;\n    au[1] = x_1;\n    au[2] = x_2;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(au);\n\n    // range space vector\n    size_t m = 2;\n    vector< AD<double> > ay(m);\n\n    // call atomic function\n    vector< AD<double> > ax(n);\n    ax[0] = au[0];\n    ax[2] = au[2];\n    if( x_1_variable )\n        ax[1] = au[1];\n    else\n        ax[1] = x_1;\n    afun(ax, ay);          // y = [ x_2 * x_2 ,  x_0 * x_1 ]^T\n\n    // create f: u -> y and stop tape recording\n    CppAD::ADFun<double> f;\n    f.Dependent (au, ay);  // f(u) = y\n    //\n    // check function value\n    double check = x_2 * x_2;\n    ok &= NearEqual( Value(ay[0]) , check,  eps, eps);\n    check = x_0 * x_1;\n    ok &= NearEqual( Value(ay[1]) , check,  eps, eps);\n\n    // check zero order forward mode\n    size_t q;\n    vector<double> xq(n), yq(m);\n    q     = 0;\n    xq[0] = x_0;\n    xq[1] = x_1;\n    xq[2] = x_2;\n    yq    = f.Forward(q, xq);\n    check = x_2 * x_2;\n    ok &= NearEqual(yq[0] , check,  eps, eps);\n    check = x_0 * x_1;\n    ok &= NearEqual(yq[1] , check,  eps, eps);\n\n    // reverse sparse Hessian\n    CppAD::vectorBool r(n * n), s(m), h(n * n);\n    for(size_t i = 0; i < n; i++)\n    {   for(size_t j = 0; j < n; j++)\n            r[i * n + j] = i == j;\n    }\n    for(size_t i = 0; i < m; i++)\n        s[i] = true;\n    f.ForSparseJac(n, r);\n    h = f.RevSparseHes(n, s);\n\n    // check result\n    CppAD::vectorBool check_h(n * n);\n    for(size_t i = 0; i < n * n; i++)\n        check_h[i] = false;\n    check_h[ 2 * n + 2 ] = true;\n    if( x_1_variable )\n    {   check_h[0 * n + 1] = true;\n        check_h[1 * n + 0] = true;\n    }\n    for(size_t i = 0; i < n * n; i++)\n        ok &= h[ i ] == check_h[ i ];\n    //\n    return ok;\n}\n}  // End empty namespace\n/* %$$\n$head Test with x_1 Both a Variable and a Parameter$$\n$srccode%cpp% */\nbool rev_sparse_hes(void)\n{   bool ok = true;\n    // test with x_1 a variable\n    ok     &= use_atomic_rev_sparse_hes(true);\n    // test with x_1 a parameter\n    ok     &= use_atomic_rev_sparse_hes(false);\n    return ok;\n}\n/* %$$\n$end\n*/\n"
  },
  {
    "path": "test_more/deprecated/atomic_two/rev_sparse_jac.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n@begin atomic_two_rev_sparse_jac.cpp@@\n$spell\n    Jacobian\n    Jacobians\n$$\n\n$section Atomic Reverse Jacobian Sparsity: Example and Test$$\n\n$head Purpose$$\nThis example demonstrates calculation of the\nreverse Jacobians sparsity pattern for an atomic operation.\n\n$head function$$\nFor this example, the atomic function\n$latex f : \\B{R}^3 \\rightarrow \\B{R}^2$$ is defined by\n$latex \\[\nf( x ) = \\left( \\begin{array}{c}\n    x_2 * x_2 \\\\\n    x_0 * x_1\n\\end{array} \\right)\n\\] $$\nThe corresponding Jacobian is\n$latex \\[\nf^{(1)} (x) = \\left( \\begin{array}{ccc}\n  0  &   0 & 2 x_2 \\\\\nx_1  & x_0 & 0\n\\end{array} \\right)\n\\] $$\n\n$head Start  Class Definition$$\n$srccode%cpp% */\n# include <cppad/cppad.hpp>\nnamespace {          // isolate items below to this file\nusing CppAD::vector; // abbreviate as vector\n//\nclass atomic_rev_sparse_jac : public CppAD::atomic_base<double> {\n/* %$$\n$head Constructor $$\n$srccode%cpp% */\npublic:\n    // constructor (could use const char* for name)\n    atomic_rev_sparse_jac(const std::string& name) :\n    // this example only uses pack sparsity patterns\n    CppAD::atomic_base<double>(name, pack_sparsity_enum)\n    { }\nprivate:\n/* %$$\n$head forward$$\n$srccode%cpp% */\n    // forward mode routine called by CppAD\n    virtual bool forward(\n        size_t                    p ,\n        size_t                    q ,\n        const vector<bool>&      vx ,\n        vector<bool>&            vy ,\n        const vector<double>&    tx ,\n        vector<double>&          ty\n    )\n    {\n# ifndef NDEBUG\n        size_t n = tx.size() / (q + 1);\n        size_t m = ty.size() / (q + 1);\n# endif\n        assert( n == 3 );\n        assert( m == 2 );\n\n        // return flag\n        bool ok = q == 0;\n        if( ! ok )\n            return ok;\n\n        // check for defining variable information\n        // This case must always be implemented\n        if( vx.size() > 0 )\n        {   vy[0] = vx[0];\n            vy[1] = vx[0] || vy[0];\n        }\n\n        // Order zero forward mode.\n        // This case must always be implemented\n        // f(x) = [ x_0 * x_0 ]\n        //        [ x_0 * x_1 ]\n        assert( p <= 0 );\n        if( p <= 0 )\n        {   ty[0] = tx[2] * tx[2];\n            ty[1] = tx[0] * tx[1];\n        }\n        return ok;\n    }\n/* %$$\n$head rev_sparse_jac$$\n$srccode%cpp% */\n    // reverse Jacobian sparsity routine called by CppAD\n    virtual bool rev_sparse_jac(\n        size_t                     q  ,\n        const CppAD::vectorBool&   rt ,\n        CppAD::vectorBool&         st ,\n        const vector<double>&      x  )\n    {   // This function needed because we are using RevSparseHes\n        // with afun.option( CppAD::atomic_base<double>::pack_sparsity_enum )\n# ifndef NDEBUG\n        size_t m = rt.size() / q;\n        size_t n = st.size() / q;\n# endif\n        assert( n == x.size() );\n        assert( n == 3 );\n        assert( m == 2 );\n\n        //           [     0,  x_1 ]\n        // f'(x)^T = [     0,  x_0 ]\n        //           [ 2 x_2,    0 ]\n\n        // sparsity for first row of S(x)^T = f'(x)^T * R^T\n        size_t i = 0;\n        for(size_t j = 0; j < q; j++)\n            st[ i * q + j ] = rt[ 1 * q + j ];\n\n        // sparsity for second row of S(x)^T = f'(x)^T * R^T\n        i = 1;\n        for(size_t j = 0; j < q; j++)\n            st[ i * q + j ] = rt[ 1 * q + j ];\n\n        // sparsity for third row of S(x)^T = f'(x)^T * R^T\n        i = 2;\n        for(size_t j = 0; j < q; j++)\n            st[ i * q + j ] = rt[ 0 * q + j ];\n\n        return true;\n    }\n}; // End of atomic_rev_sparse_jac class\n\n/* %$$\n$head Use Atomic Function$$\n$srccode%cpp% */\nbool use_atomic_rev_sparse_jac(bool x_1_variable)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps = 10. * CppAD::numeric_limits<double>::epsilon();\n    //\n    // Create the atomic rev_sparse_jac object\n    atomic_rev_sparse_jac afun(\"atomic_rev_sparse_jac\");\n    //\n    // Create the function f(u)\n    //\n    // domain space vector\n    size_t n  = 3;\n    double x_0 = 1.00;\n    double x_1 = 2.00;\n    double x_2 = 3.00;\n    vector< AD<double> > au(n);\n    au[0] = x_0;\n    au[1] = x_1;\n    au[2] = x_2;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(au);\n\n    // range space vector\n    size_t m = 2;\n    vector< AD<double> > ay(m);\n\n    // call atomic function\n    vector< AD<double> > ax(n);\n    ax[0] = au[0];\n    ax[2] = au[2];\n    if( x_1_variable )\n        ax[1] = au[1];\n    else\n        ax[1] = x_1;\n    afun(ax, ay);          // y = [ x_2 * x_2 ,  x_0 * x_1 ]^T\n\n    // create f: u -> y and stop tape recording\n    CppAD::ADFun<double> f;\n    f.Dependent (au, ay);  // f(u) = y\n    //\n    // check function value\n    double check = x_2 * x_2;\n    ok &= NearEqual( Value(ay[0]) , check,  eps, eps);\n    check = x_0 * x_1;\n    ok &= NearEqual( Value(ay[1]) , check,  eps, eps);\n\n    // check zero order forward mode\n    size_t q;\n    vector<double> xq(n), yq(m);\n    q     = 0;\n    xq[0] = x_0;\n    xq[1] = x_1;\n    xq[2] = x_2;\n    yq    = f.Forward(q, xq);\n    check = x_2 * x_2;\n    ok &= NearEqual(yq[0] , check,  eps, eps);\n    check = x_0 * x_1;\n    ok &= NearEqual(yq[1] , check,  eps, eps);\n\n    // forward sparse Jacobian\n    CppAD::vectorBool r(m * m), s(m * n);\n    // r = identity matrix\n    for(size_t i = 0; i < m; i++)\n        for(size_t j = 0; j < m; j++)\n            r[ i * m + j] = i == j;\n    s = f.RevSparseJac(m, r);\n\n    // check result\n    CppAD::vectorBool check_s(m * n);\n    check_s[ 0 * n + 0 ] = false;\n    check_s[ 0 * n + 1 ] = false;\n    check_s[ 0 * n + 2 ] = true;\n    check_s[ 1 * n + 0 ] = true;\n    check_s[ 1 * n + 1 ] = x_1_variable;\n    check_s[ 1 * n + 2 ] = false;\n    //\n    for(size_t i = 0; i < m * n; i++)\n        ok &= s[ i ] == check_s[ i ];\n    //\n    return ok;\n}\n}  // End empty namespace\n/* %$$\n$head Test with x_1 Both a Variable and a Parameter$$\n$srccode%cpp% */\nbool rev_sparse_jac(void)\n{   bool ok = true;\n    // test with x_1 a variable\n    ok     &= use_atomic_rev_sparse_jac(true);\n    // test with x_1 a parameter\n    ok     &= use_atomic_rev_sparse_jac(false);\n    return ok;\n}\n/* %$$\n$end\n*/\n"
  },
  {
    "path": "test_more/deprecated/atomic_two/reverse.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n@begin atomic_two_reverse.cpp@@\n$spell\n    Jacobian\n$$\n\n$section Atomic Reverse: Example and Test$$\n\n$head Purpose$$\nThis example demonstrates reverse mode derivative calculation\nusing an atomic operation.\n\n$head function$$\nFor this example, the atomic function\n$latex f : \\B{R}^3 \\rightarrow \\B{R}^2$$ is defined by\n$latex \\[\nf(x) = \\left( \\begin{array}{c}\n    x_2 * x_2 \\\\\n    x_0 * x_1\n\\end{array} \\right)\n\\] $$\nThe corresponding Jacobian is\n$latex \\[\nf^{(1)} (x) = \\left( \\begin{array}{ccc}\n  0  &   0 & 2 x_2 \\\\\nx_1  & x_0 & 0\n\\end{array} \\right)\n\\] $$\nThe Hessians of the component functions are\n$latex \\[\nf_0^{(2)} ( x ) = \\left( \\begin{array}{ccc}\n    0 & 0 & 0  \\\\\n    0 & 0 & 0  \\\\\n    0 & 0 & 2\n\\end{array} \\right)\n\\W{,}\nf_1^{(2)} ( x ) = \\left( \\begin{array}{ccc}\n    0 & 1 & 0 \\\\\n    1 & 0 & 0 \\\\\n    0 & 0 & 0\n\\end{array} \\right)\n\\] $$\n\n$head Start  Class Definition$$\n$srccode%cpp% */\n# include <cppad/cppad.hpp>\nnamespace {          // isolate items below to this file\nusing CppAD::vector; // abbreviate as vector\n//\nclass atomic_reverse : public CppAD::atomic_base<double> {\n/* %$$\n$head Constructor $$\n$srccode%cpp% */\npublic:\n    // constructor (could use const char* for name)\n    atomic_reverse(const std::string& name) :\n    // this example does not use sparsity patterns\n    CppAD::atomic_base<double>(name)\n    { }\nprivate:\n/* %$$\n$head forward$$\n$srccode%cpp% */\n    // forward mode routine called by CppAD\n    virtual bool forward(\n        size_t                    p ,\n        size_t                    q ,\n        const vector<bool>&      vx ,\n        vector<bool>&            vy ,\n        const vector<double>&    tx ,\n        vector<double>&          ty\n    )\n    {\n        size_t q1 = q + 1;\n# ifndef NDEBUG\n        size_t n = tx.size() / q1;\n        size_t m = ty.size() / q1;\n# endif\n        assert( n == 3 );\n        assert( m == 2 );\n        assert( p <= q );\n\n        // this example only implements up to first order forward mode\n        bool ok = q <= 1;\n        if( ! ok )\n            return ok;\n\n        // check for defining variable information\n        // This case must always be implemented\n        if( vx.size() > 0 )\n        {   vy[0] = vx[2];\n            vy[1] = vx[0] || vx[1];\n        }\n        // ------------------------------------------------------------------\n        // Zero forward mode.\n        // This case must always be implemented\n        // f(x) = [ x_2 * x_2 ]\n        //        [ x_0 * x_1 ]\n        // y^0  = f( x^0 )\n        if( p <= 0 )\n        {   // y_0^0 = x_2^0 * x_2^0\n            ty[0 * q1 + 0] = tx[2 * q1 + 0] * tx[2 * q1 + 0];\n            // y_1^0 = x_0^0 * x_1^0\n            ty[1 * q1 + 0] = tx[0 * q1 + 0] * tx[1 * q1 + 0];\n        }\n        if( q <= 0 )\n            return ok;\n        // ------------------------------------------------------------------\n        // First order one forward mode.\n        // This case is needed if first order forward mode is used.\n        // f'(x) = [   0,   0, 2 * x_2 ]\n        //         [ x_1, x_0,       0 ]\n        // y^1 =  f'(x^0) * x^1\n        if( p <= 1 )\n        {   // y_0^1 = 2 * x_2^0 * x_2^1\n            ty[0 * q1 + 1] = 2.0 * tx[2 * q1 + 0] * tx[2 * q1 + 1];\n\n            // y_1^1 = x_1^0 * x_0^1 + x_0^0 * x_1^1\n            ty[1 * q1 + 1]  = tx[1 * q1 + 0] * tx[0 * q1 + 1];\n            ty[1 * q1 + 1] += tx[0 * q1 + 0] * tx[1 * q1 + 1];\n        }\n        return ok;\n    }\n/* %$$\n$head reverse$$\n$srccode%cpp% */\n    // reverse mode routine called by CppAD\n    virtual bool reverse(\n        size_t                   q ,\n        const vector<double>&    tx ,\n        const vector<double>&    ty ,\n        vector<double>&          px ,\n        const vector<double>&    py\n    )\n    {\n        size_t q1 = q + 1;\n        size_t n = tx.size() / q1;\n# ifndef NDEBUG\n        size_t m = ty.size() / q1;\n# endif\n        assert( n == 3 );\n        assert( m == 2 );\n\n        // this example only implements up to second order reverse mode\n        bool ok = q1 <= 2;\n        if( ! ok )\n            return ok;\n        //\n        // initialize summation as zero\n        for(size_t j = 0; j < n; j++)\n            for(size_t k = 0; k < q1; k++)\n                px[j * q1 + k] = 0.0;\n        //\n        if( q1 == 2 )\n        {   // --------------------------------------------------------------\n            // Second order reverse first compute partials of first order\n            // We use the notation pf_ij^k for partial of F_i^1 w.r.t. x_j^k\n            //\n            // y_0^1    = 2 * x_2^0 * x_2^1\n            // pf_02^0  = 2 * x_2^1\n            // pf_02^1  = 2 * x_2^0\n            //\n            // y_1^1    = x_1^0 * x_0^1 + x_0^0 * x_1^1\n            // pf_10^0  = x_1^1\n            // pf_11^0  = x_0^1\n            // pf_10^1  = x_1^0\n            // pf_11^1  = x_0^0\n            //\n            // px_0^0 += py_0^1 * pf_00^0 + py_1^1 * pf_10^0\n            //        += py_1^1 * x_1^1\n            px[0 * q1 + 0] += py[1 * q1 + 1] * tx[1 * q1 + 1];\n            //\n            // px_0^1 += py_0^1 * pf_00^1 + py_1^1 * pf_10^1\n            //        += py_1^1 * x_1^0\n            px[0 * q1 + 1] += py[1 * q1 + 1] * tx[1 * q1 + 0];\n            //\n            // px_1^0 += py_0^1 * pf_01^0 + py_1^1 * pf_11^0\n            //        += py_1^1 * x_0^1\n            px[1 * q1 + 0] += py[1 * q1 + 1] * tx[0 * q1 + 1];\n            //\n            // px_1^1 += py_0^1 * pf_01^1 + py_1^1 * pf_11^1\n            //        += py_1^1 * x_0^0\n            px[1 * q1 + 1] += py[1 * q1 + 1] * tx[0 * q1 + 0];\n            //\n            // px_2^0 += py_0^1 * pf_02^0 + py_1^1 * pf_12^0\n            //        += py_0^1 * 2 * x_2^1\n            px[2 * q1 + 0] += py[0 * q1 + 1] * 2.0 * tx[2 * q1 + 1];\n            //\n            // px_2^1 += py_0^1 * pf_02^1 + py_1^1 * pf_12^1\n            //        += py_0^1 * 2 * x_2^0\n            px[2 * q1 + 1] += py[0 * q1 + 1] * 2.0 * tx[2 * q1 + 0];\n        }\n        // --------------------------------------------------------------\n        // First order reverse computes partials of zero order coefficients\n        // We use the notation pf_ij for partial of F_i^0 w.r.t. x_j^0\n        //\n        // y_0^0 = x_2^0 * x_2^0\n        // pf_00 = 0,     pf_01 = 0,  pf_02 = 2 * x_2^0\n        //\n        // y_1^0 = x_0^0 * x_1^0\n        // pf_10 = x_1^0, pf_11 = x_0^0,  pf_12 = 0\n        //\n        // px_0^0 += py_0^0 * pf_00 + py_1^0 * pf_10\n        //        += py_1^0 * x_1^0\n        px[0 * q1 + 0] += py[1 * q1 + 0] * tx[1 * q1 + 0];\n        //\n        // px_1^0 += py_1^0 * pf_01 + py_1^0 * pf_11\n        //        += py_1^0 * x_0^0\n        px[1 * q1 + 0] += py[1 * q1 + 0] * tx[0 * q1 + 0];\n        //\n        // px_2^0 += py_1^0 * pf_02 + py_1^0 * pf_12\n        //        += py_0^0 * 2.0 * x_2^0\n        px[2 * q1 + 0] += py[0 * q1 + 0] * 2.0 * tx[2 * q1 + 0];\n        // --------------------------------------------------------------\n        return ok;\n    }\n};\n}  // End empty namespace\n/* %$$\n$head Use Atomic Function$$\n$srccode%cpp% */\nbool reverse(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps = 10. * CppAD::numeric_limits<double>::epsilon();\n    //\n    // Create the atomic_reverse object\n    atomic_reverse afun(\"atomic_reverse\");\n    //\n    // Create the function f(u)\n    //\n    // domain space vector\n    size_t n  = 3;\n    double x_0 = 1.00;\n    double x_1 = 2.00;\n    double x_2 = 3.00;\n    vector< AD<double> > au(n);\n    au[0] = x_0;\n    au[1] = x_1;\n    au[2] = x_2;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(au);\n\n    // range space vector\n    size_t m = 2;\n    vector< AD<double> > ay(m);\n\n    // call atomic function\n    vector< AD<double> > ax = au;\n    afun(ax, ay);\n\n    // create f: u -> y and stop tape recording\n    CppAD::ADFun<double> f;\n    f.Dependent (au, ay);  // y = f(u)\n    //\n    // check function value\n    double check = x_2 * x_2;\n    ok &= NearEqual( Value(ay[0]) , check,  eps, eps);\n    check = x_0 * x_1;\n    ok &= NearEqual( Value(ay[1]) , check,  eps, eps);\n\n    // --------------------------------------------------------------------\n    // zero order forward\n    //\n    vector<double> x0(n), y0(m);\n    x0[0] = x_0;\n    x0[1] = x_1;\n    x0[2] = x_2;\n    y0   = f.Forward(0, x0);\n    check = x_2 * x_2;\n    ok &= NearEqual(y0[0] , check,  eps, eps);\n    check = x_0 * x_1;\n    ok &= NearEqual(y0[1] , check,  eps, eps);\n    // --------------------------------------------------------------------\n    // first order reverse\n    //\n    // value of Jacobian of f\n    double check_jac[] = {\n        0.0, 0.0, 2.0 * x_2,\n        x_1, x_0,       0.0\n    };\n    vector<double> w(m), dw(n);\n    //\n    // check derivative of f_0 (x)\n    for(size_t i = 0; i < m; i++)\n    {   w[i]   = 1.0;\n        w[1-i] = 0.0;\n        dw = f.Reverse(1, w);\n        for(size_t j = 0; j < n; j++)\n        {   // compute partial in j-th component direction\n            ok &= NearEqual(dw[j], check_jac[i * n + j], eps, eps);\n        }\n    }\n    // --------------------------------------------------------------------\n    // second order reverse\n    //\n    // value of Hessian of f_0\n    double check_hes_0[] = {\n        0.0, 0.0, 0.0,\n        0.0, 0.0, 0.0,\n        0.0, 0.0, 2.0\n    };\n    //\n    // value of Hessian of f_1\n    double check_hes_1[] = {\n        0.0, 1.0, 0.0,\n        1.0, 0.0, 0.0,\n        0.0, 0.0, 0.0\n    };\n    vector<double> x1(n), dw2( 2 * n );\n    for(size_t j = 0; j < n; j++)\n    {   for(size_t j1 = 0; j1 < n; j1++)\n            x1[j1] = 0.0;\n        x1[j] = 1.0;\n        // first order forward\n        f.Forward(1, x1);\n        w[0] = 1.0;\n        w[1] = 0.0;\n        dw2  = f.Reverse(2, w);\n        for(size_t i = 0; i < n; i++)\n            ok &= NearEqual(dw2[i * 2 + 1], check_hes_0[i * n + j], eps, eps);\n        w[0] = 0.0;\n        w[1] = 1.0;\n        dw2  = f.Reverse(2, w);\n        for(size_t i = 0; i < n; i++)\n            ok &= NearEqual(dw2[i * 2 + 1], check_hes_1[i * n + j], eps, eps);\n    }\n    // --------------------------------------------------------------------\n    return ok;\n}\n/* %$$\n$end\n*/\n"
  },
  {
    "path": "test_more/deprecated/atomic_two/set_sparsity.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n@begin atomic_two_set_sparsity.cpp@@\n$spell\n    enum\n$$\n\n$section Atomic Sparsity with Set Patterns: Example and Test$$\n\n$head function$$\nFor this example, the atomic function\n$latex f : \\B{R}^3 \\rightarrow \\B{R}^2$$ is defined by\n$latex \\[\nf( x ) = \\left( \\begin{array}{c}\n    x_2 \\\\\n    x_0 * x_1\n\\end{array} \\right)\n\\] $$\n\n$head set_sparsity_enum$$\nThis example only uses set sparsity patterns.\n\n$head Start Class Definition$$\n$srccode%cpp% */\n# include <cppad/cppad.hpp>\nnamespace {   // isolate items below to this file\nusing   CppAD::vector;                          // vector\ntypedef vector< std::set<size_t> > set_vector;  // atomic_sparsity\n//\n// a utility to compute the union of two sets.\nusing CppAD::set_union;\n//\nclass atomic_set_sparsity : public CppAD::atomic_base<double> {\n/* %$$\n$head Constructor $$\n$srccode%cpp% */\npublic:\n    // constructor\n    atomic_set_sparsity(const std::string& name) :\n    // this example only uses set sparsity patterns\n    CppAD::atomic_base<double>(name, set_sparsity_enum )\n    { }\nprivate:\n/* %$$\n$head forward$$\n$srccode%cpp% */\n    // forward\n    virtual bool forward(\n        size_t                    p ,\n        size_t                    q ,\n        const vector<bool>&      vx ,\n        vector<bool>&            vy ,\n        const vector<double>&    tx ,\n        vector<double>&          ty\n    )\n    {\n        size_t n = tx.size() / (q + 1);\n# ifndef NDEBUG\n        size_t m = ty.size() / (q + 1);\n# endif\n        assert( n == 3 );\n        assert( m == 2 );\n\n        // only order zero\n        bool ok = q == 0;\n        if( ! ok )\n            return ok;\n\n        // check for defining variable information\n        if( vx.size() > 0 )\n        {   ok   &= vx.size() == n;\n            vy[0] = vx[2];\n            vy[1] = vx[0] || vx[1];\n        }\n\n        // Order zero forward mode.\n        // y[0] = x[2], y[1] = x[0] * x[1]\n        if( p <= 0 )\n        {   ty[0] = tx[2];\n            ty[1] = tx[0] * tx[1];\n        }\n        return ok;\n    }\n/* %$$\n$head for_sparse_jac$$\n$srccode%cpp% */\n    // for_sparse_jac\n    virtual bool for_sparse_jac(\n        size_t                          p ,\n        const set_vector&               r ,\n        set_vector&                     s ,\n        const vector<double>&           x )\n    {   // This function needed if using f.ForSparseJac\n# ifndef NDEBUG\n        size_t n = r.size();\n        size_t m = s.size();\n# endif\n        assert( n == x.size() );\n        assert( n == 3 );\n        assert( m == 2 );\n\n        // sparsity for S(x) = f'(x) * R  = [ 0,   0, 1 ] * R\n        s[0] = r[2];\n        // s[1] = union(r[0], r[1])\n        s[1] = set_union(r[0], r[1]);\n        //\n        return true;\n    }\n/* %$$\n$head rev_sparse_jac$$\n$srccode%cpp% */\n    virtual bool rev_sparse_jac(\n        size_t                                p  ,\n        const set_vector&                     rt ,\n        set_vector&                           st ,\n        const vector<double>&                 x  )\n    {   // This function needed if using RevSparseJac or optimize\n# ifndef NDEBUG\n        size_t n = st.size();\n        size_t m = rt.size();\n# endif\n        assert( n == x.size() );\n        assert( n == 3 );\n        assert( m == 2 );\n\n        //                                       [ 0, x1 ]\n        // sparsity for S(x)^T = f'(x)^T * R^T = [ 0, x0 ] * R^T\n        //                                       [ 1, 0  ]\n        st[0] = rt[1];\n        st[1] = rt[1];\n        st[2] = rt[0];\n        return true;\n    }\n/* %$$\n$head for_sparse_hes$$\n$srccode%cpp% */\n    virtual bool for_sparse_hes(\n        const vector<bool>&                   vx,\n        const vector<bool>&                   r ,\n        const vector<bool>&                   s ,\n        set_vector&                           h ,\n        const vector<double>&                 x )\n    {\n        size_t n = r.size();\n# ifndef NDEBUG\n        size_t m = s.size();\n# endif\n        assert( x.size() == n );\n        assert( h.size() == n );\n        assert( n == 3 );\n        assert( m == 2 );\n\n        // initialize h as empty\n        for(size_t i = 0; i < n; i++)\n            h[i].clear();\n\n        // only f_1 has a non-zero hessian\n        if( ! s[1] )\n            return true;\n\n        // only the cross term between x[0] and x[1] is non-zero\n        if( ! ( r[0] && r[1] ) )\n            return true;\n\n        // set the possibly non-zero terms in the hessian\n        h[0].insert(1);\n        h[1].insert(0);\n\n        return true;\n    }\n/* %$$\n$head rev_sparse_hes$$\n$srccode%cpp% */\n    virtual bool rev_sparse_hes(\n        const vector<bool>&                   vx,\n        const vector<bool>&                   s ,\n        vector<bool>&                         t ,\n        size_t                                p ,\n        const set_vector&                     r ,\n        const set_vector&                     u ,\n        set_vector&                           v ,\n        const vector<double>&                 x )\n    {   // This function needed if using RevSparseHes\n# ifndef NDEBUG\n        size_t m = s.size();\n        size_t n = t.size();\n# endif\n        assert( x.size() == n );\n        assert( r.size() == n );\n        assert( u.size() == m );\n        assert( v.size() == n );\n        assert( n == 3 );\n        assert( m == 2 );\n\n        // sparsity for T(x) = S(x) * f'(x) = S(x) * [  0,  0,  1 ]\n        //                                           [ x1, x0,  0 ]\n        t[0] = s[1];\n        t[1] = s[1];\n        t[2] = s[0];\n\n        // V(x) = f'(x)^T * g''(y) * f'(x) * R  +  g'(y) * f''(x) * R\n        // U(x) = g''(y) * f'(x) * R\n        // S(x) = g'(y)\n\n        //                                      [ 0, x1 ]\n        // sparsity for W(x) = f'(x)^T * U(x) = [ 0, x0 ] * U(x)\n        //                                      [ 1, 0  ]\n        v[0] = u[1];\n        v[1] = u[1];\n        v[2] = u[0];\n        //\n        //                                      [ 0, 1, 0 ]\n        // sparsity for V(x) = W(x) + S_1 (x) * [ 1, 0, 0 ] * R\n        //                                      [ 0, 0, 0 ]\n        if( s[1] )\n        {   // v[0] = union( v[0], r[1] )\n            v[0] = set_union(v[0], r[1]);\n            // v[1] = union( v[1], r[0] )\n            v[1] = set_union(v[1], r[0]);\n        }\n        return true;\n    }\n/* %$$\n$head End Class Definition$$\n$srccode%cpp% */\n}; // End of atomic_set_sparsity class\n}  // End empty namespace\n\n/* %$$\n$head Test Atomic Function$$\n$srccode%cpp% */\nbool set_sparsity(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps = 10. * std::numeric_limits<double>::epsilon();\n/* %$$\n$subhead Constructor$$\n$srccode%cpp% */\n    // Create the atomic get_started object\n    atomic_set_sparsity afun(\"atomic_set_sparsity\");\n/* %$$\n$subhead Recording$$\n$srccode%cpp% */\n    size_t n = 3;\n    size_t m = 2;\n    vector< AD<double> > ax(n), ay(m);\n    for(size_t j = 0; j < n; j++)\n        ax[j] = double(j + 1);\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(ax);\n\n    // call atomic function\n    afun(ax, ay);\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f;\n    f.Dependent (ax, ay);  // f(x) = x\n\n    // check function value\n    ok &= NearEqual(ay[0] , ax[2],  eps, eps);\n    ok &= NearEqual(ay[1] , ax[0] * ax[1],  eps, eps);\n\n/* %$$\n$subhead for_sparse_jac$$\n$srccode%cpp% */\n    // correct Jacobian result\n    set_vector check_s(m);\n    check_s[0].insert(2);\n    check_s[1].insert(0);\n    check_s[1].insert(1);\n    // compute and test forward mode\n    {   set_vector r(n), s(m);\n        for(size_t i = 0; i < n; i++)\n            r[i].insert(i);\n        s = f.ForSparseJac(n, r);\n        for(size_t i = 0; i < m; i++)\n            ok &= s[i] == check_s[i];\n    }\n/* %$$\n$subhead rev_sparse_jac$$\n$srccode%cpp% */\n    // compute and test reverse mode\n    {   set_vector r(m), s(m);\n        for(size_t i = 0; i < m; i++)\n            r[i].insert(i);\n        s = f.RevSparseJac(m, r);\n        for(size_t i = 0; i < m; i++)\n            ok &= s[i] == check_s[i];\n    }\n/* %$$\n$subhead for_sparse_hes$$\n$srccode%cpp% */\n    // correct Hessian result\n    set_vector check_h(n);\n    check_h[0].insert(1);\n    check_h[1].insert(0);\n    // compute and test forward mode\n    {   set_vector r(1), s(1), h(n);\n        for(size_t i = 0; i < m; i++)\n            s[0].insert(i);\n        for(size_t j = 0; j < n; j++)\n            r[0].insert(j);\n        h = f.ForSparseHes(r, s);\n        for(size_t i = 0; i < n; i++)\n            ok &= h[i] == check_h[i];\n    }\n/* %$$\n$subhead rev_sparse_hes$$\nNote the previous call to $code ForSparseJac$$ above\nstored its results in $icode f$$.\n$srccode%cpp% */\n    // compute and test reverse mode\n    {   set_vector s(1), h(n);\n        for(size_t i = 0; i < m; i++)\n            s[0].insert(i);\n        h = f.RevSparseHes(n, s);\n        for(size_t i = 0; i < n; i++)\n            ok &= h[i] == check_h[i];\n    }\n/* %$$\n$subhead Test Result$$\n$srccode%cpp% */\n    return ok;\n}\n/* %$$\n$end\n*/\n"
  },
  {
    "path": "test_more/deprecated/atomic_two/tangent.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n@begin atomic_two_tangent.cpp@@\n$spell\n    Tanh\n    bool\n$$\n\n$section Tan and Tanh as User Atomic Operations: Example and Test$$\n\n$head Theory$$\nThe code below uses the $cref tan_forward$$ and $cref tan_reverse$$\nto implement the tangent and hyperbolic tangent\nfunctions as atomic function operations.\n\n$head sparsity$$\nThis atomic operation can use both set and bool sparsity patterns.\n\n$head Start Class Definition$$\n$srccode%cpp% */\n# include <cppad/cppad.hpp>\nnamespace { // Begin empty namespace\nusing CppAD::vector;\n//\n// a utility to compute the union of two sets.\nusing CppAD::set_union;\n//\nclass atomic_tangent : public CppAD::atomic_base<float> {\n/* %$$\n$head Constructor $$\n$srccode%cpp% */\nprivate:\n    const bool hyperbolic_; // is this hyperbolic tangent\npublic:\n    // constructor\n    atomic_tangent(const char* name, bool hyperbolic)\n    : CppAD::atomic_base<float>(name),\n    hyperbolic_(hyperbolic)\n    { }\nprivate:\n/* %$$\n$head forward$$\n$srccode%cpp% */\n    // forward mode routine called by CppAD\n    bool forward(\n        size_t                    p ,\n        size_t                    q ,\n        const vector<bool>&      vx ,\n                  vector<bool>&     vzy ,\n        const vector<float>&     tx ,\n                  vector<float>&    tzy\n    )\n    {   size_t q1 = q + 1;\n# ifndef NDEBUG\n        size_t n  = tx.size()  / q1;\n        size_t m  = tzy.size() / q1;\n# endif\n        assert( n == 1 );\n        assert( m == 2 );\n        assert( p <= q );\n        size_t j, k;\n\n        // check if this is during the call to old_tan(id, ax, ay)\n        if( vx.size() > 0 )\n        {   // set variable flag for both y an z\n            vzy[0] = vx[0];\n            vzy[1] = vx[0];\n        }\n\n        if( p == 0 )\n        {   // z^{(0)} = tan( x^{(0)} ) or tanh( x^{(0)} )\n            if( hyperbolic_ )\n                tzy[0] = float( tanh( tx[0] ) );\n            else\n                tzy[0] = float( tan( tx[0] ) );\n\n            // y^{(0)} = z^{(0)} * z^{(0)}\n            tzy[q1 + 0] = tzy[0] * tzy[0];\n\n            p++;\n        }\n        for(j = p; j <= q; j++)\n        {   float j_inv = 1.f / float(j);\n            if( hyperbolic_ )\n                j_inv = - j_inv;\n\n            // z^{(j)} = x^{(j)} +- sum_{k=1}^j k x^{(k)} y^{(j-k)} / j\n            tzy[j] = tx[j];\n            for(k = 1; k <= j; k++)\n                tzy[j] += tx[k] * tzy[q1 + j-k] * float(k) * j_inv;\n\n            // y^{(j)} = sum_{k=0}^j z^{(k)} z^{(j-k)}\n            tzy[q1 + j] = 0.;\n            for(k = 0; k <= j; k++)\n                tzy[q1 + j] += tzy[k] * tzy[j-k];\n        }\n\n        // All orders are implemented and there are no possible errors\n        return true;\n    }\n/* %$$\n$head reverse$$\n$srccode%cpp% */\n    // reverse mode routine called by CppAD\n    virtual bool reverse(\n        size_t                    q ,\n        const vector<float>&     tx ,\n        const vector<float>&    tzy ,\n                  vector<float>&     px ,\n        const vector<float>&    pzy\n    )\n    {   size_t q1 = q + 1;\n# ifndef NDEBUG\n        size_t n  = tx.size()  / q1;\n        size_t m  = tzy.size() / q1;\n# endif\n        assert( px.size()  == n * q1 );\n        assert( pzy.size() == m * q1 );\n        assert( n == 1 );\n        assert( m == 2 );\n\n        size_t j, k;\n\n        // copy because partials w.r.t. y and z need to change\n        vector<float> qzy = pzy;\n\n        // initialize accumultion of reverse mode partials\n        for(k = 0; k < q1; k++)\n            px[k] = 0.;\n\n        // eliminate positive orders\n        for(j = q; j > 0; j--)\n        {   float j_inv = 1.f / float(j);\n            if( hyperbolic_ )\n                j_inv = - j_inv;\n\n            // H_{x^{(k)}} += delta(j-k) +- H_{z^{(j)} y^{(j-k)} * k / j\n            px[j] += qzy[j];\n            for(k = 1; k <= j; k++)\n                px[k] += qzy[j] * tzy[q1 + j-k] * float(k) * j_inv;\n\n            // H_{y^{j-k)} += +- H_{z^{(j)} x^{(k)} * k / j\n            for(k = 1; k <= j; k++)\n                qzy[q1 + j-k] += qzy[j] * tx[k] * float(k) * j_inv;\n\n            // H_{z^{(k)}} += H_{y^{(j-1)}} * z^{(j-k-1)} * 2.\n            for(k = 0; k < j; k++)\n                qzy[k] += qzy[q1 + j-1] * tzy[j-k-1] * 2.f;\n        }\n\n        // eliminate order zero\n        if( hyperbolic_ )\n            px[0] += qzy[0] * (1.f - tzy[q1 + 0]);\n        else\n            px[0] += qzy[0] * (1.f + tzy[q1 + 0]);\n\n        return true;\n    }\n/* %$$\n$head for_sparse_jac$$\n$srccode%cpp% */\n    // forward Jacobian sparsity routine called by CppAD\n    virtual bool for_sparse_jac(\n        size_t                                p ,\n        const vector<bool>&                   r ,\n                  vector<bool>&                   s ,\n        const vector<float>&                  x )\n    {\n# ifndef NDEBUG\n        size_t n = r.size() / p;\n        size_t m = s.size() / p;\n# endif\n        assert( n == x.size() );\n        assert( n == 1 );\n        assert( m == 2 );\n\n        // sparsity for S(x) = f'(x) * R\n        for(size_t j = 0; j < p; j++)\n        {   s[0 * p + j] = r[j];\n            s[1 * p + j] = r[j];\n        }\n\n        return true;\n    }\n    // forward Jacobian sparsity routine called by CppAD\n    virtual bool for_sparse_jac(\n        size_t                                p ,\n        const vector< std::set<size_t> >&     r ,\n                  vector< std::set<size_t> >&     s ,\n        const vector<float>&                  x )\n    {\n# ifndef NDEBUG\n        size_t n = r.size();\n        size_t m = s.size();\n# endif\n        assert( n == x.size() );\n        assert( n == 1 );\n        assert( m == 2 );\n\n        // sparsity for S(x) = f'(x) * R\n        s[0] = r[0];\n        s[1] = r[0];\n\n        return true;\n    }\n/* %$$\n$head rev_sparse_jac$$\n$srccode%cpp% */\n    // reverse Jacobian sparsity routine called by CppAD\n    virtual bool rev_sparse_jac(\n        size_t                                p ,\n        const vector<bool>&                  rt ,\n                  vector<bool>&                  st ,\n        const vector<float>&                  x )\n    {\n# ifndef NDEBUG\n        size_t n = st.size() / p;\n        size_t m = rt.size() / p;\n# endif\n        assert( n == 1 );\n        assert( m == 2 );\n        assert( n == x.size() );\n\n        // sparsity for S(x)^T = f'(x)^T * R^T\n        for(size_t j = 0; j < p; j++)\n            st[j] = rt[0 * p + j] || rt[1 * p + j];\n\n        return true;\n    }\n    // reverse Jacobian sparsity routine called by CppAD\n    virtual bool rev_sparse_jac(\n        size_t                                p ,\n        const vector< std::set<size_t> >&    rt ,\n                  vector< std::set<size_t> >&    st ,\n        const vector<float>&                  x )\n    {\n# ifndef NDEBUG\n        size_t n = st.size();\n        size_t m = rt.size();\n# endif\n        assert( n == 1 );\n        assert( m == 2 );\n        assert( n == x.size() );\n\n        // sparsity for S(x)^T = f'(x)^T * R^T\n        st[0] = set_union(rt[0], rt[1]);\n        return true;\n    }\n/* %$$\n$head rev_sparse_hes$$\n$srccode%cpp% */\n    // reverse Hessian sparsity routine called by CppAD\n    virtual bool rev_sparse_hes(\n        const vector<bool>&                   vx,\n        const vector<bool>&                   s ,\n                  vector<bool>&                   t ,\n        size_t                                p ,\n        const vector<bool>&                   r ,\n        const vector<bool>&                   u ,\n                  vector<bool>&                   v ,\n        const vector<float>&                  x )\n    {\n# ifndef NDEBUG\n        size_t m = s.size();\n        size_t n = t.size();\n# endif\n        assert( x.size() == n );\n        assert( r.size() == n * p );\n        assert( u.size() == m * p );\n        assert( v.size() == n * p );\n        assert( n == 1 );\n        assert( m == 2 );\n\n        // There are no cross term second derivatives for this case,\n        // so it is not necessary to vx.\n\n        // sparsity for T(x) = S(x) * f'(x)\n        t[0] =  s[0] || s[1];\n\n        // V(x) = f'(x)^T * g''(y) * f'(x) * R  +  g'(y) * f''(x) * R\n        // U(x) = g''(y) * f'(x) * R\n        // S(x) = g'(y)\n\n        // back propagate the sparsity for U, note both components\n        // of f'(x) may be non-zero;\n        size_t j;\n        for(j = 0; j < p; j++)\n            v[j] = u[ 0 * p + j ] || u[ 1 * p + j ];\n\n        // include forward Jacobian sparsity in Hessian sparsity\n        // (note sparsty for f''(x) * R same as for R)\n        if( s[0] || s[1] )\n        {   for(j = 0; j < p; j++)\n            {   // Visual Studio 2013 generates warning without bool below\n                v[j] |= bool( r[j] );\n            }\n        }\n\n        return true;\n    }\n    // reverse Hessian sparsity routine called by CppAD\n    virtual bool rev_sparse_hes(\n        const vector<bool>&                   vx,\n        const vector<bool>&                   s ,\n                  vector<bool>&                   t ,\n        size_t                                p ,\n        const vector< std::set<size_t> >&     r ,\n        const vector< std::set<size_t> >&     u ,\n                  vector< std::set<size_t> >&     v ,\n        const vector<float>&                  x )\n    {\n# ifndef NDEBUG\n        size_t m = s.size();\n        size_t n = t.size();\n# endif\n        assert( x.size() == n );\n        assert( r.size() == n );\n        assert( u.size() == m );\n        assert( v.size() == n );\n        assert( n == 1 );\n        assert( m == 2 );\n\n        // There are no cross term second derivatives for this case,\n        // so it is not necessary to vx.\n\n        // sparsity for T(x) = S(x) * f'(x)\n        t[0] =  s[0] || s[1];\n\n        // V(x) = f'(x)^T * g''(y) * f'(x) * R  +  g'(y) * f''(x) * R\n        // U(x) = g''(y) * f'(x) * R\n        // S(x) = g'(y)\n\n        // back propagate the sparsity for U, note both components\n        // of f'(x) may be non-zero;\n        v[0] = set_union(u[0], u[1]);\n\n        // include forward Jacobian sparsity in Hessian sparsity\n        // (note sparsty for f''(x) * R same as for R)\n        if( s[0] || s[1] )\n            v[0] = set_union(v[0], r[0]);\n\n        return true;\n    }\n/* %$$\n$head End Class Definition$$\n$srccode%cpp% */\n}; // End of atomic_tangent class\n}  // End empty namespace\n\n/* %$$\n$head Use Atomic Function$$\n$srccode%cpp% */\nbool tangent(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    float eps = 10.f * CppAD::numeric_limits<float>::epsilon();\n/* %$$\n$subhead Constructor$$\n$srccode%cpp% */\n    // --------------------------------------------------------------------\n    // Create a tan and tanh object\n    atomic_tangent my_tan(\"my_tan\", false), my_tanh(\"my_tanh\", true);\n/* %$$\n$subhead Recording$$\n$srccode%cpp% */\n    // domain space vector\n    size_t n  = 1;\n    float  x0 = 0.5;\n    CppAD::vector< AD<float> > ax(n);\n    ax[0]     = x0;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(ax);\n\n    // range space vector\n    size_t m = 3;\n    CppAD::vector< AD<float> > af(m);\n\n    // temporary vector for computations\n    // (my_tan and my_tanh computes tan or tanh and its square)\n    CppAD::vector< AD<float> > az(2);\n\n    // call atomic tan function and store tan(x) in f[0] (ignore tan(x)^2)\n    my_tan(ax, az);\n    af[0] = az[0];\n\n    // call atomic tanh function and store tanh(x) in f[1] (ignore tanh(x)^2)\n    my_tanh(ax, az);\n    af[1] = az[0];\n\n    // put a constant in f[2] = tanh(1.) (for sparsity pattern testing)\n    CppAD::vector< AD<float> > one(1);\n    one[0] = 1.;\n    my_tanh(one, az);\n    af[2] = az[0];\n\n    // create f: x -> f and stop tape recording\n    CppAD::ADFun<float> F;\n    F.Dependent(ax, af);\n/* %$$\n$subhead forward$$\n$srccode%cpp% */\n    // check function value\n    float tan = std::tan(x0);\n    ok &= NearEqual(af[0] , tan,  eps, eps);\n    float tanh = std::tanh(x0);\n    ok &= NearEqual(af[1] , tanh,  eps, eps);\n\n    // check zero order forward\n    CppAD::vector<float> x(n), f(m);\n    x[0] = x0;\n    f    = F.Forward(0, x);\n    ok &= NearEqual(f[0] , tan,  eps, eps);\n    ok &= NearEqual(f[1] , tanh,  eps, eps);\n\n    // compute first partial of f w.r.t. x[0] using forward mode\n    CppAD::vector<float> dx(n), df(m);\n    dx[0] = 1.;\n    df    = F.Forward(1, dx);\n/* %$$\n$subhead reverse$$\n$srccode%cpp% */\n    // compute derivative of tan - tanh using reverse mode\n    CppAD::vector<float> w(m), dw(n);\n    w[0]  = 1.;\n    w[1]  = 1.;\n    w[2]  = 0.;\n    dw    = F.Reverse(1, w);\n\n    // tan'(x)   = 1 + tan(x)  * tan(x)\n    // tanh'(x)  = 1 - tanh(x) * tanh(x)\n    float tanp  = 1.f + tan * tan;\n    float tanhp = 1.f - tanh * tanh;\n    ok   &= NearEqual(df[0], tanp, eps, eps);\n    ok   &= NearEqual(df[1], tanhp, eps, eps);\n    ok   &= NearEqual(dw[0], w[0]*tanp + w[1]*tanhp, eps, eps);\n\n    // compute second partial of f w.r.t. x[0] using forward mode\n    CppAD::vector<float> ddx(n), ddf(m);\n    ddx[0] = 0.;\n    ddf    = F.Forward(2, ddx);\n\n    // compute second derivative of tan - tanh using reverse mode\n    CppAD::vector<float> ddw(2);\n    ddw   = F.Reverse(2, w);\n\n    // tan''(x)   = 2 *  tan(x) * tan'(x)\n    // tanh''(x)  = - 2 * tanh(x) * tanh'(x)\n    // Note that second order Taylor coefficient for u half the\n    // corresponding second derivative.\n    float two    = 2;\n    float tanpp  =   two * tan * tanp;\n    float tanhpp = - two * tanh * tanhp;\n    ok   &= NearEqual(two * ddf[0], tanpp, eps, eps);\n    ok   &= NearEqual(two * ddf[1], tanhpp, eps, eps);\n    ok   &= NearEqual(ddw[0], w[0]*tanp  + w[1]*tanhp , eps, eps);\n    ok   &= NearEqual(ddw[1], w[0]*tanpp + w[1]*tanhpp, eps, eps);\n/* %$$\n$subhead for_sparse_jac$$\n$srccode%cpp% */\n    // Forward mode computation of sparsity pattern for F.\n    size_t p = n;\n    // user vectorBool because m and n are small\n    CppAD::vectorBool r1(p), s1(m * p);\n    r1[0] = true;            // propagate sparsity for x[0]\n    s1    = F.ForSparseJac(p, r1);\n    ok  &= (s1[0] == true);  // f[0] depends on x[0]\n    ok  &= (s1[1] == true);  // f[1] depends on x[0]\n    ok  &= (s1[2] == false); // f[2] does not depend on x[0]\n/* %$$\n$subhead rev_sparse_jac$$\n$srccode%cpp% */\n    // Reverse mode computation of sparsity pattern for F.\n    size_t q = m;\n    CppAD::vectorBool s2(q * m), r2(q * n);\n    // Sparsity pattern for identity matrix\n    size_t i, j;\n    for(i = 0; i < q; i++)\n    {   for(j = 0; j < m; j++)\n            s2[i * q + j] = (i == j);\n    }\n    r2   = F.RevSparseJac(q, s2);\n    ok  &= (r2[0] == true);  // f[0] depends on x[0]\n    ok  &= (r2[1] == true);  // f[1] depends on x[0]\n    ok  &= (r2[2] == false); // f[2] does not depend on x[0]\n/* %$$\n$subhead rev_sparse_hes$$\n$srccode%cpp% */\n    // Hessian sparsity for f[0]\n    CppAD::vectorBool s3(m), h(p * n);\n    s3[0] = true;\n    s3[1] = false;\n    s3[2] = false;\n    h    = F.RevSparseHes(p, s3);\n    ok  &= (h[0] == true);  // Hessian is non-zero\n\n    // Hessian sparsity for f[2]\n    s3[0] = false;\n    s3[2] = true;\n    h    = F.RevSparseHes(p, s3);\n    ok  &= (h[0] == false);  // Hessian is zero\n/* %$$\n$subhead Large x Values$$\n$srccode%cpp% */\n    // check tanh results for a large value of x\n    x[0]  = std::numeric_limits<float>::max() / two;\n    f     = F.Forward(0, x);\n    tanh  = 1.;\n    ok   &= NearEqual(f[1], tanh, eps, eps);\n    df    = F.Forward(1, dx);\n    tanhp = 0.;\n    ok   &= NearEqual(df[1], tanhp, eps, eps);\n\n    return ok;\n}\n/* %$$\n$end\n*/\n"
  },
  {
    "path": "test_more/deprecated/chkpoint_one/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n#\n# BEGIN_SORT_THIS_LINE_PLUS_2\nSET(source_list\n    chkpoint_one.cpp\n    extended_ode.cpp\n    get_started.cpp\n    mul_level.cpp\n    ode.cpp\n)\n# END_SORT_THIS_LINE_MINUS_2\n\nset_compile_flags(test_more_deprecated_chkpoint_one\n    \"${cppad_debug_which}\" \"${source_list}\"\n)\n#\nADD_EXECUTABLE(test_more_deprecated_chkpoint_one\n    EXCLUDE_FROM_ALL ${source_list}\n)\n#\n# List of libraries to be linked into the specified target\nTARGET_LINK_LIBRARIES(test_more_deprecated_chkpoint_one\n    ${cppad_lib}\n    ${colpack_libs}\n)\n#\n# check_test_more_deprecated_chkpoint_one\nadd_check_executable(check_test_more_deprecated chkpoint_one)\n"
  },
  {
    "path": "test_more/deprecated/chkpoint_one/chkpoint_one.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n// CPPAD_HAS_* defines\n# include <cppad/configure.hpp>\n\n// system include files used for I/O\n# include <iostream>\n\n// C style asserts\n# include <cassert>\n\n// for thread_alloc\n# include <cppad/utility/thread_alloc.hpp>\n\n// test runner\n# include <cppad/utility/test_boolofvoid.hpp>\n\n// external complied tests\nextern bool extended_ode(void);\nextern bool get_started(void);\nextern bool mul_level(void);\nextern bool ode(void);\n\n// main program that runs all the tests\nint main(void)\n{   std::string group = \"example/chkpoint_one\";\n    size_t      width = 20;\n    CppAD::test_boolofvoid Run(group, width);\n\n    // This line is used by test_one.sh\n\n    // external compiled tests\n    Run( extended_ode,        \"extended_ode\"   );\n    Run( get_started,         \"get_started\"    );\n    Run( mul_level,           \"mul_level\"      );\n    Run( ode,                 \"ode\"            );\n    // check for memory leak\n    bool memory_ok = CppAD::thread_alloc::free_all();\n    // print summary at end\n    bool ok = Run.summary(memory_ok);\n    //\n    return static_cast<int>( ! ok );\n}\n"
  },
  {
    "path": "test_more/deprecated/chkpoint_one/extended_ode.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n@begin chkpoint_one_extended_ode.cpp@@\n$spell\n    Checkpointing\n    Runge-Kutta\n    mul\n$$\n\n$section Checkpointing an Extended ODE Solver: Example and Test$$\n$index mul_level, checkpoint$$\n\n$head See Also$$\n$cref chkpoint_one_ode.cpp$$,\n$cref chkpoint_one_mul_level.cpp$$.\n\n\n$head Discussion$$\nSuppose that we wish to extend an ODE to include derivatives with respect\nto some parameter in the ODE. In addition, suppose we wish to\ndifferentiate a function that depends on these derivatives.\nApplying checkpointing to at the second level of AD would not work;\nsee $cref chkpoint_one_mul_level.cpp$$\nIn this example we show how one can do this by\ncheckpointing an extended ODE solver.\n\n$head Problem$$\nWe consider the initial value problem with parameter $latex x$$ defined by,\n$latex z(0, x) = z_0 (x)$$,\n$latex \\[\n    \\partial_t z(t, x ) = h [ x , z(t, x) ]\n\\]$$\nNote that if $latex t$$ needs to be in the equation, one can define\nthe first component of $latex z(t, x)$$ to be equal to $latex t$$.\n\n$head ODE Solver$$\nFor this example, we consider the Fourth order Runge-Kutta ODE solver.\nGiven an approximation solution at time $latex t_k$$ denoted by\n$latex \\tilde{z}_k (x)$$, and $latex \\Delta t = t_{k+1} - t_k$$,\nit defines the approximation solution $latex \\tilde{z}_{k+1} (x)$$\nat time $latex t_{k+1}$$ by\n$latex \\[\n\\begin{array}{rcl}\nh_1 & =  & h [ x , \\tilde{z}_k (x) ]\n\\\\\nh_2 & =  & h [ x , \\tilde{z}_k (x) + \\Delta t \\; h_1 / 2 ]\n\\\\\nh_3 & =  & h [ x , \\tilde{z}_k (x) + \\Delta t \\; h_2 / 2 ]\n\\\\\nh_4 & =  & h [ x , \\tilde{z}_k (x) + \\Delta t \\; h_3 ]\n\\\\\n\\tilde{z}_{k+1} (x) & = &\n    \\tilde{z}_k (x) + \\Delta t \\; ( h_1 +  2 h_2 + 2 h_3 + h_4 ) / 6\n\\end{array}\n\\] $$\nIf $latex \\tilde{z}_k (x) = z_k (x)$$, then\n$latex \\tilde{z}_{k+1} (x) = z_{k+1} (x) + O( \\Delta t^5 )$$, then\nOther ODE solvers can use a similar method to the one used below.\n\n$head ODE$$\nFor this example the ODE is defined by\n$latex z(0, x) = 0$$ and\n$latex \\[\n    h[ x, z(t, x) ] =\n    \\left( \\begin{array}{c}\n            x_0                     \\\\\n            x_1 z_0 (t, x)          \\\\\n            \\vdots                  \\\\\n            x_{n-1} z_{n-2} (t, x)\n    \\end{array} \\right)\n    =\n    \\left( \\begin{array}{c}\n            \\partial_t z_0 (t , x)      \\\\\n            \\partial_t z_1 (t , x)      \\\\\n            \\vdots                      \\\\\n            \\partial_t z_{n-1} (t , x)\n    \\end{array} \\right)\n\\] $$\n\n$head Solution$$\nThe solution of the ODE for this example,\nwhich is used to check the results,\ncan be calculated by\nstarting with the first row and then using the solution\nfor the first row to solve the second and so on.\nDoing this we obtain\n$latex \\[\n    z(t, x) =\n    \\left( \\begin{array}{c}\n        x_0 t                  \\\\\n        x_1 x_0 t^2 / 2        \\\\\n        \\vdots                 \\\\\n        x_{n-1} x_{n-2} \\ldots x_0 t^n / n !\n    \\end{array} \\right)\n\\] $$\n\n\n$comment %example/chkpoint_one/extended_ode.cpp%0%// BEGIN C++%// END C++%1%$$\n\n$end\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n\nnamespace {\n    using CppAD::AD;\n    typedef AD<double>                     a1double;\n    typedef AD<a1double>                   a2double;\n    //\n    typedef CPPAD_TESTVECTOR(   double )   a0vector;\n    typedef CPPAD_TESTVECTOR( a1double )   a1vector;\n    typedef CPPAD_TESTVECTOR( a2double )   a2vector;\n    //\n    // set once by main and kept that way\n    double delta_t_ = std::numeric_limits<double>::quiet_NaN();\n    size_t n_       = 0;\n    //\n    // The function h( x , y)\n    template <class FloatVector>\n    FloatVector h(const FloatVector& x, const FloatVector& y)\n    {   assert( size_t( x.size() ) == n_ );\n        assert( size_t( y.size() ) == n_ );\n        FloatVector result(n_);\n        result[0] = x[0];\n        for(size_t i = 1; i < n_; i++)\n            result[i] = x[i] * y[i-1];\n        return result;\n    }\n\n    // The 4-th Order Runge-Kutta Step\n    template <class FloatVector>\n    FloatVector Runge4(const FloatVector& x, const FloatVector& z0\n    )\n    {   assert( size_t( x.size() ) == n_ );\n        assert( size_t( z0.size() ) == n_ );\n        //\n        typedef typename FloatVector::value_type Float;\n        //\n        Float  dt = Float(delta_t_);\n        size_t m  = z0.size();\n        //\n        FloatVector h1(m), h2(m), h3(m), h4(m), result(m);\n        h1 = h( x, z0 );\n        //\n        for(size_t i = 0; i < m; i++)\n            h2[i] = z0[i] + dt * h1[i] / 2.0;\n        h2 = h( x, h2 );\n        //\n        for(size_t i = 0; i < m; i++)\n            h3[i] = z0[i] + dt * h2[i] / 2.0;\n        h3 = h( x, h3 );\n        //\n        for(size_t i = 0; i < m; i++)\n            h4[i] = z0[i] + dt * h3[i];\n        h4 = h( x, h4 );\n        //\n        for(size_t i = 0; i < m; i++)\n        {   Float dz = dt * ( h1[i] + 2.0*h2[i] + 2.0*h3[i] + h4[i] ) / 6.0;\n            result[i] = z0[i] + dz;\n        }\n        return result;\n    }\n\n    // Derivative of 4-th Order Runge-Kutta Step w.r.t x\n    a1vector Runge4_x(const a1vector& x, const a1vector& z0)\n    {   assert( size_t( x.size() ) == n_ );\n        assert( size_t( z0.size() ) == n_ );\n        //\n        a2vector ax(n_);\n        for(size_t j = 0; j < n_; j++)\n            ax[j] = x[j];\n        //\n        a2vector az0(n_);\n        for(size_t i = 0; i < n_; i++)\n            az0[i] = z0[i];\n        //\n        CppAD::Independent(ax);\n        a2vector az(n_);\n        az = Runge4(ax, az0);\n        CppAD::ADFun<a1double> f(ax, az);\n        //\n        a1vector result =  f.Jacobian(x);\n        //\n        return result;\n    }\n\n    // Derivative of 4-th Order Runge-Kutta Step w.r.t z0\n    a1vector Runge4_z0(const a1vector& x, const a1vector& z0)\n    {   assert( size_t( x.size()  ) == n_ );\n        assert( size_t( z0.size() ) == n_ );\n        //\n        a2vector ax(n_);\n        for(size_t j = 0; j < n_; j++)\n            ax[j] = x[j];\n        //\n        a2vector az0(n_);\n        for(size_t i = 0; i < n_; i++)\n            az0[i] = z0[i];\n        //\n        CppAD::Independent(az0);\n        a2vector az(n_);\n        az = Runge4(ax, az0);\n        CppAD::ADFun<a1double> f(az0, az);\n        //\n        a1vector result =  f.Jacobian(z0);\n        //\n        return result;\n    }\n\n    // pack an extended ode vector\n    template <class FloatVector>\n    void pack(\n        FloatVector&         extended_ode ,\n        const FloatVector&   x            ,\n        const FloatVector&   z            ,\n        const FloatVector&   z_x          )\n    {   assert( size_t( extended_ode.size() ) == n_ + n_ + n_ * n_ );\n        assert( size_t( x.size()            ) == n_                );\n        assert( size_t( z.size()            ) == n_                );\n        assert( size_t( z_x.size()          ) == n_ * n_           );\n        //\n        size_t offset = 0;\n        for(size_t i = 0; i < n_; i++)\n            extended_ode[offset + i] = x[i];\n        offset += n_;\n        for(size_t i = 0; i < n_; i++)\n            extended_ode[offset + i] = z[i];\n        offset += n_;\n        for(size_t i = 0; i < n_; i++)\n        {   for(size_t j = 0; j < n_; j++)\n            {   // partial of z_i (t , x ) w.r.t x_j\n                extended_ode[offset + i * n_ + j] = z_x[i * n_ + j];\n            }\n        }\n    }\n\n    // unpack an extended ode vector\n    template <class FloatVector>\n    void unpack(\n        const FloatVector&         extended_ode ,\n        FloatVector&               x            ,\n        FloatVector&               z            ,\n        FloatVector&               z_x          )\n    {   assert( size_t( extended_ode.size() ) == n_ + n_ + n_ * n_ );\n        assert( size_t( x.size()            ) == n_                );\n        assert( size_t( z.size()            ) == n_                );\n        assert( size_t( z_x.size()          ) == n_ * n_           );\n        //\n        size_t offset = 0;\n        for(size_t i = 0; i < n_; i++)\n            x[i] = extended_ode[offset + i];\n        offset += n_;\n        for(size_t i = 0; i < n_; i++)\n            z[i] = extended_ode[offset + i];\n        offset += n_;\n        for(size_t i = 0; i < n_; i++)\n        {   for(size_t j = 0; j < n_; j++)\n            {   // partial of z_i (t , x ) w.r.t x_j\n                z_x[i * n_ + j] = extended_ode[offset + i * n_ + j];\n            }\n        }\n    }\n\n    // Algorithm that advances the partial of z(t, x) w.r.t x\n    void ext_ode_algo(const a1vector& ext_ode_in, a1vector& ext_ode_out)\n    {   assert( size_t( ext_ode_in.size()  ) == n_ + n_ + n_ * n_ );\n        assert( size_t( ext_ode_out.size() ) == n_ + n_ + n_ * n_ );\n        //\n        // initial extended ode information\n        a1vector x(n_), z0(n_), z0_x(n_ * n_);\n        unpack(ext_ode_in, x, z0, z0_x);\n        //\n        // advance z(t, x)\n        a1vector z1 = Runge4(x, z0);\n        //\n        // partial of z1 w.r.t. x\n        a1vector z1_x = Runge4_x(x, z0);\n        //\n        // partial of z1 w.r.t. z0\n        a1vector z1_z0 = Runge4_z0(x, z0);\n        //\n        // total derivative of z1 w.r.t x\n        for(size_t i = 0; i < n_; i++)\n        {   for(size_t j = 0; j < n_; j++)\n            {   a1double sum = 0.0;\n                for(size_t k = 0; k < n_; k++)\n                    sum += z1_z0 [ i * n_ + k ] * z0_x [ k * n_ + j ];\n                z1_x[ i * n_ + j] += sum;\n            }\n        }\n        //\n        // final extended ode information\n        pack(ext_ode_out, x, z1, z1_x);\n        //\n        return;\n    }\n}\n//\nbool extended_ode(void)\n{   bool ok = true;\n    using CppAD::NearEqual;\n    double eps = std::numeric_limits<double>::epsilon();\n    //\n    // number of terms in the differential equation\n    n_ = 6;\n    //\n    // step size for the differentiail equation\n    size_t n_step = 10;\n    double T      = 1.0;\n    delta_t_ = T / double(n_step);\n    //\n    // set parameter value and initial value of the extended ode\n    a1vector ax(n_), az0(n_), az0_x(n_ * n_);\n    for(size_t i = 0; i < n_; i++)\n    {   ax[i]  = a1double(i + 1);\n        az0[i] = a1double(0);\n        for(size_t j = 0; j < n_; j++)\n            az0_x[ i * n_ + j ] = 0.0;\n    }\n    //\n    // pack into extended ode information input vector\n    size_t n_ext = n_ + n_ + n_ * n_;\n    a1vector aext_ode_in(n_ext);\n    pack(aext_ode_in, ax, az0, az0_x);\n    //\n    // create checkpoint version of the algorithm\n    a1vector aext_ode_out(n_ext);\n    CppAD::checkpoint<double> ext_ode_check(\n        \"ext_ode\", ext_ode_algo, aext_ode_in, aext_ode_out\n    );\n    //\n    // set the independent variables for recording\n    CppAD::Independent( ax );\n    //\n    // repack to get dependence on ax\n    pack(aext_ode_in, ax, az0, az0_x);\n    //\n    // Now run the checkpoint algorithm n_step times\n    for(size_t k = 0; k < n_step; k++)\n    {   ext_ode_check(aext_ode_in, aext_ode_out);\n        aext_ode_in = aext_ode_out;\n    }\n    //\n    // Unpack the results (must use ax1 so do not overwrite ax)\n    a1vector ax1(n_), az1(n_), az1_x(n_ * n_);\n    unpack(aext_ode_out, ax1, az1, az1_x);\n    //\n    // We could record a complicated function of x and z_x(T, x) in f,\n    // but make this example simpler we record x -> z_x(T, x).\n    CppAD::ADFun<double> f(ax, az1_x);\n    //\n    // check function values\n    a0vector x(n_), z1(n_), z1_x(n_ * n_);\n    for(size_t j = 0; j < n_; j++)\n        x[j] = double(j + 1);\n    z1_x = f.Forward(0, x);\n    //\n    // use z(t, x) for checking solution\n    z1[0] = x[0] * T;\n    for(size_t i = 1; i < n_; i++)\n        z1[i] = x[i] * T * z1[i-1] / double(i+1);\n    //\n    // expected accuracy for each component of of z(t, x)\n    a0vector acc(n_);\n    for(size_t i = 0; i < n_; i++)\n    {   if( i < 4 )\n        {   // Runge-Kutta methods is exact for this case\n            acc[i] = 10. * eps;\n        }\n        else\n        {   acc[i] = 1.0;\n            for(size_t k = 0; k < 5; k++)\n                    acc[i] *= x[k] * delta_t_;\n        }\n    }\n    // check z1(T, x)\n    for(size_t i = 0; i < n_; i++)\n    {   for(size_t j = 0; j < n_; j++)\n        {   // check partial of z1_i w.r.t x_j\n            double check = 0.0;\n            if( j <= i )\n                check = z1[i] / x[j];\n            ok &= NearEqual(z1_x[ i * n_ + j ] , check, acc[i], acc[i]);\n        }\n    }\n    //\n    // Now use f to compute a derivative. For this 'simple' example it is\n    // the derivative with respect to x of the\n    // partial with respect to x[n-1] of z_{n-1} (t , x)\n    a0vector w(n_ * n_), dw(n_);\n    for(size_t i = 0; i < n_; i++)\n    {   for(size_t j = 0; j < n_; j++)\n        {   w[ i * n_ + j ] = 0.0;\n            if( i == n_ - 1 && j == n_ - 1 )\n                w[ i * n_ + j ] = 1.0;\n        }\n    }\n    dw = f.Reverse(1, w);\n    for(size_t j = 0; j < n_; j++)\n    {   double check = 0.0;\n        if( j < n_ - 1 )\n            check = z1[n_ - 1] / ( x[n_ - 1] * x[j] );\n        ok &= NearEqual(dw[j] , check, acc[n_-1], acc[n_-1]);\n    }\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "test_more/deprecated/chkpoint_one/get_started.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n@begin chkpoint_one_get_started.cpp@@\n$spell\n    checkpointing\n    Taylor\n$$\n\n$section Simple Checkpointing: Example and Test$$\n\n$head Purpose$$\nBreak a large computation into pieces and only store values at the\ninterface of the pieces.\nIn actual applications, there may be many functions, but\nfor this example there are only two.\nThe functions\n$latex F : \\B{R}^2 \\rightarrow \\B{R}^2$$\nand\n$latex G : \\B{R}^2 \\rightarrow \\B{R}^2$$\ndefined by\n$latex \\[\n    F(y) = \\left( \\begin{array}{c}\n        y_0 + y_0 + y_0\n        \\\\\n        y_1 + y_1 + y_1\n    \\end{array} \\right)\n    \\; , \\;\n    G(x) = \\left( \\begin{array}{c}\n        x_0 \\cdot x_0 \\cdot x_0\n        \\\\\n        x_1 \\cdot x_1 \\cdot x_1\n    \\end{array} \\right)\n\\] $$\n\n$comment %example/chkpoint_one/get_started.cpp%0%// BEGIN C++%// END C++%1%$$\n\n\n$end\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n\nnamespace {\n    using CppAD::AD;\n    typedef CPPAD_TESTVECTOR(AD<double>)            ADVector;\n    typedef CppAD::atomic_base<double>::option_enum option_enum;\n\n    void f_algo(const ADVector& y, ADVector& z)\n    {   z[0] = 0.0;\n        z[1] = 0.0;\n        for(size_t k = 0; k < 3; k++)\n        {   z[0] += y[0];\n            z[1] += y[1];\n        }\n        return;\n    }\n    void g_algo(const ADVector& x, ADVector& y)\n    {   y[0] = 1.0;\n        y[1] = 1.0;\n        for(size_t k = 0; k < 3; k++)\n        {   y[0] *= x[0];\n            y[1] *= x[1];\n        }\n        return;\n    }\n    bool test_case(\n        option_enum f_sparsity, option_enum g_sparsity, bool optimize )\n    {   bool ok = true;\n        using CppAD::checkpoint;\n        using CppAD::ADFun;\n        using CppAD::NearEqual;\n        size_t i, j, k, n = 2, m = n;\n        double eps = 10. * std::numeric_limits<double>::epsilon();\n\n        // checkpoint version of the function F(x)\n        ADVector ax(n), ay(n), az(m);\n        for(j = 0; j < n; j++)\n            ax[j] = double(j + 1);\n        // could also use bool_sparsity_enum or set_sparsity_enum\n        checkpoint<double> atom_f(\"atom_f\", f_algo, ax, ay, f_sparsity);\n        checkpoint<double> atom_g(\"atom_g\", g_algo, ay, az, g_sparsity);\n\n        // Record a version of z = g[f(x)] without checkpointing\n        Independent(ax);\n        f_algo(ax, ay);\n        g_algo(ay, az);\n        ADFun<double> check_not(ax, az);\n\n        // Record a version of z = g[f(x)] with checkpointing\n        Independent(ax);\n        atom_f(ax, ay);\n        atom_g(ay, az);\n        ADFun<double> check_yes(ax, az);\n\n        // checkpointing should use fewer operations\n        ok &= check_yes.size_var() < check_not.size_var();\n\n        // this does not really save space because f and g are only used once\n        ok &= check_not.size_var() <=\n            check_yes.size_var() + atom_f.size_var() + atom_g.size_var();\n\n        // compare forward mode results for orders 0, 1, 2\n        size_t q = 2;\n        CPPAD_TESTVECTOR(double) x_q(n*(q+1)), z_not(m*(q+1)), z_yes(m*(q+1));\n        for(j = 0; j < n; j++)\n        {   for(k = 0; k <= q; k++)\n                x_q[ j * (q+1) + k ] = 1.0 / double(q + 1 - k);\n        }\n        z_not = check_not.Forward(q, x_q);\n        z_yes = check_yes.Forward(q, x_q);\n        for(i = 0; i < m; i++)\n        {   for(k = 0; k <= q; k++)\n            {   double zik_not = z_not[ i * (q+1) + k];\n                double zik_yes = z_yes[ i * (q+1) + k];\n                ok &= NearEqual(zik_not, zik_yes, eps, eps);\n            }\n        }\n\n        // compare reverse mode results\n        CPPAD_TESTVECTOR(double) w(m*(q+1)), dw_not(n*(q+1)), dw_yes(n*(q+1));\n        for(i = 0; i < m * (q + 1); i++)\n            w[i] = 1.0 / double(i + 1);\n        dw_not = check_not.Reverse(q+1, w);\n        dw_yes = check_yes.Reverse(q+1, w);\n        for(j = 0; j < n; j++)\n        {   for(k = 0; k <= q; k++)\n            {   double dwjk_not = dw_not[ j * (q+1) + k];\n                double dwjk_yes = dw_yes[ j * (q+1) + k];\n                ok &= NearEqual(dwjk_not, dwjk_yes, eps, eps);\n            }\n        }\n\n        // compare forward mode Jacobian sparsity patterns\n        CppAD::vector< std::set<size_t> > r(n), s_not(m), s_yes(m);\n        for(j = 0; j < n; j++)\n            r[j].insert(j);\n        s_not = check_not.ForSparseJac(n, r);\n        s_yes = check_yes.ForSparseJac(n, r);\n        for(i = 0; i < m; i++)\n            ok &= s_not[i] == s_yes[i];\n\n        // compare reverse mode Jacobian sparsity patterns\n        CppAD::vector< std::set<size_t> > s(m), r_not(m), r_yes(m);\n        for(i = 0; i < m; i++)\n            s[i].insert(i);\n        r_not = check_not.RevSparseJac(m, s);\n        r_yes = check_yes.RevSparseJac(m, s);\n        for(i = 0; i < m; i++)\n            ok &= r_not[i] == r_yes[i];\n\n\n        // compare reverse mode Hessian sparsity patterns\n        CppAD::vector< std::set<size_t> > s_one(1), h_not(n), h_yes(n);\n        for(i = 0; i < m; i++)\n            s_one[0].insert(i);\n        h_not = check_not.RevSparseHes(n, s_one);\n        h_yes = check_yes.RevSparseHes(n, s_one);\n        for(i = 0; i < n; i++)\n            ok &= h_not[i] == h_yes[i];\n\n        return ok;\n    }\n}\n\nbool get_started(void)\n{   bool ok = true;\n\n    // different types of sparsity\n    option_enum pack_sparsity = CppAD::atomic_base<double>::pack_sparsity_enum;\n    option_enum bool_sparsity = CppAD::atomic_base<double>::bool_sparsity_enum;\n    option_enum set_sparsity  = CppAD::atomic_base<double>::set_sparsity_enum;\n\n    // test some different cases\n    ok &= test_case(pack_sparsity, pack_sparsity, true);\n    ok &= test_case(pack_sparsity, bool_sparsity, false);\n    ok &= test_case(bool_sparsity, set_sparsity,  true);\n    ok &= test_case(set_sparsity,  set_sparsity,  false);\n\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "test_more/deprecated/chkpoint_one/mul_level.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n@begin chkpoint_one_mul_level.cpp@@\n$spell\n    checkpointing\n$$\n\n$section Atomic Operations and Multiple-Levels of AD: Example and Test$$\n\n$head Discussion$$\nOne can use $cref/checkpoint/chkpoint_one/$$ or $cref atomic_two$$ to code\nan $codei%AD<%Base%>%$$ operation as atomic.\nThis means that derivative computations that use the type $icode Base$$\nwill call the corresponding $code atomic_base$$ member functions.\nOn the other hand, if $icode Base$$ is $codei%AD<%Other%>%$$ the\noperations recorded at the $icode Base$$ level will not be atomic.\nThis is demonstrated in this example.\n\n$comment %example/chkpoint_one/mul_level.cpp%0%// BEGIN C++%// END C++%1%$$\n\n\n$end\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n\nnamespace {\n    using CppAD::AD;\n    typedef AD<double>                      a1double;\n    typedef AD<a1double>                    a2double;\n    typedef CPPAD_TESTVECTOR(a1double)      a1vector;\n    typedef CPPAD_TESTVECTOR(a2double)      a2vector;\n\n    void f_algo(const a2vector& x, a2vector& y)\n    {   size_t n = x.size();\n        y[0] = 0.0;\n        for(size_t j = 1; j < n; j++)\n            y[0] += x[j-1] * x[j];\n        return;\n    }\n}\n//\nbool mul_level(void)\n{   bool ok = true;\n    using CppAD::checkpoint;\n    using CppAD::ADFun;\n    using CppAD::Independent;\n\n    // domain dimension for this problem\n    size_t n = 10;\n    size_t m = 1;\n\n    // checkpoint version of the function F(x)\n    a2vector a2x(n), a2y(m);\n    for(size_t j = 0; j < n; j++)\n        a2x[j] = a2double(j + 1);\n    //\n    // could also use bool_sparsity_enum or set_sparsity_enum\n    checkpoint<a1double> atom_f(\"atom_f\", f_algo, a2x, a2y);\n    //\n    // Record a version of y = f(x) without checkpointing\n    Independent(a2x);\n    f_algo(a2x, a2y);\n    ADFun<a1double> check_not(a2x, a2y);\n    //\n    // number of variables in a tape of f_algo that does not use checkpointing\n    size_t size_not = check_not.size_var();\n    //\n    // Record a version of y = f(x) with checkpointing\n    Independent(a2x);\n    atom_f(a2x, a2y);\n    ADFun<a1double> check_yes(a2x, a2y);\n    //\n    // f_algo is represented by one atomic operation in this tape\n    ok &= check_yes.size_var() < size_not;\n    //\n    // now record operations at a1double level\n    a1vector a1x(n), a1y(m);\n    for(size_t j = 0; j < n; j++)\n        a1x[j] = a1double(j + 1);\n    //\n    // without checkpointing\n    Independent(a1x);\n    a1y = check_not.Forward(0, a1x);\n    ADFun<double> with_not(a1x, a1y);\n    //\n    // should have the same size\n    ok &= with_not.size_var() == size_not;\n    //\n    // with checkpointing\n    Independent(a1x);\n    a1y = check_yes.Forward(0, a1x);\n    ADFun<double> with_yes(a1x, a1y);\n    //\n    // f_algo is nolonger represented by one atomic operation in this tape\n    ok &= with_yes.size_var() == size_not;\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "test_more/deprecated/chkpoint_one/ode.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n@begin chkpoint_one_ode.cpp@@\n$spell\n    Checkpointing\n    Runge-Kutta\n$$\n\n$section Checkpointing an ODE Solver: Example and Test$$\n\n$head See Also$$\n$cref chkpoint_one_extended_ode.cpp$$,\n\n$head Purpose$$\nIn this example we $cref/checkpoint/chkpoint_one/$$ one step of an ODE solver.\n\n$head Problem$$\nWe consider the initial value problem with parameter $latex x$$ defined by,\n$latex z(0, x) = z_0 (x)$$,\n$latex \\[\n    \\partial_t z(t, x ) = h [ x , z(t, x) ]\n\\]$$\nNote that if $latex t$$ needs to be in the equation, one can define\nthe first component of $latex z(t, x)$$ to be equal to $latex t$$.\n\n$head ODE Solver$$\nFor this example, we consider the Fourth order Runge-Kutta ODE solver.\nGiven an approximation solution at time $latex t_k$$ denoted by\n$latex \\tilde{z}_k (x)$$, and $latex \\Delta t = t_{k+1} - t_k$$,\nit defines the approximation solution $latex \\tilde{z}_{k+1} (x)$$\nat time $latex t_{k+1}$$ by\n$latex \\[\n\\begin{array}{rcl}\nh_1 & =  & h [ x , \\tilde{z}_k (x) ]\n\\\\\nh_2 & =  & h [ x , \\tilde{z}_k (x) + \\Delta t \\; h_1 / 2 ]\n\\\\\nh_3 & =  & h [ x , \\tilde{z}_k (x) + \\Delta t \\; h_2 / 2 ]\n\\\\\nh_4 & =  & h [ x , \\tilde{z}_k (x) + \\Delta t \\; h_3 ]\n\\\\\n\\tilde{z}_{k+1} (x) & = &\n    \\tilde{z}_k (x) + \\Delta t \\; ( h_1 +  2 h_2 + 2 h_3 + h_4 ) / 6\n\\end{array}\n\\] $$\nIf $latex \\tilde{z}_k (x) = z_k (x)$$,\n$latex \\tilde{z}_{k+1} (x) = z_{k+1} (x) + O( \\Delta t^5 )$$.\nOther ODE solvers can use a similar method to the one used below.\n\n$head ODE$$\nFor this example the ODE is defined by\n$latex z(0, x) = 0$$ and\n$latex \\[\n    h[ x, z(t, x) ] =\n    \\left( \\begin{array}{c}\n            x_0                     \\\\\n            x_1 z_0 (t, x)          \\\\\n            \\vdots                  \\\\\n            x_{n-1} z_{n-2} (t, x)\n    \\end{array} \\right)\n    =\n    \\left( \\begin{array}{c}\n            \\partial_t z_0 (t , x)      \\\\\n            \\partial_t z_1 (t , x)      \\\\\n            \\vdots                      \\\\\n            \\partial_t z_{n-1} (t , x)\n    \\end{array} \\right)\n\\] $$\n\n$head Solution$$\nThe solution of the ODE for this example,\nwhich is used to check the results,\ncan be calculated by\nstarting with the first row and then using the solution\nfor the first row to solve the second and so on.\nDoing this we obtain\n$latex \\[\n    z(t, x) =\n    \\left( \\begin{array}{c}\n        x_0 t                  \\\\\n        x_1 x_0 t^2 / 2        \\\\\n        \\vdots                 \\\\\n        x_{n-1} x_{n-2} \\ldots x_0 t^n / n !\n    \\end{array} \\right)\n\\] $$\n\n\n$comment %example/chkpoint_one/ode.cpp%0%// BEGIN C++%// END C++%1%$$\n\n$end\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n\nnamespace {\n    using CppAD::AD;\n    typedef AD<double>                     a1double;\n    typedef AD<a1double>                   a2double;\n    //\n    typedef CPPAD_TESTVECTOR(   double )   a0vector;\n    typedef CPPAD_TESTVECTOR( a1double )   a1vector;\n    typedef CPPAD_TESTVECTOR( a2double )   a2vector;\n    //\n    // set once by main and kept that way\n    double delta_t_ = std::numeric_limits<double>::quiet_NaN();\n    size_t n_       = 0;\n    //\n    // The function h( x , y)\n    template <class FloatVector>\n    FloatVector h(const FloatVector& x, const FloatVector& y)\n    {   assert( size_t( x.size() ) == n_ );\n        assert( size_t( y.size() ) == n_ );\n        FloatVector result(n_);\n        result[0] = x[0];\n        for(size_t i = 1; i < n_; i++)\n            result[i] = x[i] * y[i-1];\n        return result;\n    }\n\n    // The 4-th Order Runge-Kutta Step\n    template <class FloatVector>\n    FloatVector Runge4(const FloatVector& x, const FloatVector& z0\n    )\n    {   assert( size_t( x.size() ) == n_ );\n        assert( size_t( z0.size() ) == n_ );\n        //\n        typedef typename FloatVector::value_type Float;\n        //\n        Float  dt = Float(delta_t_);\n        size_t m  = z0.size();\n        //\n        FloatVector h1(m), h2(m), h3(m), h4(m), result(m);\n        h1 = h( x, z0 );\n        //\n        for(size_t i = 0; i < m; i++)\n            h2[i] = z0[i] + dt * h1[i] / 2.0;\n        h2 = h( x, h2 );\n        //\n        for(size_t i = 0; i < m; i++)\n            h3[i] = z0[i] + dt * h2[i] / 2.0;\n        h3 = h( x, h3 );\n        //\n        for(size_t i = 0; i < m; i++)\n            h4[i] = z0[i] + dt * h3[i];\n        h4 = h( x, h4 );\n        //\n        for(size_t i = 0; i < m; i++)\n        {   Float dz = dt * ( h1[i] + 2.0*h2[i] + 2.0*h3[i] + h4[i] ) / 6.0;\n            result[i] = z0[i] + dz;\n        }\n        return result;\n    }\n\n    // pack x and z into an ode_info vector\n    template <class FloatVector>\n    void pack(\n        FloatVector&         ode_info ,\n        const FloatVector&   x        ,\n        const FloatVector&   z        )\n    {   assert( size_t( ode_info.size() ) == n_ + n_ );\n        assert( size_t( x.size()        ) == n_      );\n        assert( size_t( z.size()        ) == n_      );\n        //\n        size_t offset = 0;\n        for(size_t i = 0; i < n_; i++)\n            ode_info[offset + i] = x[i];\n        offset += n_;\n        for(size_t i = 0; i < n_; i++)\n            ode_info[offset + i] = z[i];\n    }\n\n    // unpack an ode_info vector\n    template <class FloatVector>\n    void unpack(\n        const FloatVector&         ode_info ,\n        FloatVector&               x        ,\n        FloatVector&               z        )\n    {   assert( size_t( ode_info.size() ) == n_ + n_ );\n        assert( size_t( x.size()        ) == n_      );\n        assert( size_t( z.size()        ) == n_      );\n        //\n        size_t offset = 0;\n        for(size_t i = 0; i < n_; i++)\n            x[i] = ode_info[offset + i];\n        offset += n_;\n        for(size_t i = 0; i < n_; i++)\n            z[i] = ode_info[offset + i];\n    }\n\n    // Algorithm that z(t, x)\n    void ode_algo(const a1vector& ode_info_in, a1vector& ode_info_out)\n    {   assert( size_t( ode_info_in.size()  ) == n_ + n_ );\n        assert( size_t( ode_info_out.size() ) == n_ + n_ );\n        //\n        // initial ode information\n        a1vector x(n_), z0(n_);\n        unpack(ode_info_in, x, z0);\n        //\n        // advance z(t, x)\n        a1vector z1 = Runge4(x, z0);\n        //\n        // final ode information\n        pack(ode_info_out, x, z1);\n        //\n        return;\n    }\n}\n//\nbool ode(void)\n{   bool ok = true;\n    using CppAD::NearEqual;\n    double eps = std::numeric_limits<double>::epsilon();\n    //\n    // number of terms in the differential equation\n    n_ = 6;\n    //\n    // step size for the differentiail equation\n    size_t n_step = 10;\n    double T      = 1.0;\n    delta_t_ = T / double(n_step);\n    //\n    // set parameter value and initial value of the ode\n    a1vector ax(n_), az0(n_);\n    for(size_t i = 0; i < n_; i++)\n    {   ax[i]  = a1double(i + 1);\n        az0[i] = a1double(0);\n    }\n    //\n    // pack ode information input vector\n    a1vector ode_info_in(2 * n_);\n    pack(ode_info_in, ax, az0);\n    //\n    // create checkpoint version of the algorithm\n    a1vector ode_info_out(2 * n_);\n    CppAD::checkpoint<double> ode_check(\n        \"ode\", ode_algo, ode_info_in, ode_info_out\n    );\n    //\n    // set the independent variables for recording\n    CppAD::Independent( ax );\n    //\n    // repack to get dependence on ax\n    pack(ode_info_in, ax, az0);\n    //\n    // Now run the checkpoint algorithm n_step times\n    for(size_t k = 0; k < n_step; k++)\n    {   ode_check(ode_info_in, ode_info_out);\n        ode_info_in = ode_info_out;\n    }\n    //\n    // Unpack the results (must use ax1 so do not overwrite ax)\n    a1vector ax1(n_), az1(n_);\n    unpack(ode_info_out, ax1, az1);\n    //\n    // We could record a complicated function of x and z(T, x) in f,\n    // but make this example simpler we record x -> z(T, x).\n    CppAD::ADFun<double> f(ax, az1);\n    //\n    // check function values\n    a0vector x(n_), z1(n_);\n    for(size_t j = 0; j < n_; j++)\n        x[j] = double(j + 1);\n    z1 = f.Forward(0, x);\n    //\n    // separate calculation of z(t, x)\n    a0vector check_z1(n_);\n    check_z1[0] = x[0] * T;\n    for(size_t i = 1; i < n_; i++)\n        check_z1[i] = x[i] * T * check_z1[i-1] / double(i+1);\n    //\n    // expected accuracy for each component of of z(t, x)\n    a0vector acc(n_);\n    for(size_t i = 0; i < n_; i++)\n    {   if( i < 4 )\n        {   // Runge-Kutta methods is exact for this case\n            acc[i] = 10. * eps;\n        }\n        else\n        {   acc[i] = 1.0;\n            for(size_t k = 0; k < 5; k++)\n                    acc[i] *= x[k] * delta_t_;\n        }\n    }\n    // check z1(T, x)\n    for(size_t i = 0; i < n_; i++)\n        ok &= NearEqual(z1[i] , check_z1[i], acc[i], acc[i]);\n    //\n    // Now use f to compute a derivative. For this 'simple' example it is\n    // the derivative of z_{n-1} (T, x) respect to x of the\n    a0vector w(n_), dw(n_);\n    for(size_t i = 0; i < n_; i++)\n    {   w[i] = 0.0;\n        if( i == n_ - 1 )\n            w[i] = 1.0;\n    }\n    dw = f.Reverse(1, w);\n    for(size_t j = 0; j < n_; j++)\n    {   double check = z1[n_ - 1] / x[j];\n        ok &= NearEqual(dw[j] , check, 100.*eps, 100.*eps);\n    }\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "test_more/deprecated/deprecated.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n// CPPAD_HAS_* defines\n# include <cppad/configure.hpp>\n\n// system include files used for I/O\n# include <iostream>\n\n// memory leak checker\n# include <cppad/utility/thread_alloc.hpp>\n\n// test runner\n# include <cppad/utility/test_boolofvoid.hpp>\n\nextern bool old_mat_mul(void);\nextern bool old_reciprocal(void);\nextern bool old_tan(void);\nextern bool old_usead_1(void);\nextern bool old_usead_2(void);\nextern bool omp_alloc(void);\nextern bool track_new_del(void);\nextern bool zdouble(void);\n\n// main program that runs all the tests\nint main(void)\n{   std::string group = \"test_more/deprecated\";\n    size_t      width = 20;\n    CppAD::test_boolofvoid Run(group, width);\n\n    // This line is used by test_one.sh\n\n    Run( old_mat_mul,     \"old_mat_mul\"    );\n    Run( old_reciprocal,  \"old_reciprocal\" );\n    Run( old_tan,         \"old_tan\"        );\n    Run( old_usead_1,     \"old_usead_1\"    );\n    Run( old_usead_2,     \"old_usead_2\"    );\n    Run( omp_alloc,       \"omp_alloc\"      );\n    Run( track_new_del,   \"track_new_del\"  );\n    Run( zdouble,         \"zdouble\"        );\n    //\n    // check for memory leak\n    bool memory_ok = CppAD::thread_alloc::free_all();\n    //\n    // print summary at end\n    bool ok = Run.summary(memory_ok);\n    //\n    return static_cast<int>( ! ok );\n}\n// END PROGRAM\n"
  },
  {
    "path": "test_more/deprecated/old_mat_mul.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n@begin old_mat_mul.cpp@@\n$spell\n    mul\n$$\n\n$section Old Matrix Multiply as a User Atomic Operation: Example and Test$$\n\n$head Deprecated 2013-05-27$$\nThis example has been deprecated;\nuse $cref atomic_two_mat_mul.cpp$$ instead.\n\n$children%\n    example/deprecated/old_mat_mul.hpp\n%$$\n$head Include File$$\nThis routine uses the include file old_mat_mul.hpp.\n\n$srcthisfile%0%// BEGIN C++%// END C++%1%$$\n\n$end\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n# include \"old_mat_mul.hpp\"\n\nbool old_mat_mul(void)\n{   bool ok = true;\n    using CppAD::AD;\n\n    // matrix sizes for this test\n    size_t nr_result = 2;\n    size_t n_middle  = 2;\n    size_t nc_result = 2;\n\n    // declare the AD<double> vectors ax and ay and X\n    size_t n = nr_result * n_middle + n_middle * nc_result;\n    size_t m = nr_result * nc_result;\n    CppAD::vector< AD<double> > X(4), ax(n), ay(m);\n    size_t i, j;\n    for(j = 0; j < X.size(); j++)\n        X[j] = (j + 1);\n\n    // X is the vector of independent variables\n    CppAD::Independent(X);\n    // left matrix\n    ax[0]  = X[0];  // left[0,0]   = x[0] = 1\n    ax[1]  = X[1];  // left[0,1]   = x[1] = 2\n    ax[2]  = 5.;    // left[1,0]   = 5\n    ax[3]  = 6.;    // left[1,1]   = 6\n    // right matrix\n    ax[4]  = X[2];  // right[0,0]  = x[2] = 3\n    ax[5]  = 7.;    // right[0,1]  = 7\n    ax[6]  = X[3];  // right[1,0]  = x[3] = 4\n    ax[7]  = 8.;    // right[1,1]  = 8\n    /*\n    [ x0 , x1 ] * [ x2 , 7 ] = [ x0*x2 + x1*x3 , x0*7 + x1*8 ]\n    [ 5  , 6 ]    [ x3 , 8 ]   [ 5*x2  + 6*x3  , 5*7 + 6*8 ]\n    */\n\n    // The call back routines need to know the dimensions of the matrices.\n    // Store information about the matrix multiply for this call to mat_mul.\n    call_info info;\n    info.nr_result = nr_result;\n    info.n_middle  = n_middle;\n    info.nc_result = nc_result;\n    // info.vx gets set by forward during call to mat_mul below\n    assert( info.vx.size() == 0 );\n    size_t id      = info_.size();\n    info_.push_back(info);\n\n    // user defined AD<double> version of matrix multiply\n    mat_mul(id, ax, ay);\n    //----------------------------------------------------------------------\n    // check AD<double>  results\n    ok &= ay[0] == (1*3 + 2*4); ok &= Variable( ay[0] );\n    ok &= ay[1] == (1*7 + 2*8); ok &= Variable( ay[1] );\n    ok &= ay[2] == (5*3 + 6*4); ok &= Variable( ay[2] );\n    ok &= ay[3] == (5*7 + 6*8); ok &= Parameter( ay[3] );\n    //----------------------------------------------------------------------\n    // use mat_mul to define a function g : X -> ay\n    CppAD::ADFun<double> G;\n    G.Dependent(X, ay);\n    // g(x) = [ x0*x2 + x1*x3 , x0*7 + x1*8 , 5*x2  + 6*x3  , 5*7 + 6*8 ]^T\n    //----------------------------------------------------------------------\n    // Test zero order forward mode evaluation of g(x)\n    CppAD::vector<double> x( X.size() ), y(m);\n    for(j = 0; j <  X.size() ; j++)\n        x[j] = double(j + 2);\n    y = G.Forward(0, x);\n    ok &= y[0] == x[0] * x[2] + x[1] * x[3];\n    ok &= y[1] == x[0] * 7.   + x[1] * 8.;\n    ok &= y[2] == 5. * x[2]   + 6. * x[3];\n    ok &= y[3] == 5. * 7.     + 6. * 8.;\n\n    //----------------------------------------------------------------------\n    // Test first order forward mode evaluation of g'(x) * [1, 2, 3, 4]^T\n    // g'(x) = [ x2, x3, x0, x1 ]\n    //         [ 7 ,  8,  0, 0  ]\n    //         [ 0 ,  0,  5, 6  ]\n    //         [ 0 ,  0,  0, 0  ]\n    CppAD::vector<double> dx( X.size() ), dy(m);\n    for(j = 0; j <  X.size() ; j++)\n        dx[j] = double(j + 1);\n    dy = G.Forward(1, dx);\n    ok &= dy[0] == 1. * x[2] + 2. * x[3] + 3. * x[0] + 4. * x[1];\n    ok &= dy[1] == 1. * 7.   + 2. * 8.   + 3. * 0.   + 4. * 0.;\n    ok &= dy[2] == 1. * 0.   + 2. * 0.   + 3. * 5.   + 4. * 6.;\n    ok &= dy[3] == 1. * 0.   + 2. * 0.   + 3. * 0.   + 4. * 0.;\n\n    //----------------------------------------------------------------------\n    // Test second order forward mode\n    // g_0^2 (x) = [ 0, 0, 1, 0 ], g_0^2 (x) * [1] = [3]\n    //             [ 0, 0, 0, 1 ]              [2]   [4]\n    //             [ 1, 0, 0, 0 ]              [3]   [1]\n    //             [ 0, 1, 0, 0 ]              [4]   [2]\n    CppAD::vector<double> ddx( X.size() ), ddy(m);\n    for(j = 0; j <  X.size() ; j++)\n        ddx[j] = 0.;\n    ddy = G.Forward(2, ddx);\n    // [1, 2, 3, 4] * g_0^2 (x) * [1, 2, 3, 4]^T = 1*3 + 2*4 + 3*1 + 4*2\n    ok &= 2. * ddy[0] == 1. * 3. + 2. * 4. + 3. * 1. + 4. * 2.;\n    // for i > 0, [1, 2, 3, 4] * g_i^2 (x) * [1, 2, 3, 4]^T = 0\n    ok &= ddy[1] == 0.;\n    ok &= ddy[2] == 0.;\n    ok &= ddy[3] == 0.;\n\n    //----------------------------------------------------------------------\n    // Test second order reverse mode\n    CppAD::vector<double> w(m), dw(2 *  X.size() );\n    for(i = 0; i < m; i++)\n        w[i] = 0.;\n    w[0] = 1.;\n    dw = G.Reverse(2, w);\n    // g_0'(x) = [ x2, x3, x0, x1 ]\n    ok &= dw[0*2 + 0] == x[2];\n    ok &= dw[1*2 + 0] == x[3];\n    ok &= dw[2*2 + 0] == x[0];\n    ok &= dw[3*2 + 0] == x[1];\n    // g_0'(x)   * [1, 2, 3, 4]  = 1 * x2 + 2 * x3 + 3 * x0 + 4 * x1\n    // g_0^2 (x) * [1, 2, 3, 4]  = [3, 4, 1, 2]\n    ok &= dw[0*2 + 1] == 3.;\n    ok &= dw[1*2 + 1] == 4.;\n    ok &= dw[2*2 + 1] == 1.;\n    ok &= dw[3*2 + 1] == 2.;\n\n    //----------------------------------------------------------------------\n    // Test forward and reverse Jacobian sparsity pattern\n    /*\n    [ x0 , x1 ] * [ x2 , 7 ] = [ x0*x2 + x1*x3 , x0*7 + x1*8 ]\n    [ 5  , 6 ]    [ x3 , 8 ]   [ 5*x2  + 6*x3  , 5*7 + 6*8 ]\n    so the sparsity pattern should be\n    s[0] = {0, 1, 2, 3}\n    s[1] = {0, 1}\n    s[2] = {2, 3}\n    s[3] = {}\n    */\n    CppAD::vector< std::set<size_t> > r( X.size() ), s(m);\n    for(j = 0; j <  X.size() ; j++)\n    {   assert( r[j].empty() );\n        r[j].insert(j);\n    }\n    s = G.ForSparseJac( X.size() , r);\n    for(j = 0; j <  X.size() ; j++)\n    {   // s[0] = {0, 1, 2, 3}\n        ok &= s[0].find(j) != s[0].end();\n        // s[1] = {0, 1}\n        if( j == 0 || j == 1 )\n            ok &= s[1].find(j) != s[1].end();\n        else\n            ok &= s[1].find(j) == s[1].end();\n        // s[2] = {2, 3}\n        if( j == 2 || j == 3 )\n            ok &= s[2].find(j) != s[2].end();\n        else\n            ok &= s[2].find(j) == s[2].end();\n    }\n    // s[3] == {}\n    ok &= s[3].empty();\n\n    //----------------------------------------------------------------------\n    // Test reverse Jacobian sparsity pattern\n    /*\n    [ x0 , x1 ] * [ x2 , 7 ] = [ x0*x2 + x1*x3 , x0*7 + x1*8 ]\n    [ 5  , 6 ]    [ x3 , 8 ]   [ 5*x2  + 6*x3  , 5*7 + 6*8 ]\n    so the sparsity pattern should be\n    r[0] = {0, 1, 2, 3}\n    r[1] = {0, 1}\n    r[2] = {2, 3}\n    r[3] = {}\n    */\n    for(i = 0; i <  m; i++)\n    {   s[i].clear();\n        s[i].insert(i);\n    }\n    r = G.RevSparseJac(m, s);\n    for(j = 0; j <  X.size() ; j++)\n    {   // r[0] = {0, 1, 2, 3}\n        ok &= r[0].find(j) != r[0].end();\n        // r[1] = {0, 1}\n        if( j == 0 || j == 1 )\n            ok &= r[1].find(j) != r[1].end();\n        else\n            ok &= r[1].find(j) == r[1].end();\n        // r[2] = {2, 3}\n        if( j == 2 || j == 3 )\n            ok &= r[2].find(j) != r[2].end();\n        else\n            ok &= r[2].find(j) == r[2].end();\n    }\n    // r[3] == {}\n    ok &= r[3].empty();\n\n    //----------------------------------------------------------------------\n    /* Test reverse Hessian sparsity pattern\n    g_0^2 (x) = [ 0, 0, 1, 0 ] and for i > 0, g_i^2 = 0\n                [ 0, 0, 0, 1 ]\n                [ 1, 0, 0, 0 ]\n                [ 0, 1, 0, 0 ]\n    so for the sparsity pattern for the first component of g is\n    h[0] = {2}\n    h[1] = {3}\n    h[2] = {0}\n    h[3] = {1}\n    */\n    CppAD::vector< std::set<size_t> > h( X.size() ), t(1);\n    t[0].clear();\n    t[0].insert(0);\n    h = G.RevSparseHes(X.size() , t);\n    size_t check[] = {2, 3, 0, 1};\n    for(j = 0; j <  X.size() ; j++)\n    {   // h[j] = { check[j] }\n        for(i = 0; i < n; i++)\n        {   if( i == check[j] )\n                ok &= h[j].find(i) != h[j].end();\n            else\n                ok &= h[j].find(i) == h[j].end();\n        }\n    }\n    t[0].clear();\n    for( j = 1; j < X.size(); j++)\n            t[0].insert(j);\n    h = G.RevSparseHes(X.size() , t);\n    for(j = 0; j <  X.size() ; j++)\n    {   // h[j] = { }\n        for(i = 0; i < X.size(); i++)\n            ok &= h[j].find(i) == h[j].end();\n    }\n\n    // --------------------------------------------------------------------\n    // Free temporary work space. (If there are future calls to\n    // old_mat_mul they would create new temporary work space.)\n    CppAD::user_atomic<double>::clear();\n    info_.clear();\n\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "test_more/deprecated/old_mat_mul.hpp",
    "content": "# ifndef CPPAD_TEST_MORE_DEPRECATED_OLD_MAT_MUL_HPP\n# define CPPAD_TEST_MORE_DEPRECATED_OLD_MAT_MUL_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n@begin old_mat_mul.hpp@@\n$spell\n    old_mat_mul.hpp\n    cppad\n    CppAD\n    namespace\n    struct\n    nr\n    nc\n    bool\n    vx\n    const\n    im\n    mj\n    ij\n    px\n    py\n    std\n    tx\n    ty\n    resize\n    nz\n    var\n    jac\n    Jacobian\n    hes\n    vy\n$$\n\n\n$section Define Matrix Multiply as a User Atomic Operation$$\n\n\n$head Syntax$$\nThis file is located in the $code example$$ directory.\nIt can be copied to the current working directory and included\nwith the syntax\n$codei%\n    # include \"old_mat_mul.hpp\"\n%$$\n\n$head Example$$\nThe file old_mat_mul.cpp contains an example use of\n$code old_mat_mul.hpp$$.\n\n$head Begin Source$$\n$srccode%cpp% */\n# include <cppad/cppad.hpp>      // Include CppAD definitions\nnamespace {                      // Begin empty namespace\n    using CppAD::vector;        // Let vector denote CppAD::vector\n/* %$$\n\n$head Extra Call Information$$\n$srccode%cpp% */\n    // Information we will attach to each mat_mul call\n    struct call_info {\n        size_t nr_result;\n        size_t n_middle;\n        size_t nc_result;\n        vector<bool>  vx;\n    };\n    vector<call_info> info_; // vector of call information\n\n    // number of orders for this operation (k + 1)\n    size_t n_order_ = 0;\n    // number of rows in the result matrix\n    size_t nr_result_ = 0;\n    // number of columns in left matrix and number of rows in right matrix\n    size_t n_middle_ = 0;\n    // number of columns in the result matrix\n    size_t nc_result_ = 0;\n    // which components of x are variables\n    vector<bool>* vx_ = nullptr;\n\n    // get the information corresponding to this call\n    void get_info(size_t id, size_t k, size_t n, size_t m)\n    {   n_order_   = k + 1;\n        nr_result_ = info_[id].nr_result;\n        n_middle_  = info_[id].n_middle;\n        nc_result_ = info_[id].nc_result;\n        vx_        = &(info_[id].vx);\n\n        assert(n == nr_result_ * n_middle_ + n_middle_ * nc_result_);\n        assert(m ==  nr_result_ * nc_result_);\n    }\n\n/* %$$\n$head Matrix Indexing$$\n$srccode%cpp% */\n    // Convert left matrix index pair and order to a single argument index\n    size_t left(size_t i, size_t j, size_t ell)\n    {   assert( i < nr_result_ );\n        assert( j < n_middle_ );\n        return (i * n_middle_ + j) * n_order_ + ell;\n    }\n    // Convert right matrix index pair and order to a single argument index\n    size_t right(size_t i, size_t j, size_t ell)\n    {   assert( i < n_middle_ );\n        assert( j < nc_result_ );\n        size_t offset = nr_result_ * n_middle_;\n        return (offset + i * nc_result_ + j) * n_order_ + ell;\n    }\n    // Convert result matrix index pair and order to a single result index\n    size_t result(size_t i, size_t j, size_t ell)\n    {   assert( i < nr_result_ );\n        assert( j < nc_result_ );\n        return (i * nc_result_ + j) * n_order_ + ell;\n    }\n/* %$$\n\n$head One Matrix Multiply$$\nForward mode matrix multiply left times right and sum into result:\n$srccode%cpp% */\n    void multiply_and_sum(\n        size_t                order_left ,\n        size_t                order_right,\n        const vector<double>&         tx ,\n        vector<double>&               ty )\n    {   size_t i, j;\n        size_t order_result = order_left + order_right;\n        for(i = 0; i < nr_result_; i++)\n        {   for(j = 0; j < nc_result_; j++)\n            {   double sum = 0.;\n                size_t middle, im_left, mj_right, ij_result;\n                for(middle = 0; middle < n_middle_; middle++)\n                {   im_left  = left(i, middle, order_left);\n                    mj_right = right(middle, j, order_right);\n                    sum     += tx[im_left] * tx[mj_right];\n                }\n                ij_result = result(i, j, order_result);\n                ty[ ij_result ] += sum;\n            }\n        }\n        return;\n    }\n/* %$$\n\n$head Reverse Partials One Order$$\nCompute reverse mode partials for one order and sum into px:\n$srccode%cpp% */\n    void reverse_multiply(\n        size_t                order_left ,\n        size_t                order_right,\n        const vector<double>&         tx ,\n        const vector<double>&         ty ,\n        vector<double>&               px ,\n        const vector<double>&         py )\n    {   size_t i, j;\n        size_t order_result = order_left + order_right;\n        for(i = 0; i < nr_result_; i++)\n        {   for(j = 0; j < nc_result_; j++)\n            {   size_t middle, im_left, mj_right, ij_result;\n                for(middle = 0; middle < n_middle_; middle++)\n                {   ij_result = result(i, j, order_result);\n                    im_left   = left(i, middle, order_left);\n                    mj_right  = right(middle, j, order_right);\n                    // sum       += tx[im_left]  * tx[mj_right];\n                    px[im_left]  += tx[mj_right] * py[ij_result];\n                    px[mj_right] += tx[im_left]  * py[ij_result];\n                }\n            }\n        }\n        return;\n    }\n/* %$$\n$head Set Union$$\n$srccode%cpp% */\n    using CppAD::set_union;\n/* %$$\n\n$head CppAD User Atomic Callback Functions$$\n$srccode%cpp% */\n    // ----------------------------------------------------------------------\n    // forward mode routine called by CppAD\n    bool mat_mul_forward(\n        size_t                   id ,\n        size_t                    k ,\n        size_t                    n ,\n        size_t                    m ,\n        const vector<bool>&      vx ,\n        vector<bool>&            vy ,\n        const vector<double>&    tx ,\n        vector<double>&          ty\n    )\n    {   size_t i, j, ell;\n        get_info(id, k, n, m);\n\n        // check if this is during the call to mat_mul(id, ax, ay)\n        if( vx.size() > 0 )\n        {   assert( k == 0 && vx.size() > 0 );\n\n            // store the vx information in info_\n            assert( vx_->size() == 0 );\n            info_[id].vx.resize(n);\n            for(j = 0; j < n; j++)\n                info_[id].vx[j] = vx[j];\n            assert( vx_->size() == n );\n\n            // now compute vy\n            for(i = 0; i < nr_result_; i++)\n            {   for(j = 0; j < nc_result_; j++)\n                {   // compute vy[ result(i, j, 0) ]\n                    bool   var = false;\n                    bool   nz_left, nz_right;\n                    size_t middle, im_left, mj_right, ij_result;\n                    for(middle = 0; middle < n_middle_; middle++)\n                    {   im_left  = left(i, middle, k);\n                        mj_right = right(middle, j, k);\n                        nz_left  = vx[im_left] || (tx[im_left] != 0.);\n                        nz_right = vx[mj_right] || (tx[mj_right]!= 0.);\n                        // if not multiplying by the constant zero\n                        if( nz_left & nz_right )\n                            var |= (vx[im_left] || vx[mj_right]);\n                    }\n                    ij_result     = result(i, j, k);\n                    vy[ij_result] = var;\n                }\n            }\n        }\n\n        // initialize result as zero\n        for(i = 0; i < nr_result_; i++)\n        {   for(j = 0; j < nc_result_; j++)\n                ty[ result(i, j, k) ] = 0.;\n        }\n        // sum the product of proper orders\n        for(ell = 0; ell <=k; ell++)\n            multiply_and_sum(ell, k-ell, tx, ty);\n\n        // All orders are implemented and there are no possible error\n        // conditions, so always return true.\n        return true;\n    }\n    // ----------------------------------------------------------------------\n    // reverse mode routine called by CppAD\n    bool mat_mul_reverse(\n        size_t                   id ,\n        size_t                    k ,\n        size_t                    n ,\n        size_t                    m ,\n        const vector<double>&    tx ,\n        const vector<double>&    ty ,\n        vector<double>&          px ,\n        const vector<double>&    py\n    )\n    {   get_info(id, k, n, m);\n\n        size_t ell = n * n_order_;\n        while(ell--)\n            px[ell] = 0.;\n\n        size_t order = n_order_;\n        while(order--)\n        {   // reverse sum the products for specified order\n            for(ell = 0; ell <=order; ell++)\n                reverse_multiply(ell, order-ell, tx, ty, px, py);\n        }\n\n        // All orders are implemented and there are no possible error\n        // conditions, so always return true.\n        return true;\n    }\n\n    // ----------------------------------------------------------------------\n    // forward Jacobian sparsity routine called by CppAD\n    bool mat_mul_for_jac_sparse(\n        size_t                               id ,\n        size_t                                n ,\n        size_t                                m ,\n        size_t                                p ,\n        const vector< std::set<size_t> >&     r ,\n        vector< std::set<size_t> >&           s )\n    {   size_t i, j, k, im_left, middle, mj_right, ij_result;\n        k = 0;\n        get_info(id, k, n, m);\n\n        for(i = 0; i < nr_result_; i++)\n        {   for(j = 0; j < nc_result_; j++)\n            {   ij_result = result(i, j, k);\n                s[ij_result].clear();\n                for(middle = 0; middle < n_middle_; middle++)\n                {   im_left   = left(i, middle, k);\n                    mj_right  = right(middle, j, k);\n\n                    // s[ij_result] = union( s[ij_result], r[im_left] )\n                    s[ij_result] = set_union(s[ij_result], r[im_left]);\n\n                    // s[ij_result] = union( s[ij_result], r[mj_right] )\n                    s[ij_result] = set_union(s[ij_result], r[mj_right]);\n                }\n            }\n        }\n        return true;\n    }\n    // ----------------------------------------------------------------------\n    // reverse Jacobian sparsity routine called by CppAD\n    bool mat_mul_rev_jac_sparse(\n        size_t                               id ,\n        size_t                                n ,\n        size_t                                m ,\n        size_t                                p ,\n        vector< std::set<size_t> >&           r ,\n        const vector< std::set<size_t> >&     s )\n    {   size_t i, j, k, im_left, middle, mj_right, ij_result;\n        k = 0;\n        get_info(id, k, n, m);\n\n        for(j = 0; j < n; j++)\n            r[j].clear();\n\n        for(i = 0; i < nr_result_; i++)\n        {   for(j = 0; j < nc_result_; j++)\n            {   ij_result = result(i, j, k);\n                for(middle = 0; middle < n_middle_; middle++)\n                {   im_left   = left(i, middle, k);\n                    mj_right  = right(middle, j, k);\n\n                    // r[im_left] = union( r[im_left], s[ij_result] )\n                    r[im_left] = set_union(r[im_left], s[ij_result]);\n\n                    // r[mj_right] = union( r[mj_right], s[ij_result] )\n                    r[mj_right] = set_union(r[mj_right], s[ij_result]);\n                }\n            }\n        }\n        return true;\n    }\n    // ----------------------------------------------------------------------\n    // reverse Hessian sparsity routine called by CppAD\n    bool mat_mul_rev_hes_sparse(\n        size_t                               id ,\n        size_t                                n ,\n        size_t                                m ,\n        size_t                                p ,\n        const vector< std::set<size_t> >&     r ,\n        const vector<bool>&                   s ,\n        vector<bool>&                         t ,\n        const vector< std::set<size_t> >&     u ,\n        vector< std::set<size_t> >&           v )\n    {   size_t i, j, k, im_left, middle, mj_right, ij_result;\n        k = 0;\n        get_info(id, k, n, m);\n\n        for(j = 0; j < n; j++)\n        {   t[j] = false;\n            v[j].clear();\n        }\n\n        assert( vx_->size() == n );\n        for(i = 0; i < nr_result_; i++)\n        {   for(j = 0; j < nc_result_; j++)\n            {   ij_result = result(i, j, k);\n                for(middle = 0; middle < n_middle_; middle++)\n                {   im_left   = left(i, middle, k);\n                    mj_right  = right(middle, j, k);\n\n                    // back propagate Jacobian sparsity\n                    t[im_left]   = (t[im_left] || s[ij_result]);\n                    t[mj_right]  = (t[mj_right] || s[ij_result]);\n                    // Visual Studio C++ 2008 warns unsafe mix of int and\n                    // bool if we use the following code directly above:\n                    // t[im_left]  |= s[ij_result];\n                    // t[mj_right] |= s[ij_result];\n\n                    // back propagate Hessian sparsity\n                    // v[im_left]  = union( v[im_left],  u[ij_result] )\n                    // v[mj_right] = union( v[mj_right], u[ij_result] )\n                    v[im_left] = set_union(v[im_left],  u[ij_result] );\n                    v[mj_right] = set_union(v[mj_right], u[ij_result] );\n\n                    // Check for case where the (i,j) result element\n                    // is in reverse Jacobian and both left and right\n                    // operands in multiplication are variables\n                    if(s[ij_result] && (*vx_)[im_left] && (*vx_)[mj_right])\n                    {   // v[im_left] = union( v[im_left], r[mj_right] )\n                        v[im_left] = set_union(v[im_left], r[mj_right] );\n                        // v[mj_right] = union( v[mj_right], r[im_left] )\n                        v[mj_right] = set_union(v[mj_right], r[im_left] );\n                    }\n                }\n            }\n        }\n        return true;\n    }\n/* %$$\n\n$head Declare mat_mul Function$$\nDeclare the $code AD<double>$$ routine $codei%mat_mul(%id%, %ax%, %ay%)%$$\nand end empty namespace\n(we could use any $cref/simple vector template class/SimpleVector/$$\ninstead of $code CppAD::vector$$):\n$srccode%cpp% */\n    CPPAD_USER_ATOMIC(\n        mat_mul                 ,\n        CppAD::vector           ,\n        double                  ,\n        mat_mul_forward         ,\n        mat_mul_reverse         ,\n        mat_mul_for_jac_sparse  ,\n        mat_mul_rev_jac_sparse  ,\n        mat_mul_rev_hes_sparse\n    )\n} // End empty namespace\n/* %$$\n$end\n*/\n\n# endif\n"
  },
  {
    "path": "test_more/deprecated/old_reciprocal.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n@begin old_reciprocal.cpp@@\n$section Old Atomic Operation Reciprocal: Example and Test$$\n\n$head Deprecated 2013-05-27$$\nThis example has been deprecated;\nsee $cref atomic_two_reciprocal.cpp$$ instead.\n\n$head Theory$$\nThe example below defines the atomic function\n$latex f : \\B{R}^n \\rightarrow \\B{R}^m$$ where\n$latex n = 1$$, $latex m = 1$$, and $latex f(x) = 1 / x$$.\n\n$srcthisfile%0%// BEGIN C++%// END C++%1%$$\n\n$end\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nnamespace { // Begin empty namespace\n    using CppAD::vector;\n    // ----------------------------------------------------------------------\n    // a utility to compute the union of two sets.\n    using CppAD::set_union;\n\n    // ----------------------------------------------------------------------\n    // forward mode routine called by CppAD\n    bool reciprocal_forward(\n        size_t                   id ,\n        size_t                    k ,\n        size_t                    n ,\n        size_t                    m ,\n        const vector<bool>&      vx ,\n        vector<bool>&            vy ,\n        const vector<double>&    tx ,\n        vector<double>&          ty\n    )\n    {   assert( id == 0 );\n        assert( n == 1 );\n        assert( m == 1 );\n        assert( k == 0 || vx.size() == 0 );\n        bool ok = false;\n        double f, fp, fpp;\n\n        // Must always define the case k = 0.\n        // Do not need case k if not using f.Forward(q, xp) for q >= k.\n        switch(k)\n        {   case 0:\n            // this case must  be implemented\n            if( vx.size() > 0 )\n                vy[0] = vx[0];\n            // y^0 = f( x^0 ) = 1 / x^0\n            ty[0] = 1. / tx[0];\n            ok    = true;\n            break;\n\n            case 1:\n            // needed if first order forward mode is used\n            assert( vx.size() == 0 );\n            // y^1 = f'( x^0 ) x^1\n            f     = ty[0];\n            fp    = - f / tx[0];\n            ty[1] = fp * tx[1];\n            ok    = true;\n            break;\n\n            case 2:\n            // needed if second order forward mode is used\n            assert( vx.size() == 0 );\n            // Y''(t) = X'(t)^\\R{T} f''[X(t)] X'(t) + f'[X(t)] X''(t)\n            // 2 y^2  = x^1 * f''( x^0 ) x^1 + 2 f'( x^0 ) x^2\n            f     = ty[0];\n            fp    = - f / tx[0];\n            fpp   = - 2.0 * fp / tx[0];\n            ty[2] = tx[1] * fpp * tx[1] / 2.0 + fp * tx[2];\n            ok    = true;\n            break;\n        }\n        return ok;\n    }\n    // ----------------------------------------------------------------------\n    // reverse mode routine called by CppAD\n    bool reciprocal_reverse(\n        size_t                   id ,\n        size_t                    k ,\n        size_t                    n ,\n        size_t                    m ,\n        const vector<double>&    tx ,\n        const vector<double>&    ty ,\n        vector<double>&          px ,\n        const vector<double>&    py\n    )\n    {   // Do not need case k if not using f.Reverse(k+1, w).\n        assert( id == 0 );\n        assert( n == 1 );\n        assert( m == 1 );\n        bool ok = false;\n\n        double f, fp, fpp, fppp;\n        switch(k)\n        {   case 0:\n            // needed if first order reverse mode is used\n            // reverse: F^0 ( tx ) = y^0 = f( x^0 )\n            f     = ty[0];\n            fp    = - f / tx[0];\n            px[0] = py[0] * fp;;\n            ok    = true;\n            break;\n\n            case 1:\n            // needed if second order reverse mode is used\n            // reverse: F^1 ( tx ) = y^1 = f'( x^0 ) x^1\n            f      = ty[0];\n            fp     = - f / tx[0];\n            fpp    = - 2.0 * fp / tx[0];\n            px[1]  = py[1] * fp;\n            px[0]  = py[1] * fpp * tx[1];\n            // reverse: F^0 ( tx ) = y^0 = f( x^0 );\n            px[0] += py[0] * fp;\n\n            ok     = true;\n            break;\n\n            case 2:\n            // needed if third order reverse mode is used\n            // reverse: F^2 ( tx ) = y^2 =\n            //            = x^1 * f''( x^0 ) x^1 / 2 + f'( x^0 ) x^2\n            f      = ty[0];\n            fp     = - f / tx[0];\n            fpp    = - 2.0 * fp / tx[0];\n            fppp   = - 3.0 * fpp / tx[0];\n            px[2]  = py[2] * fp;\n            px[1]  = py[2] * fpp * tx[1];\n            px[0]  = py[2] * tx[1] * fppp * tx[1] / 2.0 + fpp * tx[2];\n            // reverse: F^1 ( tx ) = y^1 = f'( x^0 ) x^1\n            px[1] += py[1] * fp;\n            px[0] += py[1] * fpp * tx[1];\n            // reverse: F^0 ( tx ) = y^0 = f( x^0 );\n            px[0] += py[0] * fp;\n\n            ok = true;\n            break;\n        }\n        return ok;\n    }\n    // ----------------------------------------------------------------------\n    // forward Jacobian sparsity routine called by CppAD\n    bool reciprocal_for_jac_sparse(\n        size_t                               id ,\n        size_t                                n ,\n        size_t                                m ,\n        size_t                                p ,\n        const vector< std::set<size_t> >&     r ,\n        vector< std::set<size_t> >&           s )\n    {   // Can just return false if not using f.ForSparseJac\n        assert( id == 0 );\n        assert( n == 1 );\n        assert( m == 1 );\n\n        // sparsity for S(x) = f'(x) * R is same as sparsity for R\n        s[0] = r[0];\n\n        return true;\n    }\n    // ----------------------------------------------------------------------\n    // reverse Jacobian sparsity routine called by CppAD\n    bool reciprocal_rev_jac_sparse(\n        size_t                               id ,\n        size_t                                n ,\n        size_t                                m ,\n        size_t                                p ,\n        vector< std::set<size_t> >&           r ,\n        const vector< std::set<size_t> >&     s )\n    {   // Can just return false if not using RevSparseJac.\n        assert( id == 0 );\n        assert( n == 1 );\n        assert( m == 1 );\n\n        // sparsity for R(x) = S * f'(x) is same as sparsity for S\n        for(size_t q = 0; q < p; q++)\n            r[q] = s[q];\n\n        return true;\n    }\n    // ----------------------------------------------------------------------\n    // reverse Hessian sparsity routine called by CppAD\n    bool reciprocal_rev_hes_sparse(\n        size_t                               id ,\n        size_t                                n ,\n        size_t                                m ,\n        size_t                                p ,\n        const vector< std::set<size_t> >&     r ,\n        const vector<bool>&                   s ,\n                  vector<bool>&                   t ,\n        const vector< std::set<size_t> >&     u ,\n                  vector< std::set<size_t> >&     v )\n    {   // Can just return false if not use RevSparseHes.\n        assert( id == 0 );\n        assert( n == 1 );\n        assert( m == 1 );\n\n        // sparsity for T(x) = S(x) * f'(x) is same as sparsity for S\n        t[0] = s[0];\n\n        // V(x) = [ f'(x)^T * g''(y) * f'(x) + g'(y) * f''(x) ] * R\n        // U(x) = g''(y) * f'(x) * R\n        // S(x) = g'(y)\n\n        // back propagate the sparsity for U because derivative of\n        // reciprocal may be non-zero\n        v[0] = u[0];\n\n        // convert forward Jacobian sparsity to Hessian sparsity\n        // because second derivative of reciprocal may be non-zero\n        if( s[0] )\n            v[0] = set_union(v[0], r[0] );\n\n\n        return true;\n    }\n    // ---------------------------------------------------------------------\n    // Declare the AD<double> routine reciprocal(id, ax, ay)\n    CPPAD_USER_ATOMIC(\n        reciprocal                 ,\n        CppAD::vector              ,\n        double                     ,\n        reciprocal_forward         ,\n        reciprocal_reverse         ,\n        reciprocal_for_jac_sparse  ,\n        reciprocal_rev_jac_sparse  ,\n        reciprocal_rev_hes_sparse\n    )\n} // End empty namespace\n\nbool old_reciprocal(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps = 10. * CppAD::numeric_limits<double>::epsilon();\n\n    // --------------------------------------------------------------------\n    // Create the function f(x)\n    //\n    // domain space vector\n    size_t n  = 1;\n    double  x0 = 0.5;\n    vector< AD<double> > ax(n);\n    ax[0]     = x0;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(ax);\n\n    // range space vector\n    size_t m = 1;\n    vector< AD<double> > ay(m);\n\n    // call atomic function and store reciprocal(x) in au[0]\n    vector< AD<double> > au(m);\n    size_t id = 0;           // not used\n    reciprocal(id, ax, au);  // u = 1 / x\n\n    // call atomic function and store reciprocal(u) in ay[0]\n    reciprocal(id, au, ay);  // y = 1 / u = x\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f;\n    f.Dependent (ax, ay);    // f(x) = x\n\n    // --------------------------------------------------------------------\n    // Check forward mode results\n    //\n    // check function value\n    double check = x0;\n    ok &= NearEqual( Value(ay[0]) , check,  eps, eps);\n\n    // check zero order forward mode\n    size_t q;\n    vector<double> x_q(n), y_q(m);\n    q      = 0;\n    x_q[0] = x0;\n    y_q    = f.Forward(q, x_q);\n    ok &= NearEqual(y_q[0] , check,  eps, eps);\n\n    // check first order forward mode\n    q      = 1;\n    x_q[0] = 1;\n    y_q    = f.Forward(q, x_q);\n    check  = 1.;\n    ok &= NearEqual(y_q[0] , check,  eps, eps);\n\n    // check second order forward mode\n    q      = 2;\n    x_q[0] = 0;\n    y_q    = f.Forward(q, x_q);\n    check  = 0.;\n    ok &= NearEqual(y_q[0] , check,  eps, eps);\n\n    // --------------------------------------------------------------------\n    // Check reverse mode results\n    //\n    // third order reverse mode\n    q     = 3;\n    vector<double> w(m), dw(n * q);\n    w[0]  = 1.;\n    dw    = f.Reverse(q, w);\n    check = 1.;\n    ok &= NearEqual(dw[0] , check,  eps, eps);\n    check = 0.;\n    ok &= NearEqual(dw[1] , check,  eps, eps);\n    ok &= NearEqual(dw[2] , check,  eps, eps);\n\n    // --------------------------------------------------------------------\n    // forward mode sparstiy pattern\n    size_t p = n;\n    CppAD::vectorBool r1(n * p), s1(m * p);\n    r1[0] = true;          // compute sparsity pattern for x[0]\n    s1    = f.ForSparseJac(p, r1);\n    ok  &= s1[0] == true;  // f[0] depends on x[0]\n\n    // --------------------------------------------------------------------\n    // reverse mode sparstiy pattern\n    q = m;\n    CppAD::vectorBool s2(q * m), r2(q * n);\n    s2[0] = true;          // compute sparsity pattern for f[0]\n    r2    = f.RevSparseJac(q, s2);\n    ok  &= r2[0] == true;  // f[0] depends on x[0]\n\n    // --------------------------------------------------------------------\n    // Hessian sparsity (using previous ForSparseJac call)\n    CppAD::vectorBool s3(m), h(p * n);\n    s3[0] = true;        // compute sparsity pattern for f[0]\n    h     = f.RevSparseHes(p, s3);\n    ok  &= h[0] == true; // second partial of f[0] w.r.t. x[0] may be non-zero\n\n    // -----------------------------------------------------------------\n    // Free all temporary work space associated with atomic_one objects.\n    // (If there are future calls to atomic functions, they will\n    // create new temporary work space.)\n    CppAD::user_atomic<double>::clear();\n\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "test_more/deprecated/old_tan.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n@begin old_tan.cpp@@\n$spell\n    Tanh\n$$\n\n$section Old Tan and Tanh as User Atomic Operations: Example and Test$$\n\n$head Deprecated 2013-05-27$$\nThis example has not deprecated;\nsee $cref atomic_two_tangent.cpp$$ instead.\n\n$head Theory$$\nThe code below uses the $cref tan_forward$$ and $cref tan_reverse$$\nto implement the tangent ($icode%id% == 0%$$) and hyperbolic tangent\n($icode%id% == 1%$$) functions as atomic function operations.\n\n$srcthisfile%0%// BEGIN C++%// END C++%1%$$\n\n$end\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nnamespace { // Begin empty namespace\n    using CppAD::vector;\n\n    // a utility to compute the union of two sets.\n    using CppAD::set_union;\n\n    // ----------------------------------------------------------------------\n    // forward mode routine called by CppAD\n    bool old_tan_forward(\n        size_t                   id ,\n        size_t                order ,\n        size_t                    n ,\n        size_t                    m ,\n        const vector<bool>&      vx ,\n        vector<bool>&           vzy ,\n        const vector<float>&     tx ,\n        vector<float>&          tzy\n    )\n    {\n        assert( id == 0 || id == 1 );\n        assert( n == 1 );\n        assert( m == 2 );\n        assert( tx.size() >= (order+1) * n );\n        assert( tzy.size() >= (order+1) * m );\n\n        size_t n_order = order + 1;\n        size_t j = order;\n        size_t k;\n\n        // check if this is during the call to old_tan(id, ax, ay)\n        if( vx.size() > 0 )\n        {   assert( vx.size() >= n );\n            assert( vzy.size() >= m );\n\n            // now setvzy\n            vzy[0] = vx[0];\n            vzy[1] = vx[0];\n        }\n\n        if( j == 0 )\n        {   // z^{(0)} = tan( x^{(0)} ) or tanh( x^{(0)} )\n            if( id == 0 )\n                tzy[0] = float( tan( tx[0] ) );\n            else\n                tzy[0] = float( tanh( tx[0] ) );\n\n            // y^{(0)} = z^{(0)} * z^{(0)}\n            tzy[n_order + 0] = tzy[0] * tzy[0];\n        }\n        else\n        {   float j_inv = 1.f / float(j);\n            if( id == 1 )\n                j_inv = - j_inv;\n\n            // z^{(j)} = x^{(j)} +- sum_{k=1}^j k x^{(k)} y^{(j-k)} / j\n            tzy[j] = tx[j];\n            for(k = 1; k <= j; k++)\n                tzy[j] += tx[k] * tzy[n_order + j-k] * float(k) * j_inv;\n\n            // y^{(j)} = sum_{k=0}^j z^{(k)} z^{(j-k)}\n            tzy[n_order + j] = 0.;\n            for(k = 0; k <= j; k++)\n                tzy[n_order + j] += tzy[k] * tzy[j-k];\n        }\n\n        // All orders are implemented and there are no possible errors\n        return true;\n    }\n    // ----------------------------------------------------------------------\n    // reverse mode routine called by CppAD\n    bool old_tan_reverse(\n        size_t                   id ,\n        size_t                order ,\n        size_t                    n ,\n        size_t                    m ,\n        const vector<float>&     tx ,\n        const vector<float>&    tzy ,\n        vector<float>&           px ,\n        const vector<float>&    pzy\n    )\n    {\n        assert( id == 0 || id == 1 );\n        assert( n == 1 );\n        assert( m == 2 );\n        assert( tx.size() >= (order+1) * n );\n        assert( tzy.size() >= (order+1) * m );\n        assert( px.size() >= (order+1) * n );\n        assert( pzy.size() >= (order+1) * m );\n\n        size_t n_order = order + 1;\n        size_t j, k;\n\n        // copy because partials w.r.t. y and z need to change\n        vector<float> qzy = pzy;\n\n        // initialize accumultion of reverse mode partials\n        for(k = 0; k < n_order; k++)\n            px[k] = 0.;\n\n        // eliminate positive orders\n        for(j = order; j > 0; j--)\n        {   float j_inv = 1.f / float(j);\n            if( id == 1 )\n                j_inv = - j_inv;\n\n            // H_{x^{(k)}} += delta(j-k) +- H_{z^{(j)} y^{(j-k)} * k / j\n            px[j] += qzy[j];\n            for(k = 1; k <= j; k++)\n                px[k] += qzy[j] * tzy[n_order + j-k] * float(k) * j_inv;\n\n            // H_{y^{j-k)} += +- H_{z^{(j)} x^{(k)} * k / j\n            for(k = 1; k <= j; k++)\n                qzy[n_order + j-k] += qzy[j] * tx[k] * float(k) * j_inv;\n\n            // H_{z^{(k)}} += H_{y^{(j-1)}} * z^{(j-k-1)} * 2.\n            for(k = 0; k < j; k++)\n                qzy[k] += qzy[n_order + j-1] * tzy[j-k-1] * 2.f;\n        }\n\n        // eliminate order zero\n        if( id == 0 )\n            px[0] += qzy[0] * (1.f + tzy[n_order + 0]);\n        else\n            px[0] += qzy[0] * (1.f - tzy[n_order + 0]);\n\n        return true;\n    }\n    // ----------------------------------------------------------------------\n    // forward Jacobian sparsity routine called by CppAD\n    bool old_tan_for_jac_sparse(\n        size_t                               id ,\n        size_t                                n ,\n        size_t                                m ,\n        size_t                                p ,\n        const vector< std::set<size_t> >&     r ,\n        vector< std::set<size_t> >&           s )\n    {\n        assert( n == 1 );\n        assert( m == 2 );\n        assert( id == 0 || id == 1 );\n        assert( r.size() >= n );\n        assert( s.size() >= m );\n\n        // sparsity for z and y are the same as for x\n        s[0] = r[0];\n        s[1] = r[0];\n\n        return true;\n    }\n    // ----------------------------------------------------------------------\n    // reverse Jacobian sparsity routine called by CppAD\n    bool old_tan_rev_jac_sparse(\n        size_t                               id ,\n        size_t                                n ,\n        size_t                                m ,\n        size_t                                p ,\n        vector< std::set<size_t> >&           r ,\n        const vector< std::set<size_t> >&     s )\n    {\n        assert( n == 1 );\n        assert( m == 2 );\n        assert( id == 0 || id == 1 );\n        assert( r.size() >= n );\n        assert( s.size() >= m );\n\n        // note that, if the users code only uses z, and not y,\n        // we could just set r[0] = s[0]\n        r[0] = set_union(s[0], s[1]);\n        return true;\n    }\n    // ----------------------------------------------------------------------\n    // reverse Hessian sparsity routine called by CppAD\n    bool old_tan_rev_hes_sparse(\n        size_t                               id ,\n        size_t                                n ,\n        size_t                                m ,\n        size_t                                p ,\n        const vector< std::set<size_t> >&     r ,\n        const vector<bool>&                   s ,\n        vector<bool>&                         t ,\n        const vector< std::set<size_t> >&     u ,\n        vector< std::set<size_t> >&           v )\n    {\n        assert( n == 1 );\n        assert( m == 2 );\n        assert( id == 0 || id == 1 );\n        assert( r.size() >= n );\n        assert( s.size() >= m );\n        assert( t.size() >= n );\n        assert( u.size() >= m );\n        assert( v.size() >= n );\n\n        // back propagate Jacobian sparsity. If users code only uses z,\n        // we could just set t[0] = s[0];\n        t[0] =  s[0] || s[1];\n\n        // back propagate Hessian sparsity, ...\n        v[0] = set_union(u[0], u[1]);\n\n        // convert forward Jacobian sparsity to Hessian sparsity\n        // because tan and tanh are nonlinear\n        if( t[0] )\n            v[0] = set_union(v[0], r[0]);\n\n        return true;\n    }\n    // ---------------------------------------------------------------------\n    // Declare the AD<float> routine old_tan(id, ax, ay)\n    CPPAD_USER_ATOMIC(\n        old_tan                 ,\n        CppAD::vector           ,\n        float                   ,\n        old_tan_forward         ,\n        old_tan_reverse         ,\n        old_tan_for_jac_sparse  ,\n        old_tan_rev_jac_sparse  ,\n        old_tan_rev_hes_sparse\n    )\n} // End empty namespace\n\nbool old_tan(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    float eps = 10.f * CppAD::numeric_limits<float>::epsilon();\n\n    // domain space vector\n    size_t n  = 1;\n    float  x0 = 0.5;\n    CppAD::vector< AD<float> > ax(n);\n    ax[0]     = x0;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(ax);\n\n    // range space vector\n    size_t m = 3;\n    CppAD::vector< AD<float> > af(m);\n\n    // temporary vector for old_tan computations\n    // (old_tan computes tan or tanh and its square)\n    CppAD::vector< AD<float> > az(2);\n\n    // call user tan function and store tan(x) in f[0] (ignore tan(x)^2)\n    size_t id = 0;\n    old_tan(id, ax, az);\n    af[0] = az[0];\n\n    // call user tanh function and store tanh(x) in f[1] (ignore tanh(x)^2)\n    id = 1;\n    old_tan(id, ax, az);\n    af[1] = az[0];\n\n    // put a constant in f[2] = tanh(1.) (for sparsity pattern testing)\n    CppAD::vector< AD<float> > one(1);\n    one[0] = 1.;\n    old_tan(id, one, az);\n    af[2] = az[0];\n\n    // create f: x -> f and stop tape recording\n    CppAD::ADFun<float> F;\n    F.Dependent(ax, af);\n\n    // check function value\n    float tan = std::tan(x0);\n    ok &= NearEqual(af[0] , tan,  eps, eps);\n    float tanh = std::tanh(x0);\n    ok &= NearEqual(af[1] , tanh,  eps, eps);\n\n    // check zero order forward\n    CppAD::vector<float> x(n), f(m);\n    x[0] = x0;\n    f    = F.Forward(0, x);\n    ok &= NearEqual(f[0] , tan,  eps, eps);\n    ok &= NearEqual(f[1] , tanh,  eps, eps);\n\n    // compute first partial of f w.r.t. x[0] using forward mode\n    CppAD::vector<float> dx(n), df(m);\n    dx[0] = 1.;\n    df    = F.Forward(1, dx);\n\n    // compute derivative of tan - tanh using reverse mode\n    CppAD::vector<float> w(m), dw(n);\n    w[0]  = 1.;\n    w[1]  = 1.;\n    w[2]  = 0.;\n    dw    = F.Reverse(1, w);\n\n    // tan'(x)   = 1 + tan(x)  * tan(x)\n    // tanh'(x)  = 1 - tanh(x) * tanh(x)\n    float tanp  = 1.f + tan * tan;\n    float tanhp = 1.f - tanh * tanh;\n    ok   &= NearEqual(df[0], tanp, eps, eps);\n    ok   &= NearEqual(df[1], tanhp, eps, eps);\n    ok   &= NearEqual(dw[0], w[0]*tanp + w[1]*tanhp, eps, eps);\n\n    // compute second partial of f w.r.t. x[0] using forward mode\n    CppAD::vector<float> ddx(n), ddf(m);\n    ddx[0] = 0.;\n    ddf    = F.Forward(2, ddx);\n\n    // compute second derivative of tan - tanh using reverse mode\n    CppAD::vector<float> ddw(2);\n    ddw   = F.Reverse(2, w);\n\n    // tan''(x)   = 2 *  tan(x) * tan'(x)\n    // tanh''(x)  = - 2 * tanh(x) * tanh'(x)\n    // Note that second order Taylor coefficient for u half the\n    // corresponding second derivative.\n    float two    = 2;\n    float tanpp  =   two * tan * tanp;\n    float tanhpp = - two * tanh * tanhp;\n    ok   &= NearEqual(two * ddf[0], tanpp, eps, eps);\n    ok   &= NearEqual(two * ddf[1], tanhpp, eps, eps);\n    ok   &= NearEqual(ddw[0], w[0]*tanp  + w[1]*tanhp , eps, eps);\n    ok   &= NearEqual(ddw[1], w[0]*tanpp + w[1]*tanhpp, eps, eps);\n\n    // Forward mode computation of sparsity pattern for F.\n    size_t p = n;\n    // user vectorBool because m and n are small\n    CppAD::vectorBool r1(p), s1(m * p);\n    r1[0] = true;            // propagate sparsity for x[0]\n    s1    = F.ForSparseJac(p, r1);\n    ok  &= (s1[0] == true);  // f[0] depends on x[0]\n    ok  &= (s1[1] == true);  // f[1] depends on x[0]\n    ok  &= (s1[2] == false); // f[2] does not depend on x[0]\n\n    // Reverse mode computation of sparsity pattern for F.\n    size_t q = m;\n    CppAD::vectorBool s2(q * m), r2(q * n);\n    // Sparsity pattern for identity matrix\n    size_t i, j;\n    for(i = 0; i < q; i++)\n    {   for(j = 0; j < m; j++)\n            s2[i * q + j] = (i == j);\n    }\n    r2   = F.RevSparseJac(q, s2);\n    ok  &= (r2[0] == true);  // f[0] depends on x[0]\n    ok  &= (r2[1] == true);  // f[1] depends on x[0]\n    ok  &= (r2[2] == false); // f[2] does not depend on x[0]\n\n    // Hessian sparsity for f[0]\n    CppAD::vectorBool s3(m), h(p * n);\n    s3[0] = true;\n    s3[1] = false;\n    s3[2] = false;\n    h    = F.RevSparseHes(p, s3);\n    ok  &= (h[0] == true);  // Hessian is non-zero\n\n    // Hessian sparsity for f[2]\n    s3[0] = false;\n    s3[2] = true;\n    h    = F.RevSparseHes(p, s3);\n    ok  &= (h[0] == false);  // Hessian is zero\n\n    // check tanh results for a large value of x\n    x[0]  = std::numeric_limits<float>::max() / two;\n    f     = F.Forward(0, x);\n    tanh  = 1.;\n    ok   &= NearEqual(f[1], tanh, eps, eps);\n    df    = F.Forward(1, dx);\n    tanhp = 0.;\n    ok   &= NearEqual(df[1], tanhp, eps, eps);\n\n    // --------------------------------------------------------------------\n    // Free all temporary work space associated with atomic_one objects.\n    // (If there are future calls to atomic functions, they will\n    // create new temporary work space.)\n    CppAD::user_atomic<float>::clear();\n\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "test_more/deprecated/old_usead_1.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n@begin old_usead_1.cpp@@\n$spell\n    checkpoint\n    var\n$$\n\n$section Using AD to Compute Atomic Function Derivatives$$\n\n$head Deprecated 2013-05-27$$\nThis example has been deprecated because it is easier to use the\n$cref/checkpoint/chkpoint_one/$$ class instead.\n\n$head Purpose$$\nConsider the case where an inner function is used repeatedly in the\ndefinition of an outer function.\nIn this case, it may reduce the number of variables\n$cref/size_var/fun_property/size_var/$$,\nand hence the required memory.\n\n$head Simple Case$$\nThis example is the same as old_reciprocal.cpp, except that it\nuses AD to compute the\nderivatives needed by an atomic function.\nThis is a simple example of an inner function, and hence not really\nuseful for the purpose above;\nsee old_usead_2.cpp for a more complete example.\n\n$srcthisfile%0%// BEGIN C++%// END C++%1%$$\n\n$end\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nnamespace { // Begin empty namespace\n    using CppAD::AD;\n    using CppAD::ADFun;\n    using CppAD::vector;\n\n    // ----------------------------------------------------------------------\n    // function that computes reciprocal\n    ADFun<double>* r_ptr_;\n    void create_r(void)\n    {   vector< AD<double> > ax(1), ay(1);\n        ax[0]  = 1;\n        CppAD::Independent(ax);\n        ay[0]  = 1.0 / ax[0];\n        r_ptr_ = new ADFun<double>(ax, ay);\n    }\n    void destroy_r(void)\n    {   delete r_ptr_;\n        r_ptr_ = nullptr;\n    }\n\n    // ----------------------------------------------------------------------\n    // forward mode routine called by CppAD\n    bool reciprocal_forward(\n        size_t                   id ,\n        size_t                    k ,\n        size_t                    n ,\n        size_t                    m ,\n        const vector<bool>&      vx ,\n        vector<bool>&            vy ,\n        const vector<double>&    tx ,\n        vector<double>&          ty\n    )\n    {   assert( id == 0 );\n        assert( n == 1 );\n        assert( m == 1 );\n        assert( k == 0 || vx.size() == 0 );\n        bool ok = true;\n        vector<double> x_q(1), y_q(1);\n\n        // check for special case\n        if( vx.size() > 0 )\n            vy[0] = vx[0];\n\n        // make sure r_ has proper lower order Taylor coefficients stored\n        // then compute ty[k]\n        for(size_t q = 0; q <= k; q++)\n        {   x_q[0] = tx[q];\n            y_q    = r_ptr_->Forward(q, x_q);\n            if( q == k )\n                ty[k] = y_q[0];\n            assert( q == k || ty[q] == y_q[0] );\n        }\n        return ok;\n    }\n    // ----------------------------------------------------------------------\n    // reverse mode routine called by CppAD\n    bool reciprocal_reverse(\n        size_t                   id ,\n        size_t                    k ,\n        size_t                    n ,\n        size_t                    m ,\n        const vector<double>&    tx ,\n        const vector<double>&    ty ,\n        vector<double>&          px ,\n        const vector<double>&    py\n    )\n    {   assert( id == 0 );\n        assert( n == 1 );\n        assert( m == 1 );\n        bool ok = true;\n        vector<double> x_q(1), w(k+1), dw(k+1);\n\n        // make sure r_ has proper forward mode coefficients\n        size_t q;\n        for(q = 0; q <= k; q++)\n        {   x_q[0] = tx[q];\n# ifdef NDEBUG\n            r_ptr_->Forward(q, x_q);\n# else\n            vector<double> y_q(1);\n            y_q    = r_ptr_->Forward(q, x_q);\n            assert( ty[q] == y_q[0] );\n# endif\n        }\n        for(q = 0; q <=k; q++)\n            w[q] = py[q];\n        dw = r_ptr_->Reverse(k+1, w);\n        for(q = 0; q <=k; q++)\n            px[q] = dw[q];\n\n        return ok;\n    }\n    // ----------------------------------------------------------------------\n    // forward Jacobian sparsity routine called by CppAD\n    bool reciprocal_for_jac_sparse(\n        size_t                               id ,\n        size_t                                n ,\n        size_t                                m ,\n        size_t                                p ,\n        const vector< std::set<size_t> >&     r ,\n        vector< std::set<size_t> >&           s )\n    {   assert( id == 0 );\n        assert( n == 1 );\n        assert( m == 1 );\n        bool ok = true;\n\n        vector< std::set<size_t> > R(1), S(1);\n        R[0] = r[0];\n        S = r_ptr_->ForSparseJac(p, R);\n        s[0] = S[0];\n\n        return ok;\n    }\n    // ----------------------------------------------------------------------\n    // reverse Jacobian sparsity routine called by CppAD\n    bool reciprocal_rev_jac_sparse(\n        size_t                               id ,\n        size_t                                n ,\n        size_t                                m ,\n        size_t                                p ,\n        vector< std::set<size_t> >&           r ,\n        const vector< std::set<size_t> >&     s )\n    {\n        assert( id == 0 );\n        assert( n == 1 );\n        assert( m == 1 );\n        bool ok = true;\n\n        vector< std::set<size_t> > R(p), S(p);\n        size_t q;\n        for(q = 0; q < p; q++)\n            S[q] = s[q];\n        R = r_ptr_->RevSparseJac(p, S);\n        for(q = 0; q < p; q++)\n            r[q] = R[q];\n\n        return ok;\n    }\n    // ----------------------------------------------------------------------\n    // reverse Hessian sparsity routine called by CppAD\n    bool reciprocal_rev_hes_sparse(\n        size_t                               id ,\n        size_t                                n ,\n        size_t                                m ,\n        size_t                                p ,\n        const vector< std::set<size_t> >&     r ,\n        const vector<bool>&                   s ,\n        vector<bool>&                         t ,\n        const vector< std::set<size_t> >&     u ,\n        vector< std::set<size_t> >&           v )\n    {   // Can just return false if not use RevSparseHes.\n        assert( id == 0 );\n        assert( n == 1 );\n        assert( m == 1 );\n        bool ok = true;\n\n        // compute sparsity pattern for T(x) = S(x) * f'(x)\n        vector<bool> T(1), S(1);\n        S[0]   = s[0];\n        T      = r_ptr_->RevSparseJac(1, S);\n        t[0]   = T[0];\n\n        // compute sparsity pattern for A(x) = U(x)^T * f'(x)\n        vector<bool> Ut(p), A(p);\n        size_t q;\n        for(q = 0; q < p; q++)\n            Ut[q] = false;\n        std::set<size_t>::const_iterator itr;\n        for(itr = u[0].begin(); itr != u[0].end(); itr++)\n            Ut[*itr] = true;\n        A = r_ptr_-> RevSparseJac(p, Ut);\n\n        // compute sparsity pattern for H(x) = R^T * (S * F)''(x)\n        vector<bool> H(p), R(n);\n        for(q = 0; q < p; q++)\n            R[q] = false;\n        for(itr = r[0].begin(); itr != r[0].end(); itr++)\n            R[*itr] = true;\n        r_ptr_->ForSparseJac(p, R);\n        H = r_ptr_->RevSparseHes(p, S);\n\n        // compute sparsity pattern for V(x) = A(x)^T + H(x)^T\n        v[0].clear();\n        for(q = 0; q < p; q++)\n            if( A[q] || H[q] )\n                v[0].insert(q);\n\n        return ok;\n    }\n    // ---------------------------------------------------------------------\n    // Declare the AD<double> routine reciprocal(id, ax, ay)\n    CPPAD_USER_ATOMIC(\n        reciprocal                 ,\n        CppAD::vector              ,\n        double                     ,\n        reciprocal_forward         ,\n        reciprocal_reverse         ,\n        reciprocal_for_jac_sparse  ,\n        reciprocal_rev_jac_sparse  ,\n        reciprocal_rev_hes_sparse\n    )\n} // End empty namespace\n\nbool old_usead_1(void)\n{   bool ok = true;\n    using CppAD::NearEqual;\n    double eps = 10. * CppAD::numeric_limits<double>::epsilon();\n\n    // --------------------------------------------------------------------\n    // Create the ADFun<double> r_\n    create_r();\n\n    // --------------------------------------------------------------------\n    // Create the function f(x)\n    //\n    // domain space vector\n    size_t n  = 1;\n    double  x0 = 0.5;\n    vector< AD<double> > ax(n);\n    ax[0]     = x0;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(ax);\n\n    // range space vector\n    size_t m = 1;\n    vector< AD<double> > ay(m);\n\n    // call atomic function and store reciprocal(x) in au[0]\n    vector< AD<double> > au(m);\n    size_t id = 0;           // not used\n    reciprocal(id, ax, au);  // u = 1 / x\n\n    // call atomic function and store reciprocal(u) in ay[0]\n    reciprocal(id, au, ay);  // y = 1 / u = x\n\n    // create f: x -> y and stop tape recording\n    ADFun<double> f;\n    f.Dependent(ax, ay);     // f(x) = x\n\n    // --------------------------------------------------------------------\n    // Check function value results\n    //\n    // check function value\n    double check = x0;\n    ok &= NearEqual( Value(ay[0]) , check,  eps, eps);\n\n    // check zero order forward mode\n    size_t q;\n    vector<double> x_q(n), y_q(m);\n    q      = 0;\n    x_q[0] = x0;\n    y_q    = f.Forward(q, x_q);\n    ok &= NearEqual(y_q[0] , check,  eps, eps);\n\n    // check first order forward mode\n    q      = 1;\n    x_q[0] = 1;\n    y_q    = f.Forward(q, x_q);\n    check  = 1.;\n    ok &= NearEqual(y_q[0] , check,  eps, eps);\n\n    // check second order forward mode\n    q      = 2;\n    x_q[0] = 0;\n    y_q    = f.Forward(q, x_q);\n    check  = 0.;\n    ok &= NearEqual(y_q[0] , check,  eps, eps);\n\n    // --------------------------------------------------------------------\n    // Check reverse mode results\n    //\n    // third order reverse mode\n    q     = 3;\n    vector<double> w(m), dw(n * q);\n    w[0]  = 1.;\n    dw    = f.Reverse(q, w);\n    check = 1.;\n    ok &= NearEqual(dw[0] , check,  eps, eps);\n    check = 0.;\n    ok &= NearEqual(dw[1] , check,  eps, eps);\n    ok &= NearEqual(dw[2] , check,  eps, eps);\n\n    // --------------------------------------------------------------------\n    // forward mode sparstiy pattern\n    size_t p = n;\n    CppAD::vectorBool r1(n * p), s1(m * p);\n    r1[0] = true;          // compute sparsity pattern for x[0]\n    s1    = f.ForSparseJac(p, r1);\n    ok  &= s1[0] == true;  // f[0] depends on x[0]\n\n    // --------------------------------------------------------------------\n    // reverse mode sparstiy pattern\n    q = m;\n    CppAD::vectorBool s2(q * m), r2(q * n);\n    s2[0] = true;          // compute sparsity pattern for f[0]\n    r2    = f.RevSparseJac(q, s2);\n    ok  &= r2[0] == true;  // f[0] depends on x[0]\n\n    // --------------------------------------------------------------------\n    // Hessian sparsity (using previous ForSparseJac call)\n    CppAD::vectorBool s3(m), h(p * n);\n    s3[0] = true;        // compute sparsity pattern for f[0]\n    h     = f.RevSparseJac(p, s3);\n    ok  &= h[0] == true; // second partial of f[0] w.r.t. x[0] may be non-zero\n\n    // -----------------------------------------------------------------\n    // Free all memory associated with the object r_ptr\n    destroy_r();\n\n    // -----------------------------------------------------------------\n    // Free all temporary work space associated with atomic_one objects.\n    // (If there are future calls to atomic functions, they will\n    // create new temporary work space.)\n    CppAD::user_atomic<double>::clear();\n\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "test_more/deprecated/old_usead_2.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n@begin old_usead_2.cpp@@\n$spell\n    checkpoint\n    var\n$$\n\n$section Using AD to Compute Atomic Function Derivatives$$\n\n\n$head Deprecated 2013-05-27$$\nThis example has been deprecated because it is easier to use the\n$cref/checkpoint/chkpoint_one/$$ class instead.\n\n$head Purpose$$\nConsider the case where an inner function is used repeatedly in the\ndefinition of an outer function.\nIn this case, it may reduce the number of variables\n$cref/size_var/fun_property/size_var/$$,\nand hence the required memory.\n\n$srcthisfile%0%// BEGIN C++%// END C++%1%$$\n\n$end\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nnamespace { // Begin empty namespace\n    using CppAD::AD;\n    using CppAD::ADFun;\n    using CppAD::vector;\n\n    // ----------------------------------------------------------------------\n    // ODE for [t, t^2 / 2 ] in form required by Runge45\n    class Fun {\n    public:\n        void Ode(\n            const AD<double>           &t,\n            const vector< AD<double> > &z,\n            vector< AD<double> >       &f)\n        {   assert( z.size() == 2 );\n            assert( f.size() == 2 );\n            f[0] =  1.0;\n            f[1] =  z[0];\n        }\n    };\n\n    // ----------------------------------------------------------------------\n    // Create function that takes on Runge45 step for the ODE above\n    ADFun<double>* r_ptr_;\n    void create_r(void)\n    {   size_t n = 3, m = 2;\n        vector< AD<double> > x(n), zi(m), y(m), e(m);\n        // The value of x does not matter because the operation sequence\n        // does not depend on x.\n        x[0]  = 0.0;  // initial value z_0 (t) at t = ti\n        x[1]  = 0.0;  // initial value z_1 (t) at t = ti\n        x[2]  = 0.1;  // final time for this integration\n        CppAD::Independent(x);\n        zi[0]         = x[0];  // z_0 (t) at t = ti\n        zi[1]         = x[1];  // z_1 (t) at t = ti\n        AD<double> ti = 0.0;   // t does not appear in ODE so does not matter\n        AD<double> tf = x[2];  // final time\n        size_t M      = 3;     // number of Runge45 steps to take\n        Fun F;\n        y             = CppAD::Runge45(F, M, ti, tf, zi, e);\n        r_ptr_        = new ADFun<double>(x, y);\n    }\n    void destroy_r(void)\n    {   delete r_ptr_;\n        r_ptr_ = nullptr;\n    }\n\n    // ----------------------------------------------------------------------\n    // forward mode routine called by CppAD\n    bool solve_ode_forward(\n        size_t                   id ,\n        size_t                    k ,\n        size_t                    n ,\n        size_t                    m ,\n        const vector<bool>&      vx ,\n        vector<bool>&            vy ,\n        const vector<double>&    tx ,\n        vector<double>&          ty\n    )\n    {   assert( id == 0 );\n        assert( n == 3 );\n        assert( m == 2 );\n        assert( k == 0 || vx.size() == 0 );\n        bool ok = true;\n        vector<double> xp(n), yp(m);\n        size_t i, j;\n\n        // check for special case\n        if( vx.size() > 0 )\n        {   //Compute r, a Jacobian sparsity pattern.\n            // Use reverse mode because m < n.\n            vector< std::set<size_t> > s(m), r(m);\n            for(i = 0; i < m; i++)\n                s[i].insert(i);\n            r = r_ptr_->RevSparseJac(m, s);\n            std::set<size_t>::const_iterator itr;\n            for(i = 0; i < m; i++)\n            {   vy[i] = false;\n                for(itr = s[i].begin(); itr != s[i].end(); itr++)\n                {   j = *itr;\n                    assert( j < n );\n                    // y[i] depends on the value of x[j]\n                    // Visual Studio 2013 generates warning without bool below\n                    vy[i] |= bool( vx[j] );\n                }\n            }\n        }\n        // make sure r_ has proper lower order Taylor coefficients stored\n        // then compute ty[k]\n        for(size_t q = 0; q <= k; q++)\n        {   for(j = 0; j < n; j++)\n                xp[j] = tx[j * (k+1) + q];\n            yp    = r_ptr_->Forward(q, xp);\n            if( q == k )\n            {   for(i = 0; i < m; i++)\n                    ty[i * (k+1) + q] = yp[i];\n            }\n# ifndef NDEBUG\n            else\n            {   for(i = 0; i < m; i++)\n                    assert( ty[i * (k+1) + q] == yp[i] );\n            }\n# endif\n        }\n        // no longer need the Taylor coefficients in r_ptr_\n        // (have to reconstruct them every time)\n        r_ptr_->capacity_order(0);\n        return ok;\n    }\n    // ----------------------------------------------------------------------\n    // reverse mode routine called by CppAD\n    bool solve_ode_reverse(\n        size_t                   id ,\n        size_t                    k ,\n        size_t                    n ,\n        size_t                    m ,\n        const vector<double>&    tx ,\n        const vector<double>&    ty ,\n        vector<double>&          px ,\n        const vector<double>&    py\n    )\n    {   assert( id == 0 );\n        assert( n == 3 );\n        assert( m == 2 );\n        bool ok = true;\n        vector<double> xp(n), w( (k+1) * m ), dw( (k+1) * n );\n\n        // make sure r_ has proper forward mode coefficients\n        size_t i, j, q;\n        for(q = 0; q <= k; q++)\n        {   for(j = 0; j < n; j++)\n                xp[j] = tx[j * (k+1) + q];\n# ifdef NDEBUG\n            r_ptr_->Forward(q, xp);\n# else\n            vector<double> yp(m);\n            yp = r_ptr_->Forward(q, xp);\n            for(i = 0; i < m; i++)\n                assert( ty[i * (k+1) + q] == yp[i] );\n# endif\n        }\n        for(i = 0; i < m; i++)\n        {   for(q = 0; q <=k; q++)\n                w[ i * (k+1) + q] = py[ i * (k+1) + q];\n        }\n        dw = r_ptr_->Reverse(k+1, w);\n        for(j = 0; j < n; j++)\n        {   for(q = 0; q <=k; q++)\n                px[ j * (k+1) + q] = dw[ j * (k+1) + q];\n        }\n        // no longer need the Taylor coefficients in r_ptr_\n        // (have to reconstruct them every time)\n        r_ptr_->capacity_order(0);\n\n        return ok;\n    }\n    // ----------------------------------------------------------------------\n    // forward Jacobian sparsity routine called by CppAD\n    bool solve_ode_for_jac_sparse(\n        size_t                               id ,\n        size_t                                n ,\n        size_t                                m ,\n        size_t                                p ,\n        const vector< std::set<size_t> >&     r ,\n        vector< std::set<size_t> >&           s )\n    {   assert( id == 0 );\n        assert( n == 3 );\n        assert( m == 2 );\n        bool ok = true;\n\n        vector< std::set<size_t> > R(n), S(m);\n        for(size_t j = 0; j < n; j++)\n            R[j] = r[j];\n        S = r_ptr_->ForSparseJac(p, R);\n        for(size_t i = 0; i < m; i++)\n            s[i] = S[i];\n\n        // no longer need the forward mode sparsity pattern\n        // (have to reconstruct them every time)\n        r_ptr_->size_forward_set(0);\n\n        return ok;\n    }\n    // ----------------------------------------------------------------------\n    // reverse Jacobian sparsity routine called by CppAD\n    bool solve_ode_rev_jac_sparse(\n        size_t                               id ,\n        size_t                                n ,\n        size_t                                m ,\n        size_t                                p ,\n        vector< std::set<size_t> >&           r ,\n        const vector< std::set<size_t> >&     s )\n    {\n        assert( id == 0 );\n        assert( n == 3 );\n        assert( m == 2 );\n        bool ok = true;\n\n        vector< std::set<size_t> > R(p), S(p);\n        std::set<size_t>::const_iterator itr;\n        size_t i;\n        // untranspose s\n        for(i = 0; i < m; i++)\n        {   for(itr = s[i].begin(); itr != s[i].end(); itr++)\n                S[*itr].insert(i);\n        }\n        R = r_ptr_->RevSparseJac(p, S);\n        // transpose r\n        for(i = 0; i < m; i++)\n            r[i].clear();\n        for(i = 0; i < p; i++)\n        {   for(itr = R[i].begin(); itr != R[i].end(); itr++)\n                r[*itr].insert(i);\n        }\n        return ok;\n    }\n    // ----------------------------------------------------------------------\n    // reverse Hessian sparsity routine called by CppAD\n    bool solve_ode_rev_hes_sparse(\n        size_t                               id ,\n        size_t                                n ,\n        size_t                                m ,\n        size_t                                p ,\n        const vector< std::set<size_t> >&     r ,\n        const vector<bool>&                   s ,\n        vector<bool>&                         t ,\n        const vector< std::set<size_t> >&     u ,\n        vector< std::set<size_t> >&           v )\n    {   // Can just return false if not use RevSparseHes.\n        assert( id == 0 );\n        assert( n == 3 );\n        assert( m == 2 );\n        bool ok = true;\n        std::set<size_t>::const_iterator itr;\n\n        // compute sparsity pattern for T(x) = S(x) * f'(x)\n        vector< std::set<size_t> > S(1);\n        size_t i, j;\n        S[0].clear();\n        for(i = 0; i < m; i++)\n            if( s[i] )\n                S[0].insert(i);\n        t = r_ptr_->RevSparseJac(1, s);\n\n        // compute sparsity pattern for A(x)^T = U(x)^T * f'(x)\n        vector< std::set<size_t> > Ut(p), At(p);\n        for(i = 0; i < m; i++)\n        {   for(itr = u[i].begin(); itr != u[i].end(); itr++)\n                Ut[*itr].insert(i);\n        }\n        At = r_ptr_->RevSparseJac(p, Ut);\n\n        // compute sparsity pattern for H(x)^T = R^T * (S * F)''(x)\n        vector< std::set<size_t> > R(n), Ht(p);\n        for(j = 0; j < n; j++)\n            R[j] = r[j];\n        r_ptr_->ForSparseJac(p, R);\n        Ht = r_ptr_->RevSparseHes(p, S);\n\n        // compute sparsity pattern for V(x) = A(x) + H(x)^T\n        for(j = 0; j < n; j++)\n            v[j].clear();\n        for(i = 0; i < p; i++)\n        {   for(itr = At[i].begin(); itr != At[i].end(); itr++)\n                v[*itr].insert(i);\n            for(itr = Ht[i].begin(); itr != Ht[i].end(); itr++)\n                v[*itr].insert(i);\n        }\n\n        // no longer need the forward mode sparsity pattern\n        // (have to reconstruct them every time)\n        r_ptr_->size_forward_set(0);\n\n        return ok;\n    }\n    // ---------------------------------------------------------------------\n    // Declare the AD<double> routine solve_ode(id, ax, ay)\n    CPPAD_USER_ATOMIC(\n        solve_ode                 ,\n        CppAD::vector             ,\n        double                    ,\n        solve_ode_forward         ,\n        solve_ode_reverse         ,\n        solve_ode_for_jac_sparse  ,\n        solve_ode_rev_jac_sparse  ,\n        solve_ode_rev_hes_sparse\n    )\n} // End empty namespace\n\nbool old_usead_2(void)\n{   bool ok = true;\n    using CppAD::NearEqual;\n    double eps = 10. * CppAD::numeric_limits<double>::epsilon();\n\n    // --------------------------------------------------------------------\n    // Create the ADFun<double> r_\n    create_r();\n\n    // --------------------------------------------------------------------\n    // domain and range space vectors\n    size_t n = 3, m = 2;\n    vector< AD<double> > au(n), ax(n), ay(m);\n    au[0]         = 0.0;        // value of z_0 (t) = t, at t = 0\n    ax[1]         = 0.0;        // value of z_1 (t) = t^2/2, at t = 0\n    au[2]         = 1.0;        // final t\n    CppAD::Independent(au);\n    size_t M      = 2;          // number of r steps to take\n    ax[0]         = au[0];      // value of z_0 (t) = t, at t = 0\n    ax[1]         = au[1];      // value of z_1 (t) = t^2/2, at t = 0\n    AD<double> dt = au[2] / double(M);  // size of each r step\n    ax[2]         = dt;\n    for(size_t i_step = 0; i_step < M; i_step++)\n    {   size_t id = 0;               // not used\n        solve_ode(id, ax, ay);\n        ax[0] = ay[0];\n        ax[1] = ay[1];\n    }\n\n    // create f: u -> y and stop tape recording\n    // y_0(t) = u_0 + t                   = u_0 + u_2\n    // y_1(t) = u_1 + u_0 * t + t^2 / 2   = u_1 + u_0 * u_2 + u_2^2 / 2\n    // where t = u_2\n    ADFun<double> f;\n    f.Dependent(au, ay);\n\n    // --------------------------------------------------------------------\n    // Check forward mode results\n    //\n    // zero order forward\n    vector<double> up(n), yp(m);\n    size_t q  = 0;\n    double u0 = 0.5;\n    double u1 = 0.25;\n    double u2 = 0.75;\n    double check;\n    up[0]     = u0;\n    up[1]     = u1;\n    up[2]     = u2;\n    yp        = f.Forward(q, up);\n    check     = u0 + u2;\n    ok       &= NearEqual( yp[0], check,  eps, eps);\n    check     = u1 + u0 * u2 + u2 * u2 / 2.0;\n    ok       &= NearEqual( yp[1], check,  eps, eps);\n    //\n    // forward mode first derivative w.r.t t\n    q         = 1;\n    up[0]     = 0.0;\n    up[1]     = 0.0;\n    up[2]     = 1.0;\n    yp        = f.Forward(q, up);\n    check     = 1.0;\n    ok       &= NearEqual( yp[0], check,  eps, eps);\n    check     = u0 + u2;\n    ok       &= NearEqual( yp[1], check,  eps, eps);\n    //\n    // forward mode second order Taylor coefficient w.r.t t\n    q         = 2;\n    up[0]     = 0.0;\n    up[1]     = 0.0;\n    up[2]     = 0.0;\n    yp        = f.Forward(q, up);\n    check     = 0.0;\n    ok       &= NearEqual( yp[0], check,  eps, eps);\n    check     = 1.0 / 2.0;\n    ok       &= NearEqual( yp[1], check,  eps, eps);\n    // --------------------------------------------------------------------\n    // reverse mode derivatives of \\partial_t y_1 (t)\n    vector<double> w(m * q), dw(n * q);\n    w[0 * q + 0]  = 0.0;\n    w[1 * q + 0]  = 0.0;\n    w[0 * q + 1]  = 0.0;\n    w[1 * q + 1]  = 1.0;\n    dw        = f.Reverse(q, w);\n    // derivative of y_1(u) = u_1 + u_0 * u_2 + u_2^2 / 2,  w.r.t. u\n    // is equal deritative of \\partial_u2 y_1(u) w.r.t \\partial_u2 u\n    check     = u2;\n    ok       &= NearEqual( dw[0 * q + 1], check,  eps, eps);\n    check     = 1.0;\n    ok       &= NearEqual( dw[1 * q + 1], check,  eps, eps);\n    check     = u0 + u2;\n    ok       &= NearEqual( dw[2 * q + 1], check,  eps, eps);\n    // derivative of \\partial_t y_1 w.r.t u = u_0 + t,  w.r.t u\n    check     = 1.0;\n    ok       &= NearEqual( dw[0 * q + 0], check,  eps, eps);\n    check     = 0.0;\n    ok       &= NearEqual( dw[1 * q + 0], check,  eps, eps);\n    check     = 1.0;\n    ok       &= NearEqual( dw[2 * q + 0], check,  eps, eps);\n    // --------------------------------------------------------------------\n    // forward mode sparsity pattern for the Jacobian\n    // f_u = [   1, 0,   1 ]\n    //       [ u_2, 1, u_2 ]\n    size_t i, j, p = n;\n    CppAD::vectorBool r(n * p), s(m * p);\n    // r = identity sparsity pattern\n    for(i = 0; i < n; i++)\n        for(j = 0; j < p; j++)\n            r[i*n +j] = (i == j);\n    s   = f.ForSparseJac(p, r);\n    ok &= s[ 0 * p + 0] == true;\n    ok &= s[ 0 * p + 1] == false;\n    ok &= s[ 0 * p + 2] == true;\n    ok &= s[ 1 * p + 0] == true;\n    ok &= s[ 1 * p + 1] == true;\n    ok &= s[ 1 * p + 2] == true;\n    // --------------------------------------------------------------------\n    // reverse mode sparsity pattern for the Jacobian\n    q = m;\n    s.resize(q * m);\n    r.resize(q * n);\n    // s = identity sparsity pattern\n    for(i = 0; i < q; i++)\n        for(j = 0; j < m; j++)\n            s[i*m +j] = (i == j);\n    r   = f.RevSparseJac(q, s);\n    ok &= r[ 0 * n + 0] == true;\n    ok &= r[ 0 * n + 1] == false;\n    ok &= r[ 0 * n + 2] == true;\n    ok &= r[ 1 * n + 0] == true;\n    ok &= r[ 1 * n + 1] == true;\n    ok &= r[ 1 * n + 2] == true;\n\n    // --------------------------------------------------------------------\n    // Hessian sparsity for y_1 (u) = u_1 + u_0 * u_2 + u_2^2 / 2\n    s.resize(m);\n    s[0] = false;\n    s[1] = true;\n    r.resize(n * n);\n    for(i = 0; i < n; i++)\n        for(j = 0; j < n; j++)\n            r[ i * n + j ] = (i == j);\n    CppAD::vectorBool h(n * n);\n    h   = f.RevSparseHes(n, s);\n    ok &= h[0 * n + 0] == false;\n    ok &= h[0 * n + 1] == false;\n    ok &= h[0 * n + 2] == true;\n    ok &= h[1 * n + 0] == false;\n    ok &= h[1 * n + 1] == false;\n    ok &= h[1 * n + 2] == false;\n    ok &= h[2 * n + 0] == true;\n    ok &= h[2 * n + 1] == false;\n    ok &= h[2 * n + 2] == true;\n\n    // --------------------------------------------------------------------\n    destroy_r();\n\n    // Free all temporary work space associated with atomic_one objects.\n    // (If there are future calls to atomic functions, they will\n    // create new temporary work space.)\n    CppAD::user_atomic<double>::clear();\n\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "test_more/deprecated/omp_alloc.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n@begin omp_alloc.cpp@@\n$spell\n    openmp\n$$\n\n$section OpenMP Memory Allocator: Example and Test$$\n\n\n$head Deprecated 2011-08-31$$\nThis example is only intended to help convert calls to $cref omp_alloc$$\nto calls to $cref thread_alloc$$.\n\n$srcthisfile%0%// BEGIN C++%// END C++%1%$$\n\n$end\n*/\n// BEGIN C++\n# include <cppad/utility/omp_alloc.hpp>\n# include <cppad/utility/memory_leak.hpp>\n# include <vector>\n\nnamespace { // Begin empty namespace\n\nbool omp_alloc_bytes(void)\n{   bool ok = true;\n    using CppAD::omp_alloc;\n    size_t thread;\n\n    // check initial memory values\n    ok &= ! CppAD::memory_leak();\n\n    // amount of static memory used by thread zero\n    size_t static_inuse = omp_alloc::inuse(0);\n\n    // determine the currently executing thread\n    // (should be zero because not in parallel mode)\n    thread = omp_alloc::get_thread_num();\n\n    // repeatedly allocate enough memory for at least two size_t values.\n    size_t min_size_t = 2;\n    size_t min_bytes  = min_size_t * sizeof(size_t);\n    size_t n_outer   = 10;\n    size_t n_inner    = 5;\n    size_t cap_bytes(0), i, j, k;\n    for(i = 0; i < n_outer; i++)\n    {   // Do not use CppAD::vector here because its use of omp_alloc\n        // complicates the inuse and available results.\n        std::vector<void*> v_ptr(n_inner);\n        for( j = 0; j < n_inner; j++)\n        {   // allocate enough memory for min_size_t size_t objects\n            v_ptr[j]    = omp_alloc::get_memory(min_bytes, cap_bytes);\n            size_t* ptr = reinterpret_cast<size_t*>(v_ptr[j]);\n            // determine the number of size_t values we have obtained\n            size_t  cap_size_t = cap_bytes / sizeof(size_t);\n            ok                &= min_size_t <= cap_size_t;\n            // use placement new to call the size_t copy constructor\n            for(k = 0; k < cap_size_t; k++)\n                new(ptr + k) size_t(i + j + k);\n            // check that the constructor worked\n            for(k = 0; k < cap_size_t; k++)\n                ok &= ptr[k] == (i + j + k);\n        }\n        // check that n_inner * cap_bytes are inuse and none are available\n        ok &= omp_alloc::inuse(thread) == n_inner*cap_bytes + static_inuse;\n        ok &= omp_alloc::available(thread) == 0;\n        // return the memrory to omp_alloc\n        for(j = 0; j < n_inner; j++)\n            omp_alloc::return_memory(v_ptr[j]);\n        // check that now n_inner * cap_bytes are now available\n        // and none are in use\n        ok &= omp_alloc::inuse(thread) == static_inuse;\n        ok &= omp_alloc::available(thread) == n_inner * cap_bytes;\n    }\n    // return all the available memory to the system\n    omp_alloc::free_available(thread);\n    ok &= ! CppAD::memory_leak();\n\n    return ok;\n}\n\nclass my_char {\npublic:\n    char ch_ ;\n    my_char(void) : ch_(' ')\n    { }\n    my_char(const my_char& my_ch) : ch_(my_ch.ch_)\n    { }\n};\n\nbool omp_alloc_array(void)\n{   bool ok = true;\n    using CppAD::omp_alloc;\n    size_t i;\n\n    // check initial memory values\n    size_t thread = omp_alloc::get_thread_num();\n    ok &= thread == 0;\n    ok &= ! CppAD::memory_leak();\n    size_t static_inuse = omp_alloc::inuse(0);\n\n    // initial allocation of an array\n    size_t  size_min  = 3;\n    size_t  size_one;\n    my_char *array_one  =\n        omp_alloc::create_array<my_char>(size_min, size_one);\n\n    // check the values and change them to null 'x'\n    for(i = 0; i < size_one; i++)\n    {   ok &= array_one[i].ch_ == ' ';\n        array_one[i].ch_ = 'x';\n    }\n\n    // now create a longer array\n    size_t size_two;\n    my_char *array_two =\n        omp_alloc::create_array<my_char>(2 * size_min, size_two);\n\n    // check the values in array one\n    for(i = 0; i < size_one; i++)\n        ok &= array_one[i].ch_ == 'x';\n\n    // check the values in array two\n    for(i = 0; i < size_two; i++)\n        ok &= array_two[i].ch_ == ' ';\n\n    // check the amount of inuse and available memory\n    // (an extra size_t value is used for each memory block).\n    size_t check = static_inuse + sizeof(my_char)*(size_one + size_two);\n    ok   &= omp_alloc::inuse(thread) - check < sizeof(my_char);\n    ok   &= omp_alloc::available(thread) == 0;\n\n    // delete the arrays\n    omp_alloc::delete_array(array_one);\n    omp_alloc::delete_array(array_two);\n    ok   &= omp_alloc::inuse(thread) == static_inuse;\n    check = sizeof(my_char)*(size_one + size_two);\n    ok   &= omp_alloc::available(thread) - check < sizeof(my_char);\n\n    // free the memory for use by this thread\n    omp_alloc::free_available(thread);\n    ok &= ! CppAD::memory_leak();\n\n    return ok;\n}\n} // End empty namespace\n\nbool omp_alloc(void)\n{   bool ok  = true;\n    using CppAD::omp_alloc;\n\n    // check initial state of allocator\n    ok  &= omp_alloc::get_max_num_threads() == 1;\n\n    // set the maximum number of threads greater than one\n    // so that omp_alloc holds onto memory\n    CppAD::omp_alloc::set_max_num_threads(2);\n    ok  &= omp_alloc::get_max_num_threads() == 2;\n    ok  &= ! CppAD::memory_leak();\n\n    // now use memory allocator in state where it holds onto memory\n    ok   &= omp_alloc_bytes();\n    ok   &= omp_alloc_array();\n\n    // check that the tests have not held onto memory\n    ok  &= ! CppAD::memory_leak();\n\n    // set the maximum number of threads back to one\n    // so that omp_alloc no longer holds onto memory\n    CppAD::omp_alloc::set_max_num_threads(1);\n\n    return ok;\n}\n\n\n// END C++\n"
  },
  {
    "path": "test_more/deprecated/track_new_del.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n@begin TrackNewDel.cpp@@\n\n$section Tracking Use of New and Delete: Example and Test$$\n\n\n\n$srcthisfile%0%// BEGIN C++%// END C++%1%$$\n\n$end\n*/\n// BEGIN C++\n\n# include <cppad/utility/track_new_del.hpp>\n\nbool track_new_del(void)\n{   bool ok = true;\n\n    // initial count\n    size_t count = CPPAD_TRACK_COUNT();\n\n    // allocate an array of length 5\n    double *ptr = nullptr;\n    size_t  newlen = 5;\n    ptr = CPPAD_TRACK_NEW_VEC(newlen, ptr);\n\n    // copy data into the array\n    size_t ncopy = newlen;\n    size_t i;\n    for(i = 0; i < ncopy; i++)\n        ptr[i] = double(i);\n\n    // extend the buffer to be length 10\n    newlen = 10;\n    ptr    = CPPAD_TRACK_EXTEND(newlen, ncopy, ptr);\n\n    // copy data into the new part of the array\n    for(i = ncopy; i < newlen; i++)\n        ptr[i] = double(i);\n\n    // check the values in the array\n    for(i = 0; i < newlen; i++)\n        ok &= (ptr[i] == double(i));\n\n    // free the memory allocated since previous call to TrackCount\n    CPPAD_TRACK_DEL_VEC(ptr);\n\n    // check for memory leak\n    ok &= (count == CPPAD_TRACK_COUNT());\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "test_more/deprecated/zdouble.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n@begin zdouble.cpp@@\n$spell\n    zdouble\n$$\n\n$section zdouble: Example and Test$$\n\n$srcthisfile%0%// BEGIN C++%// END C++%1%$$\n\n$end\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nnamespace {\n    template <class Base> bool test_one(void)\n    {   bool ok = true;\n        Base eps99 = 99. * std::numeric_limits<double>::epsilon();\n\n        typedef CppAD::AD<Base>   a1type;\n        typedef CppAD::AD<a1type> a2type;\n\n        // value during taping\n        size_t n = 2;\n        CPPAD_TESTVECTOR(Base) x(n);\n        x[0] = 0.0;\n        x[1] = 0.0;\n\n        // declare independent variable\n        CPPAD_TESTVECTOR(a2type) a2x(n);\n        for (size_t j = 0; j < n; j++)\n            a2x[j] = a2type( a1type(x[j]) );\n        Independent(a2x);\n\n        // zero and one as a2type values\n        a2type a2zero = a2type(0.0);\n        a2type a2one  = a2type(1.0);\n\n        // h(x) = x[0] / x[1] if x[1] > x[0] else 1.0\n        a2type h_x = CondExpGt(a2x[1], a2x[0], a2x[0] / a2x[1], a2one);\n\n        // f(x) = h(x) if x[0] > 0.0 else 0.0\n        //      = x[0] / x[1] if x[1] > x[0]  and x[0] > 0.0\n        //      = 1.0         if x[0] >= x[1] and x[0] > 0.0\n        //      = 0.0         if x[0] <= 0.0\n        a2type f_x = CondExpGt(a2x[0], a2zero, h_x, a2one);\n\n        // define the function f(x)\n        size_t m = 1;\n        CPPAD_TESTVECTOR(a2type) a2y(m);\n        a2y[0] = f_x;\n        CppAD::ADFun<a1type> af1;\n        af1.Dependent(a2x, a2y);\n\n        // Define function g(x) = gradient of f(x)\n        CPPAD_TESTVECTOR(a1type) a1x(n), a1z(n), a1w(m);\n        for (size_t j = 0; j < n; j++)\n            a1x[j] = a1type(x[j]);\n        a1w[0] = a1type(1.0);\n        Independent(a1x);\n        af1.Forward(0, a1x);\n        a1z = af1.Reverse(1, a1w);\n        CppAD::ADFun<Base> g;\n        g.Dependent(a1x, a1z);\n\n        // check result for a case where f(x) = 0.0;\n        CPPAD_TESTVECTOR(Base) z(2);\n        x[0] = 0.0;\n        x[1] = 0.0;\n        z    = g.Forward(0, x);\n        ok &= z[0] == 0.0;\n        ok &= z[1] == 0.0;\n\n        // check result for a case where f(x) = 1.0;\n        x[0] = 1.0;\n        x[1] = 0.5;\n        z    = g.Forward(0, x);\n        ok &= z[0] == 0.0;\n        ok &= z[1] == 0.0;\n\n        // check result for a case where f(x) = x[0] / x[1];\n        x[0] = 1.0;\n        x[1] = 2.0;\n        z    = g.Forward(0, x);\n        ok &= CppAD::NearEqual(z[0], 1.0/x[1], eps99, eps99);\n        ok &= CppAD::NearEqual(z[1], - x[0]/(x[1]*x[1]), eps99, eps99);\n\n        return ok;\n    }\n    bool test_two(void)\n    {   bool ok = true;\n        using CppAD::zdouble;\n        //\n        zdouble eps = CppAD::numeric_limits<zdouble>::epsilon();\n        ok          &= eps == std::numeric_limits<double>::epsilon();\n        //\n        zdouble min = CppAD::numeric_limits<zdouble>::min();\n        ok          &= min == std::numeric_limits<double>::min();\n        //\n        zdouble max = CppAD::numeric_limits<zdouble>::max();\n        ok          &= max == std::numeric_limits<double>::max();\n        //\n        zdouble nan = CppAD::numeric_limits<zdouble>::quiet_NaN();\n        ok          &= nan != nan;\n        //\n        int digits10 = CppAD::numeric_limits<zdouble>::digits10;\n        ok          &= digits10 == std::numeric_limits<double>::digits10;\n        //\n        return ok;\n    }\n}\n\nbool zdouble(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    using CppAD::zdouble;\n    //\n    ok &= test_one<zdouble>();\n    ok &= test_one<double>();\n    //\n    ok &= test_two();\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "test_more/general/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# Build the test_more/general tests\n#\n# adolc_sources\nIF( cppad_has_adolc )\n    SET(adolc_sources base_adolc.cpp)\nELSE( cppad_has_adolc )\n    SET(adolc_sources \"\")\nENDIF( cppad_has_adolc )\n#\n# eigen_sources\nIF( cppad_has_eigen )\n    SET(eigen_sources cppad_eigen.cpp eigen_mat_inv.cpp)\nELSE( cppad_has_eigen )\n    SET(eigen_sources \"\")\nENDIF( cppad_has_eigen )\n#\n# ipopt_sourced\nIF( cppad_has_ipopt )\n    SET(ipopt_sources ipopt_solve.cpp)\nELSE( cppad_has_ipopt )\n    SET(ipopt_sources \"\")\nENDIF( cppad_has_ipopt )\n#\n# BEGIN_SORT_THIS_LINE_PLUS_5\nSET(source_list\n    ${adolc_sources}\n    ${eigen_sources}\n    ${ipopt_sources}\n    abs_normal.cpp\n    acos.cpp\n    acosh.cpp\n    add.cpp\n    add_eq.cpp\n    add_zero.cpp\n    adfun.cpp\n    asin.cpp\n    asinh.cpp\n    assign.cpp\n    atan.cpp\n    atan2.cpp\n    atanh.cpp\n    atomic_four.cpp\n    atomic_three.cpp\n    azmul.cpp\n    base2ad.cpp\n    base_alloc.cpp\n    base_complex.cpp\n    bool_sparsity.cpp\n    check_simple_vector.cpp\n    chkpoint_one.cpp\n    chkpoint_two.cpp\n    compare.cpp\n    compare_change.cpp\n    cond_exp.cpp\n    cond_exp_ad.cpp\n    cond_exp_rev.cpp\n    copy.cpp\n    cos.cpp\n    cosh.cpp\n    cpp_graph.cpp\n    cppad_vector.cpp\n    dbl_epsilon.cpp\n    dependency.cpp\n    div.cpp\n    div_eq.cpp\n    div_zero_one.cpp\n    erf.cpp\n    exp.cpp\n    expm1.cpp\n    extern_value.cpp\n    fabs.cpp\n    for_hes_sparsity.cpp\n    for_hess.cpp\n    for_jac_sparsity.cpp\n    forward.cpp\n    forward_dir.cpp\n    forward_order.cpp\n    from_base.cpp\n    fun_check.cpp\n    general.cpp\n    hes_sparsity.cpp\n    jacobian.cpp\n    json_graph.cpp\n    local/is_pod.cpp\n    local/json_lexer.cpp\n    local/json_parser.cpp\n    local/temp_file.cpp\n    local/vector_set.cpp\n    log.cpp\n    log10.cpp\n    log1p.cpp\n    mul.cpp\n    mul_cond_rev.cpp\n    mul_cskip.cpp\n    mul_eq.cpp\n    mul_level.cpp\n    mul_zdouble.cpp\n    mul_zero_one.cpp\n    near_equal_ext.cpp\n    neg.cpp\n    new_dynamic.cpp\n    num_limits.cpp\n    ode_err_control.cpp\n    optimize.cpp\n    parameter.cpp\n    poly.cpp\n    pow.cpp\n    pow_int.cpp\n    print_for.cpp\n    rev_sparse_jac.cpp\n    rev_two.cpp\n    reverse.cpp\n    romberg_one.cpp\n    rosen_34.cpp\n    runge_45.cpp\n    simple_vector.cpp\n    sin.cpp\n    sin_cos.cpp\n    sinh.cpp\n    sparse_hessian.cpp\n    sparse_jac_work.cpp\n    sparse_jacobian.cpp\n    sparse_sub_hes.cpp\n    sparse_vec_ad.cpp\n    sqrt.cpp\n    std_math.cpp\n    sub.cpp\n    sub_eq.cpp\n    sub_zero.cpp\n    subgraph_1.cpp\n    subgraph_2.cpp\n    subgraph_hes2jac.cpp\n    tan.cpp\n    to_csrc.cpp\n    to_string.cpp\n    value.cpp\n    vec_ad.cpp\n    vec_ad_par.cpp\n    vec_unary.cpp\n)\n# END_SORT_THIS_LINE_MINUS_2\nset_compile_flags( test_more_general \"${cppad_debug_which}\" \"${source_list}\" )\n#\nADD_EXECUTABLE(test_more_general EXCLUDE_FROM_ALL ${source_list})\n#\n# List of libraries to be linked into the specified target\nTARGET_LINK_LIBRARIES(test_more_general\n    ${cppad_lib}\n    ${adolc_LINK_LIBRARIES}\n    ${ipopt_LINK_LIBRARIES}\n    ${colpack_libs}\n)\n#\n# check_test_more_general\nadd_check_executable(check_test_more general)\n"
  },
  {
    "path": "test_more/general/abs_normal.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/cppad.hpp>\n\nnamespace { // BEGIN_EMPTY_NAMESPACE\n// join\nCPPAD_TESTVECTOR(double) join(\n    const CPPAD_TESTVECTOR(double)& x ,\n    const CPPAD_TESTVECTOR(double)& u )\n{   size_t n = x.size();\n    size_t s = u.size();\n    CPPAD_TESTVECTOR(double) xu(n + s);\n    for(size_t j = 0; j < n; j++)\n        xu[j] = x[j];\n    for(size_t j = 0; j < s; j++)\n        xu[n + j] = u[j];\n    return xu;\n}\n// test_pow\nbool test_pow(void)\n{   bool ok = true;\n    //\n    using CppAD::AD;\n    using CppAD::ADFun;\n    //\n    typedef CPPAD_TESTVECTOR(double)       d_vector;\n    typedef CPPAD_TESTVECTOR( AD<double> ) ad_vector;\n    //\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    //\n    size_t n = 2; // size of x\n    size_t m = 1; // size of y\n    size_t s = 1; // number of absolute value terms\n    //\n    // record the function f(x)\n    ad_vector ad_x(n), ad_y(m);\n    for(size_t j = 0; j < n; j++)\n        ad_x[j] = double(j + 1);\n    Independent( ad_x );\n    //\n    // for this example, we the function is\n    // f(x) = pow( |x_0|, x_1) + pow( |x_0| , 2) + pow(2, |x_0|)\n    AD<double> abs_x0 = abs( ad_x[0] );\n    AD<double> pow_vv = pow( abs_x0 , ad_x[1] );\n    AD<double> pow_vp = pow( abs_x0 , 2.0 );\n    AD<double> pow_pv = pow( 2.0 , abs_x0 );\n    ad_y[0] = pow_vv + pow_vp + pow_pv;\n    ADFun<double> f(ad_x, ad_y);\n\n    // create its abs_normal representation in g, a\n    ADFun<double> g, a;\n    f.abs_normal_fun(g, a);\n\n    // check dimension of domain and range space for g\n    ok &= g.Domain() == n + s;\n    ok &= g.Range()  == m + s;\n\n    // check dimension of domain and range space for a\n    ok &= a.Domain() == n;\n    ok &= a.Range()  == s;\n\n    // --------------------------------------------------------------------\n    // Choose a point x_hat\n    d_vector x_hat(n);\n    x_hat[0] = -2.0;\n    x_hat[1] = 2.0;\n\n    // value of a_hat = a(x_hat)\n    d_vector a_hat = a.Forward(0, x_hat);\n\n    // (x_hat, a_hat)\n    d_vector xu_hat = join(x_hat, a_hat);\n\n    // value of g[ x_hat, a_hat ]\n    d_vector g_hat = g.Forward(0, xu_hat);\n\n    // Jacobian of g[ x_hat, a_hat ]\n    d_vector g_jac = g.Jacobian(xu_hat);\n\n    // value of delta_x\n    d_vector delta_x(n);\n    delta_x[0] =  4.0;\n    delta_x[1] =  1.0;\n\n    // value of x\n    d_vector x(n);\n    for(size_t j = 0; j < n; j++)\n        x[j] = x_hat[j] + delta_x[j];\n\n    // value of f(x)\n    d_vector y = f.Forward(0, x);\n\n    // check\n    double check = std::pow( std::fabs(x[0]) , x[1]);\n    check       += std::pow( std::fabs(x[0]) , 2.0 );\n    check       += std::pow( 2.0, std::fabs(x[0]) );\n    ok          &= CppAD::NearEqual(y[0], check, eps99, eps99);\n\n    return ok;\n}\n} // END_EMPTY_NAMESPACE\n\nbool abs_normal(void)\n{   bool ok = true;\n    ok     &= test_pow();\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/acos.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\nOld acos examples now used just for valiadation testing\n*/\n# include <cppad/cppad.hpp>\n\nbool acos(void)\n{   bool ok = true;\n    using CppAD::acos;\n    using namespace CppAD;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // independent variable vector\n    CPPAD_TESTVECTOR(AD<double>) U(1);\n    U[0]     = .5;\n    Independent(U);\n\n    // a temporary values\n    AD<double> x = cos(U[0]);\n\n    // dependent variable vector\n    CPPAD_TESTVECTOR(AD<double>) Z(1);\n    Z[0] = acos(x); // acos( cos(u) )\n\n    // create f: U -> Z and vectors used for derivative calculations\n    ADFun<double> f(U, Z);\n    CPPAD_TESTVECTOR(double) v(1);\n    CPPAD_TESTVECTOR(double) w(1);\n\n    // check value\n    ok &= NearEqual(U[0] , Z[0],  eps99 , eps99);\n\n    // forward computation of partials w.r.t. u\n    size_t j;\n    size_t p     = 5;\n    double jfac  = 1.;\n    double value = 1.;\n    v[0]         = 1.;\n    for(j = 1; j < p; j++)\n    {   jfac *= double(j);\n        w     = f.Forward(j, v);\n        ok &= NearEqual(w[0], value/jfac, eps99, eps99);// d^jz/du^j\n        v[0]  = 0.;\n        value = 0.;\n    }\n\n    // reverse computation of partials of Taylor coefficients\n    CPPAD_TESTVECTOR(double) r(p);\n    w[0]  = 1.;\n    r     = f.Reverse(p, w);\n    jfac  = 1.;\n    value = 1.;\n    for(j = 0; j < p; j++)\n    {   ok &= NearEqual(r[j], value/jfac, eps99, eps99);// d^jz/du^j\n        jfac *= double(j + 1);\n        value = 0.;\n    }\n\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/acosh.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/cppad.hpp>\n\nbool acosh(void)\n{   bool ok = true;\n\n    using CppAD::AD;\n    using CppAD::NearEqual;\n\n    // 10 times machine epsilon\n    double eps = 200. * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n  = 1;\n    double x0 = 0.5;\n    CPPAD_TESTVECTOR(AD<double>) ax(n);\n    ax[0]     = x0;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(ax);\n\n    // a temporary value\n    AD<double> cosh_of_x0 = CppAD::cosh(ax[0]);\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) ay(m);\n    ay[0] = CppAD::acosh(cosh_of_x0);\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(ax, ay);\n\n    // check value\n    ok &= NearEqual(ay[0] , x0,  eps, eps);\n\n    // forward computation of first partial w.r.t. x[0]\n    CPPAD_TESTVECTOR(double) dx(n);\n    CPPAD_TESTVECTOR(double) dy(m);\n    dx[0] = 1.;\n    dy    = f.Forward(1, dx);\n    ok   &= NearEqual(dy[0], 1., eps, eps);\n\n    // forward computation of higher order partials w.r.t. x[0]\n    size_t n_order = 5;\n    for(size_t order = 2; order < n_order; order++)\n    {   dx[0] = 0.;\n        dy    = f.Forward(order, dx);\n        ok   &= NearEqual(dy[0], 0., eps, eps);\n    }\n    // reverse computation of derivatives\n    CPPAD_TESTVECTOR(double)  w(m);\n    CPPAD_TESTVECTOR(double) dw(n_order * n);\n    w[0]  = 1.;\n    dw    = f.Reverse(n_order, w);\n    ok   &= NearEqual(dw[0], 1., eps, eps);\n    for(size_t order = 1; order < n_order; order++)\n        ok   &= NearEqual(dw[order * n + 0], 0., eps, eps);\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "test_more/general/add.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\nTwo old Add examples now used just for valiadation testing\n*/\n\n# include <cppad/cppad.hpp>\n\nnamespace { // BEGIN empty namespace\n\nbool AddTestOne(void)\n{   bool ok = true;\n\n    using namespace CppAD;\n\n    // independent variable vector, indices, values, and declaration\n    CPPAD_TESTVECTOR(AD<double>) U(2);\n    size_t s = 0;\n    size_t t = 1;\n    U[s]     = 3.;\n    U[t]     = 2.;\n    Independent(U);\n\n    // dependent variable vector and indices\n    CPPAD_TESTVECTOR(AD<double>) Z(3);\n    size_t x = 0;\n    size_t y = 1;\n    size_t z = 2;\n\n    // dependent variable values\n    Z[x] = U[s]  + U[t];   // AD<double> + AD<double>\n    Z[y] = Z[x]  + 1.;     // AD<double> + double\n    Z[z] = 1.    + Z[y];   // double + AD<double>\n\n    // create f: U -> Z and vectors used for derivative calculations\n    ADFun<double> f(U, Z);\n    CPPAD_TESTVECTOR(double) v( f.Domain() );\n    CPPAD_TESTVECTOR(double) w( f.Range() );\n\n    // check function values\n    ok &= ( Z[x] == 3. + 2. );\n    ok &= ( Z[y] == 3. + 2. + 1. );\n    ok &= ( Z[z] == 1. + 3. + 2. + 1. );\n\n    // forward computation of partials w.r.t. s\n    v[s] = 1.;\n    v[t] = 0.;\n    w    = f.Forward(1, v);\n    ok &= ( w[x] == 1. );   // dx/ds\n    ok &= ( w[y] == 1. );   // dy/ds\n    ok &= ( w[z] == 1. );   // dz/ds\n\n    // reverse computation of second partials of z\n    CPPAD_TESTVECTOR(double) r( f.Domain() * 2 );\n    w[x] = 0.;\n    w[y] = 0.;\n    w[z] = 1.;\n    r    = f.Reverse(2, w);\n    ok &= ( r[2 * s + 1] == 0. );  // d^2 z / (ds ds)\n    ok &= ( r[2 * t + 1] == 0. );  // d^2 z / (ds dt)\n\n    return ok;\n}\n\nbool AddTestTwo(void)\n{   bool ok = true;\n    using namespace CppAD;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // independent variable vector\n    double u0 = .5;\n    CPPAD_TESTVECTOR(AD<double>) U(1);\n    U[0]      = u0;\n    Independent(U);\n\n    AD<double> a = U[0] + 1.; // AD<double> + double\n    AD<double> b = a  + 2;    // AD<double> + int\n    AD<double> c = 3. + b;    // double     + AD<double>\n    AD<double> d = 4  + c;    // int        + AD<double>\n\n    // dependent variable vector\n    CPPAD_TESTVECTOR(AD<double>) Z(1);\n    Z[0] = d + U[0];          // AD<double> + AD<double>\n\n    // create f: U -> Z and vectors used for derivative calculations\n    ADFun<double> f(U, Z);\n    CPPAD_TESTVECTOR(double) v(1);\n    CPPAD_TESTVECTOR(double) w(1);\n\n    // check value\n    ok &= NearEqual(Z[0] , 2 * u0 + 10,  eps99 , eps99);\n\n    // forward computation of partials w.r.t. u\n    size_t j;\n    size_t p     = 5;\n    double jfac  = 1.;\n    double value = 2.;\n    v[0]         = 1.;\n    for(j = 1; j < p; j++)\n    {   jfac *= double(j);\n        w     = f.Forward(j, v);\n        ok &= NearEqual(w[0], value/jfac, eps99, eps99); // d^jz/du^j\n        v[0]  = 0.;\n        value = 0.;\n    }\n\n    // reverse computation of partials of Taylor coefficients\n    CPPAD_TESTVECTOR(double) r(p);\n    w[0]  = 1.;\n    r     = f.Reverse(p, w);\n    jfac  = 1.;\n    value = 2.;\n    for(j = 0; j < p; j++)\n    {   ok &= NearEqual(r[j], value/jfac, eps99, eps99); // d^jz/du^j\n        jfac *= double(j + 1);\n        value = 0.;\n    }\n\n    return ok;\n}\n\n} // END empty namespace\n\nbool Add(void)\n{   bool ok = true;\n    ok &= AddTestOne();\n    ok &= AddTestTwo();\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/add_eq.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\nTwo old example now used just for valiadation testing\n*/\n# include <cppad/cppad.hpp>\n\nnamespace { // BEGIN empty namespace\n\nbool AddEqOne(void)\n{   bool ok = true;\n\n    using namespace CppAD;\n\n\n    // independent variable vector, indices, values, and declaration\n    CPPAD_TESTVECTOR(AD<double>) U(2);\n    size_t s = 0;\n    size_t t = 1;\n    U[s]     = 3.;\n    U[t]     = 2.;\n    Independent(U);\n\n    // dependent variable vector and indices\n    CPPAD_TESTVECTOR(AD<double>) Z(2);\n    size_t x = 0;\n    size_t y = 1;\n\n    // dependent variable values\n    Z[x]  = 4.;\n    Z[y]  = U[t];\n    Z[x] += U[s];  // parameter += variable\n    Z[x] += U[t];  // variable  += variable\n    Z[y] += .5;    // variable  += double\n    // use .5 because it is represented exactly in binary and\n    // because it makes sure that += does not slice the double to an int\n\n    // create f: U -> Z and vectors used for derivative calculations\n    ADFun<double> f(U, Z);\n    CPPAD_TESTVECTOR(double) v( f.Domain() );\n    CPPAD_TESTVECTOR(double) w( f.Range() );\n\n    // check function values\n    ok &= ( Z[x] == 4. + 3. + 2. );\n    ok &= ( Z[y] == 2. + .5 );\n\n    // forward computation of partials w.r.t. s\n    v[s] = 1.;\n    v[t] = 0.;\n    w    = f.Forward(1, v);\n    ok &= ( w[x] == 1. );  // dx/ds\n    ok &= ( w[y] == 0. );  // dy/ds\n\n    // reverse computation of second partials of x\n    CPPAD_TESTVECTOR(double) r( f.Domain() * 2 );\n    w[x] = 1.;\n    w[y] = 0.;\n    r    = f.Reverse(2, w);\n    ok &= ( r[2 * s + 1] == 0. );\n    ok &= ( r[2 * t + 1] == 0. );\n\n    return ok;\n}\n\nbool AddEqTwo(void)\n{   bool ok = true;\n    using namespace CppAD;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // independent variable vector\n    double u0 = .5;\n    CPPAD_TESTVECTOR(AD<double>) U(1);\n    U[0]      = u0;\n    Independent(U);\n\n    // dependent variable vector\n    CPPAD_TESTVECTOR(AD<double>) Z(1);\n    Z[0] = U[0];       // initial value\n    Z[0] += 2;         // AD<double> += int\n    Z[0] += 4.;        // AD<double> += double\n    Z[0] += U[0];      // AD<double> += AD<double>\n\n    // create f: U -> Z and vectors used for derivative calculations\n    ADFun<double> f(U, Z);\n    CPPAD_TESTVECTOR(double) v(1);\n    CPPAD_TESTVECTOR(double) w(1);\n\n    // check value\n    ok &= NearEqual(Z[0] , u0+2+4+u0,  eps99 , eps99);\n\n    // forward computation of partials w.r.t. u\n    size_t j;\n    size_t p     = 5;\n    double jfac  = 1.;\n    double value = 2.;\n    v[0]         = 1.;\n    for(j = 1; j < p; j++)\n    {   jfac *= double(j);\n        w     = f.Forward(j, v);\n        ok &= NearEqual(w[0], value/jfac, eps99, eps99); // d^jz/du^j\n        v[0]  = 0.;\n        value = 0.;\n    }\n\n    // reverse computation of partials of Taylor coefficients\n    CPPAD_TESTVECTOR(double) r(p);\n    w[0]  = 1.;\n    r     = f.Reverse(p, w);\n    jfac  = 1.;\n    value = 2.;\n    for(j = 0; j < p; j++)\n    {   ok &= NearEqual(r[j], value/jfac, eps99, eps99); // d^jz/du^j\n        jfac *= double(j + 1);\n        value = 0.;\n    }\n\n    return ok;\n}\n\n} // END empty namespace\n\nbool AddEq(void)\n{   bool ok = true;\n    ok     &= AddEqOne();\n    ok     &= AddEqTwo();\n    return ok;\n}\n\n// END PROGRAM\n"
  },
  {
    "path": "test_more/general/add_zero.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\nTest the use of the special parameters zero and one with the multiply operator\n*/\n\n# include <cppad/cppad.hpp>\n\ntypedef CppAD::AD<double>      ADdouble;\ntypedef CppAD::AD< ADdouble > ADDdouble;\n\nbool AddZero(void)\n{\n    using namespace CppAD;\n\n    bool ok = true;\n\n    size_t i;\n    for(i = 0; i < 2; i++)\n    {   // run through the cases x = 0, 1\n\n        size_t j;\n        for(j = 0; j < 2; j++)\n        {   // run through the cases y = 0, 1\n\n            CPPAD_TESTVECTOR( ADdouble ) x(1);\n            x[0] = double(i);\n            Independent(x);\n\n            CPPAD_TESTVECTOR( ADDdouble ) y(1);\n            y[0] = ADDdouble(j);\n            Independent(y);\n\n            CPPAD_TESTVECTOR( ADDdouble ) z(2);\n            z[0]  = x[0] + y[0];\n            z[1]  = y[0] + x[0];\n            z[1] += x[0];\n\n            // f(y) = z = { x + y , y + x + x }\n            ADFun< ADdouble > f(y, z);\n            CPPAD_TESTVECTOR( ADdouble ) u( f.Domain() );\n            CPPAD_TESTVECTOR( ADdouble ) v( f.Range() );\n\n            // v = f(y)\n            u[0] = ADdouble(j);\n            v = f.Forward(0, u);\n\n            // check value of f\n            ok &= v[0] == x[0] + ADdouble(j);\n            ok &= v[1] == ADdouble(j) + x[0] + x[0];\n\n            // g(x) = f(y) = {x + y , y + x + x}\n            ADFun<double> g(x, v);\n            CPPAD_TESTVECTOR( double ) a( g.Domain() );\n            CPPAD_TESTVECTOR( double ) b( g.Range() );\n\n            // b = g'(x)\n            a[0] = 1.;\n            b = g.Forward(1, a);\n\n            // check derivatives of g\n            ok &= (b[0] == 1.);\n            ok &= (b[1] == 2.);\n\n        }\n    }\n\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/adfun.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\nTest that ADFun copy constructor generates an error message.\n*/\n\n# include <cppad/cppad.hpp>\n# include <string>\n\nnamespace { // BEGIN_EMPTY_NAMESPACE\n\n\nbool adfun_empty(void)\n{   bool ok = true;\n    size_t thread  = CppAD::thread_alloc::thread_num();\n    //\n    // Allocate this memory first incase we are using\n    // CppAD::vector which uses thread_alloc.\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) ax(1), ay(1);\n    //\n    // check that an empty function does not hold memory\n    size_t inuse_1  = CppAD::thread_alloc::inuse(thread);\n    CppAD::ADFun<double> f;\n    size_t inuse_2  = CppAD::thread_alloc::inuse(thread);\n    ok &= inuse_1 == inuse_2;\n    //\n    // check that creating an adfun uses memory\n    CppAD::Independent(ax);\n    ay = ax;\n    CppAD::ADFun<double> g(ax, ay);\n    size_t inuse_3  = CppAD::thread_alloc::inuse(thread);\n    ok &= inuse_1 < inuse_3;\n    //\n    // assigning to an empty function uses assignment to pod_vectors\n    // which just changes their length to zero\n    g = f;\n    size_t inuse_4  = CppAD::thread_alloc::inuse(thread);\n    ok &= inuse_3 == inuse_4;\n    //\n    // assigning to a temporary empty function to g\n    // uses move semantics (hence frees all memory in g)\n    g = CppAD::ADFun<double>();\n    size_t inuse_5  = CppAD::thread_alloc::inuse(thread);\n    ok &= inuse_1 == inuse_5;\n    //\n    return ok;\n}\n\nbool adfun_swap(void)\n{   bool ok = true;\n    //\n    // Independent variables\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) ax(1);\n    CppAD::Independent(ax);\n    //\n    // Dependent variables\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) ay(2);\n    ay[0] = ax[0];\n    ay[1] = ax[0];\n    //\n    // Nonempty ADFun\n    CppAD::ADFun<double> f(ax, ay);\n    ok &= f.size_var() != 0;\n    //\n    // Empry ADFun\n    CppAD::ADFun<double> g;\n    ok &= g.size_var() == 0;\n    //\n    // swap\n    f.swap(g);\n    ok &= f.size_var() == 0;\n    ok &= g.size_var() != 0;\n    //\n    return ok;\n}\n\n} // END_EMPTY_NAMESPACE\n\nbool adfun(void)\n{   bool ok = true;\n    ok     &= adfun_empty();\n    ok     &= adfun_swap();\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/alloc_openmp.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n// BEGIN C++\n# include <cppad/cppad.hpp>\n# include <omp.h>\n# define NUMBER_THREADS  2\n\nnamespace {\n    using CppAD::thread_alloc;\n\n    // used to inform CppAD when we are in parallel execution mode\n    bool in_parallel(void)\n    {   return static_cast<bool>( omp_in_parallel() ); }\n\n    // used to inform CppAD of current thread number thread_number()\n    size_t thread_number(void)\n    {   return static_cast<bool>( omp_get_thread_num() ); }\n\n    // structure with information for one thread\n    typedef struct {\n        // function object (worker input)\n        CppAD::vector<double> x;\n    } thread_one_t;\n\n    // vector with information for all threads\n    thread_one_t thread_all_[NUMBER_THREADS];\n\n    // --------------------------------------------------------------------\n    // function that does the work for one thread\n    void worker(void)\n    {\n        size_t thread_num = thread_number();\n        thread_all_[thread_num].x.resize(1);\n        thread_all_[thread_num].x[0]=static_cast<double>(thread_num);\n    }\n}\n\n// Test routine called by the master thread (thread_num = 0).\nbool alloc_openmp(void)\n{   bool ok = true;\n\n    int num_threads = NUMBER_THREADS;\n\n    // call setup for using thread_alloc in parallel mode.\n    thread_alloc::parallel_setup(\n        size_t(num_threads), in_parallel, thread_number\n    );\n\n    // Execute the worker function in parallel\n    int thread_num;\n# pragma omp parallel for\n    for(thread_num = 0; thread_num < num_threads; thread_num++)\n        worker();\n// end omp parallel for\n\n    // now inform CppAD that there is only one thread\n    thread_alloc::parallel_setup(1, nullptr, nullptr);\n\n    for(thread_num = 0; thread_num < num_threads; thread_num++)\n    {   // check calculations by this thread in parallel model\n        ok &= thread_all_[thread_num].x[0] == static_cast<double>(thread_num);\n\n        // test having master thread (thread number zero)\n        // free memory that was allocated by thread number thread_num.\n        thread_all_[thread_num].x.clear();\n    }\n\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/asin.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\nOld example now only used for validation testing.\n*/\n\n# include <cppad/cppad.hpp>\n\nbool asin(void)\n{   bool ok = true;\n    using CppAD::asin;\n    using namespace CppAD;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // independent variable vector\n    CPPAD_TESTVECTOR(AD<double>) U(1);\n    U[0]     = .5;\n    Independent(U);\n\n    // a temporary values\n    AD<double> x = sin(U[0]);\n\n    // dependent variable vector\n    CPPAD_TESTVECTOR(AD<double>) Z(1);\n    Z[0] = asin(x); // asin( sin(u) )\n\n    // create f: U -> Z and vectors used for derivative calculations\n    ADFun<double> f(U, Z);\n    CPPAD_TESTVECTOR(double) v(1);\n    CPPAD_TESTVECTOR(double) w(1);\n\n    // check value\n    ok &= NearEqual(U[0] , Z[0],  eps99 , eps99);\n\n    // forward computation of partials w.r.t. u\n    size_t j;\n    size_t p     = 5;\n    double jfac  = 1.;\n    double value = 1.;\n    v[0]         = 1.;\n    for(j = 1; j < p; j++)\n    {   jfac *= double(j);\n        w     = f.Forward(j, v);\n        ok &= NearEqual(w[0], value/jfac, eps99, eps99); // d^jz/du^j\n        v[0]  = 0.;\n        value = 0.;\n    }\n\n    // reverse computation of partials of Taylor coefficients\n    CPPAD_TESTVECTOR(double) r(p);\n    w[0]  = 1.;\n    r     = f.Reverse(p, w);\n    jfac  = 1.;\n    value = 1.;\n    for(j = 0; j < p; j++)\n    {   ok &= NearEqual(r[j], value/jfac, eps99, eps99); // d^jz/du^j\n        jfac *= double(j + 1);\n        value = 0.;\n    }\n\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/asinh.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/cppad.hpp>\n\nbool asinh(void)\n{   bool ok = true;\n\n    using CppAD::AD;\n    using CppAD::NearEqual;\n\n    // 10 times machine epsilon\n    double eps = 10. * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n  = 1;\n    double x0 = 0.5;\n    CPPAD_TESTVECTOR(AD<double>) ax(n);\n    ax[0]     = x0;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(ax);\n\n    // a temporary value\n    AD<double> sinh_of_x0 = CppAD::sinh(ax[0]);\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) ay(m);\n    ay[0] = CppAD::asinh(sinh_of_x0);\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(ax, ay);\n\n    // check value\n    ok &= NearEqual(ay[0] , x0,  eps, eps);\n\n    // forward computation of first partial w.r.t. x[0]\n    CPPAD_TESTVECTOR(double) dx(n);\n    CPPAD_TESTVECTOR(double) dy(m);\n    dx[0] = 1.;\n    dy    = f.Forward(1, dx);\n    ok   &= NearEqual(dy[0], 1., eps, eps);\n\n    // forward computation of higher order partials w.r.t. x[0]\n    size_t n_order = 5;\n    for(size_t order = 2; order < n_order; order++)\n    {   dx[0] = 0.;\n        dy    = f.Forward(order, dx);\n        ok   &= NearEqual(dy[0], 0., eps, eps);\n    }\n    // reverse computation of derivatives\n    CPPAD_TESTVECTOR(double)  w(m);\n    CPPAD_TESTVECTOR(double) dw(n_order * n);\n    w[0]  = 1.;\n    dw    = f.Reverse(n_order, w);\n    ok   &= NearEqual(dw[0], 1., eps, eps);\n    for(size_t order = 1; order < n_order; order++)\n        ok   &= NearEqual(dw[order * n + 0], 0., eps, eps);\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "test_more/general/assign.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\nOld example, now used just for validation testing\n*/\n\n# include <cppad/cppad.hpp>\n\nbool assign(void)\n{   bool ok = true;\n    using CppAD::AD;\n\n    // domain space vector\n    size_t n = 3;\n    CPPAD_TESTVECTOR(AD<double>) x(n);\n    x[0]     = 2;      // AD<double> = int\n    x[1]     = 3.;     // AD<double> = double\n    x[2]     = x[1];   // AD<double> = AD<double>\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(x);\n\n    // range space vector\n    size_t m = 3;\n    CPPAD_TESTVECTOR(AD<double>) y(m);\n\n    // assign an AD<Base> object equal to an independent variable\n    // (choose the first independent variable to check a special case)\n    // use the value returned by the assignment (for another assignment)\n    y[0] = y[1] = x[0];\n\n    // assign an AD<Base> object equal to an expression\n    y[1] = x[1] + 1.;\n    y[2] = x[2] + 2.;\n\n    // check that all the resulting components of y depend on x\n    ok &= Variable(y[0]);  // y[0] = x[0]\n    ok &= Variable(y[1]);  // y[1] = x[1] + 1\n    ok &= Variable(y[2]);  // y[2] = x[2] + 2\n\n    // construct f : x -> y and stop the tape recording\n    CppAD::ADFun<double> f(x, y);\n\n    // check variable values\n    ok &= ( y[0] == 2.);\n    ok &= ( y[1] == 4.);\n    ok &= ( y[2] == 5.);\n\n    // compute partials w.r.t x[1]\n    CPPAD_TESTVECTOR(double) dx(n);\n    CPPAD_TESTVECTOR(double) dy(m);\n    dx[0] = 0.;\n    dx[1] = 1.;\n    dx[2] = 0.;\n    dy   = f.Forward(1, dx);\n    ok  &= (dy[0] == 0.);  // dy[0] / dx[1]\n    ok  &= (dy[1] == 1.);  // dy[1] / dx[1]\n    ok  &= (dy[2] == 0.);  // dy[2] / dx[1]\n\n    // compute the derivative y[2]\n    CPPAD_TESTVECTOR(double)  w(m);\n    CPPAD_TESTVECTOR(double) dw(n);\n    w[0] = 0.;\n    w[1] = 0.;\n    w[2] = 1.;\n    dw   = f.Reverse(1, w);\n    ok  &= (dw[0] == 0.);  // dy[2] / dx[0]\n    ok  &= (dw[1] == 0.);  // dy[2] / dx[1]\n    ok  &= (dw[2] == 1.);  // dy[2] / dx[2]\n\n    // assign a VecAD<Base>::reference\n    CppAD::VecAD<double> v(1);\n    AD<double> zero(0);\n    v[zero] = 5.;\n    ok     &= (v[0] == 5.);\n\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/atan.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n\n/*\nTwo old atan examples now used just for validation testing.\n*/\n\n# include <cppad/cppad.hpp>\n\nnamespace { // BEGIN empty namespace\n\nbool AtanTestOne(void)\n{   bool ok = true;\n\n    using CppAD::atan;\n    using namespace CppAD;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // independent variable vector, indices, values, and declaration\n    CPPAD_TESTVECTOR(AD<double>) U(1);\n    size_t s = 0;\n    U[s]     = 1.;\n    Independent(U);\n\n    // some temporary values\n    AD<double> x = cos(U[s]);\n    AD<double> y = sin(U[s]);\n    AD<double> z = y / x;       // tan(s)\n\n    // dependent variable vector and indices\n    CPPAD_TESTVECTOR(AD<double>) Z(1);\n    size_t a = 0;\n\n    // dependent variable values\n    Z[a] = atan(z); // atan( tan(s) )\n\n    // create f: U -> Z and vectors used for dierivative calculations\n    ADFun<double> f(U, Z);\n    CPPAD_TESTVECTOR(double) v( f.Domain() );\n    CPPAD_TESTVECTOR(double) w( f.Range() );\n\n    // check value\n    ok &= NearEqual(U[s] , Z[a],  eps99 , eps99);\n\n    // forward computation of partials w.r.t. s\n    v[s] = 1.;\n    w    = f.Forward(1, v);\n    ok &= NearEqual(w[a], 1e0, eps99 , eps99);  // da/ds\n\n    // reverse computation of first order partial of a\n    w[a] = 1.;\n    v    = f.Reverse(1, w);\n    ok &= NearEqual(v[s], 1e0, eps99 , eps99);  // da/ds\n\n    // forward computation of second partials w.r.t. s and s\n    v[s] = 1.;\n    f.Forward(1, v);\n    v[s] = 0.;\n    w    = f.Forward(2, v);\n    ok &= NearEqual(2. * w[a], 0e0, eps99 , eps99);     // d^2 a / (ds ds)\n\n    // reverse computation of second partials of a\n    CPPAD_TESTVECTOR(double) r( f.Domain() * 2 );\n    w[a] = 1.;\n    r    = f.Reverse(2, w);\n    ok &= NearEqual(r[2 * s + 1] ,0e0, eps99 , eps99 ); // d^2 a / (ds ds)\n\n    return ok;\n}\n\nbool AtanTestTwo(void)\n{   bool ok = true;\n\n    using CppAD::atan;\n    using CppAD::sin;\n    using CppAD::cos;\n    using namespace CppAD;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // independent variable vector\n    CPPAD_TESTVECTOR(AD<double>) U(1);\n    U[0]     = 1.;\n    Independent(U);\n\n    // a temporary values\n    AD<double> x = sin(U[0]) / cos(U[0]);\n\n    // dependent variable vector\n    CPPAD_TESTVECTOR(AD<double>) Z(1);\n    Z[0] = atan(x); // atan( tan(u) )\n\n    // create f: U -> Z and vectors used for derivative calculations\n    ADFun<double> f(U, Z);\n    CPPAD_TESTVECTOR(double) v(1);\n    CPPAD_TESTVECTOR(double) w(1);\n\n    // check value\n    ok &= NearEqual(U[0] , Z[0],  eps99 , eps99);\n\n    // forward computation of partials w.r.t. u\n    size_t j;\n    size_t p     = 5;\n    double jfac  = 1.;\n    double value = 1.;\n    v[0]         = 1.;\n    for(j = 1; j < p; j++)\n    {   jfac *= double(j);\n        w     = f.Forward(j, v);\n        ok &= NearEqual(w[0], value/jfac, eps99, eps99);// d^jz/du^j\n        v[0]  = 0.;\n        value = 0.;\n    }\n\n    // reverse computation of partials of Taylor coefficients\n    CPPAD_TESTVECTOR(double) r(p);\n    w[0]  = 1.;\n    r     = f.Reverse(p, w);\n    jfac  = 1.;\n    value = 1.;\n    for(j = 0; j < p; j++)\n    {   ok &= NearEqual(r[j], value/jfac, eps99, eps99);// d^jz/du^j\n        jfac *= double(j + 1);\n        value = 0.;\n    }\n\n    return ok;\n}\n\n} // END empty namespace\n\nbool atan(void)\n{   bool ok = true;\n    ok &= AtanTestOne();\n    ok &= AtanTestTwo();\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/atan2.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\nOld example and test now just used for validation testing.\n*/\n\n# include <cppad/cppad.hpp>\n# include <cmath>\n\nnamespace { // begin empty namespace\n\nbool ad_ad(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    AD< AD<double> > x(2.), y(2.);\n    AD< AD<double> > z = atan2(y, x);\n    NearEqual( Value( Value(z) ), atan(1.), eps99, eps99);\n\n    return ok;\n}\n\nbool general(void)\n{   bool ok = true;\n\n    using CppAD::atan;\n    using CppAD::sin;\n    using CppAD::cos;\n    using namespace CppAD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // independent variable vector\n    CPPAD_TESTVECTOR(AD<double>) U(1);\n    U[0]     = 1.;\n    Independent(U);\n\n    // a temporary values\n    AD<double> x = cos(U[0]);\n    AD<double> y = sin(U[0]);\n\n    // dependent variable vector\n    CPPAD_TESTVECTOR(AD<double>) Z(1);\n    Z[0] = atan2(y, x);\n\n    // create f: U -> Z and vectors used for derivative calculations\n    ADFun<double> f(U, Z);\n    CPPAD_TESTVECTOR(double) v(1);\n    CPPAD_TESTVECTOR(double) w(1);\n\n    // check original value (u in first quadrant)\n    ok &= NearEqual(U[0] , Z[0], eps99, eps99);\n\n    // check case where u is in second quadrant\n    v[0] = 3.;\n    w    = f.Forward(0, v);\n    ok  &= NearEqual(w[0] , v[0], eps99, eps99);\n\n    // check case where u is in third quadrant\n    v[0] = -3.;\n    w    = f.Forward(0, v);\n    ok  &= NearEqual(w[0] , v[0], eps99, eps99);\n\n    // check case where u is in fourth quadrant\n    v[0] = -1.;\n    w    = f.Forward(0, v);\n    ok  &= NearEqual(w[0] , v[0], eps99, eps99);\n\n    // forward computation of partials w.r.t. u\n    size_t j;\n    size_t p     = 5;\n    double jfac  = 1.;\n    double value = 1.;\n    v[0]         = 1.;\n    for(j = 1; j < p; j++)\n    {   jfac *= double(j);\n        w     = f.Forward(j, v);\n        ok &= NearEqual(w[0], value/jfac, eps99, eps99); // d^jz/du^j\n        v[0]  = 0.;\n        value = 0.;\n    }\n\n    // reverse computation of partials of Taylor coefficients\n    CPPAD_TESTVECTOR(double) r(p);\n    w[0]  = 1.;\n    r     = f.Reverse(p, w);\n    jfac  = 1.;\n    value = 1.;\n    for(j = 0; j < p; j++)\n    {   ok &= NearEqual(r[j], value/jfac, eps99, eps99); // d^jz/du^j\n        jfac *= double(j + 1);\n        value = 0.;\n    }\n\n    return ok;\n}\n\n} // end empty namespace\n\nbool atan2(void)\n{   bool ok = true;\n    ok     &= ad_ad();\n    ok     &= general();\n\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/atanh.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/cppad.hpp>\n\nbool atanh(void)\n{   bool ok = true;\n\n    using CppAD::AD;\n    using CppAD::NearEqual;\n\n    // 10 times machine epsilon\n    double eps = 10. * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n  = 1;\n    double x0 = 0.5;\n    CPPAD_TESTVECTOR(AD<double>) ax(n);\n    ax[0]     = x0;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(ax);\n\n    // a temporary value\n    AD<double> tanh_of_x0 = CppAD::tanh(ax[0]);\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) ay(m);\n    ay[0] = CppAD::atanh(tanh_of_x0);\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(ax, ay);\n\n    // check value\n    ok &= NearEqual(ay[0] , x0,  eps, eps);\n\n    // forward computation of first partial w.r.t. x[0]\n    CPPAD_TESTVECTOR(double) dx(n);\n    CPPAD_TESTVECTOR(double) dy(m);\n    dx[0] = 1.;\n    dy    = f.Forward(1, dx);\n    ok   &= NearEqual(dy[0], 1., eps, eps);\n\n    // forward computation of higher order partials w.r.t. x[0]\n    size_t n_order = 5;\n    for(size_t order = 2; order < n_order; order++)\n    {   dx[0] = 0.;\n        dy    = f.Forward(order, dx);\n        ok   &= NearEqual(dy[0], 0., eps, eps);\n    }\n    // reverse computation of derivatives\n    CPPAD_TESTVECTOR(double)  w(m);\n    CPPAD_TESTVECTOR(double) dw(n_order * n);\n    w[0]  = 1.;\n    dw    = f.Reverse(n_order, w);\n    ok   &= NearEqual(dw[0], 1., eps, eps);\n    for(size_t order = 1; order < n_order; order++)\n        ok   &= NearEqual(dw[order * n + 0], 0., eps, eps);\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "test_more/general/atomic_four.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/cppad.hpp>\n# include <cppad/example/atomic_four/lin_ode/lin_ode.hpp>\n\nnamespace { // BEGIN_EMPTY_NAMESPACE\n\n// atomic_norm_sq\nclass atomic_norm_sq : public CppAD::atomic_four<double> {\npublic:\n    atomic_norm_sq(const std::string& name) :\n    CppAD::atomic_four<double>(name)\n    { }\n// END CONSTRUCTOR\nprivate:\n    // BEGIN FOR_TYPE\n    bool for_type(\n        size_t                                     call_id     ,\n        const CppAD::vector<CppAD::ad_type_enum>&  type_x      ,\n        CppAD::vector<CppAD::ad_type_enum>&        type_y      ) override\n    {   assert( call_id == 0 );       // default value\n        assert(type_y.size() == 1 );  // m\n        //\n        // type_y\n        size_t n     = type_x.size();\n        type_y[0] = CppAD::constant_enum;\n        for(size_t j = 0; j < n; ++j)\n            type_y[0] = std::max(type_y[0], type_x[j]);\n        return true;\n    }\n    // END FOR_TYPE\n    // BEGIN FORWARD\n    bool forward(\n        size_t                             call_id     ,\n        const CppAD::vector<bool>&         select_y    ,\n        size_t                             order_low   ,\n        size_t                             order_up    ,\n        const CppAD::vector<double>&       tx          ,\n        CppAD::vector<double>&             ty          ) override\n    {\n        size_t q = order_up + 1;\n        size_t n = tx.size() / q;\n# ifndef NDEBUG\n        size_t m = ty.size() / q;\n        assert( call_id == 0 );\n        assert( m == 1 );\n        assert( m == select_y.size() );\n# endif\n        // ok\n        bool ok = order_up <= 1 && order_low <= order_up;\n        if ( ! ok )\n            return ok;\n        //\n        // sum = x_0^0 * x_0^0 + x_1^0 * x_1^0 + ...\n        double sum = 0.0;\n        for(size_t j = 0; j < n; ++j)\n        {   double xj0 = tx[ j * q + 0];\n            sum       += xj0 * xj0;\n        }\n        //\n        // ty[0] = sum\n        if( order_low <= 0 )\n            ty[0] = sum;\n        if( order_up < 1 )\n            return ok;\n\n        // sum = x_0^0 * x_0^1 + x_1^0 ^ x_1^1 + ...\n        sum   = 0.0;\n        for(size_t j = 0; j < n; ++j)\n        {   double xj0 = tx[ j * q + 0];\n            double xj1 = tx[ j * q + 1];\n            sum       += xj0 * xj1;\n        }\n        // ty[1] = 2.0 * sum\n        assert( order_up == 1 );\n        ty[1] = 2.0 * sum;\n        return ok;\n    }\n};\n\n// forward_dir\nbool forward_dir(void)\n{   // ok, eps\n    bool ok    = true;\n    double eps = 10. * CppAD::numeric_limits<double>::epsilon();\n    //\n    // atom_norm_sq\n    atomic_norm_sq afun(\"atomic_norm_sq\");\n    //\n    // n, m\n    size_t n = 2;\n    size_t m = 1;\n    //\n    // x\n    CPPAD_TESTVECTOR(double) x(n);\n    for(size_t j = 0; j < n; ++j)\n        x[j] = 1.0 / (double(j) + 1.0);\n    //\n    // ax\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) ax(n);\n    for(size_t j = 0; j < n; ++j)\n        ax[j] = x[j];\n    CppAD::Independent(ax);\n    //\n    // ay\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) ay(m);\n    afun(ax, ay);\n    //\n    // f\n    CppAD::ADFun<double> f;\n    f.Dependent (ax, ay);\n    //\n    // check\n    double check = 0.0;\n    for(size_t j = 0; j < n; ++j)\n        check += x[j] * x[j];\n    //\n    // ok\n    // check ay[0]\n    ok &= CppAD::NearEqual( Value(ay[0]) , check,  eps, eps);\n    //\n    // ok\n    // check zero order forward mode\n    CPPAD_TESTVECTOR(double) y(m);\n    y   = f.Forward(0, x);\n    ok &= CppAD::NearEqual(y[0] , check,  eps, eps);\n    //\n    // y1\n    // first order forward mode partial w.r.t. each component of x\n    size_t r = n;\n    CPPAD_TESTVECTOR(double) x1(n * r), y1(m * r);\n    for(size_t j = 0; j < n; ++j)\n    {   for(size_t ell = 0; ell < r; ++ell)\n        {   x1[j * r + ell] = 0.0;\n            if( ell == j )\n                x1[j * r + ell] = 1.0;\n        }\n    }\n    y1     = f.Forward(1, r, x1);\n    //\n    // ok\n    for(size_t j = 0; j < n; ++j)\n        ok &= CppAD::NearEqual(y1[j] , 2.0 * x[j],  eps, eps);\n    //\n    return ok;\n}\n\n/*\n\\{xrst_begin atomic_four_lin_ode_rev_depend.cpp}\n{xrst_spell\n    cccc\n}\n\nAtomic Linear ODE Reverse Dependency Analysis: Example and Test\n###############################################################\n\nPurpose\n*******\nThis example demonstrates calculating reverse dependency with\nthe :ref:`atomic_four_lin_ode-name` class; see\n:ref:`atomic_four_lin_ode_rev_depend.hpp-name` .\n\nf(x)\n****\nFor this example, the function :math:`f(x) = z_2 (r, u)` where\n:math:`z(t, u)` solves the following ODE\n\n.. math::\n\n    z_t (t, x) =\n    \\left( \\begin{array}{cccc}\n    0   & 0  & 0    & 0   \\\\\n    x_0 & 0  & 0    & 0   \\\\\n    0   & x_1 & 0   & 0   \\\\\n    0   & 0   & x_2 & 0   \\\\\n    \\end{array} \\right)\n    z(t, u)\n    \\W{,}\n    z(0, u) =\n    \\left( \\begin{array}{c}\n    x_3 \\\\\n    x_4 \\\\\n    x_5 \\\\\n    x_6 \\\\\n    \\end{array} \\right)\n\nSolution\n********\nThe actual solution to this ODE is\n\n.. math::\n\n    z(t, x) =\n    \\left( \\begin{array}{l}\n    x_3  \\\\\n    x_4 + x_0 x_3 t \\\\\n    x_5 + x_1 x_4 t + x_1 x_0 x_3 t^2 / 2  \\\\\n    x_6 + x_2 x_5 t + x_2 x_1 x_4 t^2 / 2 + x_2 x_1 x_0 x_3 t^3 / 6\n    \\end{array} \\right)\n\nSource\n******\n{xrst_literal\n    // BEGIN C++\n    // END C++\n}\n\n\\{xrst_end atomic_four_lin_ode_rev_depend.cpp}\n*/\n\ntemplate <class Scalar, class Vector>\nVector Y(Scalar t, const Vector& x)\n{   size_t m = 4;\n    Vector y(m);\n    //\n    y[0]  = x[3];\n    y[1]  = x[4] + x[0]*x[3]*t;\n    y[2]  = x[5] + x[1]*x[4]*t + x[1]*x[0]*x[3]*t*t/2.0;\n    y[3]  = x[6] + x[2]*x[5]*t + x[2]*x[1]*x[4]*t*t/2.0\n             + x[2]*x[1]*x[0]*x[3]*t*t*t/6.0;\n    //\n    return y;\n}\n\n\nbool rev_depend(void)\n{   // ok, eps\n    bool ok = true;\n    //\n    // sparse_rc, AD, eps99\n    typedef CppAD::sparse_rc< CppAD::vector<size_t> > sparse_rc;\n    using CppAD::AD;\n    double eps99 = std::numeric_limits<double>::epsilon() * 99.0;\n    // -----------------------------------------------------------------------\n    // Record f\n    // -----------------------------------------------------------------------\n    //\n    // afun\n    CppAD::atomic_lin_ode<double> afun(\"atomic_lin_ode\");\n    //\n    // m, r\n    size_t m      = 4;\n    double r      = 2.0;\n    double step   = 1.0;\n    //\n    // pattern, transpose\n    size_t nr  = m;\n    size_t nc  = m;\n    size_t nnz = 3;\n    sparse_rc pattern(nr, nc, nnz);\n    for(size_t k = 0; k < nnz; ++k)\n    {   size_t i = k + 1;\n        size_t j = k;\n        pattern.set(k, i, j);\n    }\n    bool transpose = false;\n    //\n    // ax\n    CPPAD_TESTVECTOR( AD<double> ) ax(nnz + m);\n    for(size_t k = 0; k < nnz + m; ++k)\n        ax[k] = double(k + 1);\n    CppAD::Independent(ax);\n    //\n    // ay\n    CPPAD_TESTVECTOR( AD<double> ) ay(m);\n    size_t call_id = afun.set(r, step, pattern, transpose);\n    afun(call_id, ax, ay);\n    //\n    // z_index\n    size_t z_index = 1;\n    //\n    // az\n    CPPAD_TESTVECTOR( AD<double> ) az(1);\n    az[0] = ay[z_index];\n    //\n    // f\n    // optimize uses rev_depend\n    CppAD::ADFun<double> f(ax, az);\n    f.optimize();\n    // -----------------------------------------------------------------------\n    // check_f\n    // -----------------------------------------------------------------------\n    CppAD::Independent(ax);\n    AD<double> ar = r;\n    ay    = Y(ar, ax);\n    az[0] = ay[z_index];\n    CppAD::ADFun<double> check_f(ax, az);\n    // -----------------------------------------------------------------------\n    // rev_depend\n    // use test_rev_depend to call rev_depend directly\n    // -----------------------------------------------------------------------\n    //\n    // depend_x\n    CppAD::vector<bool> ident_zero_x(nnz + m), depend_x(nnz + m), depend_y(m);\n    for(size_t i = 0; i < m; ++i)\n    {   depend_y[i]     = i == z_index;\n        ident_zero_x[i] = false;\n    }\n    afun.test_rev_depend(call_id, ident_zero_x, depend_x, depend_y);\n    //\n    // x\n    CPPAD_TESTVECTOR(double) x(nnz + m);\n    for(size_t j = 0; j < nnz + m; ++j)\n        x[j] = double( j + 2 );\n    //\n    // dw\n    check_f.Forward(0, x);\n    CPPAD_TESTVECTOR(double) w(1), dw(nnz + m);\n    w[0] = 1.0;\n    dw = check_f.Reverse(1, w);\n    //\n    // ok\n    // note that for this x, partial w.r.t x[j] is non-zero if and only if\n    // y[z_index] depends on x[j]\n    for(size_t j = 0; j < nnz + m; ++j)\n        ok &= depend_x[j] == (dw[j] != 0.0);\n    //\n    // -----------------------------------------------------------------------\n    // forward mode on f\n    // Check that the optimized version of agrees with check_f.\n    // -----------------------------------------------------------------------\n    //\n    // z\n    // zero order forward mode computation of f(x)\n    CPPAD_TESTVECTOR(double) z = f.Forward(0, x);\n    //\n    // ok\n    CPPAD_TESTVECTOR(double) check_z = check_f.Forward(0, x);\n    ok &= CppAD::NearEqual(z[0], check_z[0], eps99, eps99);\n    //\n    // du, ok\n    CPPAD_TESTVECTOR(double) dx(nnz + m), dz(1), check_dz(1);\n    for(size_t j = 0; j < nnz + m; ++j)\n        dx[j] = 0.0;\n    //\n    for(size_t j = 0; j < nnz + m; ++j)\n    {   dx[j]     = 1.0;\n        dz        = f.Forward(1, dx);\n        check_dz  = check_f.Forward(1, dx);\n        ok       &= CppAD::NearEqual(dz[0], check_dz[0], eps99, eps99);\n        dx[j]     = 0.0;\n    }\n    // -----------------------------------------------------------------------\n    return ok;\n}\n} // END_EMPTY_NAMESPACE\n\nbool atomic_four(void)\n{   bool ok = true;\n    ok     &= forward_dir();\n    ok     &= rev_depend();\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/atomic_three.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\ng_0 (x) = x_0 * x_0\ng_1 (x) = x_0 * x_1\ng_2 (x) = x_1 * x_2\ng_3 (x) = x_2 * x_2\n\n*/\n# include <cppad/cppad.hpp>  // CppAD include file\nnamespace {                  // start empty namespace\nusing CppAD::vector;         // abbreviate CppAD::vector using vector\n\n// ============================================================================\n// Testing dynamic parameters in atomic_three functions.\n// ============================================================================\nclass dynamic_optimize : public CppAD::atomic_three<double> {\npublic:\n    // can use const char* name when calling this constructor\n    dynamic_optimize(const std::string& name) : // can have more arguments\n    CppAD::atomic_three<double>(name)          // inform base class of name\n    { }\n\nprivate:\n    // calculate type_y\n    virtual bool for_type(\n        const vector<double>&               parameter_x ,\n        const vector<CppAD::ad_type_enum>&  type_x      ,\n        vector<CppAD::ad_type_enum>&        type_y      )\n    {   assert( parameter_x.size() == type_x.size() );\n        bool ok = type_x.size() == 3; // n\n        ok     &= type_y.size() == 4; // m\n        if( ! ok )\n            return false;\n        type_y[0] = type_x[0];\n        type_y[1] = std::max( type_x[0], type_x[1] );\n        type_y[2] = std::max( type_x[1], type_x[2] );\n        type_y[3] = type_x[2];\n        return true;\n    }\n    // calculate depend_x\n    virtual bool rev_depend(\n        const vector<double>&               parameter_x ,\n        const vector<CppAD::ad_type_enum>&  type_x      ,\n        vector<bool>&                       depend_x    ,\n        const vector<bool>&                 depend_y    )\n    {   assert( parameter_x.size() == depend_x.size() );\n        bool ok = depend_x.size() == 3; // n\n        ok     &= depend_y.size() == 4; // m\n        if( ! ok )\n            return false;\n        depend_x[0] = depend_y[0] || depend_y[1];\n        depend_x[1] = depend_y[1] || depend_y[2];\n        depend_x[2] = depend_y[2] || depend_y[3];\n        return true;\n    }\n    virtual bool forward(\n        const vector<double>&               parameter_x ,\n        const vector<CppAD::ad_type_enum>&  type_x      ,\n        size_t                              need_y    ,\n        size_t                              order_low ,\n        size_t                              order_up  ,\n        const vector<double>&               taylor_x  ,\n        vector<double>&                     taylor_y\n    )\n    {\n# ifndef NDEBUG\n        size_t n = taylor_x.size() / (order_up + 1);\n        size_t m = taylor_y.size() / (order_up + 1);\n# endif\n        assert( n == 3 );\n        assert( m == 4 );\n        assert( order_low <= order_up );\n\n        // return flag\n        bool ok = order_up == 0;\n        if( ! ok )\n            return ok;\n\n        // g_0 = x_0 * x_0\n        taylor_y[0] = taylor_x[0] * taylor_x[0];\n        // g_1 = x_0 * x_1\n        taylor_y[1] = taylor_x[0] * taylor_x[1];\n        // g_2 = x_1 * x_2\n        taylor_y[2] = taylor_x[1] * taylor_x[2];\n        // g_3 = x_2 * x_2\n        taylor_y[3] = taylor_x[2] * taylor_x[2];\n\n        return ok;\n    }\n}; // End of dynamic_optimize class\n\n// ---------------------------------------------------------------------------\nbool optimize_dynamic_one(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps = 10. * CppAD::numeric_limits<double>::epsilon();\n    dynamic_optimize afun(\"dynamic_optimize\");\n    //\n    // constant parameter\n    double c_0 = 2.0;\n    //\n    // independent dynamic parameter vector\n    size_t np = 1;\n    CPPAD_TESTVECTOR(double) p(np);\n    CPPAD_TESTVECTOR( AD<double> ) ap(np);\n    ap[0] = p[0] = 3.0;\n    //\n    // independent variable vector\n    size_t  nu  = 1;\n    double  u_0 = 0.5;\n    CPPAD_TESTVECTOR( AD<double> ) au(nu);\n    au[0] = u_0;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(au, ap);\n\n    // create a dynamic parameter that is not used\n    AD<double> ar = 2.0 * ap[0];\n\n    // call atomic function and store result in ay\n    CPPAD_TESTVECTOR( AD<double> ) ax(3), av(4);\n    ax[0] = c_0;   // x_0 = c\n    ax[1] = ap[0]; // x_1 = p\n    ax[2] = au[0]; // x_2 = u\n    afun(ax, av);\n\n    // check type of result\n    ok &= Constant( av[0] ); // v_0 = c * c\n    ok &= Dynamic(  av[1] ); // v_1 = c * p\n    ok &= Variable( av[2] ); // v_2 = p * u\n    ok &= Variable( av[3] ); // v_3 = u * u\n\n    // range space vector\n    size_t ny = 3;\n    CPPAD_TESTVECTOR( AD<double> ) ay(ny);\n    for(size_t i = 0; i < ny; ++i)\n        ay[i] = av[i];\n\n    // create f: u -> y and stop tape recording\n    CppAD::ADFun<double> f;\n    f.Dependent (au, ay);  // f(u) = (c * c, c * p, p * u)\n\n    // sequence properties\n    ok &= f.size_dyn_ind() == 1; // p\n    ok &= f.size_dyn_par() == 3; // p, r, c * p\n    // Three constant parameters: nan, c, c * c\n    ok &= f.size_par() == 6;\n    // Normal variables: u, p * u, u * u\n    // Extra variables: phanton at index 0, y[0], y[1]\n    ok &= f.size_var() == 6;\n\n    // optimize\n    f.optimize();\n\n    // sequence properties\n    ok &= f.size_dyn_ind() == 1; // p\n    ok &= f.size_dyn_par() == 2; // c * p\n\n    // Four constant parameters: nan, zero, c, c * c\n    ok &= f.size_par() == 6;\n\n    // Normal variables: u, p * u\n    // Extra variables: phanton at index 0, y[0], y[1]\n    ok &= f.size_var() == 5;\n\n    // check\n    double check;\n\n    // check zero order forward mode\n    size_t q;\n    CPPAD_TESTVECTOR( double ) u_q(nu), y_q(ny);\n    q      = 0;\n    u_q[0] = u_0;\n    y_q    = f.Forward(q, u_q);\n    check  = c_0 * c_0;\n    ok    &= NearEqual(y_q[0] , check,  eps, eps);\n    check = c_0 * p[0];\n    ok    &= NearEqual(y_q[1] , check,  eps, eps);\n    check = p[0] * u_0;\n    ok    &= NearEqual(y_q[2] , check,  eps, eps);\n\n    // set new value for dynamic parameters\n    p[0]  = 2.0 * p[0];\n    f.new_dynamic(p);\n    y_q   = f.Forward(q, u_q);\n    check = c_0 * c_0;\n    ok    &= NearEqual(y_q[0] , check,  eps, eps);\n    check = c_0 * p[0];\n    ok    &= NearEqual(y_q[1] , check,  eps, eps);\n    check = p[0] * u_0;\n    ok    &= NearEqual(y_q[2] , check,  eps, eps);\n\n    return ok;\n}\n// ---------------------------------------------------------------------------\nbool optimize_dynamic_two(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps = 10. * CppAD::numeric_limits<double>::epsilon();\n    dynamic_optimize afun(\"dynamic_optimize\");\n    //\n    // independent dynamic parameter vector\n    size_t np = 1;\n    CPPAD_TESTVECTOR(double) p(np);\n    CPPAD_TESTVECTOR( AD<double> ) ap(np);\n    ap[0] = p[0] = 3.0;\n    //\n    // independent variable vector\n    size_t  nu  = 1;\n    double  u_0 = 0.5;\n    CPPAD_TESTVECTOR( AD<double> ) au(nu);\n    au[0] = u_0;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(au, ap);\n\n    // create a dynamic parameter that is used by atomic function\n    // but not needed to compute f(u)\n    AD<double> ar = 2.0 * ap[0];\n\n    // call atomic function and store result in ay\n    CPPAD_TESTVECTOR( AD<double> ) ax(3), av(4);\n    ax[0] = au[0]; // x_0 = u\n    ax[1] = ap[0]; // x_1 = p\n    ax[2] = ar;    // x_2 = r\n    afun(ax, av);\n\n    // check type of result\n    ok &= Variable( av[0] );  // v_0 = u * u , used\n    ok &= Variable( av[1] );  // v_1 = u * p , used\n    ok &= Dynamic( av[2] );   // v_2 = r * p , not used\n    ok &= Dynamic( av[3] );   // v_3 = r * r , not used\n\n    // range space vector\n    size_t ny = 2;\n    CPPAD_TESTVECTOR( AD<double> ) ay(ny);\n    for(size_t i = 0; i < ny; ++i)\n        ay[i] = av[i];\n\n    // create f: u -> y and stop tape recording\n    CppAD::ADFun<double> f;\n    f.Dependent (au, ay);  // f(u) = (u * u, u * p)\n\n    // sequence properties\n    ok &= f.size_dyn_ind() == 1; // p\n    ok &= f.size_dyn_par() == 4; // p, r, r * p, r * r\n    // Two constant parameters: nan, 2.0 in computation of r\n    ok &= f.size_par() == 6;\n\n\n    // optimize\n    f.optimize();\n\n    // sequence properties\n    ok &= f.size_dyn_ind() == 1; // p\n    ok &= f.size_dyn_par() == 1; // p\n    // Two constant parameter: nan, zero\n    ok &= f.size_par() == 3;\n\n    // check\n    double check;\n\n    // check zero order forward mode\n    size_t q;\n    CPPAD_TESTVECTOR( double ) u_q(nu), y_q(ny);\n    q      = 0;\n    u_q[0] = u_0;\n    y_q    = f.Forward(q, u_q);\n    check  = u_0 * u_0;\n    ok    &= NearEqual(y_q[0] , check,  eps, eps);\n    check = u_0 * p[0];\n    ok    &= NearEqual(y_q[1] , check,  eps, eps);\n\n    // set new value for dynamic parameters\n    p[0]  = 2.0 * p[0];\n    f.new_dynamic(p);\n    y_q   = f.Forward(q, u_q);\n    check = u_0 * u_0;\n    ok    &= NearEqual(y_q[0] , check,  eps, eps);\n    check = u_0 * p[0];\n    ok    &= NearEqual(y_q[1] , check,  eps, eps);\n\n    return ok;\n}\n// ---------------------------------------------------------------------------\nbool optimize_dynamic_three(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps = 10. * CppAD::numeric_limits<double>::epsilon();\n    dynamic_optimize afun(\"dynamic_optimize\");\n    //\n    // independent dynamic parameter vector\n    size_t np = 1;\n    CPPAD_TESTVECTOR(double) p(np);\n    CPPAD_TESTVECTOR( AD<double> ) ap(np);\n    ap[0] = p[0] = 3.0;\n    //\n    // independent variable vector\n    size_t  nu  = 1;\n    double  u_0 = 0.5;\n    CPPAD_TESTVECTOR( AD<double> ) au(nu);\n    au[0] = u_0;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(au, ap);\n\n    // create a dynamic parameter that is used by atomic function\n    // but not needed to compute f(u)\n    AD<double> ar = 2.0 * ap[0];\n\n    // call atomic function and store result in ay\n    CPPAD_TESTVECTOR( AD<double> ) ax(3), av(4);\n    ax[0] = au[0]; // x_0 = u\n    ax[1] = ar;    // x_1 = r\n    ax[2] = ap[0]; // x_2 = p\n    afun(ax, av);\n\n    // check type of result\n    ok &= Variable( av[0] );  // v_0 = u * u , used\n    ok &= Variable( av[1] );  // v_1 = u * r , used\n    ok &= Dynamic( av[2] );   // v_2 = r * p , not used\n    ok &= Dynamic( av[3] );   // v_3 = p * p , not used\n\n    // range space vector\n    size_t ny = 2;\n    CPPAD_TESTVECTOR( AD<double> ) ay(ny);\n    for(size_t i = 0; i < ny; ++i)\n        ay[i] = av[i];\n\n    // create f: u -> y and stop tape recording\n    CppAD::ADFun<double> f;\n    f.Dependent (au, ay);  // f(u) = (u * u, u * p)\n\n    // sequence properties\n    ok &= f.size_dyn_ind() == 1; // p\n    ok &= f.size_dyn_par() == 4; // p, r, r * p, p * p\n    // Two constant parameters: nan, 2.0 in computation of r\n    ok &= f.size_par() == 6;\n\n\n    // optimize\n    f.optimize();\n\n    // sequence properties\n    ok &= f.size_dyn_ind() == 1; // p\n    ok &= f.size_dyn_par() == 2; // p, r\n    // Three constant parameters: nan, zero, 2.0 in computation of r\n    ok &= f.size_par() == 5;\n\n    // check\n    double check;\n\n    // check zero order forward mode\n    double r = 2.0 * p[0];\n    size_t q;\n    CPPAD_TESTVECTOR( double ) u_q(nu), y_q(ny);\n    q      = 0;\n    u_q[0] = u_0;\n    y_q    = f.Forward(q, u_q);\n    check  = u_0 * u_0;\n    ok    &= NearEqual(y_q[0] , check,  eps, eps);\n    check = u_0 * r;\n    ok    &= NearEqual(y_q[1] , check,  eps, eps);\n\n    // set new value for dynamic parameters\n    p[0]  = 2.0 * p[0];\n    r     = 2.0 * p[0];\n    f.new_dynamic(p);\n    y_q   = f.Forward(q, u_q);\n    check = u_0 * u_0;\n    ok    &= NearEqual(y_q[0] , check,  eps, eps);\n    check = u_0 * r;\n    ok    &= NearEqual(y_q[1] , check,  eps, eps);\n\n    return ok;\n}\n// ============================================================================\n// Testing Variables that get removed\n// ============================================================================\nclass variable_optimize : public CppAD::atomic_three<double> {\npublic:\n    // can use const char* name when calling this constructor\n    variable_optimize(const std::string& name) : // can have more arguments\n    CppAD::atomic_three<double>(name)          // inform base class of name\n    { }\n\nprivate:\n    // calculate type_y\n    virtual bool for_type(\n        const vector<double>&               parameter_x ,\n        const vector<CppAD::ad_type_enum>&  type_x      ,\n        vector<CppAD::ad_type_enum>&        type_y      )\n    {   assert( parameter_x.size() == type_x.size() );\n        bool ok = type_x.size() == 2; // n\n        ok     &= type_y.size() == 2; // m\n        if( ! ok )\n            return false;\n        type_y[0] = type_x[0];\n        type_y[1] = std::max( type_x[0], type_x[1] );\n        return true;\n    }\n    // calculate depend_x\n    virtual bool rev_depend(\n        const vector<double>&               parameter_x ,\n        const vector<CppAD::ad_type_enum>&  type_x      ,\n        vector<bool>&                       depend_x    ,\n        const vector<bool>&                 depend_y    )\n    {   assert( parameter_x.size() == depend_x.size() );\n        bool ok = depend_x.size() == 2; // n\n        ok     &= depend_y.size() == 2; // m\n        if( ! ok )\n            return false;\n        depend_x[0] = depend_y[0] || depend_y[1];\n        depend_x[1] = depend_y[1];\n        return true;\n    }\n    virtual bool forward(\n        const vector<double>&               parameter_x ,\n        const vector<CppAD::ad_type_enum>&  type_x      ,\n        size_t                              need_y    ,\n        size_t                              order_low ,\n        size_t                              order_up  ,\n        const vector<double>&               taylor_x  ,\n        vector<double>&                     taylor_y\n    )\n    {\n# ifndef NDEBUG\n        size_t n = taylor_x.size() / (order_up + 1);\n        size_t m = taylor_y.size() / (order_up + 1);\n# endif\n        assert( n == 2 );\n        assert( m == 2 );\n        assert( order_low <= order_up );\n\n        // return flag\n        bool ok = order_up == 0;\n        if( ! ok )\n            return ok;\n\n        // g_0 = exp( x_0 )\n        taylor_y[0] = std::exp( taylor_x[0] );\n        // g_1 = exp( x_0 * x_1 )\n        taylor_y[1] = std::exp( taylor_x[0] * taylor_x[1] );\n\n        return ok;\n    }\n    virtual bool reverse(\n        const vector<double>&               parameter_x ,\n        const vector<CppAD::ad_type_enum>&  type_x      ,\n        size_t                              order_up    ,\n        const vector<double>&               taylor_x    ,\n        const vector<double>&               taylor_y    ,\n        vector<double>&                     partial_x   ,\n        const vector<double>&               partial_y\n    )\n    {\n        size_t q1 = order_up + 1;\n        size_t n  = taylor_x.size() / q1;\n# ifndef NDEBUG\n        size_t m  = taylor_y.size() / q1;\n# endif\n        assert( n == 2 );\n        assert( m == 2 );\n\n        // return flag\n        bool ok = order_up == 0;\n        if( ! ok )\n            return ok;\n\n        // initialize summation as zero\n        for(size_t j = 0; j < n; ++j)\n            partial_x[j] = 0.0;\n\n        // g_0  = exp( x_0 )\n        partial_x[0] += partial_y[0] * taylor_y[0];\n        // g_1 = exp( x_0 * x_1 )\n        partial_x[0] += partial_y[1] * taylor_y[1] * taylor_x[1];\n        partial_x[1] += partial_y[1] * taylor_y[1] * taylor_x[0];\n        //\n        return ok;\n    }\n}; // End of variable_optimize class\n// ---------------------------------------------------------------------------\nbool optimize_variable_one(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps = 10. * CppAD::numeric_limits<double>::epsilon();\n    variable_optimize afun(\"variable_optimize\");\n    //\n    // independent variable vector\n    size_t  nu  = 2;\n    CPPAD_TESTVECTOR( AD<double> ) au(nu);\n    for(size_t j = 0; j < nu; ++j)\n        au[j] = double(j + 1);\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(au);\n\n    // call atomic function and store result in ay\n    CPPAD_TESTVECTOR( AD<double> ) ax(nu), av(nu);\n    for(size_t j = 0; j < nu; ++j)\n        ax[j] = au[j] / 2.0; // x = u / 2\n    afun(ax, av);\n\n    // check type of result\n    for(size_t j = 0; j < nu; ++j)\n        ok &= Variable( av[j] );\n\n    // range space vector\n    size_t ny = 1;\n    CPPAD_TESTVECTOR( AD<double> ) ay(ny);\n    //\n    // only the first component of av affects the function value\n    ay[0] = av[0];\n\n    // create f: u -> y and stop tape recording\n    CppAD::ADFun<double> f;\n    f.Dependent (au, ay);  // f(u) = exp( u[0] / 2 )\n\n    // optimize\n    f.optimize();\n\n    // check\n    double check;\n\n    // check zero order forward mode\n    CPPAD_TESTVECTOR( double ) u(nu), y(ny);\n    for(size_t j = 0; j < nu; ++j)\n        u[j] = double(j + 1) / double(nu);\n    y    = f.Forward(0, u);\n    check  = std::exp( u[0] / 2.0 );\n    ok    &= NearEqual(y[0] , check,  eps, eps);\n\n    // Check first order reverse mode. This test would vaile when\n    // nan was used for argument and function values that were optimized out\n    // because they were not used.\n    CPPAD_TESTVECTOR( double ) w(ny), dw(nu);\n    w[0] = 1.0;\n    dw  = f.Reverse(1, w);\n    check  = std::exp( u[0] / 2.0 ) / 2.0;\n    ok    &= NearEqual(dw[0] , check,  eps, eps);\n    check  = 0.0;\n    ok    &= NearEqual(dw[1] , check,  eps, eps);\n    //\n    return ok;\n}\n}  // End empty namespace\n\nbool atomic_three(void)\n{   bool ok = true;\n    ok     &= optimize_dynamic_one();\n    ok     &= optimize_dynamic_two();\n    ok     &= optimize_dynamic_three();\n    ok     &= optimize_variable_one();\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/azmul.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/cppad.hpp>\n# include <cmath>\n\nnamespace {\n    bool test_base2ad(void)\n    {   bool ok = true;\n        double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n        using CppAD::AD;\n\n        // Both recordiings are done with the dynamic  parameter p = 0, 1\n        // to make sure does not short circuit multiply\n        for(size_t ip = 0; ip < 2; ++ip)\n        {\n            // f(p; x) = p[0] * x[0] * x[0]\n            CPPAD_TESTVECTOR(AD<double>)  ap(1), ax(1), ay(1), aw(1);\n            ap[0] = double(ip);\n            ax[0] = 0.0;\n            CppAD::Independent(ax, ap);\n            ay[0] = ap[0] * ax[0] * ax[0];\n            CppAD::ADFun<double> f(ax, ay);\n\n            // AD version of f\n            CppAD::ADFun< AD<double> , double > af = f.base2ad();\n\n            // g(p; x) = d/dx f(p, x) = 2 * p[0] * x[0]\n            CppAD::Independent(ax, ap);\n            af.new_dynamic(ap);\n            af.Forward(0, ax);\n            aw[0] = 1.0;\n            ay    = af.Reverse(1, aw);\n            CppAD::ADFun<double> g(ax, ay);\n\n            // Evaluate g(p, x)\n            CPPAD_TESTVECTOR(double) p(1), x(1), y(1);\n            p[0] = 2.0;\n            x[0] = 3.0;\n            g.new_dynamic(p);\n            y = g.Forward(0, x);\n\n            // check result\n            double check = 2.0 * p[0] * x[0];\n            ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n        }\n        return ok;\n    }\n    bool test_forward(void)\n    {   bool ok = true;\n\n        using CppAD::AD;\n        using CppAD::NearEqual;\n        double inf = std::numeric_limits<double>::infinity();\n        double eps = 10. * std::numeric_limits<double>::epsilon();\n\n        typedef AD<double>    a1double;\n        typedef AD<a1double>  a2double;\n\n        // domain space vector\n        size_t n = 2;\n        size_t m = 3;\n\n        // double level\n        CPPAD_TESTVECTOR(double) x(n), z(m);\n        x[0] = 3.0;\n        x[1] = 4.0;\n\n        // start a1 level recording\n        CPPAD_TESTVECTOR(a1double) a1x(n), a1dx(n), a1y(m), a1z(m);\n        for(size_t j = 0; j < n; j++)\n            a1x[j] = x[j];\n        CppAD::Independent(a1x);\n\n        // start a2 level recording\n        CPPAD_TESTVECTOR(a2double) a2x(n), a2y(m);\n        for(size_t j = 0; j < n; j++)\n            a2x[j] = a1x[j];\n        CppAD::Independent(a2x);\n\n        // y\n        a2y[0] = CppAD::azmul(a2x[0], a2x[1]); // azmul(variable, variable)\n        a2y[1] = CppAD::azmul(a1x[0], a2x[1]); // azmul(parameter, variable)\n        a2y[2] = CppAD::azmul(a2x[0], a1x[1]); // azmul(variable, parameter)\n\n        // create f: x -> y and stop a2 recording\n        CppAD::ADFun<a1double> a1f;\n        a1f.Dependent(a2x, a2y);\n\n        // check y\n        a1y = a1f.Forward(0, a1x);  // azmul(variable, variable) only\n        for(size_t i = 0; i < m; i++)\n            ok &= NearEqual(a1y[i] , x[0] * x[1],  eps, eps);\n\n        for(size_t j = 0; j < n; j++)\n            a1dx[j] = a1double(1.0);\n        a1z = a1f.Forward(1, a1dx);\n\n        // create g: x -> z and stop a1 recording\n        CppAD::ADFun<double> g;\n        g.Dependent(a1x, a1z);\n\n        // check value when x[0] is not zero\n        z = g.Forward(0, x);\n\n        // z_0 = d_lambda [ ( x[0] + lambda ) * ( x[1] + lambda ) ]\n        ok &= NearEqual(z[0] , x[0] + x[1],  eps, eps);\n\n        // z_1 = d_lambda [ x[0] * ( x[1] + lambda ) ]\n        ok &= NearEqual(z[1] , x[0],  eps, eps);\n\n        // z_2 = d_lambda [ ( x[0] + lambda ) * x[1] ]\n        ok &= NearEqual(z[2] , x[1],  eps, eps);\n\n        // check value x[0] is zero and x[1] is infinity\n        x[0] = 0.0;\n        x[1] = inf;\n        z    = g.Forward(0, x);\n        ok  &= z[0] == inf;\n        ok  &= z[1] == 0.0;\n        ok  &= z[2] == inf;\n\n        return ok;\n    }\n    bool test_reverse(void)\n    {   bool ok = true;\n\n        using CppAD::AD;\n        using CppAD::NearEqual;\n        double inf = std::numeric_limits<double>::infinity();\n        double eps = 10. * std::numeric_limits<double>::epsilon();\n\n        typedef AD<double>    a1double;\n        typedef AD<a1double>  a2double;\n\n        // domain space vector\n        size_t n = 2;\n        size_t m = 3;\n\n        // double level\n        CPPAD_TESTVECTOR(double) x(n), z(n);\n        x[0] = 3.0;\n        x[1] = 4.0;\n\n        // start a1 level recording\n        CPPAD_TESTVECTOR(a1double) a1x(n), a1dx(n), a1w(m), a1z(n);\n        for(size_t j = 0; j < n; j++)\n            a1x[j] = x[j];\n        CppAD::Independent(a1x);\n\n        // start a2 level recording\n        CPPAD_TESTVECTOR(a2double) a2x(n), a2y(m);\n        for(size_t j = 0; j < n; j++)\n            a2x[j] = a1x[j];\n        CppAD::Independent(a2x);\n\n        // y\n        a2y[0] = CppAD::azmul(a2x[0], a2x[1]); // azmul(variable, variable)\n        a2y[1] = CppAD::azmul(a1x[0], a2x[1]); // azmul(parameter, variable)\n        a2y[2] = CppAD::azmul(a2x[0], a1x[1]); // azmul(variable, parameter)\n\n        // create f: x -> y and stop a2 recording\n        CppAD::ADFun<a1double> a1f;\n        a1f.Dependent(a2x, a2y);\n\n        // w(x) = y[0] + y[1] + y[2]\n        for(size_t i = 0; i < m; i++)\n            a1w[i] = a1double(1.0);\n        a1f.Forward(0, a1x);\n        a1dx = a1f.Reverse(1, a1w);\n\n        // create g: x -> z and stop a1 recording\n        CppAD::ADFun<double> g;\n        g.Dependent(a1x, a1dx);\n\n        // check value when x[0] is not zero\n        z = g.Forward(0, x);\n\n        // partial y[0] w.r.t x[0] = x[1]\n        // partial y[1] w.r.t x[0] = 0\n        // partial y[2] w.r.t x[0] = x[1]\n        ok &= NearEqual(z[0] , x[1] + x[1],  eps, eps);\n\n        // partial y[0] w.r.t x[1] = x[0]\n        // partial y[1] w.r.t x[1] = x[0]\n        // partial y[2] w.r.t x[1] = 0\n        ok &= NearEqual(z[1] , x[0] + x[0],  eps, eps);\n\n        // check value x[0] is zero and x[1] is infinity\n        x[0] = 0.0;\n        x[1] = inf;\n        z    = g.Forward(0, x);\n        ok  &= z[0] == inf;\n        ok  &= z[1] == 0.0;\n\n        return ok;\n    }\n    bool test_forward_dir(void)\n    {   bool ok = true;\n\n        using CppAD::AD;\n        using CppAD::NearEqual;\n        double inf = std::numeric_limits<double>::infinity();\n        double eps = 10. * std::numeric_limits<double>::epsilon();\n\n        typedef AD<double>    a1double;\n        typedef AD<a1double>  a2double;\n\n        // domain space vector\n        size_t n = 2;\n        size_t m = 3;\n        size_t r = 2;\n\n        // double level\n        CPPAD_TESTVECTOR(double) x(n), z(r * m);\n        x[0] = 3.0;\n        x[1] = 4.0;\n\n        // start a1 level recording\n        CPPAD_TESTVECTOR(a1double) a1x(n), a1dx(r * n), a1y(m), a1z(r * m);\n        for(size_t j = 0; j < n; j++)\n            a1x[j] = x[j];\n        CppAD::Independent(a1x);\n\n        // start a2 level recording\n        CPPAD_TESTVECTOR(a2double) a2x(n), a2y(m);\n        for(size_t j = 0; j < n; j++)\n            a2x[j] = a1x[j];\n        CppAD::Independent(a2x);\n\n        // y\n        a2y[0] = CppAD::azmul(a2x[0], a2x[1]); // azmul(variable, variable)\n        a2y[1] = CppAD::azmul(a1x[0], a2x[1]); // azmul(parameter, variable)\n        a2y[2] = CppAD::azmul(a2x[0], a1x[1]); // azmul(variable, parameter)\n\n        // create f: x -> y and stop a2 recording\n        CppAD::ADFun<a1double> a1f;\n        a1f.Dependent(a2x, a2y);\n\n        // check y\n        a1y = a1f.Forward(0, a1x);  // azmul(variable, variable) only\n        for(size_t i = 0; i < m; i++)\n            ok &= NearEqual(a1y[i] , x[0] * x[1],  eps, eps);\n\n        for(size_t j = 0; j < n; j++)\n        {   for(size_t ell = 0; ell < r; ell++)\n                a1dx[r * j + ell] = a1double(1.0 + double(ell));\n        }\n        a1z = a1f.Forward(1, r, a1dx);\n\n\n        // create g: x -> z and stop a1 recording\n        CppAD::ADFun<double> g;\n        g.Dependent(a1x, a1z);\n\n        // check value when x[0] is not zero\n        z = g.Forward(0, x);\n\n        // z_00 = d_lambda [ ( x[0] + lambda ) * ( x[1] + lambda ) ]\n        ok &= NearEqual(z[r * 0 + 0] , x[0] + x[1],  eps, eps);\n\n        // z_01 = d_lambda [ ( x[0] + 2 * lambda ) * ( x[1] + 2 * lambda ) ]\n        ok &= NearEqual(z[r * 0 + 1] , 2.0*(x[0] + x[1]),  eps, eps);\n\n        // z_10 = d_lambda [ x[0] * ( x[1] + lambda ) ]\n        ok &= NearEqual(z[r * 1 + 0] , x[0],  eps, eps);\n\n        // z_11 = d_lambda [ x[0] * ( x[1] + 2 * lambda ) ]\n        ok &= NearEqual(z[r * 1 + 1] , 2.0 * x[0],  eps, eps);\n\n        // z_20 = d_lambda [ ( x[0] + lambda ) * x[1] ]\n        ok &= NearEqual(z[r * 2 + 0] , x[1],  eps, eps);\n\n        // z_21 = d_lambda [ ( x[0] + 2 * lambda ) * x[1] ]\n        ok &= NearEqual(z[r * 2 + 1] , 2.0 * x[1],  eps, eps);\n\n        // check value x[0] is zero and x[1] is infinity\n        x[0] = 0.0;\n        x[1] = inf;\n        z    = g.Forward(0, x);\n        ok  &= z[r * 0 + 0] == inf;\n        ok  &= z[r * 0 + 1] == inf;\n        ok  &= z[r * 1 + 0] == 0.0;\n        ok  &= z[r * 1 + 1] == 0.0;\n        ok  &= z[r * 2 + 0] == inf;\n        ok  &= z[r * 2 + 1] == inf;\n\n        return ok;\n    }\n}\nbool azmul(void)\n{   bool ok = true;\n\n    ok &= test_base2ad();\n    ok &= test_forward();\n    ok &= test_reverse();\n    ok &= test_forward_dir();\n\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/base2ad.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n// Tests corresponding to some base2ad bug fixes; i.e., regression test\n\n# include <cppad/cppad.hpp>\n\nnamespace { // BEGIN_EMPTY_NAMESPACE\n    //\n    // my_integer\n    double my_integer(const double& x)\n    {   return std::floor(x); }\n    CPPAD_DISCRETE_FUNCTION(double, my_integer);\n    //\n    // discrete\n    bool discrete(void)\n    {   bool ok = true;\n        using CppAD::AD;\n        //\n        // af\n        CPPAD_TESTVECTOR( AD<double> ) ax(1), ay(1);\n        ax[0] = 2.5;\n        Independent( ax );\n        ay[0] = my_integer( ax[0] );\n        CppAD::ADFun<double> f(ax, ay);\n        CppAD::ADFun< AD<double>, double> af = f.base2ad();\n        //\n        // g\n        Independent( ax );\n        ay = af.Forward(0, ax);\n        CppAD::ADFun<double> g(ax, ay);\n        //\n        // ok\n        CPPAD_TESTVECTOR(double) x(1), y(1);\n        x[0] = 5.5;\n        y    = g.Forward(0, x);\n        ok &= y[0] == std::floor( x[0] );\n        //\n        return ok;\n    }\n} // END_EMPTY_NAMESPACE\n\nbool base2ad(void)\n{   bool ok = true;\n\n    ok &= discrete();\n\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/base_adolc.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n// adolc examples should suppress conversion warnings\n# include <cppad/wno_conversion.hpp>\n\n# include <adolc/adouble.h>\n# include <adolc/taping.h>\n# include <adolc/interfaces.h>\n\n// adouble definitions not in Adolc distribution and\n// required in order to use CppAD::AD<adouble>\n# include <cppad/example/base_adolc.hpp>\n\n# include <cppad/cppad.hpp>\n\nbool base_adolc(void)\n{   bool ok = true;                   // initialize test result\n\n    typedef adouble             ADdouble;  // for first level of taping\n    typedef CppAD::AD<ADdouble> ADDdouble; // for second level of taping\n    size_t n = 4;                          // number independent variables\n\n    CPPAD_TESTVECTOR(ADdouble)   a_x(n);\n    CPPAD_TESTVECTOR(ADDdouble) aa_x(n);\n\n    // value of the independent variables\n    short tag = 0;      // Adolc setup\n    int keep = 1;\n    trace_on(tag, keep);\n    size_t j;\n    for(j = 0; j < n; j++)\n        a_x[j] <<= double(n - j);  // a_x is independent for ADdouble\n    for(j = 0; j < n; j++)\n        aa_x[j] = a_x[j];          // track how aa_x depends on a_x\n    CppAD::Independent(aa_x);          // aa_x is independent for ADDdouble\n\n\n    // compute function\n    size_t m = 5;\n    CPPAD_TESTVECTOR(ADDdouble) aa_f(m);    // dependent variables\n\n    // different cases of conditional expressions\n    aa_f[0] = CondExpLt(aa_x[0], aa_x[1], aa_x[2], aa_x[3]);\n    aa_f[1] = CondExpLe(aa_x[0], aa_x[1], aa_x[2], aa_x[3]);\n    aa_f[2] = CondExpEq(aa_x[0], aa_x[1], aa_x[2], aa_x[3]);\n    aa_f[3] = CondExpGe(aa_x[0], aa_x[1], aa_x[2], aa_x[3]);\n    aa_f[4] = CondExpGt(aa_x[0], aa_x[1], aa_x[2], aa_x[3]);\n\n    // declare inner function (just to stop inner taping)\n    CppAD::ADFun<ADdouble> a_F(aa_x, aa_f);\n\n    // set values for outer function same as inner function\n    // (corresponding to the tape of adobule operations)\n    double f_j;\n    for(j = 0; j < m; j++)\n        Value(aa_f[j]) >>= f_j;\n    trace_off();\n\n    // arrays for Adolc zos_forward\n    double *x = nullptr, *y = nullptr;\n    x = CPPAD_TRACK_NEW_VEC(n, x);\n    y = CPPAD_TRACK_NEW_VEC(m, y);\n\n    // switch order of arguments from when taping was done\n    for(j = 0; j < n; j++)\n        x[j] = double(j);\n    zos_forward(tag, int(m), int(n), keep, x, y);\n    // CondExpLt(0, 1, 2, 3)\n    ok &= (y[0] == double(2));\n    // CondExpLe(0, 1, 2, 3)\n    ok &= (y[1] == double(2));\n    // CondExpEq(0, 1, 2, 3)\n    ok &= (y[2] == double(3));\n    // CondExpGe(0, 1, 2, 3)\n    ok &= (y[3] == double(3));\n    // CondExpGt(0, 1, 2, 3)\n    ok &= (y[4] == double(3));\n\n    // set left = right and true < false\n    x[0] = x[1] = 1.;\n    x[2] = 2.;\n    x[3] = 3.;\n    zos_forward(tag, int(m), int(n), keep, x, y);\n    // CondExpLt(1, 1, 2, 3)\n    ok &= (y[0] == double(3));\n    // CondExpLe(1, 1, 2, 3)\n    ok &= (y[1] == double(2));\n    // CondExpEq(1, 1, 2, 3)\n    ok &= (y[2] == double(2));\n    // CondExpGe(1, 1, 2, 3)\n    ok &= (y[3] == double(2));\n    // CondExpGt(1, 1, 2, 3)\n    ok &= (y[4] == double(3));\n\n    CPPAD_TRACK_DEL_VEC(x);\n    CPPAD_TRACK_DEL_VEC(y);\n    return ok;\n}\n// END PROGRAM\n"
  },
  {
    "path": "test_more/general/base_alloc.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include \"../../example/general/base_alloc.hpp\"\n# include <cppad/cppad.hpp>\n\nnamespace { // BEGIN empty namespace\n\nbool test_parameter(void)\n{   bool ok = true;\n    typedef CppAD::AD<base_alloc> my_ad;\n\n    // y = x + 0 + 1 + 2 + ... + N-1\n    CppAD::vector<my_ad>   a_x, a_y;\n    a_x.resize(1);\n    a_x[0] = my_ad(1.);\n    CppAD::Independent(a_x);\n    a_y.resize(1);\n    a_y[0] = a_x[0];\n\n    // create a new parameter for each iteration of this loop\n    size_t i, N = 50;\n    for(i = 0; i < N; i++)\n        a_y[0] += double(i);\n\n    CppAD::ADFun<base_alloc> f(a_x, a_y);\n\n    return ok;\n}\n\nbool test_numeric_limits(void)\n{   bool ok = true;\n    typedef CppAD::AD<base_alloc> my_ad;\n    //\n    base_alloc eps = Value( CppAD::numeric_limits<my_ad>::epsilon() );\n    ok            &= *eps.ptrdbl_ == std::numeric_limits<double>::epsilon();\n    //\n    base_alloc min = Value( CppAD::numeric_limits<my_ad>::min() );\n    ok            &= *min.ptrdbl_ == std::numeric_limits<double>::min();\n    //\n    base_alloc max = Value( CppAD::numeric_limits<my_ad>::max() );\n    ok            &= *max.ptrdbl_ == std::numeric_limits<double>::max();\n    //\n    base_alloc nan = Value( CppAD::numeric_limits<my_ad>::quiet_NaN() );\n    ok            &= *nan.ptrdbl_ != *nan.ptrdbl_;\n    //\n    int   digits10 = CppAD::numeric_limits<my_ad>::digits10;\n    ok            &= digits10 == std::numeric_limits<double>::digits10;\n    //\n    return ok;\n}\n\nbool test_to_string(void)\n{   bool ok = true;\n    typedef CppAD::AD<base_alloc> my_ad;\n    //\n    double      dbl_pi = 4.0 * std::atan(1.0);\n    my_ad       ad_pi  = my_ad(dbl_pi);\n    std::string str_pi = to_string( ad_pi );\n    //\n    // Check the length of the string \"3.1415...\". One extra character\n    // for machine epsilon precision and another for the decimal point.\n    ok &= str_pi.size() == size_t( 2 + std::numeric_limits<double>::digits10 );\n    //\n    // check value\n    double eps   = std::numeric_limits<double>::epsilon();\n    double check = std::atof( str_pi.c_str() );\n    ok          &= (check / dbl_pi - 1.0) <= eps;\n    //\n    return ok;\n}\n\n\n} // END empty namespace\n\nbool base_alloc_test(void)\n{   bool ok = true;\n    //\n    ok     &= test_parameter();\n    ok     &= test_numeric_limits();\n    ok     &= test_to_string();\n    //\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/base_complex.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n#include <cppad/cppad.hpp>\n\nbool base_complex(void)\n{   // ok\n    bool ok = true;\n    //\n    // base, ad_base\n    typedef std::complex<double> base;\n    typedef CppAD::AD<base>      ad_base;\n    //\n    // f\n    CPPAD_TESTVECTOR(ad_base) ax(1), ay(1);\n    ax[0] = 0.0;\n    CppAD::Independent(ax);\n    ay[0] = ax[0] * ax[0];\n    CppAD::ADFun<base> f(ax, ay);\n    //\n    // f\n    f.optimize();\n    //\n    // dy\n    std::vector<base> x(1), dx(1), dy(1);\n    x[0]  = 5;\n    f.Forward(0, x);\n    dx[0] = 1;\n    dy    = f.Forward(1, dx);\n    //\n    // ok\n    ok &= dy[0] == 2.0 * x[0];\n    //\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/bool_sparsity.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\nOld example / test\n@begin bool_sparsity.cpp$$\n$spell\n    Bool\n$$\n\n$section Using vectorBool Sparsity To Conserve Memory: Example and Test$$\n\n$head Purpose$$\nThis example show how to conserve memory when computing sparsity patterns.\n\n$srcthisfile%0%// BEGIN C++%// END C++%1%$$\n\n@end\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\nnamespace {\n    using CppAD::vector;\n    using std::cout;\n    using CppAD::vectorBool;\n    using CppAD::AD;\n    using CppAD::ADFun;\n\n    // function f(x) that we are computing sparsity patterns for\n    template <class Float>\n    vector<Float> fun(const vector<Float>& x)\n    {   size_t n  = x.size();\n        vector<Float> ret(n + 1);\n        for(size_t j = 0; j < n; j++)\n        {   size_t k = (j + 1) % n;\n            ret[j] = x[j] * x[j] * x[k];\n        }\n        ret[n] = 0.0;\n        return ret;\n    }\n    // check sparsity pattern for f(x)\n    bool check_jac(const vectorBool& pattern, size_t n)\n    {   bool ok = true;\n        for(size_t i = 0; i < n; i++)\n        {   size_t k = (i + 1) % n;\n            for(size_t j = 0; j < n; j++)\n            {   bool non_zero = (i == j) || (j == k);\n                ok &= pattern[ i * n + j] == non_zero;\n            }\n        }\n        for(size_t j = 0; j < n; j++)\n            ok &= pattern[ n * n + j] == false;\n        return ok;\n    }\n    // check sparsity pattern for the Hessian of sum_i f_i(x)\n    bool check_hes(const vectorBool& pattern, size_t n)\n    {   bool ok = true;\n        for(size_t i = 0; i < n; i++)\n        {   size_t k1 = (i + 1) % n;\n            size_t k2 = (n + i - 1) % n;\n            for(size_t j = 0; j < n; j++)\n            {   bool non_zero = (i == j) || (j == k1) || (j == k2);\n                ok &= pattern[ i * n + j] == non_zero;\n            }\n        }\n        return ok;\n    }\n    // compute sparsity for Jacobian of f(x) using forward mode\n    bool for_sparse_jac(ADFun<double>& f)\n    {   bool ok = true;\n        size_t n = f.Domain();\n        size_t m = f.Range();\n        //\n        // number of columns of the sparsity patter to compute at a time\n        size_t n_col = vectorBool::bit_per_unit();\n        vectorBool pattern(m * n), s(m * n_col), r(n * n_col);\n        //\n        size_t n_loop = (n - 1) / n_col + 1;\n        for(size_t i_loop = 0; i_loop < n_loop; i_loop++)\n        {   size_t j_col = i_loop * n_col;\n\n            for(size_t i = 0; i < n; i++)\n            {   for(size_t j = 0; j < n_col; j++)\n                    r[i * n_col + j] = (i == j_col + j);\n            }\n            s = f.ForSparseJac(n_col, r);\n            for(size_t i = 0; i < m; i++)\n            {   for(size_t j = 0; j < n_col; j++)\n                    if( j_col + j < n )\n                        pattern[ i * n + j_col + j ] = s[ i * n_col + j];\n            }\n        }\n        ok &= check_jac(pattern, n);\n        //\n        return ok;\n    }\n    // compute sparsity for Jacobian of f(x) using reverse mode\n    bool rev_sparse_jac(ADFun<double>& f)\n    {   bool ok = true;\n        size_t n = f.Domain();\n        size_t m = f.Range();\n        //\n        // number of rows of the sparsity patter to compute at a time\n        size_t n_row = vectorBool::bit_per_unit();\n        vectorBool pattern(m * n), s(n_row * n), r(n_row * m);\n        //\n        size_t n_loop = (m - 1) / n_row + 1;\n        for(size_t i_loop = 0; i_loop < n_loop; i_loop++)\n        {   size_t i_row = i_loop * n_row;\n\n            for(size_t i = 0; i < n_row; i++)\n            {   for(size_t j = 0; j < m; j++)\n                    r[i * m + j] = (i_row + i == j);\n            }\n            s = f.RevSparseJac(n_row, r);\n            for(size_t i = 0; i < n_row; i++)\n            {   for(size_t j = 0; j < n; j++)\n                    if( i_row + i < m )\n                        pattern[ (i_row + i) * n + j ] = s[ i * n + j];\n            }\n        }\n        ok &= check_jac(pattern, n);\n        //\n        return ok;\n    }\n    // compute sparsity for Hessian of sum_i f_i (x)\n    bool rev_sparse_hes(ADFun<double>& f)\n    {   bool ok = true;\n        size_t n = f.Domain();\n        size_t m = f.Range();\n        //\n        // number of columns of the sparsity patter to compute at a time\n        size_t n_col = vectorBool::bit_per_unit();\n        vectorBool pattern(n * n), r(n * n_col), h(n * n_col);\n\n        // consider case where Hessian for sum of f_i(x) w.r.t i\n        vectorBool s(m);\n        for(size_t i = 0; i < m; i++)\n            s[i] = true;\n        //\n        size_t n_loop = (n - 1) / n_col + 1;\n        for(size_t i_loop = 0; i_loop < n_loop; i_loop++)\n        {   size_t j_col = i_loop * n_col;\n\n            for(size_t i = 0; i < n; i++)\n            {   for(size_t j = 0; j < n_col; j++)\n                    r[i * n_col + j] = (i == j_col + j);\n            }\n            //\n            f.ForSparseJac(n_col, r);\n            bool transpose = true;\n            h = f.RevSparseHes(n_col, s, transpose);\n            //\n            for(size_t i = 0; i < n; i++)\n            {   for(size_t j = 0; j < n_col; j++)\n                    if( j_col + j < n )\n                        pattern[ i * n + j_col + j ] = h[ i * n_col + j];\n            }\n        }\n        ok &= check_hes(pattern, n);\n        //\n        return ok;\n    }\n}\n// driver for all of the cases above\nbool bool_sparsity(void)\n{   bool ok = true;\n    //\n    // record the function\n    size_t n = 100;\n    size_t m = n + 1;\n    vector< AD<double> > x(n), y(m);\n    for(size_t j = 0; j < n; j++)\n        x[j] = AD<double>(j+1);\n    CppAD::Independent(x);\n    y = fun(x);\n    ADFun<double> f(x, y);\n    //\n    // run the three example / tests\n    ok &= for_sparse_jac(f);\n    ok &= rev_sparse_jac(f);\n    ok &= rev_sparse_hes(f);\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "test_more/general/check_simple_vector.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/cppad.hpp>\n# include <set>\n# include <vector>\n# include <valarray>\n\nnamespace {\n    template <class Scalar>\n    void Case(const Scalar& x, const Scalar& y)\n    {   using CppAD::CheckSimpleVector;\n\n        CheckSimpleVector<Scalar, CppAD::vector<Scalar> > (x, y);\n        CheckSimpleVector<Scalar, std::vector<Scalar>   > (x, y);\n        CheckSimpleVector<Scalar, std::valarray<Scalar> > (x, y);\n        typedef CPPAD_TESTVECTOR(Scalar) testvector;\n        CheckSimpleVector<Scalar, testvector > (x, y);\n    }\n}\nbool check_simple_vector(void)\n{   // Unusual test in that CheckSimpleVector will abort if an error occurs\n    Case(float(0), float(1));\n    Case(double(0), double(1));\n    //\n    std::set<size_t> x, y;\n    x.insert(1);\n    y.insert(2);\n    Case(x, y);\n    //\n    return true;\n}\n"
  },
  {
    "path": "test_more/general/chkpoint_one.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/cppad.hpp>\n\nnamespace {\n    using CppAD::AD;\n    typedef CPPAD_TESTVECTOR(AD<double>) ADVector;\n\n    // ------------------------------------------------------------------------\n    bool f_algo(const ADVector& x, ADVector& y)\n    {   size_t m = y.size();\n        assert( size_t(x.size()) == m + 1);\n        for(size_t i = 0; i < m; i++)\n            y[i] = x[i] * x[i+1];\n        return true;\n    }\n    bool g_algo(const ADVector& y, ADVector& z)\n    {   size_t m = z.size();\n        assert( size_t(y.size()) + 1 == m );\n        z[0] = 0.0;\n        for(size_t i = 1; i < m; i++)\n        {   z[0] += y[i-1];\n            z[i]  = y[i-1];\n        }\n        return true;\n    }\n    bool test_one(void)\n    {   bool ok = true;\n        using CppAD::checkpoint;\n        using CppAD::ADFun;\n        using CppAD::NearEqual;\n        size_t i, j, k, n = 4, ell = n-1 , m = ell + 1;\n        double eps = 10. * std::numeric_limits<double>::epsilon();\n\n        // checkpoint version of the function F(x)\n        ADVector ax(n), ay(ell), az(m);\n        for(j = 0; j < n; j++)\n            ax[j] = double(j);\n        checkpoint<double> f_check(\"f_check\", f_algo, ax, ay);\n        checkpoint<double> g_check(\"g_check\", g_algo, ay, az);\n\n        // Record a version of z = g[f(x)] without checkpointing\n        Independent(ax);\n        f_algo(ax, ay);\n        g_algo(ay, az);\n        ADFun<double> check_not(ax, az);\n\n        // Record a version of z = g[f(x)] with checkpointing\n        Independent(ax);\n        f_check(ax, ay);\n        g_check(ay, az);\n        ADFun<double> check_yes(ax, az);\n\n        // compare forward mode results for orders 0, 1, 2\n        size_t p = 2;\n        CPPAD_TESTVECTOR(double) x_p(n*(p+1)), z_not(m*(p+1)), z_yes(m*(p+1));\n        for(j = 0; j < n; j++)\n        {   for(k = 0; k <= p; k++)\n                x_p[ j * (p+1) + k ] = 1.0 / double(p + 1 - k);\n        }\n        z_not = check_not.Forward(p, x_p);\n        z_yes = check_yes.Forward(p, x_p);\n        for(i = 0; i < m; i++)\n        {   for(k = 0; k <= p; k++)\n            {   double zik_not = z_not[ i * (p+1) + k];\n                double zik_yes = z_yes[ i * (p+1) + k];\n                ok &= NearEqual(zik_not, zik_yes, eps, eps);\n            }\n        }\n\n        // compare reverse mode results\n        CPPAD_TESTVECTOR(double) w(m*(p+1)), dw_not(n*(p+1)), dw_yes(n*(p+1));\n        for(i = 0; i < m; i++)\n        {   for(k = 0; k <= p; k++)\n                w[ i * (p+1) + k ] = 2.0 / double(p + 1 - k );\n        }\n        dw_not = check_not.Reverse(p+1, w);\n        dw_yes = check_yes.Reverse(p+1, w);\n        for(j = 0; j < n; j++)\n        {   for(k = 0; k <= p; k++)\n            {   double dwjk_not = dw_not[ j * (p+1) + k];\n                double dwjk_yes = dw_yes[ j * (p+1) + k];\n                ok &= NearEqual(dwjk_not, dwjk_yes, eps, eps);\n            }\n        }\n\n        // mix sparsity so test both cases\n        f_check.option( CppAD::atomic_base<double>::bool_sparsity_enum );\n        g_check.option( CppAD::atomic_base<double>::set_sparsity_enum );\n\n        // compare forward mode Jacobian sparsity patterns\n        size_t q = n - 1;\n        CppAD::vector< std::set<size_t> > r(n), s_not(m), s_yes(m);\n        for(j = 0; j < n; j++)\n        {   if( j < q )\n                r[j].insert(j);\n            else\n            {   r[j].insert(0);\n                r[j].insert(1);\n            }\n        }\n        s_not = check_not.ForSparseJac(q, r);\n        s_yes = check_yes.ForSparseJac(q, r);\n        for(i = 0; i < m; i++)\n            ok &= s_not[i] == s_yes[i];\n\n        // compare reverse mode Jacobian sparsity patterns\n        CppAD::vector< std::set<size_t> > s(m), r_not(m), r_yes(m);\n        for(i = 0; i < m; i++)\n            s[i].insert(i);\n        r_not = check_not.RevSparseJac(m, s);\n        r_yes = check_yes.RevSparseJac(m, s);\n        for(i = 0; i < m; i++)\n            ok &= s_not[i] == s_yes[i];\n\n\n        // compare reverse mode Hessian sparsity patterns\n        CppAD::vector< std::set<size_t> > s_one(1), h_not(q), h_yes(q);\n        for(i = 0; i < m; i++)\n            s_one[0].insert(i);\n        h_not = check_not.RevSparseHes(q, s_one);\n        h_yes = check_yes.RevSparseHes(q, s_one);\n        for(i = 0; i < q; i++)\n            ok &= h_not[i] == h_yes[i];\n\n        checkpoint<double>::clear();\n        return ok;\n    }\n    // ------------------------------------------------------------------------\n    bool h_algo(const ADVector& ax, ADVector& ay)\n    {   ay[0] = ax[0];\n        ay[1] = ax[1] + ax[2];\n        return true;\n    }\n    bool test_two(void)\n    {   bool ok = true;\n        using CppAD::checkpoint;\n        using CppAD::ADFun;\n        using CppAD::NearEqual;\n\n        // checkpoint version of H(x)\n        size_t m = 2;\n        size_t n = 3;\n        ADVector ax(n), ay(m);\n        for(size_t j = 0; j < n; j++)\n            ax[j] = double(j);\n        checkpoint<double> h_check(\"h_check\", h_algo, ax, ay);\n\n        // record function using h_check\n        Independent(ax);\n        h_check(ax, ay);\n        ADFun<double> h(ax, ay);\n        //\n        // --------------------------------------------------------------------\n        // sparsity pattern\n        // --------------------------------------------------------------------\n        for(size_t k = 0; k < 3; k++)\n        {   if( k == 0 )\n                h_check.option(CppAD::atomic_base<double>::pack_sparsity_enum);\n            if( k == 1 )\n                h_check.option(CppAD::atomic_base<double>::bool_sparsity_enum);\n            if( k == 2 )\n                h_check.option(CppAD::atomic_base<double>::set_sparsity_enum);\n\n            // compute sparsity pattern h_1(x) = x[1] + x[2]\n            CppAD::vector< std::set<size_t> > r(1), s(1);\n            r[0].insert(1);\n            s = h.RevSparseJac(1, r);\n\n            // check result\n            std::set<size_t> check;\n            check.insert(1);\n            check.insert(2);\n            ok &= s[0] == check;\n        }\n        // --------------------------------------------------------------------\n        // base2ad\n        // --------------------------------------------------------------------\n        ADFun< AD<double> , double > ah;\n        ah = h.base2ad();\n        //\n        // forward mode\n        ADVector au(n), av(m);\n        for(size_t j = 0; j < n; j++)\n            ax[j] = au[j] = double(j + 1);\n        av = ah.Forward(0, au);\n        h_algo(ax, ay);\n        for(size_t i = 0; i < m; ++i)\n            ok &= av[i] == ay[i];\n        //\n        // reverse mode\n        ADVector adw(n), aw(m);\n        for(size_t i = 0; i < m; ++i)\n            aw[i] = 1.0;\n        adw = ah.Reverse(1, aw);\n        ok &= Value( adw[0] ) == 1.0;\n        ok &= Value( adw[1] ) == 1.0;\n        ok &= Value( adw[2] ) == 1.0;\n        //\n        return ok;\n    }\n}\n\nbool chkpoint_one(void)\n{   bool ok = true;\n    ok  &= test_one();\n    ok  &= test_two();\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "test_more/general/chkpoint_two.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/cppad.hpp>\n\nnamespace {\n    using CppAD::AD;\n    using CppAD::vector;\n    using CppAD::chkpoint_two;\n    // -----------------------------------------------------------------------\n    template <class Algo>\n    chkpoint_two<double> checkpoint_two(\n        std::string name ,\n        Algo&      algo  ,\n        vector< AD<double> >& ax ,\n        vector< AD<double> >& ay )\n    {   CppAD::Independent(ax);\n        algo(ax, ay);\n        CppAD::ADFun<double> g_fun(ax, ay);\n        bool internal_bool = false;\n        bool use_hes_sparsity = true;\n        bool use_base2ad      = true;\n        bool use_in_parallel  = false;\n        return chkpoint_two<double>(g_fun, name,\n            internal_bool, use_hes_sparsity, use_base2ad, use_in_parallel\n        );\n    }\n    // ----------------------------------------------------------------\n    // Test for bug where checkpoint function did not depend on\n    // the operands in the logical comparison because of the CondExp\n    // sparsity pattern.\n    void j_algo(\n        const CppAD::vector< CppAD::AD<double> >& ax ,\n                  CppAD::vector< CppAD::AD<double> >& ay )\n    {   ay[0] = CondExpGt(ax[0], ax[1], ax[2], ax[3]); }\n\n    bool test_one(void)\n    {   bool ok = true;\n        using CppAD::NearEqual;\n        double eps10 = 10.0 * std::numeric_limits<double>::epsilon();\n\n        // Create a checkpoint version of the function g\n        vector< AD<double> > au(4), av(1);\n        for(size_t i = 0; i < 4; i++)\n            au[i] = AD<double>(i);\n        chkpoint_two<double> j_check =\n            checkpoint_two(\"j_check\", j_algo, au, av);\n\n        // independent variable vector\n        vector< AD<double> > ax(2), ay(1);\n        ax[0] = 1.;\n        ax[1] = 1.;\n        Independent(ax);\n\n        // call atomic function that does not get used\n        for(size_t i = 0; i < 4; i++)\n            au[i] = ax[0] + AD<double>(i + 1) * ax[1];\n        j_check(au, ay);\n\n        // create function object f : ax -> ay\n        CppAD::ADFun<double> f(ax, ay);\n\n\n        // now optimize the operation sequence\n        f.optimize();\n\n        // check result where true case is used; i.e., au[0] > au[1]\n        vector<double> x(2), y(1);\n        x[0] = 1.;\n        x[1] = -1;\n        y    = f.Forward(0, x);\n        ok &= NearEqual(y[0], x[0] + double(3) * x[1], eps10, eps10);\n\n\n        // check result where false case is used; i.e., au[0] <= au[1]\n        x[0] = 1.;\n        x[1] = 1;\n        y    = f.Forward(0, x);\n        ok &= NearEqual(y[0], x[0] + double(4) * x[1], eps10, eps10);\n\n        return ok;\n    }\n    // -------------------------------------------------------------------\n    // Test conditional optimizing out call to an atomic function call\n    void k_algo(\n        const CppAD::vector< CppAD::AD<double> >& x ,\n                  CppAD::vector< CppAD::AD<double> >& y )\n    {   y[0] = x[0] + x[1]; }\n\n    void h_algo(\n        const CppAD::vector< CppAD::AD<double> >& x ,\n                  CppAD::vector< CppAD::AD<double> >& y )\n    {   y[0] = x[0] - x[1]; }\n\n    bool test_two(void)\n    {   bool ok = true;\n        typedef vector< AD<double> > ADVector;\n        using CppAD::NearEqual;\n        double eps10 = 10.0 * std::numeric_limits<double>::epsilon();\n\n        // Create a checkpoint version of the function g\n        ADVector ax(2), ag(1), ah(1), ay(1);\n        ax[0] = 0.;\n        ax[1] = 1.;\n        chkpoint_two<double> k_check =\n            checkpoint_two(\"k_check\", k_algo, ax, ag);\n        chkpoint_two<double> h_check =\n            checkpoint_two(\"h_check\", h_algo, ax, ah);\n\n        // independent variable vector\n        Independent(ax);\n\n        // atomic function calls that get conditionally used\n        k_check(ax, ag);\n        h_check(ax, ah);\n\n        // conditional expression\n        ay[0] = CondExpLt(ax[0], ax[1], ag[0], ah[0]);\n\n        // create function object f : ax -> ay\n        CppAD::ADFun<double> f;\n        f.Dependent(ax, ay);\n\n        // use zero order to evaluate when condition is true\n        CppAD::vector<double>  x(2), dx(2);\n        CppAD::vector<double>  y(1), dy(1), w(1);\n        x[0] = 3.;\n        x[1] = 4.;\n        y    = f.Forward(0, x);\n        ok &= NearEqual(y[0], x[0] + x[1], eps10, eps10);\n\n        // before optimize\n        ok  &= f.number_skip() == 0;\n\n        // now optimize the operation sequence\n        f.optimize();\n\n        // optimized zero order forward when condition is false\n        x[0] = 4.;\n        x[1] = 3.;\n        y    = f.Forward(0, x);\n        ok &= NearEqual(y[0], x[0] - x[1], eps10, eps10);\n\n        // after optimize can skip either call to g or call to h\n        ok  &= f.number_skip() == 1;\n\n        // optimized first order forward\n        dx[0] = 2.;\n        dx[1] = 1.;\n        dy    = f.Forward(1, dx);\n        ok &= NearEqual(dy[0], dx[0] - dx[1], eps10, eps10);\n\n        // optimized first order reverse\n        w[0]  = 1.;\n        dx    = f.Reverse(1, w);\n        ok &= NearEqual(dx[0], 1., eps10, eps10);\n        ok &= NearEqual(dx[1], -1., eps10, eps10);\n\n        return ok;\n    }\n    // -------------------------------------------------------------------\n    // Test of optimizing out arguments to an atomic function\n    void g_algo(\n        const CppAD::vector< CppAD::AD<double> >& ax ,\n                  CppAD::vector< CppAD::AD<double> >& ay )\n    {   ay = ax; }\n\n    bool test_three(void)\n    {   bool ok = true;\n        using CppAD::NearEqual;\n        double eps10 = 10.0 * std::numeric_limits<double>::epsilon();\n\n        // Create a checkpoint version of the function g\n        vector< AD<double> > ax(2), ay(2), az(1);\n        ax[0] = 0.;\n        ax[1] = 1.;\n        chkpoint_two<double> g_check =\n            checkpoint_two(\"g_check\", g_algo, ax, ay);\n\n        // independent variable vector\n        Independent(ax);\n\n        // call atomic function that does not get used\n        g_check(ax, ay);\n\n        // conditional expression\n        az[0] = CondExpLt(ax[0], ax[1], ax[0] + ax[1], ax[0] - ax[1]);\n\n        // create function object f : ax -> az\n        CppAD::ADFun<double> f(ax, az);\n\n        // number of variables before optimization\n        // (include ay[0] and ay[1])\n        size_t n_before = f.size_var();\n\n        // now optimize the operation sequence\n        f.optimize();\n\n        // number of variables after optimization\n        // (does not include ay[0] and ay[1])\n        size_t n_after = f.size_var();\n        ok            &= n_after + 2 == n_before;\n\n        // check optimization works ok\n        vector<double> x(2), z(1);\n        x[0] = 4.;\n        x[1] = 3.;\n        z    = f.Forward(0, x);\n        ok &= NearEqual(z[0], x[0] - x[1], eps10, eps10);\n\n        return ok;\n    }\n    bool test_four(void)\n    {   bool ok = true;\n        using CppAD::NearEqual;\n        double eps10 = 10.0 * std::numeric_limits<double>::epsilon();\n        vector< AD<double> > au(2), aw(2), ax(2), ay(1);\n\n        // create atomic function corresponding to g_algo\n        au[0] = 1.0;\n        au[1] = 2.0;\n        chkpoint_two<double> g_check =\n            checkpoint_two(\"g_algo\", g_algo, au, ax);\n\n        // start recording a new function\n        CppAD::Independent(ax);\n\n        // now use g_check during the recording\n        au[0] = ax[0] + ax[1]; // this argument requires a new variable\n        au[1] = ax[0] - ax[1]; // this argument also requires a new variable\n        g_check(au, aw);\n\n        // now create f(x) = x_0 + x_1\n        ay[0] = aw[0];\n        CppAD::ADFun<double> f(ax, ay);\n\n        // number of variables before optimization\n        // ax[0], ax[1], ax[0] + ax[1], ax[0] - ax[1], g[0], g[1]\n        // and phantom variable at index 0\n        size_t n_before = f.size_var();\n        ok &= n_before == 7;\n\n        // now optimize f so that the calculation of au[1] is removed\n        f.optimize();\n\n        // number of variables after optimization\n        // ax[0], ax[1], ax[0] + ax[1], g[0]\n        // and phantom variable at index 0\n        size_t n_after = f.size_var();\n        ok &= n_after == 5;\n\n        // now compute and check a forward mode calculation\n        vector<double> x(2), y(1);\n        x[0] = 5.0;\n        x[1] = 6.0;\n        y    = f.Forward(0, x);\n        ok &= NearEqual(y[0], x[0] + x[1], eps10, eps10);\n\n        return ok;\n    }\n    // -----------------------------------------------------------------------\n    void i_algo(\n        const CppAD::vector< CppAD::AD<double> >& ax ,\n                  CppAD::vector< CppAD::AD<double> >& ay )\n    {   ay[0] = 1.0 / ax[0]; }\n    //\n    // Test bug where atomic functions were not properly conditionally skipped.\n    bool test_five(bool conditional_skip)\n    {   bool ok = true;\n        using CppAD::AD;\n        using CppAD::NearEqual;\n        double eps10 = 10.0 * std::numeric_limits<double>::epsilon();\n        using CppAD::vector;\n\n        // Create a checkpoint version of the function i_algo\n        vector< AD<double> > au(1), av(1), aw(1);\n        au[0] = 1.0;\n        chkpoint_two<double> i_check =\n            checkpoint_two(\"i_check\", i_algo, au, av);\n\n        // independent variable vector\n        vector< AD<double> > ax(2), ay(1);\n        ax[0] = 1.0;\n        ax[1] = 2.0;\n        Independent(ax);\n\n        // call atomic function that does not get used\n        au[0] = ax[0];\n        i_check(au, av);\n        au[0] = ax[1];\n        i_check(au, aw);\n        AD<double> zero = 0.0;\n        ay[0] = CondExpGt(av[0], zero, av[0], aw[0]);\n\n        // create function object f : ax -> ay\n        CppAD::ADFun<double> f(ax, ay);\n\n        // run case that skips the second call to afun\n        // (can use trace in sweep/forward_0.hpp to see this).\n        vector<double> x(2), y_before(1), y_after(1);\n        x[0]      = 1.0;\n        x[1]      = 2.0;\n        y_before  = f.Forward(0, x);\n        if( conditional_skip )\n            f.optimize();\n        else\n            f.optimize(\"no_conditional_skip\");\n        y_after   = f.Forward(0, x);\n\n        ok &= NearEqual(y_before[0], y_after[0], eps10, eps10);\n\n        return ok;\n    }\n    // -----------------------------------------------------------------------\n    void m_algo(\n        const CppAD::vector< CppAD::AD<double> >& ax ,\n                  CppAD::vector< CppAD::AD<double> >& ay )\n    {   ay[0] = 0.0;\n        for(size_t j = 0; j < ax.size(); ++j)\n            ay[0] += ax[j] * ax[j];\n    }\n    //\n    // Test bug where select_y[i] should be select_x[i]\n    bool test_six(void)\n    {   bool ok = true;\n        using CppAD::AD;\n        using CppAD::NearEqual;\n        using CppAD::vector;\n\n        // Create a checkpoint version of the function m_algo\n        size_t n = 3, m = 1;\n        vector< AD<double> > ax(n), ay(m);\n        for(size_t j = 0; j < n; ++j)\n            ax[j] = 1.0;\n        chkpoint_two<double> m_check =\n            checkpoint_two(\"m_check\", m_algo, ax, ay);\n\n        // independent variable vector\n        Independent(ax);\n\n        // call atomic function that does not get used\n        m_check(ax, ay);\n\n        // create function object f : ax -> ay\n        CppAD::ADFun<double> f(ax, ay);\n\n        // Evaluate Hessian sparsity\n        vector<bool> select_domain(n), select_range(m);\n        select_range[0] = true;\n        for(size_t j = 0; j < n; ++j)\n            select_domain[j] = true;\n        bool internal_bool = true;\n        CppAD::sparse_rc< vector<size_t> > pattern_out;\n        //\n        f.for_hes_sparsity(\n            select_domain, select_range, internal_bool, pattern_out\n        );\n        size_t nnz = pattern_out.nnz();\n        const vector<size_t>& row( pattern_out.row() );\n        const vector<size_t>& col( pattern_out.col() );\n        vector<size_t> row_major = pattern_out.row_major();\n        //\n        ok &= nnz == n;\n        for(size_t k = 0; k < nnz; ++k)\n        {   ok &= row[ row_major[k] ] == k;\n            ok &= col[ row_major[k] ] == k;\n        }\n        return ok;\n    }\n\n}\nbool chkpoint_two(void)\n{   bool ok = true;\n    //\n    ok  &= test_one();\n    ok  &= test_two();\n    ok  &= test_three();\n    ok  &= test_four();\n    ok  &= test_five(true);\n    ok  &= test_five(false);\n    ok  &= test_six();\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "test_more/general/compare.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\nCheck comparison operators between AD< AD<Base> > and Base, int\n*/\n# include <cppad/cppad.hpp>\n\nnamespace {\n    // ---------------------------------------------------------------------\n    bool compare_parameter(bool optimize)\n    {   bool ok = true;\n        using CppAD::AD;\n        //\n        // f\n        CPPAD_TESTVECTOR( AD<double> ) ax(1), ap(1), ay(1);\n        ax[0] = 1.0;\n        ap[0] = 3.0;\n        CppAD::Independent( ax, ap );\n        if( ap[0] < 2.0 )\n            ay[0] = ax[0] + ax[0];\n        else\n            ay[0] = ax[0] * ax[0];\n        CppAD::ADFun<double> f(ax, ay);\n        if( optimize )\n            f.optimize();\n        //\n        // x, y, ok\n        CPPAD_TESTVECTOR(double) x(1), y(1);\n        x[0] = 4.0;\n        y    = f.Forward(0, x);\n        ok  &= y[0] == x[0] * x[0];\n        ok &= f.compare_change_number() == 0;\n        //\n        // p, ok\n        CPPAD_TESTVECTOR(double) p(1);\n        p[0] = 1.0;\n        f.new_dynamic(p);\n        y    = f.Forward(0, x);\n        ok  &= y[0] == x[0] * x[0];\n        ok &= f.compare_change_number() == 1;\n        //\n        return ok;\n    }\n    // ---------------------------------------------------------------------\n    template <class Type>\n    bool compare_type(void)\n    {   bool ok = true;\n        using CppAD::AD;\n\n        Type      middle = 4;\n        AD<double> three = 3;\n        AD<double> four  = 4;\n        AD<double> five  = 5;\n\n        // AD<double> > Type\n        ok &= ! (three  >  middle);\n        ok &= ! (four   >  middle);\n        ok &=   (five   >  middle);\n        // Type > AD<double>\n        ok &=   (middle >  three );\n        ok &= ! (middle >  four  );\n        ok &= ! (middle >  five  );\n\n        // AD<double> >= Type\n        ok &= ! (three  >= middle);\n        ok &=   (four   >= middle);\n        ok &=   (five   >= middle);\n        // Type > AD<double>\n        ok &=   (middle >= three );\n        ok &=   (middle >= four  );\n        ok &= ! (middle >= five  );\n\n        // AD<double> < Type\n        ok &=   (three  <  middle);\n        ok &= ! (four   <  middle);\n        ok &= ! (five   <  middle);\n        // Type > AD<double>\n        ok &= ! (middle <  three );\n        ok &= ! (middle <  four  );\n        ok &=   (middle <  five  );\n\n        // AD<double> <= Type\n        ok &=   (three  <= middle);\n        ok &=   (four   <= middle);\n        ok &= ! (five   <= middle);\n        // Type > AD<double>\n        ok &= ! (middle <= three );\n        ok &=   (middle <= four  );\n        ok &=   (middle <= five  );\n\n        return ok;\n    }\n}\nbool Compare(void)\n{   bool ok = true;\n    ok  &= compare_type<int>();\n    ok  &= compare_type<double>();\n    ok  &= compare_type< CppAD::AD<double> >();\n    ok  &= compare_parameter(true);\n    ok  &= compare_parameter(false);\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/compare_change.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\nOld CompareChange examples and tests, now just used for validation testing\n*/\n\n# include <cppad/cppad.hpp>\n\nnamespace {\n    // ----------------------------------------------------------------------\n    bool CompareChange_one(void)\n    {   bool ok = true;\n\n        using namespace CppAD;\n\n        // ------------------------------- < ----------------------------\n\n        // create independent variables\n        CPPAD_TESTVECTOR(AD<double>) X(2);\n        X[0] = 3.;\n        X[1] = 4.;\n        Independent(X);\n\n        // create dependent variables\n        CPPAD_TESTVECTOR(AD<double>) Y(6);\n\n        // CondExp would never require retaping\n        if( X[0] < X[1] )      // True variable < variable\n            Y[0] = X[0];\n        else\n            Y[0] = X[1];\n        if( X[1] < X[0] )      // False variable < variable\n            Y[1] = X[0];\n        else\n            Y[1] = X[1];\n        if( 3.5  < X[1] )      // True parameter < variable\n            Y[2] = X[0];\n        else\n            Y[2] = X[1];\n        if( 3.5  < X[0] )      // False parameter < variable\n            Y[3] = X[0];\n        else\n            Y[3] = X[1];\n        if( X[0] < 4.   )      // True variable < parameter\n            Y[4] = X[0];\n        else\n            Y[4] = X[1];\n        if( X[1] < 4.   )      // False variable < parameter\n            Y[5] = X[0];\n        else\n            Y[5] = X[1];\n\n        // f : X -> Y\n        ADFun<double> *f;\n        f = new ADFun<double>(X, Y);\n\n        // new argument value\n        CPPAD_TESTVECTOR(double) x( X.size() );\n        x[0] = 4.;\n        x[1] = 3.;\n\n        // evaluate the function at new argument\n        CPPAD_TESTVECTOR(double) y( Y.size() );\n        y = f->Forward(0, x);\n\n        // check results\n        ok &= (y[0] == x[0]);           // this is what the was taped\n        ok &= (y[1] == x[1]);\n        ok &= (y[2] == x[0]);\n        ok &= (y[3] == x[1]);\n        ok &= (y[4] == x[0]);\n        ok &= (y[5] == x[1]);\n        ok &= (f->CompareChange() == 6); // all comparisons have changed\n\n        // done with this function\n        delete f;\n\n        // ------------------------------- > ----------------------------\n        // create independent variables\n        Independent(X);\n\n        if( X[0] > X[1] )      // False variable > variable\n            Y[0] = X[0];\n        else\n            Y[0] = X[1];\n        if( X[1] > X[0] )      // True variable > variable\n            Y[1] = X[0];\n        else\n            Y[1] = X[1];\n        if( 3.5  > X[1] )      // False parameter > variable\n            Y[2] = X[0];\n        else\n            Y[2] = X[1];\n        if( 3.5  > X[0] )      // True parameter > variable\n            Y[3] = X[0];\n        else\n            Y[3] = X[1];\n        if( X[0] > 3.   )      // False variable > parameter\n            Y[4] = X[0];\n        else\n            Y[4] = X[1];\n        if( X[1] > 3.   )      // True variable > parameter\n            Y[5] = X[0];\n        else\n            Y[5] = X[1];\n\n        // f : X -> Y\n        f = new ADFun<double> (X, Y);\n\n        // evaluate the function at new argument\n        y = f->Forward(0, x);\n\n        // check results\n        ok &= (y[0] == x[1]);           // this is what the was taped\n        ok &= (y[1] == x[0]);\n        ok &= (y[2] == x[1]);\n        ok &= (y[3] == x[0]);\n        ok &= (y[4] == x[1]);\n        ok &= (y[5] == x[0]);\n        ok &= (f->CompareChange() == 6); // all comparisons have changed\n\n        // done with this function\n        delete f;\n\n        // ------------------------------- <= ----------------------------\n        // create independent variables\n        Independent(X);\n\n        if( X[0] <= X[1] )      // True variable <= variable\n            Y[0] = X[0];\n        else\n            Y[0] = X[1];\n        if( X[1] <= X[0] )      // False variable <= variable\n            Y[1] = X[0];\n        else\n            Y[1] = X[1];\n        if( 4.  <= X[1] )       // True parameter <= variable\n            Y[2] = X[0];\n        else\n            Y[2] = X[1];\n        if( 4.  <= X[0] )       // False parameter <= variable\n            Y[3] = X[0];\n        else\n            Y[3] = X[1];\n        if( X[0] <= 3.5   )     // True variable <= parameter\n            Y[4] = X[0];\n        else\n            Y[4] = X[1];\n        if( X[1] <= 3.5  )      // False variable <= parameter\n            Y[5] = X[0];\n        else\n            Y[5] = X[1];\n\n        // f : X -> Y\n        f = new ADFun<double> (X, Y);\n\n        // evaluate the function at new argument\n        y = f->Forward(0, x);\n\n        // check results\n        ok &= (y[0] == x[0]);           // this is what the was taped\n        ok &= (y[1] == x[1]);\n        ok &= (y[2] == x[0]);\n        ok &= (y[3] == x[1]);\n        ok &= (y[4] == x[0]);\n        ok &= (y[5] == x[1]);\n        ok &= (f->CompareChange() == 6); // all comparisons have changed\n\n        // done with this function\n        delete f;\n\n\n        // ------------------------------- >= ----------------------------\n        // create independent variables\n        Independent(X);\n\n        if( X[0] >= X[1] )      // False variable >= variable\n            Y[0] = X[0];\n        else\n            Y[0] = X[1];\n        if( X[1] >= X[0] )      // True variable >= variable\n            Y[1] = X[0];\n        else\n            Y[1] = X[1];\n        if( 3.5  >= X[1] )      // False parameter >= variable\n            Y[2] = X[0];\n        else\n            Y[2] = X[1];\n        if( 3.5  >= X[0] )      // True parameter >= variable\n            Y[3] = X[0];\n        else\n            Y[3] = X[1];\n        if( X[0] >= 4.   )      // False variable >= parameter\n            Y[4] = X[0];\n        else\n            Y[4] = X[1];\n        if( X[1] >= 4.   )      // True variable >= parameter\n            Y[5] = X[0];\n        else\n            Y[5] = X[1];\n\n        // f : X -> Y\n        f = new ADFun<double> (X, Y);\n\n        // evaluate the function at new argument\n        y = f->Forward(0, x);\n\n        // check results\n        ok &= (y[0] == x[1]);           // this is what the was taped\n        ok &= (y[1] == x[0]);\n        ok &= (y[2] == x[1]);\n        ok &= (y[3] == x[0]);\n        ok &= (y[4] == x[1]);\n        ok &= (y[5] == x[0]);\n        ok &= (f->CompareChange() == 6); // all comparisons have changed\n\n        // done with this function\n        delete f;\n\n        // ------------------------------- == ----------------------------\n        // create independent variables\n        Independent(X);\n\n        if( X[0] == X[1] )      // False variable == variable\n            Y[0] = X[0];\n        else\n            Y[0] = X[1];\n        if( X[0] == X[0] )      // True variable == variable\n            Y[1] = X[0];\n        else\n            Y[1] = X[1];\n        if( 3.  == X[1] )       // False parameter == variable\n            Y[2] = X[0];\n        else\n            Y[2] = X[1];\n        if( 3.  == X[0] )       // True parameter == variable\n            Y[3] = X[0];\n        else\n            Y[3] = X[1];\n        if( X[0] == 4.   )      // False variable == parameter\n            Y[4] = X[0];\n        else\n            Y[4] = X[1];\n        if( X[1] == 4.   )      // True variable == parameter\n            Y[5] = X[0];\n        else\n            Y[5] = X[1];\n\n        // f : X -> Y\n        f = new ADFun<double> (X, Y);\n\n        // evaluate the function at new argument\n        y = f->Forward(0, x);\n\n        // check results\n        ok &= (y[0] == x[1]);           // this is what the was taped\n        ok &= (y[1] == x[0]);\n        ok &= (y[2] == x[1]);\n        ok &= (y[3] == x[0]);\n        ok &= (y[4] == x[1]);\n        ok &= (y[5] == x[0]);\n        // the first two comparisons do not change\n        ok &= (f->CompareChange() == 4);\n\n        // done with this function\n        delete f;\n\n        // ------------------------------- != ----------------------------\n        // create independent variables\n        Independent(X);\n\n        if( X[0] != X[1] )      // True variable != variable\n            Y[0] = X[0];\n        else\n            Y[0] = X[1];\n        if( X[0] != X[0] )      // False variable != variable\n            Y[1] = X[0];\n        else\n            Y[1] = X[1];\n        if( 3.  != X[1] )       // True parameter != variable\n            Y[2] = X[0];\n        else\n            Y[2] = X[1];\n        if( 3.  != X[0] )       // False parameter != variable\n            Y[3] = X[0];\n        else\n            Y[3] = X[1];\n        if( X[0] != 4.   )      // True variable != parameter\n            Y[4] = X[0];\n        else\n            Y[4] = X[1];\n        if( X[1] != 4.   )      // False variable != parameter\n            Y[5] = X[0];\n        else\n            Y[5] = X[1];\n\n        // f : X -> Y\n        f = new ADFun<double> (X, Y);\n\n        // evaluate the function at new argument\n        y = f->Forward(0, x);\n\n        // check results\n        ok &= (y[0] == x[0]);           // this is what the was taped\n        ok &= (y[1] == x[1]);\n        ok &= (y[2] == x[0]);\n        ok &= (y[3] == x[1]);\n        ok &= (y[4] == x[0]);\n        ok &= (y[5] == x[1]);\n        // the first two comparisons do not change\n        ok &= (f->CompareChange() == 4);\n\n        // done with this function\n        delete f;\n\n        return ok;\n    }\n    // ----------------------------------------------------------------------\n    template <class Type>\n    Type Minimum(const Type &x, const Type &y)\n    {   // Use a comparison to compute the min(x, y)\n        // (note that CondExp would never require retaping).\n        if( x < y )\n            return x;\n        return y;\n    }\n\n    bool CompareChange_two(void)\n    {   bool ok = true;\n\n        using CppAD::AD;\n        using CppAD::ADFun;\n        using CppAD::Independent;\n\n        // domain space vector\n        size_t n = 2;\n        CPPAD_TESTVECTOR(AD<double>) X(n);\n        X[0] = 3.;\n        X[1] = 4.;\n\n        // declare independent variables and start tape recording\n        CppAD::Independent(X);\n\n        // range space vector\n        size_t m = 1;\n        CPPAD_TESTVECTOR(AD<double>) Y(m);\n        Y[0] = Minimum(X[0], X[1]);\n\n        // create f: x -> y and stop tape recording\n        ADFun<double> f(X, Y);\n\n        // evaluate zero mode Forward where conditional has the same result\n        // note that f.CompareChange is not defined when NDEBUG is true\n        CPPAD_TESTVECTOR(double) x(n);\n        CPPAD_TESTVECTOR(double) y(m);\n        x[0] = 3.5;\n        x[1] = 4.;\n        y    = f.Forward(0, x);\n        ok  &= (y[0] == x[0]);\n        ok  &= (y[0] == Minimum(x[0], x[1]));\n        ok  &= (f.CompareChange() == 0);\n\n        // evaluate zero mode Forward where conditional has different result\n        x[0] = 4.;\n        x[1] = 3.;\n        y    = f.Forward(0, x);\n        ok  &= (y[0] == x[0]);\n        ok  &= (y[0] != Minimum(x[0], x[1]));\n        ok  &= (f.CompareChange() == 1);\n\n        // re-tape to obtain the new AD operation sequence\n        X[0] = 4.;\n        X[1] = 3.;\n        Independent(X);\n        Y[0] = Minimum(X[0], X[1]);\n\n        // stop tape and store result in f\n        f.Dependent(Y);\n\n        // evaluate the function at new argument values\n        y    = f.Forward(0, x);\n        ok  &= (y[0] == x[1]);\n        ok  &= (y[0] == Minimum(x[0], x[1]));\n        ok  &= (f.CompareChange() == 0);\n\n        return ok;\n    }\n}\n\nbool compare_change(void)\n{   bool ok  = true;\n    ok &= CompareChange_one();\n    ok &= CompareChange_two();\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "test_more/general/cond_exp.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\nComprehensive test built on 08/07 for new user interface to CondExp\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n\nnamespace { // Begin empty namespace\n\nbool CondExp_ppvv(void)\n{   bool ok = true;\n    using CppAD::AD;\n\n    // independent variable vector\n    CPPAD_TESTVECTOR(AD<double>) ax(2), ap(2);\n    ap[0]     = 0.;\n    ap[1]     = 1.;\n    ax[0]     = 2.;\n    ax[1]     = 3.;\n    size_t abort_op_index = 0;\n    bool   record_compare = false;\n    CppAD::Independent(ax, abort_op_index, record_compare, ap);\n\n    // dependent variable vector\n    CPPAD_TESTVECTOR(AD<double>) ay(5);\n\n    // CondExp(parameter, variable, variable, variable)\n    ay[0] = CondExpLt(ap[0], ap[1], ax[0], ax[1]);\n    ay[1] = CondExpLt(ap[0], ap[1], ax[0], ax[1]);\n    ay[2] = CondExpEq(ap[0], ap[1], ax[0], ax[1]);\n    ay[3] = CondExpGe(ap[0], ap[1], ax[0], ax[1]);\n    ay[4] = CondExpGt(ap[0], ap[1], ax[0], ax[1]);\n\n    // create f: X -> Y\n    CppAD::ADFun<double> f(ax, ay);\n\n    // vectors for function values\n    CPPAD_TESTVECTOR(double) x( f.Domain() );\n    CPPAD_TESTVECTOR(double) y( f.Range() );\n\n    // vectors for derivative values\n    CPPAD_TESTVECTOR(double) dx( f.Domain() );\n    CPPAD_TESTVECTOR(double) dy( f.Range() );\n\n    // check original function values\n    // ap[0] < ap[1]\n    ok &= ay[0] == ax[0];\n    ok &= ay[1] == ax[0];\n    ok &= ay[2] == ax[1];\n    ok &= ay[3] == ax[1];\n    ok &= ay[4] == ax[1];\n\n    // function values\n    x[0] = 2.;\n    x[1] = 3.;\n    y    = f.Forward(0, x);\n    ok &= ( y[0] == x[0] );\n    ok &= ( y[1] == x[0] );\n    ok &= ( y[2] == x[1] );\n    ok &= ( y[3] == x[1] );\n    ok &= ( y[4] == x[1] );\n\n    // forward mode derivative values\n    dx[0] = 1.;\n    dx[1] = 2.;\n    dy    = f.Forward(1, dx);\n    ok   &= (dy[0] == dx[0] );\n    ok   &= (dy[1] == dx[0] );\n    ok   &= (dy[2] == dx[1] );\n    ok   &= (dy[3] == dx[1] );\n    ok   &= (dy[4] == dx[1] );\n\n    // reverse mode derivative values\n    dy[0] = 1.;\n    dy[1] = 2.;\n    dy[2] = 3.;\n    dy[3] = 4.;\n    dy[4] = 5.;\n    dx    = f.Reverse(1, dy);\n    ok   &= dx[0] == dy[0] + dy[1];\n    ok   &= dx[1] == dy[2] + dy[3] + dy[4];\n\n    // now change the dynamic parameter so the results are reversed\n    CPPAD_TESTVECTOR(double) p( f.size_dyn_ind() );\n    p[0] = 1.0;\n    p[1] = 0.0;\n    f.new_dynamic(p);\n\n    // function values\n    y    = f.Forward(0, x);\n    ok &= ( y[0] == x[1] );\n    ok &= ( y[1] == x[1] );\n    ok &= ( y[2] == x[1] );\n    ok &= ( y[3] == x[0] );\n    ok &= ( y[4] == x[0] );\n\n    // forward mode derivative values\n    dx[0] = 1.;\n    dx[1] = 2.;\n    dy    = f.Forward(1, dx);\n    ok   &= (dy[0] == dx[1] );\n    ok   &= (dy[1] == dx[1] );\n    ok   &= (dy[2] == dx[1] );\n    ok   &= (dy[3] == dx[0] );\n    ok   &= (dy[4] == dx[0] );\n\n    // reverse mode derivative values\n    dy[0] = 1.;\n    dy[1] = 2.;\n    dy[2] = 3.;\n    dy[3] = 4.;\n    dy[4] = 5.;\n    dx    = f.Reverse(1, dy);\n    ok   &= dx[0] == dy[3] + dy[4];\n    ok   &= dx[1] == dy[0] + dy[1] + dy[2];\n\n    return ok;\n}\n\nbool CondExp_pvvv(void)\n{   bool ok = true;\n\n    using namespace CppAD;\n\n    // independent variable vector\n    CPPAD_TESTVECTOR(AD<double>) X(3);\n    X[0]     = 0.;\n    X[1]     = 1.;\n    X[2]     = 2.;\n    Independent(X);\n\n    // parameter value\n    AD<double> one = 1.;\n\n    // dependent variable vector\n    CPPAD_TESTVECTOR(AD<double>) Y(5);\n\n    // CondExp(parameter, variable, variable, variable)\n    Y[0] = CondExpLt(one, X[0], X[1], X[2]);\n    Y[1] = CondExpLe(one, X[0], X[1], X[2]);\n    Y[2] = CondExpEq(one, X[0], X[1], X[2]);\n    Y[3] = CondExpGe(one, X[0], X[1], X[2]);\n    Y[4] = CondExpGt(one, X[0], X[1], X[2]);\n\n    // create f: X -> Y\n    ADFun<double> f(X, Y);\n\n    // vectors for function values\n    CPPAD_TESTVECTOR(double) v( f.Domain() );\n    CPPAD_TESTVECTOR(double) w( f.Range() );\n\n    // vectors for derivative values\n    CPPAD_TESTVECTOR(double) dv( f.Domain() );\n    CPPAD_TESTVECTOR(double) dw( f.Range() );\n\n    // check original function values\n    ok &= Y[0] == X[2];\n    ok &= Y[1] == X[2];\n    ok &= Y[2] == X[2];\n    ok &= Y[3] == X[1];\n    ok &= Y[4] == X[1];\n\n    // function values\n    v[0] = 2.;\n    v[1] = 1.;\n    v[2] = 0.;\n    w    = f.Forward(0, v);\n    ok &= ( w[0] == v[1] );\n    ok &= ( w[1] == v[1] );\n    ok &= ( w[2] == v[2] );\n    ok &= ( w[3] == v[2] );\n    ok &= ( w[4] == v[2] );\n\n    // forward mode derivative values\n    dv[0] = 1.;\n    dv[1] = 2.;\n    dv[2] = 3.;\n    dw    = f.Forward(1, dv);\n    ok   &= (dw[0] == dv[1] );\n    ok   &= (dw[1] == dv[1] );\n    ok   &= (dw[2] == dv[2] );\n    ok   &= (dw[3] == dv[2] );\n    ok   &= (dw[4] == dv[2] );\n\n    // reverse mode derivative values\n    dw[0] = 1.;\n    dw[1] = 2.;\n    dw[2] = 3.;\n    dw[3] = 4.;\n    dw[4] = 5.;\n    dv    = f.Reverse(1, dw);\n    ok   &= (dv[0] == 0.);\n    ok   &= (dv[1] == dw[0] + dw[1] );\n    ok   &= (dv[2] == dw[2] + dw[3] + dw[4] );\n\n    return ok;\n}\nbool CondExp_vpvv(void)\n{   bool ok = true;\n\n    using namespace CppAD;\n\n    // independent variable vector\n    CPPAD_TESTVECTOR(AD<double>) X(3);\n    X[0]     = 0.;\n    X[1]     = 1.;\n    X[2]     = 2.;\n    Independent(X);\n\n    // parameter value\n    AD<double> one = 1.;\n\n    // dependent variable vector\n    CPPAD_TESTVECTOR(AD<double>) Y(5);\n\n    // CondExp(variable, parameter, variable, variable)\n    Y[0] = CondExpLt(X[0], one, X[1], X[2]);\n    Y[1] = CondExpLe(X[0], one, X[1], X[2]);\n    Y[2] = CondExpEq(X[0], one, X[1], X[2]);\n    Y[3] = CondExpGe(X[0], one, X[1], X[2]);\n    Y[4] = CondExpGt(X[0], one, X[1], X[2]);\n\n    // create f: X -> Y\n    ADFun<double> f(X, Y);\n\n    // vectors for function values\n    CPPAD_TESTVECTOR(double) v( f.Domain() );\n    CPPAD_TESTVECTOR(double) w( f.Range() );\n\n    // vectors for derivative values\n    CPPAD_TESTVECTOR(double) dv( f.Domain() );\n    CPPAD_TESTVECTOR(double) dw( f.Range() );\n\n    // check original function values\n    ok &= Y[0] == X[1];\n    ok &= Y[1] == X[1];\n    ok &= Y[2] == X[2];\n    ok &= Y[3] == X[2];\n    ok &= Y[4] == X[2];\n\n    // function values\n    v[0] = 2.;\n    v[1] = 1.;\n    v[2] = 0.;\n    w    = f.Forward(0, v);\n    ok &= ( w[0] == v[2] );\n    ok &= ( w[1] == v[2] );\n    ok &= ( w[2] == v[2] );\n    ok &= ( w[3] == v[1] );\n    ok &= ( w[4] == v[1] );\n\n    // forward mode derivative values\n    dv[0] = 1.;\n    dv[1] = 2.;\n    dv[2] = 3.;\n    dw    = f.Forward(1, dv);\n    ok   &= (dw[0] == dv[2] );\n    ok   &= (dw[1] == dv[2] );\n    ok   &= (dw[2] == dv[2] );\n    ok   &= (dw[3] == dv[1] );\n    ok   &= (dw[4] == dv[1] );\n\n    // reverse mode derivative values\n    dw[0] = 1.;\n    dw[1] = 2.;\n    dw[2] = 3.;\n    dw[3] = 4.;\n    dw[4] = 5.;\n    dv    = f.Reverse(1, dw);\n    ok   &= (dv[0] == 0.);\n    ok   &= (dv[1] == dw[3] + dw[4] );\n    ok   &= (dv[2] == dw[0] + dw[1] + dw[2] );\n\n    return ok;\n}\nbool CondExp_vvpv(void)\n{   bool ok = true;\n\n    using namespace CppAD;\n\n    // independent variable vector\n    CPPAD_TESTVECTOR(AD<double>) X(3);\n    X[0]     = 0.;\n    X[1]     = 1.;\n    X[2]     = 2.;\n    Independent(X);\n\n    // parameter value\n    AD<double> three = 3.;\n\n    // dependent variable vector\n    CPPAD_TESTVECTOR(AD<double>) Y(5);\n\n    // CondExp(variable, variable, parameter, variable)\n    Y[0] = CondExpLt(X[0], X[1], three, X[2]);\n    Y[1] = CondExpLe(X[0], X[1], three, X[2]);\n    Y[2] = CondExpEq(X[0], X[1], three, X[2]);\n    Y[3] = CondExpGe(X[0], X[1], three, X[2]);\n    Y[4] = CondExpGt(X[0], X[1], three, X[2]);\n\n    // create f: X -> Y\n    ADFun<double> f(X, Y);\n\n    // vectors for function values\n    CPPAD_TESTVECTOR(double) v( f.Domain() );\n    CPPAD_TESTVECTOR(double) w( f.Range() );\n\n    // vectors for derivative values\n    CPPAD_TESTVECTOR(double) dv( f.Domain() );\n    CPPAD_TESTVECTOR(double) dw( f.Range() );\n\n    // check original function values\n    ok &= Y[0] == three;\n    ok &= Y[1] == three;\n    ok &= Y[2] == X[2];\n    ok &= Y[3] == X[2];\n    ok &= Y[4] == X[2];\n\n    // function values\n    v[0] = 2.;\n    v[1] = 1.;\n    v[2] = 0.;\n    w    = f.Forward(0, v);\n    ok &= ( w[0] == v[2] );\n    ok &= ( w[1] == v[2] );\n    ok &= ( w[2] == v[2] );\n    ok &= ( w[3] == three );\n    ok &= ( w[4] == three );\n\n    // forward mode derivative values\n    dv[0] = 1.;\n    dv[1] = 2.;\n    dv[2] = 3.;\n    dw    = f.Forward(1, dv);\n    ok   &= (dw[0] == dv[2] );\n    ok   &= (dw[1] == dv[2] );\n    ok   &= (dw[2] == dv[2] );\n    ok   &= (dw[3] == 0.    );\n    ok   &= (dw[4] == 0.    );\n\n    // reverse mode derivative values\n    dw[0] = 1.;\n    dw[1] = 2.;\n    dw[2] = 3.;\n    dw[3] = 4.;\n    dw[4] = 5.;\n    dv    = f.Reverse(1, dw);\n    ok   &= (dv[0] == 0.);\n    ok   &= (dv[1] == 0.);\n    ok   &= (dv[2] == dw[0] + dw[1] + dw[2] );\n\n    return ok;\n}\nbool CondExp_vvvp(void)\n{   bool ok = true;\n\n    using namespace CppAD;\n\n    // independent variable vector\n    CPPAD_TESTVECTOR(AD<double>) X(3);\n    X[0]     = 0.;\n    X[1]     = 1.;\n    X[2]     = 2.;\n    Independent(X);\n\n    // parameter value\n    AD<double> three = 3.;\n\n    // dependent variable vector\n    CPPAD_TESTVECTOR(AD<double>) Y(5);\n\n    // CondExp(variable, variable, variable, parameter)\n    Y[0] = CondExpLt(X[0], X[1], X[2], three);\n    Y[1] = CondExpLe(X[0], X[1], X[2], three);\n    Y[2] = CondExpEq(X[0], X[1], X[2], three);\n    Y[3] = CondExpGe(X[0], X[1], X[2], three);\n    Y[4] = CondExpGt(X[0], X[1], X[2], three);\n\n    // create f: X -> Y\n    ADFun<double> f(X, Y);\n\n    // vectors for function values\n    CPPAD_TESTVECTOR(double) v( f.Domain() );\n    CPPAD_TESTVECTOR(double) w( f.Range() );\n\n    // vectors for derivative values\n    CPPAD_TESTVECTOR(double) dv( f.Domain() );\n    CPPAD_TESTVECTOR(double) dw( f.Range() );\n\n    // check original function values\n    ok &= Y[0] == X[2];\n    ok &= Y[1] == X[2];\n    ok &= Y[2] == three;\n    ok &= Y[3] == three;\n    ok &= Y[4] == three;\n\n    // function values\n    v[0] = 2.;\n    v[1] = 1.;\n    v[2] = 0.;\n    w    = f.Forward(0, v);\n    ok &= ( w[0] == three );\n    ok &= ( w[1] == three );\n    ok &= ( w[2] == three );\n    ok &= ( w[3] == v[2]  );\n    ok &= ( w[4] == v[2]  );\n\n    // forward mode derivative values\n    dv[0] = 1.;\n    dv[1] = 2.;\n    dv[2] = 3.;\n    dw    = f.Forward(1, dv);\n    ok   &= (dw[0] == 0.    );\n    ok   &= (dw[1] == 0.    );\n    ok   &= (dw[2] == 0.    );\n    ok   &= (dw[3] == dv[2] );\n    ok   &= (dw[4] == dv[2] );\n\n    // reverse mode derivative values\n    dw[0] = 1.;\n    dw[1] = 2.;\n    dw[2] = 3.;\n    dw[3] = 4.;\n    dw[4] = 5.;\n    dv    = f.Reverse(1, dw);\n    ok   &= (dv[0] == 0.);\n    ok   &= (dv[1] == 0.);\n    ok   &= (dv[2] == dw[3] + dw[4] );\n\n    return ok;\n}\n\n# include <limits>\nbool SecondOrderReverse(void)\n{   // Bradley M. Bell 2009-07-04\n    // Reverse mode for CExpOp was only modifying the highest order partial\n    // This test demonstrated the bug\n    bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps = 10. * std::numeric_limits<double>::epsilon();\n\n    size_t n = 1;\n    CPPAD_TESTVECTOR(AD<double>) X(n);\n    X[0] = 2.;\n    CppAD::Independent(X);\n\n    size_t m = 2;\n    CPPAD_TESTVECTOR(AD<double>) Y(m);\n\n    AD<double> left = X[0];\n    AD<double> right = X[0] * X[0];\n    AD<double> exp_if_true  = left;\n    AD<double> exp_if_false = right;\n\n    // Test of reverse mode using exp_if_true case\n    // For this value of X, should be the same as Z = X[0]\n    AD<double> Z = CondExpLt(left, right, exp_if_true, exp_if_false);\n    Y[0] = Z * Z;\n\n    // Test of reverse mode  using exp_if_false case\n    exp_if_false = left;\n    exp_if_true  = right;\n    Z            = CondExpGt(left, right, exp_if_true, exp_if_false);\n    Y[1]         = Z * Z;\n\n    CppAD::ADFun<double> f(X, Y);\n\n    // first order forward\n    CPPAD_TESTVECTOR(double) dx(n);\n    size_t p = 1;\n    dx[0]    = 1.;\n    f.Forward(p, dx);\n\n    // second order reverse (test exp_if_true case)\n    CPPAD_TESTVECTOR(double) w(m), dw(2 * n);\n    w[0] = 1.;\n    w[1] = 0.;\n    p    = 2;\n    dw = f.Reverse(p, w);\n\n    // check first derivative in dw\n    double check = 2. * Value( X[0] );\n    ok &= NearEqual(dw[0], check, eps, eps);\n\n    // check second derivative in dw\n    check = 2.;\n    ok &= NearEqual(dw[1], check, eps, eps);\n\n    // test exp_if_false case\n    w[0] = 0.;\n    w[1] = 1.;\n    p    = 2;\n    dw = f.Reverse(p, w);\n\n    // check first derivative in dw\n    check = 2. * Value( X[0] );\n    ok &= NearEqual(dw[0], check, eps, eps);\n\n    // check second derivative in dw\n    check = 2.;\n    ok &= NearEqual(dw[1], check, eps, eps);\n\n    return ok;\n}\n\ndouble Infinity(double zero)\n{        return 1. / zero; }\n\nbool OldExample(void)\n{   bool ok = true;\n\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    using CppAD::log;\n    double eps = 100. * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n = 5;\n    CPPAD_TESTVECTOR(AD<double>) X(n);\n    size_t j;\n    for(j = 0; j < n; j++)\n        X[j] = 1.;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(X);\n\n    // sum with respect to j of log of absolute value of X[j]\n    // should be - infinity if any of the X[j] are zero\n    AD<double> MinusInfinity = - Infinity(0.);\n    AD<double> Sum           = 0.;\n    AD<double> Zero(0);\n    for(j = 0; j < n; j++)\n    {   // if X[j] > 0\n        Sum += CppAD::CondExpGt(X[j], Zero, log(X[j]),     Zero);\n\n        // if X[j] < 0\n        Sum += CppAD::CondExpLt(X[j], Zero, log(-X[j]),    Zero);\n\n        // if X[j] == 0\n        Sum += CppAD::CondExpEq(X[j], Zero, MinusInfinity, Zero);\n    }\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) Y(m);\n    Y[0] = Sum;\n\n    // create f: X -> Y and stop tape recording\n    CppAD::ADFun<double> f(X, Y);\n\n    // vectors for arguments to the function object f\n    CPPAD_TESTVECTOR(double) x(n);   // argument values\n    CPPAD_TESTVECTOR(double) y(m);   // function values\n    CPPAD_TESTVECTOR(double) w(m);   // function weights\n    CPPAD_TESTVECTOR(double) dw(n);  // derivative of weighted function\n\n    // a case where fabs( x[j] ) > 0 for all j\n    double check  = 0.;\n    double sign   = 1.;\n    for(j = 0; j < n; j++)\n    {   sign *= -1.;\n        x[j] = sign * double(j + 1);\n        check += log( fabs( x[j] ) );\n    }\n\n    // function value\n    y  = f.Forward(0, x);\n    ok &= ( y[0] == check );\n\n    // compute derivative of y[0]\n    w[0] = 1.;\n    dw   = f.Reverse(1, w);\n    for(j = 0; j < n; j++)\n    {   if( x[j] > 0. )\n            ok &= NearEqual(dw[j], 1./fabs( x[j] ), eps, eps);\n        else\n            ok &= NearEqual(dw[j], -1./fabs( x[j] ), eps, eps);\n    }\n\n    // a case where x[0] is equal to zero\n    sign = 1.;\n    for(j = 0; j < n; j++)\n    {   sign *= -1.;\n        x[j] = sign * double(j);\n    }\n\n    // function value\n    y   = f.Forward(0, x);\n    ok &= ( y[0] == -Infinity(0.) );\n\n    // compute derivative of y[0]\n    f.check_for_nan(false);\n    w[0] = 1.;\n    dw   = f.Reverse(1, w);\n    for(j = 0; j < n; j++)\n    {   if( x[j] > 0. )\n            ok &= NearEqual(dw[j], 1./fabs( x[j] ), eps, eps);\n        else if( x[j] < 0. )\n            ok &= NearEqual(dw[j], -1./fabs( x[j] ), eps, eps);\n        else\n            ok &= NearEqual(dw[j], 0.0, eps, eps);\n    }\n\n    return ok;\n}\n} // end empty namespace\n\nbool CondExp(void)\n{   bool ok  = true;\n    ok      &= CondExp_ppvv();\n    ok      &= CondExp_pvvv();\n    ok      &= CondExp_vpvv();\n    ok      &= CondExp_vvpv();\n    ok      &= CondExp_vvvp();\n    ok      &= SecondOrderReverse();\n    ok      &= OldExample();\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "test_more/general/cond_exp_ad.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\nTest of CondExp with AD< AD< Base > > types\n*/\n\n# include <cppad/cppad.hpp>\n\ntypedef CppAD::AD< double >     ADdouble;\ntypedef CppAD::AD< ADdouble > ADADdouble;\n\nnamespace { // BEGIN empty namespace\n\nbool CondExpADOne(void)\n{   bool ok = true;\n\n    using namespace CppAD;\n    size_t n = 3;\n    size_t m = 8;\n\n    // ADdouble independent variable vector\n    CPPAD_TESTVECTOR( ADdouble ) Xa(n);\n    Xa[0] = -1.;\n    Xa[1] =  0.;\n    Xa[2] =  1.;\n    Independent(Xa);\n\n    // ADdouble independent variable vector\n    CPPAD_TESTVECTOR( ADADdouble ) Xaa(n);\n    Xaa[0] = Xa[0];\n    Xaa[1] = Xa[1];\n    Xaa[2] = Xa[2];\n    Independent(Xaa);\n\n    // ADADdouble parameter\n    ADADdouble p = ADADdouble(Xa[0]);\n    ADADdouble q = ADADdouble(Xa[1]);\n    ADADdouble r = ADADdouble(Xa[2]);\n\n    // ADADdouble dependent variable vector\n    CPPAD_TESTVECTOR( ADADdouble ) Yaa(m);\n\n    // CondExp(parameter, parameter, parameter)\n    Yaa[0] = CondExp(p, q, r);\n\n    // CondExp(parameter, parameter, variable)\n    Yaa[1] = CondExp(p, q, Xaa[2]);\n\n    // CondExp(parameter, variable, parameter)\n    Yaa[2] = CondExp(p, Xaa[1], r);\n\n    // CondExp(parameter, variable, variable)\n    Yaa[3] = CondExp(p, Xaa[1], Xaa[2]);\n\n    // CondExp(variable, variable, variable)\n    Yaa[5] = CondExp(Xaa[0], Xaa[1], Xaa[2]);\n\n    // CondExp(variable, variable, parameter)\n    Yaa[4] = CondExp(Xaa[0], Xaa[1], r);\n\n    // CondExp(variable, parameter, variable)\n    Yaa[6] =  CondExp(Xaa[0], q, Xaa[2]);\n\n    // CondExp(variable, parameter, parameter)\n    Yaa[7] =  CondExp(Xaa[0], q, r);\n\n    // create fa: Xaa -> Yaa function object\n    ADFun< ADdouble > fa(Xaa, Yaa);\n\n    // function values\n    CPPAD_TESTVECTOR( ADdouble ) Ya(m);\n    Ya  = fa.Forward(0, Xa);\n\n    // create f: Xa -> Ya function object\n    ADFun<double> f(Xa, Ya);\n\n    // check result of function evaluation\n    CPPAD_TESTVECTOR(double) x(n);\n    CPPAD_TESTVECTOR(double) y(m);\n    x[0] = 1.;\n    x[1] = 0.;\n    x[2] = -1.;\n    y = f.Forward(0, x);\n    size_t i;\n    for(i = 0; i < m; i++)\n    {   // y[i] = CondExp(x[0], x[1], x[2])\n        if( x[0] > 0 )\n            ok &= (y[i] == x[1]);\n        else\n            ok &= (y[i] == x[2]);\n    }\n\n    // check forward mode derivatives\n    CPPAD_TESTVECTOR(double) dx(n);\n    CPPAD_TESTVECTOR(double) dy(m);\n    dx[0] = 1.;\n    dx[1] = 2.;\n    dx[2] = 3.;\n    dy    = f.Forward(1, dx);\n    for(i = 0; i < m; i++)\n    {   if( x[0] > 0. )\n            ok &= (dy[i] == dx[1]);\n        else\n            ok &= (dy[i] == dx[2]);\n    }\n\n    // calculate Jacobian\n    CPPAD_TESTVECTOR(double) J(m * n);\n    size_t j;\n    for(i = 0; i < m; i++)\n    {   for(j = 0; j < n; j++)\n            J[i * n + j] = 0.;\n        if( x[0] > 0. )\n            J[i * n + 1] = 1.;\n        else\n            J[i * n + 2] = 1.;\n    }\n\n    // check reverse mode derivatives\n    for(i = 0; i < m; i++)\n        dy[i] = double(i);\n    dx    = f.Reverse(1, dy);\n    double sum;\n    for(j = 0; j < n; j++)\n    {   sum = 0;\n        for(i = 0; i < m; i++)\n            sum += dy[i] * J[i * n + j];\n        ok &= (sum == dx[j]);\n    }\n\n    // forward mode computation of sparsity pattern\n    CPPAD_TESTVECTOR(bool) Px(n * n);\n    for(i = 0; i < n; i++)\n    {   for(j = 0; j < n; j++)\n            Px[i * n + j] = false;\n        Px[i * n + i] = true;\n    }\n    CPPAD_TESTVECTOR(bool) Py(m * n);\n    Py = f.ForSparseJac(n, Px);\n    for(i = 0; i < m; i++)\n    {   ok &= Py[ i * n + 0 ] == false;\n        ok &= Py[ i * n + 1 ] == true;\n        ok &= Py[ i * n + 2 ] == true;\n    }\n\n    // reverse mode computation of sparsity pattern\n    Py.resize(m * m);\n    for(i = 0; i < m; i++)\n    {   for(j = 0; j < m; j++)\n            Py[i * m + j] = false;\n        Py[i * m + i] = true;\n    }\n    Px.resize(m * n);\n    Px = f.RevSparseJac(m, Py);\n    for(i = 0; i < m; i++)\n    {   for(j = 0; j < n; j++)\n            ok &= ( Px[i * n + j] == ( j > 0 ) );\n    }\n\n    return ok;\n}\nbool CondExpADTwo(void)\n{   bool ok = true;\n\n    using namespace CppAD;\n    size_t n = 3;\n    size_t m = 8;\n\n    // ADdouble independent variable vector\n    CPPAD_TESTVECTOR( ADdouble ) Xa(n);\n    Xa[0] = -1.;\n    Xa[1] =  0.;\n    Xa[2] =  1.;\n    Independent(Xa);\n\n    // use VecAD so that sparsity results are local\n    VecAD<double> Va(1);\n    ADdouble zero = 0.;\n    Va[zero]      = Xa[0];\n\n    // ADdouble independent variable vector\n    CPPAD_TESTVECTOR( ADADdouble ) Xaa(n);\n    Xaa[0] = ADdouble( Va[zero] );\n    Xaa[1] = Xa[1];\n    Xaa[2] = Xa[2];\n    Independent(Xaa);\n\n    // ADADdouble parameter\n    ADADdouble p = ADADdouble(Xa[0]);\n    ADADdouble q = ADADdouble(Xa[1]);\n    ADADdouble r = ADADdouble(Xa[2]);\n\n    // ADADdouble dependent variable vector\n    CPPAD_TESTVECTOR( ADADdouble ) Yaa(m);\n\n    // CondExp(parameter, parameter, parameter)\n    Yaa[0] = CondExp(p, q, r);\n\n    // CondExp(parameter, parameter, variable)\n    Yaa[1] = CondExp(p, q, Xaa[2]);\n\n    // CondExp(parameter, variable, parameter)\n    Yaa[2] = CondExp(p, Xaa[1], r);\n\n    // CondExp(parameter, variable, variable)\n    Yaa[3] = CondExp(p, Xaa[1], Xaa[2]);\n\n    // CondExp(variable, variable, variable)\n    Yaa[5] = CondExp(Xaa[0], Xaa[1], Xaa[2]);\n\n    // CondExp(variable, variable, parameter)\n    Yaa[4] = CondExp(Xaa[0], Xaa[1], r);\n\n    // CondExp(variable, parameter, variable)\n    Yaa[6] =  CondExp(Xaa[0], q, Xaa[2]);\n\n    // CondExp(variable, parameter, parameter)\n    Yaa[7] =  CondExp(Xaa[0], q, r);\n\n    // create fa: Xaa -> Yaa function object\n    ADFun< ADdouble > fa(Xaa, Yaa);\n\n    // function values\n    CPPAD_TESTVECTOR( ADdouble ) Ya(m);\n    Ya  = fa.Forward(0, Xa);\n\n    // create f: Xa -> Ya function object\n    ADFun<double> f(Xa, Ya);\n\n    // check use_VecAD\n    ok &= f.use_VecAD();\n\n    // check result of function evaluation\n    CPPAD_TESTVECTOR(double) x(n);\n    CPPAD_TESTVECTOR(double) y(m);\n    x[0] = 1.;\n    x[1] = 0.;\n    x[2] = -1.;\n    y = f.Forward(0, x);\n    size_t i;\n    for(i = 0; i < m; i++)\n    {   // y[i] = CondExp(x[0], x[1], x[2])\n        if( x[0] > 0 )\n            ok &= (y[i] == x[1]);\n        else\n            ok &= (y[i] == x[2]);\n    }\n\n    // check forward mode derivatives\n    CPPAD_TESTVECTOR(double) dx(n);\n    CPPAD_TESTVECTOR(double) dy(m);\n    dx[0] = 1.;\n    dx[1] = 2.;\n    dx[2] = 3.;\n    dy    = f.Forward(1, dx);\n    for(i = 0; i < m; i++)\n    {   if( x[0] > 0. )\n            ok &= (dy[i] == dx[1]);\n        else\n            ok &= (dy[i] == dx[2]);\n    }\n\n    // calculate Jacobian\n    CPPAD_TESTVECTOR(double) J(m * n);\n    size_t j;\n    for(i = 0; i < m; i++)\n    {   for(j = 0; j < n; j++)\n            J[i * n + j] = 0.;\n        if( x[0] > 0. )\n            J[i * n + 1] = 1.;\n        else\n            J[i * n + 2] = 1.;\n    }\n\n    // check reverse mode derivatives\n    for(i = 0; i < m; i++)\n        dy[i] = double(i);\n    dx    = f.Reverse(1, dy);\n    double sum;\n    for(j = 0; j < n; j++)\n    {   sum = 0;\n        for(i = 0; i < m; i++)\n            sum += dy[i] * J[i * n + j];\n        ok &= (sum == dx[j]);\n    }\n\n    // forward mode computation of sparsity pattern\n    CPPAD_TESTVECTOR(bool) Px(n * n);\n    for(i = 0; i < n; i++)\n    {   for(j = 0; j < n; j++)\n            Px[i * n + j] = false;\n        Px[i * n + i] = true;\n    }\n    CPPAD_TESTVECTOR(bool) Py(m * n);\n    Py = f.ForSparseJac(n, Px);\n    for(i = 0; i < m; i++)\n    {   for(j = 0; j < n; j++)\n            // sparsity pattern works for both true and false cases.\n            ok &= ( Py[i * n + j] == (j > 0) );\n    }\n\n    // reverse mode computation of sparsity pattern\n    Py.resize(m * m);\n    for(i = 0; i < m; i++)\n    {   for(j = 0; j < m; j++)\n            Py[i * m + j] = false;\n        Py[i * m + i] = true;\n    }\n    Px.resize(m * n);\n    Px = f.RevSparseJac(m, Py);\n    for(i = 0; i < m; i++)\n    {   for(j = 0; j < n; j++)\n            ok &= ( Px[i * n + j] == (j > 0) );\n    }\n\n    return ok;\n}\n\n} // END empty namespace\n\nbool CondExpAD(void)\n{   bool ok = true;\n    ok     &= CondExpADOne();\n    ok     &= CondExpADTwo();\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/cond_exp_rev.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n// Test that reverse mode handles conditional expressions properly\n// in that infinity and nans do not propagate thouh un-used case.\n\n# include <cppad/cppad.hpp>\n\nbool cond_exp_rev(void)\n{   bool ok = true;\n    using CppAD::vector;\n    using CppAD::AD;\n\n    AD<double> anan  = std::numeric_limits<double>::quiet_NaN();\n    AD<double> azero = 0.0;\n\n\n    size_t n = 2;\n    vector< AD<double> > ax(n), ay;\n    ax[0] = 1.0;\n    ax[1] = anan;\n    Independent(ax);\n\n    // AbsOp\n    ay.push_back( CondExpGt(ax[0], azero, ax[0], fabs(ax[1]) ));\n\n    // AcosOp\n    ay.push_back( CondExpGt(ax[0], azero, ax[0], acos(ax[1]) ));\n\n    // AddvvOp\n    ay.push_back( CondExpGt(ax[0], azero, ax[0], ax[0] + ax[1] ));\n\n    // AddpvOp\n    ay.push_back( CondExpGt(ax[0], azero, ax[0], 1.0 + ax[1] ));\n\n    // AsinOp\n    ay.push_back( CondExpGt(ax[0], azero, ax[0], asin(ax[1]) ));\n\n    // AtanOp\n    ay.push_back( CondExpGt(ax[0], azero, ax[0], atan(ax[1]) ));\n\n    // CosOp\n    ay.push_back( CondExpGt(ax[0], azero, ax[0], cos(ax[1]) ));\n\n    // CoshOp\n    ay.push_back( CondExpGt(ax[0], azero, ax[0], cosh(ax[1]) ));\n\n    // DivvvOp\n    ay.push_back( CondExpGt(ax[0], azero, ax[0], ax[0] / ax[1] ));\n\n    // DivpvOp\n    ay.push_back( CondExpGt(ax[0], azero, ax[0], 1.0 / ax[1] ));\n\n    // DivvpOp\n    ay.push_back( CondExpGt(ax[0], azero, ax[0], ax[1] / 2.0 ));\n\n    // ErfOp\n    ay.push_back( CondExpGt(ax[0], azero, ax[0], erf(ax[1]) ));\n\n    // ExpOp\n    ay.push_back( CondExpGt(ax[0], azero, ax[0], exp(ax[1]) ));\n\n    // LogOp\n    ay.push_back( CondExpGt(ax[0], azero, ax[0], log(ax[1]) ));\n\n    // MulvvOp\n    ay.push_back( CondExpGt(ax[0], azero, ax[0], ax[0] * ax[1] ));\n\n    // MulpvOp\n    ay.push_back( CondExpGt(ax[0], azero, ax[0], 2.0 * ax[1] ));\n\n    // PowvvOP\n    // uses check in log, mul, and exp\n    ay.push_back( CondExpGt(ax[0], azero, ax[0], pow(ax[1], ax[1]) ));\n\n    // PowvpOP\n    // uses check in log, mul, and exp\n    ay.push_back( CondExpGt(ax[0], azero, ax[0], pow(ax[1], 2.0) ));\n\n    // PowpvOP\n    // uses check in log, mul, and exp\n    ay.push_back( CondExpGt(ax[0], azero, ax[0], pow(2.0, ax[1]) ));\n\n    // SignOp\n    ay.push_back( CondExpGt(ax[0], azero, ax[0], sign(ax[1]) ));\n\n    // SinOp\n    ay.push_back( CondExpGt(ax[0], azero, ax[0], sin(ax[1]) ));\n\n    // SinhOp\n    ay.push_back( CondExpGt(ax[0], azero, ax[0], sinh(ax[1]) ));\n\n    // SqrtOp\n    ay.push_back( CondExpGt(ax[0], azero, ax[0], sqrt(ax[1]) ));\n\n    // SubvvOp\n    ay.push_back( CondExpGt(ax[0], azero, ax[0], ax[0] - ax[1] ));\n\n    // SubpvOp\n    ay.push_back( CondExpGt(ax[0], azero, ax[0], 1.0 - ax[1] ));\n\n    // SubvpOp\n    ay.push_back( CondExpGt(ax[0], azero, ax[0], ax[1] - 1.0 ));\n\n    // TanOp\n    ay.push_back( CondExpGt(ax[0], azero, ax[0], tan(ax[1]) ));\n\n    // TanhOp\n    ay.push_back( CondExpGt(ax[0], azero, ax[0], tanh(ax[1]) ));\n\n    // create f : x -> y\n    size_t m = ay.size();\n    CppAD::ADFun<double> f(ax, ay);\n\n    // weighting vector and reverse mode derivative\n    vector<double> w(m), dw(n);\n    for(size_t i = 0; i < m; i++)\n        w[i] = 0.0;\n\n    // check DivvOp\n    for(size_t i = 0; i < m; i++)\n    {   w[i] = 1.0;\n        dw = f.Reverse(1, w);\n        ok &= dw[0] == 1.0;\n        ok &= dw[1] == 0.0;\n        w[i] = 0.0;\n    }\n\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/copy.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\nOld Copy example now used just for valiadation testing\n*/\n\n# include <cppad/cppad.hpp>\n\nnamespace { // begin empty namespace\n\nbool copy_older(void)\n{   bool ok = true;\n\n    using namespace CppAD;\n\n    // independent variable vector, indices, values, and declaration\n    CPPAD_TESTVECTOR(AD<double>) U(1);\n    size_t is = 0;\n    U[is]     = 2.;\n    Independent(U);\n\n    // create an AD<double> that does not depend on s\n    AD<double> t = 3.;\n\n    // use copy constructor\n    AD<double> x(U[is]);\n    AD<double> y(t);\n\n    // check which are parameters\n    ok &= ! Parameter(x);\n    ok &= Parameter(y);\n\n    // dependent variable vector, indices, and values\n    CPPAD_TESTVECTOR(AD<double>) Z(2);\n    size_t ix = 0;\n    size_t iy = 1;\n    Z[ix]     = x;\n    Z[iy]     = y;\n\n    // create f: U -> Z and vectors used for derivative calculations\n    ADFun<double> f(U, Z);\n    CPPAD_TESTVECTOR(double) v( f.Domain() );\n    CPPAD_TESTVECTOR(double) w( f.Range() );\n\n    // check parameters flags\n    ok &= ! f.Parameter(ix);\n    ok &=   f.Parameter(iy);\n\n    // check function values\n    ok &= ( Z[ix] == 2. );\n    ok &= ( Z[iy] == 3. );\n\n    // forward computation of partials w.r.t. s\n    v[is] = 1.;\n    w     = f.Forward(1, v);\n    ok &= ( w[ix] == 1. );   // dx/ds\n    ok &= ( w[iy] == 0. );   // dy/ds\n\n    return ok;\n}\n\nbool copy_ad(void)\n{   bool ok = true;   // initialize test result flag\n    using CppAD::AD;  // so can use AD in place of CppAD::AD\n\n    // domain space vector\n    size_t n = 1;\n    CPPAD_TESTVECTOR(AD<double>) x(n);\n    x[0]     = 2.;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(x);\n\n    // create an AD<double> that does not depend on x\n    AD<double> b = 3.;\n\n    // use copy constructor\n    AD<double> u(x[0]);\n    AD<double> v = b;\n\n    // check which are parameters\n    ok &= Variable(u);\n    ok &= Parameter(v);\n\n    // range space vector\n    size_t m = 2;\n    CPPAD_TESTVECTOR(AD<double>) y(m);\n    y[0]  = u;\n    y[1]  = v;\n\n    // create f: x -> y and vectors used for derivative calculations\n    CppAD::ADFun<double> f(x, y);\n    CPPAD_TESTVECTOR(double) dx(n);\n    CPPAD_TESTVECTOR(double) dy(m);\n\n    // check parameters flags\n    ok &= ! f.Parameter(0);\n    ok &=   f.Parameter(1);\n\n    // check function values\n    ok &= ( y[0] == 2. );\n    ok &= ( y[1] == 3. );\n\n    // forward computation of partials w.r.t. x[0]\n    dx[0] = 1.;\n    dy    = f.Forward(1, dx);\n    ok   &= ( dy[0] == 1. );   // du / dx\n    ok   &= ( dy[1] == 0. );   // dv / dx\n\n    return ok;\n}\nbool copy_base(void)\n{   bool ok = true;    // initialize test result flag\n    using CppAD::AD;   // so can use AD in place of CppAD::AD\n\n    // construct directly from Base where Base is double\n    AD<double> x(1.);\n\n    // construct from a type that converts to Base where Base is double\n    AD<double> y = 2;\n\n    // construct from a type that converts to Base where Base = AD<double>\n    AD< AD<double> > z(3);\n\n    // check that resulting objects are parameters\n    ok &= Parameter(x);\n    ok &= Parameter(y);\n    ok &= Parameter(z);\n\n    // check values of objects (compare AD<double> with double)\n    ok &= ( x == 1.);\n    ok &= ( y == 2.);\n    ok &= ( Value(z) == 3.);\n\n    // user constructor through the static_cast template function\n    x   = static_cast < AD<double> >( 4 );\n    z  = static_cast < AD< AD<double> > >( 5 );\n\n    ok &= ( x == 4. );\n    ok &= ( Value(z) == 5. );\n\n    return ok;\n}\nbool default_ctor(void)\n{   bool ok = true;\n    using CppAD::AD;\n\n    // default AD constructor\n    AD<double> x, y;\n\n    // check that they are parameters\n    ok &= Parameter(x);\n    ok &= Parameter(y);\n\n    // assign them values\n    x = 3.;\n    y = 4.;\n\n    // just check a simple operation\n    ok &= (x + y == 7.);\n\n    return ok;\n}\n\n// END PROGRAM\n} // end empty namespace\nbool copy(void)\n{   bool ok = true;\n    ok &= copy_older();\n    ok &= copy_ad();\n    ok &= copy_base();\n    ok &= default_ctor();\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/cos.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\nOld example now just used for validation testing\n*/\n# include <cppad/cppad.hpp>\n\nbool Cos(void)\n{   bool ok = true;\n    using CppAD::sin;\n    using CppAD::cos;\n    using namespace CppAD;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // independent variable vector\n    CPPAD_TESTVECTOR(AD<double>) U(1);\n    U[0]     = 1.;\n    Independent(U);\n\n    // dependent variable vector\n    CPPAD_TESTVECTOR(AD<double>) Z(1);\n    Z[0] = cos(U[0]);\n\n    // create f: U -> Z and vectors used for derivative calculations\n    ADFun<double> f(U, Z);\n    CPPAD_TESTVECTOR(double) v(1);\n    CPPAD_TESTVECTOR(double) w(1);\n\n    // check value\n    double sin_u = sin( Value(U[0]) );\n    double cos_u = cos( Value(U[0]) );\n\n    ok &= NearEqual(cos_u, Value(Z[0]),  eps99 , eps99);\n\n    // forward computation of partials w.r.t. u\n    size_t j;\n    size_t p     = 5;\n    double jfac  = 1.;\n    v[0]         = 1.;\n    for(j = 1; j < p; j++)\n    {   w     = f.Forward(j, v);\n\n        double value;\n        if( j % 4 == 1 )\n            value = -sin_u;\n        else if( j % 4 == 2 )\n            value = -cos_u;\n        else if( j % 4 == 3 )\n            value = sin_u;\n        else\n            value = cos_u;\n\n        jfac *= double(j);\n        ok &= NearEqual(w[0], value/jfac, eps99, eps99); // d^jz/du^j\n        v[0]  = 0.;\n    }\n\n    // reverse computation of partials of Taylor coefficients\n    CPPAD_TESTVECTOR(double) r(p);\n    w[0]  = 1.;\n    r     = f.Reverse(p, w);\n    jfac  = 1.;\n    for(j = 0; j < p; j++)\n    {\n        double value;\n        if( j % 4 == 0 )\n            value = -sin_u;\n        else if( j % 4 == 1 )\n            value = -cos_u;\n        else if( j % 4 == 2 )\n            value = sin_u;\n        else\n            value = cos_u;\n\n        ok &= NearEqual(r[j], value/jfac, eps99, eps99); // d^jz/du^j\n\n        jfac *= double(j + 1);\n    }\n\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/cosh.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\nOld example now just used for validation testing.\n*/\n# include <cppad/cppad.hpp>\n\nbool Cosh(void)\n{   bool ok = true;\n    using CppAD::sinh;\n    using CppAD::cosh;\n    using namespace CppAD;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // independent variable vector\n    CPPAD_TESTVECTOR(AD<double>) U(1);\n    U[0]     = 1.;\n    Independent(U);\n\n    // dependent variable vector\n    CPPAD_TESTVECTOR(AD<double>) Z(1);\n    Z[0] = cosh(U[0]);\n\n    // create f: U -> Z and vectors used for derivative calculations\n    ADFun<double> f(U, Z);\n    CPPAD_TESTVECTOR(double) v(1);\n    CPPAD_TESTVECTOR(double) w(1);\n\n    // check value\n    double sinh_u = sinh( Value(U[0]) );\n    double cosh_u = cosh( Value(U[0]) );\n\n    ok &= NearEqual(cosh_u, Value(Z[0]),  eps99 , eps99);\n\n    // forward computation of partials w.r.t. u\n    size_t j;\n    size_t p     = 5;\n    double jfac  = 1.;\n    v[0]         = 1.;\n    for(j = 1; j < p; j++)\n    {   w     = f.Forward(j, v);\n\n        double value;\n        if( j % 2 == 1 )\n            value = sinh_u;\n        else\n            value = cosh_u;\n\n        jfac *= double(j);\n        ok &= NearEqual(w[0], value/jfac, eps99, eps99); // d^jz/du^j\n        v[0]  = 0.;\n    }\n\n    // reverse computation of partials of Taylor coefficients\n    CPPAD_TESTVECTOR(double) r(p);\n    w[0]  = 1.;\n    r     = f.Reverse(p, w);\n    jfac  = 1.;\n    for(j = 0; j < p; j++)\n    {\n        double value;\n        if( j % 2 == 0 )\n            value = sinh_u;\n        else\n            value = cosh_u;\n\n        ok &= NearEqual(r[j], value/jfac, eps99, eps99); // d^jz/du^j\n\n        jfac *= double(j + 1);\n    }\n\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/cpp_graph.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\n@begin graph_unary_op.cpp$$\n$spell\n    sin\n$$\n\n$section Graph Unary Operator: Example and Test$$\n\n$head Source Code$$\n$srcthisfile%0%// BEGIN C++%// END C++%1%$$\n\n$end\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nnamespace { // BEGIN_EMPTY_NAMESPACE\n\ntypedef double (*unary_fun_t)(double);\n\nbool test_unary_fun(unary_fun_t fun, CppAD::graph::graph_op_enum op_enum)\n{   bool ok = true;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    //\n    // C++ graph object\n    CppAD::cpp_graph graph_obj;\n    //\n    // value of constant in function\n    CPPAD_TESTVECTOR(double) p(1), x(1), c(1);\n    c[0] = 0.1;\n    p[0] = 0.2;\n    x[0] = 0.3;\n    if( std::isnan( fun( c[0] ) ) )\n        c[0] = 1.0;\n    if( std::isnan( fun( p[0] ) ) )\n        p[0] = 2.0;\n    if( std::isnan( fun( x[0] ) ) )\n        x[0] = 3.0;\n    //\n    // set scalars\n    graph_obj.function_name_set(\"unary_op example\");\n    size_t n_dynamic_ind = 1;\n    graph_obj.n_dynamic_ind_set(n_dynamic_ind);\n    size_t n_variable_ind = 1;\n    graph_obj.n_variable_ind_set(n_variable_ind);\n    graph_obj.constant_vec_push_back( c[0] );\n    //\n    // node_4 : sin(p[0])\n    graph_obj.operator_vec_push_back(op_enum);\n    graph_obj.operator_arg_push_back(1);\n    //\n    // node_5 : sin(x[0])\n    graph_obj.operator_vec_push_back(op_enum);\n    graph_obj.operator_arg_push_back(2);\n    //\n    // node_6 : sin(c[0])\n    graph_obj.operator_vec_push_back(op_enum);\n    graph_obj.operator_arg_push_back(3);\n    //\n    // y[0]   = sin(p[0])\n    graph_obj.dependent_vec_push_back(4);\n    // y[1]   = sin(x[0])\n    graph_obj.dependent_vec_push_back(5);\n    // y[2]   = sin(c[0])\n    graph_obj.dependent_vec_push_back(6);\n    //\n    // f(p, x) = y\n    CppAD::ADFun<double> f;\n    f.from_graph(graph_obj);\n    ok &= f.Domain() == 1;\n    ok &= f.size_dyn_ind() == 1;\n    ok &= f.Range() == 3;\n    //\n    //\n    // compute y = f(p, x)\n    f.new_dynamic(p);\n    CPPAD_TESTVECTOR(double) y = f.Forward(0, x);\n    //\n    // check result\n    ok &= CppAD::NearEqual(y[0], fun(p[0]), eps99, eps99);\n    ok &= CppAD::NearEqual(y[1], fun(x[0]), eps99, eps99);\n    ok &= CppAD::NearEqual(y[2], fun(c[0]), eps99, eps99);\n    // ------------------------------------------------------------------\n    // Convert to Graph graph and back again\n    f.to_graph(graph_obj);\n    f.from_graph(graph_obj);\n    // -------------------------------------------------------------------\n    //\n    // compute y = f(p, x)\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    //\n    // check result\n    ok &= CppAD::NearEqual(y[0], fun(p[0]), eps99, eps99);\n    ok &= CppAD::NearEqual(y[1], fun(x[0]), eps99, eps99);\n    ok &= CppAD::NearEqual(y[2], fun(c[0]), eps99, eps99);\n    //\n    return ok;\n}\n\ndouble sign(double x)\n{   return CppAD::sign(x);\n}\ndouble neg(double x)\n{   return - x;\n}\n\n} // END_EMPTY_NAMESPACE\n\nbool cpp_graph(void)\n{   bool ok = true;\n    ok     &= test_unary_fun(std::fabs,   CppAD::graph::abs_graph_op);\n    ok     &= test_unary_fun(std::acos,   CppAD::graph::acos_graph_op);\n    ok     &= test_unary_fun(std::acosh,  CppAD::graph::acosh_graph_op);\n    ok     &= test_unary_fun(std::asinh,  CppAD::graph::asinh_graph_op);\n    ok     &= test_unary_fun(std::atanh,  CppAD::graph::atanh_graph_op);\n    ok     &= test_unary_fun(std::erf,    CppAD::graph::erf_graph_op);\n    ok     &= test_unary_fun(std::erfc,   CppAD::graph::erfc_graph_op);\n    ok     &= test_unary_fun(std::expm1,  CppAD::graph::expm1_graph_op);\n    ok     &= test_unary_fun(std::log1p,  CppAD::graph::log1p_graph_op);\n    ok     &= test_unary_fun(neg,         CppAD::graph::neg_graph_op);\n    ok     &= test_unary_fun(sign,        CppAD::graph::sign_graph_op);\n    ok     &= test_unary_fun(std::sinh,   CppAD::graph::sinh_graph_op);\n    ok     &= test_unary_fun(std::sin,    CppAD::graph::sin_graph_op);\n    ok     &= test_unary_fun(std::sqrt,   CppAD::graph::sqrt_graph_op);\n    ok     &= test_unary_fun(std::tanh,   CppAD::graph::tanh_graph_op);\n    ok     &= test_unary_fun(std::tan,    CppAD::graph::tan_graph_op);\n    ok     &= test_unary_fun(std::acosh,  CppAD::graph::acosh_graph_op);\n    ok     &= test_unary_fun(std::acosh,  CppAD::graph::acosh_graph_op);\n    ok     &= test_unary_fun(std::sin,    CppAD::graph::sin_graph_op);\n    //\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/cppad_eigen.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\nTest of Eigen Interface to CppAD Scalar Types\n$end\n*/\n# include <cppad/example/cppad_eigen.hpp>\n\nbool cppad_eigen(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using Eigen::Dynamic;\n    using Eigen::Matrix;\n\n    typedef Eigen::NumTraits<AD<double> >         traits;\n\n    ok &= traits::IsComplex              == 0;\n    ok &= traits::IsInteger              == 0;\n    ok &= traits::IsSigned               == 1;\n    ok &= traits::RequireInitialization  == 1;\n    ok &= traits::ReadCost               == 1;\n    ok &= traits::AddCost                == 2;\n    ok &= traits::MulCost                == 2;\n\n    ok &= traits::epsilon() ==\n        std::numeric_limits<double>::epsilon();\n    ok &= traits::dummy_precision() ==\n        100.* std::numeric_limits<double>::epsilon();\n    ok &= traits::highest() ==\n        std::numeric_limits<double>::max();\n    ok &= traits::lowest() ==\n        std::numeric_limits<double>::min();\n    ok &= std::isnan(traits::quiet_NaN());\n    ok &= std::isinf(traits::infinity());\n\n    AD<double> x = 2.0;\n    ok  &= conj(x)  == x;\n    ok  &= real(x)  == x;\n    ok  &= imag(x)  == 0.0;\n    ok  &= abs2(x)  == 4.0;\n\n    ok  &= (!std::isinf(x));\n    ok  &= (!std::isnan(x));\n\n    x = traits::quiet_NaN();\n    ok  &= std::isnan(x);\n\n    x = traits::infinity();\n    ok  &= std::isinf(x);\n\n    // Outputting a matrix used to fail before partial specialization of\n    // struct significant_decimals_default_impl in cppad_eigen.hpp.\n    Matrix< AD<double>, 1, 1> X;\n    X(0, 0) = AD<double>(1);\n    std::stringstream stream_out;\n    stream_out << X;\n    ok &= \"1\" == stream_out.str();\n\n    // multiplying three matrices together used to cause warning\n    // before making ctor from arbitrary type to AD<Base> explicit.\n    typedef CppAD::AD<double> AScalar;\n    Matrix<AScalar, Dynamic, Dynamic> A(1,1), B(1,1), C(1,1), D(1,1);\n    A(0,0) = 1.0;\n    B(0,0) = 2.0;\n    C(0,0) = 3.0;\n    D      = A * B * C;\n    ok    &= D(0,0) == 6.0 ;\n\n    // Multiplying Eigen objects (such as matrices) of element types used to\n    // fail before appropriate \"ScalarBinaryOpTraits\" was added.\n    const int nn = 3;\n    Matrix<double,  nn, nn> d_matrix = Matrix<double,  nn, nn>::Zero();\n    Matrix<AScalar, nn, nn> a_matrix = Matrix<AScalar, nn, nn>::Zero();\n    a_matrix  = a_matrix * d_matrix;\n    a_matrix  = d_matrix * a_matrix;\n    ok       &= a_matrix(0, 0) == AScalar(0);\n\n    // Test multiply matrix elements of mixed types\n    // (This worked before corresponding ScalarBinaryOpTraits was added.)\n    AScalar a_scalar = a_matrix(0,0) * d_matrix(0,0);\n    ok              &= a_scalar == AScalar(0);\n    a_scalar         = d_matrix(0, 0) * a_matrix(0, 0);\n    ok              &= a_scalar == AScalar(0);\n\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/cppad_vector.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n// CppAD::vector tests\n# include <cppad/utility/vector.hpp>\n# include <vector>\n# include <algorithm>\n\nnamespace { // BEGIN_EMPTY_NAMESPACE\n\nbool test_find(void)\n{   // find requires an input iterator\n    bool ok = true;\n    typedef CppAD::vector<char>::const_iterator const_iterator;\n    //\n    size_t n = 10;\n    CppAD::vector<char> vec(n);\n    for(size_t i = 0; i < n; ++i)\n        vec[i] = static_cast<char>( '0' + i);\n    const_iterator itr;\n    //\n    itr = std::find(vec.begin(), vec.end(), '3');\n    ok &= itr != vec.end();\n    ok &= *itr == '3';\n    //\n    itr = std::find(vec.begin(), vec.end(), 'a');\n    ok &= itr == vec.end();\n    //\n    return ok;\n}\n\nbool test_copy(void)\n{   // copy requires a forward iterator\n    bool ok = true;\n    //\n    size_t n = 10;\n    CppAD::vector<char> vec(n), des(n);\n    for(size_t i = 0; i < n; ++i)\n        vec[i] = static_cast<char>( '0' + i);\n    const CppAD::vector<char> src(vec);\n    //\n    // src.begin(), src.end() are const_iterator\n    // des.begin() is an iterator\n    std::copy(src.begin(), src.end(), des.begin());\n    //\n    for(size_t i = 0; i < n; ++i)\n        ok &= src[i] == des[i];\n    //\n    return ok;\n}\n\nbool test_reverse(void)\n{   // copy requires a bidirectional iterator\n    bool ok = true;\n    //\n    size_t n = 10;\n    CppAD::vector<char> src(n), des(n);\n    for(size_t i = 0; i < n; ++i)\n        src[i] = static_cast<char>( '0' + i);\n    //\n    std::reverse(src.begin(), src.end());\n    //\n    for(size_t i = 0; i < n; ++i)\n        ok &= src[i] == static_cast<char>( '0' + (n - i - 1) );\n    //\n    return ok;\n}\n\nbool test_sort(void)\n{   // copy requires a random access iterator\n    bool ok = true;\n    //\n    size_t n = 10;\n    CppAD::vector<char> vec(n);\n    for(size_t i = 0; i < n; ++i)\n        vec[i] = static_cast<char>( '0' + (n - i - 1) );\n    //\n    std::sort(vec.begin(), vec.end());\n    //\n    for(size_t i = 0; i < n; ++i)\n        ok &= vec[i] == static_cast<char>( '0' + i );\n    //\n    return ok;\n}\n\n\n} // END_EMPTY_NAMESPACE\n\nbool cppad_vector(void)\n{   bool ok = true;\n    //\n    ok &= test_find();\n    ok &= test_copy();\n    ok &= test_reverse();\n    ok &= test_sort();\n    //\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/dbl_epsilon.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\nCheck the value of machine epsilon is accurate enough for the correctness tests\n*/\n\n# include <cfloat>\n# include <limits>\n\nbool dbl_epsilon(void)\n{   bool ok = true;\n\n    // CppAD correctness tests assume machine epsilon is less than 1e-13\n    ok &= DBL_EPSILON < 1e-13;\n    ok &= std::numeric_limits<double>::digits10 >= 13;\n\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/dependency.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\nOld example for deprecated interface.\n$spell\n    CppAD\n    Jac\n$$\n\n$section Computing Dependency: Example and Test$$\n\n$head Discussion$$\nThe partial of an dependent variable with respect to an independent variable\nmight always be zero even though the dependent variable depends on the\nvalue of the dependent variable. Consider the following case\n$latex \\[\nf(x) = {\\rm sign} (x) =\n\\left\\{ \\begin{array}{rl}\n    +1 & {\\rm if} \\; x > 0 \\\\\n    0  & {\\rm if} \\; x = 0 \\\\\n    -1 & {\\rm if} \\; x < 0\n\\end{array} \\right.\n\\] $$\nIn this case the value of $latex f(x)$$ depends on the value of $latex x$$\nbut CppAD always returns zero for the derivative of the $cref sign$$ function.\n\n$head Dependency Pattern$$\nIf the $th i$$ dependent variables depends on the\nvalue of the $th j$$ independent variable,\nthe corresponding entry in the dependency pattern is non-zero (true).\nOtherwise it is zero (false).\nCppAD uses $cref/sparsity patterns/glossary/Sparsity Pattern/$$\nto represent dependency matrices.\nThe $icode dependency$$ argument to\n$cref/ForSparseJac/ForSparseJac/dependency/$$ and\n$cref/RevSparseJac/RevSparseJac/dependency/$$ is a flag that signals\nthat the dependency pattern (instead of the sparsity pattern) is computed.\n\n$srcthisfile%0%// BEGIN C++%// END C++%1%$$\n\n$end\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\nnamespace {\n    double heavyside(const double& x)\n    {   if( x <= 0.0 )\n            return 0.0;\n        return 1.0;\n    }\n    CPPAD_DISCRETE_FUNCTION(double, heavyside)\n}\n\nbool dependency(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n\n    // VecAD object for use later\n    CppAD::VecAD<double> vec_ad(2);\n    vec_ad[0] = 0.0;\n    vec_ad[1] = 1.0;\n\n    // domain space vector\n    size_t n  = 5;\n    CPPAD_TESTVECTOR(AD<double>) ax(n);\n    for(size_t j = 0; j < n; j++)\n        ax[j] = AD<double>(j + 1);\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(ax);\n\n    // some AD constants\n    AD<double> azero(0.0), aone(1.0);\n\n    // range space vector\n    size_t m  = n;\n    size_t m1 = n - 1;\n    CPPAD_TESTVECTOR(AD<double>) ay(m);\n    ay[m1-0] = sign( ax[0] );\n    ay[m1-1] = CondExpLe( ax[1], azero, azero, aone);\n    ay[m1-2] = CondExpLe( azero, ax[2], azero, aone);\n    ay[m1-3] = heavyside( ax[3] );\n    ay[m1-4] = vec_ad[ ax[4] - AD<double>(4.0) ];\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(ax, ay);\n\n    // -----------------------------------------------------------\n    // ForSparseJac and bool dependency\n    bool transpose  = false;\n    bool dependency;\n    // could replace CppAD::vectorBooll by CPPAD_TESTVECTOR<bool>\n    CppAD::vectorBool eye_bool(n * n), depend_bool(m * n);\n    for(size_t i = 0; i < n; i++)\n    {   for(size_t j = 0; j < n; j++)\n            eye_bool[i * n + j] = (i == j);\n    }\n    dependency = true;\n    depend_bool = f.ForSparseJac(n, eye_bool, transpose, dependency);\n    for(size_t i = 0; i < m; i++)\n    {   for(size_t j = 0; j < n; j++)\n            ok &= depend_bool[i * n + j] == (i == (m1-j));\n    }\n    dependency = false;\n    depend_bool = f.ForSparseJac(n, eye_bool, transpose, dependency);\n    for(size_t i = 0; i < m; i++)\n    {   for(size_t j = 0; j < n; j++)\n            ok &= depend_bool[i * n + j] == false;\n    }\n\n    // -----------------------------------------------------------\n    // RevSparseJac and set dependency\n    CppAD::vector<    std::set<size_t> > eye_set(m), depend_set(m);\n    for(size_t i = 0; i < m; i++)\n    {   ok &= eye_set[i].empty();\n        eye_set[i].insert(i);\n    }\n    dependency = true;\n    depend_set = f.RevSparseJac(n, eye_set, transpose, dependency);\n    for(size_t i = 0; i < m; i++)\n    {   std::set<size_t> check;\n        check.insert(m1 - i);\n        ok &= depend_set[i] == check;\n    }\n    dependency = false;\n    depend_set = f.RevSparseJac(n, eye_set, transpose, dependency);\n    for(size_t i = 0; i < m; i++)\n        ok &= depend_set[i].empty();\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "test_more/general/div.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\nTwo old Div examples now used just for valiadation testing\n*/\n\n# include <cppad/cppad.hpp>\n\nnamespace { // BEGIN empty namespace\n\nbool DivTestOne(void)\n{   bool ok = true;\n\n    using namespace CppAD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // assign some parameters\n    AD<double> zero = 0.;\n    AD<double>  one = 1.;\n\n    // independent variable vector, indices, values, and declaration\n    CPPAD_TESTVECTOR(AD<double>) U(2);\n    size_t s = 0;\n    size_t t = 1;\n    U[s]     = 2.;\n    U[t]     = 3.;\n    Independent(U);\n\n    // dependent variable vector and indices\n    CPPAD_TESTVECTOR(AD<double>) Z(6);\n    size_t x = 0;\n    size_t y = 1;\n    size_t z = 2;\n    size_t u = 3;\n    size_t v = 4;\n    size_t w = 5;\n\n    // dependent variables\n    Z[x] = U[s]   / U[t];   // AD<double> / AD<double>\n    Z[y] = Z[x]   / 4.;     // AD<double> / double\n    Z[z] = 5. / Z[y];       //     double / AD<double>\n    Z[u] =  Z[z] / one;     // division by a parameter equal to one\n    Z[v] =  Z[z] / 1.;      // division by a double equal to one\n    Z[w] =  zero / Z[z];    // division into a parameter equal to zero\n\n    // check division into a zero valued parameter results in a parameter\n    // (must do this before creating f because it erases the tape)\n    ok &= Parameter(Z[w]);\n\n    // create f : U -> Z and vectors used for derivative calculations\n    ADFun<double> f(U, Z);\n    CPPAD_TESTVECTOR(double) q( f.Domain() );\n    CPPAD_TESTVECTOR(double) r( f.Range() );\n\n    // check parameter flag\n    ok &= f.Parameter(w);\n\n    // check values\n    ok &= NearEqual( Z[x] , 2. / 3. , eps99, eps99);\n    ok &= NearEqual( Z[y] , 2. / ( 3. * 4. ) , eps99, eps99);\n    ok &= NearEqual( Z[z] , 5. * 3. * 4. / 2. , eps99, eps99);\n    ok &= ( Z[w] == 0. );\n    ok &= ( Z[u] == Z[z] );\n\n    // forward computation of partials w.r.t. s\n    q[s] = 1.;\n    q[t] = 0.;\n    r    = f.Forward(1, q);\n    ok &= NearEqual(r[x], 1./U[t], eps99, eps99); // dx/ds\n    ok &= NearEqual(r[y], 1./(U[t]*4.), eps99, eps99); // dy/ds\n    ok &= NearEqual(r[z], -5.*U[t]*4./(U[s]*U[s]), eps99, eps99); // dz/ds\n    ok &= ( r[u] == r[z] );                                       // du/ds\n    ok &= ( r[v] == r[z] );                                       // dv/ds\n    ok &= ( r[w] == 0. );                                         // dw/ds\n\n    // forward computation in the direction (1, 1)\n    q[s] = 1.;\n    q[t] = 1.;\n    r    = f.Forward(1, q);\n    ok  &= NearEqual(r[x], 1./U[t] - U[s]/(U[t] * U[t]), eps99, eps99);\n\n    // second order reverse mode computation\n    CPPAD_TESTVECTOR(double) Q( f.Domain() * 2 );\n    r[x] = 1.;\n    r[y] = r[z] = r[u] = r[v] = r[w] = 0.;\n    Q    = f.Reverse(2, r);\n    ok  &= NearEqual(\n        Q[s * f.Domain() + 1],\n        - 1. / (U[t] * U[t]),\n        eps99,\n        eps99\n    );\n\n    return ok;\n}\n\nbool DivTestTwo(void)\n{   bool ok = true;\n    using namespace CppAD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // independent variable vector\n    double u0 = .5;\n    CPPAD_TESTVECTOR(AD<double>) U(1);\n    U[0]      = u0;\n    Independent(U);\n\n    AD<double> a = U[0] / 1.; // AD<double> / double\n    AD<double> b = a  / 2;    // AD<double> / int\n    AD<double> c = 3. / b;    // double     / AD<double>\n    AD<double> d = 4  / c;    // int        / AD<double>\n\n    // dependent variable vector\n    CPPAD_TESTVECTOR(AD<double>) Z(1);\n    Z[0] = U[0] * U[0] / d;   // AD<double> / AD<double>\n\n    // create f: U -> Z and vectors used for derivative calculations\n    ADFun<double> f(U, Z);\n    CPPAD_TESTVECTOR(double) v(1);\n    CPPAD_TESTVECTOR(double) w(1);\n\n    // check value\n    ok &= NearEqual(Value(Z[0]) , u0*u0/(4/(3/(u0/2))), eps99, eps99);\n\n    // forward computation of partials w.r.t. u\n    size_t j;\n    size_t p     = 5;\n    double jfac  = 1.;\n    v[0]         = 1.;\n    double value = 6. / 4.;\n    for(j = 1; j < p; j++)\n    {\n        jfac *= double(j);\n        w     = f.Forward(j, v);\n        ok &= NearEqual(w[0], value/jfac, eps99, eps99); // d^jz/du^j\n        v[0]  = 0.;\n        value = 0.;\n    }\n\n    // reverse computation of partials of Taylor coefficients\n    CPPAD_TESTVECTOR(double) r(p);\n    w[0]  = 1.;\n    r     = f.Reverse(p, w);\n    jfac  = 1.;\n    value = 6. / 4.;\n    for(j = 0; j < p; j++)\n    {\n        ok &= NearEqual(r[j], value/jfac, eps99, eps99); // d^jz/du^j\n        jfac *= double(j + 1);\n        value = 0.;\n    }\n\n    return ok;\n}\n\nbool DivTestThree(void)\n{   bool ok = true;\n    using namespace CppAD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // more testing of variable / variable case\n    double x0 = 2.;\n    double x1 = 3.;\n    size_t n  = 2;\n    CPPAD_TESTVECTOR(AD<double>) X(n);\n    X[0]      = x0;\n    X[1]      = x1;\n    Independent(X);\n    size_t m  = 1;\n    CPPAD_TESTVECTOR(AD<double>) Y(m);\n    Y[0]      = X[0] / X[1];\n    ADFun<double> f(X, Y);\n\n    CPPAD_TESTVECTOR(double) dx(n), dy(m);\n    double check;\n    dx[0] = 1.;\n    dx[1] = 1.;\n    dy    = f.Forward(1, dx);\n    check = 1. / x1 - x0 / (x1 * x1);\n    ok   &= NearEqual(dy[0], check, eps99, eps99);\n\n    CPPAD_TESTVECTOR(double) w(m), dw(n);\n    w[0]  = 1.;\n    dw    = f.Reverse(1, w);\n    check = 1. / x1;\n    ok   &= NearEqual(dw[0], check, eps99, eps99);\n    check = - x0 / (x1 * x1);\n    ok   &= NearEqual(dw[1], check, eps99, eps99);\n\n    return ok;\n}\n\n} // END empty namespace\n\nbool Div(void)\n{   bool ok = true;\n    ok &= DivTestOne();\n    ok &= DivTestTwo();\n    ok &= DivTestThree();\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/div_eq.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\nOld DivEq example now used just for valiadation testing\n*/\n# include <cppad/cppad.hpp>\n\nnamespace { // BEGIN empty namespace\n\nbool DivEqTestOne(void)\n{   bool ok = true;\n\n    using namespace CppAD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // independent variable vector, indices, values, and declaration\n    CPPAD_TESTVECTOR(AD<double>) U(2);\n    size_t s = 0;\n    size_t t = 1;\n    U[s]     = 3.;\n    U[t]     = 2.;\n    Independent(U);\n\n    // dependent variable vector and indices\n    CPPAD_TESTVECTOR(AD<double>) Z(2);\n    size_t x = 0;\n    size_t y = 1;\n\n    // some constants\n    AD<double> zero = 0.;\n    AD<double> one  = 1.;\n\n    // dependent variable values\n    Z[x] = U[s];\n    Z[y] = U[t];\n    Z[x] /= U[t]; // AD<double> *= AD<double>\n    Z[y] /= 5.;   // AD<double> *= double\n    zero /= Z[y]; // divide into a parameter equal to zero\n    Z[y] /= one;  // divide by a parameter equal to one\n    Z[y] /= 1.;   // divide by a double equal to one\n\n    // check that zero is still a parameter\n    // (must do this before creating f because it erases the tape)\n    ok &= Parameter(zero);\n\n    // create f : U -> Z and vectors for derivative calculations\n    ADFun<double> f(U, Z);\n    CPPAD_TESTVECTOR(double) v( f.Domain() );\n    CPPAD_TESTVECTOR(double) w( f.Range() );\n\n    // check that none of the components of f are parameters\n    size_t i;\n    for(i = 0; i < f.Range(); i++)\n        ok &= ! f.Parameter(i);\n\n    // check function values\n    ok &= NearEqual(Z[x] , 3. / 2. , eps99, eps99);\n    ok &= NearEqual(Z[y] , 2. / 5. , eps99, eps99);\n\n    // forward computation of partials w.r.t. t\n    v[s] = 0.;\n    v[t] = 1.;\n    w    = f.Forward(1, v);\n    ok &= NearEqual(w[x] , -1.*U[s]/(U[t]*U[t]) , eps99, eps99); // dx/dt\n    ok &= NearEqual(w[y] , 1. / 5.              , eps99, eps99); // dy/dt\n\n    // reverse computation of second partials of x\n    CPPAD_TESTVECTOR(double) r( f.Domain() * 2 );\n    w[x] = 1.;\n    w[y] = 0.;\n    r    = f.Reverse(2, w);\n    ok &= NearEqual(r[2 * s + 1]                 // d^2 x / (dt ds)\n            , - 1. / (U[t] * U[t])     , eps99 , eps99 );\n    ok &= NearEqual(r[2 * t + 1]                 // d^2 x / (dt dt)\n        , 2. * U[s] / (U[t] * U[t] * U[t])  , eps99 , eps99 );\n\n    return ok;\n}\n\nbool DivEqTestTwo(void)\n{   bool ok = true;\n\n    using namespace CppAD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // independent variable vector\n    double u0 = .5;\n    CPPAD_TESTVECTOR(AD<double>) U(1);\n    U[0]      = u0;\n    Independent(U);\n\n    // dependent variable vector\n    CPPAD_TESTVECTOR(AD<double>) Z(1);\n    Z[0] = U[0] * U[0]; // initial value\n    Z[0] /= 2;          // AD<double> /= int\n    Z[0] /= 4.;         // AD<double> /= double\n    Z[0] /= U[0];       // AD<double> /= AD<double>\n\n    // create f: U -> Z and vectors used for derivative calculations\n    ADFun<double> f(U, Z);\n    CPPAD_TESTVECTOR(double) v(1);\n    CPPAD_TESTVECTOR(double) w(1);\n\n    // check value\n    ok &= NearEqual(Z[0] , u0*u0/(2*4*u0), eps99, eps99);\n\n    // forward computation of partials w.r.t. u\n    size_t j;\n    size_t p     = 5;\n    double jfac  = 1.;\n    double value = 1./8.;\n    v[0]         = 1.;\n    for(j = 1; j < p; j++)\n    {   jfac *= double(j);\n        w     = f.Forward(j, v);\n        ok &= NearEqual(w[0], value/jfac, eps99, eps99); // d^jz/du^j\n        v[0]  = 0.;\n        value = 0.;\n    }\n\n    // reverse computation of partials of Taylor coefficients\n    CPPAD_TESTVECTOR(double) r(p);\n    w[0]  = 1.;\n    r     = f.Reverse(p, w);\n    jfac  = 1.;\n    value = 1./8.;\n    for(j = 0; j < p; j++)\n    {   ok &= NearEqual(r[j], value/jfac, eps99, eps99); // d^jz/du^j\n        jfac *= double(j + 1);\n        value = 0.;\n    }\n\n    return ok;\n}\n\n} // END empty namespace\n\nbool DivEq(void)\n{   bool ok = true;\n    ok &= DivEqTestOne();\n    ok &= DivEqTestTwo();\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/div_zero_one.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\nTest the use of the special parameters zero and one with the multiply operator\n*/\n\n# include <cppad/cppad.hpp>\n\ntypedef CppAD::AD<double>      ADdouble;\ntypedef CppAD::AD< ADdouble > ADDdouble;\n\nbool DivZeroOne(void)\n{   bool ok = true;\n    using namespace CppAD;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    size_t i;\n    for(i = 0; i < 3; i++)\n    {   // run through the cases x = 0, 1, 2\n\n        size_t j;\n        for(j = 0; j < 3; j++)\n        {   // run through the cases y = 0, 1, 2\n\n            CPPAD_TESTVECTOR( ADdouble ) x(1);\n            x[0] = double(i);\n            Independent(x);\n\n            CPPAD_TESTVECTOR( ADDdouble ) y(1);\n            y[0] = ADDdouble(j);\n            Independent(y);\n\n            CPPAD_TESTVECTOR( ADDdouble ) z(2);\n            if( j == 0 )\n                z[0] = ADDdouble(0);\n            else\n                z[0] = x[0] / y[0];\n            if( i == 0 )\n                z[1] = ADDdouble(0);\n            else\n            {   z[1]  = y[0] / x[0];\n                z[1] /= x[0];\n            }\n\n            // f(y) = z = { x / y , y / (x * x) }\n            ADFun< ADdouble > f(y, z);\n            CPPAD_TESTVECTOR( ADdouble ) u( f.Domain() );\n            CPPAD_TESTVECTOR( ADdouble ) v( f.Range() );\n\n            // v = f'(y)\n            u[0] = ADdouble(1.);\n            v = f.Forward(1, u);\n\n            // check derivatives of f\n            ADdouble check = - double(i) / double(j * j);\n            if( j != 0 ) ok &= NearEqual(\n                v[0], check, eps99, eps99 );\n\n            check = 1. / double(i * i);\n            if( i != 0 ) ok &= NearEqual(\n                v[1], check, eps99, eps99);\n\n            // g(x) = f'(y) = {-x/y^2 , 1/(x * x)}\n            ADFun<double> g(x, v);\n            CPPAD_TESTVECTOR( double ) a( g.Domain() );\n            CPPAD_TESTVECTOR( double ) b( g.Range() );\n\n            // b = g'(x)\n            a[0] = 1.;\n            b = g.Forward(1, a);\n\n            // check derivatives of g\n            if( j != 0 ) ok &= NearEqual(\n                b[0], - 1./double(j*j), eps99, eps99 );\n            if( i != 0 ) ok &= NearEqual(\n                b[1], -2./double(i*i*i), eps99, eps99);\n\n        }\n    }\n\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/eigen_mat_inv.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/cppad.hpp>\n# include <cppad/example/atomic_two/eigen_mat_inv.hpp>\n\nnamespace { // BEGIN_EMPTY_NAMESPACE\n\ntypedef double                                   scalar;\ntypedef CppAD::AD<scalar>                        ad_scalar;\ntypedef atomic_eigen_mat_inv<scalar>::ad_matrix  ad_matrix;\n\nscalar eps = 10. * std::numeric_limits<scalar>::epsilon();\nusing CppAD::NearEqual;\n// --------------------------------------------------------------------------\n/*\nTest atomic_eigen_mat_inv using a non-symmetric matrix\n\nf(x) = [ x[0]   -1  ]^{-1}\n         [ 2     x[1] ]\n\n      = [ x[1]  1    ] / (x[0] * x[1] + 2)\n         [ -2    x[0] ]\n\ny[0] = x[1] / (x[0] * x[1] + 2)\ny[1] = 1.0  / (x[0] * x[1] + 2)\ny[2] = -2.0 / (x[0] * x[1] + 2)\ny[3] = x[0] / (x[0] * x[1] + 2)\n*/\nbool non_symmetric(void)\n{\n    bool ok    = true;\n    using Eigen::Index;\n    // -------------------------------------------------------------------\n    // object that computes inverse of a 2x2 matrix\n    atomic_eigen_mat_inv<scalar> mat_inv;\n    // -------------------------------------------------------------------\n    // declare independent variable vector x\n    size_t n = 2;\n    CPPAD_TESTVECTOR(ad_scalar) ad_x(n);\n    for(size_t j = 0; j < n; j++)\n        ad_x[j] = ad_scalar(j);\n    CppAD::Independent(ad_x);\n    // -------------------------------------------------------------------\n    // arg = [ x[0]  -1   ]\n    //       [ 2     x[1] ]\n    size_t nr  = 2;\n    ad_matrix ad_arg(nr, nr);\n    ad_arg(0, 0) = ad_x[0];\n    ad_arg(0, 1) = ad_scalar(-1.0);\n    ad_arg(1, 0) = ad_scalar(2.0);\n    ad_arg(1, 1) = ad_x[1];\n    // -------------------------------------------------------------------\n    // use atomic operation to compute arg^{-1}\n    ad_matrix ad_result = mat_inv.op(ad_arg);\n    // -------------------------------------------------------------------\n    // declare the dependent variable vector y\n    size_t m = 4;\n    CPPAD_TESTVECTOR(ad_scalar) ad_y(4);\n    for(size_t i = 0; i < nr; i++)\n        for(size_t j = 0; j < nr; j++)\n            ad_y[ i * nr + j ] = ad_result( Index(i), Index(j) );\n    /* Used to test hand calculated derivaives\n    CppAD::AD<scalar> ad_dinv = 1.0 / (ad_x[0] * ad_x[1] + 2.0);\n    ad_y[0] = ad_x[1] * ad_dinv;\n    ad_y[1] = 1.0  * ad_dinv;\n    ad_y[2] = -2.0 * ad_dinv;\n    ad_y[3] = ad_x[0] * ad_dinv;\n    */\n    CppAD::ADFun<scalar> f(ad_x, ad_y);\n    // -------------------------------------------------------------------\n    // check zero order forward mode\n    CPPAD_TESTVECTOR(scalar) x(n), y(m);\n    for(size_t i = 0; i < n; i++)\n        x[i] = scalar(i + 2);\n    scalar dinv = 1.0 / (x[0] * x[1] + 2.0);\n    y          = f.Forward(0, x);\n    ok        &= NearEqual(y[0], x[1] * dinv,  eps, eps);\n    ok        &= NearEqual(y[1], 1.0  * dinv,  eps, eps);\n    ok        &= NearEqual(y[2], -2.0 * dinv,  eps, eps);\n    ok        &= NearEqual(y[3], x[0] * dinv,  eps, eps);\n    // -------------------------------------------------------------------\n    // check first order forward mode\n    CPPAD_TESTVECTOR(scalar) x1(n), y1(m);\n    scalar dinv_x0 = - x[1] * dinv * dinv;\n    x1[0] = 1.0;\n    x1[1] = 0.0;\n    y1    = f.Forward(1, x1);\n    ok   &= NearEqual(y1[0], x[1] * dinv_x0,        eps, eps);\n    ok   &= NearEqual(y1[1], 1.0  * dinv_x0,        eps, eps);\n    ok   &= NearEqual(y1[2], -2.0 * dinv_x0,        eps, eps);\n    ok   &= NearEqual(y1[3], dinv + x[0] * dinv_x0, eps, eps);\n    //\n    scalar dinv_x1 = - x[0] * dinv * dinv;\n    x1[0] = 0.0;\n    x1[1] = 1.0;\n    y1    = f.Forward(1, x1);\n    ok   &= NearEqual(y1[0], dinv + x[1] * dinv_x1, eps, eps);\n    ok   &= NearEqual(y1[1], 1.0  * dinv_x1,        eps, eps);\n    ok   &= NearEqual(y1[2], -2.0 * dinv_x1,        eps, eps);\n    ok   &= NearEqual(y1[3], x[0] * dinv_x1,        eps, eps);\n    // -------------------------------------------------------------------\n    // check second order forward mode\n    CPPAD_TESTVECTOR(scalar) x2(n), y2(m);\n    scalar dinv_x1_x1 = 2.0 * x[0] * x[0] * dinv * dinv * dinv;\n    x2[0] = 0.0;\n    x2[1] = 0.0;\n    y2    = f.Forward(2, x2);\n    ok   &= NearEqual(2.0*y2[0], 2.0*dinv_x1 + x[1]*dinv_x1_x1, eps, eps);\n    ok   &= NearEqual(2.0*y2[1], 1.0  * dinv_x1_x1,             eps, eps);\n    ok   &= NearEqual(2.0*y2[2], -2.0 * dinv_x1_x1,             eps, eps);\n    ok   &= NearEqual(2.0*y2[3], x[0] * dinv_x1_x1,             eps, eps);\n    // -------------------------------------------------------------------\n    // check first order reverse\n    CPPAD_TESTVECTOR(scalar) w(m), d1w(n);\n    for(size_t i = 0; i < m; i++)\n        w[i] = 0.0;\n    w[0] = 1.0;\n    d1w  = f.Reverse(1, w);\n    ok  &= NearEqual(d1w[0], x[1] * dinv_x0,        eps, eps);\n    ok  &= NearEqual(d1w[1], dinv + x[1] * dinv_x1, eps, eps);\n    w[0] = 0.0;\n    w[1] = 1.0;\n    d1w  = f.Reverse(1, w);\n    ok  &= NearEqual(d1w[0], 1.0 * dinv_x0,         eps, eps);\n    ok  &= NearEqual(d1w[1], 1.0 * dinv_x1,         eps, eps);\n    w[1] = 0.0;\n    w[2] = 1.0;\n    d1w  = f.Reverse(1, w);\n    ok  &= NearEqual(d1w[0], -2.0 * dinv_x0,        eps, eps);\n    ok  &= NearEqual(d1w[1], -2.0 * dinv_x1,        eps, eps);\n    w[2] = 0.0;\n    w[3] = 1.0;\n    d1w  = f.Reverse(1, w);\n    ok  &= NearEqual(d1w[0], dinv + x[0] * dinv_x0, eps, eps);\n    ok  &= NearEqual(d1w[1], x[0] * dinv_x1,        eps, eps);\n    // -------------------------------------------------------------------\n    // check second order reverse\n    CPPAD_TESTVECTOR(scalar) d2w(2 * n);\n    // dinv_x1 = - x[0] * dinv * dinv;\n    scalar dinv_x1_x0 = 2.0 * x[0] * x[1] * dinv * dinv * dinv - dinv * dinv;\n    d2w  = f.Reverse(2, w);\n    // partial f_3 w.r.t x_0\n    ok  &= NearEqual(d2w[0 * 2 + 0], dinv + x[0] * dinv_x0, eps, eps);\n    // partial f_3 w.r.t x_1\n    ok  &= NearEqual(d2w[1 * 2 + 0], x[0] * dinv_x1,              eps, eps);\n    // partial f_3 w.r.t. x_1, x_0\n    ok  &= NearEqual(d2w[0 * 2 + 1], dinv_x1 + x[0] * dinv_x1_x0, eps, eps);\n    // partial f_3 w.r.t. x_1, x_1\n    ok  &= NearEqual(d2w[1 * 2 + 1], x[0] * dinv_x1_x1,           eps, eps);\n    // -------------------------------------------------------------------\n    return ok;\n}\n\n} // END_EMPTY_NAMESPACE\n\nbool eigen_mat_inv(void)\n{   bool ok = true;\n    ok     &= non_symmetric();\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/erf.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/cppad.hpp>\n\nnamespace {\n    // ---------------------------------------------------------------------\n    bool old_example(void)\n    {   bool ok = true;\n        using namespace CppAD;\n        using CppAD::atan;\n        using CppAD::exp;\n        using CppAD::sqrt;\n        double eps = 100.0 * std::numeric_limits<double>::epsilon();\n        // Construct function object corresponding to erf\n        CPPAD_TESTVECTOR(AD<double>) ax(1);\n        CPPAD_TESTVECTOR(AD<double>) ay(1);\n        ax[0] = 0.;\n        Independent(ax);\n        ay[0] = erf(ax[0]);\n        ADFun<double> f(ax, ay);\n\n        // Construct function object corresponding to derivative of erf\n        Independent(ax);\n        double pi = 4.0 * atan(1.0);\n        ay[0] = exp( - ax[0] * ax[0] ) * 2.0 / sqrt(pi);\n        ADFun<double> df(ax, ay);\n\n        // vectors to use with function object\n        CPPAD_TESTVECTOR(double) x0(1), y0(1), x1(1), y1(1), check(1);\n\n        // check value at zero\n        x0[0]    = 1.5;\n        y0       = f.Forward(0, x0);\n        check[0] = 0.96611;\n        ok      &= std::fabs(check[0] - y0[0]) <= 4e-4;\n\n        // check the derivative of error function\n        x1[0] = 1.0;\n        y1    = f.Forward(1, x1);\n        check = df.Forward(0, x0);\n        ok   &= NearEqual(check[0], y1[0], 0., 2e-3);\n        ok   &= NearEqual(check[0], y1[0], eps, eps);\n\n        // check second derivative\n        CPPAD_TESTVECTOR(double) x2(1), y2(1);\n        x2[0] = 0.0;\n        y2    = f.Forward(2, x2);\n        check = df.Forward(1, x1);\n        ok   &= NearEqual(check[0] / 2.0, y2[0], 0., 2e-3);\n        ok   &= NearEqual(check[0] / 2.0, y2[0], eps, eps);\n\n        // check third derivative\n        CPPAD_TESTVECTOR(double) x3(1), y3(1);\n        x3[0] = 0.0;\n        y3    = f.Forward(3, x3);\n        check = df.Forward(2, x2);\n        ok   &= NearEqual(check[0] / 3.0, y3[0], 0., 2e-3);\n        ok   &= NearEqual(check[0] / 3.0, y3[0], eps, eps);\n\n        // check 4-th order of reverse mode\n        CPPAD_TESTVECTOR(double) w(1), dy(4), x4(1), y4(1);\n        x4[0] = 0.0;\n        w[0]  = 1.0;\n        dy    = f.Reverse(4, w);\n        y4    = f.Forward(4, x4);\n        //\n        ok  &= NearEqual(dy[0], y1[0], 0., 2e-3);\n        ok  &= NearEqual(dy[0], y1[0], eps, eps);\n        //\n        ok  &= NearEqual(dy[1], 2.0 * y2[0], 0., 2e-3);\n        ok  &= NearEqual(dy[1], 2.0 * y2[0], eps, eps);\n        //\n        ok  &= NearEqual(dy[2], 3.0 * y3[0], 0., 2e-3);\n        ok  &= NearEqual(dy[2], 3.0 * y3[0], eps, eps);\n        //\n        ok  &= NearEqual(dy[3], 4.0 * y4[0], 0., 2e-3);\n        ok  &= NearEqual(dy[3], 4.0 * y4[0], eps, eps);\n\n        return ok;\n    }\n    // ---------------------------------------------------------------------\n    bool hessian(void)\n    {   bool ok = true;\n        double eps = 1.0 * std::numeric_limits<double>::epsilon();\n        using CppAD::vector;\n        using CppAD::AD;\n\n        size_t n = 2;\n        size_t m = 1;\n        vector<double> x(n), w(m);\n        w[0] = 1.0;\n        vector< AD<double> > ax(n), ay(m);\n        ax[0] = x[0] = 0.5;\n        ax[1] = x[1] = 0.0;\n\n        // construct function\n        CppAD::Independent(ax);\n        ay[0] = erf( 2.0 * ax[0] );\n        CppAD::ADFun<double> f(ax, ay);\n\n        // dense hessian\n        vector<double> dense_hess = f.Hessian(x, 0);\n\n        // sparse_hessian\n        vector<double> sparse_hess = f.SparseHessian(x, w);\n\n        // Define g(u) = erf(2 * u)\n        // g'(u)   = 2 * erf'(2 * u)\n        //         = 2 * exp( - 2 * u * 2 * u ) * 2 / sqrt(pi)\n        //         = exp( - 4 * u * u ) * 4 / sqrt(pi)\n        // g''(u)  = - exp( - 4 * u * u ) * 32 * u / sqrt(pi)\n        double root_pi = std::sqrt( 4.0 * atan(1.0) );\n        double check   = -std::exp(-4.0 * x[0] * x[0]) * 32.0 * x[0] / root_pi;\n\n        ok &= CppAD::NearEqual(dense_hess[0], check, eps, eps);\n        ok &= CppAD::NearEqual(sparse_hess[0], check, eps, eps);\n\n        for(size_t k = 1; k < n * n; k++)\n        {   ok &= CppAD::NearEqual(dense_hess[k], 0.0, eps, eps);\n            ok &= CppAD::NearEqual(sparse_hess[k], 0.0, eps, eps);\n        }\n        return ok;\n    }\n    // ---------------------------------------------------------------------\n    bool mul_dir(void)\n    {   bool ok = true;\n        using namespace CppAD;\n        using CppAD::atan;\n        using CppAD::exp;\n        using CppAD::sqrt;\n        double eps = 100.0 * std::numeric_limits<double>::epsilon();\n\n        // Construct function object corresponding to erf\n        CPPAD_TESTVECTOR(AD<double>) ax(1);\n        CPPAD_TESTVECTOR(AD<double>) ay(1);\n        ax[0] = 0.;\n        Independent(ax);\n        ay[0] = erf(ax[0]);\n        ADFun<double> f(ax, ay);\n\n        // Construct function object corresponding to derivative of erf\n        Independent(ax);\n        double pi = 4.0 * atan(1.0);\n        ay[0] = exp( - ax[0] * ax[0] ) * 2.0 / sqrt(pi);\n        ADFun<double> df(ax, ay);\n\n        // number of directions\n        size_t r = 1;\n\n        // vectors to use with objects\n        CPPAD_TESTVECTOR(double) x0(1), y0(1), x1(1), y1(1), y2(1), y3(1);\n        CPPAD_TESTVECTOR(double) zero(1), check(1);\n        CPPAD_TESTVECTOR(double) xq(r), yq(r), checkq(r), zeroq(r);\n\n        // check function value\n        x0[0]      = 1.5;\n        y0         = f.Forward(0, x0);\n        check[0]   = 0.9661051464753108;\n        double tmp = std::max(1e-15, eps);\n        ok        &= NearEqual(check[0], y0[0], 0.0, tmp);\n\n        // check first order derivative\n        x1[0] = 1.0;\n        y1    = f.Forward(1, x1);\n        check = df.Forward(0, x0);\n        ok   &= NearEqual(check[0], y1[0], eps, eps);\n        for(size_t ell = 0; ell < r; ell++)\n        {   xq[ell]     = x1[ell] / double(ell + 1);\n            zeroq[ell]  = 0.0;\n        }\n        yq    = f.Forward(1, r, xq);\n        for(size_t ell = 0; ell < r; ell++)\n        {   checkq[ell] = check[0] * xq[ell];\n            ok         &= NearEqual(checkq[ell], yq[ell], eps, eps);\n        }\n\n        // check second order derivative\n        zero[0]   = 0.0;\n        y2        = f.Forward(2, zero);\n        check     = df.Forward(1, x1);\n        check[0] /= 2.0;\n        ok       &= NearEqual(check[0], y2[0], eps, eps);\n        yq        = f.Forward(2, r, zeroq);\n        for(size_t ell = 0; ell < r; ell++)\n        {   checkq[ell] = check[0] * xq[ell];\n            ok         &= NearEqual(checkq[ell], yq[ell], eps, eps);\n        }\n\n        // check third order derivative\n        zero[0]   = 0.0;\n        y3        = f.Forward(3, zero);\n        check     = df.Forward(2, zero);\n        check[0] /= 3.0;\n        ok       &= NearEqual(check[0], y3[0], eps, eps);\n        yq        = f.Forward(3, r, zeroq);\n        for(size_t ell = 0; ell < r; ell++)\n        {   checkq[ell] = check[0] * xq[ell];\n            ok         &= NearEqual(checkq[ell], yq[ell], eps, eps);\n        }\n\n        return ok;\n    }\n    // -------------------------------------------------------------------\n}\nbool erf(void)\n{   bool ok = true;\n    ok     &= old_example();\n    ok     &= hessian();\n    ok     &= mul_dir();\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/exp.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\nTwo old exp example now used just for validation testing.\n*/\n# include <cppad/cppad.hpp>\n\n# include <cmath>\n\nnamespace { // BEGIN empty namespace\n\nbool ExpTestOne(void)\n{   bool ok = true;\n    using CppAD::exp;\n    using namespace CppAD;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // independent variable vector, indices, values, and declaration\n    CPPAD_TESTVECTOR(AD<double>) U(1);\n    size_t s = 0;\n    U[s]     = 1.;\n    Independent(U);\n\n    // dependent variable vector, indices, and values\n    CPPAD_TESTVECTOR(AD<double>) Z(2);\n    size_t x = 0;\n    size_t y = 1;\n    Z[x]     = exp(U[s]);\n    Z[y]     = exp(Z[x]);\n\n    // define f : U -> Z and vectors for derivative calculations\n    ADFun<double> f(U, Z);\n    CPPAD_TESTVECTOR(double) v( f.Domain() );\n    CPPAD_TESTVECTOR(double) w( f.Range() );\n\n    // check values\n    ok &= NearEqual(Z[x] , exp(1.),         eps99 , eps99);\n    ok &= NearEqual(Z[y] , exp( exp(1.) ),  eps99 , eps99);\n\n    // forward computation of partials w.r.t. s\n    v[s] = 1.;\n    w    = f.Forward(1, v);\n    ok &= NearEqual(w[x], Z[x],            eps99 , eps99); // dx/ds\n    ok &= NearEqual(w[y], Z[y] * Z[x],     eps99 , eps99); // dy/ds\n\n    // reverse computation of partials of y\n    w[x] = 0.;\n    w[y] = 1.;\n    v    = f.Reverse(1,w);\n    ok &= NearEqual(v[s], Z[y] * Z[x],     eps99 , eps99); // dy/ds\n\n    // forward computation of second partials w.r.t s\n    v[s] = 1.;\n    w    = f.Forward(1, v);\n    v[s] = 0.;\n    w    = f.Forward(2, v);\n    ok &= NearEqual(       // d^2 y / (ds ds)\n        2. * w[y] ,\n        Z[y] * Z[x] * Z[x] + Z[y] * Z[x],\n        eps99 ,\n        eps99\n    );\n\n    // reverse computation of second partials of y\n    CPPAD_TESTVECTOR(double) r( f.Domain() * 2 );\n    w[x] = 0.;\n    w[y] = 1.;\n    r    = f.Reverse(2, w);\n    ok &= NearEqual(      // d^2 y / (ds ds)\n        r[2 * s + 1] ,\n        Z[y] * Z[x] * Z[x] + Z[y] * Z[x],\n        eps99 ,\n        eps99\n    );\n\n    return ok;\n}\nbool ExpTestTwo(void)\n{   bool ok = true;\n    using CppAD::exp;\n    using namespace CppAD;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // independent variable vector\n    CPPAD_TESTVECTOR(AD<double>) U(1);\n    U[0]     = 1.;\n    Independent(U);\n\n    // dependent variable vector\n    CPPAD_TESTVECTOR(AD<double>) Z(1);\n    Z[0] = exp(U[0]);\n\n    // create f: U -> Z and vectors used for derivative calculations\n    ADFun<double> f(U, Z);\n    CPPAD_TESTVECTOR(double) v(1);\n    CPPAD_TESTVECTOR(double) w(1);\n\n    // check value\n    double exp_u = exp( Value(U[0]) );\n    ok &= NearEqual(exp_u, Value(Z[0]),  eps99 , eps99);\n\n    // forward computation of partials w.r.t. u\n    size_t j;\n    size_t p     = 5;\n    double jfac  = 1.;\n    v[0]         = 1.;\n    for(j = 1; j < p; j++)\n    {   w     = f.Forward(j, v);\n        jfac *= double(j);\n        ok &= NearEqual(jfac*w[0], exp_u, eps99 , eps99); // d^jz/du^j\n        v[0]  = 0.;\n    }\n\n    // reverse computation of partials of Taylor coefficients\n    CPPAD_TESTVECTOR(double) r(p);\n    w[0]  = 1.;\n    r     = f.Reverse(p, w);\n    jfac  = 1.;\n    for(j = 0; j < p; j++)\n    {   ok &= NearEqual(jfac*r[j], exp_u, eps99 , eps99); // d^jz/du^j\n        jfac *= double(j + 1);\n    }\n\n    return ok;\n}\n\n} // END empty namespace\n\nbool Exp(void)\n{   bool ok = true;\n    ok &= ExpTestOne();\n    ok &= ExpTestTwo();\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/expm1.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/cppad.hpp>\n\nbool expm1(void)\n{   bool ok = true;\n\n    using CppAD::AD;\n    using CppAD::NearEqual;\n\n    // 10 times machine epsilon\n    double eps = 10. * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n  = 1;\n    double x0 = 0.5;\n    CPPAD_TESTVECTOR(AD<double>) ax(n);\n    ax[0]     = x0;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(ax);\n\n    // a temporary value\n    AD<double> log_p1 = CppAD::log(ax[0] + 1.0);\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) ay(m);\n    ay[0] = CppAD::expm1(log_p1);\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(ax, ay);\n\n    // check value\n    ok &= NearEqual(ay[0] , x0,  eps, eps);\n\n    // forward computation of first partial w.r.t. x[0]\n    CPPAD_TESTVECTOR(double) dx(n);\n    CPPAD_TESTVECTOR(double) dy(m);\n    dx[0] = 1.;\n    dy    = f.Forward(1, dx);\n    ok   &= NearEqual(dy[0], 1., eps, eps);\n\n    // forward computation of higher order partials w.r.t. x[0]\n    size_t n_order = 5;\n    for(size_t order = 2; order < n_order; order++)\n    {   dx[0] = 0.;\n        dy    = f.Forward(order, dx);\n        ok   &= NearEqual(dy[0], 0., eps, eps);\n    }\n    // reverse computation of derivatives\n    CPPAD_TESTVECTOR(double)  w(m);\n    CPPAD_TESTVECTOR(double) dw(n_order * n);\n    w[0]  = 1.;\n    dw    = f.Reverse(n_order, w);\n    ok   &= NearEqual(dw[0], 1., eps, eps);\n    for(size_t order = 1; order < n_order; order++)\n        ok   &= NearEqual(dw[order * n + 0], 0., eps, eps);\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "test_more/general/extern_value.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/cppad.hpp>\n# include \"extern_value.hpp\"\n\n# define INSTANTIATE(Type) template class extern_value< Type >\n\ntemplate <class Type>\nextern_value<Type>::extern_value(Type value)\n{   value_ = value; }\n\ntemplate <class Type>\nvoid extern_value<Type>::set(Type value)\n{   value_ = value; }\n\ntemplate <class Type>\nType extern_value<Type>::get(void)\n{   return value_; }\n\nINSTANTIATE( float );\nINSTANTIATE( double );\nINSTANTIATE( std::complex<float> );\nINSTANTIATE( std::complex<double> );\n//\nINSTANTIATE( CppAD::AD< float > );\nINSTANTIATE( CppAD::AD< double > );\nINSTANTIATE( CppAD::AD< std::complex<float> > );\nINSTANTIATE( CppAD::AD< std::complex<double> > );\n"
  },
  {
    "path": "test_more/general/extern_value.hpp",
    "content": "# ifndef CPPAD_TEST_MORE_GENERAL_EXTERN_VALUE_HPP\n# define CPPAD_TEST_MORE_GENERAL_EXTERN_VALUE_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\ntemplate <class Type>\nclass extern_value  {\nprivate:\n    Type value_;\npublic:\n    extern_value(Type value);\n    void set(Type value);\n    Type get(void);\n};\n\n# endif\n"
  },
  {
    "path": "test_more/general/fabs.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\nTest of directional derivative in AD< AD< double > > case.\n*/\n\n# include <cppad/cppad.hpp>\n\n\nbool fabs(void)\n{   // test if CppAD::abs uses if statement during forward computations\n    bool ok = true;\n\n    using CppAD::Independent;\n    using CppAD::ADFun;\n    typedef CppAD::AD<double>      ADdouble;\n    typedef CppAD::AD< ADdouble > ADDdouble;\n\n    // af(x) = |x|\n    CPPAD_TESTVECTOR( ADDdouble ) aax(1), aay(1);\n    aax[0] = ADDdouble(0.);\n    CppAD::Independent(aax);\n    aay[0] = fabs(aax[0]);\n    CppAD::ADFun< ADdouble > af(aax, aay);\n\n    // f(x) = |x|\n    CPPAD_TESTVECTOR( ADdouble ) ax(1), ay(1);\n    ax[0] = ADdouble(0.);\n    CppAD::Independent(ax);\n    ay    = af.Forward(0, ax);\n    CppAD::ADFun<double> f(ax, ay);\n\n    // compute derivative of af at a positive argument\n    CPPAD_TESTVECTOR( ADdouble ) adx(1), ady(1);\n    ax[0]  = 1.;\n    ay     = af.Forward(0, ax);\n    adx[0] = 1;\n    ady    = af.Forward(1, adx);\n    ok    &= (ady[0] == 1.);\n\n    // compute derivative of af at a zero argument\n    ax[0]  = 0.;\n    ay     = af.Forward(0, ax);\n    adx[0] = 1;\n    ady    = af.Forward(1, adx);\n    ok    &= (ady[0] == 0.);\n\n    // compute derivative of f at zero argument\n    CPPAD_TESTVECTOR(double) x(1), y(1), dx(1), dy(1);\n    x[0]  = 0.;\n    y     = f.Forward(0, x);\n    dx[0] = 1;\n    dy    = f.Forward(1, dx);\n    ok    &= (dy[0] == 0.);\n\n    // compute derivative of af at a negative argument\n    x[0]  = -1.;\n    y     = f.Forward(0, x);\n    dx[0] = 1;\n    dy    = f.Forward(1, dx);\n    ok    &= (dy[0] == -1.);\n\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/for_hes_sparsity.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n\n# include <cppad/cppad.hpp>\n\nnamespace { // Begin empty namespace\n\n// --------------------------------------------------------------------------\nbool test_old_interface()\n{   volatile bool ok = true;\n    using namespace CppAD;\n\n    // dimension of the domain space\n    size_t n = 14;\n\n    // dimension of the range space\n    size_t m = 1;\n\n    // temporary indices\n    size_t i, j;\n\n    // for testing load and store operations\n    CppAD::VecAD<double> ad_vec(2);\n    ad_vec[0] = 3.0;\n    ad_vec[1] = 4.0;\n\n    // initialize check values to false\n    CPPAD_TESTVECTOR(bool) check(n * n);\n    for(j = 0; j < n * n; j++)\n        check[j] = false;\n\n    // independent variable vector\n    CPPAD_TESTVECTOR(AD<double>) ax(n);\n    for(j = 0; j < n; j++)\n        ax[j] = AD<double>(j);\n    Independent(ax);\n\n    // accumulate sum here\n    AD<double> sum(0.);\n\n    // first operand\n    size_t F = 0;\n\n    // ad_vec[variable] when ad_vec is a parameter\n    sum += ad_vec[ax[F]]; // use fact ax[F] is zero\n    F += 1;\n\n    // ad_vec[parameter] when ad_vec depends on a variable\n    // (CppAD sparsity does not separate elements of ad_vec)\n    ad_vec[ AD<double>(0) ] = ax[F] * ax[F];\n    sum += ad_vec[ ax[F] ];  // user fact that ax[F] is one\n    check[F * n + F] = true;\n    F += 1;\n\n    // parameter / variable\n    sum += 2.0 / ax[F];\n    check[F * n + F] = true;\n    F += 1;\n\n    // erf(variable)\n    sum += erf( ax[F] );\n    check[F * n + F] = true;\n    F += 1;\n\n    // pow(parameter, variable)\n    sum += pow( 2.0 , ax[F] );\n    check[F * n + F] = true;\n    F += 1;\n\n    // pow(variable, parameter)\n    sum += pow( ax[F] , 2.0 );\n    check[F * n + F] = true;\n    F += 1;\n    // second operand\n    size_t S = F + 1;\n\n    // variable * variable\n    sum += ax[F] * ax[S];\n    check[F * n + S] = check[S * n + F] = true;\n    F += 2;\n    S += 2;\n\n    // azmul(variable, variable)\n    sum += azmul(ax[F], ax[S]);\n    check[F * n + S] = check[S * n + F] = true;\n    F += 2;\n    S += 2;\n\n    // variable / variable\n    sum += ax[F] / ax[S];\n    check[F * n + S] = check[S * n + F] = check[S * n + S] = true;\n    F += 2;\n    S += 2;\n\n    // pow( variable , variable )\n    sum += pow( ax[F] , ax[S] );\n    check[F * n + F] = check[S * n + S] = true;\n    check[F * n + S] = check[S * n + F] = true;\n    F += 2;\n    S += 2;\n\n    ok &= F == n;\n    CPPAD_TESTVECTOR(AD<double>) ay(m);\n    ay[0] = sum;\n\n    // create function object f : x -> y\n    ADFun<double> f(ax, ay);\n\n    // ------------------------------------------------------------------\n    // compute sparsity\n    CPPAD_TESTVECTOR(bool) r(n), s(m), h(n * n);\n    for(j = 0; j < n; j++)\n        r[j] = true;\n    for(i = 0; i < m; i++)\n        s[i] = true;\n    h = f.ForSparseHes(r, s);\n    // check result\n    for(i = 0; i < n; i++)\n        for(j = 0; j < n; j++)\n        {\n            if(h[i * n + j] != check[i * n + j])\n            {\n                std::cout << \"i: \" << i << std::endl;\n                std::cout << \"j: \" << j << std::endl;\n                std::cout << \"h[i * n + j]: \" << h[i * n + j] << std::endl;\n                std::cout << \"check[i * n + j]: \" << check[i * n + j] << std::endl;\n            }\n            ok &= h[i * n + j] == check[i * n + j];\n        }\n    // ------------------------------------------------------------------\n\n    return ok;\n}\n// --------------------------------------------------------------------------\n// This case demonstrated a bug that was fixed on 2024-11-16.\nbool test_csum(void)\n{\n    // ok\n    bool ok = true;\n    //\n    // n, ax\n    size_t n = 5;\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) ax(n);\n    for(size_t j = 0; j < n; ++j)\n        ax[j] = double(j + 1);\n    CppAD::Independent(ax);\n    //\n    // ay\n    size_t m = 1;\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) ay(m);\n    CppAD::AD<double> sum = ax[0];\n    for(size_t j = 1; j < n; ++j)\n        sum += ax[j];\n    ay[0] = sum * sum;\n    //\n    // f\n    // the optimize step should create a CSumOp operation\n    CppAD::ADFun<double> f(ax, ay);\n    f.optimize();\n    //\n    // sparse_rc\n    typedef CppAD::sparse_rc< CppAD::vector<size_t> > sparse_rc;\n    //\n    // pattern_hes\n    sparse_rc pattern_hes;\n    CPPAD_TESTVECTOR(bool) select_domain(n), select_range(m);\n    for(size_t j = 0; j < n; ++j)\n        select_domain[j] = true;\n    select_range[0] = true;\n    bool internal_bool = false;\n    f.for_hes_sparsity(\n        select_domain, select_range, internal_bool, pattern_hes\n    );\n    //\n    // pattern_check\n    size_t nr = n, nc = n, nnz = n * n;\n    sparse_rc pattern_check(nr, nc, nnz);\n    size_t k = 0;\n    for(size_t i = 0; i < n; ++i)\n    {   for(size_t j = 0; j < n; ++j)\n        {   pattern_check.set(k, i, j);\n            ++k;\n        }\n    }\n    //\n    // ok\n    ok &= pattern_hes == pattern_check;\n    //\n    return ok;\n}\n} // End of empty namespace\n\n// ---------------------------------------------------------------------------\nbool for_hes_sparsity(void)\n{   bool ok = true;\n    //\n    ok &= test_old_interface();\n    ok &= test_csum();\n    //\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/for_hess.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n\n/*\nOld ForHess example now used just for valiadation testing\n*/\n\n# include <cppad/cppad.hpp>\n\n\nbool ForHess(void)\n{   bool ok = true;\n\n    using namespace CppAD;\n    using CppAD::exp;\n    using CppAD::sin;\n    using CppAD::cos;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    size_t i;\n\n    // create independent variable vector with assigned values\n    CPPAD_TESTVECTOR(double)      u0(3);\n    CPPAD_TESTVECTOR(AD<double>) U(3);\n    for(i = 0; i < 3; i++)\n        U[i] = u0[i] = double(i+1);\n    Independent( U );\n\n    // define the function\n    CPPAD_TESTVECTOR(AD<double>) Y(2);\n    Y[0] = U[0] * exp( U[1] );\n    Y[1] = U[1] * sin( U[2] );\n\n    // create the function y = F(u)\n    ADFun<double> F(U, Y);\n\n    // formulas for the upper triangle of Hessian of F_0\n    CPPAD_TESTVECTOR(double) H0(9);\n    H0[0] = 0.;                    // d^2 y[0] / d_u[0] d_u[0]\n    H0[1] = exp( u0[1] );          // d^2 y[0] / d_u[0] d_u[1]\n    H0[2] = 0.;                    // d^2 y[0] / d_u[0] d_u[2]\n\n    H0[4] = u0[0] * exp( u0[1] );  // d^2 y[0] / d_u[1] d_u[1]\n    H0[5] = 0.;                    // d^2 y[0] / d_u[1] d_u[2]\n\n    H0[8] = 0.;                    // d^2 y[0] / d_u[2] d_u[2]\n\n    // formulas for the upper triangle of Hessian of F_1\n    CPPAD_TESTVECTOR(double) H1(9);\n    H1[0] = 0.;                    // d^2 Y[1] / d_U[0] d_U[0]\n    H1[1] = 0.;                    // d^2 Y[1] / d_U[0] d_U[1]\n    H1[2] = 0.;                    // d^2 Y[1] / d_U[0] d_U[2]\n\n    H1[4] = 0.;                    // d^2 Y[1] / d_U[1] d_U[1]\n    H1[5] = cos( u0[2] );          // d^2 Y[1] / d_U[1] d_U[2]\n\n    H1[8] = - u0[1] * sin( u0[2] );// d^2 Y[1] / d_U[2] d_U[2]\n\n\n    // Define U(t) = u0 + u1 t + u2 t^2 / 2\n    CPPAD_TESTVECTOR(double) u1(3);\n    CPPAD_TESTVECTOR(double) u2(3);\n    for(i = 0; i < 3; i++)\n        u1[i] = u2[i] = 0.;\n\n    size_t j;\n    for(i = 0; i < 3; i++)\n    {   // diagonal of Hessians in i-th coordinate direction\n        u1[i] = 1.;\n        F.Forward(1, u1);\n        CPPAD_TESTVECTOR(double) Di = F.Forward(2, u2);\n        ok &= NearEqual( 2. * Di[0] , H0[ i + 3 * i], eps99, eps99);\n        ok &= NearEqual( 2. * Di[1] , H1[ i + 3 * i], eps99, eps99);\n        //\n        for(j = i+1; j < 3; j++)\n        {   // cross term in i and j direction\n            u1[j] = 1.;\n            F.Forward(1, u1);\n            CPPAD_TESTVECTOR(double) Cij = F.Forward(2, u2);\n\n            // diagonal of Hessian in j-th coordinate direction\n            u1[i] = 0.;\n            F.Forward(1, u1);\n            CPPAD_TESTVECTOR(double) Dj = F.Forward(2, u2);\n\n            // (i, j) elements of the Hessians\n            double H0ij = Cij[0] - Di[0] - Dj[0];\n            ok &= NearEqual( H0ij, H0[j + 3 * i], eps99, eps99);\n            double H1ij = Cij[1] - Di[1] - Dj[1];\n            ok &= NearEqual( H1ij, H1[j + 3 * i], eps99, eps99);\n\n            // reset all components of u1 to zero\n            u1[j] = 0.;\n        }\n    }\n\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/for_jac_sparsity.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n\n# include <cppad/cppad.hpp>\n# include <vector>\n# include <valarray>\n\n# define CheckOp(Op)                   \\\n    Y[index] = X[0] Op 2.;         \\\n    Check[index * n + 0] = true;   \\\n    Check[index * n + 1] = false;  \\\n    Check[index * n + 2] = false;  \\\n    index++;                       \\\n    Y[index] = X[0] Op X[1];       \\\n    Check[index * n + 0] = true;   \\\n    Check[index * n + 1] = true;   \\\n    Check[index * n + 2] = false;  \\\n    index++;                       \\\n    Y[index] = 3.   Op X[1];       \\\n    Check[index * n + 0] = false;  \\\n    Check[index * n + 1] = true;   \\\n    Check[index * n + 2] = false;  \\\n    index++;\n\n# define CheckUnaryFun(Fun)            \\\n    Y[index] = Fun(X[0]);          \\\n    Check[index * n + 0] = true;   \\\n    Check[index * n + 1] = false;  \\\n    Check[index * n + 2] = false;  \\\n    index++;                       \\\n    Y[index] = Fun(X[0] + X[1]);   \\\n    Check[index * n + 0] = true;   \\\n    Check[index * n + 1] = true;   \\\n    Check[index * n + 2] = false;  \\\n    index++;                       \\\n    Y[index] = Fun(X[1]);          \\\n    Check[index * n + 0] = false;  \\\n    Check[index * n + 1] = true;   \\\n    Check[index * n + 2] = false;  \\\n    index++;\n\n\n# define CheckBinaryFun(Fun)           \\\n    Y[index] = Fun( X[0] , 2.);    \\\n    Check[index * n + 0] = true;   \\\n    Check[index * n + 1] = false;  \\\n    Check[index * n + 2] = false;  \\\n    index++;                       \\\n    Y[index] = Fun( X[0] , X[1]);  \\\n    Check[index * n + 0] = true;   \\\n    Check[index * n + 1] = true;   \\\n    Check[index * n + 2] = false;  \\\n    index++;                       \\\n    Y[index] = Fun( 3.   , X[1]);  \\\n    Check[index * n + 0] = false;  \\\n    Check[index * n + 1] = true;   \\\n    Check[index * n + 2] = false;  \\\n    index++;\n\n\nnamespace { // Begin empty namespace\n\nbool case_one()\n{   bool ok = true;\n    using namespace CppAD;\n\n    // dimension of the domain space\n    size_t n = 3;\n\n    // dimension of the range space\n    size_t m = (4 + 11 + 1) * 3 + 4;\n\n    // independent variable vector\n    CPPAD_TESTVECTOR(AD<double>) X(n);\n    X[0] = .1;\n    X[1] = .2;\n    X[2] = .3;\n    Independent(X);\n\n    // dependent variable vector\n    CPPAD_TESTVECTOR(AD<double>) Y(m);\n\n    // check results vector\n    CPPAD_TESTVECTOR( bool )       Check(m * n);\n\n    // initialize index into Y\n    size_t index = 0;\n\n    // 4 binary operators\n    CheckOp(+);\n    CheckOp(-);\n    CheckOp(*);\n    CheckOp(/);\n\n    // 11 unary functions\n    CheckUnaryFun(abs);\n    CheckUnaryFun(acos);\n    CheckUnaryFun(asin);\n    CheckUnaryFun(atan);\n    CheckUnaryFun(cos);\n    CheckUnaryFun(cosh);\n    CheckUnaryFun(exp);\n    CheckUnaryFun(log);\n    CheckUnaryFun(sin);\n    CheckUnaryFun(sinh);\n    CheckUnaryFun(sqrt);\n\n    // 1 binary function\n    CheckBinaryFun(pow);\n\n    // conditional expression (value of comparison does not matter)\n    Y[index] = CondExpLt(X[0], X[1], X[0], AD<double>(2.));\n    Check[index * n + 0] = true;\n    Check[index * n + 1] = false;\n    Check[index * n + 2] = false;\n    index++;\n    Y[index] = CondExpLt(X[0], X[1], X[0], X[1]);\n    Check[index * n + 0] = true;\n    Check[index * n + 1] = true;\n    Check[index * n + 2] = false;\n    index++;\n    Y[index] = CondExpLt(X[0], X[1], AD<double>(3.), X[1]);\n    Check[index * n + 0] = false;\n    Check[index * n + 1] = true;\n    Check[index * n + 2] = false;\n    index++;\n\n    // non-trivial composition\n    Y[index] = X[0] * X[1] + X[1] * X[2];\n    Check[index * n + 0] = true;\n    Check[index * n + 1] = true;\n    Check[index * n + 2] = true;\n    index++;\n\n    // check final index\n    assert( index == m );\n\n    // create function object F : X -> Y\n    ADFun<double> F(X, Y);\n\n    // ---------------------------------------------------------\n    // dependency matrix for the identity function W(x) = x\n    CPPAD_TESTVECTOR( bool ) Px(n * n);\n    size_t i, j;\n    for(i = 0; i < n; i++)\n    {   for(j = 0; j < n; j++)\n            Px[ i * n + j ] = false;\n        Px[ i * n + i ] = true;\n    }\n\n    // evaluate the dependency matrix for F(X(x))\n    CPPAD_TESTVECTOR( bool ) Py(m * n);\n    Py = F.ForSparseJac(n, Px);\n\n    // check values\n    for(i = 0; i < m; i++)\n    {   for(j = 0; j < n; j++)\n            ok &= (Py[i * n + j] == Check[i * n + j]);\n    }\n\n    // ---------------------------------------------------------\n    // dependency matrix for the identity function W(x) = x\n    CPPAD_TESTVECTOR(std::set<size_t>) Sx(n);\n    for(i = 0; i < n; i++)\n    {   assert( Sx[i].empty() );\n        Sx[i].insert(i);\n    }\n\n    // evaluate the dependency matrix for F(X(x))\n    CPPAD_TESTVECTOR(std::set<size_t>) Sy(m);\n    Sy = F.ForSparseJac(n, Sx);\n\n    // check values\n    bool found;\n    for(i = 0; i < m; i++)\n    {   for(j = 0; j < n; j++)\n        {   found = Sy[i].find(j) != Sy[i].end();\n            ok &= (found == Check[i * n + j]);\n        }\n    }\n\n    return ok;\n}\n\nbool case_two()\n{   bool ok = true;\n    using namespace CppAD;\n\n    // dimension of the domain space\n    size_t n = 3;\n\n    // dimension of the range space\n    size_t m = 3;\n\n    // initialize the vector as zero\n    CppAD::VecAD<double> Z(n - 1);\n    size_t k;\n    for(k = 0; k < n-1; k++)\n        Z[k] = 0.;\n\n    // independent variable vector\n    CPPAD_TESTVECTOR(AD<double>) X(n);\n    X[0] = 0.;\n    X[1] = 1.;\n    X[2] = 2.;\n    Independent(X);\n\n    // VecAD vector is going to depend on X[1] and X[2]\n    Z[ X[0] ] = X[1];\n    Z[ X[1] ] = X[2];\n\n    // dependent variable vector\n    CPPAD_TESTVECTOR(AD<double>) Y(m);\n\n    // check results vector\n    CPPAD_TESTVECTOR( bool )       Check(m * n);\n\n    // initialize index into Y\n    size_t index = 0;\n\n    // First component only depends on X[0];\n    Y[index]             = X[0];\n    Check[index * n + 0] = true;\n    Check[index * n + 1] = false;\n    Check[index * n + 2] = false;\n    index++;\n\n    // Second component depends on the vector Z\n    AD<double> zero(0);\n    Y[index]             = Z[zero]; // Load by a parameter\n    Check[index * n + 0] = false;\n    Check[index * n + 1] = true;\n    Check[index * n + 2] = true;\n    index++;\n\n    // Third component depends on the vector Z\n    Y[index]             = Z[ X[0] ]; // Load by a variable\n    Check[index * n + 0] = false;\n    Check[index * n + 1] = true;\n    Check[index * n + 2] = true;\n    index++;\n\n    // check final index\n    assert( index == m );\n\n    // create function object F : X -> Y\n    ADFun<double> F(X, Y);\n\n    // -----------------------------------------------------------------\n    // dependency matrix for the identity function W(x) = x\n    CPPAD_TESTVECTOR( bool ) Px(n * n);\n    size_t i, j;\n    for(i = 0; i < n; i++)\n    {   for(j = 0; j < n; j++)\n            Px[ i * n + j ] = false;\n        Px[ i * n + i ] = true;\n    }\n\n    // evaluate the dependency matrix for F(X(x))\n    CPPAD_TESTVECTOR( bool ) Py(m * n);\n    Py = F.ForSparseJac(n, Px);\n\n    // check values\n    for(i = 0; i < m; i++)\n    {   for(j = 0; j < n; j++)\n            ok &= (Py[i * n + j] == Check[i * n + j]);\n    }\n\n    // ---------------------------------------------------------\n    // dependency matrix for the identity function W(x) = x\n    CPPAD_TESTVECTOR(std::set<size_t>) Sx(n);\n    for(i = 0; i < n; i++)\n    {   assert( Sx[i].empty() );\n        Sx[i].insert(i);\n    }\n\n    // evaluate the dependency matrix for F(X(x))\n    CPPAD_TESTVECTOR(std::set<size_t>) Sy(m);\n    Sy = F.ForSparseJac(n, Sx);\n\n    // check values\n    bool found;\n    for(i = 0; i < m; i++)\n    {   for(j = 0; j < n; j++)\n        {   found = Sy[i].find(j) != Sy[i].end();\n            ok &= (found == Check[i * n + j]);\n        }\n    }\n\n    return ok;\n}\n\nbool case_three()\n{   bool ok = true;\n    using namespace CppAD;\n\n    // dimension of the domain space\n    size_t n = 2;\n\n    // dimension of the range space\n    size_t m = 3;\n\n    // independent variable vector\n    CPPAD_TESTVECTOR(AD<double>) X(n);\n    X[0] = 2.;\n    X[1] = 3.;\n    Independent(X);\n\n    // dependent variable vector\n    CPPAD_TESTVECTOR(AD<double>) Y(m);\n\n    // check results vector\n    CPPAD_TESTVECTOR( bool )       Check(m * n);\n\n    // initialize index into Y\n    size_t index = 0;\n\n    // Y[0] only depends on X[0];\n    Y[index]             = pow(X[0], 2.);\n    Check[index * n + 0] = true;\n    Check[index * n + 1] = false;\n    index++;\n\n    // Y[1] depends on X[1]\n    Y[index]             = pow(2., X[1]);\n    Check[index * n + 0] = false;\n    Check[index * n + 1] = true;\n    index++;\n\n    // Y[2] depends on X[0] and X[1]\n    Y[index]             = pow(X[0], X[1]);\n    Check[index * n + 0] = true;\n    Check[index * n + 1] = true;\n    index++;\n\n    // check final index\n    assert( index == m );\n\n    // create function object F : X -> Y\n    ADFun<double> F(X, Y);\n\n    // -----------------------------------------------------------------\n    // dependency matrix for the identity function\n    CPPAD_TESTVECTOR( bool ) Px(n * n);\n    size_t i, j;\n    for(i = 0; i < n; i++)\n    {   for(j = 0; j < n; j++)\n            Px[ i * n + j ] = false;\n        Px[ i * n + i ] = true;\n    }\n\n    // evaluate the dependency matrix for F(X(x))\n    CPPAD_TESTVECTOR( bool ) Py(m * n);\n    Py = F.ForSparseJac(n, Px);\n\n    // check values\n    for(i = 0; i < m; i++)\n    {   for(j = 0; j < n; j++)\n            ok &= (Py[i * n + j] == Check[i * n + j]);\n    }\n\n    // ---------------------------------------------------------\n    // dependency matrix for the identity function\n    CPPAD_TESTVECTOR(std::set<size_t>) Sx(n);\n    for(i = 0; i < n; i++)\n    {   assert( Sx[i].empty() );\n        Sx[i].insert(i);\n    }\n\n    // evaluate the dependency matrix for F(X(x))\n    CPPAD_TESTVECTOR(std::set<size_t>) Sy(m);\n    Sy = F.ForSparseJac(n, Sx);\n\n    // check values\n    bool found;\n    for(i = 0; i < m; i++)\n    {   for(j = 0; j < n; j++)\n        {   found = Sy[i].find(j) != Sy[i].end();\n            ok &= (found == Check[i * n + j]);\n        }\n    }\n\n    return ok;\n}\n\nbool case_four()\n{   bool ok = true;\n    using namespace CppAD;\n\n    // dimension of the domain space\n    size_t n = 2;\n\n    // dimension of the range space\n    size_t m = 3;\n\n    // independent variable vector\n    CPPAD_TESTVECTOR(AD<double>) X(n);\n    X[0] = 2.;\n    X[1] = 3.;\n    Independent(X);\n\n    // dependent variable vector\n    CPPAD_TESTVECTOR(AD<double>) Y(m);\n\n    // check results vector\n    CPPAD_TESTVECTOR( bool )       Check(m * n);\n\n    // initialize index into Y\n    size_t index = 0;\n\n    // Y[0] only depends on X[0];\n    Y[index]             = pow(X[0], 2.);\n    Check[index * n + 0] = true;\n    Check[index * n + 1] = false;\n    index++;\n\n    // Y[1] depends on X[1]\n    Y[index]             = pow(2., X[1]);\n    Check[index * n + 0] = false;\n    Check[index * n + 1] = true;\n    index++;\n\n    // Y[2] depends on X[0] and X[1]\n    Y[index]             = pow(X[0], X[1]);\n    Check[index * n + 0] = true;\n    Check[index * n + 1] = true;\n    index++;\n\n    // check final index\n    assert( index == m );\n\n    // create function object F : X -> Y\n    ADFun<double> F(X, Y);\n\n    // -----------------------------------------------------------------\n    // dependency matrix for the identity function\n    CPPAD_TESTVECTOR( bool ) Px(n * n);\n    size_t i, j;\n    for(i = 0; i < n; i++)\n    {   for(j = 0; j < n; j++)\n            Px[ i * n + j ] = false;\n        Px[ i * n + i ] = true;\n    }\n\n    // evaluate the dependency matrix for F(X(x))\n    bool transpose = true;\n    CPPAD_TESTVECTOR( bool ) Py(n * m);\n    Py = F.ForSparseJac(n, Px, transpose);\n\n    // check values\n    for(i = 0; i < m; i++)\n    {   for(j = 0; j < n; j++)\n            ok &= (Py[j * m + i] == Check[i * n + j]);\n    }\n\n    // ---------------------------------------------------------\n    // dependency matrix for the identity function\n    CPPAD_TESTVECTOR(std::set<size_t>) Sx(n);\n    for(i = 0; i < n; i++)\n    {   assert( Sx[i].empty() );\n        Sx[i].insert(i);\n    }\n\n    // evaluate the dependency matrix for F(X(x))\n    CPPAD_TESTVECTOR(std::set<size_t>) Sy(n);\n    Sy = F.ForSparseJac(n, Sx, transpose);\n\n    // check values\n    bool found;\n    for(i = 0; i < m; i++)\n    {   for(j = 0; j < n; j++)\n        {   found = Sy[j].find(i) != Sy[j].end();\n            ok &= (found == Check[i * n + j]);\n        }\n    }\n\n    return ok;\n}\n\n} // End empty namespace\n\nbool for_jac_sparsity(void)\n{   bool ok = true;\n\n    ok &= case_one();\n    ok &= case_two();\n    ok &= case_three();\n    ok &= case_four();\n\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/forward.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\nTwo old Forward example now used just for valiadation testing\n*/\n\n# include <cppad/cppad.hpp>\n\nnamespace { // Begin empty namespace\n\ntemplate <class DoubleVector> // vector class, elements of type double\nbool ForwardCases(void)\n{   bool ok = true;\n\n    using namespace CppAD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // independent variable vector\n    CPPAD_TESTVECTOR(AD<double>) X(2);\n    X[0] = 0.;\n    X[1] = 1.;\n    Independent(X);\n\n    // compute product of elements in X\n    CPPAD_TESTVECTOR(AD<double>) Y(1);\n    Y[0] = X[0] * X[0] * X[1];\n\n    // create function object F : X -> Y\n    ADFun<double> F(X, Y);\n\n    // use zero order to evaluate F[ (3, 4) ]\n    DoubleVector x0( F.Domain() );\n    DoubleVector y0( F.Range() );\n    x0[0]    = 3.;\n    x0[1]    = 4.;\n    y0       = F.Forward(0, x0);\n    ok      &= NearEqual(y0[0] , x0[0]*x0[0]*x0[1], eps99, eps99);\n\n    // evaluate derivative of F in X[0] direction\n    DoubleVector x1( F.Domain() );\n    DoubleVector y1( F.Range() );\n    x1[0]    = 1.;\n    x1[1]    = 0.;\n    y1       = F.Forward(1, x1);\n    ok      &= NearEqual(y1[0] , 2.*x0[0]*x0[1], eps99, eps99);\n\n    // evaluate second derivative of F in X[0] direction\n    DoubleVector x2( F.Domain() );\n    DoubleVector y2( F.Range() );\n    x2[0]       = 0.;\n    x2[1]       = 0.;\n    y2          = F.Forward(2, x2);\n    double F_00 = 2. * y2[0];\n    ok         &= NearEqual(F_00, 2.*x0[1], eps99, eps99);\n\n    // evaluate derivative of F in X[1] direction\n    x1[0]    = 0.;\n    x1[1]    = 1.;\n    y1       = F.Forward(1, x1);\n    ok      &= NearEqual(y1[0] , x0[0]*x0[0], eps99, eps99);\n\n    // evaluate second derivative of F in X[1] direction\n    y2          = F.Forward(2, x2);\n    double F_11 = 2. * y2[0];\n    ok         &= NearEqual(F_11, 0., eps99, eps99);\n\n    // evaluate derivative of F in X[0] + X[1] direction\n    x1[0]    = 1.;\n    x1[1]    = 1.;\n    y1       = F.Forward(1, x1);\n    ok      &= NearEqual(y1[0], 2.*x0[0]*x0[1] + x0[0]*x0[0], eps99, eps99);\n\n    // use second derivative of F in X[0] direction to\n    // compute second partial of F w.r.t X[1] w.r.t X[2]\n    y2          = F.Forward(2, x2);\n    double F_01 = y2[0] - F_00 / 2. - F_11 / 2.;\n    ok         &= NearEqual(F_01 , 2.*x0[0], eps99, eps99);\n\n    return ok;\n}\n\nbool ForwardOlder(void)\n{   bool ok = true;\n\n    using namespace CppAD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // independent variable vector\n    CPPAD_TESTVECTOR(AD<double>) U(3);\n    U[0] = 0.; U[1] = 1.; U[2] = 2.;\n    Independent(U);\n\n    // compute sum and product of elements in U\n    AD<double> sum  = 0.;\n    AD<double> prod = 1.;\n    size_t i;\n    for(i = 0; i < 3; i++)\n    {   sum  += U[i];\n        prod *= U[i];\n    }\n\n    // dependent variable vector\n    CPPAD_TESTVECTOR(AD<double>) V(2);\n    V[0] = sum;\n    V[1] = prod;\n\n    // V = f(U)\n    ADFun<double> f(U, V);\n\n    // use ADFun object to evaluate f[ (1, 2, 3)^T ] -----------------\n    CPPAD_TESTVECTOR(double) u0( f.Domain() );\n    CPPAD_TESTVECTOR(double) v0( f.Range() );\n    size_t p;\n    p     = 0;\n    u0[0] = 1.; u0[1] = 2.; u0[2] = 3.;\n    v0    = f.Forward(p, u0);\n\n    // direct evaluation of f[ u0 ]\n    CPPAD_TESTVECTOR(double) f0(2);\n    f0[0] = u0[0] + u0[1] + u0[2];\n    f0[1] = u0[0] * u0[1] * u0[2];\n\n    // compare values\n    ok &= NearEqual(v0[0] , f0[0], eps99, eps99);\n    ok &= NearEqual(v0[1] , f0[1], eps99, eps99);\n\n    // use ADFun object to evaluate f^(1) [ u0 ] * u1 -----------------\n    CPPAD_TESTVECTOR(double) u1( f.Domain() );\n    CPPAD_TESTVECTOR(double) v1( f.Range() );\n    p     = 1;\n    u1[0] = 1.; u1[1] = 1.; u1[2] = 1.;\n    v1    = f.Forward(p, u1);\n\n    // direct evaluation of gradients of components of f\n    CPPAD_TESTVECTOR(double) g0(3), g1(3);\n    g0[0] =          1.; g0[1] =          1.; g0[2] =          1.;\n    g1[0] = u0[1]*u0[2]; g1[1] = u0[0]*u0[2]; g1[2] = u0[0]*u0[1];\n\n    // compare values\n    ok &= NearEqual(v1[0] ,\n        g0[0]*u1[0] + g0[1]*u1[1] + g0[2]*u1[2] , eps99, eps99);\n    ok &= NearEqual(v1[1] ,\n        g1[0]*u1[0] + g1[1]*u1[1] + g1[2]*u1[2] , eps99, eps99);\n\n    // use ADFun object to evaluate ------------------------------------\n    // (1/2) * { f^(1)[ u0 ] * u2 + u1^T * f^(2)[ u0 ] * u1 }\n    CPPAD_TESTVECTOR(double) u2( f.Domain() );\n    CPPAD_TESTVECTOR(double) v2( f.Range() );\n    p     = 2;\n    u2[0] = .5; u2[1] = .4; u2[2] = .3;\n    v2    = f.Forward(p, u2);\n\n    // direct evaluation of Hessian of second components of f\n    // (the Hessian of the first component is zero)\n    CPPAD_TESTVECTOR(double) H1(9);\n    H1[0] =    0.; H1[1] = u0[2]; H1[2] = u0[1];\n    H1[3] = u0[2]; H1[4] =    0.; H1[5] = u0[0];\n    H1[6] = u0[1]; H1[7] = u0[0]; H1[8] =    0.;\n\n    // compare values\n    ok &= NearEqual(v2[0] ,\n        g0[0]*u2[0] + g0[1]*u2[1] + g0[2]*u2[2] , eps99, eps99);\n\n    size_t j;\n    double v2_1 = 0.;\n    for(i = 0; i < 3; i++)\n    {   v2_1 += g1[i] * u2[i];\n        for(j = 0; j < 3; j++)\n            v2_1 += .5 * u1[i] * H1[i * 3 + j] * u1[j];\n    }\n    ok &= NearEqual(v2[1], v2_1, eps99, eps99);\n\n\n    return ok;\n}\n\n# ifndef NDEBUG\n# if ! CPPAD_DEBUG_AND_RELEASE\nvoid my_error_handler(\n    bool known           ,\n    int  line            ,\n    const char *file     ,\n    const char *exp      ,\n    const char *msg      )\n{   // error handler must not return, so throw an exception\n    std::string message = msg;\n    throw message;\n}\n\nbool forward_nan(void)\n{\n\n    using CppAD::vector;\n    using CppAD::AD;\n\n    size_t n = 2, m = 1;\n    vector< AD<double> > a_x(n), a_y(m);\n    a_x[0] = 1.;\n    a_x[1] = 2.;\n    Independent(a_x);\n    a_y[0] = a_x[0] / a_x[1];\n    CppAD::ADFun<double> f(a_x, a_y);\n    //\n    vector<double> x(n), y(m);\n    x[0] = 0.;\n    x[1] = 0.;\n\n    // replace the default CppAD error handler\n    CppAD::ErrorHandler info(my_error_handler);\n\n    bool ok = false;\n    try {\n        y    = f.Forward(0, x);\n    }\n    catch( std::string msg )\n    {   // check that the message contains\n        // \"vector_size = \" and \"file_name = \"\n        ok = msg.find(\"vector_size = \") != std::string::npos;\n        ok = msg.find(\"file_name = \") != std::string::npos;\n    }\n\n    return ok;\n}\n# endif\n# endif\n} // END empty namespace\n\n# include <vector>\n# include <valarray>\nbool Forward(void)\n{   bool ok = true;\n    ok &= ForwardCases< CppAD::vector  <double> >();\n    ok &= ForwardCases< std::vector    <double> >();\n    ok &= ForwardCases< std::valarray  <double> >();\n    ok &= ForwardOlder();\n# ifndef NDEBUG\n# if ! CPPAD_DEBUG_AND_RELEASE\n    // CppAD does not check for nan when NDEBUG is defined\n    ok &= forward_nan();\n# endif\n# endif\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/forward_dir.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n// test multiple directions operators\n// MulvvOp is tested by example/forward_dir.cpp\n\n# include <limits>\n# include <cmath>\n# include <cppad/cppad.hpp>\n\nnamespace {\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    // ---------------------------------------------------------------------\n    // Used the check that fun is an identity function\n    typedef AD<double> (*adfun)(const AD<double>&);\n    bool check_identity(adfun identity, double argument)\n    {\n        bool ok = true;\n        double eps = 10. * std::numeric_limits<double>::epsilon();\n        size_t j;\n\n\n        // domain space vector\n        size_t n = 1;\n        CPPAD_TESTVECTOR(AD<double>) ax(n);\n        ax[0] = argument;\n\n        // declare independent variables and starting recording\n        CppAD::Independent(ax);\n\n        // range space vector\n        size_t m = 1;\n        CPPAD_TESTVECTOR(AD<double>) ay(m);\n        ay[0] = identity(ax[0]);\n\n        // create f: x -> y and stop tape recording\n        CppAD::ADFun<double> f(ax, ay);\n\n        // first order Taylor coefficients\n        size_t r = 2, ell;\n        CPPAD_TESTVECTOR(double) x1(r*n), y1;\n        for(ell = 0; ell < r; ell++)\n        {   for(j = 0; j < n; j++)\n                x1[ r * j + ell ] = double(j + ell + 1);\n        }\n        y1  = f.Forward(1, r, x1);\n        ok &= size_t( y1.size() ) == r*m;\n\n        // secondorder Taylor coefficients\n        CPPAD_TESTVECTOR(double) x2(r*n), y2;\n        for(ell = 0; ell < r; ell++)\n        {   for(j = 0; j < n; j++)\n                x2[ r * j + ell ] = double(j + ell + 2);\n        }\n        y2  = f.Forward(2, r, x2);\n        ok &= size_t( y2.size() ) == r*m;\n        //\n        // Y_0  (t)    = F[X_0(t)] = X_0(t)\n        //             =  0.5 + 1t + 2t^2\n        double y_1_0   = 1.0;\n        double y_2_0   = 2.0;\n        //\n        // Y_1  (t)    = F[X_1(t)] = X_1(t)\n        //             =  0.5 + 2t + 3t^2\n        double y_1_1   = 2.0;\n        double y_2_1   = 3.0;\n        //\n        ok  &= NearEqual(y1[0] , y_1_0, eps, eps);\n        ok  &= NearEqual(y1[1] , y_1_1, eps, eps);\n        ok  &= NearEqual(y2[0] , y_2_0, eps, eps);\n        ok  &= NearEqual(y2[1] , y_2_1, eps, eps);\n        //\n        return ok;\n    }\n    // ---------------------------------------------------------------------\n    // AbsOp\n    bool abs_op(void)\n    {   bool ok = true;\n        double eps = 10. * std::numeric_limits<double>::epsilon();\n        size_t j;\n\n        // domain space vector\n        size_t n = 2;\n        CPPAD_TESTVECTOR(AD<double>) ax(n);\n        ax[0] = 0.5;\n        ax[1] = -1.0;\n\n        // declare independent variables and starting recording\n        CppAD::Independent(ax);\n\n        // range space vector\n        size_t m = 1;\n        CPPAD_TESTVECTOR(AD<double>) ay(m);\n        ay[0] = fabs( ax[0] ) + fabs( 2.0 * ax[1] );\n\n        // create f: x -> y and stop tape recording\n        CppAD::ADFun<double> f(ax, ay);\n\n        // first order Taylor coefficients\n        size_t r = 2, ell;\n        CPPAD_TESTVECTOR(double) x1(r*n), y1;\n        for(ell = 0; ell < r; ell++)\n        {   for(j = 0; j < n; j++)\n                x1[ r * j + ell ] = double(j + ell + 1);\n        }\n        y1  = f.Forward(1, r, x1);\n        ok &= size_t( y1.size() ) == r*m;\n\n        // secondorder Taylor coefficients\n        CPPAD_TESTVECTOR(double) x2(r*n), y2;\n        for(ell = 0; ell < r; ell++)\n        {   for(j = 0; j < n; j++)\n                x2[ r * j + ell ] = double(j + ell + 2);\n        }\n        y2  = f.Forward(2, r, x2);\n        ok &= size_t( y2.size() ) == r*m;\n        //\n        // Y_0  (t)    = F[X_0(t)]\n        //             = fabs(0.5 + 1t + 2t^2) + fabs( 2*(-1.0 + 2t + 3t^2 ) )\n        double y_1_0   = -3.0;\n        double y_2_0   = -4.0;\n        //\n        // Y_1  (t)    = F[X_1(t)]\n        //             = fabs(0.5 + 2t + 3t^2) + fabs( 2*(-1.0 + 3t + 4t^2 ) )\n        double y_1_1   = -4.0;\n        double y_2_1   = -5.0;\n        //\n        ok  &= NearEqual(y1[0] , y_1_0, eps, eps);\n        ok  &= NearEqual(y1[1] , y_1_1, eps, eps);\n        ok  &= NearEqual(y2[0] , y_2_0, eps, eps);\n        ok  &= NearEqual(y2[1] , y_2_1, eps, eps);\n        //\n        return ok;\n    }\n    // ---------------------------------------------------------------------\n    // AddpvOp\n    bool addpv_op(void)\n    {   bool ok = true;\n        double eps = 10. * std::numeric_limits<double>::epsilon();\n        size_t j;\n\n        // domain space vector\n        size_t n = 1;\n        CPPAD_TESTVECTOR(AD<double>) ax(n);\n        ax[0] = 0.5;\n\n        // declare independent variables and starting recording\n        CppAD::Independent(ax);\n\n        // range space vector\n        size_t m = 1;\n        CPPAD_TESTVECTOR(AD<double>) ay(m);\n        ay[0] = 2.0 + ax[0];\n\n        // create f: x -> y and stop tape recording\n        CppAD::ADFun<double> f(ax, ay);\n\n        // first order Taylor coefficients\n        size_t r = 2, ell;\n        CPPAD_TESTVECTOR(double) x1(r*n), y1;\n        for(ell = 0; ell < r; ell++)\n        {   for(j = 0; j < n; j++)\n                x1[ r * j + ell ] = double(j + ell + 1);\n        }\n        y1  = f.Forward(1, r, x1);\n        ok &= size_t( y1.size() ) == r*m;\n\n        // secondorder Taylor coefficients\n        CPPAD_TESTVECTOR(double) x2(r*n), y2;\n        for(ell = 0; ell < r; ell++)\n        {   for(j = 0; j < n; j++)\n                x2[ r * j + ell ] = double(j + ell + 3);\n        }\n        y2  = f.Forward(2, r, x2);\n        ok &= size_t( y2.size() ) == r*m;\n        //\n        // Y_0 (t)     = F[X_0(t)]\n        //             =  2.0 + (0.5 + 1t + 3t^2)\n        double y_1_0   = 1.0;\n        double y_2_0   = 3.0;\n        //\n        // Y_1 (t)     = F[X_1(t)]\n        //             =  2.0 + (0.5 + 2t + 4t^2)\n        double y_1_1   = 2.0;\n        double y_2_1   = 4.0;\n        //\n        ok  &= NearEqual(y1[0] , y_1_0, eps, eps);\n        ok  &= NearEqual(y1[1] , y_1_1, eps, eps);\n        ok  &= NearEqual(y2[0] , y_2_0, eps, eps);\n        ok  &= NearEqual(y2[1] , y_2_1, eps, eps);\n        //\n        return ok;\n    }\n    // ---------------------------------------------------------------------\n    // AddvvOp\n    bool addvv_op(void)\n    {   bool ok = true;\n        double eps = 10. * std::numeric_limits<double>::epsilon();\n        size_t j;\n\n        // domain space vector\n        size_t n = 2;\n        CPPAD_TESTVECTOR(AD<double>) ax(n);\n        ax[0] = 0.5;\n        ax[1] = 2.0;\n\n        // declare independent variables and starting recording\n        CppAD::Independent(ax);\n\n        // range space vector\n        size_t m = 1;\n        CPPAD_TESTVECTOR(AD<double>) ay(m);\n        ay[0] = ax[0] + ax[1];\n\n        // create f: x -> y and stop tape recording\n        CppAD::ADFun<double> f(ax, ay);\n\n        // first order Taylor coefficients\n        size_t r = 2, ell;\n        CPPAD_TESTVECTOR(double) x1(r*n), y1;\n        for(ell = 0; ell < r; ell++)\n        {   for(j = 0; j < n; j++)\n                x1[ r * j + ell ] = double(j + ell + 1);\n        }\n        y1  = f.Forward(1, r, x1);\n        ok &= size_t( y1.size() ) == r*m;\n\n        // secondorder Taylor coefficients\n        CPPAD_TESTVECTOR(double) x2(r*n), y2;\n        for(ell = 0; ell < r; ell++)\n        {   for(j = 0; j < n; j++)\n                x2[ r * j + ell ] = double(j + ell + 2);\n        }\n        y2  = f.Forward(2, r, x2);\n        ok &= size_t( y2.size() ) == r*m;\n        //\n        // Y_0 (t)     = F[X_0(t)]\n        //             =  (0.5 + 1t + 2t^2) + (2.0 + 2t + 3t^2)\n        double y_1_0   = 1.0 + 2.0;\n        double y_2_0   = 2.0 + 3.0;\n        //\n        // Y_1 (t)     = F[X_1(t)]\n        //             =  (2.0 + 2t + 3t^2) + (2.0 + 3t + 4t^2)\n        double y_1_1   = 2.0 + 3.0;\n        double y_2_1   = 3.0 + 4.0;\n        //\n        ok  &= NearEqual(y1[0] , y_1_0, eps, eps);\n        ok  &= NearEqual(y1[1] , y_1_1, eps, eps);\n        ok  &= NearEqual(y2[0] , y_2_0, eps, eps);\n        ok  &= NearEqual(y2[1] , y_2_1, eps, eps);\n        //\n        return ok;\n    }\n    // ---------------------------------------------------------------------\n    // CosOp\n    bool cos_op(void)\n    {   bool ok = true;\n        double eps = 10. * std::numeric_limits<double>::epsilon();\n        size_t j;\n\n\n        // domain space vector\n        size_t n = 1;\n        CPPAD_TESTVECTOR(AD<double>) ax(n);\n        ax[0] = 0.5;\n\n        // declare independent variables and starting recording\n        CppAD::Independent(ax);\n\n        // range space vector\n        size_t m = 1;\n        CPPAD_TESTVECTOR(AD<double>) ay(m);\n        ay[0] = cos( ax[0] );\n\n        // create f: x -> y and stop tape recording\n        CppAD::ADFun<double> f(ax, ay);\n\n        // first order Taylor coefficients\n        size_t r = 2, ell;\n        CPPAD_TESTVECTOR(double) x1(r*n), y1;\n        for(ell = 0; ell < r; ell++)\n        {   for(j = 0; j < n; j++)\n                x1[ r * j + ell ] = double(j + ell + 1);\n        }\n        y1  = f.Forward(1, r, x1);\n        ok &= size_t( y1.size() ) == r*m;\n\n        // secondorder Taylor coefficients\n        CPPAD_TESTVECTOR(double) x2(r*n), y2;\n        for(ell = 0; ell < r; ell++)\n        {   for(j = 0; j < n; j++)\n                x2[ r * j + ell ] = double(j + ell + 2);\n        }\n        y2  = f.Forward(2, r, x2);\n        ok &= size_t( y2.size() ) == r*m;\n        //\n        // Y_0  (t)    = F[X_0(t)]\n        //             =  cos( 0.5 + 1t + 2t^2 )\n        // Y_0' (t)    = -sin( 0.5 + 1t + 2t^2) * (1 + 4t)\n        double y_1_0   = - sin(0.5);\n        double y_2_0   = - ( cos(0.5) + 4.0 * sin(0.5) ) / 2.0;\n        //\n        // Y_1  (t)    = F[X_1(t)]\n        //             =  cos( 0.5 + 2t + 3t^2 )\n        // Y_1' (t)    = -sin( 0.5 + 2t + 3t^2) * (2 + 6t)\n        double y_1_1   = - sin(0.5) * 2.0;\n        double y_2_1   = - ( cos(0.5) * 4.0 + 6.0 * sin(0.5) ) / 2.0;\n        //\n        ok  &= NearEqual(y1[0] , y_1_0, eps, eps);\n        ok  &= NearEqual(y1[1] , y_1_1, eps, eps);\n        ok  &= NearEqual(y2[0] , y_2_0, eps, eps);\n        ok  &= NearEqual(y2[1] , y_2_1, eps, eps);\n        //\n        return ok;\n    }\n    // ---------------------------------------------------------------------\n    // CoshOp\n    bool cosh_op(void)\n    {   bool ok = true;\n        double eps = 10. * std::numeric_limits<double>::epsilon();\n        size_t j;\n\n\n        // domain space vector\n        size_t n = 1;\n        CPPAD_TESTVECTOR(AD<double>) ax(n);\n        ax[0] = 0.5;\n\n        // declare independent variables and starting recording\n        CppAD::Independent(ax);\n\n        // range space vector\n        size_t m = 1;\n        CPPAD_TESTVECTOR(AD<double>) ay(m);\n        ay[0] = cosh( ax[0] );\n\n        // create f: x -> y and stop tape recording\n        CppAD::ADFun<double> f(ax, ay);\n\n        // first order Taylor coefficients\n        size_t r = 2, ell;\n        CPPAD_TESTVECTOR(double) x1(r*n), y1;\n        for(ell = 0; ell < r; ell++)\n        {   for(j = 0; j < n; j++)\n                x1[ r * j + ell ] = double(j + ell + 1);\n        }\n        y1  = f.Forward(1, r, x1);\n        ok &= size_t( y1.size() ) == r*m;\n\n        // secondorder Taylor coefficients\n        CPPAD_TESTVECTOR(double) x2(r*n), y2;\n        for(ell = 0; ell < r; ell++)\n        {   for(j = 0; j < n; j++)\n                x2[ r * j + ell ] = double(j + ell + 2);\n        }\n        y2  = f.Forward(2, r, x2);\n        ok &= size_t( y2.size() ) == r*m;\n        //\n        // Y_0  (t)    = F[X_0(t)]\n        //             = cosh( 0.5 + 1t + 2t^2 )\n        // Y_0' (t)    = sinh( 0.5 + 1t + 2t^2) * (1 + 4t)\n        double y_1_0   = sinh(0.5);\n        double y_2_0   = ( sinh(0.5) * 4.0 + cosh(0.5) ) / 2.0;\n        //\n        // Y_1  (t)    = F[X_1(t)]\n        //             = cosh( 0.5 + 2t + 3t^2 )\n        // Y_1' (t)    = sinh( 0.5 + 2t + 3t^2) * (2 + 6t)\n        double y_1_1   = sinh(0.5) * 2.0;\n        double y_2_1   = ( sinh(0.5) * 6.0 + cosh(0.5) * 4.0 ) / 2.0;\n        //\n        ok  &= NearEqual(y1[0] , y_1_0, eps, eps);\n        ok  &= NearEqual(y1[1] , y_1_1, eps, eps);\n        ok  &= NearEqual(y2[0] , y_2_0, eps, eps);\n        ok  &= NearEqual(y2[1] , y_2_1, eps, eps);\n        //\n        return ok;\n    }\n    // ---------------------------------------------------------------------\n    // CExpOp\n    bool cexp_op(void)\n    {   bool ok = true;\n        double eps = 10. * std::numeric_limits<double>::epsilon();\n        size_t j;\n\n        // domain space vector\n        size_t n = 4;\n        CPPAD_TESTVECTOR(AD<double>) ax(n);\n        for(j = 0; j < n; j++)\n            ax[j] = double(j);\n\n        // declare independent variables and starting recording\n        CppAD::Independent(ax);\n\n        // range space vector\n        size_t m = 2;\n        CPPAD_TESTVECTOR(AD<double>) ay(m);\n        ay[0] = CondExpLt(ax[0], ax[1], ax[2], ax[3]);\n        ay[1] = CondExpGt(ax[0], ax[1], ax[2], ax[3]);\n\n        // create f: x -> y and stop tape recording\n        CppAD::ADFun<double> f(ax, ay);\n\n        // first order Taylor coefficients\n        size_t r = 2, ell;\n        CPPAD_TESTVECTOR(double) x1(r*n), y1;\n        for(ell = 0; ell < r; ell++)\n        {   for(j = 0; j < n; j++)\n                x1[ r * j + ell ] = double(j + ell + 1);\n        }\n        y1  = f.Forward(1, r, x1);\n        ok &= size_t( y1.size() ) == r*m;\n\n        // secondorder Taylor coefficients\n        CPPAD_TESTVECTOR(double) x2(r*n), y2;\n        for(ell = 0; ell < r; ell++)\n        {   for(j = 0; j < n; j++)\n                x2[ r * j + ell ] = double(j + ell + 2);\n        }\n        y2  = f.Forward(2, r, x2);\n        ok &= size_t( y2.size() ) == r*m;\n        //\n        // Y0_0 (t)     = X2_0(t)\n        //             =  2.0 + 3t + 4t^2\n        double y0_1_0  = 3.0;\n        double y0_2_0  = 4.0;\n        //\n        // Y1_0 (t)     = X3_0(t)\n        //             =  3.0 + 4t + 5t^2\n        double y1_1_0  = 4.0;\n        double y1_2_0  = 5.0;\n        //\n        // Y0_1 (t)     = X2_1(t)\n        //             =  2.0 + 4t + 5t^2\n        double y0_1_1  = 4.0;\n        double y0_2_1  = 5.0;\n        //\n        // Y1_1 (t)     = X3_0(t)\n        //             =  3.0 + 5t + 6t^2\n        double y1_1_1  = 5.0;\n        double y1_2_1  = 6.0;\n        //\n        ok  &= NearEqual(y1[0*r+0] , y0_1_0, eps, eps);\n        ok  &= NearEqual(y1[1*r+0] , y1_1_0, eps, eps);\n        ok  &= NearEqual(y1[0*r+1] , y0_1_1, eps, eps);\n        ok  &= NearEqual(y1[1*r+1] , y1_1_1, eps, eps);\n        //\n        ok  &= NearEqual(y2[0*r+0] , y0_2_0, eps, eps);\n        ok  &= NearEqual(y2[1*r+0] , y1_2_0, eps, eps);\n        ok  &= NearEqual(y2[0*r+1] , y0_2_1, eps, eps);\n        ok  &= NearEqual(y2[1*r+1] , y1_2_1, eps, eps);\n        //\n        return ok;\n    }\n\n    // ---------------------------------------------------------------------\n    // CSumOp\n    bool csum_op(void)\n    {   bool ok = true;\n        double eps = 10. * std::numeric_limits<double>::epsilon();\n        size_t j;\n\n        // domain space vector\n        size_t n = 3;\n        CPPAD_TESTVECTOR(AD<double>) ax(n);\n        for(j = 0; j < n; j++)\n            ax[j] = double(j);\n\n        // declare independent variables and starting recording\n        CppAD::Independent(ax);\n\n        // range space vector\n        size_t m = 1;\n        CPPAD_TESTVECTOR(AD<double>) ay(m);\n        ay[0] = 0.0;\n        for(j = 0; j < n; j++)\n            ay[0] += ax[j];\n\n        // create f: x -> y and stop tape recording\n        CppAD::ADFun<double> f(ax, ay);\n\n        // optimize the tape so converts summation to on CSumOp operator\n        f.optimize();\n\n        // zero order\n        CPPAD_TESTVECTOR(double) x0(n);\n        for(j = 0; j < n; j++)\n            x0[j] = double(j);\n        f.Forward(0, x0);\n\n        // first order Taylor coefficients\n        size_t r = 2, ell;\n        CPPAD_TESTVECTOR(double) x1(r*n), y1;\n        for(ell = 0; ell < r; ell++)\n        {   for(j = 0; j < n; j++)\n                x1[ r * j + ell ] = double(j + ell + 1);\n        }\n        y1  = f.Forward(1, r, x1);\n        ok &= size_t( y1.size() ) == r*m;\n\n        // secondorder Taylor coefficients\n        CPPAD_TESTVECTOR(double) x2(r*n), y2;\n        for(ell = 0; ell < r; ell++)\n        {   for(j = 0; j < n; j++)\n                x2[ r * j + ell ] = double(j + ell + 3);\n        }\n        y2  = f.Forward(2, r, x2);\n        ok &= size_t( y2.size() ) == r*m;\n        //\n        double check = 0.0;\n        for(j = 0; j < n; j++)\n            check += x1[ r * j + 0];\n        ok  &= NearEqual(y1[0] , check, eps, eps);\n        //\n        check = 0.0;\n        for(j = 0; j < n; j++)\n            check += x1[ r * j + 1];\n        ok  &= NearEqual(y1[1] , check, eps, eps);\n        //\n        check = 0.0;\n        for(j = 0; j < n; j++)\n            check += x2[ r * j + 0];\n        ok  &= NearEqual(y2[0] , check, eps, eps);\n        //\n        check = 0.0;\n        for(j = 0; j < n; j++)\n            check += x2[ r * j + 1];\n        ok  &= NearEqual(y2[1] , check, eps, eps);\n        //\n        return ok;\n    }\n    // ---------------------------------------------------------------------\n    // DisOp (test assuming that AddvvOp is correct)\n    double round_off(const double& x)\n    {   // std::round(x); is C++11, so we avoid using it\n        return std::floor( x + 0.5 );\n    }\n    CPPAD_DISCRETE_FUNCTION(double, round_off)\n    bool dis_op(void)\n    {   bool ok = true;\n        double eps = 10. * std::numeric_limits<double>::epsilon();\n        size_t j;\n\n        // domain space vector\n        size_t n = 1;\n        CPPAD_TESTVECTOR(AD<double>) ax(n);\n        ax[0] = 0.5;\n\n        // declare independent variables and starting recording\n        CppAD::Independent(ax);\n\n        // range space vector\n        size_t m = 1;\n        CPPAD_TESTVECTOR(AD<double>) ay(m);\n        ay[0] = round_off( ax[0] ) + ax[0];\n\n        // create f: x -> y and stop tape recording\n        CppAD::ADFun<double> f(ax, ay);\n\n        // zero order\n        CPPAD_TESTVECTOR(double) x0(n), y0;\n        x0[0] = 2.2;\n        y0  = f.Forward(0, x0);\n        ok &= size_t( y0.size() ) == m;\n        ok &= NearEqual(y0[0], round_off(x0[0]) + x0[0], eps, eps);\n\n        // first order Taylor coefficients\n        size_t r = 2, ell;\n        CPPAD_TESTVECTOR(double) x1(r*n), y1;\n        for(ell = 0; ell < r; ell++)\n        {   for(j = 0; j < n; j++)\n                x1[ r * j + ell ] = double(j + ell + 1);\n        }\n        y1  = f.Forward(1, r, x1);\n        ok &= size_t( y1.size() ) == r*m;\n\n        // secondorder Taylor coefficients\n        CPPAD_TESTVECTOR(double) x2(r*n), y2;\n        for(ell = 0; ell < r; ell++)\n        {   for(j = 0; j < n; j++)\n                x2[ r * j + ell ] = double(j + ell + 2);\n        }\n        y2  = f.Forward(2, r, x2);\n        ok &= size_t( y2.size() ) == r*m;\n        //\n        //\n        // Y_0 (t)     = F[X_0(t)]\n        //             =  2.0 + (2.2 + 1t + 2t^2)\n        double y_1_0   = 1.0;\n        double y_2_0   = 2.0;\n        //\n        // Y_1 (t)     = F[X_1(t)]\n        //             =  2.0 + (2.2 + 2t + 3t^2)\n        double y_1_1   = 2.0;\n        double y_2_1   = 3.0;\n        //\n        ok  &= NearEqual(y1[0] , y_1_0, eps, eps);\n        ok  &= NearEqual(y1[1] , y_1_1, eps, eps);\n        ok  &= NearEqual(y2[0] , y_2_0, eps, eps);\n        ok  &= NearEqual(y2[1] , y_2_1, eps, eps);\n        //\n        return ok;\n    }\n    // ---------------------------------------------------------------------\n    // DivpvOp (testing assumping MulpvOp is correct)\n    bool divpv_op(void)\n    {   bool ok = true;\n        double eps = 10. * std::numeric_limits<double>::epsilon();\n        size_t j;\n\n        // domain space vector\n        size_t n = 1;\n        CPPAD_TESTVECTOR(AD<double>) ax(n);\n        ax[0] = 0.5;\n\n        // declare independent variables and starting recording\n        CppAD::Independent(ax);\n\n        // range space vector\n        size_t m = 1;\n        CPPAD_TESTVECTOR(AD<double>) ay(m);\n        ay[0] = (2.0 / ax[0]) * (ax[0] * ax[0]);\n\n        // create f: x -> y and stop tape recording\n        CppAD::ADFun<double> f(ax, ay);\n\n        // first order Taylor coefficients\n        size_t r = 2, ell;\n        CPPAD_TESTVECTOR(double) x1(r*n), y1;\n        for(ell = 0; ell < r; ell++)\n        {   for(j = 0; j < n; j++)\n                x1[ r * j + ell ] = double(j + ell + 1);\n        }\n        y1  = f.Forward(1, r, x1);\n        ok &= size_t( y1.size() ) == r*m;\n\n        // secondorder Taylor coefficients\n        CPPAD_TESTVECTOR(double) x2(r*n), y2;\n        for(ell = 0; ell < r; ell++)\n        {   for(j = 0; j < n; j++)\n                x2[ r * j + ell ] = double(j + ell + 2);\n        }\n        y2  = f.Forward(2, r, x2);\n        ok &= size_t( y2.size() ) == r*m;\n        //\n        // Y_0 (t)     = F[X_0(t)]\n        //             = 2.0 * (0.5 + 1t + 2t^2)\n        double y_1_0   = 2.0;\n        double y_2_0   = 4.0;\n        //\n        // Y_1 (t)     = F[X_1(t)]\n        //             = 2.0 * (0.5 + 2t + 3t^2)/2.0\n        double y_1_1   = 4.0;\n        double y_2_1   = 6.0;\n        //\n        ok  &= NearEqual(y1[0] , y_1_0, eps, eps);\n        ok  &= NearEqual(y1[1] , y_1_1, eps, eps);\n        ok  &= NearEqual(y2[0] , y_2_0, eps, eps);\n        ok  &= NearEqual(y2[1] , y_2_1, eps, eps);\n        //\n        return ok;\n    }\n    // ---------------------------------------------------------------------\n    // DivvpOp\n    bool divvp_op(void)\n    {   bool ok = true;\n        double eps = 10. * std::numeric_limits<double>::epsilon();\n        size_t j;\n\n        // domain space vector\n        size_t n = 1;\n        CPPAD_TESTVECTOR(AD<double>) ax(n);\n        ax[0] = 0.5;\n\n        // declare independent variables and starting recording\n        CppAD::Independent(ax);\n\n        // range space vector\n        size_t m = 1;\n        CPPAD_TESTVECTOR(AD<double>) ay(m);\n        ay[0] = ax[0] / 2.0;\n\n        // create f: x -> y and stop tape recording\n        CppAD::ADFun<double> f(ax, ay);\n\n        // first order Taylor coefficients\n        size_t r = 2, ell;\n        CPPAD_TESTVECTOR(double) x1(r*n), y1;\n        for(ell = 0; ell < r; ell++)\n        {   for(j = 0; j < n; j++)\n                x1[ r * j + ell ] = double(j + ell + 1);\n        }\n        y1  = f.Forward(1, r, x1);\n        ok &= size_t( y1.size() ) == r*m;\n\n        // secondorder Taylor coefficients\n        CPPAD_TESTVECTOR(double) x2(r*n), y2;\n        for(ell = 0; ell < r; ell++)\n        {   for(j = 0; j < n; j++)\n                x2[ r * j + ell ] = double(j + ell + 3);\n        }\n        y2  = f.Forward(2, r, x2);\n        ok &= size_t( y2.size() ) == r*m;\n        //\n        // Y_0 (t)     = F[X_0(t)]\n        //             =  (0.5 + 1t + 3t^2)/2.0\n        double y_1_0   = 1.0 / 2.0;\n        double y_2_0   = 3.0 / 2.0;\n        //\n        // Y_1 (t)     = F[X_1(t)]\n        //             =  (0.5 + 2t + 4t^2)/2.0\n        double y_1_1   = 2.0 / 2.0;\n        double y_2_1   = 4.0 / 2.0;\n        //\n        ok  &= NearEqual(y1[0] , y_1_0, eps, eps);\n        ok  &= NearEqual(y1[1] , y_1_1, eps, eps);\n        ok  &= NearEqual(y2[0] , y_2_0, eps, eps);\n        ok  &= NearEqual(y2[1] , y_2_1, eps, eps);\n        //\n        return ok;\n    }\n    // ---------------------------------------------------------------------\n    // ExpOp\n    bool exp_op(void)\n    {   bool ok = true;\n        double eps = 10. * std::numeric_limits<double>::epsilon();\n        size_t j;\n\n        // domain space vector\n        size_t n = 1;\n        CPPAD_TESTVECTOR(AD<double>) ax(n);\n        ax[0] = 0.5;\n\n        // declare independent variables and starting recording\n        CppAD::Independent(ax);\n\n        // range space vector\n        size_t m = 1;\n        CPPAD_TESTVECTOR(AD<double>) ay(m);\n        ay[0] = exp( ax[0] );\n\n        // create f: x -> y and stop tape recording\n        CppAD::ADFun<double> f(ax, ay);\n\n        // first order Taylor coefficients\n        size_t r = 2, ell;\n        CPPAD_TESTVECTOR(double) x1(r*n), y1;\n        for(ell = 0; ell < r; ell++)\n        {   for(j = 0; j < n; j++)\n                x1[ r * j + ell ] = double(j + ell + 1);\n        }\n        y1  = f.Forward(1, r, x1);\n        ok &= size_t( y1.size() ) == r*m;\n\n        // secondorder Taylor coefficients\n        CPPAD_TESTVECTOR(double) x2(r*n), y2;\n        for(ell = 0; ell < r; ell++)\n        {   for(j = 0; j < n; j++)\n                x2[ r * j + ell ] = double(j + ell + 2);\n        }\n        y2  = f.Forward(2, r, x2);\n        ok &= size_t( y2.size() ) == r*m;\n        //\n        // Y_0  (t)    = F[X_0(t)]\n        //             =  exp(0.5 + 1t + 2t^2)\n        // Y_0' (t)    =  exp(0.5 + 1t + 2t^2)*(1 + 4t)\n        double y_1_0   = exp(0.5);\n        double y_2_0   = ( exp(0.5)*4.0 + exp(0.5) ) / 2.0;\n        //\n        // Y_1  (t)    = F[X_1(t)]\n        //             =  exp(0.5 + 2t + 3t^2)\n        // Y_1' (t)    =  exp(0.5 + 2t + 3t^2)*(2 + 6t)\n        double y_1_1   = exp(0.5)*2.0;\n        double y_2_1   = ( exp(0.5)*6.0 + exp(0.5)*2.0*2.0 ) / 2.0;\n        //\n        ok  &= NearEqual(y1[0] , y_1_0, eps, eps);\n        ok  &= NearEqual(y1[1] , y_1_1, eps, eps);\n        ok  &= NearEqual(y2[0] , y_2_0, eps, eps);\n        ok  &= NearEqual(y2[1] , y_2_1, eps, eps);\n        //\n        return ok;\n    }\n    // ---------------------------------------------------------------------\n    // LdpOp and LdvOp (test assuming AdvvOp is correct)\n    bool load_op(void)\n    {   bool ok = true;\n        double eps = 10. * std::numeric_limits<double>::epsilon();\n        size_t j;\n\n        // domain space vector\n        size_t n = 2;\n        CPPAD_TESTVECTOR(AD<double>) ax(n);\n        ax[0] = 0.0;\n        ax[1] = 1.0;\n\n        // declare independent variables and starting recording\n        CppAD::Independent(ax);\n\n        // Store operations\n        CppAD::VecAD<double> avec(3);\n        avec[ AD<double>(0) ]    = ax[0];  // store a variable\n        avec[ AD<double>(1) ]    = ax[1];  // store a variable\n        avec[ AD<double>(2) ]    = 5.0;    // store a parameter\n\n        // range space vector\n        size_t m = 2;\n        CPPAD_TESTVECTOR(AD<double>) ay(m);\n        ay[0] = avec[ AD<double>(0) ];     // load using parameter index\n        ay[1] = avec[ ax[0] ];             // load using variable index\n\n        // create f: x -> y and stop tape recording\n        CppAD::ADFun<double> f(ax, ay);\n\n        // zero order Taylor coefficients\n        CPPAD_TESTVECTOR(double) x0(n), y0;\n        x0[0] = 2;\n        x0[1] = 3;\n        y0  = f.Forward(0, x0);\n        ok &= size_t( y0.size() ) == m;\n        // y[0] = avec[0] = x[0]\n        ok &= y0[0] == x0[0];\n        // y[1] = avec[ x[0] ] = avec[2] = 5.0\n        ok &= y0[1] == 5.0;\n\n        // first order Taylor coefficients\n        size_t r = 2, ell;\n        CPPAD_TESTVECTOR(double) x1(r*n), y1;\n        for(ell = 0; ell < r; ell++)\n        {   for(j = 0; j < n; j++)\n                x1[ r * j + ell ] = double(j + ell + 1);\n        }\n        y1  = f.Forward(1, r, x1);\n        ok &= size_t( y1.size() ) == r*m;\n\n        // secondorder Taylor coefficients\n        CPPAD_TESTVECTOR(double) x2(r*n), y2;\n        for(ell = 0; ell < r; ell++)\n        {   for(j = 0; j < n; j++)\n                x2[ r * j + ell ] = double(j + ell + 2);\n        }\n        y2  = f.Forward(2, r, x2);\n        ok &= size_t( y2.size() ) == r*m;\n        //\n        // Y0_0 (t)    = 2.0 + 1t + 2t^2\n        double y0_1_0  = 1.0;\n        double y0_2_0  = 2.0;\n        //\n        // Y1_0 (t)    = 5.0\n        double y1_1_0  = 0.0;\n        double y1_2_0  = 0.0;\n        //\n        // Y0_1 (t)    = 2.0 + 2t + 3t^2\n        double y0_1_1  = 2.0;\n        double y0_2_1  = 3.0;\n        //\n        // Y1_1 (t)    = 5.0\n        double y1_1_1  = 0.0;\n        double y1_2_1  = 0.0;\n        //\n        ok  &= NearEqual(y1[0*r+0] , y0_1_0, eps, eps);\n        ok  &= NearEqual(y1[1*r+0] , y1_1_0, eps, eps);\n        ok  &= NearEqual(y1[0*r+1] , y0_1_1, eps, eps);\n        ok  &= NearEqual(y1[1*r+1] , y1_1_1, eps, eps);\n        //\n        ok  &= NearEqual(y2[0*r+0] , y0_2_0, eps, eps);\n        ok  &= NearEqual(y2[1*r+0] , y1_2_0, eps, eps);\n        ok  &= NearEqual(y2[0*r+1] , y0_2_1, eps, eps);\n        ok  &= NearEqual(y2[1*r+1] , y1_2_1, eps, eps);\n        //\n        return ok;\n    }\n\n    // ---------------------------------------------------------------------\n    // MulpvOp\n    bool mulpv_op(void)\n    {   bool ok = true;\n        double eps = 10. * std::numeric_limits<double>::epsilon();\n        size_t j;\n\n        // domain space vector\n        size_t n = 1;\n        CPPAD_TESTVECTOR(AD<double>) ax(n);\n        ax[0] = 0.5;\n\n        // declare independent variables and starting recording\n        CppAD::Independent(ax);\n\n        // range space vector\n        size_t m = 1;\n        CPPAD_TESTVECTOR(AD<double>) ay(m);\n        ay[0] = 2.0 * ax[0];\n\n        // create f: x -> y and stop tape recording\n        CppAD::ADFun<double> f(ax, ay);\n\n        // first order Taylor coefficients\n        size_t r = 2, ell;\n        CPPAD_TESTVECTOR(double) x1(r*n), y1;\n        for(ell = 0; ell < r; ell++)\n        {   for(j = 0; j < n; j++)\n                x1[ r * j + ell ] = double(j + ell + 1);\n        }\n        y1  = f.Forward(1, r, x1);\n        ok &= size_t( y1.size() ) == r*m;\n\n        // secondorder Taylor coefficients\n        CPPAD_TESTVECTOR(double) x2(r*n), y2;\n        for(ell = 0; ell < r; ell++)\n        {   for(j = 0; j < n; j++)\n                x2[ r * j + ell ] = double(j + ell + 3);\n        }\n        y2  = f.Forward(2, r, x2);\n        ok &= size_t( y2.size() ) == r*m;\n        //\n        // Y_0 (t)     = F[X_0(t)]\n        //             =  2.0 * (0.5 + 1t + 3t^2)\n        double y_1_0   = 2.0 * 1.0;\n        double y_2_0   = 2.0 * 3.0;\n        //\n        // Y_1 (t)     = F[X_1(t)]\n        //             =  2.0 * (0.5 + 2t + 4t^2)\n        double y_1_1   = 2.0 * 2.0;\n        double y_2_1   = 2.0 * 4.0;\n        //\n        ok  &= NearEqual(y1[0] , y_1_0, eps, eps);\n        ok  &= NearEqual(y1[1] , y_1_1, eps, eps);\n        ok  &= NearEqual(y2[0] , y_2_0, eps, eps);\n        ok  &= NearEqual(y2[1] , y_2_1, eps, eps);\n        //\n        return ok;\n    }\n    // ---------------------------------------------------------------------\n    // ParOp\n    bool par_op(void)\n    {   bool ok = true;\n        size_t j;\n\n        // domain space vector\n        size_t n = 1;\n        CPPAD_TESTVECTOR(AD<double>) ax(n);\n        ax[0] = 0.5;\n\n        // declare independent variables and starting recording\n        CppAD::Independent(ax);\n\n        // range space vector\n        size_t m = 1;\n        CPPAD_TESTVECTOR(AD<double>) ay(m);\n        ay[0] = 0.0 * ax[0];\n\n        // create f: x -> y and stop tape recording\n        CppAD::ADFun<double> f(ax, ay);\n\n        // first order Taylor coefficients\n        size_t r = 2, ell;\n        CPPAD_TESTVECTOR(double) x1(r*n), y1;\n        for(ell = 0; ell < r; ell++)\n        {   for(j = 0; j < n; j++)\n                x1[ r * j + ell ] = double(j + ell + 1);\n        }\n        y1  = f.Forward(1, r, x1);\n        ok &= size_t( y1.size() ) == r*m;\n\n        // secondorder Taylor coefficients\n        CPPAD_TESTVECTOR(double) x2(r*n), y2;\n        for(ell = 0; ell < r; ell++)\n        {   for(j = 0; j < n; j++)\n                x2[ r * j + ell ] = double(j + ell + 2);\n        }\n        y2  = f.Forward(2, r, x2);\n        ok &= size_t( y2.size() ) == r*m;\n        //\n        // Y_0  (t)    = 0.0\n        for(ell = 0; ell < r; ell++)\n        {   ok &= y1[ell] == 0.0;\n            ok &= y2[ell] == 0.0;\n        }\n        return ok;\n    }\n    // ---------------------------------------------------------------------\n    // PowvvOp  (test assuming LogOp, ExpOp and DivvvOp are correct)\n    bool powvv_op(void)\n    {   bool ok = true;\n        double eps = 10. * std::numeric_limits<double>::epsilon();\n        size_t j;\n\n        // domain space vector\n        size_t n = 2;\n        CPPAD_TESTVECTOR(AD<double>) ax(n);\n        ax[0] = 0.5;\n        ax[1] = 2.0;\n\n        // declare independent variables and starting recording\n        CppAD::Independent(ax);\n\n        // range space vector\n        size_t m = 2;\n        CPPAD_TESTVECTOR(AD<double>) ay(m);\n        ay[0] = log( pow( exp(ax[0]) , ax[1] ) ) / ax[1] ;\n        ay[1] = log( pow( exp(ax[0]) , ax[1] ) ) / ax[0] ;\n\n        // create f: x -> y and stop tape recording\n        CppAD::ADFun<double> f(ax, ay);\n\n        // first order Taylor coefficients\n        size_t r = 2, ell;\n        CPPAD_TESTVECTOR(double) x1(r*n), y1;\n        for(ell = 0; ell < r; ell++)\n        {   for(j = 0; j < n; j++)\n                x1[ r * j + ell ] = double(j + ell + 1);\n        }\n        y1  = f.Forward(1, r, x1);\n        ok &= size_t( y1.size() ) == r*m;\n\n        // secondorder Taylor coefficients\n        CPPAD_TESTVECTOR(double) x2(r*n), y2;\n        for(ell = 0; ell < r; ell++)\n        {   for(j = 0; j < n; j++)\n                x2[ r * j + ell ] = double(j + ell + 2);\n        }\n        y2  = f.Forward(2, r, x2);\n        ok &= size_t( y2.size() ) == r*m;\n        //\n        // Y0_0 (t)    = 0.5 + 1t + 2t^2\n        double y0_1_0  = 1.0;\n        double y0_2_0  = 2.0;\n        //\n        // Y0_1 (t)    = 0.5 + 2t + 3t^2\n        double y0_1_1  = 2.0;\n        double y0_2_1  = 3.0;\n        //\n        // Y1_0 (t)    = 2.0 + 2t + 3t^2\n        double y1_1_0  = 2.0;\n        double y1_2_0  = 3.0;\n        //\n        // Y1_1 (t)    = 2.0 + 3t + 4t^2\n        double y1_1_1  = 3.0;\n        double y1_2_1  = 4.0;\n        //\n        ok  &= NearEqual(y1[0*r+0] , y0_1_0, eps, eps);\n        ok  &= NearEqual(y1[1*r+0] , y1_1_0, eps, eps);\n        ok  &= NearEqual(y1[0*r+1] , y0_1_1, eps, eps);\n        ok  &= NearEqual(y1[1*r+1] , y1_1_1, eps, eps);\n        //\n        ok  &= NearEqual(y2[0*r+0] , y0_2_0, eps, eps);\n        ok  &= NearEqual(y2[1*r+0] , y1_2_0, eps, eps);\n        ok  &= NearEqual(y2[0*r+1] , y0_2_1, eps, eps);\n        ok  &= NearEqual(y2[1*r+1] , y1_2_1, eps, eps);\n        //\n        return ok;\n    }\n    // ---------------------------------------------------------------------\n    // SignOp (test assuming that MulvvOp is correct)\n    bool sign_op(void)\n    {   bool ok = true;\n        double eps = 10. * std::numeric_limits<double>::epsilon();\n        size_t j;\n\n        // domain space vector\n        size_t n = 1;\n        CPPAD_TESTVECTOR(AD<double>) ax(n);\n        ax[0] = 0.5;\n\n        // declare independent variables and starting recording\n        CppAD::Independent(ax);\n\n        // range space vector\n        size_t m = 1;\n        CPPAD_TESTVECTOR(AD<double>) ay(m);\n        ay[0] = sign( ax[0] ) * ax[0];\n\n        // create f: x -> y and stop tape recording\n        CppAD::ADFun<double> f(ax, ay);\n\n        // zero order\n        CPPAD_TESTVECTOR(double) x0(n), y0;\n        x0[0] = -3.0;\n        y0  = f.Forward(0, x0);\n        ok &= size_t( y0.size() ) == m;\n        ok &= NearEqual(y0[0], fabs(x0[0]), eps, eps);\n\n        // first order Taylor coefficients\n        size_t r = 2, ell;\n        CPPAD_TESTVECTOR(double) x1(r*n), y1;\n        for(ell = 0; ell < r; ell++)\n        {   for(j = 0; j < n; j++)\n                x1[ r * j + ell ] = double(j + ell + 1);\n        }\n        y1  = f.Forward(1, r, x1);\n        ok &= size_t( y1.size() ) == r*m;\n\n        // secondorder Taylor coefficients\n        CPPAD_TESTVECTOR(double) x2(r*n), y2;\n        for(ell = 0; ell < r; ell++)\n        {   for(j = 0; j < n; j++)\n                x2[ r * j + ell ] = double(j + ell + 2);\n        }\n        y2  = f.Forward(2, r, x2);\n        ok &= size_t( y2.size() ) == r*m;\n        //\n        //\n        // Y_0 (t)     = F[X_0(t)]\n        //             =  -(-3.0 + 1t + 2t^2)\n        double y_1_0   = -1.0;\n        double y_2_0   = -2.0;\n        //\n        // Y_1 (t)     = F[X_1(t)]\n        //             =  -(-3.0 + 2t + 3t^2)\n        double y_1_1   = -2.0;\n        double y_2_1   = -3.0;\n        //\n        ok  &= NearEqual(y1[0] , y_1_0, eps, eps);\n        ok  &= NearEqual(y1[1] , y_1_1, eps, eps);\n        ok  &= NearEqual(y2[0] , y_2_0, eps, eps);\n        ok  &= NearEqual(y2[1] , y_2_1, eps, eps);\n        //\n        return ok;\n    }\n\n    // ---------------------------------------------------------------------\n    // SinOp\n    bool sin_op(void)\n    {   bool ok = true;\n        double eps = 10. * std::numeric_limits<double>::epsilon();\n        size_t j;\n\n\n        // domain space vector\n        size_t n = 1;\n        CPPAD_TESTVECTOR(AD<double>) ax(n);\n        ax[0] = 0.5;\n\n        // declare independent variables and starting recording\n        CppAD::Independent(ax);\n\n        // range space vector\n        size_t m = 1;\n        CPPAD_TESTVECTOR(AD<double>) ay(m);\n        ay[0] = sin( ax[0] );\n\n        // create f: x -> y and stop tape recording\n        CppAD::ADFun<double> f(ax, ay);\n\n        // first order Taylor coefficients\n        size_t r = 2, ell;\n        CPPAD_TESTVECTOR(double) x1(r*n), y1;\n        for(ell = 0; ell < r; ell++)\n        {   for(j = 0; j < n; j++)\n                x1[ r * j + ell ] = double(j + ell + 1);\n        }\n        y1  = f.Forward(1, r, x1);\n        ok &= size_t( y1.size() ) == r*m;\n\n        // secondorder Taylor coefficients\n        CPPAD_TESTVECTOR(double) x2(r*n), y2;\n        for(ell = 0; ell < r; ell++)\n        {   for(j = 0; j < n; j++)\n                x2[ r * j + ell ] = double(j + ell + 2);\n        }\n        y2  = f.Forward(2, r, x2);\n        ok &= size_t( y2.size() ) == r*m;\n        //\n        // Y_0  (t)    = F[X_0(t)]\n        //             = sin( 0.5 + 1t + 2t^2 )\n        // Y_0' (t)    = cos( 0.5 + 1t + 2t^2) * (1 + 4t)\n        double y_1_0   = cos(0.5);\n        double y_2_0   = ( cos(0.5) * 4.0 - sin(0.5) ) / 2.0;\n        //\n        // Y_1  (t)    = F[X_1(t)]\n        //             = sin( 0.5 + 2t + 3t^2 )\n        // Y_1' (t)    = cos( 0.5 + 2t + 3t^2) * (2 + 6t)\n        double y_1_1   = cos(0.5) * 2.0;\n        double y_2_1   = ( cos(0.5) * 6.0 - sin(0.5) * 4.0 ) / 2.0;\n        //\n        ok  &= NearEqual(y1[0] , y_1_0, eps, eps);\n        ok  &= NearEqual(y1[1] , y_1_1, eps, eps);\n        ok  &= NearEqual(y2[0] , y_2_0, eps, eps);\n        ok  &= NearEqual(y2[1] , y_2_1, eps, eps);\n        //\n        return ok;\n    }\n    // ---------------------------------------------------------------------\n    // SinhOp\n    bool sinh_op(void)\n    {   bool ok = true;\n        double eps = 10. * std::numeric_limits<double>::epsilon();\n        size_t j;\n\n\n        // domain space vector\n        size_t n = 1;\n        CPPAD_TESTVECTOR(AD<double>) ax(n);\n        ax[0] = 0.5;\n\n        // declare independent variables and starting recording\n        CppAD::Independent(ax);\n\n        // range space vector\n        size_t m = 1;\n        CPPAD_TESTVECTOR(AD<double>) ay(m);\n        ay[0] = sinh( ax[0] );\n\n        // create f: x -> y and stop tape recording\n        CppAD::ADFun<double> f(ax, ay);\n\n        // first order Taylor coefficients\n        size_t r = 2, ell;\n        CPPAD_TESTVECTOR(double) x1(r*n), y1;\n        for(ell = 0; ell < r; ell++)\n        {   for(j = 0; j < n; j++)\n                x1[ r * j + ell ] = double(j + ell + 1);\n        }\n        y1  = f.Forward(1, r, x1);\n        ok &= size_t( y1.size() ) == r*m;\n\n        // secondorder Taylor coefficients\n        CPPAD_TESTVECTOR(double) x2(r*n), y2;\n        for(ell = 0; ell < r; ell++)\n        {   for(j = 0; j < n; j++)\n                x2[ r * j + ell ] = double(j + ell + 2);\n        }\n        y2  = f.Forward(2, r, x2);\n        ok &= size_t( y2.size() ) == r*m;\n        //\n        // Y_0  (t)    = F[X_0(t)]\n        //             = sinh( 0.5 + 1t + 2t^2 )\n        // Y_0' (t)    = cosh( 0.5 + 1t + 2t^2) * (1 + 4t)\n        double y_1_0   = cosh(0.5);\n        double y_2_0   = ( cosh(0.5) * 4.0 + sinh(0.5) ) / 2.0;\n        //\n        // Y_1  (t)    = F[X_1(t)]\n        //             = sinh( 0.5 + 2t + 3t^2 )\n        // Y_1' (t)    = cosh( 0.5 + 2t + 3t^2) * (2 + 6t)\n        double y_1_1   = cosh(0.5) * 2.0;\n        double y_2_1   = ( cosh(0.5) * 6.0 + sinh(0.5) * 4.0 ) / 2.0;\n        //\n        ok  &= NearEqual(y1[0] , y_1_0, eps, eps);\n        ok  &= NearEqual(y1[1] , y_1_1, eps, eps);\n        ok  &= NearEqual(y2[0] , y_2_0, eps, eps);\n        ok  &= NearEqual(y2[1] , y_2_1, eps, eps);\n        //\n        return ok;\n    }\n    // ---------------------------------------------------------------------\n    // SubpvOp\n    bool subpv_op(void)\n    {   bool ok = true;\n        double eps = 10. * std::numeric_limits<double>::epsilon();\n        size_t j;\n\n        // domain space vector\n        size_t n = 1;\n        CPPAD_TESTVECTOR(AD<double>) ax(n);\n        ax[0] = 0.5;\n\n        // declare independent variables and starting recording\n        CppAD::Independent(ax);\n\n        // range space vector\n        size_t m = 1;\n        CPPAD_TESTVECTOR(AD<double>) ay(m);\n        ay[0] = 2.0 - ax[0];\n\n        // create f: x -> y and stop tape recording\n        CppAD::ADFun<double> f(ax, ay);\n\n        // first order Taylor coefficients\n        size_t r = 2, ell;\n        CPPAD_TESTVECTOR(double) x1(r*n), y1;\n        for(ell = 0; ell < r; ell++)\n        {   for(j = 0; j < n; j++)\n                x1[ r * j + ell ] = double(j + ell + 1);\n        }\n        y1  = f.Forward(1, r, x1);\n        ok &= size_t( y1.size() ) == r*m;\n\n        // secondorder Taylor coefficients\n        CPPAD_TESTVECTOR(double) x2(r*n), y2;\n        for(ell = 0; ell < r; ell++)\n        {   for(j = 0; j < n; j++)\n                x2[ r * j + ell ] = double(j + ell + 3);\n        }\n        y2  = f.Forward(2, r, x2);\n        ok &= size_t( y2.size() ) == r*m;\n        //\n        // Y_0 (t)     = F[X_0(t)]\n        //             =  2.0 - (0.5 + 1t + 3t^2)/2.0\n        double y_1_0   = - 1.0;\n        double y_2_0   = - 3.0;\n        //\n        // Y_1 (t)     = F[X_1(t)]\n        //             =  3.0 - (0.5 + 2t + 4t^2)/2.0\n        double y_1_1   = - 2.0;\n        double y_2_1   = - 4.0;\n        //\n        ok  &= NearEqual(y1[0] , y_1_0, eps, eps);\n        ok  &= NearEqual(y1[1] , y_1_1, eps, eps);\n        ok  &= NearEqual(y2[0] , y_2_0, eps, eps);\n        ok  &= NearEqual(y2[1] , y_2_1, eps, eps);\n        //\n        return ok;\n    }\n    // ---------------------------------------------------------------------\n    // SubvvOp\n    bool subvv_op(void)\n    {   bool ok = true;\n        double eps = 10. * std::numeric_limits<double>::epsilon();\n        size_t j;\n\n        // domain space vector\n        size_t n = 2;\n        CPPAD_TESTVECTOR(AD<double>) ax(n);\n        ax[0] = 0.5;\n        ax[1] = 2.0;\n\n        // declare independent variables and starting recording\n        CppAD::Independent(ax);\n\n        // range space vector\n        size_t m = 1;\n        CPPAD_TESTVECTOR(AD<double>) ay(m);\n        ay[0] = ax[0] - 2.0 * ax[1];\n\n        // create f: x -> y and stop tape recording\n        CppAD::ADFun<double> f(ax, ay);\n\n        // first order Taylor coefficients\n        size_t r = 2, ell;\n        CPPAD_TESTVECTOR(double) x1(r*n), y1;\n        for(ell = 0; ell < r; ell++)\n        {   for(j = 0; j < n; j++)\n                x1[ r * j + ell ] = double(j + ell + 1);\n        }\n        y1  = f.Forward(1, r, x1);\n        ok &= size_t( y1.size() ) == r*m;\n\n        // secondorder Taylor coefficients\n        CPPAD_TESTVECTOR(double) x2(r*n), y2;\n        for(ell = 0; ell < r; ell++)\n        {   for(j = 0; j < n; j++)\n                x2[ r * j + ell ] = double(j + ell + 2);\n        }\n        y2  = f.Forward(2, r, x2);\n        ok &= size_t( y2.size() ) == r*m;\n        //\n        // Y_0 (t)     = F[X_0(t)]\n        //             =  (0.5 + 1t + 2t^2) - 2.0 * (2.0 + 2t + 3t^2)\n        double y_1_0   = 1.0 - 4.0;\n        double y_2_0   = 2.0 - 6.0;\n        //\n        // Y_1 (t)     = F[X_1(t)]\n        //             =  (2.0 + 2t + 3t^2) - 2.0 * (2.0 + 3t + 4t^2)\n        double y_1_1   = 2.0 - 6.0;\n        double y_2_1   = 3.0 - 8.0;\n        //\n        ok  &= NearEqual(y1[0] , y_1_0, eps, eps);\n        ok  &= NearEqual(y1[1] , y_1_1, eps, eps);\n        ok  &= NearEqual(y2[0] , y_2_0, eps, eps);\n        ok  &= NearEqual(y2[1] , y_2_1, eps, eps);\n        //\n        return ok;\n    }\n    // ---------------------------------------------------------------------\n    // TanOp\n    bool tan_op(void)\n    {   bool ok = true;\n        double eps = 10. * std::numeric_limits<double>::epsilon();\n        size_t j;\n\n        // domain space vector\n        size_t n = 1;\n        CPPAD_TESTVECTOR(AD<double>) ax(n);\n        ax[0] = 0.5;\n\n        // declare independent variables and starting recording\n        CppAD::Independent(ax);\n\n        // range space vector\n        size_t m = 1;\n        CPPAD_TESTVECTOR(AD<double>) ay(m);\n        ay[0] = tan( ax[0] );\n\n        // create f: x -> y and stop tape recording\n        CppAD::ADFun<double> f(ax, ay);\n\n        // first order Taylor coefficients\n        size_t r = 2, ell;\n        CPPAD_TESTVECTOR(double) x1(r*n), y1;\n        for(ell = 0; ell < r; ell++)\n        {   for(j = 0; j < n; j++)\n                x1[ r * j + ell ] = double(j + ell + 1);\n        }\n        y1  = f.Forward(1, r, x1);\n        ok &= size_t( y1.size() ) == r*m;\n\n        // secondorder Taylor coefficients\n        CPPAD_TESTVECTOR(double) x2(r*n), y2;\n        for(ell = 0; ell < r; ell++)\n        {   for(j = 0; j < n; j++)\n                x2[ r * j + ell ] = double(j + ell + 2);\n        }\n        y2  = f.Forward(2, r, x2);\n        ok &= size_t( y2.size() ) == r*m;\n        //\n        // Y_0  (t)    = F[X_0(t)]\n        //             =  tan(0.5 + 1t + 2t^2)\n        // Y_0' (t)    =  cos(0.5 + 1t + 2t^2)^(-2)*(1 + 4t)\n        // Y_0''(0)    = 2*cos(0.5)^(-3)*sin(0.5) + 4*cos(0.5)^(-2)\n        double sec_sq  = 1.0 / ( cos(0.5) * cos(0.5) );\n        double y_1_0   = sec_sq;\n        double y_2_0   = (2.0 * tan(0.5) + 4.0) * sec_sq / 2.0;\n        //\n        // Y_1  (t)    = F[X_1(t)]\n        //             = tan(0.5 + 2t + 3t^2)\n        // Y_1' (t)    = cos(0.5 + 2t + 3t^2)^(-2)*(2 + 6t)\n        // Y_1''(0)    = 2*cos(0.5)^(-3)*sin(0.5)*2*2 + 6*cos(0.5)^(-2)\n        double y_1_1   = 2.0 * sec_sq;\n        double y_2_1   = (8.0 * tan(0.5) + 6.0) * sec_sq / 2.0;\n        //\n        ok  &= NearEqual(y1[0] , y_1_0, eps, eps);\n        ok  &= NearEqual(y1[1] , y_1_1, eps, eps);\n        ok  &= NearEqual(y2[0] , y_2_0, eps, eps);\n        ok  &= NearEqual(y2[1] , y_2_1, eps, eps);\n        //\n        return ok;\n    }\n    // ---------------------------------------------------------------------\n    // Usr*Op\n    typedef CPPAD_TESTVECTOR(AD<double>) avector;\n    void usr_algo(const avector& x, avector& z)\n    {   z[0] = ( x[0] + x[1] ) / 2.0;\n        z[1] = x[0] * x[1];\n        z[2] = ( x[0] - x[1] ) / 2.0;\n        return;\n    }\n    bool usr_op(void)\n    {   bool ok = true;\n        double eps = 10. * std::numeric_limits<double>::epsilon();\n        size_t j;\n\n        // define checkpoint function\n        size_t n = 2;\n        avector ax(n), az(3);\n        ax[0] = 0.5;\n        ax[1] = 2.0;\n        CppAD::checkpoint<double> usr_check(\"usr_check\", usr_algo, ax, az);\n\n        // declare independent variables and starting recording\n        CppAD::Independent(ax);\n\n        // record checkpoint function\n        usr_check(ax, az);\n\n        // range space vector\n        size_t m = 2;\n        avector ay(m);\n        ay[0] = az[0] + az[2]; // = ax[0]\n        ay[1] = az[0] - az[2]; // = ax[1]\n\n        // create f: x -> y and stop tape recording\n        CppAD::ADFun<double> f(ax, ay);\n\n        // first order Taylor coefficients\n        size_t r = 2, ell;\n        CPPAD_TESTVECTOR(double) x1(r*n), y1;\n        for(ell = 0; ell < r; ell++)\n        {   for(j = 0; j < n; j++)\n                x1[ r * j + ell ] = double(j + ell + 1);\n        }\n        y1  = f.Forward(1, r, x1);\n        ok &= size_t( y1.size() ) == r*m;\n\n        // secondorder Taylor coefficients\n        CPPAD_TESTVECTOR(double) x2(r*n), y2;\n        for(ell = 0; ell < r; ell++)\n        {   for(j = 0; j < n; j++)\n                x2[ r * j + ell ] = double(j + ell + 2);\n        }\n        y2  = f.Forward(2, r, x2);\n        ok &= size_t( y2.size() ) == r*m;\n        //\n        // Y0_0 (t)    = 0.5 + 1t + 2t^2\n        double y0_1_0  = 1.0;\n        double y0_2_0  = 2.0;\n        //\n        // Y0_1 (t)    = 0.5 + 2t + 3t^2\n        double y0_1_1  = 2.0;\n        double y0_2_1  = 3.0;\n        //\n        // Y1_0 (t)    = 2.0 + 2t + 3t^2\n        double y1_1_0  = 2.0;\n        double y1_2_0  = 3.0;\n        //\n        // Y1_1 (t)    = 2.0 + 3t + 4t^2\n        double y1_1_1  = 3.0;\n        double y1_2_1  = 4.0;\n        //\n        ok  &= NearEqual(y1[0*r+0] , y0_1_0, eps, eps);\n        ok  &= NearEqual(y1[1*r+0] , y1_1_0, eps, eps);\n        ok  &= NearEqual(y1[0*r+1] , y0_1_1, eps, eps);\n        ok  &= NearEqual(y1[1*r+1] , y1_1_1, eps, eps);\n        //\n        ok  &= NearEqual(y2[0*r+0] , y0_2_0, eps, eps);\n        ok  &= NearEqual(y2[1*r+0] , y1_2_0, eps, eps);\n        ok  &= NearEqual(y2[0*r+1] , y0_2_1, eps, eps);\n        ok  &= NearEqual(y2[1*r+1] , y1_2_1, eps, eps);\n        //\n        return ok;\n    }\n    // ---------------------------------------------------------------------\n    // Inverse functions assume the following already tested:\n    // CosOp, SinOp, TanOp, ExpOp, MulvvOp, DivvpOp, AddpvOp\n    //\n    // AcosOp\n    AD<double> acos_fun(const AD<double>& x)\n    {   return acos( cos(x) ); }\n    bool acos_op(void)\n    {   return check_identity(acos_fun, 0.5); }\n    //\n    // AcoshOp\n    AD<double> acosh_fun(const AD<double>& x)\n    {   return acosh( cosh(x) ); }\n    bool acosh_op(void)\n    {   return check_identity(acosh_fun, 0.5); }\n    //\n    // AsinOp\n    AD<double> asin_fun(const AD<double>& x)\n    {   return asin( sin(x) ); }\n    bool asin_op(void)\n    {   return check_identity(asin_fun, 0.5); }\n    //\n    // AsinhOp\n    AD<double> asinh_fun(const AD<double>& x)\n    {   return asinh( sinh(x) ); }\n    bool asinh_op(void)\n    {   return check_identity(asinh_fun, 0.5); }\n    //\n    // AtanOp\n    AD<double> atan_fun(const AD<double>& x)\n    {   return atan( tan(x) ); }\n    bool atan_op(void)\n    {   return check_identity(atan_fun, 0.5); }\n    //\n    // AtanhOp\n    AD<double> atanh_fun(const AD<double>& x)\n    {   return atanh( tanh(x) ); }\n    bool atanh_op(void)\n    {   return check_identity(atanh_fun, 0.5); }\n    //\n    // LogOp\n    AD<double> log_fun(const AD<double>& x)\n    {   return log( exp(x) ); }\n    bool log_op(void)\n    {   return check_identity(log_fun, 0.5); }\n    //\n    // DivvvOp\n    AD<double> divvv_fun(const AD<double>& x)\n    {   return (x * x) / x; }\n    bool divvv_op(void)\n    {   return check_identity(divvv_fun, 0.5); }\n    //\n    // PowpvOp\n    AD<double> powpv_fun(const AD<double>& x )\n    {   return log( pow( exp(3.0) , x ) ) / 3.0; }\n    bool powpv_op(void)\n    {   return check_identity(powpv_fun, 0.5); }\n    //\n    // PowvpOp\n    AD<double> powvp_fun(const AD<double>& x )\n    {   return log( pow( exp(x) , 3.0 ) ) / 3.0; }\n    bool powvp_op(void)\n    {   return check_identity(powvp_fun, 0.5); }\n    //\n    // SqrtOp\n    AD<double> sqrt_fun(const AD<double>& x )\n    {   return sqrt( x * x ); }\n    bool sqrt_op(void)\n    {   return check_identity(sqrt_fun, 0.5); }\n    //\n    // SubvpOp\n    AD<double> subvp_fun(const AD<double>& x )\n    {   return 3.0 + ( x - 3.0 ); }\n    bool subvp_op(void)\n    {   return check_identity(subvp_fun, 0.5); }\n    //\n    // TanhOp\n    AD<double> tanh_fun(const AD<double>& x )\n    {   AD<double> z = tanh(x);\n        return log( (1.0 + z) / (1.0 - z) ) / 2.0;\n    }\n    bool tanh_op(void)\n    {   return check_identity(tanh_fun, 0.5); }\n}\n\nbool forward_dir(void)\n{   bool ok = true;\n    //\n    ok     &= abs_op();\n    ok     &= acos_op();\n    ok     &= acosh_op();\n    ok     &= asin_op();\n    ok     &= asinh_op();\n    ok     &= atan_op();\n    ok     &= atanh_op();\n    ok     &= addpv_op();\n    ok     &= addvv_op();\n    ok     &= cexp_op();\n    ok     &= cosh_op();\n    ok     &= cos_op();\n    ok     &= csum_op();\n    ok     &= dis_op();\n    ok     &= divpv_op();\n    ok     &= divvp_op();\n    ok     &= divvv_op();\n    ok     &= exp_op();\n    ok     &= load_op();\n    ok     &= log_op();\n    ok     &= mulpv_op();\n    ok     &= par_op();\n    ok     &= powpv_op();\n    ok     &= powvp_op();\n    ok     &= powvv_op();\n    ok     &= sign_op();\n    ok     &= sin_op();\n    ok     &= sinh_op();\n    ok     &= subpv_op();\n    ok     &= subvp_op();\n    ok     &= subvv_op();\n    ok     &= sqrt_op();\n    ok     &= tan_op();\n    ok     &= tanh_op();\n    ok     &= usr_op();\n    //\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/forward_order.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nnamespace {\n\n    double my_discrete(const double& x)\n    {   return static_cast<int> ( x ); }\n    CPPAD_DISCRETE_FUNCTION(double, my_discrete)\n\n}\nbool forward_order(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    size_t j, k;\n    double eps = 10. * CppAD::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n = 23, m = n;\n    CPPAD_TESTVECTOR(AD<double>) X(n), Y(m);\n    for(j = 0; j < n; j++)\n        X[j] = 0.0;\n\n    // declare independent variables and starting recording\n    CppAD::Independent(X);\n\n    // identity function values\n    size_t i = 0;\n    size_t identity_begin = i;\n    Y[i] = cos( acos( X[i] ) );                   i++; // AcosOp,  CosOp\n    Y[i] = sin( asin( X[i] ) );                   i++; // AsinOp,  SinOp\n    Y[i] = tan( atan( X[i] ) );                   i++; // AtanOp,  TanOp\n    Y[i] = CondExpGt(X[i], X[i-1], X[i], X[i-2]); i++; // CExpOp\n    Y[i] = X[i-1] * X[i] / X[i-1];                i++; // DivvvOp, MulvvOp\n    Y[i] = X[i] * X[i] * 1.0 / X[i];              i++; // DivpvOp\n    Y[i] = 5.0 * X[i] / 5.0;                      i++; // DivvpOp, MulpvOp\n    Y[i] = exp( log( X[i] ) );                    i++; // ExpOp,   LogOp\n    Y[i] = pow( sqrt( X[i] ), 2.0);               i++; // PowvpOp, SqrtOp\n    Y[i] = log( pow( std::exp(1.), X[i] ) );      i++; // PowpvOp\n    Y[i] = log( pow( X[i], X[i] ) ) / log( X[i]); i++; // PowvvOp\n    Y[i] = -2. - ((X[i-1] - X[i]) - 2.) + X[i-1]; i++; // Sub*Op: pv, vv, vp\n    size_t identity_end = i;\n\n    // other functions\n    Y[i] = fabs( X[i] );        i++;   // AbsOp\n    Y[i] = X[i-1] + X[i] + 2.0; i++;   // AddvvOp, AddvpOp\n    Y[i] = cosh( X[i] );        i++;   // CoshOp\n    Y[i] = my_discrete( X[i] ); i++;   // DisOp\n    Y[i] = 4.0;                 i++;   // ParOp\n    Y[i] = sign( X[i] );        i++;   // SignOp\n    Y[i] = sinh( X[i] );        i++;   // SinhOp\n    Y[i] = tanh(X[i]);          i++;   // TanhOp\n\n    // VecAD operations\n    CppAD::VecAD<double> V(n);\n    AD<double> index = 1.;\n    V[index] = 3.0;\n    Y[i]     = V[index];            i++;   // StppOp, LdpOp\n    V[index] = X[0];\n    Y[i]     = V[index];            i++;   // StpvOp, LdpOp\n    index    = double(n) * X[3];\n    V[index] = X[1];\n    Y[i]     = V[index];            i++;   // StvvOp, LdvOp\n\n    // create f: X -> Y and stop tape recording\n    assert( i == m );\n    CppAD::ADFun<double> f;\n    f.Dependent(X, Y);\n\n    // initially, no values stored in f\n    ok &= f.size_order() == 0;\n\n    // Set X_j (t) = x + t\n    size_t p = 2, p1 = p+1;\n    CPPAD_TESTVECTOR(double) x(n), x_p(n * p1), y_p(m * p1);\n    for(j = 0; j < n; j++)\n    {   x[j]            = double(j) / double(n);\n        x_p[j * p1 + 0] = x[j]; // order 0\n        x_p[j * p1 + 1] = 1.;   // order 1\n        x_p[j * p1 + 2] = 0.;   // order 2\n    }\n    // compute orders 0, 1, 2\n    y_p  = f.Forward(p, x_p);\n\n    // identity functions\n    CPPAD_TESTVECTOR(double) y(p1);\n    i = 0;\n    for(j = identity_begin; j != identity_end; j++)\n    {   y[0] = x[j];\n        y[1] = 1.0;\n        y[2] = 0.0;\n        for(k = 0; k < p1; k++)\n            ok  &= NearEqual(y[k] , y_p[i * p1 + k], eps, eps);\n        i++;\n    }\n\n    // y_i = fabs( x_i )\n    y[0] = fabs( x[i] );\n    y[1] = CppAD::sign( x[i] );\n    y[2] = 0.0;\n    for(k = 0; k < p1; k++)\n        ok  &= NearEqual(y[k] , y_p[i * p1 + k], eps, eps);\n\n    // y_i = x_[i-1] + x_i + 2\n    i++;\n    y[0] = x[i-1] + x[i] + 2.0;\n    y[1] = 2.0;\n    y[2] = 0.0;\n    for(k = 0; k < p1; k++)\n        ok  &= NearEqual(y[k] , y_p[i * p1 + k], eps, eps);\n\n    // y_i = cosh( x_i )\n    i++;\n    y[0] = CppAD::cosh( x[i] );\n    y[1] = CppAD::sinh( x[i] );\n    y[2] = CppAD::cosh( x[i] ) / 2.0;\n    for(k = 0; k < p1; k++)\n        ok  &= NearEqual(y[k] , y_p[i * p1 + k], eps, eps);\n\n    // y_i = my_discrete( x_i )\n    i++;\n    y[0] = my_discrete( x[i] );\n    y[1] = 0.0;\n    y[2] = 0.0;\n    for(k = 0; k < p1; k++)\n        ok  &= NearEqual(y[k] , y_p[i * p1 + k], eps, eps);\n\n    // y_i = 4\n    i++;\n    y[0] = 4.0;\n    y[1] = 0.0;\n    y[2] = 0.0;\n    for(k = 0; k < p1; k++)\n        ok  &= NearEqual(y[k] , y_p[i * p1 + k], eps, eps);\n\n    // y_i = sign( x_i )\n    i++;\n    y[0] = CppAD::sign( x[i] );\n    y[1] = 0.0;\n    y[2] = 0.0;\n    for(k = 0; k < p1; k++)\n        ok  &= NearEqual(y[k] , y_p[i * p1 + k], eps, eps);\n\n    // y_i = sinh( x_i )\n    i++;\n    y[0] = CppAD::sinh( x[i] );\n    y[1] = CppAD::cosh( x[i] );\n    y[2] = CppAD::sinh( x[i] ) / 2.0;\n    for(k = 0; k < p1; k++)\n        ok  &= NearEqual(y[k] , y_p[i * p1 + k], eps, eps);\n\n    // y_i = tanh( x_i )\n    i++;\n    y[0] = CppAD::tanh( x[i] );\n    y[1] = 1.0 - y[0] * y[0];\n    y[2] = - 2.0 * y[0] * y[1] / 2.0;\n    for(k = 0; k < p1; k++)\n        ok  &= NearEqual(y[k] , y_p[i * p1 + k], eps, eps);\n\n    // y_i = 3.0;\n    i++;\n    y[0] = 3.0;\n    y[1] = 0.0;\n    y[2] = 0.0;\n    for(k = 0; k < p1; k++)\n        ok  &= NearEqual(y[k] , y_p[i * p1 + k], eps, eps);\n\n    // y_i = x_0\n    i++;\n    y[0] = x[0];\n    y[1] = 1.0;\n    y[2] = 0.0;\n    for(k = 0; k < p1; k++)\n        ok  &= NearEqual(y[k] , y_p[i * p1 + k], eps, eps);\n\n    // y_i = x_1\n    i++;\n    y[0] = x[1];\n    y[1] = 1.0;\n    y[2] = 0.0;\n    for(k = 0; k < p1; k++)\n        ok  &= NearEqual(y[k] , y_p[i * p1 + k], eps, eps);\n\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "test_more/general/from_base.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n\n/*\nOld FromBase example now used just for valiadation testing\n*/\n# include <cppad/cppad.hpp>\n\nbool FromBase(void)\n{   bool ok = true;\n\n    using namespace CppAD;\n\n    // construct directly form Base where Base = double\n    AD<double> x(1.);\n    AD<double> y = 2.;\n\n    // construct from a type that can be converted to Base\n    // where Base = AD<double>\n    AD< AD<double> > X(1.);\n    AD< AD<double> > Y(2);\n\n    // check that resulting objects are parameters\n    ok &= Parameter(x);\n    ok &= Parameter(y);\n\n    ok &= Parameter(X);\n    ok &= Parameter(Y);\n\n    // check values of objects\n    ok &= (x == 1.);\n    ok &= (X == x);\n\n    ok &= (y == 2.);\n    ok &= (Y == y);\n\n    // user constructor through the static_cast template function\n    x   = static_cast < AD<double> >( 4 );\n    X   = static_cast < AD< AD<double> > >( 4 );\n\n    ok &= (x == 4.);\n    ok &= (X == x);\n\n    return ok;\n}\n\n// END PROGRAM\n"
  },
  {
    "path": "test_more/general/fun_check.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\nold example, now just used for testing deprecated syntax f.Dependent(y)\n*/\n\n// BEGIN C++\n# include <cppad/cppad.hpp>\n\nnamespace { // -----------------------------------------------------------\n// define the template function object Fun<Type,Vector> in empty namespace\ntemplate <class Type, class Vector>\nclass Fun {\nprivate:\n    size_t n;\npublic:\n    // function constructor\n    Fun(size_t n_) : n(n_)\n    { }\n    // function evaluator\n    Vector operator() (const Vector &x)\n    {   Vector y(n);\n        size_t i;\n        for(i = 0; i < n; i++)\n        {   // This operation sequence depends on x\n            if( x[i] >= 0 )\n                y[i] = exp(x[i]);\n            else\n                y[i] = exp(-x[i]);\n        }\n        return y;\n    }\n};\n// template function FunCheckCases<Vector, ADVector> in empty namespace\ntemplate <class Vector, class ADVector>\nbool FunCheckCases(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::ADFun;\n    using CppAD::Independent;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // use the ADFun default constructor\n    ADFun<double> f;\n\n    // domain space vector\n    size_t n = 2;\n    ADVector X(n);\n    X[0] = -1.;\n    X[1] = 1.;\n\n    // declare independent variables and starting recording\n    Independent(X);\n\n    // create function object to use with AD<double>\n    Fun< AD<double>, ADVector > G(n);\n\n    // range space vector\n    size_t m = n;\n    ADVector Y(m);\n    Y = G(X);\n\n    // stop tape and store operation sequence in f : X -> Y\n    f.Dependent(Y);\n    ok &= (f.size_order() == 0);  // no implicit forward operation\n\n    // create function object to use with double\n    Fun<double, Vector> g(n);\n\n    // function values should agree when the independent variable\n    // values are the same as during recording\n    Vector x(n);\n    size_t j;\n    for(j = 0; j < n; j++)\n        x[j] = Value(X[j]);\n    double r = eps99;\n    double a = eps99;\n    ok      &= FunCheck(f, g, x, a, r);\n\n    // function values should not agree when the independent variable\n    // values are the negative of values during recording\n    for(j = 0; j < n; j++)\n        x[j] = - Value(X[j]);\n    ok      &= ! FunCheck(f, g, x, a, r);\n\n    // re-tape to obtain the new AD of double operation sequence\n    for(j = 0; j < n; j++)\n        X[j] = x[j];\n    Independent(X);\n    Y = G(X);\n\n    // stop tape and store operation sequence in f : X -> Y\n    f.Dependent(Y);\n    ok &= (f.size_order() == 0);  // no implicit forward with this x\n\n    // function values should agree now\n    ok      &= FunCheck(f, g, x, a, r);\n\n    return ok;\n}\n} // End empty namespace\n# include <vector>\n# include <valarray>\nbool FunCheck(void)\n{   bool ok = true;\n    typedef CppAD::vector<double>                Vector1;\n    typedef CppAD::vector< CppAD::AD<double> > ADVector1;\n    typedef   std::vector<double>                Vector2;\n    typedef   std::vector< CppAD::AD<double> > ADVector2;\n    typedef std::valarray<double>                Vector3;\n    typedef std::valarray< CppAD::AD<double> > ADVector3;\n    // Run with Vector and ADVector equal to three different cases\n    // all of which are Simple Vectors with elements of type\n    // double and AD<double> respectively.\n    ok &= FunCheckCases< Vector1, ADVector2 >();\n    ok &= FunCheckCases< Vector2, ADVector3 >();\n    ok &= FunCheckCases< Vector3, ADVector1 >();\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "test_more/general/general.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n// CPPAD_HAS_* defines\n# include <cppad/configure.hpp>\n\n// system include files used for I/O\n# include <iostream>\n\n// memory leak checker\n# include <cppad/utility/thread_alloc.hpp>\n\n// test runner\n# include <cppad/utility/test_boolofvoid.hpp>\n\n// BEGIN_SORT_THIS_LINE_PLUS_1\nextern bool Add(void);\nextern bool AddEq(void);\nextern bool AddZero(void);\nextern bool Compare(void);\nextern bool CondExp(void);\nextern bool CondExpAD(void);\nextern bool Cos(void);\nextern bool Cosh(void);\nextern bool Div(void);\nextern bool DivEq(void);\nextern bool DivZeroOne(void);\nextern bool Exp(void);\nextern bool ForHess(void);\nextern bool Forward(void);\nextern bool FromBase(void);\nextern bool FunCheck(void);\nextern bool Mul(void);\nextern bool MulEq(void);\nextern bool MulZeroOne(void);\nextern bool Neg(void);\nextern bool Poly(void);\nextern bool Pow(void);\nextern bool PowInt(void);\nextern bool RevTwo(void);\nextern bool RombergOne(void);\nextern bool Rosen34(void);\nextern bool Runge45(void);\nextern bool SimpleVector(void);\nextern bool Sin(void);\nextern bool SinCos(void);\nextern bool Sinh(void);\nextern bool Sqrt(void);\nextern bool Sub(void);\nextern bool SubEq(void);\nextern bool SubZero(void);\nextern bool Value(void);\nextern bool VecAD(void);\nextern bool VecADPar(void);\nextern bool VecUnary(void);\nextern bool abs_normal(void);\nextern bool acos(void);\nextern bool acosh(void);\nextern bool adfun(void);\nextern bool alloc_openmp(void);\nextern bool asin(void);\nextern bool asinh(void);\nextern bool assign(void);\nextern bool atan(void);\nextern bool atan2(void);\nextern bool atanh(void);\nextern bool atomic_four(void);\nextern bool atomic_three(void);\nextern bool azmul(void);\nextern bool base2ad(void);\nextern bool base_adolc(void);\nextern bool base_alloc_test(void);\nextern bool base_complex(void);\nextern bool bool_sparsity(void);\nextern bool check_simple_vector(void);\nextern bool chkpoint_one(void);\nextern bool chkpoint_two(void);\nextern bool compare_change(void);\nextern bool cond_exp_rev(void);\nextern bool copy(void);\nextern bool cpp_graph(void);\nextern bool cppad_eigen(void);\nextern bool cppad_vector(void);\nextern bool dbl_epsilon(void);\nextern bool dependency(void);\nextern bool eigen_mat_inv(void);\nextern bool erf(void);\nextern bool expm1(void);\nextern bool fabs(void);\nextern bool for_hes_sparsity(void);\nextern bool for_jac_sparsity(void);\nextern bool forward_dir(void);\nextern bool forward_order(void);\nextern bool hes_sparsity(void);\nextern bool ipopt_solve(void);\nextern bool jacobian(void);\nextern bool json_graph(void);\nextern bool log(void);\nextern bool log10(void);\nextern bool log1p(void);\nextern bool mul_cond_rev(void);\nextern bool mul_cskip(void);\nextern bool mul_level(void);\nextern bool mul_zdouble(void);\nextern bool near_equal_ext(void);\nextern bool new_dynamic(void);\nextern bool num_limits(void);\nextern bool ode_err_control(void);\nextern bool optimize(void);\nextern bool parameter(void);\nextern bool print_for(void);\nextern bool rev_sparse_jac(void);\nextern bool reverse(void);\nextern bool sparse_hessian(void);\nextern bool sparse_jac_work(void);\nextern bool sparse_jacobian(void);\nextern bool sparse_sub_hes(void);\nextern bool sparse_vec_ad(void);\nextern bool std_math(void);\nextern bool subgraph_1(void);\nextern bool subgraph_2(void);\nextern bool subgraph_hes2jac(void);\nextern bool tan(void);\nextern bool to_csrc(void);\nextern bool to_string(void);\n// END_SORT_THIS_LINE_MINUS_1\n\n// tests in local subdirectory\nextern bool is_pod(void);\nextern bool json_lexer(void);\nextern bool json_parser(void);\nextern bool temp_file(void);\nextern bool vector_set(void);\n\n// main program that runs all the tests\nint main(void)\n{   std::string group = \"test_more/general\";\n    size_t      width = 20;\n    CppAD::test_boolofvoid Run(group, width);\n\n    // This line is used by test_one.sh\n\n    // BEGIN_SORT_THIS_LINE_PLUS_1\n    Run( Add,             \"Add\"            );\n    Run( AddEq,           \"AddEq\"          );\n    Run( AddZero,         \"AddZero\"        );\n    Run( Compare,         \"Compare\"        );\n    Run( CondExp,         \"CondExp\"        );\n    Run( CondExpAD,       \"CondExpAD\"      );\n    Run( Cos,             \"Cos\"            );\n    Run( Cosh,            \"Cosh\"           );\n    Run( Div,             \"Div\"            );\n    Run( DivEq,           \"DivEq\"          );\n    Run( DivZeroOne,      \"DivZeroOne\"     );\n    Run( Exp,             \"Exp\"            );\n    Run( ForHess,         \"ForHess\"        );\n    Run( Forward,         \"Forward\"        );\n    Run( FromBase,        \"FromBase\"       );\n    Run( FunCheck,        \"FunCheck\"       );\n    Run( Mul,             \"Mul\"            );\n    Run( MulEq,           \"MulEq\"          );\n    Run( MulZeroOne,      \"MulZeroOne\"     );\n    Run( Neg,             \"Neg\"            );\n    Run( Poly,            \"Poly\"           );\n    Run( Pow,             \"Pow\"            );\n    Run( PowInt,          \"PowInt\"         );\n    Run( RevTwo,          \"RevTwo\"         );\n    Run( RombergOne,      \"RombergOne\"     );\n    Run( Rosen34,         \"Rosen34\"        );\n    Run( Runge45,         \"Runge45\"        );\n    Run( SimpleVector,    \"SimpleVector\"   );\n    Run( Sin,             \"Sin\"            );\n    Run( SinCos,          \"SinCos\"         );\n    Run( Sinh,            \"Sinh\"           );\n    Run( Sqrt,            \"Sqrt\"           );\n    Run( Sub,             \"Sub\"            );\n    Run( SubEq,           \"SubEq\"          );\n    Run( SubZero,         \"SubZero\"        );\n    Run( Value,           \"Value\"          );\n    Run( VecAD,           \"VecAD\"          );\n    Run( VecADPar,        \"VecADPar\"       );\n    Run( VecUnary,        \"VecUnary\"       );\n    Run( abs_normal,      \"abs_normal\"     );\n    Run( acos,            \"acos\"           );\n    Run( acosh,           \"acosh\"          );\n    Run( adfun,           \"adfun\"          );\n    Run( asin,            \"asin\"           );\n    Run( asinh,           \"asinh\"          );\n    Run( assign,          \"assign\"         );\n    Run( atan,            \"atan\"           );\n    Run( atan2,           \"atan2\"          );\n    Run( atanh,           \"atanh\"          );\n    Run( atomic_four,     \"atomic_four\"    );\n    Run( atomic_three,    \"atomic_three\"   );\n    Run( azmul,           \"azmul\"          );\n    Run( base2ad,         \"base2ad\"        );\n    Run( base_complex,    \"base_complex\"   );\n    Run( bool_sparsity,   \"bool_sparsity\"  );\n    Run( check_simple_vector, \"check_simple_vector\" );\n    Run( chkpoint_one,    \"chkpoint_one\"   );\n    Run( chkpoint_two,    \"chkpoint_two\"   );\n    Run( compare_change,  \"compare_change\" );\n    Run( cond_exp_rev,    \"cond_exp_rev\"   );\n    Run( copy,            \"copy\"           );\n    Run( cpp_graph,       \"cpp_graph\"      );\n    Run( cppad_vector,    \"cppad_vector\"   );\n    Run( dbl_epsilon,     \"dbl_epsilon\"    );\n    Run( dependency,      \"dependency\"     );\n    Run( erf,             \"erf\"            );\n    Run( expm1,           \"expm1\"          );\n    Run( fabs,            \"fabs\"           );\n    Run( for_hes_sparsity, \"for_hes_sparsity\" );\n    Run( for_jac_sparsity, \"for_jac_sparsity\" );\n    Run( forward_dir,     \"forward_dir\"    );\n    Run( forward_order,   \"forward_order\"  );\n    Run( hes_sparsity,    \"hes_sparsity\"   );\n    Run( jacobian,        \"jacobian\"       );\n    Run( json_graph,      \"json_graph\"     );\n    Run( log,             \"log\"            );\n    Run( log10,           \"log10\"          );\n    Run( log1p,           \"log1p\"          );\n    Run( mul_cond_rev,    \"mul_cond_rev\"   );\n    Run( mul_cskip,       \"Mul_cskip\"      );\n    Run( mul_level,       \"mul_level\"      );\n    Run( mul_zdouble,     \"mul_zdouble\"    );\n    Run( near_equal_ext,  \"near_equal_ext\" );\n    Run( new_dynamic,     \"new_dynamic\"    );\n    Run( num_limits,      \"num_limits\"     );\n    Run( ode_err_control, \"ode_err_control\");\n    Run( optimize,        \"optimize\"       );\n    Run( parameter,       \"parameter\"      );\n    Run( print_for,       \"print_for\"      );\n    Run( rev_sparse_jac,  \"rev_sparse_jac\" );\n    Run( reverse,         \"reverse\"        );\n    Run( sparse_hessian,  \"sparse_hessian\" );\n    Run( sparse_jac_work, \"sparse_jac_work\");\n    Run( sparse_jacobian, \"sparse_jacobian\");\n    Run( sparse_sub_hes,  \"sparse_sub_hes\" );\n    Run( sparse_vec_ad,   \"sparse_vec_ad\"  );\n    Run( std_math,        \"std_math\"       );\n    Run( subgraph_1,      \"subgraph_1\"     );\n    Run( subgraph_2,      \"subgraph_2\"     );\n    Run( subgraph_hes2jac, \"subgraph_hes2jac\" );\n    Run( tan,             \"tan\"            );\n    Run( to_string,       \"to_string\"      );\n    // END_SORT_THIS_LINE_MINUS_1\n# if CPPAD_C_COMPILER_GNU_FLAGS || CPPAD_C_COMPILER_MSVC_FLAGS\n# if ! CPPAD_LINK_FLAGS_HAS_M32\n    Run( to_csrc,         \"to_csrc\"        );\n# endif\n# endif\n#if CPPAD_HAS_ADOLC\n    Run( base_adolc,      \"base_adolc\"     );\n# endif\n#if CPPAD_HAS_IPOPT\n    Run( ipopt_solve,     \"ipopt_solve\"    );\n# endif\n# ifdef CPPAD_OPENMP_TEST\n    Run( alloc_openmp,    \"alloc_openmp\"   );\n# endif\n# if CPPAD_HAS_EIGEN\n    Run( cppad_eigen,     \"cppad_eigen\"    );\n    Run( eigen_mat_inv,   \"eigen_mat_inv\"  );\n# endif\n    // local sub-directory\n    Run( is_pod,         \"is_pod\"          );\n    Run( json_lexer,     \"json_lexer\"      );\n    Run( json_parser,    \"json_parser\"     );\n    Run( temp_file,       \"temp_file\"      );\n    Run( vector_set,      \"vector_set\"     );\n    //\n    // check for memory leak\n    bool memory_ok = CppAD::thread_alloc::free_all();\n    //\n    // Run base_alloc after memory leak check because base_alloc.hpp uses\n    // thread_alloc to allocate memory for static copies of nan.\n    Run( base_alloc_test,  \"base_alloc\"    );\n    //\n    // print summary at end\n    bool ok = Run.summary(memory_ok);\n    //\n    return static_cast<int>( ! ok );\n}\n// END PROGRAM\n"
  },
  {
    "path": "test_more/general/hes_sparsity.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n\n# include <cppad/cppad.hpp>\n\nnamespace { // Begin empty namespace\n\nvoid forward_sparse_jacobian_bool(CppAD::ADFun<double>& f)\n{   size_t n = f.Domain();\n    CPPAD_TESTVECTOR(bool) eye(n * n);\n    for(size_t i = 0; i < n; i++)\n    {   for(size_t j = 0; j < n; j++)\n            eye[ i * n + j] = (i == j);\n    }\n    f.ForSparseJac(n, eye);\n    return;\n}\nvoid forward_sparse_jacobian_set(CppAD::ADFun<double>& f)\n{   size_t n = f.Domain();\n    CPPAD_TESTVECTOR(std::set<size_t>) eye(n);\n    for(size_t i = 0; i < n; i++)\n        eye[i].insert(i);\n    f.ForSparseJac(n, eye);\n    return;\n}\n\nbool sparse_hessian_test(\n    CppAD::ADFun<double>&    f     ,\n    size_t                   index ,\n    CPPAD_TESTVECTOR(bool)&  check )\n{   bool   ok = true;\n    size_t n  = f.Domain();\n    size_t m  = f.Range();\n\n    // boolean sparsity patterns\n    CPPAD_TESTVECTOR(bool) r_bool(n), s_bool(m), h_bool(n * n);\n    for(size_t j = 0; j < n; j++)\n        r_bool[j] = true;\n    for(size_t i = 0; i < m; i++)\n        s_bool[i] = i == index;\n    //\n    // bool ForSparseHes\n    h_bool = f.ForSparseHes(r_bool, s_bool);\n    for(size_t i = 0; i < n * n; i++)\n        ok &= h_bool[i] == check[i];\n    //\n    // bool RevSparseHes\n    forward_sparse_jacobian_bool(f);\n    h_bool = f.RevSparseHes(n, s_bool);\n    for(size_t i = 0; i < n * n; i++)\n        ok &= h_bool[i] == check[i];\n    //\n    // set sparsity patterns\n    CPPAD_TESTVECTOR( std::set<size_t> ) r_set(1), s_set(1), h_set(n);\n    for(size_t j = 0; j < n; j++)\n        r_set[0].insert(j);\n    s_set[0].insert(index);\n    //\n    // set ForSparseHes\n    h_set = f.ForSparseHes(r_set, s_set);\n    for(size_t i = 0; i < n; i++)\n    {   for(size_t j = 0; j < n; j++)\n        {   bool found = h_set[i].find(j) != h_set[i].end();\n            ok        &= found == check[i * n + j];\n        }\n    }\n    //\n    // set RevSparseHes\n    forward_sparse_jacobian_set(f);\n    h_set = f.RevSparseHes(n, s_set);\n    for(size_t i = 0; i < n; i++)\n    {   for(size_t j = 0; j < n; j++)\n        {   bool found = h_set[i].find(j) != h_set[i].end();\n            ok        &= found == check[i * n + j];\n        }\n    }\n    //\n    return ok;\n}\n\n\n\nbool case_one()\n{   bool ok = true;\n    using namespace CppAD;\n\n    // dimension of the domain space\n    size_t n = 10;\n\n    // dimension of the range space\n    size_t m = 2;\n\n    // temporary indices\n\n    // initialize check values to false\n    CPPAD_TESTVECTOR(bool) Check(n * n);\n    for(size_t j = 0; j < n * n; j++)\n        Check[j] = false;\n\n    // independent variable vector\n    CPPAD_TESTVECTOR(AD<double>) X(n);\n    for(size_t j = 0; j < n; j++)\n        X[j] = AD<double>(j);\n    Independent(X);\n\n    // accumulate sum here\n    AD<double> sum(0.);\n\n    // variable * variable\n    sum += X[2] * X[3];\n    Check[2 * n + 3] = Check[3 * n + 2] = true;\n\n    // variable / variable\n    sum += X[4] / X[5];\n    Check[4 * n + 5] = Check[5 * n + 4] = Check[5 * n + 5] = true;\n\n    // CondExpLt(variable, variable, variable, variable)\n    sum += CondExpLt(X[1], X[2], sin(X[6]), cos(X[7]) );\n    Check[6 * n + 6] = true;\n    Check[7 * n + 7] = true;\n\n    // pow(variable, variable)\n    sum += pow(X[8], X[9]);\n    Check[8 * n + 8] = Check[8 * n + 9] = true;\n    Check[9 * n + 8] = Check[9 * n + 9] = true;\n\n    // dependent variable vector\n    CPPAD_TESTVECTOR(AD<double>) Y(m);\n    Y[0] = sum;\n\n    // variable - variable\n    Y[1]  = X[0] - X[1];\n\n    // create function object F : X -> Y\n    ADFun<double> F(X, Y);\n\n    // check Hessian of F_0\n    ok &= sparse_hessian_test(F, 0, Check);\n\n    // check Hessian of F_1\n    for(size_t j = 0; j < n * n; j++)\n        Check[j] = false;\n    ok &= sparse_hessian_test(F, 1, Check);\n\n    // -----------------------------------------------------------------------\n    return ok;\n}\n\nbool case_two()\n{   bool ok = true;\n    using namespace CppAD;\n\n    // dimension of the domain space\n    size_t n = 4;\n\n    // dimension of the range space\n    size_t m = 1;\n\n    // initialize check values to false\n    CPPAD_TESTVECTOR(bool) Check(n * n);\n    for(size_t j = 0; j < n * n; j++)\n        Check[j] = false;\n\n    // independent variable vector\n    CPPAD_TESTVECTOR(AD<double>) X(n);\n    for(size_t j = 0; j < n; j++)\n        X[j] = AD<double>(j);\n    Independent(X);\n\n    // Test the case where dependent variable is a non-linear function\n    // of the result of a conditional expression.\n    CPPAD_TESTVECTOR(AD<double>) Y(m);\n    Y[0] = CondExpLt(X[0], X[1], X[2], X[3]);\n    Y[0] = cos(Y[0]) + X[0] + X[1];\n\n    // Hessian with respect to x[0] and x[1] is zero.\n    // Hessian with respect to x[2] and x[3] is full\n    // (although we know that there are no cross terms, this is an\n    // inefficiency of the conditional expression operator).\n    Check[2 * n + 2] = Check[ 2 * n + 3 ] = true;\n    Check[3 * n + 2] = Check[ 3 * n + 3 ] = true;\n\n    // create function object F : X -> Y\n    ADFun<double> F(X, Y);\n\n    // -----------------------------------------------------------------\n    sparse_hessian_test(F, 0, Check);\n    //\n    return ok;\n}\n\nbool case_three()\n{   bool ok = true;\n    using CppAD::AD;\n\n    // domain space vector\n    size_t n = 1;\n    CPPAD_TESTVECTOR(AD<double>) X(n);\n    X[0] = 0.;\n\n    // declare independent variables and start recording\n    CppAD::Independent(X);\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) Y(m);\n\n    // make sure reverse jacobian is propagating dependency to\n    // intermediate values (not just final ones).\n    Y[0] = X[0] * X[0] + 2;\n\n    // create f: X -> Y and stop tape recording\n    CppAD::ADFun<double> f(X, Y);\n\n    // ------------------------------------------------------------------\n    CPPAD_TESTVECTOR(bool) check(n * n);\n    check[0] = true;\n    sparse_hessian_test(f, 0, check);\n    //\n    return ok;\n}\n\nbool case_four()\n{   bool ok = true;\n    using namespace CppAD;\n\n    // dimension of the domain space\n    size_t n = 3;\n\n    // dimension of the range space\n    size_t m = 1;\n\n    // initialize the vector as zero\n    CppAD::VecAD<double> Z(n - 1);\n    size_t k;\n    for(k = 0; k < n-1; k++)\n        Z[k] = 0.;\n\n    // independent variable vector\n    CPPAD_TESTVECTOR(AD<double>) X(n);\n    X[0] = 0.;\n    X[1] = 1.;\n    X[2] = 2.;\n    Independent(X);\n\n    // VecAD vector z depends on both x[1] and x[2]\n    // (component indices do not matter because they can change).\n    Z[ X[0] ] = X[1] * X[2];\n    Z[ X[1] ] = 0.;\n\n    // dependent variable vector\n    CPPAD_TESTVECTOR(AD<double>) Y(m);\n\n    // check results vector\n    CPPAD_TESTVECTOR( bool )       Check(n * n);\n\n    // y = z[j] where j might be zero or one.\n    Y[0]  =  Z[ X[1] ];\n\n    Check[0 * n + 0] = false; // partial w.r.t x[0], x[0]\n    Check[0 * n + 1] = false; // partial w.r.t x[0], x[1]\n    Check[0 * n + 2] = false; // partial w.r.t x[0], x[2]\n\n    Check[1 * n + 0] = false; // partial w.r.t x[1], x[0]\n    Check[1 * n + 1] = false; // partial w.r.t x[1], x[1]\n    Check[1 * n + 2] = true;  // partial w.r.t x[1], x[2]\n\n    Check[2 * n + 0] = false; // partial w.r.t x[2], x[0]\n    Check[2 * n + 1] = true;  // partial w.r.t x[2], x[1]\n    Check[2 * n + 2] = false; // partial w.r.t x[2], x[2]\n\n    // create function object F : X -> Y\n    ADFun<double> F(X, Y);\n\n    // -----------------------------------------------------\n    sparse_hessian_test(F, 0, Check);\n    //\n    return ok;\n}\n\nbool case_five(void)\n{   bool ok = true;\n    using CppAD::AD;\n\n    size_t n = 2;\n    CPPAD_TESTVECTOR(AD<double>) X(n);\n    X[0] = 1.;\n    X[1] = 2.;\n    CppAD::Independent(X);\n\n    size_t m = 2;\n    CPPAD_TESTVECTOR(AD<double>) Y(m);\n    Y[0] = pow(X[0], 2.);\n    Y[1] = pow(2., X[1]);\n\n    // create function object F : X -> Y\n    CppAD::ADFun<double> F(X, Y);\n\n    // Test F_0 and F_1\n    for(size_t index = 0; index < n; index++)\n    {   CPPAD_TESTVECTOR(bool) check(n * n);\n        for(size_t i = 0; i < n; i++)\n            for(size_t j = 0; j < n; j++)\n                check[i * n + j] = (i == index) && (j == index);\n        sparse_hessian_test(F, index, check);\n    }\n    //\n    return ok;\n}\n\n// Note ForSparseHes does not work for this case because R not diagonal.\nbool case_six()\n{   bool ok = true;\n    using namespace CppAD;\n\n    // dimension of the domain space\n    size_t n = 3;\n\n    // dimension of the range space\n    size_t m = 1;\n\n    // independent variable vector\n    CPPAD_TESTVECTOR(AD<double>) X(n);\n    X[0] = 0.;\n    X[1] = 1.;\n    X[2] = 2.;\n    Independent(X);\n    // y = z[j] where j might be zero or one.\n    CPPAD_TESTVECTOR(AD<double>) Y(m);\n    Y[0]  =  X[1] * X[2];\n    // create function object F : X -> Y\n    ADFun<double> F(X, Y);\n\n    // sparsity pattern for hessian of F^2\n    CPPAD_TESTVECTOR(bool) F2(n * n);\n    F2[0 * n + 0] = false; // partial w.r.t x[0], x[0]\n    F2[0 * n + 1] = false; // partial w.r.t x[0], x[1]\n    F2[0 * n + 2] = false; // partial w.r.t x[0], x[2]\n\n    F2[1 * n + 0] = false; // partial w.r.t x[1], x[0]\n    F2[1 * n + 1] = false; // partial w.r.t x[1], x[1]\n    F2[1 * n + 2] = true;  // partial w.r.t x[1], x[2]\n\n    F2[2 * n + 0] = false; // partial w.r.t x[2], x[0]\n    F2[2 * n + 1] = true;  // partial w.r.t x[2], x[1]\n    F2[2 * n + 2] = false; // partial w.r.t x[2], x[2]\n\n    // choose a non-symmetric sparsity pattern for R\n    CPPAD_TESTVECTOR( bool ) r(n * n);\n    size_t i, j, k;\n    for(i = 0; i < n; i++)\n    {   for(j = 0; j < n; j++)\n            r[ i * n + j ] = false;\n        j = n - i - 1;\n        r[ j * n + j ] = true;\n    }\n\n    // sparsity pattern for H^T\n    CPPAD_TESTVECTOR(bool) Check(n * n);\n    for(i = 0; i < n; i++)\n    {   for(j = 0; j < n; j++)\n        {   Check[ i * n + j] = false;\n            for(k = 0; k < n; k++)\n            {   // some gcc versions std::vector<bool> do not support |=\n                // on elements (because they pack the bits).\n                bool tmp         = Check[i * n + j];\n                Check[i * n + j] = tmp | (F2[i * n + k] && r[ k * n + j]);\n            }\n        }\n    }\n\n    // compute the reverse Hessian sparsity pattern for F^2 * R\n    F.ForSparseJac(n, r);\n    CPPAD_TESTVECTOR( bool ) s(m), h(n * n);\n    s[0] = 1.;\n    bool transpose = true;\n    h = F.RevSparseHes(n, s, transpose);\n\n    // check values\n    for(i = 0; i < n; i++)\n    {   for(j = 0; j < n; j++)\n            ok &= (h[i * n + j] == Check[i * n + j]);\n    }\n\n    // compute the reverse Hessian sparsity pattern for R^T * F^2\n    transpose = false;\n    h = F.RevSparseHes(n, s, transpose);\n\n    // check values\n    for(i = 0; i < n; i++)\n    {   for(j = 0; j < n; j++)\n            ok &= (h[j * n + i] == Check[i * n + j]);\n    }\n\n    return ok;\n}\n\n// bug in cppad/local/sweep/for_hes.hpp fixed on 2022-05-15\nbool case_seven()\n{   bool ok = true;\n    using namespace CppAD;\n    typedef CPPAD_TESTVECTOR(size_t) size_vector;\n\n    // dimension of the domain space\n    size_t n = 3;\n\n    // dimension of the range space\n    size_t m = 2;\n\n    // independent variable vector\n    CPPAD_TESTVECTOR(AD<double>) ax(n);\n    ax[0] = 0.;\n    ax[1] = 1.;\n    ax[2] = 2.;\n    Independent(ax);\n\n    // dependent variable vector\n    CPPAD_TESTVECTOR(AD<double>) ay(m);\n    ay[0] = ax[0] * ax[1];\n    ay[1] = ax[1] * ax[2];\n\n    // create function object f : x -> y\n    ADFun<double> f(ax, ay);\n\n    // sparsity pattern for Hessian of y[1]\n    CppAD::sparse_rc<size_vector> pattern_out;\n    bool internal_bool = false;\n    CPPAD_TESTVECTOR(bool) select_domain(n), select_range(m);\n    select_domain[0] = false;\n    select_domain[1] = true;\n    select_domain[2] = true;\n    select_range[0]  = false;\n    select_range[1]  = true;\n    f.for_hes_sparsity(\n        select_domain, select_range, internal_bool, pattern_out\n    );\n    //\n    ok &= pattern_out.nnz() == 2;\n    for(size_t k = 0; k < pattern_out.nnz(); ++k)\n    {   size_t i = pattern_out.row()[k];\n        size_t j = pattern_out.col()[k];\n        if( i == 1 )\n            ok &= j == 2;\n        else if( i == 2 )\n            ok &= j == 1;\n        else\n            ok = false;\n    }\n    //\n    return ok;\n}\n\n} // End of empty namespace\n\nbool hes_sparsity(void)\n{   bool ok = true;\n\n    ok &= case_one();\n    ok &= case_two();\n    ok &= case_three();\n    ok &= case_four();\n    ok &= case_five();\n    ok &= case_six();\n    ok &= case_seven();\n\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/ipopt_solve.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\nTesting ipopt::solve\n*/\n\n// CPPAD_HAS_* defines\n# include <cppad/configure.hpp>\n\n# if CPPAD_HAS_IPOPT\n\n# include <cppad/ipopt/solve.hpp>\n\nnamespace {\n    using CppAD::AD;\n\n    class FG_eval {\n    public:\n        typedef CPPAD_TESTVECTOR( AD<double> ) ADvector;\n        void operator()(ADvector& fg, const ADvector& x)\n        {   assert( fg.size() == 3 );\n            assert( x.size()  == 4 );\n\n            // Fortran style indexing\n            AD<double> x1 = x[0];\n            AD<double> x2 = x[1];\n            AD<double> x3 = x[2];\n            AD<double> x4 = x[3];\n            // f(x)\n            fg[0] = x1 * x4 * (x1 + x2 + x3) + x3;\n            // g_1 (x)\n            fg[1] = x1 * x2 * x3 * x4;\n            // g_2 (x)\n            fg[2] = x1 * x1 + x2 * x2 + x3 * x3 + x4 * x4;\n            //\n            return;\n        }\n    };\n}\n\nbool ipopt_solve(void)\n{   bool ok = true;\n    size_t i, j;\n    typedef CPPAD_TESTVECTOR( double ) Dvector;\n\n    // number of independent variables (domain dimension for f and g)\n    size_t nx = 4;\n    // number of constraints (range dimension for g)\n    size_t ng = 2;\n    // initial value of the independent variables\n    Dvector xi(nx);\n    xi[0] = 1.0;\n    xi[1] = 5.0;\n    xi[2] = 5.0;\n    xi[3] = 1.0;\n    // lower and upper limits for x\n    Dvector xl(nx), xu(nx);\n    for(j = 0; j < nx; j++)\n    {   xl[j] = 1.0;\n        xu[j] = 5.0;\n    }\n    // lower and upper limits for g\n    Dvector gl(ng), gu(ng);\n    gl[0] = 25.0;     gu[0] = 1.0e19;\n    gl[1] = 40.0;     gu[1] = 40.0;\n\n    // object that computes objective and constraints\n    FG_eval fg_eval;\n\n    // options\n    std::string base_options;\n    // turn off any printing\n    base_options += \"Integer print_level  0\\n\";\n    base_options += \"String  sb         yes\\n\";\n    // maximum number of iterations\n    base_options += \"Integer max_iter     10\\n\";\n    // approximate accuracy in first order necessary conditions;\n    // see Mathematical Programming, Volume 106, Number 1,\n    // Pages 25-57, Equation (6)\n    base_options += \"Numeric tol          1e-6\\n\";\n    // derivative testing\n    base_options += \"String  derivative_test            second-order\\n\";\n    // maximum amount of random perturbation; e.g.,\n    // when evaluation finite diff\n    base_options += \"Numeric point_perturbation_radius  0.\\n\";\n\n    // place to return solution\n    CppAD::ipopt::solve_result<Dvector> solution;\n\n    // solution values and tolerances\n    double check_x[]  = { 1.000000, 4.743000, 3.82115, 1.379408 };\n    double check_zl[] = { 1.087871, 0.,       0.,      0.       };\n    double check_zu[] = { 0.,       0.,       0.,      0.       };\n    double rel_tol    = 1e-6;  // relative tolerance\n    double abs_tol    = 1e-6;  // absolute tolerance\n\n    for(i = 0; i < 3; i++)\n    {   std::string options( base_options );\n        if( i == 1 )\n            options += \"Sparse true forward\\n\";\n        if( i == 2 )\n            options += \"Sparse true reverse\\n\";\n\n        // solve the problem\n        CppAD::ipopt::solve<Dvector, FG_eval>(\n            options, xi, xl, xu, gl, gu, fg_eval, solution\n        );\n        ok &= solution.status==CppAD::ipopt::solve_result<Dvector>::success;\n        //\n        // Check some of the solution values\n        for(j = 0; j < nx; j++)\n        {   ok &= CppAD::NearEqual(\n                check_x[j],  solution.x[j],   rel_tol, abs_tol\n            );\n            ok &= CppAD::NearEqual(\n                check_zl[j], solution.zl[j], rel_tol, abs_tol\n            );\n            ok &= CppAD::NearEqual(\n                check_zu[j], solution.zu[j], rel_tol, abs_tol\n            );\n        }\n    }\n\n    return ok;\n}\n\n# endif\n"
  },
  {
    "path": "test_more/general/jacobian.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/cppad.hpp>\n\nnamespace { // ---------------------------------------------------------\n\ntemplate <class Vector>\nVector eval_g(const Vector&  x)\n{   Vector g(2);\n\n    g[0] = x[0] * x[1] * x[2] * x[3];\n    g[1] = x[0] * x[0] + x[1] * x[1] + x[2] * x[2] + x[3] * x[3];\n\n    return g;\n}\n\ntemplate <class Vector>\nVector eval_jac_g(const Vector&  x)\n{   Vector jac_g(8);\n\n    // g[0] = x[0] * x[1] * x[2] * x[3];\n    jac_g[0] = x[1] * x[2] * x[3];\n    jac_g[1] = x[0] * x[2] * x[3];\n    jac_g[2] = x[0] * x[1] * x[3];\n    jac_g[3] = x[0] * x[1] * x[2];\n\n    // g[1] = x[0] * x[0] + x[1] * x[1] + x[2] * x[2] + x[3] * x[3];\n    jac_g[4+0] = 2. * x[0];\n    jac_g[4+1] = 2. * x[1];\n    jac_g[4+2] = 2. * x[2];\n    jac_g[4+3] = 2. * x[3];\n\n    return jac_g;\n}\n\n\n} // End empty namespace\n\nbool jacobian(void)\n{   bool ok = true;\n    using CppAD::vector;\n    size_t i, j, k;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    size_t n = 4;\n    size_t m = 2;\n    vector< CppAD::AD<double> > ad_x(n);\n    vector< CppAD::AD<double> > ad_g(m);\n\n    vector<double> x(n);\n    x[0] = 1.; x[1] = 5.0; x[2] = 5.0; x[3] = 1.0;\n    for(j = 0; j < n; j++)\n        ad_x[j] = x[j];\n    //\n    CppAD::Independent(ad_x);\n    ad_g = eval_g(ad_x);\n    CppAD::ADFun<double> fun_g(ad_x, ad_g);\n\n    vector<double> check(m * n);\n    check = eval_jac_g(x);\n\n    // regular jacobian\n    vector<double> jac_g = fun_g.Jacobian(x);\n    for(k = 0; k < m *n; k++)\n        ok &= NearEqual(jac_g[k], check[k], eps99, eps99);\n\n    // one argument sparse jacobian\n    jac_g = fun_g.SparseJacobian(x);\n    for(k = 0; k < m *n; k++)\n        ok &= NearEqual(jac_g[k], check[k], eps99, eps99);\n\n    // sparse jacobian using bool vectors\n    CPPAD_TESTVECTOR(bool) p_b(m * n) , r_b(n * n);\n    for(i = 0; i < n; i++)\n        for(j = 0; j < n; j++)\n            r_b[i * n + j] = (i == j);\n    p_b = fun_g.ForSparseJac(n, r_b);\n    jac_g = fun_g.SparseJacobian(x, p_b);\n    for(k = 0; k < m *n; k++)\n        ok &= NearEqual(jac_g[k], check[k], eps99, eps99);\n\n    // sparse jacobian using vectors of sets\n    std::vector< std::set<size_t> > p_s(m) , r_s(n);\n    for(i = 0; i < n; i++)\n        for(j = 0; j < n; j++)\n            r_s[i].insert(j);\n    p_s = fun_g.ForSparseJac(n, r_s);\n    jac_g = fun_g.SparseJacobian(x, p_s);\n    for(k = 0; k < m *n; k++)\n        ok &= NearEqual(jac_g[k], check[k], eps99, eps99);\n\n    return ok;\n}\n// END PROGRAM\n"
  },
  {
    "path": "test_more/general/json_graph.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/cppad.hpp>\n\nnamespace { // BEGIN_EMPTY_NAMESPACE\n// ---------------------------------------------------------------------------\nbool comp_op_dyn_dyn(void)\n{   bool ok = true;\n    using CppAD::vector;\n    using CppAD::AD;\n    //\n    // AD graph example\n    // node[0:4] : p[0], p[1], p[2], p[3], p[4]\n    // node_5    : x[0]\n    //           : p[0] == p[1]\n    //           : p[0] <= p[2]\n    //           : p[0] <  p[3]\n    //           : p[0] != p[4]\n    // y[0]      = p[0]\n    std::string json =\n        \"{\\n\"\n        \"   'function_name'  : 'comp_op example',\\n\"\n        \"   'op_define_vec'  : [ 4, [\\n\"\n        \"       { 'op_code':1, 'name':'comp_eq'            } ,\\n\"\n        \"       { 'op_code':2, 'name':'comp_le'            } ,\\n\"\n        \"       { 'op_code':3, 'name':'comp_lt'            } ,\\n\"\n        \"       { 'op_code':4, 'name':'comp_ne'            } ]\\n\"\n        \"   ],\\n\"\n        \"   'n_dynamic_ind'  : 5,\\n\"\n        \"   'n_variable_ind' : 1,\\n\"\n        \"   'constant_vec'   : [ 0, [ ] ],\\n\"\n        \"   'op_usage_vec'   : [ 4, [\\n\"\n        \"       [ 1, 0, 2, [1, 2 ] ] ,\\n\" // p[0] == p[1]\n        \"       [ 2, 0, 2, [1, 3 ] ] ,\\n\" // p[0] <= p[2]\n        \"       [ 3, 0, 2, [1, 4 ] ] ,\\n\" // p[0] <  p[3]\n        \"       [ 4, 0, 2, [1, 5 ] ] ]\\n\" // p[0] != p[4]\n        \"   ],\\n\"\n        \"   'dependent_vec' : [ 1, [1] ] \\n\"\n        \"}\\n\";\n    // Convert the single quote to double quote\n    for(size_t i = 0; i < json.size(); ++i)\n        if( json[i] == '\\'' ) json[i] = '\"';\n    //\n    // f(x, p) = p[0]\n    CppAD::ADFun<double> f;\n    f.from_json(json);\n    //\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 5;\n    //\n    // set independent variables and parameters so all comparisons true\n    vector<double> x(1), p(5);\n    x[0] = 1.0;\n    p[0] = 3.0;\n    p[1] = p[0];\n    p[2] = p[0] + 1.0;\n    p[3] = p[0] + 1.0;\n    p[4] = p[0] + 1.0;\n    //\n    // compute y = f(x; p)\n    f.new_dynamic(p);\n    vector<double> y = f.Forward(0, x);\n    //\n    // check that all comparisons are true\n    ok &= f.compare_change_number() == 0;\n    //\n    // case where all the comparisons are false\n    p[1] = p[0] - 1.0;\n    p[2] = p[0] - 1.0;\n    p[3] = p[0] - 1.0;\n    p[4] = p[0];\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    y = f.Forward(0, x);\n    ok &= f.compare_change_number() == 4;\n    //\n    // -----------------------------------------------------------------------\n    // Convert to Json graph and back again\n    json = f.to_json();\n    f.from_json(json);\n    // -----------------------------------------------------------------------\n    //\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 5;\n    //\n    // set independent variables and parameters so all comparisons true\n    p[0] = 3.0;\n    p[1] = p[0];\n    p[2] = p[0] + 1.0;\n    p[3] = p[0] + 1.0;\n    p[4] = p[0] + 1.0;\n    //\n    // compute y = f(x)\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    //\n    // check that all comparisons are true\n    ok &= f.compare_change_number() == 0;\n    //\n    // case where all the comparisons are false\n    p[1] = p[0] - 1.0;\n    p[2] = p[0] - 1.0;\n    p[3] = p[0] - 1.0;\n    p[4] = p[0];\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    ok &= f.compare_change_number() == 4;\n    //\n    return ok;\n}\n// ---------------------------------------------------------------------------\nbool comp_op_var_var(void)\n{   bool ok = true;\n    using CppAD::vector;\n    using CppAD::AD;\n    //\n    // AD graph example\n    // node[1:5] : x[0], x[1], x[2], x[3], x[4]\n    //           : x[0] == x[1]\n    //           : x[0] <= x[2]\n    //           : x[0] <  x[3]\n    //           : x[0] != x[4]\n    // y[0]      = x[0]\n    std::string json =\n        \"{\\n\"\n        \"   'function_name'  : 'comp_op example',\\n\"\n        \"   'op_define_vec'  : [ 4, [\\n\"\n        \"       { 'op_code':1, 'name':'comp_eq'            } ,\\n\"\n        \"       { 'op_code':2, 'name':'comp_le'            } ,\\n\"\n        \"       { 'op_code':3, 'name':'comp_lt'            } ,\\n\"\n        \"       { 'op_code':4, 'name':'comp_ne'            } ]\\n\"\n        \"   ],\\n\"\n        \"   'n_dynamic_ind'  : 0,\\n\"\n        \"   'n_variable_ind' : 5,\\n\"\n        \"   'constant_vec'   : [ 0, [ ] ],\\n\"\n        \"   'op_usage_vec'   : [ 4, [\\n\"\n        \"       [ 1, 0, 2, [1, 2 ] ] ,\\n\" // x[0] == x[1]\n        \"       [ 2, 0, 2, [1, 3 ] ] ,\\n\" // x[0] <= x[2]\n        \"       [ 3, 0, 2, [1, 4 ] ] ,\\n\" // x[0] <  x[3]\n        \"       [ 4, 0, 2, [1, 5 ] ] ]\\n\" // x[0] != x[4]\n        \"   ],\\n\"\n        \"   'dependent_vec' : [ 1, [1] ] \\n\"\n        \"}\\n\";\n    // Convert the single quote to double quote\n    for(size_t i = 0; i < json.size(); ++i)\n        if( json[i] == '\\'' ) json[i] = '\"';\n    //\n    // f(x, p) = p[0]\n    CppAD::ADFun<double> f;\n    f.from_json(json);\n    //\n    ok &= f.Domain() == 5;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 0;\n    //\n    // set independent variables and parameters so all comparisons true\n    vector<double> x(5);\n    x[0] = 3.0;\n    x[1] = x[0];\n    x[2] = x[0] + 1.0;\n    x[3] = x[0] + 1.0;\n    x[4] = x[0] + 1.0;\n    //\n    // compute y = f(x)\n    vector<double> y = f.Forward(0, x);\n    //\n    // check that all comparisons are true\n    ok &= f.compare_change_number() == 0;\n    //\n    // case where all the comparisons are false\n    x[1] = x[0] - 1.0;\n    x[2] = x[0] - 1.0;\n    x[3] = x[0] - 1.0;\n    x[4] = x[0];\n    y = f.Forward(0, x);\n    ok &= f.compare_change_number() == 4;\n    //\n    // -----------------------------------------------------------------------\n    // Convert to Json graph and back again\n    json = f.to_json();\n    f.from_json(json);\n    // -----------------------------------------------------------------------\n    //\n    ok &= f.Domain() == 5;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 0;\n    //\n    // set independent variables and parameters so all comparisons true\n    x[0] = 3.0;\n    x[1] = x[0];\n    x[2] = x[0] + 1.0;\n    x[3] = x[0] + 1.0;\n    x[4] = x[0] + 1.0;\n    //\n    // compute y = f(x)\n    y = f.Forward(0, x);\n    //\n    // check that all comparisons are true\n    ok &= f.compare_change_number() == 0;\n    //\n    // case where all the comparisons are false\n    x[1] = x[0] - 1.0;\n    x[2] = x[0] - 1.0;\n    x[3] = x[0] - 1.0;\n    x[4] = x[0];\n    y = f.Forward(0, x);\n    ok &= f.compare_change_number() == 4;\n    //\n    return ok;\n}\n// ---------------------------------------------------------------------------\nbool comp_op_dyn_var(void)\n{   bool ok = true;\n    using CppAD::vector;\n    using CppAD::AD;\n    //\n    // AD graph example\n    // node_1    : p[0]\n    // node[2:5] : x[0], x[1], x[2], x[3]\n    //           : p[0] == x[0]\n    //           : p[0] <= x[1]\n    //           : p[0] <  x[2]\n    //           : p[0] != x[3]\n    // y[0]      = p[0]\n    std::string json =\n        \"{\\n\"\n        \"   'function_name'  : 'comp_op example',\\n\"\n        \"   'op_define_vec'  : [ 4, [\\n\"\n        \"       { 'op_code':1, 'name':'comp_eq'            } ,\\n\"\n        \"       { 'op_code':2, 'name':'comp_le'            } ,\\n\"\n        \"       { 'op_code':3, 'name':'comp_lt'            } ,\\n\"\n        \"       { 'op_code':4, 'name':'comp_ne'            } ]\\n\"\n        \"   ],\\n\"\n        \"   'n_dynamic_ind'  : 1,\\n\"\n        \"   'n_variable_ind' : 4,\\n\"\n        \"   'constant_vec'   : [ 0, [ ] ],\\n\"\n        \"   'op_usage_vec'   : [ 4, [\\n\"\n        \"       [ 1, 0, 2, [1, 2 ] ] ,\\n\" // p[0] == x[0]\n        \"       [ 2, 0, 2, [1, 3 ] ] ,\\n\" // p[0] <= x[1]\n        \"       [ 3, 0, 2, [1, 4 ] ] ,\\n\" // p[0] <  x[2]\n        \"       [ 4, 0, 2, [1, 5 ] ] ]\\n\" // p[0] != x[3]\n        \"   ],\\n\"\n        \"   'dependent_vec' : [ 1, [1] ] \\n\"\n        \"}\\n\";\n    // Convert the single quote to double quote\n    for(size_t i = 0; i < json.size(); ++i)\n        if( json[i] == '\\'' ) json[i] = '\"';\n    //\n    // f(x, p) = p[0]\n    CppAD::ADFun<double> f;\n    f.from_json(json);\n    //\n    ok &= f.Domain() == 4;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 1;\n    //\n    // set independent variables and parameters so all comparisons true\n    vector<double> x(4), p(1);\n    p[0] = 3.0;\n    x[0] = p[0];\n    x[1] = p[0] + 1.0;\n    x[2] = p[0] + 1.0;\n    x[3] = p[0] + 1.0;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    vector<double> y = f.Forward(0, x);\n    //\n    // check that all comparisons are true\n    ok &= f.compare_change_number() == 0;\n    //\n    // case where all the comparisons are false\n    x[0] = p[0] - 1.0;\n    x[1] = p[0] - 1.0;\n    x[2] = p[0] - 1.0;\n    x[3] = p[0];\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    ok &= f.compare_change_number() == 4;\n    //\n    // -----------------------------------------------------------------------\n    // Convert to Json graph and back again\n    json = f.to_json();\n    f.from_json(json);\n    // -----------------------------------------------------------------------\n    //\n    ok &= f.Domain() == 4;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 1;\n    //\n    // set independent variables and parameters so all comparisons true\n    p[0] = 3.0;\n    x[0] = p[0];\n    x[1] = p[0] + 1.0;\n    x[2] = p[0] + 1.0;\n    x[3] = p[0] + 1.0;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    //\n    // check that all comparisons are true\n    ok &= f.compare_change_number() == 0;\n    //\n    // case where all the comparisons are false\n    x[0] = p[0] - 1.0;\n    x[1] = p[0] - 1.0;\n    x[2] = p[0] - 1.0;\n    x[3] = p[0];\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    ok &= f.compare_change_number() == 4;\n    //\n    return ok;\n}\n// ---------------------------------------------------------------------------\nbool comp_op_var_dyn(void)\n{   bool ok = true;\n    using CppAD::vector;\n    using CppAD::AD;\n    //\n    // AD graph example\n    // node[1:4] : p[0], p[1], p[2], p[3]\n    // node_5    : x[0]\n    //           : x[0] == p[0]\n    //           : x[0] <= p[1]\n    //           : x[0] <  p[2]\n    //           : x[0] != p[3]\n    // y[0]      = p[0]\n    std::string json =\n        \"{\\n\"\n        \"   'function_name'  : 'comp_op example',\\n\"\n        \"   'op_define_vec'  : [ 4, [\\n\"\n        \"       { 'op_code':1, 'name':'comp_eq'            } ,\\n\"\n        \"       { 'op_code':2, 'name':'comp_le'            } ,\\n\"\n        \"       { 'op_code':3, 'name':'comp_lt'            } ,\\n\"\n        \"       { 'op_code':4, 'name':'comp_ne'            } ]\\n\"\n        \"   ],\\n\"\n        \"   'n_dynamic_ind'  : 4,\\n\"\n        \"   'n_variable_ind' : 1,\\n\"\n        \"   'constant_vec'   : [ 0, [ ] ],\\n\"\n        \"   'op_usage_vec'   : [ 4, [\\n\"\n        \"       [ 1, 0, 2, [5, 1 ] ] ,\\n\" // x[0] == p[0]\n        \"       [ 2, 0, 2, [5, 2 ] ] ,\\n\" // x[0] <= p[1]\n        \"       [ 3, 0, 2, [5, 3 ] ] ,\\n\" // x[0] <  p[2]\n        \"       [ 4, 0, 2, [5, 4 ] ] ]\\n\" // x[0] != p[3]\n        \"   ],\\n\"\n        \"   'dependent_vec' : [ 1, [1] ] \\n\"\n        \"}\\n\";\n    // Convert the single quote to double quote\n    for(size_t i = 0; i < json.size(); ++i)\n        if( json[i] == '\\'' ) json[i] = '\"';\n    //\n    // f(x, p) = p[0]\n    CppAD::ADFun<double> f;\n    f.from_json(json);\n    //\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 4;\n    //\n    // set independent variables and parameters so all comparisons true\n    vector<double> x(1), p(4);\n    x[0] = 3.0;\n    p[0] = x[0];\n    p[1] = x[0] + 1.0;\n    p[2] = x[0] + 1.0;\n    p[3] = x[0] + 1.0;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    vector<double> y = f.Forward(0, x);\n    //\n    // check that all comparisons are true\n    ok &= f.compare_change_number() == 0;\n    //\n    // case where all the comparisons are false\n    p[0] = x[0] - 1.0;\n    p[1] = x[0] - 1.0;\n    p[2] = x[0] - 1.0;\n    p[3] = x[0];\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    ok &= f.compare_change_number() == 4;\n    //\n    // -----------------------------------------------------------------------\n    // Convert to Json graph and back again\n    json = f.to_json();\n    f.from_json(json);\n    // -----------------------------------------------------------------------\n    //\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 4;\n    //\n    // set independent variables and parameters so all comparisons true\n    x[0] = 3.0;\n    p[0] = x[0];\n    p[1] = x[0] + 1.0;\n    p[2] = x[0] + 1.0;\n    p[3] = x[0] + 1.0;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    //\n    // check that all comparisons are true\n    ok &= f.compare_change_number() == 0;\n    //\n    // case where all the comparisons are false\n    p[0] = x[0] - 1.0;\n    p[1] = x[0] - 1.0;\n    p[2] = x[0] - 1.0;\n    p[3] = x[0];\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    ok &= f.compare_change_number() == 4;\n    //\n    return ok;\n}\n// ===========================================================================\nbool acosh_op(void)\n{   bool ok = true;\n    using CppAD::vector;\n    using CppAD::AD;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    //\n    // AD graph example\n    // node_1 : p[0]\n    // node_2 : x[0]\n    // node_3 : c[0]\n    // node_4 : acosh(p[0])\n    // node_5 : acosh(x[0])\n    // node_6 : acosh(c[0])\n    // node_7 : acosh(p[0]) + acosh(x[0]) + acosh(c[0])\n    // y[0]   = acosh(p[0]) + acosh(x[0]) + acosh(c[0])\n    // use single quote to avoid having to escape double quote\n    std::string json =\n        \"{\\n\"\n        \"   'function_name'  : 'acosh_op example',\\n\"\n        \"   'op_define_vec'  : [ 2, [\\n\"\n        \"       { 'op_code':1, 'name':'acosh', 'n_arg':1 } ,\\n\"\n        \"       { 'op_code':2, 'name':'sum'              } ]\\n\"\n        \"   ],\\n\"\n        \"   'n_dynamic_ind'  : 1,\\n\"\n        \"   'n_variable_ind' : 1,\\n\"\n        \"   'constant_vec'   : [ 1, [ 1.3 ] ],\\n\" // c[0]\n        \"   'op_usage_vec'   : [ 4, [\\n\"\n        \"       [ 1, 1]                ,\\n\" // acosh(p0)\n        \"       [ 1, 2]                ,\\n\" // acosh(x0)\n        \"       [ 1, 3]                ,\\n\" // acosh(c0)\n        \"       [ 2, 1, 3, [4, 5, 6] ] ]\\n\" // acosh(p0)+acosh(x0)+acosh(c0)\n        \"   ],\\n\"\n        \"   'dependent_vec' : [ 1, [7] ] \\n\"\n        \"}\\n\";\n    // Convert the single quote to double quote\n    for(size_t i = 0; i < json.size(); ++i)\n        if( json[i] == '\\'' ) json[i] = '\"';\n    //\n    // f(x, p) = acosh(p0) + acosh(x0) + acosh(c0)\n    CppAD::ADFun<double> f;\n    f.from_json(json);\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 1;\n    //\n    // value of constant in function\n    vector<double> c(1);\n    c[0] = 1.3;\n    //\n    // set independent variables and parameters\n    vector<double> p(1), x(1);\n    p[0] = 1.1;\n    x[0] = 1.2;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    vector<double> y = f.Forward(0, x);\n    //\n    // check result\n    double check = CppAD::acosh(p[0]) + CppAD::acosh(x[0]) + CppAD::acosh(c[0]);\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n    //\n    // Convert to Json graph and back again\n    json = f.to_json();\n    f.from_json(json);\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    //\n    // check result\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n    //\n    return ok;\n}\n// ---------------------------------------------------------------------------\nbool log1p_op(void)\n{   bool ok = true;\n    using CppAD::vector;\n    using CppAD::AD;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    //\n    // AD graph example\n    // node_1 : p[0]\n    // node_2 : x[0]\n    // node_3 : c[0]\n    // node_4 : log1p(p[0])\n    // node_5 : log1p(x[0])\n    // node_6 : log1p(c[0])\n    // node_7 : log1p(p[0]) + log1p(x[0]) + log1p(c[0])\n    // y[0]   = log1p(p[0]) + log1p(x[0]) + log1p(c[0])\n    // use single quote to avoid having to escape double quote\n    std::string json =\n        \"{\\n\"\n        \"   'function_name'  : 'log1p_op example',\\n\"\n        \"   'op_define_vec'  : [ 2, [\\n\"\n        \"       { 'op_code':1, 'name':'log1p', 'n_arg':1 } ,\\n\"\n        \"       { 'op_code':2, 'name':'sum'               } ]\\n\"\n        \"   ],\\n\"\n        \"   'n_dynamic_ind'  : 1,\\n\"\n        \"   'n_variable_ind' : 1,\\n\"\n        \"   'constant_vec'   : [ 1, [ 0.3 ] ],\\n\" // c[0]\n        \"   'op_usage_vec'   : [ 4, [\\n\"\n        \"       [ 1, 1]                ,\\n\" // log1p(p0)\n        \"       [ 1, 2]                ,\\n\" // log1p(x0)\n        \"       [ 1, 3]                ,\\n\" // log1p(c0)\n        \"       [ 2, 1, 3, [4, 5, 6] ] ]\\n\" // log1p(p0)+log1p(x0)+log1p(c0)\n        \"   ],\\n\"\n        \"   'dependent_vec' : [ 1, [7] ] \\n\"\n        \"}\\n\";\n    // Convert the single quote to double quote\n    for(size_t i = 0; i < json.size(); ++i)\n        if( json[i] == '\\'' ) json[i] = '\"';\n    //\n    // f(x, p) = log1p(p0) + log1p(x0) + log1p(c0)\n    CppAD::ADFun<double> f;\n    f.from_json(json);\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 1;\n    //\n    // value of constant in function\n    vector<double> c(1);\n    c[0] = 0.3;\n    //\n    // set independent variables and parameters\n    vector<double> p(1), x(1);\n    p[0] = -0.1;\n    x[0] = 0.2;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    vector<double> y = f.Forward(0, x);\n    //\n    // check result\n    double check = CppAD::log1p(p[0]) + CppAD::log1p(x[0]) + CppAD::log1p(c[0]);\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n    //\n    // Convert to Json graph and back again\n    json = f.to_json();\n    f.from_json(json);\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    //\n    // check result\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n    //\n    return ok;\n}\n// ---------------------------------------------------------------------------\nbool expm1_op(void)\n{   bool ok = true;\n    using CppAD::vector;\n    using CppAD::AD;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    //\n    // AD graph example\n    // node_1 : p[0]\n    // node_2 : x[0]\n    // node_3 : c[0]\n    // node_4 : expm1(p[0])\n    // node_5 : expm1(x[0])\n    // node_6 : expm1(c[0])\n    // node_7 : expm1(p[0]) + expm1(x[0]) + expm1(c[0])\n    // y[0]   = expm1(p[0]) + expm1(x[0]) + expm1(c[0])\n    // use single quote to avoid having to escape double quote\n    std::string json =\n        \"{\\n\"\n        \"   'function_name'  : 'expm1_op example',\\n\"\n        \"   'op_define_vec'  : [ 2, [\\n\"\n        \"       { 'op_code':1, 'name':'expm1', 'n_arg':1 } ,\\n\"\n        \"       { 'op_code':2, 'name':'sum'              } ]\\n\"\n        \"   ],\\n\"\n        \"   'n_dynamic_ind'  : 1,\\n\"\n        \"   'n_variable_ind' : 1,\\n\"\n        \"   'constant_vec'   : [ 1, [ 0.3 ] ],\\n\" // c[0]\n        \"   'op_usage_vec'   : [ 4, [\\n\"\n        \"       [ 1, 1]                ,\\n\" // expm1(p0)\n        \"       [ 1, 2]                ,\\n\" // expm1(x0)\n        \"       [ 1, 3]                ,\\n\" // expm1(c0)\n        \"       [ 2, 1, 3, [4, 5, 6] ] ]\\n\" // expm1(p0)+expm1(x0)+expm1(c0)\n        \"   ],\\n\"\n        \"   'dependent_vec' : [ 1, [7] ] \\n\"\n        \"}\\n\";\n    // Convert the single quote to double quote\n    for(size_t i = 0; i < json.size(); ++i)\n        if( json[i] == '\\'' ) json[i] = '\"';\n    //\n    // f(x, p) = expm1(p0) + expm1(x0) + expm1(c0)\n    CppAD::ADFun<double> f;\n    f.from_json(json);\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 1;\n    //\n    // value of constant in function\n    vector<double> c(1);\n    c[0] = 0.3;\n    //\n    // set independent variables and parameters\n    vector<double> p(1), x(1);\n    p[0] = -0.1;\n    x[0] = 0.2;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    vector<double> y = f.Forward(0, x);\n    //\n    // check result\n    double check = CppAD::expm1(p[0]) + CppAD::expm1(x[0]) + CppAD::expm1(c[0]);\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n    //\n    // Convert to Json graph and back again\n    json = f.to_json();\n    f.from_json(json);\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    //\n    // check result\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n    //\n    return ok;\n}\n// ---------------------------------------------------------------------------\nbool erfc_op(void)\n{   bool ok = true;\n    using CppAD::vector;\n    using CppAD::AD;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    //\n    // AD graph example\n    // node_1 : p[0]\n    // node_2 : x[0]\n    // node_3 : c[0]\n    // node_4 : erfc(p[0])\n    // node_5 : erfc(x[0])\n    // node_6 : erfc(c[0])\n    // node_7 : erfc(p[0]) + erfc(x[0]) + erfc(c[0])\n    // y[0]   = erfc(p[0]) + erfc(x[0]) + erfc(c[0])\n    // use single quote to avoid having to escape double quote\n    std::string json =\n        \"{\\n\"\n        \"   'function_name'  : 'erfc_op example',\\n\"\n        \"   'op_define_vec'  : [ 2, [\\n\"\n        \"       { 'op_code':1, 'name':'erfc', 'n_arg':1 } ,\\n\"\n        \"       { 'op_code':2, 'name':'sum'             } ]\\n\"\n        \"   ],\\n\"\n        \"   'n_dynamic_ind'  : 1,\\n\"\n        \"   'n_variable_ind' : 1,\\n\"\n        \"   'constant_vec'   : [ 1, [ 0.3 ] ],\\n\" // c[0]\n        \"   'op_usage_vec'   : [ 4, [\\n\"\n        \"       [ 1, 1]                ,\\n\" // erfc(p0)\n        \"       [ 1, 2]                ,\\n\" // erfc(x0)\n        \"       [ 1, 3]                ,\\n\" // erfc(c0)\n        \"       [ 2, 1, 3, [4, 5, 6] ] ]\\n\" // erfc(p0)+erfc(x0)+erfc(c0)\n        \"   ],\\n\"\n        \"   'dependent_vec' : [ 1, [7] ] \\n\"\n        \"}\\n\";\n    // Convert the single quote to double quote\n    for(size_t i = 0; i < json.size(); ++i)\n        if( json[i] == '\\'' ) json[i] = '\"';\n    //\n    // f(x, p) = erfc(p0) + erfc(x0) + erfc(c0)\n    CppAD::ADFun<double> f;\n    f.from_json(json);\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 1;\n    //\n    // value of constant in function\n    vector<double> c(1);\n    c[0] = 0.3;\n    //\n    // set independent variables and parameters\n    vector<double> p(1), x(1);\n    p[0] = -0.1;\n    x[0] = 0.2;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    vector<double> y = f.Forward(0, x);\n    //\n    // check result\n    double check = CppAD::erfc(p[0]) + CppAD::erfc(x[0]) + CppAD::erfc(c[0]);\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n    //\n    // Convert to Json graph and back again\n    json = f.to_json();\n    f.from_json(json);\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    //\n    // check result\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n    //\n    return ok;\n}\n// ---------------------------------------------------------------------------\nbool erf_op(void)\n{   bool ok = true;\n    using CppAD::vector;\n    using CppAD::AD;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    //\n    // AD graph example\n    // node_1 : p[0]\n    // node_2 : x[0]\n    // node_3 : c[0]\n    // node_4 : erf(p[0])\n    // node_5 : erf(x[0])\n    // node_6 : erf(c[0])\n    // node_7 : erf(p[0]) + erf(x[0]) + erf(c[0])\n    // y[0]   = erf(p[0]) + erf(x[0]) + erf(c[0])\n    // use single quote to avoid having to escape double quote\n    std::string json =\n        \"{\\n\"\n        \"   'function_name'  : 'erf_op example',\\n\"\n        \"   'op_define_vec'  : [ 2, [\\n\"\n        \"       { 'op_code':1, 'name':'erf', 'n_arg':1 } ,\\n\"\n        \"       { 'op_code':2, 'name':'sum'            } ]\\n\"\n        \"   ],\\n\"\n        \"   'n_dynamic_ind'  : 1,\\n\"\n        \"   'n_variable_ind' : 1,\\n\"\n        \"   'constant_vec'   : [ 1, [ 0.3 ] ],\\n\" // c[0]\n        \"   'op_usage_vec'   : [ 4, [\\n\"\n        \"       [ 1, 1]                ,\\n\" // erf(p0)\n        \"       [ 1, 2]                ,\\n\" // erf(x0)\n        \"       [ 1, 3]                ,\\n\" // erf(c0)\n        \"       [ 2, 1, 3, [4, 5, 6] ] ]\\n\" // erf(p0)+erf(x0)+erf(c0)\n        \"   ],\\n\"\n        \"   'dependent_vec' : [ 1, [7] ] \\n\"\n        \"}\\n\";\n    // Convert the single quote to double quote\n    for(size_t i = 0; i < json.size(); ++i)\n        if( json[i] == '\\'' ) json[i] = '\"';\n    //\n    // f(x, p) = erf(p0) + erf(x0) + erf(c0)\n    CppAD::ADFun<double> f;\n    f.from_json(json);\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 1;\n    //\n    // value of constant in function\n    vector<double> c(1);\n    c[0] = 0.3;\n    //\n    // set independent variables and parameters\n    vector<double> p(1), x(1);\n    p[0] = -0.1;\n    x[0] = 0.2;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    vector<double> y = f.Forward(0, x);\n    //\n    // check result\n    double check = CppAD::erf(p[0]) + CppAD::erf(x[0]) + CppAD::erf(c[0]);\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n    //\n    // Convert to Json graph and back again\n    json = f.to_json();\n    f.from_json(json);\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    //\n    // check result\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n    //\n    return ok;\n}\n// ---------------------------------------------------------------------------\nbool atanh_op(void)\n{   bool ok = true;\n    using CppAD::vector;\n    using CppAD::AD;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    //\n    // AD graph example\n    // node_1 : p[0]\n    // node_2 : x[0]\n    // node_3 : c[0]\n    // node_4 : atanh(p[0])\n    // node_5 : atanh(x[0])\n    // node_6 : atanh(c[0])\n    // node_7 : atanh(p[0]) + atanh(x[0]) + atanh(c[0])\n    // y[0]   = atanh(p[0]) + atanh(x[0]) + atanh(c[0])\n    // use single quote to avoid having to escape double quote\n    std::string json =\n        \"{\\n\"\n        \"   'function_name'  : 'atanh_op example',\\n\"\n        \"   'op_define_vec'  : [ 2, [\\n\"\n        \"       { 'op_code':1, 'name':'atanh', 'n_arg':1 } ,\\n\"\n        \"       { 'op_code':2, 'name':'sum'              } ]\\n\"\n        \"   ],\\n\"\n        \"   'n_dynamic_ind'  : 1,\\n\"\n        \"   'n_variable_ind' : 1,\\n\"\n        \"   'constant_vec'   : [ 1, [ 0.3 ] ],\\n\" // c[0]\n        \"   'op_usage_vec'   : [ 4, [\\n\"\n        \"       [ 1, 1]                ,\\n\" // atanh(p0)\n        \"       [ 1, 2]                ,\\n\" // atanh(x0)\n        \"       [ 1, 3]                ,\\n\" // atanh(c0)\n        \"       [ 2, 1, 3, [4, 5, 6] ] ]\\n\" // atanh(p0)+atanh(x0)+atanh(c0)\n        \"   ],\\n\"\n        \"   'dependent_vec' : [ 1, [7] ] \\n\"\n        \"}\\n\";\n    // Convert the single quote to double quote\n    for(size_t i = 0; i < json.size(); ++i)\n        if( json[i] == '\\'' ) json[i] = '\"';\n    //\n    // f(x, p) = atanh(p0) + atanh(x0) + atanh(c0)\n    CppAD::ADFun<double> f;\n    f.from_json(json);\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 1;\n    //\n    // value of constant in function\n    vector<double> c(1);\n    c[0] = 0.3;\n    //\n    // set independent variables and parameters\n    vector<double> p(1), x(1);\n    p[0] = -0.1;\n    x[0] = 0.2;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    vector<double> y = f.Forward(0, x);\n    //\n    // check result\n    double check = CppAD::atanh(p[0]) + CppAD::atanh(x[0]) + CppAD::atanh(c[0]);\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n    //\n    // Convert to Json graph and back again\n    json = f.to_json();\n    f.from_json(json);\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    //\n    // check result\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n    //\n    return ok;\n}\n// ---------------------------------------------------------------------------\nbool asinh_op(void)\n{   bool ok = true;\n    using CppAD::vector;\n    using CppAD::AD;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    //\n    // AD graph example\n    // node_1 : p[0]\n    // node_2 : x[0]\n    // node_3 : c[0]\n    // node_4 : asinh(p[0])\n    // node_5 : asinh(x[0])\n    // node_6 : asinh(c[0])\n    // node_7 : asinh(p[0]) + asinh(x[0]) + asinh(c[0])\n    // y[0]   = asinh(p[0]) + asinh(x[0]) + asinh(c[0])\n    // use single quote to avoid having to escape double quote\n    std::string json =\n        \"{\\n\"\n        \"   'function_name'  : 'asinh_op example',\\n\"\n        \"   'op_define_vec'  : [ 2, [\\n\"\n        \"       { 'op_code':1, 'name':'asinh', 'n_arg':1 } ,\\n\"\n        \"       { 'op_code':2, 'name':'sum'              } ]\\n\"\n        \"   ],\\n\"\n        \"   'n_dynamic_ind'  : 1,\\n\"\n        \"   'n_variable_ind' : 1,\\n\"\n        \"   'constant_vec'   : [ 1, [ 0.3 ] ],\\n\" // c[0]\n        \"   'op_usage_vec'   : [ 4, [\\n\"\n        \"       [ 1, 1]                ,\\n\" // asinh(p0)\n        \"       [ 1, 2]                ,\\n\" // asinh(x0)\n        \"       [ 1, 3]                ,\\n\" // asinh(c0)\n        \"       [ 2, 1, 3, [4, 5, 6] ] ]\\n\" // asinh(p0)+asinh(x0)+asinh(c0)\n        \"   ],\\n\"\n        \"   'dependent_vec' : [ 1, [7] ] \\n\"\n        \"}\\n\";\n    // Convert the single quote to double quote\n    for(size_t i = 0; i < json.size(); ++i)\n        if( json[i] == '\\'' ) json[i] = '\"';\n    //\n    // f(x, p) = asinh(p0) + asinh(x0) + asinh(c0)\n    CppAD::ADFun<double> f;\n    f.from_json(json);\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 1;\n    //\n    // value of constant in function\n    vector<double> c(1);\n    c[0] = 0.3;\n    //\n    // set independent variables and parameters\n    vector<double> p(1), x(1);\n    p[0] = -0.1;\n    x[0] = 0.2;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    vector<double> y = f.Forward(0, x);\n    //\n    // check result\n    double check = CppAD::asinh(p[0]) + CppAD::asinh(x[0]) + CppAD::asinh(c[0]);\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n    //\n    // Convert to Json graph and back again\n    json = f.to_json();\n    f.from_json(json);\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    //\n    // check result\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n    //\n    return ok;\n}\n// ===========================================================================\nbool tan_op(void)\n{   bool ok = true;\n    using CppAD::vector;\n    using CppAD::AD;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    //\n    // AD graph example\n    // node_1 : p[0]\n    // node_2 : x[0]\n    // node_3 : c[0]\n    // node_4 : tan(p[0])\n    // node_5 : tan(x[0])\n    // node_6 : tan(c[0])\n    // node_7 : tan(p[0]) + tan(x[0]) + tan(c[0])\n    // y[0]   = tan(p[0]) + tan(x[0]) + tan(c[0])\n    // use single quote to avoid having to escape double quote\n    std::string json =\n        \"{\\n\"\n        \"   'function_name'  : 'tan_op example',\\n\"\n        \"   'op_define_vec'  : [ 2, [\\n\"\n        \"       { 'op_code':1, 'name':'tan', 'n_arg':1 } ,\\n\"\n        \"       { 'op_code':2, 'name':'sum'            } ]\\n\"\n        \"   ],\\n\"\n        \"   'n_dynamic_ind'  : 1,\\n\"\n        \"   'n_variable_ind' : 1,\\n\"\n        \"   'constant_vec'   : [ 1, [ -0.1 ] ],\\n\" // c[0]\n        \"   'op_usage_vec'   : [ 4, [\\n\"\n        \"       [ 1, 1]                ,\\n\" // tan(p[0])\n        \"       [ 1, 2]                ,\\n\" // tan(x[0])\n        \"       [ 1, 3]                ,\\n\" // tan(c[0])\n        \"       [ 2, 1, 3, [4, 5, 6] ] ]\\n\" // tan(p[0])+tan(x[0])+tan(c[0])\n        \"   ],\\n\"\n        \"   'dependent_vec' : [ 1, [7] ] \\n\"\n        \"}\\n\";\n    // Convert the single quote to double quote\n    for(size_t i = 0; i < json.size(); ++i)\n        if( json[i] == '\\'' ) json[i] = '\"';\n    //\n    // f(x, p) = tan(p_0) + tan(x_0) + tan(c_0)\n    CppAD::ADFun<double> f;\n    f.from_json(json);\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 1;\n    //\n    // value of constant that is in function\n    vector<double> c(1);\n    c[0] = -0.1;\n    //\n    // set independent variables and parameters\n    vector<double> p(1), x(1);\n    p[0] = 0.2;\n    x[0] = 0.3;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    vector<double> y = f.Forward(0, x);\n    //\n    // check result\n    double check = std::tan(p[0]) + std::tan(x[0]) + std::tan(c[0]);\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n    //\n    // Convert to Json graph and back again\n    json = f.to_json();\n    f.from_json(json);\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    //\n    // check result\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n    //\n    return ok;\n}\n// ---------------------------------------------------------------------------\nbool tanh_op(void)\n{   bool ok = true;\n    using CppAD::vector;\n    using CppAD::AD;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    //\n    // AD graph example\n    // node_1 : p[0]\n    // node_2 : x[0]\n    // node_3 : c[0]\n    // node_4 : tanh(p[0])\n    // node_5 : tanh(x[0])\n    // node_6 : tanh(c[0])\n    // node_7 : tanh(p[0]) + tanh(x[0]) + tanh(c[0])\n    // y[0]   = tanh(p[0]) + tanh(x[0]) + tanh(c[0])\n    // use single quote to avoid having to escape double quote\n    std::string json =\n        \"{\\n\"\n        \"   'function_name'  : 'tanh_op example',\\n\"\n        \"   'op_define_vec'  : [ 2, [\\n\"\n        \"       { 'op_code':1, 'name':'tanh', 'n_arg':1 } ,\\n\"\n        \"       { 'op_code':2, 'name':'sum'             } ]\\n\"\n        \"   ],\\n\"\n        \"   'n_dynamic_ind'  : 1,\\n\"\n        \"   'n_variable_ind' : 1,\\n\"\n        \"   'constant_vec'   : [ 1, [ -0.1 ] ],\\n\" // c[0]\n        \"   'op_usage_vec'   : [ 4, [\\n\"\n        \"       [ 1, 1]                ,\\n\" // tanh(p[0])\n        \"       [ 1, 2]                ,\\n\" // tanh(x[0])\n        \"       [ 1, 3]                ,\\n\" // tanh(c[0])\n        \"       [ 2, 1, 3, [4, 5, 6] ] ]\\n\" // tanh(p[0])+tanh(x[0])+tanh(c[0])\n        \"   ],\\n\"\n        \"   'dependent_vec' : [ 1, [7] ] \\n\"\n        \"}\\n\";\n    // Convert the single quote to double quote\n    for(size_t i = 0; i < json.size(); ++i)\n        if( json[i] == '\\'' ) json[i] = '\"';\n    //\n    // f(x, p) = tanh(p_0) + tanh(x_0) + tanh(c_0)\n    CppAD::ADFun<double> f;\n    f.from_json(json);\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 1;\n    //\n    // value of constant in function\n    vector<double> c(1);\n    c[0] = -0.1;\n    //\n    // set independent variables and parameters\n    vector<double> p(1), x(1);\n    p[0] = 0.2;\n    x[0] = 0.3;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    vector<double> y = f.Forward(0, x);\n    //\n    // check result\n    double check = std::tanh(p[0]) + std::tanh(x[0]) + std::tanh(c[0]);\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n    //\n    // Convert to Json graph and back again\n    json = f.to_json();\n    f.from_json(json);\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    //\n    // check result\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n    //\n    return ok;\n}\n// ---------------------------------------------------------------------------\nbool sqrt_op(void)\n{   bool ok = true;\n    using CppAD::vector;\n    using CppAD::AD;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    //\n    // AD graph example\n    // node_1 : p[0]\n    // node_2 : x[0]\n    // node_3 : c[0]\n    // node_4 : sqrt(p[0])\n    // node_5 : sqrt(x[0])\n    // node_6 : sqrt(c[0])\n    // node_7 : sqrt(p[0]) + sqrt(x[0]) + sqrt(c[0])\n    // y[0]   = sqrt(p[0]) + sqrt(x[0]) + sqrt(c[0])\n    // use single quote to avoid having to escape double quote\n    std::string json =\n        \"{\\n\"\n        \"   'function_name'  : 'sqrt_op example',\\n\"\n        \"   'op_define_vec'  : [ 2, [\\n\"\n        \"       { 'op_code':1, 'name':'sqrt', 'n_arg':1 } ,\\n\"\n        \"       { 'op_code':2, 'name':'sum'             } ]\\n\"\n        \"   ],\\n\"\n        \"   'n_dynamic_ind'  : 1,\\n\"\n        \"   'n_variable_ind' : 1,\\n\"\n        \"   'constant_vec'   : [ 1, [ +0.1 ] ],\\n\" // c[0]\n        \"   'op_usage_vec'   : [ 4, [\\n\"\n        \"       [ 1, 1]                ,\\n\" // sqrt(p[0])\n        \"       [ 1, 2]                ,\\n\" // sqrt(x[0])\n        \"       [ 1, 3]                ,\\n\" // sqrt(c[0])\n        \"       [ 2, 1, 3, [4, 5, 6] ] ]\\n\" // sqrt(p[0])+sqrt(x[0])+sqrt(c[0])\n        \"   ],\\n\"\n        \"   'dependent_vec' : [ 1, [7] ] \\n\"\n        \"}\\n\";\n    // Convert the single quote to double quote\n    for(size_t i = 0; i < json.size(); ++i)\n        if( json[i] == '\\'' ) json[i] = '\"';\n    //\n    // f(x, p) = sqrt(p_0) + sqrt(x_0) + sqrt(c_0)\n    CppAD::ADFun<double> f;\n    f.from_json(json);\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 1;\n    //\n    // value of constant in function\n    vector<double> c(1);\n    c[0] = +0.1;\n    //\n    // set independent variables and parameters\n    vector<double> p(1), x(1);\n    p[0] = 0.2;\n    x[0] = 0.3;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    vector<double> y = f.Forward(0, x);\n    //\n    // check result\n    double check = std::sqrt(p[0]) + std::sqrt(x[0]) + std::sqrt(c[0]);\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n    //\n    // Convert to Json graph and back again\n    json = f.to_json();\n    f.from_json(json);\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    //\n    // check result\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n    //\n    return ok;\n}\n// ---------------------------------------------------------------------------\nbool sin_op(void)\n{   bool ok = true;\n    using CppAD::vector;\n    using CppAD::AD;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    //\n    // AD graph example\n    // node_1 : p[0]\n    // node_2 : x[0]\n    // node_3 : c[0]\n    // node_4 : sin(p[0])\n    // node_5 : sin(x[0])\n    // node_6 : sin(c[0])\n    // node_7 : sin(p[0]) + sin(x[0]) + sin(c[0])\n    // y[0]   = sin(p[0]) + sin(x[0]) + sin(c[0])\n    // use single quote to avoid having to escape double quote\n    std::string json =\n        \"{\\n\"\n        \"   'function_name'  : 'sin_op example',\\n\"\n        \"   'op_define_vec'  : [ 2, [\\n\"\n        \"       { 'op_code':1, 'name':'sin', 'n_arg':1 } ,\\n\"\n        \"       { 'op_code':2, 'name':'sum'            } ]\\n\"\n        \"   ],\\n\"\n        \"   'n_dynamic_ind'  : 1,\\n\"\n        \"   'n_variable_ind' : 1,\\n\"\n        \"   'constant_vec'   : [ 1, [ -0.1 ] ],\\n\" // c[0]\n        \"   'op_usage_vec'   : [ 4, [\\n\"\n        \"       [ 1, 1]                ,\\n\" // sin(p[0])\n        \"       [ 1, 2]                ,\\n\" // sin(x[0])\n        \"       [ 1, 3]                ,\\n\" // sin(c[0])\n        \"       [ 2, 1, 3, [4, 5, 6] ] ]\\n\" // sin(p[0])+sin(x[0])+sin(c[0])\n        \"   ],\\n\"\n        \"   'dependent_vec' : [ 1, [7] ] \\n\"\n        \"}\\n\";\n    // Convert the single quote to double quote\n    for(size_t i = 0; i < json.size(); ++i)\n        if( json[i] == '\\'' ) json[i] = '\"';\n    //\n    // f(x, p) = sin(p_0) + sin(x_0) + sin(c_0)\n    CppAD::ADFun<double> f;\n    f.from_json(json);\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 1;\n    //\n    // value of constant in function\n    vector<double> c(1);\n    c[0] = -0.1;\n    //\n    // set independent variables and parameters\n    vector<double> p(1), x(1);\n    p[0] = 0.2;\n    x[0] = 0.3;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    vector<double> y = f.Forward(0, x);\n    //\n    // check result\n    double check = std::sin(p[0]) + std::sin(x[0]) + std::sin(c[0]);\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n    //\n    // Convert to Json graph and back again\n    json = f.to_json();\n    f.from_json(json);\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    //\n    // check result\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n    //\n    return ok;\n}\n// ---------------------------------------------------------------------------\nbool sinh_op(void)\n{   bool ok = true;\n    using CppAD::vector;\n    using CppAD::AD;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    //\n    // AD graph example\n    // node_1 : p[0]\n    // node_2 : x[0]\n    // node_3 : c[0]\n    // node_4 : sinh(p[0])\n    // node_5 : sinh(x[0])\n    // node_6 : sinh(c[0])\n    // node_7 : sinh(p[0]) + sinh(x[0]) + sinh(c[0])\n    // y[0]   = sinh(p[0]) + sinh(x[0]) + sinh(c[0])\n    // use single quote to avoid having to escape double quote\n    std::string json =\n        \"{\\n\"\n        \"   'function_name'  : 'sinh_op example',\\n\"\n        \"   'op_define_vec'  : [ 2, [\\n\"\n        \"       { 'op_code':1, 'name':'sinh', 'n_arg':1 } ,\\n\"\n        \"       { 'op_code':2, 'name':'sum'             } ]\\n\"\n        \"   ],\\n\"\n        \"   'n_dynamic_ind'  : 1,\\n\"\n        \"   'n_variable_ind' : 1,\\n\"\n        \"   'constant_vec'   : [ 1, [ -0.1 ] ],\\n\" // c[0]\n        \"   'op_usage_vec'   : [ 4, [\\n\"\n        \"       [ 1, 1]                ,\\n\" // sinh(p[0])\n        \"       [ 1, 2]                ,\\n\" // sinh(x[0])\n        \"       [ 1, 3]                ,\\n\" // sinh(c[0])\n        \"       [ 2, 1, 3, [4, 5, 6] ] ]\\n\" // sinh(p[0])+sinh(x[0])+sinh(c[0])\n        \"   ],\\n\"\n        \"   'dependent_vec' : [ 1, [7] ] \\n\"\n        \"}\\n\";\n    // Convert the single quote to double quote\n    for(size_t i = 0; i < json.size(); ++i)\n        if( json[i] == '\\'' ) json[i] = '\"';\n    //\n    // f(x, p) = sinh(p_0) + sinh(x_0) + sinh(c_0)\n    CppAD::ADFun<double> f;\n    f.from_json(json);\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 1;\n    //\n    // value of constant in function\n    vector<double> c(1);\n    c[0] = -0.1;\n    //\n    // set independent variables and parameters\n    vector<double> p(1), x(1);\n    p[0] = 0.2;\n    x[0] = 0.3;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    vector<double> y = f.Forward(0, x);\n    //\n    // check result\n    double check = std::sinh(p[0]) + std::sinh(x[0]) + std::sinh(c[0]);\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n    //\n    // Convert to Json graph and back again\n    json = f.to_json();\n    f.from_json(json);\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    //\n    // check result\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n    //\n    return ok;\n}\n// ---------------------------------------------------------------------------\nbool sign_op(void)\n{   bool ok = true;\n    using CppAD::vector;\n    using CppAD::AD;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    //\n    // AD graph example\n    // node_1 : p[0]\n    // node_2 : x[0]\n    // node_3 : c[0]\n    // node_4 : sign(p[0])\n    // node_5 : sign(x[0])\n    // node_6 : sign(c[0])\n    // node_7 : sign(p[0]) + sign(x[0]) + sign(c[0])\n    // y[0]   = sign(p[0]) + sign(x[0]) + sign(c[0])\n    // use single quote to avoid having to escape double quote\n    std::string json =\n        \"{\\n\"\n        \"   'function_name'  : 'sign_op example',\\n\"\n        \"   'op_define_vec'  : [ 2, [\\n\"\n        \"       { 'op_code':1, 'name':'sign', 'n_arg':1 } ,\\n\"\n        \"       { 'op_code':2, 'name':'sum'             } ]\\n\"\n        \"   ],\\n\"\n        \"   'n_dynamic_ind'  : 1,\\n\"\n        \"   'n_variable_ind' : 1,\\n\"\n        \"   'constant_vec'   : [ 1, [ -0.1 ] ],\\n\" // c[0]\n        \"   'op_usage_vec'   : [ 4, [\\n\"\n        \"       [ 1, 1]                ,\\n\" // sign(p[0])\n        \"       [ 1, 2]                ,\\n\" // sign(x[0])\n        \"       [ 1, 3]                ,\\n\" // sign(c[0])\n        \"       [ 2, 1, 3, [4, 5, 6] ] ]\\n\" // sign(p[0])+sign(x[0])+sign(c[0])\n        \"   ],\\n\"\n        \"   'dependent_vec' : [ 1, [7] ] \\n\"\n        \"}\\n\";\n    // Convert the single quote to double quote\n    for(size_t i = 0; i < json.size(); ++i)\n        if( json[i] == '\\'' ) json[i] = '\"';\n    //\n    // f(x, p) = sign(p_0) + sign(x_0) + sign(c_0)\n    CppAD::ADFun<double> f;\n    f.from_json(json);\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 1;\n    //\n    // value of constant in function\n    vector<double> c(1);\n    c[0] = -0.1;\n    //\n    // set independent variables and parameters\n    vector<double> p(1), x(1);\n    p[0] = 0.2;\n    x[0] = 0.3;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    vector<double> y = f.Forward(0, x);\n    //\n    // check result\n    double check = CppAD::sign(p[0]) + CppAD::sign(x[0]) + CppAD::sign(c[0]);\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n    //\n    // Convert to Json graph and back again\n    json = f.to_json();\n    f.from_json(json);\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    //\n    // check result\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n    //\n    return ok;\n}\n// ---------------------------------------------------------------------------\nbool log_op(void)\n{   bool ok = true;\n    using CppAD::vector;\n    using CppAD::AD;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    //\n    // AD graph example\n    // node_1 : p[0]\n    // node_2 : x[0]\n    // node_3 : c[0]\n    // node_4 : log(p[0])\n    // node_5 : log(x[0])\n    // node_6 : log(c[0])\n    // node_7 : log(p[0]) + log(x[0]) + log(c[0])\n    // y[0]   = log(p[0]) + log(x[0]) + log(c[0])\n    // use single quote to avoid having to escape double quote\n    std::string json =\n        \"{\\n\"\n        \"   'function_name'  : 'log_op example',\\n\"\n        \"   'op_define_vec'  : [ 2, [\\n\"\n        \"       { 'op_code':1, 'name':'log', 'n_arg':1 } ,\\n\"\n        \"       { 'op_code':2, 'name':'sum'            } ]\\n\"\n        \"   ],\\n\"\n        \"   'n_dynamic_ind'  : 1,\\n\"\n        \"   'n_variable_ind' : 1,\\n\"\n        \"   'constant_vec'   : [ 1, [ +0.1 ] ],\\n\" // c[0]\n        \"   'op_usage_vec'   : [ 4, [\\n\"\n        \"       [ 1, 1]                ,\\n\" // log(p[0])\n        \"       [ 1, 2]                ,\\n\" // log(x[0])\n        \"       [ 1, 3]                ,\\n\" // log(c[0])\n        \"       [ 2, 1, 3, [4, 5, 6] ] ]\\n\" // log(p[0])+log(x[0])+log(c[0])\n        \"   ],\\n\"\n        \"   'dependent_vec' : [ 1, [7] ] \\n\"\n        \"}\\n\";\n    // Convert the single quote to double quote\n    for(size_t i = 0; i < json.size(); ++i)\n        if( json[i] == '\\'' ) json[i] = '\"';\n    //\n    // f(x, p) = log(p_0) + log(x_0) + log(c_0)\n    CppAD::ADFun<double> f;\n    f.from_json(json);\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 1;\n    //\n    // value of constant in function\n    vector<double> c(1);\n    c[0] = +0.1;\n    //\n    // set independent variables and parameters\n    vector<double> p(1), x(1);\n    p[0] = 0.2;\n    x[0] = 0.3;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    vector<double> y = f.Forward(0, x);\n    //\n    // check result\n    double check = std::log(p[0]) + std::log(x[0]) + std::log(c[0]);\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n    //\n    // Convert to Json graph and back again\n    json = f.to_json();\n    f.from_json(json);\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    //\n    // check result\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n    //\n    return ok;\n}\n// ---------------------------------------------------------------------------\nbool exp_op(void)\n{   bool ok = true;\n    using CppAD::vector;\n    using CppAD::AD;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    //\n    // AD graph example\n    // node_1 : p[0]\n    // node_2 : x[0]\n    // node_3 : c[0]\n    // node_4 : exp(p[0])\n    // node_5 : exp(x[0])\n    // node_6 : exp(c[0])\n    // node_7 : exp(p[0]) + exp(x[0]) + exp(c[0])\n    // y[0]   = exp(p[0]) + exp(x[0]) + exp(c[0])\n    // use single quote to avoid having to escape double quote\n    std::string json =\n        \"{\\n\"\n        \"   'function_name'  : 'exp_op example',\\n\"\n        \"   'op_define_vec'  : [ 2, [\\n\"\n        \"       { 'op_code':1, 'name':'exp', 'n_arg':1 } ,\\n\"\n        \"       { 'op_code':2, 'name':'sum'            } ]\\n\"\n        \"   ],\\n\"\n        \"   'n_dynamic_ind'  : 1,\\n\"\n        \"   'n_variable_ind' : 1,\\n\"\n        \"   'constant_vec'   : [ 1, [ -0.1 ] ],\\n\" // c[0]\n        \"   'op_usage_vec'   : [ 4, [\\n\"\n        \"       [ 1, 1]                ,\\n\" // exp(p[0])\n        \"       [ 1, 2]                ,\\n\" // exp(x[0])\n        \"       [ 1, 3]                ,\\n\" // exp(c[0])\n        \"       [ 2, 1, 3, [4, 5, 6] ] ]\\n\" // exp(p[0])+exp(x[0])+exp(c[0])\n        \"   ],\\n\"\n        \"   'dependent_vec' : [ 1, [7] ] \\n\"\n        \"}\\n\";\n    // Convert the single quote to double quote\n    for(size_t i = 0; i < json.size(); ++i)\n        if( json[i] == '\\'' ) json[i] = '\"';\n    //\n    // f(x, p) = exp(p_0) + exp(x_0) + exp(c_0)\n    CppAD::ADFun<double> f;\n    f.from_json(json);\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 1;\n    //\n    // value of constant in function\n    vector<double> c(1);\n    c[0] = -0.1;\n    //\n    // set independent variables and parameters\n    vector<double> p(1), x(1);\n    p[0] = 0.2;\n    x[0] = 0.3;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    vector<double> y = f.Forward(0, x);\n    //\n    // check result\n    double check = std::exp(p[0]) + std::exp(x[0]) + std::exp(c[0]);\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n    //\n    // Convert to Json graph and back again\n    json = f.to_json();\n    f.from_json(json);\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    //\n    // check result\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n    //\n    return ok;\n}\n// ---------------------------------------------------------------------------\nbool cos_op(void)\n{   bool ok = true;\n    using CppAD::vector;\n    using CppAD::AD;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    //\n    // AD graph example\n    // node_1 : p[0]\n    // node_2 : x[0]\n    // node_3 : c[0]\n    // node_4 : cos(p[0])\n    // node_5 : cos(x[0])\n    // node_6 : cos(c[0])\n    // node_7 : cos(p[0]) + cos(x[0]) + cos(c[0])\n    // y[0]   = cos(p[0]) + cos(x[0]) + cos(c[0])\n    // use single quote to avoid having to escape double quote\n    std::string json =\n        \"{\\n\"\n        \"   'function_name'  : 'cos_op example',\\n\"\n        \"   'op_define_vec'  : [ 2, [\\n\"\n        \"       { 'op_code':1, 'name':'cos', 'n_arg':1 } ,\\n\"\n        \"       { 'op_code':2, 'name':'sum'            } ]\\n\"\n        \"   ],\\n\"\n        \"   'n_dynamic_ind'  : 1,\\n\"\n        \"   'n_variable_ind' : 1,\\n\"\n        \"   'constant_vec'   : [ 1, [ -0.1 ] ],\\n\" // c[0]\n        \"   'op_usage_vec'   : [ 4, [\\n\"\n        \"       [ 1, 1]                ,\\n\" // cos(p[0])\n        \"       [ 1, 2]                ,\\n\" // cos(x[0])\n        \"       [ 1, 3]                ,\\n\" // cos(c[0])\n        \"       [ 2, 1, 3, [4, 5, 6] ] ]\\n\" // cos(p[0])+cos(x[0])+cos(c[0])\n        \"   ],\\n\"\n        \"   'dependent_vec' : [ 1, [7] ] \\n\"\n        \"}\\n\";\n    // Convert the single quote to double quote\n    for(size_t i = 0; i < json.size(); ++i)\n        if( json[i] == '\\'' ) json[i] = '\"';\n    //\n    // f(x, p) = cos(p_0) + cos(x_0) + cos(c_0)\n    CppAD::ADFun<double> f;\n    f.from_json(json);\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 1;\n    //\n    // value of constant in function\n    vector<double> c(1);\n    c[0] = -0.1;\n    //\n    // set independent variables and parameters\n    vector<double> p(1), x(1);\n    p[0] = 0.2;\n    x[0] = 0.3;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    vector<double> y = f.Forward(0, x);\n    //\n    // check result\n    double check = std::cos(p[0]) + std::cos(x[0]) + std::cos(c[0]);\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n    //\n    // Convert to Json graph and back again\n    json = f.to_json();\n    f.from_json(json);\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    //\n    // check result\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n    //\n    return ok;\n}\n// ---------------------------------------------------------------------------\nbool cosh_op(void)\n{   bool ok = true;\n    using CppAD::vector;\n    using CppAD::AD;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    //\n    // AD graph example\n    // node_1 : p[0]\n    // node_2 : x[0]\n    // node_3 : c[0]\n    // node_4 : cosh(p[0])\n    // node_5 : cosh(x[0])\n    // node_6 : cosh(c[0])\n    // node_7 : cosh(p[0]) + cosh(x[0]) + cosh(c[0])\n    // y[0]   = cosh(p[0]) + cosh(x[0]) + cosh(c[0])\n    // use single quote to avoid having to escape double quote\n    std::string json =\n        \"{\\n\"\n        \"   'function_name'  : 'cosh_op example',\\n\"\n        \"   'op_define_vec'  : [ 2, [\\n\"\n        \"       { 'op_code':1, 'name':'cosh', 'n_arg':1 } ,\\n\"\n        \"       { 'op_code':2, 'name':'sum'             } ]\\n\"\n        \"   ],\\n\"\n        \"   'n_dynamic_ind'  : 1,\\n\"\n        \"   'n_variable_ind' : 1,\\n\"\n        \"   'constant_vec'   : [ 1, [ -0.1 ] ],\\n\" // c[0]\n        \"   'op_usage_vec'   : [ 4, [\\n\"\n        \"       [ 1, 1]                ,\\n\" // cosh(p[0])\n        \"       [ 1, 2]                ,\\n\" // cosh(x[0])\n        \"       [ 1, 3]                ,\\n\" // cosh(c[0])\n        \"       [ 2, 1, 3, [4, 5, 6] ] ]\\n\" // cosh(p[0])+cosh(x[0])+cosh(c[0])\n        \"   ],\\n\"\n        \"   'dependent_vec' : [ 1, [7] ] \\n\"\n        \"}\\n\";\n    // Convert the single quote to double quote\n    for(size_t i = 0; i < json.size(); ++i)\n        if( json[i] == '\\'' ) json[i] = '\"';\n    //\n    // f(x, p) = cosh(p_0) + cosh(x_0) + cosh(c_0)\n    CppAD::ADFun<double> f;\n    f.from_json(json);\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 1;\n    //\n    // value of constant in function\n    vector<double> c(1);\n    c[0] = -0.1;\n    //\n    // set independent variables and parameters\n    vector<double> p(1), x(1);\n    p[0] = 0.2;\n    x[0] = 0.3;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    vector<double> y = f.Forward(0, x);\n    //\n    // check result\n    double check = std::cosh(p[0]) + std::cosh(x[0]) + std::cosh(c[0]);\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n    //\n    // Convert to Json graph and back again\n    json = f.to_json();\n    f.from_json(json);\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    //\n    // check result\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n    //\n    return ok;\n}\n// ---------------------------------------------------------------------------\nbool atan_op(void)\n{   bool ok = true;\n    using CppAD::vector;\n    using CppAD::AD;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    //\n    // AD graph example\n    // node_1 : p[0]\n    // node_2 : x[0]\n    // node_3 : c[0]\n    // node_4 : atan(p[0])\n    // node_5 : atan(x[0])\n    // node_6 : atan(c[0])\n    // node_7 : atan(p[0]) + atan(x[0]) + atan(c[0])\n    // y[0]   = atan(p[0]) + atan(x[0]) + atan(c[0])\n    // use single quote to avoid having to escape double quote\n    std::string json =\n        \"{\\n\"\n        \"   'function_name'  : 'atan_op example',\\n\"\n        \"   'op_define_vec'  : [ 2, [\\n\"\n        \"       { 'op_code':1, 'name':'atan', 'n_arg':1 } ,\\n\"\n        \"       { 'op_code':2, 'name':'sum'             } ]\\n\"\n        \"   ],\\n\"\n        \"   'n_dynamic_ind'  : 1,\\n\"\n        \"   'n_variable_ind' : 1,\\n\"\n        \"   'constant_vec'   : [ 1, [ -0.1 ] ],\\n\" // c[0]\n        \"   'op_usage_vec'   : [ 4, [\\n\"\n        \"       [ 1, 1]                ,\\n\" // atan(p[0])\n        \"       [ 1, 2]                ,\\n\" // atan(x[0])\n        \"       [ 1, 3]                ,\\n\" // atan(c[0])\n        \"       [ 2, 1, 3, [4, 5, 6] ] ]\\n\" // atan(p[0])+atan(x[0])+atan(c[0])\n        \"   ],\\n\"\n        \"   'dependent_vec' : [ 1, [7] ] \\n\"\n        \"}\\n\";\n    // Convert the single quote to double quote\n    for(size_t i = 0; i < json.size(); ++i)\n        if( json[i] == '\\'' ) json[i] = '\"';\n    //\n    // f(x, p) = atan(p_0) + atan(x_0) + atan(c_0)\n    CppAD::ADFun<double> f;\n    f.from_json(json);\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 1;\n    //\n    // value of constant in function\n    vector<double> c(1);\n    c[0] = -0.1;\n    //\n    // set independent variables and parameters\n    vector<double> p(1), x(1);\n    p[0] = 0.2;\n    x[0] = 0.3;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    vector<double> y = f.Forward(0, x);\n    //\n    // check result\n    double check = std::atan(p[0]) + std::atan(x[0]) + std::atan(c[0]);\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n    //\n    // Convert to Json graph and back again\n    json = f.to_json();\n    f.from_json(json);\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    //\n    // check result\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n    //\n    return ok;\n}\n// ---------------------------------------------------------------------------\nbool asin_op(void)\n{   bool ok = true;\n    using CppAD::vector;\n    using CppAD::AD;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    //\n    // AD graph example\n    // node_1 : p[0]\n    // node_2 : x[0]\n    // node_3 : c[0]\n    // node_4 : asin(p[0])\n    // node_5 : asin(x[0])\n    // node_6 : asin(c[0])\n    // node_7 : asin(p[0]) + asin(x[0]) + asin(c[0])\n    // y[0]   = asin(p[0]) + asin(x[0]) + asin(c[0])\n    // use single quote to avoid having to escape double quote\n    std::string json =\n        \"{\\n\"\n        \"   'function_name'  : 'asin_op example',\\n\"\n        \"   'op_define_vec'  : [ 2, [\\n\"\n        \"       { 'op_code':1, 'name':'asin', 'n_arg':1 } ,\\n\"\n        \"       { 'op_code':2, 'name':'sum'             } ]\\n\"\n        \"   ],\\n\"\n        \"   'n_dynamic_ind'  : 1,\\n\"\n        \"   'n_variable_ind' : 1,\\n\"\n        \"   'constant_vec'   : [ 1, [ -0.1 ] ],\\n\" // c[0]\n        \"   'op_usage_vec'   : [ 4, [\\n\"\n        \"       [ 1, 1]                ,\\n\" // asin(p[0])\n        \"       [ 1, 2]                ,\\n\" // asin(x[0])\n        \"       [ 1, 3]                ,\\n\" // asin(c[0])\n        \"       [ 2, 1, 3, [4, 5, 6] ] ]\\n\" // asin(p[0])+asin(x[0])+asin(c[0])\n        \"   ],\\n\"\n        \"   'dependent_vec' : [ 1, [7] ] \\n\"\n        \"}\\n\";\n    // Convert the single quote to double quote\n    for(size_t i = 0; i < json.size(); ++i)\n        if( json[i] == '\\'' ) json[i] = '\"';\n    //\n    // f(x, p) = asin(p_0) + asin(x_0) + asin(c_0)\n    CppAD::ADFun<double> f;\n    f.from_json(json);\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 1;\n    //\n    // value of constant in function\n    vector<double> c(1);\n    c[0] = -0.1;\n    //\n    // set independent variables and parameters\n    vector<double> p(1), x(1);\n    p[0] = 0.2;\n    x[0] = 0.3;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    vector<double> y = f.Forward(0, x);\n    //\n    // check result\n    double check = std::asin(p[0]) + std::asin(x[0]) + std::asin(c[0]);\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n    //\n    // Convert to Json graph and back again\n    json = f.to_json();\n    f.from_json(json);\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    //\n    // check result\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n    //\n    return ok;\n}\n// ---------------------------------------------------------------------------\nbool acos_op(void)\n{   bool ok = true;\n    using CppAD::vector;\n    using CppAD::AD;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    //\n    // AD graph example\n    // node_1 : p[0]\n    // node_2 : x[0]\n    // node_3 : c[0]\n    // node_4 : acos(p[0])\n    // node_5 : acos(x[0])\n    // node_6 : acos(c[0])\n    // node_7 : acos(p[0]) + acos(x[0]) + acos(c[0])\n    // y[0]   = acos(p[0]) + acos(x[0]) + acos(c[0])\n    // use single quote to avoid having to escape double quote\n    std::string json =\n        \"{\\n\"\n        \"   'function_name'  : 'acos_op example',\\n\"\n        \"   'op_define_vec'  : [ 2, [\\n\"\n        \"       { 'op_code':1, 'name':'acos', 'n_arg':1 } ,\\n\"\n        \"       { 'op_code':2, 'name':'sum'             } ]\\n\"\n        \"   ],\\n\"\n        \"   'n_dynamic_ind'  : 1,\\n\"\n        \"   'n_variable_ind' : 1,\\n\"\n        \"   'constant_vec'   : [ 1, [ -0.1 ] ],\\n\" // c[0]\n        \"   'op_usage_vec'   : [ 4, [\\n\"\n        \"       [ 1, 1]                ,\\n\" // acos(p[0])\n        \"       [ 1, 2]                ,\\n\" // acos(x[0])\n        \"       [ 1, 3]                ,\\n\" // acos(c[0])\n        \"       [ 2, 1, 3, [4, 5, 6] ] ]\\n\" // acos(p[0])+acos(x[0])+acos(c[0])\n        \"   ],\\n\"\n        \"   'dependent_vec' : [ 1, [7] ] \\n\"\n        \"}\\n\";\n    // Convert the single quote to double quote\n    for(size_t i = 0; i < json.size(); ++i)\n        if( json[i] == '\\'' ) json[i] = '\"';\n    //\n    // f(x, p) = acos(p_0) + acos(x_0) + acos(c_0)\n    CppAD::ADFun<double> f;\n    f.from_json(json);\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 1;\n    //\n    // value of constant in function\n    vector<double> c(1);\n    c[0] = -0.1;\n    //\n    // set independent variables and parameters\n    vector<double> p(1), x(1);\n    p[0] = 0.2;\n    x[0] = 0.3;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    vector<double> y = f.Forward(0, x);\n    //\n    // check result\n    double check = std::acos(p[0]) + std::acos(x[0]) + std::acos(c[0]);\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n    //\n    // Convert to Json graph and back again\n    json = f.to_json();\n    f.from_json(json);\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    //\n    // check result\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n    //\n    return ok;\n}\n// ---------------------------------------------------------------------------\nbool abs_op(void)\n{   bool ok = true;\n    using CppAD::vector;\n    using CppAD::AD;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    //\n    // AD graph example\n    // node_1 : p[0]\n    // node_2 : x[0]\n    // node_3 : c[0]\n    // node_4 : abs(p[0])\n    // node_5 : abs(x[0])\n    // node_6 : abs(c[0])\n    // node_7 : abs(p[0]) + abs(x[0]) + abs(c[0])\n    // y[0]   = abs(p[0]) + abs(x[0]) + abs(c[0])\n    // use single quote to avoid having to escape double quote\n    std::string json =\n        \"{\\n\"\n        \"   'function_name'  : 'abs_op example',\\n\"\n        \"   'op_define_vec'  : [ 2, [\\n\"\n        \"       { 'op_code':1, 'name':'abs', 'n_arg':1 } ,\\n\"\n        \"       { 'op_code':2, 'name':'sum'            } ]\\n\"\n        \"   ],\\n\"\n        \"   'n_dynamic_ind'  : 1,\\n\"\n        \"   'n_variable_ind' : 1,\\n\"\n        \"   'constant_vec'   : [ 1, [ -0.1 ] ],\\n\" // c[0]\n        \"   'op_usage_vec'   : [ 4, [\\n\"\n        \"       [ 1, 1]                ,\\n\" // abs(p[0])\n        \"       [ 1, 2]                ,\\n\" // abs(x[0])\n        \"       [ 1, 3]                ,\\n\" // abs(c[0])\n        \"       [ 2, 1, 3, [4, 5, 6] ] ]\\n\" // abs(p[0])+abs(x[0])+abs(c[0])\n        \"   ],\\n\"\n        \"   'dependent_vec' : [ 1, [7] ] \\n\"\n        \"}\\n\";\n    // Convert the single quote to double quote\n    for(size_t i = 0; i < json.size(); ++i)\n        if( json[i] == '\\'' ) json[i] = '\"';\n    //\n    // f(x, p) = abs(p_0) + abs(x_0) + abs(c_0)\n    CppAD::ADFun<double> f;\n    f.from_json(json);\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 1;\n    //\n    // value of constant in function\n    vector<double> c(1);\n    c[0] = -0.1;\n    //\n    // set independent variables and parameters\n    vector<double> p(1), x(1);\n    p[0] = 0.2;\n    x[0] = 0.3;\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    vector<double> y = f.Forward(0, x);\n    //\n    // check result\n    double check = std::fabs(p[0]) + std::fabs(x[0]) + std::fabs(c[0]);\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n    //\n    // Convert to Json graph and back again\n    json = f.to_json();\n    // std::cout << graph;\n    f.from_json(json);\n    //\n    // compute y = f(x, p)\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    //\n    // check result\n    ok &= CppAD::NearEqual(y[0], check, eps99, eps99);\n    //\n    return ok;\n}\n// ---------------------------------------------------------------------------\n// Test conditional expression\nbool cexp_lt_variable(void)\n{   bool ok = true;\n    using CppAD::vector;\n    //\n    // An AD graph example\n    // node_1 : x[0]\n    // node_2 : x[1]\n    // node_3 : cexp_lt(x[0], x[1], x[1], x[0])\n    // y[0]   = max(x[0], x[1])\n    // use single quote to avoid having to escape double quote\n    std::string json =\n        \"{\\n\"\n        \"   'function_name'  : 'cexp_lt test',\\n\"\n        \"   'op_define_vec'  : [ 1, [\\n\"\n        \"       { 'op_code':1, 'name':'cexp_lt', 'n_arg':4 } ]\\n\"\n        \"   ],\\n\"\n        \"   'n_dynamic_ind'  : 0,\\n\"\n        \"   'n_variable_ind' : 2,\\n\"\n        \"   'constant_vec'   : [ 0, [] ],\\n\"\n        \"   'op_usage_vec'   : [ 1, [\\n\"\n        \"       [ 1, 1, 2, 2, 1 ] ] \\n\"\n        \"   ],\\n\"\n        \"   'dependent_vec'   : [ 1, [3] ] \\n\"\n        \"}\\n\";\n    // Convert the single quote to double quote\n    for(size_t i = 0; i < json.size(); ++i)\n        if( json[i] == '\\'' ) json[i] = '\"';\n    //\n    CppAD::ADFun<double> f;\n    f.from_json(json);\n    // ---------------------------------------------------------------------\n    ok &= f.Domain() == 2;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 0;\n    //\n    vector<double> x(2), y(1);\n    x[0] = 2.0;\n    x[1] = 3.0;\n    y = f.Forward(0, x);\n    ok &= y[0] == std::max(x[0], x[1]);\n    //\n    x[0] = 3.0;\n    x[1] = 2.0;\n    y = f.Forward(0, x);\n    ok &= y[0] == std::max(x[0], x[1]);\n    // ---------------------------------------------------------------------\n    json = f.to_json();\n    f.from_json(json);\n    // ---------------------------------------------------------------------\n    ok &= f.Domain() == 2;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 0;\n    //\n    x[0] = 2.0;\n    x[1] = 3.0;\n    y = f.Forward(0, x);\n    ok &= y[0] == std::max(x[0], x[1]);\n    //\n    x[0] = 3.0;\n    x[1] = 2.0;\n    y = f.Forward(0, x);\n    ok &= y[0] == std::max(x[0], x[1]);\n    //\n    // std::cout << graph;\n    return ok;\n}\n// Test conditional expression\nbool cexp_lt_constant(void)\n{   bool ok = true;\n    using CppAD::vector;\n    //\n    // An AD graph example\n    // node_1 : x[0]\n    // node_2 : c[0]\n    // node_3 : c[1]\n    // node_4 : cexp_lt(c[0], c[1], c[1], c[0])\n    // y[0]   = max(c[0], c[1])\n    // use single quote to avoid having to escape double quote\n    std::string json =\n        \"{\\n\"\n        \"   'function_name'  : 'cexp_lt test',\\n\"\n        \"   'op_define_vec'  : [ 1, [\\n\"\n        \"       { 'op_code':1, 'name':'cexp_lt', 'n_arg':4 } ]\\n\"\n        \"   ],\\n\"\n        \"   'n_dynamic_ind'  : 0,\\n\"\n        \"   'n_variable_ind' : 1,\\n\"\n        \"   'constant_vec'   : [ 2, [ 5.0, -5.0 ] ],\\n\"\n        \"   'op_usage_vec'   : [ 1, [\\n\"\n        \"       [ 1, 2, 3,  3, 2 ] ] \\n\"\n        \"   ],\\n\"\n        \"   'dependent_vec'   : [ 1, [4] ] \\n\"\n        \"}\\n\";\n    // Convert the single quote to double quote\n    for(size_t i = 0; i < json.size(); ++i)\n        if( json[i] == '\\'' ) json[i] = '\"';\n    //\n    CppAD::ADFun<double> f;\n    f.from_json(json);\n    // ---------------------------------------------------------------------\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 0;\n    //\n    vector<double> c(2), x(1), y(1);\n    c[0] = 5.0;\n    c[1] = -5.0;\n    y = f.Forward(0, x);\n    ok &= y[0] == std::max(c[0], c[1]);\n    // ---------------------------------------------------------------------\n    json = f.to_json();\n    f.from_json(json);\n    // ---------------------------------------------------------------------\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 0;\n    //\n    ok &= y[0] == std::max(c[0], c[1]);\n    // ---------------------------------------------------------------------\n    // std::cout << graph;\n    return ok;\n}\nbool cexp_lt_dynamic(void)\n{   bool ok = true;\n    using CppAD::vector;\n    //\n    // An AD graph example\n    // node_1 : p[0]\n    // node_2 : p[1]\n    // node_3 : x[0]\n    // node_4 : cexp_lt(p[0], p[1], p[1], p[0])\n    // y[0]   = max(p[0], p[1])\n    // use single quote to avoid having to escape double quote\n    std::string json =\n        \"{\\n\"\n        \"   'function_name'  : 'cexp_lt test',\\n\"\n        \"   'op_define_vec'  : [ 1, [\\n\"\n        \"       { 'op_code':1, 'name':'cexp_lt', 'n_arg':4 } ]\\n\"\n        \"   ],\\n\"\n        \"   'n_dynamic_ind'  : 2,\\n\"\n        \"   'n_variable_ind' : 1,\\n\"\n        \"   'constant_vec'   : [ 0, [ ] ],\\n\"\n        \"   'op_usage_vec'   : [ 1, [\\n\"\n        \"       [ 1, 1, 2, 2, 1 ] ] \\n\"\n        \"   ],\\n\"\n        \"   'dependent_vec'   : [ 1, [4] ] \\n\"\n        \"}\\n\";\n    // Convert the single quote to double quote\n    for(size_t i = 0; i < json.size(); ++i)\n        if( json[i] == '\\'' ) json[i] = '\"';\n    //\n    CppAD::ADFun<double> f;\n    f.from_json(json);\n    // ---------------------------------------------------------------------\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 2;\n    //\n    vector<double> p(2), x(1), y(1);\n    p[0] = 3.0;\n    p[1] = 2.0;\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    ok &= y[0] == std::max(p[0], p[1]);\n    // ---------------------------------------------------------------------\n    json = f.to_json();\n    // std::cout << graph;\n    f.from_json(json);\n    // ---------------------------------------------------------------------\n    ok &= f.Domain() == 1;\n    ok &= f.Range() == 1;\n    ok &= f.size_dyn_ind() == 2;\n    //\n    p[0] = 2.0;\n    p[1] = 3.0;\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    ok &= y[0] == std::max(p[0], p[1]);\n    // ---------------------------------------------------------------------\n    // std::cout << graph;\n    return ok;\n}\n// ---------------------------------------------------------------------------\n// Test atomic function that gets passed both variables and dynamic parameters\nbool atomic_both(void)\n{   bool ok = true;\n    using CppAD::vector;\n    using CppAD::AD;\n    //\n    // y[0] = p[0] * x[0]\n    vector< AD<double> > ap(1), ax(1), ay(1);\n    ap[0] = 2.0;\n    ax[0] = 3.0;\n    size_t abort_op_index = 0;\n    bool   record_compare = false;\n    CppAD::Independent(ax, abort_op_index, record_compare, ap);\n    ay[0] = ap[0] * ax[0];\n    CppAD::ADFun<double> f(ax, ay);\n    //\n    // Create a ckhpoint_two with name f(x; p).\n    // (This also creates an atomic_three function with same name.)\n    bool internal_bool    = false;\n    bool use_hes_sparsity = false;\n    bool use_base2ad      = false;\n    bool use_in_parallel  = false;\n    CppAD::chkpoint_two<double> chk_f(f, \"f(x; p)\",\n        internal_bool, use_hes_sparsity, use_base2ad, use_in_parallel\n    );\n    // -----------------------------------------------------------------------\n    // g(u; p)\n    vector< AD<double> > au(2), av(1);\n    au[0] = 5.0;\n    au[1] = 6.0;\n    CppAD::Independent(au);\n    ax[0] = au[0];\n    chk_f(ax, av);          // v[0] = p[0] * u[0]\n    ay[0] = au[1] + av[0];  // y[0] = u[1] + p[0] * u[0]\n    CppAD::ADFun<double> g(au, ay);\n    // ---------------------------------------------------------------------\n    ok &= g.Domain() == 2;\n    ok &= g.Range() == 1;\n    ok &= g.size_dyn_ind() == 0;\n    //\n    // evaluate g(u; p)\n    vector<double> p(1), u(2), y(1);\n    p[0] = 3.0;\n    u[0] = 4.0;\n    u[1] = 5.0;\n    chk_f.new_dynamic(p);\n    y    = g.Forward(0, u);\n    //\n    // check value\n    double check = u[1] + p[0] * u[0];\n    ok &= y[0] == check;\n    // ---------------------------------------------------------------------\n    std::string json = g.to_json();\n    // std::cout << json;\n    g.from_json(json);\n    // ---------------------------------------------------------------------\n    ok &= g.Domain() == 2;\n    ok &= g.Range() == 1;\n    ok &= g.size_dyn_ind() == 0;\n    //\n    // evaluate g(u; p)\n    p[0] = 4.0;\n    u[0] = 5.0;\n    u[1] = 6.0;\n    chk_f.new_dynamic(p);\n    y    = g.Forward(0, u);\n    //\n    // check value\n    check = u[1] + p[0] * u[0];\n    ok &= y[0] == check;\n\n    // -----------------------------------------------------------------------\n    // std::cout << graph;\n    return ok;\n}\n// ---------------------------------------------------------------------------\n// Test atomic function that only gets passed dynamic parameters\nbool atomic_dynamic(void)\n{   bool ok = true;\n    using CppAD::vector;\n    using CppAD::AD;\n    //\n    // y[0] = x[0] * x[1]\n    vector< AD<double> > ax(2), ay(1);\n    ax[0] = 2.0;\n    ax[1] = 3.0;\n    CppAD::Independent(ax);\n    ay[0] = ax[0] * ax[1];\n    CppAD::ADFun<double> f(ax, ay);\n    //\n    // Create a ckhpoint_two with name f(x).\n    // (This also creates an atomic_three function with same name.)\n    bool internal_bool    = false;\n    bool use_hes_sparsity = false;\n    bool use_base2ad      = false;\n    bool use_in_parallel  = false;\n    CppAD::chkpoint_two<double> chk_f(f, \"f(x)\",\n        internal_bool, use_hes_sparsity, use_base2ad, use_in_parallel\n    );\n    // -----------------------------------------------------------------------\n    vector< AD<double> > au(1), aq(2), av(1);\n    aq[0] = 4.0;\n    aq[1] = 5.0;\n    au[0] = 6.0;\n    size_t abort_op_index = 0;\n    bool   record_compare = false;\n    CppAD::Independent(au, abort_op_index, record_compare, aq);\n    chk_f(aq, av);          // v[0] = q[0] * q[1]\n    ay[0] = au[0] + av[0];  // y[0] = u[0] + q[0] * q[1]\n    CppAD::ADFun<double> g(au, ay);\n    //\n    // ---------------------------------------------------------------------\n    ok &= g.Domain() == 1;\n    ok &= g.Range() == 1;\n    ok &= g.size_dyn_ind() == 2;\n    //\n    // set q in g(u; q)\n    vector<double> q(2);\n    q[0] = 2.0;\n    q[1] = 3.0;\n    g.new_dynamic(q);\n    //\n    // evaluate g(u; q)\n    vector<double> u(1), y(1);\n    u[0] = 4.0;\n    y    = g.Forward(0, u);\n    //\n    // check value\n    double check = u[0] + q[0] * q[1];\n    ok &= y[0] == check;\n    // ---------------------------------------------------------------------\n    std::string json = g.to_json();\n    // std::cout << graph;\n    g.from_json(json);\n    //\n    ok &= g.Domain() == 1;\n    ok &= g.Range() == 1;\n    ok &= g.size_dyn_ind() == 2;\n    //\n    // set q in g(u; q)\n    q[0] = 3.0;\n    q[1] = 4.0;\n    g.new_dynamic(q);\n    //\n    // evaluate g(u; q)\n    u[0] = 5.0;\n    y    = g.Forward(0, u);\n    //\n    // check value\n    check = u[0] + q[0] * q[1];\n    ok &= y[0] == check;\n    // ----------------------------------------------------------------------\n    // std::cout << graph;\n    return ok;\n}\n// ---------------------------------------------------------------------------\n// Test transforming to Json and back to a function\nbool to_json_and_back(void)\n{   bool ok = true;\n    using CppAD::vector;\n    //\n    // An AD graph example\n    // node_1 : p[0]\n    // node_2 : x[0]\n    // node_3 : x[1]\n    // node_4 : -2.0\n    // node_5 : p[0] + x[0] + x[1]\n    // node_6 : (p[0] + x[0] + x[1]) * (p[0] + x[0] + x[1])\n    // y[0]   = (p[0] + x[0] + x[1]) * (p[0] + x[0] + x[1])\n    // use single quote to avoid having to escape double quote\n    std::string json =\n        \"{\\n\"\n        \"   'function_name'  : 'to_json_and_back test',\\n\"\n        \"   'op_define_vec'  : [ 3, [\\n\"\n        \"       { 'op_code':1, 'name':'add', 'n_arg':2 } ,\\n\"\n        \"       { 'op_code':2, 'name':'mul', 'n_arg':2 } ,\\n\"\n        \"       { 'op_code':3, 'name':'sum'            } ]\\n\"\n        \"   ],\\n\"\n        \"   'n_dynamic_ind'  : 1,\\n\"\n        \"   'n_variable_ind' : 2,\\n\"\n        \"   'constant_vec'   : [ 1, [ -2.0 ] ],\\n\"\n        \"   'op_usage_vec'   : [ 2, [\\n\"\n        \"       [ 3, 1, 3, [1, 2, 3 ] ] ,\\n\"\n        \"       [ 2, 5, 5             ] ] \\n\"\n        \"   ],\\n\"\n        \"   'dependent_vec'   : [ 1, [6] ] \\n\"\n        \"}\\n\";\n    // Convert the single quote to double quote\n    for(size_t i = 0; i < json.size(); ++i)\n        if( json[i] == '\\'' ) json[i] = '\"';\n    //\n    CppAD::ADFun<double> fun;\n    fun.from_json(json);\n    json = fun.to_json();\n    // For debugging\n    // std::cout << \"json = \" << json;\n    fun.from_json(json);\n    //\n    // Compute function value\n    vector<double> p(1), x(2);\n    p[0] = 1.0;\n    x[0] = 2.0;\n    x[1] = 3.0;\n    fun.new_dynamic(p);\n    vector<double> y = fun.Forward(0, x);\n    ok  &= y[0] ==  (p[0] + x[0] + x[1]) * (p[0] + x[0] + x[1]);\n    //\n    // Conpute derivative value\n    vector<double> jac = fun.Jacobian(x);\n    ok &= jac[0] == 2.0 * (p[0] + x[0] + x[1]);\n    ok &= jac[1] == 2.0 * (p[0] + x[0] + x[1]);\n    //\n    // Uncomment statement below to see the graph\n    // std::cout << graph;\n    //\n    return ok;\n}\n// ---------------------------------------------------------------------------\n// Test binary operators that should be implemented\nbool binary_operators(void)\n{   bool ok   = true;\n    using CppAD::AD;\n    //\n    size_t np = 1;\n    size_t nx = 2;\n    size_t ny = 10;\n    CPPAD_TESTVECTOR(double)       p(np),   x(nx);\n    CPPAD_TESTVECTOR( AD<double> ) ap(np), ax(nx), ay(ny);\n    for(size_t i = 0; i < np; ++i)\n    {   ap[i] = 0.5;\n        p[i]  = double(i + 1);\n    }\n    for(size_t i = 0; i < nx; ++i)\n    {   ax[i] = 0.25;\n        x[i]  = double(2 * i + 1);\n    }\n    CppAD::Independent(ax, ap);\n    //\n    size_t j = 0;\n    ay[j++] = ap[0] + 2.0;    // dynamic + constant (and ParOp)\n    ay[j++] = 2.0 + ap[0];    // constant + dynamic (and ParOp)\n    ay[j++] = ax[0] + ap[0];  // variable + dynamic\n    ay[j++] = ap[0] + ax[0];  // dynamic + variable\n    ay[j++] = ax[0] + ax[1];  // variable + variable\n    //\n    ay[j++] = ap[0] * 2.0;    // dynamic * constant (and ParOp)\n    ay[j++] = 2.0 * ap[0];    // constant * dynamic (and ParOp)\n    ay[j++] = ax[0] * ap[0];  // variable * dynamic\n    ay[j++] = ap[0] * ax[0];  // dynamic * variable\n    ay[j++] = ax[0] * ax[1];  // variable * variable\n    //\n    ok &= j == ny;\n    //\n    // Create function\n    CppAD::ADFun<double> f(ax, ay);\n    //\n    // Evaluate function at x before\n    f.new_dynamic(p);\n    CPPAD_TESTVECTOR(double) y_before = f.Forward(0, x);\n    //\n    // Convert to Json and back again\n    std::string json = f.to_json();\n    // std::cout << graph;\n    f.from_json(json);\n    //\n    // Evaluate function at x after\n    f.new_dynamic(p);\n    CPPAD_TESTVECTOR(double) y_after = f.Forward(0, x);\n    //\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    for(size_t i = 0; i < ny; ++i)\n        ok &= CppAD::NearEqual( y_before[i], y_after[i], eps99, eps99 );\n    //\n    // Uncomment statement below to see the graph\n    // std::cout << graph;\n    return ok;\n}\n// ---------------------------------------------------------------------------\n// Test cumulative sum operator\nbool cumulative_sum(void)\n{   bool ok   = true;\n    using CppAD::AD;\n    //\n    size_t np = 2;\n    size_t nx = 2;\n    size_t ny = 1;\n    CPPAD_TESTVECTOR(double)       p(np),   x(nx);\n    CPPAD_TESTVECTOR( AD<double> ) ap(np), ax(nx), ay(ny);\n    for(size_t i = 0; i < np; ++i)\n    {   ap[i] = 0.5;\n        p[i]  = double(i + 1);\n    }\n    for(size_t i = 0; i < nx; ++i)\n    {   ax[i] = 0.25;\n        x[i]  = double(2 * i + 1);\n    }\n    CppAD::Independent(ax, ap);\n    //\n    AD<double> asum = 0.0;\n    asum +=  1.0 + ap[0];\n    asum += ap[1] + 1.0;\n    asum -= ap[1] + ap[0];\n    //\n    asum +=  1.0 + ax[0];\n    asum += ax[1] + 1.0;\n    asum -= ax[1] + ax[0];\n    //\n    asum += ap[0] + ax[0];\n    asum += ax[1] + ap[1];\n    //\n    ay[0] = asum;\n    //\n    // Create function\n    CppAD::ADFun<double> f(ax, ay);\n    f.optimize();\n    //\n    // Evaluate function at x before\n    f.new_dynamic(p);\n    CPPAD_TESTVECTOR(double) y_before = f.Forward(0, x);\n    //\n    // Convert to Json and back again\n    std::string json = f.to_json();\n    // std::cout << graph;\n    f.from_json(json);\n    //\n    // Evaluate function at x after\n    f.new_dynamic(p);\n    CPPAD_TESTVECTOR(double) y_after = f.Forward(0, x);\n    //\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    for(size_t i = 0; i < ny; ++i)\n        ok &= CppAD::NearEqual( y_before[i], y_after[i], eps99, eps99 );\n    //\n    // Uncomment statement below to see the graph\n    // std::cout << graph;\n    return ok;\n}\n// ---------------------------------------------------------------------------\n// Test unary operators\nbool unary(bool p_first)\n{   bool ok   = true;\n    using CppAD::AD;\n    //\n    size_t np = 11;\n    size_t nx = 11;\n    size_t ny = np + nx;\n    CPPAD_TESTVECTOR(double)       p(np),  x(nx), y(ny);\n    CPPAD_TESTVECTOR( AD<double> ) ap(np), ax(nx), ay(ny);\n    for(size_t i = 0; i < np; ++i)\n    {   p[i]  = double(i + 1) / double( np + nx + 1 );\n        ap[i] = p[i] / 2.0;\n    }\n    for(size_t i = 0; i < nx; ++i)\n    {   x[i]  = double(i + 1 + np) / double( np + nx + 1);\n        ax[i] = x[i] / 2.0;\n    }\n    CppAD::Independent(ax, ap);\n    //\n    CPPAD_TESTVECTOR( AD<double> ) atmp(np + nx);\n    if( p_first )\n    {   for(size_t i = 0; i < np; ++i)\n            atmp[i] = ap[i];\n        for(size_t i = 0; i < nx; ++i)\n            atmp[i + np] = ax[i];\n    }\n    else\n    {   for(size_t i = 0; i < np; ++i)\n            atmp[i + nx] = ap[i];\n        for(size_t i = 0; i < nx; ++i)\n            atmp[i] = ax[i];\n    }\n    //\n    ay[0]  = fabs(atmp[0]);\n    ay[1]  = acos(atmp[1]);\n    ay[2]  = acosh(atmp[2] + 1.0);\n    ay[3]  = asin(atmp[3]);\n    ay[4]  = asinh(atmp[4]);\n    ay[5]  = atan(atmp[5]);\n    ay[6]  = atanh(atmp[6]);\n    ay[7]  = cos(atmp[7]);\n    ay[8]  = cosh(atmp[8]);\n    ay[9]  = erf(atmp[9]);\n    ay[10] = erfc(atmp[10]);\n    ay[11] = exp(atmp[11]);\n    ay[12] = expm1(atmp[12]);\n    ay[13] = log(atmp[13]);\n    ay[14] = log1p(atmp[14]);\n    ay[15] = - atmp[15];\n    ay[16] = sign(atmp[16]);\n    ay[17] = sin(atmp[17]);\n    ay[18] = sinh(atmp[18]);\n    ay[19] = sqrt(atmp[19]);\n    ay[20] = tan(atmp[20]);\n    ay[21] = sin(atmp[21]);\n    // Create function\n    CppAD::ADFun<double> f(ax, ay);\n    f.optimize();\n    //\n    // Evaluate function at x before\n    f.new_dynamic(p);\n    CPPAD_TESTVECTOR(double) y_before = f.Forward(0, x);\n    //\n    // Convert to Json and back again\n    std::string json = f.to_json();\n    // std::cout << graph;\n    f.from_json(json);\n    //\n    // Evaluate function at x after\n    f.new_dynamic(p);\n    CPPAD_TESTVECTOR(double) y_after = f.Forward(0, x);\n    //\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    for(size_t i = 0; i < ny; ++i)\n        ok &= CppAD::NearEqual( y_before[i], y_after[i], eps99, eps99 );\n    //\n    return ok;\n}\n\n// ---------------------------------------------------------------------------\n} // END_EMPTY_NAMESPACE\n\n\nbool json_graph(void)\n{   bool ok = true;\n    ok     &= comp_op_dyn_dyn();\n    ok     &= comp_op_var_var();\n    ok     &= comp_op_dyn_var();\n    ok     &= comp_op_var_dyn();\n    ok     &= acosh_op();\n    ok     &= log1p_op();\n    ok     &= expm1_op();\n    ok     &= erfc_op();\n    ok     &= erf_op();\n    ok     &= atanh_op();\n    ok     &= asinh_op();\n    ok     &= tan_op();\n    ok     &= tanh_op();\n    ok     &= sqrt_op();\n    ok     &= sin_op();\n    ok     &= sinh_op();\n    ok     &= sign_op();\n    ok     &= log_op();\n    ok     &= exp_op();\n    ok     &= cos_op();\n    ok     &= cosh_op();\n    ok     &= atan_op();\n    ok     &= asin_op();\n    ok     &= acos_op();\n    ok     &= abs_op();\n    ok     &= cexp_lt_variable();\n    ok     &= cexp_lt_constant();\n    ok     &= cexp_lt_dynamic();\n    ok     &= atomic_both();\n    ok     &= atomic_dynamic();\n    ok     &= to_json_and_back();\n    ok     &= binary_operators();\n    ok     &= cumulative_sum();\n    ok     &= unary(true);\n    ok     &= unary(false);\n    //\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/local/is_pod.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cstddef>\n# include <cppad/cppad.hpp>\n\nbool is_pod(void)\n{   bool ok = true;\n    using CppAD::local::is_pod;\n    //\n    // Check all the cases that are the same as short int on\n    // https://en.cppreference.com/w/cpp/language/types on 2020-12-04.\n    ok &= is_pod<short>();\n    ok &= is_pod<short int>();\n    ok &= is_pod<signed short>();\n    ok &= is_pod<signed short int>();\n    //\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/local/json_lexer.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/cppad.hpp>\n\nbool json_lexer(void)\n{   bool ok = true;\n    typedef CppAD::graph::graph_op_enum graph_op_enum;\n    using CppAD::local::graph::op_name2enum;\n    //\n    // match_any_string\n    std::string match_any_string = \"\";\n    //\n    // An AD graph example\n    // node_1 : p[0]\n    // node_2 : x[0]\n    // node_3 : x[1]\n    // node_4 : -2.0\n    // node_5 : p[0] + x[0] + x[1]\n    // node_6 : (p[0] + x[0] + x[1]) * (p[0] + x[0] + x[1])\n    // y[0] = (p[0] + x[0] + x[1]) * (p[0] + x[0] + x[1])\n    // use single quote to avoid having to escape double quote\n    std::string graph =\n        \"{\\n\"\n        \"   'op_define_vec'  : [ 3, [\\n\"\n        \"       { 'op_code':1, 'name':'add', 'n_arg':2 } ,\\n\"\n        \"       { 'op_code':2, 'name':'mul', 'n_arg':2 } ,\\n\"\n        \"       { 'op_code':3, 'name':'sum'            } ]\\n\"\n        \"   ],\\n\"\n        \"   'n_dynamic_ind'  : 1,\\n\"\n        \"   'n_variable_ind' : 2,\\n\"\n        \"   'constant_vec'   : [ 1, [ -2.0 ] ],\\n\"\n        \"   'op_usage_vec'   : [ 2, [\\n\"\n        \"       [ 3, 1, 3, [1, 2, 3] ] ,\\n\"\n        \"       [ 2, 5, 5 ] ] \\n\"\n        \"   ],\\n\"\n        \"   'dependent_vec'   : [ 1, [6] ]\\n\"\n        \"}\\n\";\n    // Convert the single quote to double quote\n    for(size_t i = 0; i < graph.size(); ++i)\n        if( graph[i] == '\\'' ) graph[i] = '\"';\n    //\n    // json_lexer constructor checks for { at beginning\n    CppAD::local::graph::json_lexer json_lexer(graph);\n    // -----------------------------------------------------------------------\n    // op_define_vec\n    json_lexer.check_next_string(\"op_define_vec\");\n    json_lexer.check_next_char(':');\n    json_lexer.check_next_char('[');\n    //\n    // n_define\n    json_lexer.next_non_neg_int();\n    size_t n_define = json_lexer.token2size_t();\n    json_lexer.check_next_char(',');\n    json_lexer.check_next_char('[');\n    CppAD::vector<graph_op_enum> op_code2enum(1);\n    for(size_t i = 0; i < n_define; ++i)\n    {   json_lexer.check_next_char('{');\n        //\n        // op_code\n        json_lexer.check_next_string(\"op_code\");\n        json_lexer.check_next_char(':');\n        json_lexer.next_non_neg_int();\n# ifndef NDEBUG\n        size_t op_code = json_lexer.token2size_t();\n        assert( op_code == op_code2enum.size() );\n# endif\n        json_lexer.check_next_char(',');\n        //\n        // name\n        json_lexer.check_next_string(\"name\");\n        json_lexer.check_next_char(':');\n        json_lexer.check_next_string(match_any_string);\n        std::string   name   = json_lexer.token();\n        graph_op_enum op_enum = op_name2enum[name];\n        //\n        // op_code2enum\n        op_code2enum.push_back(op_enum);\n        //\n        if( op_enum != CppAD::graph::sum_graph_op )\n        {   json_lexer.check_next_char(',');\n            //\n            // n_arg\n            json_lexer.check_next_string(\"n_arg\");\n            json_lexer.check_next_char(':');\n            json_lexer.next_non_neg_int();\n            ok &= json_lexer.token2size_t() == 2;\n        }\n        //\n        json_lexer.check_next_char('}');\n        if( i + 1 == n_define )\n            json_lexer.check_next_char(']');\n        else\n            json_lexer.check_next_char(',');\n    }\n    json_lexer.check_next_char(']');\n    json_lexer.check_next_char(',');\n    // -----------------------------------------------------------------------\n    // n_dynamic_ind\n    json_lexer.check_next_string(\"n_dynamic_ind\");\n    json_lexer.check_next_char(':');\n    json_lexer.next_non_neg_int();\n    size_t n_dynamic_ind = json_lexer.token2size_t();\n    json_lexer.check_next_char(',');\n    //\n    ok &= n_dynamic_ind == 1;\n    // -----------------------------------------------------------------------\n    // n_variable_ind\n    json_lexer.check_next_string(\"n_variable_ind\");\n    json_lexer.check_next_char(':');\n    json_lexer.next_non_neg_int();\n    size_t n_variable_ind = json_lexer.token2size_t();\n    json_lexer.check_next_char(',');\n    //\n    ok &= n_variable_ind == 2;\n    // -----------------------------------------------------------------------\n    // constant_vec\n    json_lexer.check_next_string(\"constant_vec\");\n    json_lexer.check_next_char(':');\n    json_lexer.check_next_char('[');\n    json_lexer.next_non_neg_int();\n    size_t n_constant = json_lexer.token2size_t();\n    CppAD::vector<double> constant_vec(n_constant);\n    json_lexer.check_next_char(',');\n    //\n    // [ first_constant, ... , last_constant ]\n    json_lexer.check_next_char('[');\n    for(size_t i = 0; i < n_constant; ++i)\n    {   json_lexer.next_float();\n        constant_vec[i] = json_lexer.token2double();\n        //\n        if( i + 1 == n_constant )\n            json_lexer.check_next_char(']');\n        else\n            json_lexer.check_next_char(',');\n    }\n    //\n    json_lexer.check_next_char(']');\n    json_lexer.check_next_char(',');\n    //\n    ok &= constant_vec.size() == 1;\n    ok &= constant_vec[0] == -2.0;\n    // -----------------------------------------------------------------------\n    // op_usage_vec\n    json_lexer.check_next_string(\"op_usage_vec\");\n    //\n    json_lexer.check_next_char(':');\n    json_lexer.check_next_char('[');\n    //\n    json_lexer.next_non_neg_int();\n    size_t n_usage = json_lexer.token2size_t();\n    CppAD::vector<graph_op_enum> operator_vec(n_usage);\n    //\n    json_lexer.check_next_char(',');\n    //\n    // [ first_operator, ... , last_operator ]\n    json_lexer.check_next_char('[');\n    for(size_t i = 0; i < n_usage; ++i)\n    {   // start next operator\n        json_lexer.check_next_char('[');\n        graph_op_enum op_usage;\n        //\n        // op_code\n        json_lexer.next_non_neg_int();\n        size_t op_code   = json_lexer.token2size_t();\n        //\n        // op_enum\n        op_usage = op_code2enum[op_code];\n        json_lexer.check_next_char(',');\n        //\n        size_t n_result, n_arg;\n        if( op_usage != CppAD::graph::sum_graph_op )\n        {   n_result = 1;\n            n_arg    = 2;\n        }\n        else\n        {   // n_result\n            json_lexer.next_non_neg_int();\n            n_result = json_lexer.token2size_t();\n            json_lexer.check_next_char(',');\n            ok &= n_result == 1;\n            //\n            // n_arg\n            json_lexer.next_non_neg_int();\n            n_arg = json_lexer.token2size_t();\n            json_lexer.check_next_char(',');\n            json_lexer.check_next_char('[');\n            ok &= n_arg == 3;\n            //\n        }\n        ok &= n_result == 1;\n        CppAD::vector<size_t> arg_node(0);\n        // first_arg_node, ... , last_arg_node\n        for(size_t j = 0; j < n_arg; ++j)\n        {   // next argument node\n            json_lexer.next_non_neg_int();\n            size_t argument_node = json_lexer.token2size_t();\n            arg_node.push_back( argument_node );\n            //\n            if( j + 1 == n_arg )\n                json_lexer.check_next_char(']');\n            else\n                json_lexer.check_next_char(',');\n        }\n        if( op_usage == CppAD::graph::sum_graph_op )\n        {\n            json_lexer.check_next_char(']');\n            ok &= arg_node.size() == 3;\n            ok &= arg_node[0] == 1;\n            ok &= arg_node[1] == 2;\n            ok &= arg_node[2] == 3;\n        }\n        else\n        {   ok &= arg_node.size() == 2;\n            ok &= arg_node[0] == 5;\n            ok &= arg_node[1] == 5;\n        }\n        //\n        // end of this operator\n        operator_vec[i] = op_usage;\n        //\n        if( i + 1 == n_usage )\n            json_lexer.check_next_char(']');\n        else\n            json_lexer.check_next_char(',');\n\n    }\n    json_lexer.check_next_char(']');\n    //\n    json_lexer.check_next_char(',');\n    //\n    ok &= operator_vec.size() == 2;\n    //\n    graph_op_enum op_enum = operator_vec[0];\n    ok &= op_enum == CppAD::graph::sum_graph_op;\n    //\n    op_enum   = operator_vec[1];\n    ok &= op_enum == CppAD::graph::mul_graph_op;\n    // -----------------------------------------------------------------------\n    // dependent_vec\n    json_lexer.check_next_string(\"dependent_vec\");\n    json_lexer.check_next_char(':');\n    json_lexer.check_next_char('[');\n    json_lexer.next_non_neg_int();\n    size_t n_dependent = json_lexer.token2size_t();\n    CppAD::vector<size_t> dependent_vec(n_dependent);\n    //\n    json_lexer.check_next_char(',');\n    //\n    // [ first_dependent, ... , last_dependent ]\n    json_lexer.check_next_char('[');\n    for(size_t i = 0; i < n_dependent; ++i)\n    {   json_lexer.next_float();\n        dependent_vec[i] = json_lexer.token2size_t();\n        //\n        if( i + 1 == n_dependent )\n            json_lexer.check_next_char(']');\n        else\n            json_lexer.check_next_char(',');\n    }\n    //\n    json_lexer.check_next_char(']');\n    //\n    ok &= dependent_vec.size() == 1;\n    ok &= dependent_vec[0] == 6;\n    // -----------------------------------------------------------------------\n    // }\n    json_lexer.check_next_char('}');\n    //\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/local/json_parser.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/local/graph/json_parser.hpp>\n\nbool json_parser(void)\n{   bool ok = true;\n    using CppAD::cpp_graph;\n    using CppAD::vector;\n    //\n    // An AD graph example\n    // node_1 : p[0]\n    // node_2 : x[0]\n    // node_3 : x[1]\n    // node_4 : -2.0\n    // node_5 : p[0] + x[0] + x[1]\n    // node_6 : (p[0] + x[0] + x[1]) * (p[0] + x[0] + x[1])\n    // y[0]   = (p[0] + x[0] + x[1]) * (p[0] + x[0] + x[1])\n    // use single quote to avoid having to escape double quote\n    std::string json =\n        \"{\\n\"\n        \"   'function_name' : 'json_parser test',\\n\"\n        \"   'op_define_vec'  : [ 3, [\\n\"\n        \"       { 'op_code':1, 'name':'add', 'n_arg':2 } ,\\n\"\n        \"       { 'op_code':2, 'name':'mul', 'n_arg':2 } ,\\n\"\n        \"       { 'op_code':3, 'name':'sum'            } ]\\n\"\n        \"   ],\\n\"\n        \"   'n_dynamic_ind'  : 1,\\n\"\n        \"   'n_variable_ind' : 2,\\n\"\n        \"   'constant_vec'   : [ 1, [ -2.0 ] ],\\n\"\n        \"   'op_usage_vec'   : [ 2, [\\n\"\n        \"       [ 3, 1, 3, [1, 2, 3 ] ] ,\\n\"\n        \"       [ 2, 5, 5             ] ] \\n\"\n        \"   ],\\n\"\n        \"   'dependent_vec'   : [ 1, [6] ] \\n\"\n        \"}\\n\";\n    // Convert the single quote to double quote\n    for(size_t i = 0; i < json.size(); ++i)\n        if( json[i] == '\\'' ) json[i] = '\"';\n    //\n    // C++ graph object\n    cpp_graph graph_obj;\n    //\n    const std::string& function_name(    graph_obj.function_name_get() );\n    const size_t&      n_dynamic_ind(    graph_obj.n_dynamic_ind_get() );\n    const size_t&      n_variable_ind(    graph_obj.n_variable_ind_get() );\n    //\n    // call parser\n    CppAD::local::graph::json_parser( json, graph_obj );\n    //\n    ok &= function_name == \"json_parser test\";\n    ok &= n_dynamic_ind == 1;\n    ok &= n_variable_ind == 2;\n    ok &= graph_obj.atomic_name_vec_size() == 0;\n    //\n    ok &= graph_obj.constant_vec_size() == 1;\n    ok &= graph_obj.constant_vec_get(0) == -2.0;\n    //\n    ok &= graph_obj.operator_vec_size() == 2;\n    //\n    //\n    vector<size_t> arg_node;\n    cpp_graph::const_iterator graph_itr             = graph_obj.begin();\n    cpp_graph::const_iterator::value_type itr_value = *graph_itr;\n    arg_node = *(itr_value.arg_node_ptr);\n    ok &= itr_value.op_enum == CppAD::graph::sum_graph_op;\n    ok &= arg_node.size() == 3;\n    ok &= arg_node[0] == 1;\n    ok &= arg_node[1] == 2;\n    ok &= arg_node[2] == 3;\n    //\n    itr_value = *++graph_itr;\n    ok &= itr_value.op_enum == CppAD::graph::mul_graph_op;\n    arg_node.resize(0); // to avoid CppAD::vector assignment error\n    arg_node = *(itr_value.arg_node_ptr);\n    ok &= arg_node.size() == 2;\n    ok &= arg_node[0] == 5;\n    ok &= arg_node[1] == 5;\n    //\n    ok &= graph_obj.dependent_vec_size() == 1;\n    ok &= graph_obj.dependent_vec_get(0) == 6;\n    // -----------------------------------------------------------------------\n    //\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/local/temp_file.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <fstream>\n# include <cppad/local/temp_file.hpp>\n\nbool temp_file(void)\n{   bool ok = true;\n    //\n    // file_name\n    // create file\n    std::string file_name = CppAD::local::temp_file();\n    //\n    // ifs\n    std::ifstream ifs;\n    ifs.open(file_name);\n    //\n    // ok\n    ok   &= ifs.good();\n    int c = ifs.get();\n    ok   &= c == EOF;\n    //\n    // ok\n    // remove file\n    ifs.close();\n    int flag = std::remove(file_name.c_str());\n    ok &= flag == 0;\n    //\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/local/vector_set.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/cppad.hpp>\n\nnamespace { //  BEGIN empty namespace\n\ntemplate <class SetVector>\nbool test_no_other(void)\n{   bool ok = true;\n\n    SetVector vec_set;\n    size_t n_set = 4;\n    size_t end   = 5;\n    //\n    // set size of vec_set\n    vec_set.resize(n_set, end);\n    ok &= end == vec_set.end();\n    ok &= n_set == vec_set.n_set();\n    //\n    // test resizing to zero\n    vec_set.resize(0, 0);\n    ok &= 0 == vec_set.n_set();\n    ok &= 0 == vec_set.end();\n    //\n    // set size of vec_set\n    vec_set.resize(n_set, end);\n    ok &= end == vec_set.end();\n    ok &= n_set == vec_set.n_set();\n\n    //\n    // add the element i+1 to set i\n    for(size_t i = 1; i < n_set; i++)\n        vec_set.add_element(i, i+1);\n    //\n    // check for element i and i+1 in set i\n    for(size_t i = 0; i < n_set; i++)\n    {   ok &= ! vec_set.is_element(i, i);\n        if( i == 0 )\n            ok &=  ! vec_set.is_element(i, i+1);\n        else\n            ok &=  vec_set.is_element(i, i+1);\n    }\n    //\n    // set an empty set to value of set 2\n    size_t target = 0;\n    size_t source = 2;\n    vec_set.assignment(target, source, vec_set);\n    ok &= ! vec_set.is_element(target, source);\n    ok &= vec_set.is_element(target, source+1);\n    //\n    // set a non-empty set to the value of set 2\n    target = 1;\n    vec_set.assignment(target, source, vec_set);\n    ok &= ! vec_set.is_element(target, source);\n    ok &= vec_set.is_element(target, source+1);\n    //\n    // add an element to set 1, one of the three vectors equal to set 2\n    target = 1;\n    vec_set.add_element(target, source);\n    ok &= vec_set.is_element(target, source);\n    ok &= vec_set.is_element(target, source+1);\n    ok &= ! vec_set.is_element(source, source);\n    ok &= vec_set.is_element(source, source+1);\n    //\n    // now take the union of set 2 and set 3 and place in set 0\n    // (which is sharing a list with set 2)\n    target = 0;\n    vec_set.binary_union(target, source, source+1, vec_set);\n    ok &= vec_set.is_element(target, source+1);\n    ok &= vec_set.is_element(target, source+2);\n    ok &= vec_set.is_element(source, source+1);\n    ok &= ! vec_set.is_element(source, source+2);\n    //\n    // now check the elements in set 0 by iterating over them\n    typename SetVector::const_iterator itr(vec_set, target);\n    ok &= *itr     == source+1;\n    ok &= *(++itr) == source+2;\n    ok &= *(++itr) == end;\n    //\n    // now test clear\n    vec_set.clear(1);\n    ok &= ! vec_set.is_element(1, source+1);\n    ok &= vec_set.is_element(0, source+1);\n    //\n    // now force list_setvec garbage collection by setting all sets\n    // equal to set 0\n    for(size_t i = 1; i < n_set; i++)\n    {   vec_set.assignment(i, 0, vec_set);\n        ok &= vec_set.is_element(i, source+1);\n        ok &= vec_set.is_element(i, source+2);\n    }\n    //\n    return ok;\n}\n\ntemplate <class SetVector>\nbool test_yes_other(void)\n{   bool ok = true;\n\n    SetVector vec_set, other_vec;\n    size_t n_set = 4;\n    size_t end   = 5;\n    vec_set.resize(n_set, end);\n    other_vec.resize(n_set, end);\n    //\n    // add element i to set i in vec_set\n    // add element i+1 to set i in other\n    for(size_t i = 1; i < n_set; i++)\n    {   vec_set.add_element(i, i);\n        other_vec.add_element(i, i+1);\n    }\n    //\n    // assignment of one set from other\n    size_t target = 0;\n    size_t source = 1;\n    vec_set.assignment(target, source, other_vec);\n    ok &= ! vec_set.is_element(target, source);\n    ok &= vec_set.is_element(target, source+1);\n    //\n    // now take the union of a set from vec_set and from other_vec\n    target       = 2; // where result goes in vec_set\n    size_t left  = 2; // left operand in vec_set\n    size_t right = 2; // right operand in other\n    vec_set.binary_union(target, left, right, other_vec);\n    ok &= vec_set.is_element(target, left);\n    ok &= vec_set.is_element(target, right+1);\n    //\n    // now use assignment for entire vector of sets\n    vec_set = other_vec;\n    ok &= ! vec_set.is_element(0, 0);\n    ok &= ! vec_set.is_element(0, 1);\n    for(size_t i = 1; i < n_set; i++)\n    {   ok &= ! vec_set.is_element(i, i);\n        ok &=   vec_set.is_element(i, i+1);\n    }\n    return ok;\n}\n\ntemplate <class SetVector>\nbool test_intersection(void)\n{   bool ok = true;\n    //\n    SetVector vec_set;\n    size_t n_set = 3;\n    size_t end   = 5;\n    vec_set.resize(n_set, end);\n    //\n    // set[0] = {1, 2}\n    vec_set.add_element(0, 1);\n    vec_set.add_element(0, 2);\n    //\n    // set[1] = {2, 3}\n    vec_set.add_element(1, 2);\n    vec_set.add_element(1, 3);\n    //\n    // set[2] = set[0] intersect set[1]\n    size_t target = 2;\n    size_t left   = 0;\n    size_t right  = 1;\n    vec_set.binary_intersection(target, left, right, vec_set);\n    //\n    typename SetVector::const_iterator itr1(vec_set, target);\n    ok &= *itr1     == 2;\n    ok &= *(++itr1) == end;\n    //\n    // other[1] = set[1]\n    SetVector other;\n    other.resize(n_set, end);\n    target        = 1;\n    size_t source = 1;\n    other.assignment(target, source, vec_set);\n    //\n    // set[2] = set[0] intersect other[1]\n    target = 2;\n    left   = 0;\n    right  = 1;\n    vec_set.binary_intersection(target, left, right, other);\n    //\n    typename SetVector::const_iterator itr2(vec_set, target);\n    ok &= *itr2     == 2;\n    ok &= *(++itr2) == end;\n    //\n    return ok;\n}\n\ntemplate<class SetVector>\nbool test_post(void)\n{   bool ok = true;\n    //\n    SetVector vec_set;\n    size_t n_set = 3;\n    size_t end   = 5;\n    vec_set.resize(n_set, end);\n    //\n    // set[1] = {1, 2}\n    vec_set.add_element(1, 1);\n    vec_set.add_element(1, 2);\n    //\n    // set[1] = {1, 2} union (2, 4, 4)  = {1, 2, 4}\n    size_t target = 1;\n    vec_set.post_element(target, 2);\n    vec_set.post_element(target, 4);\n    vec_set.post_element(target, 4);\n    vec_set.process_post(target);\n    //\n    typename SetVector::const_iterator itr1(vec_set, target);\n    ok &= *itr1     == 1;\n    ok &= *(++itr1) == 2;\n    ok &= *(++itr1) == 4;\n    ok &= *(++itr1) == end;\n    //\n    // set[1] = {1, 2, 4} union (1, 2)\n    target = 1;\n    vec_set.post_element(target, 1);\n    vec_set.post_element(target, 2);\n    vec_set.process_post(target);\n    //\n    typename SetVector::const_iterator itr2(vec_set, target);\n    ok &= *itr2     == 1;\n    ok &= *(++itr2) == 2;\n    ok &= *(++itr2) == 4;\n    ok &= *(++itr2) == end;\n    //\n    return ok;\n}\n\n} // END empty namespace\n\nbool vector_set(void)\n{   bool ok = true;\n    //\n    ok     &= test_no_other<CppAD::local::sparse::pack_setvec>();\n    ok     &= test_no_other<CppAD::local::sparse::list_setvec>();\n    ok     &= test_no_other<CppAD::local::sparse::svec_setvec>();\n    //\n    ok     &= test_yes_other<CppAD::local::sparse::pack_setvec>();\n    ok     &= test_yes_other<CppAD::local::sparse::list_setvec>();\n    ok     &= test_yes_other<CppAD::local::sparse::svec_setvec>();\n    //\n    ok     &= test_intersection<CppAD::local::sparse::pack_setvec>();\n    ok     &= test_intersection<CppAD::local::sparse::list_setvec>();\n    ok     &= test_intersection<CppAD::local::sparse::svec_setvec>();\n    //\n    ok     &= test_post<CppAD::local::sparse::pack_setvec>();\n    ok     &= test_post<CppAD::local::sparse::list_setvec>();\n# ifdef CPPAD_DO_NOT_RUN_THIS_TEST\n    // 2DO: This class tested below is not currently being used.\n    // This test is failing due to a bug.  To be specific, push_back on a vector\n    // is invalidating some pointers.\n    // We need to use a different temporary vector for these push_backs.\n    ok     &= test_post<CppAD::local::sparse::svec_setvec>();\n# endif\n    //\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/log.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n\n/*\nTwo old log examples now used just for validation testing\n*/\n\n# include <cppad/cppad.hpp>\n\nnamespace { // BEGIN empty namespace\n\nbool LogTestOne(void)\n{   bool ok = true;\n    using CppAD::log;\n    using namespace CppAD;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // independent variable vector, indices, values, and declaration\n    CPPAD_TESTVECTOR(AD<double>) U(1);\n    size_t s = 0;\n    U[s]     = 2.;\n    Independent(U);\n\n    // dependent variable vector, indices, and values\n    CPPAD_TESTVECTOR(AD<double>) Z(2);\n    size_t x = 0;\n    size_t y = 1;\n    Z[x]     = log(U[s]);\n    Z[y]     = log(Z[x]);\n\n    // define f : U -> Z and vectors for derivative calculations\n    ADFun<double> f(U, Z);\n    CPPAD_TESTVECTOR(double) v( f.Domain() );\n    CPPAD_TESTVECTOR(double) w( f.Range() );\n\n    // check values\n    ok &= NearEqual(Z[x] , log(2.),  eps99 , eps99);\n    ok &= NearEqual(Z[y] , log( log(2.) ),  eps99 , eps99);\n\n    // forward computation of partials w.r.t. s\n    v[s] = 1.;\n    w    = f.Forward(1, v);\n    ok &= NearEqual(w[x], 1. / U[s],          eps99 , eps99); // dx/ds\n    ok &= NearEqual(w[y], 1. / (U[s] * Z[x]), eps99 , eps99); // dy/ds\n\n    // reverse computation of partials of y\n    w[x] = 0.;\n    w[y] = 1.;\n    v    = f.Reverse(1,w);\n    ok &= NearEqual(v[s], 1. / (U[s] * Z[x]), eps99 , eps99); // dy/ds\n\n    // forward computation of second partials w.r.t. s\n    v[s] = 1.;\n    w    = f.Forward(1, v);\n    v[s] = 0.;\n    w    = f.Forward(2, v);\n    ok &= NearEqual(\n        2. * w[y] ,\n        - 1. / (Z[x]*Z[x]*U[s]*U[s]) - 1. / (Z[x]*U[s]*U[s]),\n        eps99 ,\n        eps99\n    );\n\n    // reverse computation of second partials of y\n    CPPAD_TESTVECTOR(double) r( f.Domain() * 2 );\n    w[x] = 0.;\n    w[y] = 1.;\n    r    = f.Reverse(2, w);\n    ok &= NearEqual(\n        r[2 * s + 1] ,\n        - 1. / (Z[x]*Z[x]*U[s]*U[s]) - 1. / (Z[x]*U[s]*U[s]),\n        eps99 ,\n        eps99\n    );\n\n    return ok;\n}\nbool LogTestTwo(void)\n{   bool ok = true;\n    using CppAD::log;\n    using namespace CppAD;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // independent variable vector\n    CPPAD_TESTVECTOR(AD<double>) U(1);\n    U[0]     = 1.;\n    Independent(U);\n\n    // a temporary values\n    AD<double> x = exp(U[0]);\n\n    // dependent variable vector\n    CPPAD_TESTVECTOR(AD<double>) Z(1);\n    Z[0] = log(x);       // log( exp(u) )\n\n    // create f: U -> Z and vectors used for derivative calculations\n    ADFun<double> f(U, Z);\n    CPPAD_TESTVECTOR(double) v(1);\n    CPPAD_TESTVECTOR(double) w(1);\n\n    // check value\n    ok &= NearEqual(U[0] , Z[0],  eps99 , eps99);\n\n    // forward computation of partials w.r.t. u\n    size_t j;\n    size_t p     = 5;\n    double jfac  = 1.;\n    double value = 1.;\n    v[0]         = 1.;\n    for(j = 1; j < p; j++)\n    {   jfac *= double(j);\n        w     = f.Forward(j, v);\n        ok &= NearEqual(w[0], value/jfac, eps99, eps99); // d^jz/du^j\n        v[0]  = 0.;\n        value = 0.;\n    }\n\n    // reverse computation of partials of Taylor coefficients\n    CPPAD_TESTVECTOR(double) r(p);\n    w[0]  = 1.;\n    r     = f.Reverse(p, w);\n    jfac  = 1.;\n    value = 1.;\n    for(j = 0; j < p; j++)\n    {   ok &= NearEqual(r[j], value/jfac, eps99, eps99); // d^jz/du^j\n        jfac *= double(j + 1);\n        value = 0.;\n    }\n\n    return ok;\n}\n\n} // END empty namespace\n\nbool log(void)\n{   bool ok = true;\n    ok &= LogTestOne();\n    ok &= LogTestTwo();\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/log10.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\nOld example now used just for validation testing.\n*/\n# include <cppad/cppad.hpp>\n\nbool log10(void)\n{   bool ok = true;\n    using CppAD::log10;\n    using CppAD::log;\n    using namespace CppAD;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // independent variable vector, indices, values, and declaration\n    CPPAD_TESTVECTOR(AD<double>) U(1);\n    size_t s = 0;\n    U[s]     = 10.;\n    Independent(U);\n\n    // dependent variable vector, indices, and values\n    CPPAD_TESTVECTOR(AD<double>) Z(2);\n    size_t x = 0;\n    size_t y = 1;\n    Z[x]     = log10(U[s]);\n    Z[y]     = log10(Z[x]);\n\n    // define f : U -> Z and vectors for derivative calculations\n    ADFun<double> f(U, Z);\n    CPPAD_TESTVECTOR(double) v( f.Domain() );\n    CPPAD_TESTVECTOR(double) w( f.Range() );\n\n    // check values\n    ok &= NearEqual(Z[x] , 1.,  eps99 , eps99);\n    ok &= NearEqual(Z[y] , 0.,  eps99 , eps99);\n\n    // forward computation of partials w.r.t. s\n    double l10 = log(10.);\n    v[s] = 1.;\n    w    = f.Forward(1, v);\n    ok &= NearEqual(w[x], 1./(U[s]*l10)         , eps99 , eps99); // dx/ds\n    ok &= NearEqual(w[y], 1./(U[s]*Z[x]*l10*l10), eps99 , eps99); // dy/ds\n\n    // reverse computation of partials of y\n    w[x] = 0.;\n    w[y] = 1.;\n    v    = f.Reverse(1,w);\n    ok &= NearEqual(v[s], 1./(U[s]*Z[x]*l10*l10), eps99 , eps99); // dy/ds\n\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/log1p.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/cppad.hpp>\n\nbool log1p(void)\n{   bool ok = true;\n\n    using CppAD::AD;\n    using CppAD::NearEqual;\n\n    // 10 times machine epsilon\n    double eps = 10. * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n  = 1;\n    double x0 = 0.5;\n    CPPAD_TESTVECTOR(AD<double>) ax(n);\n    ax[0]     = x0;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(ax);\n\n    // a temporary value\n    AD<double> expm1_of_x0 = CppAD::expm1(ax[0]);\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) ay(m);\n    ay[0] = CppAD::log1p(expm1_of_x0);\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(ax, ay);\n\n    // check value\n    ok &= NearEqual(ay[0] , x0,  eps, eps);\n\n    // forward computation of first partial w.r.t. x[0]\n    CPPAD_TESTVECTOR(double) dx(n);\n    CPPAD_TESTVECTOR(double) dy(m);\n    dx[0] = 1.;\n    dy    = f.Forward(1, dx);\n    ok   &= NearEqual(dy[0], 1., eps, eps);\n\n    // forward computation of higher order partials w.r.t. x[0]\n    size_t n_order = 5;\n    for(size_t order = 2; order < n_order; order++)\n    {   dx[0] = 0.;\n        dy    = f.Forward(order, dx);\n        ok   &= NearEqual(dy[0], 0., eps, eps);\n    }\n    // reverse computation of derivatives\n    CPPAD_TESTVECTOR(double)  w(m);\n    CPPAD_TESTVECTOR(double) dw(n_order * n);\n    w[0]  = 1.;\n    dw    = f.Reverse(n_order, w);\n    ok   &= NearEqual(dw[0], 1., eps, eps);\n    for(size_t order = 1; order < n_order; order++)\n        ok   &= NearEqual(dw[order * n + 0], 0., eps, eps);\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "test_more/general/mul.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\nTwo old Mul examples now used just for valiadation testing\n*/\n# include <cppad/cppad.hpp>\n\nnamespace { // BEGIN empty namespace\n\nbool zero_times_nan(void)\n{   bool ok = true;\n\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) ax(2), ay(3);\n    ax[0] = 0.0;\n    ax[1] = 0.0;\n    CppAD::Independent(ax);\n    CppAD::AD<double> adiv = ax[0] / ax[1];\n    //\n    // the result for each of these cases should be identically zero\n    ay[0] = 0.0 * adiv;\n    ay[1] = adiv * 0.0;\n    ay[2] = 0.0 / adiv;\n    //\n    CppAD::ADFun<double> f(ax, ay);\n    //\n    CPPAD_TESTVECTOR(double) x(2), y(3);\n    x[0] = 1.0;\n    x[1] = 1.0;\n    y    = f.Forward(0, x);\n    ok  &= y[0] == 0.0;\n    ok  &= y[1] == 0.0;\n    ok  &= y[2] == 0.0;\n\n    return ok;\n}\n\nbool MulTestOne(void)\n{   bool ok = true;\n\n    using namespace CppAD;\n\n    // independent variable vector, indices, values, and declaration\n    CPPAD_TESTVECTOR(AD<double>) U(2);\n    size_t s = 0;\n    size_t t = 1;\n    U[s]     = 3.;\n    U[t]     = 2.;\n    Independent(U);\n\n    // assign some parameters\n    AD<double> zero = 0.;\n    AD<double> one  = 1.;\n\n    // dependent variable vector and indices\n    CPPAD_TESTVECTOR(AD<double>) Z(5);\n    size_t x = 0;\n    size_t y = 1;\n    size_t z = 2;\n    size_t u = 3;\n    size_t v = 4;\n\n    // assign the dependent variables\n    Z[x] = U[s] * U[t];   // AD<double> * AD<double>\n    Z[y] = Z[x] * 4.;     // AD<double> *    double\n    Z[z] = 4.   * Z[y];   //    double  * AD<double>\n    Z[u] =  one * Z[z];   // multiplication by parameter equal to one\n    Z[v] = zero * Z[z];   // multiplication by parameter equal to zero\n\n    // check multipilcation by zero results in a parameter\n    ok &= Parameter(Z[v]);\n\n    // create f: U -> Z and vectors used for derivative calculations\n    ADFun<double> f(U, Z);\n    CPPAD_TESTVECTOR(double) q( f.Domain() );\n    CPPAD_TESTVECTOR(double) r( f.Range() );\n\n    // check parameter flag\n    ok &= f.Parameter(v);\n\n    // check values\n    ok &= ( Z[x] == 3. * 2. );\n    ok &= ( Z[y] == 3. * 2. * 4. );\n    ok &= ( Z[z] == 4. * 3. * 2. * 4. );\n    ok &= ( Z[u] == Z[z] );\n    ok &= ( Z[v] == 0. );\n\n    // forward computation of partials w.r.t. s\n    q[s] = 1.;\n    q[t] = 0.;\n    r    = f.Forward(1, q);\n    ok &= ( r[x] == U[t] );           // dx/ds\n    ok &= ( r[y] == U[t] * 4. );      // dy/ds\n    ok &= ( r[z] == 4. * U[t] * 4. ); // dz/ds\n    ok &= ( r[u] == r[z] );           // du/ds\n    ok &= ( r[v] == 0. );             // dv/ds\n\n    // reverse computation of second partials of z\n    CPPAD_TESTVECTOR(double) d2( f.Domain() * 2 );\n    r[x] = 0.;\n    r[y] = 0.;\n    r[z] = 1.;\n    r[u] = 0.;\n    r[v] = 0.;\n    d2   = f.Reverse(2, r);\n\n    // check second order partials\n    ok &= ( d2[2 * s + 1] == 0. );             // d^2 z / (ds ds)\n    ok &= ( d2[2 * t + 1] == 4. * 4. );        // d^2 z / (ds dt)\n\n    return ok;\n}\n\nbool MulTestTwo(void)\n{   bool ok = true;\n    using namespace CppAD;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // independent variable vector\n    double u0 = .5;\n    CPPAD_TESTVECTOR(AD<double>) U(1);\n    U[0]      = u0;\n    Independent(U);\n\n    AD<double> a = U[0] * 1.; // AD<double> * double\n    AD<double> b = a  * 2;    // AD<double> * int\n    AD<double> c = 3. * b;    // double     * AD<double>\n    AD<double> d = 4  * c;    // int        * AD<double>\n\n    // dependent variable vector\n    CPPAD_TESTVECTOR(AD<double>) Z(1);\n    Z[0] = U[0] * d;          // AD<double> * AD<double>\n\n    // create f: U -> Z and vectors used for derivative calculations\n    ADFun<double> f(U, Z);\n    CPPAD_TESTVECTOR(double) v(1);\n    CPPAD_TESTVECTOR(double) w(1);\n\n    // check value\n    ok &= NearEqual(Value(Z[0]) , u0*4*3*2*u0,  eps99 , eps99);\n\n    // forward computation of partials w.r.t. u\n    size_t j;\n    size_t p     = 5;\n    double jfac  = 1.;\n    v[0]         = 1.;\n    for(j = 1; j < p; j++)\n    {   double value;\n        if( j == 1 )\n            value = 48. * u0;\n        else if( j == 2 )\n            value = 48.;\n        else\n            value = 0.;\n\n        jfac *= double(j);\n        w     = f.Forward(j, v);\n        ok &= NearEqual(w[0], value/jfac, eps99, eps99); // d^jz/du^j\n        v[0]  = 0.;\n    }\n\n    // reverse computation of partials of Taylor coefficients\n    CPPAD_TESTVECTOR(double) r(p);\n    w[0]  = 1.;\n    r     = f.Reverse(p, w);\n    jfac  = 1.;\n    for(j = 0; j < p; j++)\n    {   double value;\n        if( j == 0 )\n            value = 48. * u0;\n        else if( j == 1 )\n            value = 48.;\n        else\n            value = 0.;\n\n        ok &= NearEqual(r[j], value/jfac, eps99, eps99); // d^jz/du^j\n        jfac *= double(j + 1);\n    }\n\n    return ok;\n}\n\n} // END empty namespace\n\nbool Mul(void)\n{   bool ok = true;\n    ok &= MulTestOne();\n    ok &= MulTestTwo();\n    ok &= zero_times_nan();\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/mul_cond_rev.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n/*\nTest of multi-level conditional expressions reverse mode\n*/\n\n# include <cppad/cppad.hpp>\n\nbool mul_cond_rev(void)\n{\n    bool ok = true;\n    using CppAD::vector;\n    using CppAD::NearEqual;\n    double eps = 10. * std::numeric_limits<double>::epsilon();\n    //\n    typedef CppAD::AD<double>   a1double;\n    typedef CppAD::AD<a1double> a2double;\n    //\n    a1double a1zero = 0.0;\n    a2double a2zero = a1zero;\n    a1double a1one  = 1.0;\n    a2double a2one  = a1one;\n    //\n    // --------------------------------------------------------------------\n    // create a1f = f(x)\n    size_t n = 1;\n    size_t m = 25;\n    //\n    vector<a2double> a2x(n), a2y(m);\n    a2x[0] = a2double( 5.0 );\n    Independent(a2x);\n    //\n    size_t i = 0;\n    // variable that is greater than one when x[0] is zero\n    // and less than one when x[0] is 1.0 or greater\n    a2double a2switch  = a2one / (a2x[0] + a2double(0.5));\n    // variable that is infinity when x[0] is zero\n    // and a normal number when x[0] is 1.0 or greater\n    a2double a2inf_var = a2one / a2x[0];\n    // variable that is nan when x[0] is zero\n    // and a normal number when x[0] is 1.0 or greater\n    a2double a2nan_var = ( a2one / a2inf_var ) / a2x[0];\n    // variable that is one when x[0] is zero\n    // and less then one when x[0] is 1.0 or greater\n    a2double a2one_var = a2one / ( a2one + a2x[0] );\n    // div\n    a2y[i++]  = CondExpGt(a2x[0], a2zero, a2nan_var, a2zero);\n    // abs\n    a2y[i++]  = CondExpGt(a2x[0], a2zero, fabs( a2y[0] ), a2zero);\n    // add\n    a2y[i++]  = CondExpGt(a2x[0], a2zero, a2nan_var + a2nan_var, a2zero);\n    // acos\n    a2y[i++]  = CondExpGt(a2x[0], a2zero, acos(a2switch), a2zero);\n    // asin\n    a2y[i++]  = CondExpGt(a2x[0], a2zero, asin(a2switch), a2zero);\n    // atan\n    a2y[i++]  = CondExpGt(a2x[0], a2zero, atan(a2nan_var), a2zero);\n    // cos\n    a2y[i++]  = CondExpGt(a2x[0], a2zero, cos(a2nan_var), a2zero);\n    // cosh\n    a2y[i++]  = CondExpGt(a2x[0], a2zero, cosh(a2nan_var), a2zero);\n    // exp\n    a2y[i++]  = CondExpGt(a2x[0], a2zero, exp(a2nan_var), a2zero);\n    // log\n    a2y[i++]  = CondExpGt(a2x[0], a2zero, log(a2x[0]), a2zero);\n    // mul\n    a2y[i++]  = CondExpGt(a2x[0], a2zero, a2x[0] * a2inf_var, a2zero);\n    // pow\n    a2y[i++]  = CondExpGt(a2x[0], a2zero, pow(a2inf_var, a2x[0]), a2zero);\n    // sin\n    a2y[i++]  = CondExpGt(a2x[0], a2zero, sin(a2nan_var), a2zero);\n    // sinh\n    a2y[i++]  = CondExpGt(a2x[0], a2zero, sinh(a2nan_var), a2zero);\n    // sqrt\n    a2y[i++]  = CondExpGt(a2x[0], a2zero, sqrt(a2x[0]), a2zero);\n    // sub\n    a2y[i++]  = CondExpGt(a2x[0], a2zero, a2inf_var - a2nan_var, a2zero);\n    // tan\n    a2y[i++]  = CondExpGt(a2x[0], a2zero, tan(a2nan_var), a2zero);\n    // tanh\n    a2y[i++]  = CondExpGt(a2x[0], a2zero, tanh(a2nan_var), a2zero);\n    // azmul\n    a2y[i++]  = CondExpGt(a2x[0], a2zero, azmul(a2x[0], a2inf_var), a2zero);\n    //\n    // Operations that are C+11 atomic\n    //\n    // acosh\n    a2y[i++]  = CondExpGt(a2x[0], a2zero, acosh( a2x[0] ), a2zero);\n    // asinh\n    a2y[i++]  = CondExpGt(a2x[0], a2zero, asinh( a2nan_var ), a2zero);\n    // atanh\n    a2y[i++]  = CondExpGt(a2x[0], a2zero, atanh( a2one_var ), a2zero);\n    // erf\n    a2y[i++]  = CondExpGt(a2x[0], a2zero, erf( a2nan_var ), a2zero);\n    // expm1\n    a2y[i++]  = CondExpGt(a2x[0], a2zero, expm1(a2nan_var), a2zero);\n    // log1p\n    a2y[i++]  = CondExpGt(a2x[0], a2zero, log1p(- a2one_var ), a2zero);\n    //\n    ok &= i == m;\n    CppAD::ADFun<a1double> a1f;\n    a1f.Dependent(a2x, a2y);\n    // --------------------------------------------------------------------\n    // create h = f(x)\n    vector<a1double> a1x(n), a1y(m);\n    a1x[0] = 5.0;\n    //\n    Independent(a1x);\n    i = 0;\n    a1double a1switch  = a1one / (a1x[0] + a1double(0.5));\n    a1double a1inf_var = a1one / a1x[0];\n    a1double a1nan_var = ( a1one / a1inf_var ) / a1x[0];\n    a1double a1one_var = a1one / ( a1one + a1x[0] );\n    // div\n    a1y[i++]  = CondExpGt(a1x[0], a1zero, a1nan_var, a1zero);\n    // abs\n    a1y[i++]  = CondExpGt(a1x[0], a1zero, fabs( a1y[0] ), a1zero);\n    // add\n    a1y[i++]  = CondExpGt(a1x[0], a1zero, a1nan_var + a1nan_var, a1zero);\n    // acos\n    a1y[i++]  = CondExpGt(a1x[0], a1zero, acos(a1switch), a1zero);\n    // asin\n    a1y[i++]  = CondExpGt(a1x[0], a1zero, asin(a1switch), a1zero);\n    // atan\n    a1y[i++]  = CondExpGt(a1x[0], a1zero, atan(a1nan_var), a1zero);\n    // cos\n    a1y[i++]  = CondExpGt(a1x[0], a1zero, cos(a1nan_var), a1zero);\n    // cosh\n    a1y[i++]  = CondExpGt(a1x[0], a1zero, cosh(a1nan_var), a1zero);\n    // exp\n    a1y[i++]  = CondExpGt(a1x[0], a1zero, exp(a1nan_var), a1zero);\n    // log\n    a1y[i++]  = CondExpGt(a1x[0], a1zero, log(a1x[0]), a1zero);\n    // mul\n    a1y[i++]  = CondExpGt(a1x[0], a1zero, a1x[0] * a1inf_var, a1zero);\n    // pow\n    a1y[i++]  = CondExpGt(a1x[0], a1zero, pow(a1inf_var, a1x[0]), a1zero);\n    // sin\n    a1y[i++]  = CondExpGt(a1x[0], a1zero, sin(a1nan_var), a1zero);\n    // sinh\n    a1y[i++]  = CondExpGt(a1x[0], a1zero, sinh(a1nan_var), a1zero);\n    // sqrt\n    a1y[i++]  = CondExpGt(a1x[0], a1zero, sqrt(a1x[0]), a1zero);\n    // sub\n    a1y[i++]  = CondExpGt(a1x[0], a1zero, a1inf_var - a1nan_var, a1zero);\n    // tan\n    a1y[i++]  = CondExpGt(a1x[0], a1zero, tan(a1nan_var), a1zero);\n    // tanh\n    a1y[i++]  = CondExpGt(a1x[0], a1zero, tanh(a1nan_var), a1zero);\n    // azmul\n    a1y[i++]  = CondExpGt(a1x[0], a1zero, azmul(a1x[0], a1inf_var), a1zero);\n    //\n    // Operations that are C+11 atomic\n    //\n    // acosh\n    a1y[i++]  = CondExpGt(a1x[0], a1zero, acosh( a1x[0] ), a1zero);\n    // asinh\n    a1y[i++]  = CondExpGt(a1x[0], a1zero, asinh( a1nan_var ), a1zero);\n    // atanh\n    a1y[i++]  = CondExpGt(a1x[0], a1zero, atanh( a1one_var ), a1zero);\n    // erf\n    a1y[i++]  = CondExpGt(a1x[0], a1zero, erf( a1nan_var ), a1zero);\n    // expm1\n    a1y[i++]  = CondExpGt(a1x[0], a1zero, expm1(a1nan_var), a1zero);\n    // log1p\n    a1y[i++]  = CondExpGt(a1x[0], a1zero, log1p(- a1one_var ), a1zero);\n    //\n    ok &= i == m;\n    CppAD::ADFun<double> h;\n    h.Dependent(a1x, a1y);\n    // --------------------------------------------------------------------\n    // create g = f'(x)\n    vector<a1double> a1dy(m), a1w(m);\n    a1x[0] = 2.0;\n    for(i = 0; i < m; i++)\n        a1w[i] = 0.0;\n    //\n    Independent(a1x);\n    a1f.Forward(0, a1x);\n    //\n    for(i = 0; i < m; i++)\n    {   a1w[i] = 1.0;\n        vector<a1double> dyi_dx = a1f.Reverse(1, a1w);\n        a1dy[i] = dyi_dx[0];\n        a1w[i] = 0.0;\n    }\n    CppAD::ADFun<double> g; // g uses reverse mode derivatives\n    g.Dependent(a1x, a1dy);\n    // --------------------------------------------------------------------\n    // check case where x[0] > 0\n    vector<double> x(1), dx(1), dg(m), dh(m);\n    x[0]  = 2.0;\n    dx[0] = 1.0;\n    h.Forward(0, x);\n    dh   = h.Forward(1, dx); // dh uses forward mode derivatives\n    dg   = g.Forward(0, x);\n    for(i = 0; i < m; i++)\n        ok  &= NearEqual(dg[i], dh[i], eps, eps);\n    // --------------------------------------------------------------------\n    // check case where x[0] = 0\n    x[0] = 0.0;\n    dg   = g.Forward(0, x);\n    h.Forward(0, x);\n    dh   = h.Forward(1, dx);\n    for(i = 0; i < m; i++)\n    {   ok  &= dg[i] == 0.0;\n        ok  &= dh[i] == 0.0;\n    }\n    // --------------------------------------------------------------------\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/mul_cskip.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <iostream>\n# include <cppad/cppad.hpp>\n\n// Test multiple level conditional skip where value of comparison is\n// uncertain during forward mode base Base value can be a variable.\nbool mul_cskip(void)\n{   bool ok = true;\n    using namespace CppAD;\n    using CppAD::vector;\n\n    typedef AD<double>  a1type;\n    typedef AD<a1type>  a2type;\n\n    size_t n = 2;\n    size_t m = 1;\n    vector<double> x(n), y(m);\n    x[0] = 0.0;\n    x[1] = 1.0;\n\n    // start recording a2type operations\n    vector<a2type> a2x(n), a2y(m);\n    for (size_t j = 0; j < n; j++)\n        a2x[j] = a2type( a1type(x[j]) );\n    Independent(a2x);\n\n    // a1f(x) = x_0 * x_1 if x[0] == 1\n    //         0.0       otherwise\n    a2type a2zero = a2type(0.0);\n    a2type a2one  = a2type(1.0);\n    a2type a2p    = a2x[0] * a2x[1];\n    a2y[0]        = CondExpEq(a2x[0], a2one, a2p, a2zero);\n    ADFun<a1type> a1f(a2x, a2y);\n\n    // Optimization will check to see if we can skip part of conditional\n    // expression that is not used.\n    a1f.optimize();\n\n    // f(x) = x_0 * x_1 if x[0] == 1\n    //        0.0       otherwise\n    vector<a1type> a1x(n), a1y(m);\n    for (size_t j = 0; j < n; j++)\n        a1x[j] = a1type(x[j]);\n    Independent(a1x);\n    a1y = a1f.Forward(0, a1x);\n    CppAD::ADFun<double> f(a1x, a1y);\n\n    // check case where x[0] == 1\n    x[0] = 1.0;\n    x[1] = 2.0;\n    y = f.Forward(0, x);\n    ok &= y[0] == x[1];\n\n    // check case where x[0] != 1\n    x[0] = 3.0;\n    x[1] = 2.0;\n    y = f.Forward(0, x);\n    ok &= y[0] == 0.0;\n\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/mul_eq.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\nTwo old MulEq examples now used just for valiadation testing\n*/\n# include <cppad/cppad.hpp>\n\nnamespace { // BEGIN empty namespace\n\nbool MulEqTestOne(void)\n{   bool ok = true;\n\n    using namespace CppAD;\n\n    // independent variable vector, indices, values, and declaration\n    CPPAD_TESTVECTOR(AD<double>) U(2);\n    size_t s = 0;\n    size_t t = 1;\n    U[s]     = 3.;\n    U[t]     = 2.;\n    Independent(U);\n\n    // dependent variable vector and indices\n    CPPAD_TESTVECTOR(AD<double>) Z(2);\n    size_t x = 0;\n    size_t y = 1;\n\n    // some initial values\n    AD<double> zero = 0.;\n    AD<double> one  = 1.;\n\n    // dependent variable values\n    Z[x]  = U[s];\n    Z[y]  = U[t];\n    Z[x] *= U[t];  // AD<double> *= AD<double>\n    Z[y] *= 5.;    // AD<double> *= double\n    zero *= Z[x];\n    one  *= Z[x];\n\n    // check that zero is a parameter\n    ok &= Parameter(zero);\n\n    // create f: U -> Z and vectors used for derivative calculations\n    ADFun<double> f(U, Z);\n    CPPAD_TESTVECTOR(double) v( f.Domain() );\n    CPPAD_TESTVECTOR(double) w( f.Range() );\n\n    // check values\n    ok &= ( Z[x] == 3. * 2. );\n    ok &= ( Z[y] == 2. * 5. );\n    ok &= ( zero == 0. );\n    ok &= ( one == Z[x] );\n\n    // forward computation of partials w.r.t. t\n    v[s] = 0.;\n    v[t] = 1.;\n    w    = f.Forward(1, v);\n    ok &= ( w[x] == U[s] );  // dx/dt\n    ok &= ( w[y] == 5. );    // dy/dt\n\n    // reverse computation of second partials of x\n    CPPAD_TESTVECTOR(double) r( f.Domain() * 2 );\n    w[x] = 1.;\n    w[y] = 0.;\n    r    = f.Reverse(2, w);\n    ok &= ( r[2 * s + 1] == 1. );\n    ok &= ( r[2 * t + 1] == 0. );\n\n    return ok;\n}\n\nbool MulEqTestTwo(void)\n{   bool ok = true;\n    using namespace CppAD;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // independent variable vector\n    double u0 = .5;\n    CPPAD_TESTVECTOR(AD<double>) U(1);\n    U[0]      = u0;\n    Independent(U);\n\n    // dependent variable vector\n    CPPAD_TESTVECTOR(AD<double>) Z(1);\n    Z[0] = U[0];       // initial value\n    Z[0] *= 2;         // AD<double> *= int\n    Z[0] *= 4.;        // AD<double> *= double\n    Z[0] *= U[0];      // AD<double> *= AD<double>\n\n    // create f: U -> Z and vectors used for derivative calculations\n    ADFun<double> f(U, Z);\n    CPPAD_TESTVECTOR(double) v(1);\n    CPPAD_TESTVECTOR(double) w(1);\n\n    // check value\n    ok &= NearEqual(Z[0] , u0*2*4*u0,  eps99 , eps99);\n\n    // forward computation of partials w.r.t. u\n    size_t j;\n    size_t p     = 5;\n    double jfac  = 1.;\n    v[0]         = 1.;\n    for(j = 1; j < p; j++)\n    {   double value;\n        if( j == 1 )\n            value = 16. * u0;\n        else if( j == 2 )\n            value = 16.;\n        else\n            value = 0.;\n\n        jfac *= double(j);\n        w     = f.Forward(j, v);\n        ok &= NearEqual(w[0], value/jfac, eps99, eps99); // d^jz/du^j\n        v[0]  = 0.;\n    }\n\n    // reverse computation of partials of Taylor coefficients\n    CPPAD_TESTVECTOR(double) r(p);\n    w[0]  = 1.;\n    r     = f.Reverse(p, w);\n    jfac  = 1.;\n    for(j = 0; j < p; j++)\n    {   double value;\n        if( j == 0 )\n            value = 16. * u0;\n        else if( j == 1 )\n            value = 16.;\n        else\n            value = 0.;\n\n        ok &= NearEqual(r[j], value/jfac, eps99, eps99); // d^jz/du^j\n        jfac *= double(j + 1);\n    }\n\n    return ok;\n}\n\n} // END empty namespace\n\nbool MulEq(void)\n{   bool ok = true;\n    ok &= MulEqTestOne();\n    ok &= MulEqTestTwo();\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/mul_level.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n\n// CPPAD_HAS_* defines and CPPAD_COMPILER_IS_GNUCXX\n# include <cppad/configure.hpp>\n\n# if CPPAD_HAS_ADOLC\n// adolc examples should suppress conversion warnings\n# include <cppad/wno_conversion.hpp>\n//\n# include <adolc/adouble.h>\n# include <adolc/taping.h>\n# include <adolc/interfaces.h>\n// adouble definitions not in Adolc distribution and\n// required in order to use CppAD::AD<adouble>\n# include <cppad/example/base_adolc.hpp>\n# endif\n\n# include <cppad/cppad.hpp>\n# include <limits>\n\nnamespace { // BEGIN empty namespace\n\nbool One(void)\n{   bool ok = true;                          // initialize test result\n    using CppAD::NearEqual;\n    double eps = 10. * std::numeric_limits<double>::epsilon();\n\n\n    typedef CppAD::AD<double>   ADdouble;    // for one level of taping\n    typedef CppAD::AD<ADdouble> ADDdouble;   // for two levels of taping\n    size_t n = 2;                            // dimension for example\n\n    // value of the independent variables\n    CPPAD_TESTVECTOR(ADDdouble) aa_x(n);\n    aa_x[0] = 1.; aa_x[1] = 3.; // test conversion double to AD< AD<double> >\n    aa_x[0] = 2. * aa_x[0];     // test double * AD< AD<double> >\n    CppAD::Independent(aa_x);\n\n    // compute the function f(x) = 2 * x[0] * x[1]\n    CPPAD_TESTVECTOR(ADDdouble) aa_f(1);\n    aa_f[0] = 2. * aa_x[0] * aa_x[1];\n    CppAD::ADFun<ADdouble> F(aa_x, aa_f);\n\n    // value of the independent variables\n    CPPAD_TESTVECTOR(ADdouble)   a_x(n);\n    a_x[0] = 2.; a_x[1] = 3.;\n    Independent(a_x);\n\n    // re-evaluate f(2, 3) (must get deepedence on a_x).\n    size_t p = 0;\n    CPPAD_TESTVECTOR(ADdouble) a_fp(1);\n    a_fp    = F.Forward(p, a_x);\n    ok     &= NearEqual(a_fp[0], 2. * a_x[0] * a_x[1], eps, eps);\n\n    // compute the function g(x) = 2 * partial_x[0] f(x) = 4 * x[1]\n    p = 1;\n    CPPAD_TESTVECTOR(ADdouble) a_dx(n), a_g(1);\n    a_dx[0] = 1.; a_dx[1] = 0.;\n    a_fp    = F.Forward(p, a_dx);\n    a_g[0]  = 2. * a_fp[0];\n    CppAD::ADFun<double> G(a_x, a_g);\n\n    // compute partial_x[1] g(x)\n    CPPAD_TESTVECTOR(double)  xp(n), gp(1);\n    p = 0;\n    xp[0] = 4.; xp[1] = 5.;\n    gp    = G.Forward(p, xp);\n    ok   &= NearEqual(gp[0], 4. * xp[1], eps, eps);\n\n    p = 1;\n    xp[0] = 0.; xp[1] = 1.;\n    gp    = G.Forward(p, xp);\n    ok   &= NearEqual(gp[0], 4., eps, eps);\n\n    return ok;\n}\n\n// f(x) = |x|^2 = .5 * ( x[0]^2 + ... + x[n-1]^2 )\ntemplate <class Type>\nType f_Two(CPPAD_TESTVECTOR(Type) &x)\n{   Type sum;\n\n    // check assignment of AD< AD<double> > = double\n    sum  = .5;\n    sum += .5;\n\n    size_t i = x.size();\n    while(i--)\n        sum += x[i] * x[i];\n\n    // check compound assignment AD< AD<double> > -= int\n    sum -= 1;\n\n    // check double * AD< AD<double> >\n    return .5 * sum;\n}\n\nbool Two(void)\n{   bool ok = true;                          // initialize test result\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    typedef CppAD::AD<double>   ADdouble;    // for one level of taping\n    typedef CppAD::AD<ADdouble> ADDdouble;   // for two levels of taping\n    size_t n = 5;                            // dimension for example\n    size_t j;                                // a temporary index variable\n\n    CPPAD_TESTVECTOR(double)       x(n);\n    CPPAD_TESTVECTOR(ADdouble)   a_x(n);\n    CPPAD_TESTVECTOR(ADDdouble) aa_x(n);\n\n    // value of the independent variables\n    for(j = 0; j < n; j++)\n        a_x[j] = x[j] = double(j); // x[j] = j\n    Independent(a_x);                  // a_x is indedendent for ADdouble\n    for(j = 0; j < n; j++)\n        aa_x[j] = a_x[j];          // track how aa_x depends on a_x\n    CppAD::Independent(aa_x);          // aa_x is independent for ADDdouble\n\n    // compute function\n    CPPAD_TESTVECTOR(ADDdouble) aa_f(1);    // scalar valued function\n    aa_f[0] = f_Two(aa_x);                   // has only one component\n\n    // declare inner function (corresponding to ADDdouble calculation)\n    CppAD::ADFun<ADdouble> a_F(aa_x, aa_f);\n\n    // compute f'(x)\n    size_t p = 1;                        // order of derivative of a_F\n    CPPAD_TESTVECTOR(ADdouble) a_w(1);  // weight vector for a_F\n    CPPAD_TESTVECTOR(ADdouble) a_df(n); // value of derivative\n    a_w[0] = 1;                          // weighted function same as a_F\n    a_df   = a_F.Reverse(p, a_w);        // gradient of f\n\n    // declare outer function (corresponding to ADdouble calculation)\n    CppAD::ADFun<double> df(a_x, a_df);\n\n    // compute the d/dx of f'(x) * v = f''(x) * v\n    CPPAD_TESTVECTOR(double) v(n);\n    CPPAD_TESTVECTOR(double) ddf_v(n);\n    for(j = 0; j < n; j++)\n        v[j] = double(n - j);\n    ddf_v = df.Reverse(p, v);\n\n    // f(x)       = .5 * ( x[0]^2 + x[1]^2 + ... + x[n-1]^2 )\n    // f'(x)      = (x[0], x[1], ... , x[n-1])\n    // f''(x) * v = ( v[0], v[1],  ... , x[n-1] )\n    for(j = 0; j < n; j++)\n        ok &= CppAD::NearEqual(ddf_v[j], v[j], eps99, eps99);\n\n    return ok;\n}\n\n# if CPPAD_HAS_ADOLC\n\nbool adolc(void)\n{   bool ok = true;                   // initialize test result\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    typedef adouble      ADdouble;         // for first level of taping\n    typedef CppAD::AD<ADdouble> ADDdouble; // for second level of taping\n    size_t n = 5;                          // number independent variables\n\n    CPPAD_TESTVECTOR(double)       x(n);\n    CPPAD_TESTVECTOR(ADdouble)   a_x(n);\n    CPPAD_TESTVECTOR(ADDdouble) aa_x(n);\n\n    // value of the independent variables\n    short tag = 0;         // Adolc setup\n    int keep = 1;\n    trace_on(tag, keep);\n    size_t j;\n    for(j = 0; j < n; j++)\n    {   x[j] = double(j);           // x[j] = j\n        a_x[j] <<= x[j];            // a_x is independent for ADdouble\n    }\n    for(j = 0; j < n; j++)\n        aa_x[j] = a_x[j];          // track how aa_x depends on a_x\n    CppAD::Independent(aa_x);          // aa_x is independent for ADDdouble\n\n    // compute function\n    CPPAD_TESTVECTOR(ADDdouble) aa_f(1);    // scalar valued function\n    aa_f[0] = f_Two(aa_x);                   // has only one component\n\n    // declare inner function (corresponding to ADDdouble calculation)\n    CppAD::ADFun<ADdouble> a_F(aa_x, aa_f);\n\n    // compute f'(x)\n    size_t p = 1;                        // order of derivative of a_F\n    CPPAD_TESTVECTOR(ADdouble) a_w(1);  // weight vector for a_F\n    CPPAD_TESTVECTOR(ADdouble) a_df(n); // value of derivative\n    a_w[0] = 1;                          // weighted function same as a_F\n    a_df   = a_F.Reverse(p, a_w);        // gradient of f\n\n    // declare outer function\n    // (corresponding to the tape of adouble operations)\n    double df_j;\n    for(j = 0; j < n; j++)\n        a_df[j] >>= df_j;\n    trace_off();\n\n    // compute the d/dx of f'(x) * v = f''(x) * v\n    size_t m      = n;                     // # dependent in f'(x)\n    double *v = nullptr, *ddf_v = nullptr;\n    v     = CPPAD_TRACK_NEW_VEC(m, v);     // track v = new double[m]\n    ddf_v = CPPAD_TRACK_NEW_VEC(n, ddf_v); // track ddf_v = new double[n]\n    for(j = 0; j < n; j++)\n        v[j] = double(n - j);\n    fos_reverse(tag, int(m), int(n), v, ddf_v);\n\n    // f(x)       = .5 * ( x[0]^2 + x[1]^2 + ... + x[n-1]^2 )\n    // f'(x)      = (x[0], x[1], ... , x[n-1])\n    // f''(x) * v = ( v[0], v[1],  ... , x[n-1] )\n    for(j = 0; j < n; j++)\n        ok &= CppAD::NearEqual(ddf_v[j], v[j], eps99, eps99);\n\n    CPPAD_TRACK_DEL_VEC(v);                 // check usage of delete\n    CPPAD_TRACK_DEL_VEC(ddf_v);\n    return ok;\n}\n\n# endif // CPPAD_HAS_ADOLC\n\nbool std_math(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::Independent;\n    using CppAD::ADFun;\n    double eps = std::numeric_limits<double>::epsilon();\n\n\n    typedef AD<double>      ADdouble; // for first level of taping\n    typedef AD<ADdouble>   ADDdouble; // for second level of taping\n    size_t n = 1;         // number independent variables\n    size_t m = 1;         // number dependent and independent variables\n\n    CPPAD_TESTVECTOR(double)       x(n),   y(m);\n    CPPAD_TESTVECTOR(ADdouble)    ax(n),  ay(m);\n    CPPAD_TESTVECTOR(ADDdouble)  aax(n), aay(m);\n\n    // create af(x) = tanh(x)\n    aax[0] = 1.;\n    Independent( aax );\n    aay[0] = tanh(aax[0]);\n    ADFun<ADdouble> af(aax, aay);\n\n    // create g(x) = af(x)\n    ax[0] = 1.;\n    Independent( ax );\n    ay = af.Forward(0, ax);\n    ADFun<double> g(ax, ay);\n\n    // evaluate h(x) = g(x)\n    x[0] = 1.;\n    y = g.Forward(0, x);\n\n    // check result\n    double check  = tanh(x[0]);\n    ok &= CppAD::NearEqual(y[0], check, eps, eps);\n\n    return ok;\n}\n\nbool fabs(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::Independent;\n    using CppAD::ADFun;\n    double eps = std::numeric_limits<double>::epsilon();\n\n\n    typedef AD<double>      ADdouble; // for first level of taping\n    typedef AD<ADdouble>   ADDdouble; // for second level of taping\n    size_t n = 1;         // number independent variables\n    size_t m = 1;         // number dependent and independent variables\n\n    CPPAD_TESTVECTOR(double)       x(n),   y(m);\n    CPPAD_TESTVECTOR(ADdouble)    ax(n),  ay(m);\n    CPPAD_TESTVECTOR(ADDdouble)  aax(n), aay(m);\n\n    // create af(x) = fabs(x)\n    aax[0] = 1.;\n    Independent( aax );\n    aay[0] = fabs(aax[0]);\n    ADFun<ADdouble> af(aax, aay);\n\n    // create g(x) = af'(x)\n    ax[0] = 1.;\n    Independent( ax );\n    ay = af.Jacobian(ax);\n    ADFun<double> g(ax, ay);\n\n    // evaluate g(x) at same x as recording\n    x[0] = 1.;\n    y = g.Forward(0, x);\n\n    // check result\n    double check  = 1.;\n    ok &= CppAD::NearEqual(y[0], check, eps, eps);\n\n    // evaluate g(x) at different x from recording\n    // (but abs is an atomic operation so derivative should work)\n    x[0] = -1.;\n    y = g.Forward(0, x);\n\n    // check result\n    check  = -1.;\n    ok &= CppAD::NearEqual(y[0], check, eps, eps);\n\n    return ok;\n}\n\n} // END empty namespace\n\nbool mul_level(void)\n{   bool ok = true;\n    ok     &= One();\n    ok     &= Two();\n# if CPPAD_HAS_ADOLC\n    ok     &= adolc();\n# endif\n    ok     &= std_math();\n    ok     &= fabs();\n\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/mul_zdouble.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n// Check that multilevel reverse with conditional expressions works properly\n// when using AD< AD<zdouble> >.\n\n# include <cppad/cppad.hpp>\nnamespace {\n    using CppAD::AD;\n    using CppAD::zdouble;\n    using CppAD::ADFun;\n    using CppAD::vector;\n    typedef AD<zdouble> a1type;\n    typedef AD<a1type>  a2type;\n    typedef vector<a2type> (*a2fun)(const vector<a2type>& a2x);\n    //\n    zdouble eps    = 10. * std::numeric_limits<double>::epsilon();\n    size_t  n_     = 2;\n    size_t  m_     = 1;\n    //\n    void record(a2fun fun, ADFun<zdouble>& g)\n    {   vector<zdouble>  x(n_);\n        vector<a1type> a1x(n_), a1w(m_), a1z(m_ * n_);\n        vector<a2type> a2x(n_), a2y(m_);\n        //\n        for(size_t j = 0; j < n_; j++)\n        {   x[j]   = 0.0;\n            a1x[j] = a1type( x[j] );\n            a2x[j] = a2type( a1x[j] );\n        }\n        Independent(a2x);\n        // f(x) = x[0] / x[1] if x[1] > 0.0 else 0.0\n        a2y = fun(a2x);\n        ADFun<a1type> a1f;\n        a1f.Dependent(a2x, a2y);\n        // use reverse mode to calculate g(x) = f'(x)\n        a1w[0] = a1type(1.0);\n        Independent(a1x);\n        a1f.Forward(0, a1x);\n        a1z    = a1f.Reverse(1, a1w);\n        g.Dependent(a1x, a1z);\n        //\n        return;\n    }\n    // ----------------------------------------------------------------------\n    vector<a2type> div(const vector<a2type>& a2x)\n    {   vector<a2type> a2y(m_);\n        a2type a2zero = a2type(0.0);\n        a2type a2four = a2type(4.0);\n        a2y[0]  = CondExpGt(a2x[1], a2zero, a2x[0] / a2x[1], a2zero);\n        a2y[0] += CondExpGt(a2x[1], a2zero, a2four / a2x[1], a2zero);\n        return a2y;\n    }\n    bool check_div(void)\n    {   bool ok = true;\n        // record division operations\n        ADFun<zdouble> g;\n        record(div, g);\n        vector<zdouble>  x(n_), z(n_);\n        // check result where x[1] <= 0.0 (would be nan without absolute zero)\n        x[0] = 0.0;\n        x[1] = 0.0;\n        z   = g.Forward(0, x);\n        z = g.Forward(0, x);\n        ok &= z[0] == 0.0;\n        ok &= z[1] == 0.0;\n        // check result where x[1] > 0.0\n        x[0] = 2.0;\n        x[1] = 3.0;\n        z   = g.Forward(0, x);\n        ok &= CppAD::NearEqual(z[0], 1.0/x[1], eps, eps);\n        ok &= CppAD::NearEqual(z[1], - (x[0]+4.0)/(x[1]*x[1]), eps, eps);\n        //\n        return ok;\n    }\n    // ----------------------------------------------------------------------\n    vector<a2type> mul(const vector<a2type>& a2x)\n    {   vector<a2type> a2y(m_);\n        a2type a2zero = a2type(0.0);\n        a2type a2four = a2type(4.0);\n        a2y[0]  = CondExpLt(a2x[0], a2four, a2x[0] * a2x[1], a2zero);\n        a2y[0] += CondExpLt(a2x[0], a2four, a2four * a2x[1], a2zero);\n        a2y[0] += CondExpLt(a2x[0], a2four, a2x[1] * a2four, a2zero);\n        return a2y;\n    }\n    bool check_mul(void)\n    {   bool ok = true;\n        // record multiplication operations\n        ADFun<zdouble> g;\n        record(mul, g);\n        vector<zdouble>  x(n_), z(n_);\n        // check result where x[0] > 4 (would be nan without absolute zero)\n        ok &= std::numeric_limits<double>::has_infinity;\n        x[0] = std::numeric_limits<double>::infinity();\n        x[1] = 0.0;\n        z = g.Forward(0, x);\n        ok &= z[0] == 0.0;\n        ok &= z[1] == 0.0;\n        // check result where x[0] < 4\n        x[0] = 2.0;\n        x[1] = 3.0;\n        z   = g.Forward(0, x);\n        ok &= CppAD::NearEqual(z[0], x[1], eps, eps);\n        ok &= CppAD::NearEqual(z[1], x[0]+8.0, eps, eps);\n        //\n        return ok;\n    }\n    // ----------------------------------------------------------------------\n    bool check_numeric_limits(void)\n    {   bool ok = true;\n        //\n        double   double_eps  = std::numeric_limits<double>::epsilon();\n        zdouble  zdouble_eps = CppAD::numeric_limits<zdouble>::epsilon();\n        ok &= double_eps == zdouble_eps;\n        //\n        double   double_min  = std::numeric_limits<double>::min();\n        zdouble  zdouble_min = CppAD::numeric_limits<zdouble>::min();\n        ok &= double_min == zdouble_min;\n        //\n        double   double_max  = std::numeric_limits<double>::max();\n        zdouble  zdouble_max = CppAD::numeric_limits<zdouble>::max();\n        ok &= double_max == zdouble_max;\n        //\n        return ok;\n    }\n\n}\n\nbool mul_zdouble(void)\n{   bool ok = true;\n\n    ok &= check_div();\n    ok &= check_mul();\n    ok &= check_numeric_limits();\n\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/mul_zero_one.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\nTest the use of the special parameters zero and one with the multiply operator\n*/\n\n# include <cppad/cppad.hpp>\n\ntypedef CppAD::AD<double>      ADdouble;\ntypedef CppAD::AD< ADdouble > ADDdouble;\n\nbool MulZeroOne(void)\n{\n    using namespace CppAD;\n\n    bool ok = true;\n\n    size_t i;\n    for(i = 0; i < 3; i++)\n    {   // run through the cases x = 0, 1, 2\n\n        size_t j;\n        for(j = 0; j < 3; j++)\n        {   // run through the cases y = 0, 1, 2\n\n            CPPAD_TESTVECTOR( ADdouble ) x(1);\n            x[0] = double(i);\n            Independent(x);\n\n            CPPAD_TESTVECTOR( ADDdouble ) y(1);\n            y[0] = ADDdouble(j);\n            Independent(y);\n\n            CPPAD_TESTVECTOR( ADDdouble ) z(2);\n            z[0]  = x[0] * y[0];\n            z[1]  = y[0] * x[0];\n            z[1] *= x[0];\n\n            // f(y) = z = { x * y , y * x * x }\n            ADFun< ADdouble > f(y, z);\n            CPPAD_TESTVECTOR( ADdouble ) u( f.Domain() );\n            CPPAD_TESTVECTOR( ADdouble ) v( f.Range() );\n\n            // v = f'(y)\n            u[0] = ADdouble(1.);\n            v = f.Forward(1, u);\n\n            // check derivatives of f\n            ok &= v[0] == x[0];\n            ok &= v[1] == x[0] * x[0];\n\n            // g(x) = f'(y) = {x , x * x}\n            ADFun<double> g(x, v);\n            CPPAD_TESTVECTOR( double ) a( g.Domain() );\n            CPPAD_TESTVECTOR( double ) b( g.Range() );\n\n            // b = g'(x)\n            a[0] = 1.;\n            b = g.Forward(1, a);\n\n            // check derivatives of g\n            ok &= (b[0] == 1.);\n            ok &= (b[1] == 2. * x[0]);\n        }\n    }\n\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/near_equal_ext.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\nOld example now just used for validation testing\n*/\n\n# include <cppad/cppad.hpp>\n# include <complex>\n\nbool near_equal_ext(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n\n    // double\n    double x    = 1.00000;\n    double y    = 1.00001;\n    double a    =  .00005;\n    double r    =  .00005;\n    double zero = 0.;\n    double inf  = 1. / zero;\n    double nan  = 0. / zero;\n\n    // AD<double>\n    AD<double> X(x);\n    AD<double> Y(y);\n    AD<double> Inf(inf);\n    AD<double> Nan(nan);\n\n    ok &= NearEqual(X, Y, zero, a);\n    ok &= NearEqual(X, y, zero, a);\n    ok &= NearEqual(x, Y, zero, a);\n\n    ok &= ! NearEqual(X, Y, zero, a/25.);\n    ok &= ! NearEqual(X, y, zero, a/25.);\n    ok &= ! NearEqual(x, Y, zero, a/25.);\n\n    ok &= NearEqual(X, Y, r, zero);\n    ok &= NearEqual(X, y, r, zero);\n    ok &= NearEqual(x, Y, r, zero);\n\n    ok &= ! NearEqual(X, Y, r/25., zero);\n    ok &= ! NearEqual(X, y, r/25., zero);\n    ok &= ! NearEqual(x, Y, r/25., zero);\n\n    ok &= ! NearEqual(Inf, Inf, r, a);\n    ok &= ! NearEqual(Inf, inf, r, a);\n    ok &= ! NearEqual(inf, Inf, r, a);\n\n    ok &= ! NearEqual(-Inf, -Inf, r, a);\n    ok &= ! NearEqual(-Inf, -inf, r, a);\n    ok &= ! NearEqual(-inf, -Inf, r, a);\n\n    ok &= ! NearEqual(Nan, Nan, r, a);\n    ok &= ! NearEqual(Nan, nan, r, a);\n    ok &= ! NearEqual(nan, Nan, r, a);\n\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/neg.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\nold example and test now only used for testing\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n\nbool Neg(void)\n{   bool ok = true;\n\n    using namespace CppAD;\n\n    // independent variable vector, indices, values, and declaration\n    CPPAD_TESTVECTOR(AD<double>) U(2);\n    size_t s = 0;\n    size_t t = 1;\n    U[s]     = 3.;\n    U[t]     = 4.;\n    Independent(U);\n\n    // dependent variable vector and indices\n    CPPAD_TESTVECTOR(AD<double>) Z(1);\n    size_t x = 0;\n\n    // dependent variable values\n    Z[x] = - U[t];   //  - AD<double>\n\n    // create f: U -> Z and vectors used for derivative calculations\n    ADFun<double> f(U, Z);\n    CPPAD_TESTVECTOR(double) v( f.Domain() );\n    CPPAD_TESTVECTOR(double) w( f.Range() );\n\n    // check values\n    ok &= ( Z[x] == -4. );\n\n    // forward computation of partials w.r.t. s\n    v[s] = 1.;\n    v[t] = 0.;\n    w    = f.Forward(1, v);\n    ok &= ( w[x] == 0. );   // dx/ds\n\n    // forward computation of partials w.r.t. t\n    v[s] = 0.;\n    v[t] = 1.;\n    w    = f.Forward(1, v);\n    ok &= ( w[x] == -1. );   // dx/dt\n\n    // reverse computation of second partials of z\n    CPPAD_TESTVECTOR(double) r( f.Domain() * 2 );\n    w[x] = 1.;\n    r    = f.Reverse(2, w);\n    ok &= ( r[2 * s + 1] == 0. );  // d^2 x / (ds ds)\n    ok &= ( r[2 * t + 1] == 0. );  // d^2 x / (ds dt)\n\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "test_more/general/new_dynamic.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <limits>\n# include <cppad/cppad.hpp>\n\nnamespace { // BEGIN_EMPTY_NAMESPACE\n// ----------------------------------------------------------------------------\n//\n// pul_323\n// Test that the with_no_op has the same number of dynamic parameters\n// (and variables) as without_no_op.\nbool pull_232_fun(\n    bool with_no_op         ,\n    CppAD::ADFun<double>& f )\n{   //\n    // ok\n    bool ok = true;\n    //\n    // azero, aone\n    CppAD::AD<double> azero(0.0);\n    CppAD::AD<double> aone(1.0);\n    //\n    // ap, ax, ay\n    CPPAD_TESTVECTOR( CppAD::AD<double> ) ap(1), ax(1), ay(1);\n    ap[0] = 2.0;\n    ax[0] = 3.0;\n    //\n    // ax. ap\n    CppAD::Independent(ax, ap);\n    //\n    // ay\n    ay[0] = 0.0;\n    if( with_no_op ) {\n        ay[0] += ax[0] * ( ap[0] + azero );\n        ay[0] += ax[0] * ( ap[0] - azero );\n        ay[0] += ax[0] * ( ap[0] * aone );\n        ay[0] += ax[0] * ( ap[0] / aone );\n        ay[0] += azero;\n        ay[0] -= azero;\n        ay[0] *= aone;\n        ay[0] /= aone;\n        ay[0] += ax[0] * pow(ap[0] , azero);\n        ay[0] += ax[0] + pow(azero, ap[0]);\n        ay[0] += ax[0] + azmul(azero, ap[0]);\n        ay[0] += ax[0] + azmul(ap[0], azero);\n    } else {\n        ay[0] += ax[0] * ap[0];\n        ay[0] += ax[0] * ap[0];\n        ay[0] += ax[0] * ap[0];\n        ay[0] += ax[0] * ap[0];\n        ay[0] += ax[0];\n        ay[0] += ax[0];\n        ay[0] += ax[0];\n        ay[0] += ax[0];\n    }\n    //\n    // f\n    f.Dependent(ay);\n    //\n    // y, check\n    CPPAD_TESTVECTOR(double) p(1), x(1), y(1);\n    p[0] = 4.0;\n    x[0] = 5.0;\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    double check = 0;\n    check += x[0] * p[0];\n    check += x[0] * p[0];\n    check += x[0] * p[0];\n    check += x[0] * p[0];\n    check += x[0];\n    check += x[0];\n    check += x[0];\n    check += x[0];\n    //\n    // ok\n    ok &= y[0] == check;\n    //\n    return ok;\n}\nbool pull_232(void)\n{   //\n    // ok, no_op\n    bool ok = true;\n    //\n    // with_no_op\n    bool with_no_op;\n    //\n    // ok, f_without\n    CppAD::ADFun<double> f_without;\n    with_no_op = false;\n    ok     &= pull_232_fun(with_no_op, f_without);\n    //\n    // ok, f_with\n    CppAD::ADFun<double> f_with;\n    with_no_op = true;\n    ok     &= pull_232_fun(with_no_op, f_with);\n    //\n    // ok\n    ok &= f_without.size_dyn_par() == f_with.size_dyn_par();\n    ok &= f_without.size_var() == f_with.size_var();\n    //\n    return ok;\n}\n// ----------------------------------------------------------------------------\nbool vecad(void)\n{   bool ok = true;\n    using CppAD::AD;\n\n    // dynamic parameter vector\n    size_t np = 2;\n    size_t nx = 1;\n    size_t ny = 2;\n    CPPAD_TESTVECTOR(AD<double>) ap(np), ax(nx), ay(ny);\n    ap[0] = 0.0;\n    ap[1] = 1.0;\n    ax[0] = 2.0;\n\n    // declare independent variables, dynamic parameters, start recording\n    CppAD::Independent(ax, ap);\n\n    // Create a VecAD object\n    size_t nv = 2;\n    CppAD::VecAD<double> av(nv);\n    // ap[0] is either 0 or 1\n    av[ ap[0] ]       = ap[1];\n    av[ 1.0 - ap[0] ] = 2.0 * ap[1];\n\n    // create f: x -> y and stop tape recording\n    CppAD::AD<double> zero(0.0), one(1.0);\n    ay[0] = av[zero];\n    ay[1] = av[one];\n    CppAD::ADFun<double> f(ax, ay);\n\n    // zero order forward mode with p[0] = 0\n    CPPAD_TESTVECTOR(double) p(np), x(nx), y(ny);\n    p[0] = 0.0;\n    p[1] = 1.0;\n    x[0] = 2.0;\n    f.new_dynamic(p);\n    y   = f.Forward(0, x);\n    ok &= y[0] == p[1];\n    ok &= y[1] == 2.0 * p[1];\n\n    // zero order forward mode with p[0] = 1\n    p[0] = 1.0;\n    p[1] = 2.0;\n    x[0] = 3.0;\n    f.new_dynamic(p);\n    y   = f.Forward(0, x);\n    ok &= y[0] == 2.0 * p[1];\n    ok &= y[1] == p[1];\n    CPPAD_TESTVECTOR(double) dx(nx), dy(ny);\n    dx[0] = 1.0;\n    dy    = f.Forward(1, dx);\n    ok   &= dy[0] == 0.0;\n    ok   &= dy[1] == 0.0;\n\n    return ok;\n}\n// ----------------------------------------------------------------------------\nbool operator_with_variable(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    using CppAD::azmul;\n    using CppAD::CondExpLt;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    size_t n   = 11;\n\n    // dynamic parameter vector\n    CPPAD_TESTVECTOR(AD<double>) adynamic(n);\n    for(size_t j = 0; j < n; ++j)\n        adynamic[j] = 2.0;\n\n    // domain space vector\n    CPPAD_TESTVECTOR(AD<double>) ax(n);\n    for(size_t j = 0; j < n; ++j)\n        ax[j] = AD<double>(j + 1);\n\n    // declare independent variables, dynamic parameters, starting recording\n    CppAD::Independent(ax, adynamic);\n\n    // range space vector\n    CPPAD_TESTVECTOR(AD<double>) ay(n);\n    size_t k = 0;\n    ay[k] = -1.0*double(k+1)*(adynamic[k] + ax[k]) * (ax[k] + adynamic[k]);\n    ++k;\n    ay[k] = -1.0*double(k+1)*(adynamic[k] - ax[k]) * (ax[k] - adynamic[k]);\n    ++k;\n    ay[k] = -1.0*double(k+1)*(adynamic[k] * ax[k]) + (ax[k] * adynamic[k]);\n    ++k;\n    ay[k] = -1.0*double(k+1)*(adynamic[k] / ax[k]) + (ax[k] / adynamic[k]);\n    ++k;\n    ay[k]  = ax[k];\n    ay[k] += adynamic[k];\n    ++k;\n    ay[k]  = adynamic[k];\n    ay[k] -= ax[k];\n    ++k;\n    ay[k]  = ax[k];\n    ay[k] *= adynamic[k];\n    ++k;\n    ay[k]  = adynamic[k];\n    ay[k] /= ax[k];\n    ++k;\n    ay[k]  = pow(ax[k], adynamic[k]) + pow(adynamic[k], ax[k]);\n    ++k;\n    ay[k]  = azmul(ax[k], adynamic[k]) + azmul(adynamic[k], ax[k]);\n    ++k;\n    ay[k]  = CondExpLt(ax[k], adynamic[k], ax[k], adynamic[k]);\n    ++k;\n    ok &= size_t(k) == n;\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(ax, ay);\n\n    // zero order forward mode\n    CPPAD_TESTVECTOR(double) x(n), y(n);\n    for(size_t j = 0; j < n; ++j)\n        x[j] = double(j + 1);\n    y    = f.Forward(0, x);\n    double check;\n    k = 0;\n    check  = ( Value(adynamic[k]) + x[k] ) * ( x[k] + Value(adynamic[k]) );\n    check *= -1.0*double(k+1);\n    ok    &= NearEqual(y[k] , check, eps99, eps99);\n    ++k;\n    check  = ( Value(adynamic[k]) - x[k] ) * ( x[k] - Value(adynamic[k]) );\n    check *= -1.0*double(k+1);\n    ok    &= NearEqual(y[k] , check, eps99, eps99);\n    ++k;\n    check  = -1.0*double(k+1)*( Value(adynamic[k]) * x[k] );\n    check += ( x[k] * Value(adynamic[k]) );\n    ok    &= NearEqual(y[k] , check, eps99, eps99);\n    ++k;\n    check  = -1.0*double(k+1)*( Value(adynamic[k]) / x[k] );\n    check += ( x[k] / Value(adynamic[k]) );\n    ok    &= NearEqual(y[k] , check, eps99, eps99);\n    ++k;\n    check  = x[k] + Value(adynamic[k]);\n    ok    &= NearEqual(y[k] , check, eps99, eps99);\n    ++k;\n    check  = Value(adynamic[k]) - x[k];\n    ok    &= NearEqual(y[k] , check, eps99, eps99);\n    ++k;\n    check  = x[k] * Value(adynamic[k]);\n    ok    &= NearEqual(y[k] , check, eps99, eps99);\n    ++k;\n    check  = Value(adynamic[k]) / x[k];\n    ok    &= NearEqual(y[k] , check, eps99, eps99);\n    ++k;\n    check  = std::pow(x[k], Value(adynamic[k]));\n    check += std::pow(Value(adynamic[k]), x[k]);\n    ok    &= NearEqual(y[k] , check, eps99, eps99);\n    ++k;\n    check  = azmul(x[k], Value(adynamic[k])) + azmul(Value(adynamic[k]), x[k]);\n    ok    &= NearEqual(y[k] , check, eps99, eps99);\n    ++k;\n    check  = CondExpLt( x[k], Value(adynamic[k]), x[k], Value(adynamic[k]) );\n    ok    &= NearEqual(y[k] , check, eps99, eps99);\n    ++k;\n    ok &= size_t(k) == n;\n\n    // change the dynamic parameter values\n    CPPAD_TESTVECTOR(double) dynamic(n);\n    for(size_t j = 0; j < n; j++)\n        dynamic[j] = double(2 * j + 1);\n    f.new_dynamic(dynamic);\n    //\n    y = f.Forward(0, x);\n    k     = 0;\n    check = -1.0*double(k+1)*( dynamic[k] + x[k] ) * ( x[k] + dynamic[k] );\n    ok   &= NearEqual(y[k] , check, eps99, eps99);\n    ++k;\n    check = -1.0*double(k+1)*( dynamic[k] - x[k] ) * ( x[k] - dynamic[k] );\n    ok   &= NearEqual(y[k] , check, eps99, eps99);\n    ++k;\n    check = -1.0*double(k+1)*( dynamic[k] * x[k] ) + ( x[k] * dynamic[k] );\n    ok   &= NearEqual(y[k] , check, eps99, eps99);\n    ++k;\n    check = -1.0*double(k+1)*( dynamic[k] / x[k] ) + ( x[k] / dynamic[k] );\n    ok   &= NearEqual(y[k] , check, eps99, eps99);\n    ++k;\n    check = x[k] + dynamic[k];\n    ok   &= NearEqual(y[k] , check, eps99, eps99);\n    ++k;\n    check = dynamic[k] - x[k];\n    ok   &= NearEqual(y[k] , check, eps99, eps99);\n    ++k;\n    check = x[k] * dynamic[k];\n    ok   &= NearEqual(y[k] , check, eps99, eps99);\n    ++k;\n    check = dynamic[k] / x[k];\n    ok   &= NearEqual(y[k] , check, eps99, eps99);\n    ++k;\n    check  = std::pow(x[k], dynamic[k]);\n    check += std::pow(dynamic[k], x[k]);\n    ok    &= NearEqual(y[k] , check, eps99, eps99);\n    ++k;\n    check  = azmul(x[k], dynamic[k]) + CppAD::azmul(dynamic[k], x[k]);\n    ok    &= NearEqual(y[k] , check, eps99, eps99);\n    ++k;\n    check  = CondExpLt(x[k], dynamic[k], x[k], dynamic[k]);\n    ok    &= NearEqual(y[k] , check, eps99, eps99);\n    ++k;\n    ok &= size_t(k) == n;\n    //\n    return ok;\n}\n// ----------------------------------------------------------------------------\nbool dynamic_operator(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    using CppAD::azmul;\n    using CppAD::sign;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // independent dynamic parameter vector\n    size_t nd  = 1;\n    CPPAD_TESTVECTOR(AD<double>) adynamic(nd);\n    adynamic[0] = 0.5;\n\n    // domain space vector\n    size_t nx = 1;\n    CPPAD_TESTVECTOR(AD<double>) ax(nx);\n    ax[0] = 0.25;\n\n    // declare independent variables, dynamic parameters, starting recording\n    CppAD::Independent(ax, adynamic);\n\n    // range space vector\n    size_t ny = 27;\n    ny += 6;\n    CPPAD_TESTVECTOR(AD<double>) ay(ny);\n    size_t k = 0;\n    // ----------------------------------------------------------\n    // 98 standard math\n    ay[k] = acos(adynamic[0]);\n    ++k;\n    ay[k] = asin(adynamic[0]);\n    ++k;\n    ay[k] = atan(adynamic[0]);\n    ++k;\n    ay[k] = cos(adynamic[0]);\n    ++k;\n    ay[k] = cosh(adynamic[0]);\n    ++k;\n    ay[k] = exp(adynamic[0]);\n    ++k;\n    ay[k] = acos(adynamic[0]);\n    ++k;\n    ay[k] = log(adynamic[0]);\n    ++k;\n    ay[k] = sin(adynamic[0]);\n    ++k;\n    ay[k] = sinh(adynamic[0]);\n    ++k;\n    ay[k] = sqrt(adynamic[0]);\n    ++k;\n    ay[k] = tan(adynamic[0]);\n    ++k;\n    ay[k] = tanh(adynamic[0]);\n    ++k;\n    // ----------------------------------------------------------\n    // 2011 standard math\n    ay[k] = asinh(adynamic[0]);\n    ++k;\n    ay[k] = acosh(adynamic[0] + 1.0);\n    ++k;\n    ay[k] = atanh(adynamic[0]);\n    ++k;\n    ay[k] = expm1(adynamic[0]);\n    ++k;\n    ay[k] = erf(adynamic[0]);\n    ++k;\n    ay[k] = log1p(adynamic[0]);\n    ++k;\n    // ----------------------------------------------------------\n    // binary\n    ay[k]  = 2.0 + adynamic[0];\n    ++k;\n    ay[k]  = 2.0;\n    ay[k] += adynamic[0];  // constant += dynamic\n    ++k;\n    ay[k]  = adynamic[0] / 2.0;\n    ++k;\n    ay[k]  = adynamic[0];\n    ay[k] /= 2.0;          // dynamic /= constant\n    ++k;\n    ay[k]  = 2.0 * adynamic[0];\n    ++k;\n    ay[k]  = 2.0;\n    ay[k] *= adynamic[0];  // constant *= dynamic\n    ++k;\n    ay[k]  = adynamic[0] - 2.0;\n    ++k;\n    ay[k]  = adynamic[0];\n    ay[k] -= 2.0;          // dynamic -= constant\n    ++k;\n    // ----------------------------------------------------------\n    // other\n    ay[k] = - adynamic[0];\n    ++k;\n    ay[k] = fabs(adynamic[0]);\n    ++k;\n    ay[k] = pow(adynamic[0], 2.0);\n    ++k;\n    ay[k] = sign(adynamic[0]);\n    ++k;\n    ay[k] = azmul(2.0, adynamic[0]);\n    ++k;\n    // if dynamic[0] == 0.5 then ay[k] = 1.0 else ay[k] = -1.0\n    ay[k] = CppAD::CondExpEq(\n        adynamic[0], AD<double>(0.5), AD<double>(1.0), AD<double>(-1.0)\n    );\n    ++k;\n    // ----------------------------------------------------------\n    ok &= size_t(k) == ny;\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(ax, ay);\n\n    // change the dynamic parameter values\n    CPPAD_TESTVECTOR(double) dynamic(nd);\n    dynamic[0] = 0.75;\n    f.new_dynamic(dynamic);\n    //\n    CPPAD_TESTVECTOR(double) x(nx), y(ny);\n    y = f.Forward(0, x);\n    k = 0;\n    // ----------------------------------------------------------\n    // 98 standard math\n    double check = std::acos(dynamic[0]);\n    ok   &= NearEqual(y[k], check, eps99, eps99);\n    ++k;\n    check = std::asin(dynamic[0]);\n    ok   &= NearEqual(y[k], check, eps99, eps99);\n    ++k;\n    check = std::atan(dynamic[0]);\n    ok   &= NearEqual(y[k], check, eps99, eps99);\n    ++k;\n    check = std::cos(dynamic[0]);\n    ok   &= NearEqual(y[k], check, eps99, eps99);\n    ++k;\n    check = std::cosh(dynamic[0]);\n    ok   &= NearEqual(y[k], check, eps99, eps99);\n    ++k;\n    check = std::exp(dynamic[0]);\n    ok   &= NearEqual(y[k], check, eps99, eps99);\n    ++k;\n    check = std::acos(dynamic[0]);\n    ok   &= NearEqual(y[k], check, eps99, eps99);\n    ++k;\n    check = std::log(dynamic[0]);\n    ok   &= NearEqual(y[k], check, eps99, eps99);\n    ++k;\n    check = std::sin(dynamic[0]);\n    ok   &= NearEqual(y[k], check, eps99, eps99);\n    ++k;\n    check = std::sinh(dynamic[0]);\n    ok   &= NearEqual(y[k], check, eps99, eps99);\n    ++k;\n    check = std::sqrt(dynamic[0]);\n    ok   &= NearEqual(y[k], check, eps99, eps99);\n    ++k;\n    check = std::tan(dynamic[0]);\n    ok   &= NearEqual(y[k], check, eps99, eps99);\n    ++k;\n    check = std::tanh(dynamic[0]);\n    ok   &= NearEqual(y[k], check, eps99, eps99);\n    ++k;\n    // ----------------------------------------------------------\n    // 2011 standard math\n    check = asinh(dynamic[0]);\n    ok   &= NearEqual(y[k], check, eps99, eps99);\n    ++k;\n    check = std::acosh(dynamic[0] + 1.0);\n    ok   &= NearEqual(y[k], check, eps99, eps99);\n    ++k;\n    check = std::atanh(dynamic[0]);\n    ok   &= NearEqual(y[k], check, eps99, eps99);\n    ++k;\n    check = std::expm1(dynamic[0]);\n    ok   &= NearEqual(y[k], check, eps99, eps99);\n    ++k;\n    check = std::erf(dynamic[0]);\n    ok   &= NearEqual(y[k], check, eps99, eps99);\n    ++k;\n    check = std::log1p(dynamic[0]);\n    ok   &= NearEqual(y[k], check, eps99, eps99);\n    ++k;\n    // ----------------------------------------------------------\n    // binary\n    check = 2.0 + dynamic[0];\n    ok   &= NearEqual(y[k], check, eps99, eps99);\n    ++k;\n    ok   &= NearEqual(y[k], check, eps99, eps99);\n    ++k;\n    check = dynamic[0] / 2.0;\n    ok   &= NearEqual(y[k], check, eps99, eps99);\n    ++k;\n    ok   &= NearEqual(y[k], check, eps99, eps99);\n    ++k;\n    check = 2.0 * dynamic[0];\n    ok   &= NearEqual(y[k], check, eps99, eps99);\n    ++k;\n    ok   &= NearEqual(y[k], check, eps99, eps99);\n    ++k;\n    check = dynamic[0] - 2.0;\n    ok   &= NearEqual(y[k], check, eps99, eps99);\n    ++k;\n    ok   &= NearEqual(y[k], check, eps99, eps99);\n    ++k;\n    // ----------------------------------------------------------\n    // other\n    check = - dynamic[0];\n    ok   &= NearEqual(y[k], check, eps99, eps99);\n    ++k;\n    check = std::fabs(dynamic[0]);\n    ok   &= NearEqual(y[k], check, eps99, eps99);\n    ++k;\n    check = std::pow(dynamic[0], 2.0);\n    ok   &= NearEqual(y[k], check, eps99, eps99);\n    ++k;\n    check = CppAD::sign(dynamic[0]);\n    ok   &= NearEqual(y[k], check, eps99, eps99);\n    ++k;\n    check = azmul(2.0, dynamic[0]);\n    ok   &= NearEqual(y[k], check, eps99, eps99);\n    ++k;\n    // if dynamic[0] == 0.5 then ay[k] = 1.0 else ay[k] = -1.0\n    check = CppAD::CondExpEq(dynamic[0], 0.5, 1.0, -1.0);\n    ++k;\n    // ----------------------------------------------------------\n    ok &= k == ny;\n    //\n    return ok;\n}\n// ----------------------------------------------------------------------------\nbool dynamic_compare(void)\n{   bool ok = true;\n    using CppAD::AD;\n\n    // independent dynamic parameter vector\n    size_t nd  = 1;\n    CPPAD_TESTVECTOR(AD<double>) adynamic(nd);\n\n    // domain space vector\n    size_t nx = 1;\n    CPPAD_TESTVECTOR(AD<double>) ax(nx);\n    ax[0] = 0.0; // value does not matter for this example;\n\n    // range space vector\n    size_t ny = 2;\n    CPPAD_TESTVECTOR(AD<double>) ay(ny);\n\n    // not using abort_op_index, are recording compare operators\n    size_t abort_op_index = 0;\n    bool   record_compare = true;\n\n    // Function object\n    CppAD::ADFun<double> f;\n\n    // vectors used for new_dynamic and Forward.\n    CPPAD_TESTVECTOR(double) dynamic(nd), x(nx), y(ny);\n\n    // ----------------------------------------------------------\n    // operators: ==, !=\n    adynamic[0] = 0.5;\n    CppAD::Independent(ax, abort_op_index, record_compare, adynamic);\n    //\n    // ==\n    if( adynamic[0] == 0.5 )\n        ay[0] = 1.0;\n    else\n        ay[0] = 0.0;\n    //\n    // !=\n    if( adynamic[0] != 0.5 )\n        ay[1] = 1.0;\n    else\n        ay[1] = 0.0;\n\n    // create f: x -> y and stop tape recording\n    f.Dependent(ax, ay);\n    //\n    dynamic[0] = Value( adynamic[0] );\n    f.new_dynamic(dynamic);\n    y  = f.Forward(0, x);\n    ok = f.compare_change_number() == 0;\n    //\n    dynamic[0] = 1.0;\n    f.new_dynamic(dynamic);\n    y  = f.Forward(0, x);\n    ok = f.compare_change_number() == 2;\n\n    // ----------------------------------------------------------\n    // operators: <, <=\n    adynamic[0] = 0.5;\n    CppAD::Independent(ax, abort_op_index, record_compare, adynamic);\n    //\n    // <\n    if( adynamic[0] < 0.5 )\n        ay[0] = 0.0;\n    else\n        ay[0] = 1.0;\n    //\n    // <=\n    if( adynamic[0] <= 0.5 )\n        ay[1] = 1.0;\n    else\n        ay[1] = 0.0;\n\n    // create f: x -> y and stop tape recording\n    f.Dependent(ax, ay);\n    //\n    dynamic[0] = Value( adynamic[0] );\n    f.new_dynamic(dynamic);\n    y  = f.Forward(0, x);\n    ok = f.compare_change_number() == 0;\n    //\n    dynamic[0] = 1.0;\n    f.new_dynamic(dynamic);\n    y  = f.Forward(0, x);\n    ok = f.compare_change_number() == 1;\n\n    // ----------------------------------------------------------\n    // operators: >, >=\n    adynamic[0] = 0.5;\n    CppAD::Independent(ax, abort_op_index, record_compare, adynamic);\n    //\n    // >\n    if( adynamic[0] > 0.4 )\n        ay[0] = 1.0;\n    else\n        ay[0] = 0.0;\n    //\n    // >=\n    if( adynamic[0] >= 0.4 )\n        ay[1] = 1.0;\n    else\n        ay[1] = 0.0;\n\n    // create f: x -> y and stop tape recording\n    f.Dependent(ax, ay);\n    //\n    dynamic[0] = Value( adynamic[0] );\n    f.new_dynamic(dynamic);\n    y  = f.Forward(0, x);\n    ok = f.compare_change_number() == 0;\n    //\n    dynamic[0] = 0.3;\n    f.new_dynamic(dynamic);\n    y  = f.Forward(0, x);\n    ok = f.compare_change_number() == 2;\n    //\n    // ----------------------------------------------------------\n    return ok;\n}\n// ----------------------------------------------------------------------------\nbool optimize_csum(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // independent dynamic parameter vector\n    size_t num_dyn_ind  = 2;\n    CPPAD_TESTVECTOR(AD<double>) adynamic(num_dyn_ind);\n\n    // domain space vector\n    size_t nx = 1;\n    CPPAD_TESTVECTOR(AD<double>) ax(nx);\n    ax[0] = 0.0; // value does not matter for this example;\n\n    // range space vector\n    size_t ny = 2;\n    CPPAD_TESTVECTOR(AD<double>) ay(ny);\n\n    // not using abort_op_index, are recording compare operators\n    size_t abort_op_index = 0;\n    bool   record_compare = true;\n\n    // Function object\n    CppAD::ADFun<double> f;\n    // ----------------------------------------------------------\n    // record f\n    adynamic[0] = 1.0;\n    adynamic[1] = 2.0;\n    CppAD::Independent(ax, abort_op_index, record_compare, adynamic);\n    //\n    // create three constant parameters that are only used in a cumulative\n    // summation and will be optimized to just one constant parameter\n    ay[0] = 3.0 - ax[0];\n    ay[0] = ay[0] - 4.0;\n    ay[0] = ay[0] + 5.0;\n    //\n    // create a dependent dynamic parameter that is not used\n    AD<double> adp1 = adynamic[0] + adynamic[1];\n    //\n    // create a dependent dynamic parameter that is used\n    AD<double> adp2 = adynamic[1] - adynamic[0];\n    ay[1] = ax[0] + adp2;\n    //\n    // create f: x -> y and stop tape recording\n    f.Dependent(ax, ay);\n    ok &= f.size_dyn_ind() == num_dyn_ind;\n    ok &= f.size_dyn_par() == num_dyn_ind + 2;\n    // constant parameters: nan, 3.0, 4.0, 5.0\n    ok &= f.size_par()     == num_dyn_ind + 2 + 4;\n    // -------------------------------------------------------------\n    // vectors used for new_dynamic and Forward.\n    CPPAD_TESTVECTOR(double) dynamic(num_dyn_ind), x(nx), y(ny);\n    dynamic[0] = 3.0;\n    dynamic[1] = 4.0;\n    f.new_dynamic(dynamic);\n    x[0] = 5.0;\n    y    = f.Forward(0, x);\n    double check = 3.0 - x[0] - 4.0 + 5.0;\n    ok   &= NearEqual(y[0], check, eps99, eps99);\n    check = x[0] + dynamic[1] - dynamic[0];\n    ok   &= NearEqual(y[1], check, eps99, eps99);\n    // -------------------------------------------------------------\n    // optimize and re-test\n    f.optimize(); // add the zero parameter\n    ok &= f.size_dyn_ind() == num_dyn_ind;\n    ok &= f.size_dyn_par() == num_dyn_ind + 1;\n    // constant parameters: nan, zero, (3.0 - 4.0 + 5.0)\n    ok &= f.size_par()     == num_dyn_ind + 1 + 3;\n    dynamic[0] = 0.3;\n    dynamic[1] = 0.4;\n    f.new_dynamic(dynamic);\n    x[0] = 0.5;\n    y    = f.Forward(0, x);\n    check = 3.0 - x[0] - 4.0 + 5.0;\n    ok   &= NearEqual(y[0], check, eps99, eps99);\n    check = x[0] + dynamic[1] - dynamic[0];\n    ok   &= NearEqual(y[1], check, eps99, eps99);\n    //\n    return ok;\n}\n\n// ----------------------------------------------------------------------------\ntypedef CPPAD_TESTVECTOR( CppAD::AD<double> )  ADvector;\nvoid g_algo(const ADvector& ax, ADvector& ay)\n{   ay[0] = ax[0] * ax[1];\n}\nbool dynamic_atomic(void)\n{   bool ok = true;\n\n    // checkpoint version of g(x) = x[0] * x[1];\n    ADvector ax(2), ay(1);\n    ax[0] = 2.0;\n    ax[1] = 3.0;\n    CppAD::checkpoint<double> atom_g(\"g_algo\", g_algo, ax, ay);\n\n    // record the function f(x) = dynamic[0] * dynamic[1]\n    // using atom_g to compute the product\n    ADvector adynamic(2);\n    adynamic[0] = 1.0;\n    adynamic[1] = 2.0;\n    size_t abort_op_index = 0;\n    bool   record_compare = true;\n    Independent(ax, abort_op_index, record_compare, adynamic);\n    atom_g(adynamic, ay);\n    CppAD::ADFun<double> f(ax, ay);\n\n    // change the dynamic parameter values\n    CPPAD_TESTVECTOR(double) x(2), y(1), dynamic(2);\n    dynamic[0] = 4.0;\n    dynamic[1] = 5.0;\n    f.new_dynamic(dynamic);\n\n    // check zero order forward\n    x[0] = std::numeric_limits<double>::quiet_NaN();\n    x[1] = std::numeric_limits<double>::quiet_NaN();\n    y    = f.Forward(0, x);\n    ok  &= y[0] == dynamic[0] * dynamic[1];\n\n\n    return ok;\n}\n\n// ----------------------------------------------------------------------------\ndouble n_digits(const double& x)\n{   double logx = std::log10(x);\n    double ret  = floor(logx) + 1.0;\n    return ret;\n}\nCPPAD_DISCRETE_FUNCTION(double, n_digits)\n//\nbool dynamic_discrete(void)\n{   bool ok = true;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // record the function f(x) = x[0] * n_digits( dynamic[0] )\n    ADvector ax(1);\n    ax[0] = 2.0;\n    ADvector adynamic(1);\n    adynamic[0] = 3.0;\n    size_t abort_op_index = 0;\n    bool   record_compare = true;\n    Independent(ax, abort_op_index, record_compare, adynamic);\n    ADvector ay(1);\n    ay[0] = ax[0] * n_digits( adynamic[0] );\n    CppAD::ADFun<double> f(ax, ay);\n\n    // change the dynamic parameter value to 14\n    CPPAD_TESTVECTOR(double) x(1), y(1), dynamic(1);\n    dynamic[0] = 14.0;\n    f.new_dynamic(dynamic);\n\n    // check zero order forward\n    x[0] = 3.0;\n    y    = f.Forward(0, x);\n    ok  &= CppAD::NearEqual(y[0], x[0] * 2.0, eps99, eps99);\n\n    return ok;\n}\n// ----------------------------------------------------------------------------\nbool dynamic_optimize(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // independent dynamic parameter vector\n    size_t nd  = 1;\n    CPPAD_TESTVECTOR(AD<double>) adynamic(nd);\n\n    // domain space vector\n    size_t nx = 1;\n    CPPAD_TESTVECTOR(AD<double>) ax(nx);\n    ax[0] = 0.0; // value does not matter for this example;\n\n    // range space vector\n    size_t ny = 2;\n    CPPAD_TESTVECTOR(AD<double>) ay(ny);\n\n    // not using abort_op_index, are recording compare operators\n    size_t abort_op_index = 0;\n    bool   record_compare = true;\n\n    // Function object\n    CppAD::ADFun<double> f;\n    // ----------------------------------------------------------\n    // record f\n    adynamic[0] = 1.0;\n    CppAD::Independent(ax, abort_op_index, record_compare, adynamic);\n    //\n    // Avoid cumulative summations because it adds constant parameters.\n    // Use one constant parameter, namely 3.0.\n    // Create five dynamic parameters where the second, fourth, and fifth,\n    // should be optimized out.\n    //\n    // first extra dynamic parameter (also is in optimized tape)\n    AD<double> first  = 3.0 + adynamic[0];\n    //\n    // second that is the same as first because addition is communative\n    AD<double> second = adynamic[0] + 3.0;\n    //\n    // third extra dynamic parameter (also in optimized tape)\n    AD<double> third  = first * first;\n    //\n    // fourth is same as third and uses second which gets optimized out\n    AD<double> fourth = second * second;\n    //\n    // fifth is not used and so should be optimized out\n    AD<double> fifth  = first / 3.0;\n    //\n    ay[0] = ax[0] + third;\n    ay[1] = ax[0] * fourth;\n    //\n    // create f: x -> y and stop tape recording\n    f.Dependent(ax, ay);\n    ok &= f.size_dyn_ind() == nd;\n    ok &= f.size_dyn_par() == nd + 5;\n    // constant parameters: nan, 3.0\n    ok &= f.size_par()     == nd + 5 + 2;\n    // -------------------------------------------------------------\n    // vectors used for new_dynamic and Forward.\n    CPPAD_TESTVECTOR(double) dynamic(nd), x(nx), y(ny);\n    dynamic[0] = 4.0;\n    f.new_dynamic(dynamic);\n    x[0] = 5.0;\n    y    = f.Forward(0, x);\n    double check = x[0] + (3.0 + dynamic[0] ) * (3.0 + dynamic[0]);\n    ok   &= NearEqual(y[0], check, eps99, eps99);\n    check = x[0] * (3.0 + dynamic[0] ) * (3.0 + dynamic[0]);\n    ok   &= NearEqual(y[1], check, eps99, eps99);\n    // -------------------------------------------------------------\n    // optimize and re-test\n    f.optimize(); // adds the zero parameter\n    ok &= f.size_dyn_ind() == nd;\n    ok &= f.size_dyn_par() == nd + 2;\n    // constant parameters: nan, zero, 3.0\n    ok &= f.size_par()     == nd + 2 + 3;\n    dynamic[0] = 6.0;\n    f.new_dynamic(dynamic);\n    y     = f.Forward(0, x);\n    check = x[0] + (3.0 + dynamic[0]) * (3.0 + dynamic[0]);\n    ok   &= NearEqual(y[0], check, eps99, eps99);\n    check = x[0] * (3.0 + dynamic[0]) * (3.0 + dynamic[0]);\n    ok   &= NearEqual(y[1], check, eps99, eps99);\n    //\n    return ok;\n}\n\n\n} // END_EMPTY_NAMESPACE\n\n// ----------------------------------------------------------------------------\nbool new_dynamic(void)\n{   bool ok = true;\n    ok     &= pull_232();\n    ok     &= vecad();\n    ok     &= operator_with_variable();\n    ok     &= dynamic_operator();\n    ok     &= dynamic_compare();\n    ok     &= optimize_csum();\n    ok     &= dynamic_atomic();\n    ok     &= dynamic_discrete();\n    ok     &= dynamic_optimize();\n    //\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/num_limits.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\nold num_limits.cpp example / test\n$spell\n$$\n\n$section Numeric Limits: Example and Test$$\n$index limits$$\n$index example, limits$$\n$index test, limits$$\n\n$head Assumption$$\nThis code assumes that the decimal point is infront of the mantissa.\nHence dividing the minimum normalized value looses precision,\nwhile multiplying the maximum normalized value results in infinity.\n\n$head Externals$$\nThis example using external routines to get and set values\nso that the compiler does not set the correspdong code and optimize\nit out.\n\nold verbatim%example/num_limits.cpp%0%// BEGIN C++%// END C++%1%$$\n\n$end\n*/\n// BEGIN C++\n// Complex examples should suppress conversion warnings\n# include <cppad/wno_conversion.hpp>\n\n# ifdef _MSC_VER\n// Suppress Microsoft compiler warning about possible loss of precision,\n// in the constructors (when converting to std::complex<float>)\n//    Type one = 1\n//    Type two = 2\n// 1 and 2 are small enough so no loss of precision when converting to float.\n# pragma warning(disable:4244)\n# endif\n\n# include <cppad/cppad.hpp>\n# include <complex>\n# include \"extern_value.hpp\"\n\nnamespace {\n    using CppAD::vector;\n    using CppAD::abs_geq;\n\n    template <class Type>\n    Type add_one(const Type& value)\n    {   return( Type(1) + value ); }\n    // -----------------------------------------------------------------\n    template <class Type>\n    bool check_epsilon(void)\n    {   bool ok    = true;\n        typedef extern_value<Type> value;\n        value eps( CppAD::numeric_limits<Type>::epsilon() );\n        value one( Type(1) );\n        value two( Type(2) );\n        value tmp( Type(0) );\n        //\n        tmp.set( add_one( eps.get() / two.get() ) );\n        ok        &= one.get() == tmp.get();\n        //\n        tmp.set( add_one( eps.get() ) );\n        ok        &= one.get() != tmp.get();\n        return ok;\n    }\n    // -----------------------------------------------------------------\n    template <class Type>\n    bool check_min(void)\n    {   bool ok    = true;\n        typedef extern_value<Type> value;\n        value min( CppAD::numeric_limits<Type>::min() );\n        value eps3( Type(3) * CppAD::numeric_limits<Type>::epsilon() );\n        value one( Type(1) );\n        value hun( Type(100) );\n        value tmp( Type(0) );\n        //\n        tmp.set( min.get() / hun.get() );\n        tmp.set( tmp.get() * hun.get() );\n        ok        &= abs_geq(tmp.get()/min.get() - one.get(), eps3.get());\n        //\n        tmp.set( min.get() * hun.get() );\n        tmp.set( tmp.get() / hun.get() );\n        ok        &= ! abs_geq(tmp.get()/min.get() - one.get(), eps3.get());\n        return ok;\n    }\n\n    // -----------------------------------------------------------------\n    template <class Type>\n    bool check_max(void)\n    {   bool ok    = true;\n        typedef extern_value<Type> value;\n        value max2( CppAD::numeric_limits<Type>::max() / Type(2) );\n        value eps3( Type(3) * CppAD::numeric_limits<Type>::epsilon() );\n        value one( Type(1) );\n        value hun( Type(100) );\n        value tmp( Type(0) );\n\n        // In complex case, this operation can result in (inf, 0)\n        tmp.set( max2.get() * hun.get() );\n\n        // In complex case, this operaiotn can result in (inf,-nan)\n        // (where nan corresponds to inf * 0)\n        tmp.set( tmp.get() / hun.get() );\n\n        if( ! CppAD::isnan( tmp.get() ) ) ok &= abs_geq(\n            tmp.get() / max2.get() - one.get(), eps3.get()\n        );\n        //\n        tmp.set( max2.get() / hun.get() );\n        tmp.set( tmp.get() * hun.get() );\n        ok        &= ! abs_geq(tmp.get() / max2.get() - one.get(), eps3.get() );\n        return ok;\n    }\n    // -----------------------------------------------------------------\n    template <class Type>\n    bool check_quiet_NaN(void)\n    {   bool ok    = true;\n        typedef extern_value<Type> value;\n        value nan( CppAD::numeric_limits<Type>::quiet_NaN() );\n        value same( nan.get() );\n        //\n        ok &= nan.get() != same.get();\n        ok &= ! (nan.get() == same.get() );\n        //\n        return ok;\n    }\n    // -----------------------------------------------------------------\n    template <class Type>\n    bool check_infinity(void)\n    {   bool ok    = true;\n        typedef extern_value<Type> value;\n        value inf( CppAD::numeric_limits<Type>::infinity() );\n        value hun( Type(100) );\n\n        value tmp( Type(0) );\n\n        tmp.set( inf.get() + hun.get() );\n        ok &= inf.get() == tmp.get();\n\n        tmp.set( inf.get() - inf.get() );\n        ok &= CppAD::isnan( tmp.get() );\n        return ok;\n    }\n}\n\nbool num_limits(void)\n{   bool ok = true;\n    using CppAD::AD;\n\n    // -------------------------------------------------------------------\n    // epsilon for Base types defined by CppAD\n    ok &= check_epsilon<float>();\n    ok &= check_epsilon<double>();\n    ok &= check_epsilon< std::complex<float> >();\n    ok &= check_epsilon< std::complex<double> >();\n\n    // epsilon for some AD types.\n    ok &= check_epsilon< AD<float> >();\n    ok &= check_epsilon< AD<double> >();\n    ok &= check_epsilon<  AD<std::complex<float> > >();\n    ok &= check_epsilon<  AD<std::complex<double> > >();\n\n    // -------------------------------------------------------------------\n    // min for Base types defined by CppAD\n    ok &= check_min<float>();\n    ok &= check_min<double>();\n    ok &= check_min< std::complex<float> >();\n    ok &= check_min< std::complex<double> >();\n\n    // min for some AD types.\n    ok &= check_min< AD<float> >();\n    ok &= check_min< AD<double> >();\n    ok &= check_min<  AD<std::complex<float> > >();\n    ok &= check_min<  AD<std::complex<double> > >();\n\n    // -------------------------------------------------------------------\n    // max for Base types defined by CppAD\n    ok &= check_max<float>();\n    ok &= check_max<double>();\n    ok &= check_max< std::complex<float> >();\n    ok &= check_max< std::complex<double> >();\n\n    // max for some AD types.\n    ok &= check_max< AD<float> >();\n    ok &= check_max< AD<double> >();\n    ok &= check_max< AD< std::complex<float> > >();\n    ok &= check_max< AD< std::complex<double> > >();\n    // -------------------------------------------------------------------\n    // quiet_NaN for Base types defined by CppAD\n    ok &= check_quiet_NaN<float>();\n    ok &= check_quiet_NaN<double>();\n    ok &= check_quiet_NaN< std::complex<float> >();\n    ok &= check_quiet_NaN< std::complex<double> >();\n\n    // quiet_NaN for some AD types.\n    ok &= check_quiet_NaN< AD<float> >();\n    ok &= check_quiet_NaN< AD<double> >();\n    ok &= check_quiet_NaN< AD< std::complex<float> > >();\n    ok &= check_quiet_NaN< AD< std::complex<double> > >();\n\n    // -------------------------------------------------------------------\n    // infinity for Base types defined by CppAD\n    ok &= check_infinity<float>();\n    ok &= check_infinity<double>();\n    ok &= check_infinity< std::complex<float> >();\n    ok &= check_infinity< std::complex<double> >();\n\n    // infinity for some AD types.\n    ok &= check_infinity< AD<float> >();\n    ok &= check_infinity< AD<double> >();\n    ok &= check_infinity< AD< std::complex<float> > >();\n    ok &= check_infinity< AD< std::complex<double> > >();\n\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "test_more/general/ode_err_control.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cstddef>                    // for size_t\n# include <cmath>                      // for exp\n# include <cppad/utility/ode_err_control.hpp>  // CppAD::OdeErrControl\n# include <cppad/utility/near_equal.hpp>       // CppAD::NearEqual\n# include <cppad/utility/vector.hpp>           // CppAD::vector\n# include <cppad/utility/runge_45.hpp>         // CppAD::Runge45\n\n/* -------------------------------------------------------------------------\nTest relative error with zero initial conditions.\n(Uses minimum step size to integrate).\n*/\n\nnamespace {\n    // --------------------------------------------------------------\n    class Fun_one {\n    private:\n            size_t n;   // dimension of the state space\n    public:\n        // constructor\n        Fun_one(size_t n_) : n(n_)\n        { }\n\n        // given x(0) = 0\n        // solution is x_i (t) = t^(i+1)\n        void Ode(\n            const double                &t,\n            const CppAD::vector<double> &x,\n            CppAD::vector<double>       &f)\n        {   size_t i;\n            f[0] = 1.;\n            for(i = 1; i < n; i++)\n                f[i] = double(i+1) * x[i-1];\n        }\n    };\n\n    // --------------------------------------------------------------\n    class Method_one {\n    private:\n        Fun_one F;\n    public:\n        // constructor\n        Method_one(size_t n_) : F(n_)\n        { }\n        void step(\n            double ta,\n            double tb,\n            CppAD::vector<double> &xa ,\n            CppAD::vector<double> &xb ,\n            CppAD::vector<double> &eb )\n        {   xb = CppAD::Runge45(F, 1, ta, tb, xa, eb);\n        }\n        size_t order(void)\n        {   return 4; }\n    };\n}\n\nbool OdeErrControl_one(void)\n{   bool   ok = true;     // initial return value\n\n    using CppAD::NearEqual;\n\n    // Runge45 should yield exact results for x_i (t) = t^(i+1), i < 4\n    size_t  n = 6;\n\n    // construct method for n component solution\n    Method_one method(n);\n\n    // inputs to OdeErrControl\n\n    double ti   = 0.;\n    double tf   = .9;\n    double smin = 1e-2;\n    double smax = 1.;\n    double scur = .5;\n    double erel = 1e-7;\n\n    CppAD::vector<double> xi(n);\n    CppAD::vector<double> eabs(n);\n    size_t i;\n    for(i = 0; i < n; i++)\n    {   xi[i]   = 0.;\n        eabs[i] = 0.;\n    }\n\n    // outputs from OdeErrControl\n\n    CppAD::vector<double> ef(n);\n    CppAD::vector<double> xf(n);\n\n    xf = OdeErrControl(method,\n        ti, tf, xi, smin, smax, scur, eabs, erel, ef);\n\n    double check = 1.;\n    for(i = 0; i < n; i++)\n    {   check *= tf;\n        ok &= NearEqual(check, xf[i], erel, 0.);\n    }\n\n    return ok;\n}\n\n/*\nOld example now just a test\nDefine\n$latex X : \\B{R} \\rightarrow \\B{R}^2$$ by\n$latex \\[\n\\begin{array}{rcl}\nX_0 (t) & = &  - \\exp ( - w_0 t )  \\\\\nX_1 (t) & = & \\frac{w_0}{w_1 - w_0} [ \\exp ( - w_0 t ) - \\exp( - w_1 t )]\n\\end{array}\n\\] $$\nIt follows that $latex X_0 (0) = 1$$, $latex X_1 (0) = 0$$ and\n$latex \\[\n\\begin{array}{rcl}\n    X_0^{(1)} (t) & = & - w_0 X_0 (t)  \\\\\n    X_1^{(1)} (t) & = & + w_0 X_0 (t) - w_1 X_1 (t)\n\\end{array}\n\\] $$\n*/\n\nnamespace {\n    // --------------------------------------------------------------\n    class Fun_two {\n    private:\n            CppAD::vector<double> w;\n    public:\n        // constructor\n        Fun_two(const CppAD::vector<double> &w_) : w(w_)\n        { }\n\n        // set f = x'(t)\n        void Ode(\n            const double                &t,\n            const CppAD::vector<double> &x,\n            CppAD::vector<double>       &f)\n        {   f[0] = - w[0] * x[0];\n            f[1] = + w[0] * x[0] - w[1] * x[1];\n        }\n    };\n\n    // --------------------------------------------------------------\n    class Method_two {\n    private:\n        Fun_two F;\n    public:\n        // constructor\n        Method_two(const CppAD::vector<double> &w_) : F(w_)\n        { }\n        void step(\n            double ta,\n            double tb,\n            CppAD::vector<double> &xa ,\n            CppAD::vector<double> &xb ,\n            CppAD::vector<double> &eb )\n        {   xb = CppAD::Runge45(F, 1, ta, tb, xa, eb);\n        }\n        size_t order(void)\n        {   return 4; }\n    };\n}\n\nbool OdeErrControl_two(void)\n{   bool ok = true;     // initial return value\n    using CppAD::NearEqual;\n\n    CppAD::vector<double> w(2);\n    w[0] = 10.;\n    w[1] = 1.;\n    Method_two method(w);\n\n    CppAD::vector<double> xi(2);\n    xi[0] = 1.;\n    xi[1] = 0.;\n\n    CppAD::vector<double> eabs(2);\n    eabs[0] = 1e-4;\n    eabs[1] = 1e-4;\n\n    // inputs\n    double ti   = 0.;\n    double tf   = 1.;\n    double smin = 1e-4;\n    double smax = 1.;\n    double scur = .5;\n    double erel = 0.;\n\n    // outputs\n    CppAD::vector<double> ef(2);\n    CppAD::vector<double> xf(2);\n    CppAD::vector<double> maxabs(2);\n    size_t nstep;\n\n\n    xf = OdeErrControl(method,\n        ti, tf, xi, smin, smax, scur, eabs, erel, ef, maxabs, nstep);\n\n    double x0 = exp(-w[0]*tf);\n    ok &= NearEqual(x0, xf[0], 1e-4, 1e-4);\n    ok &= NearEqual(0., ef[0], 1e-4, 1e-4);\n\n    double x1 = w[0] * (exp(-w[0]*tf) - exp(-w[1]*tf))/(w[1] - w[0]);\n    ok &= NearEqual(x1, xf[1], 1e-4, 1e-4);\n    ok &= NearEqual(0., ef[1], 1e-4, 1e-4);\n\n    return ok;\n}\n/*\nDefine\n$latex X : \\B{R} \\rightarrow \\B{R}^2$$ by\n$latex \\[\n\\begin{array}{rcl}\n    X_0 (0)       & = & 1  \\\\\n    X_1 (0)       & = & 0  \\\\\n    X_0^{(1)} (t) & = & 2 \\alpha t X_0 (t)  \\\\\n    X_1^{(1)} (t) & = &  1 / X_0 (t)\n\\end{array}\n\\] $$\nIt follows that\n$latex \\[\n\\begin{array}{rcl}\nX_0 (t) & = &  \\exp ( \\alpha t^2 )  \\\\\nX_1 (t) & = &  \\int_0^t \\exp( - \\alpha s^2 ) {\\bf d} s \\\\\n& = &\n\\frac{1}{ \\sqrt{\\alpha} \\int_0^{\\sqrt{\\alpha} t} \\exp( - r^2 ) {\\bf d} r\n\\\\\n& = & \\frac{\\sqrt{\\pi}}{ 2 \\sqrt{\\alpha} {\\rm erf} ( \\sqrt{\\alpha} t )\n\\end{array}\n\\] $$\nIf $latex X_0 (t) < 0$$,\nwe return $code nan$$ in order to inform\n$code OdeErrControl$$ that its is taking to large a step.\n\n*/\n\n# include <cppad/utility/rosen_34.hpp>          // CppAD::Rosen34\n# include <cppad/cppad.hpp>\n\nnamespace {\n    // --------------------------------------------------------------\n    class Fun_three {\n    private:\n        const double alpha_;\n        bool was_negative_;\n    public:\n        // constructor\n        Fun_three(double alpha) : alpha_(alpha), was_negative_(false)\n        { }\n\n        // set f = x'(t)\n        void Ode(\n            const double                &t,\n            const CppAD::vector<double> &x,\n            CppAD::vector<double>       &f)\n        {   f[0] = 2. * alpha_ * t * x[0];\n            f[1] = 1. / x[0];\n            // case where ODE does not make sense\n            if( x[0] < 0. || x[1] < 0. )\n            {   was_negative_ = true;\n                f[0] = std::numeric_limits<double>::quiet_NaN();\n            }\n        }\n        // set f_t = df / dt\n        void Ode_ind(\n            const double                &t,\n            const CppAD::vector<double> &x,\n            CppAD::vector<double>       &f_t)\n        {\n            f_t[0] =  2. * alpha_ * x[0];\n            f_t[1] = 0.;\n            if( x[0] < 0. || x[1] < 0. )\n            {   was_negative_ = true;\n                f_t[0] = std::numeric_limits<double>::quiet_NaN();\n            }\n        }\n        // set f_x = df / dx\n        void Ode_dep(\n            const double                &t,\n            const CppAD::vector<double> &x,\n            CppAD::vector<double>       &f_x)\n        {   double x0_sq = x[0] * x[0];\n            f_x[0 * 2 + 0] = 2. * alpha_ * t;   // f0 w.r.t. x0\n            f_x[0 * 2 + 1] = 0.;                // f0 w.r.t. x1\n            f_x[1 * 2 + 0] = -1./x0_sq;         // f1 w.r.t. x0\n            f_x[1 * 2 + 1] = 0.;                // f1 w.r.t. x1\n            if( x[0] < 0. || x[1] < 0. )\n            {   was_negative_ = true;\n                f_x[0] = std::numeric_limits<double>::quiet_NaN();\n            }\n        }\n        bool was_negative(void)\n        {   return was_negative_; }\n\n    };\n\n    // --------------------------------------------------------------\n    class Method_three {\n    public:\n        Fun_three F;\n\n        // constructor\n        Method_three(double alpha) : F(alpha)\n        { }\n        void step(\n            double ta,\n            double tb,\n            CppAD::vector<double> &xa ,\n            CppAD::vector<double> &xb ,\n            CppAD::vector<double> &eb )\n        {   xb = CppAD::Rosen34(F, 1, ta, tb, xa, eb);\n        }\n        size_t order(void)\n        {   return 3; }\n    };\n}\n\nbool OdeErrControl_three(void)\n{   bool ok = true;     // initial return value\n    using CppAD::NearEqual;\n\n    double alpha = 10.;\n    Method_three method(alpha);\n\n    CppAD::vector<double> xi(2);\n    xi[0] = 1.;\n    xi[1] = 0.;\n\n    CppAD::vector<double> eabs(2);\n    eabs[0] = 1e-4;\n    eabs[1] = 1e-4;\n\n    // inputs\n    double ti   = 0.;\n    double tf   = 1.;\n    double smin = 1e-4;\n    double smax = 1.;\n    double scur = 1.;\n    double erel = 0.;\n\n    // outputs\n    CppAD::vector<double> ef(2);\n    CppAD::vector<double> xf(2);\n    CppAD::vector<double> maxabs(2);\n    size_t nstep;\n\n\n    xf = OdeErrControl(method,\n        ti, tf, xi, smin, smax, scur, eabs, erel, ef, maxabs, nstep);\n\n\n    double x0       = exp( alpha * tf * tf );\n    ok &= NearEqual(x0, xf[0], 1e-4, 1e-4);\n    ok &= NearEqual(0., ef[0], 1e-4, 1e-4);\n\n    double root_pi    = sqrt( 4. * atan(1.));\n    double root_alpha = sqrt( alpha );\n    double x1 = CppAD::erf(alpha * tf) * root_pi / (2 * root_alpha);\n    ok &= NearEqual(x1, xf[1], 1e-4, 1e-4);\n    ok &= NearEqual(0., ef[1], 1e-4, 1e-4);\n\n    ok &= method.F.was_negative();\n\n    return ok;\n}\n\nnamespace {\n    // --------------------------------------------------------------\n    class Fun_four {\n    private:\n            size_t n;   // dimension of the state space\n    public:\n        // constructor\n        Fun_four(size_t n_) : n(n_)\n        { }\n\n        // given x(0) = 0\n        // solution is x_i (t) = t^(i+1)\n        void Ode(\n            const double                &t,\n            const CppAD::vector<double> &x,\n            CppAD::vector<double>       &f)\n        {   size_t i;\n            f[0] = std::numeric_limits<double>::quiet_NaN();\n            for(i = 1; i < n; i++)\n                f[i] = double(i+1) * x[i-1];\n        }\n    };\n\n    // --------------------------------------------------------------\n    class Method_four {\n    private:\n        Fun_four F;\n    public:\n        // constructor\n        Method_four(size_t n_) : F(n_)\n        { }\n        void step(\n            double ta,\n            double tb,\n            CppAD::vector<double> &xa ,\n            CppAD::vector<double> &xb ,\n            CppAD::vector<double> &eb )\n        {   xb = CppAD::Runge45(F, 1, ta, tb, xa, eb);\n        }\n        size_t order(void)\n        {   return 4; }\n    };\n}\n\nbool OdeErrControl_four(void)\n{   bool   ok = true;     // initial return value\n\n    // construct method for n component solution\n    size_t  n = 6;\n    Method_four method(n);\n\n    // inputs to OdeErrControl\n\n    // special case where scur is converted to ti - tf\n    // (so it is not equal to smin)\n    double ti   = 0.;\n    double tf   = .9;\n    double smin = .8;\n    double smax = 1.;\n    double scur = smin;\n    double erel = 1e-7;\n\n    CppAD::vector<double> xi(n);\n    CppAD::vector<double> eabs(n);\n    size_t i;\n    for(i = 0; i < n; i++)\n    {   xi[i]   = 0.;\n        eabs[i] = 0.;\n    }\n\n    // outputs from OdeErrControl\n    CppAD::vector<double> ef(n);\n    CppAD::vector<double> xf(n);\n\n    xf = OdeErrControl(method,\n        ti, tf, xi, smin, smax, scur, eabs, erel, ef);\n\n    // check that Fun_four always returning nan results in nan\n    for(i = 0; i < n; i++)\n    {   ok &= CppAD::isnan(xf[i]);\n        ok &= CppAD::isnan(ef[i]);\n    }\n\n    return ok;\n}\n\n// ==========================================================================\nbool ode_err_control(void)\n{   bool ok = true;\n    ok     &= OdeErrControl_one();\n    ok     &= OdeErrControl_two();\n    ok     &= OdeErrControl_three();\n    ok     &= OdeErrControl_four();\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/optimize.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n// 2DO: Test that optimize.hpp use of atomic_base<Base>::rev_sparse_jac works.\n\n# include <limits>\n# include <cppad/cppad.hpp>\n# include <cppad/speed/det_by_minor.hpp>\n\nnamespace {\n    //\n    // use val_optimize and ignore conditional_skip_\n    bool use_val_optimize_;\n    //\n    // include conditional skip optimization\n    bool conditional_skip_;\n    //\n    // optimize_with_options\n    void optimize_with_options(CppAD::ADFun<double>& f)\n    {   if( use_val_optimize_ )\n        {   f.optimize(\"val_graph no_conditional_skip\");\n        }\n        else if( conditional_skip_ )\n            f.optimize();\n        else\n            f.optimize(\"no_conditional_skip\");\n    }\n\n    // accuracy for almost equal checks\n    using CppAD::NearEqual;\n\n    // note this enum type is not part of the API (but its values are)\n    CppAD::atomic_base<double>::option_enum atomic_sparsity_option_;\n\n    // =======================================================================\n    // Test conditional expressions where left and right are dynamic parameters\n    bool cond_exp_ppvv(void)\n    {   bool ok = true;\n        using CppAD::AD;\n\n        // independent variable vector\n        CPPAD_TESTVECTOR(AD<double>) ax(2), ap(2);\n        ap[0]     = 0.;\n        ap[1]     = 1.;\n        ax[0]     = 2.;\n        ax[1]     = 3.;\n        size_t abort_op_index = 0;\n        bool   record_compare = false;\n        CppAD::Independent(ax, abort_op_index, record_compare, ap);\n\n        // dependent variable vector\n        CPPAD_TESTVECTOR(AD<double>) ay(5);\n\n        // CondExp(parameter, variable, variable, variable)\n        ay[0] = CondExpLt(ap[0], ap[1], ax[0], ax[1]);\n        ay[1] = CondExpLt(ap[0], ap[1], ax[0], ax[1]);\n        ay[2] = CondExpEq(ap[0], ap[1], ax[0], ax[1]);\n        ay[3] = CondExpGe(ap[0], ap[1], ax[0], ax[1]);\n        ay[4] = CondExpGt(ap[0], ap[1], ax[0], ax[1]);\n\n        // create f: X -> Y\n        CppAD::ADFun<double> f(ax, ay);\n        optimize_with_options(f);\n\n        // vectors for function values\n        CPPAD_TESTVECTOR(double) x( f.Domain() ), p( f.size_dyn_ind() );\n        CPPAD_TESTVECTOR(double) y( f.Range() );\n\n        // vectors for derivative values\n        CPPAD_TESTVECTOR(double) dx( f.Domain() );\n        CPPAD_TESTVECTOR(double) dy( f.Range() );\n\n        // check original function values\n        // ap[0] < ap[1]\n        ok &= ay[0] == ax[0];\n        ok &= ay[1] == ax[0];\n        ok &= ay[2] == ax[1];\n        ok &= ay[3] == ax[1];\n        ok &= ay[4] == ax[1];\n\n        // function values\n        p[0] = 0.;\n        p[1] = 1.;\n        x[0] = 2.;\n        x[1] = 3.;\n        f.new_dynamic(p);\n        y    = f.Forward(0, x);\n        ok &= ( y[0] == x[0] );\n        ok &= ( y[1] == x[0] );\n        ok &= ( y[2] == x[1] );\n        ok &= ( y[3] == x[1] );\n        ok &= ( y[4] == x[1] );\n\n        // forward mode derivative values\n        dx[0] = 1.;\n        dx[1] = 2.;\n        dy    = f.Forward(1, dx);\n        ok   &= (dy[0] == dx[0] );\n        ok   &= (dy[1] == dx[0] );\n        ok   &= (dy[2] == dx[1] );\n        ok   &= (dy[3] == dx[1] );\n        ok   &= (dy[4] == dx[1] );\n\n        // reverse mode derivative values\n        dy[0] = 1.;\n        dy[1] = 2.;\n        dy[2] = 3.;\n        dy[3] = 4.;\n        dy[4] = 5.;\n        dx    = f.Reverse(1, dy);\n        ok   &= dx[0] == dy[0] + dy[1];\n        ok   &= dx[1] == dy[2] + dy[3] + dy[4];\n\n        // now change the dynamic parameter so the results are reversed\n        p[0] = 1.0;\n        p[1] = 0.0;\n        f.new_dynamic(p);\n\n        // function values\n        y    = f.Forward(0, x);\n        ok &= ( y[0] == x[1] );\n        ok &= ( y[1] == x[1] );\n        ok &= ( y[2] == x[1] );\n        ok &= ( y[3] == x[0] );\n        ok &= ( y[4] == x[0] );\n\n        // forward mode derivative values\n        dx[0] = 1.;\n        dx[1] = 2.;\n        dy    = f.Forward(1, dx);\n        ok   &= (dy[0] == dx[1] );\n        ok   &= (dy[1] == dx[1] );\n        ok   &= (dy[2] == dx[1] );\n        ok   &= (dy[3] == dx[0] );\n        ok   &= (dy[4] == dx[0] );\n\n        // reverse mode derivative values\n        dy[0] = 1.;\n        dy[1] = 2.;\n        dy[2] = 3.;\n        dy[3] = 4.;\n        dy[4] = 5.;\n        dx    = f.Reverse(1, dy);\n        ok   &= dx[0] == dy[3] + dy[4];\n        ok   &= dx[1] == dy[0] + dy[1] + dy[2];\n\n        return ok;\n    }\n    // ====================================================================\n    // test collision_limit\n    bool exceed_collision_limit(void)\n    {   bool ok = true;\n        using CppAD::vector;\n        using CppAD::AD;\n\n        // number of rows in the matrix\n        size_t nr = 5;\n\n        // number of element in the matrix\n        size_t n  = nr * nr;\n\n        // independent variable\n        vector< AD<double> > ax(n);\n        for(size_t j = 0; j < n; ++j)\n            ax[j] = double(j);\n        CppAD::Independent(ax);\n\n        // determinant by minors function\n        CppAD::det_by_minor< AD<double> > adet(nr);\n\n        // dependent variable\n        vector< AD<double> > ay(1);\n        ay[0] = adet(ax);\n\n        // ADFun\n        CppAD::ADFun<double> f(ax, ay);\n\n        // optimize the function\n        std::string options = \"collision_limit=1\";\n        f.optimize(options);\n\n        // check that the limit was exceeded\n        ok &= f.exceed_collision_limit();\n\n        return ok;\n    }\n    // ====================================================================\n    // check no_cumulative_sum_op option\n    bool no_cumulative_sum(void)\n    {   bool ok = true;\n        using CppAD::AD;\n        using CppAD::NearEqual;\n        double eps10 = 10.0 * std::numeric_limits<double>::epsilon();\n\n        // domain space vector\n        size_t n  = 2;\n        CppAD::vector< AD<double> > ax(n);\n        for(size_t j = 0; j < n; j++)\n            ax[j] = double(j + 2);\n\n        size_t n_original = 1 + n;\n        size_t n_optimize = 1 + n;\n\n        // range space vector\n        size_t m = 1;\n        CppAD::vector< AD<double> > ay(m);\n\n        // declare independent variables and start tape recording\n        CppAD::Independent(ax);\n\n        // A cumulative summation and a multiply\n        AD<double> sum = 1.0;\n        for(size_t j = 0; j < n; ++j)\n            sum += ax[j];\n        ay[0]       =  ax[0] * sum;\n        n_original += n + 1;\n        n_optimize += n + 1; // not gathered as a cumulative sum\n\n        // same cumulative summation different multiply\n        // all of the terms in the sum have been calculated before\n        sum = 1.0;\n        for(size_t j = 0; j < n; ++j)\n            sum += ax[j];\n        ay[0]      +=  ax[1] * sum;\n        n_original += n + 2; // n sums, one multiply, and final sum\n        n_optimize += 2;     // one multiply, and final sum\n\n        CppAD::ADFun<double> f;\n        f.Dependent(ax, ay);\n\n        // check number of variables in original function\n        ok &= f.size_var() ==  n_original;\n\n        CppAD::vector<double> x(n), y(m);\n        for(size_t j = 0; j < n; j++)\n            x[j] = double(j + 2);\n\n        y   = f.Forward(0, x);\n        for(size_t i = 0; i < m; i++)\n            ok &= NearEqual(y[i], Value(ay[i]), eps10, eps10);\n\n        if( conditional_skip_ )\n            f.optimize(\"no_cumulative_sum_op\");\n        else\n            f.optimize(\"no_conditional_skip no_cumulative_sum_op\");\n\n        // check number of variables  in optimized version\n        ok &= (f.size_var() == n_optimize );\n\n        y   = f.Forward(0, x);\n        for(size_t i = 0; i < m; i++)\n            ok &= NearEqual(y[i], Value(ay[i]), eps10, eps10);\n\n        return ok;\n    }\n    // ---------------------------------------------------------------------\n    // optimize_csum\n    bool optimize_csum(void)\n    {   bool ok = true;\n        using CppAD::AD;\n        using CppAD::vector;\n\n        size_t n = 4;\n        vector< AD<double> > ax(n), ap(n);\n        for(size_t j = 0; j < n; ++j)\n        {   ax[j] = 0.0;\n            ap[j] = 0.0;\n        }\n        size_t abort_op_index = 0;\n        bool   record_compare = false;\n        Independent(ax, abort_op_index, record_compare, ap);\n        //\n        AD<double> aplus  = ax[0] + ax[1];\n        AD<double> aminus = ax[0] - ax[1];\n        AD<double> asum   = CondExpLe(ax[0], ax[1], aplus, aminus);\n        size_t n2 = n / 2;\n        for(size_t j = 0; j < n2; ++j)\n            asum += ax[j] + ap[j];\n        for(size_t j = n2; j < n; ++j)\n            asum -= ax[j] + ap[j];\n        //\n        vector< AD<double> > ay(1);\n        ay[0] = asum * asum;\n        CppAD::ADFun<double> f(ax, ay);\n        //\n        optimize_with_options(f); // creates a cumulative sum operator\n        optimize_with_options(f); // optimizes such a function\n        //\n        // zero order forward\n        vector<double> x(n), p(n), y(1);\n        double sum = 0.0;\n        for(size_t j = 0; j < n2; ++j)\n        {   x[j]  = double(j + 1);\n            p[j]  = double(j + 1);\n            sum  += x[j] + p[j];\n        }\n        for(size_t j = n2; j < n; ++j)\n        {   x[j]  = double(j + 1);\n            p[j]  = double(j + 1);\n            sum  -= x[j] + p[j];\n        }\n        if( x[0] <= x[1] )\n            sum += x[0] + x[1];\n        else\n            sum += x[0] - x[1];\n        f.new_dynamic(p);\n        y     = f.Forward(0, x);\n        double check = sum * sum;\n        ok &= y[0] == check;\n\n        //\n        vector<double> w(1), dx(n);\n        w[0] = 1.0;\n        dx   = f.Reverse(1, w);\n        //\n        ok &= 1 < n2;\n        if( x[0] <= x[1] )\n        {   ok &= dx[0] == 4.0 * sum;\n            ok &= dx[1] == 4.0 * sum;\n        }\n        else\n        {   ok &= dx[0] == 4.0 * sum;\n            ok &= dx[1] == 0.0;\n        }\n        for(size_t j = 2; j < n2; ++j)\n            ok &= dx[j] == 2.0 * sum;\n        for(size_t j = n2; j < n; ++j)\n            ok &= dx[j] == - 2.0 * sum;\n        //\n        return ok;\n    }\n    // ----------------------------------------------------------------\n    class ode_evaluate_fun {\n    public:\n        // Given that y_i (0) = x_i,\n        // the following y_i (t) satisfy the ODE below:\n        // y_0 (t) = x[0]\n        // y_1 (t) = x[1] + x[0] * t\n        // y_2 (t) = x[2] + x[1] * t + x[0] * t^2/2\n        // y_3 (t) = x[3] + x[2] * t + x[1] * t^2/2 + x[0] * t^3 / 3!\n        // ...\n        void Ode(\n            const CppAD::AD<double>&                      t,\n            const CppAD::vector< CppAD::AD<double> >&     y,\n            CppAD::vector< CppAD::AD<double> >&           f)\n        {   size_t n  = y.size();\n            f[0]      = 0.;\n            for(size_t k = 1; k < n; k++)\n                f[k] = y[k-1];\n        }\n    };\n    bool optimize_ode(void)\n    {   bool ok = true;\n        using CppAD::AD;\n        using CppAD::NearEqual;\n        double eps10 = 10.0 * std::numeric_limits<double>::epsilon();\n        using CppAD::vector;\n\n        // independent variable vector\n        size_t n = 2;\n        vector< AD<double> > ax(n);\n        for(size_t j = 0; j < n; j++)\n            ax[j] = AD<double>(j+1);\n        Independent(ax);\n\n        // function that defines the ode\n        ode_evaluate_fun F;\n\n        // initial and final time\n        AD<double> ati = 0.0;\n        AD<double> atf = 0.5;\n\n        // initial value for y(x, t); i.e. y(x, 0)\n        // (is a reference to x)\n        size_t m = n;\n        vector< AD<double> >  ayi = ax;\n\n        // final value for y(x, t); i.e., y(x, 1)\n        vector< AD<double> >  ayf(m);\n\n        // Use one fourth order Runge-Kutta step to solve ODE\n        size_t M = 1;\n        ayf = CppAD::Runge45(F, M, ati, atf, ayi);\n\n        // function f(x) = y(x, tf)\n        CppAD::ADFun<double> f(ax, ayf);\n\n        // optimize f(x)\n        optimize_with_options(f);\n\n        // compute f'(x)\n        vector<double> x(n), jac(m * n);\n        for(size_t j = 0; j < n; j++)\n            x[j] = double(j+1);\n        jac = f.Jacobian(x);\n\n\n        // check f'(x)\n        double tj = 1.0;\n        for(size_t j = 0; j < n; j++)\n        {   for(size_t i = j; i < m; i++)\n                ok &= CppAD::NearEqual( tj , jac[ i * n * j], eps10, eps10);\n            tj *= Value( atf - ati );\n        }\n        return ok;\n    }\n    // ----------------------------------------------------------------\n    // Test nested conditional expressions.\n    bool nested_cond_exp(void)\n    {   bool ok = true;\n        using CppAD::AD;\n        using CppAD::NearEqual;\n        double eps10 = 10.0 * std::numeric_limits<double>::epsilon();\n        using CppAD::vector;\n\n        // independent variable vector\n        vector< AD<double> > ax(2), ay(1);\n        ax[0] = 1.0;\n        ax[1] = 2.0;\n        Independent(ax);\n\n        // first conditional expression\n        AD<double> ac1 = CondExpLe(ax[0], ax[1], 2.0 * ax[0], 3.0 * ax[1] );\n\n        // second conditional expression\n        AD<double> ac2 = CondExpGe(ax[0], ax[1], 4.0 * ax[0], 5.0 * ax[1] );\n\n        // third conditional expression\n        AD<double> ac3 = CondExpLt(ax[0], ax[1], 6.0 * ac1, 7.0 * ac2 );\n\n        // create function object f : ax -> ay\n        ay[0] = ac3;\n        CppAD::ADFun<double> f(ax, ay);\n\n        // now optimize the operation sequence\n        optimize_with_options(f);\n\n        // now zero order forward\n        vector<double> x(2), y(1);\n        for(size_t i = 0; i < 3; i++)\n        {   x[0] = 1.0 - double(i);\n            x[1] = - x[0];\n            y    = f.Forward(0, x);\n            //\n            // first conditional expression\n            double c1;\n            if( x[0] <= x[1] )\n                c1 = 2.0 * x[0];\n            else\n                c1 = 3.0 * x[1];\n            //\n            // second conditional expression\n            double c2;\n            if( x[0] >= x[1] )\n                c2 = 4.0 * x[0];\n            else\n                c2 = 5.0 * x[1];\n\n            // third conditional expression\n            double c3;\n            if( x[0] < x[1] )\n                c3 = 6.0 * c1;\n            else\n                c3 = 7.0 * c2;\n\n            ok &= NearEqual(y[0], c3, eps10, eps10);\n        }\n        return ok;\n    }\n    // ----------------------------------------------------------------\n    // Test for bug where checkpoint function did not depend on\n    // the operands in the logical comparison because of the CondExp\n    // sparsity pattern.\n    void j_algo(\n        const CppAD::vector< CppAD::AD<double> >& ax ,\n                  CppAD::vector< CppAD::AD<double> >& ay )\n    {   ay[0] = CondExpGt(ax[0], ax[1], ax[2], ax[3]); }\n\n    bool atomic_cond_exp_sparsity(void)\n    {   bool ok = true;\n        using CppAD::AD;\n        using CppAD::NearEqual;\n        double eps10 = 10.0 * std::numeric_limits<double>::epsilon();\n        using CppAD::vector;\n\n        // Create a checkpoint version of the function g\n        vector< AD<double> > au(4), av(1);\n        for(size_t i = 0; i < 4; i++)\n            au[i] = AD<double>(i);\n        CppAD::checkpoint<double> j_check(\"j_check\", j_algo, au, av);\n\n        // independent variable vector\n        vector< AD<double> > ax(2), ay(1);\n        ax[0] = 1.;\n        ax[1] = 1.;\n        Independent(ax);\n\n        // call atomic function that does not get used\n        for(size_t i = 0; i < 4; i++)\n            au[i] = ax[0] + AD<double>(i + 1) * ax[1];\n        j_check(au, ay);\n\n        // create function object f : ax -> ay\n        CppAD::ADFun<double> f(ax, ay);\n\n        // now optimize the operation sequence\n        optimize_with_options(f);\n\n        // check result where true case is used; i.e., au[0] > au[1]\n        vector<double> x(2), y(1);\n        x[0] = 1.;\n        x[1] = -1;\n        y    = f.Forward(0, x);\n        ok &= NearEqual(y[0], x[0] + double(3) * x[1], eps10, eps10);\n\n\n        // check result where false case is used; i.e., au[0] <= au[1]\n        x[0] = 1.;\n        x[1] = 1;\n        y    = f.Forward(0, x);\n        ok &= NearEqual(y[0], x[0] + double(4) * x[1], eps10, eps10);\n\n        return ok;\n    }\n    // -------------------------------------------------------------------\n    // Test conditional optimizing out call to an atomic function call\n    void k_algo(\n        const CppAD::vector< CppAD::AD<double> >& x ,\n                  CppAD::vector< CppAD::AD<double> >& y )\n    {   y[0] = x[0] + x[1]; }\n\n    void h_algo(\n        const CppAD::vector< CppAD::AD<double> >& x ,\n                  CppAD::vector< CppAD::AD<double> >& y )\n    {   y[0] = x[0] - x[1]; }\n\n    bool atomic_cond_exp(void)\n    {   bool ok = true;\n        typedef CppAD::vector< CppAD::AD<double> > ADVector;\n        using CppAD::NearEqual;\n        double eps10 = 10.0 * std::numeric_limits<double>::epsilon();\n\n        // Create a checkpoint version of the function g\n        ADVector ax(2), ag(1), ah(1), ay(1);\n        ax[0] = 0.;\n        ax[1] = 1.;\n        CppAD::checkpoint<double> k_check(\"k_check\", k_algo, ax, ag);\n        CppAD::checkpoint<double> h_check(\"h_check\", h_algo, ax, ah);\n\n        // independent variable vector\n        Independent(ax);\n\n        // atomic function calls that get conditionally used\n        k_check(ax, ag);\n        h_check(ax, ah);\n\n        // conditional expression\n        ay[0] = CondExpLt(ax[0], ax[1], ag[0], ah[0]);\n\n        // create function object f : ax -> ay\n        CppAD::ADFun<double> f;\n        f.Dependent(ax, ay);\n\n        // use zero order to evaluate when condition is true\n        CppAD::vector<double>  x(2), dx(2);\n        CppAD::vector<double>  y(1), dy(1), w(1);\n        x[0] = 3.;\n        x[1] = 4.;\n        y    = f.Forward(0, x);\n        ok &= NearEqual(y[0], x[0] + x[1], eps10, eps10);\n\n        // before optimize\n        k_check.option( atomic_sparsity_option_ );\n        h_check.option( atomic_sparsity_option_ );\n        ok  &= f.number_skip() == 0;\n\n        // now optimize the operation sequence\n        optimize_with_options(f);\n\n        // optimized zero order forward when condition is false\n        x[0] = 4.;\n        x[1] = 3.;\n        y    = f.Forward(0, x);\n        ok &= NearEqual(y[0], x[0] - x[1], eps10, eps10);\n\n        // after optimize can skip either call to g or call to h\n        ok  &= f.number_skip() == 1;\n\n        // optimized first order forward\n        dx[0] = 2.;\n        dx[1] = 1.;\n        dy    = f.Forward(1, dx);\n        ok &= NearEqual(dy[0], dx[0] - dx[1], eps10, eps10);\n\n        // optimized first order reverse\n        w[0]  = 1.;\n        dx    = f.Reverse(1, w);\n        ok &= NearEqual(dx[0], 1., eps10, eps10);\n        ok &= NearEqual(dx[1], -1., eps10, eps10);\n\n        return ok;\n    }\n    // -------------------------------------------------------------------\n    // Test of optimizing out arguments to an atomic function\n    void g_algo(\n        const CppAD::vector< CppAD::AD<double> >& ax ,\n                  CppAD::vector< CppAD::AD<double> >& ay )\n    {   ay = ax; }\n\n    bool atomic_no_used(void)\n    {   bool ok = true;\n        using CppAD::AD;\n        using CppAD::NearEqual;\n        double eps10 = 10.0 * std::numeric_limits<double>::epsilon();\n        using CppAD::vector;\n\n        // Create a checkpoint version of the function g\n        vector< AD<double> > ax(2), ay(2), az(1);\n        ax[0] = 0.;\n        ax[1] = 1.;\n        CppAD::checkpoint<double> g_check(\"g_check\", g_algo, ax, ay);\n\n        // independent variable vector\n        Independent(ax);\n\n        // call atomic function that does not get used\n        g_check(ax, ay);\n\n        // conditional expression\n        az[0] = CondExpLt(ax[0], ax[1], ax[0] + ax[1], ax[0] - ax[1]);\n\n        // create function object f : ax -> az\n        CppAD::ADFun<double> f(ax, az);\n\n        // number of variables before optimization\n        // (include ay[0] and ay[1])\n        size_t n_before = f.size_var();\n\n        // now optimize the operation sequence\n        g_check.option( atomic_sparsity_option_ );\n        optimize_with_options(f);\n\n        // number of variables after optimization\n        // (does not include ay[0] and ay[1])\n        size_t n_after = f.size_var();\n        ok            &= n_after + 2 == n_before;\n\n        // check optimization works ok\n        vector<double> x(2), z(1);\n        x[0] = 4.;\n        x[1] = 3.;\n        z    = f.Forward(0, x);\n        ok &= NearEqual(z[0], x[0] - x[1], eps10, eps10);\n\n        return ok;\n    }\n    bool atomic_arguments(void)\n    {   bool ok = true;\n        using CppAD::AD;\n        using CppAD::NearEqual;\n        double eps10 = 10.0 * std::numeric_limits<double>::epsilon();\n        using CppAD::vector;\n        vector< AD<double> > au(2), aw(2), ax(2), ay(1);\n\n        // create atomic function corresponding to g_algo\n        au[0] = 1.0;\n        au[1] = 2.0;\n        CppAD::checkpoint<double> g_check(\"g_algo\", g_algo, au, ax);\n\n        // start recording a new function\n        CppAD::Independent(ax);\n\n        // now use g_check during the recording\n        au[0] = ax[0] + ax[1]; // this argument requires a new variable\n        au[1] = ax[0] - ax[1]; // this argument also requires a new variable\n        g_check(au, aw);\n\n        // now create f(x) = x_0 + x_1\n        ay[0] = aw[0];\n        CppAD::ADFun<double> f(ax, ay);\n\n        // number of variables before optimization\n        size_t n_before = f.size_var();\n        // ax[0], ax[1], ax[0] + ax[1]. ax[0] - ax[1], g[0], g[1]\n        // and phantom variable at index 0\n        ok &= n_before == 7;\n\n        // now optimize f so that the calculation of au[1] is removed\n        g_check.option( atomic_sparsity_option_ );\n        optimize_with_options(f);\n\n        // number of variables after optimization\n        size_t n_after = f.size_var();\n        // ax[0], ax[1], ax[0] + ax[1]. g[0]\n        // and phantom variable at index 0\n        ok &= n_after == 5;\n\n        // now compute and check a forward mode calculation\n        vector<double> x(2), y(1);\n        x[0] = 5.0;\n        x[1] = 6.0;\n        y    = f.Forward(0, x);\n        ok &= NearEqual(y[0], x[0] + x[1], eps10, eps10);\n\n        return ok;\n    }\n\n    // -------------------------------------------------------------------\n    // Test the reverse dependency analysis optimization\n    template <class Vector>\n    void depend_fun\n    (const Vector& x, Vector& y, size_t& original, size_t& opt)\n    {   typedef typename Vector::value_type Scalar;\n        Scalar not_used;\n        Scalar one(1), two(2), three(3);\n\n        // independent variable and phantom at beginning\n        original = 1 + x.size();\n        opt      = 1 + x.size();\n\n        // unary operator where operand is arg[0]\n        // (note that sin corresponds to two tape variables)\n        not_used = fabs(x[0]);\n        y[0]     = sin(x[0]);\n        original += 3;\n        opt      += 2;\n\n        // binary operator where left operand is a variable\n        // and right operand is a parameter\n        not_used = not_used + 2.;\n        y[1]     = x[1] * 3.;\n        original += 2;\n        opt      += 1;\n\n        // binary operator where left operand is a parameter\n        // and right operation is a variable\n        not_used = 2. - not_used;\n        y[2]     = 3. / x[2];\n        original += 2;\n        opt      += 1;\n\n        // binary operator where both operands are variables\n        not_used  = x[3] - not_used;\n        y[3]      = x[3] / x[2];\n        original += 2;\n        opt      += 1;\n\n        // conditional expression that will be optimized out\n        not_used = CppAD::CondExpLt(x[0], x[1], x[2], x[3]) + not_used;\n        y[4]     = CppAD::CondExpLt(x[4], one, two, three);\n        original += 3;\n        opt      += 1;\n\n        // y[5] does not depend on the value of not_used.\n        // Make sure a parameter, corresponding to a dependent variable,\n        // is not optimized out of the operation sequence.\n        y[5]      = 0.0 * not_used;\n        original += 1;\n        opt      += 1;\n\n        // We do not use the argument x[5], to\n        // make sure it is not optimized out.\n\n        return;\n    }\n\n    bool depend_one(void)\n    {   // Test all except for VecAD operations\n        bool ok = true;\n        using CppAD::AD;\n        using CppAD::NearEqual;\n        double eps10 = 10.0 * std::numeric_limits<double>::epsilon();\n        size_t original;\n        size_t opt;\n        size_t i, j;\n\n        // domain space vector\n        size_t n  = 6;\n        CppAD::vector< AD<double> > X(n);\n        for(j = 0; j < n; j++)\n            X[j] = 1. / double(j + 1);\n\n        // declare independent variables and start tape recording\n        CppAD::Independent(X);\n\n        // range space vector\n        size_t m = n;\n        CppAD::vector< AD<double> > Y(m);\n        depend_fun(X, Y, original, opt);\n\n        // create f: X -> Y and stop tape recording\n        CppAD::ADFun<double> F;\n        F.Dependent(X, Y);\n\n        CppAD::vector<double> x(n), y(m), check(m);\n        for(j = 0; j < n; j++)\n            x[j] = Value(X[j]);\n        y = F.Forward(0, x);\n        depend_fun(x, check, original, opt);\n        for(i = 0; i < m; i++)\n            ok &= NearEqual(y[i], check[i], eps10, eps10);\n\n        // Check size before optimization\n        ok &= F.size_var() == original;\n\n        // Optimize the operation sequence\n        optimize_with_options(F);\n\n        // Check size after optimization\n        ok &= F.size_var() == opt;\n\n        // check result now\n        // (should have already been checked if NDEBUG not defined)\n        y = F.Forward(0, x);\n        for(i = 0; i < m; i++)\n            ok &= NearEqual(y[i], check[i], eps10, eps10);\n\n        return ok;\n    }\n\n    bool depend_two(void)\n    {   // Test VecAD operations\n        bool ok = true;\n        using CppAD::AD;\n        using CppAD::NearEqual;\n        double eps10 = 10.0 * std::numeric_limits<double>::epsilon();\n        size_t i, j;\n\n        // domain space vector\n        size_t n  = 2;\n        CppAD::vector< AD<double> > X(n);\n        for(j = 0; j < n; j++)\n            X[j] = double(j);\n\n        // range space vector\n        size_t m = 3;\n        CppAD::vector< AD<double> > Y(m);\n\n        CppAD::VecAD<double> U(m);\n        CppAD::VecAD<double> V(n);\n        for(i = 0; i < m; i++)\n            U[i] = 0;\n        for(j = 0; j < n; j++)\n            V[j] = 0;\n\n        // declare independent variables and start tape recording\n        CppAD::Independent(X);\n\n        // first vecad vector that is a variable\n        U[ X[0] ] = X[1];\n\n        // second vecad vector that is a variable\n        V[ X[0] ] = X[1];\n\n        // Make dependency for vecad vectors different that for\n        // variables because original code used wrong dependency info.\n        // Y does not depend on the first variable in the tape; i.e.\n        // the one corresponding to the BeginOp. So make it depend\n        // on the first vecad vector in the tape.\n        for(i = 0; i < m; i++)\n        {   AD<double> I(i);\n            Y[i] = U[I];\n        }\n\n        // create f: X -> Y and stop tape recording\n        // Y[ X[0] ] = X[1] and other components of Y are zero.\n        CppAD::ADFun<double> F;\n        F.Dependent(X, Y);\n\n        // Check number of VecAD vectors plus number of VecAD elements\n        ok &= (F.size_VecAD() == 2 + n + m);\n\n        CppAD::vector<double> x(n), y(m);\n        for(j = 0; j < n; j++)\n            x[j] = double(j);\n\n        y = F.Forward(0, x);\n        for(i = 0; i < m; i++)\n        {   if( i != static_cast<size_t>(x[0]) )\n                ok &= NearEqual(y[i], 0., eps10, eps10);\n            else\n                ok &= NearEqual(y[i], x[1], eps10, eps10);\n        }\n\n        if( conditional_skip_ )\n            F.optimize();\n        else\n            F.optimize(\"no_conditional_skip\");\n\n        // Check number of VecAD vectors plus number of VecAD elements\n        ok &= (F.size_VecAD() == 1 + m);\n        y = F.Forward(0, x);\n        for(i = 0; i < m; i++)\n        {   if( i != static_cast<size_t>(x[0]) )\n                ok &= NearEqual(y[i], 0., eps10, eps10);\n            else\n                ok &= NearEqual(y[i], x[1], eps10, eps10);\n        }\n\n        return ok;\n    }\n    bool depend_three(void)\n    {   // Power function is a special case for optimize\n        bool ok = true;\n        using CppAD::AD;\n        using CppAD::NearEqual;\n        double eps10 = 10.0 * std::numeric_limits<double>::epsilon();\n        using CppAD::vector;\n\n        size_t n = 3;\n        size_t j;\n\n        vector< AD<double> >    X(n), Y(n);\n        vector<double>          x(n), y(n);\n\n        for(j = 0; j < n; j++)\n            X[j] = x[j] = double(j+2);\n\n        CppAD::Independent(X);\n\n        Y[0] = pow(X[0], 2.0);\n        Y[1] = pow(2.0, X[1]);\n        Y[2] = pow(X[0], X[1]);\n\n        CppAD::ADFun<double> F(X, Y);\n        optimize_with_options(F);\n        y = F.Forward(0, x);\n\n        // Use identically equal because the result of the operations\n        // have been stored as double and guard bits have been dropped.\n        // (This may not be true for some compiler in the future).\n        for(j = 0; j < n; j++)\n            ok &= NearEqual(y[j], Value(Y[j]), eps10, eps10);\n\n        // check reverse mode derivative\n        vector<double>   w(n), dw(n);\n        w[0] = 0.;\n        w[1] = 0.;\n        w[2] = 1.;\n        dw = F.Reverse(1, w);\n\n        double check = x[1] * pow( x[0], x[1] - 1. );\n        ok &= NearEqual( dw[0], check, eps10, eps10 );\n\n        check = log( x[0] ) * pow( x[0], x[1] );\n        ok &= NearEqual( dw[1], check, eps10, eps10 );\n\n        check = 0.;\n        ok &= NearEqual( dw[2], check, eps10, eps10 );\n\n        return ok;\n    }\n    bool depend_four(void)\n    {   // erf function is a special case for optimize\n        bool ok = true;\n        using CppAD::AD;\n        using CppAD::NearEqual;\n        double eps10 = 10.0 * std::numeric_limits<double>::epsilon();\n        using CppAD::vector;\n\n        size_t n = 1;\n        size_t m = 2;\n        vector< AD<double> > X(n), Y(m);\n        vector<double>       x(n);\n        X[0] = x[0] = double(0.5);\n\n        CppAD::Independent(X);\n\n        Y[0] = erf(X[0])  + erf(X[0]);\n        Y[1] = erfc(X[0]) + erfc(X[0]);\n\n        CppAD::ADFun<double> F(X, Y);\n\n        vector<double> y_original     = F.Forward(0, x);\n        size_t         size_original  = F.size_var();\n        optimize_with_options(F);\n        //\n        // each erf (erfc) has 5 result values:\n        //  x*x, -x*x, exp(-x*x), exp(-x*x)*2/sqrt(pi), erf(x)\n        ok &= F.size_var() + 10 == size_original;\n        //\n        vector<double> y = F.Forward(0, x);\n        ok &=  NearEqual(y[0], y_original[0], eps10, eps10);\n        ok &=  NearEqual(y[1], y_original[1], eps10, eps10);\n        return ok;\n    }\n    // ===================================================================\n    // Test duplicate operation analysis\n\n    template <class Vector>\n    void duplicate_fun\n    (const Vector& x, Vector& y, size_t& original, size_t& opt)\n    {   typedef typename Vector::value_type Scalar;\n        original = 0;\n        opt      = 0;\n\n        // unary operator where operand is arg[0] and one result\n        Scalar a1 = CppAD::exp(x[0]);\n        original += 1;\n        opt      += 1;\n\n        // unary operator where operand is arg[0] and two results\n        Scalar b1 = CppAD::sin(x[1]);\n        original += 2;\n        opt      += 2;\n\n        // non-commutative binary operator where left is a variable\n        // and right is a parameter\n        Scalar c1 = x[2] - 3.;\n        original += 1;\n        opt      += 1;\n\n        // non-commutative binary operator where left is a parameter\n        // and right is a variable\n        Scalar d1 = 3. / x[3];\n        original += 1;\n        opt      += 1;\n\n        // non-commutative binary operator where left is a variable\n        // and right is a variable\n        Scalar e1 = pow(x[3], x[4]);\n        original += 3;\n        opt      += 3;\n\n        // commutative binary operator where  left is a variable\n        // and right is a parameter\n        Scalar f1 = x[5] * 5.;\n        original += 1;\n        opt      += 1;\n\n        // commutative binary operator where  left is a variable\n        // and right is a variable\n        Scalar g1 = x[5] + x[6];\n        original += 1;\n        opt      += 1;\n\n        // duplicate variables\n        Scalar a2 = CppAD::exp(x[0]);\n        Scalar b2 = CppAD::sin(x[1]);  // counts for 2 variables\n        Scalar c2 = x[2] - 3.;\n        Scalar d2 = 3. / x[3];\n        Scalar e2 = pow(x[3], x[4]);   // counts for 3 variables\n        Scalar f2 = 5. * x[5];\n        Scalar g2 = x[6] + x[5];\n        original += 10;\n\n        // result vector\n        y[0] = a1 * a2;\n        y[1] = b1 * b2;\n        y[2] = c1 * c2;\n        y[3] = d1 * d2;\n        y[4] = e1 * e2;\n        y[5] = f1 * f2;\n        y[6] = g1 * g2;\n        original += 7;\n        opt      += 7;\n\n        return;\n    }\n    bool duplicate_one(void)\n    {\n        bool ok = true;\n        using CppAD::AD;\n        using CppAD::NearEqual;\n        double eps10 = 10.0 * std::numeric_limits<double>::epsilon();\n        size_t original;\n        size_t opt;\n        size_t i, j;\n\n        // domain space vector\n        size_t n  = 7;\n        CppAD::vector< AD<double> > X(n);\n        for(j = 0; j < n; j++)\n            X[j] = 1. / double(j + 1);\n\n        // declare independent variables and start tape recording\n        CppAD::Independent(X);\n\n        // range space vector\n        size_t m = n;\n        CppAD::vector< AD<double> > Y(m);\n        duplicate_fun(X, Y, original, opt);\n\n        // create f: X -> Y and stop tape recording\n        CppAD::ADFun<double> F;\n        F.Dependent(X, Y);\n\n        CppAD::vector<double> x(n), y(m), check(m);\n        for(j = 0; j < n; j++)\n            x[j] = Value(X[j]);\n        y = F.Forward(0, x);\n        duplicate_fun(x, check, original, opt);\n        for(i = 0; i < m; i++)\n            ok &= NearEqual(y[i], check[i], eps10, eps10);\n\n        // Check size before optimization\n        ok &= F.size_var() == (n + 1 + original);\n\n        // Optimize the operation sequence\n        optimize_with_options(F);\n\n        // Check size after optimization\n        ok &= F.size_var() == (n + 1 + opt);\n\n        // check result now\n        // (should have already been checked if NDEBUG not defined)\n        y = F.Forward(0, x);\n        for(i = 0; i < m; i++)\n            ok &= NearEqual(y[i], check[i], eps10, eps10);\n\n        return ok;\n    }\n    // -------------------------------------------------------------------\n    bool duplicate_two(void)\n    {   // test that duplicate expression removal is relative to\n        // new and not just old argument indices.\n        bool ok = true;\n        using CppAD::AD;\n        using CppAD::NearEqual;\n        double eps10 = 10.0 * std::numeric_limits<double>::epsilon();\n        size_t i, j;\n\n        // domain space vector\n        size_t n  = 1;\n        CppAD::vector< AD<double> > X(n);\n        for(j = 0; j < n; j++)\n            X[j] = double(j + 2);\n\n        // range space vector\n        size_t m = 1;\n        CppAD::vector< AD<double> > Y(m);\n\n        // declare independent variables and start tape recording\n        CppAD::Independent(X);\n\n        // create a new variable\n        AD<double> A1 = X[0] - 2.;\n\n        // create a duplicate variable\n        AD<double> A2 = X[0] - 2.;\n\n        // create a new variable using first version of duplicate\n        AD<double> B1 = A1 / 2.;\n\n        // create a duplicate that can only be detected using new\n        // argument indices\n        AD<double> B2 = A2 / 2.;\n\n        // Make a new variable for result\n        // and make it depend on all the variables\n        Y[0] = B1 + B2;\n\n        // create f: X -> Y and stop tape recording\n        CppAD::ADFun<double> F;\n        F.Dependent(X, Y);\n\n        // check number of variables in original function\n        ok &= (F.size_var() ==  1 + n + m + 4 );\n\n        CppAD::vector<double> x(n), y(m);\n        for(j = 0; j < n; j++)\n            x[j] = double(j + 2);\n\n        y   = F.Forward(0, x);\n        for(i = 0; i < m; i++)\n            ok &= NearEqual(y[i], Value(Y[i]), eps10, eps10);\n\n        // optimize\n        optimize_with_options(F);\n\n        // check number of variables  in optimized version\n        ok &= (F.size_var() == 1 + n + m + 2 );\n\n        y   = F.Forward(0, x);\n        for(i = 0; i < m; i++)\n            ok &= NearEqual(y[i], Value(Y[i]), eps10, eps10);\n\n        return ok;\n    }\n    // -------------------------------------------------------------------\n    bool duplicate_three(void)\n    {   // test that duplicate expression removal is relative to\n        // new and not just old argument indices (commutative case).\n        bool ok = true;\n        using CppAD::AD;\n        using CppAD::NearEqual;\n        double eps10 = 10.0 * std::numeric_limits<double>::epsilon();\n        size_t i, j;\n\n        // domain space vector\n        size_t n  = 1;\n        CppAD::vector< AD<double> > X(n);\n        for(j = 0; j < n; j++)\n            X[j] = double(j + 2);\n\n        // range space vector\n        size_t m = 1;\n        CppAD::vector< AD<double> > Y(m);\n\n        // declare independent variables and start tape recording\n        CppAD::Independent(X);\n\n        // create a new variable\n        AD<double> A1 = X[0] + 2.;\n\n        // create a duplicate variable\n        AD<double> A2 = 2. + X[0];\n\n        // create a new variable using first version of duplicate\n        AD<double> B1 = A1 * 2.;\n\n        // create a duplicate that can only be detected using new\n        // argument indices\n        AD<double> B2 = 2. * A2;\n\n        // Make a new variable for result\n        // and make it depend on all the variables\n        Y[0] = B1 + B2;\n\n        // create f: X -> Y and stop tape recording\n        CppAD::ADFun<double> F;\n        F.Dependent(X, Y);\n\n        // check number of variables in original function\n        ok &= (F.size_var() ==  1 + n + m + 4 );\n\n        CppAD::vector<double> x(n), y(m);\n        for(j = 0; j < n; j++)\n            x[j] = double(j + 2);\n\n        y   = F.Forward(0, x);\n        for(i = 0; i < m; i++)\n            ok &= NearEqual(y[i], Value(Y[i]), eps10, eps10);\n\n        // optimize\n        optimize_with_options(F);\n\n        // check number of variables  in optimized version\n        ok &= (F.size_var() == 1 + n + m + 2 );\n\n        y   = F.Forward(0, x);\n        for(i = 0; i < m; i++)\n            ok &= NearEqual(y[i], Value(Y[i]), eps10, eps10);\n\n        return ok;\n    }\n    // -------------------------------------------------------------------\n    bool duplicate_four(void)\n    {   // Check that unary expression matching not only checks hash code,\n        // and operator, but also operand (old bug that has been fixed).\n        bool ok = true;\n        using CppAD::AD;\n        using CppAD::NearEqual;\n        double eps10 = 10.0 * std::numeric_limits<double>::epsilon();\n        size_t j;\n\n        // domain space vector\n        size_t n  = 1;\n        CppAD::vector< AD<double> > X(n);\n        X[0] = 1.;\n\n        // range space vector\n        size_t m = 1;\n        CppAD::vector< AD<double> > Y(m);\n\n        // declare independent variables and start tape recording\n        CppAD::Independent(X);\n\n        // check a huge number of same operation with different operands\n        size_t n_operations = std::min(\n            size_t(CPPAD_HASH_TABLE_SIZE) + 5,\n            size_t(std::numeric_limits<CPPAD_TAPE_ADDR_TYPE>::max()) - 5\n        );\n        Y[0] = X[0];\n        for(j = 0; j < n_operations; j++)\n            Y[0] = fabs(Y[0]);\n\n        // create f: X -> Y and stop tape recording\n        CppAD::ADFun<double> F;\n        F.Dependent(X, Y);\n\n        // check number of variables in original function\n        ok &= (F.size_var() ==  1 + n + n_operations );\n\n        CppAD::vector<double> x(n), y(m);\n        x[0] = 1.;\n\n        y   = F.Forward(0, x);\n        ok &= NearEqual(y[0], Value(Y[0]), eps10, eps10);\n\n        // optimize\n        optimize_with_options(F);\n\n        // check same number of variables in optimized version\n        ok &= (F.size_var() == 1 + n + n_operations );\n\n        y   = F.Forward(0, x);\n        ok &= NearEqual(y[0], Value(Y[0]), eps10, eps10);\n\n        return ok;\n    }\n    // ====================================================================\n    bool cumulative_sum(void)\n    {   // test conversion of a sequence of additions and subtraction\n        // to a cumulative summation sequence.\n        bool ok = true;\n        using CppAD::AD;\n        using CppAD::NearEqual;\n        double eps10 = 10.0 * std::numeric_limits<double>::epsilon();\n        size_t i, j;\n\n        // domain space vector\n        size_t n  = 7;\n        CppAD::vector< AD<double> > X(n);\n        for(j = 0; j < n; j++)\n            X[j] = double(j + 2);\n\n        size_t n_original = 1 + n;\n        size_t n_optimize = 1 + n;\n\n        // range space vector\n        size_t m = 2;\n        CppAD::vector< AD<double> > Y(m);\n\n        // declare independent variables and start tape recording\n        CppAD::Independent(X);\n\n        // Operations inside of optimize_cadd\n        Y[0] = 5. + (X[0] + X[1]) + (X[1] - X[2]) // Addvv, Subvv\n                 + (X[2] - 1.) + (2. - X[3])   // Subvp, Subpv\n                 + (X[4] + 3.) + (4. + X[5]);  // Addpv, Addpv (no Addvp)\n        n_original += 12;\n        n_optimize += 1;\n\n\n        // Operations inside of optimize_csub\n        Y[1] = 5. - (X[1] + X[2]) - (X[2] - X[3]) // Addvv, Subvv\n                 - (X[3] - 1.) - (2. - X[4])   // Subvp, Subpv\n                 - (X[5] + 3.) - (4. + X[6]);  // Addpv, Addpv (no Addvp)\n        n_original += 12;\n        n_optimize += 1;\n\n        CppAD::ADFun<double> F;\n        F.Dependent(X, Y);\n\n        // check number of variables in original function\n        ok &= (F.size_var() ==  n_original );\n\n        CppAD::vector<double> x(n), y(m);\n        for(j = 0; j < n; j++)\n            x[j] = double(j + 2);\n\n        y   = F.Forward(0, x);\n        for(i = 0; i < m; i++)\n            ok &= NearEqual(y[i], Value(Y[i]), eps10, eps10);\n\n        // optimize\n        optimize_with_options(F);\n\n        // check number of variables  in optimized version\n        ok &= (F.size_var() == n_optimize );\n\n        y   = F.Forward(0, x);\n        for(i = 0; i < m; i++)\n            ok &= NearEqual(y[i], Value(Y[i]), eps10, eps10);\n\n        return ok;\n    }\n    // -------------------------------------------------------------------\n    bool forward_csum(void)\n    {   bool ok = true;\n\n        using namespace CppAD;\n        using CppAD::NearEqual;\n        double eps10 = 10.0 * std::numeric_limits<double>::epsilon();\n\n        // independent variable vector\n        CppAD::vector< AD<double> > X(2);\n        X[0] = 0.;\n        X[1] = 1.;\n        Independent(X);\n\n        // compute sum of elements in X\n        CppAD::vector< AD<double> > Y(1);\n        Y[0] = X[0] + X[0] + X[1];\n\n        // create function object F : X -> Y\n        ADFun<double> F(X, Y);\n\n        // optimize\n        optimize_with_options(F);\n\n        // use zero order to evaluate F[ (3, 4) ]\n        CppAD::vector<double>  x0( F.Domain() );\n        CppAD::vector<double>  y0( F.Range() );\n        x0[0]    = 3.;\n        x0[1]    = 4.;\n        y0       = F.Forward(0, x0);\n        ok      &= NearEqual(y0[0] , x0[0]+x0[0]+x0[1], eps10, eps10);\n\n        // evaluate derivative of F in X[0] direction\n        CppAD::vector<double> x1( F.Domain() );\n        CppAD::vector<double> y1( F.Range() );\n        x1[0]    = 1.;\n        x1[1]    = 0.;\n        y1       = F.Forward(1, x1);\n        ok      &= NearEqual(y1[0] , x1[0]+x1[0]+x1[1], eps10, eps10);\n\n        // evaluate second derivative of F in X[0] direction\n        CppAD::vector<double> x2( F.Domain() );\n        CppAD::vector<double> y2( F.Range() );\n        x2[0]       = 0.;\n        x2[1]       = 0.;\n        y2          = F.Forward(2, x2);\n        double F_00 = 2. * y2[0];\n        ok         &= NearEqual(F_00, 0., eps10, eps10);\n\n        return ok;\n    }\n    // -------------------------------------------------------------------\n    bool reverse_csum(void)\n    {   bool ok = true;\n\n        using namespace CppAD;\n        using CppAD::NearEqual;\n        double eps10 = 10.0 * std::numeric_limits<double>::epsilon();\n\n        // independent variable vector\n        CppAD::vector< AD<double> > X(2);\n        X[0] = 0.;\n        X[1] = 1.;\n        Independent(X);\n\n        // compute sum of elements in X\n        CppAD::vector< AD<double> > Y(1);\n        Y[0] = X[0] - (X[0] - X[1]);\n\n        // create function object F : X -> Y\n        ADFun<double> F(X, Y);\n\n        // optimize\n        optimize_with_options(F);\n\n        // use zero order to evaluate F[ (3, 4) ]\n        CppAD::vector<double>  x0( F.Domain() );\n        CppAD::vector<double>  y0( F.Range() );\n        x0[0]    = 3.;\n        x0[1]    = 4.;\n        y0       = F.Forward(0, x0);\n        ok      &= NearEqual(y0[0] , x0[0]-x0[0]+x0[1], eps10, eps10);\n\n        // evaluate derivative of F\n        CppAD::vector<double> dF( F.Domain() );\n        CppAD::vector<double> w( F.Range() );\n        w[0]    = 1.;\n        dF      = F.Reverse(1, w);\n        ok     &= NearEqual(dF[0] , 0., eps10, eps10);\n        ok     &= NearEqual(dF[1] , 1., eps10, eps10);\n\n        return ok;\n    }\n    bool forward_sparse_jacobian(void)\n    {   bool ok = true;\n        using namespace CppAD;\n\n        // dimension of the domain space\n        size_t n = 3;\n\n        // dimension of the range space\n        size_t m = 3;\n\n        // independent variable vector\n        CppAD::vector< AD<double> > X(n);\n        X[0] = 2.;\n        X[1] = 3.;\n        X[2] = 4.;\n        Independent(X);\n\n        // dependent variable vector\n        CppAD::vector< AD<double> > Y(m);\n\n        // check results vector\n        CppAD::vector< bool >       Check(m * n);\n\n        // initialize index into Y\n        size_t index = 0;\n\n        // Y[0]\n        Y[index]             = X[0] + X[1] + 5.;\n        Check[index * n + 0] = true;\n        Check[index * n + 1] = true;\n        Check[index * n + 2] = false;\n        index++;\n\n        // Y[1]\n        Y[index]             = Y[0] - (X[1] + X[2]);\n        Check[index * n + 0] = true;\n        Check[index * n + 1] = true;\n        Check[index * n + 2] = true;\n        index++;\n\n        // Y[2]\n        // 2DO: There is a subtitle issue that has to do with using reverse\n        // jacobian sparsity patterns during the optimization process.\n        // We need an option to include X[0] in the sparsity pattern\n        // so the optimizer can know it affects the results.\n        Y[index]             = CondExpLe(X[0], X[1], X[1]+X[1], X[2]-X[2]);\n        Check[index * n + 0] = false;\n        Check[index * n + 1] = true;\n        Check[index * n + 2] = true;\n        index++;\n\n        // check final index\n        assert( index == m );\n\n        // create function object F : X -> Y\n        ADFun<double> F(X, Y);\n\n        // optimize\n        optimize_with_options(F);\n\n        // ---------------------------------------------------------\n        // dependency matrix for the identity function\n        CppAD::vector< std::set<size_t> > Sx(n);\n        size_t i, j;\n        for(i = 0; i < n; i++)\n        {   assert( Sx[i].empty() );\n            Sx[i].insert(i);\n        }\n\n        // evaluate the dependency matrix for F(x)\n        CppAD::vector< std::set<size_t> > Sy(m);\n        Sy = F.ForSparseJac(n, Sx);\n\n        // check values\n        bool found;\n        for(i = 0; i < m; i++)\n        {   for(j = 0; j < n; j++)\n            {   found = Sy[i].find(j) != Sy[i].end();\n                ok &= (found == Check[i * n + j]);\n            }\n        }\n\n        return ok;\n    }\n    bool reverse_sparse_jacobian(void)\n    {   bool ok = true;\n        using namespace CppAD;\n\n        // dimension of the domain space\n        size_t n = 3;\n\n        // dimension of the range space\n        size_t m = 3;\n\n        // independent variable vector\n        CppAD::vector< AD<double> > X(n);\n        X[0] = 2.;\n        X[1] = 3.;\n        X[2] = 4.;\n        Independent(X);\n\n        // dependent variable vector\n        CppAD::vector< AD<double> > Y(m);\n\n        // check results vector\n        CppAD::vector< bool >       Check(m * n);\n\n        // initialize index into Y\n        size_t index = 0;\n\n        // Y[0]\n        Y[index]             = X[0] + X[1] + 5.;\n        Check[index * n + 0] = true;\n        Check[index * n + 1] = true;\n        Check[index * n + 2] = false;\n        index++;\n\n        // Y[1]\n        Y[index]             = Y[0] - (X[1] + X[2]);\n        Check[index * n + 0] = true;\n        Check[index * n + 1] = true;\n        Check[index * n + 2] = true;\n        index++;\n\n        // Y[2]\n        Y[index]             = CondExpLe(X[0], X[1], X[1]+X[1], X[2]-X[2]);\n        Check[index * n + 0] = false;\n        Check[index * n + 1] = true;\n        Check[index * n + 2] = true;\n        index++;\n\n        // check final index\n        assert( index == m );\n\n        // create function object F : X -> Y\n        ADFun<double> F(X, Y);\n\n        // optimize\n        optimize_with_options(F);\n\n        // ----------------------------------------------------------\n        // dependency matrix for the identity function\n        CppAD::vector< bool > Py(m * m);\n        size_t i, j;\n        for(i = 0; i < m; i++)\n        {   for(j = 0; j < m; j++)\n                Py[ i * m + j ] = i == j;\n        }\n\n        // evaluate the dependency matrix for F(x)\n        CppAD::vector< bool > Px(m * n);\n        Px = F.RevSparseJac(m, Py);\n\n        // check values\n        for(i = 0; i < m; i++)\n        {   for(j = 0; j < n; j++)\n                ok &= Px[i * n + j] == Check[i * n + j];\n        }\n\n        return ok;\n    }\n    bool reverse_sparse_hessian(void)\n    {   bool ok = true;\n        using CppAD::AD;\n        size_t i, j;\n\n        size_t n = 3;\n        CppAD::vector< AD<double> > X(n);\n        X[0] = 1.;\n        X[1] = 2.;\n        X[2] = 3.;\n        CppAD::Independent(X);\n\n        size_t m = 1;\n        CppAD::vector< AD<double> > Y(m);\n        Y[0] = CondExpGe( X[0], X[1],\n            X[0] + (2. + X[1] + 3.) * X[1],\n            X[0] + (2. + X[2] + 3.) * X[1]\n        );\n\n        CppAD::vector<bool> check(n * n);\n        check[0 * n + 0] = false; // partial w.r.t. x[0], x[0]\n        check[0 * n + 1] = false; //                x[0], x[1]\n        check[0 * n + 2] = false; //                x[0], x[2]\n\n        check[1 * n + 0] = false; // partial w.r.t. x[1], x[0]\n        check[1 * n + 1] = true;  //                x[1], x[1]\n        check[1 * n + 2] = true;  //                x[1], x[2]\n\n        check[2 * n + 0] = false; // partial w.r.t. x[2], x[0]\n        check[2 * n + 1] = true;  //                x[2], x[1]\n        check[2 * n + 2] = false; //                x[2], x[2]\n\n        // create function object F : X -> Y\n        CppAD::ADFun<double> F(X, Y);\n\n        // optimize\n        optimize_with_options(F);\n\n        // sparsity pattern for the identity function U(x) = x\n        CppAD::vector<bool> Px(n * n);\n        for(i = 0; i < n; i++)\n            for(j = 0; j < n; j++)\n                Px[ i * n + j ] = i == j;\n\n        // compute sparsity pattern for Jacobian of F(U(x))\n        CppAD::vector<bool> P_jac(m * n);\n        P_jac = F.ForSparseJac(n, Px);\n\n        // compute sparsity pattern for Hessian of F_k ( U(x) )\n        CppAD::vector<bool> Py(m);\n        CppAD::vector<bool> Pxx(n * n);\n        Py[0] = true;\n        Pxx = F.RevSparseHes(n, Py);\n        // check values\n        for(i = 0; i < n * n; i++)\n            ok &= (Pxx[i] == check[i]);\n\n        return ok;\n    }\n    // check that CondExp properly detects dependencies\n    bool cond_exp_depend(void)\n    {   bool ok = true;\n        using CppAD::AD;\n        using CppAD::NearEqual;\n        double eps10 = 10.0 * std::numeric_limits<double>::epsilon();\n\n        AD<double> zero(0.), one(1.), two(2.), three(3.);\n\n        size_t n = 4;\n        CppAD::vector< AD<double> > X(n);\n        X[0] = zero;\n        X[1] = one;\n        X[2] = two;\n        X[3] = three;\n        CppAD::Independent(X);\n\n        size_t m = 4;\n        CppAD::vector< AD<double> > Y(m);\n        Y[0] = CondExpLt(X[0] + .5,  one,  two, three);\n        Y[1] = CondExpLt(zero, X[1] + .5,  two, three);\n        Y[2] = CondExpLt(zero,  one, X[2] + .5, three);\n        Y[3] = CondExpLt(zero,  one,  two,  X[3] + .5);\n\n        CppAD::ADFun<double> f(X, Y);\n\n        // optimize\n        optimize_with_options(f);\n\n        CppAD::vector<double> x(n), y(m);\n        size_t i;\n        for(i = 0; i < n; i++)\n            x[i] = double(n - i);\n        y    = f.Forward(0, x);\n\n        if( x[0] + .5 < 1. )\n            ok &= NearEqual(y[0], 2., eps10, eps10);\n        else\n            ok &= NearEqual(y[0], 3., eps10, eps10);\n        if( 0. < x[1] + .5 )\n            ok &= NearEqual(y[1], 2., eps10, eps10);\n        else\n            ok &= NearEqual(y[1], 3., eps10, eps10);\n        ok &= NearEqual(y[2], x[2] + .5, eps10, eps10);;\n        ok &= NearEqual(y[3], 2., eps10, eps10);\n\n        return ok;\n    }\n    // check that CondExp properly handles expressions that get\n    // removed during optimization\n    bool cond_exp_removed(void)\n    {   bool ok = true;\n        using CppAD::AD;\n        using CppAD::NearEqual;\n        double eps10 = 10.0 * std::numeric_limits<double>::epsilon();\n        AD<double> zero(0.);\n\n        size_t n = 1;\n        CppAD::vector< AD<double> > X(n);\n        X[0] = 1.0;\n        CppAD::Independent(X);\n\n        size_t m = 1;\n        CppAD::vector< AD<double> > Y(m);\n\n        AD<double> true_case  = sin(X[0]) + sin(X[0]);\n        AD<double> false_case = cos(X[0]) + cos(X[0]);\n        Y[0] = CondExpLt(X[0],  zero,  true_case, false_case);\n\n        CppAD::ADFun<double> f(X, Y);\n\n        // optimize\n        optimize_with_options(f);\n\n        CppAD::vector<double> x(n), y(m), w(m), dw(n);\n        x[0] = 1.0;\n        y    = f.Forward(0, x);\n        ok &= NearEqual(y[0], false_case, eps10, eps10);\n\n        w[0] = 1.0;\n        dw   = f.Reverse(1, w);\n        // derivative of cos is minus sin\n        ok &= NearEqual(dw[0], - true_case, eps10, eps10);\n\n        return ok;\n    }\n    // -------------------------------------------------------------------\n    using CppAD::set_union;\n\n    bool atomic_one_forward(\n        size_t                         id ,\n        size_t                          k ,\n        size_t                          n ,\n        size_t                          m ,\n        const CppAD::vector<bool>&     vx ,\n        CppAD::vector<bool>&           vy ,\n        const CppAD::vector<double>&   tx ,\n        CppAD::vector<double>&         ty )\n    {   assert(n == 3 && m == 2);\n        if( k > 0 )\n            return false;\n\n        // y[0] = x[0] + x[1]\n        ty[0] = tx[0] + tx[1];\n\n        // y[1] = x[1] + x[2]\n        ty[1] = tx[1] + tx[2];\n\n        if( vy.size() > 0 )\n        {   vy[0] = vx[0] || vx[1];\n            vy[1] = vx[1] || vx[2];\n        }\n        return true;\n    }\n\n    bool atomic_one_reverse(\n        size_t                         id ,\n        size_t                          k ,\n        size_t                          n ,\n        size_t                          m ,\n        const CppAD::vector<double>&   tx ,\n        const CppAD::vector<double>&   ty ,\n        CppAD::vector<double>&         px ,\n        const CppAD::vector<double>&   py )\n    {   return false; }\n\n    bool atomic_one_for_jac_sparse(\n        size_t                                  id ,\n        size_t                                   n ,\n        size_t                                   m ,\n        size_t                                   q ,\n        const CppAD::vector< std::set<size_t> >& r ,\n        CppAD::vector< std::set<size_t>  >&      s )\n    {   return false; }\n\n    bool atomic_one_rev_jac_sparse(\n        size_t                                  id ,\n        size_t                                   n ,\n        size_t                                   m ,\n        size_t                                   q ,\n        CppAD::vector< std::set<size_t> >&       r ,\n        const CppAD::vector< std::set<size_t> >& s )\n    {   assert(n == 3 && m == 2);\n        r[0].clear();\n        r[1].clear();\n        r[2].clear();\n        // y[0] = x[0] + x[1]\n        r[0] = set_union(r[0], s[0]);\n        r[1] = set_union(r[1], s[0]);\n        // y[1] = x[1] + x[2]\n        r[1] = set_union(r[1], s[1]);\n        r[2] = set_union(r[2], s[1]);\n\n        return true;\n    }\n\n    bool atomic_one_rev_hes_sparse(\n        size_t                                  id ,\n        size_t                                   n ,\n        size_t                                   m ,\n        size_t                                   q ,\n        const CppAD::vector< std::set<size_t> >& r ,\n        const CppAD::vector<bool>&               s ,\n        CppAD::vector<bool>&                     t ,\n        const CppAD::vector< std::set<size_t> >& u ,\n        CppAD::vector< std::set<size_t> >&       v )\n    {   return false; }\n\n    CPPAD_USER_ATOMIC(\n        my_atomic_one             ,\n        CppAD::vector              ,\n        double                     ,\n        atomic_one_forward        ,\n        atomic_one_reverse        ,\n        atomic_one_for_jac_sparse ,\n        atomic_one_rev_jac_sparse ,\n        atomic_one_rev_hes_sparse\n    )\n\n    bool atomic_one_test(void)\n    {   bool ok = true;\n\n        using CppAD::AD;\n        using CppAD::NearEqual;\n        double eps10 = 10.0 * std::numeric_limits<double>::epsilon();\n        size_t j;\n        size_t n = 3;\n        size_t m = 2;\n        CppAD::vector< AD<double> > ax(n), ay(m), az(m);\n        for(j = 0; j < n; j++)\n            ax[j] = AD<double>(j + 1);\n        CppAD::Independent(ax);\n\n        size_t id = 0;\n        // first call should stay in the tape\n        my_atomic_one(id++, ax, ay);\n        // second call will not get used\n        my_atomic_one(id++, ax, az);\n        // create function\n        CppAD::ADFun<double> g(ax, ay);\n        // should have 1 + n + m + m variables\n        ok &= g.size_var() == (1 + n + m + m);\n\n        // optimize\n        optimize_with_options(g);\n\n        // should have 1 + n + m variables\n        ok &= g.size_var() == (1 + n + m);\n\n        // now test that the optimized function gives same results\n        CppAD::vector<double> x(n), y(m);\n        for(j = 0; j < n; j++)\n            x[j] = double( (j + 1) * (j + 1) );\n        y = g.Forward(0, x);\n        // y[0] = x[0] + x[1]\n        ok &= NearEqual(y[0], x[0] + x[1], eps10, eps10);\n        // y[1] = x[1] + x[2]\n        ok &= NearEqual(y[0], x[0] + x[1], eps10, eps10);\n\n        return ok;\n    }\n    bool not_identically_equal(void)\n    {   bool ok = true;\n        using CppAD::AD;\n\n        // independent variable vector\n        size_t n = 5;\n        CppAD::vector< AD<double> > ax(n);\n        size_t j;\n        for(j = 0; j < n; j++)\n            ax[j] = 1. / 3.;\n        CppAD::Independent(ax);\n\n        // dependent variable vector\n        size_t m = 1;\n        CppAD::vector< AD<double> > ay(m);\n        ay[0]       = 0.;\n        for(j = 0; j < n; j++)\n        {   if( j % 2 == 0 )\n                ay[0] += ax[j];\n            else\n                ay[0] -= ax[j];\n        }\n        CppAD::ADFun<double> f(ax, ay);\n\n        // Used to fail assert in optimize that forward mode results\n        // are identically equal\n        optimize_with_options(f);\n\n        return ok;\n    }\n    // -----------------------------------------------------------------------\n    double floor(const double& x)\n    {   return std::floor(x); }\n    CPPAD_DISCRETE_FUNCTION(double, floor)\n    bool discrete_function(void)\n    {   bool ok = true;\n        using CppAD::vector;\n        using CppAD::NearEqual;\n        double eps10 = 10.0 * std::numeric_limits<double>::epsilon();\n\n        vector< CppAD::AD<double> > ax(1), ay(1);\n        ax[0] = 0.0;\n        CppAD::Independent(ax);\n        ay[0] =  floor(ax[0]) + floor(ax[0]);\n        CppAD::ADFun<double> f(ax, ay);\n\n        size_t size_before = f.size_var();\n\n        // optimize\n        optimize_with_options(f);\n\n        size_t size_after = f.size_var();\n        ok &= size_after + 1 == size_before;\n\n        vector<double> x(1), y(1);\n        x[0] = -2.2;\n        y    = f.Forward(0, x);\n        ok &= NearEqual(y[0], -6.0, eps10, eps10);\n\n        return ok;\n    }\n    // ----------------------------------------------------------------\n    void i_algo(\n        const CppAD::vector< CppAD::AD<double> >& ax ,\n                  CppAD::vector< CppAD::AD<double> >& ay )\n    {   ay[0] = 1.0 / ax[0]; }\n    //\n    // Test bug where atomic functions were not properly conditionally skipped.\n    bool cond_exp_skip_atomic(void)\n    {   bool ok = true;\n        using CppAD::AD;\n        using CppAD::NearEqual;\n        double eps10 = 10.0 * std::numeric_limits<double>::epsilon();\n        using CppAD::vector;\n\n        // Create a checkpoint version of the function i_algo\n        vector< AD<double> > au(1), av(1), aw(1);\n        au[0] = 1.0;\n        CppAD::checkpoint<double> i_check(\"i_check\", i_algo, au, av);\n\n        // independent variable vector\n        vector< AD<double> > ax(2), ay(1);\n        ax[0] = 1.0;\n        ax[1] = 2.0;\n        Independent(ax);\n\n        // call atomic function that does not get used\n        au[0] = ax[0];\n        i_check(au, av);\n        au[0] = ax[1];\n        i_check(au, aw);\n        AD<double> zero = 0.0;\n        ay[0] = CondExpGt(av[0], zero, av[0], aw[0]);\n\n        // create function object f : ax -> ay\n        CppAD::ADFun<double> f(ax, ay);\n\n        // run case that skips the second call to afun\n        // (can use trace in sweep/forward_0.hpp to see this).\n        vector<double> x(2), y_before(1), y_after(1);\n        x[0]      = 1.0;\n        x[1]      = 2.0;\n        y_before  = f.Forward(0, x);\n\n        // optimize\n        optimize_with_options(f);\n\n        y_after   = f.Forward(0, x);\n\n        ok &= NearEqual(y_before[0], y_after[0], eps10, eps10);\n\n        return ok;\n    }\n    //\n    // Test bug where conditional dependence did not pass through\n    // atomic functions\n    bool cond_exp_atomic_dependence(void)\n    {   bool ok = true;\n        using CppAD::AD;\n        using CppAD::NearEqual;\n        double eps10 = 10.0 * std::numeric_limits<double>::epsilon();\n        using CppAD::vector;\n\n        // Create a checkpoint version of the function i_algo\n        vector< AD<double> > au(1), av(1), aw(1);\n        au[0] = 1.0;\n        CppAD::checkpoint<double> i_check(\"i_check\", i_algo, au, av);\n\n        vector< AD<double> > ax(2), ay(1);\n        AD<double> zero = 0.0;\n        ax[0] = 1.0;\n        ax[1] = 1.0;\n        Independent(ax);\n        av[0] = ax[0] + ax[1];\n        i_check(av, aw);\n        ay[0] = CondExpGt(aw[0], zero, zero, aw[0]);\n        CppAD::ADFun<double> f;\n        f.Dependent(ax, ay);\n\n        // run case that skips the second call to afun\n        // (but not for order zero)\n        vector<double> x(2), y_before(1), y_after(1);\n        vector<double> dx(2), dy_before(1), dy_after(1);\n        x[0]      = 1.0;\n        x[1]      = 1.0;\n        y_before  = f.Forward(0, x);\n        dx[0]     = 2.0;\n        dx[1]     = 2.0;\n        dy_before = f.Forward(1, dx);\n\n        // optimize\n        optimize_with_options(f);\n\n        y_after   = f.Forward(0, x);\n        dy_after  = f.Forward(1, dx);\n\n        ok &= NearEqual(y_before[0] , y_after[0], eps10, eps10);\n        ok &= NearEqual(dy_before[0], dy_after[0], eps10, eps10);\n\n        return ok;\n    }\n    // -----------------------------------------------------------------------\n    // Test reverse mode conditionalay skipping commands.\n    template <class Type>\n    Type my_max(const CppAD::vector<Type>& arg)\n    {   Type res = arg[0];\n        for(size_t j = 0;j < arg.size(); j++)\n        res = CondExpGt(res, arg[j], res, arg[j]);\n        return res;\n    }\n    bool cond_exp_reverse(void)\n    {   bool ok = true;\n        size_t n = 3;\n        using CppAD::vector;\n        using CppAD::AD;\n        using CppAD::NearEqual;\n        double eps10 = 10.0 * std::numeric_limits<double>::epsilon();\n\n        vector< AD<double> > ax(n), ay(1);\n        for(size_t j = 0; j < n; j++)\n            ax[j] = 1.0;\n        Independent(ax);\n        ay[0] = my_max(ax) + my_max(ax);\n        CppAD::ADFun<double> f(ax, ay);\n\n\n        // optimize\n        optimize_with_options(f);\n\n        vector<double> x(n), w(1), dx(n);\n        for(size_t j = 0;j < n; j++)\n            x[j] = double(j);\n        f.Forward(0, x);\n        w[0] = 1.0;\n        dx = f.Reverse(1, w);\n        for(size_t j = 0; j < n; j++)\n        {   if( j == n-1 )\n                ok &= NearEqual(dx[j], 2.0, eps10, eps10);\n            else\n                ok &= NearEqual(dx[j], 0.0, eps10, eps10);\n        }\n        return ok;\n    }\n    // -----------------------------------------------------------------------\n    // Test case where an expression depends on both the true\n    // and false cases (bug fixed 2014-12-22)\n    bool cond_exp_both_true_and_false(void)\n    {   bool ok = true;\n        using CppAD::vector;\n        using CppAD::AD;\n        using CppAD::NearEqual;\n        double eps10 = 10.0 * std::numeric_limits<double>::epsilon();\n\n        // f(x) = x[0] + x[0] if x[0] >= 3\n        //      = x[0] + x[1] otherwise\n        vector< AD<double> > ax(2), ay(3);\n        ax[0] = 1.0;\n        ax[1] = 2.0;\n        Independent(ax);\n        AD<double> three(3);\n        AD<double> value = ax[0] + ax[1];\n        // a simple value\n        ay[0]  = CppAD::CondExpGe(ax[0], three, value, value);\n        // a  binary exprpression\n        ay[1]  = CppAD::CondExpGe(ax[0], three, ax[0]-ax[1], ax[0]-ax[1]);\n        // a unary expression\n        ay[2]  = CppAD::CondExpGe(ax[0], three, exp(ax[0]), exp(ax[0]) );\n        CppAD::ADFun<double> f(ax, ay);\n\n        // optimize\n        optimize_with_options(f);\n\n        // check case where x[0] >= 3\n        vector<double> x(2), y(3);\n        x[0] = 4.0;\n        x[1] = 2.0;\n        y    = f.Forward(0, x);\n        ok &= NearEqual(y[0], x[0] + x[1], eps10, eps10);\n        ok &= NearEqual(y[1], x[0] - x[1], eps10, eps10);\n        ok &= NearEqual(y[2], exp(x[0]), eps10, eps10);\n\n        // check case where x[0] < 3\n        x[0] = 1.0;\n        x[1] = 2.0;\n        y    = f.Forward(0, x);\n        ok &= NearEqual(y[0], x[0] + x[1], eps10, eps10);\n        ok &= NearEqual(y[1], x[0] - x[1], eps10, eps10);\n        ok &= NearEqual(y[2], exp(x[0]), eps10, eps10);\n\n        return ok;\n    }\n\n    // Test case where a variable is removed during optimization\n    // (bug fixed 2017-03-04)\n    bool cond_exp_skip_remove_var(void)\n    {   bool ok = true;\n        using CppAD::vector;\n        using CppAD::AD;\n        using CppAD::NearEqual;\n        double eps10 = 10.0 * std::numeric_limits<double>::epsilon();\n\n        vector< AD<double> > ax(2), ay(2);\n        ax[0] = 1.0;\n        ax[1] = 2.0;\n        Independent(ax);\n        //\n        AD<double> var_1   = ax[0] + ax[1];\n        AD<double> var_2   = ax[0] + ax[1]; // gets removed during optimization\n        AD<double> var_3   = ax[0] + ax[1]; // gets removed during optimization\n        AD<double> var_4   = ax[0] - ax[1];\n        AD<double> par_1   = 1.0;\n        //\n        // first conditional expression depends on var_1\n        // 6 * x_0 if x_0 + x_1 >= 1.0,  7 * x_1 otherwise\n        ay[0] = CppAD::CondExpGe(var_1, par_1, 6.0 * ax[0], 7.0 * ax[1]);\n        //\n        // second conditional expression depends on var_4\n        // 8 * x_0 if x_0 - x_1 >= x_0 + x_1, 9 * x_1 otherwise\n        ay[1] = CppAD::CondExpGe(var_4, par_1, 8.0 * ax[0], 9.0 * ax[1]);\n        CppAD::ADFun<double> f(ax, ay);\n        //\n        // optimize\n        optimize_with_options(f);\n\n        // check case where x[0] = 2, x[1] = 4\n        vector<double> x(2), y(2);\n        x[0] = 2.0;\n        x[1] = 4.0;\n        y    = f.Forward(0, x);\n        ok &= NearEqual(y[0], 6.0 * x[0], eps10, eps10);\n        ok &= NearEqual(y[1], 9.0 * x[1], eps10, eps10);\n\n        return ok;\n    }\n\n    // -----------------------------------------------------------------------\n    // Test case where if_false case is not used by conditional expression\n    // but is use after conditional expression.\n    // (bug fixed 2017-04-02)\n    bool cond_exp_if_false_used_after(void)\n    {   bool ok = true;\n        using CppAD::vector;\n        using CppAD::AD;\n        using CppAD::NearEqual;\n        double eps10 = 10.0 * std::numeric_limits<double>::epsilon();\n\n        vector< AD<double> > ax(2), ay(1);\n        ax[0] = 1.0;\n        ax[1] = 2.0;\n        Independent(ax);\n        //\n        AD<double> left     = ax[0];\n        AD<double> right    = ax[1];\n        AD<double> if_true  = ax[0] + ax[0];\n        AD<double> if_false = ax[1] + ax[1];\n        //\n        AD<double> cexp = CondExpLt(left, right, if_true, if_false);\n        ay[0] = cexp + if_false;\n        CppAD::ADFun<double> f(ax, ay);\n\n        // optimize\n        optimize_with_options(f);\n        //\n        // check case where x[0] < x[1]\n        vector<double> x(2), y(1);\n        x[0] = 2.0;\n        x[1] = 4.0;\n        y    = f.Forward(0, x);\n        ok &= NearEqual(y[0], x[0] + x[0] + x[1] + x[1], eps10, eps10);\n        ok &= f.number_skip() == 0;\n        //\n        // check case where x[0] >= x[1] (if_true is not used)\n        x[0] = 4.0;\n        x[1] = 2.0;\n        y    = f.Forward(0, x);\n        ok &= NearEqual(y[0], x[1] + x[1] + x[1] + x[1], eps10, eps10);\n        if( conditional_skip_ )\n            ok &= f.number_skip() == 1;\n        else\n            ok &= f.number_skip() == 0;\n        //\n        return ok;\n    }\n\n    // -----------------------------------------------------------------------\n    // Test case where only variable arguments were being checked for\n    // a complete match once hash_codes were equal.\n    // (*bug fixed 2017-11-23)\n    bool only_check_variables_when_hash_codes_match(void)\n    {   bool ok = true;\n        using CppAD::AD;\n        using CppAD::vector;\n        //\n        double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n        //\n        // length of the data vector z\n        size_t nz = 9999;\n        //\n        // factor for last term\n        double factor = 1e+5;\n        //\n        // z starts at -1.0 and ends at 1.0\n        vector<double> z(nz);\n        for(size_t i = 0; i < nz; i++)\n            z[i] = -1.0 + 2.0 * double(i) / double(nz - 1);\n        //\n        // f(x) = sum from i=0 to nz-1 of (x - z[i])^2\n        vector< AD<double> > ax(1), ay(1);\n        ax[0] = 0.0;\n        CppAD::Independent(ax);\n        AD<double> asum = 0.0;\n        for(size_t i = 0; i < nz; i++)\n        {   AD<double> aterm = z[i] - ax[0];\n            if( i == nz - 1 )\n                asum += factor * aterm;\n            else\n                asum += aterm / factor;\n        }\n        ay[0] = asum;\n        CppAD::ADFun<double> f(ax, ay);\n        //\n        // value of x where we are computing derivative\n        vector<double> x(1), y_before(1), y_after(1);\n        x[0]     = .1;\n        y_before = f.Forward(0, x);\n\n        // optimize\n        optimize_with_options(f);\n\n        y_after  = f.Forward(0, x);\n        //\n        ok &= CppAD::NearEqual(y_before[0], y_after[0], eps99, eps99);\n        //\n        return ok;\n    }\n\n    // -----------------------------------------------------------------------\n    // Test case with print operator in optimized f\n    bool check_print_for(void)\n    {   bool ok = true;\n        using CppAD::AD;\n        using CppAD::vector;\n        //\n        double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n        //\n        vector< AD<double> > ax(1), ay(1);\n        ax[0] = 1.0;\n        CppAD::Independent(ax);\n        //\n        // check case where value is a parameter\n        AD<double>  pos    = ax[0];\n        const char* before = \"long text before: value = \";\n        AD<double>  value  = 2.0;\n        const char* after  = \"\\n\";\n        CppAD::PrintFor(pos, before, value, after);\n        CppAD::PrintFor(pos, before, value, after);\n        //\n        ay[0] = ax[0];\n        CppAD::ADFun<double> f;\n        f.Dependent(ax, ay);\n        //\n        // value of x where we are computing derivative\n        std::stringstream s;\n        vector<double> x(1), y_before(1), y_after(1);\n        x[0]     = -0.1;\n        y_before = f.Forward(0, x, s);\n\n        // optimize\n        optimize_with_options(f);\n\n        y_after  = f.Forward(0, x, s);\n        //\n        ok &= CppAD::NearEqual(y_before[0], y_after[0], eps99, eps99);\n        //\n        return ok;\n    }\n    // ----------------------------------------------------------------\n    // Test case where two non-empty sets need to be intersected to obtain\n    // set of variables that can be skipped\n    bool intersect_cond_exp(void)\n    {   bool ok = true;\n        using CppAD::AD;\n        using CppAD::NearEqual;\n        double eps10 = 10.0 * std::numeric_limits<double>::epsilon();\n        using CppAD::vector;\n\n        // independent variable vector\n        vector< AD<double> > ax(2), ay(1);\n        ax[0] = 1.0;\n        ax[1] = 2.0;\n        Independent(ax);\n\n        // can only be skipped when second conditional expression is true\n        AD<double> askip_second_true = ax[1] + 1.0;\n\n        // at this point reverse mode analysis yields\n        // skip set for askip_second_true = {skip if 2 true}\n\n        // value of first conditional expression when it is true / false\n        AD<double> first_true   = askip_second_true * 2.0;\n        AD<double> first_false  = askip_second_true;\n\n        // at this point reverse mode analysis yields\n        // skip set for askip_second_true = {skip if 1 true, skip if 2 true}\n\n        // first conditional expression\n        AD<double> ac1 = CondExpLe(ax[0], ax[1], first_true, first_false);\n\n        // value of second conditional expression when it is true / false\n        AD<double> second_true   = ax[1] + 2.0;\n        AD<double> second_false  = ac1;\n\n        // at this point reverse mode analysis yields\n        // skip set for ac1 = {skip if 2 true}\n\n        // second conditional expression\n        AD<double> ac2 = CondExpLe(ax[0], ax[1], second_true, second_false);\n\n        // create function object f : ax -> ay\n        ay[0] = ac2;\n        CppAD::ADFun<double> f(ax, ay);\n\n        // optimize\n        optimize_with_options(f);\n\n        // now zero order forward\n        vector<double> x(2), y(1);\n        for(size_t i = 0; i < 3; i++)\n        {   x[0] = 1.0 - double(i);\n            x[1] = - x[0];\n            y    = f.Forward(0, x);\n            //\n            double skip_second_true = x[1] + 1.0;;\n            //\n            // first conditional expression\n            double c1;\n            if( x[0] <= x[1] )\n                c1 = skip_second_true * 2.0;\n            else\n                c1 = skip_second_true;\n            //\n            // second conditional expression\n            double c2;\n            if( x[0] <= x[1] )\n                c2 = x[1] + 2.0;\n            else\n                c2 = c1;\n            //\n            ok &= NearEqual(y[0], c2, eps10, eps10);\n        }\n        return ok;\n    }\n}\n\nbool optimize(void)\n{   bool ok = true;\n    //\n    // val_optimize cases\n    use_val_optimize_      = true;\n    ok     &= cond_exp_ppvv();\n    // skip:  exceed_collision_limit(void)\n    // skip: no_cumulative_sum(void)\n    ok     &= optimize_csum();\n    ok     &= optimize_ode();\n    ok     &= nested_cond_exp();\n    ok     &= atomic_cond_exp_sparsity();\n    ok     &= atomic_no_used();\n    ok     &= atomic_arguments();\n    ok     &= depend_one();\n    ok     &= depend_two();\n    ok     &= depend_three();\n    ok     &= depend_four();\n    ok     &= duplicate_one();\n    ok     &= duplicate_two();\n    ok     &= duplicate_three();\n    ok     &= duplicate_four();\n    ok     &= cumulative_sum();\n    ok     &= forward_csum();\n    ok     &= reverse_csum();\n    ok     &= forward_sparse_jacobian();\n    ok     &= reverse_sparse_jacobian();\n    ok     &= reverse_sparse_hessian();\n    ok     &= cond_exp_depend();\n    ok     &= cond_exp_removed();\n    ok     &= atomic_one_test();\n    ok     &= not_identically_equal();\n    ok     &= discrete_function();\n    ok     &= cond_exp_skip_atomic();\n    ok     &= cond_exp_atomic_dependence();\n    ok     &= cond_exp_reverse();\n    ok     &= cond_exp_both_true_and_false();\n    ok     &= cond_exp_skip_remove_var();\n    ok     &= cond_exp_if_false_used_after();\n    ok     &= only_check_variables_when_hash_codes_match();\n    ok     &= check_print_for();\n    ok     &= intersect_cond_exp();\n    use_val_optimize_      = false;\n    //\n    // conditional_skip_, atomic_sparsity_option_\n    conditional_skip_       = true;\n    atomic_sparsity_option_ = CppAD::atomic_base<double>::bool_sparsity_enum;\n    //\n\n    ok     &= atomic_cond_exp_sparsity();\n\n    // check exceed_collision_limit\n    ok &= exceed_collision_limit();\n\n    // check no_cumulative_sum_op\n    ok &= no_cumulative_sum();\n\n    // check optimization with cumulative sum operators\n    ok &= optimize_csum();\n\n    // check optimization with print_for operations\n    ok &= check_print_for();\n\n    // optimize an example ODE\n    ok &= optimize_ode();\n\n    // atomic sparsity loop\n    for(size_t i = 0; i < 3; i++)\n    {   if( i == 0 ) atomic_sparsity_option_ =\n            CppAD::atomic_base<double>::pack_sparsity_enum;\n        else if( i == 1 ) atomic_sparsity_option_ =\n            CppAD::atomic_base<double>::bool_sparsity_enum;\n        else if( i == 2 ) atomic_sparsity_option_ =\n            CppAD::atomic_base<double>::set_sparsity_enum;\n        else\n            ok &= false;\n        //\n        // check conditional expression sparsity pattern\n        // (used to optimize calls to atomic functions).\n        ok     &= atomic_cond_exp_sparsity();\n        // check optimizing out entire atomic function\n        ok     &= atomic_cond_exp();\n        // check optimizing out atomic arguments\n        ok     &= atomic_no_used();\n        ok     &= atomic_arguments();\n    }\n\n    // conditional skip loop\n    for(size_t i = 0; i < 2; i++)\n    {   conditional_skip_ = i == 0;\n        // dynamic parameter conditional expression\n        ok     &= cond_exp_ppvv();\n        //\n        // check nested conditional expressions\n        ok     &= nested_cond_exp();\n        // check reverse dependency analysis optimization\n        ok     &= depend_one();\n        ok     &= depend_two();\n        ok     &= depend_three();\n        ok     &= depend_four();\n        // check removal of duplicate expressions\n        ok     &= duplicate_one();\n        ok     &= duplicate_two();\n        ok     &= duplicate_three();\n        ok     &= duplicate_four();\n        // convert sequence of additions to cumulative summation\n        ok     &= cumulative_sum();\n        ok     &= forward_csum();\n        ok     &= reverse_csum();\n        // sparsity patterns\n        ok     &= forward_sparse_jacobian();\n        ok     &= reverse_sparse_jacobian();\n        ok     &= reverse_sparse_hessian();\n        // check that CondExp properly detects dependencies\n        ok     &= cond_exp_depend();\n        // check that it properly handles expressions that have been removed\n        ok     &= cond_exp_removed();\n        // check atomic_one functions\n        ok     &= atomic_one_test();\n        // case where results are not identically equal\n        ok     &= not_identically_equal();\n        // case where a discrete function is used\n        ok     &= discrete_function();\n        // check conditional skip of an atomic function\n        ok     &= cond_exp_skip_atomic();\n        // check conditional dependence through atomic function\n        ok     &= cond_exp_atomic_dependence();\n        // check reverse mode conditional skipping\n        ok     &= cond_exp_reverse();\n        // check case where an expression needed by both true and false case\n        ok     &= cond_exp_both_true_and_false();\n        // check case were a variable in left or right expressions\n        // is removed during the optimization\n        ok     &= cond_exp_skip_remove_var();\n        // check case where an if case is used after the conditional expression\n        ok     &= cond_exp_if_false_used_after();\n        // check case that has non-empty binary intersection operation\n        ok     &= intersect_cond_exp();\n    }\n\n    // not using conditional_skip or atomic functions\n    ok &= only_check_variables_when_hash_codes_match();\n    // -----------------------------------------------------------------------\n    //\n    CppAD::user_atomic<double>::clear();\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/parameter.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n// Test hash coding of parameter during recording\n\n# include <cppad/cppad.hpp>\n\nnamespace { // BEGIN empty namespace\n\ntemplate <class Float>\nbool test_repeat(void)\n{   bool ok = true;\n    using namespace CppAD;\n\n    // number of different constant parameters\n    size_t n_constant = 13;\n\n    // number of normal parameter repeats\n    size_t n_repeat = 17;\n\n    // number of independent dynamic parameters\n    size_t n_dynamic = 5;\n\n    // independent variable vector\n    size_t n = n_constant * n_repeat;\n    CPPAD_TESTVECTOR(AD<Float>) ax(n), dynamic(n_dynamic);\n    // dynamic parameter all have same value, but that could change\n    for(size_t j = 0; j < n_dynamic; ++j)\n        dynamic[j] = 3.0;\n    for(size_t j = 0; j < n; j++)\n        ax[j] = Float(j);\n    size_t abort_op_index = 0;\n    bool   record_compare = true;\n    Independent(ax, abort_op_index, record_compare, dynamic);\n\n    // dependent variable vector and indices\n    size_t m = n;\n    CPPAD_TESTVECTOR(AD<Float>) ay(m);\n    for(size_t i = 0; i < m; i++)\n    {   // must avoid Float(k) = 0 because it would get optimized out\n        size_t k = (i % n_constant);\n        k        = k * k * 10 + 1;\n        size_t j = i;\n        ay[i] = ax[j] + Float(k);\n    }\n\n    // create f: ax -> ay\n    ADFun<Float> f(ax, ay);\n\n    // add one for the phantom parameter at index zero\n    ok = f.size_par() == 1 + n_constant + n_dynamic;\n\n    return ok;\n}\n\n} // END empty namespace\n\nbool parameter(void)\n{   bool ok = true;\n    ok &= test_repeat<double>();\n    ok &= test_repeat<float>();\n    //\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/poly.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n// Old GetStarted example now used just for validation testing\n*/\n// BEGIN C++\n\n// directory where cppad/cppad.hpp is stored must be searched by compiler\n# include <cppad/cppad.hpp>\n\nbool Poly(void)\n{   bool ok = true;\n\n    // make CppAD routines visible without CppAD:: infront of names\n    using namespace CppAD;\n\n    // degree of the polynomial that we will differentiate\n    size_t deg = 4;\n\n    // vector that will hold polynomial coefficients for p(z)\n    CPPAD_TESTVECTOR(AD<double>) A(deg + 1);  // AD<double> elements\n    CPPAD_TESTVECTOR(double)       a(deg + 1);  //    double  elements\n\n    // set the polynomial coefficients\n    A[0] = 1.;\n    size_t k;\n    for(k = 1; k <= deg; k++)\n        A[k] = a[k] = 1.;\n\n    // independent variables\n    CPPAD_TESTVECTOR(AD<double>) Z(1); // one independent variable\n    Z[0]     = 3.;                        // value of independent variable\n    Independent(Z);                       // declare independent variable\n\n    // dependent variables\n    CPPAD_TESTVECTOR(AD<double>) P(1); // one dependent variable\n    P[0]     = Poly(0, A, Z[0]);    // value of polynomial at Z[0]\n\n    // define f : Z -> P as a function mapping independent to dependent\n    ADFun<double> f(Z, P);          // ADFun corresponding to polynomial\n\n    // compute derivative of polynomial\n    CPPAD_TESTVECTOR(double) z(1);  // vector length f.Domain()\n    CPPAD_TESTVECTOR(double) J(1);  // vector length f.Range * f.Domain()\n    z[0] = 3.;                 // point at which to compute derivative\n    J    = f.Jacobian(z);      // value of derivative\n\n    // compare with derivative as computed by Poly\n    ok  &= (Poly(1, a, z[0]) == J[0]);\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "test_more/general/pow.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-25 Bradley M. Bell\n// SPDX-FileContributor: 2025 Perry de Valpine\n// ----------------------------------------------------------------------------\n\n/*\nOld examples now just used for validation testing.\n*/\n# include <cppad/cppad.hpp>\n\nnamespace { // BEGIN empty namespace\n\n// ---------------------------------------------------------------------------\n// dynamic_zero\n// Cases during recording where the base or exponent is a dynamic parameter\n// with value zero.\nbool dynamic_zero(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    const size_t nd = 1, nx = 1, ny = 1;\n    size_t abort_op_index = 0;\n    bool   record_compare = false;\n    // -----------------------------\n    // Case A: x = variable, y = dynamic; y == 0 during recording\n    // -----------------------------\n    {\n        CPPAD_TESTVECTOR(AD<double>) ax(nx), ay(ny), adyn(nd);\n        ax[0]  = 2.0;      // x during recording\n        adyn[0]= 0.0;      // y during recording (dynamic zero)\n\n        CppAD::Independent(ax, abort_op_index, record_compare, adyn);\n\n        AD<double> x = ax[0];\n        AD<double> y = adyn[0]; // dynamic param (zero)\n        ay[0] = pow(x, y);      // variable ^ dynamic 0\n\n        CppAD::ADFun<double> f(ax, ay);\n\n        // Evaluate with new dynamic values\n        CPPAD_TESTVECTOR(double) x_in(nx), y_out(ny), dyn(nd);\n\n        // First eval: y = 3 (non-zero), x = 2 => 2^3 = 8\n        x_in[0] = 2.0;\n        dyn[0]  = 3.0;\n        f.new_dynamic(dyn);\n        y_out = f.Forward(0, x_in);\n        ok &= NearEqual(y_out[0], 8.0, eps99, eps99);\n\n        // Second eval: y = 2, x = 3 => 3^2\n        x_in[0] = 3.0;\n        dyn[0]  = 2.0;\n        f.new_dynamic(dyn);\n        y_out = f.Forward(0, x_in);\n        ok &= NearEqual(y_out[0], std::pow(3.0, 2.0), eps99, eps99);\n    }\n\n    // -----------------------------\n    // Case B: x = dynamic (zero at recording), y = variable\n    // -----------------------------\n    {\n        CPPAD_TESTVECTOR(AD<double>) ax(nx), ay(ny), adyn(nd);\n        ax[0]   = 3.0;     // y during recording\n        adyn[0] = 0.0;     // x during recording (dynamic zero)\n\n        CppAD::Independent(ax, abort_op_index, record_compare, adyn);\n\n        AD<double> x = adyn[0]; // dynamic param (zero)\n        AD<double> y = ax[0];   // variable\n        ay[0] = pow(x, y);      // dynamic 0 ^ variable\n\n        CppAD::ADFun<double> f(ax, ay);\n\n        // Evaluate with new dynamic values\n        CPPAD_TESTVECTOR(double) x_in(nx), y_out(ny), dyn(nd);\n\n        // First eval: x = 2 (non-zero), y = 3 => 2^3 = 8\n        x_in[0] = 3.0;  // y\n        dyn[0]  = 2.0;  // x\n        f.new_dynamic(dyn);\n        y_out = f.Forward(0, x_in);\n        ok &= NearEqual(y_out[0], 8.0, eps99, eps99);\n\n        // Second eval: x = 3, y = 2 => 3^2\n        x_in[0] = 2.0;  // y\n        dyn[0]  = 3.0;  // x\n        f.new_dynamic(dyn);\n        y_out = f.Forward(0, x_in);\n        ok &= NearEqual(y_out[0], std::pow(3.0, 2.0), eps99, eps99);\n    }\n\n    return ok;\n}\n// ---------------------------------------------------------------------------\nbool PowTestOne(void)\n{   bool ok = true;\n\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n  = 2;\n    double x = 0.5;\n    double y = 2.;\n    CPPAD_TESTVECTOR(AD<double>) XY(n);\n    XY[0]      = x;\n    XY[1]      = y;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(XY);\n\n    // range space vector\n    size_t m = 3;\n    CPPAD_TESTVECTOR(AD<double>) Z(m);\n    Z[0] = CppAD::pow(XY[0], XY[1]);  // pow(variable, variable)\n    Z[1] = CppAD::pow(XY[0], y);      // pow(variable, parameter)\n    Z[2] = CppAD::pow(x,     XY[1]);  // pow(parameter, variable)\n\n    // create f: XY -> Z and stop tape recording\n    CppAD::ADFun<double> f(XY, Z);\n\n    // check value\n    double check = std::pow(x, y);\n    size_t i;\n    for(i = 0; i < m; i++)\n        ok &= NearEqual(Z[i] , check, eps99, eps99);\n\n    // forward computation of first partial w.r.t. x\n    CPPAD_TESTVECTOR(double) dxy(n);\n    CPPAD_TESTVECTOR(double) dz(m);\n    dxy[0] = 1.;\n    dxy[1] = 0.;\n    dz    = f.Forward(1, dxy);\n    check = y * std::pow(x, y-1.);\n    ok   &= NearEqual(dz[0], check, eps99, eps99);\n    ok   &= NearEqual(dz[1], check, eps99, eps99);\n    ok   &= NearEqual(dz[2],    0., eps99, eps99);\n\n    // forward computation of first partial w.r.t. y\n    dxy[0] = 0.;\n    dxy[1] = 1.;\n    dz    = f.Forward(1, dxy);\n    check = std::log(x) * std::pow(x, y);\n    ok   &= NearEqual(dz[0], check, eps99, eps99);\n    ok   &= NearEqual(dz[1],    0., eps99, eps99);\n    ok   &= NearEqual(dz[2], check, eps99, eps99);\n\n    // reverse computation of derivative of z[0] + z[1] + z[2]\n    CPPAD_TESTVECTOR(double)  w(m);\n    CPPAD_TESTVECTOR(double) dw(n);\n    w[0]  = 1.;\n    w[1]  = 1.;\n    w[2]  = 1.;\n    dw    = f.Reverse(1, w);\n    check = y * std::pow(x, y-1.);\n    ok   &= NearEqual(dw[0], 2. * check, eps99, eps99);\n    check = std::log(x) * std::pow(x, y);\n    ok   &= NearEqual(dw[1], 2. * check, eps99, eps99);\n\n    // use a VecAD<Base>::reference object with pow\n    CppAD::VecAD<double> v(2);\n    AD<double> zero(0);\n    AD<double> one(1);\n    v[zero]           = XY[0];\n    v[one]            = XY[1];\n    AD<double> result = CppAD::pow(v[zero], v[one]);\n    ok               &= NearEqual(result, Z[0], eps99, eps99);\n\n    return ok;\n}\n\nbool PowTestTwo(void)\n{   bool ok = true;\n\n    using CppAD::pow;\n    using CppAD::exp;\n    using namespace CppAD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n\n    // independent variable vector, indices, values, and declaration\n    CPPAD_TESTVECTOR(AD<double>) U(2);\n    size_t s = 0;\n    size_t t = 1;\n    U[s]     = 2.;\n    U[t]     = 3.;\n    Independent(U);\n\n    // dependent variable vector and indices\n    CPPAD_TESTVECTOR(AD<double>) Z(2);\n    size_t x = 0;\n    size_t y = 1;\n\n\n    // dependent variable values\n    AD<double> u = exp(U[s]);        // u = exp(s)\n    Z[x]         = pow(u, U[t]);     // x = exp(s * t)\n    Z[y]         = pow(Z[x], u);     // y = exp( s * t * exp(s) )\n\n    // create f: U -> Z and vectors used for derivative calculations\n    ADFun<double> f(U, Z);\n    CPPAD_TESTVECTOR(double) v( f.Domain() );\n    CPPAD_TESTVECTOR(double) w( f.Range() );\n\n    /*\n    u_s  (s, t) = u\n    u_t  (s, t) = 0\n    y_s  (s, t) = (1 + s) t * u * y\n    y_t  (s, t) = s * u * y\n    y_st (s, t) = ( u + s * u ) * y\n                    + ( t * u + s * t * u ) * s * u * y\n    */\n\n    // check values\n    ok &= NearEqual(Z[x] , exp(2. * 3.), eps99, eps99);\n    ok &= NearEqual(Z[y] , exp( 2. * 3. * exp(2.) ), eps99, eps99);\n\n    // forward computation of partials w.r.t. s\n    v[s] = 1.;\n    v[t] = 0.;\n    w = f.Forward(1, v);\n    ok &= ( w[x] == U[t] * Z[x] );                   // dx/ds\n    ok &= ( w[y] == (1. + U[s]) * U[t] * u * Z[y] ); // dy/ds\n\n    // forward computation of partials w.r.t. t\n    v[s] = 0.;\n    v[t] = 1.;\n    w = f.Forward(1, v);\n    ok &= ( w[y] == U[s] * u * Z[y] );               // dy/dt\n\n    // forward computation of second Taylor coefficient w.r.t. t\n    v[t] = 1.;\n    w    = f.Forward(1, v);\n    v[t] = 0.;\n    CPPAD_TESTVECTOR(double) f_tt = f.Forward(2, v);\n\n    // forward computation of second Taylor coefficient w.r.t. s\n    v[s] = 1.;\n    w    = f.Forward(1, v);\n    v[s] = 0.;\n    CPPAD_TESTVECTOR(double) f_ss = f.Forward(2, v);\n\n    // second Taylor coefficient w.r.t. direction r = (s,t)\n    v[s] = 1.;\n    v[t] = 1.;\n    w    = f.Forward(1, v);\n    v[s] = 0.;\n    v[t] = 0.;\n    CPPAD_TESTVECTOR(double) f_rr = f.Forward(2, v);\n\n    // check second order partial of y\n    ok &= NearEqual(\n        f_rr[y] - f_ss[y] - f_tt[y],\n        (1. + U[s]) * u * Z[y] +\n            (1. + U[s]) * U[t] * u * U[s] * u * Z[y],\n        eps99 ,\n        eps99\n    );\n\n    return ok;\n}\n\nbool PowTestThree(void)\n{   bool ok = true;\n\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n  = 1;\n    CPPAD_TESTVECTOR(AD<double>) x(n);\n    x[0]      = 2.;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(x);\n\n    // range space vector\n    size_t m = 4;\n    CPPAD_TESTVECTOR(AD<double>) y(m);\n\n    // some special cases\n    y[0] = pow(x[0], 0.);\n    y[1] = pow(0., x[0]);\n    y[2] = pow(x[0], 1.);\n    y[3] = pow(1., x[0]);\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(x, y);\n\n    // check function values\n    ok  &= (Value(y[0]) == 1.);\n    ok  &= (Value(y[1]) == 0.);\n    ok  &= (Value(y[2]) == Value(x[0]));\n    ok  &= (Value(y[3]) == 1.);\n\n    // forward computation of first partial w.r.t. x\n    CPPAD_TESTVECTOR(double) dx(n);\n    CPPAD_TESTVECTOR(double) dy(m);\n    dx[0] = 1.;\n    dy    = f.Forward(1, dx);\n    ok   &= (dy[0] == 0.);\n    ok   &= (dy[1] == 0.);\n    ok   &= NearEqual(dy[2], 1., eps99, eps99);\n    ok   &= (dy[3] == 0.);\n\n    // reverse mode computation of derivative of y[0]+y[1]+y[2]+y[3]\n    CPPAD_TESTVECTOR(double)  w(m);\n    CPPAD_TESTVECTOR(double) dw(n);\n    w[0] = 1.;\n    w[1] = 1.;\n    w[2] = 1.;\n    w[3] = 1.;\n    dw   = f.Reverse(1, w);\n    ok  &= NearEqual(dw[0], 1., eps99, eps99);\n\n    return ok;\n}\n\nbool PowTestFour(void)\n{   bool ok = true;\n\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n  = 1;\n    double x0 = -2;\n    CPPAD_TESTVECTOR(AD<double>) x(n);\n    x[0]      = x0;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(x);\n\n    // range space vector\n    size_t m = 5;\n    CPPAD_TESTVECTOR(AD<double>) y(m);\n\n    // some special cases (skip zero raised to a negative power)\n    y[0] = pow(1., x[0]);\n    size_t i;\n    for(i = 1; i < m; i++)\n        y[i] = CppAD::pow(x[0], int(i-1) );   // pow(AD<double>, int)\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(x, y);\n\n    ok  &= (Value(y[0]) == 1.);\n    double check;\n    for(i = 1; i < m; i++)\n    {   check = std::pow(x0, double(i-1));\n        ok   &= NearEqual(y[i], check, eps99, eps99);\n    }\n\n    // forward computation of first partial w.r.t. x\n    CPPAD_TESTVECTOR(double) dx(n);\n    CPPAD_TESTVECTOR(double) dy(m);\n    dx[0] = 1.;\n    dy    = f.Forward(1, dx);\n    ok   &= (dy[0] == 0.);\n    double sum = 0;\n    for(i = 1; i < m; i++)\n    {   if( i == 1 )\n            check = 0.;\n        else\n            check = double(i-1) * std::pow(x0, double(i-2));\n        ok   &= NearEqual(dy[i], check, eps99, eps99);\n        sum  += check;\n    }\n\n    // reverse mode computation of derivative of y[0] + .. y[m-1];\n    CPPAD_TESTVECTOR(double)  w(m);\n    CPPAD_TESTVECTOR(double) dw(n);\n    for(i = 0; i < m; i++)\n        w[i] = 1.;\n    dw   = f.Reverse(1, w);\n    ok  &= NearEqual(dw[0], sum, eps99, eps99);\n\n    return ok;\n}\nbool PowTestFive(void)\n{   bool ok = true;\n\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n  = 1;\n    double x0 = -1.;\n    CPPAD_TESTVECTOR(AD<double>) x(n);\n    x[0]      = x0;\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(x);\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) y(m);\n\n    // case of zero raised to a positive integer power\n    double e = 2.;\n    y[0] = pow(x[0], int(e)); // use pow(AD<double>, int)\n\n    // create f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(x, y);\n\n    // check function value\n    ok  &= (Value(y[0]) == pow(x0, e) );\n\n    // forward computation of first partial w.r.t. x[1]\n    double d1 = e * pow(x0, (e-1));\n    CPPAD_TESTVECTOR(double) dx(n);\n    CPPAD_TESTVECTOR(double) dy(m);\n    dx[0] = 1.;\n    dy    = f.Forward(1, dx);\n    ok   &= NearEqual(dy[0], d1, eps99, eps99);\n\n    // reverse mode computation of second partials\n    // x.r.t. x[1],x[0]  and x[1], x[1]\n    double d2 = e * (e-1) * pow(x0, (e-2));\n    CPPAD_TESTVECTOR(double)   w(m);\n    CPPAD_TESTVECTOR(double) ddw(2*n);\n    w[0] = 1.;\n    ddw  = f.Reverse(2, w);\n    ok  &= NearEqual(ddw[0], d1, eps99, eps99);\n    ok  &= NearEqual(ddw[1], d2, eps99, eps99);\n\n    return ok;\n}\nbool PowTestSix(void)\n{   bool ok = true;\n\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n  = 1;\n    double x0 = 1.5;\n    CPPAD_TESTVECTOR(AD<double>) x(n);\n    x[0]      = x0;\n\n    // domain space vector\n    CPPAD_TESTVECTOR(AD< AD<double> >) X(n);\n    X[0]      = x[0];\n\n    // declare independent variables and start tape recording\n    CppAD::Independent(X);\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD< AD<double> >) Y(m);\n\n    // case of AD< AD<double> > raised to a double power\n    double e = 2.5;\n    Y[0] = pow(X[0], e);\n\n    // create F: X -> Y and stop tape recording\n    CppAD::ADFun< AD<double> > F(X, Y);\n\n    // check function value\n    ok  &= NearEqual(Value(Value(Y[0])), pow(x0, e), eps99, eps99);\n\n    // forward computation of first partial w.r.t. x[1]\n    double d1 = e * pow(x0, (e-1));\n    CPPAD_TESTVECTOR(AD<double>) dx(n);\n    CPPAD_TESTVECTOR(AD<double>) dy(m);\n    dx[0] = 1.;\n    dy    = F.Forward(1, dx);\n    ok   &= NearEqual(dy[0], d1, eps99, eps99);\n\n    // reverse mode computation of second partials\n    // x.r.t. x[1],x[0]  and x[1], x[1]\n    double d2 = e * (e-1) * pow(x0, (e-2));\n    CPPAD_TESTVECTOR(AD<double>)   w(m);\n    CPPAD_TESTVECTOR(AD<double>) ddw(2*n);\n    w[0] = 1.;\n    ddw  = F.Reverse(2, w);\n    ok  &= NearEqual(ddw[0], d1, eps99, eps99);\n    ok  &= NearEqual(ddw[1], d2, eps99, eps99);\n\n    return ok;\n}\n\n// Test x^e where x is negative and e is AD<double> equal to an integer\nbool PowTestEight(void)\n{   bool ok = true;\n\n    using std::cout;\n    using CppAD::AD;\n    using CppAD::vector;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    //\n    vector<double>      x(1), y(2), dx(1), dy(2), w(2), dw(2);\n    vector< AD<double> > ax(1), ay(2);\n    //\n    x[0]  = -2.0;\n    ax[0] = x[0];\n    //\n    CppAD::Independent(ax);\n    ay[0] = pow(ax[0],  2.0);\n    ay[1] = pow(ax[0], -2.0);\n    CppAD::ADFun<double> f(ax, ay);\n    f.check_for_nan(true);\n    //\n    double check;\n    y     = f.Forward(0, x);\n    check = x[0] * x[0];\n    ok   &= NearEqual(y[0], check, eps99, eps99);\n    check = 1.0 / (x[0] * x[0]);\n    ok   &= NearEqual(y[1], check, eps99, eps99);\n    //\n    dx[0] = 1.0;\n    dy    = f.Forward(1, dx);\n    check = 2.0 * x[0];\n    ok   &= NearEqual(dy[0], check, eps99, eps99);\n    check = -2.0 / ( x[0] * x[0] * x[0] );\n    ok   &= NearEqual(dy[1], check, eps99, eps99);\n    //\n    w[0]   = 1.0;\n    w[1]   = 0.0;\n    dw     = f.Reverse(2, w);\n    check  = 2.0 * x[0];\n    ok    &= NearEqual(dw[0], check, eps99, eps99);\n    check  = 2.0;\n    ok    &= NearEqual(dw[1], check, eps99, eps99);\n    //\n    w[0]   = 0.0;\n    w[1]   = 1.0;\n    dw     = f.Reverse(2, w);\n    check  = - 2.0 / (x[0] * x[0] * x[0]);\n    ok    &= NearEqual(dw[0], check, eps99, eps99);\n    check  = 6.0 / (x[0] * x[0] * x[0] * x[0]);\n    ok    &= NearEqual(dw[1], check, eps99, eps99);\n    //\n    return ok;\n}\n// k-th derivative of x^y .w.r.t. x\ndouble dpow_dx(double x, double y, size_t k)\n{   double result = std::pow(x, y - double(k));\n    for(size_t ell = 0; ell < k; ++ell)\n        result *= (y - double(ell));\n    return result;\n}\n// Testing PowvpOp\nbool PowTestNine(void)\n{   bool ok = true;\n    //\n    using std::cout;\n    using CppAD::AD;\n    using CppAD::vector;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    //\n    vector<double> x(1), dx(1);\n    vector<double> z(1), dz(1);\n    vector<double> w(1), dw(5);\n    vector< AD<double> > ax(1), az(1);\n    //\n    ax[0]    = 1.0;\n    double y = 2.5;\n    //\n    CppAD::Independent(ax);\n    az[0] = pow(ax[0], y);\n    CppAD::ADFun<double> f(ax, az);\n    //\n    double check;\n    //\n    // zero order forward\n    for(size_t ix = 0; ix < 3; ++ix)\n    {   x[0]  = double(ix);\n        z     = f.Forward(0, x);\n        check = dpow_dx(x[0], y, 0);\n        ok   &= NearEqual(z[0], check, eps99, eps99);\n        //\n        // first order forward\n        dx[0] = 1.0;\n        dz    = f.Forward(1, dx);\n        check = dpow_dx(x[0], y, 1);\n        ok   &= NearEqual(dz[0], check, eps99, eps99);\n        //\n        // ell-th order forward\n        double factorial = 1.0;\n        for(size_t k = 2; k < 5; ++k)\n        {   factorial *= double(k);\n            dx[0]      = 0.0; // x^(k)\n            dz         = f.Forward(k, dx);\n            check      = dpow_dx(x[0], y, k) / factorial;\n            ok        &= NearEqual(dz[0], check, eps99, eps99);\n        }\n        // second order reverse\n        w[0]  = 1.0;\n        dw    = f.Reverse(5, w);\n        factorial = 1.0;\n        for(size_t k = 0; k < 5; ++k)\n        {   check = dpow_dx(x[0], y, k+1) / factorial;\n            ok   &= NearEqual(dw[k], check, eps99, eps99);\n            factorial *= double(k+1);\n        }\n    }\n    //\n    return ok;\n}\n// Testing PowvpOp multiple direction forward\nbool PowTestTen(void)\n{   bool ok = true;\n    //\n    using std::cout;\n    using CppAD::AD;\n    using CppAD::vector;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    //\n    size_t n = 3;\n    vector<double> x(n), xq(n * n);\n    vector<double> z(n), zq(n * n);\n    vector<double> y(n);\n    vector< AD<double> > ax(n), az(n);\n    //\n    for(size_t j = 0; j < n; ++j)\n    {   ax[j] = double(j);\n        y[j]  = double(j) + 1.5;\n    }\n    //\n    CppAD::Independent(ax);\n    for(size_t j = 0; j < n; ++j)\n        az[j] = pow(ax[j], y[j]);\n    CppAD::ADFun<double> f(ax, az);\n    //\n    // zero order forward\n    for(size_t j = 0; j < n; ++j)\n        x[j]  = double(j) + 1.5;\n    z     = f.Forward(0, x);\n    double check;\n    for(size_t j = 0; j < n; ++j)\n    {   check = dpow_dx(x[j], y[j], 0);\n        ok   &= NearEqual(z[j], check, eps99, eps99);\n    }\n    //\n    // first order forward multiple directions\n    size_t r = n;\n    for(size_t j = 0; j < n; ++j)\n    {   for(size_t ell = 0; ell < r; ell++)\n        {   if( j == ell )\n                xq[ r * j + ell] = 1.0;\n            else\n                xq[ r * j + ell] = 0.0;\n        }\n    }\n    size_t q = 1;\n    zq = f.Forward(q, r, xq);\n    for(size_t j = 0; j < n; ++j)\n    {   for(size_t ell = 0; ell < r; ell++)\n        {   if( j == ell )\n                check = dpow_dx(x[j], y[j], 1);\n            else\n                check = 0.0;\n            ok   &= NearEqual(zq[r * j + ell], check, eps99, eps99);\n        }\n    }\n    //\n    // second order forward multiple directions\n    for(size_t j = 0; j < n; ++j)\n    {   for(size_t ell = 0; ell < r; ell++)\n                xq[ r * j + ell] = 0.0;\n    }\n    q = 2;\n    zq = f.Forward(q, r, xq);\n    for(size_t j = 0; j < n; ++j)\n    {   for(size_t ell = 0; ell < r; ell++)\n        {   if( j == ell )\n                check = dpow_dx(x[j], y[j], 2) / 2.0;\n            else\n                check = 0.0;\n            ok   &= NearEqual(zq[r * j + ell], check, eps99, eps99);\n        }\n    }\n    return ok;\n}\n\n} // END empty namespace\n\nbool Pow(void)\n{   bool ok = true;\n    ok     &= dynamic_zero();\n    ok     &= PowTestOne();\n    ok     &= PowTestTwo();\n    ok     &= PowTestThree();\n    ok     &= PowTestFour();\n    ok     &= PowTestFive();\n    ok     &= PowTestSix();\n    // PowTestSeven was removed\n    ok     &= PowTestEight();\n    ok     &= PowTestNine();\n    ok     &= PowTestTen();\n    //\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/pow_int.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\nOld example now just used for validation testing.\n*/\n\n# include <cppad/cppad.hpp>\n\nbool PowInt(void)\n{   bool ok = true;\n    using CppAD::pow;\n    using CppAD::exp;\n    using CppAD::log;\n    using namespace CppAD;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n\n    // independent variable vector, indices, values, and declaration\n    CPPAD_TESTVECTOR(AD<double>) U(1);\n    U[0]     = 2.;\n    Independent(U);\n\n    // dependent variable vector and indices\n    CPPAD_TESTVECTOR(AD<double>) Z(2);\n\n    // dependent variable values\n    Z[0]         = pow(U[0], 5);     // x = u^5\n    Z[1]         = pow(U[0], -5);    // y = u^{-5}\n\n    // create f: U -> Z and vectors used for derivative calculations\n    ADFun<double> f(U, Z);\n    CPPAD_TESTVECTOR(double) v( f.Domain() );\n    CPPAD_TESTVECTOR(double) w( f.Range() );\n\n    /*\n    x_u = 5 * u^4\n    y_u = - 5 * u^{-6}\n    */\n\n    // check function values values\n    double u = Value(U[0]);\n    ok &= NearEqual(Z[0] , exp( log(u) * 5.),              eps99 , eps99);\n    ok &= NearEqual(Z[1] , exp( - log(u) * 5.),            eps99 , eps99);\n\n    // forward computation of partials\n    v[0] = 1.;\n    w = f.Forward(1, v);\n    ok &= NearEqual(w[0] , 5. * exp( log(u) * 4.),         eps99 , eps99);\n    ok &= NearEqual(w[1] , - 5. * exp( - log(u) * 6.),     eps99 , eps99);\n\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/print_for.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n// modified version of test that used to be in ../example/print_for/print_for.cpp\n# include <cppad/cppad.hpp>\n\nnamespace {\n    using std::endl;\n    using CppAD::AD;\n\n    // use of PrintFor to check for invalid function arguments\n    AD<double> check_log(const AD<double>& y)\n    {   // check during recording\n        CPPAD_ASSERT_UNKNOWN( y > 0. );\n\n        // check during zero order forward calculation\n        PrintFor(y, \"check_log: y == \", y , \" which is <= 0\\n\");\n\n        return log(y);\n    }\n}\n\nbool print_for(void)\n{   bool ok = true;\n    using CppAD::PrintFor;\n\n    std::stringstream stream_out;   // stream that output is written to\n    std::string       string_check; // what we expect the output to be\n\n    // independent variable vector\n    size_t n = 1;\n    CPPAD_TESTVECTOR(AD<double>) ax(n);\n    ax[0] = 1.;\n    Independent(ax);\n\n    // print a VecAD<double>::reference object that is a parameter\n    CppAD::VecAD<double> av(1);\n    AD<double> Zero(0);\n    av[Zero] = 0.;\n    PrintFor(\"v[0] = \", av[Zero]);\n    string_check += \"v[0] = 0\"; // v[0] == 0 during Forward(0, x)\n\n    // Print a newline to separate this from previous output,\n    // then print an AD<double> object that is a variable.\n    PrintFor(\"\\nv[0] + x[0] = \", av[0] + ax[0]);\n    string_check += \"\\nv[0] + x[0] = 2\"; // x[0] == 2 during Forward(0, x)\n\n    // A conditional print that will not generate output when x[0] = 2.\n    PrintFor(ax[0], \"\\n  2. + x[0] = \",   2. + ax[0], \"\\n\");\n\n    // A conditional print that will generate output when x[0] = 2.\n    PrintFor(ax[0] - 2., \"\\n  3. + x[0] = \",   3. + ax[0], \"\\n\");\n    string_check += \"\\n  3. + x[0] = 5\\n\";\n\n    // A log evaluations that will result in an error message when x[0] = 2.\n    AD<double> var     = 2. - ax[0];\n    AD<double> log_var = check_log(var);\n    string_check += \"check_log: y == 0 which is <= 0\\n\";\n\n    // dependent variable vector\n    size_t m = 2;\n    CPPAD_TESTVECTOR(AD<double>) ay(m);\n    ay[0] = av[Zero] + ax[0];\n\n    // define f: x -> y and stop tape recording\n    CppAD::ADFun<double> f(ax, ay);\n\n    // zero order forward with x[0] = 2\n    CPPAD_TESTVECTOR(double) x(n);\n    x[0] = 2.;\n    f.Forward(0, x, stream_out);\n\n    std::string string_out = stream_out.str();\n    ok &= string_out == string_check;\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/rev_sparse_jac.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n\n# include <cppad/cppad.hpp>\n# include <vector>\n# include <valarray>\n\n# define CheckOp(Op)                   \\\n    Y[index] = X[0] Op 2.;         \\\n    Check[index * n + 0] = true;   \\\n    Check[index * n + 1] = false;  \\\n    Check[index * n + 2] = false;  \\\n    index++;                       \\\n    Y[index] = X[0] Op X[1];       \\\n    Check[index * n + 0] = true;   \\\n    Check[index * n + 1] = true;   \\\n    Check[index * n + 2] = false;  \\\n    index++;                       \\\n    Y[index] = 3.   Op X[1];       \\\n    Check[index * n + 0] = false;  \\\n    Check[index * n + 1] = true;   \\\n    Check[index * n + 2] = false;  \\\n    index++;\n\n# define CheckUnaryFun(Fun)            \\\n    Y[index] = Fun(X[0]);          \\\n    Check[index * n + 0] = true;   \\\n    Check[index * n + 1] = false;  \\\n    Check[index * n + 2] = false;  \\\n    index++;                       \\\n    Y[index] = Fun(X[0] + X[1]);   \\\n    Check[index * n + 0] = true;   \\\n    Check[index * n + 1] = true;   \\\n    Check[index * n + 2] = false;  \\\n    index++;                       \\\n    Y[index] = Fun(X[1]);          \\\n    Check[index * n + 0] = false;  \\\n    Check[index * n + 1] = true;   \\\n    Check[index * n + 2] = false;  \\\n    index++;\n\n\n# define CheckBinaryFun(Fun)           \\\n    Y[index] = Fun( X[0] , 2.);    \\\n    Check[index * n + 0] = true;   \\\n    Check[index * n + 1] = false;  \\\n    Check[index * n + 2] = false;  \\\n    index++;                       \\\n    Y[index] = Fun( X[0] , X[1]);  \\\n    Check[index * n + 0] = true;   \\\n    Check[index * n + 1] = true;   \\\n    Check[index * n + 2] = false;  \\\n    index++;                       \\\n    Y[index] = Fun( 3.   , X[1]);  \\\n    Check[index * n + 0] = false;  \\\n    Check[index * n + 1] = true;   \\\n    Check[index * n + 2] = false;  \\\n    index++;\n\nnamespace { // BEGIN empty namespace\n\nbool case_one()\n{   bool ok = true;\n    using namespace CppAD;\n\n    // dimension of the domain space\n    size_t n = 3;\n\n    // dimension of the range space\n    size_t m = (4 + 11 + 1) * 3 + 4;\n\n    // independent variable vector\n    CPPAD_TESTVECTOR(AD<double>) X(n);\n    X[0] = .1;\n    X[1] = .2;\n    X[2] = .3;\n    Independent(X);\n\n    // dependent variable vector\n    CPPAD_TESTVECTOR(AD<double>) Y(m);\n\n    // check results vector\n    CPPAD_TESTVECTOR( bool )       Check(m * n);\n\n    // initialize index into Y\n    size_t index = 0;\n\n    // 4 binary operators\n    CheckOp(+);\n    CheckOp(-);\n    CheckOp(*);\n    CheckOp(/);\n\n    // 11 unary functions\n    CheckUnaryFun(abs);\n    CheckUnaryFun(acos);\n    CheckUnaryFun(asin);\n    CheckUnaryFun(atan);\n    CheckUnaryFun(cos);\n    CheckUnaryFun(cosh);\n    CheckUnaryFun(exp);\n    CheckUnaryFun(log);\n    CheckUnaryFun(sin);\n    CheckUnaryFun(sinh);\n    CheckUnaryFun(sqrt);\n\n    // 1 binary function\n    CheckBinaryFun(pow);\n\n    // conditional expression\n    Y[index] = CondExpLt(X[0], X[1], X[0], AD<double>(2.));\n    Check[index * n + 0] = true;\n    Check[index * n + 1] = false;\n    Check[index * n + 2] = false;\n    index++;\n    Y[index] = CondExpLt(X[0], X[1], X[0], X[1]);\n    Check[index * n + 0] = true;\n    Check[index * n + 1] = true;\n    Check[index * n + 2] = false;\n    index++;\n    Y[index] = CondExpLt(X[0], X[1], AD<double>(3.), X[1]);\n    Check[index * n + 0] = false;\n    Check[index * n + 1] = true;\n    Check[index * n + 2] = false;\n    index++;\n\n    // non-trivial composition\n    Y[index] = Y[0] + Y[1] + X[2];\n    Check[index * n + 0] = true;\n    Check[index * n + 1] = true;\n    Check[index * n + 2] = true;\n    index++;\n\n    // check final index\n    assert( index == m );\n\n\n    // create function object F : X -> Y\n    ADFun<double> F(X, Y);\n\n    // --------------------------------------------------------\n    // dependency matrix for the identity function U(y) = y\n    CPPAD_TESTVECTOR( bool ) Py(m * m);\n    size_t i, j;\n    for(i = 0; i < m; i++)\n    {   for(j = 0; j < m; j++)\n            Py[ i * m + j ] = false;\n        Py[ i * m + i ] = true;\n    }\n\n    // evaluate the dependency matrix for F(x)\n    CPPAD_TESTVECTOR( bool ) Px(m * n);\n    Px = F.RevSparseJac(m, Py);\n\n    // check values\n    for(i = 0; i < m; i++)\n    {   for(j = 0; j < n; j++)\n            ok &= (Px[i * n + j] == Check[i * n + j]);\n    }\n    // --------------------------------------------------------\n    // dependency matrix for the identity function U(y) = y\n    CPPAD_TESTVECTOR(std::set<size_t>) Sy(m);\n    for(i = 0; i < m; i++)\n    {   assert( Sy[i].empty() );\n        Sy[i].insert(i);\n    }\n\n    // evaluate the dependency matrix for U(F(x))\n    CPPAD_TESTVECTOR(std::set<size_t>) Sx(m);\n    Sx = F.RevSparseJac(m, Sy);\n\n    // check values\n    std::set<size_t>::iterator itr;\n    bool found;\n    for(i = 0; i < m; i++)\n    {   for(j = 0; j < n; j++)\n        {   found = Sx[i].find(j) != Sx[i].end();\n            ok    &= (found == Check[i * n + j]);\n        }\n    }\n\n    return ok;\n}\n\nbool case_two()\n{   bool ok = true;\n    using namespace CppAD;\n\n    // dimension of the domain space\n    size_t n = 3;\n\n    // dimension of the range space\n    size_t m = 3;\n\n    // initialize the vector as zero\n    CppAD::VecAD<double> Z(n - 1);\n    size_t k;\n    for(k = 0; k < n-1; k++)\n        Z[k] = 0.;\n\n    // independent variable vector\n    CPPAD_TESTVECTOR(AD<double>) X(n);\n    X[0] = 0.;\n    X[1] = 1.;\n    X[2] = 2.;\n    Independent(X);\n\n    // VecAD vector is going to depend on X[1] and X[2]\n    Z[ X[0] ] = X[1];\n    Z[ X[1] ] = X[2];\n\n    // dependent variable vector\n    CPPAD_TESTVECTOR(AD<double>) Y(m);\n\n    // check results vector\n    CPPAD_TESTVECTOR( bool )       Check(m * n);\n\n    // initialize index into Y\n    size_t index = 0;\n\n    // First component only depends on X[0];\n    Y[index]             = X[0];\n    Check[index * n + 0] = true;\n    Check[index * n + 1] = false;\n    Check[index * n + 2] = false;\n    index++;\n\n    // Second component depends on the vector Z\n    AD<double> zero(0);\n    Y[index]             = Z[zero]; // Load by a parameter\n    Check[index * n + 0] = false;\n    Check[index * n + 1] = true;\n    Check[index * n + 2] = true;\n    index++;\n\n    // Third component depends on the vector Z\n    Y[index]             = Z[ X[0] ]; // Load by a variable\n    Check[index * n + 0] = false;\n    Check[index * n + 1] = true;\n    Check[index * n + 2] = true;\n    index++;\n\n    // check final index\n    assert( index == m );\n\n    // create function object F : X -> Y\n    ADFun<double> F(X, Y);\n\n    // dependency matrix for the identity function S(y) = y\n    CPPAD_TESTVECTOR( bool ) Py(m * m);\n    size_t i, j;\n    for(i = 0; i < m; i++)\n    {   for(j = 0; j < m; j++)\n            Py[ i * m + j ] = false;\n        Py[ i * m + i ] = true;\n    }\n\n    // evaluate the dependency matrix for S [ F(x) ]\n    CPPAD_TESTVECTOR( bool ) Px(m * n);\n    Px = F.RevSparseJac(m, Py);\n\n    // check values\n    for(i = 0; i < m; i++)\n    {   for(j = 0; j < n; j++)\n            ok &= (Px[i * n + j] == Check[i * n + j]);\n    }\n    // --------------------------------------------------------\n    // dependency matrix for the identity function U(y) = y\n    CPPAD_TESTVECTOR(std::set<size_t>) Sy(m);\n    for(i = 0; i < m; i++)\n    {   assert( Sy[i].empty() );\n        Sy[i].insert(i);\n    }\n\n    // evaluate the dependency matrix for U(F(x))\n    CPPAD_TESTVECTOR(std::set<size_t>) Sx(m);\n    Sx = F.RevSparseJac(m, Sy);\n\n    // check values\n    std::set<size_t>::iterator itr;\n    bool found;\n    for(i = 0; i < m; i++)\n    {   for(j = 0; j < n; j++)\n        {   found = Sx[i].find(j) != Sx[i].end();\n            ok    &= (found == Check[i * n + j]);\n        }\n    }\n\n    return ok;\n}\n\nbool case_three()\n{   bool ok = true;\n    using namespace CppAD;\n\n    // dimension of the domain space\n    size_t n = 2;\n\n    // dimension of the range space\n    size_t m = 3;\n\n    // independent variable vector\n    CPPAD_TESTVECTOR(AD<double>) X(n);\n    X[0] = 2.;\n    X[1] = 3.;\n    Independent(X);\n\n    // dependent variable vector\n    CPPAD_TESTVECTOR(AD<double>) Y(m);\n\n    // check results vector\n    CPPAD_TESTVECTOR( bool )       Check(m * n);\n\n    // initialize index into Y\n    size_t index = 0;\n\n    // Y[0] only depends on X[0];\n    Y[index]             = pow(X[0], 2.);\n    Check[index * n + 0] = true;\n    Check[index * n + 1] = false;\n    index++;\n\n    // Y[1] depends on X[1]\n    Y[index]             = pow(2., X[1]);\n    Check[index * n + 0] = false;\n    Check[index * n + 1] = true;\n    index++;\n\n    // Y[2] depends on X[0] and X[1]\n    Y[index]             = pow(X[0], X[1]);\n    Check[index * n + 0] = true;\n    Check[index * n + 1] = true;\n    index++;\n\n    // check final index\n    assert( index == m );\n\n    // create function object F : X -> Y\n    ADFun<double> F(X, Y);\n\n    // -----------------------------------------------------------------\n    // dependency matrix for the identity function\n    CPPAD_TESTVECTOR( bool ) Py(m * m);\n    size_t i, j;\n    for(i = 0; i < m; i++)\n    {   for(j = 0; j < m; j++)\n            Py[ i * m + j ] = (i == j);\n    }\n\n    // evaluate the dependency matrix for F(x)\n    CPPAD_TESTVECTOR( bool ) Px(m * n);\n    Px = F.RevSparseJac(m, Py);\n\n    // check values\n    for(i = 0; i < m; i++)\n    {   for(j = 0; j < n; j++)\n            ok &= (Px[i * n + j] == Check[i * n + j]);\n    }\n\n    // ---------------------------------------------------------\n    // dependency matrix for the identity function\n    CPPAD_TESTVECTOR(std::set<size_t>) Sy(m);\n    for(i = 0; i < m; i++)\n    {   assert( Sy[i].empty() );\n        Sy[i].insert(i);\n    }\n\n    // evaluate the dependency matrix for F(x)\n    CPPAD_TESTVECTOR(std::set<size_t>) Sx(m);\n    Sx = F.RevSparseJac(m, Sy);\n\n    // check values\n    bool found;\n    for(i = 0; i < m; i++)\n    {   for(j = 0; j < n; j++)\n        {   found = Sx[i].find(j) != Sx[i].end();\n            ok &= (found == Check[i * n + j]);\n        }\n    }\n\n    return ok;\n}\n\n\n// case where s is not identity matrix\nbool case_four()\n{\n    bool ok = true;\n    using namespace CppAD;\n\n    // dimension of the domain space\n    size_t n = 2;\n\n    // dimension of the range space\n    size_t m = n;\n\n    // independent and variable vectors\n    CPPAD_TESTVECTOR(AD<double>) ax(n), ay(m);\n    ax[0] = 2.;\n    ax[1] = 3.;\n    Independent(ax);\n    ay[0] = ax[1];\n    ay[1] = ax[0];\n\n    // create function object F : x -> y\n    ADFun<double> F(ax, ay);\n\n    // evaluate the dependency matrix for F(x)\n    size_t q = 1;\n    CPPAD_TESTVECTOR( bool ) s(q * m), r(q * n);\n    s[0] = true;\n    s[1] = false;\n    r = F.RevSparseJac(q, s);\n\n    ok &= size_t( r.size() ) == q * n;\n    ok &= r[0] == false;\n    ok &= r[1] == true;\n\n    return ok;\n}\n\nbool case_five()\n{   bool ok = true;\n    using namespace CppAD;\n\n    // dimension of the domain space\n    size_t n = 2;\n\n    // dimension of the range space\n    size_t m = 3;\n\n    // independent variable vector\n    CPPAD_TESTVECTOR(AD<double>) X(n);\n    X[0] = 2.;\n    X[1] = 3.;\n    Independent(X);\n\n    // dependent variable vector\n    CPPAD_TESTVECTOR(AD<double>) Y(m);\n\n    // check results vector\n    CPPAD_TESTVECTOR( bool )       Check(m * n);\n\n    // initialize index into Y\n    size_t index = 0;\n\n    // Y[0] only depends on X[0];\n    Y[index]             = pow(X[0], 2.);\n    Check[index * n + 0] = true;\n    Check[index * n + 1] = false;\n    index++;\n\n    // Y[1] depends on X[1]\n    Y[index]             = pow(2., X[1]);\n    Check[index * n + 0] = false;\n    Check[index * n + 1] = true;\n    index++;\n\n    // Y[2] depends on X[0] and X[1]\n    Y[index]             = pow(X[0], X[1]);\n    Check[index * n + 0] = true;\n    Check[index * n + 1] = true;\n    index++;\n\n    // check final index\n    assert( index == m );\n\n    // create function object F : X -> Y\n    ADFun<double> F(X, Y);\n\n    // -----------------------------------------------------------------\n    // dependency matrix for the identity function\n    CPPAD_TESTVECTOR( bool ) Py(m * m);\n    size_t i, j;\n    for(i = 0; i < m; i++)\n    {   for(j = 0; j < m; j++)\n            Py[ i * m + j ] = (i == j);\n    }\n\n    // evaluate the dependency matrix for F(x)\n    bool transpose = true;\n    CPPAD_TESTVECTOR( bool ) Px(n * m);\n    Px = F.RevSparseJac(m, Py, transpose);\n\n    // check values\n    for(i = 0; i < m; i++)\n    {   for(j = 0; j < n; j++)\n            ok &= (Px[j * m + i] == Check[i * n + j]);\n    }\n\n    // ---------------------------------------------------------\n    // dependency matrix for the identity function\n    CPPAD_TESTVECTOR(std::set<size_t>) Sy(m);\n    for(i = 0; i < m; i++)\n    {   assert( Sy[i].empty() );\n        Sy[i].insert(i);\n    }\n\n    // evaluate the dependency matrix for F(x)\n    CPPAD_TESTVECTOR(std::set<size_t>) Sx(n);\n    Sx = F.RevSparseJac(m, Sy, transpose);\n\n    // check values\n    bool found;\n    for(i = 0; i < m; i++)\n    {   for(j = 0; j < n; j++)\n        {   found = Sx[j].find(i) != Sx[j].end();\n            ok &= (found == Check[i * n + j]);\n        }\n    }\n\n    return ok;\n}\n\n\n\n} // END empty namespace\n\nbool rev_sparse_jac(void)\n{   bool ok = true;\n\n    ok &= case_one();\n    ok &= case_two();\n    ok &= case_three();\n    ok &= case_four();\n    ok &= case_five();\n\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/rev_two.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/cppad.hpp>\n\nbool RevTwo()\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::vector;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n\n    size_t n = 2;\n    vector< AD<double> > X(n);\n    X[0] = 1.;\n    X[1] = 1.;\n    Independent(X);\n\n    size_t m = 1;\n    vector< AD<double> > Y(m);\n    Y[0] = X[0] * X[0] + X[0] * X[1] + 2. * X[1] * X[1];\n    CppAD::ADFun<double> F(X,Y);\n\n    vector<double> x(n);\n    x[0] = .5;\n    x[1] = 1.5;\n\n    size_t L = 1;\n    vector<size_t> I(L);\n    vector<size_t> J(L);\n    vector<double> H(n);\n    I[0] = 0;\n    J[0] = 0;\n    H    = F.RevTwo(x, I, J);\n    ok  &= NearEqual(H[0], 2., eps99, eps99);\n    ok  &= NearEqual(H[1], 1., eps99, eps99);\n    J[0] = 1;\n    H    = F.RevTwo(x, I, J);\n    ok  &= NearEqual(H[0], 1., eps99, eps99);\n    ok  &= NearEqual(H[1], 4., eps99, eps99);\n\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/reverse.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\nOld Reverse example now used just for valiadation testing\n*/\n\n# include <cppad/cppad.hpp>\nnamespace { // ----------------------------------------------------------\n\nbool reverse_one(void)\n{   bool ok = true;\n    using namespace CppAD;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // independent variable vector\n    CPPAD_TESTVECTOR(AD<double>) U(3);\n    U[0] = 0.; U[1] = 1.; U[2] = 2.;\n    Independent(U);\n\n    // compute sum and product of elements in U\n    AD<double> Sum  = 0.;\n    AD<double> Prod = 1.;\n    size_t i;\n    for(i = 0; i < 3; i++)\n    {   Sum  += U[i];\n        Prod *= U[i];\n    }\n\n    // dependent variable vector\n    CPPAD_TESTVECTOR(AD<double>) V(2);\n    V[0] = Sum;\n    V[1] = Prod;\n\n    // V = f(U)\n    ADFun<double> f(U, V);\n\n    // Evaluate ( v[0] * f_0 + v[1] * f_1 )^(1) [ u0 ] ---------------\n    size_t p  = 1;\n    CPPAD_TESTVECTOR(double) v( f.Range() );\n    CPPAD_TESTVECTOR(double) u0( f.Domain() );\n    CPPAD_TESTVECTOR(double) r1( f.Domain() * p );\n\n    v[0]  = 1.; v[1] = -1.;\n    r1    = f.Reverse(p, v);\n\n    // direct evaluation of gradients of components of f\n    CPPAD_TESTVECTOR(double) g0(3), g1(3);\n    u0[0] = Value(U[0]); u0[1] = Value(U[1]); u0[2] = Value(U[2]);\n    g0[0] =          1.; g0[1] =          1.; g0[2] =          1.;\n    g1[0] = u0[1]*u0[2]; g1[1] = u0[0]*u0[2]; g1[2] = u0[0]*u0[1];\n\n    // compare values\n    for(i = 0; i < 3; i++)\n    {   ok &= NearEqual(r1[i] ,\n            v[0] * g0[i] + v[1] * g1[i], eps99, eps99);\n    }\n\n    // -------------------------------------------------------------------\n\n    // Define the function z(t, u0, u1) = f( u0 + u1 * t ) and evaluate\n    // the first order Taylor coefficient column vector z(*, u0, u1)\n    p = 1;\n    CPPAD_TESTVECTOR(double) u1( f.Domain() );\n\n    u1[0] = 2.; u1[1] = -1.; u1[2] = 3.;\n    f.Forward(p, u1);\n\n    // Evaluate the derivatives with respect to u0 of the functions\n    // order 0: v[0] *      z_0 (0, u0, u1) + v[1] *      z_1 (0, u0, u1)\n    // order 1: v[0] * d/dt z_0 (0, u0, u1) + v[1] * d/dt z_1 (0, u0, u1)\n    p    = 2;\n    CPPAD_TESTVECTOR(double) r2( f.Domain() * p );\n    v[0] = -.5; v[1] = .5;\n    r2   = f.Reverse(p, v);\n\n    // check derivative of the zero order term\n    for(i = 0; i < 3; i++)\n    {   ok &= NearEqual(r2[p * i + 0] ,\n            v[0] * g0[i] + v[1] * g1[i], eps99, eps99);\n    }\n\n    /*\n    The j-th component of the first order term is\n        d/dt z_j(0, u0, u1) = f_j^{(1)} (u0) * u1\n    We use ei to denote the vector with its i-th component one and all\n    the other components zero. The partial derivative of the j-th\n    component of the first order term with respect u0[i] is\n        ei * f_j^{(2)} ( u0 ) * u1\n    */\n\n\n    // direct evaluation of the Hessian f_1^{(2)} (u0)\n    // (the Hessian f_0^{(2)} is identically zero)\n    CPPAD_TESTVECTOR(double) H1(9);\n    H1[0] =    0.; H1[1] = u0[2]; H1[2] = u0[1];\n    H1[3] = u0[2]; H1[4] =    0.; H1[5] = u0[0];\n    H1[6] = u0[1]; H1[7] = u0[0]; H1[8] =    0.;\n\n\n    size_t j;\n    for(i = 0; i < 3; i++)\n    {   double sum = 0.;\n        for(j = 0; j < 3; j++)\n            sum += H1[i * 3 + j] * u1[j];\n\n        // note term corresponding to v[0] is zero\n        ok &= NearEqual(r2[p * i + 1], v[1] * sum, eps99, eps99);\n    }\n\n    return ok;\n}\n\n// define the template function reverse_any_cases<Vector> in empty namespace\ntemplate <class Vector>\nbool reverse_any_cases(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n = 3;\n    CPPAD_TESTVECTOR(AD<double>) X(n);\n    X[0] = 0.;\n    X[1] = 1.;\n    X[2] = 2.;\n\n    // declare independent variables and start recording\n    CppAD::Independent(X);\n\n    // range space vector\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) Y(m);\n    Y[0] = X[0] * X[1] * X[2];\n\n    // create f : X -> Y and stop recording\n    CppAD::ADFun<double> f(X, Y);\n\n    // define W(t, u) = (u_0 + dx_0*t)*(u_1 + dx_1*t)*(u_2 + dx_2*t)\n    // use zero order forward to evaluate W0(u) = W(0, u)\n    Vector u(n), W0(m);\n    u[0]    = 2.;\n    u[1]    = 3.;\n    u[2]    = 4.;\n    W0      = f.Forward(0, u);\n    double check;\n    check   =  u[0]*u[1]*u[2];\n    ok     &= NearEqual(W0[0] , check, eps99, eps99);\n\n    // define W_t(t, u) = partial W(t, u) w.r.t t\n    // W_t(t, u)  = (u_0 + dx_0*t)*(u_1 + dx_1*t)*dx_2\n    //            + (u_0 + dx_0*t)*(u_2 + dx_2*t)*dx_1\n    //            + (u_1 + dx_1*t)*(u_2 + dx_2*t)*dx_0\n    // use first order forward mode to evaluate W1(u) = W_t(0, u)\n    Vector dx(n), W1(m);\n    dx[0] = .2;\n    dx[1] = .3;\n    dx[2] = .4;\n    W1    = f.Forward(1, dx);\n        check =  u[0]*u[1]*dx[2] + u[0]*u[2]*dx[1] + u[1]*u[2]*dx[0];\n    ok   &= NearEqual(W1[0], check, eps99, eps99);\n\n    // define W_tt (t, u) = partial W_t(t, u) w.r.t t\n    // W_tt(t, u) = 2*(u_0 + dx_0*t)*dx_1*dx_2\n    //            + 2*(u_1 + dx_1*t)*dx_0*dx_2\n    //            + 2*(u_3 + dx_3*t)*dx_0*dx_1\n    // use second order forward to evaluate W2(u) = 1/2 * W_tt(0, u)\n    Vector ddx(n), W2(m);\n    ddx[0] = ddx[1] = ddx[2] = 0.;\n        W2     = f.Forward(2, ddx);\n        check  =  u[0]*dx[1]*dx[2] + u[1]*dx[0]*dx[2] + u[2]*dx[0]*dx[1];\n    ok    &= NearEqual(W2[0], check, eps99, eps99);\n\n    // use third order reverse mode to evaluate derivatives\n    size_t p = 3;\n    Vector w(m), dw(n * p);\n    w[0]   = 1.;\n    dw     = f.Reverse(p, w);\n\n    // check derivative of W0(u) w.r.t. u\n    ok    &= NearEqual(dw[0*p+0], u[1]*u[2], eps99, eps99);\n    ok    &= NearEqual(dw[1*p+0], u[0]*u[2], eps99, eps99);\n    ok    &= NearEqual(dw[2*p+0], u[0]*u[1], eps99, eps99);\n\n    // check derivative of W1(u) w.r.t. u\n    ok    &= NearEqual(dw[0*p+1], u[1]*dx[2] + u[2]*dx[1], eps99, eps99);\n    ok    &= NearEqual(dw[1*p+1], u[0]*dx[2] + u[2]*dx[0], eps99, eps99);\n    ok    &= NearEqual(dw[2*p+1], u[0]*dx[1] + u[1]*dx[0], eps99, eps99);\n\n    // check derivative of W2(u) w.r.t u\n    ok    &= NearEqual(dw[0*p+2], dx[1]*dx[2], eps99, eps99);\n    ok    &= NearEqual(dw[1*p+2], dx[0]*dx[2], eps99, eps99);\n    ok    &= NearEqual(dw[2*p+2], dx[0]*dx[1], eps99, eps99);\n\n    return ok;\n}\n/*\n$comment rev_checkpoint.cpp$$\n$spell\n    Taylor\n$$\n\n$section Reverse Mode General Case: Example and Test$$\n\n$index general, reverse example$$\n$index reverse, general example$$\n$index example, general reverse$$\n$index test, general reverse$$\n\n$index composition, example$$\n$index example, composition$$\n$index test, composition$$\n\n$head Purpose$$\nBreak a derivative computation into pieces and only store values at the\ninterface of the pieces.\nIn actual applications, there may be many functions, but\nfor this example there are only two.\nThe functions\n$latex F : \\B{R}^2 \\rightarrow \\B{R}^2$$\nand\n$latex G : \\B{R}^2 \\rightarrow \\B{R}^2$$\ndefined by\n$latex \\[\n    F(x) = \\left( \\begin{array}{c} x_0 x_1   \\\\ x_1 - x_0 \\end{array} \\right)\n    \\; , \\;\n    G(y) = \\left( \\begin{array}{c} y_0 - y_1 \\\\ y_1  y_0   \\end{array} \\right)\n\\] $$\nAnother difference is that in actual applications,\nthe memory corresponding to function objects not currently being used\nis sometimes returned to the system (see $cref/checkpoint/chkpoint_one/.cpp$$).\n\n$head Processing Steps$$\nWe apply reverse mode to compute the derivative of\n$latex H : \\B{R}^2 \\rightarrow \\B{R}$$\nis defined by\n$latex \\[\n\\begin{array}{rcl}\n    H(x)\n    & = & G_0 [ F(x) ] + G_1 [ F(x)  ]\n    \\\\\n    & = & x_0 x_1 - ( x_1 - x_0 ) + x_0 x_1 ( x_1 - x_0 )\n    \\\\\n    & = & x_0 x_1 ( 1 - x_0 + x_1 ) - x_1 + x_0\n\\end{array}\n\\] $$\nGiven the zero and first order Taylor coefficients\n$latex x^{(0)} $$ and $latex x^{(1)}$$,\nwe use $latex X(t)$$, $latex Y(t)$$ and $latex Z(t)$$\nfor the corresponding functions; i.e.,\n$latex \\[\n\\begin{array}{rcl}\n    X(t) & = & x^{(0)} + x^{(1)} t\n    \\\\\n    Y(t) & = & F[X(t)] = y^{(0)} + y^{(1)} t  + O(t^2)\n    \\\\\n    Z(t) & = & G \\{ F [ X(t) ] \\} = z^{(0)} + z^{(1)} t  + O(t^2)\n    \\\\\n    h^{(0)} & = & z^{(0)}_0 + z^{(0)}_1\n    \\\\\n    h^{(1)} & = & z^{(1)}_0 + z^{(1)}_1\n\\end{array}\n\\] $$\nHere are the processing steps:\n$list number$$\nUse forward mode on $latex F(x)$$ to compute\n$latex y^{(0)}$$ and $latex y^{(1)}$$\n$lnext\nUse forward mode on $latex G(y)$$ to compute\n$latex z^{(0)}$$ and $latex z^{(1)}$$\n$lnext\nUse reverse mode on $latex G(y)$$ to compute the derivative of\n$latex h^{(k)}$$ with respect to\n$latex y^{(0)}$$ and $latex y^{(1)}$$.\n$lnext\nUse reverse mode on $latex F(x)$$ to compute the derivative of\n$latex h^{(k)}$$ with respect to\n$latex x^{(0)}$$ and $latex x^{(1)}$$.\n$lend\nThis uses the following relations for $latex k = 0 , 1$$:\n$latex \\[\n\\begin{array}{rcl}\n    \\partial_{x(0)} h^{(k)} [ x^{(0)} , x^{(1)} ]\n    & = &\n    \\partial_{y(0)} h^{(k)} [ y^{(0)} , y^{(1)} ]\n    \\partial_{x(0)} y^{(0)} [ x^{(0)} , x^{(1)} ]\n    \\\\\n    & + &\n    \\partial_{y(1)} h^{(k)} [ y^{(0)} , y^{(1)} ]\n    \\partial_{x(0)} y^{(1)} [ x^{(0)} , x^{(1)} ]\n    \\\\\n    \\partial_{x(1)} h^{(k)} [ x^{(0)} , x^{(1)} ]\n    & = &\n    \\partial_{y(0)} h^{(k)} [ y^{(0)} , y^{(1)} ]\n    \\partial_{x(1)} y^{(0)} [ x^{(0)} , x^{(1)} ]\n    \\\\\n    & + &\n    \\partial_{y(1)} h^{(k)} [ y^{(0)} , y^{(1)} ]\n    \\partial_{x(1)} y^{(1)} [ x^{(0)} , x^{(1)} ]\n\\end{array}\n\\] $$\nwhere $latex \\partial_{x(0)}$$ denotes the partial with respect\nto $latex x^{(0)}$$.\n\n$end\n*/\ntemplate <class Vector>\nVector F_reverse_mul(const Vector& x)\n{   Vector y(2);\n    y[0] = x[0] * x[1];\n    y[1] = x[1] - x[0];\n    return y;\n}\ntemplate <class Vector>\nVector G_reverse_mul(const Vector& y)\n{   Vector z(2);\n    z[0] = y[0] - y[1];\n    z[1] = y[1] * y[0];\n    return z;\n}\nbool reverse_mul(void)\n{\n    bool ok = true;\n    double eps = 10. * CppAD::numeric_limits<double>::epsilon();\n\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    CppAD::ADFun<double> f, g;\n\n    // Record the function F(x)\n    size_t n    = 2;\n    CPPAD_TESTVECTOR(AD<double>) X(n), Y(n);\n    X[0] = X[1] = 0.;\n    CppAD::Independent(X);\n    Y = F_reverse_mul(X);\n    f.Dependent(X, Y);\n\n    // Record the function G(x)\n    CPPAD_TESTVECTOR(AD<double>) Z(n);\n    Y[0] = Y[1] = 0.;\n    CppAD::Independent(Y);\n    Z = G_reverse_mul(Y);\n    g.Dependent(Y, Z);\n\n    // argument and function values\n    CPPAD_TESTVECTOR(double) x0(n), y0(n), z0(n);\n    x0[0] = 1.;\n    x0[1] = 2.;\n    y0    = f.Forward(0, x0);\n    z0    = g.Forward(0, y0);\n\n    // check function value\n    double check = x0[0] * x0[1] * (1. - x0[0] + x0[1]) - x0[1] + x0[0];\n    double h0    = z0[0] + z0[1];\n    ok          &= NearEqual(h0, check, eps, eps);\n\n    // first order Taylor coefficients\n    CPPAD_TESTVECTOR(double) x1(n), y1(n), z1(n);\n    x1[0] = 3.;\n    x1[1] = 4.;\n    y1    = f.Forward(1, x1);\n    z1    = g.Forward(1, y1);\n\n    // check first order Taylor coefficients\n    check     = x0[0] * x0[1] * (- x1[0] + x1[1]) - x1[1] + x1[0];\n    check    += x1[0] * x0[1] * (1. - x0[0] + x0[1]);\n    check    += x0[0] * x1[1] * (1. - x0[0] + x0[1]);\n    double h1 = z1[0] + z1[1];\n    ok       &= NearEqual(h1, check, eps, eps);\n\n    // ----------------------------------------------------------------\n    // dw^0 (y) = \\partial_y^0 h^0 (y)\n    // dw^1 (y) = \\partial_y^1 h^0 (y)\n    size_t p = 2;\n    CPPAD_TESTVECTOR(double) w(n*p), dw(n*p);\n    w[0*p+0] = 1.; // coefficient for z^0_0\n    w[1*p+0] = 1.; // coefficient for z^0_1\n    w[0*p+1] = 0.; // coefficient for z^1_0\n    w[1*p+1] = 0.; // coefficient for z^1_1\n    dw       = g.Reverse(p, w);\n\n    // dv^0 = dw^0 * \\partial_x^0 y^0 (x) + dw^1 * \\partial_x^0 y^1 (x)\n    // dv^1 = dw^0 * \\partial_x^1 y^0 (x) + dw^1 * \\partial_x^1 y^1 (x)\n    CPPAD_TESTVECTOR(double) dv(n*p);\n    dv   = f.Reverse(p, dw);\n\n    // check partial of h^0 w.r.t x^0_0\n    check  = x0[1] * (1. - x0[0] + x0[1]) + 1.;\n    check -= x0[0] * x0[1];\n    ok    &= NearEqual(dv[0*p+0], check, eps, eps);\n\n    // check partial of h^0 w.r.t x^0_1\n    check  = x0[0] * (1. - x0[0] + x0[1]) - 1.;\n    check += x0[0] * x0[1];\n    ok    &= NearEqual(dv[1*p+0], check, eps, eps);\n\n    // check partial of h^0 w.r.t x^1_0 and x^1_1\n    check  = 0.;\n    ok    &= NearEqual(dv[0*p+1], check, eps, eps);\n    ok    &= NearEqual(dv[1*p+1], check, eps, eps);\n\n    // ----------------------------------------------------------------\n    // dw^0 (y) = \\partial_y^0 h^1 (y)\n    // dw^1 (y) = \\partial_y^1 h^1 (y)\n    w[0*p+0] = 0.; // coefficient for z^0_0\n    w[1*p+0] = 0.; // coefficient for z^0_1\n    w[0*p+1] = 1.; // coefficient for z^1_0\n    w[1*p+1] = 1.; // coefficient for z^1_1\n    dw       = g.Reverse(p, w);\n\n    // dv^0 = dw^0 * \\partial_x^0 y^0 (x) + dw^1 * \\partial_x^0 y^1 (x)\n    // dv^1 = dw^0 * \\partial_x^1 y^0 (x) + dw^1 * \\partial_x^1 y^1 (x)\n    dv   = f.Reverse(p, dw);\n\n    // check partial of h^1 w.r.t x^0_0\n    check  = x0[1] * (- x1[0] + x1[1]);\n    check -= x1[0] * x0[1];\n    check += x1[1] * (1. - x0[0] + x0[1]) - x0[0] * x1[1];\n    ok    &= NearEqual(dv[0*p+0], check, eps, eps);\n\n    // check partial of h^1 w.r.t x^0_1\n    check  = x0[0] * (- x1[0] + x1[1]);\n    check += x1[0] * (1. - x0[0] + x0[1]) + x1[0] * x0[1];\n    check += x0[0] * x1[1];\n    ok    &= NearEqual(dv[1*p+0], check, eps, eps);\n\n    // check partial of h^1 w.r.t x^1_0\n    // (by reverse mode identity is equal to partial h^0 w.r.t. x^0_0)\n    check  = 1. - x0[0] * x0[1];\n    check += x0[1] * (1. - x0[0] + x0[1]);\n    ok    &= NearEqual(dv[0*p+1], check, eps, eps);\n\n    // check partial of h^1 w.r.t x^1_1\n    // (by reverse mode identity is equal to partial h^0 w.r.t. x^0_1)\n    check  = x0[0] * x0[1] - 1.;\n    check += x0[0] * (1. - x0[0] + x0[1]);\n    ok    &= NearEqual(dv[1*p+1], check, eps, eps);\n\n    return ok;\n}\n// ----------------------------------------------------------------------------\nbool duplicate_dependent_var(void)\n{   bool ok = true;\n    using CppAD::AD;\n\n    // f(x) = [ y_0, y_1 ] = [ x_0 * x_0 , x_0 * x_0 ]\n    size_t nx = 1;\n    size_t ny = 2;\n    CPPAD_TESTVECTOR( AD<double> ) ax(nx), ay(ny);\n    ax[0] = 1.0;\n    CppAD::Independent(ax);\n    ay[0] = ax[0] * ax[0];\n    ay[1] = ay[0];\n    CppAD::ADFun<double> f(ax, ay);\n    //\n    // Forward zero\n    CPPAD_TESTVECTOR(double) x0(nx), x1(nx), yk(ny);\n    x0[0] = 3.0;\n    yk = f.Forward(0, x0);\n    ok &= yk[0] == x0[0] * x0[0];\n    ok &= yk[1] == yk[0];\n    //\n    // Forward one\n    x1[0] = 1.0;\n    yk = f.Forward(1, x1);\n    ok &= yk[0] == 2.0 * x0[0];\n    ok &= yk[1] == yk[0];\n    //\n    // Reverse two\n    size_t q = 2; // number of orders\n    CPPAD_TESTVECTOR(double) w(ny * q), dw(nx * q);\n    for(size_t i = 0; i < ny; ++i)\n    {   w[ i * q + 0 ] = 0.0; // derivative w.r.t. zero order coefficient\n        w[ i * q + 1 ] = 1.0; // derivative w.r.t. first order coefficient\n    }\n    dw = f.Reverse(2, w);\n    // derivative w.r.t zero order coefficients\n    ok &= dw[nx * 0 + 0] == 4.0;\n    // derivative w.r.t first order coefficients\n    ok &= dw[nx * 0 + 1] == 4.0 * x0[0];\n    //\n    return ok;\n}\n\n} // End empty namespace\n\n# include <vector>\n# include <valarray>\nbool reverse(void)\n{   bool ok = true;\n    ok &= reverse_one();\n    ok &= reverse_mul();\n    ok &= duplicate_dependent_var();\n\n    ok &= reverse_any_cases< CppAD::vector  <double> >();\n    ok &= reverse_any_cases< std::vector    <double> >();\n    ok &= reverse_any_cases< std::valarray  <double> >();\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/romberg_one.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\nold romberg_one.cpp example / test\n$spell\n    Romberg\n$$\n\n$section One Dimensional Romberg Integration: Example and Test$$\n\n$index Romberg, example$$\n$index example, Romberg$$\n$index test, Romberg$$\n\nold verbatim%example/romberg_one.cpp%0%// BEGIN C++%// END C++%1%$$\n\n$end\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n\nnamespace {\n    class Fun {\n    private:\n        const size_t degree;\n    public:\n        // constructor\n        Fun(size_t degree_) : degree(degree_)\n        { }\n\n        // function F(x) = x^degree\n        template <class Float>\n        Float operator () (const Float &x)\n        {   size_t i;\n            Float   f(1);\n            for(i = 0; i < degree; i++)\n                f *= x;\n            return f;\n        }\n    };\n\n    template <class Float>\n    bool RombergOneCase(void)\n    {   bool ok = true;\n        size_t i;\n\n        size_t degree = 4;\n        Fun F(degree);\n\n        // arguments to RombergOne\n        Float a(0);\n        Float b(1);\n        Float r;\n        size_t n = 4;\n        Float e;\n        size_t p;\n\n        // int_a^b F(x) dx =\n        //    [ b^(degree+1) - a^(degree+1) ] / (degree+1)\n        Float bpow(1);\n        Float apow(1);\n        for(i = 0; i <= degree; i++)\n        {   bpow *= b;\n            apow *= a;\n        }\n        Float check = (bpow - apow) / Float(degree+1);\n\n        // step size corresponding to r\n        Float step = (b - a) / exp(log(Float(2.))*Float(n-1));\n        // step size corresponding to error estimate\n        step *= Float(2.);\n        // step size raised to a power\n        Float spow = Float(1);\n\n        for(p = 0; p < n; p++)\n        {   spow = spow * step * step;\n\n            r = CppAD::RombergOne(F, a, b, n, p, e);\n\n            ok  &= e < double(degree+1) * spow;\n            ok  &= CppAD::NearEqual(check, r, Float(0.), e);\n        }\n\n        return ok;\n    }\n}\n\nbool RombergOne(void)\n{   bool ok = true;\n    using CppAD::AD;\n\n    ok     &= RombergOneCase<double>();\n    ok     &= RombergOneCase< AD<double> >();\n    ok     &= RombergOneCase< AD< AD<double> > >();\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "test_more/general/rosen_34.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\nOld OdeImplicit example now used just for valiadation testing of Rosen34\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n\n# include <iostream>\n# include <cassert>\n\n/*\nCase where\nx[0](0) = 1, x[0]'(t) = - w[0] * x[0](t)\nx[1](0) = 1, x[1]'(t) = - w[1] * x[1](t)\nx[2](0) = 0, x[2]'(t) =   w[2] * t\n\nx[0](t) = exp( - w[0] * t )\nx[1](t) = exp( - w[1] * t )\nx[2](t) = w[2] * t^2 / 2\n*/\n\nnamespace {  // BEGIN Empty namespace\n    class TestFun {\n    public:\n        TestFun(const CPPAD_TESTVECTOR(CppAD::AD<double>) &w_)\n        {   w.resize( w_.size() );\n            w = w_;\n        }\n        void Ode(\n            const CppAD::AD<double>                      &t,\n            const CPPAD_TESTVECTOR(CppAD::AD<double>) &x,\n            CPPAD_TESTVECTOR(CppAD::AD<double>)       &f)\n        {\n            f[0] = - w[0] * x[0];\n            f[1] = - w[1] * x[1];\n            f[2] =   w[2] * t;\n\n        }\n\n        void Ode_ind(\n            const CppAD::AD<double>                      &t,\n            const CPPAD_TESTVECTOR(CppAD::AD<double>) &x,\n            CPPAD_TESTVECTOR(CppAD::AD<double>)       &f_t)\n        {\n            f_t[0] = 0.;\n            f_t[1] = 0.;\n            f_t[2] = w[2];\n\n        }\n\n        void Ode_dep(\n            const CppAD::AD<double>                      &t,\n            const CPPAD_TESTVECTOR(CppAD::AD<double>) &x,\n            CPPAD_TESTVECTOR(CppAD::AD<double>)       &f_x)\n        {\n            f_x[0] = - w[0];    f_x[1] = 0.;      f_x[2] = 0.;\n            f_x[3] = 0.;        f_x[4] = - w[1];  f_x[5] = 0.;\n            f_x[6] = 0.;        f_x[7] = 0.;      f_x[8] = 0.;\n\n        }\n\n    private:\n        CPPAD_TESTVECTOR(CppAD::AD<double>) w;\n    };\n}   // END empty namespace\n\nbool Rosen34(void)\n{   bool ok = true;\n\n    using namespace CppAD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    CPPAD_TESTVECTOR(AD<double>) x(3);\n    CPPAD_TESTVECTOR(AD<double>) w(3);\n    size_t         n     = 3;\n    size_t         nstep = 20;\n    AD<double>     t0    = 0.;\n    AD<double>     t1    = 1.;\n\n    // set independent variables\n    size_t i;\n    for(i = 0; i < n; i++)\n        w[i] = double(100 * i + 1);\n    Independent(w);\n\n    // construct the function object using the independent variables\n    TestFun  fun(w);\n\n    // initial value of x\n    CPPAD_TESTVECTOR(AD<double>) xini(3);\n    xini[0] = 1.;\n    xini[1] = 1.;\n    xini[2] = 0.;\n\n\n    // integrate the differential equation\n    x  = Rosen34(fun, nstep, t0, t1, xini);\n\n    // create f : w -> x and vectors for evaluating derivatives\n    ADFun<double> f(w, x);\n    CPPAD_TESTVECTOR(double) q( f.Domain() );\n    CPPAD_TESTVECTOR(double) r( f.Range() );\n\n    // check function values\n    AD<double> x0 = exp( - w[0] * t1 );\n    ok &= NearEqual(x[0], x0, 0., 1. / double(nstep * nstep) );\n\n    AD<double> x1 = exp( - w[1] * t1 );\n    ok &= NearEqual(x[1],  x1, 0., 1. / double(nstep * nstep) );\n\n    AD<double> x2 = w[2] * t1 * t1 / 2.;\n    ok &= NearEqual(x[2],  x2, eps99, eps99);\n\n    // check dx[0] / dw[0]\n    for(i = 0; i < size_t(w.size()); i++)\n        q[i] = 0.;\n    q[0] = 1.;\n    r    = f.Forward(1, q);\n    ok &= NearEqual(r[0], - w[0] * x0, 0., 1. / double(nstep * nstep) );\n\n    // check dx[1] / dw[1]\n    q[0] = 0.;\n    q[1] = 1.;\n    r    = f.Forward(1, q);\n    ok &= NearEqual(r[1], - w[1] * x1, 0., 1. / double(nstep * nstep) );\n\n    // check dx[2] / dw[2]\n    q[1] = 0.;\n    q[2] = 1.;\n    r    = f.Forward(1, q);\n    ok &= NearEqual(r[2], x2 / w[2], eps99, eps99);\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "test_more/general/runge_45.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\nOld OdeRunge example now used just for valiadation testing of Runge45\n*/\n\n# include <cppad/cppad.hpp>\n# include <iostream>\n# include <cassert>\n\nnamespace { // BEGIN Empty namespace\n    class TestFun {\n    public:\n        TestFun(const CPPAD_TESTVECTOR(CppAD::AD<double>) &w_)\n        {   w.resize( w_.size() );\n            w = w_;\n        }\n        void Ode(\n            const CppAD::AD<double>                      &t,\n            const CPPAD_TESTVECTOR(CppAD::AD<double>) &x,\n            CPPAD_TESTVECTOR(CppAD::AD<double>)       &f)\n        {\n            using CppAD::exp;\n\n            size_t n = x.size();\n\n            size_t i;\n            f[0]  = 0.;\n            for(i = 1; i < n-1; i++)\n                f[i] = w[i] * x[i-1];\n\n            f[n-1] = x[0] * x[1];\n        }\n    private:\n        CPPAD_TESTVECTOR(CppAD::AD<double>) w;\n    };\n} // END Empty namespace\n\nbool Runge45(void)\n{   bool ok = true;\n\n    using namespace CppAD;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    size_t i;\n    size_t j;\n    size_t k;\n\n    size_t n = 6;\n    size_t m = n - 1;\n\n    CPPAD_TESTVECTOR(AD<double>) x(n);\n    AD<double>                t0    = 0.;\n    AD<double>                t1    = 2.;\n    size_t                    nstep = 2;\n\n    // vector of independent variables\n    CPPAD_TESTVECTOR(AD<double>) w(m);\n    for(i = 0; i < m; i++)\n        w[i] = double(i);\n    Independent(w);\n\n    // construct function object using independent variables\n    TestFun fun(w);\n\n    // initial value of x\n    CPPAD_TESTVECTOR(AD<double>) x0(n);\n    for(i = 0; i < n; i++)\n        x0[i] = 0.;\n    x0[0] = exp( w[0] );\n\n    // solve the differential equation\n    x = Runge45(fun, nstep, t0, t1, x0);\n\n    // create f : w -> x and vectors for evaluating derivatives\n    ADFun<double> f(w, x);\n    CPPAD_TESTVECTOR(double) q( f.Domain() );\n    CPPAD_TESTVECTOR(double) r( f.Range() );\n\n    // for i < n-1,\n    // x[i](2) = exp( w[0] ) * (w[1] / 1) * ... * (w[i] / i) * 2^i\n    AD<double> xi2 = exp(w[0]);\n    for(i = 0; i < n-1; i++)\n    {   ok &= NearEqual(x[i],  xi2, eps99, eps99);\n        if( i < n-2 )\n            xi2 *= w[i+1] * 2. / double(i+1);\n    }\n\n    // x[n-1](2) = exp(2 * w[0]) * w[1] * 2^2 / 2\n    xi2 = exp(2. * w[0]) * w[1] * 2.;\n    ok &= NearEqual(x[n-1], xi2, eps99, eps99);\n\n    // the partial of x[i](2) with respect to w[j] is\n    //    x[i](2) / w[j] if 0 < j <= i < n-1\n    //    x[i](2)        if j == 0 and i < n-1\n    //    2*x[i](2)      if j == 0 and i = n-1\n    //    x[i](2) / w[j] if j == 1 and i = n-1\n    //    zero           otherwise\n\n    for(i = 0; i < n-1; i++)\n    {   // compute partials of x[i]\n        for(k = 0; k < n; k++)\n            r[k] = 0.;\n        r[i] = 1.;\n        q    = f.Reverse(1,r);\n\n        for(j = 0; j < m; j++)\n        {   // check partial of x[i] w.r.t w[j]\n            if (j == 0 )\n                ok &= NearEqual(q[j], x[i], eps99, eps99);\n            else if( j <= i  )\n                ok &= NearEqual(\n                    q[j], x[i]/w[j], 1e-14, 1e-14);\n            else\n                ok &= NearEqual(q[j], 0., eps99, eps99);\n        }\n    }\n\n    // compute partials of x[n-1]\n    i = n-1;\n    for(k = 0; k < n; k++)\n        r[k] = 0.;\n    r[i] = 1.;\n    q    = f.Reverse(1,r);\n\n    for(j = 0; j < m; j++)\n    {   // check partial of x[n-1] w.r.t w[j]\n        if (j == 0 )\n            ok &= NearEqual(q[j], 2.*x[i], eps99, eps99);\n        else if( j == 1  )\n            ok &= NearEqual(\n                q[j], x[i]/w[1], 1e-14, 1e-14);\n        else\n            ok &= NearEqual(q[j], 0., eps99, eps99);\n    }\n\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/simple_vector.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n\n/*\nOld simple vector example now used just for validation testing\n*/\n// BEGIN C++\n\n// need this to define size_t\n# include <cstddef>\n\n// # include <vector>\n// # define MySimpleVector std::vector\n\n// # include <valarray>\n// # define MySimpleVector std::valarray\n\n# include <cppad/utility/vector.hpp>\n# define MySimpleVector CppAD::vector\n\n// Assuming Boost (http://www.boost.org) is installed\n// # include <boost/numeric/ublas/vector.hpp>\n// # define MySimpleVector boost::numeric::ublas::vector\n\n// A special type of element that counts assignment operations\nclass MyInt {\npublic:\n    // constructors\n    MyInt(void)       : count(0), value(0)\n    { }\n    MyInt(int _value) : count(0), value(_value)\n    { }\n    // assignment operator\n    MyInt& operator=(const MyInt &x)\n    {   value = x.value;\n        count++;\n        return *this;\n    }\n    // equality operator\n    bool operator==(const MyInt &x) const\n    {   return value == x.value; }\n\n    int Value(void) const\n    {   return value; }\n    size_t Count(void) const\n    {   return count; }\nprivate:\n    size_t count;  // count number of assignments\n    int    value;  // value of this object\n};\n\n// Test of a Simple Vector template class\nbool SimpleVector(void)\n{   bool ok = true;\n    typedef MySimpleVector<MyInt> vector;    // class we are testing\n    typedef vector::value_type myInt;        // type of elements\n\n    vector x;                // default constructor\n    ok &= (x.size() == 0);\n\n    x.resize(2);             // resize and set element assignment\n    ok &= (x.size() == 2);\n    x[0] = myInt(0);\n    x[1] = myInt(1);\n\n    vector y(2);             // sizing constructor\n    ok &= (y.size() == 2);\n\n    const vector z(x);       // copy constructor and const element access\n    ok &= (z.size() == 2);\n    ok &= ( (z[0] == myInt(0)) && (z[1] == myInt(1)) );\n\n    // check that vector assignment\n    x[0] = 2;                      // modify so that assignment changes x\n    size_t x0count = x[0].Count(); // store initial counts\n    size_t y1count = y[1].Count();\n    size_t z0count = z[0].Count();\n    x = y = z;                     // vector assignment\n\n    // check resulting values\n    ok &= ( (x[0] == myInt(0)) && (x[1] == myInt(1)) );\n    ok &= ( (y[0] == myInt(0)) && (y[1] == myInt(1)) );\n    ok &= ( (z[0] == myInt(0)) && (z[1] == myInt(1)) );\n\n    // check that MyInt assignment was called (not raw memory copy)\n    ok &= (x[0].Count() == x0count + 1);\n    ok &= (y[1].Count() == y1count + 1);\n    ok &= (z[0].Count() == z0count);\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "test_more/general/sin.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\nOld example now just used for validation testing.\n*/\n# include <cppad/cppad.hpp>\n\nbool Sin(void)\n{   bool ok = true;\n    using CppAD::sin;\n    using CppAD::cos;\n    using namespace CppAD;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // independent variable vector\n    CPPAD_TESTVECTOR(AD<double>) U(1);\n    U[0]     = 1.;\n    Independent(U);\n\n    // dependent variable vector\n    CPPAD_TESTVECTOR(AD<double>) Z(1);\n    Z[0] = sin(U[0]);\n\n    // create f: U -> Z and vectors used for derivative calculations\n    ADFun<double> f(U, Z);\n    CPPAD_TESTVECTOR(double) v(1);\n    CPPAD_TESTVECTOR(double) w(1);\n\n    // check value\n    double sin_u = sin( Value(U[0]) );\n    double cos_u = cos( Value(U[0]) );\n\n    ok &= NearEqual(sin_u, Value(Z[0]),  eps99 , eps99);\n\n    // forward computation of partials w.r.t. u\n    size_t j;\n    size_t p     = 5;\n    double jfac  = 1.;\n    v[0]         = 1.;\n    for(j = 1; j < p; j++)\n    {   w     = f.Forward(j, v);\n\n        double value;\n        if( j % 4 == 1 )\n            value = cos_u;\n        else if( j % 4 == 2 )\n            value = -sin_u;\n        else if( j % 4 == 3 )\n            value = -cos_u;\n        else\n            value = sin_u;\n\n        jfac *= double(j);\n        ok &= NearEqual(w[0], value/jfac, eps99, eps99); // d^jz/du^j\n        v[0]  = 0.;\n    }\n\n    // reverse computation of partials of Taylor coefficients\n    CPPAD_TESTVECTOR(double) r(p);\n    w[0]  = 1.;\n    r     = f.Reverse(p, w);\n    jfac  = 1.;\n    for(j = 0; j < p; j++)\n    {\n        double value;\n        if( j % 4 == 0 )\n            value = cos_u;\n        else if( j % 4 == 1 )\n            value = -sin_u;\n        else if( j % 4 == 2 )\n            value = -cos_u;\n        else\n            value = sin_u;\n\n        ok &= NearEqual(r[j], value/jfac, eps99, eps99); // d^jz/du^j\n\n        jfac *= double(j + 1);\n    }\n\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/sin_cos.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\nComprehensive test of Trigonometric and Hyperbolic Sine and Cosine\n*/\n\n# include <cppad/cppad.hpp>\n# include <cmath>\n\nnamespace { // Begin empty namespace\n\nbool Sin(void)\n{   bool ok = true;\n    using CppAD::sin;\n    using CppAD::cos;\n    using namespace CppAD;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // independent variable vector\n    double x = .5;\n    double y = .8;\n    CPPAD_TESTVECTOR(AD<double>) X(2);\n    X[0]     = x;\n    X[1]     = y;\n    Independent(X);\n\n    // dependent variable vector\n    CPPAD_TESTVECTOR(AD<double>) Z(1);\n    AD<double> U = X[0] * X[1];\n    Z[0] = sin( U );\n\n    // create f: X -> Z and vectors used for derivative calculations\n    // f(x, y) = sin(x, y)\n    ADFun<double> f(X, Z);\n    CPPAD_TESTVECTOR(double) v( 2 );\n    CPPAD_TESTVECTOR(double) w( 1 );\n\n    // check value\n    double sin_u = sin( Value(U) );\n    double cos_u = cos( Value(U) );\n\n    ok &= NearEqual(sin_u, Value(Z[0]),  eps99 , eps99);\n\n    // forward computation of partials w.r.t. u\n    size_t j;\n    size_t p     = 5;\n    double jfac  = 1.;\n    v[0]         = 1.;  // differential w.r.t. x\n    v[1]         = 0;   // differential w.r.t. y\n    double yj    = 1;   // y^j\n    for(j = 1; j < p; j++)\n    {   w      = f.Forward(j, v);\n\n        // compute j-th power of y\n        yj *= y ;\n\n        // compute j-th derivartive of sin function\n        double sinj;\n        if( j % 4 == 1 )\n            sinj = cos_u;\n        else if( j % 4 == 2 )\n            sinj = -sin_u;\n        else if( j % 4 == 3 )\n            sinj = -cos_u;\n        else\n            sinj = sin_u;\n\n        jfac *= double(j);\n\n        // check j-th derivative of z w.r.t x\n        ok &= NearEqual(jfac*w[0], sinj * yj, eps99 , eps99);\n\n        v[0]  = 0.;\n    }\n\n    // reverse computation of partials of Taylor coefficients\n    CPPAD_TESTVECTOR(double) r( 2 * p);\n    w[0]  = 1.;\n    r     = f.Reverse(p, w);\n    jfac  = 1.;\n    yj    = 1.;\n    double sinjp = 0.;\n    for(j = 0; j < p; j++)\n    {\n        double sinj = sinjp;\n\n        // compute j+1 derivative of sin function\n        if( j % 4 == 0 )\n            sinjp = cos_u;\n        else if( j % 4 == 1 )\n            sinjp = -sin_u;\n        else if( j % 4 == 2 )\n            sinjp = -cos_u;\n        else\n            sinjp = sin_u;\n\n        // derivative w.r.t x of sin^{(j)} (x * y) * y^j\n        ok &= NearEqual(jfac*r[0+j], sinjp * yj * y, eps99 , eps99);\n\n        // derivative w.r.t y of sin^{(j)} (x * y) * y^j\n        double value = sinjp * yj * x + double(j) * sinj * yj / y;\n        ok &= NearEqual(r[p+j], value/jfac, eps99, eps99);\n\n        jfac  *= double(j + 1);\n        yj    *= y;\n    }\n\n    return ok;\n}\n\nbool Cos(void)\n{   bool ok = true;\n    using CppAD::sin;\n    using CppAD::cos;\n    using namespace CppAD;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // independent variable vector\n    double x = .5;\n    double y = .8;\n    CPPAD_TESTVECTOR(AD<double>) X(2);\n    X[0]     = x;\n    X[1]     = y;\n    Independent(X);\n\n    // dependent variable vector\n    CPPAD_TESTVECTOR(AD<double>) Z(1);\n    AD<double> U = X[0] * X[1];\n    Z[0] = cos( U );\n\n    // create f: X -> Z and vectors used for derivative calculations\n    // f(x, y) = cos(x, y)\n    ADFun<double> f(X, Z);\n    CPPAD_TESTVECTOR(double) v( 2 );\n    CPPAD_TESTVECTOR(double) w( 1 );\n\n    // check value\n    double sin_u = sin( Value(U) );\n    double cos_u = cos( Value(U) );\n\n    ok &= NearEqual(cos_u, Value(Z[0]),  eps99 , eps99);\n\n    // forward computation of partials w.r.t. u\n    size_t j;\n    size_t p     = 5;\n    double jfac  = 1.;\n    v[0]         = 1.;  // differential w.r.t. x\n    v[1]         = 0;   // differential w.r.t. y\n    double yj    = 1;   // y^j\n    for(j = 1; j < p; j++)\n    {   w      = f.Forward(j, v);\n\n        // compute j-th power of y\n        yj *= y ;\n\n        // compute j-th derivartive of cos function\n        double cosj;\n        if( j % 4 == 1 )\n            cosj = -sin_u;\n        else if( j % 4 == 2 )\n            cosj = -cos_u;\n        else if( j % 4 == 3 )\n            cosj = sin_u;\n        else\n            cosj = cos_u;\n\n        jfac *= double(j);\n\n        // check j-th derivative of z w.r.t x\n        ok &= NearEqual(jfac*w[0], cosj * yj, eps99 , eps99);\n\n        v[0]  = 0.;\n    }\n\n    // reverse computation of partials of Taylor coefficients\n    CPPAD_TESTVECTOR(double) r( 2 * p);\n    w[0]  = 1.;\n    r     = f.Reverse(p, w);\n    jfac  = 1.;\n    yj    = 1.;\n    double cosjp = 0.;\n    for(j = 0; j < p; j++)\n    {\n        double cosj = cosjp;\n\n        // compute j+1 derivative of cos function\n        if( j % 4 == 0 )\n            cosjp = -sin_u;\n        else if( j % 4 == 1 )\n            cosjp = -cos_u;\n        else if( j % 4 == 2 )\n            cosjp = sin_u;\n        else\n            cosjp = cos_u;\n\n        // derivative w.r.t x of cos^{(j)} (x * y) * y^j\n        ok &= NearEqual(jfac*r[0+j], cosjp * yj * y, eps99 , eps99);\n\n        // derivative w.r.t y of cos^{(j)} (x * y) * y^j\n        double value = cosjp * yj * x + double(j) * cosj * yj / y;\n        ok &= NearEqual(r[p+j], value/jfac, eps99, eps99);\n\n        jfac  *= double(j + 1);\n        yj    *= y;\n    }\n\n    return ok;\n}\n\nbool Cosh(void)\n{   bool ok = true;\n    using CppAD::sinh;\n    using CppAD::cosh;\n    using namespace CppAD;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // independent variable vector\n    double x = .5;\n    double y = .8;\n    CPPAD_TESTVECTOR(AD<double>) X(2);\n    X[0]     = x;\n    X[1]     = y;\n    Independent(X);\n\n    // dependent variable vector\n    CPPAD_TESTVECTOR(AD<double>) Z(1);\n    AD<double> U = X[0] * X[1];\n    Z[0] = cosh( U );\n\n    // create f: X -> Z and vectors used for derivative calculations\n    // f(x, y) = cosh(x, y)\n    ADFun<double> f(X, Z);\n    CPPAD_TESTVECTOR(double) v( 2 );\n    CPPAD_TESTVECTOR(double) w( 1 );\n\n    // check value\n    double sinh_u = sinh( Value(U) );\n    double cosh_u = cosh( Value(U) );\n\n    ok &= NearEqual(cosh_u, Value(Z[0]),  eps99 , eps99);\n\n    // forward computation of partials w.r.t. u\n    size_t j;\n    size_t p     = 5;\n    double jfac  = 1.;\n    v[0]         = 1.;  // differential w.r.t. x\n    v[1]         = 0;   // differential w.r.t. y\n    double yj    = 1;   // y^j\n    for(j = 1; j < p; j++)\n    {   w      = f.Forward(j, v);\n\n        // compute j-th power of y\n        yj *= y ;\n\n        // compute j-th derivartive of cosh function\n        double coshj;\n        if( j % 2 == 1 )\n            coshj = sinh_u;\n        else\n            coshj = cosh_u;\n\n        jfac *= double(j);\n\n        // check j-th derivative of z w.r.t x\n        ok &= NearEqual(jfac*w[0], coshj * yj, eps99 , eps99);\n\n        v[0]  = 0.;\n    }\n\n    // reverse computation of partials of Taylor coefficients\n    CPPAD_TESTVECTOR(double) r( 2 * p);\n    w[0]  = 1.;\n    r     = f.Reverse(p, w);\n    jfac  = 1.;\n    yj    = 1.;\n    double coshjp = 0.;\n    for(j = 0; j < p; j++)\n    {\n        double coshj = coshjp;\n\n        // compute j+1 derivative of cosh function\n        if( j % 2 == 0 )\n            coshjp = sinh_u;\n        else\n            coshjp = cosh_u;\n\n        // derivative w.r.t x of cosh^{(j)} (x * y) * y^j\n        ok &= NearEqual(jfac*r[0+j], coshjp * yj * y, eps99 , eps99);\n\n        // derivative w.r.t y of cosh^{(j)} (x * y) * y^j\n        double value = coshjp * yj * x + double(j) * coshj * yj / y;\n        ok &= NearEqual(r[p+j], value/jfac, eps99, eps99);\n\n        jfac  *= double(j + 1);\n        yj    *= y;\n    }\n\n    return ok;\n}\n\nbool Sinh(void)\n{   bool ok = true;\n    using CppAD::sinh;\n    using CppAD::cosh;\n    using namespace CppAD;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // independent variable vector\n    double x = .5;\n    double y = .8;\n    CPPAD_TESTVECTOR(AD<double>) X(2);\n    X[0]     = x;\n    X[1]     = y;\n    Independent(X);\n\n    // dependent variable vector\n    CPPAD_TESTVECTOR(AD<double>) Z(1);\n    AD<double> U = X[0] * X[1];\n    Z[0] = sinh( U );\n\n    // create f: X -> Z and vectors used for derivative calculations\n    // f(x, y) = sinh(x, y)\n    ADFun<double> f(X, Z);\n    CPPAD_TESTVECTOR(double) v( 2 );\n    CPPAD_TESTVECTOR(double) w( 1 );\n\n    // check value\n    double sinh_u = sinh( Value(U) );\n    double cosh_u = cosh( Value(U) );\n\n    ok &= NearEqual(sinh_u, Value(Z[0]),  eps99 , eps99);\n\n    // forward computation of partials w.r.t. u\n    size_t j;\n    size_t p     = 5;\n    double jfac  = 1.;\n    v[0]         = 1.;  // differential w.r.t. x\n    v[1]         = 0;   // differential w.r.t. y\n    double yj    = 1;   // y^j\n    for(j = 1; j < p; j++)\n    {   w      = f.Forward(j, v);\n\n        // compute j-th power of y\n        yj *= y ;\n\n        // compute j-th derivartive of sinh function\n        double sinhj;\n        if( j % 2 == 1 )\n            sinhj = cosh_u;\n        else\n            sinhj = sinh_u;\n\n        jfac *= double(j);\n\n        // check j-th derivative of z w.r.t x\n        ok &= NearEqual(jfac*w[0], sinhj * yj, eps99 , eps99);\n\n        v[0]  = 0.;\n    }\n\n    // reverse computation of partials of Taylor coefficients\n    CPPAD_TESTVECTOR(double) r( 2 * p);\n    w[0]  = 1.;\n    r     = f.Reverse(p, w);\n    jfac  = 1.;\n    yj    = 1.;\n    double sinhjp = 0.;\n    for(j = 0; j < p; j++)\n    {\n        double sinhj = sinhjp;\n\n        // compute j+1 derivative of sinh function\n        if( j % 2 == 0 )\n            sinhjp = cosh_u;\n        else\n            sinhjp = sinh_u;\n\n        // derivative w.r.t x of sinh^{(j)} (x * y) * y^j\n        ok &= NearEqual(jfac*r[0+j], sinhjp * yj * y, eps99 , eps99);\n\n        // derivative w.r.t y of sinh^{(j)} (x * y) * y^j\n        double value = sinhjp * yj * x + double(j) * sinhj * yj / y;\n        ok &= NearEqual(r[p+j], value/jfac, eps99, eps99);\n\n        jfac  *= double(j + 1);\n        yj    *= y;\n    }\n\n    return ok;\n}\n\n} // End empty namespace\n\nbool SinCos(void)\n{   bool ok = Sin() && Cos() && Cosh() && Sinh();\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/sinh.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\nOld example now just used for validation testing.\n*/\n# include <cppad/cppad.hpp>\n\nbool Sinh(void)\n{   bool ok = true;\n    using CppAD::sinh;\n    using CppAD::cosh;\n    using namespace CppAD;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // independent variable vector\n    CPPAD_TESTVECTOR(AD<double>) U(1);\n    U[0]     = 1.;\n    Independent(U);\n\n    // dependent variable vector\n    CPPAD_TESTVECTOR(AD<double>) Z(1);\n    Z[0] = sinh(U[0]);\n\n    // create f: U -> Z and vectors used for derivative calculations\n    ADFun<double> f(U, Z);\n    CPPAD_TESTVECTOR(double) v(1);\n    CPPAD_TESTVECTOR(double) w(1);\n\n    // check value\n    double sin_u = sinh( Value(U[0]) );\n    double cos_u = cosh( Value(U[0]) );\n\n    ok &= NearEqual(sin_u, Value(Z[0]),  eps99 , eps99);\n\n    // forward computation of partials w.r.t. u\n    size_t j;\n    size_t p     = 5;\n    double jfac  = 1.;\n    v[0]         = 1.;\n    for(j = 1; j < p; j++)\n    {   w     = f.Forward(j, v);\n\n        double value;\n        if( j % 2 == 1 )\n            value = cos_u;\n        else\n            value = sin_u;\n\n        jfac *= double(j);\n        ok &= NearEqual(w[0], value/jfac, eps99, eps99); // d^jz/du^j\n        v[0]  = 0.;\n    }\n\n    // reverse computation of partials of Taylor coefficients\n    CPPAD_TESTVECTOR(double) r(p);\n    w[0]  = 1.;\n    r     = f.Reverse(p, w);\n    jfac  = 1.;\n    for(j = 0; j < p; j++)\n    {\n        double value;\n        if( j % 2 == 0 )\n            value = cos_u;\n        else\n            value = sin_u;\n\n        ok &= NearEqual(r[j], value/jfac, eps99, eps99); // d^jz/du^j\n\n        jfac *= double(j + 1);\n    }\n\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/sparse_hessian.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\nOld SparseHessian example\n*/\n\n# include <cppad/cppad.hpp>\nnamespace { // ---------------------------------------------------------\n\nbool rc_tridiagonal(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    size_t i, j, k, ell;\n    double eps10 = 10. * CppAD::epsilon<double>();\n\n    size_t n = 12; // must be greater than or equal 3; see n_sweep.\n    size_t m = n - 1;\n    CPPAD_TESTVECTOR(AD<double>) a_x(n), a_y(m);\n    CPPAD_TESTVECTOR(double) x(n), check(n * n), w(m);\n    for(j = 0; j < n; j++)\n        a_x[j] = x[j] = double(j+1);\n\n    // declare independent variables and start taping\n    CppAD::Independent(a_x);\n\n    for(ell = 0; ell < n * n; ell++)\n        check[ell] = 0.0;\n\n    for(i = 0; i < m; i++)\n    {   AD<double> diff = a_x[i+1] - a_x[i];\n        a_y[i] = 0.5 * diff * diff / double(i+2);\n        w[i] = double(i+1);\n        ell         = i * n + i;\n        check[ell] += w[i] / double(i+2);\n        ell         = (i+1) * n + i+1;\n        check[ell] += w[i] / double(i+2);\n        ell         = (i+1) * n + i;\n        check[ell] -= w[i] / double(i+2);\n        ell         = i * n + i+1;\n        check[ell] -= w[i] / double(i+2);\n    }\n\n    // create f: x -> y\n    CppAD::ADFun<double> f(a_x, a_y);\n\n    // determine the sparsity pattern p for Hessian of w^T f\n    typedef CppAD::vector< std::set<size_t> > SetVector;\n    SetVector p_r(n);\n    for(j = 0; j < n; j++)\n        p_r[j].insert(j);\n    f.ForSparseJac(n, p_r);\n    //\n    SetVector p_s(1);\n    for(i = 0; i < m; i++)\n        if( w[i] != 0 )\n            p_s[0].insert(i);\n    SetVector p_h = f.RevSparseHes(n, p_s);\n\n    // requires the upper triangle of the Hessian\n    size_t K = 2 * n - 1;\n    CPPAD_TESTVECTOR(size_t) r(K), c(K);\n    CPPAD_TESTVECTOR(double) hes(K);\n    k = 0;\n    for(i = 0; i < n; i++)\n    {   r[k] = i;\n        c[k] = i;\n        k++;\n        if( i < n-1 )\n        {   r[k] = i;\n            c[k] = i+1;\n            k++;\n        }\n    }\n    ok &= k == K;\n\n    // test computing sparse Hessian\n    CppAD::sparse_hessian_work work;\n    size_t n_sweep = f.SparseHessian(x, w, p_h, r, c, hes, work);\n    ok &= n_sweep == 3;\n    for(k = 0; k < K; k++)\n    {   ell = r[k] * n + c[k];\n        ok &=  NearEqual(check[ell], hes[k], eps10, eps10);\n        ell = c[k] * n + r[k];\n        ok &=  NearEqual(check[ell], hes[k], eps10, eps10);\n    }\n\n    return ok;\n}\n\n\ntemplate <class BaseVector, class BoolVector>\nbool bool_case()\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    size_t i, j, k;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n = 3;\n    CPPAD_TESTVECTOR(AD<double>)  X(n);\n    for(i = 0; i < n; i++)\n        X[i] = AD<double> (0);\n\n    // declare independent variables and starting recording\n    CppAD::Independent(X);\n\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>)  Y(m);\n    Y[0] = X[0] * X[0] + X[0] * X[1] + X[1] * X[1] + X[2] * X[2];\n\n    // create f: X -> Y and stop tape recording\n    CppAD::ADFun<double> f(X, Y);\n\n    // new value for the independent variable vector\n    BaseVector x(n);\n    for(i = 0; i < n; i++)\n        x[i] = double(i);\n\n    // second derivative of y[1]\n    BaseVector w(m);\n    w[0] = 1.;\n    BaseVector h( n * n );\n    h = f.SparseHessian(x, w);\n    /*\n         [ 2 1 0 ]\n    h = [ 1 2 0 ]\n         [ 0 0 2 ]\n    */\n    BaseVector check(n * n);\n    check[0] = 2.; check[1] = 1.; check[2] = 0.;\n    check[3] = 1.; check[4] = 2.; check[5] = 0.;\n    check[6] = 0.; check[7] = 0.; check[8] = 2.;\n    for(k = 0; k < n * n; k++)\n        ok &=  NearEqual(check[k], h[k], eps99, eps99 );\n\n    // determine the sparsity pattern p for Hessian of w^T F\n    BoolVector r(n * n);\n    for(j = 0; j < n; j++)\n    {   for(k = 0; k < n; k++)\n        r[j * n + k] = false;\n        r[j * n + j] = true;\n    }\n    f.ForSparseJac(n, r);\n    //\n    BoolVector s(m);\n    for(i = 0; i < m; i++)\n        s[i] = w[i] != 0;\n    BoolVector p = f.RevSparseHes(n, s);\n\n    // test passing sparsity pattern\n    h = f.SparseHessian(x, w, p);\n    for(k = 0; k < n * n; k++)\n        ok &=  NearEqual(check[k], h[k], eps99, eps99 );\n\n    return ok;\n}\ntemplate <class BaseVector, class SetVector>\nbool set_case()\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    size_t i, j, k;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n = 3;\n    CPPAD_TESTVECTOR(AD<double>)  X(n);\n    for(i = 0; i < n; i++)\n        X[i] = AD<double> (0);\n\n    // declare independent variables and starting recording\n    CppAD::Independent(X);\n\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>)  Y(m);\n    Y[0] = X[0] * X[0] + X[0] * X[1] + X[1] * X[1] + X[2] * X[2];\n\n    // create f: X -> Y and stop tape recording\n    CppAD::ADFun<double> f(X, Y);\n\n    // new value for the independent variable vector\n    BaseVector x(n);\n    for(i = 0; i < n; i++)\n        x[i] = double(i);\n\n    // second derivative of y[1]\n    BaseVector w(m);\n    w[0] = 1.;\n    BaseVector h( n * n );\n    h = f.SparseHessian(x, w);\n    /*\n         [ 2 1 0 ]\n    h = [ 1 2 0 ]\n         [ 0 0 2 ]\n    */\n    BaseVector check(n * n);\n    check[0] = 2.; check[1] = 1.; check[2] = 0.;\n    check[3] = 1.; check[4] = 2.; check[5] = 0.;\n    check[6] = 0.; check[7] = 0.; check[8] = 2.;\n    for(k = 0; k < n * n; k++)\n        ok &=  NearEqual(check[k], h[k], eps99, eps99 );\n\n    // determine the sparsity pattern p for Hessian of w^T F\n    SetVector r(n);\n    for(j = 0; j < n; j++)\n        r[j].insert(j);\n    f.ForSparseJac(n, r);\n    //\n    SetVector s(1);\n    for(i = 0; i < m; i++)\n        if( w[i] != 0 )\n            s[0].insert(i);\n    SetVector p = f.RevSparseHes(n, s);\n\n    // test passing sparsity pattern\n    h = f.SparseHessian(x, w, p);\n    for(k = 0; k < n * n; k++)\n        ok &=  NearEqual(check[k], h[k], eps99, eps99 );\n\n    return ok;\n}\n} // End empty namespace\n# include <vector>\n# include <valarray>\nbool sparse_hessian(void)\n{   bool ok = true;\n\n    ok &= rc_tridiagonal();\n    // ---------------------------------------------------------------\n    // vector of bool cases\n    ok &= bool_case< CppAD::vector  <double>, CppAD::vectorBool   >();\n    ok &= bool_case< std::vector    <double>, CppAD::vector<bool> >();\n    ok &= bool_case< std::valarray  <double>, std::vector<bool>   >();\n    // ---------------------------------------------------------------\n    // vector of set cases\n    typedef std::vector< std::set<size_t> >   std_vector_set;\n    typedef CppAD::vector< std::set<size_t> > cppad_vector_set;\n    //\n    ok &= set_case< CppAD::vector<double>, std_vector_set   >();\n    ok &= set_case< std::valarray<double>, std_vector_set   >();\n    ok &= set_case< std::vector<double>,   cppad_vector_set >();\n    ok &= set_case< CppAD::vector<double>, cppad_vector_set >();\n    //\n    // According to section 26.3.2.3 of the 1998 C++ standard\n    // a const valarray does not return references to its elements.\n    // so do not include it in the testing for sets.\n    // ---------------------------------------------------------------\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/sparse_jac_work.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n@begin sparse_jac_work.cpp@@\n$spell\n    Cpp\n    Jacobian\n$$\n\n$section Using Same Work With Different Levels of AD: Example and Test$$\n\n$srcthisfile%0%// BEGIN C++%// END C++%1%$$\n\n$end\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\nbool sparse_jac_work(void)\n{   bool ok = true;\n    //\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    using CppAD::sparse_rc;\n    using CppAD::sparse_rcv;\n    //\n    typedef AD<double>                   a1double;\n    typedef AD<a1double>                 a2double;\n    typedef CPPAD_TESTVECTOR(double)     d_vector;\n    typedef CPPAD_TESTVECTOR(a1double)   a1vector;\n    typedef CPPAD_TESTVECTOR(a2double)   a2vector;\n    typedef CPPAD_TESTVECTOR(size_t)     s_vector;\n    //\n    // domain space vector\n    size_t n = 4;\n    a2vector a2x(n);\n    a1vector a1x(n);\n    for(size_t j = 0; j < n; j++)\n        a2x[j] = a1x[j] = 0.0;\n    //\n    // declare independent variables and starting recording\n    CppAD::Independent(a2x);\n    //\n    size_t m = 3;\n    a2vector  a2y(m);\n    a2y[0] = a2x[0] + a2x[1];\n    a2y[1] = a2x[2] + a2x[3];\n    a2y[2] = a2x[0] + a2x[1] + a2x[2] + a2x[3] * a2x[3] / 2.;\n    //\n    // create f: x -> y for computation with a1double\n    CppAD::ADFun<a1double> a1f(a2x, a2y);\n    //\n    // create an identical function for computation with double\n    CppAD::Independent(a1x);\n    a1vector a1y = a1f.Forward(0, a1x);\n    CppAD::ADFun<double> f(a1x, a1y);\n    //\n    // new value for the independent variable vector\n    d_vector x(n);\n    for(size_t j = 0; j < n; j++)\n        x[j] = double(j);\n    /*\n              [ 1 1 0 0  ]\n    J(x) = [ 0 0 1 1  ]\n              [ 1 1 1 x_3]\n    */\n    //\n    // row-major order values of J(x)\n    size_t nnz = 8;\n    s_vector check_row(nnz), check_col(nnz);\n    d_vector check_val(nnz);\n    for(size_t k = 0; k < nnz; k++)\n    {   // check_val\n        if( k < 7 )\n            check_val[k] = 1.0;\n        else\n            check_val[k] = x[3];\n        //\n        // check_row and check_col\n        check_col[k] = k;\n        if( k < 2 )\n            check_row[k] = 0;\n        else if( k < 4 )\n            check_row[k] = 1;\n        else\n        {   check_row[k] = 2;\n            check_col[k] = k - 4;\n        }\n    }\n    //\n    // m by m identity matrix sparsity\n    sparse_rc<s_vector> pattern_in(m, m, m);\n    for(size_t k = 0; k < m; k++)\n        pattern_in.set(k, k, k);\n    //\n    // sparsity for J(x)\n    bool transpose     = false;\n    bool dependency    = false;\n    bool internal_bool = true;\n    sparse_rc<s_vector> pattern_jac;\n    f.rev_jac_sparsity(\n        pattern_in, transpose, dependency, internal_bool, pattern_jac\n    );\n    //\n    // compute entire reverse mode Jacobian\n    sparse_rcv<s_vector, d_vector> subset( pattern_jac );\n    CppAD::sparse_jac_work work;\n    std::string coloring = \"cppad\";\n    size_t n_sweep = f.sparse_jac_rev(x, subset, pattern_jac, coloring, work);\n    ok &= n_sweep == 2;\n    //\n    const s_vector row( subset.row() );\n    const s_vector col( subset.col() );\n    const d_vector val( subset.val() );\n    s_vector row_major = subset.row_major();\n    ok  &= subset.nnz() == nnz;\n    for(size_t k = 0; k < nnz; k++)\n    {   ok &= row[ row_major[k] ] == check_row[k];\n        ok &= col[ row_major[k] ] == check_col[k];\n        ok &= val[ row_major[k] ] == check_val[k];\n    }\n    //\n    // test using work stored by previous sparse_jac_rev with f\n    sparse_rc<s_vector> pattern_not_used;\n    std::string         coloring_not_used;\n    n_sweep = f.sparse_jac_rev(x, subset, pattern_jac, coloring, work);\n    ok &= n_sweep == 2;\n    for(size_t k = 0; k < nnz; k++)\n    {   ok &= row[ row_major[k] ] == check_row[k];\n        ok &= col[ row_major[k] ] == check_col[k];\n        ok &= val[ row_major[k] ] == check_val[k];\n    }\n    //\n    // test using work stored by previous sparse_jac_rev with a1f\n    sparse_rcv<s_vector, a1vector> a1subset( pattern_jac );\n    for(size_t j = 0; j < n; ++j)\n        a1x[j] = x[j];\n    n_sweep = a1f.sparse_jac_rev(a1x, a1subset, pattern_jac, coloring, work);\n    ok &= n_sweep == 2;\n    const a1vector a1val( a1subset.val() );\n    for(size_t k = 0; k < nnz; k++)\n    {   ok &= row[ row_major[k] ] == check_row[k];\n        ok &= col[ row_major[k] ] == check_col[k];\n        ok &= Value( a1val[ row_major[k] ] ) == check_val[k];\n    }\n    //\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "test_more/general/sparse_jacobian.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\nOld sparse Jacobian example\n*/\n\n# include <cppad/cppad.hpp>\nnamespace { // ---------------------------------------------------------\n\nbool rc_tridiagonal(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    size_t i, j, k, ell;\n    double eps10 = 10. * CppAD::epsilon<double>();\n\n    // domain space vector\n    size_t n = 13; // must be greater than or equal 3 (see n_sweep below)\n    CPPAD_TESTVECTOR(AD<double>)  X(n);\n    CPPAD_TESTVECTOR(double)        x(n);\n    for(j = 0; j < n; j++)\n        X[j] = x[j] = double(j+1);\n\n    // declare independent variables and starting recording\n    CppAD::Independent(X);\n\n    size_t m = n;\n    CPPAD_TESTVECTOR(AD<double>)  Y(m);\n    CPPAD_TESTVECTOR(double) check(m * n );\n    for(ell = 0; ell < m * n; ell++)\n        check[ell] = 0.0;\n\n    size_t K = 0;\n    for(i = 0; i < n; i++)\n    {   ell        = i * n + i;\n        Y[i]       = double(ell+1) * 0.5 * X[i] * X[i];\n        check[ell] = double(ell+1) * x[i];\n        K++;\n        if( i < n-1 )\n        {   j          = i + 1;\n            ell        = i * n + j;\n            Y[i]      += double(ell+1) * 0.5 * X[i+1] * X[i+1];\n            check[ell] = double(ell+1) * x[i+1];\n            K++;\n        }\n        if(i > 0 )\n        {   j          = i - 1;\n            ell        = i * n + j;\n            Y[i]      += double(ell+1) * 0.5 * X[i-1] * X[i-1];\n            check[ell] = double(ell+1) * x[i-1];\n        }\n    }\n\n    // create f: X -> Y and stop tape recording\n    CppAD::ADFun<double> f(X, Y);\n\n    // sparsity pattern\n    CppAD::vector< std::set<size_t> > s(m), p(m);\n    for(i = 0; i < m; i++)\n        s[i].insert(i);\n    p   = f.RevSparseJac(m, s);\n\n    // Request the upper triangle of the array\n    CPPAD_TESTVECTOR(size_t) r(K), c(K);\n    CPPAD_TESTVECTOR(double) jac(K);\n    k = 0;\n    for(i = 0; i < n; i++)\n    {   r[k] = i;\n        c[k] = i;\n        k++;\n        if( i < n-1 )\n        {   r[k] = i;\n            c[k] = i+1;\n            k++;\n        }\n    }\n    ok &= K == k;\n\n    CppAD::sparse_jacobian_work work;\n    size_t n_sweep = f.SparseJacobianForward(x, p, r, c, jac, work);\n    ok &= n_sweep == 3;\n    for(k = 0; k < K; k++)\n    {   ell = r[k] * n + c[k];\n        ok &=  NearEqual(check[ell], jac[k], eps10, eps10);\n    }\n    work.clear();\n    n_sweep = f.SparseJacobianReverse(x, p, r, c, jac, work);\n    ok &= n_sweep == 3;\n    for(k = 0; k < K; k++)\n    {   ell = r[k] * n + c[k];\n        ok &=  NearEqual(check[ell], jac[k], eps10, eps10);\n    }\n\n    return ok;\n}\n\ntemplate <class BaseVector, class SetVector>\nbool rc_set(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    size_t i, j, k, ell;\n    double eps10 = 10. * CppAD::epsilon<double>();\n\n    // domain space vector\n    size_t n = 4;\n    CPPAD_TESTVECTOR(AD<double>)  X(n);\n    for(j = 0; j < n; j++)\n        X[j] = AD<double> (0);\n\n    // declare independent variables and starting recording\n    CppAD::Independent(X);\n\n    size_t m = 3;\n    CPPAD_TESTVECTOR(AD<double>)  Y(m);\n    Y[0] = 1.0*X[0] + 2.0*X[1];\n    Y[1] = 3.0*X[2] + 4.0*X[3];\n    Y[2] = 5.0*X[0] + 6.0*X[1] + 7.0*X[3]*X[3]/2.;\n\n    // create f: X -> Y and stop tape recording\n    CppAD::ADFun<double> f(X, Y);\n\n    // new value for the independent variable vector\n    BaseVector x(n);\n    for(j = 0; j < n; j++)\n        x[j] = double(j);\n\n    // Jacobian of y\n    /*\n             [ 1 2 0 0    ]\n    jac = [ 0 0 3 4    ]\n             [ 5 6 0 7*x_3]\n    */\n    BaseVector check(m * n);\n    check[0] = 1.; check[1] = 2.; check[2]  = 0.; check[3]  = 0.;\n    check[4] = 0.; check[5] = 0.; check[6]  = 3.; check[7]  = 4.;\n    check[8] = 5.; check[9] = 6.; check[10] = 0.; check[11] = 7.*x[3];\n\n    // sparsity pattern\n    SetVector s(m), p(m);\n    for(i = 0; i < m; i++)\n        s[i].insert(i);\n    p   = f.RevSparseJac(m, s);\n\n    // Use forward mode to compute columns 0 and 2\n    // (make sure order of rows and columns does not matter)\n    CPPAD_TESTVECTOR(size_t) r(3), c(3);\n    BaseVector jac(3);\n    r[0] = 2; c[0] = 0;\n    r[1] = 1; c[1] = 2;\n    r[2] = 0; c[2] = 0;\n    CppAD::sparse_jacobian_work work;\n    size_t n_sweep = f.SparseJacobianForward(x, p, r, c, jac, work);\n    for(k = 0; k < 3; k++)\n    {   ell = r[k] * n + c[k];\n        ok &=  NearEqual(check[ell], jac[k], eps10, eps10);\n    }\n    ok &= (n_sweep == 1);\n\n    // Use reverse mode to compute rows 0 and 1\n    // (make sure order of rows and columns does not matter)\n    r.resize(4), c.resize(4); jac.resize(4);\n    r[0] = 0; c[0] = 0;\n    r[1] = 1; c[1] = 2;\n    r[2] = 0; c[2] = 1;\n    r[3] = 1; c[3] = 3;\n    work.clear();\n    n_sweep = f.SparseJacobianReverse(x, p, r, c, jac, work);\n    for(k = 0; k < 4; k++)\n    {   ell = r[k] * n + c[k];\n        ok &=  NearEqual(check[ell], jac[k], eps10, eps10);\n    }\n    ok &= (n_sweep == 1);\n\n    return ok;\n}\ntemplate <class BaseVector, class BoolVector>\nbool rc_bool(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    size_t j, k, ell;\n    double eps10 = 10. * CppAD::epsilon<double>();\n\n    // domain space vector\n    size_t n = 4;\n    CPPAD_TESTVECTOR(AD<double>)  X(n);\n    for(j = 0; j < n; j++)\n        X[j] = AD<double> (0);\n\n    // declare independent variables and starting recording\n    CppAD::Independent(X);\n\n    size_t m = 3;\n    CPPAD_TESTVECTOR(AD<double>)  Y(m);\n    Y[0] = 1.0*X[0] + 2.0*X[1];\n    Y[1] = 3.0*X[2] + 4.0*X[3];\n    Y[2] = 5.0*X[0] + 6.0*X[1] + 7.0*X[3]*X[3]/2.;\n\n    // create f: X -> Y and stop tape recording\n    CppAD::ADFun<double> f(X, Y);\n\n    // new value for the independent variable vector\n    BaseVector x(n);\n    for(j = 0; j < n; j++)\n        x[j] = double(j);\n\n    // Jacobian of y\n    /*\n             [ 1 2 0 0    ]\n    jac = [ 0 0 3 4    ]\n             [ 5 6 0 7*x_3]\n    */\n    BaseVector check(m * n);\n    check[0] = 1.; check[1] = 2.; check[2]  = 0.; check[3]  = 0.;\n    check[4] = 0.; check[5] = 0.; check[6]  = 3.; check[7]  = 4.;\n    check[8] = 5.; check[9] = 6.; check[10] = 0.; check[11] = 7.*x[3];\n    BoolVector s(m * n);\n    s[0] = true;   s[1] = true;   s[2] = false;   s[3] = false;\n    s[4] = false;  s[5] = false;  s[6] = true;    s[7] = true;\n    s[8] = true;   s[9] = true;  s[10] = false;  s[11] = true;\n\n    // Use forward mode to compute columns 0 and 2\n    // (make sure order of rows and columns does not matter)\n    CPPAD_TESTVECTOR(size_t) r(3), c(3);\n    BaseVector jac(3);\n    r[0] = 2; c[0] = 0;\n    r[1] = 1; c[1] = 2;\n    r[2] = 0; c[2] = 0;\n    CppAD::sparse_jacobian_work work;\n    size_t n_sweep = f.SparseJacobianForward(x, s, r, c, jac, work);\n    for(k = 0; k < 3; k++)\n    {   ell = r[k] * n + c[k];\n        ok &=  NearEqual(check[ell], jac[k], eps10, eps10);\n    }\n    ok &= (n_sweep == 1);\n\n    // Use reverse mode to compute rows 0 and 1\n    // (make sure order of rows and columns does not matter)\n    r.resize(4), c.resize(4); jac.resize(4);\n    r[0] = 0; c[0] = 0;\n    r[1] = 1; c[1] = 2;\n    r[2] = 0; c[2] = 1;\n    r[3] = 1; c[3] = 3;\n    work.clear();\n    n_sweep = f.SparseJacobianReverse(x, s, r, c, jac, work);\n    for(k = 0; k < 4; k++)\n    {   ell = r[k] * n + c[k];\n        ok &=  NearEqual(check[ell], jac[k], eps10, eps10);\n    }\n    ok &= (n_sweep == 1);\n\n    return ok;\n}\n\n\ntemplate <class BaseVector, class BoolVector>\nbool reverse_bool(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    size_t i, j, k;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n = 4;\n    CPPAD_TESTVECTOR(AD<double>)  X(n);\n    for(j = 0; j < n; j++)\n        X[j] = AD<double> (0);\n\n    // declare independent variables and starting recording\n    CppAD::Independent(X);\n\n    size_t m = 3;\n    CPPAD_TESTVECTOR(AD<double>)  Y(m);\n    Y[0] = 1.0*X[0] + 2.0*X[1];\n    Y[1] = 3.0*X[2] + 4.0*X[3];\n    Y[2] = 5.0*X[0] + 6.0*X[1] + 7.0*X[2] + 8.0*X[3]*X[3]/2.;\n\n    // create f: X -> Y and stop tape recording\n    CppAD::ADFun<double> f(X, Y);\n\n    // new value for the independent variable vector\n    BaseVector x(n);\n    for(j = 0; j < n; j++)\n        x[j] = double(j);\n\n    // Jacobian of y without sparsity pattern\n    BaseVector jac(m * n);\n    jac = f.SparseJacobian(x);\n    /*\n             [ 1 2 0 0    ]\n    jac = [ 0 0 3 4    ]\n             [ 5 6 7 8*x_3]\n    */\n    BaseVector check(m * n);\n    check[0] = 1.; check[1] = 2.; check[2]  = 0.; check[3]  = 0.;\n    check[4] = 0.; check[5] = 0.; check[6]  = 3.; check[7]  = 4.;\n    check[8] = 5.; check[9] = 6.; check[10] = 7.; check[11] = 8.*x[3];\n    for(k = 0; k < 12; k++)\n        ok &=  NearEqual(check[k], jac[k], eps99, eps99 );\n\n    // test passing sparsity pattern\n    BoolVector s(m * m);\n    BoolVector p(m * n);\n    for(i = 0; i < m; i++)\n    {   for(k = 0; k < m; k++)\n            s[i * m + k] = false;\n        s[i * m + i] = true;\n    }\n    p   = f.RevSparseJac(m, s);\n    jac = f.SparseJacobian(x, p);\n    for(k = 0; k < 12; k++)\n        ok &=  NearEqual(check[k], jac[k], eps99, eps99 );\n\n    return ok;\n}\n\ntemplate <class BaseVector, class SetVector>\nbool reverse_set(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    size_t i, j, k;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n = 4;\n    CPPAD_TESTVECTOR(AD<double>)  X(n);\n    for(j = 0; j < n; j++)\n        X[j] = AD<double> (0);\n\n    // declare independent variables and starting recording\n    CppAD::Independent(X);\n\n    size_t m = 3;\n    CPPAD_TESTVECTOR(AD<double>)  Y(m);\n    Y[0] = X[0] + X[1];\n    Y[1] = X[2] + X[3];\n    Y[2] = X[0] + X[1] + X[2] + X[3] * X[3] / 2.;\n\n    // create f: X -> Y and stop tape recording\n    CppAD::ADFun<double> f(X, Y);\n\n    // new value for the independent variable vector\n    BaseVector x(n);\n    for(j = 0; j < n; j++)\n        x[j] = double(j);\n\n    // Jacobian of y without sparsity pattern\n    BaseVector jac(m * n);\n    jac = f.SparseJacobian(x);\n    /*\n             [ 1 1 0 0  ]\n    jac = [ 0 0 1 1  ]\n             [ 1 1 1 x_3]\n    */\n    BaseVector check(m * n);\n    check[0] = 1.; check[1] = 1.; check[2]  = 0.; check[3]  = 0.;\n    check[4] = 0.; check[5] = 0.; check[6]  = 1.; check[7]  = 1.;\n    check[8] = 1.; check[9] = 1.; check[10] = 1.; check[11] = x[3];\n    for(k = 0; k < 12; k++)\n        ok &=  NearEqual(check[k], jac[k], eps99, eps99 );\n\n    // test passing sparsity pattern\n    SetVector s(m), p(m);\n    for(i = 0; i < m; i++)\n        s[i].insert(i);\n    p   = f.RevSparseJac(m, s);\n    jac = f.SparseJacobian(x, p);\n    for(k = 0; k < 12; k++)\n        ok &=  NearEqual(check[k], jac[k], eps99, eps99 );\n\n    return ok;\n}\n\ntemplate <class BaseVector, class BoolVector>\nbool forward_bool(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    size_t j, k;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n = 3;\n    CPPAD_TESTVECTOR(AD<double>)  X(n);\n    for(j = 0; j < n; j++)\n        X[j] = AD<double> (0);\n\n    // declare independent variables and starting recording\n    CppAD::Independent(X);\n\n    size_t m = 4;\n    CPPAD_TESTVECTOR(AD<double>)  Y(m);\n    Y[0] = X[0] + X[2];\n    Y[1] = X[0] + X[2];\n    Y[2] = X[1] + X[2];\n    Y[3] = X[1] + X[2] * X[2] / 2.;\n\n    // create f: X -> Y and stop tape recording\n    CppAD::ADFun<double> f(X, Y);\n\n    // new value for the independent variable vector\n    BaseVector x(n);\n    for(j = 0; j < n; j++)\n        x[j] = double(j);\n\n    // Jacobian of y without sparsity pattern\n    BaseVector jac(m * n);\n    jac = f.SparseJacobian(x);\n    /*\n             [ 1 0 1   ]\n    jac = [ 1 0 1   ]\n             [ 0 1 1   ]\n             [ 0 1 x_2 ]\n    */\n    BaseVector check(m * n);\n    check[0] = 1.; check[1]  = 0.; check[2]  = 1.;\n    check[3] = 1.; check[4]  = 0.; check[5]  = 1.;\n    check[6] = 0.; check[7]  = 1.; check[8]  = 1.;\n    check[9] = 0.; check[10] = 1.; check[11] = x[2];\n    for(k = 0; k < 12; k++)\n        ok &=  NearEqual(check[k], jac[k], eps99, eps99 );\n\n    // test passing sparsity pattern\n    BoolVector r(n * n);\n    BoolVector p(m * n);\n    for(j = 0; j < n; j++)\n    {   for(k = 0; k < n; k++)\n            r[j * n + k] = false;\n        r[j * n + j] = true;\n    }\n    p   = f.ForSparseJac(n, r);\n    jac = f.SparseJacobian(x, p);\n    for(k = 0; k < 12; k++)\n        ok &=  NearEqual(check[k], jac[k], eps99, eps99 );\n\n    return ok;\n}\n\ntemplate <class BaseVector, class SetVector>\nbool forward_set(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    size_t j, k;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // domain space vector\n    size_t n = 3;\n    CPPAD_TESTVECTOR(AD<double>)  X(n);\n    for(j = 0; j < n; j++)\n        X[j] = AD<double> (0);\n\n    // declare independent variables and starting recording\n    CppAD::Independent(X);\n\n    size_t m = 4;\n    CPPAD_TESTVECTOR(AD<double>)  Y(m);\n    Y[0] = X[0] + X[2];\n    Y[1] = X[0] + X[2];\n    Y[2] = X[1] + X[2];\n    Y[3] = X[1] + X[2] * X[2] / 2.;\n\n    // create f: X -> Y and stop tape recording\n    CppAD::ADFun<double> f(X, Y);\n\n    // new value for the independent variable vector\n    BaseVector x(n);\n    for(j = 0; j < n; j++)\n        x[j] = double(j);\n\n    // Jacobian of y without sparsity pattern\n    BaseVector jac(m * n);\n    jac = f.SparseJacobian(x);\n    /*\n             [ 1 0 1   ]\n    jac = [ 1 0 1   ]\n             [ 0 1 1   ]\n             [ 0 1 x_2 ]\n    */\n    BaseVector check(m * n);\n    check[0] = 1.; check[1]  = 0.; check[2]  = 1.;\n    check[3] = 1.; check[4]  = 0.; check[5]  = 1.;\n    check[6] = 0.; check[7]  = 1.; check[8]  = 1.;\n    check[9] = 0.; check[10] = 1.; check[11] = x[2];\n    for(k = 0; k < 12; k++)\n        ok &=  NearEqual(check[k], jac[k], eps99, eps99 );\n\n    // test passing sparsity pattern\n    SetVector r(n), p(m);\n    for(j = 0; j < n; j++)\n        r[j].insert(j);\n    p   = f.ForSparseJac(n, r);\n    jac = f.SparseJacobian(x, p);\n    for(k = 0; k < 12; k++)\n        ok &=  NearEqual(check[k], jac[k], eps99, eps99 );\n\n    return ok;\n}\n\nbool multiple_of_n_bit(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::vector;\n    size_t i, j;\n\n    // should be the same as the corresponding typedef in\n    // cppad/local/sparse/pack.hpp\n    typedef size_t Pack;\n\n    // number of bits per packed value\n    size_t n_bit = std::numeric_limits<Pack>::digits;\n\n    // check case where number of variables is equal to n_bit\n    vector< AD<double> > x(n_bit);\n    vector< AD<double> > y(n_bit);\n\n    // create an AD function with domain and range dimension equal to n_bit\n    CppAD::Independent(x);\n    for(i = 0; i < n_bit; i++)\n        y[i] = x[n_bit - i - 1];\n    CppAD::ADFun<double> f(x, y);\n\n    // Jacobian sparsity patterns\n    vector<bool> r(n_bit * n_bit);\n    vector<bool> s(n_bit * n_bit);\n    for(i = 0; i < n_bit; i++)\n    {   for(j = 0; j < n_bit; j++)\n            r[ i * n_bit + j ] = (i == j);\n    }\n    s = f.ForSparseJac(n_bit, r);\n\n    // check the result\n    for(i = 0; i < n_bit; i++)\n    {   for(j = 0; j < n_bit; j++)\n        {   if( i == n_bit - j - 1 )\n                ok = ok & s[ i * n_bit + j ];\n            else\n                ok = ok & (! s[i * n_bit + j] );\n        }\n    }\n\n    return ok;\n}\n\n// check for a sparse_list bug that was fixed on 2017-04-06\nvoid algo_sparse_list_bug(\n    const CppAD::vector < CppAD::AD<double> >& ax ,\n    CppAD::vector < CppAD::AD<double> >&       ay )\n{\n    ay[2] = 1.0;\n    ay[0] = 1.0;\n    ay[1] = ax[2];\n    ay[3] = ax[2];\n}\nbool sparse_list_bug(void)\n{   bool ok  = true;\n    using CppAD::AD;\n    using CppAD::vector;\n    typedef CppAD::vector < std::set<size_t> > sparsity;\n    //\n    size_t n = 4;\n    vector< AD<double> > ay(n), ax(n);\n    for(size_t i = 0; i < n; ++i)\n        ax[i] = 1.0;\n    //\n    // sparsity pattern corresponding to identity matrix\n    sparsity eye(n);\n    for (size_t i = 0; i < n; i++)\n        eye[i].insert(i);\n    //\n    CppAD::checkpoint<double> atom_fun(\n        \"sparse_list_bug\",\n        algo_sparse_list_bug,\n        ax,\n        ay,\n        CppAD::atomic_base<double>::set_sparsity_enum\n    );\n    //\n    vector < AD<double> > au(n);\n    for (size_t j = 0; j < n; j++)\n        au[j] = 1.0;\n    //\n    // version of function that uses atom_fun\n    CppAD::Independent(au);\n    vector< AD<double> > av(n);\n    atom_fun(au, ay);\n    for (size_t j = 0; j < n; j++) {\n        av[j] = ay[j] +  au[j];\n    }\n    CppAD::ADFun<double> yes_atom_fun(au, av);\n    //\n    // version of function that uses algoright\n    CppAD::Independent(au);\n    algo_sparse_list_bug(au, ay);\n    for (size_t j = 0; j < n; j++) {\n        av[j] = ay[j] +  au[j];\n    }\n    CppAD::ADFun<double> no_atom_fun(au, av);\n\n    //\n    sparsity pattern_yes = yes_atom_fun.RevSparseJac(n, eye);\n    sparsity pattern_no  = no_atom_fun.RevSparseJac(n, eye);\n    //\n    for(size_t i = 0; i < n; i++)\n        ok &= pattern_yes[i] == pattern_no[i];\n    //\n    return ok;\n}\n\n\n\n} // End empty namespace\n\n# include <vector>\n# include <valarray>\nbool sparse_jacobian(void)\n{   bool ok = true;\n    ok &= rc_tridiagonal();\n    ok &= multiple_of_n_bit();\n    ok &= sparse_list_bug();\n    // ---------------------------------------------------------------\n    // vector of bool cases\n    ok &=      rc_bool< CppAD::vector<double>, CppAD::vectorBool   >();\n    ok &= forward_bool< CppAD::vector<double>, CppAD::vector<bool> >();\n    //\n    ok &= reverse_bool< std::vector<double>,   std::vector<bool>   >();\n    ok &=      rc_bool< std::vector<double>,   std::valarray<bool> >();\n    //\n    ok &= forward_bool< std::valarray<double>, CppAD::vectorBool   >();\n    ok &= reverse_bool< std::valarray<double>, CppAD::vector<bool> >();\n    // ---------------------------------------------------------------\n    // vector of set cases\n    typedef std::vector< std::set<size_t> >   std_vector_set;\n    typedef CppAD::vector< std::set<size_t> > cppad_vector_set;\n    //\n    ok &=      rc_set< CppAD::vector<double>, std_vector_set   >();\n    ok &= forward_set< std::valarray<double>, std_vector_set   >();\n    //\n    ok &= reverse_set< std::vector<double>,   cppad_vector_set >();\n    ok &=      rc_set< CppAD::vector<double>, cppad_vector_set >();\n    //\n    // According to section 26.3.2.3 of the 1998 C++ standard\n    // a const valarray does not return references to its elements.\n    // typedef std::valarray< std::set<size_t> > std_valarray_set;\n    // ok &= forward_set< std::valarray<double>, std_valarray_set >();\n    // ok &= reverse_set< std::valarray<double>, std_valarray_set >();\n    // ---------------------------------------------------------------\n    //\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/sparse_sub_hes.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\n@begin sparse_sub_hes.cpp$$\n$spell\n$$\n\n$section Sparse Hessian on Subset of Variables: Example and Test$$\n\n$head Purpose$$\nThis example uses a\n$cref/column subset/sparse_hessian/p/Column Subset/$$ of the sparsity pattern\nto compute the Hessian for a subset of the variables.\nThe values in the rest of the sparsity pattern do not matter.\n\n$head See Also$$\n$cref sub_sparse_hes.cpp$$\n\n$end\n*/\n// BEGIN C++\n# include <cppad/cppad.hpp>\nnamespace { // BEGIN_EMPTY_NAMESPACE\n\n// --------------------------------------------------------------------------\nvoid record_function(CppAD::ADFun<double>& f, size_t n)\n{   // must be greater than or equal 3; see n_sweep below\n    assert( n >= 3 );\n    //\n    using CppAD::AD;\n    typedef CppAD::vector< AD<double> >     a_vector;\n    //\n    // domain space vector\n    a_vector a_x(n);\n    for(size_t j = 0; j < n; j++)\n        a_x[j] = AD<double> (0);\n\n    // declare independent variables and starting recording\n    CppAD::Independent(a_x);\n\n    // range space vector\n    size_t m = 1;\n    a_vector a_y(m);\n    a_y[0] = 0.0;\n    for(size_t j = 1; j < n; j++)\n        a_y[0] += a_x[j-1] * a_x[j] * a_x[j];\n\n    // create f: x -> y and stop tape recording\n    // (without executing zero order forward calculation)\n    f.Dependent(a_x, a_y);\n    //\n    return;\n}\n// --------------------------------------------------------------------------\nbool test_set(const char* color_method)\n{   bool ok = true;\n    //\n    typedef CppAD::vector< double >                   d_vector;\n    typedef CppAD::vector<size_t>                     i_vector;\n    typedef CppAD::vector< std::set<size_t> >         s_vector;\n    //\n    size_t n = 12;\n    CppAD::ADFun<double> f;\n    record_function(f, n);\n    //\n    // sparsity patteren for the sub-set of variables we are computing\n    // the hessian w.r.t.\n    size_t n_sub = 4;\n    s_vector r(n);\n    for(size_t j = 0; j < n_sub; j++)\n    {   assert(  r[j].empty() );\n        r[j].insert(j);\n    }\n\n    // store forward sparsity for J(x) = F^{(1)} (x) * R\n    f.ForSparseJac(n_sub, r);\n\n    // compute sparsity pattern for H(x) = (S * F)^{(2)} ( x ) * R\n    s_vector s(1);\n    assert(  s[0].empty() );\n    s[0].insert(0);\n    bool transpose = true;\n    s_vector h = f.RevSparseHes(n_sub, s, transpose);\n\n    // set the row and column indices that correspond to lower triangle\n    i_vector row, col;\n    for(size_t i = 0; i < n_sub; i++)\n    {   if( i > 0 )\n        {   // diagonal element\n            row.push_back(i);\n            col.push_back(i);\n            // lower diagonal element\n            row.push_back(i);\n            col.push_back(i-1);\n        }\n    }\n\n    // weighting for the Hessian\n    d_vector w(1);\n    w[0] = 1.0;\n\n    // compute Hessian\n    CppAD::sparse_hessian_work work;\n    work.color_method = color_method;\n    d_vector x(n), hes( row.size() );\n    for(size_t j = 0; j < n; j++)\n        x[j] = double(j+1);\n    f.SparseHessian(x, w, h, row, col, hes, work);\n\n    // check the values in the sparse hessian\n    for(size_t ell = 0; ell < row.size(); ell++)\n    {   size_t i = row[ell];\n        size_t j = col[ell];\n        if( i == j )\n            ok &= hes[ell] == 2.0 * x[i-1];\n        else\n        {   ok &= j+1 == i;\n            ok &= hes[ell] == 2.0 * x[i];\n        }\n    }\n    return ok;\n}\n// --------------------------------------------------------------------------\nbool test_bool(const char* color_method)\n{   bool ok = true;\n    //\n    typedef CppAD::vector< double >    d_vector;\n    typedef CppAD::vector<size_t>      i_vector;\n    typedef CppAD::vector<bool>        s_vector;\n    //\n    size_t n = 12;\n    CppAD::ADFun<double> f;\n    record_function(f, n);\n    //\n    // sparsity patteren for the sub-set of variables we are computing\n    // the hessian w.r.t.\n    size_t n_sub = 4;\n    s_vector r(n * n_sub);\n    for(size_t i = 0; i < n; i++)\n    {   for(size_t j = 0; j < n_sub; j++)\n            r[ i * n_sub + j ] = (i == j);\n    }\n\n    // store forward sparsity for J(x) = F^{(1)} (x) * R\n    f.ForSparseJac(n_sub, r);\n\n    // compute sparsity pattern for H(x) = (S * F)^{(2)} ( x ) * R\n    s_vector s(1);\n    s[0] = true;\n    bool transpose = true;\n    s_vector h = f.RevSparseHes(n_sub, s, transpose);\n\n    // set the row and column indices that correspond to lower triangle\n    i_vector row, col;\n    for(size_t i = 0; i < n_sub; i++)\n    {   if( i > 0 )\n        {   // diagonal element\n            row.push_back(i);\n            col.push_back(i);\n            // lower diagonal element\n            row.push_back(i);\n            col.push_back(i-1);\n        }\n    }\n\n    // weighting for the Hessian\n    d_vector w(1);\n    w[0] = 1.0;\n\n    // extend sparsity pattern (values in extended columns do not matter)\n    s_vector h_extended(n * n);\n    for(size_t i = 0; i < n; i++)\n    {   for(size_t j = 0; j < n_sub; j++)\n            h_extended[ i * n + j ] = h[ i * n_sub + j ];\n        for(size_t j = n_sub; j < n; j++)\n            h_extended[ i * n + j ] = false;\n    }\n    // compute Hessian\n    CppAD::sparse_hessian_work work;\n    work.color_method = color_method;\n    d_vector x(n), hes( row.size() );\n    for(size_t j = 0; j < n; j++)\n        x[j] = double(j+1);\n    f.SparseHessian(x, w, h_extended, row, col, hes, work);\n\n    // check the values in the sparse hessian\n    for(size_t ell = 0; ell < row.size(); ell++)\n    {   size_t i = row[ell];\n        size_t j = col[ell];\n        if( i == j )\n            ok &= hes[ell] == 2.0 * x[i-1];\n        else\n        {   ok &= j+1 == i;\n            ok &= hes[ell] == 2.0 * x[i];\n        }\n    }\n    return ok;\n}\n} // END_EMPTY_NAMESPACE\n\nbool sparse_sub_hes(void)\n{   bool ok = true;\n    ok &= test_set(\"cppad.symmetric\");\n    ok &= test_set(\"cppad.general\");\n    //\n    ok &= test_bool(\"cppad.symmetric\");\n    ok &= test_bool(\"cppad.general\");\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "test_more/general/sparse_vec_ad.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n\n# include <cppad/cppad.hpp>\n\nbool sparse_vec_ad(void)\n{   bool ok = true;\n    using namespace CppAD;\n\n    // dimension of the domain space\n    size_t n = 3;\n\n    size_t i, j;\n\n    // independent variable vector\n    CPPAD_TESTVECTOR(AD<double>) X(n);\n    for(j = 0; j < n; j++)\n        X[j] = AD<double>(j);\n    Independent(X);\n\n    // dependent variable vector\n    size_t m = n;\n    CPPAD_TESTVECTOR(AD<double>) Y(m);\n\n    // check results vector\n    CPPAD_TESTVECTOR( bool )  Check(m * n);\n\n    // Create a VecAD so that there are two in the tape and the sparsity\n    // pattern depends on the second one (checks addressing VecAD objects)\n    VecAD<double> W(n);\n\n    // VecAD equal to X\n    VecAD<double> Z(n);\n    AD<double> J;\n    for(j = 0; j < n; j++)\n    {   J    = AD<double>(j);\n        W[J] = X[0];\n        Z[J] = X[j];\n\n        // y[i] depends on x[j] for j <= i\n        // (and is non-linear for j <= 1).\n        if( j == 1 )\n            Y[j] = Z[J] * Z[J];\n        else\n            Y[j] = Z[J];\n    }\n\n    // compute dependent variables values\n    AD<double> P = 1;\n    J = AD<double>(0);\n    for(j = 0; j < n; j++)\n    {   for(i = 0; i < m; i++)\n            Check[ i * m + j ] = (j <= i);\n    }\n\n    // create function object F : X -> Y\n    ADFun<double> F(X, Y);\n\n    // dependency matrix for the identity function W(x) = x\n    CPPAD_TESTVECTOR( bool ) Identity(n * n);\n    for(i = 0; i < n; i++)\n    {   for(j = 0; j < n; j++)\n            Identity[ i * n + j ] = false;\n        Identity[ i * n + i ] = true;\n    }\n    // evaluate the dependency matrix for Identity(F(x))\n    CPPAD_TESTVECTOR( bool ) Px(m * n);\n    Px = F.RevSparseJac(n, Identity);\n\n    // check values\n    for(i = 0; i < m; i++)\n    {   for(j = 0; j < n; j++)\n            ok &= (Px[i * m + j] == Check[i * m + j]);\n    }\n\n    // evaluate the dependency matrix for F(Identity(x))\n    CPPAD_TESTVECTOR( bool ) Py(m * n);\n    Py = F.ForSparseJac(n, Identity);\n\n    // check values\n    for(i = 0; i < m; i++)\n    {   for(j = 0; j < n; j++)\n            ok &= (Py[i * m + j] == Check[i * m + j]);\n    }\n\n    // test sparsity pattern for Hessian of F_2 ( Identity(x) )\n    CPPAD_TESTVECTOR(bool) Hy(m);\n    for(i = 0; i < m; i++)\n        Hy[i] = false;\n    Hy[2] = true;\n    CPPAD_TESTVECTOR(bool) Pxx(n * n);\n    Pxx = F.RevSparseHes(n, Hy);\n    for(i = 0; i < n; i++)\n    {   for(j = 0; j < n; j++)\n            ok &= (Pxx[i * n + j] == false );\n    }\n\n    // test sparsity pattern for Hessian of F_1 ( Identity(x) )\n    for(i = 0; i < m; i++)\n        Hy[i] = false;\n    Hy[1] = true;\n    Pxx = F.RevSparseHes(n, Hy);\n    for(i = 0; i < n; i++)\n    {   for(j = 0; j < n; j++)\n            ok &= (Pxx[i * n + j] == ( (i <= 1) && (j <= 1) ) );\n    }\n\n\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/sqrt.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\nTwo old sqrt examples now used just for validation testing.\n*/\n# include <cppad/cppad.hpp>\n# include <cmath>\n\nnamespace { // BEGIN empty namespace\n\nbool SqrtTestOne(void)\n{   bool ok = true;\n    using CppAD::sqrt;\n    using CppAD::pow;\n    using namespace CppAD;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // independent variable vector, indices, values, and declaration\n    CPPAD_TESTVECTOR(AD<double>) U(1);\n    size_t s = 0;\n    U[s]     = 4.;\n    Independent(U);\n\n    // dependent variable vector, indices, and values\n    CPPAD_TESTVECTOR(AD<double>) Z(2);\n    size_t x = 0;\n    size_t y = 1;\n    Z[x]     = sqrt(U[s]);\n    Z[y]     = sqrt(Z[x]);\n\n    // define f : U -> Z and vectors for derivative calculations\n    ADFun<double> f(U, Z);\n    CPPAD_TESTVECTOR(double) v( f.Domain() );\n    CPPAD_TESTVECTOR(double) w( f.Range() );\n\n    // check values\n    ok &= NearEqual(Z[x] , 2.,        eps99 , eps99);\n    ok &= NearEqual(Z[y] , sqrt(2.),  eps99 , eps99);\n\n    // forward computation of partials w.r.t. s\n    v[s] = 1.;\n    w    = f.Forward(1, v);\n    ok &= NearEqual(w[x], .5  * pow(4., -.5),   eps99 , eps99); // dx/ds\n    ok &= NearEqual(w[y], .25 * pow(4., -.75),  eps99 , eps99); // dy/ds\n\n    // reverse computation of partials of y\n    w[x] = 0.;\n    w[y] = 1.;\n    v    = f.Reverse(1,w);\n    ok &= NearEqual(v[s], .25 * pow(4., -.75),  eps99 , eps99); // dy/ds\n\n    // forward computation of second partials w.r.t s\n    v[s] = 1.;\n    w    = f.Forward(1, v);\n    v[s] = 0.;\n    w    = f.Forward(2, v);\n    ok &= NearEqual(       // d^2 y / (ds ds)\n        2. * w[y] ,\n        -.75 * .25 * pow(4., -1.75),\n        eps99 ,\n        eps99\n    );\n\n    // reverse computation of second partials of y\n    CPPAD_TESTVECTOR(double) r( f.Domain() * 2 );\n    w[x] = 0.;\n    w[y] = 1.;\n    r    = f.Reverse(2, w);\n    ok &= NearEqual(      // d^2 y / (ds ds)\n        r[2 * s + 1] ,\n        -.75 * .25 * pow(4., -1.75),\n        eps99 ,\n        eps99\n    );\n\n    return ok;\n\n}\nbool SqrtTestTwo(void)\n{   bool ok = true;\n    using namespace CppAD;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // independent variable vector\n    CPPAD_TESTVECTOR(AD<double>) U(1);\n    U[0]     = 2.;\n    Independent(U);\n\n    // a temporary values\n    AD<double> x = U[0] * U[0];\n\n    // dependent variable vector\n    CPPAD_TESTVECTOR(AD<double>) Z(1);\n    Z[0] =  sqrt( x ); // z = sqrt( u * u )\n\n    // create f: U -> Z and vectors used for derivative calculations\n    ADFun<double> f(U, Z);\n    CPPAD_TESTVECTOR(double) v(1);\n    CPPAD_TESTVECTOR(double) w(1);\n\n    // check value\n    ok &= NearEqual(U[0] , Z[0],  eps99 , eps99);\n\n    // forward computation of partials w.r.t. u\n    size_t j;\n    size_t p     = 5;\n    double jfac  = 1.;\n    double value = 1.;\n    v[0]         = 1.;\n    for(j = 1; j < p; j++)\n    {   jfac *= double(j);\n        w     = f.Forward(j, v);\n        ok &= NearEqual(w[0], value/jfac, eps99, eps99); // d^jz/du^j\n        v[0]  = 0.;\n        value = 0.;\n    }\n\n    // reverse computation of partials of Taylor coefficients\n    CPPAD_TESTVECTOR(double) r(p);\n    w[0]  = 1.;\n    r     = f.Reverse(p, w);\n    jfac  = 1.;\n    value = 1.;\n    for(j = 0; j < p; j++)\n    {   ok &= NearEqual(r[j], value/jfac, eps99, eps99); // d^jz/du^j\n        jfac *= double(j + 1);\n        value = 0.;\n    }\n\n    return ok;\n}\nbool SqrtTestThree(void)\n{   bool ok = true;\n    using CppAD::sqrt;\n    using CppAD::exp;\n    using namespace CppAD;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // independent variable vector, indices, values, and declaration\n    double x = 4.;\n    CPPAD_TESTVECTOR(AD<double>) X(1);\n    X[0]     = x;\n    Independent(X);\n\n    // dependent variable vector, indices, and values\n    CPPAD_TESTVECTOR(AD<double>) Y(1);\n    Y[0]     = sqrt( exp(X[0]) );\n\n    // define f : X -> Y and vectors for derivative calculations\n    ADFun<double> f(X, Y);\n\n    // forward computation of first Taylor coefficient\n    CPPAD_TESTVECTOR(double) x1( f.Domain() );\n    CPPAD_TESTVECTOR(double) y1( f.Range() );\n    x1[0] = 1.;\n    y1    = f.Forward(1, x1);\n    ok   &= NearEqual(y1[0], exp(x/2.)/2.,   eps99 , eps99);\n\n    // forward computation of second Taylor coefficient\n    CPPAD_TESTVECTOR(double) x2( f.Domain() );\n    CPPAD_TESTVECTOR(double) y2( f.Range() );\n    x2[0] = 0.;\n    y2    = f.Forward(2, x2);\n    ok   &= NearEqual(2.*y2[0] , exp(x/2.)/4., eps99 , eps99 );\n\n    // forward computation of third Taylor coefficient\n    CPPAD_TESTVECTOR(double) x3( f.Domain() );\n    CPPAD_TESTVECTOR(double) y3( f.Range() );\n    x3[0] = 0.;\n    y3    = f.Forward(3, x3);\n    ok   &= NearEqual(6.*y3[0] , exp(x/2.)/8., eps99 , eps99 );\n\n    // reverse computation of deritavitve of Taylor coefficients\n    CPPAD_TESTVECTOR(double) r( f.Domain() * 4 );\n    CPPAD_TESTVECTOR(double) w(1);\n    w[0] = 1.;\n    r    = f.Reverse(4, w);\n    ok   &= NearEqual(r[0], exp(x/2.)/2., eps99 , eps99);\n    ok   &= NearEqual(r[1], exp(x/2.)/4., eps99 , eps99 );\n    ok   &= NearEqual(2.*r[2], exp(x/2.)/8., eps99 , eps99 );\n    ok   &= NearEqual(6.*r[3], exp(x/2.)/16., eps99 , eps99 );\n\n    return ok;\n\n}\n\n} // END empty namespace\n\nbool Sqrt(void)\n{   bool ok = true;\n    ok &= SqrtTestOne();\n    ok &= SqrtTestTwo();\n    ok &= SqrtTestThree();\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/std_math.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\nTest the using standard math functions with AD< AD<double> >\n*/\n\n# include <cppad/cppad.hpp>\n\ntypedef CppAD::AD<double>      ADdouble;\ntypedef CppAD::AD< ADdouble > ADDdouble;\n\nbool std_math(void)\n{   using CppAD::NearEqual;\n    bool ok = true;\n    ADDdouble half(.5);\n    ADDdouble one(1.);\n    ADDdouble two(2.);\n    ADDdouble ten(10.);\n    ADDdouble eps(1e-6);\n    ADDdouble pi_4(3.141592653 / 4.);\n    ADDdouble root_2( sqrt(two) );\n\n    ADDdouble y( acos(one / root_2) );\n    ok &= NearEqual( pi_4, y, eps, eps );\n\n    y = cos(pi_4);\n    ok &= NearEqual( one / root_2, y, eps, eps );\n\n    y = asin(one / root_2);\n    ok &= NearEqual( pi_4, y, eps, eps );\n\n    y = sin(pi_4);\n    ok &= NearEqual( one / root_2, y, eps, eps );\n\n    y = atan(one);\n    ok &= NearEqual( pi_4, y, eps, eps );\n\n    y = tan(pi_4);\n    ok &= NearEqual( one, y, eps, eps );\n\n    y = two * cosh(one);\n    ok &= NearEqual( exp(one) + exp(-one), y, eps, eps );\n\n    y = two * sinh(one);\n    ok &= NearEqual( exp(one) - exp(-one), y, eps, eps );\n\n    y = log( exp(one) );\n    ok &= NearEqual( one, y, eps, eps );\n\n    y = log10( exp( log(ten) ) );\n    ok &= NearEqual( one, y, eps, eps );\n\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/sub.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n\n/*\nTwo old Sub examples now used just for valiadation testing\n*/\n# include <cppad/cppad.hpp>\n\nnamespace { // BEGIN empty namespace\n\nbool One(void)\n{   bool ok = true;\n\n    using namespace CppAD;\n\n\n    // independent variable vector, indices, values, and declaration\n    CPPAD_TESTVECTOR(AD<double>) U(2);\n    size_t s = 0;\n    size_t t = 1;\n    U[s] = 3.;\n    U[t] = 2.;\n    Independent(U);\n\n    // dependent variable vector and indices\n    CPPAD_TESTVECTOR(AD<double>) Z(3);\n    size_t x = 0;\n    size_t y = 1;\n    size_t z = 2;\n\n    // dependent variable values\n    Z[x] = U[s]  - U[t];   // AD<double> - AD<double>\n    Z[y] = Z[x]  - 1.;     // AD<double> - double\n    Z[z] = 1.    - Z[y];   // double - AD<double>\n\n    // create f: U -> Z and vectors used for derivative calculations\n    ADFun<double> f(U, Z);\n    CPPAD_TESTVECTOR(double) v( f.Domain() );\n    CPPAD_TESTVECTOR(double) w( f.Range() );\n\n    // check function values\n    ok &= ( Z[x] == 3. - 2. );\n    ok &= ( Z[y] == 3. - 2. - 1. );\n    ok &= ( Z[z] == 1. - 3. + 2. + 1. );\n\n    // forward computation of partials w.r.t. s\n    v[s] = 1.;\n    v[t] = 0.;\n    w = f.Forward(1, v);\n    ok &= ( w[x] == 1. );   // dx/ds\n    ok &= ( w[y] == 1. );   // dy/ds\n    ok &= ( w[z] == -1. );   // dz/ds\n\n    // reverse computation of second partials of z\n    CPPAD_TESTVECTOR(double) r( f.Domain() * 2 );\n    w[x] = 0.;\n    w[y] = 0.;\n    w[z] = 1.;\n    r = f.Reverse(2, w);\n    ok &= ( r[2 * s + 1] == 0. );  // d^2 z / (ds ds)\n    ok &= ( r[2 * t + 1] == 0. );  // d^2 z / (ds dt)\n\n    return ok;\n\n}\n\nbool Two(void)\n{   bool ok = true;\n    using namespace CppAD;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // independent variable vector\n    double u0 = .5;\n    CPPAD_TESTVECTOR(AD<double>) U(1);\n    U[0]      = u0;\n    Independent(U);\n\n    AD<double> a = 2. * U[0] - 1.; // AD<double> - double\n    AD<double> b = a  - 2;         // AD<double> - int\n    AD<double> c = 3. - b;         // double     - AD<double>\n    AD<double> d = 4  - c;         // int        - AD<double>\n\n    // dependent variable vector\n    CPPAD_TESTVECTOR(AD<double>) Z(1);\n    Z[0] = U[0] - d;          // AD<double> - AD<double>\n\n    // create f: U -> Z and vectors used for derivative calculations\n    ADFun<double> f(U, Z);\n    CPPAD_TESTVECTOR(double) v(1);\n    CPPAD_TESTVECTOR(double) w(1);\n\n    // check value\n    ok &= NearEqual(Value(Z[0]) , u0-4+3-2*u0+1+2,  eps99 , eps99);\n\n    // forward computation of partials w.r.t. u\n    size_t j;\n    size_t p     = 5;\n    double jfac  = 1.;\n    double value = -1.;\n    v[0]         = 1.;\n    for(j = 1; j < p; j++)\n    {   jfac *= double(j);\n        w     = f.Forward(j, v);\n        ok &= NearEqual(w[0], value/jfac, eps99, eps99); // d^jz/du^j\n        v[0]  = 0.;\n        value = 0.;\n    }\n\n    // reverse computation of partials of Taylor coefficients\n    CPPAD_TESTVECTOR(double) r(p);\n    w[0]  = 1.;\n    r     = f.Reverse(p, w);\n    jfac  = 1.;\n    value = -1.;\n    for(j = 0; j < p; j++)\n    {   ok &= NearEqual(r[j], value/jfac, eps99, eps99); // d^jz/du^j\n        jfac *= double(j + 1);\n        value = 0.;\n    }\n\n    return ok;\n}\n\nbool Three(void)\n{   bool ok = true;\n    using namespace CppAD;\n\n    // special cases where tests above check OK and SubpvOp\n    // implementation is known to be wrong.\n    // Probably two minuses make a plus.\n    size_t n = 1;\n    CPPAD_TESTVECTOR(AD<double>) X(n);\n    X[0] = 1.;\n    Independent(X);\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) Y(m);\n    Y[0] = 1. - X[0];\n    ADFun<double> f(X, Y);\n\n    CPPAD_TESTVECTOR(double) w(m), dw(n);\n    w[0] = 1.;\n    dw = f.Reverse(1, w);\n    ok &= (dw[0] == -1.);\n\n    return ok;\n}\n\nbool Four(void)\n{   bool ok = true;\n    using namespace CppAD;\n\n    // special cases where parameter number is equal to\n    // variable index in result.\n    size_t n = 1;\n    CPPAD_TESTVECTOR(AD<double>) X(n);\n    X[0] = 1.;\n    Independent(X);\n    size_t m = 1;\n    CPPAD_TESTVECTOR(AD<double>) Y(m);\n    if( 0. < X[0] && X[0] < 10. )\n        Y[0] = X[0] - 2.;\n    else\n        Y[0] = X[0] - 2.;\n    ADFun<double> f(X, Y);\n\n    CPPAD_TESTVECTOR(double) y(m), x(n);\n    x[0] = 1.;\n    y    = f.Forward(0, x);\n    ok  &= (y[0] == -1.);\n\n    CPPAD_TESTVECTOR(double) dy(m), dx(n);\n    dx[0] = 1.;\n    dy    = f.Forward(1, dx);\n    ok  &= (dy[0] == 1.);\n\n    return ok;\n}\n\n\n} // END empty namespace\n\nbool Sub(void)\n{   bool ok = true;\n    ok &= One();\n    ok &= Two();\n    ok &= Three();\n    ok &= Four();\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/sub_eq.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\nTwo old SubEq examples now used just for valiadation testing\n*/\n# include <cppad/cppad.hpp>\n\nnamespace { // BEGIN empty namespace\n\nbool SubEqTestOne(void)\n{   bool ok = true;\n\n    using namespace CppAD;\n\n    // independent variable vector, indices, values, and declaration\n    CPPAD_TESTVECTOR(AD<double>) U(2);\n    size_t s = 0;\n    size_t t = 1;\n    U[s] = 3.;\n    U[t] = 2.;\n    Independent(U);\n\n    // dependent variable vector and indices\n    CPPAD_TESTVECTOR(AD<double>) Z(2);\n    size_t x = 0;\n    size_t y = 1;\n\n    // dependent variable values\n    Z[x]  = U[s];\n    Z[y]  = U[t];\n    Z[x] -= U[t];  // AD<double> -= AD<double>\n    Z[y] -= 5.;    // AD<double> -= double\n\n    // create f: U -> Z and vectors used for derivative calculations\n    ADFun<double> f(U, Z);\n    CPPAD_TESTVECTOR(double) v( f.Domain() );\n    CPPAD_TESTVECTOR(double) w( f.Range() );\n\n    // check function values\n    ok &= ( Z[x] == 3. - 2. );\n    ok &= ( Z[y] == 2. - 5. );\n\n    // forward computation of partials w.r.t. t\n    v[s] = 0.;\n    v[t] = 1.;\n    w = f.Forward(1, v);\n    ok &= ( w[x] == -1. );  // dx/dt\n    ok &= ( w[y] == 1. );   // dy/dt\n\n    // reverse computation of second partials of x\n    CPPAD_TESTVECTOR(double) r( f.Domain() * 2 );\n    w[x] = 1.;\n    w[y] = 0.;\n    r = f.Reverse(2, w);\n    ok &= ( r[2 * s + 1] == 0. );  // d^2 x / (ds ds)\n    ok &= ( r[2 * t + 1] == 0. );  // d^2 x / (ds dt)\n\n    return ok;\n}\n\nbool SubEqTestTwo(void)\n{   bool ok = true;\n    using namespace CppAD;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    // independent variable vector\n    double u0 = .5;\n    CPPAD_TESTVECTOR(AD<double>) U(1);\n    U[0]      = u0;\n    Independent(U);\n\n    // dependent variable vector\n    CPPAD_TESTVECTOR(AD<double>) Z(1);\n    Z[0] = U[0];       // initial value\n    Z[0] -= 2;         // AD<double> -= int\n    Z[0] -= 4.;        // AD<double> -= double\n    Z[0] -= 2 * U[0];  // AD<double> -= AD<double>\n\n    // create f: U -> Z and vectors used for derivative calculations\n    ADFun<double> f(U, Z);\n    CPPAD_TESTVECTOR(double) v(1);\n    CPPAD_TESTVECTOR(double) w(1);\n\n    // check value\n    ok &= NearEqual(Z[0] , u0-2-4-2*u0,  eps99 , eps99);\n\n    // forward computation of partials w.r.t. u\n    size_t j;\n    size_t p     = 5;\n    double jfac  = 1.;\n    double value = -1.;\n    v[0]         = 1.;\n    for(j = 1; j < p; j++)\n    {   jfac *= double(j);\n        w     = f.Forward(j, v);\n        ok &= NearEqual(w[0], value/jfac, eps99, eps99); // d^jz/du^j\n        v[0]  = 0.;\n        value = 0.;\n    }\n\n    // reverse computation of partials of Taylor coefficients\n    CPPAD_TESTVECTOR(double) r(p);\n    w[0]  = 1.;\n    r     = f.Reverse(p, w);\n    jfac  = 1.;\n    value = -1.;\n    for(j = 0; j < p; j++)\n    {   ok &= NearEqual(r[j], value/jfac, eps99, eps99); // d^jz/du^j\n        jfac *= double(j + 1);\n        value = 0.;\n    }\n\n    return ok;\n}\n\n} // END empty namespace\n\nbool SubEq(void)\n{   bool ok = true;\n    ok &= SubEqTestOne();\n    ok &= SubEqTestTwo();\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/sub_zero.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\nTest the use of the special parameters zero and one with the multiply operator\n*/\n\n# include <cppad/cppad.hpp>\n\ntypedef CppAD::AD<double>      ADdouble;\ntypedef CppAD::AD< ADdouble > ADDdouble;\n\nbool SubZero(void)\n{\n    using namespace CppAD;\n\n    bool ok = true;\n\n    size_t i;\n    for(i = 0; i < 2; i++)\n    {   // run through the cases x = 0, 1\n\n        size_t j;\n        for(j = 0; j < 2; j++)\n        {   // run through the cases y = 0, 1\n\n            CPPAD_TESTVECTOR( ADdouble ) x(1);\n            x[0] = double(i);\n            Independent(x);\n\n            CPPAD_TESTVECTOR( ADDdouble ) y(1);\n            y[0] = ADDdouble(j);\n            Independent(y);\n\n            CPPAD_TESTVECTOR( ADDdouble ) z(2);\n            z[0]  = x[0] - y[0];\n            z[1]  = y[0] - x[0];\n            z[1] -= x[0];\n\n            // f(y) = z = { x - y , y - x - x }\n            ADFun< ADdouble > f(y, z);\n            CPPAD_TESTVECTOR( ADdouble ) u( f.Domain() );\n            CPPAD_TESTVECTOR( ADdouble ) v( f.Range() );\n\n            // v = f(y)\n            u[0] = ADdouble(j);\n            v = f.Forward(0, u);\n\n            // check value of f\n            ok &= v[0] == x[0] - ADdouble(j);\n            ok &= v[1] == ADdouble(j) - x[0] - x[0];\n\n            // g(x) = f(y) = {x - y , y - x - x}\n            ADFun<double> g(x, v);\n            CPPAD_TESTVECTOR( double ) a( g.Domain() );\n            CPPAD_TESTVECTOR( double ) b( g.Range() );\n\n            // b = g'(x)\n            a[0] = 1.;\n            b = g.Forward(1, a);\n\n            // check derivatives of g\n            ok &= (b[0] == 1.);\n            ok &= (b[1] == -2.);\n\n        }\n    }\n\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/subgraph_1.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n# include <cppad/cppad.hpp>\n\nnamespace {\n    typedef CPPAD_TESTVECTOR(size_t)  svector;\n    typedef CppAD::sparse_rc<svector> sparsity;\n    //\n    using CppAD::AD;\n    typedef CPPAD_TESTVECTOR(AD<double>) avector;\n\n    // ========================================================================\n    // algorithm that will be checkpointed\n    void g_algo(const avector& u, avector& v)\n    {   for(size_t j = 0; j < size_t( u.size() ); ++j)\n            v[0] += u[j];\n    }\n\n    // will be a pointer to atomic version of g_algo\n    CppAD::checkpoint<double>* atom_g = nullptr;\n    // ------------------------------------------------------------------------\n    // record function\n    void record_function(\n        bool                  optimize ,\n        size_t&               n        ,\n        size_t&               m        ,\n        CppAD::ADFun<double>& fun      )\n    {\n        // declare checkpoint function\n        avector au(3), av(1);\n        for(size_t j = 0; j < 3; j++)\n            au[j] = AD<double>(j);\n        if( atom_g == nullptr )\n            atom_g = new CppAD::checkpoint<double>(\"atom_g\", g_algo, au, av);\n        //\n        // domain space vector\n        n = 6;\n        CPPAD_TESTVECTOR(AD<double>) ax(n);\n        for(size_t j = 0; j < n; j++)\n            ax[j] = AD<double>(j);\n\n        // declare independent variables and start recording\n        CppAD::Independent(ax);\n\n        // range space vector\n        m = 8;\n        CPPAD_TESTVECTOR(AD<double>) ay(m);\n        ay[0] = 0.0;                     // does not depend on anything\n        ay[1] = ax[1];                   // is equal to an independent variable\n        AD<double> sum = ax[1] + ax[1];  // only uses ax[1]\n        ay[2] = sum * ax[2];             // operator(variable, variable)\n        ay[3] = sin(ax[1]);              // operator(variable)\n        ay[4] = ax[4] / 2.0;             // operator(variable, parameter)\n        ay[5] = 2.0 / ax[3];             // operator(parameter, variable)\n        //\n        // a atomic function call\n        for(size_t j = 0; j < size_t(au.size()); ++j)\n            au[j] = ax[j + 3];\n        (*atom_g)(au, av);\n        ay[6] = av[0];\n        //\n        // variable + variable operatros that optimizer will change to\n        // cumulative summation\n        ay[7] = 0.0;\n        for(size_t j = 0; j < n; ++j)\n            ay[7] += ax[j];\n        //\n        // create f: x -> y and stop tape recording\n        fun.Dependent(ax, ay);\n        //\n        if( optimize )\n            fun.optimize();\n        return;\n    }\n    // ------------------------------------------------------------------------\n    bool compare_subgraph_sparsity(\n        CppAD::sparse_rc<svector> subgraph  ,\n        CppAD::sparse_rc<svector> check     )\n    {   bool ok = true;\n\n        // check nnz\n        size_t sub_nnz = subgraph.nnz();\n        size_t chk_nnz = check.nnz();\n        ok            &= sub_nnz == chk_nnz;\n        size_t nnz     = std::min(sub_nnz, chk_nnz);\n\n        // row major order\n        svector sub_order = subgraph.row_major();\n        svector chk_order = check.row_major();\n\n        // check row indices\n        const svector& sub_row( subgraph.row() );\n        const svector& chk_row( check.row() );\n        for(size_t k = 0; k < nnz; k++)\n            ok &= sub_row[ sub_order[k] ] == chk_row[ chk_order[k] ];\n\n        // check column indices\n        const svector& sub_col( subgraph.col() );\n        const svector& chk_col( check.col() );\n        for(size_t k = 0; k < nnz; k++)\n            ok &= sub_col[ sub_order[k] ] == chk_col[ chk_order[k] ];\n\n        /*\n        std::cout << \"\\nsub_row = \" << sub_row << \"\\n\";\n        std::cout << \"chk_row = \" << chk_row << \"\\n\";\n        std::cout << \"sub_col = \" << sub_col << \"\\n\";\n        std::cout << \"chk_col = \" << chk_col << \"\\n\";\n        */\n\n        return ok;\n\n    }\n    // ------------------------------------------------------------------------\n    bool test_subgraph_sparsity(bool optimize)\n    {   bool ok = true;\n\n        // create f: x -> y\n        size_t n, m;\n        CppAD::ADFun<double> f;\n        record_function(optimize, n, m, f);\n\n        // --------------------------------------------------------------------\n        // Entire sparsity pattern\n\n        // compute sparsity using subgraph_sparsity\n        CPPAD_TESTVECTOR(bool) select_domain(n), select_range(m);\n        for(size_t j = 0; j < n; j++)\n            select_domain[j] = true;\n        for(size_t i = 0; i < m; i++)\n            select_range[i] = true;\n        bool transpose       = false;\n        sparsity subgraph_out;\n        f.subgraph_sparsity(\n            select_domain, select_range, transpose, subgraph_out\n        );\n\n        // compute sparsity using for_jac_sparsity\n        sparsity pattern_in(n, n, n);\n        for(size_t k = 0; k < n; k++)\n            pattern_in.set(k, k, k);\n        bool dependency     = true;\n        bool internal_bool  = true;\n        sparsity check_out;\n        f.for_jac_sparsity(\n            pattern_in, transpose, dependency, internal_bool, check_out\n        );\n\n        // compare results\n        ok &= compare_subgraph_sparsity(subgraph_out, check_out);\n\n        // --------------------------------------------------------------------\n        // Exclude ax[1]\n        select_domain[1] = false;\n        f.subgraph_sparsity(\n            select_domain, select_range, transpose, subgraph_out\n        );\n\n        pattern_in.resize(n, n, n-1);\n        for(size_t k = 0; k < n-1; k++)\n        {   if( k < 1 )\n                pattern_in.set(k, k, k);\n            else\n                pattern_in.set(k, k+1, k+1);\n        }\n        f.for_jac_sparsity(\n            pattern_in, transpose, dependency, internal_bool, check_out\n        );\n\n        // compare results\n        ok &= compare_subgraph_sparsity(subgraph_out, check_out);\n\n        return ok;\n    }\n    // ------------------------------------------------------------------------\n    bool compare_subgraph_reverse(\n        const CPPAD_TESTVECTOR(size_t)&  col   ,\n        const CPPAD_TESTVECTOR(double)&  dw    ,\n        const CPPAD_TESTVECTOR(double)&  check )\n    {   bool ok = true;\n        double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n        //\n        size_t n = size_t( check.size() );\n        //\n        // check order in col\n        for(size_t c = 1; c < size_t( col.size() ); c++)\n            ok &= col[c] > col[c-1];\n        //\n        size_t c = 0;\n        for(size_t j = 1; j < n; j++)\n        {   while( c < size_t( col.size() ) && col[c] < j )\n                ++c;\n            if( c < size_t( col.size() ) && col[c] == j )\n                ok &= CppAD::NearEqual(dw[j], check[j], eps99, eps99);\n            else\n                ok &= CppAD::NearEqual(0.0, check[j], eps99, eps99);\n        }\n        return ok;\n    }\n    // ------------------------------------------------------------------------\n    bool test_subgraph_reverse(bool optimize)\n    {   bool ok = true;\n\n        // create f: x -> y\n        size_t n, m;\n        CppAD::ADFun<double> f;\n        record_function(optimize, n, m, f);\n\n        // value of x at which to compute derivatives\n        CPPAD_TESTVECTOR(double) x(n);\n        for(size_t j = 0; j < n; ++j)\n            x[j] = double(n) / double(j + 1);\n        f.Forward(0, x);\n\n        // exclude x[4] from the derivative calculations\n        CPPAD_TESTVECTOR(bool) select_domain(n);\n        for(size_t j = 0; j < n; j++)\n            select_domain[j] = true;\n        select_domain[4] = false;\n        f.subgraph_reverse(select_domain);\n\n        // vector used to check results\n        CPPAD_TESTVECTOR(double) check(n);\n        for(size_t j = 0; j < n; j++)\n            check[j] = 0.0;\n\n        // derivative of y[0]\n        CPPAD_TESTVECTOR(size_t) col;\n        CPPAD_TESTVECTOR(double) dw;\n        size_t q   = 1;\n        size_t ell = 0;\n        f.subgraph_reverse(q, ell, col, dw);\n        ok &= compare_subgraph_reverse(col, dw, check);\n        //\n        // derivative of y[1]\n        check[1] = 1.0;\n        ell = 1;\n        f.subgraph_reverse(q, ell, col, dw);\n        ok &= compare_subgraph_reverse(col, dw, check);\n        //\n        // derivative of y[2]\n        check[1] = 2.0 * x[2];\n        check[2] = 2.0 * x[1];\n        ell = 2;\n        f.subgraph_reverse(q, ell, col, dw);\n        ok &= compare_subgraph_reverse(col, dw, check);\n        //\n        // derivative of y[3]\n        check[1] = cos( x[1] );\n        check[2] = 0.0;\n        ell = 3;\n        f.subgraph_reverse(q, ell, col, dw);\n        ok &= compare_subgraph_reverse(col, dw, check);\n        //\n        // derivative of y[4] (x[4] is not selected)\n        check[1] = 0.0;\n        ell = 4;\n        f.subgraph_reverse(q, ell, col, dw);\n        ok &= compare_subgraph_reverse(col, dw, check);\n        //\n        // derivative of y[5]\n        check[3] = -2.0 / (x[3] * x[3]);\n        ell = 5;\n        f.subgraph_reverse(q, ell, col, dw);\n        ok &= compare_subgraph_reverse(col, dw, check);\n        //\n        // derivative of y[6]  (x[4] is not selected)\n        check[3] = 1.0;\n        check[5] = 1.0;\n        ell = 6;\n        f.subgraph_reverse(q, ell, col, dw);\n        ok &= compare_subgraph_reverse(col, dw, check);\n        //\n        // derivative of y[7] (x[4] is not selected)\n        for(size_t j = 0; j < n;  ++j)\n            check[j] = 1.0;\n        check[4] = 0.0;\n        ell = 7;\n        f.subgraph_reverse(q, ell, col, dw);\n        ok &= compare_subgraph_reverse(col, dw, check);\n        //\n        return ok;\n    }\n\n}\nbool subgraph_1(void)\n{   bool ok       = true;\n    bool optimize = false;\n    ok           &= test_subgraph_sparsity(optimize);\n    ok           &= test_subgraph_reverse(optimize);\n    optimize      = true;\n    ok           &= test_subgraph_sparsity(optimize);\n    ok           &= test_subgraph_reverse(optimize);\n    //\n    ok           &= atom_g != nullptr;\n    delete atom_g;\n    //\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/subgraph_2.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/cppad.hpp>\n\nnamespace { // BEGIN_EMPTY_NAMESPACE\n\nbool test_subgraph_subset(void)\n{   bool ok = true;\n    using std::cout;\n    using CppAD::AD;\n    using CppAD::vector;\n    typedef vector<double> d_vector;\n    typedef vector<size_t> s_vector;\n    //\n    size_t n = 4;\n    d_vector x(n);\n    vector< AD<double> > ax(n), ay(n);\n    for(size_t j = 0; j < n; ++j)\n        ax[j] = x[j] = double(j);\n    CppAD::Independent(ax);\n    for(size_t i = 0; i < n; ++i)\n    {   ay[i] = 0.0;\n        for(size_t j = 0; j < n; ++j)\n            ay[i] += double(i + j + 1) * ax[j];\n    }\n    CppAD::ADFun<double> f(ax, ay);\n    //\n    size_t nnz = (n * (n + 1)) / 2;\n    CppAD::sparse_rc<s_vector> upper_triangle(n, n, nnz);\n    size_t k = 0;\n    for(size_t i = 0; i < n; ++i)\n    {   for(size_t j = i; j < n; ++j)\n            upper_triangle.set(k++, i, j);\n    }\n    ok &= k == nnz;\n    CppAD::sparse_rcv<s_vector, d_vector> subset( upper_triangle );\n    //\n    f.subgraph_jac_rev(x, subset);\n    const d_vector& val = subset.val();\n    k = 0;\n    for(size_t i = 0; i < n; ++i)\n    {   for(size_t j = i; j < n; ++j)\n            ok &= val[k++] == double(i + j + 1);\n    }\n    ok &= k == nnz;\n    //\n    return ok;\n}\n\n} // END_EMPTY_NAMESPACE\n\nbool subgraph_2(void)\n{   bool ok = true;\n    ok &= test_subgraph_subset();\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/subgraph_hes2jac.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\nSparse Hessian Using Subgraphs and Jacobian: Example and Test\n*/\n# include <cppad/cppad.hpp>\nbool subgraph_hes2jac(void)\n{   bool ok = true;\n    using CppAD::NearEqual;\n    typedef CppAD::AD<double>                      a1double;\n    typedef CppAD::AD<a1double>                    a2double;\n    typedef CPPAD_TESTVECTOR(double)               d_vector;\n    typedef CPPAD_TESTVECTOR(a1double)             a1vector;\n    typedef CPPAD_TESTVECTOR(a2double)             a2vector;\n    typedef CPPAD_TESTVECTOR(size_t)               s_vector;\n    typedef CPPAD_TESTVECTOR(bool)                 b_vector;\n    typedef CppAD::sparse_rcv<s_vector, d_vector>  sparse_matrix;\n    //\n    double eps = 10. * CppAD::numeric_limits<double>::epsilon();\n    //\n    // double version of x\n    size_t n = 12;\n    d_vector x(n);\n    for(size_t j = 0; j < n; j++)\n        x[j] = double(j + 2);\n    //\n    // a1double version of x\n    a1vector a1x(n);\n    for(size_t j = 0; j < n; j++)\n        a1x[j] = x[j];\n    //\n    // a2double version of x\n    a2vector a2x(n);\n    for(size_t j = 0; j < n; j++)\n        a2x[j] = a1x[j];\n    //\n    // declare independent variables and starting recording\n    CppAD::Independent(a2x);\n    //\n    // a2double version of y = f(x) = 5 * x0 * x1 + sum_j xj^3\n    size_t m = 1;\n    a2vector a2y(m);\n    a2y[0] = 5.0 * a2x[0] * a2x[1];\n    for(size_t j = 0; j < n; j++)\n        a2y[0] += a2x[j] * a2x[j] * a2x[j];\n    //\n    // create a1double version of f: x -> y and stop tape recording\n    // (without executing zero order forward calculation)\n    CppAD::ADFun<a1double> a1f;\n    a1f.Dependent(a2x, a2y);\n    //\n    // Optimize this function to reduce future computations.\n    // Perhaps only one optimization at the end would be faster.\n    a1f.optimize();\n    //\n    // declare independent variables and start recording g(x) = f'(x)\n    Independent(a1x);\n    //\n    // Use one reverse mode pass to compute z = f'(x)\n    a1vector a1w(m), a1z(n);\n    a1w[0] = 1.0;\n    a1f.Forward(0, a1x);\n    a1z = a1f.Reverse(1, a1w);\n    //\n    // create double version of g : x -> f'(x)\n    CppAD::ADFun<double> g;\n    g.Dependent(a1x, a1z);\n    ok &= g.size_random() == 0;\n    //\n    // Optimize this function to reduce future computations.\n    // Perhaps no optimization would be faster.\n    g.optimize();\n    //\n    // compute f''(x) = g'(x)\n    b_vector select_domain(n), select_range(n);\n    for(size_t j = 0; j < n; ++j)\n    {   select_domain[j] = true;\n        select_range[j]  = true;\n    }\n    sparse_matrix hessian;\n    g.subgraph_jac_rev(select_domain, select_range, x, hessian);\n    // -------------------------------------------------------------------\n    // check number of non-zeros in the Hessian\n    // (only x0 * x1 generates off diagonal terms)\n    ok &= hessian.nnz() == n + 2;\n    //\n    for(size_t k = 0; k < hessian.nnz(); ++k)\n    {   size_t r = hessian.row()[k];\n        size_t c = hessian.col()[k];\n        double v = hessian.val()[k];\n        //\n        if( r == c )\n        {   // a diagonal element\n            double check = 6.0 * x[r];\n            ok          &= NearEqual(v, check, eps, eps);\n        }\n        else\n        {   // off diagonal element\n            ok   &= (r == 0 && c == 1) || (r == 1 && c == 0);\n            double check = 5.0;\n            ok          &= NearEqual(v, check, eps, eps);\n        }\n    }\n    ok &= g.size_random() > 0;\n    g.clear_subgraph();\n    ok &= g.size_random() == 0;\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/tan.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n\n/*\nTest higher order derivatives for tan(x) function.\n*/\n\n# include <cppad/cppad.hpp>\n\nnamespace {\n    bool tan_two(void)\n    {   bool ok = true;\n        using CppAD::AD;\n        using CppAD::NearEqual;\n        double eps = 10. * std::numeric_limits<double>::epsilon();\n\n        // domain space vector\n        size_t n = 1;\n        CPPAD_TESTVECTOR(AD<double>) ax(n);\n        ax[0] = 0.5;\n\n        // declare independent variables and starting recording\n        CppAD::Independent(ax);\n\n        // range space vector\n        size_t m = 1;\n        CPPAD_TESTVECTOR(AD<double>) ay(m);\n        ay[0] = tan( ax[0] );\n\n        // create f: x -> y and stop tape recording\n        CppAD::ADFun<double> f(ax, ay);\n\n        // first order Taylor coefficient\n        CPPAD_TESTVECTOR(double) x1(n), y1;\n        x1[0] = 2.0;\n        y1    = f.Forward(1, x1);\n        ok   &= size_t( y1.size() ) == m;\n\n        // secondorder Taylor coefficients\n        CPPAD_TESTVECTOR(double) x2(n), y2;\n        x2[0] = 0.0;\n        y2    = f.Forward(2, x2);\n        ok   &= size_t( y2.size() ) == m;\n        //\n        // Y  (t)    = F[X_0(t)]\n        //           =  tan(0.5 + 2t )\n        // Y' (t)    =  2 * cos(0.5 + 2t )^(-2)\n        double sec_sq  = 1.0 / ( cos(0.5) * cos(0.5) );\n        double check   = 2.0 * sec_sq;\n        ok  &= NearEqual(y1[0] , check, eps, eps);\n        //\n        // Y''(0)    = 8*cos(0.5)^(-3)*sin(0.5)\n        check = 8.0 * tan(0.5) * sec_sq / 2.0;\n        ok    &= NearEqual(y2[0] , check, eps, eps);\n        //\n        return ok;\n    }\n    bool tan_case(bool tan_first)\n    {   bool ok = true;\n        double eps = 100. * std::numeric_limits<double>::epsilon();\n        using CppAD::AD;\n        using CppAD::NearEqual;\n\n        // independent variable vector, indices, values, and declaration\n        size_t n = 1;\n        CPPAD_TESTVECTOR(AD<double>) ax(n);\n        ax[0]     = .7;\n        Independent(ax);\n\n        // dependent variable vector and indices\n        size_t m = 1;\n        CPPAD_TESTVECTOR(AD<double>) ay(m);\n        if( tan_first )\n            ay[0] = atan( tan( ax[0] ) );\n        else\n            ay[0] = tan( atan( ax[0] ) );\n\n        // check value\n        ok &= NearEqual(ax[0] , ay[0],  eps, eps);\n\n        // create f: x -> y and vectors used for derivative calculations\n        CppAD::ADFun<double> f(ax, ay);\n        CPPAD_TESTVECTOR(double) dx(n), dy(m);\n\n        // forward computation of partials w.r.t. x\n        dx[0] = 1.;\n        dy    = f.Forward(1, dx);\n        ok   &= NearEqual(dy[0], 1e0, eps, eps);\n        size_t p, order = 5;\n        dx[0] = 0.;\n        for(p = 2; p < order; p++)\n        {   dy    = f.Forward(p, dx);\n            ok   &= NearEqual(dy[0], 0e0, eps, eps);\n        }\n\n        // reverse computation of order partial\n        CPPAD_TESTVECTOR(double)  w(m), dw(n * order);\n        w[0] = 1.;\n        dw   = f.Reverse(order, w);\n        ok   &= NearEqual(dw[0], 1e0, eps, eps);\n        for(p = 1; p < order; p++)\n            ok   &= NearEqual(dw[p], 0e0, eps, eps);\n\n        return ok;\n    }\n    bool tanh_case(bool tanh_first)\n    {   bool ok = true;\n        double eps = 100. * std::numeric_limits<double>::epsilon();\n        using CppAD::AD;\n        using CppAD::NearEqual;\n\n        // independent variable vector, indices, values, and declaration\n        size_t n = 1;\n        CPPAD_TESTVECTOR(AD<double>) ax(n);\n        ax[0]     = .5;\n        Independent(ax);\n\n        // dependent variable vector and indices\n        size_t m = 1;\n        CPPAD_TESTVECTOR(AD<double>) ay(m);\n        AD<double> z;\n        if( tanh_first )\n        {   z     = tanh( ax[0] );\n            ay[0] = .5 * log( (1. + z) / (1. - z) );\n        }\n        else\n        {   z     = .5 * log( (1. + ax[0]) / (1. - ax[0]) );\n            ay[0] = tanh(z);\n        }\n        // check value\n        ok &= NearEqual(ax[0] , ay[0],  eps, eps);\n\n        // create f: x -> y and vectors used for derivative calculations\n        CppAD::ADFun<double> f(ax, ay);\n        CPPAD_TESTVECTOR(double) dx(n), dy(m);\n\n        // forward computation of partials w.r.t. x\n        dx[0] = 1.;\n        dy    = f.Forward(1, dx);\n        ok   &= NearEqual(dy[0], 1e0, eps, eps);\n        size_t p, order = 5;\n        dx[0] = 0.;\n        for(p = 2; p < order; p++)\n        {   dy    = f.Forward(p, dx);\n            ok   &= NearEqual(dy[0], 0e0, eps, eps);\n        }\n\n        // reverse computation of order partial\n        CPPAD_TESTVECTOR(double)  w(m), dw(n * order);\n        w[0] = 1.;\n        dw   = f.Reverse(order, w);\n        ok   &= NearEqual(dw[0], 1e0, eps, eps);\n        for(p = 1; p < order; p++)\n            ok   &= NearEqual(dw[p], 0e0, eps, eps);\n\n        return ok;\n    }\n}\nbool tan(void)\n{   bool ok = true;\n    //\n    ok     &= tan_case(true);\n    ok     &= tan_case(false);\n    ok     &= tanh_case(true);\n    ok     &= tanh_case(false);\n    //\n    ok     &= tan_two();\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/to_csrc.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-23 Bradley M. Bell\n// ----------------------------------------------------------------------------\n# include <cppad/cppad.hpp>\n# include <cppad/utility/link_dll_lib.hpp>\n\n# if CPPAD_USE_CPLUSPLUS_2017\n# include <filesystem>\n# endif\n\n//  DIR_SEP, DLL_EXT\n# ifndef _WIN32\n# define DIR_SEP         '/'\n# define DLL_EXT         \".so\"\n# else\n# define DIR_SEP         '\\\\'\n# define DLL_EXT         \".dll\"\n# endif\n\nnamespace { // BEGIN_EMPTY_NAMESPACE\n//\n// dll_file_name\nstd::string dll_file_name(void)\n{   //\n# if ! CPPAD_USE_CPLUSPLUS_2017\n    std::string tmp_dir = \"./\";\n# else\n    // tmp_dir\n    std::string  tmp_dir = std::filesystem::temp_directory_path().string();\n    if( tmp_dir.back() != DIR_SEP )\n        tmp_dir += DIR_SEP;\n# endif\n    //\n    // base_name\n# ifdef _WIN32\n    std::string base_name = \"test_to_csrc.dll\";\n# else\n    std::string base_name = \"test_to_csrc.so\";\n# endif\n    //\n    // file_name\n    std::string file_name = tmp_dir + base_name;\n    //\n    return file_name;\n}\n//\n// create_csrc_file\nstd::string create_csrc_file(size_t index, const std::string& csrc)\n{   //\n# if ! CPPAD_USE_CPLUSPLUS_2017\n    std::string tmp_dir = \"./\";\n# else\n    // tmp_dir\n    std::string  tmp_dir = std::filesystem::temp_directory_path().string();\n    if( tmp_dir.back() != DIR_SEP )\n        tmp_dir += DIR_SEP;\n# endif\n    //\n    // base_name\n    std::string base_name = \"test_to_csrc_\" + CppAD::to_string(index) + \".c\";\n    //\n    // file_name\n    std::string file_name = tmp_dir + base_name;\n    //\n    // write file_name\n    std::ofstream os;\n    os.open(file_name, std::ios::out);\n    os << csrc;\n    os.close();\n    //\n    return file_name;\n}\n//\n// atomic_fun\nclass atomic_fun : public CppAD::atomic_four<double> {\nprivate:\n    const std::string name_;\npublic:\n    atomic_fun(const std::string& name) :\n    CppAD::atomic_four<double>(name),\n    name_(name)\n    {}\nprivate:\n    bool for_type(\n        size_t                                     call_id     ,\n        const CppAD::vector<CppAD::ad_type_enum>&  type_x      ,\n        CppAD::vector<CppAD::ad_type_enum>&        type_y      ) override\n    {   type_y[0] = type_x[0];\n        return true;\n    }\n    // forward double\n    bool forward(\n        size_t                              call_id      ,\n        const CppAD::vector<bool>&          select_y     ,\n        size_t                              order_low    ,\n        size_t                              order_up     ,\n        const CppAD::vector<double>&        taylor_x     ,\n        CppAD::vector<double>&              taylor_y     ) override\n    {   if( order_up != 0 )\n            return false;;\n        taylor_y[0] = 1.0 / taylor_x[0];\n        return true;\n    }\npublic:\n    // forward_zero\n    std::string forward_zero(void)\n    {   std::string csrc =\n            \"# include <stddef.h>\\n\"\n            \"int cppad_atomic_\" + name_ + \"(\\n\";\n        csrc +=R\"_(\n    size_t        call_id,\n    size_t        nx,\n    const double* x,\n    size_t        ny,\n    double*       y,\n    size_t*       compare_change)\n{   if( nx != 1 ) return 1;\n    if( ny != 1 ) return 2;\n    y[0] = 1.0 / x[0];\n    return 0;\n}\n)_\";\n        return csrc;\n    }\n};\n// --------------------------------------------------------------------------\n// integer\nfloat integer(const float& x)\n{   if( x >= 0.0 ) return std::floor(x);\n    return std::ceil(x);\n}\nCPPAD_DISCRETE_FUNCTION(float, integer)\nstd::string discrete_integer(void)\n{   std::string csrc = R\"_(\n# include <math.h>\nfloat cppad_discrete_integer(const float x)\n{   if( x >= 0.0 ) return floor(x);\n    return ceil(x);\n}\n)_\";\n    return csrc;\n}\n// --------------------------------------------------------------------------\nbool simple_cases(void)\n{   // ok\n    bool ok = true;\n    //\n    // AD, NearEqual\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    //\n    // eps99\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n    //\n    // function_name\n    std::string function_name = \"test_to_csrc\";\n    //\n    // library_name\n    std::string library_name = function_name;\n    //\n    // nx, ax\n    size_t nx = 2;\n    CPPAD_TESTVECTOR( AD<double> ) ax(nx);\n    ax[0] = 0.5;\n    ax[1] = 2.0;\n    CppAD::Independent(ax);\n    //\n    // ny, ay\n    size_t ny = 28;\n    CPPAD_TESTVECTOR( AD<double> ) ay(ny);\n    //\n    // binary operators\n    ay[0] = ax[0] + ax[1]; // add\n    ay[1] = ax[0] / ax[1]; // div\n    ay[2] = ax[0] * ax[1]; // mul\n    ay[3] = ax[0] - ax[1]; // sub\n    //\n    // unary functions\n    ay[4]  = abs(   ax[0] );\n    ay[5]  = acos(  ax[0] ); // ax[0] < 1\n    ay[6]  = acosh( ax[1] ); // ax[1] > 1\n    ay[7]  = asin(  ax[0] ); // ax[0] < 1\n    ay[8]  = asinh( ax[0] );\n    ay[9]  = atan(  ax[0] );\n    ay[10] = atanh( ax[0] );\n    ay[11] = cos(   ax[0] );\n    ay[12] = cosh(  ax[0] );\n    ay[13] = erf(   ax[0] );\n    ay[14] = erfc(  ax[0] );\n    ay[15] = exp(   ax[0] );\n    ay[16] = expm1( ax[0] );\n    ay[17] = log1p( ax[0] );\n    ay[18] = log(   ax[0] );\n    ay[19] = sign(  ax[0] );\n    ay[20] = sin(   ax[0] );\n    ay[21] = sinh(  ax[0] );\n    ay[22] = sqrt(  ax[0] );\n    ay[23] = tan(   ax[0] );\n    ay[24] = tanh(  ax[0] );\n    //\n    // binary functions\n    ay[25] = azmul( ax[0], ax[1] );\n    ay[26] = pow(   ax[0], ax[1] ); // ax[0] > 0\n    //\n    // constant function\n    ay[27] = 3.0;\n    //\n    // f\n    CppAD::ADFun<double> f(ax, ay);\n    f.function_name_set(function_name);\n    //\n    // dll_file\n    std::string dll_file = dll_file_name();\n    //\n    // csrc_files\n    CppAD::vector<std::string> csrc_files(1);\n    std::string type = \"double\";\n    std::stringstream ss;\n    f.to_csrc(ss, type);\n    csrc_files[0] = create_csrc_file(0, ss.str() );\n    //\n    // create dll_lib\n    std::map< std::string, std::string > options;\n    std::string err_msg = CppAD::create_dll_lib(dll_file, csrc_files, options);\n    if( err_msg != \"\" )\n    {   std::cout << err_msg << \"\\n\";\n        ok = false;\n        return ok;\n    }\n    //\n    // dll_linker\n    CppAD::link_dll_lib dll_linker(dll_file, err_msg);\n    //\n    // jit_double\n    using CppAD::jit_double;\n    //\n    // jit_function\n    jit_double jit_function = nullptr;\n    if( err_msg != \"\" )\n    {   std::cout << \"dll_linker ctor error: \" << err_msg << \"\\n\";\n        ok = false;\n    }\n    else\n    {   // jit_function\n        std::string complete_name = \"cppad_jit_\" + function_name;\n        jit_function = reinterpret_cast<jit_double>(\n                dll_linker(complete_name, err_msg)\n        );\n        if( err_msg != \"\" )\n        {   std::cout << \"dll_linker fun_ptr error: \" << err_msg << \"\\n\";\n            ok = false;\n        }\n    }\n    if( ok )\n    {   //\n        // ok\n        // no change\n        CppAD::vector<double> x(nx), y(ny);\n        x[0] = Value( ax[0] );\n        x[1] = Value( ax[1] );\n        for(size_t i = 0; i < ny; ++i)\n            y[i] = std::numeric_limits<double>::quiet_NaN();\n        size_t compare_change = 0;\n        int flag = jit_function(\n            nx, x.data(), ny, y.data(), &compare_change\n        );\n        ok &= flag == 0;\n        ok &= compare_change == 0;\n        //\n        // check\n        for(size_t i = 0; i < ny; ++i)\n        {   // std::cout << \"y = \" << y[i] << \", ay = \" << ay[i] << \"\\n\";\n            ok &= CppAD::NearEqual( y[i], Value(ay[i]), eps99, eps99);\n        }\n    }\n    return ok;\n}\n// --------------------------------------------------------------------------\nbool compare_cases(void)\n{   // ok\n    bool ok = true;\n    //\n    // AD, NearEqual\n    using CppAD::AD;\n    //\n    // function_name\n    std::string function_name = \"test_to_csrc\";\n    //\n    // library_name\n    std::string library_name = function_name;\n    //\n    // nx, ax\n    size_t nx = 1;\n    CPPAD_TESTVECTOR( AD<double> ) ax(nx);\n    double x0  = 0.5;\n    ax[0] = x0;\n    CppAD::Independent(ax);\n    //\n    // ny, ay\n    size_t ny = 4;\n    CPPAD_TESTVECTOR( AD<double> ) ay(ny);\n    //\n    // comp_eq_graph_op\n    if( ax[0] == x0 )\n        ay[0] = 1.0;\n    else\n        ay[0] = 0.0;\n    //\n    // comp_le_graph_op\n    if( ax[0] <= x0 )\n        ay[1] = 1.0;\n    else\n        ay[1] = 0.0;\n    //\n    // comp_lt_graph_op\n    if( ax[0] <= x0 )\n        ay[2] = 1.0;\n    else\n        ay[2] = 0.0;\n    //\n    // comp_ne_graph_op\n    if( ax[0] != 2.0 * x0 )\n        ay[3] = 1.0;\n    else\n        ay[3] = 0.0;\n    //\n    // f\n    CppAD::ADFun<double> f(ax, ay);\n    f.function_name_set(function_name);\n    //\n    // dll_file\n    std::string dll_file = dll_file_name();\n    //\n    // csrc_files\n    CppAD::vector<std::string> csrc_files(1);\n    std::string type = \"double\";\n    std::stringstream ss;\n    f.to_csrc(ss, type);\n    csrc_files[0] = create_csrc_file(0, ss.str());\n    //\n    // create_dll_lib\n    std::map< std::string, std::string > options;\n    std::string err_msg = CppAD::create_dll_lib(dll_file, csrc_files, options);\n    if( err_msg != \"\" )\n    {   std::cout << err_msg << \"\\n\";\n        ok = false;\n        return ok;\n    }\n    //\n    // dll_linker\n    CppAD::link_dll_lib dll_linker(dll_file, err_msg);\n    //\n    // jit_double\n    using CppAD::jit_double;\n    //\n    // jit_function\n    jit_double jit_function = nullptr;\n    if( err_msg != \"\" )\n    {   std::cout << \"dll_linker ctor error: \" << err_msg << \"\\n\";\n        ok = false;\n    }\n    else\n    {   // jit_function\n        std::string complete_name = \"cppad_jit_\" + function_name;\n        jit_function = reinterpret_cast<jit_double>(\n                dll_linker(complete_name, err_msg)\n        );\n        if( err_msg != \"\" )\n        {   std::cout << \"dll_linker fun_ptr error: \" << err_msg << \"\\n\";\n            ok = false;\n        }\n    }\n    if( ok )\n    {   //\n        // ok\n        // no change\n        CppAD::vector<double> x(nx), y(ny);\n        x[0] = x0;\n        for(size_t i = 0; i < ny; ++i)\n            y[i] = std::numeric_limits<double>::quiet_NaN();\n        size_t compare_change = 0;\n        int flag = jit_function(\n            nx, x.data(), ny, y.data(), &compare_change\n        );\n        ok &= flag == 0;\n        ok &= compare_change == 0;\n        for(size_t i = 0; i < ny; ++i)\n            ok &= y[i] == Value( ay[i] );\n        //\n        // ok\n        // check all change\n        x[0] = 2.0 * x0;\n        flag = jit_function(\n            nx, x.data(), ny, y.data(), &compare_change\n        );\n        ok &= flag == 0;\n        ok &= compare_change == 4;\n        for(size_t i = 0; i < ny; ++i)\n            ok &= y[i] == Value( ay[i] );\n    }\n    return ok;\n}\n// ---------------------------------------------------------------------------\nbool atomic_case(void)\n{   // ok\n    bool ok = true;\n    //\n    // AD\n    using CppAD::AD;\n    //\n    // function_name\n    std::string function_name = \"reciprocal\";\n    //\n    // reciprocal\n    atomic_fun reciprocal(function_name);\n    //\n    // nx, ax\n    size_t nx = 2;\n    CPPAD_TESTVECTOR( AD<double> ) ax(nx);\n    double x0 = 0.5, x1 = 4.0;\n    ax[0] = x0;\n    ax[1] = x1;\n    CppAD::Independent(ax);\n    //\n    // ny, ay\n    size_t ny = nx;\n    CPPAD_TESTVECTOR( AD<double> ) ay(ny);\n    CPPAD_TESTVECTOR( AD<double> ) au(1), aw(1);\n    for(size_t j = 0; j < nx; ++j)\n    {   au[0] = ax[j];\n        reciprocal(au, aw);\n        ay[j] = aw[0];\n    }\n    //\n    // function_name\n    function_name = \"use_reciprocal\";\n    //\n    // f\n    CppAD::ADFun<double> f(ax, ay);\n    f.function_name_set(function_name);\n    //\n    // library_name\n    std::string library_name = \"test_to_csrc\";\n    //\n    // dll_file\n    std::string dll_file = dll_file_name();\n    //\n    // csrc_files\n    CppAD::vector<std::string> csrc_files(2);\n    csrc_files[0] = create_csrc_file(0, reciprocal.forward_zero() );\n    std::string type = \"double\";\n    std::stringstream ss;\n    f.to_csrc(ss, type);\n    csrc_files[1] = create_csrc_file(1, ss.str() );\n    //\n    // create_dll_lib\n    std::map< std::string, std::string > options;\n    std::string err_msg = CppAD::create_dll_lib(dll_file, csrc_files, options);\n    if( err_msg != \"\" )\n    {   std::cout << err_msg << \"\\n\";\n        ok = false;\n        return ok;\n    }\n    //\n    // dll_linker\n    CppAD::link_dll_lib dll_linker(dll_file, err_msg);\n    //\n    // jit_double\n    using CppAD::jit_double;\n    //\n    // jit_function\n    jit_double jit_function = nullptr;\n    if( err_msg != \"\" )\n    {   std::cout << \"dll_linker ctor error: \" << err_msg << \"\\n\";\n        ok = false;\n    }\n    else\n    {   // jit_function\n        std::string complete_name = \"cppad_jit_\" + function_name;\n        jit_function = reinterpret_cast<jit_double>(\n                dll_linker(complete_name, err_msg)\n        );\n        if( err_msg != \"\" )\n        {   std::cout << \"dll_linker fun_ptr error: \" << err_msg << \"\\n\";\n            ok = false;\n        }\n    }\n    if( ok )\n    {   //\n        // ok\n        // no change\n        CppAD::vector<double> x(nx), y(ny);\n        x[0] = x0;\n        x[1] = x1;\n        for(size_t i = 0; i < ny; ++i)\n            y[i] = std::numeric_limits<double>::quiet_NaN();\n        size_t compare_change = 0;\n        int flag = jit_function(\n            nx, x.data(), ny, y.data(), &compare_change\n        );\n        ok &= flag == 0;\n        ok &= compare_change == 0;\n        for(size_t i = 0; i < ny; ++i)\n            ok &= y[i] == Value( ay[i] );\n    }\n    return ok;\n}\n// ---------------------------------------------------------------------------\nbool discrete_case(void)\n{   // ok\n    bool ok = true;\n    //\n    // AD\n    using CppAD::AD;\n    //\n    // nx, ax\n    size_t nx = 2;\n    CPPAD_TESTVECTOR( AD<float> ) ax(nx);\n    float x0 = -1.5, x1 = 1.5;\n    ax[0] = x0;\n    ax[1] = x1;\n    CppAD::Independent(ax);\n    //\n    // ny, ay\n    size_t ny = nx;\n    CPPAD_TESTVECTOR( AD<float> ) ay(ny);\n    for(size_t j = 0; j < nx; ++j)\n        ay[j] = integer( ax[j] );\n    //\n    // function_name\n    std::string function_name = \"use_integer\";\n    //\n    // f\n    CppAD::ADFun<float> f(ax, ay);\n    f.function_name_set(function_name);\n    //\n    // library_name\n    std::string library_name = \"test_to_csrc\";\n    //\n    // dll_file\n    std::string dll_file = dll_file_name();\n    //\n    // csrc_files\n    CppAD::vector<std::string> csrc_files(2);\n    csrc_files[0] = create_csrc_file(0, discrete_integer() );\n    std::string type = \"float\";\n    std::stringstream ss;\n    f.to_csrc(ss, type);\n    csrc_files[1] = create_csrc_file(1, ss.str());\n    //\n    // dll_file_str\n    std::map< std::string, std::string > options;\n    std::string err_msg = create_dll_lib(dll_file, csrc_files, options);\n    if( err_msg != \"\" )\n    {   std::cout << err_msg << \"\\n\";\n        ok = false;\n        return ok;\n    }\n    //\n    // dll_linker\n    CppAD::link_dll_lib dll_linker(dll_file, err_msg);\n    //\n    // jit_float\n    using CppAD::jit_float;\n    //\n    // jit_function\n    jit_float jit_function = nullptr;\n    if( err_msg != \"\" )\n    {   std::cout << \"dll_linker ctor error: \" << err_msg << \"\\n\";\n        ok = false;\n    }\n    else\n    {   // jit_function\n        std::string complete_name = \"cppad_jit_\" + function_name;\n        jit_function = reinterpret_cast<jit_float>(\n                dll_linker(complete_name, err_msg)\n        );\n        if( err_msg != \"\" )\n        {   std::cout << \"dll_linker fun_ptr error: \" << err_msg << \"\\n\";\n            ok = false;\n        }\n    }\n    if( ok )\n    {   //\n        // ok\n        // no change\n        CppAD::vector<float> x(nx), y(ny);\n        x[0] = x0;\n        x[1] = x1;\n        for(size_t i = 0; i < ny; ++i)\n            y[i] = std::numeric_limits<float>::quiet_NaN();\n        size_t compare_change = 0;\n        int flag = jit_function(\n            nx, x.data(), ny, y.data(), &compare_change\n        );\n        ok &= flag == 0;\n        ok &= compare_change == 0;\n        for(size_t i = 0; i < ny; ++i)\n            ok &= y[i] == Value( ay[i] );\n    }\n    return ok;\n}\n// ---------------------------------------------------------------------------\nbool csum_case(void)\n{   // ok\n    bool ok = true;\n    //\n    // AD\n    using CppAD::AD;\n    //\n    // nx, ax\n    size_t nx = 4;\n    CPPAD_TESTVECTOR( AD<double> ) ax(nx);\n    for(size_t j = 0; j < nx; ++j)\n        ax[j] = 0.0;\n    CppAD::Independent(ax);\n    //\n    // ny, ay\n    size_t ny = 2;\n    CPPAD_TESTVECTOR( AD<double> ) ay(ny);\n    ay[0] = 0.0;\n    ay[1] = 0.0;\n    for(size_t j = 0; j < nx; ++j)\n    {   ay[0] += ax[j];\n        ay[1] -= ax[j];\n    }\n    //\n    // function_name\n    std::string function_name = \"csum\";\n    //\n    // f\n    CppAD::ADFun<double> f(ax, ay);\n    f.optimize();\n    f.function_name_set(function_name);\n    //\n    // library_name\n    std::string library_name = \"test_to_csrc\";\n    //\n    // dll_file\n    std::string dll_file = dll_file_name();\n    //\n    // csrc_files\n    CppAD::vector<std::string> csrc_files(1);\n    std::string type = \"double\";\n    std::stringstream ss;\n    f.to_csrc(ss, type);\n    csrc_files[0] = create_csrc_file(0, ss.str() );\n    //\n    // dll_file_str\n    std::map< std::string, std::string > options;\n    std::string err_msg = create_dll_lib(dll_file, csrc_files, options);\n    if( err_msg != \"\" )\n    {   std::cout << err_msg << \"\\n\";\n        ok = false;\n        return ok;\n    }\n    //\n    // dll_linker\n    CppAD::link_dll_lib dll_linker(dll_file, err_msg);\n    //\n    // jit_double\n    using CppAD::jit_double;\n    //\n    // jit_function\n    jit_double jit_function = nullptr;\n    if( err_msg != \"\" )\n    {   std::cout << \"dll_linker ctor error: \" << err_msg << \"\\n\";\n        ok = false;\n    }\n    else\n    {   // jit_function\n        std::string complete_name = \"cppad_jit_\" + function_name;\n        jit_function = reinterpret_cast<jit_double>(\n                dll_linker(complete_name, err_msg)\n        );\n        if( err_msg != \"\" )\n        {   std::cout << \"dll_linker fun_ptr error: \" << err_msg << \"\\n\";\n            ok = false;\n        }\n    }\n    if( ok )\n    {   //\n        // ok\n        // no change\n        CppAD::vector<double> x(nx), y(ny);\n        for(size_t j = 0; j < nx; ++j)\n            x[j] = double(j+1);\n        y[0] = std::numeric_limits<double>::quiet_NaN();\n        y[1] = std::numeric_limits<double>::quiet_NaN();\n        size_t compare_change = 0;\n        int flag = jit_function(\n            nx, x.data(), ny, y.data(), &compare_change\n        );\n        ok &= flag == 0;\n        ok &= compare_change == 0;\n        ok &= y[0] == double(( nx * (nx + 1) )  / 2 );\n        ok &= y[1] == - double(( nx * (nx + 1) )  / 2 );\n    }\n    return ok;\n}\n// ---------------------------------------------------------------------------\n} // END_EMPTY_NAMESPACE\n// ---------------------------------------------------------------------------\nbool to_csrc(void)\n{   bool ok = true;\n    ok     &= simple_cases();\n    ok     &= compare_cases();\n    ok     &= atomic_case();\n    ok     &= discrete_case();\n    ok     &= csum_case();\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/to_string.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n// Complex examples should suppress conversion warnings\n# include <cppad/wno_conversion.hpp>\n//\n# include <cppad/cppad.hpp>\n\nnamespace {\n    template <class Float>\n    bool test(void)\n    {   bool  ok  = true;\n        Float eps = std::numeric_limits<Float>::epsilon();\n        Float pi  = Float( 4.0 * std::atan(1.0) );\n        Float e   = Float( std::exp(1.0) );\n        typedef std::complex<Float> Base;\n        Base  c   = Base(pi, e);\n        std::string s = CppAD::to_string( CppAD::AD<Base>(c) );\n        //\n        // get strings corresponding to real and imaginary parts\n        std::string real = \"\";\n        std::string imag = \"\";\n        size_t index = 1; // skip ( at front\n        while( s[index] != ',' )\n            real += s[index++];\n        index++;\n        while( s[index] != ')' )\n            imag += s[index++];\n        //\n        Float check   = Float( std::atof( real.c_str() ) );\n        ok           &= std::fabs( check / pi - 1.0 ) <= 2.0 * eps;\n        //\n        check         = Float( std::atof( imag.c_str() ) );\n        ok           &= std::fabs( check / e - 1.0 ) <= 2.0 * eps;\n        //\n        return ok;\n    }\n}\n\nbool to_string(void)\n{   bool ok = true;\n\n    ok &= test<float>();\n    ok &= test<double>();\n\n    return ok;\n}\n\n// END C++\n"
  },
  {
    "path": "test_more/general/value.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\nOld Value example now used just for valiadation testing\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n\nbool Value(void)\n{   bool ok = true;\n\n    using namespace CppAD;\n\n    // independent variable vector, indices, values, and declaration\n    CPPAD_TESTVECTOR(AD<double>) U(2);\n    size_t s = 0;\n    size_t t = 1;\n    U[s] = 3.;\n    U[t] = 4.;\n    Independent(U);\n\n    // cannot call Value after Independent (tape is recording)\n\n    // dependent variable vector and indices\n    CPPAD_TESTVECTOR(AD<double>) Z(1);\n    size_t x = 0;\n\n    // dependent variable values\n    Z[x] = - U[t];\n\n    // create f: U -> Z and vectors used for derivative calculations\n    ADFun<double> f(U, Z);\n    CPPAD_TESTVECTOR(double) v( f.Domain() );\n    CPPAD_TESTVECTOR(double) w( f.Range() );\n\n    // can call Value after ADFun constructor (tape is no longer recording)\n\n    // check value of s\n    double sValue = Value(U[s]);\n    ok &= ( sValue == 3. );\n\n    // check value of x\n    double xValue = Value(Z[x]);\n    ok &= ( xValue == -4. );\n\n    return ok;\n}\n// END C++\n"
  },
  {
    "path": "test_more/general/vec_ad.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-24 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\nOld examples now only used for validation testing\n*/\n// BEGIN C++\n\n# include <cppad/cppad.hpp>\n# include <cmath>\n# include <limits>\n# include <cppad/speed/uniform_01.hpp>\n\n\nnamespace { // Begin empty namespace\n\nvoid myhandler(\n    bool known       ,\n    int  line        ,\n    const char *file ,\n    const char *exp  ,\n    const char *msg  )\n{   // error handler must not return, so throw an exception\n    throw msg;\n}\n\nbool test_comp_assign(void)\n{   bool ok = true;\n\n    // replace the default CppAD error handler\n    CppAD::ErrorHandler info(myhandler);\n\n\n    // create a VecAD vector\n    CppAD::VecAD<double> v(1);\n\n    // assign its element a value\n    v[0] = 1.0;\n\n# ifndef NDEBUG\n    // use try / catch because error haandler throws an exception\n    try {\n        // set ok to false unless catch block is executed\n        ok = false;\n\n        // attempt to use a compound assignment operator\n        // with a reference to a VecAD object\n        CppAD::AD<double> x = 0.0;\n        v[x] += 1.0;\n    }\n    catch (const char* msg)\n    {   std::string check =\n            \"Can't use VecAD<Base>::reference on left side of +=\";\n        ok = msg == check;\n    }\n# endif\n\n    return ok;\n}\n\nbool VecADTestOne(void)\n{   bool ok = true;\n    using namespace CppAD;\n    using CppAD::sin;\n    using CppAD::cos;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n\n    size_t      n = 3;\n    AD<double>  N(n);\n\n    AD<double>  a;\n    size_t      i;\n\n    // create the array\n    CppAD::VecAD<double> V(n);\n\n    // check assignment from double (while not taping)\n    for(i = 0; i < n; i++)\n        V[i] = double(n - i);\n\n    // check assignment from an AD<double> (while not taping)\n    for(i = 0; i < n; i++)\n        V[i] = 2. * V[i];\n\n    // check array values (while not taping)\n    for(i = 0; i < n; i++)\n        ok &= ( V[i] == 2. * double(n - i) );\n\n    // independent variable\n    CPPAD_TESTVECTOR(AD<double>) X(1);\n    X[0] = double(n - 1);\n    Independent(X);\n\n    // check assignment from double during taping\n    a = -1.;\n    for(i = 0; i < n; i++)\n    {   a += 1.;\n        V[a] = double(n - i);\n    }\n\n    // check assignment from AD<double> during taping\n    a = -1.;\n    for(i = 0; i < n; i++)\n    {   a += 1.;\n        V[a] = sin( X[0] ) * V[a];\n    }\n\n    // dependent variable\n    CPPAD_TESTVECTOR(AD<double>) Z(1);\n    Z[0] = V[ X[0] ];\n\n    // create f: X -> Z\n    ADFun<double> f(X, Z);\n    CPPAD_TESTVECTOR(double)  x( f.Domain() );\n    CPPAD_TESTVECTOR(double) dx( f.Domain() );\n    CPPAD_TESTVECTOR(double)  z( f.Range() );\n    CPPAD_TESTVECTOR(double) dz( f.Range() );\n\n    double vx;\n    for(i = 0; i < n; i++)\n    {   // check that the indexing operation was taped\n        x[0] = double(i);\n        z    = f.Forward(0, x);\n        vx   = double(n - i);\n        ok  &= NearEqual(z[0], sin(x[0]) * vx, eps99, eps99);\n\n        // note that derivative of v[x] w.r.t. x is zero\n        dx[0] = 1.;\n        dz    = f.Forward(1, dx);\n        ok   &= NearEqual(dz[0], cos(x[0]) * vx, eps99, eps99);\n\n        // reverse mode calculation of same value\n        dz[0] = 1.;\n        dx    = f.Reverse(1, dz);\n        ok   &= NearEqual(dx[0], cos(x[0]) * vx, eps99, eps99);\n    }\n\n\n    return ok;\n}\n\n// create the discrete function AD<double> Floor(const AD<double> &X)\ndouble Floor(const double &x)\n{   return std::floor(x); }\nCPPAD_DISCRETE_FUNCTION(double, Floor)\n\nbool VecADTestTwo(void)\n{   bool ok = true;\n    using namespace CppAD;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    double pi    = 4. * CppAD::atan(1.);\n    size_t nx    = 10;                             // number of x grid point\n    double xLow  = 0;                              // minimum value for x\n    double xUp   = 2 * pi;                         // maximum value for x\n    double xStep = (xUp - xLow) / double(nx - 1);  // step size in x\n    double xCur;                                   // current value for x\n\n    // fill in the data vector on a uniform grid\n    VecAD<double> Data(nx);\n    size_t i;\n    for(i = 0; i < nx; i++)\n    {   xCur = xLow + double(i) * xStep;\n        // use size_t indexing of Data while not taping\n        Data[i] = CppAD::sin(xCur);\n    }\n\n    // declare independent variable\n    CPPAD_TESTVECTOR(AD<double>) X(1);\n    X[0] = 2.;\n    Independent(X);\n\n    // compute index corresponding to current value of X[0]\n    AD<double> I = X[0] / xStep;\n    AD<double> Ifloor = Floor(I);\n\n    // make sure Ifloor >= 0  (during taping)\n    AD<double> Zero(0);\n    Ifloor = CondExpLt(Ifloor, Zero, Zero, Ifloor);\n\n    // make sure Ifloor <= nx - 2 (during taping)\n    AD<double> Nxminus2(nx - 2);\n    Ifloor = CondExpGt(Ifloor, Nxminus2, Nxminus2, Ifloor);\n\n    // Iceil is Ifloor + 1\n    AD<double> Iceil  = Ifloor + 1.;\n\n    // linear interpolate Data\n    CPPAD_TESTVECTOR(AD<double>) Y(1);\n    Y[0] = Data[Ifloor] + (I - Ifloor) * (Data[Iceil] - Data[Ifloor]);\n\n    // create f: X -> Y that linearly interpolates the data vector\n    ADFun<double> f(X, Y);\n\n    // evaluate the linear interpolant at the mid point for first interval\n    CPPAD_TESTVECTOR(double)  x(1);\n    CPPAD_TESTVECTOR(double)  y(1);\n    x[0] = xStep / 2.;\n    y    = f.Forward(0, x);\n    ok  &= NearEqual(y[0], (Data[0] + Data[1])/2., eps99, eps99);\n\n    // evaluate the derivative with respect to x\n    CPPAD_TESTVECTOR(double) dx(1);\n    CPPAD_TESTVECTOR(double) dy(1);\n    dx[0] = 1.;\n    dy    = f.Forward(1, dx);\n    ok   &= NearEqual(dy[0], (Data[1] - Data[0]) / xStep, eps99, eps99);\n\n    return ok;\n}\n\nbool SecondOrderReverse(void)\n{   // Bradley M. Bell 2009-07-06\n    // Reverse mode for LdpOp was only modifying the highest order partial\n    // This test demonstrated the bug\n    bool ok = true;\n    using CppAD::AD;\n    using CppAD::NearEqual;\n    double eps = 10. * std::numeric_limits<double>::epsilon();\n\n    size_t n = 1;\n    CPPAD_TESTVECTOR(AD<double>) X(n);\n    X[0] = 2.;\n    CppAD::Independent(X);\n\n    size_t m = 2;\n    CPPAD_TESTVECTOR(AD<double>) Y(m);\n\n    // The LdpOp instruction corresponds to operations with VecAD vectors.\n    CppAD::VecAD<double> Z(2);\n    AD<double> zero = 0;\n    Z[zero] = X[0] + 1;\n\n    // The LdvOp instruction corresponds to the index being a variable.\n    AD<double> one = X[0] - 1; // one in a variable here\n    Z[one]  = X[0] + 1.;\n\n\n    // Compute a function where the second order partial for y\n    // depends on the first order partials for z\n    // This will use the LdpOp instruction because the index\n    // access to z is the parameter zero.\n    Y[0] = Z[zero] * Z[zero];\n    Y[1] = Z[one]  * Z[one];\n\n    CppAD::ADFun<double> f(X, Y);\n\n    // first order forward\n    CPPAD_TESTVECTOR(double) dx(n);\n    size_t p = 1;\n    dx[0]    = 1.;\n    f.Forward(p, dx);\n\n    // Test LdpOp\n    // second order reverse (test exp_if_true case)\n    CPPAD_TESTVECTOR(double) w(m), dw(2 * n);\n    w[0] = 1.;\n    w[1] = 0.;\n    p    = 2;\n    dw = f.Reverse(p, w);\n\n    // check first derivative in dw\n    double check = 2. * (Value( X[0] ) + 1.);\n    ok &= NearEqual(dw[0], check, eps, eps);\n\n    // check second derivative in dw\n    check = 2.;\n    ok &= NearEqual(dw[1], check, eps, eps);\n\n    // Test LdvOp\n    // second order reverse (test exp_if_true case)\n    w[0] = 0.;\n    w[1] = 1.;\n    p    = 2;\n    dw = f.Reverse(p, w);\n\n    // check first derivative in dw\n    check = 2. * (Value( X[0] ) + 1.);\n    ok &= NearEqual(dw[0], check, eps, eps);\n\n    // check second derivative in dw\n    check = 2.;\n    ok &= NearEqual(dw[1], check, eps, eps);\n\n    return ok;\n}\n\n/*\nget_test_function\nFunction that uses all the VecAD operators; i.e.\nStppOp, StpvOp, StvpOp, StvvOp, LdOpOp, LdvOp\n\nThe funcntion v(x) is defined by\nv_0(x) = 6.0\nv_1(x) = x_2\nv_2(x) = if int(x_0) == 2 then      x_3\n            else if int(x_1) == 2 then 5.0\n            else                       2.0\nv_3(x) = if int(x_0) == 3 then      x_3\n            else if int(x_1) == 3 then 5.0\n            else                       3.0\n\nThe function y(x) is defined by\ny_i(x) = if i < 4 then v_i(x) * v_i(x)\n            else v_k(x) * v_k(x) where k = int(x_4)\n*/\nCppAD::ADFun<double> get_test_function(void)\n{   //\n    // AD, VecAD\n    using CppAD::AD;\n    //\n    // ax\n    CPPAD_TESTVECTOR( AD<double> ) ax(5);\n    for(size_t i = 0; i < 5; ++i)\n        ax[i] = 2.0;\n    CppAD::Independent(ax);\n    //\n    // av (parameter)\n    CppAD::VecAD<double> av(4);\n    for(size_t i = 0; i < 4; ++i)\n        av[i] = double(i);\n    //\n    // av (variable)\n    AD<double> azero(0);\n    AD<double> aone(1);\n    av[ ax[1] ] = 5.0;    // StvpOp\n    av[ ax[0] ] = ax[3];  // StvvOp\n    av[azero]   = 6.0;    // StppOp\n    av[aone]    = ax[2];  // StpvOp\n    //\n    // ay\n    CPPAD_TESTVECTOR( AD<double> ) ay(5);\n    for(size_t i = 0; i < 4; ++i)\n    {   AD<double> ai(i);\n        ay[i] = av[ai] * av[ai]; // LdpOp\n    }\n    ay[4] = av[ ax[4] ] * av[ ax[4] ];   // LdvOp\n    //\n    // test_function\n    return CppAD::ADFun<double>(ax, ay);\n}\n//\n// get_test_function_x\nCPPAD_TESTVECTOR(double) get_test_function_x(void)\n{   //\n    // seed\n    using std::chrono::seconds;\n    seconds sec = std::chrono::duration_cast<seconds>(\n        std::chrono::system_clock::now().time_since_epoch()\n    );\n    unsigned int seed = static_cast<unsigned int>( sec.count() );\n    //\n    // uniform_01\n    CppAD::uniform_01(seed);\n    //\n    // x\n    CPPAD_TESTVECTOR(double) x(5);\n    CppAD::uniform_01(x.size(), x);\n    for(size_t i = 0; i < 5; ++i)\n        x[i] = 3.999999 * x[i];\n    //\n    return x;\n}\n//\n// forward_zero_test_function\nbool forward_zero_test_function(\n    CppAD::ADFun<double>&     fun ,\n    CPPAD_TESTVECTOR(double)& x   )\n{   //\n    // ok\n    bool ok = true;\n    //\n    // eps99\n    double eps99 = std::numeric_limits<double>::epsilon();\n    //\n    // y\n    CPPAD_TESTVECTOR(double) y(5);\n    y = fun.Forward(0, x);\n    //\n    // v\n    CPPAD_TESTVECTOR(double) v(4);\n    v[0] = 6.0;\n    v[1] = x[2];\n    // v[2]\n    if( int(x[0]) == 2 )\n        v[2] = x[3];\n    else if( int(x[1]) == 2 )\n        v[2] = 5.0;\n    else\n        v[2] = 2.0;\n    // v[3]\n    if( int(x[0]) == 3 )\n        v[3] = x[3];\n    else if( int(x[1]) == 3 )\n        v[3] = 5.0;\n    else\n        v[3] = 3.0;\n    //\n    // ok\n    for(size_t i = 0; i < 4; ++i)\n        ok &= CppAD::NearEqual(y[i], v[i] * v[i], eps99, eps99);\n    size_t k = size_t(x[4]);\n    ok &= CppAD::NearEqual(y[4], v[k] * v[k], eps99, eps99);\n    //\n    return ok;\n}\n\n// forward_one_test_function\nbool forward_one_test_function(\n    CppAD::ADFun<double>&     fun ,\n    CPPAD_TESTVECTOR(double)& x   )\n{   //\n    // ok\n    bool ok = true;\n    //\n    // eps99\n    double eps99 = std::numeric_limits<double>::epsilon();\n    //\n    // fun\n    fun.Forward(0, x);\n    //\n    // dx, dy\n    CPPAD_TESTVECTOR(double) dx(5), dy(5);\n    for(size_t j = 0; j < 5; ++j)\n    {   // dx\n        for(size_t k = 0; k < 5; ++k)\n            dx[k] = 0.0;\n        dx[j] = 1.0;\n        //\n        // dy\n        dy = fun.Forward(1, dx);\n        //\n        // ok\n        // for dy_i / dx_j for i = 0, ..., 3\n        for(size_t i = 0; i < 4; ++i)\n        {   if( j == 0 || j == 1 )\n                ok &= dy[i] == 0.0;\n            else if( j == 2 )\n            {   if( i == 1 )\n                    ok &= CppAD::NearEqual(dy[i], 2.0 * x[2], eps99, eps99);\n                else\n                    ok &= dy[i] == 0.0;\n            }\n            else if( j == 3 )\n            {   if( size_t(x[0]) == i )\n                {   if( i == 2 || i == 3 )\n                        ok &= CppAD::NearEqual(dy[i], 2.0 * x[3], eps99, eps99);\n                    else\n                        ok &= dy[i] == 0.0;\n                }\n            }\n            else\n            {    assert( j == 4 );\n                 ok &= dy[i] == 0.0;\n            }\n        }\n        //\n        // ok\n        // for dy_4 / dx_j\n        if( j == 0 || j == 1 || j == 4 )\n                ok &= dy[4] == 0.0;\n        else\n        {   size_t k = size_t( x[4] );\n            if( k == 1 && j == 2 )\n                ok &= CppAD::NearEqual(dy[4], 2.0 * x[2], eps99, eps99);\n            else if( (k == 2 || k == 3) && j == 3 && size_t(x[0]) == k )\n                ok &= CppAD::NearEqual(dy[4], 2.0 * x[3], eps99, eps99);\n            else\n                ok &= dy[4] == 0.0;\n        }\n    }\n    //\n    return ok;\n}\n\nbool jac_sparsity_test_function(CppAD::ADFun<double>& fun)\n{   //\n    // ok\n    bool ok = true;\n    //\n    // size_vector\n    typedef CppAD::vector<size_t> size_vector;\n    //\n    // sparse_rc\n    typedef CppAD::sparse_rc<size_vector> sparse_rc;\n    //\n    // dependency\n    for(bool dependency : {false, true})\n    {   //\n        // pattern_check\n        size_t nr = 5, nc = 5, nnz = 0;\n        sparse_rc pattern_check(nr, nc, nnz);\n        for(size_t i = 0; i < nr; ++i)\n        {   // values in v depend on x_2 and x_3\n            pattern_check.push_back(i, 2);\n            pattern_check.push_back(i, 3);\n            if( dependency )\n            {   // indices in v depend on x_0 and x_1\n                pattern_check.push_back(i, 0);\n                pattern_check.push_back(i, 1);\n                if( i == 4 )\n                {   // y_4 depends on x_4 as an index in v\n                    pattern_check.push_back(i, 4);\n                }\n            }\n        }\n        //\n        // pattern_eye\n        nr = 5, nc = 5, nnz = 5;\n        sparse_rc pattern_eye(nr, nc, nnz);\n        for(size_t k = 0; k < nr; ++k)\n            pattern_eye.set(k, k, k);\n        //\n        // pattern_jac\n        sparse_rc pattern_jac;\n        bool transpose     = false;\n        bool internal_bool = false;\n        fun.for_jac_sparsity(\n            pattern_eye, transpose, dependency, internal_bool, pattern_jac\n        );\n        //\n        // ok\n        ok &= pattern_jac == pattern_check;\n        //\n        // pattern_jac\n        fun.rev_jac_sparsity(\n            pattern_eye, transpose, dependency, internal_bool, pattern_jac\n        );\n        //\n        // ok\n        ok &= pattern_jac == pattern_check;\n    }\n    //\n    return ok;\n}\n\nbool hes_sparsity_test_function(CppAD::ADFun<double>& fun)\n{   //\n    // ok\n    bool ok = true;\n    //\n    // size_vector\n    typedef CppAD::vector<size_t> size_vector;\n    //\n    // sparse_rc\n    typedef CppAD::sparse_rc<size_vector> sparse_rc;\n    //\n    // pattern_check\n    size_t nr = 5, nc = 5, nnz = 0;\n    sparse_rc pattern_check(nr, nc, nnz);\n    for(int r : {2, 3} )\n    {   for(int c : {2, 3} )\n            pattern_check.push_back(size_t(r), size_t(c));\n    }\n    //\n    // pattern_eye\n    nr = 5, nc = 5, nnz = 5;\n    sparse_rc pattern_eye(nr, nc, nnz);\n    for(size_t k = 0; k < nr; ++k)\n        pattern_eye.set(k, k, k);\n    //\n    // pattern_jac\n    sparse_rc pattern_jac;\n    bool dependency    = false;\n    bool transpose     = false;\n    bool internal_bool = false;\n    fun.for_jac_sparsity(\n        pattern_eye, transpose, dependency, internal_bool, pattern_jac\n    );\n    //\n    // select_domain\n    CPPAD_TESTVECTOR(bool) select_domain(5);\n    for(size_t i = 0; i < 5; ++i)\n        select_domain[i] = true;\n    //\n    // select_range\n    CPPAD_TESTVECTOR(bool) select_range(5);\n    for(size_t i = 0; i < 5; ++i)\n        select_range[i] = false;\n    //\n    // pattern_hes\n    sparse_rc pattern_hes;\n    //\n    // i\n    for(size_t i = 0; i < 5; ++i)\n    {   //\n        // pattern_hes\n        select_range[i] = true;\n        fun.rev_hes_sparsity(\n            select_range, transpose, internal_bool, pattern_hes\n        );\n        select_range[i] = false;\n        //\n        // ok\n        ok &= pattern_hes == pattern_check;\n        //\n        // pattern_hes\n        select_range[i] = true;\n        fun.for_hes_sparsity(\n            select_domain, select_range, internal_bool, pattern_hes\n        );\n        select_range[i] = false;\n        //\n        // ok\n        ok &= pattern_hes == pattern_check;\n    }\n    //\n    return ok;\n}\n\n} // END empty namespace\n\nbool VecAD(void)\n{   bool ok = true;\n    ok &= test_comp_assign();\n    ok &= VecADTestOne();\n    ok &= VecADTestTwo();\n    ok &= SecondOrderReverse();\n    //\n    // fun, x\n    CppAD::ADFun<double>     fun = get_test_function();\n    CPPAD_TESTVECTOR(double) x   = get_test_function_x();\n    //\n    ok &= forward_zero_test_function(fun, x);\n    ok &= forward_one_test_function(fun, x);\n    ok &= jac_sparsity_test_function(fun);\n    ok &= hes_sparsity_test_function(fun);\n    //\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/vec_ad_par.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\nTest the use of the parameters in VecAD element assignments\n*/\n\n# include <cppad/cppad.hpp>\n\ntypedef CppAD::AD<double>      ADdouble;\ntypedef CppAD::AD< ADdouble > ADDdouble;\n\nbool VecADPar(void)\n{\n    using namespace CppAD;\n\n    bool ok = true;\n\n    CPPAD_TESTVECTOR( ADdouble ) x(2);\n    x[0] = 0;\n    x[1] = 0;\n    Independent(x);\n\n    CPPAD_TESTVECTOR( ADDdouble ) y(1);\n    y[0] = 1;\n    Independent(y);\n\n    VecAD< ADdouble > v(2);\n    ADDdouble zero(0);\n    ADDdouble one(1);\n    v[zero] = x[0]; // these two parameter values are equal,\n    v[one]  = x[1]; // but they are not identically equal\n\n    CPPAD_TESTVECTOR( ADDdouble ) z(1);\n    z[0] = v[zero] + v[one];\n\n    // f(y) = x[0] + x[1]\n    ADFun< ADdouble > f(y, z);\n    CPPAD_TESTVECTOR( ADdouble ) a( f.Domain() );\n    CPPAD_TESTVECTOR( ADdouble ) b( f.Range() );\n\n    // fy = f(y) = x[0] + x[1]\n    a[0]  = 0.;\n    b     = f.Forward(0, a);\n\n    // check value of f\n    ok &= b[0] == (x[0] + x[1]);\n\n    // g(x) = x[0] + x[1];\n    ADFun<double> g(x, b);\n    CPPAD_TESTVECTOR( double ) c( g.Domain() );\n    CPPAD_TESTVECTOR( double ) d( g.Range() );\n\n    // d = g(1, 2)\n    c[0] = 1.;   // these tow values are not equal and correspond\n    c[1] = 2.;   // to replacements for the equal parameter values above\n    d = g.Forward(0, c);\n\n    // check function value\n    ok &= (d[0] == c[0] + c[1]);\n\n    return ok;\n}\n"
  },
  {
    "path": "test_more/general/vec_unary.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-22 Bradley M. Bell\n// ----------------------------------------------------------------------------\n\n/*\nTest the use of VecADelem with unary operators\n*/\n\n# include <cppad/cppad.hpp>\n\n\nbool VecUnary(void)\n{\n    using namespace CppAD;\n    using CppAD::sin;\n    using CppAD::atan;\n    using CppAD::cos;\n    using CppAD::exp;\n    using CppAD::log;\n    using CppAD::sqrt;\n    using CppAD::NearEqual;\n    double eps99 = 99.0 * std::numeric_limits<double>::epsilon();\n\n    bool ok  = true;\n    size_t n = 8;\n    size_t i;\n\n    CPPAD_TESTVECTOR(AD<double>) X(n);\n    VecAD<double>             Y(n);\n    CPPAD_TESTVECTOR(AD<double>) Z(n);\n\n\n    for(i = 0; i < n; i++)\n        X[i] = int(i);  // some compilers require the int here\n    Independent(X);\n\n    AD<double> j;\n\n    j    = 0.;\n    Y[j] = X[0];\n    Z[0] = -Y[j];\n\n    j    = 1.;\n    Y[j] = X[1];\n    Z[1] = sin( Y[j] );\n\n    j    = 2.;\n    Y[j] = X[2];\n    Z[2] = fabs( Y[j] );\n\n    j    = 3.;\n    Y[j] = X[3];\n    Z[3] = atan( Y[j] );\n\n    j    = 4.;\n    Y[j] = X[4];\n    Z[4] = cos( Y[j] );\n\n    j    = 5.;\n    Y[j] = X[5];\n    Z[5] = exp( Y[j] );\n\n    j    = 6.;\n    Y[j] = X[6];\n    Z[6] = log( Y[j] );\n\n    j    = 7.;\n    Y[j] = X[7];\n    Z[7] = sqrt( Y[j] );\n\n\n    ADFun<double> f(X, Z);\n    CPPAD_TESTVECTOR(double) x(n);\n    CPPAD_TESTVECTOR(double) z(n);\n\n    for(i = 0; i < n; i++)\n        x[i] = 2. / double(i + 1);\n    x[7] = fabs( x[7] );\n\n    z    = f.Forward(0, x);\n\n    ok  &= NearEqual(z[0],      - x[0], eps99, eps99);\n    ok  &= NearEqual(z[1], sin( x[1] ), eps99, eps99);\n    ok  &= NearEqual(z[2], fabs( x[2] ), eps99, eps99);\n    ok  &= NearEqual(z[3], atan(x[3] ), eps99, eps99);\n    ok  &= NearEqual(z[4], cos( x[4] ), eps99, eps99);\n    ok  &= NearEqual(z[5], exp( x[5] ), eps99, eps99);\n    ok  &= NearEqual(z[6], log( x[6] ), eps99, eps99);\n    ok  &= NearEqual(z[7], sqrt(x[7] ), eps99, eps99);\n\n    return ok;\n}\n"
  },
  {
    "path": "typos.toml",
    "content": "[default.extend-words]\nFo     = \"Fo\"\niy     = \"iy\"\nnd     = \"nd\"\not     = \"ot\"\nmak    = \"mak\"\nyout   = \"yout\"\n"
  },
  {
    "path": "user_guide.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-25 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin user_guide}\n{xrst_spell\n    adolc\n    autodiff\n    fadbad\n    openmp\n    org\n    posix\n    sacado\n    templated\n}\n\n{xrst_comment BEGIN: Before changing see new_release.sh and check_version.sh}\n\nCppAD User's Manual\n###################\n\n.. image:: {xrst_dir coin.png}\n\nLicense\n*******\nCppAD is distributed by\n`COIN-OR <https://www.coin-or.org/>`_\nwith the Eclipse Public License\n`EPL-2.0 <https://spdx.org/licenses/EPL-2.0.html>`_\nor the GNU General Public License\n`GPL-2.0-or-later <https://spdx.org/licenses/EPL-2.0.html>`_\n\nGit Repository\n**************\n`<https://github.com/coin-or/CppAD>`_\n\nVersions\n********\n\n.. list-table::\n    :widths: auto\n\n    * - This version\n      - cppad-20260408\n    * - Documentation for latest version\n      - `latest <https://cppad.readthedocs.io/latest>`_\n    * - Documentation for most recent stable version\n      - `stable-2026 <https://cppad.readthedocs.io/stable-2026>`_\n    * - Most recent release of this stable version\n      - `release-2026 <https://codeload.github.com/coin-or/CppAD/tar.gz/refs/tags/20260000.0>`_\n\n{xrst_comment END: Before changing see new_release.sh and check_version.sh}\n\nOther Links\n***********\n\n.. list-table::\n    :widths: auto\n\n    * - :ref:`install-name`\n      - :ref:`get_started<get_started.cpp-name>`\n      - :ref:`whats_new-name`\n      - :ref:`addon-name`\n      - `project manager <https://www.seanet.com/~bradbell/>`_\n\n\nAlgorithmic Differentiation\n***************************\nWe refer to the automatic creation of an algorithm that\ncomputes derivative values from an algorithm that computes function values\nas *Algorithmic Differentiation* ,\nalso referred to as *Automatic Differentiation* or just AD.\nA brief introduction to AD can be found in\n`wikipedia <https://en.wikipedia.org/wiki/Automatic_differentiation>`_.\nThe web site\n`autodiff.org <https://www.autodiff.org/>`_\nis dedicated to research about, and promoting the use of, AD.\n\nFeatures\n********\n\nOperator Overloading\n====================\nCppAD uses operator overloading of the C++ template class :ref:`AD-name`\nto compute derivatives of algorithms defined using AD objects; see\nthe :ref:`introduction-name` for a description of how this is accomplished.\n\nBase Type\n=========\nThe operator overloading uses a templated base type that\ncan be user defined; see :ref:`base_require-name` .\nThe required definitions for ``AD<float>`` and\n``AD<double>`` are included as part of CppAD.\n\nRecording Operations\n====================\nA sequence of ``AD`` < *Base* >\n:ref:`operations<glossary@Operation@Sequence>`\ncan be recorded and stored in an\n:ref:`AD function object<ADFun-name>` .\nThis object can then be used to evaluate\nfunction values and arbitrary order derivatives,\nand sparsity patterns of derivative values using the *Base* type.\n\nMulti-Threading\n===============\nCppAD supports an arbitrary :ref:`multi threading<multi_thread-name>` environment.\nExamples are provided using Boost threads, Posix threads, and Openmp threads.\n\nOptimizing Operations Sequences\n===============================\nDuring the recording of a function,\nthe :ref:`Independent-name` variables are know and a forward dependency\nanalysis is used to determine which operations should be recorded.\nOnce the :ref:`Dependent-name` variables are determined,\na reverse dependency analysis can be preformed.\nThis :ref:`optimize-name` routine uses a reverse dependency analysis,\nand other techniques,\nto remove unnecessary operations.\n\nDynamic Parameters\n==================\nCppAD enables one to specify a vector of\n:ref:`glossary@Parameter@Dynamic` parameters.\nThe value of the function and derivatives can depend on these parameters,\nbut no derivatives are taken with respect to these parameters.\nThis enables CppAD to reduce the derivative calculations; e.g.,\nthe derivative of variable times a variable has two terms\nwhile a variable times a parameter only has one.\n\nDerivative Calculations\n=======================\nArbitrary order\n:ref:`Forward-name` and :ref:`Reverse-name`\nmode derivative calculations\ncan be preformed using an ``ADFun`` object.\nEasy to user drivers that compute the\nentire :ref:`Jacobian-name` and a specific :ref:`Hessian-name` are included.\n\nSparsity\n========\nBoth forward and reverse mode can be used to calculation the sparsity\npattern for Jacobians and Hessians; see :ref:`sparsity_pattern-name` .\nWhere a Jacobian or Hessian is sparse,\nboth forward and reverse mode can be combined with the sparsity pattern\nto speed up the calculation of\n:ref:`sparse derivatives<sparse_derivative-name>` .\nIn addition, a :ref:`subgraph<subgraph_jac_rev-name>` method,\nthat does not require a sparsity pattern, can be used\nto speed up these derivative calculations.\n\nRecording Derivative Operations\n===============================\nA ``ADFun`` object can be converted into an object that\nevaluates derivatives using the type ``AD`` < *Base* > ; see :ref:`base2ad-name` .\nThis enables one to record new functions that\nare expressed using derivatives of other functions.\n\nAtomic Functions\n================\nUser defined derivative calculations for arbitrary functions\ncan also be included in\na recording using :ref:`atomic functions<atomic_two-name>` .\nA special :ref:`checkpoint<chkpoint_one-name>` class is included\nwhich allows one to record a function and reuse it as\nan atomic operation in other functions.\nThere also is a special interface for user defined unary\n:ref:`discrete functions<Discrete-name>` ; i.e.,\nfunctions that depend on the\n:ref:`independent variables<glossary@Tape@Independent Variable>`\nbut which have identically zero derivatives (e.g., a step function).\n\nLogical Comparisons\n===================\nLogical comparisons can be included in an operation sequence\nusing AD :ref:`conditional expressions<CondExp-name>` .\n\nVectors\n=======\nThe CppAD API allows one to use any\n:ref:`SimpleVector-name` class.\nThe preprocessor symbol :ref:`CPPAD_TESTVECTOR<testvector-name>`\nis template vector class which is used for correctness testing.\nMany of the correctness tests use this template vector class\nwhich you can choose during the :ref:`cmake-name` configuration command.\n\nSoftware Engineering\n********************\nCppAD is developed using the software engineering procedures described\non the project manager's\n`software <https://www.seanet.com/~bradbell/software.html>`_\nweb page.\n\nTesting\n*******\n\nCorrectness\n===========\nThere is an extensive set of correctness tests; see :ref:`cmake_check-name` .\n\nSpeed\n=====\nA set of programs for doing :ref:`speed-name` comparisons between\n`Adolc <https://github.com/coin-or/ADOL-C>`_,\nCppAD,\n`Fadbad <http://uning.dk//>`_,\nand\n`Sacado <https://trilinos.github.io/sacado.html>`_\nare included.\n\nUtilities\n*********\nCppAD includes a set of C++ :ref:`utilities<utility-name>` that are useful\nfor general operator overloaded numerical methods.\n\nRelease Notes\n*************\nThis :ref:`whats_new-name` for a list of recent extensions and bug fixes.\n\nExample\n*******\nThe file :ref:`get_started.cpp-name`\ncontains an example and test of using CppAD to compute\nthe derivative of a polynomial.\nThere are many other\n:ref:`examples<Example-name>` .\nAll of the examples are also correctness tests,\nwhich ensures that they work properly.\n\nContents\n********\n{xrst_toc_table\n    xrst/install/install.xrst\n    xrst/theory/theory.xrst\n    include/cppad/core/user_ad.hpp\n    include/cppad/core/ad_fun.hpp\n    xrst/preprocessor.xrst\n    xrst/multi_thread.xrst\n    include/cppad/utility/xrst/utility.xrst\n    include/cppad/ipopt/solve.hpp\n    xrst/example.xrst\n    speed/speed.xrst\n}\n\n\n{xrst_end user_guide}\n"
  },
  {
    "path": "uw_copy_040507.html",
    "content": "<html><head><title>Vol 4, Part 5, Chapter 7</title>\n\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\"></head>\n<body bgcolor=\"#ffffff\" link=\"#0000ff\" vlink=\"#800080\"><font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\"> \n</font><p><font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\"><b>Chapter 7</b></font></p>\n<p><font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\"><b>PATENT, INVENTION, AND COPYRIGHT POLICY</b></font></p>\n<p><font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\"><a name=\"anchor1\"></a><b>Section 1. Patent and Invention Policy</b></font></p>\n\n<ol type=\"A\"><font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\"> \n<li>This policy covers both patented and nonpatented innovations, including computer \n  software with commercial value, and is applicable to all faculty, staff, and \n  students. The policy is intended to show the University's positive attitude \n  toward transfer of results of its research to the private sector.</li>\n</font><p></p>\n<font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">  <li>The purpose of university research is to seek new knowledge for the general \n     benefit. Although university research is not directed intentionally toward \n     inventions, commercially valuable inventions do often result, and it is generally \n     in the best interests of the University and the public that patents be obtained \n     and/or licenses granted as described in this policy. Inventions shall be promptly \n     reported to the University's Office of Intellectual Property and Technology \n     Transfer and all concerned shall cooperate to assure prompt initiation of \n     appropriate technology transfer actions. The term \"invention\" means any invention \n     or discovery which is or may be patentable or otherwise protectable as to \n     ownership. An invention may be a process, machine, manufacture, composition \n     of matter or design, or any new or useful improvement thereof. An invention \n     is deemed to be \"made\" when it is conceived or first actually reduced to practice. \n  </li>\n</font><p></p>\n<li><font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">University employees shall report all inventions and discoveries to the \n  University's Office of Intellectual Property and Technology Transfer. As a condition \n  of employment, and even if a specific patent agreement is not signed, University \n  employees agree to assign all inventions in which the University has an interest \n  to the University, to an invention management agency designated by the University, \n  or to the sponsor if required under agreements governing the research. Employees \n  shall execute documents of assignment and do everything reasonably required \n  to assist the assignee(s) in obtaining, protecting, and maintaining patent or \n  other proprietary rights. Students who are also employees, students working \n  on a sponsored project, and students who have used University resources (other \n  than for lecture-based coursework) shall also report all inventions and discoveries \n  to the University's Office of Intellectual Property and Technology Transfer \n  and shall assign all such inventions and discoveries in the same manner as University \n  employees. Inventions in which the University has an interest but which do not \n  meet University criteria for patenting shall be managed in accordance with policies \n  and procedures determined by the University Office of Intellectual Property \n  and Technology Transfer. If and to the extent permitted by state law and other \n  University policies, those procedures may include: (a) a mechanism by which \n  the inventor(s) may personally pay patenting costs; (b) the formation of a commercial \n  enterprise to pursue commercialization; and, under very rare circumstances, \n  (c) the transfer, for appropriate consideration, of the patent rights to the \n  inventor(s). These procedures shall be implemented at the discretion of the \n  Vice Provost for Intellectual Property and Technology Transfer.\n  \n</font><p><font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">Although all inventions and discoveries must be reported to the Office of Intellectual \n  Property and Technology Transfer, there are instances when the University may \n  choose not to assert ownership. The University will not require assignment of \n  interests for any invention for which no equipment, supplies, facilities, or \n  trade secret information of the University was used and which was developed \n  entirely on the employee's own time, unless (a) the inventions related (i) directly \n  to the business of the University, or (ii) the University's actual or demonstrably \n  anticipated research or development, or (b) the invention results from any work \n  performed by the employee for the University.</font></p>\n<font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">  </font><p></p>\n</li><li><font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">Research funded wholly or in part by an outside sponsor is subject to this \n  policy as modified by the provisions of the agreement covering such work. Employees \n  engaged in sponsored research are bound by the provisions of the agreement between \n  the University and the sponsor. Title to any inventions conceived or first reduced \n  to practice in the course of research supported by Federal agencies, industry, \n  or other sponsors shall generally vest in the University. In rare cases, an \n  industrial sponsor may possess a dominant patent position in a certain technology \n  area so that any patent the University might seek would be of little or no value. \n  For this or other reasons, an exception to the University title policy may be \n  approved by the University's Office of Intellectual Property and Technology \n  Transfer when to do so will honor the general principles of this policy, protect \n  the equities involved, and satisfy the requirements of the parties.</font></li>\n<font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">  </font><p></p>\n<li><font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\"> Industry supported research is valued by the University when it embraces \n  a proper balance between the University's educational mission and industry's \n  quest for the development of commercial products, processes, and services. Interaction \n  with industry may take any of several forms, including grants, contracts, consortia \n  agreements, and affiliate programs. Industry sponsors may be assured of at least \n  a non-exclusive license to inventions conceived or developed with their support. \n  Where the sponsor uses the invention entirely within its own operations, the \n  license may be royalty-free. Where the sponsor, or a third party, manufactures \n  and sells products, services, or processes based on the invention, reasonable \n  royalty payments to the University, or its assignee, are required. If necessary \n  for the effective development and marketing of a University invention, an exclusive \n  license may be granted, usually for a limited time period. Where an invention \n  is not identifiable in advance, the University may grant the sponsor an option \n  to an exclusive license if the sponsor agrees to finance the cost of the University's \n  patent application and observe certain diligence requirements that will assure \n  promptly bringing the invention into public use. The patent financing may be \n  treated as an offset against royalties payable when the invention is marketed.</font></li>\n<font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">  </font><p></p>\n<li><font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">The University retains the right to file patents itself or to use other \n  patent management firms. The University has agreements with the Washington Research \n  Foundation, Research Corporation Technologies of Tucson, Arizona and Battelle \n  Development Corporation in Columbus, Ohio as patent and license agents.</font></li>\n<font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">  </font><p></p>\n<li><font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">Both the University and the inventor are entitled to a share of income from \n  licensed inventions; the University on the basis of salary and facilities support \n  for the inventor and the cost of patent or license administration; and the inventor \n  on the basis of creative activity, documenting the invention, and assisting \n  as necessary with commercialization. Thus, the University allocates a share \n  of income to the inventor. The remainder is dedicated to further research by \n  allocating shares to the college/department (or other unit) in which the invention \n  was conceived or first reduced to practice and to the Office of the Provost.</font></li>\n<font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">  </font><p></p>\n<li><font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\"><a name=\"h\"></a>The University may take an equity position in a company \n  whether or not license fees or royalties are paid to the University as part \n  of a negotiated agreement. A typical circumstance under which the University \n  might receive equity would be as part of an agreement licensing University-developed \n  technology to a start-up or developing business venture. Another example might \n  occur when an employee of the University utilizes the expertise and/or technology \n  he or she has developed in the course of University employment and assists a \n  business venture in the commercialization of an idea. (A business venture includes \n  corporations, partnerships, or other commercial enterprises.) Such a commercial \n  association with the University and its employees adds both value and credibility \n  to the new business venture. To assure a balance of interests for the business \n  venture as well as for the University, the University will generally require \n  that it receive an equity position in such circumstances. </font></li>\n<font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">  \n</font><p><font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">The University's equity interests are managed and disposed of in accordance \n  with guidelines established by the Treasury Office in consultation with the \n  Office of the Provost and the policies and procedures stated in the <i>University \n  Handbook</i> and <i>Administrative Policy Statements</i>. University employees \n  may be eligible to receive a portion of the University's equity interest in \n  accordance with the policies and procedures described in the University's <i>Administrative \n  Policy Statements</i> and as allowed under state law and University conflict \n  of interest policies. When such equities are liquidated, the net proceeds, after \n  recovery of all University costs and after any distributions to eligible recipients, \n  accrue to appropriate University accounts and are administered by the Provost \n  to promote research and technology transfer across the entire University. If \n  the proceeds from the disposition of a particular equity interest are unusually \n  large, the Provost shall confer with the University Budget Committee, the Research \n  Advisory Board, or other appropriate faculty bodies, on alternative uses for \n  amounts in excess of a base figure (set at $3 million in 2000 dollars).</font></p>\n<font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">  \n</font><p><font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">There may be situations in which both the University and its employees separately \n  own equity interests in a business venture. In such circumstances, the employee's \n  equity interest is considered to be independent of the University's equity interest \n  and is not held, managed, disposed of, or distributed by the University. An \n  example would be a case in which the University receives an equity interest \n  in a business venture as a result of licensing certain intellectual property \n  developed by one of its employees and in which the same employee also owns a \n  equity interest as a result of being a founder of the business venture receiving \n  the license. In this example, the employee's equity interest is not held or \n  managed by the University, but rather by the employee, and the employee's status \n  as a founder having an ownership stake in the business venture renders the employee \n  ineligible to receive a distribution of a portion of the University-owned equity.</font></p>\n<font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">  </font><p></p>\n<li><font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">As a public institution, the University should undertake sponsored research \n  only when the results can be published. Publication may be deferred for a reasonable \n  time during which the University and the sponsor review the feasibility of patent \n  coverage or other protection on an invention described in the publication. Likewise, \n  graduate student theses or dissertations containing invention details may be \n  withheld from the Library shelves for a limited period while this evaluation \n  process is conducted. Some research agreements may involve University access \n  to a sponsor's proprietary data subject to a clause defining the conditions \n  under which such data will be identified, accepted, and used. Students should \n  be able to participate in such research in a meaningful way without access to \n  proprietary data. When publication of the research involving proprietary data \n  is contemplated, the University may agree to provide the sponsor with advance \n  copy prior to submission for publication to allow the sponsor an opportunity \n  to identify any inadvertent disclosure of proprietary data.</font></li>\n<font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">  </font><p></p>\n<li><font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">Employee consulting with commercial enterprises can be of significant benefit \n  to the University, the employee, the commercial entity, and the general public. \n  However, such involvements include the potential for conflicts of interest, \n  for the inhibition of the free exchange of information, and for interference \n  with the employee's primary allegiance to the University. University employees \n  should be guided in these arrangements by the policy stated in Volume Four, \n  Part V, Chapters <a href=\"http://www.washington.edu/faculty/facsenate/handbook/04-05-02.html\">2</a> and <a href=\"http://www.washington.edu/faculty/facsenate/handbook/04-05-06.html\">6</a> \n  of the <i>University Handbook</i>. Invention clauses in consulting agreements \n  must be consistent with the policy of the University and with University commitments \n  under sponsored research agreements. Questions concerning potential conflicts \n  should be referred to the University's Office of the Provost and the Office \n  of Research.</font></li>\n<font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">  </font><p></p>\n<li><font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">Conflicts of interest are of prime concern when a faculty member is involved \n  in \"deeper than consulting\" arrangements with business ventures. Although the \n  faculty member may hold an equity interest or a management position in a business \n  venture, he or she must do so consistent with the principles and procedures \n  of Executive Order 57 (<i>University Handbook</i>, <a href=\"http://www.washington.edu/faculty/facsenate/handbook/04-05-06.html\">Volume \n  Four, Part V, Chapter 6</a>, Section 6, Involvement with Commercial Enterprise, \n  Deeper than Consulting). In situations where the employee is a board member, \n  manager, or receives shares of stock, the option to purchase stock, or other \n  equity interest in return for the use of his or her services and/or inventions \n  in a business venture, approval by the Office of the Provost (after review by \n  the dean and the chair) is required. The primary focus of the review by the \n  Office of the Provost will be to ensure that potential conflicts of interest \n  and exposure to liability are properly managed. For example, the interests of \n  the graduate students involved in such cases must be protected, there must be \n  no direct managerial involvement of the faculty member in the business venture, \n  there must be an arms-length relationship between the faculty member's responsibilities \n  to the business venture and the faculty member's academic responsibilities, \n  and mechanisms must be in place to ensure that the research program of the faculty \n  member is not distorted by his or her interests in the business venture.</font></li>\n<font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">  </font></ol>\n\n<p><font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\"><a name=\"anchor2\"></a><b>Section 2. Copyright Policy</b></font></p>\n<ol type=\"A\">\n\n<li><font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">Background.</font></li>\n<p><font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">The University encourages the publication of scholarly works as an inherent \n  part of its educational mission. In this connection, the University acknowledges \n  the right of faculty, staff, and students to prepare and publish, through individual \n  initiative, articles, pamphlets, and books that are copyrighted by the authors \n  or their publishers and that may generate royalty income for the authors.</font></p>\n<p><font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">The variety and number of copyrightable materials that may be created in the \n  university community have increased significantly in recent years as have the \n  author-university- sponsor relationships under which such materials are produced. \n  Therefore, the following statement of University policy on ownership and use \n  of copyrightable materials is provided to clarify the respective rights of individuals \n  and the University in this increasingly important area. The policy will be administered \n  by the University's Office of Intellectual Property and Technology Transfer.</font></p>\n<p></p>\n<li><font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">General Statement of University Policy on Ownership and Use of Copyrightable \n  Materials</font></li>\n<p><font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">University faculty, staff, and students retain all rights in copyrightable \n  materials they create, including scholarly works, subject to the following exceptions \n  and conditions:</font></p>\n<ol type=\"1\">\n<font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">  <li>Grant and Contract Limitations. Conditions regarding rights in data or restrictions \n     on copyright privileges contained in sponsored grants, contracts, or other \n     awards are binding on the University and on faculty, staff, or student authors. \n     Copyright works, with the exception of routine progress reports, prepared \n     as required elements of such sponsored grants, contracts, or other awards \n     shall be reported to the Office of Intellectual Property and Technology Transfer \n     for review prior to any external dissemination of the work. If necessary to \n     fulfill grant and contract limitations, authors shall execute an appropriate \n     written assignment of copyrights to the University.</li>\n\t</font><p></p>\n<font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">  <li>University-Owned Materials. Materials shall be \"University-owned\" within \n     the meaning of this policy statement if the work is a \"work for hire\" under \n     copyright law or the author was commissioned in writing by the University \n     (or one of its colleges, schools, departments, or other divisions) to develop \n     the materials as a part of the author's regularly compensated duties, as for \n     example, released time arrangements in the case of faculty members. As to \n     a faculty member, \"commissioned in writing\" specifically does not refer to \n     his or her general obligation to produce scholarly works.</li>\n\t</font><p></p>\n<font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">  <li>University-Sponsored Materials. Materials shall be \"University-sponsored \n     materials\" within the meaning of this policy statement if the author developed \n     the materials in the course of performance of his or her normal duties and \n     utilized University staff, resources, or funding to develop the work. As to \n     a faculty member, \"normal duties\" does not include his or her usual scholarly \n     activity unless it involves extensive uncompensated use of University resources.</li>\n\t</font><p></p>\n<font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">  <li>Written Agreements. It is desirable to reach agreement in writing as to \n     the rights of the University and of participants before work begins whenever \n     (1) a question exists as to whether the materials will be University-owned \n     or University-sponsored, or (2) copyrightable materials are likely to result \n     from the joint efforts of persons in academic departments and University service \n     departments. As to jointly-developed materials, determination of rights in \n     written form shall be accomplished no later than prior to sale of the materials \n     in question. Questions concerning the interpretation and administration of \n     this policy shall be resolved in accordance with Section 3.</li>\n\t</font><p></p>\n<font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">  <li>Proportional Ownership. In case of materials developed in substantial part \n     under commission and in substantial part through other means, the materials \n     shall be regarded as \"University-owned\" in an appropriate proportion. In the \n     case of materials developed in substantial part during the course of normal \n     duties and with use of University staff, resources, or funding the materials \n     shall be regarded as \"University-sponsored\" in an appropriate proportion.</li>\n\t</font><p></p>\n<font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">  <li>Royalty-Free Privileges to University. The University retains a right to \n     royalty-free use of any copyrightable materials developed by University employees \n     (other than books and materials available from a publisher through normal \n     distribution channels) when the development of such materials was advanced \n     through the use of University facilities, supplies, equipment, or staff services. \n     This right exists even though the materials do not constitute University-owned \n     or University-sponsored materials as defined above (e.g., where use of facilities \n     by a faculty member was not extensive).</li>\n\t</font><p></p>\n<font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">  <li>Student Writings. Students employed by the University in any capacity are \n     covered by the terms of this policy. In addition, where a student receives \n     financial aid or remuneration under a sponsored research, training, or fellowship \n     program, his or her rights in copyrightable materials are limited by the terms \n     of the University agreement with the sponsoring agency. The University has \n     no ownership rights in copyrightable materials developed by students who are \n     not employees of the University or in materials unrelated to their employment.</li>\n</font></ol>\n<p></p>\n<li><font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">Types of Materials.</font></li>\n<p><font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">The types of materials to which this policy is intended to apply include:</font></p>\n<ol>\n<font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">  <li>Video and audio recordings, tapes, and cassettes.</li>\n  <li>Film, film strips and other visual aids.</li>\n  <li>Books, texts, study guides and similar published materials.</li>\n  <li>Computer programs and software when copyright rather than patent or trade \n     secret protection is relied upon as the primary source of legal protection. \n     (When the primary commercial value of a computer program lies in its transfer \n     in limited quantities under arrangements of confidentiality, it shall be treated \n     as unpatented technology and be subject to the University Patent and Invention \n     Policy.)</li>\n  <li>Musical or dramatic compositions.</li>\n  <li>Internet-based productions and multimedia products.</li>\n  <li>Other copyrightable materials.</li>\n</font></ol>\n<p></p>\n<li><font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">Rights Involved in use of University-Owned or University- Sponsored Materials.</font></li>\n<p></p>\n<ol>\n<font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">  <li>Two categories of use are differentiated for purposes of this policy:  internal \n     use and external use. Internal use refers to use by any unit of the University \n     for instruction, research, or other educational purposes. External use refers \n     to use by other educational institutions, government and other nonprofit institutions, \n     and use resulting from lease or other contractual arrangements for commercial \n     distribution of the materials.</li>\n\t</font><p></p>\n<font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">  <li>Use of University-owned or University-sponsored materials under this policy \n     shall be subject to the following conditions:</li>\n\t</font><p></p>\n<font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">\t</font><ol type=\"a\">\n<font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">    <li>Internal use</li>\n\t</font><p></p>\n<font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">\t</font><ol type=\"1\">\n<li><font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\"> Each instance of use of such materials within \n     the University requires the approval of the author and the department or college \n     unless advance approval is waived through a prior written understanding or \n     the author's consent is implicit in the terms of the grant or contract supporting \n     the work. Internal uses of such materials will not involve a transfer of funds \n     between departments unless the lending department incurs incremental costs \n     in order to make the materials available.</font></li>\n<font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">\t</font><p></p>\n<li><font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">As long as the author or producer of such \n     materials remains an employee of the University, the author may: (a) request \n     reasonable revisions of the materials prior to any instance of internal use, \n     or (b) ask that the materials be withdrawn from internal use if revisions \n     are not feasible.</font></li>\n<font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">\t</font><p></p>\n<font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">    In cases where the University has invested significant funds in the production \n     of the materials and the author/producer is unable to agree with the department \n     head on appropriate revision or withdrawal of materials, the question will \n     be referred to the dean of the school or college for mediation.\n\t</font><p></p>\n<font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">    <li>If the author or producer terminates employment \n     with the University, then the University retains the right to continue internal \n     use of the material unless the author/producer and the University agree in \n     writing on special conditions for subsequent internal use of the materials \n     and the procedures for their revision.</li>\n\t</font></ol>\n<p></p>\n<font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">    <li>External use</li>\n\t</font><p></p>\n<font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">    Licensing or sale of University-owned or University- sponsored materials for \n     external use shall be preceded by a written agreement between the University \n     and the author or producer specifying the conditions of use, and including \n     provisions concerning the right of the author or producer to revise the materials \n     periodically, or to withdraw them from use-- subject to existing agreements--in \n     the event revisions are not feasible. \n</font></ol>\n</ol></ol>\n<p>\n</p><ol start=\"5\" type=\"A\">\n<li><font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">Division of Royalties.\n</font><p>\n</p><ol>\n<font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">  <li>General Policy on Royalties. As to University-owned materials, all royalties \n     and income should inure to the University and its schools, colleges, and departments \n     as such materials are prepared in exchange for agreed compensation. As to \n     University-sponsored materials, a sharing of royalties and income is appropriate \n     because of the author's provision of creative efforts on the one hand and \n     the University's provision of salary, facilities, administrative support, \n     and other resources.</li>\n\t</font><p></p>\n<font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">  <li>Royalties on Sales to Outside Users. Where University-owned or University-sponsored \n     materials are to be sold or rented to outside users, the following guidelines \n     pertaining to financial arrangements should be observed (subject to any limitations \n     specified by granting agencies):</li>\n\t</font><p></p>\n<font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">\t</font><ol type=\"a\">\n<li><font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">All incremental expenses related to the distribution of copies will be \n     recovered from each sale or rental. Original costs for production of the materials \n     shall be recovered only if and as agreed to in writing prior to preparation \n     of the materials by the author and the academic departments and/or other University \n     units which incur those costs.</font></li>\n<font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">\t</font><p></p>\n<font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">    <li>In the case of University-owned materials, royalty and other income from \n     sale or use of the materials (after recovery of costs as specified in 1.) \n     shall be divided one-half to the University and one-half to the school/college/department \n     of the author or authors. The University share shall be used to promote research \n     across the whole University and shall normally be administered by the Office \n     of Research. The school/college/department share shall be allocated to the \n     dean of the college or school, and may be used for research, education, and \n     communications. At least 75% of this share should normally go to the author's \n     department for use there according to departmental and college goals. The \n     dean should have discretion in distributing the remaining 25% to promote activities \n     according to the nature and needs of the college or school in question.</li>\n\t</font><p></p>\n<font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">    <li>In the case of University-sponsored materials, royalty and other income \n     from the sale or use of materials (after recovery of costs as specified in \n     a.) shall be divided according to the Administrative Policy Statement 59.4, \n     \"Technology Transfer.\" In any given case covered by this subsection, the author \n     may dedicate all or any portion of his/her allocation to the school/college/department, \n     the Office of Research, or other administrative unit, subject to the provisions \n     of Administrative Policy Statement 59.4).</li>\n\t</font><p></p>\n<font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">    <li>In certain instances it may be advantageous to market University-owned \n     or University-sponsored materials through outside commercial sources or the \n     University Press. Net royalty income from such sources shall be divided as \n     specified in b. and c.</li>\n\t</font><p></p>\n<font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">    <li>Royalty and other income from updating and revision of University-sponsored \n     materials shall be treated as income and royalty from such University-sponsored \n     materials, unless otherwise agreed to in writing by the author/producer and \n     the University before preparation of the original materials. The net income \n     from such upkeep or revision shall be separately computed on an annual basis \n     for the purpose of applying the distributions referenced in paragraph c.</li>\n</font></ol></ol>\n<p>\n</p></li><li><font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">Protection and Liability.\n</font><p>\n</p><ol>\n<font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">  <li>Protection. The Office of Intellectual Property and Technology Transfer \n     shall investigate allegations of unauthorized use or copyright infringement \n     of University-owned and University-sponsored materials and shall recommend \n     appropriate action. If such action is started by the University, all costs \n     of such action shall be borne by the University. All proceeds in excess of \n     such costs shall be shared as provided in Subection F. (subject to sponsoring \n     agency limitations if a grant or contract is involved).</li>\n\t</font><p></p>\n<font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">  <li>Liability. When there are allegations of violation of personal or property \n     rights by the University, or by the author or producer of University-owned \n     or University-sponsored materials copyrighted by the University, the University \n     shall assume responsibility for the defense of any action and the satisfaction \n     of any judgment rendered against the University or the author or producer.</li>\n</font></ol></li></ol>\n\n<p><font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\"><a name=\"anchor3\"></a><b>Section 3. Interpretation and Administration of Policy.</b></font></p>\n<ol type=\"A\">\n\n<li><font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">The President has designated the Vice Provost for Intellectual Property and \n  Technology Transfer as the officer of the University to administer, apply, and \n  interpret the provisions of this policy. The Vice Provost shall have the authority \n  to determine whether the facts of a given case merit special consideration.</font></li>\n<font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">  </font><p></p>\n<li><font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">Committee. The President of the University will appoint an Intellectual Property \nManagement Advisory Committee to review periodically the policy set forth in this \nstatement and recommend such changes to the President as the Committee deems desirable. \nThe Committee will also advise on broader intellectual property issues that arise \nin the promotion and protection of research. The Committee will report to the \nVice Provost for Intellectual Property and Technology Transfer and consist of \nno fewer than five members, a majority of whom shall be chosen from the faculty. \n</font><p></p>\n<font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">  </font></li><li><font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">Distribution of Statement. When this statement becomes effective as University \n     policy, the President's office shall see that all departments and administrative \n     offices of the University are properly informed. Thereafter, the Vice Provost \n     for Intellectual Property and Technology Transfer shall remind deans and department \n     heads periodically of the existence of the policy, inform them about any significant \n     interpretations of the policy, and invite comments or questions regarding \n     it.</font></li>\n<font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">\t</font><p></p>\n<font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">  <li>Duties of Vice Provost for Intellectual Property and Technology Transfer. \n     The Vice Provost for Intellectual Property and Technology Transfer shall manage \n     the Office of Intellectual Property and Technology Transfer, which will represent \n     the University in negotiating agreements with inventors, authors or producers, \n     or licensees pursuant to this policy. She or he may consult also with department \n     heads and the heads of production units involved in a specific technology \n     transfer transaction, and she or he shall sign or recommend all agreements \n     for signing consistent with delegated authority. Where copyright coverage \n     should be obtained on University-sponsored or University-owned materials, \n     the Office of Intellectual Property and Technology Transfer will facilitate \n     the copyright application. The faculty or staff member who is the author of \n     University-owned or University-sponsored materials shall execute a written \n     transfer of copyright to the University when necessary or appropriate.</li>\n\t</font><p></p>\n<font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">  <li>Inquiries on Status of Materials. Any faculty or staff member who has a \n     question as to whether or not particular materials will be considered University-owned \n     or University- sponsored should initiate an inquiry to the Office of Intellectual \n     Property and Technology Transfer as to their status. This inquiry, with all \n     relevant facts, should be forwarded via the author's department head. Thereafter, \n     the Vice Provost for Intellectual Property and Technology Transfer shall advise \n     the author or producer as promptly as possible as to whether or not it appears \n     that the materials should be regarded as University-owned or University-sponsored \n     within the meaning of this policy. The Vice Provost for Intellectual Property \n     and Technology Transfer's decision in such cases will be considered as an \n     advisory opinion subject to final clarification when the work is completed. \n     At that time, the faculty or staff member should either (1) indicate concurrence \n     in the original decision, or (2) request that the question of rights be submitted \n     for decision to the Vice Provost for Intellectual Property and Technology \n     Transfer. In the latter case, the decision of the Vice Provost will be final \n     unless the faculty or staff member requests arbitration of the question.</li>\n\t</font><p></p>\n<font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\">  <li>Arbitration. In the event of any differences between faculty or staff members, \n     on the one hand, and the Vice Provost for Intellectual Property and Technology \n     Transfer, on the other hand, and when the questions cannot be reconciled by \n     direct negotiation, the matter shall be submitted for binding arbitration \n     either to a single arbitrator agreed on by all parties or to a special three-person \n     panel consisting of one person representing the faculty or staff member, one \n     person representing the University, and a third person designated by the first \n     two. Knowledgeable members of the University community will normally be chosen \n     for such panels in order to expedite a decision and minimize cost. In the \n     event costs are incurred, they shall be divided equally between the faculty/staff \n     member and the University. Decisions of the panel will be binding on both \n     parties. The panel shall have full access to any pertinent records over which \n     the faculty/staff member or the University has jurisdiction.</li>\n</font></ol>\n<p><font font=\"\" face=\"Arial, Helvetica, sans-serif\" size=\"2\"><i>BR, March 1969; Executive Order No. 36 of the President, June 1, 1972; revised \n  October 3, 1977; September 26, 1983; September 21, 1992; May 2, 2000, December \n  20, 2000; October 27, 2003.</i></font></p>\n</body></html>"
  },
  {
    "path": "val_graph/CMakeLists.txt",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-23 Bradley M. Bell\n# ----------------------------------------------------------------------------\n# Build the val_graph directory tests\n#\n# BEGIN_SORT_THIS_LINE_PLUS_2\nSET(source_list val_graph.cpp\n    binary_xam.cpp\n    call_xam.cpp\n    cexp_xam.cpp\n    comp_xam.cpp\n    compress_xam.cpp\n    con_xam.cpp\n    csum_xam.cpp\n    cumulative_xam.cpp\n    dead_xam.cpp\n    dis_xam.cpp\n    fold_con_xam.cpp\n    fun2val_xam.cpp\n    pri_xam.cpp\n    renumber_xam.cpp\n    summation_xam.cpp\n    test/ad_double.cpp\n    test/fold.cpp\n    test/fun2val.cpp\n    test/nan.cpp\n    test/opt_call.cpp\n    test/optimize.cpp\n    test/val2fun.cpp\n    test/val_optimize.cpp\n    unary_xam.cpp\n    val2fun_xam.cpp\n    vec_xam.cpp\n)\n# END_SORT_THIS_LINE_MINUS_2\n#\nset_compile_flags( val_graph \"${cppad_debug_which}\" \"${source_list}\" )\n#\nADD_EXECUTABLE(val_graph EXCLUDE_FROM_ALL ${source_list})\n#\n# List of libraries to be linked into the specified target\nTARGET_LINK_LIBRARIES(val_graph\n    ${cppad_lib}\n    ${colpack_libs}\n)\n#\n# check_example_print_for\nadd_check_executable(check val_graph)\n"
  },
  {
    "path": "val_graph/atomic_xam.hpp",
    "content": "# ifndef CPPAD_VAL_GRAPH_ATOMIC_XAM_HPP\n# define CPPAD_VAL_GRAPH_ATOMIC_XAM_HPP\n// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2023-23 Bradley M. Bell\n/*\n{xrst_begin val_atomic_xam.hpp dev}\n\nAn Example Atomic Function\n##########################\n\nFunction\n********\nThis function maps :math:`\\B{R}^4 \\rightarrow \\B{R}^2` by\n\n.. math::\n\n    f_0 (x) & = x_0 + x_1       \\\\\n    f_1 (x) & = x_1 \\cdot x_2\n\nIdentically Zero\n****************\nIf :math:`x_1` or :math:`x_2` is identically zero,\n:math:`f_1 (x)` is identically zero.\nThe routine below keeps the constant zero,\nbut the expression it multiplies may get replaced by nan during optimization.\nNote the for ``double``, identically zero is the same as equals zero.\n\nSource\n******\nThis is an :ref:`atomic_four-name` implementation\nof the function above\n{xrst_literal\n    // BEGIN_VAL_ATOMIC_XAM\n    // END_VAL_ATOMIC_XAM\n}\n{xrst_end val_atomic_xam.hpp}\n*/\n// BEGIN_VAL_ATOMIC_XAM\n# include <cppad/cppad.hpp>\n\nclass val_atomic_xam : public CppAD::atomic_four<double> {\npublic:\n    val_atomic_xam(void) :\n    CppAD::atomic_four<double>(\"val_atomic_xam\")\n    { }\nprivate:\n    // for_type\n    bool for_type(\n        size_t                                    call_id     ,\n        const CppAD::vector<CppAD::ad_type_enum>& type_x      ,\n        CppAD::vector<CppAD::ad_type_enum>&       type_y      ) override\n    {\n        assert( call_id == 0 );       // default value\n        CPPAD_ASSERT_UNKNOWN( type_x.size() == 4 );\n        assert( type_y.size() == 2 );\n        //\n        type_y[0] = std::max(type_x[0], type_x[1]);\n        type_y[1] = std::max(type_x[2], type_x[3]);\n        //\n        return true;\n    }\n    // forward\n    bool forward(\n        size_t                       call_id      ,\n        const CppAD::vector<bool>&   select_y     ,\n        size_t                       order_low    ,\n        size_t                       order_up     ,\n        const CppAD::vector<double>& taylor_x     ,\n        CppAD::vector<double>&       taylor_y     ) override\n    {   //\n        assert( call_id == 0 );       // default value\n        assert( order_low == 0);\n        assert( order_up == 0);\n        assert( taylor_x.size() == 4 );\n        assert( taylor_y.size() == 2 );\n        //\n        // x, y\n        const CppAD::vector<double>& x = taylor_x;\n        CppAD::vector<double>&       y = taylor_y;\n        //\n        y[0] = x[0] + x[1];\n        //\n        // y[1] = x[2] * x[3];\n        if( x[2] == 0.0 )\n            y[1] = 0.0;\n        else if ( x[3] == 0.0 )\n            y[1] = 0.0;\n        else\n            y[1] = x[2] * x[3];\n        //\n        return true;\n    }\n    bool rev_depend(\n        size_t                     call_id      ,\n        const CppAD::vector<bool>& ident_zero_x ,\n        CppAD::vector<bool>&       depend_x     ,\n        const CppAD::vector<bool>& depend_y     ) override\n    {   //\n        assert( call_id == 0 );\n        assert( depend_x.size() == 4 );\n        assert( depend_y.size() == 2 );\n        //\n        depend_x[0] = depend_x[1] = depend_y[0];\n        if( ident_zero_x[2]  )\n        {   // Keep the constant zero (so forward (see above) knows about it).\n            depend_x[2] = true;\n            depend_x[3] = false;\n        }\n        else if( ident_zero_x[3] )\n        {   depend_x[2] = false;\n            // Keep the constant zero (not much overhead in doing so).\n            depend_x[3] = true;\n        }\n        else\n            depend_x[2] = depend_x[3] = depend_y[1];\n        //\n        return true;\n    }\n};\n// END_VAL_ATOMIC_XAM\n# endif\n"
  },
  {
    "path": "val_graph/binary_xam.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2023-23 Bradley M. Bell\n# include <cppad/local/val_graph/tape.hpp>\n/*\n{xrst_begin val_binary_xam.cpp dev}\n\nBinary Value Operator Example\n#############################\n{xrst_literal\n    // BEGIN_C++\n    // END_C++\n}\n\n{xrst_end val_binary_xam.cpp}\n*/\n// BEGIN_C++\nbool binary_xam(void)\n{   bool ok = true;\n    //\n    // tape_t, Vector, addr_t, add_op_enum;\n    using CppAD::local::val_graph::tape_t;\n    using CppAD::local::val_graph::Vector;\n    using CppAD::local::val_graph::addr_t;\n    using CppAD::local::val_graph::op_enum_t;\n    op_enum_t add_op_enum = CppAD::local::val_graph::add_op_enum;\n    //\n    // tape, ok\n    tape_t<double> tape;\n    addr_t n_ind = 2;\n    addr_t index_of_nan = tape.set_ind(n_ind);\n    ok &= index_of_nan == n_ind;\n    //\n    // op_arg\n    Vector<addr_t> op_arg(2);\n    op_arg[0] = 0; // x[0]\n    op_arg[1] = 1; // x[1]\n    //\n    // dep_vec\n    Vector<addr_t> dep_vec(1);\n    //\n    // tape\n    dep_vec[0] = tape.record_op(add_op_enum, op_arg); // x[0] + x[1]\n    //\n    // set_dep\n    tape.set_dep( dep_vec );\n    //\n    // x\n    Vector<double> x(2);\n    x[0] = 5.0;\n    x[1] = 6.0;\n    //\n    // trace\n    bool trace = false;\n    //\n    // val_vec\n    Vector<double> val_vec( tape.n_val() );\n    for(addr_t i = 0; i < n_ind; ++i)\n        val_vec[i] = x[i];\n    tape.eval(trace, val_vec);\n    //\n    // ok\n    ok &= tape.n_op()  == 2;\n    ok &= tape.arg_vec().size() == 3;\n    ok &= tape.con_vec().size() == 1;\n    ok &= tape.n_val()          == n_ind + 2;\n    //\n    // y\n    Vector<double> y(1);\n    y[0] = val_vec[ dep_vec[0] ];\n    //\n    // ok\n    ok &= y[0] == x[0] + x[1];\n    //\n    return ok;\n}\n// END_C++\n"
  },
  {
    "path": "val_graph/call_xam.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2023-23 Bradley M. Bell\n# include <cppad/local/val_graph/tape.hpp>\n# include \"atomic_xam.hpp\"\n/*\n{xrst_begin val_call_xam.cpp dev}\n\nFunction Value Operator Example\n###############################\n\n{xrst_toc_hidden\n    val_graph/atomic_xam.hpp\n}\natomic_xam\n**********\nThis example uses :ref:`val_atomic_xam.hpp-name` .\n\nSource Code\n***********\n{xrst_literal\n    // BEGIN_C++\n    // END_C++\n}\n\n{xrst_end val_call_xam.cpp}\n*/\n// BEGIN_C++\n// call_xam\nbool call_xam(void)\n{   bool ok = true;\n    //\n    // tape_t, Vector, addr_t\n    using CppAD::local::val_graph::tape_t;\n    using CppAD::local::val_graph::Vector;\n    using CppAD::local::val_graph::addr_t;\n    //\n    // atomic_xam\n    val_atomic_xam atomic_xam;\n    //\n    // callarg, op_arg\n    Vector<addr_t> callarg(4), op_arg(2);\n    //\n    // f\n    tape_t<double> tape;\n    addr_t n_ind = 4;\n    addr_t index_of_nan = tape.set_ind(n_ind);\n    ok &= index_of_nan == n_ind;\n    //\n    // n_res, dep_vec\n    addr_t n_res = 2;\n    Vector<addr_t> dep_vec(n_res);\n    //\n    // atomic_index\n    addr_t atomic_index = addr_t( atomic_xam.atomic_index() );\n    //\n    // f_0(x) = x[0] + x[1]\n    // f_1(x) = x[2] * x[3]\n    for(addr_t i = 0; i < 4; ++i)\n        callarg[i] = i;\n    addr_t call_id    = 0;\n    addr_t n_call_res = 2;\n    addr_t res_index = tape.record_call_op(\n        atomic_index, call_id, n_call_res, callarg\n    );\n    //\n    // dep_vec\n    dep_vec[0] = res_index + 0;\n    dep_vec[1] = res_index + 1;\n    //\n    // set_dep\n    tape.set_dep( dep_vec );\n    //\n    // x\n    Vector<double> x(n_ind);\n    for(addr_t i = 0; i < n_ind; ++i)\n        x[i] = 2.0 + double(n_ind - i);\n    //\n    // trace\n    bool trace = false;\n    //\n    // val_vec\n    Vector<double> val_vec( tape.n_val() );\n    for(addr_t i = 0; i < n_ind; ++i)\n        val_vec[i] = x[i];\n    tape.eval(trace, val_vec);\n    //\n    // ok\n    ok &= tape.arg_vec().size() == 1 + 4 + 5;\n    ok &= tape.con_vec().size() == 1;\n    ok &= tape.n_op()  == 2;\n    ok &= tape.n_val()          == n_ind + 1 + 2;\n    //\n    // y\n    Vector<double> y(n_res);\n    dep_vec = tape.dep_vec();\n    for(addr_t i = 0; i < n_res; ++i)\n        y[i] = val_vec[ dep_vec[i] ];\n    //\n    // ok\n    ok &= y[0] == x[0] + x[1];\n    ok &= y[1] == x[2] * x[3];\n    //\n    return ok;\n}\n// END_C++\n"
  },
  {
    "path": "val_graph/cexp_xam.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2023-23 Bradley M. Bell\n# include <cppad/local/val_graph/tape.hpp>\n# include <cppad/local/val_graph/val_type.hpp>\n/*\n{xrst_begin val_cexp_xam.cpp dev}\n\nConditional Expression Value Operator Example\n#############################################\n{xrst_literal\n    // BEGIN_C++\n    // END_C++\n}\n\n{xrst_end val_cexp_xam.cpp}\n*/\n// BEGIN_C++\nbool cexp_xam(void)\n{   bool ok = true;\n    //\n    // tape_t, Vector, addr_t, compare_lt_enum\n    using CppAD::local::val_graph::tape_t;\n    using CppAD::local::val_graph::Vector;\n    using CppAD::local::val_graph::addr_t;\n    using CppAD::local::val_graph::compare_enum_t;\n    compare_enum_t compare_lt_enum = CppAD::local::val_graph::compare_lt_enum;\n    //\n    // tape, ok\n    tape_t<double> tape;\n    addr_t n_ind = 4;\n    addr_t index_of_nan = tape.set_ind(n_ind);\n    ok &= index_of_nan == n_ind;\n    //\n    // dep_vec, tape\n    Vector<addr_t> dep_vec(1);\n    addr_t left     = 3; // x[3]\n    addr_t right    = 2; // x[2]\n    addr_t if_true  = 1; // x[1]\n    addr_t if_false = 0; // x[0]\n    dep_vec[0] = tape.record_cexp_op(\n        compare_lt_enum, left, right, if_true, if_false\n    );\n    //\n    // set_dep\n    tape.set_dep( dep_vec );\n    //\n    // x\n    Vector<double> x(n_ind);\n    for(addr_t i = 0; i < n_ind; ++i)\n        x[0] = double(i + 1);\n    //\n    // trace\n    bool trace = false;\n    //\n    // val_vec\n    Vector<double> val_vec( tape.n_val() );\n    for(addr_t i = 0; i < n_ind; ++i)\n        val_vec[i] = x[i];\n    tape.eval(trace, val_vec);\n    //\n    // ok\n    ok &= tape.n_op()           == 2;\n    ok &= tape.con_vec().size() == 1;\n    ok &= tape.arg_vec().size() == 1 + 5;\n    ok &= tape.n_val()          == n_ind + 2;\n    //\n    // y\n    Vector<double> y(1);\n    y[0] = val_vec[ dep_vec[0] ];\n    //\n    // ok\n    if( x[left] < x[right] )\n        ok &= y[0] == x[if_true];\n    else\n        ok &= y[0] == x[if_false];\n    //\n    return ok;\n}\n// END_C++\n"
  },
  {
    "path": "val_graph/comp_xam.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2023-23 Bradley M. Bell\n# include <cppad/local/val_graph/tape.hpp>\n# include <cppad/local/val_graph/val_type.hpp>\n/*\n{xrst_begin val_comp_xam.cpp dev}\n\nBinary Value Operator Example\n#############################\n{xrst_literal\n    // BEGIN_C++\n    // END_C++\n}\n\n{xrst_end val_comp_xam.cpp}\n*/\n// BEGIN_C++\nbool comp_xam(void)\n{   bool ok = true;\n    //\n    // tape_t, Vector, addr_t, add_op_enum, compare_lt_enum;\n    using CppAD::local::val_graph::tape_t;\n    using CppAD::local::val_graph::Vector;\n    using CppAD::local::val_graph::addr_t;\n    using CppAD::local::val_graph::op_enum_t;\n    using CppAD::local::val_graph::compare_enum_t;\n    op_enum_t add_op_enum = CppAD::local::val_graph::add_op_enum;\n    compare_enum_t compare_lt_enum = CppAD::local::val_graph::compare_lt_enum;\n    //\n    // tape, ok\n    tape_t<double> tape;\n    addr_t n_ind = 2;\n    addr_t index_of_nan = tape.set_ind(n_ind);\n    ok &= index_of_nan == n_ind;\n    //\n    // dep_vec\n    Vector<addr_t> dep_vec(1);\n    //\n    // op_arg\n    Vector<addr_t> op_arg(2);\n    op_arg[0] = 0; // x[0]\n    op_arg[1] = 1; // x[1]\n    //\n    // tape\n    // put two identical compare operators in the tape\n    addr_t left_index  = 0; // x[0]\n    addr_t right_index = 1; // x[1]\n    for(size_t i = 0; i < 2; ++i)\n    {   addr_t res_index = tape.record_comp_op(\n            compare_lt_enum, left_index, right_index // x[0] < x[1]\n        );\n        ok &= res_index == 0; // no result for this operator\n    }\n    //\n    // tape, dep_vec\n    tape.record_op(add_op_enum, op_arg);              // not used\n    dep_vec[0] = tape.record_op(add_op_enum, op_arg); // x[0] + x[1]\n    //\n    // set_dep\n    tape.set_dep( dep_vec );\n    //\n    // trace\n    bool trace = false;\n    //\n    // x\n    Vector<double> x(2);\n    x[0] = 5.0;\n    x[1] = 6.0;\n    //\n    // val_vec, compare_false\n    Vector<double> val_vec( tape.n_val() );\n    for(addr_t i = 0; i < n_ind; ++i)\n        val_vec[i] = x[i];\n    size_t compare_false = 0;\n    tape.eval(trace, val_vec, compare_false);\n    ok &= compare_false == 0;  // x[0] < x[1] is true\n    //\n    // x\n    x[0] = 6.0;\n    x[1] = 5.0;\n    //\n    // val_vec, compare_false\n    for(addr_t i = 0; i < n_ind; ++i)\n        val_vec[i] = x[i];\n    compare_false = 0;\n    tape.eval(trace, val_vec, compare_false);\n    ok &= compare_false == 2;        // there are two x[0] < x[1] comparisons\n    ok &= tape.n_op() == 5; // 1 con_op, 2 comp_op, 2 add_op\n    //\n    // tape\n    tape.set_option(\"keep_compare\", \"true\");\n    tape.renumber();\n    tape.dead_code();\n    ok &= tape.n_op() == 3; // 1 con_op, 1 comp_op, 1 add_op\n    //\n    // ok, val_vec\n    compare_false = 0;\n    val_vec.resize( tape.n_val() );\n    tape.eval(trace, val_vec, compare_false);\n    ok &= compare_false == 1;  // only one x[0] < x[1] left\n    //\n    // tape\n    tape.set_option(\"keep_compare\", \"false\");\n    tape.dead_code();\n    ok &= tape.n_op() == 2; // 1 con_op, 0 comp_op, 1 add_op\n    //\n    // ok, val_vec\n    val_vec.resize( tape.n_val() );\n    compare_false = 0;\n    tape.eval(trace, val_vec, compare_false);\n    ok &= compare_false == 0;  // none of the x[0] < x[1] left\n    //\n    // ok\n    Vector<double> y(1);\n    dep_vec = tape.dep_vec();\n    y[0] = val_vec[ dep_vec[0] ];\n    ok &= y[0] == x[0] + x[1];\n    //\n    return ok;\n}\n// END_C++\n"
  },
  {
    "path": "val_graph/compress_xam.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2023-23 Bradley M. Bell\n# include <cppad/local/val_graph/tape.hpp>\n/*\n{xrst_begin val_compress_xam.cpp dev}\n\nCompress Tape Example\n#####################\n{xrst_literal\n    // BEGIN_C++\n    // END_C++\n}\n\n{xrst_end val_compress_xam.cpp}\n*/\n// BEGIN_C++\nbool compress_xam(void)\n{   bool ok = true;\n    //\n    // tape_t, Vector, addr_t, add_op_enum, sub_op_enum;\n    using CppAD::local::val_graph::tape_t;\n    using CppAD::local::val_graph::Vector;\n    using CppAD::local::val_graph::addr_t;\n    using CppAD::local::val_graph::op_enum_t;\n    op_enum_t add_op_enum = CppAD::local::val_graph::add_op_enum;\n    op_enum_t sub_op_enum = CppAD::local::val_graph::sub_op_enum;\n    //\n    // tape\n    tape_t<double> tape;\n    addr_t n_ind = 2;\n    addr_t index_of_nan = tape.set_ind(n_ind);\n    ok &= index_of_nan == n_ind;\n    //\n    // op_arg\n    Vector<addr_t> op_arg(2);\n    op_arg[0] = 0; // x[0]\n    op_arg[1] = 1; // x[1]\n    //\n    // operator that is not used\n    tape.record_op(sub_op_enum, op_arg); // x[0] - x[1]\n    //\n    // operator that is computer twich\n    addr_t add_zero_one_1 = tape.record_op(add_op_enum, op_arg); // x[0] + x[1]\n    addr_t add_zero_one_2 = tape.record_op(add_op_enum, op_arg); // x[0] + x[1]\n    //\n    // dep_vec\n    // y[0] = x[0] + x[1] + x[0] + x[1]\n    Vector<addr_t> dep_vec(1);\n    op_arg[0]       = add_zero_one_1;\n    op_arg[1]       = add_zero_one_2;\n    dep_vec[0]      = tape.record_op(add_op_enum, op_arg);\n    //\n    // set_dep\n    tape.set_dep( dep_vec );\n    //\n    // x\n    Vector<double> x(2);\n    x[0] = 5.0;\n    x[1] = 6.0;\n    //\n    // trace\n    bool trace = false;\n    //\n    // val_vec\n    Vector<double> val_vec;\n    //\n    // val_vec, ok\n    // before optimizing\n    val_vec.resize( tape.n_val() );\n    for(addr_t i = 0; i < n_ind; ++i)\n        val_vec[i] = x[i];\n    tape.eval(trace, val_vec);\n    ok &= tape.n_op() == 1 + 4;\n    ok &= tape.arg_vec().size() == 1 + 4 * 2;\n    ok &= tape.con_vec().size() == 1;\n    //\n    // compress, val_vec\n    tape.compress();\n    val_vec.resize( tape.n_val() );\n    tape.eval(trace, val_vec);\n    //\n    // ok\n    ok &= tape.n_op() == 1 + 2;\n    ok &= tape.arg_vec().size() == 1 + 2 * 2;\n    ok &= tape.con_vec().size() == 1;\n    //\n    // dep_vec\n    dep_vec = tape.dep_vec();\n    //\n    // y\n    Vector<double> y(1);\n    y[0] = val_vec[ dep_vec[0] ];\n    //\n    // ok\n    ok &= y[0] == x[0] + x[1] + x[0] + x[1];\n    //\n    return ok;\n}\n// END_C++\n"
  },
  {
    "path": "val_graph/con_xam.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2023-23 Bradley M. Bell\n# include <cppad/local/val_graph/tape.hpp>\n/*\n{xrst_begin val_con_xam.cpp dev}\n\nConstant Operator Example\n#########################\n{xrst_literal\n    // BEGIN_C++\n    // END_C++\n}\n\n{xrst_end val_con_xam.cpp}\n*/\n// BEGIN_C++\nbool con_xam(void)\n{   bool ok = true;\n    //\n    // tape_t, Vector, addr_t, con_op_enum, add_op_enum;\n    using CppAD::local::val_graph::tape_t;\n    using CppAD::local::val_graph::Vector;\n    using CppAD::local::val_graph::addr_t;\n    using CppAD::local::val_graph::op_enum_t;\n    op_enum_t add_op_enum = CppAD::local::val_graph::add_op_enum;\n    //\n    // tape\n    tape_t<double> tape;\n    addr_t n_ind = 1;\n    addr_t index_of_nan = tape.set_ind(n_ind);\n    ok &= index_of_nan == n_ind;\n    //\n    // op_arg\n    Vector<addr_t> op_arg(2);\n    //\n    // dep_vec\n    Vector<addr_t> dep_vec(1);\n    //\n    // tape\n    addr_t five = tape.record_con_op(5.0); // 5.0\n    op_arg[0] = 0; // x[0]\n    op_arg[1] = five;\n    dep_vec[0] = tape.record_op(add_op_enum, op_arg); // x[0] + 5.0\n    //\n    // set_dep\n    tape.set_dep( dep_vec );\n    //\n    // x\n    Vector<double> x(1);\n    x[0] = 6.0;\n    //\n    // trace\n    bool trace = false;\n    //\n    // val_vec\n    Vector<double> val_vec( tape.n_val() );\n    for(addr_t i = 0; i < n_ind; ++i)\n        val_vec[i] = x[i];\n    tape.eval(trace, val_vec);\n    //\n    // ok\n    ok &= tape.n_op()  == 3;\n    ok &= tape.arg_vec().size() == 4;\n    ok &= tape.con_vec().size() == 2;\n    ok &= tape.n_val()          == n_ind + 3;\n    //\n    // y\n    Vector<double> y(1);\n    y[0] = val_vec[ dep_vec[0] ];\n    //\n    // ok\n    ok &= y[0] == x[0] + 5.0;\n    //\n    return ok;\n}\n// END_C++\n"
  },
  {
    "path": "val_graph/csum_xam.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2023-23 Bradley M. Bell\n# include <cppad/local/val_graph/tape.hpp>\n/*\n{xrst_begin val_csum_xam.cpp dev}\n\nCumulative Summation Value Operator Example\n###########################################\n{xrst_literal\n    // BEGIN_C++\n    // END_C++\n}\n\n{xrst_end val_csum_xam.cpp}\n*/\n// BEGIN_C++\nbool csum_xam(void)\n{   bool ok = true;\n    //\n    // tape_t, Vector, addr_t, csum_op_enum;\n    using CppAD::local::val_graph::tape_t;\n    using CppAD::local::val_graph::Vector;\n    using CppAD::local::val_graph::addr_t;\n    //\n    // tape, ok\n    tape_t<double> tape;\n    addr_t n_ind = 2;\n    addr_t index_of_nan = tape.set_ind(n_ind);\n    ok &= index_of_nan == n_ind;\n    //\n    // p0, p1\n    addr_t p0 = tape.record_con_op(5.0);\n    addr_t p1 = tape.record_con_op(6.0);\n    //\n    // add\n    Vector<addr_t> add(2), sub(2);\n    add[0] = 0;   // x[0]\n    add[1] = 1;   // x[1]\n    sub[0] = p0;  // 5.0\n    sub[1] = p1;  // 6.0\n    //\n    // dep_vec, tape\n    Vector<addr_t> dep_vec(1);\n    dep_vec[0] = tape.record_csum_op(add, sub); // x[0] + x[1] - 5.0 - 6.0\n    //\n    // set_dep\n    tape.set_dep( dep_vec );\n    //\n    // x\n    Vector<double> x(2);\n    x[0] = 3.0;\n    x[1] = 4.0;\n    //\n    // trace\n    bool trace = false;\n    //\n    // val_vec\n    Vector<double> val_vec( tape.n_val() );\n    for(addr_t i = 0; i < n_ind; ++i)\n        val_vec[i] = x[i];\n    tape.eval(trace, val_vec);\n    //\n    // ok\n    ok &= tape.n_op()  == 4;\n    ok &= tape.con_vec().size() == 3;\n    ok &= tape.arg_vec().size() == 3 + 7;\n    ok &= tape.n_val()          == n_ind + 4;\n    //\n    // y\n    Vector<double> y(1);\n    y[0] = val_vec[ dep_vec[0] ];\n    //\n    // ok\n    ok &= y[0] == x[0] + x[1] - 11.0;\n    //\n    return ok;\n}\n// END_C++\n"
  },
  {
    "path": "val_graph/cumulative_xam.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2023-23 Bradley M. Bell\n# include <cppad/local/val_graph/tape.hpp>\n/*\n{xrst_begin val_cumulative_xam dev}\n\nExample Converting Add, Subtract and Negative to a Cumulative Summation\n#######################################################################\n{xrst_literal\n    // BEGIN_C++\n    // END_C++\n}\n\n{xrst_end val_cumulative_xam}\n*/\n// BEGIN_C++\nbool cumulative_xam(void)\n{   bool ok = true;\n    //\n    // tape_t, Vector, addr_t, add_op_enum, sub_op_enum, neg_op_enum\n    using CppAD::local::val_graph::tape_t;\n    using CppAD::local::val_graph::Vector;\n    using CppAD::local::val_graph::addr_t;\n    using CppAD::local::val_graph::op_enum_t;\n    op_enum_t con_op_enum  = CppAD::local::val_graph::con_op_enum;\n    op_enum_t add_op_enum  = CppAD::local::val_graph::add_op_enum;\n    op_enum_t sub_op_enum  = CppAD::local::val_graph::sub_op_enum;\n    op_enum_t neg_op_enum  = CppAD::local::val_graph::neg_op_enum;\n    op_enum_t csum_op_enum = CppAD::local::val_graph::csum_op_enum;\n    //\n    // tape, ok\n    tape_t<double> tape;\n    addr_t n_ind = 5;\n    addr_t index_of_nan = tape.set_ind(n_ind);\n    ok &= index_of_nan == n_ind;\n    Vector<addr_t> op_arg(2);\n    //\n    // op_arg, add = x[0] + x[1]\n    op_arg[0] = 0;   // x[0]\n    op_arg[1] = 1;   // x[1]\n    addr_t add = tape.record_op(add_op_enum, op_arg);\n    //\n    // op_arg, sub = x[2] - x[3]\n    op_arg[0] = 2;   // x[2]\n    op_arg[1] = 3;   // x[3]\n    addr_t sub = tape.record_op(sub_op_enum, op_arg);\n    //\n    // op_arg, neg = - x[4]\n    op_arg.resize(1);\n    op_arg[0] = 4;\n    addr_t neg = tape.record_op(neg_op_enum, op_arg);\n    //\n    // dep_vec, tape\n    Vector<addr_t> dep_vec(3);\n    dep_vec[0] = add; // x[0] + x[1]\n    dep_vec[1] = sub; // x[2] - x[3]\n    dep_vec[2] = neg; // - x[4]\n    //\n    // set_dep\n    tape.set_dep( dep_vec );\n    //\n    // x\n    Vector<double> x(n_ind);\n    for(addr_t i = 0; i < n_ind; ++i)\n        x[i] = double(2 + i);\n    //\n    // trace\n    bool trace = false;\n    //\n    // val_vec\n    Vector<double> val_vec( tape.n_val() );\n    for(addr_t i = 0; i < n_ind; ++i)\n        val_vec[i] = x[i];\n    tape.eval(trace, val_vec);\n    //\n    // ok\n    addr_t i_op = 0;\n    ok &= tape.base_op_ptr(i_op++)->op_enum() == con_op_enum;\n    ok &= tape.base_op_ptr(i_op++)->op_enum() == add_op_enum;\n    ok &= tape.base_op_ptr(i_op++)->op_enum() == sub_op_enum;\n    ok &= tape.base_op_ptr(i_op++)->op_enum() == neg_op_enum;\n    //\n    // ok\n    ok &= tape.n_op()  == 4;\n    ok &= tape.con_vec().size() == 1;\n    ok &= tape.arg_vec().size() == 6;\n    ok &= tape.n_val()          == n_ind + 4;\n    //\n    // y\n    Vector<double> y(3);\n    dep_vec = tape.dep_vec();\n    y[0]    = val_vec[ dep_vec[0] ];\n    y[1]    = val_vec[ dep_vec[1] ];\n    y[2]    = val_vec[ dep_vec[2] ];\n    //\n    // ok\n    ok &= y[0] == x[0] + x[1];\n    ok &= y[1] == x[2] - x[3];\n    ok &= y[2] == - x[4];\n    //\n    // tape\n    tape.set_op2arg_index();\n    for(addr_t op_index = 1; op_index < 4; ++op_index)\n        tape.op2csum(op_index);\n    //\n    // val_vec\n    for(addr_t i = 0; i < n_ind; ++i)\n        val_vec[i] = x[i];\n    tape.eval(trace, val_vec);\n    //\n    // ok\n    i_op = 0;\n    ok &= tape.base_op_ptr(i_op++)->op_enum() == con_op_enum;\n    ok &= tape.base_op_ptr(i_op++)->op_enum() == csum_op_enum;\n    ok &= tape.base_op_ptr(i_op++)->op_enum() == csum_op_enum;\n    ok &= tape.base_op_ptr(i_op++)->op_enum() == csum_op_enum;\n    //\n    // ok\n    ok &= tape.n_op()  == 4;\n    ok &= tape.con_vec().size() == 1;\n    ok &= tape.arg_vec().size() == 6 + 3 * 5 - 1;\n    ok &= tape.n_val()          == n_ind + 4;\n    //\n    // y\n    dep_vec = tape.dep_vec();\n    y[0]    = val_vec[ dep_vec[0] ];\n    y[1]    = val_vec[ dep_vec[1] ];\n    y[2]    = val_vec[ dep_vec[2] ];\n    //\n    // ok\n    ok &= y[0] == x[0] + x[1];\n    ok &= y[1] == x[2] - x[3];\n    ok &= y[2] == - x[4];\n    //\n    return ok;\n}\n// END_C++\n"
  },
  {
    "path": "val_graph/dead_xam.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2023-23 Bradley M. Bell\n# include <cppad/local/val_graph/tape.hpp>\n/*\n{xrst_begin val_dead_xam.cpp dev}\n\nDead Code Elimination Example\n#############################\n{xrst_literal\n    // BEGIN_C++\n    // END_C++\n}\n\n{xrst_end val_dead_xam.cpp}\n*/\n// BEGIN_C++\nbool dead_xam(void)\n{   bool ok = true;\n    //\n    // tape_t, Vector, addr_t, add_op_enum, sub_op_enum;\n    using CppAD::local::val_graph::tape_t;\n    using CppAD::local::val_graph::Vector;\n    using CppAD::local::val_graph::addr_t;\n    using CppAD::local::val_graph::op_enum_t;\n    op_enum_t add_op_enum = CppAD::local::val_graph::add_op_enum;\n    op_enum_t sub_op_enum = CppAD::local::val_graph::sub_op_enum;\n    //\n    // tape\n    tape_t<double> tape;\n    addr_t n_ind = 2;\n    addr_t index_of_nan = tape.set_ind(n_ind);\n    ok &= index_of_nan == n_ind;\n    //\n    // op_arg\n    Vector<addr_t> op_arg(2);\n    op_arg[0] = 0; // x[0]\n    op_arg[1] = 1; // x[1]\n    //\n    // dep_vec\n    Vector<addr_t> dep_vec(2);\n    //\n    // operators that are not used\n    tape.record_op(add_op_enum, op_arg); // x[0] + x[1]\n    tape.record_con_op(5.0);             // 5.0\n    //\n    // operators that are used\n    dep_vec[0]      = tape.record_op(add_op_enum, op_arg); // x[0] + x[1]\n    op_arg[0]       = dep_vec[0];                          // x[0] + x[1]\n    op_arg[1]       = tape.record_con_op(4.0);             // 4.0\n    dep_vec[1]      = tape.record_op(sub_op_enum, op_arg); // x[0] + x[1] - 4.0\n    //\n    // set_dep\n    tape.set_dep( dep_vec );\n    //\n    // x\n    Vector<double> x(2);\n    x[0] = 5.0;\n    x[1] = 6.0;\n    //\n    // trace\n    bool trace = false;\n    //\n    // val_vec\n    Vector<double> val_vec;\n    //\n    // val_vec, ok\n    // before optimizing\n    val_vec.resize( tape.n_val() );\n    for(addr_t i = 0; i < n_ind; ++i)\n        val_vec[i] = x[i];\n    tape.eval(trace, val_vec);\n    ok &= tape.n_op() == 6;\n    ok &= tape.arg_vec().size() == 9;\n    ok &= tape.con_vec().size() == 3;\n    //\n    // dead_code, val_vec\n    tape.dead_code();\n    val_vec.resize( tape.n_val() );\n    tape.eval(trace, val_vec);\n    //\n    // ok\n    ok &= tape.n_op() == 4;\n    ok &= tape.arg_vec().size() == 6;\n    ok &= tape.con_vec().size() == 2;\n    //\n    // dep_vec\n    dep_vec = tape.dep_vec();\n    //\n    // y\n    Vector<double> y(2);\n    for(size_t i = 0; i < 2; ++i)\n        y[i] = val_vec[ dep_vec[i] ];\n    //\n    // ok\n    ok &= y[0] == x[0] + x[1];\n    ok &= y[1] == x[0] + x[1] - 4.0;\n    //\n    return ok;\n}\n// END_C++\n"
  },
  {
    "path": "val_graph/dis_xam.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2023-23 Bradley M. Bell\n# include <cppad/local/val_graph/tape.hpp>\n# include <cppad/cppad.hpp>\n/*\n{xrst_begin val_dis_xam.cpp dev}\n\nUnary Value Operator Example\n############################\n{xrst_literal\n    // BEGIN_C++\n    // END_C++\n}\n\n{xrst_end val_dis_xam.cpp}\n*/\n// BEGIN_C++\nnamespace {\n    double floor(const double& arg)\n    {   return std::floor(arg); }\n    //\n    CPPAD_DISCRETE_FUNCTION(double, floor);\n}\nbool dis_xam(void)\n{   bool ok = true;\n    //\n    // tape_t, Vector, addr_t\n    using CppAD::local::val_graph::tape_t;\n    using CppAD::local::val_graph::Vector;\n    using CppAD::local::val_graph::addr_t;\n    //\n    //\n    // tape, ok\n    tape_t<double> tape;\n    addr_t n_ind = 1;\n    addr_t index_of_nan = tape.set_ind(n_ind);\n    ok &= index_of_nan == n_ind;\n    //\n    // dep_vec\n    Vector<addr_t> dep_vec(1);\n    //\n    // tape, dep_vec\n    addr_t discrete_index = addr_t( CppAD::discrete<double>::index(\"floor\") );\n    addr_t val_index      = 0; // x[0];\n    dep_vec[0] = tape.record_dis_op(discrete_index, val_index); // floor( x[0] )\n    //\n    // tape\n    tape.set_dep( dep_vec );\n    //\n    // x\n    Vector<double> x(1);\n    x[0] = 6.5;\n    //\n    // trace\n    bool trace = false;\n    //\n    // val_vec\n    Vector<double> val_vec( tape.n_val() );\n    val_vec[0] = x[0];\n    tape.eval(trace, val_vec);\n    //\n    // ok\n    ok &= tape.n_op()  == 2;\n    ok &= tape.arg_vec().size() == 3;\n    ok &= tape.con_vec().size() == 1;\n    ok &= tape.n_val()          == n_ind + 2;\n    //\n    // y\n    Vector<double> y(1);\n    //\n    // ok\n    y[0] = val_vec[ dep_vec[0] ];\n    ok &= y[0] == std::floor( x[0] );\n    //\n    return ok;\n}\n// END_C++\n"
  },
  {
    "path": "val_graph/fold_con_xam.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2023-23 Bradley M. Bell\n# include <cppad/local/val_graph/tape.hpp>\n/*\n{xrst_begin val_fold_con_xam.cpp dev}\n\nValue Tape Re-Numbering Example\n###############################\n{xrst_literal\n    // BEGIN_C++\n    // END_C++\n}\n\n{xrst_end val_fold_con_xam.cpp}\n*/\n// BEGIN_C++\nbool fold_con_xam(void)\n{   bool ok = true;\n    //\n    // tape_t, Vector, addr_t, add_op_enum;\n    using CppAD::local::val_graph::tape_t;\n    using CppAD::local::val_graph::Vector;\n    using CppAD::local::val_graph::addr_t;\n    using CppAD::local::val_graph::op_enum_t;\n    op_enum_t add_op_enum = CppAD::local::val_graph::add_op_enum;\n    //\n    // tape\n    tape_t<double> tape;\n    addr_t n_ind = 1;\n    addr_t index_of_nan = tape.set_ind(n_ind);\n    ok &= index_of_nan == n_ind;\n    //\n    // c_0, c_1\n    Vector<double> c(2);\n    c[0] = 1.0;\n    c[1] = 2.0;\n    addr_t c_0 = tape.record_con_op( c[0] );\n    addr_t c_1 = tape.record_con_op( c[1] );\n    //\n    // tape, c_2\n    Vector<addr_t> op_arg(2);\n    op_arg[0]  = c_0;\n    op_arg[1]  = c_1;\n    addr_t c_2 = tape.record_op(add_op_enum, op_arg); // c[2] = c[0] + c[1]\n    //\n    // dep_vec\n    Vector<addr_t> dep_vec(1);\n    //\n    // tape\n    op_arg[0]  = 0;\n    op_arg[1]  = c_2;\n    dep_vec[0] = tape.record_op(add_op_enum, op_arg); // y[0] = x[0] + c[2]\n    //\n    // set_dep\n    tape.set_dep( dep_vec );\n    //\n    // trace\n    bool trace = false;\n    //\n    // x\n    Vector<double> x(1);\n    x[0] = 5.0;\n    //\n    // val_vec\n    Vector<double> val_vec( tape.n_val() );\n    for(addr_t i = 0; i < n_ind; ++i)\n        val_vec[i] = x[i];\n    tape.eval(trace, val_vec);\n    //\n    // y, ok\n    Vector<double> y(1);\n    dep_vec = tape.dep_vec();\n    y[0]    = val_vec[ dep_vec[0] ];\n    ok     &= y[0] == x[0] + c[0] + c[1];\n    ok     &= tape.con_vec().size() == 3;\n    ok     &= tape.n_op() == 5;\n    //\n    // fold_con\n    tape.fold_con();\n    ok     &= tape.con_vec().size() == 4;\n    //\n    // val_vec\n    val_vec.resize( tape.n_val() );\n    tape.eval(trace, val_vec);\n    //\n    // dead_code\n    tape.dead_code();\n    ok     &= tape.con_vec().size() == 2;\n    //\n    // val_vec\n    val_vec.resize( tape.n_val() );\n    for(addr_t i = 0; i < n_ind; ++i)\n        val_vec[i] = x[i];\n    tape.eval(trace, val_vec);\n    //\n    // y, ok\n    dep_vec = tape.dep_vec();\n    y[0]    = val_vec[ dep_vec[0] ];\n    ok     &= y[0] == x[0] + c[0] + c[1];\n    //\n    return ok;\n}\n// END_C++\n"
  },
  {
    "path": "val_graph/fun2val_xam.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2023-23 Bradley M. Bell\n# include <cppad/cppad.hpp>\n# include <cppad/local/val_graph/tape.hpp>\n# include <cppad/local/val_graph/fun2val.hpp>\n/*\n{xrst_begin val_fun2val_xam.cpp dev}\n\nExample Vale Graph From ADFun\n#############################\n{xrst_literal\n    // BEGIN_C++\n    // END_C++\n}\n\n{xrst_end val_fun2val_xam.cpp}\n*/\n// BEGIN_C++\nbool fun2val_xam(void)\n{   bool ok = true;\n    //\n    // AD, addr_t\n    using CppAD::AD;\n    using CppAD::addr_t;\n    //\n    // tape_t, Vector\n    using CppAD::local::val_graph::tape_t;\n    using CppAD::local::val_graph::Vector;\n    //\n    // ax, ay, f\n    Vector< AD<double> > ap(1), ax(2), ay(2);\n    ap[0] = 1.0;\n    ax[0] = 2.0;\n    ax[1] = 3.0;\n    CppAD::Independent(ax, ap);\n    ay[0] = ax[0] + 7.0;\n    ay[1] = ax[1] - ap[0];\n    CppAD::ADFun<double> f(ax, ay);\n    //\n    // tape\n    tape_t<double> tape;\n    f.fun2val(tape);\n    //\n    // dep_vec\n    Vector<addr_t> dep_vec = tape.dep_vec();\n    //\n    // x\n    Vector<double> p(1), x(2);\n    p[0] = 4.0;\n    x[0] = 5.0;\n    x[1] = 6.0;\n    //\n    // trace\n    bool trace = false;\n    //\n    // val_vec\n    Vector<double> val_vec( tape.n_val() );\n    val_vec[0] = p[0];\n    val_vec[1] = x[0];\n    val_vec[2] = x[1];\n    tape.eval(trace, val_vec);\n    //\n    // y\n    Vector<double> y(2);\n    y[0] = val_vec[ dep_vec[0] ];\n    y[1] = val_vec[ dep_vec[1] ];\n    //\n    // ok\n    ok &= y[0] == x[0] + 7.0;\n    ok &= y[1] == x[1] - p[0];\n    //\n    return ok;\n}\n// END_C++\n"
  },
  {
    "path": "val_graph/pri_xam.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2023-23 Bradley M. Bell\n# include <cppad/local/val_graph/tape.hpp>\n# include <cppad/local/val_graph/val_type.hpp>\n/*\n{xrst_begin val_pri_xam.cpp dev}\n\nPrint Operator Example\n######################\n{xrst_literal\n    // BEGIN_C++\n    // END_C++\n}\n\n{xrst_end val_pri_xam.cpp}\n*/\n// BEGIN_C++\nbool pri_xam(void)\n{   bool ok = true;\n    //\n    // tape_t, Vector, addr_t, add_op_enum, compare_lt_enum;\n    using CppAD::local::val_graph::tape_t;\n    using CppAD::local::val_graph::Vector;\n    using CppAD::local::val_graph::addr_t;\n    using CppAD::local::val_graph::op_enum_t;\n    op_enum_t sub_op_enum = CppAD::local::val_graph::sub_op_enum;\n    //\n    // tape, ok\n    tape_t<double> tape;\n    addr_t n_ind = 2;\n    addr_t index_of_nan = tape.set_ind(n_ind);\n    ok &= index_of_nan == n_ind;\n    //\n    // op_arg\n    Vector<addr_t> op_arg(2);\n    op_arg[0] = 0; // x[0]\n    op_arg[1] = 1; // x[1]\n    //\n    // tape, dep_vec\n    Vector<addr_t> dep_vec(1);\n    dep_vec[0] = tape.record_op(sub_op_enum, op_arg); // x[0] - x[1]\n    //\n    // tape\n    std::string before       = \"0 >= x[0] - x[1] = \";\n    std::string after        = \"\\n\";\n    addr_t      flag_index   = dep_vec[0];\n    addr_t      value_index  = dep_vec[0];\n    tape.record_pri_op(before, after, flag_index, value_index);\n    tape.record_pri_op(before, after, flag_index, value_index);\n    //\n    // set_dep\n    tape.set_dep( dep_vec );\n    //\n    // trace\n    bool trace = false;\n    //\n    // x\n    Vector<double> x(2);\n    x[0] = 6.0;\n    x[1] = 5.0;\n    //\n    // val_vec, compare_false\n    Vector<double> val_vec( tape.n_val() );\n    for(addr_t i = 0; i < n_ind; ++i)\n        val_vec[i] = x[i];\n    tape.eval(trace, val_vec);\n    //\n    // ok\n    ok &= tape.n_val()          == 4;\n    ok &= tape.n_op()           == 4;\n    ok &= tape.str_vec().size() == 3;\n    ok &= tape.str_vec()[0]     == \"\";\n    //\n    // tape\n    tape.set_option(\"keep_print\", \"true\");\n    tape.renumber();\n    tape.dead_code();\n    //\n    // val_vec, compare_false\n    val_vec.resize( tape.n_val() );\n    tape.eval(trace, val_vec);\n    //\n    // ok\n    ok &= tape.n_val()          == 4;\n    ok &= tape.n_op()           == 3;\n    ok &= tape.str_vec().size() == 3;\n    ok &= tape.str_vec()[0]     == \"\";\n    //\n    // ok\n    Vector<double> y(1);\n    dep_vec = tape.dep_vec();\n    y[0] = val_vec[ dep_vec[0] ];\n    ok &= y[0] == x[0] - x[1];\n    //\n    return ok;\n}\n// END_C++\n"
  },
  {
    "path": "val_graph/renumber_xam.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2023-23 Bradley M. Bell\n# include <cppad/local/val_graph/tape.hpp>\n/*\n{xrst_begin val_renumber_xam.cpp dev}\n\nValue Tape Re-Numbering Example\n###############################\n{xrst_literal\n    // BEGIN_C++\n    // END_C++\n}\n\n{xrst_end val_renumber_xam.cpp}\n*/\n// BEGIN_C++\nbool renumber_xam(void)\n{   bool ok = true;\n    //\n    // tape_t, Vector, addr_t, add_op_enum;\n    using CppAD::local::val_graph::tape_t;\n    using CppAD::local::val_graph::Vector;\n    using CppAD::local::val_graph::addr_t;\n    using CppAD::local::val_graph::op_enum_t;\n    op_enum_t add_op_enum = CppAD::local::val_graph::add_op_enum;\n    //\n    // tape\n    tape_t<double> tape;\n    addr_t n_ind = 2;\n    addr_t index_of_nan = tape.set_ind(n_ind);\n    ok &= index_of_nan == n_ind;\n    //\n    // op_arg\n    Vector<addr_t> op_arg(2);\n    op_arg[0] = 0; // x[0]\n    op_arg[1] = 1; // x[1]\n    //\n    // dep_vec\n    Vector<addr_t> dep_vec(1);\n    //\n    // tape\n    tape.record_op(add_op_enum, op_arg);              // x[0] + x[1]\n    dep_vec[0] = tape.record_op(add_op_enum, op_arg); // x[0] + x[1]\n    //\n    // set_dep\n    tape.set_dep( dep_vec );\n    //\n    // trace\n    bool trace = false;\n    //\n    // x\n    Vector<double> x(2);\n    x[0] = 5.0;\n    x[1] = 6.0;\n    //\n    // val_vec\n    Vector<double> val_vec( tape.n_val() );\n    for(addr_t i = 0; i < n_ind; ++i)\n        val_vec[i] = x[i];\n    tape.eval(trace, val_vec);\n    //\n    // y, ok\n    Vector<double> y(1);\n    dep_vec = tape.dep_vec();\n    y[0]    = val_vec[ dep_vec[0] ];\n    ok     &= dep_vec[0] == n_ind + 2;\n    ok     &= y[0] == x[0] + x[1];\n    //\n    // renumber\n    ok &= dep_vec[0] == n_ind + 2;\n    tape.renumber();\n    dep_vec = tape.dep_vec();\n    ok &= dep_vec[0] == n_ind + 1;\n    //\n    // val_vec\n    tape.eval(trace, val_vec);\n    //\n    // y, ok\n    dep_vec = tape.dep_vec();\n    y[0]    = val_vec[ dep_vec[0] ];\n    ok     &= dep_vec[0] == n_ind + 1;\n    ok     &= y[0] == x[0] + x[1];\n    //\n    return ok;\n}\n// END_C++\n"
  },
  {
    "path": "val_graph/summation_xam.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2023-23 Bradley M. Bell\n# include <cppad/local/val_graph/tape.hpp>\n/*\n{xrst_begin val_summation_xam.cpp dev}\n\nCombining Value Operators Into a Cumulative Summation Example\n#############################################################\n{xrst_literal\n    // BEGIN_C++\n    // END_C++\n}\n\n{xrst_end val_summation_xam.cpp}\n*/\n// BEGIN_C++\nbool summation_xam(void)\n{   bool ok = true;\n    //\n    // tape_t, Vector, addr_t,\n    //    add_op_enum, sub_op_enum, mul_op_enum, neg_op_enum\n    using CppAD::local::val_graph::tape_t;\n    using CppAD::local::val_graph::Vector;\n    using CppAD::local::val_graph::addr_t;\n    using CppAD::local::val_graph::op_enum_t;\n    op_enum_t add_op_enum = CppAD::local::val_graph::add_op_enum;\n    op_enum_t sub_op_enum = CppAD::local::val_graph::sub_op_enum;\n    op_enum_t mul_op_enum = CppAD::local::val_graph::mul_op_enum;\n    op_enum_t neg_op_enum = CppAD::local::val_graph::neg_op_enum;\n    //\n    // tape, ok\n    tape_t<double> tape;\n    addr_t n_ind = 4;\n    addr_t index_of_nan = tape.set_ind(n_ind);\n    ok &= index_of_nan == n_ind;\n    Vector<addr_t> op_arg(2);\n    //\n    // op_arg, add = x[0] + x[1]\n    op_arg[0] = 0;   // x[0]\n    op_arg[1] = 1;   // x[1]\n    addr_t add = tape.record_op(add_op_enum, op_arg);\n    //\n    // op_arg, mul = x[2] * x[3]\n    op_arg[0] = 2;   // x[2]\n    op_arg[1] = 3;   // x[3]\n    addr_t mul = tape.record_op(mul_op_enum, op_arg);\n    //\n    // op_arg, sub = x[0] + x[1] - x[2] * x[3]\n    op_arg[0] = add;\n    op_arg[1] = mul;\n    addr_t sub = tape.record_op(sub_op_enum, op_arg);\n    //\n    // op_arg, neg = x[2] * x[3] - x[0] - x[1]\n    op_arg.resize(1);\n    op_arg[0] = sub;\n    addr_t neg = tape.record_op(neg_op_enum, op_arg);\n    //\n    // dep_vec, tape\n    Vector<addr_t> dep_vec(1);\n    dep_vec[0] = neg; // x[2] * x[3] - x[0] - x[1]\n    //\n    // set_dep\n    tape.set_dep( dep_vec );\n    //\n    // x\n    Vector<double> x(n_ind);\n    for(addr_t i = 0; i < n_ind; ++i)\n        x[i] = double(2 + i);\n    //\n    // trace\n    bool trace = false;\n    //\n    // val_vec\n    Vector<double> val_vec( tape.n_val() );\n    for(addr_t i = 0; i < n_ind; ++i)\n        val_vec[i] = x[i];\n    tape.eval(trace, val_vec);\n    //\n    // ok\n    ok &= tape.n_op()  == 5;\n    ok &= tape.con_vec().size() == 1;\n    ok &= tape.arg_vec().size() == 2 + 3 * 2;\n    ok &= tape.n_val()          == n_ind + 1 + 4;\n    //\n    // summation\n    tape.summation();\n    tape.dead_code();\n    //\n    // ok\n    ok &= tape.n_op()  == 3;\n    ok &= tape.con_vec().size() == 1;\n    ok &= tape.arg_vec().size() == 1 + 2 + 6;\n    ok &= tape.n_val()          == n_ind + 3;\n    //\n    // eval\n    val_vec.resize( tape.n_val() );\n    tape.eval(trace, val_vec);\n    //\n    // y\n    Vector<double> y(1);\n    dep_vec = tape.dep_vec();\n    y[0]    = val_vec[ dep_vec[0] ];\n    //\n    // ok\n    ok &= y[0] == x[2] * x[3] - x[0] - x[1];\n    //\n    return ok;\n}\n// END_C++\n"
  },
  {
    "path": "val_graph/test/ad_double.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2023-23 Bradley M. Bell\n# include <cppad/cppad.hpp>\nnamespace { // BEGIN_EMPTY_NAMESPACE\n// ----------------------------------------------------------------------------\nbool con_op(void)\n{   bool ok = true;\n    //\n    // AD, tape_t, Vector, addr_t, con_op_enum, add_op_enum;\n    using CppAD::AD;\n    using CppAD::local::val_graph::tape_t;\n    using CppAD::local::val_graph::Vector;\n    using CppAD::local::val_graph::addr_t;\n    using CppAD::local::val_graph::op_enum_t;\n    op_enum_t add_op_enum = CppAD::local::val_graph::add_op_enum;\n    //\n    // tape\n    tape_t< AD<double> > tape;\n    addr_t n_ind = 1;\n    addr_t index_of_nan = tape.set_ind(n_ind);\n    ok &= index_of_nan == n_ind;\n    //\n    // op_arg\n    Vector<addr_t> op_arg(2);\n    //\n    // dep_vec\n    Vector<addr_t> dep_vec(1);\n    //\n    // tape\n    addr_t five     = tape.record_con_op(5.0); // 5.0\n    tape.record_con_op(5.0);                   // not used\n    op_arg[0] = 0; // x[0]\n    op_arg[1] = five;\n    dep_vec[0] = tape.record_op(add_op_enum, op_arg); // x[0] + 5.0\n    //\n    // set_dep\n    tape.set_dep( dep_vec );\n    //\n    // x\n    Vector< AD<double> > ax(1);\n    ax[0] = 6.0;\n    //\n    // trace\n    bool trace = false;\n    //\n    // val_vec\n    Vector< AD<double> > val_vec( tape.n_val() );\n    for(addr_t i = 0; i < n_ind; ++i)\n        val_vec[i] = ax[i];\n    tape.eval(trace, val_vec);\n    //\n    // ok\n    ok &= tape.n_op()  == 4;\n    ok &= tape.arg_vec().size() == 5;\n    ok &= tape.con_vec().size() == 3;\n    ok &= tape.n_val()          == n_ind + 4;\n    //\n    // renumber\n    tape.renumber();\n    //\n    // ok\n    ok &= tape.n_op()  == 4;\n    ok &= tape.arg_vec().size() == 5;\n    ok &= tape.con_vec().size() == 3;\n    ok &= tape.n_val()          == n_ind + 4;\n    //\n    // dead_code\n    tape.dead_code();\n    //\n    // val_vec\n    val_vec.resize( tape.n_val() );\n    tape.eval(trace, val_vec);\n    dep_vec =  tape.dep_vec();\n    //\n    // ok\n    ok &= tape.n_op()  == 3;\n    ok &= tape.arg_vec().size() == 4;\n    ok &= tape.con_vec().size() == 2;\n    ok &= tape.n_val()          == n_ind + 3;\n    //\n    // y\n    Vector< AD<double> > ay(1);\n    ay[0] = val_vec[ dep_vec[0] ];\n    //\n    // ok\n    ok &= ay[0] == ax[0] + 5.0;\n    //\n    return ok;\n}\n// ----------------------------------------------------------------------------\n} // END_EMPTY_NAMESPACE\nbool test_ad_double(void)\n{   bool ok = true;\n    ok     &= con_op();\n    return ok;\n}\n"
  },
  {
    "path": "val_graph/test/fold.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2023-23 Bradley M. Bell\n# include <cppad/local/val_graph/tape.hpp>\n# include \"../atomic_xam.hpp\"\n//\nnamespace { // BEGIN_EMPTY_NAMESPACE\n// ----------------------------------------------------------------------------\n// atom\nbool atom(void)\n{   bool ok = true;\n    //\n    // tape_t, Vector, addr_t, add_op_enum;\n    using CppAD::local::val_graph::tape_t;\n    using CppAD::local::val_graph::Vector;\n    using CppAD::local::val_graph::addr_t;\n    using CppAD::local::val_graph::op_enum_t;\n    op_enum_t add_op_enum = CppAD::local::val_graph::add_op_enum;\n    //\n    // atomic_xam\n    val_atomic_xam atomic_xam;\n    //\n    // callarg, op_arg\n    Vector<addr_t> callarg(4), op_arg(2);\n    //\n    // tape, ok\n    tape_t<double> tape;\n    addr_t n_ind = 1;\n    addr_t index_of_nan = tape.set_ind(n_ind);\n    ok &= index_of_nan == n_ind;\n    //\n    // atomic_index\n    addr_t atomic_index = addr_t( atomic_xam.atomic_index() );\n    //\n    // g_0(x) = c[0] + c[1]\n    // g_1(x) = c[2] * c[3]\n    Vector<double> c(4);\n    for(addr_t i = 0; i < 4; ++i)\n    {   c[i] = double(i + 2);\n        callarg[i] = tape.record_con_op(c[i]);\n    }\n    addr_t n_call_res = 2;\n    addr_t call_id    = 0;\n    addr_t res_index = tape.record_call_op(\n        atomic_index, call_id, n_call_res, callarg\n    );\n    //\n    // dep_vec\n    Vector<addr_t> dep_vec(2);\n    //\n    // y[0] = x[0] + c[0] + c[1]\n    op_arg[0] = 0;\n    op_arg[1] = res_index;\n    dep_vec[0] = tape.record_op(add_op_enum, op_arg);\n    //\n    // y[0] = x[0] + c[2] * c[3]\n    op_arg[0] = 0;\n    op_arg[1] = res_index + 1;\n    dep_vec[1] = tape.record_op(add_op_enum, op_arg);\n    //\n    // set_dep\n    tape.set_dep( dep_vec );\n    //\n    // trace\n    bool trace = false;\n    //\n    // x\n    Vector<double> x(1);\n    x[0] = 5.0;\n    //\n    // val_vec\n    Vector<double> val_vec( tape.n_val() );\n    for(addr_t i = 0; i < n_ind; ++i)\n        val_vec[i] = x[i];\n    tape.eval(trace, val_vec);\n    //\n    // y, ok\n    Vector<double> y(2);\n    y[0]    = val_vec[ dep_vec[0] ];\n    y[1]    = val_vec[ dep_vec[1] ];\n    ok     &= y[0] == x[0] + c[0] + c[1];\n    ok     &= y[1] == x[0] + c[2] * c[3];\n    ok     &= tape.con_vec().size() == 5;\n    ok     &= tape.n_op()  == 8;\n    ok     &= tape.arg_vec().size() == 1 + 4 + 4 + 5 + 2 + 2;\n    //\n    // fold_con\n    tape.fold_con();\n    //\n    // val_vec\n    val_vec.resize( tape.n_val() );\n    for(addr_t i = 0; i < n_ind; ++i)\n        val_vec[i] = x[i];\n    tape.eval(trace, val_vec);\n    //\n    // dead_code\n    tape.dead_code();\n    //\n    // val_vec\n    val_vec.resize( tape.n_val() );\n    for(addr_t i = 0; i < n_ind; ++i)\n        val_vec[i] = x[i];\n    tape.eval(trace, val_vec);\n    //\n    // y, ok\n    dep_vec = tape.dep_vec();\n    y[0]    = val_vec[ dep_vec[0] ];\n    y[1]    = val_vec[ dep_vec[1] ];\n    ok     &= y[0] == x[0] + c[0] + c[1];\n    ok     &= y[1] == x[0] + c[2] * c[3];\n    ok     &= tape.con_vec().size() == 3;\n    ok     &= tape.n_op()  == 5;\n    ok     &= tape.arg_vec().size() == 7;\n    //\n    return ok;\n}\n// ----------------------------------------------------------------------------\n// dis_op\n//\ndouble floor(const double& arg)\n{   return std::floor(arg); }\n//\nCPPAD_DISCRETE_FUNCTION(double, floor);\nbool dis_op(void)\n{   bool ok = true;\n    //\n    // tape_t, Vector, addr_t, add_op_enum;\n    using CppAD::local::val_graph::tape_t;\n    using CppAD::local::val_graph::Vector;\n    using CppAD::local::val_graph::addr_t;\n    using CppAD::local::val_graph::op_enum_t;\n    op_enum_t add_op_enum = CppAD::local::val_graph::add_op_enum;\n    //\n    // tape, ok\n    tape_t<double> tape;\n    addr_t n_ind = 1;\n    addr_t index_of_nan = tape.set_ind(n_ind);\n    ok &= index_of_nan == n_ind;\n    //\n    // dep_vec\n    Vector<addr_t> dep_vec(1);\n    //\n    // c\n    Vector<double> c(2);\n    c[0] = 5.5;\n    c[1] = floor( c[0] );\n    //\n    // tape\n    addr_t c0_addr        = tape.record_con_op( c[0] );\n    addr_t discrete_index = addr_t( CppAD::discrete<double>::index(\"floor\") );\n    addr_t c1_addr        = tape.record_dis_op(discrete_index, c0_addr);\n    //\n    // tape, dep_vec\n    // y[0] = x[0] + c[1]\n    Vector<addr_t> op_arg(2);\n    op_arg[0] = 0;        // x[0]\n    op_arg[1] = c1_addr;  // c[1]\n    dep_vec[0]            = tape.record_op(add_op_enum, op_arg); // x[0] + c[1]\n    //\n    // tape\n    tape.set_dep( dep_vec );\n    //\n    // trace\n    bool trace = false;\n    //\n    // x\n    Vector<double> x(1);\n    x[0] = 3.0;\n    //\n    // val_vec\n    Vector<double> val_vec( tape.n_val() );\n    for(addr_t i = 0; i < n_ind; ++i)\n        val_vec[i] = x[i];\n    tape.eval(trace, val_vec);\n    //\n    // y, ok\n    Vector<double> y(1);\n    y[0]    = val_vec[ dep_vec[0] ];\n    ok     &= y[0] == x[0] + c[1];\n    ok     &= tape.con_vec().size() == 2;\n    ok     &= tape.n_op()  == 4;\n    ok     &= tape.arg_vec().size() == 6;\n    //\n    // fold_con\n    tape.fold_con();\n    //\n    // dead_code\n    tape.dead_code();\n    //\n    // val_vec\n    val_vec.resize( tape.n_val() );\n    for(addr_t i = 0; i < n_ind; ++i)\n        val_vec[i] = x[i];\n    tape.eval(trace, val_vec);\n    //\n    // y, ok\n    dep_vec = tape.dep_vec();\n    y[0]    = val_vec[ dep_vec[0] ];\n    ok     &= y[0] == x[0] + c[1];\n    ok     &= tape.con_vec().size() == 2;\n    ok     &= tape.n_op()  == 3;\n    ok     &= tape.arg_vec().size() == 4;\n    //\n    return ok;\n}\n// ----------------------------------------------------------------------------\n// cexp_op\nbool cexp_op(void)\n{   bool ok = true;\n    //\n    // tape_t, Vector, addr_t, add_op_enum;\n    using CppAD::local::val_graph::tape_t;\n    using CppAD::local::val_graph::Vector;\n    using CppAD::local::val_graph::addr_t;\n    CppAD::local::val_graph::compare_enum_t\n        compare_lt_enum = CppAD::local::val_graph::compare_lt_enum;\n    //\n    // tape, ok\n    tape_t<double> tape;\n    addr_t n_ind = 1;\n    addr_t index_of_nan = tape.set_ind(n_ind);\n    ok &= index_of_nan == n_ind;\n    //\n    addr_t left     = tape.record_con_op( 5.0 );\n    addr_t right    = tape.record_con_op( 4.0 );\n    addr_t if_true  = tape.record_con_op( 3.0 );\n    addr_t if_false = tape.record_con_op( 2.0 );\n    // y[0] = x[0] + c[1]\n    Vector<addr_t> op_arg(2);\n    //\n    // dep_vec\n    Vector<addr_t> dep_vec(1);\n    dep_vec[0] = tape.record_cexp_op(\n        compare_lt_enum, left, right, if_true, if_false\n    );\n    //\n    // tape\n    tape.set_dep( dep_vec );\n    //\n    // trace\n    bool trace = false;\n    //\n    // x\n    Vector<double> x(1);\n    x[0] = 3.0;\n    //\n    // val_vec\n    Vector<double> val_vec( tape.n_val() );\n    for(addr_t i = 0; i < n_ind; ++i)\n        val_vec[i] = x[i];\n    tape.eval(trace, val_vec);\n    //\n    // y, ok\n    Vector<double> y(1);\n    y[0]    = val_vec[ dep_vec[0] ];\n    ok     &= y[0] == 2.0;\n    ok     &= tape.con_vec().size() == 5;\n    ok     &= tape.n_op()           == 6;\n    ok     &= tape.arg_vec().size() == 5 + 5;\n    //\n    // fold_con\n    tape.fold_con();\n    //\n    // dead_code\n    tape.dead_code();\n    //\n    // val_vec\n    val_vec.resize( tape.n_val() );\n    for(addr_t i = 0; i < n_ind; ++i)\n        val_vec[i] = x[i];\n    tape.eval(trace, val_vec);\n    //\n    // y, ok\n    dep_vec = tape.dep_vec();\n    y[0]    = val_vec[ dep_vec[0] ];\n    ok     &= y[0] == 2.0;\n    ok     &= tape.con_vec().size() == 2;\n    ok     &= tape.n_op()           == 2;\n    ok     &= tape.arg_vec().size() == 2;\n    //\n    return ok;\n}\n// ----------------------------------------------------------------------------\n} // END_EMPTY_NAMESPACE\n//\n// test_fold\nbool test_fold(void)\n{   bool ok = true;\n    //\n    ok &= cexp_op();\n    ok &= atom();\n    ok &= dis_op();\n    //\n    return ok;\n}\n"
  },
  {
    "path": "val_graph/test/fun2val.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2023-24 Bradley M. Bell\n# include <cppad/cppad.hpp>\n# include <cppad/local/val_graph/tape.hpp>\n# include \"../atomic_xam.hpp\"\nnamespace { // BEGIN_EMPTY_NAMESPACE\n// ----------------------------------------------------------------------------\n// dynamic_atom\nbool dynamic_atom(void)\n{   bool ok = true;\n    //\n    // AD, addr_t\n    using CppAD::AD;\n    using CppAD::addr_t;\n    //\n    // tape_t, Vector\n    using CppAD::local::val_graph::tape_t;\n    using CppAD::local::val_graph::Vector;\n    //\n    // atomic_xam\n    val_atomic_xam atomic_xam;\n    //\n    // ap, ax\n    Vector< AD<double> > ap(4), ax(1);\n    for(size_t i = 0; i < 4; ++i)\n        ap[i] = double(i + 1);\n    ax[0] = 5.0;\n    CppAD::Independent(ax, ap);\n    //\n    // f\n    Vector< AD<double> > ad(2), ay(1);\n    atomic_xam(ap, ad);            // d[0] = p[0] + p[1],  d[1] = p[2] * p[3]\n    ay[0] = ad[0] + ad[1] + ax[0]; // y[0] = p[0] + p[1] + p[2] * p[3] + x[0]\n    CppAD::ADFun<double> f(ax, ay);\n    //\n    // tape\n    tape_t<double> tape;\n    f.fun2val(tape);\n    //\n    // dep_vec\n    Vector<addr_t> dep_vec = tape.dep_vec();\n    ok &= dep_vec.size() == 1;\n    //\n    // x\n    ok &= tape.n_ind() == 5;\n    Vector<double> p(4), x(1);\n    for(size_t i = 0; i < 4; ++i)\n        p[i] = double(i + 2);\n    x[0] = 6.0;\n    //\n    // trace\n    bool trace = false;\n    //\n    // val_vec\n    Vector<double> val_vec( tape.n_val() );\n    for(size_t i = 0; i < 4; ++i)\n        val_vec[i] = p[i];\n    val_vec[4] = x[0];\n    size_t compare_false = 0;\n    tape.eval(trace, val_vec, compare_false);\n    ok &= compare_false == 0;\n    //\n    // y\n    Vector<double> y(1);\n    y[0] = val_vec[ dep_vec[0] ];\n    //\n    // ok\n    ok &= y[0] == p[0] + p[1] + p[2] * p[3] + x[0];\n    //\n    return ok;\n}\n// ----------------------------------------------------------------------------\n// variable_atom\nbool variable_atom(void)\n{   bool ok = true;\n    //\n    // AD, addr_t\n    using CppAD::AD;\n    using CppAD::addr_t;\n    //\n    // tape_t, Vector\n    using CppAD::local::val_graph::tape_t;\n    using CppAD::local::val_graph::Vector;\n    //\n    // atomic_xam\n    val_atomic_xam atomic_xam;\n    //\n    // ax, ap\n    Vector< AD<double> > ax(4), ap(1);\n    for(size_t i = 0; i < 4; ++i)\n        ax[i] = double(i + 1);\n    ap[0] = 5.0;\n    CppAD::Independent(ax, ap);\n    //\n    // f\n    Vector< AD<double> > ay(2);\n    atomic_xam(ax, ay);\n    ay[0] = ay[0] + ap[0]; // y[0] = x[0] + x[1] + p[0]\n    ay[1] = ay[1] - ap[0]; // y[1] = x[2] * x[3] - p[0]\n    CppAD::ADFun<double> f(ax, ay);\n    //\n    // tape\n    tape_t<double> tape;\n    f.fun2val(tape);\n    //\n    // dep_vec\n    Vector<addr_t> dep_vec = tape.dep_vec();\n    ok &= dep_vec.size() == 2;\n    //\n    // x\n    ok &= tape.n_ind() == 5;\n    Vector<double> x(4), p(1);\n    for(size_t i = 0; i < 4; ++i)\n        x[i] = double(i + 2);\n    p[0] = 6.0;\n    //\n    // trace\n    bool trace = false;\n    //\n    // val_vec\n    Vector<double> val_vec( tape.n_val() );\n    val_vec[0] = p[0];\n    for(size_t i = 0; i < 4; ++i)\n        val_vec[i + 1] = x[i];\n    size_t compare_false = 0;\n    tape.eval(trace, val_vec, compare_false);\n    ok &= compare_false == 0;\n    //\n    // y\n    Vector<double> y(2);\n    y[0] = val_vec[ dep_vec[0] ];\n    y[1] = val_vec[ dep_vec[1] ];\n    //\n    // ok\n    ok &= y[0] == x[0] + x[1] + p[0];\n    ok &= y[1] == x[2] * x[3] - p[0];\n    //\n    return ok;\n}\n// ----------------------------------------------------------------------------\n// unary\nbool unary_op(void)\n{   bool ok = true;\n    //\n    // AD, addr_t\n    using CppAD::AD;\n    using CppAD::addr_t;\n    //\n    // tape_t, Vector\n    using CppAD::local::val_graph::tape_t;\n    using CppAD::local::val_graph::Vector;\n    //\n    // ap, ax\n    Vector< AD<double> > ap(1), ax(1);\n    ap[0] = 2.0;\n    ax[0] = 3.0;\n    CppAD::Independent(ax, ap);\n    //\n    // f\n    Vector< AD<double> > ay(2);\n    ay[0] = - ap[0];\n    ay[1] = - ax[0];\n    CppAD::ADFun<double> f(ax, ay);\n    //\n    // tape\n    tape_t<double> tape;\n    f.fun2val(tape);\n    //\n    // dep_vec\n    Vector<addr_t> dep_vec = tape.dep_vec();\n    ok &= dep_vec.size() == 2;\n    //\n    // x\n    ok &= tape.n_ind() == 2;\n    Vector<double> p(1), x(1);\n    p[0] = 5.0;\n    x[0] = 6.0;\n    //\n    // trace\n    bool trace = false;\n    //\n    // val_vec\n    Vector<double> val_vec( tape.n_val() );\n    val_vec[0] = p[0];\n    val_vec[1] = x[0];\n    size_t compare_false = 0;\n    tape.eval(trace, val_vec, compare_false);\n    ok &= compare_false == 0;\n    //\n    // y\n    Vector<double> y(2);\n    y[0] = val_vec[ dep_vec[0] ];\n    y[1] = val_vec[ dep_vec[1] ];\n    //\n    // ok\n    ok &= y[0] == - p[0];\n    ok &= y[1] == - x[0];\n    //\n    return ok;\n}\n// -------------------------------------------------------------------------\n// comp_op\nbool comp_op(void)\n{   bool ok = true;\n    //\n    // AD, addr_t\n    using CppAD::AD;\n    using CppAD::addr_t;\n    //\n    // tape_t, Vector\n    using CppAD::local::val_graph::tape_t;\n    using CppAD::local::val_graph::Vector;\n    //\n    // ap, ax\n    Vector< AD<double> > ap(1), ax(1);\n    ap[0] = 2.0;\n    ax[0] = 3.0;\n    CppAD::Independent(ax, ap);\n    //\n    // f\n    Vector< AD<double> > ay(1);\n    if( ap[0] < ax[0] )\n        // 2024-03-01: Test for bug in val_graph/fun2val.hpp:\n        // changed from ay[0] = ax[0] to ay[0] = ax[0] * ax[0]\n        ay[0] = ax[0] * ax[0];\n    else\n        ay[0] = ap[0];\n    CppAD::ADFun<double> f(ax, ay);\n    //\n    // tape\n    tape_t<double> tape;\n    f.fun2val(tape);\n    //\n    // dep_vec\n    Vector<addr_t> dep_vec = tape.dep_vec();\n    ok &= dep_vec.size() == 1;\n    ok &= tape.n_ind() == 2;\n    //\n    // trace\n    bool trace = false;\n    //\n    // p, x\n    Vector<double> p(1), x(1);\n    p[0] = 5.0; // p[0] < x[0] is true\n    x[0] = 6.0;\n    //\n    // val_vec\n    Vector<double> val_vec( tape.n_val() );\n    val_vec[0] = p[0];\n    val_vec[1] = x[0];\n    size_t compare_false = 0;\n    tape.eval(trace, val_vec, compare_false);\n    ok &= compare_false == 0;\n    //\n    // y, ok\n    Vector<double> y(2);\n    y[0] = val_vec[ dep_vec[0] ];\n    ok &= y[0] == x[0] * x[0];\n    //\n    // p, x\n    p[0] = 6.0; // p[0] < x[0] is false\n    x[0] = 5.0;\n    //\n    // val_vec\n    val_vec[0] = p[0];\n    val_vec[1] = x[0];\n    tape.eval(trace, val_vec, compare_false);\n    ok &= compare_false == 1;\n    //\n    // y, ok\n    y[0] = val_vec[ dep_vec[0] ];\n    ok &= y[0] == x[0] * x[0];\n    //\n    return ok;\n}\n// ----------------------------------------------------------------------------\n// dis_op\ndouble floor(const double& arg)\n{   return std::floor(arg); }\n//\nCPPAD_DISCRETE_FUNCTION(double, floor);\nbool dis_op(void)\n{   bool ok = true;\n    //\n    // AD, addr_t\n    using CppAD::AD;\n    using CppAD::addr_t;\n    //\n    // tape_t, Vector\n    using CppAD::local::val_graph::tape_t;\n    using CppAD::local::val_graph::Vector;\n    //\n    // ap, ax\n    Vector< AD<double> > ap(1), ax(1);\n    ap[0] = 2.0;\n    ax[0] = 3.0;\n    CppAD::Independent(ax, ap);\n    //\n    // f\n    Vector< AD<double> > ay(2);\n    ay[0] = floor( ap[0] );\n    ay[1] = floor( ax[0] );\n    CppAD::ADFun<double> f(ax, ay);\n    //\n    // tape\n    tape_t<double> tape;\n    f.fun2val(tape);\n    //\n    // dep_vec\n    Vector<addr_t> dep_vec = tape.dep_vec();\n    ok &= dep_vec.size() == 2;\n    //\n    // x\n    ok &= tape.n_ind() == 2;\n    Vector<double> p(1), x(1);\n    p[0] =   5.5;\n    x[0] = - 5.5;\n    //\n    // trace\n    bool trace = false;\n    //\n    // val_vec\n    Vector<double> val_vec( tape.n_val() );\n    val_vec[0] = p[0];\n    val_vec[1] = x[0];\n    size_t compare_false = 0;\n    tape.eval(trace, val_vec, compare_false);\n    ok &= compare_false == 0;\n    //\n    // y\n    Vector<double> y(2);\n    y[0] = val_vec[ dep_vec[0] ];\n    y[1] = val_vec[ dep_vec[1] ];\n    //\n    // ok\n    ok &= y[0] == std::floor( p[0] );\n    ok &= y[1] == std::floor( x[0] );\n    //\n    return ok;\n}\n// ----------------------------------------------------------------------------\n// cexp_op\nbool cexp_op(void)\n{   bool ok = true;\n    //\n    // AD, addr_t\n    using CppAD::AD;\n    using CppAD::addr_t;\n    //\n    // tape_t, Vector\n    using CppAD::local::val_graph::tape_t;\n    using CppAD::local::val_graph::Vector;\n    //\n    // ap, ax\n    Vector< AD<double> > ap(2), ax(2);\n    ap[0] = 2.0;\n    ap[1] = 3.0;\n    ax[0] = 4.0;\n    ax[1] = 5.0;\n    CppAD::Independent(ax, ap);\n    //\n    // ay\n    Vector< AD<double> > ay(2);\n    ay[0] = CondExpGt(ap[0], ap[1], AD<double>(6.0), AD<double>(7.0) );\n    ay[1] = CondExpLt(ax[0], ax[1], ap[0], ap[1]);\n    //\n    // f\n    CppAD::ADFun<double> f(ax, ay);\n    //\n    // tape\n    tape_t<double> tape;\n    f.fun2val(tape);\n    //\n    // dep_vec\n    Vector<addr_t> dep_vec = tape.dep_vec();\n    ok &= dep_vec.size() == 2;\n    //\n    // x\n    ok &= tape.n_ind() == 4;\n    Vector<double> p(2), x(2);\n    p[0] =   5.0;\n    p[1] =   4.0;\n    x[0] =   3.0;\n    x[1] =   2.0;\n    //\n    // trace\n    bool trace = false;\n    //\n    // val_vec\n    Vector<double> val_vec( tape.n_val() );\n    val_vec[0] = p[0];\n    val_vec[1] = p[1];\n    val_vec[2] = x[0];\n    val_vec[3] = x[1];\n    size_t compare_false = 0;\n    tape.eval(trace, val_vec, compare_false);\n    ok &= compare_false == 0;\n    //\n    // y\n    Vector<double> y(2);\n    y[0] = val_vec[ dep_vec[0] ];\n    y[1] = val_vec[ dep_vec[1] ];\n    //\n    // ok\n    ok &= y[0] == 6.0;\n    ok &= y[1] == p[1];\n    //\n    return ok;\n}\n// ----------------------------------------------------------------------------\n// csum_op\nbool csum_op(void)\n{   bool ok = true;\n    //\n    // tape_t, Vector, addr_t\n    using CppAD::local::val_graph::tape_t;\n    using CppAD::local::val_graph::Vector;\n    using CppAD::local::val_graph::addr_t;\n    //\n    // tape, ok\n    tape_t<double> tape;\n    addr_t n_ind = 4;\n    addr_t index_of_nan = tape.set_ind(n_ind);\n    ok &= index_of_nan == n_ind;\n    //\n    // c[0], c[1]\n    Vector<double> c(2);\n    c[0] = -2.0;\n    c[1] = -3.0;\n    addr_t c0 = tape.record_con_op( c[0] );\n    addr_t c1 = tape.record_con_op( c[1] );\n    //\n    // add, sub\n    Vector<addr_t> add(3), sub(3);\n    add[0] = 0;  // x[0]\n    add[1] = 2;  // p[0]\n    add[2] = c0; // c[0]\n    //\n    sub[0] = 1;   // x[1]\n    sub[1] = 3;   // p[1]\n    sub[2] = c1;  // c[1]\n    //\n    // tape, dep_vec\n    Vector<addr_t> dep_vec(1);\n    dep_vec[0] = tape.record_csum_op(add, sub);\n    tape.set_dep( dep_vec );\n    //\n    // trace\n    bool trace = false;\n    //\n    // val_vec, ok\n    Vector<double> x(2), p(2), val_vec( tape.n_val() );\n    val_vec[0] = x[0] = 2.0;\n    val_vec[1] = x[1] = 3.0;\n    val_vec[2] = p[0] = 5.0;\n    val_vec[3] = p[1] = 8.0;\n    size_t compare_false = 0;\n    tape.eval(trace, val_vec, compare_false);\n    ok &= compare_false == 0;\n    //\n    // y, ok\n    Vector<double> y(1);\n    y[0] = val_vec[ dep_vec[0] ];\n    ok &= y[0] == x[0] - x[1] + p[0] - p[1]  + c[0] - c[1];\n    //\n    // f: val2fun\n    Vector<size_t> var_ind(2), dyn_ind(2);\n    var_ind[0] = 0; // x[0]\n    var_ind[1] = 1; // x[1]\n    dyn_ind[0] = 2; // p[0]\n    dyn_ind[1] = 3; // p[1]\n    CppAD::ADFun<double> f;\n    f.val2fun(tape, dyn_ind, var_ind);\n    //\n    // tape: fun2val, dep_vec\n    f.fun2val(tape);\n    dep_vec = tape.dep_vec();\n    //\n    // y, ok\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    y[0] = val_vec[ dep_vec[0] ];\n    ok &= y[0] == x[0] - x[1] + p[0] - p[1]  + c[0] - c[1];\n    //\n    // val_vec, ok\n    val_vec.resize( tape.n_val() );\n    tape.eval(trace, val_vec, compare_false);\n    ok &= compare_false == 0;\n    //\n    // y, ok\n    y[0] = val_vec[ dep_vec[0] ];\n    ok &= y[0] == x[0] - x[1] + p[0] - p[1]  + c[0] - c[1];\n    //\n    //\n    return ok;\n}\n// -------------------------------------------------------------------------\n// pri_op\nbool pri_op(void)\n{   bool ok = true;\n    //\n    // AD, addr_t\n    using CppAD::AD;\n    using CppAD::addr_t;\n    //\n    // tape_t, Vector\n    using CppAD::local::val_graph::tape_t;\n    using CppAD::local::val_graph::Vector;\n    //\n    // ap, ax\n    Vector< AD<double> > ap(1), ax(1);\n    ap[0] = 3.0;\n    ax[0] = 2.0;\n    CppAD::Independent(ax, ap);\n    //\n    // f\n    Vector< AD<double> > ay(1);\n    ay[0] = ax[0] - ap[0];\n    PrintFor(ay[0], \"0 >= ax[0] - ap[0] = \", ay[0], \"\\n\");\n    CppAD::ADFun<double> f(ax, ay);\n    //\n    // tape\n    tape_t<double> tape;\n    f.fun2val(tape);\n    //\n    // dep_vec\n    Vector<addr_t> dep_vec = tape.dep_vec();\n    ok &= dep_vec.size() == 1;\n    ok &= tape.n_ind() == 2;\n    //\n    // trace\n    bool trace = false;\n    //\n    // p, x\n    Vector<double> p(1), x(1);\n    p[0] = 2.0; // 0 >= x[0] - p[0]\n    x[0] = 3.0;\n    //\n    // val_vec\n    Vector<double> val_vec( tape.n_val() );\n    val_vec[0] = p[0];\n    val_vec[1] = x[0];\n    size_t compare_false = 0;\n    tape.eval(trace, val_vec, compare_false);\n    ok &= compare_false == 0;\n    //\n    // y, ok\n    Vector<double> y(2);\n    y[0] = val_vec[ dep_vec[0] ];\n    ok &= y[0] == x[0] - p[0];\n    //\n    return ok;\n}\n// -------------------------------------------------------------------------\n// vector_op\nbool vector_op(void)\n{   bool ok = true;\n    //\n    // AD, addr_t\n    using CppAD::AD;\n    using CppAD::addr_t;\n    //\n    // tape_t, Vector\n    using CppAD::local::val_graph::tape_t;\n    using CppAD::local::val_graph::Vector;\n    //\n    // ax\n    Vector< AD<double> > ax(3);\n    ax[0] = 0.0; // zero or one\n    ax[1] = 2.0;\n    ax[2] = 3.0;\n    CppAD::Independent(ax);\n    //\n    // av\n    CppAD::VecAD<double> au(2);\n    au[ ax[0] ]       = ax[1];\n    au[ 1.0 - ax[0] ] = ax[2];\n    //\n    // f\n    Vector< AD<double> > ay(2);\n    ay[0] = au[ AD<double>(0) ];\n    ay[1] = au[ AD<double>(1) ];\n    CppAD::ADFun<double> f(ax, ay);\n    //\n    // tape\n    tape_t<double> tape;\n    f.fun2val(tape);\n    //\n    // dep_vec\n    Vector<addr_t> dep_vec = tape.dep_vec();\n    ok &= dep_vec.size() == 2;\n    ok &= tape.n_ind() == 3;\n    //\n    // trace\n    bool trace = false;\n    //\n    // x\n    Vector<double> x(3);\n    x[0] = 1.0; // zero or one\n    x[1] = 4.0;\n    x[2] = 5.0;\n    //\n    // val_vec\n    Vector<double> val_vec( tape.n_val() );\n    for(size_t i = 0; i < 3; ++i)\n        val_vec[i] = x[i];\n    tape.eval(trace, val_vec);\n    //\n    // y, ok\n    Vector<double> y(2);\n    y[0] = val_vec[ dep_vec[0] ];\n    y[1] = val_vec[ dep_vec[1] ];\n    //\n    ok &= y[ size_t( x[0] ) ]       == x[1];\n    ok &= y[ size_t( 1.0 - x[0] ) ] == x[2];\n    //\n    return ok;\n}\n// ----------------------------------------------------------------------------\n} // END_EMPTY_NAMESPACE\nbool test_fun2val(void)\n{   bool ok = true;\n    ok     &= vector_op();\n    ok     &= dynamic_atom();\n    ok     &= variable_atom();\n    ok     &= unary_op();\n    ok     &= comp_op();\n    ok     &= dis_op();\n    ok     &= cexp_op();\n    ok     &= csum_op();\n    ok     &= pri_op();\n    return ok;\n}\n"
  },
  {
    "path": "val_graph/test/nan.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2023-23 Bradley M. Bell\n# include <cppad/local/val_graph/tape.hpp>\n# include <limits>\n//\nbool test_nan(void)\n{   bool ok = true;\n    //\n    // tape_t, Vector, addr_t, con_op_enum\n    using CppAD::local::val_graph::tape_t;\n    using CppAD::local::val_graph::Vector;\n    using CppAD::local::val_graph::addr_t;\n    using CppAD::local::val_graph::op_enum_t;\n    //\n    // nan\n    double nan = std::numeric_limits<double>::quiet_NaN();\n    //\n    // tape\n    tape_t<double> tape;\n    addr_t n_ind = 1;\n    addr_t index_of_nan = tape.set_ind(n_ind);\n    ok &= index_of_nan == n_ind;\n    //\n    // op_arg\n    Vector<addr_t> op_arg(2);\n    //\n    // dep_vec\n    Vector<addr_t> dep_vec(1);\n    //\n    // tape\n    tape.record_con_op(5.0);               // not used\n    dep_vec[0] =  tape.record_con_op(nan); // nan\n    //\n    // set_dep\n    tape.set_dep( dep_vec );\n    //\n    ok &= tape.n_op()  == 2;\n    ok &= tape.con_vec().size() == 2;\n    ok &= tape.arg_vec().size() == 2;\n    //\n    bool trace = false;\n    //\n    // val_vec\n    Vector<double> val_vec( tape.n_val() );\n    for(addr_t i = 0; i < n_ind; ++i)\n        val_vec[i] = 0.0;\n    tape.eval(trace, val_vec);\n    //\n    // renumber\n    tape.renumber();\n    //\n    // dead_code\n    tape.dead_code();\n    //\n    ok &= tape.n_op()  == 1;\n    ok &= tape.con_vec().size() == 1;\n    ok &= tape.arg_vec().size() == 1;\n    //\n    // val_vec\n    val_vec.resize( tape.n_val() );\n    for(addr_t i = 0; i < n_ind; ++i)\n        val_vec[i] = 0.0;\n    tape.eval(trace, val_vec);\n    //\n    // y\n    Vector<double> y(1);\n    dep_vec = tape.dep_vec();\n    y[0] = val_vec[ dep_vec[0] ];\n    //\n    // ok\n    ok &= std::isnan( y[0] );\n    //\n    return ok;\n}\n// END_C++\n"
  },
  {
    "path": "val_graph/test/opt_call.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2023-23 Bradley M. Bell\n# include <cppad/local/val_graph/tape.hpp>\n# include \"../atomic_xam.hpp\"\n\nnamespace { // BEGIN_EMPTY_NAMESPACE\n// ---------------------------------------------------------------------------\n//\n// result_not_used\nbool result_not_used(void)\n{   bool ok = true;\n    //\n    // tape_t, Vector, addr_t, op_enum_t\n    using CppAD::local::val_graph::tape_t;\n    using CppAD::local::val_graph::Vector;\n    using CppAD::local::val_graph::addr_t;\n    using CppAD::local::val_graph::op_enum_t;\n    //\n    // add_op_enum;\n    op_enum_t add_op_enum = CppAD::local::val_graph::add_op_enum;\n    op_enum_t sub_op_enum = CppAD::local::val_graph::sub_op_enum;\n    //\n    // atomic_xam\n    val_atomic_xam atomic_xam;\n    //\n    // f\n    tape_t<double> tape;\n    addr_t n_ind = 2;\n    addr_t index_of_nan = tape.set_ind(n_ind);\n    ok &= index_of_nan == n_ind;\n    //\n    // n_dep\n    size_t n_dep = 1;\n    //\n    // fun_arg, op_arg\n    Vector<addr_t> fun_arg(4), op_arg(2);\n    //\n    // dep_vec\n    Vector<addr_t> dep_vec(n_dep);\n    //\n    // atomic_index\n    addr_t atomic_index  = addr_t( atomic_xam.atomic_index() );\n    //\n    // add = x[0] + x[1]\n    op_arg[0] = 0;\n    op_arg[1] = 1;\n    addr_t add = tape.record_op(add_op_enum, op_arg);\n    //\n    // sub = x[0] - x[1]\n    op_arg[0] = 0;\n    op_arg[1] = 1;\n    addr_t sub = tape.record_op(sub_op_enum, op_arg);\n    //\n    // g_0(x) = 3.0 + 3.0\n    // g_1(x) = (x[0] + x[1]) * (x[0] - x[1])\n    fun_arg[0] = tape.record_con_op(3.0);\n    fun_arg[1] = tape.record_con_op(3.0);\n    fun_arg[2] = add;\n    fun_arg[3] = sub;\n    addr_t call_id   = 0;\n    addr_t n_fun_res = 2;\n    addr_t res_index = tape.record_call_op(\n        atomic_index, call_id, n_fun_res, fun_arg\n    );\n    //\n    // dep_vec\n    // f(x) = g_1(x) =  (x[0] + x[1]) * (x[0] - x[1])\n    dep_vec[0] = res_index + 1;\n    //\n    // set_dep\n    tape.set_dep( dep_vec );\n    //\n    // x\n    Vector<double> x(n_ind);\n    for(addr_t i = 0; i < n_ind; ++i)\n        x[i] = 2.0 + double(n_ind - i);\n    //\n    // trace\n    bool trace = false;\n    //\n    // val_vec\n    Vector<double> val_vec( tape.n_val() );\n    for(addr_t i = 0; i < n_ind; ++i)\n        val_vec[i] = x[i];\n    tape.eval(trace, val_vec);\n    //\n    // ok\n    // before optimizing\n    ok &= tape.arg_vec().size() == 1 + 2 + 2 + 2 + 4 + 5;\n    ok &= tape.con_vec().size() == 3;\n    ok &= tape.n_op() == 6;\n    //\n    // renumber\n    tape.renumber();\n    val_vec.resize( tape.n_val() );\n    tape.eval(trace, val_vec);\n    //\n    // dead_code\n    tape.dead_code();\n    val_vec.resize( tape.n_val() );\n    tape.eval(trace, val_vec);\n    //\n    // ok\n    // after optimizing\n    ok &= tape.arg_vec().size() == 1 + 2 + 2 + 4 + 5;\n    ok &= tape.con_vec().size() == 1;\n    ok &= tape.n_op() == 4;\n    //\n    // y\n    Vector<double> y(n_dep);\n    dep_vec = tape.dep_vec();\n    for(size_t i = 0; i < n_dep; ++i)\n        y[i] = val_vec[ dep_vec[i] ];\n    //\n    // ok\n    ok &= y[0] == (x[0] + x[1]) * (x[0] - x[1]);\n    //\n    return ok;\n}\n// ---------------------------------------------------------------------------\n//\n// ident_zero\nbool ident_zero(void)\n{   bool ok = true;\n    //\n    // tape_t, Vector, addr_t, op_enum_t\n    using CppAD::local::val_graph::tape_t;\n    using CppAD::local::val_graph::Vector;\n    using CppAD::local::val_graph::addr_t;\n    using CppAD::local::val_graph::op_enum_t;\n    //\n    // add_op_enum;\n    op_enum_t add_op_enum = CppAD::local::val_graph::add_op_enum;\n    op_enum_t sub_op_enum = CppAD::local::val_graph::sub_op_enum;\n    //\n    // atomic_xam\n    val_atomic_xam atomic_xam;\n    //\n    // f\n    tape_t<double> tape;\n    addr_t n_ind = 2;\n    addr_t index_of_nan = tape.set_ind(n_ind);\n    ok &= index_of_nan == n_ind;\n    //\n    // n_dep\n    size_t n_dep = 2;\n    //\n    // fun_arg, op_arg\n    Vector<addr_t> fun_arg(4), op_arg(2);\n    //\n    // dep_vec\n    Vector<addr_t> dep_vec(n_dep);\n    //\n    // atomic_index\n    addr_t atomic_index = addr_t( atomic_xam.atomic_index() );\n    //\n    // add = x[0] + x[1]\n    op_arg[0] = 0;\n    op_arg[1] = 1;\n    addr_t add = tape.record_op(add_op_enum, op_arg);\n    //\n    // sub = x[0] - x[1]\n    op_arg[0] = 0;\n    op_arg[1] = 1;\n    addr_t sub = tape.record_op(sub_op_enum, op_arg);\n    //\n    // f_0(x) = (x[0] + x[1]) + 3.0\n    // f_1(x) = (x[0] - x[1]) * 0.0\n    fun_arg[0] = add;\n    fun_arg[1] = tape.record_con_op(3.0);\n    fun_arg[2] = sub;\n    fun_arg[3] = tape.record_con_op(0.0);\n    addr_t call_id   = 0;\n    addr_t n_fun_res = 2;\n    addr_t res_index = tape.record_call_op(\n        atomic_index, call_id, n_fun_res, fun_arg\n    );\n    //\n    // dep_vec\n    dep_vec[0] = res_index + 0;\n    dep_vec[1] = res_index + 1;\n    //\n    // set_dep\n    tape.set_dep( dep_vec );\n    //\n    // x\n    Vector<double> x(n_ind);\n    for(addr_t i = 0; i < n_ind; ++i)\n        x[i] = 2.0 + double(n_ind - i);\n    //\n    // trace\n    bool trace = false;\n    //\n    // val_vec\n    Vector<double> val_vec( tape.n_val() );\n    for(addr_t i = 0; i < n_ind; ++i)\n        val_vec[i] = x[i];\n    tape.eval(trace, val_vec);\n    //\n    // ok\n    // before optimizing\n    ok &= tape.arg_vec().size() == 1 + 2 + 2 + 2 + 4 + 5;\n    ok &= tape.con_vec().size() == 3;\n    ok &= tape.n_op() == 6;\n    //\n    // dead_code\n    tape.dead_code();\n    val_vec.resize( tape.n_val() );\n    tape.eval(trace, val_vec);\n    //\n    // ok\n    // after optimizing the subtract operator has been removd\n    ok &= tape.arg_vec().size() == 1 + 2 + 2 + 4 + 5;\n    ok &= tape.con_vec().size() == 3;\n    ok &= tape.n_op() == 5;\n    //\n    // y\n    Vector<double> y(n_dep);\n    dep_vec = tape.dep_vec();\n    for(size_t i = 0; i < n_dep; ++i)\n        y[i] = val_vec[ dep_vec[i] ];\n    //\n    // ok\n    ok &= y[0] == (x[0] + x[1]) + 3.0;\n    ok &= y[1] == 0.0;\n    //\n    return ok;\n}\n// ---------------------------------------------------------------------------\n} // END_EMPTY_NAMESPACE\n\n//\n// test_opt_call\nbool test_opt_call(void)\n{   bool ok = true;\n    ok     &= result_not_used();\n    ok     &= ident_zero();\n    return ok;\n}\n"
  },
  {
    "path": "val_graph/test/optimize.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2023-23 Bradley M. Bell\n# include <cppad/local/val_graph/tape.hpp>\n\nnamespace { // BEGIN_EMPTY_NAMESPACE\n// ---------------------------------------------------------------------------\n// communative\nbool communative(void)\n{   bool ok = true;\n    //\n    // tape_t, Vector, addr_t, op_enum_t\n    using CppAD::local::val_graph::tape_t;\n    using CppAD::local::val_graph::Vector;\n    using CppAD::local::val_graph::addr_t;\n    using CppAD::local::val_graph::op_enum_t;\n    //\n    // add_op_enum;\n    op_enum_t add_op_enum = CppAD::local::val_graph::add_op_enum;\n    op_enum_t mul_op_enum = CppAD::local::val_graph::mul_op_enum;\n    //\n    // f\n    tape_t<double> tape;\n    addr_t n_ind = 2;\n    addr_t index_of_nan = tape.set_ind(n_ind);\n    ok &= index_of_nan == n_ind;\n    //\n    // dep_vec\n    size_t n_dep = 4;\n    Vector<addr_t> dep_vec(n_dep);\n    //\n    // op_arg\n    Vector<addr_t> op_arg(2);\n    //\n    // y[0] = x[0] + x[1]\n    op_arg[0] = 0;\n    op_arg[1] = 1;\n    dep_vec[0] = tape.record_op(add_op_enum, op_arg);\n    //\n    // y[1] = x[1] + x[0]\n    op_arg[0] = 1;\n    op_arg[1] = 0;\n    dep_vec[1] = tape.record_op(add_op_enum, op_arg);\n    //\n    // y[2] = x[0] * x[1]\n    op_arg[0] = 0;\n    op_arg[1] = 1;\n    dep_vec[2] = tape.record_op(mul_op_enum, op_arg);\n    //\n    // y[3] = x[1] * x[0]\n    op_arg[0] = 1;\n    op_arg[1] = 0;\n    dep_vec[3] = tape.record_op(mul_op_enum, op_arg);\n    //\n    // set_dep\n    tape.set_dep( dep_vec );\n    //\n    // x\n    Vector<double> x(n_ind);\n    for(addr_t i = 0; i < n_ind; ++i)\n        x[i] = 2.0 + double(n_ind - i);\n    //\n    // trace\n    bool trace = false;\n    //\n    // val_vec\n    Vector<double> val_vec( tape.n_val() );\n    for(addr_t i = 0; i < n_ind; ++i)\n        val_vec[i] = x[i];\n    tape.eval(trace, val_vec);\n    //\n    // ok\n    // before optimizing\n    ok &= tape.arg_vec().size() == 1 + 4 * 2;\n    ok &= tape.con_vec().size() == 1;\n    ok &= tape.n_op() == 1 + 4;\n    //\n    // renumber\n    tape.renumber();\n    val_vec.resize( tape.n_val() );\n    tape.eval(trace, val_vec);\n    //\n    // dead_code\n    tape.dead_code();\n    val_vec.resize( tape.n_val() );\n    tape.eval(trace, val_vec);\n    //\n    // ok\n    // after optimizing\n    ok &= tape.arg_vec().size() == 1 + 2 * 2;\n    ok &= tape.con_vec().size() == 1;\n    ok &= tape.n_op() == 1 + 2;\n    //\n    // y\n    Vector<double> y(n_dep);\n    dep_vec = tape.dep_vec();\n    for(size_t i = 0; i < n_dep; ++i)\n        y[i] = val_vec[ dep_vec[i] ];\n    //\n    // ok\n    ok &= y[0] == x[0] + x[1];\n    ok &= y[1] == y[0];\n    ok &= y[2] == x[0] * x[1];\n    ok &= y[3] == y[2];\n    //\n    return ok;\n}\n// ---------------------------------------------------------------------------\n// propagate_match\nbool propagate_match(void)\n{   bool ok = true;\n    //\n    // tape_t, Vector, addr_t, op_enum_t\n    using CppAD::local::val_graph::tape_t;\n    using CppAD::local::val_graph::Vector;\n    using CppAD::local::val_graph::addr_t;\n    using CppAD::local::val_graph::op_enum_t;\n    //\n    // add_op_enum;\n    op_enum_t add_op_enum = CppAD::local::val_graph::add_op_enum;\n    op_enum_t mul_op_enum = CppAD::local::val_graph::mul_op_enum;\n    //\n    // f\n    tape_t<double> tape;\n    addr_t n_ind = 2;\n    addr_t index_of_nan = tape.set_ind(n_ind);\n    ok &= index_of_nan == n_ind;\n    //\n    // dep_vec\n    size_t n_dep = 2;\n    Vector<addr_t> dep_vec(n_dep);\n    //\n    // op_arg\n    Vector<addr_t> op_arg(2);\n    //\n    // five\n    addr_t five = tape.record_con_op(5.0);\n    //\n    // add_1: x[0] + x[1]\n    op_arg[0] = 0;\n    op_arg[1] = 1;\n    addr_t add_1 = tape.record_op(add_op_enum, op_arg);\n    //\n    // add_2: x[1] + x[0]\n    op_arg[0] = 1;\n    op_arg[1] = 0;\n    addr_t add_2 = tape.record_op(add_op_enum, op_arg);\n    //\n    // y[0] = 5 * (x[0] * x[1])\n    op_arg[0] = five;\n    op_arg[1] = add_1;\n    dep_vec[0] = tape.record_op(mul_op_enum, op_arg);\n    //\n    // y[1] = 5 * (x[1] * x[0])\n    op_arg[0] = five;\n    op_arg[1] = add_2;\n    dep_vec[1] = tape.record_op(mul_op_enum, op_arg);\n    //\n    // set_dep\n    tape.set_dep( dep_vec );\n    //\n    // x\n    Vector<double> x(n_ind);\n    for(addr_t i = 0; i < n_ind; ++i)\n        x[i] = 2.0 + double(n_ind - i);\n    //\n    // trace\n    bool trace = false;\n    //\n    // val_vec\n    Vector<double> val_vec( tape.n_val() );\n    for(addr_t i = 0; i < n_ind; ++i)\n        val_vec[i] = x[i];\n    tape.eval(trace, val_vec);\n    //\n    // ok\n    // before optimizing\n    ok &= tape.con_vec().size() == 2;\n    ok &= tape.n_op()           == 2 + 4;\n    ok &= tape.arg_vec().size() == 2 + 4 * 2;\n    //\n    // renumber\n    tape.renumber();\n    val_vec.resize( tape.n_val() );\n    tape.eval(trace, val_vec);\n    //\n    // dead_code\n    tape.dead_code();\n    val_vec.resize( tape.n_val() );\n    tape.eval(trace, val_vec);\n    //\n    // ok\n    // after optimizing\n    ok &= tape.con_vec().size() == 2;\n    ok &= tape.n_op()           == 2 + 2;\n    ok &= tape.arg_vec().size() == 2 + 2 * 2;\n    //\n    // y\n    Vector<double> y(n_dep);\n    dep_vec = tape.dep_vec();\n    for(size_t i = 0; i < n_dep; ++i)\n        y[i] = val_vec[ dep_vec[i] ];\n    //\n    // ok\n    ok &= y[0] == 5.0 * (x[0] + x[1]);\n    ok &= y[1] == y[0];\n    //\n    return ok;\n}\n// ---------------------------------------------------------------------------\nbool not_used(void)\n{   bool ok = true;\n    //\n    // tape_t, Vector, addr_t, add_op_enum, sub_op_enum\n    using CppAD::local::val_graph::tape_t;\n    using CppAD::local::val_graph::Vector;\n    using CppAD::local::val_graph::addr_t;\n    using CppAD::local::val_graph::op_enum_t;\n    op_enum_t add_op_enum = CppAD::local::val_graph::add_op_enum;\n    op_enum_t sub_op_enum = CppAD::local::val_graph::sub_op_enum;\n    //\n    // tape\n    tape_t<double> tape;\n    addr_t n_ind = 2;\n    addr_t index_of_nan = tape.set_ind(n_ind);\n    ok &= index_of_nan == n_ind;\n    //\n    // op_arg\n    Vector<addr_t> op_arg(2);\n    op_arg[0] = 0; // x[0]\n    op_arg[1] = 1; // x[1]\n    //\n    // dep_vec\n    Vector<addr_t> dep_vec(2);\n    //\n    // tape\n    tape.record_op(add_op_enum, op_arg); // x[0] + x[1] (no used)\n    tape.record_con_op(5.0);             // 5.0 (not used)\n    //\n    dep_vec[0]      = tape.record_op(add_op_enum, op_arg); // x[0] + x[1]\n    op_arg[0]       = dep_vec[0];                          // x[0] + x[1]\n    op_arg[1]       = tape.record_con_op(4.0);             // 4.0\n    addr_t temp_1   = tape.record_op(sub_op_enum, op_arg); // x[0] + x[1] - 4.0\n    op_arg[0]       = temp_1;\n    op_arg[1]       = tape.record_con_op(4.0);             // duplicate\n    dep_vec[1]      = tape.record_op(sub_op_enum, op_arg); // x[0] + x[1] - 8.0\n    //\n    // set_dep\n    tape.set_dep( dep_vec );\n    //\n    // x\n    Vector<double> x(2);\n    x[0] = 5.0;\n    x[1] = 6.0;\n    //\n    // trace\n    bool trace = false;\n    //\n    // val_vec\n    Vector<double> val_vec;\n    //\n    // val_vec, ok\n    // before optimizing\n    val_vec.resize( tape.n_val() );\n    for(addr_t i = 0; i < n_ind; ++i)\n        val_vec[i] = x[i];\n    tape.eval(trace, val_vec);\n    ok &= tape.arg_vec().size() == 12;\n    ok &= tape.con_vec().size() == 4;\n    ok &= tape.n_op() == 8;\n    //\n    // renumber, val_vec\n    tape.renumber();\n    val_vec.resize( tape.n_val() );\n    tape.eval(trace, val_vec);\n    //\n    // dead_code, val_vec\n    tape.dead_code();\n    val_vec.resize( tape.n_val() );\n    tape.eval(trace, val_vec);\n    //\n    // ok\n    // after optimizing\n    ok &= tape.arg_vec().size() == 8;\n    ok &= tape.con_vec().size() == 2;\n    ok &= tape.n_op() == 5;\n    //\n    // dep_vec\n    dep_vec = tape.dep_vec();\n    //\n    // y\n    Vector<double> y(2);\n    for(size_t i = 0; i < 2; ++i)\n        y[i] = val_vec[ dep_vec[i] ];\n    //\n    // ok\n    ok &= y[0] == x[0] + x[1];\n    ok &= y[1] == x[0] + x[1] - 8.0;\n    //\n    return ok;\n}\n// ---------------------------------------------------------------------------\n// summation\nbool summation(void)\n{   bool ok = true;\n    //\n    // tape_t, Vector, addr_t, csum_op_enum;\n    using CppAD::local::val_graph::tape_t;\n    using CppAD::local::val_graph::Vector;\n    using CppAD::local::val_graph::addr_t;\n    using CppAD::local::val_graph::op_enum_t;\n    op_enum_t add_op_enum = CppAD::local::val_graph::add_op_enum;\n    op_enum_t sub_op_enum = CppAD::local::val_graph::sub_op_enum;\n    op_enum_t mul_op_enum = CppAD::local::val_graph::mul_op_enum;\n    //\n    // tape, ok\n    tape_t<double> tape;\n    addr_t n_ind = 4;\n    addr_t index_of_nan = tape.set_ind(n_ind);\n    ok &= index_of_nan == n_ind;\n    Vector<addr_t> op_arg(2);\n    //\n    // op_arg, add = x[0] + x[0]\n    // This operator will become part of a cumulative summation\n    op_arg[0] = 0;   // x[0]\n    op_arg[1] = 0;   // x[0]\n    addr_t add = tape.record_op(add_op_enum, op_arg);\n    //\n    // op_arg, mul = x[2] * x[3]\n    // This operator cannot become part of a cumulative summation\n    op_arg[0] = 2;   // x[2]\n    op_arg[1] = 3;   // x[3]\n    addr_t mul = tape.record_op(mul_op_enum, op_arg);\n    //\n    // op_arg, sub = x[2] * x[3] - x[0] - x[0]\n    // Test case where second arg gets replaced\n    op_arg[0] = mul;\n    op_arg[1] = add;\n    addr_t sub = tape.record_op(sub_op_enum, op_arg);\n    //\n    // op_arg, add = 2 * ( x[2] * x[3] - x[0] - x[0] )\n    op_arg[0] = sub;\n    op_arg[1] = sub;\n    add = tape.record_op(add_op_enum, op_arg);\n    //\n    // dep_vec, tape\n    Vector<addr_t> dep_vec(1);\n    dep_vec[0] = add; // 2 * ( x[2] * x[3] - x[0] - x[0] )\n    //\n    // set_dep\n    tape.set_dep( dep_vec );\n    //\n    // x\n    Vector<double> x(n_ind);\n    for(addr_t i = 0; i < n_ind; ++i)\n        x[i] = double(2 + i);\n    //\n    // trace\n    bool trace = false;\n    //\n    // val_vec\n    Vector<double> val_vec( tape.n_val() );\n    for(addr_t i = 0; i < n_ind; ++i)\n        val_vec[i] = x[i];\n    tape.eval(trace, val_vec);\n    //\n    // ok\n    ok &= tape.n_op()  == 5;\n    ok &= tape.con_vec().size() == 1;\n    ok &= tape.arg_vec().size() == 1 + 4 * 2;\n    ok &= tape.n_val()          == n_ind + 1 + 4;\n    //\n    // summation, dead_code\n    tape.summation();\n    tape.dead_code();\n    //\n    // ok\n    ok &= tape.n_op()  == 3;\n    ok &= tape.con_vec().size() == 1;\n    ok &= tape.arg_vec().size() == 1 + 2 + (6 + 3);\n    ok &= tape.n_val()          == n_ind + 3;\n    //\n    // eval\n    val_vec.resize( tape.n_val() );\n    tape.eval(trace, val_vec);\n    //\n    // y\n    Vector<double> y(1);\n    dep_vec = tape.dep_vec();\n    y[0]    = val_vec[ dep_vec[0] ];\n    //\n    // ok\n    ok &= y[0] == 2.0 * ( x[2] * x[3] - x[0] - x[0] );\n    //\n    return ok;\n}\nbool dynamic_vector(void)\n{   bool ok = true;\n    //\n    // tape_t, Vector, addr_t, compare_lt_enum\n    using CppAD::local::val_graph::tape_t;\n    using CppAD::local::val_graph::Vector;\n    using CppAD::local::val_graph::addr_t;\n    //\n    // tape, ok\n    tape_t<double> tape;\n    addr_t n_ind = 2;\n    addr_t index_of_nan = tape.set_ind(n_ind);\n    ok &= index_of_nan == n_ind;\n    //\n    // x0, x1, x2\n    addr_t x0 = 0;   // x[0]\n    addr_t x1 = 1;   // x[1]\n    //\n    // zero, one, two\n    addr_t zero = tape.record_con_op(0.0);\n    addr_t one  = tape.record_con_op(1.0);\n    //\n    // tape\n    // first_vector[0]  = x[0],  first_vector[1]  = 0\n    Vector<addr_t> first_initial = {x0, zero};\n    tape.record_vec_op(first_initial);\n    //\n    // tape, second_vector\n    // second_vector[0] = 1,     second_vector[1] = x[1]\n    Vector<addr_t> second_initial = {one, x1};\n    addr_t         second_vector  = tape.record_vec_op(second_initial);\n    //\n    // dep_vec, tape\n    Vector<addr_t> dep_vec(2);\n    dep_vec[0] = tape.record_load_op(second_vector, zero);   // 1\n    dep_vec[1] = tape.record_load_op(second_vector, one);    // x[1]\n    //\n    // set_dep\n    tape.set_dep( dep_vec );\n    //\n    // x\n    Vector<double> x(n_ind);\n    x[0] = 3.0;\n    x[1] = 4.0;\n    //\n    // trace\n    bool trace = false;\n    //\n    // val_vec\n    Vector<double> val_vec( tape.n_val() );\n    for(addr_t i = 0; i < n_ind; ++i)\n        val_vec[i] = x[i];\n    tape.eval(trace, val_vec);\n    //\n    // ok\n    ok &= tape.n_op()            == 7;\n    ok &= tape.con_vec().size()  == 3;\n    ok &= tape.arg_vec().size()  == 3 + 2 + 2 * 2;\n    ok &= tape.n_val()           == n_ind + 3 + 2;\n    ok &= tape.vec_initial().size() == 2;\n    //\n    // y\n    Vector<double> y(2);\n    for(size_t i = 0; i < 2; ++i)\n        y[i] = val_vec[ dep_vec[i] ];\n    //\n    // ok\n    ok &= y[0] == 1.0;\n    ok &= y[1] == x[1];\n    //\n    // dead_code\n    tape.dead_code();\n    //\n    // val_vec\n    val_vec.resize( tape.n_val() );\n    for(addr_t i = 0; i < n_ind; ++i)\n        val_vec[i] = x[i];\n    tape.eval(trace, val_vec);\n    //\n    // ok\n    ok &= tape.n_op()           == 6;\n    ok &= tape.con_vec().size() == 3;\n    ok &= tape.arg_vec().size() == 3 + 1 + 2 * 2;\n    ok &= tape.n_val()          == n_ind + 3 + 2;\n    ok &= tape.vec_initial().size() == 1;\n    //\n    // y\n    dep_vec = tape.dep_vec();\n    for(size_t i = 0; i < 2; ++i)\n        y[i] = val_vec[ dep_vec[i] ];\n    //\n    // ok\n    ok &= y[0] == 1.0;\n    ok &= y[1] == x[1];\n    //\n    return ok;\n}\n// END_C++\n// ---------------------------------------------------------------------------\n} // END_EMPTY_NAMESPACE\n\n//\n// test_opt_call\nbool test_optimize(void)\n{   bool ok = true;\n    ok     &= communative();\n    ok     &= propagate_match();\n    ok     &= not_used();\n    ok     &= summation();\n    ok     &= dynamic_vector();\n    return ok;\n}\n"
  },
  {
    "path": "val_graph/test/val2fun.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2023-23 Bradley M. Bell\n# include <cppad/cppad.hpp>\n# include <cppad/local/val_graph/tape.hpp>\n# include <cppad/local/val_graph/val2fun.hpp>\n# include \"../atomic_xam.hpp\"\n\nnamespace { // BEGIN_EMPTY_NAMESPACE\n// ----------------------------------------------------------------------------\nbool dynamic_atom(void)\n{   bool ok = true;\n    //\n    // tape_t, Vector, addr_t, add_op_enum;\n    using CppAD::local::val_graph::tape_t;\n    using CppAD::local::val_graph::Vector;\n    using CppAD::local::val_graph::addr_t;\n    using CppAD::local::val_graph::op_enum_t;\n    op_enum_t add_op_enum = CppAD::local::val_graph::add_op_enum;\n    op_enum_t sub_op_enum = CppAD::local::val_graph::sub_op_enum;\n    //\n    // atomic_xam\n    val_atomic_xam atomic_xam;\n    //\n    // tape, ok\n    tape_t<double> tape;\n    addr_t n_ind = 5;\n    addr_t index_of_nan = tape.set_ind(n_ind);\n    ok &= index_of_nan == n_ind;\n    //\n    // op_arg\n    Vector<addr_t> call_arg(4), op_arg(2);\n    //\n    // dep_vec\n    Vector<addr_t> dep_vec(2);\n    //\n    // atomic_index\n    addr_t atomic_index = addr_t( atomic_xam.atomic_index() );\n    //\n    // g_0(x) = p[0] + p[1]\n    // g_1(x) = p[2] * p[3]\n    for(addr_t i = 0; i < 4; ++i)\n        call_arg[i] = i;\n    addr_t call_id    = 0;\n    addr_t n_call_res = 2;\n    addr_t res_index = tape.record_call_op(\n        atomic_index, call_id, n_call_res, call_arg\n    );\n    //\n    // dep_vec[0] = x[0] + p[0] + p[1]\n    op_arg[0]  = 4;          // x[0]\n    op_arg[1]  = res_index;  // p[0] - p[1]\n    dep_vec[0] = tape.record_op(add_op_enum, op_arg);\n    //\n    // dep_vec[1] = x[0] - p[2] * p[3]\n    op_arg[0]  = 4;              // x[1]\n    op_arg[1]  = res_index + 1;  // p[2] * p[3]\n    dep_vec[1] = tape.record_op(sub_op_enum, op_arg);\n    //\n    // set_dep\n    tape.set_dep( dep_vec );\n    /*\n    // trace\n    bool trace = true;\n    Vector<double> val_vec( tape.n_val() );\n    for(addr_t i = 0; i < n_ind; ++i)\n        val_vec[i] = double(5 + i);\n    tape.eval(trace, val_vec);\n    */\n    //\n    // ADFun\n    Vector<size_t> dyn_ind(4), var_ind(1);\n    for(size_t i = 0; i < 4; i++)\n        dyn_ind[i] = i;\n    var_ind[0] = 4;\n    CppAD::ADFun<double> f;\n    f.val2fun( tape, dyn_ind, var_ind );\n    //\n\n    // p, x\n    Vector<double> p(4), x(1), y(2);\n    for(addr_t i = 0; i < 4; i++)\n        p[i] = double(i + 5);\n    x[0] = 9.0;\n    //\n    // f, y\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    //\n    ok &= y[0] == x[0] + (p[0] + p[1]);\n    ok &= y[1] == x[0] - (p[2] * p[3]);\n    //\n    return ok;\n}\n// ----------------------------------------------------------------------------\nbool variable_atom(void)\n{   bool ok = true;\n    //\n    // tape_t, Vector, addr_t, add_op_enum;\n    using CppAD::local::val_graph::tape_t;\n    using CppAD::local::val_graph::Vector;\n    using CppAD::local::val_graph::addr_t;\n    using CppAD::local::val_graph::op_enum_t;\n    op_enum_t add_op_enum = CppAD::local::val_graph::add_op_enum;\n    op_enum_t sub_op_enum = CppAD::local::val_graph::sub_op_enum;\n    //\n    // atomic_xam\n    val_atomic_xam atomic_xam;\n    //\n    // tape, ok\n    tape_t<double> tape;\n    addr_t n_ind = 5;\n    addr_t index_of_nan = tape.set_ind(n_ind);\n    ok &= index_of_nan == n_ind;\n    //\n    // op_arg\n    Vector<addr_t> call_arg(4), op_arg(2);\n    //\n    // dep_vec\n    Vector<addr_t> dep_vec(2);\n    //\n    // atomic_index\n    addr_t atomic_index = addr_t (atomic_xam.atomic_index() );\n    //\n    // g_0(x) = x[0] + x[1]\n    // g_1(x) = x[2] * x[3]\n    for(addr_t i = 0; i < 4; ++i)\n        call_arg[i] = i;\n    addr_t call_id    = 0;\n    addr_t n_call_res = 2;\n    addr_t res_index = tape.record_call_op(\n        atomic_index, call_id, n_call_res, call_arg\n    );\n    //\n    // dep_vec[0] = p[0] + x[0] + x[1]\n    op_arg[0]  = 4;          // p[0]\n    op_arg[1]  = res_index;  // x[0] - x[1]\n    dep_vec[0] = tape.record_op(add_op_enum, op_arg);\n    //\n    // dep_vec[1] = p[0] - x[2] * x[3]\n    op_arg[0]  = 4;              // p[1]\n    op_arg[1]  = res_index + 1;  // x[2] * x[3]\n    dep_vec[1] = tape.record_op(sub_op_enum, op_arg);\n    //\n    // set_dep\n    tape.set_dep( dep_vec );\n    //\n    // trace\n    bool trace = false;\n    Vector<double> val_vec( tape.n_val() );\n    for(addr_t i = 0; i < n_ind; ++i)\n        val_vec[i] = double(5 + i);\n    tape.eval(trace, val_vec);\n    //\n    // ADFun\n    Vector<size_t> var_ind(4), dyn_ind(1);\n    for(size_t i = 0; i < 4; i++)\n        var_ind[i] = i;\n    dyn_ind[0] = 4;\n    CppAD::ADFun<double> f;\n    f.val2fun( tape, dyn_ind , var_ind);\n    //\n    // p, x\n    Vector<double> x(4), p(1), y(2);\n    for(addr_t i = 0; i < 4; i++)\n        x[i] = double(i + 5);\n    p[0] = 9.0;\n    //\n    // f, y\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    //\n    ok &= y[0] == p[0] + (x[0] + x[1]);\n    ok &= y[1] == p[0] - (x[2] * x[3]);\n    //\n    return ok;\n}\n// ----------------------------------------------------------------------------\nbool comp_op(void)\n{   bool ok = true;\n    //\n    // tape_t, Vector, addr_t, sub_op_enum;\n    using CppAD::local::val_graph::tape_t;\n    using CppAD::local::val_graph::Vector;\n    using CppAD::local::val_graph::addr_t;\n    using CppAD::local::val_graph::op_enum_t;\n    using CppAD::local::val_graph::compare_enum_t;\n    op_enum_t sub_op_enum = CppAD::local::val_graph::sub_op_enum;\n    compare_enum_t compare_lt_enum = CppAD::local::val_graph::compare_lt_enum;\n    //\n    // tape, ok\n    tape_t<double> tape;\n    addr_t n_ind = 2;\n    addr_t index_of_nan = tape.set_ind(n_ind);\n    ok &= index_of_nan == n_ind;\n    //\n    // dep_vec\n    Vector<addr_t> dep_vec(1);\n    //\n    // op_arg\n    Vector<addr_t> op_arg(2);\n    op_arg[0] = 0; // x[0]\n    op_arg[1] = 1; // x[1]\n    //\n    // tape\n    // put two identical compare operators in the tape\n    addr_t left_index  = 0; // x[0]\n    addr_t right_index = 1; // x[1]\n    addr_t res_index = tape.record_comp_op(\n        compare_lt_enum, left_index, right_index // x[0] < x[1]\n    );\n    ok &= res_index == 0; // no result for this operator\n    //\n    // tape, dep_vec\n    dep_vec[0] = tape.record_op(sub_op_enum, op_arg); // x[0] - x[1]\n    //\n    // set_dep\n    tape.set_dep( dep_vec );\n    //\n    // trace\n    bool trace = false;\n    Vector<double> val_vec( tape.n_val() );\n    val_vec[0] = 5.0; // x[0]\n    val_vec[1] = 6.0; // x[1]\n    tape.eval(trace, val_vec);\n    //\n    // f\n    // switch x[0] and x[1] so y[0] = x[1] - x[0] and compare is x[1] < x[0]\n    Vector<size_t> var_ind(2), dyn_ind(0);\n    var_ind[0] = 1;\n    var_ind[1] = 0;\n    CppAD::ADFun<double> f;\n    f.val2fun(tape, dyn_ind, var_ind);\n    //\n    // f, x, y\n    Vector<double> x(2), y;\n    x[0] = 5.0;\n    x[1] = 6.0;\n    y = f.Forward(0, x);\n    //\n    // ok\n    ok &= f.compare_change_number() == 1;\n    ok &= y[0] == x[1] - x[0];\n    //\n    return ok;\n}\n// ----------------------------------------------------------------------------\n// dis_op\ndouble floor(const double& arg)\n{   return std::floor(arg); }\n//\nCPPAD_DISCRETE_FUNCTION(double, floor);\nbool dis_op(void)\n{   bool ok = true;\n    //\n    // AD, addr_t\n    using CppAD::AD;\n    using CppAD::addr_t;\n    //\n    // tape_t, Vector\n    using CppAD::local::val_graph::tape_t;\n    using CppAD::local::val_graph::Vector;\n    //\n    // tape\n    tape_t<double> tape;\n    //\n    // ap, ax\n    Vector<double> p(1), x(1);\n    p[0] = 2.3;\n    x[0] = 3.4;\n    //\n    // tape, ok\n    addr_t n_ind = 2;\n    addr_t index_of_nan = tape.set_ind(n_ind);\n    ok &= index_of_nan == n_ind;\n    //\n    // dep_vec\n    Vector<addr_t> dep_vec(2);\n    //\n    // tape, dep_vec\n    addr_t discrete_index, val_index;\n    discrete_index = addr_t( CppAD::discrete<double>::index(\"floor\") );\n    val_index  = 0; // p[0]\n    dep_vec[0] = tape.record_dis_op(discrete_index, val_index); // floor( p[0] )\n    val_index  = 1; // x[0]\n    dep_vec[1] = tape.record_dis_op(discrete_index, val_index); // floor( x[0] )\n    //\n    // tape\n    tape.set_dep(dep_vec);\n    //\n    // trace\n    bool trace = false;\n    //\n    // val_vec\n    Vector<double> val_vec( tape.n_val() );\n    val_vec[0] = p[0];\n    val_vec[1] = x[0];\n    tape.eval(trace, val_vec);\n    //\n    // f\n    Vector<size_t> var_ind(1), dyn_ind(1);\n    dyn_ind[0] = 0;\n    var_ind[0] = 1;\n    CppAD::ADFun<double> f;\n    f.val2fun( tape, dyn_ind , var_ind);\n    //\n    // ok\n    p[0] =   5.5;\n    x[0] = - 5.5;\n    f.new_dynamic(p);\n    Vector<double> y = f.Forward(0, x);\n    ok &= y[0] == std::floor( p[0] );\n    ok &= y[1] == std::floor( x[0] );\n    //\n    return ok;\n}\n// ----------------------------------------------------------------------------\n// csum_op\nbool csum_op(void)\n{   bool ok = true;\n    //\n    // tape_t, Vector, addr_t\n    using CppAD::local::val_graph::tape_t;\n    using CppAD::local::val_graph::Vector;\n    using CppAD::local::val_graph::addr_t;\n    //\n    // tape, ok\n    tape_t<double> tape;\n    addr_t n_ind = 4;\n    addr_t index_of_nan = tape.set_ind(n_ind);\n    ok &= index_of_nan == n_ind;\n    //\n    // c[0], c[1]\n    Vector<double> c(2);\n    c[0] = -2.0;\n    c[1] = -3.0;\n    addr_t c0 = tape.record_con_op( c[0] );\n    addr_t c1 = tape.record_con_op( c[1] );\n    //\n    // add, sub\n    Vector<addr_t> add(3), sub(3);\n    add[0] = 0;  // x[0]\n    add[1] = 2;  // p[0]\n    add[2] = c0; // c[0]\n    //\n    sub[0] = 1;   // x[1]\n    sub[1] = 3;   // p[1]\n    sub[2] = c1;  // c[1]\n    //\n    // tape, dep_vec\n    Vector<addr_t> dep_vec(1);\n    dep_vec[0] = tape.record_csum_op(add, sub);\n    tape.set_dep( dep_vec );\n    //\n    // trace\n    bool trace = false;\n    //\n    // val_vec, ok\n    Vector<double> x(2), p(2), val_vec( tape.n_val() );\n    val_vec[0] = x[0] = 2.0;\n    val_vec[1] = x[1] = 3.0;\n    val_vec[2] = p[0] = 5.0;\n    val_vec[3] = p[1] = 8.0;\n    tape.eval(trace, val_vec);\n    //\n    // y, ok\n    Vector<double> y(1);\n    y[0] = val_vec[ dep_vec[0] ];\n    ok &= y[0] == x[0] - x[1] + p[0] - p[1]  + c[0] - c[1];\n    //\n    // f\n    Vector<size_t> var_ind(2), dyn_ind(2);\n    var_ind[0] = 0; // x[0]\n    var_ind[1] = 1; // x[1]\n    dyn_ind[0] = 2; // p[0]\n    dyn_ind[1] = 3; // p[1]\n    CppAD::ADFun<double> f;\n    f.val2fun(tape, dyn_ind, var_ind);\n    //\n    // f, y\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    //\n    // ok\n    ok &= f.compare_change_number() == 0;\n    ok &= y[0] == x[0] - x[1] + p[0] - p[1]  + c[0] - c[1];\n    //\n    return ok;\n}\n// ----------------------------------------------------------------------------\n// cexp_op\nbool cexp_op(void)\n{   bool ok = true;\n    //\n    // tape_t, Vector, addr_t\n    using CppAD::local::val_graph::tape_t;\n    using CppAD::local::val_graph::Vector;\n    using CppAD::local::val_graph::addr_t;\n    //\n    // compare_lt_enum\n    CppAD::local::val_graph::compare_enum_t compare_lt_enum =\n        CppAD::local::val_graph::compare_lt_enum;\n    //\n    // tape, ok\n    tape_t<double> tape;\n    addr_t n_ind = 4;\n    addr_t index_of_nan = tape.set_ind(n_ind);\n    ok &= index_of_nan == n_ind;\n    //\n    // dep_vec\n    Vector<addr_t> dep_vec(2);\n    //\n    // c[0], c[1]\n    Vector<double> c(2);\n    c[0] = -2.0;\n    c[1] = -3.0;\n    addr_t c0 = tape.record_con_op( c[0] );\n    addr_t c1 = tape.record_con_op( c[1] );\n    //\n    // left, right, if_true, if_false\n    addr_t left     = 0; // p[0]\n    addr_t right    = 1; // p[1]\n    addr_t if_true  = 2; // x[0]\n    addr_t if_false = 3; // x[1]\n    //\n    // tape, dep_vec\n    dep_vec[0] = tape.record_cexp_op(\n        compare_lt_enum, left, right, if_true, if_false\n    );\n    //\n    // left, right, if_true, if_false\n    left     = c0; // c[0]\n    right    = c1; // c[1]\n    if_true  = 0;  // p[0]\n    if_false = 1;  // p[1]\n    //\n    // tape, dep_vec\n    dep_vec[1] = tape.record_cexp_op(\n        compare_lt_enum, left, right, if_true, if_false\n    );\n    tape.set_dep( dep_vec );\n    //\n    // trace\n    bool trace = false;\n    //\n    // val_vec, ok\n    Vector<double> x(2), p(2), val_vec( tape.n_val() );\n    val_vec[0] = p[0] = 2.0;\n    val_vec[1] = p[1] = 3.0;\n    val_vec[2] = x[0] = 5.0;\n    val_vec[3] = x[1] = 8.0;\n    tape.eval(trace, val_vec);\n    //\n    // y\n    Vector<double> y(2);\n    y[0] = val_vec[ dep_vec[0] ];\n    y[1] = val_vec[ dep_vec[1] ];\n    //\n    // ok\n    if( p[0] < p[1] )\n        ok &= y[0] == x[0];\n    else\n        ok &= y[0] == x[1];\n    if( c[0] < c[1] )\n        ok &= y[1] == p[0];\n    else\n        ok &= y[1] == p[1];\n    //\n    // f\n    Vector<size_t> var_ind(2), dyn_ind(2);\n    dyn_ind[0] = 0; // p[0]\n    dyn_ind[1] = 1; // p[1]\n    var_ind[0] = 2; // x[0]\n    var_ind[1] = 3; // x[1]\n    CppAD::ADFun<double> f;\n    f.val2fun(tape, dyn_ind, var_ind);\n    //\n    // f, y, ok\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    ok &= f.compare_change_number() == 0;\n    //\n    // ok\n    if( p[0] < p[1] )\n        ok &= y[0] == x[0];\n    else\n        ok &= y[0] == x[1];\n    if( c[0] < c[1] )\n        ok &= y[1] == p[0];\n    else\n        ok &= y[1] == p[1];\n    //\n    return ok;\n}\n// ----------------------------------------------------------------------------\nbool pri_op(void)\n{   bool ok = true;\n    //\n    // tape_t, Vector, addr_t, sub_op_enum;\n    using CppAD::local::val_graph::tape_t;\n    using CppAD::local::val_graph::Vector;\n    using CppAD::local::val_graph::addr_t;\n    using CppAD::local::val_graph::op_enum_t;\n    using CppAD::local::val_graph::compare_enum_t;\n    op_enum_t sub_op_enum = CppAD::local::val_graph::sub_op_enum;\n    //\n    // tape, ok\n    tape_t<double> tape;\n    addr_t n_ind = 2;\n    addr_t index_of_nan = tape.set_ind(n_ind);\n    ok &= index_of_nan == n_ind;\n    //\n    // op_arg\n    Vector<addr_t> op_arg(2);\n    op_arg[0] = 0; // x[0]\n    op_arg[1] = 1; // x[1]\n    //\n    // tape, diff_addr\n    addr_t diff_addr = tape.record_op(sub_op_enum, op_arg); // x[0] - x[1]\n    //\n    // tape\n    std::string before = \"0 >= x[0] - x[1] = \";\n    std::string after  = \"\\n\";\n    tape.record_pri_op(before, after, diff_addr, diff_addr);\n    //\n    // dep_vec\n    Vector<addr_t> dep_vec(1);\n    dep_vec[0] = diff_addr;\n    //\n    // set_dep\n    tape.set_dep( dep_vec );\n    //\n    // trace\n    bool trace = false;\n    Vector<double> val_vec( tape.n_val() );\n    val_vec[0] = 6.0; // x[0]\n    val_vec[1] = 5.0; // x[1]\n    tape.eval(trace, val_vec);\n    //\n    // f\n    Vector<size_t> var_ind(2), dyn_ind(0);\n    var_ind[0] = 0;\n    var_ind[1] = 1;\n    CppAD::ADFun<double> f;\n    f.val2fun(tape, dyn_ind, var_ind);\n    //\n    // f, x, y\n    Vector<double> x(2), y;\n    x[0] = 5.0;\n    x[1] = 6.0;\n    //\n    std::cout << \"\\nNext line should be '\" + before << x[0] - x[1];\n    std::cout << \"', line after should be 'OK'\\n\";\n    y = f.Forward(0, x);\n    //\n    // ok\n    ok &= y[0] == x[0] - x[1];\n    //\n    return ok;\n}\n// ---------------------------------------------------------------------------\nbool vector_op(void)\n{   bool ok = true;\n    //\n    // tape_t, Vector, addr_t, compare_lt_enum\n    using CppAD::local::val_graph::tape_t;\n    using CppAD::local::val_graph::Vector;\n    using CppAD::local::val_graph::addr_t;\n    using CppAD::local::val_graph::op_enum_t;\n    op_enum_t sub_op_enum = CppAD::local::val_graph::sub_op_enum;\n    //\n    // tape, ok\n    tape_t<double> tape;\n    addr_t n_ind = 3;\n    addr_t index_of_nan = tape.set_ind(n_ind);\n    ok &= index_of_nan == n_ind;\n    //\n    // x0, x1, x2\n    addr_t x0 = 0;   // x[0] must be zero or one\n    addr_t x1 = 1;   // x[1]\n    addr_t x2 = 2;   // x[2]\n    //\n    // zero, one, four\n    addr_t zero  = tape.record_con_op(0.0);\n    addr_t one   = tape.record_con_op(1.0);\n    addr_t four  = tape.record_con_op(4.0);\n    //\n    // which_vector\n    // vec[0] = 4, vec[1] = 1\n    Vector<addr_t> initial = {four, one};\n    addr_t which_vector = tape.record_vec_op(initial);\n    //\n    // dep_vec, tape\n    Vector<addr_t> dep_vec(3);\n    dep_vec[0] = tape.record_load_op(which_vector, x0); // y[0] = x[initial[x[0]]\n    //\n    // one_minus_x0\n    Vector<addr_t> op_arg = {one, x0};\n    addr_t one_minus_x0 = tape.record_op(sub_op_enum, op_arg);\n    //\n    // dep_vec, tape\n    // vec[x[0]] = x[1]\n    tape.record_store_op(which_vector, x0, x1);           // vec[x[0]]   = x[1]\n    tape.record_store_op(which_vector, one_minus_x0, x2); // vec[1-x[0]] = x[2]\n    //\n    // set_dep\n    dep_vec[1] = tape.record_load_op(which_vector, zero); // y[1] = vec[0]\n    dep_vec[2] = tape.record_load_op(which_vector, one);  // y[2] = vec[1]\n    tape.set_dep( dep_vec );\n    //\n    // x\n    Vector<double> x(n_ind);\n    x[0] = 1.0;\n    x[1] = 5.0;\n    x[2] = 6.0;\n    //\n    // trace\n    bool trace = false;\n    //\n    // val_vec\n    Vector<double> val_vec( tape.n_val() );\n    for(addr_t i = 0; i < n_ind; ++i)\n        val_vec[i] = x[i];\n    tape.eval(trace, val_vec);\n    //\n    // y\n    Vector<double> y(3);\n    for(size_t i = 0; i < 3; ++i)\n        y[i] = val_vec[ dep_vec[i] ];\n    //\n    // ok\n    if( x[0] == 0.0 )\n    {   ok &= y[0] == 4.0;\n        ok &= y[1] == x[1];\n        ok &= y[2] == x[2];\n    }\n    else\n    {   assert( x[0] == 1.0);\n        ok &= y[0] == 1.0;\n        ok &= y[1] == x[2];\n        ok &= y[2] == x[1];\n    }\n    //\n    // f\n    Vector<size_t> var_ind(3), dyn_ind(0);\n    var_ind[0] = 0;\n    var_ind[1] = 1;\n    var_ind[2] = 2;\n    CppAD::ADFun<double> f;\n    f.val2fun(tape, dyn_ind, var_ind);\n    //\n    // y\n    y = f.Forward(0, x);\n    //\n    // ok\n    if( x[0] == 0.0 )\n    {   ok &= y[0] == 4.0;\n        ok &= y[1] == x[1];\n        ok &= y[2] == x[2];\n    }\n    else\n    {   assert( x[0] == 1.0);\n        ok &= y[0] == 1.0;\n        ok &= y[1] == x[2];\n        ok &= y[2] == x[1];\n    }\n    //\n    return ok;\n}\n// END_C++\n// ---------------------------------------------------------------------------\n} // END_EMPTY_NAMESPACE\nbool test_val2fun(void)\n{   bool ok = true;\n    ok     &= dynamic_atom();\n    ok     &= variable_atom();\n    ok     &= comp_op();\n    ok     &= dis_op();\n    ok     &= csum_op();\n    ok     &= cexp_op();\n    ok     &= pri_op();\n    ok     &= vector_op();\n    return ok;\n}\n"
  },
  {
    "path": "val_graph/test/val_optimize.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2023-23 Bradley M. Bell\n# include <cppad/cppad.hpp>\nnamespace { // BEGIN_EMPTY_NAMESPACE\n// ----------------------------------------------------------------------------\n// optimize_csum\nbool csum_op(void)\n{   bool ok = true;\n    using CppAD::AD;\n    using CppAD::vector;\n    //\n    // ax, ap\n    size_t n = 2;\n    vector< AD<double> > ax(n), ap(n);\n    for(size_t j = 0; j < n; ++j)\n    {   ax[j] = 0.0;\n        ap[j] = 0.0;\n    }\n    Independent(ax, ap);\n    //\n    // asum\n    AD<double> asum = 0.0;\n    for(size_t j = 0; j < n; ++j)\n    {   asum += ax[j];\n        asum += ap[j];\n    }\n    AD<double> aplus  = ax[0] + ap[0];\n    AD<double> aminus = ax[0] - ap[0];\n    asum             += CondExpLe(ax[0], ap[0], aplus, aminus);\n    //\n    // f\n    vector< AD<double> > ay(1);\n    ay[0] = asum * asum;\n    CppAD::ADFun<double> f(ax, ay);\n    //\n    // val_optimize\n    f.val_optimize(\"val_graph no_conditional_skip\");\n    //\n    // x, p, y, check, ok\n    // zero order forward\n    vector<double> x(n), p(n), y(1);\n    double sum = 0.0;\n    for(size_t j = 0; j < n; ++j)\n    {   p[j]  = double(j + 1);\n        x[j]  = double(n + j + 1);\n        sum  += x[j];\n        sum  += p[j];\n    }\n    if( x[0] <= p[0] )\n        sum += x[0] + p[0];\n    else\n        sum += x[0] - p[0];\n    //\n    double check = sum * sum;\n    f.new_dynamic(p);\n    y     = f.Forward(0, x);\n    ok &= y[0] == check;\n    //\n    // val_optimize, y, ok\n    f.val_optimize(\"val_graph no_conditional_skip\");\n    f.new_dynamic(p);\n    y     = f.Forward(0, x);\n    ok &= y[0] == check;\n    //\n    return ok;\n}\n// ----------------------------------------------------------------------------\n} // END_EMPTY_NAMESPACE\nbool test_val_optimize(void)\n{   bool ok = true;\n    ok     &= csum_op();\n    return ok;\n}\n"
  },
  {
    "path": "val_graph/unary_xam.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2023-23 Bradley M. Bell\n# include <cppad/local/val_graph/tape.hpp>\n/*\n{xrst_begin val_unary_xam.cpp dev}\n\nUnary Value Operator Example\n############################\n{xrst_literal\n    // BEGIN_C++\n    // END_C++\n}\n\n{xrst_end val_unary_xam.cpp}\n*/\n// BEGIN_C++\nbool unary_xam(void)\n{   bool ok = true;\n    //\n    // tape_t, Vector, addr_t, neg_op_enum;\n    using CppAD::local::val_graph::tape_t;\n    using CppAD::local::val_graph::Vector;\n    using CppAD::local::val_graph::addr_t;\n    using CppAD::local::val_graph::op_enum_t;\n    op_enum_t neg_op_enum = CppAD::local::val_graph::neg_op_enum;\n    //\n    // tape, ok\n    tape_t<double> tape;\n    addr_t n_ind = 1;\n    addr_t index_of_nan = tape.set_ind(n_ind);\n    ok &= index_of_nan == n_ind;\n    //\n    // op_arg\n    Vector<addr_t> op_arg(1);\n    op_arg[0] = 0; // x[0]\n    //\n    // dep_vec\n    Vector<addr_t> dep_vec(1);\n    //\n    // tape\n    dep_vec[0] = tape.record_op(neg_op_enum, op_arg); // - x[0]\n    //\n    // set_dep\n    tape.set_dep( dep_vec );\n    //\n    // x\n    Vector<double> x(1);\n    x[0] = 5.0;\n    //\n    // trace\n    bool trace = false;\n    //\n    // val_vec\n    Vector<double> val_vec( tape.n_val() );\n    for(addr_t i = 0; i < n_ind; ++i)\n        val_vec[i] = x[i];\n    tape.eval(trace, val_vec);\n    //\n    // ok\n    ok &= tape.n_op()  == 2;\n    ok &= tape.arg_vec().size() == 2;\n    ok &= tape.con_vec().size() == 1;\n    ok &= tape.n_val()          == n_ind + 2;\n    //\n    // y\n    Vector<double> y(1);\n    y[0] = val_vec[ dep_vec[0] ];\n    //\n    // ok\n    ok &= y[0] == - x[0];\n    //\n    return ok;\n}\n// END_C++\n"
  },
  {
    "path": "val_graph/val2fun_xam.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2023-23 Bradley M. Bell\n# include <cppad/cppad.hpp>\n# include <cppad/local/val_graph/tape.hpp>\n# include <cppad/local/val_graph/val2fun.hpp>\n/*\n{xrst_begin val_val2fun_xam.cpp dev}\n\nExample ADFun From Value Graph\n##############################\n{xrst_literal\n    // BEGIN_C++\n    // END_C++\n}\n\n{xrst_end val_val2fun_xam.cpp}\n*/\n// BEGIN_C++\nbool val2fun_xam(void)\n{   bool ok = true;\n    //\n    // tape_t, Vector, addr_t, add_op_enum;\n    using CppAD::local::val_graph::tape_t;\n    using CppAD::local::val_graph::Vector;\n    using CppAD::local::val_graph::addr_t;\n    using CppAD::local::val_graph::op_enum_t;\n    op_enum_t add_op_enum = CppAD::local::val_graph::add_op_enum;\n    op_enum_t sub_op_enum = CppAD::local::val_graph::sub_op_enum;\n    //\n    // tape, ok\n    tape_t<double> tape;\n    addr_t n_ind = 4;\n    addr_t index_of_nan = tape.set_ind(n_ind);\n    ok &= index_of_nan == n_ind;\n    //\n    // op_arg\n    Vector<addr_t> op_arg(2);\n    //\n    // dep_vec\n    Vector<addr_t> dep_vec(2);\n    //\n    // addr_tmp\n    addr_t addr_tmp;\n    //\n    // tape\n    //\n    // addr_tmp = p[0] - p[1]\n    op_arg[0]  = 0; // p[0]\n    op_arg[1]  = 1; // p[1]\n    addr_tmp   = tape.record_op(sub_op_enum, op_arg);\n    //\n    // dep_vec[0] = x[0] + p[0] - p[1]\n    op_arg[0]  = 2;         // x[0]\n    op_arg[1]  = addr_tmp;  // p[0] - p[1]\n    dep_vec[0] = tape.record_op(add_op_enum, op_arg);\n    //\n    // addr_tmp = p[1] - p[0]\n    op_arg[0]  = 1; // p[1]\n    op_arg[1]  = 0; // p[0]\n    addr_tmp   = tape.record_op(sub_op_enum, op_arg);\n    //\n    // dep_vec[1] = x[1] + p[1] - p[0]\n    op_arg[0]  = 3;         // x[1]\n    op_arg[1]  = addr_tmp;  // p[1] - p[0]\n    dep_vec[1] = tape.record_op(add_op_enum, op_arg);\n    //\n    // set_dep\n    tape.set_dep( dep_vec );\n    /*\n    // trace\n    bool trace = true;\n    Vector<double> val_vec( tape.n_val() );\n    for(addr_t i = 0; i < n_ind; ++i)\n        val_vec[i] = double(5 + i);\n    tape.eval(trace, val_vec);\n    */\n    // ADFun\n    Vector<size_t> dyn_ind(2), var_ind(2);\n    dyn_ind[0] = 0;\n    dyn_ind[1] = 1;\n    var_ind[0] = 2;\n    var_ind[1] = 3;\n    CppAD::ADFun<double> f;\n    f.val2fun( tape, dyn_ind, var_ind );\n    //\n\n    // p, x\n    Vector<double> p(2), x(2), y(2);\n    p[0] = 5.0;\n    p[1] = 6.0;\n    x[0] = 7.0;\n    x[1] = 8.0;\n    //\n    // f, y\n    f.new_dynamic(p);\n    y = f.Forward(0, x);\n    //\n    ok &= y[0] == x[0] + p[0] - p[1];\n    ok &= y[1] == x[1] + p[1] - p[0];\n    //\n    return ok;\n}\n// END_C++\n"
  },
  {
    "path": "val_graph/val_graph.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2003-23 Bradley M. Bell\n// ----------------------------------------------------------------------------\n// CPPAD_HAS_* defines\n# include <cppad/configure.hpp>\n\n// system include files used for I/O\n# include <iostream>\n\n// C style asserts\n# include <cassert>\n\n// for thread_alloc\n# include <cppad/utility/thread_alloc.hpp>\n\n// test runner\n# include <cppad/utility/test_boolofvoid.hpp>\n\n// BEGIN_SORT_THIS_LINE_PLUS_1\nextern bool binary_xam(void);\nextern bool call_xam(void);\nextern bool cexp_xam(void);\nextern bool comp_xam(void);\nextern bool compress_xam(void);\nextern bool con_xam(void);\nextern bool csum_xam(void);\nextern bool cumulative_xam(void);\nextern bool dead_xam(void);\nextern bool dis_xam(void);\nextern bool fold_con_xam(void);\nextern bool fun2val_xam(void);\nextern bool pri_xam(void);\nextern bool renumber_xam(void);\nextern bool summation_xam(void);\nextern bool test_ad_double(void);\nextern bool test_fold(void);\nextern bool test_fun2val(void);\nextern bool test_nan(void);\nextern bool test_opt_call(void);\nextern bool test_optimize(void);\nextern bool test_val2fun(void);\nextern bool test_val_optimize(void);\nextern bool unary_xam(void);\nextern bool val2fun_xam(void);\nextern bool vec_xam(void);\n// END_SORT_THIS_LINE_MINUS_1\n\n// main program that runs all the tests\nint main(void)\n{   std::string group = \"val_graph\";\n    size_t      width = 20;\n    CppAD::test_boolofvoid Run(group, width);\n\n    // This line is used by test_one.sh\n\n    // BEGIN_SORT_THIS_LINE_PLUS_1\n    Run( binary_xam,          \"binary_xam\"          );\n    Run( call_xam,            \"call_xam\"            );\n    Run( cexp_xam,            \"cexp_xam\"            );\n    Run( comp_xam,            \"comp_xam\"            );\n    Run( compress_xam,        \"compress_xam\"        );\n    Run( con_xam,             \"con_xam\"             );\n    Run( csum_xam,            \"csum_xam\"            );\n    Run( cumulative_xam,      \"cumulative_xam\"      );\n    Run( dead_xam,            \"dead_xam\"            );\n    Run( dis_xam,             \"dis_xam\"             );\n    Run( fold_con_xam,        \"fold_con_xam\"        );\n    Run( fun2val_xam,         \"fun2val_xam\"         );\n    Run( pri_xam,             \"pri_xam\"             );\n    Run( renumber_xam,        \"renumber_xam\"        );\n    Run( summation_xam,       \"summation_xam\"       );\n    Run( test_ad_double,      \"test_ad_double\"      );\n    Run( test_fold,           \"test_fold\"           );\n    Run( test_fun2val,        \"test_fun2val\"        );\n    Run( test_nan,            \"test_nan\"            );\n    Run( test_opt_call,       \"test_opt_call\"       );\n    Run( test_optimize,       \"test_optimize\"       );\n    Run( test_val2fun,        \"test_val2fun\"        );\n    Run( unary_xam,           \"unary_xam\"           );\n    Run( val2fun_xam,         \"val2fun_xam\"         );\n    Run( vec_xam,             \"vec_xam\"             );\n    // END_SORT_THIS_LINE_MINUS_1\n\n    // check for memory leak\n    bool memory_ok = CppAD::thread_alloc::free_all();\n    // print summary at end\n    bool ok = Run.summary(memory_ok);\n    //\n    return static_cast<int>( ! ok );\n}\n"
  },
  {
    "path": "val_graph/vec_xam.cpp",
    "content": "// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n// SPDX-FileContributor: 2023-23 Bradley M. Bell\n# include <cppad/local/val_graph/tape.hpp>\n# include <cppad/local/val_graph/val_type.hpp>\n/*\n{xrst_begin val_vec_xam.cpp dev}\n\nConditional Expression Value Operator Example\n#############################################\n{xrst_literal\n    // BEGIN_C++\n    // END_C++\n}\n\n{xrst_end val_vec_xam.cpp}\n*/\n// BEGIN_C++\nbool vec_xam(void)\n{   bool ok = true;\n    //\n    // tape_t, Vector, addr_t, compare_lt_enum\n    using CppAD::local::val_graph::tape_t;\n    using CppAD::local::val_graph::Vector;\n    using CppAD::local::val_graph::addr_t;\n    //\n    // tape, ok\n    tape_t<double> tape;\n    addr_t n_ind = 3;\n    addr_t index_of_nan = tape.set_ind(n_ind);\n    ok &= index_of_nan == n_ind;\n    //\n    // x0, x1, x2\n    addr_t x0 = 0;   // x[0]\n    addr_t x1 = 1;   // x[1]\n    addr_t x2 = 2;   // x[2]\n    //\n    // one, four\n    addr_t one  = tape.record_con_op(1.0);\n    addr_t four = tape.record_con_op(4.0);\n    //\n    // which_vector\n    // vector[0] = 4, vector[1] = 1\n    Vector<addr_t> initial = {four, one};\n    addr_t which_vector = tape.record_vec_op(initial);\n    //\n    // dep_vec, tape\n    Vector<addr_t> dep_vec(3);\n    dep_vec[0] = tape.record_load_op(which_vector, x0);  // vector[ x[0] ]\n    //\n    // dep_vec, tape\n    // vector[ x[1] ] = x[2]\n    tape.record_store_op(which_vector, x1, x2);\n    //\n    // set_dep\n    tape.set_dep( dep_vec );\n    dep_vec[1] = tape.record_load_op(which_vector, x0);  // vector[ x[0] ]\n    dep_vec[2] = tape.record_load_op(which_vector, x1);  // vector[ x[1] ]\n    //\n    // x\n    Vector<double> x(n_ind);\n    x[0] = 0.0;\n    x[1] = 1.0;\n    x[2] = 2.0;\n    //\n    // trace\n    bool trace = false;\n    //\n    // val_vec\n    Vector<double> val_vec( tape.n_val() );\n    for(addr_t i = 0; i < n_ind; ++i)\n        val_vec[i] = x[i];\n    tape.eval(trace, val_vec);\n    //\n    // ok\n    ok &= tape.n_op()           == 8;\n    ok &= tape.con_vec().size() == 3;\n    ok &= tape.arg_vec().size() == 3 + 1 + 3 * 2 + 3;\n    ok &= tape.n_val()          == n_ind + 3 + 3;\n    //\n    // y\n    Vector<double> y(3);\n    for(size_t i = 0; i < 3; ++i)\n        y[i] = val_vec[ dep_vec[i] ];\n    //\n    // ok\n    ok &= y[0] == 4.0;\n    ok &= y[1] == 4.0;\n    ok &= y[2] == x[2];\n    //\n    return ok;\n}\n// END_C++\n"
  },
  {
    "path": "xrst/base_require/base_example.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin base_example}\n\nExample AD Base Types That are not AD<OtherBase>\n################################################\n\nContents\n********\n{xrst_toc_list\n    example/general/base_alloc.hpp\n    example/general/base_require.cpp\n    include/cppad/example/base_adolc.hpp\n    include/cppad/example/valvector/class.hpp\n    include/cppad/core/base_float.hpp\n    include/cppad/core/base_double.hpp\n    include/cppad/core/base_complex.hpp\n}\n\n{xrst_end base_example}\n"
  },
  {
    "path": "xrst/base_require/base_identical.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n/*\n{xrst_begin base_identical}\n{xrst_spell\n    adolc\n}\n\nBase Type Requirements for Identically Equal Comparisons\n########################################################\n\nEqualOpSeq\n**********\nIf function :ref:`EqualOpSeq-name` is used with\narguments of type ``AD`` < *Base* > ,\nthe type *Base* must support the syntax\n\n    *b* = ``CppAD::EqualOpSeq`` ( *u* , *v* )\n\nThis should return true if and only if\n*u* is identically equal to *v*\nand it makes no different which one is used.\nThe arguments *u* and *v* have prototype\n\n| |tab| ``const`` *Base* & *u*\n| |tab| ``const`` *Base* & *v*\n\nThe return value *b* has prototype\n\n    ``bool`` *b*\n\nThe Simple Case\n===============\nIf *Base* is a relatively simple type,\nthe ``EqualOpSeq`` function can be defined by\n\n| ``namespace CppAD`` {\n| |tab| ``inline`` *Base* ``EqualOpSeq`` ( ``const`` *Base* & ``u`` , ``const`` *Base* & ``v`` )\n| |tab| { ``return u`` == ``v`` ; }\n| }\n\nFor example, see\n:ref:`base_alloc<base_alloc.hpp@EqualOpSeq>` .\n\nMore Complicated Case\n=====================\nThe variables\n*u* and *v* are not identically equal in the following case:\n\n#. The type *Base* is ``AD<double>`` .\n#. The following assignment made using type *Base* : *x* [0] = *x* [1] = 1. ,\n#. The :ref:`independent-name` operations is used to make *x*\n   the independent variable vector,\n#. During the corresponding recording, *u* = *x* [0] , *v* = *x* [1] .\n\nNote that during a future :ref:`Forward-name` calculation,\n*u* and *v* could correspond to different values.\nFor example, see\n:ref:`adolc EqualOpSeq<base_adolc.hpp@EqualOpSeq>` .\n\nIdentical\n*********\n\nIdenticalCon\n============\nA *Base* object is a\n:ref:`glossary@Parameter@Constant` parameter\nwhen used in an ``AD`` < *Base* > operation sequence.\nIt is however still possible for a parameter to change its value; e.g.,\nsee the more complicated case above.\n\nPrototypes\n==========\nThe argument *u* has prototype\n\n    ``const`` *Base* *u*\n\nIf it is present, the argument *v* has prototype\n\n    ``const`` *Base* *v*\n\nThe result *b* has prototype\n\n    ``bool`` *b*\n\nIdentical Functions\n===================\nThe type *Base* must support the following functions\n(in the CppAD namespace):\n\n.. list-table::\n    :widths: auto\n\n    * - **Syntax**\n      - **Result**\n    * - *b* = ``IdenticalCon`` ( *u* )\n      - the *Base* value will always be the same\n    * - *b* = ``IdenticalZero`` ( *u* )\n      - *u* equals zero and ``IdenticalCon`` ( *u* )\n    * - *b* = ``IdenticalOne`` ( *u* )\n      - *u* equals one and ``IdenticalCon`` ( *u* )\n    * - *b* = ``IdenticalEqualCon`` ( *u* , *v* )\n      - *u* equals *v* ,\n         ``IdenticalCon`` ( *u* ) and\n         ``IdenticalCon`` ( *v* )\n\nExamples\n========\nSee\n:ref:`base_alloc<base_alloc.hpp@Identical>` .\n\n{xrst_end base_identical}\n*/\n"
  },
  {
    "path": "xrst/base_require/base_member.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-23 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin base_member}\n\nRequired Base Class Member Functions\n####################################\n\nNotation\n********\n\n.. csv-table::\n    :widths: auto\n\n    **Symbol**,**Meaning**\n    *Base*,The base type corresponding to ``AD`` < *Base* >\n    *b*,An object of type ``bool``\n    *i*,An object of type ``int``\n    *s*,An object of type ``size_t``\n    *d*,An object of type ``double``\n    *x*,An object of type ``const`` *Base* &\n    *y*,An object of type ``const`` *Base* &\n    *z*,An object of type *Base*\n\nConstructors\n************\n\nDefault\n=======\n*Base z*\n\nint\n===\n*Base z* ( *i* )\n\nsize_t\n======\n*Base z* ( *s* )\n\ndouble\n======\n*Base z* ( *d* )\n\nCopy\n====\n*Base z* ( *x* )\n\nUnary Operators\n***************\nFor ``op`` equal to\n``+`` ,\n``-``\nthe following operation must be supported:\n\n    *z* = *op* *x*\n\nAssignment Operators\n********************\nFor *op* equal to\n= ,\n``+=`` ,\n``-=`` ,\n``*=`` , and\n``/=`` the following operation must be supported:\n\n    *z* *op* *x*\n\nBinary Operators\n****************\nFor *op* equal to\n``+`` ,\n``-`` ,\n``*`` , and\n``/`` the following operation must be supported:\n\n    *z* = *x* *op* *y*\n\nBool Operators\n**************\nFor *op* equal to\n``==`` ,\n``!=`` ,\nthe following operation must be supported:\n\n    *b* = *x* *op* *y*\n\nExample\n*******\nSee the heading Class Definition in\n:ref:`base_alloc<base_alloc.hpp@Class Definition>` .\n\n{xrst_end base_member}\n"
  },
  {
    "path": "xrst/base_require/base_ordered.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n/*\n{xrst_begin base_ordered}\n{xrst_spell\n    geq\n}\n\nBase Type Requirements for Ordered Comparisons\n##############################################\n\nPurpose\n*******\nThe following operations\n(in the CppAD namespace) are required to use the type\n``AD`` < *Base* > :\n\n.. list-table::\n    :widths: auto\n\n    * - **Syntax**\n      - **Result**\n    * - *b* = ``GreaterThanZero`` ( *x* )\n      - :math:`x > 0`\n    * - *b* = ``GreaterThanOrZero`` ( *x* )\n      - :math:`x \\geq 0`\n    * - *b* = ``LessThanZero`` ( *x* )\n      - :math:`x < 0`\n    * - *b* = ``LessThanOrZero`` ( *x* )\n      - :math:`x \\leq 0`\n    * - *b* = ``abs_geq`` ( *x* , *y* )\n      - :math:`|x| \\geq |y|`.\n\nwhere the arguments and return value have the prototypes\n\n| |tab| ``const`` *Base* & *x*\n| |tab| ``const`` *Base* & *y*\n| |tab| ``bool`` *b*\n\nOrdered Type\n************\nIf the type *Base* supports ordered operations,\nthese functions should have their corresponding definitions.\nFor example,\n\n| ``namespace CppAD`` {\n| |tab| ``inline bool GreaterThanZero`` ( ``const`` *Base* & ``x`` )\n| |tab| { ``return`` ( ``x > 0`` );\n| |tab| }\n| }\n\nThe other functions would replace ``>`` by the corresponding operator.\nFor example, see\n:ref:`base_alloc<base_alloc.hpp@Ordered>` .\n\nNot Ordered\n***********\nIf the type *Base* does not support ordering,\none might (but need not) define ``GreaterThanZero`` as follows:\n\n| ``namespace CppAD`` {\n| |tab| ``inline bool GreaterThanZero`` ( ``const`` *Base* & ``x`` )\n| |tab| {  // ``attempt to use GreaterThanZero with a`` *Base* ``argument``\n| |tab| |tab| ``assert`` (0);\n| |tab| |tab| ``return x`` ;\n| |tab| }\n| }\n\nThe other functions would have the corresponding definition.\nFor example, see\n:ref:`complex Ordered<base_complex.hpp@Ordered>` .\n\nSpecial Requirements\n********************\nThe following are special requirements when\nthere is no ordered comparison for the base type:\n\nIndependent\n===========\n:ref:`Independent@record_compare` must be false\nin the call to ``Independent`` .\n\nOptimize\n========\nThe :ref:`optimize@options@no_conditional_skip`\noption must be present when ``optimize`` is used.\n\nPrintFor\n========\nThe :ref:`PrintFor-name` operator cannot be used.\n\n{xrst_end base_ordered}\n*/\n"
  },
  {
    "path": "xrst/det_33_hpp.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin det_33.hpp}\n\nSource: det_33\n##############\n\n| # ``ifndef CPPAD_DET_33_HPP``\n| # ``define CPPAD_DET_33_HPP``\n\n{xrst_literal\n    include/cppad/speed/det_33.hpp\n    // BEGIN C++\n    // END C++\n}\n\n``# endif``\n\n{xrst_end det_33.hpp}\n"
  },
  {
    "path": "xrst/det_by_lu_hpp.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin det_by_lu.hpp}\n\nSource: det_by_lu\n#################\n\n| # ``ifndef CPPAD_DET_BY_LU_HPP``\n| # ``define CPPAD_DET_BY_LU_HPP``\n\n{xrst_literal\n    include/cppad/speed/det_by_lu.hpp\n    // BEGIN C++\n    // END C++\n}\n\n``# endif``\n\n{xrst_end det_by_lu.hpp}\n"
  },
  {
    "path": "xrst/det_by_minor_hpp.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin det_by_minor.hpp}\n\nSource: det_by_minor\n####################\n\n| # ``ifndef CPPAD_DET_BY_MINOR_HPP``\n| # ``define CPPAD_DET_BY_MINOR_HPP``\n\n{xrst_literal\n    include/cppad/speed/det_by_minor.hpp\n    // BEGIN C++\n    // END C++\n}\n\n``# endif``\n\n{xrst_end det_by_minor.hpp}\n"
  },
  {
    "path": "xrst/det_grad_33_hpp.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin det_grad_33.hpp}\n\nSource: det_grad_33\n###################\n\n| # ``ifndef CPPAD_DET_GRAD_33_HPP``\n| # ``define CPPAD_DET_GRAD_33_HPP``\n\n{xrst_literal\n    include/cppad/speed/det_grad_33.hpp\n    // BEGIN C++\n    // END C++\n}\n\n``# endif``\n\n{xrst_end det_grad_33.hpp}\n"
  },
  {
    "path": "xrst/det_of_minor_hpp.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin det_of_minor.hpp}\n\nSource: det_of_minor\n####################\n\n| # ``ifndef CPPAD_DET_OF_MINOR_HPP``\n| # ``define CPPAD_DET_OF_MINOR_HPP``\n\n{xrst_literal\n    include/cppad/speed/det_of_minor.hpp\n    // BEGIN C++\n    // END C++\n}\n\n``# endif``\n\n{xrst_end det_of_minor.hpp}\n"
  },
  {
    "path": "xrst/devel/devel.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-25 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin_parent devel dev}\n\nDeveloper Documentation\n#######################\n\n{xrst_comment BEGIN_SORT_THIS_LINE_PLUS_4}\nContents\n********\n{xrst_toc_table\n    cppad_ipopt/example/ode1.xrst\n    cppad_lib/temp_file.cpp\n    include/cppad/configure.hpp.in\n    include/cppad/core/ad_type.hpp\n    include/cppad/core/atomic/four/devel/devel.xrst\n    include/cppad/core/discrete/devel.xrst\n    include/cppad/core/forward/devel.xrst\n    include/cppad/core/independent/devel.xrst\n    include/cppad/core/vec_ad/vec_ad.hpp\n    include/cppad/local/atomic_index.hpp\n    include/cppad/local/is_pod.hpp\n    include/cppad/local/op_code_var.hpp\n    include/cppad/local/optimize/optimize_run.hpp\n    include/cppad/local/play/dyn_player.hpp\n    include/cppad/local/pod_vector.hpp\n    include/cppad/local/record/recorder.hpp\n    include/cppad/local/set_get_in_parallel.hpp\n    include/cppad/local/sparse/dev_sparse.xrst\n    include/cppad/local/sweep/dev_sweep.xrst\n    include/cppad/utility/xrst/dev_utility.xrst\n    speed/dev_speed.xrst\n    xrst/devel/dynamic.xrst\n    xrst/devel/whats_new/2024.xrst\n}\n{xrst_comment END_SORT_THIS_LINE_MINUS_2}\n\n{xrst_end devel}\n# ----------------------------------------------------------------------------\n{xrst_begin dev_graph dev}\n\nDeveloper AD Graph Documentation\n################################\n\nContents\n********\n{xrst_toc_table\n    include/cppad/local/graph/cpp_graph_itr.xrst\n    include/cppad/local/graph/cpp_graph_op.hpp\n    include/cppad/local/graph/json_lexer.xrst\n    include/cppad/local/graph/json_parser.hpp\n    include/cppad/local/graph/json_writer.hpp\n    include/cppad/local/graph/csrc_writer.hpp\n    cppad_lib/csrc_writer.cpp\n    include/cppad/local/val_graph/val_graph.xrst\n}\n\n{xrst_end dev_graph}\n"
  },
  {
    "path": "xrst/devel/dynamic.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin dev_dynamic dev}\n\nDeveloper Documentation for Dynamic Parameters\n##############################################\n\nContents\n********\n{xrst_toc_table\n    include/cppad/local/op_code_dyn.hpp\n}\n\n{xrst_end dev_dynamic}\n"
  },
  {
    "path": "xrst/devel/whats_new/2024.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell  <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin dev_2024 dev}\n\nDevelopment Release Notes for 2024\n##################################\n\n12-11\n*****\nThe :ref:`pod_vector-name` template class was documented and simplified.\nFor example, the ``pod_vector_ptr`` function was removed\nand the ``byte_length_`` and ``byte_capacity_`` member variables\nwhere changed to ``size_`` and ``capacity_`` \nwhich use elements (instead of bytes) for their units.  \n\n12-09\n*****\nThe developer documentation for the variable \nref:`op codes <op_code_var-name>` and \n:ref:`sweeps <dev_sweep-name>` were improved.\nIn addition, the corresponding source code was simplified.\n\n\n{xrst_end dev_2024}\n\n"
  },
  {
    "path": "xrst/example.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin Example}\n\nExamples\n########\n\nIntroduction\n************\nThis section organizes the information related to the CppAD examples.\nEach CppAD operation has its own specific example,\nfor example :ref:`add.cpp-name` is an example for\n:ref:`addition<ad_binary-name>` .\nSome of the examples are of a more general nature\n(not connected of a specific feature of CppAD).\nIn addition, there are some utility functions that are used\nby the examples.\n\nget_started\n***********\nThe :ref:`get_started.cpp-name` example is a good place to start using CppAD.\n\nRunning Examples\n****************\nThe\n:ref:`installation instructions<Install-name>`\nshow how the examples can be run on your system.\n\nThe CppAD Test Vector Template Class\n************************************\nMany of the examples use the ``CPPAD_TESTVECTOR`` preprocessor symbol\n( see :ref:`testvector-name` )\nto determine which :ref:`SimpleVector-name` template class is used with\nthe examples.\n\nContents\n********\n{xrst_toc_table\n    example/get_started/get_started.cpp\n    xrst/example_list.xrst\n    include/cppad/core/testvector.hpp\n    include/cppad/wno_conversion.hpp\n}\n\n{xrst_end Example}\n"
  },
  {
    "path": "xrst/example_list.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin list_all_examples}\n{xrst_spell\n    acosh\n    adolc\n    asinh\n    azmul\n    bthread\n    cexp\n    chkpoint\n    cholesky\n    colpack\n    comp\n    conj\n    cout\n    ctor\n    div\n    dll\n    dyn\n    erfc\n    expm\n    ext\n    interp\n    inv\n    ipopt\n    jit\n    json\n    lp\n    maxabs\n    neg\n    nso\n    onetape\n    openmp\n    param\n    pthread\n    qp\n    rc\n    rcv\n    retape\n    rosen\n    runge\n    subgraph\n}\n\nList All (Except Deprecated) CppAD Examples\n###########################################\n\n{xrst_comment\n    omit:   TestOne.cpp OneCase.cpp lu_vec_ad.cpp\n}\n\n\n.. csv-table::\n    :widths: auto\n\n    {xrst_comment BEGIN_SORT_THIS_LINE_PLUS_1}\n    a11c_bthread.cpp,:ref:`a11c_bthread.cpp-title`\n    a11c_openmp.cpp,:ref:`a11c_openmp.cpp-title`\n    a11c_pthread.cpp,:ref:`a11c_pthread.cpp-title`\n    abort_recording.cpp,:ref:`abort_recording.cpp-title`\n    abs_eval.cpp,:ref:`abs_eval.cpp-title`\n    abs_eval.hpp,:ref:`abs_eval.hpp-title`\n    abs_get_started.cpp,:ref:`abs_get_started.cpp-title`\n    abs_min_linear.cpp,:ref:`abs_min_linear.cpp-title`\n    abs_min_linear.hpp,:ref:`abs_min_linear.hpp-title`\n    abs_min_quad.cpp,:ref:`abs_min_quad.cpp-title`\n    abs_min_quad.hpp,:ref:`abs_min_quad.hpp-title`\n    acos.cpp,:ref:`acos.cpp-title`\n    acosh.cpp,:ref:`acosh.cpp-title`\n    ad_assign.cpp,:ref:`ad_assign.cpp-title`\n    ad_ctor.cpp,:ref:`ad_ctor.cpp-title`\n    ad_fun.cpp,:ref:`ad_fun.cpp-title`\n    ad_in_c.cpp,:ref:`ad_in_c.cpp-title`\n    ad_input.cpp,:ref:`ad_input.cpp-title`\n    ad_output.cpp,:ref:`ad_output.cpp-title`\n    add.cpp,:ref:`add.cpp-title`\n    add_eq.cpp,:ref:`add_eq.cpp-title`\n    asin.cpp,:ref:`asin.cpp-title`\n    asinh.cpp,:ref:`asinh.cpp-title`\n    atan.cpp,:ref:`atan.cpp-title`\n    atan2.cpp,:ref:`atan2.cpp-title`\n    atanh.cpp,:ref:`atanh.cpp-title`\n    atomic_four_dynamic.cpp,:ref:`atomic_four_dynamic.cpp-title`\n    atomic_four_forward.cpp,:ref:`atomic_four_forward.cpp-title`\n    atomic_four_get_started.cpp,:ref:`atomic_four_get_started.cpp-title`\n    atomic_four_lin_ode_forward.cpp,:ref:`atomic_four_lin_ode_forward.cpp-title`\n    atomic_four_lin_ode_rev_depend.cpp,:ref:`atomic_four_lin_ode_rev_depend.cpp-title`\n    atomic_four_lin_ode_reverse.cpp,:ref:`atomic_four_lin_ode_reverse.cpp-title`\n    atomic_four_lin_ode_sparsity.cpp,:ref:`atomic_four_lin_ode_sparsity.cpp-title`\n    atomic_four_mat_mul_forward.cpp,:ref:`atomic_four_mat_mul_forward.cpp-title`\n    atomic_four_mat_mul_identical_zero.cpp,:ref:`atomic_four_mat_mul_identical_zero.cpp-title`\n    atomic_four_mat_mul_rev_depend.cpp,:ref:`atomic_four_mat_mul_rev_depend.cpp-title`\n    atomic_four_mat_mul_reverse.cpp,:ref:`atomic_four_mat_mul_reverse.cpp-title`\n    atomic_four_mat_mul_sparsity.cpp,:ref:`atomic_four_mat_mul_sparsity.cpp-title`\n    atomic_four_norm_sq.cpp,:ref:`atomic_four_norm_sq.cpp-title`\n    atomic_four_vector.hpp,:ref:`atomic_four_vector.hpp-title`\n    atomic_four_vector_add.cpp,:ref:`atomic_four_vector_add.cpp-title`\n    atomic_four_vector_add_op.hpp,:ref:`atomic_four_vector_add_op.hpp-title`\n    atomic_four_vector_div.cpp,:ref:`atomic_four_vector_div.cpp-title`\n    atomic_four_vector_div_op.hpp,:ref:`atomic_four_vector_div_op.hpp-title`\n    atomic_four_vector_for_type.hpp,:ref:`atomic_four_vector_for_type.hpp-title`\n    atomic_four_vector_forward_op.hpp,:ref:`atomic_four_vector_forward_op.hpp-title`\n    atomic_four_vector_hes_sparsity.cpp,:ref:`atomic_four_vector_hes_sparsity.cpp-title`\n    atomic_four_vector_hes_sparsity.hpp,:ref:`atomic_four_vector_hes_sparsity.hpp-title`\n    atomic_four_vector_jac_sparsity.cpp,:ref:`atomic_four_vector_jac_sparsity.cpp-title`\n    atomic_four_vector_jac_sparsity.hpp,:ref:`atomic_four_vector_jac_sparsity.hpp-title`\n    atomic_four_vector_mul.cpp,:ref:`atomic_four_vector_mul.cpp-title`\n    atomic_four_vector_mul_op.hpp,:ref:`atomic_four_vector_mul_op.hpp-title`\n    atomic_four_vector_neg.cpp,:ref:`atomic_four_vector_neg.cpp-title`\n    atomic_four_vector_neg_op.hpp,:ref:`atomic_four_vector_neg_op.hpp-title`\n    atomic_four_vector_rev_depend.cpp,:ref:`atomic_four_vector_rev_depend.cpp-title`\n    atomic_four_vector_rev_depend.hpp,:ref:`atomic_four_vector_rev_depend.hpp-title`\n    atomic_four_vector_reverse_op.hpp,:ref:`atomic_four_vector_reverse_op.hpp-title`\n    atomic_four_vector_sub.cpp,:ref:`atomic_four_vector_sub.cpp-title`\n    atomic_four_vector_sub_op.hpp,:ref:`atomic_four_vector_sub_op.hpp-title`\n    atomic_three_base2ad.cpp,:ref:`atomic_three_base2ad.cpp-title`\n    atomic_three_dynamic.cpp,:ref:`atomic_three_dynamic.cpp-title`\n    atomic_three_forward.cpp,:ref:`atomic_three_forward.cpp-title`\n    atomic_three_get_started.cpp,:ref:`atomic_three_get_started.cpp-title`\n    atomic_three_hes_sparsity.cpp,:ref:`atomic_three_hes_sparsity.cpp-title`\n    atomic_three_jac_sparsity.cpp,:ref:`atomic_three_jac_sparsity.cpp-title`\n    atomic_three_mat_mul.cpp,:ref:`atomic_three_mat_mul.cpp-title`\n    atomic_three_mat_mul.hpp,:ref:`atomic_three_mat_mul.hpp-title`\n    atomic_three_norm_sq.cpp,:ref:`atomic_three_norm_sq.cpp-title`\n    atomic_three_reciprocal.cpp,:ref:`atomic_three_reciprocal.cpp-title`\n    atomic_three_rev_depend.cpp,:ref:`atomic_three_rev_depend.cpp-title`\n    atomic_three_reverse.cpp,:ref:`atomic_three_reverse.cpp-title`\n    atomic_three_tangent.cpp,:ref:`atomic_three_tangent.cpp-title`\n    atomic_two_eigen_cholesky.cpp,:ref:`atomic_two_eigen_cholesky.cpp-title`\n    atomic_two_eigen_cholesky.hpp,:ref:`atomic_two_eigen_cholesky.hpp-title`\n    atomic_two_eigen_mat_inv.cpp,:ref:`atomic_two_eigen_mat_inv.cpp-title`\n    atomic_two_eigen_mat_inv.hpp,:ref:`atomic_two_eigen_mat_inv.hpp-title`\n    atomic_two_eigen_mat_mul.cpp,:ref:`atomic_two_eigen_mat_mul.cpp-title`\n    atomic_two_eigen_mat_mul.hpp,:ref:`atomic_two_eigen_mat_mul.hpp-title`\n    azmul.cpp,:ref:`azmul.cpp-title`\n    base2ad.cpp,:ref:`base2ad.cpp-title`\n    base2vec_ad.cpp,:ref:`base2vec_ad.cpp-title`\n    base_adolc.hpp,:ref:`base_adolc.hpp-title`\n    base_alloc.hpp,:ref:`base_alloc.hpp-title`\n    base_complex.hpp,:ref:`base_complex.hpp-title`\n    base_require.cpp,:ref:`base_require.cpp-title`\n    bender_quad.cpp,:ref:`bender_quad.cpp-title`\n    bool_fun.cpp,:ref:`bool_fun.cpp-title`\n    bthread_get_started.cpp,:ref:`bthread_get_started.cpp-title`\n    capacity_order.cpp,:ref:`capacity_order.cpp-title`\n    change_param.cpp,:ref:`change_param.cpp-title`\n    check_for_nan.cpp,:ref:`check_for_nan.cpp-title`\n    check_numeric_type.cpp,:ref:`check_numeric_type.cpp-title`\n    check_simple_vector.cpp,:ref:`check_simple_vector.cpp-title`\n    chkpoint_two_base2ad.cpp,:ref:`chkpoint_two_base2ad.cpp-title`\n    chkpoint_two_compare.cpp,:ref:`chkpoint_two_compare.cpp-title`\n    chkpoint_two_dynamic.cpp,:ref:`chkpoint_two_dynamic.cpp-title`\n    chkpoint_two_get_started.cpp,:ref:`chkpoint_two_get_started.cpp-title`\n    chkpoint_two_ode.cpp,:ref:`chkpoint_two_ode.cpp-title`\n    code_gen_fun_file.cpp,:ref:`code_gen_fun_file.cpp-title`\n    code_gen_fun_function.cpp,:ref:`code_gen_fun_function.cpp-title`\n    code_gen_fun_jac_as_fun.cpp,:ref:`code_gen_fun_jac_as_fun.cpp-title`\n    code_gen_fun_jacobian.cpp,:ref:`code_gen_fun_jacobian.cpp-title`\n    code_gen_fun_sparse_jac_as_fun.cpp,:ref:`code_gen_fun_sparse_jac_as_fun.cpp-title`\n    code_gen_fun_sparse_jacobian.cpp,:ref:`code_gen_fun_sparse_jacobian.cpp-title`\n    colpack_hes.cpp,:ref:`colpack_hes.cpp-title`\n    colpack_hessian.cpp,:ref:`colpack_hessian.cpp-title`\n    colpack_jac.cpp,:ref:`colpack_jac.cpp-title`\n    colpack_jacobian.cpp,:ref:`colpack_jacobian.cpp-title`\n    compare.cpp,:ref:`compare.cpp-title`\n    compare_change.cpp,:ref:`compare_change.cpp-title`\n    complex_poly.cpp,:ref:`complex_poly.cpp-title`\n    con_dyn_var.cpp,:ref:`con_dyn_var.cpp-title`\n    cond_exp.cpp,:ref:`cond_exp.cpp-title`\n    conj_grad.cpp,:ref:`conj_grad.cpp-title`\n    cos.cpp,:ref:`cos.cpp-title`\n    cosh.cpp,:ref:`cosh.cpp-title`\n    cppad_eigen.hpp,:ref:`cppad_eigen.hpp-title`\n    cppad_vector.cpp,:ref:`cppad_vector.cpp-title`\n    dependency.cpp,:ref:`dependency.cpp-title`\n    det_by_lu.cpp,:ref:`det_by_lu.cpp-title`\n    det_by_minor.cpp,:ref:`det_by_minor.cpp-title`\n    det_of_minor.cpp,:ref:`det_of_minor.cpp-title`\n    div.cpp,:ref:`div.cpp-title`\n    div_eq.cpp,:ref:`div_eq.cpp-title`\n    dll_lib.cpp,:ref:`dll_lib.cpp-title`\n    eigen_array.cpp,:ref:`eigen_array.cpp-title`\n    eigen_det.cpp,:ref:`eigen_det.cpp-title`\n    elapsed_seconds.cpp,:ref:`elapsed_seconds.cpp-title`\n    equal_op_seq.cpp,:ref:`equal_op_seq.cpp-title`\n    erf.cpp,:ref:`erf.cpp-title`\n    erfc.cpp,:ref:`erfc.cpp-title`\n    error_handler.cpp,:ref:`error_handler.cpp-title`\n    exp.cpp,:ref:`exp.cpp-title`\n    expm1.cpp,:ref:`expm1.cpp-title`\n    expm1.cpp,:ref:`expm1.cpp-title`\n    fabs.cpp,:ref:`fabs.cpp-title`\n    for_hes_sparsity.cpp,:ref:`for_hes_sparsity.cpp-title`\n    for_jac_sparsity.cpp,:ref:`for_jac_sparsity.cpp-title`\n    for_one.cpp,:ref:`for_one.cpp-title`\n    for_sparse_hes.cpp,:ref:`for_sparse_hes.cpp-title`\n    for_sparse_jac.cpp,:ref:`for_sparse_jac.cpp-title`\n    for_two.cpp,:ref:`for_two.cpp-title`\n    forward.cpp,:ref:`forward.cpp-title`\n    forward_dir.cpp,:ref:`forward_dir.cpp-title`\n    forward_order.cpp,:ref:`forward_order.cpp-title`\n    from_json.cpp,:ref:`from_json.cpp-title`\n    fun_assign.cpp,:ref:`fun_assign.cpp-title`\n    fun_check.cpp,:ref:`fun_check.cpp-title`\n    fun_property.cpp,:ref:`fun_property.cpp-title`\n    function_name.cpp,:ref:`function_name.cpp-title`\n    general.cpp,:ref:`general.cpp-title`\n    get_started.cpp,:ref:`get_started.cpp-title`\n    graph_add_op.cpp,:ref:`graph_add_op.cpp-title`\n    graph_atom4_op.cpp,:ref:`graph_atom4_op.cpp-title`\n    graph_atom_op.cpp,:ref:`graph_atom_op.cpp-title`\n    graph_azmul_op.cpp,:ref:`graph_azmul_op.cpp-title`\n    graph_cexp_op.cpp,:ref:`graph_cexp_op.cpp-title`\n    graph_comp_op.cpp,:ref:`graph_comp_op.cpp-title`\n    graph_discrete_op.cpp,:ref:`graph_discrete_op.cpp-title`\n    graph_div_op.cpp,:ref:`graph_div_op.cpp-title`\n    graph_mul_op.cpp,:ref:`graph_mul_op.cpp-title`\n    graph_pow_op.cpp,:ref:`graph_pow_op.cpp-title`\n    graph_print_op.cpp,:ref:`graph_print_op.cpp-title`\n    graph_sub_op.cpp,:ref:`graph_sub_op.cpp-title`\n    graph_sum_op.cpp,:ref:`graph_sum_op.cpp-title`\n    graph_unary_op.cpp,:ref:`graph_unary_op.cpp-title`\n    harmonic.cpp,:ref:`harmonic.cpp-title`\n    hes_lagrangian.cpp,:ref:`hes_lagrangian.cpp-title`\n    hes_lu_det.cpp,:ref:`hes_lu_det.cpp-title`\n    hes_minor_det.cpp,:ref:`hes_minor_det.cpp-title`\n    hes_times_dir.cpp,:ref:`hes_times_dir.cpp-title`\n    hessian.cpp,:ref:`hessian.cpp-title`\n    independent.cpp,:ref:`independent.cpp-title`\n    index_sort.cpp,:ref:`index_sort.cpp-title`\n    integer.cpp,:ref:`integer.cpp-title`\n    interface2c.cpp,:ref:`interface2c.cpp-title`\n    interp_onetape.cpp,:ref:`interp_onetape.cpp-title`\n    interp_retape.cpp,:ref:`interp_retape.cpp-title`\n    ipopt_solve_get_started.cpp,:ref:`ipopt_solve_get_started.cpp-title`\n    ipopt_solve_ode_inverse.cpp,:ref:`ipopt_solve_ode_inverse.cpp-title`\n    ipopt_solve_retape.cpp,:ref:`ipopt_solve_retape.cpp-title`\n    jac_lu_det.cpp,:ref:`jac_lu_det.cpp-title`\n    jac_minor_det.cpp,:ref:`jac_minor_det.cpp-title`\n    jacobian.cpp,:ref:`jacobian.cpp-title`\n    jit_atomic.cpp,:ref:`jit_atomic.cpp-title`\n    jit_compare_change.cpp,:ref:`jit_compare_change.cpp-title`\n    jit_compile.cpp,:ref:`jit_compile.cpp-title`\n    jit_dynamic.cpp,:ref:`jit_dynamic.cpp-title`\n    jit_get_started.cpp,:ref:`jit_get_started.cpp-title`\n    json_add_op.cpp,:ref:`json_add_op.cpp-title`\n    json_atom4_op.cpp,:ref:`json_atom4_op.cpp-title`\n    json_atom_op.cpp,:ref:`json_atom_op.cpp-title`\n    json_azmul_op.cpp,:ref:`json_azmul_op.cpp-title`\n    json_cexp_op.cpp,:ref:`json_cexp_op.cpp-title`\n    json_comp_op.cpp,:ref:`json_comp_op.cpp-title`\n    json_discrete_op.cpp,:ref:`json_discrete_op.cpp-title`\n    json_div_op.cpp,:ref:`json_div_op.cpp-title`\n    json_get_started.cpp,:ref:`json_get_started.cpp-title`\n    json_mul_op.cpp,:ref:`json_mul_op.cpp-title`\n    json_pow_op.cpp,:ref:`json_pow_op.cpp-title`\n    json_print_op.cpp,:ref:`json_print_op.cpp-title`\n    json_sparse.cpp,:ref:`json_sparse.cpp-title`\n    json_sub_op.cpp,:ref:`json_sub_op.cpp-title`\n    json_sum_op.cpp,:ref:`json_sum_op.cpp-title`\n    json_unary_op.cpp,:ref:`json_unary_op.cpp-title`\n    log.cpp,:ref:`log.cpp-title`\n    log10.cpp,:ref:`log10.cpp-title`\n    log1p.cpp,:ref:`log1p.cpp-title`\n    lp_box.cpp,:ref:`lp_box.cpp-title`\n    lp_box.hpp,:ref:`lp_box.hpp-title`\n    lu_factor.cpp,:ref:`lu_factor.cpp-title`\n    lu_invert.cpp,:ref:`lu_invert.cpp-title`\n    lu_ratio.cpp,:ref:`lu_ratio.cpp-title`\n    lu_solve.cpp,:ref:`lu_solve.cpp-title`\n    lu_vec_ad_ok.cpp,:ref:`lu_vec_ad_ok.cpp-title`\n    mat_sum_sq.cpp,:ref:`mat_sum_sq.cpp-title`\n    min_nso_linear.cpp,:ref:`min_nso_linear.cpp-title`\n    min_nso_linear.hpp,:ref:`min_nso_linear.hpp-title`\n    min_nso_quad.cpp,:ref:`min_nso_quad.cpp-title`\n    min_nso_quad.hpp,:ref:`min_nso_quad.hpp-title`\n    mul.cpp,:ref:`mul.cpp-title`\n    mul_eq.cpp,:ref:`mul_eq.cpp-title`\n    mul_level.cpp,:ref:`mul_level.cpp-title`\n    mul_level_adolc.cpp,:ref:`mul_level_adolc.cpp-title`\n    mul_level_adolc_ode.cpp,:ref:`mul_level_adolc_ode.cpp-title`\n    mul_level_ode.cpp,:ref:`mul_level_ode.cpp-title`\n    multi_atomic_three.cpp,:ref:`multi_atomic_three.cpp-title`\n    multi_atomic_two.cpp,:ref:`multi_atomic_two.cpp-title`\n    multi_chkpoint_one.cpp,:ref:`multi_chkpoint_one.cpp-title`\n    multi_chkpoint_two.cpp,:ref:`multi_chkpoint_two.cpp-title`\n    multi_newton.cpp,:ref:`multi_newton.cpp-title`\n    nan.cpp,:ref:`nan.cpp-title`\n    near_equal.cpp,:ref:`near_equal.cpp-title`\n    near_equal_ext.cpp,:ref:`near_equal_ext.cpp-title`\n    new_dynamic.cpp,:ref:`new_dynamic.cpp-title`\n    num_limits.cpp,:ref:`num_limits.cpp-title`\n    number_skip.cpp,:ref:`number_skip.cpp-title`\n    numeric_type.cpp,:ref:`numeric_type.cpp-title`\n    ode_err_control.cpp,:ref:`ode_err_control.cpp-title`\n    ode_err_maxabs.cpp,:ref:`ode_err_maxabs.cpp-title`\n    ode_evaluate.cpp,:ref:`ode_evaluate.cpp-title`\n    ode_gear.cpp,:ref:`ode_gear.cpp-title`\n    ode_gear_control.cpp,:ref:`ode_gear_control.cpp-title`\n    ode_stiff.cpp,:ref:`ode_stiff.cpp-title`\n    openmp_get_started.cpp,:ref:`openmp_get_started.cpp-title`\n    opt_val_hes.cpp,:ref:`opt_val_hes.cpp-title`\n    optimize_compare_op.cpp,:ref:`optimize_compare_op.cpp-title`\n    optimize_conditional_skip.cpp,:ref:`optimize_conditional_skip.cpp-title`\n    optimize_cumulative_sum.cpp,:ref:`optimize_cumulative_sum.cpp-title`\n    optimize_forward_active.cpp,:ref:`optimize_forward_active.cpp-title`\n    optimize_nest_conditional.cpp,:ref:`optimize_nest_conditional.cpp-title`\n    optimize_print_for.cpp,:ref:`optimize_print_for.cpp-title`\n    optimize_reverse_active.cpp,:ref:`optimize_reverse_active.cpp-title`\n    optimize_twice.cpp,:ref:`optimize_twice.cpp-title`\n    poly.cpp,:ref:`poly.cpp-title`\n    pow.cpp,:ref:`pow.cpp-title`\n    pow_int.cpp,:ref:`pow_int.cpp-title`\n    pow_nan.cpp,:ref:`pow_nan.cpp-title`\n    print_for_cout.cpp,:ref:`print_for_cout.cpp-title`\n    print_for_string.cpp,:ref:`print_for_string.cpp-title`\n    print_graph.cpp,:ref:`print_graph.cpp-title`\n    pthread_get_started.cpp,:ref:`pthread_get_started.cpp-title`\n    qp_box.cpp,:ref:`qp_box.cpp-title`\n    qp_box.hpp,:ref:`qp_box.hpp-title`\n    qp_interior.cpp,:ref:`qp_interior.cpp-title`\n    qp_interior.hpp,:ref:`qp_interior.hpp-title`\n    rc_sparsity.cpp,:ref:`rc_sparsity.cpp-title`\n    rev_checkpoint.cpp,:ref:`rev_checkpoint.cpp-title`\n    rev_hes_sparsity.cpp,:ref:`rev_hes_sparsity.cpp-title`\n    rev_jac_sparsity.cpp,:ref:`rev_jac_sparsity.cpp-title`\n    rev_one.cpp,:ref:`rev_one.cpp-title`\n    rev_sparse_hes.cpp,:ref:`rev_sparse_hes.cpp-title`\n    rev_sparse_jac.cpp,:ref:`rev_sparse_jac.cpp-title`\n    rev_two.cpp,:ref:`rev_two.cpp-title`\n    reverse_one.cpp,:ref:`reverse_one.cpp-title`\n    reverse_three.cpp,:ref:`reverse_three.cpp-title`\n    reverse_two.cpp,:ref:`reverse_two.cpp-title`\n    romberg_mul.cpp,:ref:`romberg_mul.cpp-title`\n    romberg_one.cpp,:ref:`romberg_one.cpp-title`\n    rosen_34.cpp,:ref:`rosen_34.cpp-title`\n    runge45_1.cpp,:ref:`runge45_1.cpp-title`\n    runge_45.cpp,:ref:`runge_45.cpp-title`\n    set_union.cpp,:ref:`set_union.cpp-title`\n    simple_vector.cpp,:ref:`simple_vector.cpp-title`\n    simplex_method.cpp,:ref:`simplex_method.cpp-title`\n    simplex_method.hpp,:ref:`simplex_method.hpp-title`\n    sin.cpp,:ref:`sin.cpp-title`\n    sinh.cpp,:ref:`sinh.cpp-title`\n    sparse2eigen.cpp,:ref:`sparse2eigen.cpp-title`\n    sparse_hes.cpp,:ref:`sparse_hes.cpp-title`\n    sparse_hes_fun.cpp,:ref:`sparse_hes_fun.cpp-title`\n    sparse_hessian.cpp,:ref:`sparse_hessian.cpp-title`\n    sparse_jac_for.cpp,:ref:`sparse_jac_for.cpp-title`\n    sparse_jac_fun.cpp,:ref:`sparse_jac_fun.cpp-title`\n    sparse_jac_rev.cpp,:ref:`sparse_jac_rev.cpp-title`\n    sparse_jacobian.cpp,:ref:`sparse_jacobian.cpp-title`\n    sparse_rc.cpp,:ref:`sparse_rc.cpp-title`\n    sparse_rcv.cpp,:ref:`sparse_rcv.cpp-title`\n    sparse_sub_hes.cpp,:ref:`sparse_sub_hes.cpp-title`\n    sparsity_sub.cpp,:ref:`sparsity_sub.cpp-title`\n    speed_example.cpp,:ref:`speed_example.cpp-title`\n    speed_program.cpp,:ref:`speed_program.cpp-title`\n    speed_test.cpp,:ref:`speed_test.cpp-title`\n    sqrt.cpp,:ref:`sqrt.cpp-title`\n    stack_machine.cpp,:ref:`stack_machine.cpp-title`\n    sub.cpp,:ref:`sub.cpp-title`\n    sub_eq.cpp,:ref:`sub_eq.cpp-title`\n    sub_sparse_hes.cpp,:ref:`sub_sparse_hes.cpp-title`\n    subgraph_hes2jac.cpp,:ref:`subgraph_hes2jac.cpp-title`\n    subgraph_jac_rev.cpp,:ref:`subgraph_jac_rev.cpp-title`\n    subgraph_reverse.cpp,:ref:`subgraph_reverse.cpp-title`\n    subgraph_sparsity.cpp,:ref:`subgraph_sparsity.cpp-title`\n    switch_var_dyn.cpp,:ref:`switch_var_dyn.cpp-title`\n    tan.cpp,:ref:`tan.cpp-title`\n    tanh.cpp,:ref:`tanh.cpp-title`\n    tape_index.cpp,:ref:`tape_index.cpp-title`\n    taylor_ode.cpp,:ref:`taylor_ode.cpp-title`\n    team_bthread.cpp,:ref:`team_bthread.cpp-title`\n    team_example.cpp,:ref:`team_example.cpp-title`\n    team_openmp.cpp,:ref:`team_openmp.cpp-title`\n    team_pthread.cpp,:ref:`team_pthread.cpp-title`\n    team_thread.hpp,:ref:`team_thread.hpp-title`\n    thread_alloc.cpp,:ref:`thread_alloc.cpp-title`\n    thread_test.cpp,:ref:`thread_test.cpp-title`\n    time_test.cpp,:ref:`time_test.cpp-title`\n    to_json.cpp,:ref:`to_json.cpp-title`\n    to_string.cpp,:ref:`to_string.cpp-title`\n    unary_minus.cpp,:ref:`unary_minus.cpp-title`\n    unary_plus.cpp,:ref:`unary_plus.cpp-title`\n    value.cpp,:ref:`value.cpp-title`\n    var2par.cpp,:ref:`var2par.cpp-title`\n    vec_ad.cpp,:ref:`vec_ad.cpp-title`\n    vector_bool.cpp,:ref:`vector_bool.cpp-title`\n    {xrst_comment END_SORT_THIS_LINE_MINUS_1}\n\n{xrst_end list_all_examples}\n-----------------------------------------------------------------------------\n{xrst_begin General}\n\nGeneral Examples\n################\n\nDescription\n***********\nMost of the examples in CppAD are part of the documentation\nfor a specific feature; for example, :ref:`add.cpp-name` is an\nexample using the :ref:`addition operator<ad_binary-name>` .\nThe examples list in this section are of a more general nature.\n\nContents\n********\n{xrst_toc_table\n    example/general/ad_fun.cpp\n    example/general/ad_in_c.cpp\n    example/sparse/conj_grad.cpp\n    include/cppad/example/cppad_eigen.hpp\n    example/general/hes_minor_det.cpp\n    example/general/hes_lu_det.cpp\n    example/general/interface2c.cpp\n    example/general/jac_minor_det.cpp\n    example/general/jac_lu_det.cpp\n    xrst/mul_level.xrst\n    example/general/ode_stiff.cpp\n    example/general/mul_level_ode.cpp\n    example/general/mul_level_adolc_ode.cpp\n    example/general/stack_machine.cpp\n    cppad_lib/code_gen_fun.cpp\n}\n\n{xrst_end General}\n-----------------------------------------------------------------------------\n{xrst_begin example_driver}\n\nUtility Routines used by CppAD Examples\n#######################################\n\nContents\n********\n{xrst_comment BEGIN_SORT_THIS_LINE_PLUS_2}\n{xrst_toc_table\n    example/abs_normal/abs_normal.cpp\n    example/atomic_four/atomic_four.cpp\n    example/atomic_three/atomic_three.cpp\n    example/atomic_two/atomic_two.cpp\n    example/chkpoint_two/chkpoint_two.cpp\n    example/cppad_code_gen/cppad_code_gen.cpp\n    example/general/general.cpp\n    example/general/lu_vec_ad.cpp\n    example/graph/graph.cpp\n    example/ipopt_solve/ipopt_solve.cpp\n    example/jit/jit.cpp\n    example/json/json.cpp\n    example/optimize/optimize.cpp\n    example/sparse/sparse.cpp\n    example/utility/utility.cpp\n    example/valvector/valvector.cpp\n    speed/example/example.cpp\n}\n{xrst_comment END_SORT_THIS_LINE_MINUS_2}\n\n{xrst_end example_driver}\n-----------------------------------------------------------------------------\n"
  },
  {
    "path": "xrst/install/adolc.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin adolc}\n{xrst_spell\n    bashrc\n    cygdrive\n}\n\nIncluding Adolc Examples and Tests\n##################################\n\nAdolc Home Page\n***************\nhttps://github.com/coin-or/ADOL-C\n\nPurpose\n*******\nCppAD includes examples and tests that can use the AD package Adolc.\nThe includes speed comparison with other AD packages; see\n:ref:`speed_adolc-name` .\nIt also includes examples that combine Adolc with\nCppAD; see\n\n.. csv-table::\n    :widths: auto\n\n    base_adolc.hpp,:ref:`base_adolc.hpp-title`\n    mul_level_adolc.cpp,:ref:`mul_level_adolc.cpp-title`\n    mul_level_adolc_ode.cpp,:ref:`mul_level_adolc_ode.cpp-title`\n\ninclude_adolc\n*************\nIf Adolc is installed on your system, you can\nspecify ``include_adolc=true`` on the\n:ref:`cmake-name` command line.\nThe value of ``PKG_CONFIG_PATH`` must be such that the command\n\n    ``pkg-config adolc --path --print-errors``\n\nfinds the location of the file ``adolc.pc`` .\nNote that CppAD assumes adolc has been configured with\nits sparse matrix computations enabled; i.e, using\n\n    ``--with-colpack`` = *adolc_prefix*\n\nIn other words ColPack is installed and\nwith the same prefix as ACOL-C; see\n:ref:`get_colpack.sh-name` .\n\nExamples\n********\nIf you specify :ref:`cmake@include_adolc` on the cmake command\nline, you will be able to run the Adolc examples listed above\nby executing the following commands starting in the\n:ref:`download@Distribution Directory` :\n\n| |tab| ``cd build/example``\n| |tab| ``make check_example``\n\nIf you do this,\nyou will see an indication that the examples\n``mul_level_adolc`` and ``mul_level_adolc_ode``\nhave passed their correctness check.\n\nSpeed Tests\n***********\nIf you include *adolc_prefix* on the :ref:`cmake-name` command line,\nyou will be able to run the Adolc speed correctness tests\nby executing the following commands starting in the\n:ref:`download@Distribution Directory` :\n\n| |tab| ``cd build/speed/adolc``\n| |tab| ``make check_speed_adolc``\n\nAfter executing ``make check_speed_adolc`` ,\nyou can run a specific Adolc speed tests\nby executing the command ``./speed_adolc`` ;\nsee :ref:`speed_main-name` for the meaning of the command line\noptions to this program.\n\nUnix\n****\nIf you are using Unix,\nyou may have to add\n*adolc_prefix* to ``LD_LIBRARY_PATH`` .\nFor example, if you use the ``bash`` shell to run your programs,\nyou could include\n\n| |tab| ``LD_LIBRARY_PATH`` = *adolc_prefix* / ``lib:$`` { ``LD_LIBRARY_PATH`` }\n| |tab| ``export LD_LIBRARY_PATH``\n\nin your ``$HOME/.bashrc`` file.\n\nCygwin\n******\nIf you are using Cygwin,\nyou may have to add to following lines to the file\n``.bashrc`` in your home directory:\n\n| |tab| ``PATH`` = *adolc_prefix* / ``bin:$`` { ``PATH`` }\n| |tab| ``export PATH``\n\nin order for Adolc to run properly.\nIf *adolc_prefix* begins with a disk specification,\nyou must use the Cygwin format for the disk specification.\nFor example,\nif ``d:/adolc_base`` is the proper directory,\n``/cygdrive/d/adolc_base`` should be used for *adolc_prefix* .\n\nget_adolc\n*********\nIf you are using Unix, you can download and install\na copy of Adolc using :ref:`get_adolc.sh-name` .\nThe corresponding install prefix is\n``build/prefix`` .\n\n{xrst_end adolc}\n"
  },
  {
    "path": "xrst/install/cmake.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-25 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin cmake}\n{xrst_spell\n    ansi\n    autotools\n    colpack\n    cstdint\n    cxx\n    datadir\n    dev\n    dlls\n    docdir\n    dylib\n    exe\n    ext\n    fadbad\n    gprof\n    grep\n    hsc\n    includedirs\n    libcppad\n    libdirs\n    makefile\n    makefiles\n    mingw\n    mkdir\n    msys\n    pacman\n    profiler\n    sacado\n    sed\n    testvector\n    txt\n    uint\n    usr\n    vcvarsall\n    wshadow\n    yyyy\n    yyyymmdd\n}\n\nUsing CMake to Configure CppAD\n##############################\n\nThe CMake Program\n*****************\nThe cmake program enables one to create a single set of scripts,\ncalled ``CMakeLists.txt`` ,\nthat can be used to test and install a program on Unix, Microsoft, or\nApple operating systems; see\n`cmake resources <https://cmake.org/resources/>`_ .\n\nBuild Directory\n***************\nCreate ``build`` , a subdirectory of the\n:ref:`download@Distribution Directory` ,\nchange into the ``build`` .\n\nEigen\n*****\nThe cmake command will automatically search for the eigen package.\nIf it is found,\nthe  corresponding examples will be tested and the\n:ref:`sparse2eigen-name` utility will be installed; see :ref:`eigen-name` .\nThe results of cppad's search for Eigen are reported in the output of\nthe cmake command.\n\nCMake Command\n*************\n\nSimple\n======\nThe simplest version of the ``cmake`` command is\n\n    ``cmake ..``\n\nThis assumes that you are starting in the ``build`` directory\n(so that ``..`` refers to the distribution directory).\nThe command also assumes that ``cmake`` is in your execution\npath with version greater than or equal 2.8.\nIf not, you can put the path to the version of ``cmake``\nin font the command.\nIt is suggested that you should start with the simple version of the\ncmake command above and then add options one at a time.\n\nWarning\n=======\nVersion 3.10.2 of cmake will generates the following warning if boost\nis not present your system:\n\n| ``CMake Warning at /usr/share/cmake-3.10/Modules/FindBoost.cmake:567`` ( ``message`` ):\n| |tab| ``Imported targets and dependency information not available for Boost version``\n| |tab| ( ``all versions older than 1.33`` )\n| |tab| ...\n\nThis is not a problem because CppAD will automatically exclude the\nexamples and tests that use boost.\nNewer version of cmake; e.g., 3.13.4, do not generate this warning\n(when boost is not present on your system).\n\ntrue_or_false\n=============\nThe syntax ``-D`` *name* = *true_or_false* , mean that\nthe variable *name* can be assigned the value ``true`` or ``false`` .\n\n\nOptions\n=======\nThe full version of the command, with all its optional arguments is:\n\n| ``cmake``                                                                 \\\\\n| |tab| ``-D CMAKE_VERBOSE_MAKEFILE`` = *cmake_verbose_makefile*            \\\\\n| |tab| ``-D CMAKE_BUILD_TYPE`` = *cmake_build_type*                        \\\\\n| |tab| ``-G`` *generator*                                                  \\\\\n| |tab| \\\\\n| |tab| ``-D cppad_prefix`` = *cppad_prefix*                                \\\\\n| |tab| ``-D cppad_postfix`` = *cppad_postfix*                              \\\\\n| |tab| \\\\\n| |tab| ``-D cmake_install_includedirs`` = *cmake_install_includedirs*      \\\\\n| |tab| ``-D cmake_install_libdirs`` = *cmake_install_libdirs*              \\\\\n| |tab| \\\\\n| |tab| ``-D cmake_install_datadir`` = *cmake_install_datadir*              \\\\\n| |tab| ``-D cmake_install_docdir`` = *cmake_install_docdir*                \\\\\n| |tab| \\\\\n| |tab| ``-D include_doc`` = *true_or_false*                                \\\\\n| |tab| ``-D cmake_defined_ok`` = *true_or_false*                           \\\\\n| |tab| ``-D cppad_static_lib`` = *true_or_false*                           \\\\\n| |tab| ``-D cppad_debug_and_release`` = *true_or_false*                    \\\\\n| |tab| \\\\\n| |tab| ``-D include_adolc`` = *true_or_false*                              \\\\\n| |tab| ``-D include_ipopt`` = *true_or_false*                              \\\\\n| |tab| ``-D include_cppadcg`` = *true_or_false*                            \\\\\n| |tab| \\\\\n| |tab| ``-D colpack_prefix`` = *colpack_prefix*                            \\\\\n| |tab| ``-D fadbad_prefix`` = *fadbad_prefix*                              \\\\\n| |tab| ``-D sacado_prefix`` = *sacado_prefix*                              \\\\\n| |tab| \\\\\n| |tab| ``-D cppad_cxx_flags`` = *cppad_cxx_flags*                          \\\\\n| |tab| ``-D cppad_link_flags`` = *cppad_link_flags*                        \\\\\n| |tab| ``-D cppad_profile_flag`` = *cppad_profile_flag*                    \\\\\n| |tab| ``-D cppad_testvector`` = *cppad_testvector*                        \\\\\n| |tab| ``-D cppad_max_num_threads`` = *cppad_max_num_threads*              \\\\\n| |tab| ``-D cppad_tape_id_type`` = *cppad_tape_id_type*                    \\\\\n| |tab| ``-D cppad_tape_addr_type`` = *cppad_tape_addr_type*                \\\\\n| |tab| ``-D cppad_debug_which`` = *cppad_debug_which*                      \\\\\n| |tab| \\\\\n| |tab| ..\n\nmsys2\n=====\nThe `msys2 <https://www.msys2.org/>`_ system,\nwith ``mingw-64`` and ``g++`` ,\nthe following seems to work:\nUse ``pacman`` to install\n``make`` , ``gcc`` , and ``mingw-w64-x86_64-cmake`` .\n\nVisual Studio\n=============\n\n#. Make sure you have a version of\n   `git for windows <https://git-scm.com/download/win>`_ .\n\n#. Launch the Visual Studio\n   `developer command window <https://learn.microsoft.com/en-us/visualstudio/ide/reference/command-prompt-powershell?view=vs-2022>`_\n\n#. At the command prompt enter\n   ::\n\n        where cmake.exe\n\n    to see if ``cmake.exe`` comes with your version of Visual Studio.\n    If not, download and install the win64-x64 version of the\n    `cmake program <https://cmake.org/download/>`_.\n    Make sure you select the box that adds ``cmake`` to your execution path.\n\n#. Download the CppAD repository, and make it the current directory,\n   using the following commands\n   {xrst_code bat}\n   clone https://github.com/coin-or/CppAD.git cppad.git\n   cd cppad.git\n   {xrst_code}\n\n#. Execute the following commands:\n   {xrst_literal\n       bin/build.bat\n   }\n\nNote that when using windows DLL's, CppAD builds a static version\nof ``cppad_lib`` . There are problems using a DLL for ``cppad_lib``\nbecause Windows makes separate copies of static class member functions,\none for library and one for the rest of the program.\n\nautotools\n=========\nThe autotools build with the Visual Studio compiler should work\nwith the following configure and test commands\n::\n\n    mkdir build\n    cd build\n    ../configure CC=cl CXX=cl CXX_FLAGS=\"-DEBUG\"\n    make test\n\nAn optimized versions was tested using\n::\n\n    ../configure CXX=cl CC=cl CXX_FLAGS=\"-DNDEBUG -O2 -EHsc\"\n    make test\n\nThe commands above need to be run a Dos window,\nthat has the ``vcvarsall.bat`` settings,\nextend path that includes the ``msys2`` bin directory,\nand was running the bash shell inside the Doc window.\nIt is highly recommended that you use the ``cmake`` commands above,\nan not ``../configure`` , when building with Visual Studio.\n\nmake check\n**********\nImportant information about the CppAD configuration is output\nby this command. If you have the ``grep`` program,\nand store the output in ``cmake.log`` , you can get a list of\nall the test options with the command:\n::\n\n    grep 'make check' cmake.log\n\ncmake_verbose_makefile\n**********************\nThis value should be either ``true`` or ``false`` .\nThe default value, when it is not present, is ``false`` .\nIf it is ``true`` , then the output of the ``make`` commands\nwill include all of the files and flags used to run the compiler\nand linker. This can be useful for seeing how to compile and link\nyour own applications.\n\ncmake_build_type\n****************\nThis value should be one of the valid CMake build types; e.g.,\n``Debug`` ,\n``Release`` ,\n``RelWithDebInfo`` ,\n``MinSizeRel`` .\nThe value of this option is not case sensitive; e.g.,\n``Debug`` and ``debug`` yield the same result.\nIf *cmake_build_type* is specified,\n:ref:`cmake@cppad_debug_which`\nmust be the empty string.\n\ngenerator\n*********\nThe CMake program is capable of generating different kinds of files.\nBelow is a table with a few of the possible files\n\n.. csv-table::\n    :widths: auto\n\n    *generator*,Description\n    ``\"Unix Makefiles\"``,make files for unix operating system\n    ``\"NMake Makefiles\"``,make files for Visual Studio\n    ``\"MSYS Makefiles\"``,make files for msys2\n    ``Ninja``, `Ninja`_ build system\n\n.. _Ninja: https://en.wikipedia.org/wiki/Ninja_(build_system)\n\nOther generator choices are available; see the cmake\n`generators <https://cmake.org//cmake/help/cmake2.6docs.html#section_Generators>`_ documentation.\n\ncppad_prefix\n************\nThis is the top level absolute path below which\nall of the CppAD files are installed by the command\n\n    ``make install``\n\nFor example,\nif *cppad_prefix* is ``/usr`` ,\n*cmake_install_includedirs* is ``include`` , and\n*cppad_postfix* is not specified,\nthe file ``cppad.hpp`` is installed in the location\n\n    / ``usr/include/cppad/cppad.hpp``\n\nThe default value for *cppad_prefix* is the value of\n*CMAKE_INSTALL_PREFIX* ; see the cmake documentation.\n(Before 2019-10-02 the default value was ``/usr`` ; see\nthe heading 10-02 on :ref:`2019<2019@mm-dd@10-02>` .)\n\ncppad_postfix\n*************\nThis is the bottom level relative path below which\nall of the CppAD files are installed.\nFor example,\nif *cppad_prefix* is ``/usr`` ,\n*cmake_install_includedirs* is ``include`` , and\n*cppad_postfix* is ``coin-or`` ,\nthe file ``cppad.hpp`` is installed in the location\n\n    / ``usr/include/coin-or/cppad/cppad.hpp``\n\nThe default value for *cppad_postfix* is empty; i.e,\nthere is no bottom level relative directory for the installed files.\n\ncmake_install_includedirs\n*************************\nThis is one directory, or a list of directories separated\nby spaces or by semi-colons.\nThis first entry in the list is the middle level relative path below which\nthe CppAD include files are installed.\nThe entire list is used for searching for include files.\nFor example,\nif *cppad_prefix* is ``/usr`` ,\n*cmake_install_includedirs* is ``include`` , and\n*cppad_postfix* is not specified,\nthe file ``cppad.hpp`` is installed in the location\n\n    / ``usr/include/cppad/cppad.hpp``\n\nThe default value for this directory list is ``include`` .\n\ncmake_install_libdirs\n*********************\nThis is one directory, or a list of directories separated\nby spaces or by semi-colons.\nThis first entry in the list is the middle level relative path below which\nthe CppAD library files are installed.\nThe entire list is used for searching for library files.\nThe default value for this directory list is ``lib;lib64`` .\n\ncppad_lib\n=========\nAs an example of where the CppAD library is installed,\nif *cppad_prefix* is ``/usr`` ,\n*cmake_install_libdirs* is ``lib`` ,\n*cppad_postfix* is not specified,\nthe CppAD library is installed in\n\n    / ``usr/lib/libcppad_lib.`` *ext* . *major* . *release*\n\nHere *major* is the major library version number,\n*release* is the release number for this version,\nand *ext* is the extension for shared libraries on this system.\nIf *yyyymmdd* is the CppAD :ref:`download@Version` number,\nthe major CppAD library version number is\n\n    *major* = *dd* ``- 1`` + 31 * ( *mm* ``- 1`` + 12 * ( *yyyy* ``- 2019`` ) )\n\nIf there is no :ref:`download@Release` for this version of CppAD,\nthe CppAD library is installed in\n\n    / ``usr/lib/libcppad_lib.`` *ext* . *major*\n\nThe Mac is special, *ext* is ``dylib`` and comes\nat the end of the file name for that system.\n\ncmake_install_datadir\n*********************\nThis is the middle level relative path below which\nthe CppAD data files are installed.\nFor example,\nif *cppad_prefix* is ``/usr`` ,\n*cmake_install_datadir* is ``share`` , and\n*cppad_postfix* is not specified,\nthe :ref:`pkgconfig-name` file ``cppad.pc`` is installed in the location\n\n    / ``usr/share/pkgconfig/cppad.pc``\n\nThe default value for *cmake_install_datadir* is ``share`` .\n\ncmake_install_docdir\n********************\nThis is the middle level relative path below which\nthe CppAD user documentation files are installed.\nFor example,\nif *cppad_prefix* is ``/usr`` ,\n*cmake_install_docdir* is ``share/doc`` , and\n*cppad_postfix* is not specified,\nthe file ``user_guide.html`` is installed in the location\n\n    / ``usr/share/doc/cppad/user_guide.html``\n\nIf *cmake_install_docdir* is not specified,\nor :ref:`cmake@include_doc` is false,\nthe documentation files are not installed.\n\ncmake_defined_ok\n****************\nThe default value for this option is true.\nIt must be true when running cmake with a non-empty\n``CMakeCache.txt`` file.\nIf it is false, some checks will be made to make sure\ncertain variables are not defined twice.\n\ninclude_doc\n***********\nThe default value for this option is false.\nIf it is true, is in the command line, the\n`xrst <https://xrst.readthedocs.io/latest/>`_\nprogram must be installed.\nIn this case, the user and developer documentation targets\n``doc_user`` and ``doc_dev`` will be available.\nFor example, if the :ref:`cmake@generator` is ``Ninja``\nthe commands ``ninja doc_user`` and ``ninja doc_dev``\nwill build the  corresponding documentation in the\n``build/html`` sub-directory of the\n:ref:`download@Distribution Directory` .\n\ncppad_static_lib\n****************\nThe default value for this option is true on\n``msys``, ``cygwin`` and ``Windows`` and false otherwise.\nthe cppad library will be a static (shared) library.\nIf the target system uses windows dlls, this setting should be true and\nif it is false, a warning will be issued and it will be ignored.\n\ncppad_debug_and_release\n***********************\nThe default value for this option is true.\nIf it is true,\nthe debug and release versions of CppAD can be mixed in the same program.\nThis must be true if\n:ref:`cmake@cppad_debug_which` is ``debug_even`` or ``debug_odd`` .\nIf ``NDEBUG`` is defined and *cppad_debug_and_release* is false,\n:ref:`thread_alloc-name` does more error checking.\nFor programs that do a lot of memory allocation,\nthis can take a significant amount of time.\nThis is meant for testing CppAD and as a last resort when debugging.\n\ninclude_adolc\n*************\nThe default value for this option is false.\nIf it is true,\nthe :ref:`adolc-name` examples will be compiled and tested.\nIn this case, ``adolc.pc`` must be in the ``PKG_CONFIG_PATH`` .\n\ninclude_ipopt\n*************\nThe default value for this option is false.\nIf it is true,\nthe :ref:`ipopt-name` examples will be compiled and tested.\nIn this case, ``ipopt.pc`` must be in the ``PKG_CONFIG_PATH`` .\nIn addition, :ref:`ipopt_solve-name` and :ref:`cppad_ipopt_nlp-name`\nwill be installed.\n\ninclude_cppadcg\n***************\nThe default value for this option is false.\nIf it is true,\nthe :ref:`cppadcg-name` examples will be compiled and tested.\n**Warning** :\nDo not use this option when installing cppad because\nthe cppadcg package depends on cppad and using this option\nmakes cppad depend on cppadcg.\nThis option, and the script :ref:`get_cppadcg.sh-name` are only intended\nfor testing purposes.\n\npackage_prefix\n**************\nEach of these packages do not have ``pkg-config`` files\ncorresponding to optional CppAD examples.\nIf a prefix listed below is on the command line,\nthe corresponding examples will be compiled and run:\n\n.. csv-table::\n    :widths: auto\n\n    colpack_prefix,:ref:`colpack_prefix-title`\n    fadbad_prefix,:ref:`fadbad_prefix-title`\n    sacado_prefix,:ref:`sacado_prefix-title`\n\ncppad_cxx_flags\n***************\nThis specifies the compiler flags\nthat are used when compiling the CppAD examples, tests, and library.\nThis flags are in addition to the flags automatically generated by\ncmake for debug and release build; i.e.,\n*CMAKE_CXX_FLAGS_DEBUG* and *CMAKE_CXX_FLAGS_RELEASE* .\nThe default value for these flags is the empty string ``\"\"`` .\nThese flags must be valid for the C++ compiler\non your system.\nFor example, if you are using ``g++`` you could specify\n::\n\n    -D cppad_cxx_flags=\"-Wall -ansi -pedantic-errors -std=c++17 -Wshadow\"\n\nC++17\n=====\nIn order for the compiler to take advantage of features that are in C++17\n,but not in C++11, the *cppad_cxx_flags* must enable these features.\n\ncppad_link_flags\n****************\nThis specifies additional flags to use during linking.\nThe default value for these flags is the empty string ``\"\"`` .\n\n-m32\n====\nIf you are on a 64 bit machine and using g++ to\ncompile for 32 bit code, you need to add ``-m32`` to both\nthe additional compiler and linker flags.\nIf ``-m32`` is in *cppad_link_flags* ,\nthe OpenMP, Boost, :ref:`jit <example_jit-name>` , and\n:ref:`speed_cppad_jit-name` examples will not be tested.\n\ncppad_profile_flag\n******************\nThis specifies an addition compiler and link flag that is used\nfor :ref:`profiling<speed_main@package@profile>` the speed tests.\nA profile version of the speed test is only build when this argument\nis present.\nIf this flag is specified, you can run the gnu profiler with the following\ncommand:\n\n| |tab| ``cd build/speed/profile``\n| |tab| ``make check_speed_profile``\n| |tab| ./ ``speed_profile`` *test seed option_list*\n| |tab| ``gprof -b speed_profile`` | ``sed -f gprof.sed``\n\ncppad_testvector\n****************\nSee :ref:`cppad_testvector-title`.\n\ncppad_max_num_threads\n*********************\nThe value *cppad_max_num_threads*\nmust be greater than or equal to four; i.e.,\n*max_num_threads*  >= 4 .\nThe current default value for *cppad_max_num_threads* is 48,\nbut it may change in future versions of CppAD.\nThe value *cppad_max_num_threads* in turn specifies\nthe default value for the preprocessor symbol\n:ref:`multi_thread@CPPAD_MAX_NUM_THREADS` .\n\ncppad_tape_id_type\n******************\nThe type *cppad_tape_id_type*\nis used for identifying different tapes.\nThe valid values for this type are\n``unsigned char`` ,\n``unsigned short int`` ,\n``unsigned int`` , and\n``size_t`` .\nThe smaller the value of ``sizeof`` ( *cppad_tape_id_type* ) ,\nthe less memory is used.\nOn the other hand, the value\n\n    ``std::numeric_limits<`` *cppad_tape_id_type* >:: ``max`` ()\n\nmust be larger than the maximum number of tapes used by one thread times\n:ref:`multi_thread@CPPAD_MAX_NUM_THREADS` .\n\ncstdint\n=======\nIf all of the following ``cstdint`` types are defined,\nthey can also be used as the value of *cppad_tape_addr_type* :\n``uint8_t`` ,\n``uint16_t`` ,\n``uint32_t`` ,\n``uint64_t`` .\n\ncppad_tape_addr_type\n********************\nThe type *cppad_tape_addr_type*\nis used for address in the AD recordings (tapes).\nThe valid values for this argument are\n``unsigned char`` ,\n``unsigned short int`` ,\n``unsigned int`` ,\n``size_t`` .\nThe smaller the value of ``sizeof`` ( *cppad_tape_addr_type* ) ,\nthe less memory is used.\nOn the other hand, the value\n\n    ``std::numeric_limits<`` *cppad_tape_addr_type* >:: ``max`` ()\n\nmust be larger than any of the following:\n:ref:`fun_property@size_op` ,\n:ref:`fun_property@size_op_arg` ,\n:ref:`fun_property@size_par` ,\n:ref:`fun_property@size_text` ,\n:ref:`fun_property@size_VecAD` .\n\ncstdint\n=======\nIf all of the following ``cstdint`` types are defined,\nthey can also be used as the value of *cppad_tape_addr_type* :\n``uint8_t`` ,\n``uint16_t`` ,\n``uint32_t`` ,\n``uint64_t`` .\n\ncppad_debug_which\n*****************\nAll of the CppAD examples and test can optionally be tested\nin debug or release mode (see exception below).\nThis option controls which mode is chosen for the corresponding files.\nThe value *cppad_debug_which* be one of the following:\n\n.. csv-table::\n    :widths: auto\n\n    *cppad_debug_which*,*CMAKE_BUILD_TYPE*\n    ``debug_all``,``Debug``\n    ``debug_none``,``Release``\n    ``debug_even``,not specified\n    ``debug_odd``,not specified\n    empty string,not changed\n\nIf ``CMAKE_BUILD_TYPE`` is specified on the command line,\nthen *cppad_debug_which* must be the empty string (its default value).\n\n{xrst_toc_hidden\n    bin/get_optional.sh\n    xrst/install/adolc.xrst\n    xrst/install/eigen.xrst\n    xrst/install/cppadcg.xrst\n    xrst/install/ipopt.xrst\n    xrst/install/fadbad_prefix.xrst\n    xrst/install/sacado_prefix.xrst\n    xrst/install/colpack_prefix.xrst\n    xrst/install/testvector.xrst\n}\n\n{xrst_end cmake}\n"
  },
  {
    "path": "xrst/install/cmake_check.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin cmake_check}\n{xrst_spell\n    grep\n}\n\nChecking the CppAD Examples and Tests\n#####################################\n\nPurpose\n*******\nAfter you configure your system with the\n:ref:`cmake@CMake Command` you\ncan run the CppAD example and tests to make sure that\nCppAD functions properly on your system.\n\nCheck All\n*********\nIn the ``build`` subdirectory of the\n:ref:`download@Distribution Directory`\nexecute the command\n::\n\n    make check\n\nThis will build and run all of the tests that are support\nby your system and the :ref:`cmake-name` command options.\n\nSubsets of make check\n*********************\nIn unix, you can determine which subsets of ``make check`` are available\nby putting the output of the :ref:`cmake@CMake Command`\nin a file (called *cmake.out* below) and executing:\n\n    ``grep`` ' ``make check.`` * ``available`` ' *cmake.out*\n\nFirst Level\n***********\nThe first level of subsets of ``make check`` are described below:\n\n.. list-table::\n    :widths: auto\n\n    * - Command\n      - Description\n    * - ``make check_introduction``\n      - the :ref:`Introduction-name` functions\n    * - ``make check_example``\n      - the normal :ref:`example<list_all_examples-name>` functions plus some deprecated\n         examples.\n    * - ``make check_test_more``\n      - correctness tests that are not examples\n    * - ``make check_speed``\n      - correctness for single thread :ref:`speed-name` tests\n    * - ``make check_cppad_ipopt``\n      - the deprecated :ref:`cppad_ipopt_nlp-name` speed and correctness tests\n\nNote that ``make check_example_multi_thread`` is used for the\n:ref:`multi-threading<multi_thread-name>` speed tests.\n\n{xrst_end cmake_check}\n"
  },
  {
    "path": "xrst/install/colpack_prefix.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin colpack_prefix}\n\nEnabling Colpack Sparsity Calculations\n######################################\n\nColpack Home Page\n*****************\nhttps://github.com/CSCsw/ColPack\n\nPurpose\n*******\nIf you specify a *colpack_prefix* on the\n:ref:`cmake@CMake Command` line,\nthe CppAD :ref:`sparse_jacobian-name` and :ref:`sparse_hessian-name`\ncalculations can use this package.\n\ncolpack_prefix\n**************\nIf Colpack is installed on your system, you can\nspecify a value for its install *colpack_prefix* on the\n:ref:`cmake-name` command line.\nThe value of *colpack_prefix* must be such that,\nfor one of the directories *dir* in\n:ref:`cmake@cmake_install_includedirs` ,\n\n    *colpack_prefix* / *dir* / ``ColPack/ColPackHeaders.h``\n\nis a valid way to reference to the include file ``ColPackHeaders.h`` .\n\ncppad_lib\n*********\nThe Colpack header files has a\n\n    ``using namespace std``\n\nat the global level.\nFor this reason, CppAD does not include these files.\nIt is therefore necessary to link the object library ``cppad_lib``\nwhen using Colpack.\n{xrst_toc_hidden\n    example/sparse/colpack_jac.cpp\n    example/sparse/colpack_jacobian.cpp\n    example/sparse/colpack_hes.cpp\n    example/sparse/colpack_hessian.cpp\n}\nExample\n*******\nThe file :ref:`colpack_jac.cpp-name` (:ref:`colpack_hes.cpp-name` )\ncontains an example and test of using Colpack to compute the coloring for\nsparse Jacobians (Hessians).\n\nget_colpack\n***********\nIf you are using Unix, you can download and install\na copy of Colpack using :ref:`get_colpack.sh-name` .\nThe corresponding *colpack_prefix* would be\n``build/prefix`` .\n\n{xrst_end colpack_prefix}\n"
  },
  {
    "path": "xrst/install/cppadcg.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin cppadcg}\n\nIncluding CppADCodeGen Examples and Tests\n#########################################\n\nCppADCodeGen Home Page\n**********************\nhttps://github.com/joaoleal/CppADCodeGen\n\nPurpose\n*******\nCppAD includes examples and test that use the CppADCodeGen package,\nabbreviated as ``cppadcg`` , see:\n:ref:`code_gen_fun-name` .\n\ninclude_cppadcg\n***************\nIf ``include_cppadcg=true`` is on the cmake command line,\nthen the pkg-config will find the\nnecessary information to include cppadcg.\nThe value of *PKG_CONFIG_PATH* must be such that the command\n\n    ``pkg-config cppadcg --path --print-errors``\n\nfinds the location of the file ``cppadcg.pc`` .\n\nSpeed Tests\n***********\nIf ``include_cppadcg=true`` is on the cmake command line,\nyou will be able to run the cppadcg speed correctness tests\nby executing the following commands starting in the\n:ref:`download@Distribution Directory` :\n\n| |tab| ``cd build/speed/cppadcg``\n| |tab| ``make check_speed_cppadcg``\n\nAfter executing ``make check_speed_cppadcg`` ,\nyou can run a specific cppadcg speed test\nby executing the command ``./speed_cppadcg`` ;\nsee :ref:`speed_main-name` for the meaning of the command line\noptions to this program.\n\nget_cppadcg\n***********\nIf you are using Unix, you can download and install\na copy of cppadcg using :ref:`get_cppadcg.sh-name` .\nThe corresponding install prefix is\n``build/prefix`` .\n\n{xrst_end cppadcg}\n"
  },
  {
    "path": "xrst/install/download.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin download}\n{xrst_spell\n    dev\n    github\n    grep\n    gz\n    txt\n    yyyy\n}\n\nDownload The CppAD Source Code\n##############################\n\nPurpose\n*******\nCppAD is an include file library and you therefore need the source\ncode to use it.\nThis section discusses how to download the different versions of CppAD.\n\nDistribution Directory\n**********************\nWe refer to the CppAD source directory created by the download instructions\nbelow as the distribution directory.\nAs a check, the distribution directory contains the file\n``include/cppad/cppad.hpp`` .\n\nVersion\n*******\nA CppAD *version* number has the following fields:\n*yyyy* is four decimal digits denoting a year,\n*mm* is two decimal digits denoting a month,\nand *dd* is two decimal digits denoting a day.\nFor example *version*  = 20160101 corresponds to January 1, 2016.\n\nRelease\n*******\nSpecial versions corresponding to the beginning of each year\nhave *dd* equal to zero.\nThese version numbers are combined with release numbers denoted by\n*rel* .\nHigher release numbers correspond to more bug fixes.\nFor example\n*version* . *rel*  = 20160000.0 corresponds to the first release\nof the version for 2016,\n``20160000.1`` corresponds to the first bug fix for 2016.\nThe compressed archive names on the github\n`releases <https://github.com/coin-or/CppAD/releases>`_ page\nare named *version* . *rel* . ``tar.gz`` .\nBefore 2019,\nthese archives correspond to the Eclipse Public License Version 1\nlicense and do not include the documentation.\nStarting in 2019,\nthese archives correspond to the EPL 2.0 or (GPL 2.0 or later) license and\na separate compressed archive is available\non the releases page with name *version* . ``doc.tar.gz`` .\n\nGit\n***\nCppAD source code development is current done using ``git``\nYou can a git clone of the current version using the command\n\n    ``git clone https://github.com/coin-or/CppAD.git cppad.git``\n\nThis procedure requires that\nthe `git <https://en.wikipedia.org/wiki/Git_%28software%29>`_\nis installed on your system.\n\nVersion\n=======\nAfter downloading the source code,\nand changing into the distribution directory,\nuse the following command to determine the corresponding\n:ref:`download@Version` :\n::\n\n    grep '^SET(cppad_version' CMakeLists.txt\n\nUse the following command to determine the git *hash* code\ncorresponding to this version:\n::\n\n    git show-ref | grep 'refs/heads/master'\n\nYou can get an old version using the command\n\n    ``git checkout -q`` *hash*\n\nYou can check the corresponding version number using the command\n::\n\n    grep '^SET(cppad_version' CMakeLists.txt\n\nCompressed Archives\n===================\nYou can build a compressed archive, from a clone of the git repository,\nusing the script ``bin/package.sh`` .\nThese archives have the documentation in the ``build/html`` directory\nand do not have the ``git`` information.\nThey are intended for re-distribution.\n\nBuilding Documentation\n======================\nIf you install `xrst <https://xrst.readthedocs.io/latest/>`_ ,\nyou can build the documentation for CppAD,\nand include any changes you make.\nIn the distribution directory execute the following command\n\n| |tab|   ``bin/run_xrst.sh`` *dev*\n\nwhere *dev* is ``-dev`` or ``+dev`` .\nIf you use ``+dev`` the developer documentation will be included.\n\nYou can then view documentation that you built by opening the\nfollowing file in a web browser::\n\n    build/html/index.html\n\n{xrst_end download}\n"
  },
  {
    "path": "xrst/install/eigen.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-25 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin eigen}\n{xrst_spell\n    cholesky\n    inv\n}\n\nIncluding Eigen Examples, Tests, and sparse2eigen\n#################################################\n\nEigen Home Page\n***************\nhttps://libeigen.gitlab.io/\n\nFinding Eigen\n*************\nThese example and tests will be included\nand :ref:`sparse2eigen-name` will be installed if:\n\n#. Eigen is installed on your system\n\n#. c++14 or higher is supported by your compiler\n\n#. *PKG_CONFIG_PATH* is such that the following command\n   finds the location of the file eigen3.pc :\n   ``pkg-config eigen3 --path --print-errors``\n\nThe output of the :ref:`cmake-name` command will report if these\nconditions are met.\n\n\nExamples and Tests\n******************\nCppAD can include the following examples and tests that\nuse the linear algebra package Eigen:\n{xrst_comment check list with: grep 'eigen.*\\.cpp' omh/example_list.omh'}\n\n.. csv-table::\n    :widths: auto\n\n    cppad_eigen.hpp,:ref:`cppad_eigen.hpp-title`\n    eigen_array.cpp,:ref:`eigen_array.cpp-title`\n    eigen_det.cpp,:ref:`eigen_det.cpp-title`\n    sparse2eigen.cpp,:ref:`sparse2eigen.cpp-title`\n    atomic_two_eigen_cholesky.hpp,:ref:`atomic_two_eigen_cholesky.hpp-title`\n    atomic_two_eigen_mat_inv.hpp,:ref:`atomic_two_eigen_mat_inv.hpp-title`\n    atomic_two_eigen_mat_mul.hpp,:ref:`atomic_two_eigen_mat_mul.hpp-title`\n\nExamples\n********\nIf :ref:`eigen is found <eigen@Finding Eigen>` ,\nyou will be able to run the Eigen examples list above\nby executing the following commands starting in the\n:ref:`download@Distribution Directory` :\n\n| |tab| ``cd build/example``\n| |tab| ``make check_example``\n\nIf you do this,\nyou will see an indication that the examples\n``eigen_array`` and ``eigen_det``\nhave passed their correctness check.\n\nTest Vector\n***********\nIf you eigen is found you can choose\n\n    ``-D cppad_testvector`` = ``eigen``\n\non the :ref:`cmake@CMake Command` line.\nThis we set the CppAD :ref:`testvector-name` to use Eigen vectors.\n\n{xrst_end eigen}\n"
  },
  {
    "path": "xrst/install/fadbad_prefix.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin fadbad_prefix}\n{xrst_spell\n    badiff\n}\n\nIncluding Fadbad Speed Tests\n############################\n\nFadbad Home Page\n****************\nhttp://uning.dk/\n\nPurpose\n*******\nCppAD includes speed comparisons for the Fadbad AD package; see\n:ref:`speed_fadbad-name` .\n\nfadbad_prefix\n*************\nIf Fadbad is installed on your system, you can\nspecify a value for its install *fadbad_prefix* on the\n:ref:`cmake-name` command line.\nThe value of *fadbad_prefix* must be such that,\nfor one of the directories *dir* in\n:ref:`cmake@cmake_install_includedirs` ,\n\n    *fadbad_prefix* / *dir* / ``FADBAD`` ++/ ``badiff.h``\n\nis a valid way to reference to the include file ``badiff.h`` ;\n\nSpeed Tests\n***********\nIf you include *fadbad_prefix* on the :ref:`cmake-name` command line,\nyou will be able to run the Fadbad speed correctness tests\nby executing the following commands starting in the\n:ref:`download@Distribution Directory` :\n\n| |tab| ``cd build/speed/fadbad``\n| |tab| ``make check_speed_fadbad``\n\nAfter executing ``make check_speed_fadbad`` ,\nyou can run a specific Fadbad speed test\nby executing the command ``./speed_fadbad`` ;\nsee :ref:`speed_main-name` for the meaning of the command line\noptions to this program.\n\nget_fadbad\n**********\nIf you are using Unix, you can download and install\na copy of Fadbad using :ref:`get_fadbad.sh-name` .\nThe corresponding *fadbad_prefix* would be\n``build/prefix`` .\n\n{xrst_end fadbad_prefix}\n"
  },
  {
    "path": "xrst/install/install.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin Install}\n{xrst_spell\n    autotools\n    nmake\n}\n\nCppAD Download, Test, and Install Instructions\n##############################################\n\nInstructions\n************\n\nStep 1: Download\n================\nUse the :ref:`download-name` instructions to obtain a copy or CppAD.\n\nStep 2: Cmake\n=============\nUse the :ref:`cmake-name` instructions to configure CppAD.\n\nStep 3: Check\n=============\nUse the :ref:`cmake_check-name` instructions to check the\nCppAD examples and tests.\n\nStep 4: Installation\n====================\nUse the command\n::\n\n    make install\n\nto install CppAD.\n\nGenerator\n*********\nIf you want to use ``nmake`` or ``ninja`` instead of ``make``,\nin Step 4;  see the\n:ref:`cmake@generator` option for the ``cmake`` command.\n\ncppad.spec\n**********\nIf you are thinking of creating a system specific install of CppAD,\nthe fedora spec file may be of help; see\n`cppad.spec\n<https://src.fedoraproject.org/rpms/cppad/blob/rawhide/f/cppad.spec>`_ .\n\nxrst\n****\nThe `xrst <https://xrst.readthedocs.io/latest>`_\npackage is used to build the CppAD documentation.\n\nContents\n********\n{xrst_toc_table\n    xrst/install/download.xrst\n    xrst/install/cmake.xrst\n    xrst/install/cmake_check.xrst\n    pkgconfig/CMakeLists.txt\n    bin/dos_build.bat\n}\n\nconfigure\n*********\nThe :ref:`configure-name` script provides configuration interface that is\nsimilar to the old CppAD autotools install.\n\n{xrst_end Install}\n"
  },
  {
    "path": "xrst/install/ipopt.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin ipopt}\n{xrst_spell\n    cflags\n}\n\nIncluding Ipopt Library Examples, Tests, and pkg-config\n#######################################################\n\nExamples and Tests\n******************\nIf :ref:`cmake@include_ipopt`\nis on the cmake command line,\nyou will be able to run the Ipopt examples and tests.\n\ninclude_ipopt\n*************\nIf ``include_ipopt=true`` is on the cmake command line,\nthen the pkg-config will find the\nnecessary information to link in ipopt.\nThe value of *PKG_CONFIG_PATH* must be such that the command\n\n    ``pkg-config ipopt --path --print-errors``\n\nfinds the location of the file ``ipopt.pc`` .\n\nDeprecated Library\n******************\nIf ``include_ipopt=true`` is on the cmake command line,\nthe deprecated :ref:`cppad_ipopt_nlp-name`\nexample and tests as well as installing the ``cppad_ipopt`` library\nduring the ``make install`` step.\n\nget_ipopt\n*********\nIf you are using Unix, you can download and install\na copy of Ipopt using :ref:`get_ipopt.sh-name` .\nThe corresponding install prefix is\n``build/prefix`` .\n\nInclude Directories\n*******************\nIt may be necessary to remove ``/coin-or`` from the end of the\ninclude directories reported by\n\n    ``pkg-config ipopt --cflags``\n\n{xrst_end ipopt}\n"
  },
  {
    "path": "xrst/install/sacado_prefix.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin sacado_prefix}\n{xrst_spell\n    kokkos\n    trilinos\n}\n\nIncluding Sacado Speed Tests\n############################\n\nSacado Home Page\n****************\nhttps://github.com/trilinos/Trilinos/tree/master/packages/sacado\n\nRequirement\n***********\nThe c++14 standard (or higher)\nis necessary to build Sacado because it uses Kokkos; see\n`Trilinos issue 6260 <https://github.com/trilinos/Trilinos/issues/6260>`_ .\n\nPurpose\n*******\nCppAD includes speed comparisons for the Sacado AD package;\nsee :ref:`speed_sacado-name` .\n\nsacado_prefix\n*************\nIf Sacado is installed on your system, you can\nspecify a value for its install *sacado_prefix* on the\n:ref:`cmake-name` command line.\nThe value of *sacado_prefix* must be such that,\nfor one of the directories *dir* in\n:ref:`cmake@cmake_install_includedirs` ,\n\n    *sacado_prefix* / *dir* / ``Sacado.hpp``\n\nis a valid way to reference to the include file ``Sacado.hpp`` ;\n\nSpeed Tests\n***********\nIf you include *sacado_prefix* on the :ref:`cmake-name` command line,\nyou will be able to run the Sacado speed correctness tests\nby executing the following commands starting in the\n:ref:`download@Distribution Directory` :\n\n| |tab| ``cd build/speed/sacado``\n| |tab| ``make check_speed_sacado``\n\nAfter executing ``make check_speed_sacado`` ,\nyou can run a specific Sacado speed test\nby executing the command ``./speed_sacado`` ;\nsee :ref:`speed_main-name` for the meaning of the command line\noptions to this program.\n\nget_sacado\n**********\nIf you are using Unix, you can download and install\na copy of Sacado using :ref:`get_sacado.sh-name` .\nThe corresponding *sacado_prefix* would be\n``build/prefix`` .\n\n{xrst_end sacado_prefix}\n"
  },
  {
    "path": "xrst/install/testvector.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin cppad_testvector}\n{xrst_spell\n    ublas\n}\n\nChoosing the CppAD Test Vector Template Class\n#############################################\n\nSyntax\n******\n| ``CPPAD_TESTVECTOR`` ( *Scalar* ) *vec*\n\nExample Simple Vector\n*********************\nThe value *cppad_testvector*\nin the :ref:`cmake@CMake Command` must be one of the\nfollowing:\n``boost`` , ``cppad`` , ``eigen`` , or ``std`` .\nIt specifies which :ref:`simplevector-name`\ncorresponds to the template class\n:ref:`CPPAD_TESTVECTOR<testvector-name>`\nwhich is used for many of the CppAD examples and tests.\n\nstd\n***\nIf *cppad_testvector* is *std* ,\nthe ``std::vector`` template class is used to define\n``CPPAD_TESTVECTOR`` .\n\ncppad\n*****\nIf *cppad_testvector* is *cppad* ,\nthe :ref:`cppad_vector-name` template class is used to define\n``CPPAD_TESTVECTOR`` .\n\nboost\n*****\nIf *cppad_testvector* is *boost* ,\n`boost ublas vector <https://www.boost.org/doc/libs/1_52_0/libs/numeric/ublas/doc/vector.htm>`_\ntemplate class is used to define\n``CPPAD_TESTVECTOR`` .\nIn this case, the\n`cmake FindBoost <https://cmake.org//cmake/help/cmake2.6docs.html#module:FindBoost>`_\nmodule must be able to automatically figure out where Boost is installed.\n\neigen\n*****\nIf *cppad_testvector* is *eigen* ,\none of the eigen template classes is used to define\n``CPPAD_TESTVECTOR`` .\nIn this case,\n:ref:`cmake@Eigen` must be found and c++14 must be supported.\n\n{xrst_end cppad_testvector}\n"
  },
  {
    "path": "xrst/introduction.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin Introduction}\n{xrst_spell\n    andreas\n    griewank\n}\n\nAn Introduction by Example to Algorithmic Differentiation\n#########################################################\n\nPurpose\n*******\nThis is an introduction by example\nto Algorithmic Differentiation.\nIts purpose is to aid in understand what AD calculates,\nhow the calculations are preformed,\nand the amount of computation and memory required\nfor a forward or reverse sweep.\n\nPreface\n*******\n\nAlgorithmic Differentiation\n===========================\nAlgorithmic Differentiation\n(often referred to as Automatic Differentiation or just AD)\nuses the software representation\nof a function to obtain an efficient method for calculating its derivatives.\nThese derivatives can be of arbitrary order and are analytic in nature\n(do not have any truncation error).\n\nForward Mode\n============\nA forward mode sweep computes\nthe partial derivative of all the dependent variables with respect\nto one independent variable (or independent variable direction).\n\nReverse Mode\n============\nA reverse mode sweep computes\nthe derivative of one dependent variable\n(or one dependent variable direction)\nwith respect to all the independent variables.\n\nOperation Count\n===============\nThe number of floating point operations for either a\nforward or reverse mode sweep\nis a small multiple of the number required to evaluate the original function.\nThus, using reverse mode,\nyou can evaluate the derivative of a scalar valued function\nwith respect to thousands of variables in a small multiple of the\nwork to evaluate the original function.\n\nEfficiency\n==========\nAD automatically takes advantage of the\nspeed of your algorithmic representation of a function.\nFor example,\nif you calculate a determinant using LU factorization,\nAD will use the LU representation for\nthe derivative of the determinant\n(which is faster than using the definition of the determinant).\n\nOutline\n*******\n\nA. get_started\n==============\nSee :ref:`get_started.cpp-name` for an example that uses\nCppAD to calculate derivatives of a polynomial.\n\nB. Example Algorithms\n=====================\nPresent two algorithms that approximate the exponential function.\nThe first algorithm :ref:`exp_2.hpp-name` is simpler and does not\ninclude any logical variables or loops.\nThe second algorithm :ref:`exp_eps.hpp-name` includes\nlogical operations and a ``while`` loop.\n\nC. Example Steps\n================\nFor each of the algorithms, exp_2 and exp_eps, do the following:\n\n#. Define the mathematical function corresponding to the algorithm\n   (:ref:`exp_2-name` and :ref:`exp_eps-name` ).\n#. Write out the floating point operation sequence,\n   and corresponding values,\n   that correspond to executing the algorithm for a specific input\n   (:ref:`exp_2_for0-name` and :ref:`exp_eps_for0-name` ).\n#. Compute a forward sweep derivative of the operation sequence\n   (:ref:`exp_2_for1-name` and :ref:`exp_eps_for1-name` ).\n#. Compute a reverse sweep derivative of the operation sequence\n   (:ref:`exp_2_rev1-name` and :ref:`exp_eps_rev1-name` ).\n#. Use CppAD to compute both a forward and reverse sweep\n   of the operation sequence\n   (:ref:`exp_2_cppad-name` and :ref:`exp_eps_cppad-name` ).\n\nD. Testing Examples\n===================\nThe program :ref:`exp_apx.cpp-name` runs all of the test\nroutines that validate the calculations in the :ref:`exp_2-name`\nand :ref:`exp_eps-name` presentation.\n\nReference\n*********\nAn in-depth review of AD theory and methods can be found in\nthe book\n*Evaluating Derivatives:*\n*Principles and Techniques of Algorithmic Differentiation* ,\nAndreas Griewank,\nSIAM Frontiers in Applied Mathematics,\n2000.\n\nContents\n********\n{xrst_toc_table\n    introduction/exp_2.hpp\n    introduction/exp_eps.hpp\n    introduction/introduction.cpp\n}\n\n{xrst_end Introduction}\n"
  },
  {
    "path": "xrst/lu_det_and_solve.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin lu_det_and_solve}\n\nCompute Determinants and Solve Equations by LU Factorization\n############################################################\n\nContents\n********\n{xrst_toc_table\n    include/cppad/utility/lu_solve.hpp\n    include/cppad/utility/lu_factor.hpp\n    include/cppad/utility/lu_invert.hpp\n}\n\n{xrst_end lu_det_and_solve}\n"
  },
  {
    "path": "xrst/lu_factor_hpp.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin lu_factor.hpp}\n\nSource: LuFactor\n################\n\n| # ``ifndef CPPAD_LU_FACTOR_HPP``\n| # ``define CPPAD_LU_FACTOR_HPP``\n\n{xrst_literal\n    include/cppad/utility/lu_factor.hpp\n    // BEGIN C++\n    // END C++\n}\n\n``# endif``\n\n{xrst_end lu_factor.hpp}\n"
  },
  {
    "path": "xrst/lu_invert_hpp.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin lu_invert.hpp}\n\nSource: LuInvert\n################\n\n| # ``ifndef CPPAD_LU_INVERT_HPP``\n| # ``define CPPAD_LU_INVERT_HPP``\n\n{xrst_literal\n    include/cppad/utility/lu_invert.hpp\n    // BEGIN C++\n    // END C++\n}\n\n``# endif``\n\n{xrst_end lu_invert.hpp}\n"
  },
  {
    "path": "xrst/lu_solve_hpp.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin lu_solve.hpp}\n\nSource: LuSolve\n###############\n\n| # ``ifndef CPPAD_LU_SOLVE_HPP``\n| # ``define CPPAD_LU_SOLVE_HPP``\n\n{xrst_literal\n    include/cppad/utility/lu_solve.hpp\n    // BEGIN C++\n    // END C++\n}\n\n``# endif``\n\n{xrst_end lu_solve.hpp}\n"
  },
  {
    "path": "xrst/mat_sum_sq_hpp.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin mat_sum_sq.hpp}\n\nSource: mat_sum_sq\n##################\n\n| # ``ifndef CPPAD_MAT_SUM_SQ_HPP``\n| # ``define CPPAD_MAT_SUM_SQ_HPP``\n\n{xrst_literal\n    include/cppad/speed/mat_sum_sq.hpp\n    // BEGIN C++\n    // END C++\n}\n\n``# endif``\n\n{xrst_end mat_sum_sq.hpp}\n"
  },
  {
    "path": "xrst/mul_level.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-23 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin mul_level}\n\nUsing Multiple Levels of AD\n###########################\n\nAlternative\n***********\nOften it is easier to use\n:ref:`base2ad-name` and :ref:`dynamic<new_dynamic-name>` parameters\nto accomplish the objective below.\n\nBackground\n**********\nIf *f* is an ``ADFun`` < *Base* > object,\nthe vectors returned by\n:ref:`f.Forward<Forward-name>` ,\nand\n:ref:`f.Reverse<Reverse-name>` ,\nhave values of type *Base* and not\n``AD`` < *Base* > .\nThis reflects the fact that operations used to calculate\nthese function values are not recorded by the tape corresponding to\n``AD`` < *Base* > operations.\n\nMotivation\n**********\nSuppose that you use derivatives of one or more inner functions\nas part of the operations\nneeded to compute an outer function.\nFor example,\nthe derivatives returned by *f* . ``Forward``\nmight be used as part of\nTaylor's method for solving ordinary\ndifferential equations.\nIn addition, we might want to differentiate the\nsolution of a differential equation with respect to parameters\nin the equation.\nThis can be accomplished in the following way:\n\n#. The function defining the\n   differential equation could be calculated using the class\n   ``AD< AD<double> >`` .\n\n#. The operations during the calculation of Taylor's method\n   could be done using the ``AD<double>`` class.\n\n#. Derivatives of the solution of the differential equation\n   could then be calculated using the ``double`` class.\n\nProcedure\n*********\n\nFirst Start AD<double>\n======================\nIf some of the :ref:`parameters<glossary@Parameter>`\nin the ``AD< AD<double> >`` recording depend on the\n:ref:`variables<glossary@Variable>`\nin the ``AD<double>`` recording,\nwe must first declaring these variables; i.e.,\n\n    ``Independent`` ( *a1x* )\n\nwhere *a1x* is\na :ref:`SimpleVector-name` with elements of type ``AD<double>`` .\nThis will start recording a new tape of\noperations performed using ``AD<double>`` class objects.\n\nStart AD< AD<double> > Recording\n================================\nThe next step is to declare the independent variables using\n\n    ``Independent`` ( *a2x* )\n\nwhere *a2x* is\na :ref:`SimpleVector-name` with elements of type\n``AD< AD<double> >`` .\nThis will start recording a new tape of\noperations performed using ``AD< AD<double> >`` class objects.\n\nInner Function\n==============\nThe next step is to calculate the inner function\nusing ``AD< AD<double> >`` class objects.\nWe then stop the recording using\n\n    *a1f* . ``Dependent`` ( *a2x* , *a2y* )\n\nwhere *a2y* is\na :ref:`SimpleVector-name` with elements of type\n``AD< AD<double> >``\nand *a1f* is an ``ADFun< AD<double> >`` object.\n\nSecond Start AD< AD<double> >\n=============================\nIf none of the :ref:`parameters<glossary@Parameter>`\nin the ``AD< AD<double> >`` recording depend on the\n:ref:`variables<glossary@Variable>`\nin the ``AD<double>`` recording,\nit is preferred to delay declaring these variables to this point; i.e.,\n\n    ``Independent`` ( *a1x* )\n\nwhere *a1x* is\na :ref:`SimpleVector-name` with elements of type ``AD<double>`` .\nThis will start recording a new tape of\noperations performed using ``AD<double>`` class objects.\n\nOuter Function\n==============\nThe next step is to calculate the outer function\nusing ``AD<double>`` class objects.\nNote that derivatives of the inner function can be included\nin the calculation of the outer function using *a1f* .\nWe then stop the recording of ``AD<double>`` operations using\n\n    *g* . ``Dependent`` ( *a1x* , *a1y* )\n\nwhere *a1y* is\na :ref:`SimpleVector-name` with elements of type\n``AD<double>``\nand *g* is an ``ADFun<double>`` object.\n\nDerivatives of Outer Function\n=============================\nThe AD function object *g* can then be used to calculate\nthe derivatives of the outer function.\n{xrst_toc_hidden\n    example/general/mul_level.cpp\n    example/general/change_param.cpp\n}\n\nExample\n*******\nThe files\n:ref:`mul_level.cpp-name` and :ref:`change_param.cpp-name`\ncontain an examples and tests of this procedure.\nThey return true if they succeed and false otherwise.\nThe file :ref:`mul_level_ode.cpp-name` is a more complex example\nuse of multiple tapes.\n\n{xrst_end mul_level}\n"
  },
  {
    "path": "xrst/multi_thread.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin multi_thread}\n\nUsing CppAD in a Multi-Threading Environment\n############################################\n\nPurpose\n*******\nExtra steps and care must be taken to use CppAD\nin :ref:`parallel<ta_in_parallel-name>` execution mode.\nThis section collects this information in one place.\n\nCPPAD_MAX_NUM_THREADS\n*********************\nThe value ``CPPAD_MAX_NUM_THREADS`` is an absolute maximum for\nthe number of threads that CppAD should support.\nIf this preprocessor symbol is defined\nbefore including any CppAD header files,\nit must be an integer greater than or equal to one.\nOtherwise, :ref:`cmake@cppad_max_num_threads`\nis used to define this preprocessor symbol.\nNote that the minimum allowable value for\n*cppad_max_num_threads* is 4; i.e., you can only\nget smaller values for ``CPPAD_MAX_NUM_THREADS`` by\ndefining it before including the CppAD header files.\n\nparallel_setup\n**************\nUsing any of the following routines in a multi-threading environment\nrequires that :ref:`thread_alloc::parallel_setup<ta_parallel_setup-name>`\nhas been completed:\n:ref:`CppAD::vector<CppAD_vector@Memory and Parallel Mode>` ,\n:ref:`CheckSimpleVector<CheckSimpleVector@Parallel Mode>` ,\n:ref:`CheckNumericType<CheckNumericType@Parallel Mode>` ,\n:ref:`parallel_ad-name` .\n\nhold_memory\n***********\nMemory allocation should be much faster after calling\n``hold_memory`` with\n:ref:`ta_hold_memory@value` equal to true.\nThis may even be true if there is only one thread.\n\nParallel AD\n***********\nOne must first call\n:ref:`thread_alloc::parallel_setup<ta_parallel_setup-name>`\nand then call :ref:`parallel_ad-name` before using ``AD`` types\nin :ref:`parallel<ta_in_parallel-name>` execution mode.\nIn addition, see :ref:`parallel_ad@Other Initialization` .\n\nSame Thread\n***********\nSome operations must be preformed by the same thread:\n:ref:`ADFun<fun_construct@Parallel Mode>` ,\n:ref:`Independent-name` , :ref:`Dependent-name` .\n\nParallel Prohibited\n*******************\nThe following routine cannot be called in parallel mode:\n:ref:`ErrorHandler constructor<ErrorHandler@Constructor@Parallel Mode>` .\n\nContents\n********\n{xrst_toc_table\n    include/cppad/core/parallel_ad.hpp\n    example/multi_thread/thread_test.cpp\n}\n\n{xrst_end multi_thread}\n"
  },
  {
    "path": "xrst/numeric_type.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n/*\n{xrst_begin NumericType}\n{xrst_spell\n    valarray\n}\n\nDefinition of a Numeric Type\n############################\n\nType Requirements\n*****************\nA *NumericType* is any type\nthat satisfies the requirements below.\nThe following is a list of some numeric types:\n``int`` , ``float`` , ``double`` ,\n``AD<double>`` , ``AD< AD<double> >`` .\nThe routine :ref:`CheckNumericType-name` can be used to check\nthat a type satisfies these conditions.\n\nDefault Constructor\n*******************\nThe syntax\n\n    *NumericType* *x* ;\n\ncreates a *NumericType* object\nwith an unspecified value.\n\nConstructor From Integer\n************************\nIf *i* is an ``int`` ,\nthe syntax\n\n    *NumericType* *x* ( *i* );\n\ncreates a *NumericType* object with a value\nequal to *i* where *i* can be ``const`` .\n\nCopy Constructor\n****************\nIf *x* is a *NumericType* object\nthe syntax\n\n    *NumericType* *y* ( *x* );\n\ncreates a *NumericType* object *y*\nwith the same value as *x*\nwhere *x* can be ``const`` .\n\nAssignment\n**********\nIf *x* and *y* are *NumericType* objects,\nthe syntax\n\n    *x* = *y*\n\nsets the value of *x* equal to the value of *y*\nwhere *y* can be ``const`` .\nThe expression corresponding to this operation is unspecified; i.e.,\nit could be ``void`` and hence\n\n    *x* = *y* = *z*\n\nmay not be legal.\n\nOperators\n*********\nSuppose *x* , *y* and *z* are\n*NumericType* objects where\n*x* and *y* may be ``const`` .\nIn the result type column,\n*NumericType* can be replaced by any type that can\nbe used just like a *NumericType* object.\n\n.. csv-table::\n    :widths: auto\n    :header: Operation, Description, Result Type\n\n    \\+ *x*      , unary plus,                          *NumericType*\n    \\- *x*      , unary minus,                         *NumericType*\n    *x* + *y*   , binary addition,                     *NumericType*\n    *x* - *y*   , binary subtraction,                  *NumericType*\n    *x* \\* *y*  , binary multiplication,               *NumericType*\n    *x* / *y*   , compound assignment division,        *NumericType*\n    *z* += *y*  , compound assignment addition,        *NumericType*\n    *z* -= *y*  , compound assignment subtraction,     *NumericType*\n    *z* \\*= *y* , compound assignment multiplication,  *NumericType*\n    *z* /= *y*  , compound assignment division,        *NumericType*\n\nExample\n*******\n{xrst_toc_hidden\n    example/general/numeric_type.cpp\n}\nThe file\n:ref:`numeric_type.cpp-name`\ncontains an example and test of using numeric types.\n(It is easy to modify to test additional numeric types.)\n\nExercise\n********\n\n#. List three operators that are not supported by every\n   numeric type but that are supported by the numeric types\n   ``int`` ,\n   ``float`` ,\n   ``double`` .\n\n#. Which of the following are numeric types:\n   ``std::complex<double>`` ,\n   ``std::valarray<double>`` ,\n   ``std::vector<double>`` ?\n\n{xrst_end NumericType}\n"
  },
  {
    "path": "xrst/ode_evaluate.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin ode_evaluate.hpp}\n\nSource: ode_evaluate\n####################\n\n| # ``ifndef CPPAD_ODE_EVALUATE_HPP``\n| # ``define CPPAD_ODE_EVALUATE_HPP``\n\n{xrst_literal\n    include/cppad/speed/ode_evaluate.hpp\n    // BEGIN C++\n    // END C++\n}\n\n``# endif``\n\n{xrst_end ode_evaluate.hpp}\n"
  },
  {
    "path": "xrst/poly_hpp.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin poly.hpp}\n\nSource: Poly\n############\n\n| # ``ifndef CPPAD_POLY_HPP``\n| # ``define CPPAD_POLY_HPP``\n\n{xrst_literal\n    include/cppad/utility/poly.hpp\n    // BEGIN C++\n    // END C++\n}\n\n``# endif``\n\n{xrst_end poly.hpp}\n"
  },
  {
    "path": "xrst/preprocessor.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin preprocessor}\n{xrst_spell\n    nullptr\n}\n\nCppAD API Preprocessor Symbols\n##############################\n\nRule\n****\nThe CppAD include files defines preprocessor symbols all of which begin\nwith ``CPPAD_`` .\nNote that there are some old, deprecated preprocessor symbols that\nbegin with ``CppAD`` .\nIn this section we list all of the CppAD preprocessor symbols that\nare part of the CppAD Application Interface (API).\n\nNOMINMAX, windows.h\n*******************\nThere is one exception to the rule above,\nwhen using the Microsoft Visual Studio compiler\nand including ``windows.h`` ,\nit is done as follows:\n::\n\n    # ifndef NOMINMAX\n    # define NOMINMAX\n    # endif\n    # include <windows.h>\n\nDocumented Here\n***************\n\nCPPAD_NULL\n**********\nDeprecated 2020-12-03:\nThis preprocessor symbol was used for a null pointer before c++11.\nReplace it by ``nullptr`` .\n{xrst_comment\n# undef CPPAD_NULL\n}\n\nCPPAD_PACKAGE_STRING\n====================\nIs a ``const char*`` representation of this version of CppAD.\n{xrst_comment\n# undef CPPAD_PACKAGE_STRING\n}\n\nCPPAD_USE_CPLUSPLUS_2011\n************************\nDeprecated 2020-12-03:\nIs it OK for CppAD to use C++11 features. This is always 1 (for true).\n{xrst_comment\n# undef CPPAD_USE_CPLUSPLUS_2011\n}\n\nCPPAD_USE_CPLUSPLUS_2017\n************************\nIs it OK for CppAD to use C++17 features.\n{xrst_comment\n# undef CPPAD_USE_CPLUSPLUS_2017\n}\n\nDocumented Elsewhere\n********************\n\n.. list-table::\n    :widths: auto\n\n    * - :ref:`CPPAD_BOOL_BINARY<bool_fun@Create Binary>`\n    * - :ref:`CPPAD_BOOL_UNARY<bool_fun@Create Unary>`\n    * - :ref:`CPPAD_DISCRETE_FUNCTION<Discrete-name>`\n    * - :ref:`multi_thread@CPPAD_MAX_NUM_THREADS`\n    * - :ref:`base_limits@CPPAD_NUMERIC_LIMITS`\n    * - :ref:`base_std_math@CPPAD_STANDARD_MATH_UNARY`\n    * - :ref:`cmake@cppad_tape_addr_type`\n    * - :ref:`cmake@cppad_tape_id_type`\n    * - :ref:`CPPAD_TESTVECTOR<testvector-name>`\n    * - :ref:`base_to_string@CPPAD_TO_STRING`\n\n{xrst_comment\n# undef CPPAD_BOOL_BINARY\n# undef CPPAD_BOOL_UNARY\n# undef CPPAD_DISCRETE_FUNCTION\n# undef CPPAD_MAX_NUM_THREADS\n# undef CPPAD_NUMERIC_LIMITS\n# undef CPPAD_STANDARD_MATH_UNARY\n# undef CPPAD_TAPE_ADDR_TYPE\n# undef CPPAD_TAPE_ID_TYPE\n# undef CPPAD_TESTVECTOR\n# undef CPPAD_TO_STRING\n}\n\nDeprecated\n==========\n\n.. list-table::\n    :widths: auto\n\n    * - :ref:`CppADCreateDiscrete<Discrete@CppADCreateDiscrete Deprecated 2007-07-28>`\n    * - :ref:`CPPAD_TRACK_NEW_VEC<track_new_del@TrackNewVec@Macro>`\n    * - :ref:`CPPAD_TRACK_DEL_VEC<track_new_del@TrackDelVec@Macro>`\n    * - :ref:`CPPAD_TRACK_EXTEND<track_new_del@TrackExtend@Macro>`\n    * - :ref:`CPPAD_TRACK_COUNT<track_new_del@TrackCount@Macro>`\n    * - :ref:`CppADTrackNewVec<track_new_del@TrackNewVec@Previously Deprecated>`\n    * - :ref:`CppADTrackDelVec<track_new_del@TrackDelVec@Previously Deprecated>`\n    * - :ref:`CppADTrackExtend<track_new_del@TrackExtend@Previously Deprecated>`\n    * - :ref:`CppADTrackCount<track_new_del@TrackCount@Previously Deprecated>`\n    * - :ref:`CppADCreateBinaryBool<bool_fun@Deprecated 2007-07-31>`\n    * - :ref:`CppADCreateUnaryBool<bool_fun@Deprecated 2007-07-31>`\n    * - :ref:`CPPAD_USER_ATOMIC<atomic_one@Deprecated 2013-05-27>`\n    * - :ref:`CPPAD_CPPADVECTOR<testvector@CppAD::vector@CPPAD_CPPADVECTOR, Deprecated 2022-06-22>`\n    * - :ref:`CPPAD_STDVECTOR<testvector@std::vector@CPPAD_STDVECTOR, Deprecated 2022-06-22>`\n    * - :ref:`CPPAD_EIGENVECTOR<testvector@CppAD::eigen_vector@CPPAD_EIGENVECTOR, Deprecated 2022-06-22>`\n    * - :ref:`CPPAD_BOOSTVECTOR<testvector@boost::numeric::ublas::vector@CPPAD_BOOSTVECTOR, Deprecated 2022-06-22>`\n\n{xrst_comment\n# undef CppADCreateDiscrete\n# undef CPPAD_TRACK_NEW_VEC\n# undef CPPAD_TRACK_DEL_VEC\n# undef CPPAD_TRACK_EXTEND\n# undef CPPAD_TRACK_COUNT\n# undef CPPAD_USER_ATOMIC\n# undef CppADTrackNewVec\n# undef CppADTrackDelVec\n# undef CppADTrackExtend\n# undef CppADTrackCount\n# undef CppADCreateBinaryBool\n# undef CppADCreateUnaryBool\n# undef CPPAD_USER_ATOMIC\n# undef CPPAD_CPPADVECTOR\n# undef CPPAD_STDVECTOR\n# undef CPPAD_EIGENVECTOR\n# undef CPPAD_BOOSTVECTOR\n}\n\n{xrst_end preprocessor}\n"
  },
  {
    "path": "xrst/reverse/reverse_any.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin reverse_any}\n{xrst_spell\n    dw\n}\n\nAny Order Reverse Mode\n######################\n\nSyntax\n******\n| *dw* = *f* . ``Reverse`` ( *q* , *w* )\n\nPurpose\n*******\nWe use :math:`F : \\B{R}^n \\rightarrow \\B{R}^m` to denote the\n:ref:`glossary@AD Function` corresponding to *f* .\nReverse mode computes the derivative of the :ref:`Forward-name` mode\n:ref:`Taylor coefficients<glossary@Taylor Coefficient>`\nwith respect to the domain variable :math:`x`.\nTo be specific, it computes the derivative\n:math:`W^{(1)} (u)` at :math:`u = x`\nwhich is specified by the following notation:\n\nNotation\n********\n\nu^(k)\n=====\nFor :math:`k = 0, \\ldots , q-1`,\nthe vector :math:`u^{(k)} \\in \\B{R}^n` is defined as the value of\n*x_k* in the previous calls of the form\n\n    *f* . ``Forward`` ( *k* , *x_k* )\n\nIf there is no previous call with :math:`k = 0`,\n:math:`u^{(0)}` is the value of the independent variables when the\ncorresponding\nAD of *Base*\n:ref:`operation sequence<glossary@Operation@Sequence>` was recorded.\n\nX(t, u)\n=======\nThe function\n:math:`X : \\B{R} \\times \\B{R}^{n \\times q} \\rightarrow \\B{R}^n` is defined by\n\n.. math::\n\n    X ( t , u ) = u^{(0)} + u^{(1)} * t + \\cdots + u^{(q-1)} * t^{q-1}\n\nNote that for :math:`k = 0 , \\ldots , q-1`,\n:math:`u^{(k)}` is related to the *k*-th partial of :math:`X(t, u)`\nwith respect to :math:`t` by\n\n.. math::\n\n    u^{(k)} = \\frac{1}{k !} \\Dpow{k}{t} X(0, u)\n\nY(t, u)\n=======\nThe function\n:math:`Y : \\B{R} \\times \\B{R}^{n \\times q} \\rightarrow \\B{R}^m` is defined by\n\n.. math::\n\n    Y(t, u) = F [ X(t,u) ]\n\nw^(k)\n=====\nIf the argument *w* has size *m* * *q* ,\nfor :math:`k = 0 , \\ldots , q-1` and :math:`i = 0, \\ldots , m-1`,\n\n.. math::\n\n    w_i^{(k)} = w [ i * q + k ]\n\nIf the argument *w* has size *m* ,\nfor :math:`k = 0 , \\ldots , q-1` and :math:`i = 0, \\ldots , m-1`,\n\n.. math::\n\n    w_i^{(k)} = \\left\\{ \\begin{array}{ll}\n        w [ i ] & {\\rm if} \\; k = q-1\n        \\\\\n        0       & {\\rm otherwise}\n    \\end{array} \\right.\n\nW(u)\n====\nThe function :math:`W : \\B{R}^{n \\times q} \\rightarrow \\B{R}` is defined by\n\n.. math::\n\n    W(u) = \\sum_{k=0}^{q-1} ( w^{(k)} )^\\R{T} \\frac{1}{k !} \\Dpow{k}{t} Y(0, u)\n\nf\n*\nThe object *f* has prototype\n\n    ``const ADFun`` < *Base* > *f*\n\nBefore this call to ``Reverse`` , the value returned by\n\n    *f* . ``size_order`` ()\n\nmust be greater than or equal *q*\n(see :ref:`size_order-name` ).\n\nq\n*\nThe argument *q* has prototype\n\n    ``size_t`` *q*\n\nand specifies the number of Taylor coefficient orders to be differentiated\n(for each variable).\n\nw\n*\nThe argument *w* has prototype\n\n    ``const`` *Vector* & *w*\n\n(see :ref:`reverse_any@Vector` below)\nand its size\nmust be equal to *m* or *m* * *q* ,\nIt specifies the weighting vector *w*\nin the definition of\n:ref:`reverse_any@Notation@W(u)` .\n\ndw\n**\nThe return value *dw* has prototype\n\n    *Vector* *dw*\n\n(see :ref:`reverse_any@Vector` below).\nIt is a vector with size :math:`n \\times q`.\nFor :math:`j = 0, \\ldots, n-1` and :math:`k = 0 , \\ldots , q-1`\nIf the argument *w* has size *m* * *q* ,\n\n.. math::\n\n    dw[ j * q + k ] = W^{(1)} ( x )_{j,k}\n\nwhere :math:`u = x` is value of the Taylor coefficients where the\nderivative is evaluated.\n\nIf the argument *w* has size *m* ,\n\n.. math::\n\n    dw[ j * q + q - k - 1 ] = W^{(1)} ( x )_{j,k}\n\nwhere :math:`u = x` is value of the Taylor coefficients where the\nderivative is evaluated.\nNote the reverse order in which the order indices are stored.\nThis is an unfortunate consequence of keeping ``Reverse`` backward\ncompatible.\n\nFirst Order\n***********\nWe consider the case where\n*q*  = 1 and *w* . ``size`` () == *m* .\nIn this case\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    W(u) & = & w_0 Y_0 (0, u) + \\cdots + w_m Y_m (0, u)\n    \\\\\n    W(u) & = & w_0 F_0 [ X(0, u) ] + \\cdots + w_m F_m [ X(0, u) ]\n    \\\\\n    W^{(1)} (x) & = &\n        w_0 F_0^{(1)} ( x^{(0)} ) + \\cdots + w_m F_m^{(1)} ( x^{(0)} )\n    \\end{eqnarray}\n\nThis is the same as the result documented in :ref:`reverse_one-name` .\n\nSecond Order\n************\nWe consider the case where\n*q*  = 2 and *w* . ``size`` () == *m* .\nIn this case\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    W(u) & = & w_0 \\partial_t Y_0 (0, u) + \\cdots + w_m \\partial_t Y_m (0, u)\n    \\\\\n    W(u) & = &\n        w_0 \\partial_t \\{ F_0 [ X(t, u) ] \\}_{t = 0}\n          + \\cdots +\n        w_m \\partial_t \\{ F_m [ X(t, u) ] \\}_{t = 0}\n    \\\\\n    W(u) & = &\n        w_0 F_0^{(1)} ( u^{(0)} ) u^{(1)}\n          + \\cdots +\n        w_0 F_m^{(1)} ( u^{(0)} ) u^{(1)}\n    \\\\\n    \\partial_{u(0)} W(x) & = &\n        w_0 (  x^{(1)} )^\\R{T} F_0^{(2)} ( x^{(0)} )\n        + \\cdots +\n        w_m (  x^{(1)} )^\\R{T} F_m^{(2)} ( x^{(0)} )\n    \\\\\n    \\partial_{u(1)} W(x) & = &\n        w_0 F_0^{(1)} ( x^{(0)} )\n        + \\cdots +\n        w_m F_m^{(1)} ( x^{(0)} )\n    \\end{eqnarray}\n\nwhere :math:`\\partial{u(0)}`\ndenotes partial with respect to :math:`u^{(0)}`.\nThese are the same as the result documented in :ref:`reverse_two-name` .\n\nVector\n******\nThe type *Vector* must be a :ref:`SimpleVector-name` class with\n:ref:`elements of type<SimpleVector@Elements of Specified Type>`\n*Base* .\nThe routine :ref:`CheckSimpleVector-name` will generate an error message\nif this is not the case.\n\nExample\n*******\n{xrst_toc_hidden\n    example/general/reverse_three.cpp\n    example/general/rev_checkpoint.cpp\n}\n\n#. The file :ref:`reverse_three.cpp-name`\n   contains an example and test of using reverse mode\n   to compute third order derivatives.\n#. The file :ref:`rev_checkpoint.cpp-name`\n   contains an example and test of the general reverse mode case.\n\n{xrst_end reverse_any}\n"
  },
  {
    "path": "xrst/reverse/reverse_one.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin reverse_one}\n{xrst_spell\n    dw\n}\n\nFirst Order Reverse Mode\n########################\n\nSyntax\n******\n| *dw* = *f* . ``Reverse`` (1, *w* )\n\nPurpose\n*******\nWe use :math:`F : \\B{R}^n \\rightarrow \\B{R}^m` to denote the\n:ref:`glossary@AD Function` corresponding to *f* .\nThe function :math:`W : \\B{R}^n \\rightarrow \\B{R}` is defined by\n\n.. math::\n\n    W(x) = w_0 * F_0 ( x ) + \\cdots + w_{m-1} * F_{m-1} (x)\n\nThe result of this operation is the derivative\n:math:`dw = W^{(1)} (x)`; i.e.,\n\n.. math::\n\n    dw = w_0 * F_0^{(1)} ( x ) + \\cdots + w_{m-1} * F_{m-1}^{(1)} (x)\n\nNote that if :math:`w` is the *i*-th\n:ref:`glossary@Elementary Vector` ,\n:math:`dw = F_i^{(1)} (x)`.\n\nf\n*\nThe object *f* has prototype\n\n    ``const ADFun`` < *Base* > *f*\n\nBefore this call to ``Reverse`` , the value returned by\n\n    *f* . ``size_order`` ()\n\nmust be greater than or equal one (see :ref:`size_order-name` ).\n\nx\n*\nThe vector *x* in expression for *dw* above\ncorresponds to the previous call to :ref:`forward_zero-name`\nusing this ADFun object *f* ; i.e.,\n\n    *f* . ``Forward`` (0, *x* )\n\nIf there is no previous call with the first argument zero,\nthe value of the :ref:`Independent-name` variables\nduring the recording of the AD sequence of operations is used\nfor *x* .\n\nw\n*\nThe argument *w* has prototype\n\n    ``const`` *Vector* & *w*\n\n(see :ref:`reverse_one@Vector` below)\nand its size\nmust be equal to *m* , the dimension of the\n:ref:`fun_property@Range` space for *f* .\n\ndw\n**\nThe result *dw* has prototype\n\n    *Vector* *dw*\n\n(see :ref:`reverse_one@Vector` below)\nand its value is the derivative :math:`W^{(1)} (x)`.\nThe size of *dw*\nis equal to *n* , the dimension of the\n:ref:`fun_property@Domain` space for *f* .\n\nVector\n******\nThe type *Vector* must be a :ref:`SimpleVector-name` class with\n:ref:`elements of type<SimpleVector@Elements of Specified Type>`\n*Base* .\nThe routine :ref:`CheckSimpleVector-name` will generate an error message\nif this is not the case.\n\nExample\n*******\n{xrst_toc_hidden\n    example/general/reverse_one.cpp\n}\nThe file\n:ref:`reverse_one.cpp-name`\ncontains an example and test of this operation.\n\n{xrst_end reverse_one}\n"
  },
  {
    "path": "xrst/reverse/reverse_two.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin reverse_two}\n{xrst_spell\n    dw\n}\n\nSecond Order Reverse Mode\n#########################\n\nSyntax\n******\n| *dw* = *f* . ``Reverse`` (2, *w* )\n\nPurpose\n*******\nWe use :math:`F : \\B{R}^n \\rightarrow \\B{R}^m` to denote the\n:ref:`glossary@AD Function` corresponding to *f* .\nReverse mode computes the derivative of the :ref:`Forward-name` mode\n:ref:`Taylor coefficients<glossary@Taylor Coefficient>`\nwith respect to the domain variable :math:`x`.\n\nx^(k)\n*****\nFor :math:`k = 0, 1`,\nthe vector :math:`x^{(k)} \\in \\B{R}^n` is defined as the value of\n*x_k* in the previous call (counting this call) of the form\n\n    *f* . ``Forward`` ( *k* , *x_k* )\n\nIf there is no previous call with :math:`k = 0`,\n:math:`x^{(0)}` is the value of the independent variables when the\ncorresponding\nAD of *Base*\n:ref:`operation sequence<glossary@Operation@Sequence>` was recorded.\n\nCapital W\n*********\nThe functions\n:math:`W_0 : \\B{R}^n \\rightarrow \\B{R}` and\n:math:`W_1 : \\B{R}^n \\rightarrow \\B{R}`\nare defined by\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    W_0 ( u ) & = & w_0 * F_0 ( u ) + \\cdots + w_{m-1} * F_{m-1} (u)\n    \\\\\n    W_1 ( u ) & = &\n    w_0 * F_0^{(1)} ( u ) * x^{(1)}\n        + \\cdots + w_{m-1} * F_{m-1}^{(1)} (u) * x^{(1)}\n    \\end{eqnarray}\n\nThis operation computes the derivatives\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    W_0^{(1)} (u) & = &\n        w_0 * F_0^{(1)} ( u ) + \\cdots + w_{m-1} * F_{m-1}^{(1)} (u)\n    \\\\\n    W_1^{(1)} (u) & = &\n        w_0 * \\left( x^{(1)} \\right)^\\R{T} * F_0^{(2)} ( u )\n        + \\cdots +\n        w_{m-1} * \\left( x^{(1)} \\right)^\\R{T} F_{m-1}^{(2)} (u)\n    \\end{eqnarray}\n\nat :math:`u = x^{(0)}`.\n\nf\n*\nThe object *f* has prototype\n\n    ``const ADFun`` < *Base* > *f*\n\nBefore this call to ``Reverse`` , the value returned by\n\n    *f* . ``size_order`` ()\n\nmust be greater than or equal two (see :ref:`size_order-name` ).\n\nLower w\n*******\nThe argument *w* has prototype\n\n    ``const`` *Vector* & *w*\n\n(see :ref:`reverse_two@Vector` below)\nand its size\nmust be equal to *m* , the dimension of the\n:ref:`fun_property@Range` space for *f* .\n\ndw\n**\nThe result *dw* has prototype\n\n    *Vector* *dw*\n\n(see :ref:`reverse_two@Vector` below).\nIt contains both the derivative\n:math:`W^{(1)} (x)` and the derivative :math:`U^{(1)} (x)`.\nThe size of *dw*\nis equal to :math:`n \\times 2`,\nwhere :math:`n` is the dimension of the\n:ref:`fun_property@Domain` space for *f* .\n\nFirst Order Partials\n====================\nFor :math:`j = 0 , \\ldots , n - 1`,\n\n.. math::\n\n    dw [ j * 2 + 0 ]\n    =\n    \\D{ W_0 }{ u_j } \\left( x^{(0)} \\right)\n    =\n    w_0 * \\D{ F_0 }{ u_j } \\left( x^{(0)} \\right)\n    + \\cdots +\n    w_{m-1} * \\D{ F_{m-1} }{ u_j } \\left( x^{(0)} \\right)\n\nThis part of *dw* contains the same values as are returned\nby :ref:`reverse_one-name` .\n\nSecond Order Partials\n=====================\nFor :math:`j = 0 , \\ldots , n - 1`,\n\n.. math::\n\n    dw [ j * 2 + 1 ]\n    =\n    \\D{ W_1 }{ u_j } \\left( x^{(0)} \\right)\n    =\n    \\sum_{\\ell=0}^{n-1} x_\\ell^{(1)} \\left[\n    w_0 * \\DD{ F_0 }{ u_\\ell }{ u_j } \\left( x^{(0)} \\right)\n    + \\cdots +\n    w_{m-1} * \\DD{ F_{m-1} }{ u_\\ell }{ u_j } \\left( x^{(0)} \\right)\n    \\right]\n\nVector\n******\nThe type *Vector* must be a :ref:`SimpleVector-name` class with\n:ref:`elements of type<SimpleVector@Elements of Specified Type>`\n*Base* .\nThe routine :ref:`CheckSimpleVector-name` will generate an error message\nif this is not the case.\n\nHessian Times Direction\n***********************\nSuppose that :math:`w` is the *i*-th elementary vector.\nIt follows that for :math:`j = 0, \\ldots, n-1`\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    dw[ j * 2 + 1 ]\n    & = &\n    w_i \\sum_{\\ell=0}^{n-1}\n    \\DD{F_i}{ u_j }{ u_\\ell } \\left( x^{(0)} \\right) x_\\ell^{(1)}\n    \\\\\n    & = &\n    \\left[ F_i^{(2)} \\left( x^{(0)} \\right) * x^{(1)} \\right]_j\n    \\end{eqnarray}\n\nThus the vector :math:`( dw[1], dw[3], \\ldots , dw[ n * q - 1 ] )`\nis equal to the Hessian of :math:`F_i (x)` times the direction\n:math:`x^{(1)}`.\nIn the special case where\n:math:`x^{(1)}` is the *l*-th\n:ref:`glossary@Elementary Vector` ,\n\n.. math::\n\n    dw[ j * 2 + 1 ] = \\DD{ F_i }{ x_j }{ x_\\ell } \\left( x^{(0)} \\right)\n\nExample\n*******\n{xrst_toc_hidden\n    example/general/reverse_two.cpp\n    example/general/hes_times_dir.cpp\n}\nThe files\n:ref:`reverse_two.cpp-name`\nand\n:ref:`hes_times_dir.cpp-name`\ncontain a examples and tests of reverse mode calculations.\nThey return true if they succeed and false otherwise.\n\n{xrst_end reverse_two}\n"
  },
  {
    "path": "xrst/simple_vector.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n/*\n{xrst_begin SimpleVector}\n{xrst_spell\n    valarray\n}\n\nC++ Concept: A Simple Vector\n############################\n\nTemplate Class Requirements\n***************************\nA simple vector template class *SimpleVector* ,\nis any template class\nthat satisfies the requirements below.\nThe following is a list of some simple vector template classes:\n\n.. list-table::\n    :widths: auto\n\n    * - **Name**\n      - **Documentation**\n    * - ``std::vector``\n      - Section 16.3 of\n         :ref:`Bib@The C++ Programming Language`\n    * - ``std::valarray``\n      - Section 22.4 of\n         :ref:`Bib@The C++ Programming Language`\n    * - ``CppAD::vector``\n      - :ref:`CppAD_vector-title`\n\nElements of Specified Type\n**************************\nA simple vector class with elements of type *Scalar* ,\nis any class that satisfies the requirements for a class of the form\n\n    *SimpleVector* < *Scalar* >\n\nThe routine :ref:`CheckSimpleVector-name` can be used to check\nthat a class is a simple vector class with a specified element type.\n\nDefault Constructor\n*******************\nThe syntax\n\n    *SimpleVector* < *Scalar* > *x* ;\n\ncreates an empty vector *x* ( *x* . ``size`` () is zero)\nthat can later contain elements of the specified type\n(see :ref:`SimpleVector@resize` below).\n\nSizing Constructor\n******************\nIf *n* has type ``size_t`` ,\n\n    *SimpleVector* < *Scalar* > *x* ( *n* )\n\ncreates a vector *x* with *n* elements\neach of the specified type.\n\nCopy Constructor\n****************\nIf *x* is a *SimpleVector* < *Scalar* > object,\n\n    *SimpleVector* < *Scalar* > *y* ( *x* )\n\ncreates a vector with the same type and number of elements\nas *x* .\nThe *Scalar* assignment operator ( ``=`` )\nis used to set each element of *y*\nequal to the corresponding element of *x* .\nThis is a `deep copy' in that the values of the elements\nof *x* and *y* can be set independently after the copy.\nThe argument *x* is passed by reference\nand may be ``const`` .\n\nElement Constructor and Destructor\n**********************************\nThe default constructor for type *Scalar* is called\nfor every element in a vector when the vector element is created.\nThe *Scalar* destructor is called when it is removed\nfrom the vector (this includes when the vector is destroyed).\n\nAssignment\n**********\nIf *x* and *y* are\n*SimpleVector* < *Scalar* > objects,\n\n    *y* = *x*\n\nuses the *Scalar* assignment operator ( ``=`` )\nto set each element of *y* equal to\nthe corresponding element of *x* .\nThis is a `deep assignment' in that the values of the elements\nof *x* and *y* can be set independently after the assignment.\nThe vectors *x* and *y* must have\nthe same number of elements.\nThe argument *x* is passed by reference\nand may be ``const`` .\n\nThe type returned by this assignment is unspecified; for example,\nit might be void in which case the syntax\n\n    *z* = *y* = *x*\n\nwould not be valid.\n\nsize\n****\nIf *x* is a *SimpleVector* < *Scalar* > object\nand ``n`` has type ``size_t`` ,\n\n    *n* = ``size_t`` ( *x* . ``size`` () )\n\nsets *n* to the number of elements in the vector *x* .\nThe object *x* may be ``const`` .\n\nresize\n******\nIf *x* is a *SimpleVector* < *Scalar* > object\nand ``n`` has type ``size_t`` ,\n\n    *x* . ``resize`` ( *n* )\n\nchanges the number of elements contained in the vector *x*\nto be *n* .\nThe value of the elements of *x*\nare not specified after this operation; i.e.,\nany values previously stored in *x* are lost.\n(The object *x* can not be ``const`` .)\n\nvalue_type\n**********\nIf *Vector* is any simple vector class,\nthe syntax\n\n    *Vector* :: ``value_type``\n\nis the type of the elements corresponding to the vector class; i.e.,\n\n    *SimpleVector* < *Scalar* >:: ``value_type``\n\nis equal to *Scalar* .\n\nElement Access\n**************\nIf *x* is a *SimpleVector* < *Scalar* > object\nand *i* has type ``size_t`` ,\n\n    *x* [ *i* ]\n\nreturns an object of an unspecified type,\nreferred to here as *elementType* .\n\nUsing Value\n===========\nIf *elementType* is not the same as *Scalar* ,\nthe conversion operator\n\n    ``static_cast`` < *Scalar* >( *x* [ *i* ])\n\nis used implicitly when *x* [ *i* ] is used in an expression\nwith values of type *Scalar* .\nFor this type of usage, the object *x* may be ``const`` .\n\nAssignment\n==========\nIf *y* is an object of type *Scalar* ,\n\n    *x* [ *i* ] = *y*\n\nassigns the *i*-th element of *x* to have value *y* .\nFor this type of usage, the object *x* can not be ``const`` .\nThe type returned by this assignment is unspecified; for example,\nit might be void in which case the syntax\n\n    *z* = *x* [ *i* ] = *y*\n\nwould not be valid.\n\nExample\n*******\n{xrst_toc_hidden\n    example/utility/simple_vector.cpp\n}\nThe file\n:ref:`simple_vector.cpp-name`\ncontains an example and test of a Simple template class.\n(It is easy to modify to test additional simple vector template classes.)\n\nExercise\n********\n\n#. If *Vector* is a simple vector template class,\n   the following code may not be valid:\n\n    | |tab| *Vector* < ``double> x`` (2);\n    | |tab| ``x`` [2] = 1.;\n\n    Create and run a program that executes the code segment\n    above where *Vector* is each of the following cases:\n    ``std::vector`` ,\n    ``CppAD::vector`` .\n    Do this both where the compiler option\n    ``-DNDEBUG`` is and is not present on the compilation command line.\n#. If *Vector* is a simple vector template class,\n   the following code may not be valid:\n\n    | |tab| *Vector* < ``int> x`` (2);\n    | |tab| *Vector* < ``int> y`` (1);\n    | |tab| ``x`` [0] = 0;\n    | |tab| ``x`` [1] = 1;\n    | |tab| ``y`` = ``x`` ;\n\n    Create and run a program that executes the code segment\n    above where *Vector* is each of the following cases:\n    ``std::valarray`` ,\n    ``CppAD::vector`` .\n    Do this both where the compiler option\n    ``-DNDEBUG`` is and is not present on the compilation command line.\n\n{xrst_end SimpleVector}\n"
  },
  {
    "path": "xrst/sparse_hes_fun.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin sparse_hes_fun.hpp}\n\nSource: sparse_hes_fun\n######################\n\n| # ``ifndef CPPAD_SPARSE_HES_FUN_HPP``\n| # ``define CPPAD_SPARSE_HES_FUN_HPP``\n\n{xrst_literal\n    include/cppad/speed/sparse_hes_fun.hpp\n    // BEGIN C++\n    // END C++\n}\n\n``# endif``\n\n{xrst_end sparse_hes_fun.hpp}\n"
  },
  {
    "path": "xrst/sparse_jac_fun.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin sparse_jac_fun.hpp}\n\nSource: sparse_jac_fun\n######################\n\n| # ``ifndef CPPAD_SPARSE_JAC_FUN_HPP``\n| # ``define CPPAD_SPARSE_JAC_FUN_HPP``\n\n{xrst_literal\n    include/cppad/speed/sparse_jac_fun.hpp\n    // BEGIN C++\n    // END C++\n}\n\n``# endif``\n\n{xrst_end sparse_jac_fun.hpp}\n"
  },
  {
    "path": "xrst/theory/acos_forward.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin acos_forward}\n{xrst_spell\n    acosh\n}\n\nInverse Cosine and Hyperbolic Cosine Forward Mode Theory\n########################################################\n\nDerivatives\n***********\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    \\R{acos}^{(1)} (x)  & = & - 1 / \\sqrt{ 1 - x * x }\n    \\\\\n    \\R{acosh}^{(1)} (x) & = & + 1 / \\sqrt{ x * x - 1}\n    \\end{eqnarray}\n\nIf :math:`F(x)` is :math:`\\R{acos} (x)` or :math:`\\R{acosh} (x)`\nthe corresponding derivative satisfies the equation\n\n.. math::\n\n    \\sqrt{ \\mp ( x * x - 1 ) } * F^{(1)} (x) - 0 * F (u)  = \\mp 1\n\nand in the\n:ref:`standard math function differential equation<forward_theory@Standard Math Functions@Differential Equation>` ,\n:math:`A(x) = 0`,\n:math:`B(x) = \\sqrt{ \\mp( x * x - 1 ) }`,\nand :math:`D(x) = \\mp 1`.\nWe use :math:`a`, :math:`b`, :math:`d` and :math:`z` to denote the\nTaylor coefficients for\n:math:`A [ X (t) ]`,\n:math:`B [ X (t) ]`,\n:math:`D [ X (t) ]`,\nand :math:`F [ X(t) ]` respectively.\n\nTaylor Coefficients Recursion\n*****************************\nWe define :math:`Q(x) = \\mp ( x * x - 1 )`\nand let :math:`q` be the corresponding Taylor coefficients for\n:math:`Q[ X(t) ]`.\nIt follows that\n\n.. math::\n\n    q^{(j)} = \\left\\{ \\begin{array}{ll}\n        \\mp ( x^{(0)} * x^{(0)} - 1 )      & {\\rm if} \\; j = 0 \\\\\n        \\mp \\sum_{k=0}^j x^{(k)} x^{(j-k)} & {\\rm otherwise}\n    \\end{array} \\right.\n\nIt follows that\n:math:`B[ X(t) ] = \\sqrt{ Q[ X(t) ] }` and\nfrom the equations for the\n:ref:`square root<sqrt_forward-name>`\nthat for :math:`j = 0 , 1, \\ldots`,\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    b^{(0)}   & = & \\sqrt{ q^{(0)} }\n    \\\\\n    b^{(j+1)} & = &\n        \\frac{1}{j+1} \\frac{1}{ b^{(0)} }\n        \\left(\n            \\frac{j+1}{2} q^{(j+1) }\n            - \\sum_{k=1}^j k b^{(k)} b^{(j+1-k)}\n        \\right)\n    \\end{eqnarray}\n\nIt now follows from the general\n:ref:`forward_theory@Standard Math Functions@Taylor Coefficients Recursion Formula`\nthat for :math:`j = 0 , 1, \\ldots`,\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    z^{(0)} & = & F ( x^{(0)} )\n    \\\\\n    e^{(j)}\n    & = & d^{(j)} + \\sum_{k=0}^{j} a^{(j-k)} * z^{(k)}\n    \\\\\n    & = & \\left\\{ \\begin{array}{ll}\n        \\mp 1 & {\\rm if} \\; j = 0 \\\\\n        0 & {\\rm otherwise}\n    \\end{array} \\right.\n    \\\\\n    z^{(j+1)} & = & \\frac{1}{j+1} \\frac{1}{ b^{(0)} }\n    \\left(\n        \\sum_{k=0}^j e^{(k)} (j+1-k) x^{(j+1-k)}\n        - \\sum_{k=1}^j b^{(k)} (j+1-k) z^{(j+1-k)}\n    \\right)\n    \\\\\n    z^{(j+1)} & = & \\frac{1}{j+1} \\frac{1}{ b^{(0)} }\n    \\left(\n        \\mp (j+1) x^{(j+1)}\n        - \\sum_{k=1}^j k z^{(k)}  b^{(j+1-k)}\n    \\right)\n    \\end{eqnarray}\n\n{xrst_end acos_forward}\n"
  },
  {
    "path": "xrst/theory/acos_reverse.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin acos_reverse}\n{xrst_spell\n    acosh\n}\n\nInverse Cosine and Hyperbolic Cosine Reverse Mode Theory\n########################################################\n\nWe use the reverse theory\n:ref:`standard math function<reverse_theory@Standard Math Functions>`\ndefinition for the functions :math:`H` and :math:`G`.\nIn addition, we use the forward mode notation in\n:ref:`acos_forward-name` for\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        Q(t) & = & \\mp ( X(t) * X(t) - 1 ) \\\\\n        B(t) & = & \\sqrt{ Q(t) }\n    \\end{eqnarray}\n\nWe use :math:`q` and :math:`b`\nfor the *p*-th order Taylor coefficient\nrow vectors corresponding to these functions\nand replace :math:`z^{(j)}` by\n\n.. math::\n\n    ( z^{(j)} , b^{(j)} )\n\nin the definition for :math:`G` and :math:`H`.\nThe zero order forward mode formulas for the\n:ref:`acos<acos_forward-name>`\nfunction are\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        q^{(0)}  & = & \\mp ( x^{(0)} x^{(0)} - 1) \\\\\n        b^{(0)}  & = & \\sqrt{ q^{(0)} }    \\\\\n        z^{(0)}  & = & F ( x^{(0)} )\n    \\end{eqnarray}\n\nwhere :math:`F(x) = \\R{acos} (x)` for :math:`-`\nand :math:`F(x) = \\R{acosh} (x)` for :math:`+`.\nFor orders :math:`j` greater than zero we have\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    q^{(j)} & = &\n        \\mp \\sum_{k=0}^j x^{(k)} x^{(j-k)}\n    \\\\\n    b^{(j)} & = &\n        \\frac{1}{j} \\frac{1}{ b^{(0)} }\n        \\left(\n            \\frac{j}{2} q^{(j)}\n            - \\sum_{k=1}^{j-1} k b^{(k)} b^{(j-k)}\n        \\right)\n    \\\\\n    z^{(j)} & = & \\frac{1}{j} \\frac{1}{ b^{(0)} }\n    \\left(\n        \\mp j x^{(j)}\n        - \\sum_{k=1}^{j-1} k z^{(k)}  b^{(j-k)}\n    \\right)\n    \\end{eqnarray}\n\nIf :math:`j = 0`, we note that\n:math:`F^{(1)} ( x^{(0)} ) =  \\mp 1 / b^{(0)}` and hence\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    \\D{H}{ x^{(j)} } & = &\n    \\D{G}{ x^{(j)} }\n    + \\D{G}{ z^{(j)} } \\D{ z^{(j)} }{ x^{(0)} }\n    + \\D{G}{ b^{(j)} } \\D{ b^{(j)} }{ q^{(0)} } \\D{ q^{(0)} }{ x^{(0)} }\n    \\\\\n    & = &\n    \\D{G}{ x^{(j)} }\n    \\mp \\D{G}{ z^{(j)} } \\frac{1}{ b^{(0)} }\n    \\mp \\D{G}{ b^{(j)} } \\frac{ x^{(0)} }{ b^{(0)} }\n    \\end{eqnarray}\n\nIf :math:`j > 0`, then for :math:`k = 1, \\ldots , j-1`\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    \\D{H}{ b^{(0)} } & = &\n    \\D{G}{ b^{(0)} }\n    + \\D{G}{ z^{(j)} } \\D{ z^{(j)} }{ b^{(0)} }\n    + \\D{G}{ b^{(j)} } \\D{ b^{(j)} }{ b^{(0)} }\n    \\\\\n    & = &\n    \\D{G}{ b^{(0)} }\n    - \\D{G}{ z^{(j)} } \\frac{ z^{(j)} }{ b^{(0)} }\n    - \\D{G}{ b^{(j)} } \\frac{ b^{(j)} }{ b^{(0)} }\n    \\\\\n    \\D{H}{ x^{(0)} } & = &\n    \\D{G}{ x^{(0)} }\n    +\n    \\D{G}{ b^{(j)} } \\D{ b^{(j)} }{ q^{(j)} } \\D{ q^{(j)} }{ x^{(0)} }\n    \\\\\n    & = &\n    \\D{G}{ x^{(0)} }\n    \\mp \\D{G}{ b^{(j)} } \\frac{ x^{(j)} }{ b^{(0)} }\n    \\\\\n    \\D{H}{ x^{(j)} } & = &\n    \\D{G}{ x^{(j)} }\n    + \\D{G}{ z^{(j)} } \\D{ z^{(j)} }{ x^{(j)} }\n    + \\D{G}{ b^{(j)} } \\D{ b^{(j)} }{ q^{(j)} } \\D{ q^{(j)} }{ x^{(j)} }\n    \\\\\n    & = &\n    \\D{G}{ x^{(j)} }\n    \\mp \\D{G}{ z^{(j)} } \\frac{1}{ b^{(0)} }\n    \\mp \\D{G}{ b^{(j)} } \\frac{ x^{(0)} }{ b^{(0)} }\n    \\\\\n    \\D{H}{ b^{(j - k)} } & = &\n    \\D{G}{ b^{(j - k)} }\n    + \\D{G}{ z^{(j)} } \\D{ z^{(j)} }{ b^{(j - k)} }\n    + \\D{G}{ b^{(j)} } \\D{ b^{(j)} }{ b^{(j - k)} }\n    \\\\\n    & = &\n    \\D{G}{ b^{(j - k)} }\n    - \\D{G}{ z^{(j)} } \\frac{k z^{(k)} }{j b^{(0)} }\n    - \\D{G}{ b^{(j)} } \\frac{ b^{(k)} }{ b^{(0)} }\n    \\\\\n    \\D{H}{ x^{(k)} } & = &\n    \\D{G}{ x^{(k)} }\n    + \\D{G}{ z^{(j)} } \\D{ z^{(j)} }{ x^{(k)} }\n    + \\D{G}{ b^{(j)} } \\D{ b^{(j)} }{ q^{(j)} } \\D{ q^{(j)} }{ x^{(k)} }\n    \\\\\n    & = &\n    \\D{G}{ x^{(k)} }\n    \\mp \\D{G}{ b^{(j)} } \\frac{ x^{(j-k)} }{ b^{(0)} }\n    \\\\\n    \\D{H}{ z^{(k)} } & = &\n    \\D{G}{ z^{(k)} }\n    + \\D{G}{ z^{(j)} } \\D{ z^{(j)} }{ z^{(k)} }\n    + \\D{G}{ b^{(j)} } \\D{ b^{(j)} }{ z^{(k)} }\n    \\\\\n    & = &\n    \\D{G}{ z^{(k)} }\n    - \\D{G}{ z^{(j)} } \\frac{k b^{(j-k)} }{ j b^{(0)} }\n    \\end{eqnarray}\n\n{xrst_end acos_reverse}\n"
  },
  {
    "path": "xrst/theory/asin_forward.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin asin_forward}\n{xrst_spell\n    asinh\n}\n\nInverse Sine and Hyperbolic Sine Forward Mode Theory\n####################################################\n\nDerivatives\n***********\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    \\R{asin}^{(1)} (x)  & = & 1 / \\sqrt{ 1 - x * x }\n    \\\\\n    \\R{asinh}^{(1)} (x) & = & 1 / \\sqrt{ 1 + x * x }\n    \\end{eqnarray}\n\nIf :math:`F(x)` is :math:`\\R{asin} (x)` or :math:`\\R{asinh} (x)`\nthe corresponding derivative satisfies the equation\n\n.. math::\n\n    \\sqrt{ 1 \\mp x * x } * F^{(1)} (x) - 0 * F (u)  = 1\n\nand in the\n:ref:`standard math function differential equation<forward_theory@Standard Math Functions@Differential Equation>` ,\n:math:`A(x) = 0`,\n:math:`B(x) = \\sqrt{1 \\mp x * x }`,\nand :math:`D(x) = 1`.\nWe use :math:`a`, :math:`b`, :math:`d` and :math:`z` to denote the\nTaylor coefficients for\n:math:`A [ X (t) ]`,\n:math:`B [ X (t) ]`,\n:math:`D [ X (t) ]`,\nand :math:`F [ X(t) ]` respectively.\n\nTaylor Coefficients Recursion\n*****************************\nWe define :math:`Q(x) = 1 \\mp x * x`\nand let :math:`q` be the corresponding Taylor coefficients for\n:math:`Q[ X(t) ]`.\nIt follows that\n\n.. math::\n\n    q^{(j)} = \\left\\{ \\begin{array}{ll}\n        1 \\mp x^{(0)} * x^{(0)}            & {\\rm if} \\; j = 0 \\\\\n        \\mp \\sum_{k=0}^j x^{(k)} x^{(j-k)} & {\\rm otherwise}\n    \\end{array} \\right.\n\nIt follows that\n:math:`B[ X(t) ] = \\sqrt{ Q[ X(t) ] }` and\nfrom the equations for the\n:ref:`square root<sqrt_forward-name>`\nthat for :math:`j = 0 , 1, \\ldots`,\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    b^{(0)}   & = & \\sqrt{ q^{(0)} }\n    \\\\\n    b^{(j+1)} & = &\n        \\frac{1}{j+1} \\frac{1}{ b^{(0)} }\n        \\left(\n            \\frac{j+1}{2} q^{(j+1) }\n            - \\sum_{k=1}^j k b^{(k)} b^{(j+1-k)}\n        \\right)\n    \\end{eqnarray}\n\nIt now follows from the general\n:ref:`forward_theory@Standard Math Functions@Taylor Coefficients Recursion Formula`\nthat for :math:`j = 0 , 1, \\ldots`,\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    z^{(0)} & = & F ( x^{(0)} )\n    \\\\\n    e^{(j)}\n    & = & d^{(j)} + \\sum_{k=0}^{j} a^{(j-k)} * z^{(k)}\n    \\\\\n    & = & \\left\\{ \\begin{array}{ll}\n        1 & {\\rm if} \\; j = 0 \\\\\n        0 & {\\rm otherwise}\n    \\end{array} \\right.\n    \\\\\n    z^{(j+1)} & = & \\frac{1}{j+1} \\frac{1}{ b^{(0)} }\n    \\left(\n        \\sum_{k=0}^j e^{(k)} (j+1-k) x^{(j+1-k)}\n        - \\sum_{k=1}^j b^{(k)} (j+1-k) z^{(j+1-k)}\n    \\right)\n    \\\\\n    z^{(j+1)} & = & \\frac{1}{j+1} \\frac{1}{ b^{(0)} }\n    \\left(\n        (j+1) x^{(j+1)}\n        - \\sum_{k=1}^j k z^{(k)}  b^{(j+1-k)}\n    \\right)\n    \\end{eqnarray}\n\n{xrst_end asin_forward}\n"
  },
  {
    "path": "xrst/theory/asin_reverse.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin asin_reverse}\n{xrst_spell\n    asinh\n}\n\nInverse Sine and Hyperbolic Sine Reverse Mode Theory\n####################################################\n\nWe use the reverse theory\n:ref:`standard math function<reverse_theory@Standard Math Functions>`\ndefinition for the functions :math:`H` and :math:`G`.\nIn addition, we use the forward mode notation in\n:ref:`asin_forward-name` for\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        Q(t) & = & 1 \\mp X(t) * X(t) \\\\\n        B(t) & = & \\sqrt{ Q(t) }\n    \\end{eqnarray}\n\nWe use :math:`q` and :math:`b`\nfor the *p*-th order Taylor coefficient\nrow vectors corresponding to these functions\nand replace :math:`z^{(j)}` by\n\n.. math::\n\n    ( z^{(j)} , b^{(j)} )\n\nin the definition for :math:`G` and :math:`H`.\nThe zero order forward mode formulas for the\n:ref:`asin<asin_forward-name>`\nfunction are\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        q^{(0)}  & = & 1 \\mp x^{(0)} x^{(0)} \\\\\n        b^{(0)}  & = & \\sqrt{ q^{(0)} }    \\\\\n        z^{(0)}  & = & F( x^{(0)} )\n    \\end{eqnarray}\n\nwhere :math:`F(x) = \\R{asin} (x)` for :math:`-`\nand :math:`F(x) = \\R{asinh} (x)` for :math:`+`.\nFor the orders :math:`j` greater than zero we have\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    q^{(j)} & = &\n        \\mp \\sum_{k=0}^j x^{(k)} x^{(j-k)}\n    \\\\\n    b^{(j)} & = &\n        \\frac{1}{j} \\frac{1}{ b^{(0)} }\n        \\left(\n            \\frac{j}{2} q^{(j)}\n            - \\sum_{k=1}^{j-1} k b^{(k)} b^{(j-k)}\n        \\right)\n    \\\\\n    z^{(j)} & = & \\frac{1}{j} \\frac{1}{ b^{(0)} }\n    \\left(\n        j x^{(j)}\n        - \\sum_{k=1}^{j-1} k z^{(k)}  b^{(j-k)}\n    \\right)\n    \\end{eqnarray}\n\nIf :math:`j = 0`, we note that\n:math:`F^{(1)} ( x^{(0)} ) =  1 / b^{(0)}` and hence\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    \\D{H}{ x^{(j)} } & = &\n    \\D{G}{ x^{(j)} }\n    + \\D{G}{ z^{(j)} } \\D{ z^{(j)} }{ x^{(0)} }\n    + \\D{G}{ b^{(j)} } \\D{ b^{(j)} }{ q^{(0)} } \\D{ q^{(0)} }{ x^{(0)} }\n    \\\\\n    & = &\n    \\D{G}{ x^{(j)} }\n    + \\D{G}{ z^{(j)} } \\frac{1}{ b^{(0)} }\n    \\mp \\D{G}{ b^{(j)} } \\frac{ x^{(0)} }{ b^{(0)} }\n    \\end{eqnarray}\n\nIf :math:`j > 0`, then for :math:`k = 1, \\ldots , j-1`\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    \\D{H}{ b^{(0)} } & = &\n    \\D{G}{ b^{(0)} }\n    + \\D{G}{ z^{(j)} } \\D{ z^{(j)} }{ b^{(0)} }\n    + \\D{G}{ b^{(j)} } \\D{ b^{(j)} }{ b^{(0)} }\n    \\\\\n    & = &\n    \\D{G}{ b^{(0)} }\n    - \\D{G}{ z^{(j)} } \\frac{ z^{(j)} }{ b^{(0)} }\n    - \\D{G}{ b^{(j)} } \\frac{ b^{(j)} }{ b^{(0)} }\n    \\\\\n    \\D{H}{ x^{(0)} } & = &\n    \\D{G}{ x^{(0)} }\n    +\n    \\D{G}{ b^{(j)} } \\D{ b^{(j)} }{ q^{(j)} } \\D{ q^{(j)} }{ x^{(0)} }\n    \\\\\n    & = &\n    \\D{G}{ x^{(0)} }\n    \\mp \\D{G}{ b^{(j)} } \\frac{ x^{(j)} }{ b^{(0)} }\n    \\\\\n    \\D{H}{ x^{(j)} } & = &\n    \\D{G}{ x^{(j)} }\n    + \\D{G}{ z^{(j)} } \\D{ z^{(j)} }{ x^{(j)} }\n    + \\D{G}{ b^{(j)} } \\D{ b^{(j)} }{ q^{(j)} } \\D{ q^{(j)} }{ x^{(j)} }\n    \\\\\n    & = &\n    \\D{G}{ x^{(j)} }\n    + \\D{G}{ z^{(j)} } \\frac{1}{ b^{(0)} }\n    \\mp \\D{G}{ b^{(j)} } \\frac{ x^{(0)} }{ b^{(0)} }\n    \\\\\n    \\D{H}{ b^{(j - k)} } & = &\n    \\D{G}{ b^{(j - k)} }\n    + \\D{G}{ z^{(j)} } \\D{ z^{(j)} }{ b^{(j - k)} }\n    + \\D{G}{ b^{(j)} } \\D{ b^{(j)} }{ b^{(j - k)} }\n    \\\\\n    & = &\n    \\D{G}{ b^{(j - k)} }\n    - \\D{G}{ z^{(j)} } \\frac{k z^{(k)} }{j b^{(0)} }\n    - \\D{G}{ b^{(j)} } \\frac{ b^{(k)} }{ b^{(0)} }\n    \\\\\n    \\D{H}{ x^{(k)} } & = &\n    \\D{G}{ x^{(k)} }\n    + \\D{G}{ z^{(j)} } \\D{ z^{(j)} }{ x^{(k)} }\n    + \\D{G}{ b^{(j)} } \\D{ b^{(j)} }{ q^{(j)} } \\D{ q^{(j)} }{ x^{(k)} }\n    \\\\\n    & = &\n    \\D{G}{ x^{(k)} }\n    \\mp \\D{G}{ b^{(j)} } \\frac{ x^{(j-k)} }{ b^{(0)} }\n    \\\\\n    \\D{H}{ z^{(k)} } & = &\n    \\D{G}{ z^{(k)} }\n    + \\D{G}{ z^{(j)} } \\D{ z^{(j)} }{ z^{(k)} }\n    + \\D{G}{ b^{(j)} } \\D{ b^{(j)} }{ z^{(k)} }\n    \\\\\n    & = &\n    \\D{G}{ z^{(k)} }\n    - \\D{G}{ z^{(j)} } \\frac{k b^{(j-k)} }{ j b^{(0)} }\n    \\end{eqnarray}\n\n{xrst_end asin_reverse}\n"
  },
  {
    "path": "xrst/theory/atan_forward.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin atan_forward}\n\nInverse Tangent and Hyperbolic Tangent Forward Mode Theory\n##########################################################\n\nDerivatives\n***********\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    \\R{atan}^{(1)} (x)  & = & 1 / ( 1 + x * x )\n    \\\\\n    \\R{atanh}^{(1)} (x) & = & 1 / ( 1 - x * x )\n    \\end{eqnarray}\n\nIf :math:`F(x)` is :math:`\\R{atan} (x)` or :math:`\\R{atanh} (x)`,\nthe corresponding derivative satisfies the equation\n\n.. math::\n\n    (1 \\pm x * x ) * F^{(1)} (x) - 0 * F (x)  = 1\n\nand in the\n:ref:`standard math function differential equation<forward_theory@Standard Math Functions@Differential Equation>` ,\n:math:`A(x) = 0`,\n:math:`B(x) = 1 \\pm x * x`,\nand :math:`D(x) = 1`.\nWe use :math:`a`, :math:`b`, :math:`d` and :math:`z` to denote the\nTaylor coefficients for\n:math:`A [ X (t) ]`,\n:math:`B [ X (t) ]`,\n:math:`D [ X (t) ]`,\nand :math:`F [ X(t) ]` respectively.\n\nTaylor Coefficients Recursion\n*****************************\nFor :math:`j = 0 , 1, \\ldots`,\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    z^{(0)} & = & F( x^{(0)} )\n    \\\\\n    b^{(j)}\n    & = &  \\left\\{ \\begin{array}{ll}\n        1 \\pm x^{(0)} * x^{(0)}            & {\\rm if} \\; j = 0 \\\\\n        \\pm \\sum_{k=0}^j x^{(k)} x^{(j-k)} & {\\rm otherwise}\n    \\end{array} \\right.\n    \\\\\n    e^{(j)}\n    & = & d^{(j)} + \\sum_{k=0}^{j} a^{(j-k)} * z^{(k)}\n    \\\\\n    & = & \\left\\{ \\begin{array}{ll}\n        1 & {\\rm if} \\; j = 0 \\\\\n        0 & {\\rm otherwise}\n    \\end{array} \\right.\n    \\\\\n    z^{(j+1)} & = & \\frac{1}{j+1} \\frac{1}{ b^{(0)} }\n    \\left(\n        \\sum_{k=0}^j e^{(k)} (j+1-k) x^{(j+1-k)}\n        - \\sum_{k=1}^j b^{(k)} (j+1-k) z^{(j+1-k)}\n    \\right)\n    \\\\\n    z^{(j+1)} & = & \\frac{1}{j+1} \\frac{1}{ b^{(0)} }\n    \\left(\n        (j+1) x^{(j+1)}\n        - \\sum_{k=1}^j k z^{(k)}  b^{(j+1-k)}\n    \\right)\n    \\end{eqnarray}\n\n{xrst_end atan_forward}\n"
  },
  {
    "path": "xrst/theory/atan_reverse.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin atan_reverse}\n\nInverse Tangent and Hyperbolic Tangent Reverse Mode Theory\n##########################################################\n\nWe use the reverse theory\n:ref:`standard math function<reverse_theory@Standard Math Functions>`\ndefinition for the functions :math:`H` and :math:`G`.\nIn addition, we use the forward mode notation in\n:ref:`atan_forward-name` for\n\n.. math::\n\n    B(t) = 1 \\pm X(t) * X(t)\n\nWe use :math:`b`\nfor the *p*-th order Taylor coefficient\nrow vectors corresponding to :math:`B(t)`\nand replace :math:`z^{(j)}` by\n\n.. math::\n\n    ( z^{(j)} , b^{(j)} )\n\nin the definition for :math:`G` and :math:`H`.\nThe zero order forward mode formulas for the\n:ref:`atan<atan_forward-name>`\nfunction are\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        z^{(0)}  & = & F ( x^{(0)} ) \\\\\n        b^{(0)}  & = & 1 \\pm x^{(0)} x^{(0)}\n    \\end{eqnarray}\n\nwhere :math:`F(x) = \\R{atan} (x)` for :math:`+`\nand :math:`F(x) = \\R{atanh} (x)` for :math:`-`.\nFor orders :math:`j` greater than zero we have\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    b^{(j)} & = &\n        \\pm \\sum_{k=0}^j x^{(k)} x^{(j-k)}\n    \\\\\n    z^{(j)} & = & \\frac{1}{j} \\frac{1}{ b^{(0)} }\n    \\left(\n        j x^{(j)}\n        - \\sum_{k=1}^{j-1} k z^{(k)}  b^{(j-k)}\n    \\right)\n    \\end{eqnarray}\n\nIf :math:`j = 0`, we note that\n:math:`F^{(1)} ( x^{(0)} ) =  1 / b^{(0)}` and hence\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    \\D{H}{ x^{(j)} } & = &\n    \\D{G}{ x^{(j)} }\n    + \\D{G}{ z^{(j)} } \\D{ z^{(j)} }{ x^{(0)} }\n    + \\D{G}{ b^{(j)} } \\D{ b^{(j)} }{ x^{(0)} }\n    \\\\\n    & = &\n    \\D{G}{ x^{(j)} }\n    + \\D{G}{ z^{(j)} } \\frac{1}{ b^{(0)} }\n    \\pm \\D{G}{ b^{(j)} } 2 x^{(0)}\n    \\end{eqnarray}\n\nIf :math:`j > 0`, then for :math:`k = 1, \\ldots , j-1`\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    \\D{H}{ b^{(0)} } & = &\n    \\D{G}{ b^{(0)} }\n    + \\D{G}{ z^{(j)} } \\D{ z^{(j)} }{ b^{(0)} }\n    \\\\\n    & = &\n    \\D{G}{ b^{(0)} }\n    - \\D{G}{ z^{(j)} } \\frac{ z^{(j)} }{ b^{(0)} }\n    \\\\\n    \\D{H}{ x^{(j)} } & = &\n    \\D{G}{ x^{(j)} }\n    + \\D{G}{ z^{(j)} } \\D{ z^{(j)} }{ x^{(j)} }\n    + \\D{G}{ b^{(j)} } \\D{ b^{(j)} }{ x^{(j)} }\n    \\\\\n    & = &\n    \\D{G}{ x^{(j)} }\n    + \\D{G}{ z^{(j)} } \\frac{1}{ b^{(0)} }\n    \\pm \\D{G}{ b^{(j)} } 2 x^{(0)}\n    \\\\\n    \\D{H}{ x^{(0)} } & = &\n    \\D{G}{ x^{(0)} }\n    + \\D{G}{ z^{(j)} } \\D{ z^{(j)} }{ x^{(0)} }\n    + \\D{G}{ b^{(j)} } \\D{ b^{(j)} }{ x^{(0)} }\n    \\\\\n    & = &\n    \\D{G}{ x^{(0)} }\n    \\pm \\D{G}{ b^{(j)} } 2 x^{(j)}\n    \\\\\n    \\D{H}{ x^{(k)} } & = &\n    \\D{G}{ x^{(k)} }\n    + \\D{G}{ z^{(j)} } \\D{ z^{(j)} }{ x^{(k)} }\n    + \\D{G}{ b^{(j)} } \\D{ b^{(j)} }{ x^{(k)} }\n    \\\\\n    & = &\n    \\D{G}{ x^{(k)} }\n    \\pm \\D{G}{ b^{(j)} } 2 x^{(j-k)}\n    \\\\\n    \\D{H}{ z^{(k)} } & = &\n    \\D{G}{ z^{(k)} }\n    + \\D{G}{ z^{(j)} } \\D{ z^{(j)} }{ z^{(k)} }\n    + \\D{G}{ b^{(j)} } \\D{ b^{(j)} }{ z^{(k)} }\n    \\\\\n    & = &\n    \\D{G}{ z^{(k)} }\n    - \\D{G}{ z^{(j)} } \\frac{k b^{(j-k)} }{ j b^{(0)} }\n    \\\\\n    \\D{H}{ b^{(j-k)} } & = &\n    \\D{G}{ b^{(j-k)} }\n    + \\D{G}{ z^{(j)} } \\D{ z^{(j)} }{ b^{(j-k)} }\n    + \\D{G}{ b^{(j)} } \\D{ b^{(j)} }{ b^{(j-k)} }\n    \\\\\n    & = &\n    \\D{G}{ b^{(j-k)} }\n    - \\D{G}{ z^{(j)} } \\frac{k z^{(k)} }{ j b^{(0)} }\n    \\end{eqnarray}\n\n{xrst_end atan_reverse}\n"
  },
  {
    "path": "xrst/theory/cholesky.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin cholesky_theory app}\n{xrst_spell\n    diag\n    tr\n    universitat\n    zu\n}\n\nAD Theory for Cholesky Factorization\n####################################\n\nReference\n*********\nSee section 3.6 of\nSebastian F. Walter's Ph.D. thesis,\n*Structured Higher-Order Algorithmic Differentiation*\n*in the Forward and Reverse Mode*\n*with Application in Optimum Experimental Design* ,\nHumboldt-Universitat zu Berlin,\n2011.\n\nNotation\n********\n\nCholesky Factor\n===============\nWe are given a positive definite symmetric matrix\n:math:`A \\in \\B{R}^{n \\times n}`\nand a Cholesky factorization\n\n.. math::\n\n    A = L L^\\R{T}\n\nwhere :math:`L \\in \\B{R}^{n \\times n}` is lower triangular.\n\nTaylor Coefficient\n==================\nThe matrix :math:`A` is a function of a scalar argument\n:math:`t`.\nFor :math:`k = 0 , \\ldots , K`, we use :math:`A_k` for the\ncorresponding Taylor coefficients; i.e.,\n\n.. math::\n\n    A(t) = o( t^K ) + \\sum_{k = 0}^K A_k t^k\n\nwhere :math:`o( t^K ) / t^K \\rightarrow 0` as :math:`t \\rightarrow 0`.\nWe use a similar notation for :math:`L(t)`.\n\nLower Triangular Part\n=====================\nFor a square matrix :math:`C`,\n:math:`\\R{lower} (C)` is the lower triangular part of :math:`C`,\n:math:`\\R{diag} (C)` is the diagonal matrix with the same diagonal as\n:math:`C` and\n\n.. math::\n\n    \\R{low} ( C ) = \\R{lower} (C) - \\frac{1}{2} \\R{diag} (C)\n\nForward Mode\n************\nFor Taylor coefficient order :math:`k = 0 , \\ldots , K`\nthe coefficients\n:math:`A_k \\in \\B{R}^{n \\times n}`, and\nsatisfy the equation\n\n.. math::\n\n    A_k = \\sum_{\\ell=0}^k L_\\ell L_{k-\\ell}^\\R{T}\n\nIn the case where :math:`k=0`, the\n\n.. math::\n\n    A_0 = L_0 L_0^\\R{T}\n\nThe value of :math:`L_0` can be computed using the Cholesky factorization.\nIn the case where :math:`k > 0`,\n\n.. math::\n\n    A_k = L_k L_0^\\R{T}  + L_0 L_k^\\R{T}  + B_k\n\nwhere\n\n.. math::\n\n    B_k = \\sum_{\\ell=1}^{k-1} L_\\ell L_{k-\\ell}^\\R{T}\n\nNote that :math:`B_k` is defined in terms of Taylor coefficients\nof :math:`L(t)` that have order less than :math:`k`.\nWe also note that\n\n.. math::\n\n    L_0^{-1} ( A_k - B_k ) L_0^\\R{-T}\n    =\n    L_0^{-1} L_k + L_k^\\R{T} L_0^\\R{-T}\n\nThe first matrix on the right hand side is lower triangular,\nthe second is upper triangular,\nand the diagonals are equal.\nIt follows that\n\n.. math::\n\n    L_0^{-1} L_k\n    =\n    \\R{low} [ L_0^{-1} ( A_k - B_k ) L_0^\\R{-T} ]\n\n.. math::\n\n    L_k\n    =\n    L_0 \\R{low} [ L_0^{-1} ( A_k - B_k ) L_0^\\R{-T} ]\n\nThis expresses :math:`L_k` in term of the\nTaylor coefficients of :math:`A(t)` and the lower order coefficients\nof :math:`L(t)`.\n\nLemma 1\n*******\nWe use the notation :math:`\\dot{C}` for the derivative of a matrix\nvalued function :math:`C(s)` with respect to a scalar argument :math:`s`.\nWe use the notation :math:`\\bar{S}` and :math:`\\bar{L}` for the\npartial derivative of a scalar value function :math:`\\bar{F}( S, L)`\nwith respect to a symmetric matrix :math:`S` and\nan lower triangular matrix :math:`L`.\nDefine the scalar valued function\n\n.. math::\n\n    \\hat{F}( C ) = \\bar{F} [ S , \\hat{L} (S) ]\n\nWe use :math:`\\hat{S}` for the total derivative of :math:`\\hat{F}` with\nrespect to :math:`S`.\nSuppose that :math:`\\hat{L} ( S )` is such that\n\n.. math::\n\n    \\dot{L} = L_0 \\R{low} ( L_0^{-1} \\dot{S} L_0^\\R{-T} )\n\nfor any :math:`S(s)`. It follows that\n\n.. math::\n\n    \\hat{S} = \\bar{S} + \\frac{1}{2} ( M + M^\\R{T} )\n\nwhere\n\n.. math::\n\n    M = L_0^\\R{-T} \\R{low}( L_0^\\R{T} \\bar{L} )^\\R{T} L_0^{-1}\n\nProof\n=====\n\n.. math::\n\n    \\partial_s \\hat{F} [ S(s) , L(s) ]\n    =\n    \\R{tr} ( \\bar{S}^\\R{T} \\dot{S} )\n    +\n    \\R{tr} ( \\bar{L}^\\R{T} \\dot{L} )\n\n.. math::\n\n    \\R{tr} ( \\bar{L}^\\R{T} \\dot{L} )\n    =\n    \\R{tr} [\n        \\bar{L}^\\R{T} L_0\n        \\R{low} ( L_0^{-1} \\dot{S} L_0^\\R{-T} )\n    ]\n\n.. math::\n\n    =\n    \\R{tr} [\n        \\R{low} ( L_0^{-1} \\dot{S} L_0^\\R{-T} )^\\R{T}\n        L_0^\\R{T} \\bar{L}\n    ]\n\n.. math::\n\n    =\n    \\R{tr} [\n        L_0^{-1} \\dot{S} L_0^\\R{-T}\n        \\R{low}( L_0^\\R{T} \\bar{L} )\n    ]\n\n.. math::\n\n    =\n    \\R{tr} [\n        L_0^\\R{-T} \\R{low}( L_0^\\R{T} \\bar{L} ) L_0^{-1} \\dot{S}\n    ]\n\n.. math::\n\n    \\partial_s \\hat{F} [ S(s) , L(s) ]\n    =\n    \\R{tr} ( \\bar{S}^\\R{T} \\dot{S} )\n    +\n    \\R{tr} [\n        L_0^\\R{-T} \\R{low}( L_0^\\R{T} \\bar{L} ) L_0^{-1} \\dot{S}\n    ]\n\nWe now consider the :math:`(i, j)` component function,\nfor a symmetric matrix :math:`S(s)`,\ndefined by\n\n.. math::\n\n    S_{k, \\ell} (s) = \\left\\{ \\begin{array}{ll}\n        1 & \\R{if} \\; k = i \\; \\R{and} \\; \\ell = j \\\\\n        1 & \\R{if} \\; k = j \\; \\R{and} \\; \\ell = i \\\\\n        0 & \\R{otherwise}\n    \\end{array} \\right\\}\n\nThis shows that the formula in the lemma is correct for\n:math:`\\hat{S}_{i,j}` and :math:`\\hat{S}_{j,i}`.\nThis completes the proof because the component :math:`(i, j)` was arbitrary.\n\nLemma 2\n*******\nWe use the same assumptions as in Lemma 1 except that the\nmatrix :math:`S` is lower triangular (instead of symmetric).\nIt follows that\n\n.. math::\n\n    \\hat{S} = \\bar{S} + \\R{lower}(M)\n\nwhere\n\n.. math::\n\n    M = L_0^\\R{-T} \\R{low}( L_0^\\R{T} \\bar{L} )^\\R{T} L_0^{-1}\n\nThe proof of this lemma is identical to Lemma 2 except that component function\nis defined by\n\n.. math::\n\n    S_{k, \\ell} (s) = \\left\\{ \\begin{array}{ll}\n        1 & \\R{if} \\; k = i \\; \\R{and} \\; \\ell = j \\\\\n        0 & \\R{otherwise}\n    \\end{array} \\right\\}\n\nReverse Mode\n************\n\nk Equal To 0\n============\nFor the case :math:`k = 0`,\n\n.. math::\n\n    \\dot{A}_0\n    =\n    \\dot{L}_0 L_0^\\R{T}\n    +\n    L_0  \\dot{L}_0^\\R{T}\n\n.. math::\n\n    L_0^{-1} \\dot{A}_0 L_0^\\R{-T}\n    =\n    L_0^{-1} \\dot{L}_0\n    +\n    \\dot{L}_0^\\R{T} L_0^\\R{-T}\n\n.. math::\n\n    \\R{low} ( L_0^{-1} \\dot{A}_0 L_0^\\R{-T} )\n    =\n    L_0^{-1} \\dot{L}_0\n\n.. math::\n\n    \\dot{L}_0\n    =\n    L_0 \\R{low} ( L_0^{-1} \\dot{A}_0 L_0^\\R{-T} )\n\nIt follows from Lemma 1 that\n\n.. math::\n\n    \\bar{A}_0 \\stackrel{+}{=} \\frac{1}{2} ( M + M^\\R{T} )\n\nwhere\n\n.. math::\n\n    M = L_0^\\R{-T} \\R{low} ( L_0^\\R{T} \\bar{L}_0 )^\\R{T} L_0^{-1}\n\nand :math:`\\bar{A}_0` is the partial before and after\nis before and after :math:`L_0` is removed from the scalar function\ndependency.\n\nk Greater Than 0\n================\nIn the case where :math:`k > 0`,\n\n.. math::\n\n    A_k = L_k L_0^\\R{T}  + L_0 L_k^\\R{T}  + B_k\n\nwhere :math:`B_k` is defined in terms of Taylor coefficients\nof :math:`L(t)` that have order less than :math:`k`.\nIt follows that\n\n.. math::\n\n    \\dot{L}_k L_0^\\R{T}\n    +\n    L_0 \\dot{L}_k^\\R{T}\n    =\n    \\dot{A}_k - \\dot{B}_k  - \\dot{L}_0 L_k^\\R{T} -  L_k \\dot{L}_0^\\R{T}\n\n.. math::\n\n    L_0^{-1} \\dot{L}_k\n    +\n    \\dot{L}_k^\\R{T} L_0^\\R{-T}\n    =\n    L_0^{-1} (\n    \\dot{A}_k - \\dot{B}_k  - \\dot{L}_0 L_k^\\R{T} -  L_k \\dot{L}_0^\\R{T}\n    ) L_0^\\R{-T}\n\n.. math::\n\n    L_0^{-1} \\dot{L}_k\n    =\n    \\R{low} [ L_0^{-1} (\n    \\dot{A}_k - \\dot{B}_k  - \\dot{L}_0 L_k^\\R{T} -  L_k \\dot{L}_0^\\R{T}\n    ) L_0^\\R{-T} ]\n\n.. math::\n\n    \\dot{L}_k\n    =\n    L_0 \\R{low} [ L_0^{-1} (\n    \\dot{A}_k - \\dot{B}_k  - \\dot{L}_0 L_k^\\R{T} -  L_k \\dot{L}_0^\\R{T}\n    ) L_0^\\R{-T} ]\n\nThe matrix :math:`A_k` is symmetric, it follows that\n\n.. math::\n\n    \\bar{A}_k \\stackrel{+}{=} \\frac{1}{2} ( M_k + M_k^\\R{T} )\n\nwhere\n\n.. math::\n\n    M_k = L_0^\\R{-T} \\R{low} ( L_0^\\R{T} \\bar{L}_k )^\\R{T} L_0^{-1}\n\nThe matrix :math:`B_k` is also symmetric, hence\n\n.. math::\n\n    \\bar{B}_k = - \\; \\frac{1}{2} ( M_k + M_k^\\R{T} )\n\nWe define the symmetric matrix :math:`C_k (s)` by\n\n.. math::\n\n    \\dot{C}_k = \\dot{L}_0 L_k^\\R{T} +  L_k \\dot{L}_0^\\R{T}\n\nand remove the dependency on :math:`C_k` with\n\n.. math::\n\n    \\R{tr}( \\bar{C}_k^\\R{T} \\dot{C}_k )\n    =\n    \\R{tr}( \\bar{B}_k^\\R{T} \\dot{C}_k )\n    =\n    \\R{tr}( \\bar{B}_k^\\R{T} \\dot{L}_0 L_k^\\R{T}  )\n    +\n    \\R{tr}( \\bar{B}_k^\\R{T}  L_k \\dot{L}_0^\\R{T} )\n\n.. math::\n\n    =\n    \\R{tr}( L_k^\\R{T} \\bar{B}_k^\\R{T} \\dot{L}_0 )\n    +\n    \\R{tr}( L_k^\\R{T} \\bar{B}_k \\dot{L}_0 )\n\n.. math::\n\n    =\n    \\R{tr}[ L_k^\\R{T} ( \\bar{B}_k + \\bar{B}_k^\\R{T} ) \\dot{L}_0 ]\n\nThus, removing :math:`C_k` from the dependency results in the\nfollowing update to :math:`\\bar{L}_0`:\n\n.. math::\n\n    \\bar{L}_0 \\stackrel{+}{=} \\R{lower} [ ( \\bar{B}_k + \\bar{B}_k^\\R{T} ) L_k ]\n\nwhich is the same as\n\n.. math::\n\n    \\bar{L}_0 \\stackrel{+}{=} 2 \\; \\R{lower} [ \\bar{B}_k L_k ]\n\nWe still need to remove :math:`B_k` from the dependency.\nIt follows from its definition that\n\n.. math::\n\n    \\dot{B}_k = \\sum_{\\ell=1}^{k-1}\n        \\dot{L}_\\ell L_{k-\\ell}^\\R{T} + L_\\ell \\dot{L}_{k-\\ell}^\\R{T}\n\n.. math::\n\n    \\R{tr}( \\bar{B}_k^\\R{T} \\dot{B}_k )\n    =\n    \\sum_{\\ell=1}^{k-1}\n    \\R{tr}( \\bar{B}_k^\\R{T} \\dot{L}_\\ell L_{k-\\ell}^\\R{T} )\n    +\n    \\R{tr}( \\bar{B}_k^\\R{T} L_\\ell \\dot{L}_{k-\\ell}^\\R{T} )\n\n.. math::\n\n    =\n    \\sum_{\\ell=1}^{k-1}\n    \\R{tr}( L_{k-\\ell}^\\R{T} \\bar{B}_k^\\R{T} \\dot{L}_\\ell )\n    +\n    \\sum_{\\ell=1}^{k-1}\n    \\R{tr}( L_\\ell^\\R{T} \\bar{B}_k \\dot{L}_{k-\\ell} )\n\nWe now use the fact that :math:`\\bar{B}_k` is symmetric to conclude\n\n.. math::\n\n    \\R{tr}( \\bar{B}_k^\\R{T} \\dot{B}_k )\n    =\n    2 \\sum_{\\ell=1}^{k-1}\n    \\R{tr}( L_{k-\\ell}^\\R{T} \\bar{B}_k^\\R{T} \\dot{L}_\\ell )\n\nEach of the :math:`\\dot{L}_\\ell` matrices is lower triangular.\nThus, removing :math:`B_k` from the dependency results in the following\nupdate for :math:`\\ell = 1 , \\ldots , k-1`:\n\n.. math::\n\n    \\bar{L}_\\ell\n    \\stackrel{+}{=} 2 \\; \\R{lower}( \\bar{B}_k L_{k-\\ell} )\n\n{xrst_end cholesky_theory}\n"
  },
  {
    "path": "xrst/theory/erf_forward.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin erf_forward}\n\nError Function Forward Taylor Polynomial Theory\n###############################################\n\nDerivatives\n***********\nGiven :math:`X(t)`, we define the function\n\n.. math::\n\n    Z(t) = \\R{erf}[ X(t) ]\n\nIt follows that\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    \\R{erf}^{(1)} ( u ) & = & ( 2 / \\sqrt{\\pi} ) \\exp \\left( - u^2 \\right)\n    \\\\\n    Z^{(1)} (t) & = & \\R{erf}^{(1)} [ X(t) ] X^{(1)} (t) = Y(t) X^{(1)} (t)\n    \\end{eqnarray}\n\nwhere we define the function\n\n.. math::\n\n    Y(t) = \\frac{2}{ \\sqrt{\\pi} } \\exp \\left[ - X(t)^2 \\right]\n\nTaylor Coefficients Recursion\n*****************************\nSuppose that we are given the Taylor coefficients\nup to order :math:`j` for the function :math:`X(t)` and :math:`Y(t)`.\nWe need a formula that computes the coefficient of order :math:`j`\nfor :math:`Z(t)`.\nUsing the equation above for :math:`Z^{(1)} (t)`, we have\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    \\sum_{k=1}^j k z^{(k)} t^{k-1}\n    & = &\n    \\left[ \\sum_{k=0}^j y^{(k)} t^k        \\right]\n    \\left[ \\sum_{k=1}^j k x^{(k)} t^{k-1}  \\right]\n    +\n    o( t^{j-1} )\n    \\end{eqnarray}\n\nSetting the coefficients of :math:`t^{j-1}` equal, we have\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    j z^{(j)}\n    =\n    \\sum_{k=1}^j k x^{(k)} y^{(j-k)}\n    \\\\\n    z^{(j)}\n    =\n    \\frac{1}{j} \\sum_{k=1}^j k x^{(k)} y^{(j-k)}\n    \\end{eqnarray}\n\n{xrst_end erf_forward}\n"
  },
  {
    "path": "xrst/theory/erf_reverse.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin erf_reverse}\n\nError Function Reverse Mode Theory\n##################################\n\nNotation\n********\nWe use the reverse theory\n:ref:`standard math function<reverse_theory@Standard Math Functions>`\ndefinition for the functions :math:`H` and :math:`G`.\n\nPositive Orders Z(t)\n********************\nFor order :math:`j > 0`,\nsuppose that :math:`H` is the same as :math:`G`.\n\n.. math::\n\n    z^{(j)}\n    =\n    \\frac{1}{j}  \\sum_{k=1}^j k x^{(k)} y^{(j-k)}\n\nFor :math:`k = 1 , \\ldots , j`,\nthe partial of :math:`H` with respect to :math:`x^{(k)}` is given by\n\n.. math::\n\n    \\D{H}{ x^{(k)} }\n    =\n    \\D{G}{ x^{(k)} } + \\D{G}{ z^{(j)} } \\D{ z^{(j)} }{ x^{(k)} }\n    =\n    \\D{G}{ x^{(k)} } + \\D{G}{ z^{(j)} } \\frac{k}{j} y^{(j-k)}\n\nFor :math:`k = 1 , \\ldots ,  j`\nThe partial of :math:`H` with respect to :math:`y^{j-k}`,\nis given by\n\n.. math::\n\n    \\D{H}{ y^{(j-k)} }\n    =\n    \\D{G}{ y^{(j-k)} } + \\D{G}{ z^{(j)} } \\D{ z^{(j)} }{ y^{(j-k)} }\n    =\n    \\D{G}{ y^{(j-k)} } + \\D{G}{ z^{(j)} } \\frac{k}{j} x^{k}\n\nOrder Zero Z(t)\n***************\nThe :math:`z^{(0)}` coefficient\nis expressed as a function of the Taylor coefficients\nfor :math:`X(t)` and :math:`Y(t)` as follows:\nIn this case,\n\n.. math::\n\n    \\D{H}{ x^{(0)} }\n    =\n    \\D{G}{ x^{(0)} } + \\D{G}{ z^{(0)} } \\D{ z^{(0)} }{ x^{(0)} }\n    =\n    \\D{G}{ x^{(0)} } + \\D{G}{ z^{(0)} } y^{(0)}\n\n{xrst_end erf_reverse}\n"
  },
  {
    "path": "xrst/theory/exp_forward.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin exp_forward}\n{xrst_spell\n    expm\n}\n\nExponential Function Forward Mode Theory\n########################################\n\nDerivatives\n***********\nIf :math:`F(x)` is :math:`\\R{exp} (x)` or :math:`\\R{expm1} (x)`\nthe corresponding derivative satisfies the equation\n\n.. math::\n\n    1 * F^{(1)} (x) - 1 * F (x)\n    =\n    d^{(0)}\n    =\n    \\left\\{ \\begin{array}{ll}\n        0 & \\R{if} \\; F(x) = \\R{exp}(x)\n        \\\\\n        1 & \\R{if} \\; F(x) = \\R{expm1}(x)\n    \\end{array} \\right.\n\nwhere the equation above defines :math:`d^{(0)}`.\nIn the\n:ref:`standard math function differential equation<forward_theory@Standard Math Functions@Differential Equation>` ,\n:math:`A(x) = 1`,\n:math:`B(x) = 1`,\nand :math:`D(x) = d^{(0)}`.\nWe use :math:`a`, :math:`b`, :math:`d`,\nand :math:`z` to denote the\nTaylor coefficients for\n:math:`A [ X (t) ]`,\n:math:`B [ X (t) ]`,\n:math:`D [ X (t) ]`,\nand :math:`F [ X(t) ]` respectively.\n\nTaylor Coefficients Recursion\n*****************************\nFor orders :math:`j = 0 , 1, \\ldots`,\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    z^{(0)} & = & F ( x^{(0)} )\n    \\\\\n    e^{(0)} & = & d^{(0)} + z^{(0)}\n    \\\\\n    e^{(j+1)}\n    & = & d^{(j+1)} + \\sum_{k=0}^{j+1} a^{(j+1-k)} * z^{(k)}\n    \\\\\n    & = & z^{(j+1)}\n    \\\\\n    z^{(j+1)} & = & \\frac{1}{j+1} \\frac{1}{ b^{(0)} }\n    \\left(\n        \\sum_{k=1}^{j+1} k x^{(k)} e^{(j+1-k)}\n        - \\sum_{k=1}^j k z^{(k)}  b^{(j+1-k)}\n    \\right)\n    \\\\\n    & = & x^{(j+1)} d^{(0)}\n        + \\frac{1}{j+1} \\sum_{k=1}^{j+1} k x^{(k)} z^{(j+1-k)}\n    \\end{eqnarray}\n\n{xrst_end exp_forward}\n"
  },
  {
    "path": "xrst/theory/exp_reverse.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin exp_reverse}\n{xrst_spell\n    expm\n}\n\nExponential Function Reverse Mode Theory\n########################################\n\nWe use the reverse theory\n:ref:`standard math function<reverse_theory@Standard Math Functions>`\ndefinition for the functions :math:`H` and :math:`G`.\nThe zero order forward mode formula for the\n:ref:`exponential<exp_forward-name>` is\n\n.. math::\n\n    z^{(0)}  =  F ( x^{(0)} )\n\nand for :math:`j > 0`,\n\n.. math::\n\n    z^{(j)}  = x^{(j)} d^{(0)}\n        + \\frac{1}{j} \\sum_{k=1}^{j} k x^{(k)} z^{(j-k)}\n\nwhere\n\n.. math::\n\n    d^{(0)} = \\left\\{ \\begin{array}{ll}\n        0 & \\R{if} \\; F(x) = \\R{exp}(x)\n        \\\\\n        1 & \\R{if} \\; F(x) = \\R{expm1}(x)\n    \\end{array} \\right.\n\nFor order :math:`j = 0, 1, \\ldots` we note that\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    \\D{H}{ x^{(j)} }\n    & = & \\D{G}{ x^{(j)} }  + \\D{G}{ z^{(j)} } \\D{ z^{(j)} }{ x^{(j)} }\n    \\\\\n    & = & \\D{G}{ x^{(j)} }  + \\D{G}{ z^{(j)} } ( d^{(0)} + z^{(0)} )\n    \\end{eqnarray}\n\nIf :math:`j > 0`, then for :math:`k = 1 , \\ldots , j`\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    \\D{H}{ x^{(k)} } & = &\n    \\D{G}{ x^{(k)} }  + \\D{G}{ z^{(j)} } \\frac{1}{j}  k z^{(j-k)}\n    \\\\\n    \\D{H}{ z^{(j-k)} } & = &\n    \\D{G}{ z^{(j-k)} }  + \\D{G}{ z^{(j)} } \\frac{1}{j}  k x^{(k)}\n    \\end{eqnarray}\n\n{xrst_end exp_reverse}\n"
  },
  {
    "path": "xrst/theory/forward_theory.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin forward_theory}\n\nThe Theory of Forward Mode\n##########################\n\nTaylor Notation\n***************\nIn Taylor notation, each variable corresponds to\na function of a single argument which we denote by *t*\n(see Section 10.2 of\n:ref:`Bib@Evaluating Derivatives` ).\nHere and below\n:math:`X(t)`, :math:`Y(t)`, and *Z* ( *t* ) are scalar valued functions\nand the corresponding *p*-th order Taylor coefficients row vectors are\n:math:`x`, :math:`y` and :math:`z`; i.e.,\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    X(t) & = & x^{(0)} + x^{(1)} * t + \\cdots + x^{(p)} * t^p + o( t^p ) \\\\\n    Y(t) & = & y^{(0)} + y^{(1)} * t + \\cdots + y^{(p)} * t^p + o( t^p ) \\\\\n    Z(t) & = & z^{(0)} + z^{(1)} * t + \\cdots + z^{(p)} * t^p + o( t^p )\n    \\end{eqnarray}\n\nFor the purposes of this section, we are given :math:`x` and :math:`y`\nand need to determine :math:`z`.\n\nBinary Operators\n****************\n\nAddition\n========\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    Z(t)\n    & = & X(t)   + Y(t)\n    \\\\\n    \\sum_{j=0}^p z^{(j)} * t^j\n    & = & \\sum_{j=0}^p x^{(j)} * t^j + \\sum_{j=0}^p y^{(j)} * t^j  + o( t^p )\n    \\\\\n    z^{(j)} & = & x^{(j)} + y^{(j)}\n    \\end{eqnarray}\n\nSubtraction\n===========\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    Z(t)\n    & = & X(t) - Y(t)\n    \\\\\n    \\sum_{j=0}^p z^{(j)} * t^j\n    & = & \\sum_{j=0}^p x^{(j)} * t^j - \\sum_{j=0}^p y^{(j)} * t^j  + o( t^p )\n    \\\\\n    z^{(j)} & = & x^{(j)} - y^{(j)}\n    \\end{eqnarray}\n\nMultiplication\n==============\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    Z(t)\n    & = & X(t) * Y(t)\n    \\\\\n    \\sum_{j=0}^p z^{(j)} * t^j\n    & = & \\left( \\sum_{j=0}^p x^{(j)} * t^j \\right)\n    *\n    \\left( \\sum_{j=0}^p y^{(j)} * t^j \\right) + o( t^p )\n    \\\\\n    z^{(j)} & = & \\sum_{k=0}^j x^{(j-k)} * y^{(k)}\n    \\end{eqnarray}\n\nDivision\n========\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    Z(t)\n    & = & X(t) / Y(t)\n    \\\\\n    x\n    & = & z * y\n    \\\\\n    \\sum_{j=0}^p x^{(j)} * t^j\n    & = &\n    \\left( \\sum_{j=0}^p z^{(j)} * t^j \\right)\n    *\n    \\left( \\sum_{j=0}^p y^{(j)} * t^j \\right)\n    +\n    o( t^p )\n    \\\\\n    x^{(j)} & = & \\sum_{k=0}^j z^{(j-k)} y^{(k)}\n    \\\\\n    z^{(j)} & = & \\frac{1}{y^{(0)}} \\left( x^{(j)} - \\sum_{k=1}^j z^{(j-k)} y^{(k)} \\right)\n    \\end{eqnarray}\n\nStandard Math Functions\n***********************\nSuppose that :math:`F` is a standard math function and\n\n.. math::\n\n    Z(t) = F[ X(t) ]\n\nDifferential Equation\n=====================\nAll of the standard math functions\nsatisfy a differential equation of the form\n\n.. math::\n\n    B(u) * F^{(1)} (u) - A(u) * F (u)  = D(u)\n\nWe use :math:`a`, :math:`b` and :math:`d` to denote the\n*p*-th order Taylor coefficient row vectors for\n:math:`A [ X (t) ]`, :math:`B [ X (t) ]` and :math:`D [ X (t) ]`\nrespectively.\nWe assume that these coefficients are known functions of :math:`x`,\nthe *p*-th order Taylor coefficients for :math:`X(t)`.\n\nTaylor Coefficients Recursion Formula\n=====================================\nOur problem here is to express :math:`z`,\nthe *p*-th order Taylor coefficient row vector for :math:`Z(t)`,\nin terms of these other known coefficients.\nIt follows from the formulas above that\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    Z^{(1)} (t)\n    & = & F^{(1)} [ X(t) ] * X^{(1)} (t)\n    \\\\\n    B[ X(t) ] * Z^{(1)} (t)\n    & = & \\{ D[ X(t) ] + A[ X(t) ] * Z(t) \\} * X^{(1)} (t)\n    \\\\\n    B[ X(t) ] * Z^{(1)} (t) & = & E(t) * X^{(1)} (t)\n    \\end{eqnarray}\n\nwhere we define\n\n.. math::\n\n    E(t) =  D[X(t)] + A[X(t)] * Z(t)\n\nWe can compute the value of :math:`z^{(0)}` using the formula\n\n.. math::\n\n    z^{(0)} = F ( x^{(0)} )\n\nSuppose by induction (on :math:`j`) that we are given the\nTaylor coefficients of :math:`E(t)` up to order :math:`j-1`; i.e.,\n:math:`e^{(k)}` for :math:`k = 0 , \\ldots , j-1`\nand the coefficients\n:math:`z^{(k)}` for :math:`k = 0 , \\ldots , j`.\nWe can compute :math:`e^{(j)}` using the formula\n\n.. math::\n\n    e^{(j)} = d^{(j)} + \\sum_{k=0}^j a^{(j-k)} * z^{(k)}\n\nWe need to complete the induction by finding formulas for :math:`z^{(j+1)}`.\nIt follows from the definition of :math:`E(t)` that\n\n.. math::\n\n    \\left( \\sum_{k=0}^j b^{(k)} * t^k \\right)\n    *\n    \\left( \\sum_{k=1}^{j+1} k z^{(k)} * t^{k-1} \\right)\n    =\n    \\left( \\sum_{k=0}^j e^{(k)} * t^k \\right)\n    *\n    \\left( \\sum_{k=1}^{j+1} k x^{(k)} * t^{k-1} \\right)\n    +\n    o( t^p )\n\nSetting the left and right side coefficients of :math:`t^j` equal,\nand using the formula for\n:ref:`forward_theory@Binary Operators@Multiplication` ,\nwe obtain\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    \\sum_{k=0}^j b^{(k)} (j+1-k) z^{(j+1-k)}\n    & = &\n    \\sum_{k=0}^j e^{(k)} (j+1-k) x^{(j+1-k)}\n    \\\\\n    z^{(j+1)} & = & \\frac{1}{j+1} \\frac{1}{ b^{(0)} }\n    \\left(\n        \\sum_{k=0}^j e^{(k)} (j+1-k) x^{(j+1-k)}\n        - \\sum_{k=1}^j b^{(k)} (j+1-k) z^{(j+1-k)}\n    \\right)\n    \\\\\n    z^{(j+1)} & = & \\frac{1}{j+1} \\frac{1}{ b^{(0)} }\n    \\left(\n        \\sum_{k=1}^{j+1} k x^{(k)} e^{(j+1-k)}\n        - \\sum_{k=1}^j k z^{(k)}  b^{(j+1-k)}\n    \\right)\n    \\end{eqnarray}\n\nThis completes the induction that computes :math:`e^{(j)}`\nand :math:`z^{(j+1)}`.\n{xrst_toc_hidden\n    xrst/theory/exp_forward.xrst\n    xrst/theory/log_forward.xrst\n    xrst/theory/sqrt_forward.xrst\n    xrst/theory/sin_cos_forward.xrst\n    xrst/theory/atan_forward.xrst\n    xrst/theory/asin_forward.xrst\n    xrst/theory/acos_forward.xrst\n    xrst/theory/pow_forward.xrst\n    xrst/theory/tan_forward.xrst\n    xrst/theory/erf_forward.xrst\n}\n\nCases that Apply Recursion Above\n================================\n\n.. csv-table::\n    :widths: auto\n\n    exp_forward,:ref:`exp_forward-title`\n    log_forward,:ref:`log_forward-title`\n    sqrt_forward,:ref:`sqrt_forward-title`\n    sin_cos_forward,:ref:`sin_cos_forward-title`\n    atan_forward,:ref:`atan_forward-title`\n    asin_forward,:ref:`asin_forward-title`\n    acos_forward,:ref:`acos_forward-title`\n    pow_forward,:ref:`pow_forward-title`\n\nSpecial Cases\n=============\n\n.. csv-table::\n    :widths: auto\n\n    tan_forward,:ref:`tan_forward-title`\n    erf_forward,:ref:`erf_forward-title`\n\n{xrst_end forward_theory}\n"
  },
  {
    "path": "xrst/theory/log_forward.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin log_forward}\n\nLogarithm Function Forward Mode Theory\n######################################\n\nDerivatives\n***********\nIf :math:`F(x)` is :math:`\\R{log} (x)` or :math:`\\R{log1p} (x)`\nthe corresponding derivative satisfies the equation\n\n.. math::\n\n    ( \\bar{b} + x ) * F^{(1)} (x) - 0 * F (x)  = 1\n\nwhere\n\n.. math::\n\n    \\bar{b}\n    =\n    \\left\\{ \\begin{array}{ll}\n        0 & \\R{if} \\; F(x) = \\R{log}(x)\n        \\\\\n        1 & \\R{if} \\; F(x) = \\R{log1p}(x)\n    \\end{array} \\right.\n\nIn the\n:ref:`standard math function differential equation<forward_theory@Standard Math Functions@Differential Equation>` ,\n:math:`A(x) = 0`,\n:math:`B(x) = \\bar{b} + x`,\nand :math:`D(x) = 1`.\nWe use :math:`a`, :math:`b`, :math:`d`,\nand :math:`z` to denote the\nTaylor coefficients for\n:math:`A [ X (t) ]`,\n:math:`B [ X (t) ]`,\n:math:`D [ X (t) ]`,\nand :math:`F [ X(t) ]` respectively.\n\nTaylor Coefficients Recursion\n*****************************\nFor orders :math:`j = 0 , 1, \\ldots`,\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    z^{(0)} & = & F ( x^{(0)} )\n    \\\\\n    e^{(j)}\n    & = & d^{(j)} + \\sum_{k=0}^{j} a^{(j-k)} * z^{(k)}\n    \\\\\n    & = & \\left\\{ \\begin{array}{ll}\n        1 & {\\rm if} \\; j = 0 \\\\\n        0 & {\\rm otherwise}\n    \\end{array} \\right.\n    \\\\\n    z^{(j+1)} & = & \\frac{1}{j+1} \\frac{1}{ b^{(0)} }\n    \\left(\n        \\sum_{k=1}^{j+1} k x^{(k)} e^{(j+1-k)}\n        - \\sum_{k=1}^j k z^{(k)}  b^{(j+1-k)}\n    \\right)\n    \\\\\n    & = & \\frac{1}{j+1} \\frac{1}{ \\bar{b} + x^{(0)} }\n    \\left(\n        (j+1) x^{(j+1) }\n        - \\sum_{k=1}^j k z^{(k)} x^{(j+1-k)}\n    \\right)\n    \\end{eqnarray}\n\n{xrst_end log_forward}\n"
  },
  {
    "path": "xrst/theory/log_reverse.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin log_reverse}\n\nLogarithm Function Reverse Mode Theory\n######################################\n\nWe use the reverse theory\n:ref:`standard math function<reverse_theory@Standard Math Functions>`\ndefinition for the functions :math:`H` and :math:`G`.\n\nThe zero order forward mode formula for the\n:ref:`logarithm<log_forward-name>` is\n\n.. math::\n\n    z^{(0)}  =  F( x^{(0)} )\n\nand for :math:`j > 0`,\n\n.. math::\n\n    z^{(j)}\n    =  \\frac{1}{ \\bar{b} + x^{(0)} } \\frac{1}{j}\n    \\left(\n        j x^{(j)}\n        - \\sum_{k=1}^{j-1} k z^{(k)} x^{(j-k)}\n    \\right)\n\nwhere\n\n.. math::\n\n    \\bar{b}\n    =\n    \\left\\{ \\begin{array}{ll}\n        0 & \\R{if} \\; F(x) = \\R{log}(x)\n        \\\\\n        1 & \\R{if} \\; F(x) = \\R{log1p}(x)\n    \\end{array} \\right.\n\nWe note that for :math:`j > 0`\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    \\D{ z^{(j)} } { x^{(0)} }\n    & = &\n    -\n    \\frac{1}{ \\bar{b} + x^{(0)} }\n    \\frac{1}{ \\bar{b} + x^{(0)} }\n    \\frac{1}{j}\n    \\left(\n        j x^{(j)}\n        - \\sum_{k=1}^{j-1} k z^{(k)} x^{(j-k)}\n    \\right)\n    \\\\\n    & = &\n    -\n    \\frac{z^{(j)}}{ \\bar{b} + x^{(0)} }\n    \\end{eqnarray}\n\nRemoving the zero order partials are given by\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    \\D{H}{ x^{(0)} } & = &\n    \\D{G}{ x^{(0)} }  + \\D{G}{ z^{(0)} } \\D{ z^{(0)} }{ x^{(0)} }\n    \\\\\n    & = &\n    \\D{G}{ x^{(0)} }  + \\D{G}{ z^{(0)} } \\frac{1}{ \\bar{b} + x^{(0)} }\n    \\end{eqnarray}\n\nFor orders :math:`j > 0` and for :math:`k = 1 , \\ldots , j-1`\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    \\D{H}{ x^{(0)} }\n    & = &\n    \\D{G}{ x^{(0)} } + \\D{G}{ z^{(j)} } \\D{ z^{(j)} }{ x^{(0)} }\n    \\\\\n    & = &\n    \\D{G}{ x^{(0)} } - \\D{G}{ z^{(j)} } \\frac{ z^{(j)} }{ \\bar{b} + x^{(0)} }\n    \\\\\n    \\D{H}{ x^{(j)} }\n    & = &\n    \\D{G}{ x^{(j)} } + \\D{G}{ z^{(j)} } \\D{ z^{(j)} }{ x^{(j)} }\n    \\\\\n    & = &\n    \\D{G}{ x^{(j)} } + \\D{G}{ z^{(j)} } \\frac{1}{ \\bar{b} + x^{(0)} }\n    \\\\\n    \\D{H}{ x^{(j-k)} } & = &\n    \\D{G}{ x^{(j-k)} }  -\n        \\D{G}{ z^{(j)} } \\frac{1}{ \\bar{b} + x^{(0)} } \\frac{k}{j}  z^{(k)}\n    \\\\\n    \\D{H}{ z^{(k)} } & = &\n    \\D{G}{ z^{(k)} }  -\n        \\D{G}{ z^{(j)} } \\frac{1}{ \\bar{b} + x^{(0)} } \\frac{k}{j}  x^{(j-k)}\n    \\end{eqnarray}\n\n{xrst_end log_reverse}\n"
  },
  {
    "path": "xrst/theory/pow_forward.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin pow_forward}\n\nPower Function Forward Mode Theory\n##################################\nWe consider the operation :math:`F(x) = x^y` where :math:`x`\nis a variable and :math:`y` is a parameter.\n\nDerivatives\n***********\nThe corresponding derivative satisfies the equation\n\n.. math::\n\n    x * F^{(1)} (x) -  y F(x) = 0\n\nThis is the\n:ref:`standard math function differential equation<forward_theory@Standard Math Functions@Differential Equation>` ,\nwhere\n:math:`A(x) = y`,\n:math:`B(x) = x`,\nand :math:`D(x) = 0`.\nWe use :math:`a`, :math:`b`, :math:`d`,\nand :math:`z` to denote the\nTaylor coefficients for\n:math:`A [ X (t) ]`,\n:math:`B [ X (t) ]`,\n:math:`D [ X (t) ]`,\nand :math:`F [ X(t) ]` respectively.\nIt follows that\n:math:`b^j = x^j`, :math:`d^j = 0`,\n\n.. math::\n\n    a^{(j)} = \\left\\{ \\begin{array}{ll}\n        y & \\R{if} \\; j = 0\n        \\\\\n        0 & \\R{otherwise}\n    \\end{array} \\right.\n\nTaylor Coefficients Recursion\n*****************************\n\nz^(0)\n=====\n\n.. math::\n\n    z^{(0)} = F ( x^{(0)} )\n\ne^(j)\n=====\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        e^{(j)} & = & d^{(j)} + \\sum_{k=0}^j a^{(j-k)} * z^{(k)}\n        \\\\\n        e^{(j)} & = & y * z^{(j)}\n    \\end{eqnarray}\n\nz^j\n===\nFor :math:`j = 0, \\ldots , p-1`\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    z^{(j+1)} & = & \\frac{1}{j+1} \\frac{1}{ b^{(0)} }\n    \\left(\n        \\sum_{k=1}^{j+1} k x^{(k)} e^{(j+1-k)}\n        - \\sum_{k=1}^j k z^{(k)}  b^{(j+1-k)}\n    \\right)\n    \\\\\n    & = & \\frac{1}{j+1} \\frac{1}{ x^{(0)} }\n    \\left(\n        y \\sum_{k=1}^{j+1} k x^{(k)} z^{(j+1-k)}\n        - \\sum_{k=1}^j k z^{(k)}  x^{(j+1-k)}\n    \\right)\n    \\\\\n    & = &\n    \\frac{1}{j+1} \\frac{1}{ x^{(0)} }\n    \\left(\n        y (j+1) x^{(j+1)} z^{(0)}\n        +\n        \\sum_{k=1}^j k ( y x^{(k)} z^{(j+1-k)} - z^{(k)}  x^{(j+1-k)} )\n    \\right)\n    \\\\\n    & = &\n    y z^{(0)} x^{(j+1)} / x^{(0)}\n    +\n    \\frac{1}{j+1} \\frac{1}{ x^{(0)} }\n    \\sum_{k=1}^j k ( y x^{(k)} z^{(j+1-k)} - z^{(k)}  x^{(j+1-k)} )\n    \\end{eqnarray}\n\nFor :math:`j = 1, \\ldots , p`\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    z^{(j)}\n    & = &\n    \\left. \\left(\n        y z^{(0)} x^{(j)}\n        +\n        \\frac{1}{j} \\sum_{k=1}^{j-1} k ( y x^{(k)} z^{(j-k)} - z^{(k)}  x^{(j-k)} )\n    \\right) \\right/ x^{(0)}\n    \\end{eqnarray}\n\n{xrst_end pow_forward}\n"
  },
  {
    "path": "xrst/theory/pow_reverse.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin pow_reverse}\n\nPower Function Reverse Mode Theory\n##################################\n\nWe use the reverse theory\n:ref:`standard math function<reverse_theory@Standard Math Functions>`\ndefinition for the functions :math:`H` and :math:`G`.\nThe zero order forward mode formula for the\n:ref:`power<pow_forward-name>` function is\n\n.. math::\n\n    z^{(0)}  =  F ( x^{(0)} )\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    \\D{H}{ x^{(0)} }\n    & = & \\D{G}{ x^{(0)} }  + \\D{G}{ z^{(0)} } \\D{ z^{(0)} }{ x^{(0)} }\n    \\\\\n    \\D{ z^{(0)} }{ x^{(0)} } & = & y [ x^{(0)} ]^{y - 1}  = y z^{(0)} / x{(0)}\n    \\end{eqnarray}\n\nAll the equations below apply to the case where :math:`j > 0`.\nFor this case, the equation for :math:`z^{(j)}` is\n\n.. math::\n\n    z^{(j)}\n    =\n    \\left. \\left(\n        y z^{(0)} x^{(j)}\n        +\n        \\frac{1}{j} \\sum_{k=1}^{j-1} k ( y x^{(k)} z^{(j-k)} - z^{(k)}  x^{(j-k)} )\n    \\right) \\right/ x^{(0)}\n\nx^j\n***\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    \\D{H}{ x^{(j)} }\n    & = & \\D{G}{ x^{(j)} }  + \\D{G}{ z^{(j)} } \\D{ z^{(j)} }{ x^{(j)} }\n    \\\\\n    \\D{ z^{(j)} }{ x^{(j)} } & = & y z^{(0)} / x^{(0)}\n    \\end{eqnarray}\n\nx^k\n***\nFor :math:`k = 1 , \\ldots , j-1`\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    \\D{H}{ x^{(k)} }\n    & = & \\D{G}{ x^{(k)} }  + \\D{G}{ z^{(j)} } \\D{ z^{(j)} }{ x^{(k)} }\n    \\\\\n    \\D{ z^{(j)} }{ x^{(k)} } & = &\n    \\frac{1}{j} ( k y - (j-k) ) z^{(j-k)} / x^{(0)}\n    \\end{eqnarray}\n\nz^k\n***\nFor :math:`k = 1 , \\ldots , j-1`\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    \\D{H}{ z^{(k)} }\n    & = & \\D{G}{ z^{(k)} }  + \\D{G}{ z^{(j)} } \\D{ z^{(j)} }{ z^{(k)} }\n    \\\\\n    \\D{ z^{(j)} }{ z^{(k)} } & = &\n    \\frac{1}{j} ( (j-k) y - k ) x^{(j-k)} / x^{(0)}\n    \\end{eqnarray}\n\nx^0\n***\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    \\D{H}{ x^{(0)} }\n    & = & \\D{G}{ x^{(0)} }  + \\D{G}{ z^{(j)} } \\D{ z^{(j)} }{ x^{(0)} }\n    \\\\\n    \\D{ z^{(j)} }{ x^{(0)} } & = & - z^{(j)} / x^{(0)}\n    \\end{eqnarray}\n\nz^0\n***\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    \\D{H}{ z^{(0)} }\n    & = & \\D{G}{ z^{(0)} }  + \\D{G}{ z^{(j)} } \\D{ z^{(j)} }{ z^{(0)} }\n    \\\\\n    \\D{ z^{(j)} }{ z^{(0)} } & = &  y x^{(j)} / x^{(0)}\n    \\end{eqnarray}\n\n{xrst_end pow_reverse}\n"
  },
  {
    "path": "xrst/theory/research.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin research}\n{xrst_spell\n    kasper\n    kristensen\n    py\n    subgraphs\n    symmertic\n}\n\nResearch and Software Engineering Projects Related to CppAD\n###########################################################\n\nSee Also\n********\n:ref:`wish_list-name`\n\nPurpose\n*******\nThis is a list of research topics,\nand software engineering projects, related to CppAD.\nIf you know of published results for any of the research topics,\nplease contact the project manage\nso a link to the answer can be added to the CppAD documentation.\n\nAbs-Normal Form\n***************\n`Abs-normal <https://arxiv.org/abs/1701.00753>`_ forms are\nrecent advent in AD and algorithms related to it are an important\nresearch topic.\nThe CppAD :ref:`abs_normal_fun-name` routine enables one to create approximations\nfor non-smooth functions that have higher than first order accuracy.\nThis opens the question of designing algorithms to take advantage of this.\n\nAtomic Functions\n****************\nMathematical formulas for, and implementation of,\n:ref:`atomic functions<atomic_two-name>`\nthat make AD faster and or conserve on memory for special cases; e.g.,\nspecial functions, sparse matrix operations.\n\nDynamic Parameters\n******************\nCppAD provides for :ref:`dynamic parameters<new_dynamic-name>`\nin a unique way (they can depend on other dynamic parameters).\nThis opens the question of techniques that take advantage of this.\nFor example, see :ref:`base2ad.cpp-name` which uses this feature.\n\nMulti-Threading\n***************\nInteresting algorithms and implementations that take advantage of\nthe CppAD :ref:`multi threading<multi_thread-name>` capability.\n\nOptimization\n************\nThere is no paper describing\nthe CppAD :ref:`optimization<optimize-name>` of a computational graph.\nIn particular, the optimization of\n:ref:`conditional expressions<condexp-name>` is not well understood.\nIn addition, possible improvements to the optimization would be welcome.\nFor example, detecting places where the distributive law can be\nused to reduce two multiplies and one addition to one multiply and\ntwo additions.\n\nScripting Language\n******************\nIt would be useful to make :ref:`addon-name` packages that\nconnect CppAD to a scripting languages.\nThe package\n`cppad_swig <https://github.com/bradbell/cppad_swig>`_\ndemonstrates how one could use swig to do this and\n`cppad_py <https://cppad-py.readthedocs.io>`_\nis an example connection to Python.\n\nSparsity\n********\n\nSparsity Patterns\n=================\nThere are forward, reverse and subgraph methods for computing a\n:ref:`sparsity_pattern-name` .\nIt is unclear which is better for which cases.\n\nColoring Problem\n================\nGiven the\n:ref:`glossary@Sparsity Pattern` for a Jacobian or Hessian,\na graph coloring algorithm is used to determine which row or columns\ncan be evaluated at the same time; see\n``color_general.hpp`` and ``color_symmertic.hpp``\n\nSubgraphs\n=========\nThe :ref:`subgraph_jac_rev-name` method use subgraphs to compute sparsity patterns\nand to evaluate sparse derivatives.\nThis is a new technique that should be written up.\nIt was invented by\nKasper Kristensen, DTU Technical University of Denmark.\nSee the :ref:`wish_list@Subgraph` wish list items.\n\nSpeed\n*****\nCppAD provides for some :ref:`speed-name` comparisons between\ndifferent AD packages.\nThese comparisons could be improved, extended, and written up.\n\n{xrst_end research}\n"
  },
  {
    "path": "xrst/theory/reverse_identity.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin reverse_identity}\n{xrst_spell\n    rclr\n}\n\nAn Important Reverse Mode Identity\n##################################\nThe theorem and the proof below is a restatement\nof the results on page 236 of\n:ref:`Bib@Evaluating Derivatives` .\n\nNotation\n********\nGiven a function :math:`f(u, v)` where :math:`u \\in \\B{R}^n`\nwe use the notation\n\n.. math::\n\n    \\D{f}{u} (u, v) = \\left[ \\D{f}{u_1} (u, v) , \\cdots , \\D{f}{u_n} (u, v) \\right]\n\nReverse Sweep\n*************\nWhen using :ref:`reverse mode<reverse_any-name>`\nwe are given a function :math:`F : \\B{R}^n \\rightarrow \\B{R}^m`,\na matrix of Taylor coefficients :math:`x \\in \\B{R}^{n \\times p}`,\nand a weight vector :math:`w \\in \\B{R}^m`.\nWe define the functions :math:`X : \\B{R} \\times \\B{R}^{n \\times p} \\rightarrow \\B{R}^n`,\n:math:`W : \\B{R} \\times \\B{R}^{n \\times p} \\rightarrow \\B{R}`, and\n:math:`W_j : \\B{R}^{n \\times p} \\rightarrow \\B{R}` by\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        X(t , x) & = & x^{(0)} + x^{(1)} t + \\cdots + x^{(p-1)} t^{p-1}\n        \\\\\n        W(t, x)   & = &  w_0 F_0 [X(t, x)] + \\cdots + w_{m-1} F_{m-1} [X(t, x)]\n        \\\\\n        W_j (x)   & = & \\frac{1}{j!} \\Dpow{j}{t} W(0, x)\n    \\end{eqnarray}\n\nwhere :math:`x^{(j)}` is the *j*-th column of :math:`x \\in \\B{R}^{n \\times p}`.\nThe theorem below implies that\n\n.. math::\n\n    \\D{ W_j }{ x^{(i)} } (x) = \\D{ W_{j-i} }{ x^{(0)} } (x)\n\nA :ref:`general reverse sweep<reverse_any-name>` calculates the values\n\n.. math::\n\n    \\D{ W_{p-1} }{ x^{(i)} } (x)  \\hspace{1cm} (i = 0 , \\ldots , p-1)\n\nBut the return values for a reverse sweep are specified\nin terms of the more useful values\n\n.. math::\n\n    \\D{ W_j }{ x^{(0)} } (x)  \\hspace{1cm} (j = 0 , \\ldots , p-1)\n\nTheorem\n*******\nSuppose that :math:`F : \\B{R}^n \\rightarrow \\B{R}^m` is a :math:`p` times\ncontinuously differentiable function.\nDefine the functions\n:math:`Z : \\B{R} \\times \\B{R}^{n \\times p} \\rightarrow \\B{R}^n`,\n:math:`Y : \\B{R} \\times \\B{R}^{n \\times p }\\rightarrow \\B{R}^m`,\nand\n:math:`y^{(j)} : \\B{R}^{n \\times p }\\rightarrow \\B{R}^m` by\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n        Z(t, x)  & = & x^{(0)} + x^{(1)} t + \\cdots + x^{(p-1)} t^{p-1}\n        \\\\\n        Y(t, x)  & = & F [ Z(t, x) ]\n        \\\\\n        y^{(j)} (x) & = & \\frac{1}{j !} \\Dpow{j}{t} Y(0, x)\n    \\end{eqnarray}\n\nwhere :math:`x^{(j)}` denotes the *j*-th column of\n:math:`x \\in \\B{R}^{n \\times p}`.\nIt follows that\nfor all :math:`i, j` such that :math:`i \\leq j < p`,\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    \\D{ y^{(j)} }{ x^{(i)} } (x) & = & \\D{ y^{(j-i)} }{ x^{(0)} } (x)\n    \\end{eqnarray}\n\nProof\n*****\nIf follows from the definitions that\n\n.. math::\n\n    \\begin{array}{rclr}\n    \\D{ y^{(j)} }{ x^{(i)} } (x)\n    & = &\n    \\frac{1}{j ! } \\D{ }{ x^{(i)} }\n        \\left[ \\Dpow{j}{t} (F \\circ  Z) (t, x)  \\right]_{t=0}\n    \\\\\n    & = &\n    \\frac{1}{j ! } \\left[ \\Dpow{j}{t}\n        \\D{ }{ x^{(i)} } (F \\circ  Z) (t, x)\n    \\right]_{t=0}\n    \\\\\n    & = &\n    \\frac{1}{j ! } \\left\\{\n        \\Dpow{j}{t} \\left[ t^i ( F^{(1)} \\circ Z ) (t, x) \\right]\n    \\right\\}_{t=0}\n    \\end{array}\n\nFor :math:`k > i`, the *k*-th\npartial of :math:`t^i` with respect to :math:`t` is zero.\nThus, the partial with respect to :math:`t` is given by\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    \\Dpow{j}{t} \\left[ t^i ( F^{(1)} \\circ Z ) (t, x) \\right]\n    & = &\n    \\sum_{k=0}^i\n    \\left( \\begin{array}{c} j \\\\ k \\end{array} \\right)\n    \\frac{ i ! }{ (i - k) ! } t^{i-k} \\;\n    \\Dpow{j-k}{t} ( F^{(1)} \\circ Z ) (t, x)\n    \\\\\n    \\left\\{\n        \\Dpow{j}{t} \\left[ t^i ( F^{(1)} \\circ Z ) (t, x) \\right]\n    \\right\\}_{t=0}\n    & = &\n    \\left( \\begin{array}{c} j \\\\ i \\end{array} \\right)\n    i ! \\Dpow{j-i}{t} ( F^{(1)} \\circ Z ) (t, x)\n    \\\\\n    & = &\n    \\frac{ j ! }{ (j - i) ! }\n    \\Dpow{j-i}{t} ( F^{(1)} \\circ Z ) (t, x)\n    \\\\\n    \\D{ y^{(j)} }{ x^{(i)} } (x)\n    & = &\n    \\frac{ 1 }{ (j - i) ! }\n    \\Dpow{j-i}{t} ( F^{(1)} \\circ Z ) (t, x)\n    \\end{eqnarray}\n\nApplying this formula to the case where :math:`j`\nis replaced by :math:`j - i` and :math:`i` is replaced by zero,\nwe obtain\n\n.. math::\n\n    \\D{ y^{(j-i)} }{ x^{(0)} } (x)\n    =\n    \\frac{ 1 }{ (j - i) ! }\n    \\Dpow{j-i}{t} ( F^{(1)} \\circ Z ) (t, x)\n    =\n    \\D{ y^{(j)} }{ x^{(i)} } (x)\n\nwhich completes the proof\n\n{xrst_end reverse_identity}\n"
  },
  {
    "path": "xrst/theory/reverse_theory.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin reverse_theory}\n\nThe Theory of Reverse Mode\n##########################\n\nTaylor Notation\n***************\nIn Taylor notation, each variable corresponds to\na function of a single argument which we denote by *t*\n(see Section 10.2 of\n:ref:`Bib@Evaluating Derivatives` ).\nHere and below\n:math:`X(t)`, :math:`Y(t)`, and *Z* ( *t* ) are scalar valued functions\nand the corresponding *p*-th order Taylor coefficients row vectors are\n:math:`x`, :math:`y` and :math:`z`; i.e.,\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    X(t) & = & x^{(0)} + x^{(1)} * t + \\cdots + x^{(p)} * t^p + O( t^{p+1} ) \\\\\n    Y(t) & = & y^{(0)} + y^{(1)} * t + \\cdots + y^{(p)} * t^p + O( t^{p+1} ) \\\\\n    Z(t) & = & z^{(0)} + z^{(1)} * t + \\cdots + z^{(p)} * t^p + O( t^{p+1} )\n    \\end{eqnarray}\n\nFor the purposes of this discussion,\nwe are given the *p*-th order Taylor coefficient row vectors\n:math:`x`, :math:`y`, and  :math:`z`.\nIn addition, we are given the partial derivatives of a scalar valued function\n\n.. math::\n\n    G ( z^{(j)} , \\ldots , z^{(0)}, x, y)\n\nWe need to compute the partial derivatives of the scalar valued function\n\n.. math::\n\n    H ( z^{(j-1)} , \\ldots , z^{(0)}, x, y)  =\n    G ( z^{(j)}, z^{(j-1)} , \\ldots , z^{(0)}, x , y )\n\nwhere :math:`z^{(j)}` is expressed as a function of the\n*j-1*-th order Taylor coefficient row\nvector for :math:`Z` and the vectors :math:`x`, :math:`y`; i.e.,\n:math:`z^{(j)}` above is a shorthand for\n\n.. math::\n\n    z^{(j)} ( z^{(j-1)} , \\ldots , z^{(0)}, x, y )\n\nIf we do not provide a formula for\na partial derivative of :math:`H`, then that partial derivative\nhas the same value as for the function :math:`G`.\n\nBinary Operators\n****************\n\nAddition\n========\nThe forward mode formula for\n:ref:`forward_theory@Binary Operators@Addition` is\n\n.. math::\n\n    z^{(j)} =  x^{(j)} + y^{(j)}\n\nIf follows that for :math:`k = 0 , \\ldots , j`\nand :math:`l = 0 , \\ldots , j-1`\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    \\D{H}{ x^{(k)} } & = &\n    \\D{G}{ x^{(k)} }  + \\D{G}{ z^{(k)} } \\\\\n    \\\\\n    \\D{H}{ y^{(k)} } & = &\n    \\D{G}{ y^{(k)} }  + \\D{G}{ z^{(k)} }\n    \\\\\n    \\D{H}{ z^{(l)} } & = & \\D{G}{ z^{(l)} }\n    \\end{eqnarray}\n\nSubtraction\n===========\nThe forward mode formula for\n:ref:`forward_theory@Binary Operators@Subtraction` is\n\n.. math::\n\n    z^{(j)} =  x^{(j)} - y^{(j)}\n\nIf follows that for :math:`k = 0 , \\ldots , j`\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    \\D{H}{ x^{(k)} } & = &\n    \\D{G}{ x^{(k)} }  - \\D{G}{ z^{(k)} } \\\\\n    \\\\\n    \\D{H}{ y^{(k)} } & = &\n    \\D{G}{ y^{(k)} }  - \\D{G}{ z^{(k)} }\n    \\end{eqnarray}\n\nMultiplication\n==============\nThe forward mode formula for\n:ref:`forward_theory@Binary Operators@Multiplication` is\n\n.. math::\n\n    z^{(j)} = \\sum_{k=0}^j x^{(j-k)} * y^{(k)}\n\nIf follows that for :math:`k = 0 , \\ldots , j`\nand :math:`l = 0 , \\ldots , j-1`\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    \\D{H}{ x^{(j-k)} } & = &\n    \\D{G}{ x^{(j-k)} }  +\n    \\sum_{k=0}^j \\D{G}{ z^{(j)} } y^{(k)}\n    \\\\\n    \\D{H}{ y^{(k)} } & = &\n    \\D{G}{ y^{(k)} }  +\n    \\sum_{k=0}^j \\D{G}{ z^{(j)} } x^{(j-k)}\n    \\end{eqnarray}\n\nDivision\n========\nThe forward mode formula for\n:ref:`forward_theory@Binary Operators@Division` is\n\n.. math::\n\n    z^{(j)} =\n    \\frac{1}{y^{(0)}}\n    \\left(\n        x^{(j)} - \\sum_{k=1}^j z^{(j-k)} y^{(k)}\n    \\right)\n\nIf follows that for :math:`k = 1 , \\ldots , j`\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    \\D{H}{ x^{(j)} } & = &\n    \\D{G}{ x^{(j)} }  + \\D{G}{ z^{(j)} } \\frac{1}{y^{(0)}}\n    \\\\\n    \\D{H}{ z^{(j-k)} } & = &\n    \\D{G}{ z^{(j-k)} }  - \\D{G}{ z^{(j)} } \\frac{1}{y^{(0)}} y^{(k)}\n    \\\\\n    \\D{H}{ y^{(k)} } & = &\n    \\D{G}{ y^{(k)} }  - \\D{G}{ z^{(j)} } \\frac{1}{y^{(0)}} z^{(j-k)}\n    \\\\\n    \\D{H}{ y^{(0)} } & = &\n    \\D{G}{ y^{(0)} }  - \\D{G}{ z^{(j)} } \\frac{1}{y^{(0)}} \\frac{1}{y^{(0)}}\n    \\left(\n        x^{(j)} - \\sum_{k=1}^j z^{(j-k)} y^{(k)}\n    \\right)\n    \\\\\n    & = &\n    \\D{G}{ y^{(0)} }  - \\D{G}{ z^{(j)} } \\frac{1}{y^{(0)}} z^{(j)}\n    \\end{eqnarray}\n\nStandard Math Functions\n***********************\nThe standard math functions have only one argument.\nHence we are given the partial derivatives of a scalar valued function\n\n.. math::\n\n    G ( z^{(j)} , \\ldots , z^{(0)}, x)\n\nWe need to compute the partial derivatives of the scalar valued function\n\n.. math::\n\n    H ( z^{(j-1)} , \\ldots , z^{(0)}, x)  =\n    G ( z^{(j)}, z^{(j-1)} , \\ldots , z^{(0)}, x)\n\nwhere :math:`z^{(j)}` is expressed as a function of the\n*j-1*-th order Taylor coefficient row\nvector for :math:`Z` and the vector :math:`x`; i.e.,\n:math:`z^{(j)}` above is a shorthand for\n\n.. math::\n\n    z^{(j)} ( z^{(j-1)} , \\ldots , z^{(0)}, x )\n\nContents\n********\n{xrst_toc_table\n    xrst/theory/exp_reverse.xrst\n    xrst/theory/log_reverse.xrst\n    xrst/theory/sqrt_reverse.xrst\n    xrst/theory/sin_cos_reverse.xrst\n    xrst/theory/atan_reverse.xrst\n    xrst/theory/asin_reverse.xrst\n    xrst/theory/acos_reverse.xrst\n    xrst/theory/tan_reverse.xrst\n    xrst/theory/erf_reverse.xrst\n    xrst/theory/pow_reverse.xrst\n}\n\n{xrst_end reverse_theory}\n"
  },
  {
    "path": "xrst/theory/sin_cos_forward.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin sin_cos_forward}\n\nTrigonometric and Hyperbolic Sine and Cosine Forward Theory\n###########################################################\n\nDifferential Equation\n*********************\nThe\n:ref:`standard math function differential equation<forward_theory@Standard Math Functions@Differential Equation>`\nis\n\n.. math::\n\n    B(u) * F^{(1)} (u) - A(u) * F (u)  = D(u)\n\nIn this sections we consider forward mode for the following choices:\n\n.. csv-table::\n    :widths: auto\n\n    ,,:math:`F(u)`,,:math:`\\sin(u)`,,:math:`\\cos(u)`,,:math:`\\sinh(u)`,,:math:`\\cosh(u)`\n    ,,:math:`A(u)`,,:math:`0`,,:math:`0`,,:math:`0`,,:math:`0`\n    ,,:math:`B(u)`,,:math:`1`,,:math:`1`,,:math:`1`,,:math:`1`\n    ,,:math:`D(u)`,,:math:`\\cos(u)`,,:math:`- \\sin(u)`,,:math:`\\cosh(u)`,,:math:`\\sinh(u)`\n\nWe use :math:`a`, :math:`b`, :math:`d` and :math:`f` for the\nTaylor coefficients of\n:math:`A [ X (t) ]`,\n:math:`B [ X (t) ]`,\n:math:`D [ X (t) ]`,\nand :math:`F [ X(t) ]` respectively.\nIt now follows from the general\n:ref:`forward_theory@Standard Math Functions@Taylor Coefficients Recursion Formula`\nthat for :math:`j = 0 , 1, \\ldots`,\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    f^{(0)} & = & D ( x^{(0)} )\n    \\\\\n    e^{(j)}\n    & = & d^{(j)} + \\sum_{k=0}^{j} a^{(j-k)} * f^{(k)}\n    \\\\\n    & = & d^{(j)}\n    \\\\\n    f^{(j+1)} & = & \\frac{1}{j+1} \\frac{1}{ b^{(0)} }\n    \\left(\n        \\sum_{k=1}^{j+1} k x^{(k)} e^{(j+1-k)}\n        - \\sum_{k=1}^j k f^{(k)}  b^{(j+1-k)}\n    \\right)\n    \\\\\n    & = & \\frac{1}{j+1}\n        \\sum_{k=1}^{j+1} k x^{(k)} d^{(j+1-k)}\n    \\end{eqnarray}\n\nThe formula above generates the\norder :math:`j+1` coefficient of :math:`F[ X(t) ]` from the\nlower order coefficients for :math:`X(t)` and :math:`D[ X(t) ]`.\n\n{xrst_end sin_cos_forward}\n"
  },
  {
    "path": "xrst/theory/sin_cos_reverse.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin sin_cos_reverse}\n\nTrigonometric and Hyperbolic Sine and Cosine Reverse Theory\n###########################################################\n\nWe use the reverse theory\n:ref:`standard math function<reverse_theory@Standard Math Functions>`\ndefinition for the functions :math:`H` and :math:`G`.\nIn addition,\nwe use the following definitions for :math:`s` and :math:`c`\nand the integer :math:`\\ell`\n\n.. csv-table::\n    :widths: auto\n\n    Coefficients,,:math:`s`,,:math:`c`,,:math:`\\ell`\n    Trigonometric Case,,:math:`\\sin [ X(t) ]`,,:math:`\\cos [ X(t) ]`,,1\n    Hyperbolic Case,,:math:`\\sinh [ X(t) ]`,,:math:`\\cosh [ X(t) ]`,,-1\n\nWe use the value\n\n.. math::\n\n    z^{(j)} = ( s^{(j)} , c^{(j)} )\n\nin the definition for :math:`G` and :math:`H`.\nThe forward mode formulas for the\n:ref:`sine and cosine<sin_cos_forward-name>` functions are\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    s^{(j)}  & = & \\frac{1 + \\ell}{2} \\sin ( x^{(0)} )\n                  +   \\frac{1 - \\ell}{2} \\sinh ( x^{(0)} )\n    \\\\\n    c^{(j)}  & = & \\frac{1 + \\ell}{2} \\cos ( x^{(0)} )\n                  +   \\frac{1 - \\ell}{2} \\cosh ( x^{(0)} )\n    \\end{eqnarray}\n\nfor the case :math:`j = 0`, and for :math:`j > 0`,\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    s^{(j)} & = & \\frac{1}{j}\n        \\sum_{k=1}^{j} k x^{(k)} c^{(j-k)}  \\\\\n    c^{(j)} & = & \\ell \\frac{1}{j}\n        \\sum_{k=1}^{j} k x^{(k)} s^{(j-k)}\n    \\end{eqnarray}\n\nIf :math:`j = 0`, we have the relation\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    \\D{H}{ x^{(j)} } & = &\n    \\D{G}{ x^{(j)} }\n    + \\D{G}{ s^{(j)} } c^{(0)}\n    + \\ell \\D{G}{ c^{(j)} } s^{(0)}\n    \\end{eqnarray}\n\nIf :math:`j > 0`, then for :math:`k = 1, \\ldots , j-1`\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    \\D{H}{ x^{(k)} } & = &\n    \\D{G}{ x^{(k)} }\n    + \\D{G}{ s^{(j)} } \\frac{1}{j} k c^{(j-k)}\n    + \\ell \\D{G}{ c^{(j)} } \\frac{1}{j} k s^{(j-k)}\n    \\\\\n    \\D{H}{ s^{(j-k)} } & = &\n    \\D{G}{ s^{(j-k)} } + \\ell \\D{G}{ c^{(j)} } k x^{(k)}\n    \\\\\n    \\D{H}{ c^{(j-k)} } & = &\n    \\D{G}{ c^{(j-k)} } + \\D{G}{ s^{(j)} } k x^{(k)}\n    \\end{eqnarray}\n\n{xrst_end sin_cos_reverse}\n"
  },
  {
    "path": "xrst/theory/sqrt_forward.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin sqrt_forward}\n\nSquare Root Function Forward Mode Theory\n########################################\n\nIf :math:`F(x) = \\sqrt{x}`\n\n.. math::\n\n    F(x) * F^{(1)} (x) - 0 * F (x)  = 1/2\n\nand in the\n:ref:`standard math function differential equation<forward_theory@Standard Math Functions@Differential Equation>` ,\n:math:`A(x) = 0`,\n:math:`B(x) = F(x)`,\nand :math:`D(x) = 1/2`.\nWe use :math:`a`, :math:`b`, :math:`d`,\nand :math:`z` to denote the\nTaylor coefficients for\n:math:`A [ X (t) ]`,\n:math:`B [ X (t) ]`,\n:math:`D [ X (t) ]`,\nand :math:`F [ X(t) ]` respectively.\nIt now follows from the general\n:ref:`forward_theory@Standard Math Functions@Taylor Coefficients Recursion Formula`\nthat for :math:`j = 0 , 1, \\ldots`,\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    z^{(0)} & = & \\sqrt { x^{(0)} }\n    \\\\\n    e^{(j)}\n    & = & d^{(j)} + \\sum_{k=0}^{j} a^{(j-k)} * z^{(k)}\n    \\\\\n    & = & \\left\\{ \\begin{array}{ll}\n        1/2 & {\\rm if} \\; j = 0 \\\\\n        0   & {\\rm otherwise}\n    \\end{array} \\right.\n    \\\\\n    z^{(j+1)} & = & \\frac{1}{j+1} \\frac{1}{ b^{(0)} }\n    \\left(\n        \\sum_{k=1}^{j+1} k x^{(k)} e^{(j+1-k)}\n        - \\sum_{k=1}^j k z^{(k)}  b^{(j+1-k)}\n    \\right)\n    \\\\\n    & = & \\frac{1}{j+1} \\frac{1}{ z^{(0)} }\n    \\left(\n        \\frac{j+1}{2} x^{(j+1) }\n        - \\sum_{k=1}^j k z^{(k)} z^{(j+1-k)}\n    \\right)\n    \\end{eqnarray}\n\n{xrst_end sqrt_forward}\n"
  },
  {
    "path": "xrst/theory/sqrt_reverse.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin sqrt_reverse}\n\nSquare Root Function Reverse Mode Theory\n########################################\n\nWe use the reverse theory\n:ref:`standard math function<reverse_theory@Standard Math Functions>`\ndefinition for the functions :math:`H` and :math:`G`.\n\nThe forward mode formulas for the\n:ref:`square root<sqrt_forward-name>`\nfunction are\n\n.. math::\n\n    z^{(j)}  =  \\sqrt { x^{(0)} }\n\nfor the case :math:`j = 0`, and for :math:`j > 0`,\n\n.. math::\n\n    z^{(j)}  =  \\frac{1}{j} \\frac{1}{ z^{(0)} }\n    \\left(\n        \\frac{j}{2} x^{(j) }\n        - \\sum_{\\ell=1}^{j-1} \\ell z^{(\\ell)} z^{(j-\\ell)}\n    \\right)\n\nIf :math:`j = 0`, we have the relation\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    \\D{H}{ x^{(j)} } & = &\n    \\D{G}{ x^{(j)} }  + \\D{G}{ z^{(j)} } \\D{ z^{(j)} }{ x^{(0)} }\n    \\\\\n    & = &\n    \\D{G}{ x^{(j)} }  + \\D{G}{ z^{(j)} } \\frac{1}{2 z^{(0)} }\n    \\end{eqnarray}\n\nIf :math:`j > 0`, then for :math:`k = 1, \\ldots , j-1`\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    \\D{H}{ z^{(0)} } & = &\n    \\D{G}{ z^{(0)} }  + \\D{G} { z^{(j)} } \\D{ z^{(j)} }{ z^{(0)} }\n    \\\\\n    & = &\n    \\D{G}{ z^{(0)} }  -\n    \\D{G}{ z^{(j)} }  \\frac{ z^{(j)} }{ z^{(0)} }\n    \\\\\n    \\D{H}{ x^{(j)} } & = &\n    \\D{G}{ x^{(j)} }  + \\D{G}{ z^{(j)} } \\D{ z^{(j)} }{ x^{(j)} }\n    \\\\\n    & = &\n    \\D{G}{ x^{(j)} }  + \\D{G}{ z^{(j)} } \\frac{1}{ 2 z^{(0)} }\n    \\\\\n    \\D{H}{ z^{(k)} } & = &\n    \\D{G}{ z^{(k)} }  + \\D{G}{ z^{(j)} } \\D{ z^{(j)} }{ z^{(k)} }\n    \\\\\n    & = &\n    \\D{G}{ z^{(k)} }  - \\D{G}{ z^{(j)} } \\frac{ z^{(j-k)} }{ z^{(0)} }\n    \\end{eqnarray}\n\n{xrst_end sqrt_reverse}\n"
  },
  {
    "path": "xrst/theory/tan_forward.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin tan_forward}\n\nTangent and Hyperbolic Tangent Forward Taylor Polynomial Theory\n###############################################################\n\nDerivatives\n***********\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    \\tan^{(1)} ( u ) & = & [ \\cos (u)^2 + \\sin (u)^2  ] / \\cos (u)^2\n    \\\\\n    & = & 1 + \\tan (u)^2\n    \\\\\n    \\tanh^{(1)} ( u ) & = & [ \\cosh (u)^2 - \\sinh (u)^2 ] / \\cosh (u)^2\n    \\\\\n    & = & 1 - \\tanh (u)^2\n    \\end{eqnarray}\n\nIf :math:`F(u)` is :math:`\\tan (u)` or :math:`\\tanh (u)`\nthe corresponding derivative is given by\n\n.. math::\n\n    F^{(1)} (u) = 1 \\pm F(u)^2\n\nGiven :math:`X(t)`, we define the function :math:`Z(t) = F[ X(t) ]`.\nIt follows that\n\n.. math::\n\n    Z^{(1)} (t) = F^{(1)} [ X(t) ] X^{(1)} (t) = [ 1 \\pm Y(t) ] X^{(1)} (t)\n\nwhere we define the function :math:`Y(t) = Z(t)^2`.\n\nTaylor Coefficients Recursion\n*****************************\nSuppose that we are given the Taylor coefficients\nup to order :math:`j` for the function :math:`X(t)` and\nup to order :math:`j-1` for the functions :math:`Y(t)` and :math:`Z(t)`.\nWe need a formula that computes the coefficient of order :math:`j`\nfor :math:`Y(t)` and :math:`Z(t)`.\nUsing the equation above for :math:`Z^{(1)} (t)`, we have\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    \\sum_{k=1}^j k z^{(k)} t^{k-1}\n    & = &\n    \\sum_{k=1}^j k x^{(k)} t^{k-1}\n    \\pm\n    \\left[ \\sum_{k=0}^{j-1} y^{(k)} t^k        \\right]\n    \\left[ \\sum_{k=1}^j k x^{(k)} t^{k-1}  \\right]\n    +\n    o( t^{j-1} )\n    \\end{eqnarray}\n\nSetting the coefficients of :math:`t^{j-1}` equal, we have\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    j z^{(j)}\n    =\n    j x^{(j)}\n    \\pm\n    \\sum_{k=1}^j k x^{(k)} y^{(j-k)}\n    \\\\\n    z^{(j)}\n    =\n    x^{(j)} \\pm \\frac{1}{j}  \\sum_{k=1}^j k x^{(k)} y^{(j-k)}\n    \\end{eqnarray}\n\nOnce we have computed :math:`z^{(j)}`,\nwe can compute :math:`y^{(j)}` as follows:\n\n.. math::\n\n    y^{(j)} = \\sum_{k=0}^j z^{(k)} z^{(j-k)}\n\n{xrst_end tan_forward}\n"
  },
  {
    "path": "xrst/theory/tan_reverse.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin tan_reverse}\n\nTangent and Hyperbolic Tangent Reverse Mode Theory\n##################################################\n\nNotation\n********\nWe use the reverse theory\n:ref:`standard math function<reverse_theory@Standard Math Functions>`\ndefinition for the functions :math:`H` and :math:`G`.\nIn addition, we use the forward mode notation in :ref:`tan_forward-name` for\n:math:`X(t)`, :math:`Y(t)` and :math:`Z(t)`.\n\nEliminating Y(t)\n****************\nFor :math:`j > 0`, the forward mode coefficients are given by\n\n.. math::\n\n    y^{(j-1)} = \\sum_{k=0}^{j-1} z^{(k)} z^{(j-k-1)}\n\nFix :math:`j > 0` and suppose that :math:`H` is the same as :math:`G`\nexcept that :math:`y^{(j-1)}` is replaced as a function of the Taylor\ncoefficients for :math:`Z(t)`.\nTo be specific, for :math:`k = 0 , \\ldots , j-1`,\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    \\D{H}{ z^{(k)} }\n    & = &\n    \\D{G}{ z^{(k)} } + \\D{G}{ y^{(j-1)} } \\D{ y^{(j-1)} }{ z^{(k)} }\n    \\\\\n    & = &\n    \\D{G}{ z^{(k)} } + \\D{G}{ y^{(j-1)} } 2 z^{(j-k-1)}\n    \\end{eqnarray}\n\nPositive Orders Z(t)\n********************\nFor order :math:`j > 0`,\nsuppose that :math:`H` is the same as :math:`G` except that\n:math:`z^{(j)}` is expressed as a function of\nthe coefficients for :math:`X(t)`, and the\nlower order Taylor coefficients for :math:`Y(t)`, :math:`Z(t)`.\n\n.. math::\n\n    z^{(j)}\n    =\n    x^{(j)} \\pm \\frac{1}{j}  \\sum_{k=1}^j k x^{(k)} y^{(j-k)}\n\nFor :math:`k = 1 , \\ldots , j`,\nthe partial of :math:`H` with respect to :math:`x^{(k)}` is given by\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    \\D{H}{ x^{(k)} } & = &\n    \\D{G}{ x^{(k)} } + \\D{G}{ z^{(j)} } \\D{ z^{(j)} }{ x^{(k)} }\n    \\\\\n    & = &\n    \\D{G}{ x^{(k)} } +\n    \\D{G}{ z^{(j)} }\n    \\left[ \\delta ( j - k ) \\pm \\frac{k}{j} y^{(j-k)} \\right]\n    \\end{eqnarray}\n\nwhere :math:`\\delta ( j - k )` is one if :math:`j = k` and zero\notherwise.\nFor :math:`k = 1 , \\ldots ,  j`\nThe partial of :math:`H` with respect to :math:`y^{j-k}`,\nis given by\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    \\D{H}{ y^{(j-k)} } & = &\n    \\D{G}{ y^{(j-k)} } + \\D{G}{ z^{(j)} } \\D{ z^{(j)} }{ y^{(j-k)} }\n    \\\\\n    & = &\n    \\D{G}{ y^{(j-k)} } \\pm \\D{G}{ z^{(j)} }\\frac{k}{j} x^{k}\n    \\end{eqnarray}\n\nOrder Zero Z(t)\n***************\nThe order zero coefficients for the tangent and hyperbolic tangent are\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    z^{(0)} & = & \\left\\{\n        \\begin{array}{c} \\tan ( x^{(0)} ) \\\\ \\tanh (  x^{(0)} ) \\end{array}\n    \\right.\n    \\end{eqnarray}\n\nSuppose that :math:`H` is the same as :math:`G` except that\n:math:`z^{(0)}` is expressed as a function of the Taylor coefficients\nfor :math:`X(t)`.\nIn this case,\n\n.. math::\n    :nowrap:\n\n    \\begin{eqnarray}\n    \\D{H}{ x^{(0)} }\n    & = &\n    \\D{G}{ x^{(0)} }\n    + \\D{G}{ z^{(0)} } \\D{ z^{(0)} }{ x^{(0)} }\n    \\\\\n    & = &\n    \\D{G}{ x^{(0)} } + \\D{G}{ z^{(0)} } ( 1 \\pm y^{(0)} )\n    \\end{eqnarray}\n\n{xrst_end tan_reverse}\n"
  },
  {
    "path": "xrst/theory/taylor_ode.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin taylor_ode}\n\nAD Theory for Solving ODE's Using Taylor's Method\n#################################################\n\nProblem\n*******\nWe are given an initial value problem for\n:math:`y : \\B{R} \\rightarrow \\B{R}^n`; i.e., we know\n:math:`y(0) \\in \\B{R}^n`\nand we know a function :math:`g : \\B{R}^n \\rightarrow \\B{R}^n`\nsuch that :math:`y^1 (t) = g[ y(t) ]`\nwhere :math:`y^k (t)` is the *k*-th derivative of :math:`y(t)`.\n\nz(t)\n****\nWe define the function\n:math:`z : \\B{R} \\rightarrow \\B{R}^n` by\n:math:`z(t) = g[ y(t) ]`.\nGiven the Taylor coefficients\n:math:`y^{(k)} (t)` for :math:`k = 0 , \\ldots , p`, we can\ncompute :math:`z^{(p)} (t)` using forward mode AD on the function\n:math:`g(y)`; see :ref:`forward_order-name` .\nIt follows from :math:`y^1 (t) = z(t)` that\n:math:`y^{p+1} (t) = z^p (t)`\n\n.. math::\n\n    y^{(p+1)} (t) = z^{(p)} (t) / (k + 1)\n\nwhere :math:`y^{(k)} (t)` is the *k*-th order Taylor coefficient\nfor :math:`y(t)`; i.e., :math:`y^k (t) / k !`.\nStarting with the known value :math:`y^{(0)} (t)`,\nthis gives a prescription for computing :math:`y^{(k)} (t)` for\nany :math:`k`.\n\nTaylor's Method\n***************\nThe *p*-th order Taylor method for approximates\n\n.. math::\n\n    y( t + \\Delta t )\n    \\approx\n    y^{(0)} (t) + y^{(1)} (t) \\Delta t + \\cdots + y^{(p)} (t)  \\Delta t^p\n\n{xrst_toc_hidden\n    example/general/taylor_ode.cpp\n}\nExample\n*******\nThe file :ref:`taylor_ode.cpp-name` contains an example and test\nof this method.\n\n{xrst_end taylor_ode}\n"
  },
  {
    "path": "xrst/theory/theory.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin Theory}\n\nThe Theory of Derivative Calculations\n#####################################\n\nContents\n********\n{xrst_toc_list\n    xrst/introduction.xrst\n    xrst/theory/forward_theory.xrst\n    xrst/theory/reverse_theory.xrst\n    xrst/theory/reverse_identity.xrst\n    xrst/theory/taylor_ode.xrst\n    xrst/theory/research.xrst\n}\n\n{xrst_end Theory}\n"
  },
  {
    "path": "xrst/thread_alloc.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-24 Bradley M. Bell\n# ----------------------------------------------------------------------------\n{xrst_begin thread_alloc}\n\nA Fast Multi-Threading Memory Allocator\n#######################################\n\nSyntax\n******\n| ``# include <cppad/thread_alloc.hpp>``\n\nPurpose\n*******\nThe C++ ``new`` and ``delete`` operators are thread safe,\nbut this means that a thread may have to wait for a lock on these operations.\nOnce memory is obtained for a thread, the ``thread_alloc`` memory\nallocator keeps that memory :ref:`available<ta_available-name>` for the thread so that\nit can be re-used without waiting for a lock.\nAll the CppAD memory allocations use this utility.\nThe :ref:`free_available<ta_free_available-name>` function should be used to return memory\nto the system (once it is no longer required by a thread).\n\nInclude\n*******\nThe routines in sections below are defined by ``cppad/thread_alloc.hpp`` .\nThis file is included by\n``cppad/cppad.hpp`` , but it can also be included separately with out\nthe rest of the ``CppAD`` .\n\nContents\n********\n{xrst_toc_table\n    example/utility/thread_alloc.cpp\n    include/cppad/utility/thread_alloc.hpp\n}\n\n{xrst_end thread_alloc}\n*/\n"
  },
  {
    "path": "xrst/uniform_01_hpp.xrst",
    "content": "# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later\n# SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>\n# SPDX-FileContributor: 2003-22 Bradley M. Bell\n# ----------------------------------------------------------------------------\n\n{xrst_begin uniform_01.hpp}\n\nSource: uniform_01\n##################\n\n| # ``ifndef CPPAD_UNIFORM_01_HPP``\n| # ``define CPPAD_UNIFORM_01_HPP``\n\n{xrst_literal\n    include/cppad/speed/uniform_01.hpp\n    // BEGIN C++\n    // END C++\n}\n\n``# endif``\n\n{xrst_end uniform_01.hpp}\n"
  },
  {
    "path": "xrst.toml",
    "content": "[project_name]\ndata = 'CppAD'\n\n[directory]\nproject_directory = '.'\nrst_directory     = 'build/rst'\nhtml_directory    = 'build/html'\ntex_directory     = 'build/tex'\n\n[root_file]\ndefault = 'user_guide.xrst'\napp     = 'appendix/appendix.xrst'\ndev     = 'xrst/devel/devel.xrst'\n\n[heading]\n#   level         0,     1,     2,     3,     4,\ncharacter = [   '#',   '*',   '=',   '-',   '.',  ]\noverline  = [ false, false, false, false, false,  ]\n\n[include_all]\nrst_epilog = ''\nrst_prolog = '''\n.. |space| unicode:: 0xA0\n.. |tab| replace:: |space| |space| |space| |space|\n'''\nlatex_macro = [\n    '\\newcommand{\\W}[1]{ \\; #1 \\; }',\n    '\\newcommand{\\R}[1]{ {\\rm #1} }',\n    '\\newcommand{\\B}[1]{ {\\bf #1} }',\n    '\\newcommand{\\D}[2]{ \\frac{\\partial #1}{\\partial #2} }',\n    '\\newcommand{\\DD}[3]{ \\frac{\\partial^2 #1}{\\partial #2 \\partial #3} }',\n    '\\newcommand{\\Dpow}[2]{ \\frac{\\partial^{#1}}{\\partial  {#2}^{#1}} }',\n    '\\newcommand{\\dpow}[2]{ \\frac{ {\\rm d}^{#1}}{{\\rm d}\\, {#2}^{#1}} }',\n]\n\n# BEGIN_SORT_THIS_LINE_PLUS_4\n# Words that occurred in 10 or more pages on 2025-01-06\n[project_dictionary]\ndata = [ '''\n    acos\n    addr\n    af\n    afun\n    alloc\n    asin\n    atan\n    atanh\n    bool\n    cc\n    ccc\n    checkpointing\n    cmake\n    cond\n    config\n    const\n    cpp\n    cppad\n    cygwin\n    dd\n    det\n    dir\n    dvector\n    eigen\n    endif\n    enum\n    eq\n    eqnarray\n    erf\n    eval\n    exp\n    fabs\n    gcc\n    gt\n    hes\n    hpp\n    ident\n    ifndef\n    ind\n    int\n    itr\n    jac\n    ll\n    mm\n    mul\n    multi\n    namespace\n    nc\n    nowrap\n    num\n    obj\n    op\n    pc\n    pkg\n    preprocessor\n    ptr\n    rec\n    rel\n    res\n    resize\n    seq\n    sizeof\n    sqrt\n    std\n    unix\n    var\n    vec\n    vecad\n''' ]\n# END_SORT_THIS_LINE_MINUS_2\n"
  }
]